mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-24 07:49:47 +08:00
Compare commits
15 Commits
v1.1.2
...
4539fe01fb
Author | SHA1 | Date | |
---|---|---|---|
4539fe01fb | |||
4e9839bd48 | |||
a15b683b1d | |||
9df8d2f55f | |||
710374398a | |||
52318c106d | |||
9027632bef | |||
b96c46baa9 | |||
2d31d7dc62 | |||
e538355f2b | |||
f89835578c | |||
4eb77eac78 | |||
adca2e26be | |||
ff576f3f42 | |||
8fcc70d73d |
@ -21,27 +21,27 @@ const attrs: SelectProps = useAttrs();
|
||||
|
||||
const { loading: postLoading, startLoading: startPostLoading, endLoading: endPostLoading } = useLoading();
|
||||
|
||||
/** the enabled role options */
|
||||
const roleOptions = ref<CommonType.Option<CommonType.IdType>[]>([]);
|
||||
/** the enabled post options */
|
||||
const postOptions = ref<CommonType.Option<CommonType.IdType>[]>([]);
|
||||
|
||||
watch(
|
||||
() => props.deptId,
|
||||
() => {
|
||||
if (!props.deptId) {
|
||||
roleOptions.value = [];
|
||||
postOptions.value = [];
|
||||
return;
|
||||
}
|
||||
getRoleOptions();
|
||||
getPostOptions();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
async function getRoleOptions() {
|
||||
async function getPostOptions() {
|
||||
startPostLoading();
|
||||
const { error, data } = await fetchGetPostSelect(props.deptId!);
|
||||
|
||||
if (!error) {
|
||||
roleOptions.value = data.map(item => ({
|
||||
postOptions.value = data.map(item => ({
|
||||
label: item.postName,
|
||||
value: item.postId
|
||||
}));
|
||||
@ -54,7 +54,7 @@ async function getRoleOptions() {
|
||||
<NSelect
|
||||
v-model:value="value"
|
||||
:loading="postLoading"
|
||||
:options="roleOptions"
|
||||
:options="postOptions"
|
||||
v-bind="attrs"
|
||||
placeholder="请选择岗位"
|
||||
/>
|
||||
|
@ -16,6 +16,12 @@ export function useDownload() {
|
||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||
|
||||
const isHttps = () => {
|
||||
const protocol = document.location.protocol;
|
||||
const hostname = document.location.hostname;
|
||||
return protocol === 'https' || hostname === 'localhost' || hostname === '127.0.0.1';
|
||||
};
|
||||
|
||||
/** 获取通用请求头 */
|
||||
const getCommonHeaders = (contentType = 'application/octet-stream') => ({
|
||||
Authorization: `Bearer ${localStg.get('token')}`,
|
||||
@ -109,9 +115,10 @@ export function useDownload() {
|
||||
|
||||
await handleResponse(response);
|
||||
|
||||
const finalFilename = filename || response.headers.get('Download-Filename') || `download-${timestamp}`;
|
||||
const rawHeader = response.headers.get('Download-Filename');
|
||||
const finalFilename = filename || (rawHeader ? decodeURIComponent(rawHeader) : null) || `download-${timestamp}`;
|
||||
|
||||
if (response.body) {
|
||||
if (response.body && isHttps()) {
|
||||
const contentLength = Number(response.headers.get('Content-Length'));
|
||||
await downloadByStream(response.body, finalFilename, contentLength);
|
||||
return;
|
||||
|
@ -77,7 +77,7 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
||||
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||
if (modalLogoutCodes.includes(responseCode) && isLogin) {
|
||||
const isExist = request.state.errMsgStack && request.state.errMsgStack.includes(response.data.msg);
|
||||
const isExist = request.state.errMsgStack?.includes(response.data.msg);
|
||||
if (isExist) {
|
||||
return null;
|
||||
}
|
||||
@ -85,23 +85,24 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
||||
logoutAndCleanup();
|
||||
return null;
|
||||
}
|
||||
|
||||
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
|
||||
// prevent the user from refreshing the page
|
||||
window.addEventListener('beforeunload', handleLogout);
|
||||
|
||||
window.$dialog?.warning({
|
||||
title: '系统提示',
|
||||
content: '登录状态已过期,您可以继续留在该页面,或者重新登录',
|
||||
content: '登录状态已过期,请重新登录',
|
||||
positiveText: '重新登录',
|
||||
negativeText: '取消',
|
||||
maskClosable: false,
|
||||
closeOnEsc: false,
|
||||
onAfterEnter() {
|
||||
// prevent the user from refreshing the page
|
||||
window.addEventListener('beforeunload', handleLogout);
|
||||
},
|
||||
onPositiveClick() {
|
||||
logoutAndCleanup();
|
||||
},
|
||||
onClose() {
|
||||
window.removeEventListener('beforeunload', handleLogout);
|
||||
request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg);
|
||||
logoutAndCleanup();
|
||||
}
|
||||
});
|
||||
request.cancelAllRequest();
|
||||
|
@ -67,6 +67,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
if (authRouteMode.value === 'dynamic') {
|
||||
if (route.path === '/' && route.children?.length) {
|
||||
const child = route.children[0];
|
||||
// @ts-expect-error no hidden field
|
||||
child.hidden = route.hidden;
|
||||
parseRouter(child);
|
||||
child.name = Math.random().toString(36).slice(2, 12);
|
||||
Object.assign(route, child);
|
||||
@ -123,7 +125,6 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
} else if (!isNotNull(route.meta.icon)) {
|
||||
route.meta.icon = defaultIcon;
|
||||
}
|
||||
|
||||
// @ts-expect-error no hidden field
|
||||
route.meta.hideInMenu = route.hidden;
|
||||
if (route.meta.hideInMenu && parent) {
|
||||
|
@ -13,6 +13,13 @@
|
||||
border-color: var(--un-default-border-color, #e5e7eb); /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* [Naive UI] Fix the icon size in the image preview toolbar
|
||||
*/
|
||||
.n-image-preview-toolbar .n-base-icon {
|
||||
box-sizing: unset !important;
|
||||
}
|
||||
|
||||
/*
|
||||
1. Use a consistent sensible line-height in all browsers.
|
||||
2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
|
2
src/typings/api/system.api.d.ts
vendored
2
src/typings/api/system.api.d.ts
vendored
@ -163,6 +163,8 @@ declare namespace Api {
|
||||
postIds: string[];
|
||||
/** user role ids */
|
||||
roleIds: string[];
|
||||
/** roles */
|
||||
roles: Role[];
|
||||
};
|
||||
|
||||
/** user list */
|
||||
|
@ -53,12 +53,14 @@ async function handleFetchTenantList() {
|
||||
const { data, error } = await fetchTenantList();
|
||||
if (error) return;
|
||||
tenantEnabled.value = data.tenantEnabled;
|
||||
tenantOption.value = data.voList.map(tenant => {
|
||||
return {
|
||||
label: tenant.companyName,
|
||||
value: tenant.tenantId
|
||||
};
|
||||
});
|
||||
if (data.tenantEnabled) {
|
||||
tenantOption.value = data.voList.map(tenant => {
|
||||
return {
|
||||
label: tenant.companyName,
|
||||
value: tenant.tenantId
|
||||
};
|
||||
});
|
||||
}
|
||||
endTenantLoading();
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,12 @@ const dateRangeCreateTime = ref<[string, string] | null>(null);
|
||||
const model = defineModel<Api.System.ConfigSearchParams>('model', { required: true });
|
||||
|
||||
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
if (value?.length) {
|
||||
model.value.params!.beginTime = value[0];
|
||||
model.value.params!.endTime = value[1];
|
||||
const params = model.value.params!;
|
||||
if (value && value.length === 2) {
|
||||
[params.beginTime, params.endTime] = value;
|
||||
} else {
|
||||
params.beginTime = undefined;
|
||||
params.endTime = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,24 @@ function renderLabel({ option }: { option: TreeOption }) {
|
||||
if (label?.startsWith('route.') || label?.startsWith('menu.')) {
|
||||
label = $t(label as App.I18n.I18nKey);
|
||||
}
|
||||
// 禁用的菜单显示红色
|
||||
if (option.status === '1') {
|
||||
return (
|
||||
<div class="flex items-center gap-4px text-error-200">
|
||||
{label}
|
||||
<SvgIcon icon="ri:prohibited-line" class="text-16px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// 隐藏的菜单显示灰色
|
||||
if (option.visible === '1') {
|
||||
return (
|
||||
<div class="flex items-center gap-4px text-gray-400">
|
||||
{label}
|
||||
<SvgIcon icon="codex:hidden" class="text-21px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>{label}</div>;
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,12 @@ const dateRangeCreateTime = ref<[string, string] | null>(null);
|
||||
const model = defineModel<Api.System.OssSearchParams>('model', { required: true });
|
||||
|
||||
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
if (value?.length) {
|
||||
model.value.params!.beginCreateTime = value[0];
|
||||
model.value.params!.endCreateTime = value[1];
|
||||
const params = model.value.params!;
|
||||
if (value && value.length === 2) {
|
||||
[params.beginTime, params.endTime] = value;
|
||||
} else {
|
||||
params.beginTime = undefined;
|
||||
params.endTime = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,9 +168,12 @@ const dateRangeCreateTime = ref<[string, string] | null>(null);
|
||||
const datePickerRef = ref<InstanceType<typeof NDatePicker>>();
|
||||
|
||||
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
if (value?.length) {
|
||||
searchParams.params!.beginTime = value[0];
|
||||
searchParams.params!.endTime = value[1];
|
||||
const params = searchParams.params!;
|
||||
if (value && value.length === 2) {
|
||||
[params.beginTime, params.endTime] = value;
|
||||
} else {
|
||||
params.beginTime = undefined;
|
||||
params.endTime = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,12 @@ const model = defineModel<Api.System.RoleSearchParams>('model', { required: true
|
||||
const { options: sysNormalDisableOptions } = useDict('sys_normal_disable', false);
|
||||
|
||||
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
if (value?.length) {
|
||||
model.value.params!.beginTime = `${value[0]} 00:00:00`;
|
||||
model.value.params!.endTime = `${value[1]} 23:59:59`;
|
||||
const params = model.value.params!;
|
||||
if (value && value.length === 2) {
|
||||
[params.beginTime, params.endTime] = value;
|
||||
} else {
|
||||
params.beginTime = undefined;
|
||||
params.endTime = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ function closeDrawer() {
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
console.log(data.value);
|
||||
fileList.value.forEach(item => {
|
||||
item.status = 'pending';
|
||||
});
|
||||
@ -91,6 +92,7 @@ function handleDownloadTemplate() {
|
||||
|
||||
watch(visible, () => {
|
||||
if (visible.value) {
|
||||
data.value.updateSupport = false;
|
||||
fileList.value = [];
|
||||
success.value = false;
|
||||
message.value = '';
|
||||
@ -140,7 +142,7 @@ watch(visible, () => {
|
||||
</NUploadDragger>
|
||||
</NUpload>
|
||||
<div class="flex-center">
|
||||
<NCheckbox v-model="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox>
|
||||
<NCheckbox v-model:checked="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox>
|
||||
</div>
|
||||
|
||||
<NAlert v-if="message" :title="$t('common.importResult')" :type="success ? 'success' : 'error'" :bordered="false">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import { fetchCreateUser, fetchGetUserInfo, fetchUpdateUser } from '@/service/api/system';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
@ -49,6 +49,8 @@ type Model = Api.System.UserOperateParams;
|
||||
|
||||
const model: Model = reactive(createDefaultModel());
|
||||
|
||||
const roleOptions = ref<CommonType.Option<CommonType.IdType>[]>([]);
|
||||
|
||||
function createDefaultModel(): Model {
|
||||
return {
|
||||
deptId: null,
|
||||
@ -82,6 +84,10 @@ async function getUserInfo() {
|
||||
if (!error) {
|
||||
model.roleIds = data.roleIds;
|
||||
model.postIds = data.postIds;
|
||||
roleOptions.value = data.roles.map(role => ({
|
||||
label: role.roleName,
|
||||
value: role.roleId
|
||||
}));
|
||||
}
|
||||
endLoading();
|
||||
}
|
||||
@ -209,7 +215,14 @@ watch(visible, () => {
|
||||
<PostSelect v-model:value="model.postIds" :dept-id="model.deptId" multiple clearable />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.user.roleIds')" path="roleIds">
|
||||
<RoleSelect v-model:value="model.roleIds" multiple clearable />
|
||||
<NSelect
|
||||
v-model:value="model.roleIds"
|
||||
:loading="loading"
|
||||
:options="roleOptions"
|
||||
multiple
|
||||
clearable
|
||||
placeholder="请选择角色"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.user.status')" path="status">
|
||||
<DictRadio v-model:value="model.status" dict-code="sys_normal_disable" />
|
||||
|
@ -24,9 +24,12 @@ const datePickerRef = ref<InstanceType<typeof NDatePicker>>();
|
||||
const model = defineModel<Api.System.UserSearchParams>('model', { required: true });
|
||||
|
||||
function onDateRangeCreateTimeUpdate(value: [string, string] | null) {
|
||||
if (value?.length) {
|
||||
model.value.params!.beginTime = value[0];
|
||||
model.value.params!.endTime = value[1];
|
||||
const params = model.value.params!;
|
||||
if (value && value.length === 2) {
|
||||
[params.beginTime, params.endTime] = value;
|
||||
} else {
|
||||
params.beginTime = undefined;
|
||||
params.endTime = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user