fix(全局): 问题修复
This commit is contained in:
parent
afd1704284
commit
e06854d8b1
|
@ -81,7 +81,7 @@ export class MSAxios {
|
||||||
* @description: 文件上传
|
* @description: 文件上传
|
||||||
*/
|
*/
|
||||||
uploadFile<T = any>(
|
uploadFile<T = any>(
|
||||||
config: AxiosRequestConfig,
|
config: AxiosRequestConfig & RequestOptions,
|
||||||
params: UploadFileParams,
|
params: UploadFileParams,
|
||||||
customFileKey = '',
|
customFileKey = '',
|
||||||
isMultiple = false
|
isMultiple = false
|
||||||
|
@ -110,7 +110,6 @@ export class MSAxios {
|
||||||
const { requestOptions } = this.options;
|
const { requestOptions } = this.options;
|
||||||
|
|
||||||
const opt = { ...requestOptions, isTransformResponse: false };
|
const opt = { ...requestOptions, isTransformResponse: false };
|
||||||
|
|
||||||
const { transformRequestHook } = transform || {};
|
const { transformRequestHook } = transform || {};
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.axiosInstance
|
this.axiosInstance
|
||||||
|
@ -120,8 +119,10 @@ export class MSAxios {
|
||||||
data: formData,
|
data: formData,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-type': ContentTypeEnum.FORM_DATA,
|
'Content-type': ContentTypeEnum.FORM_DATA,
|
||||||
|
},
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
'ignoreCancelToken': true, // 文件上传请求不需要添加到pending中,以免路由切换导致文件上传请求被取消
|
requestOptions: {
|
||||||
|
ignoreCancelToken: true, // 文件上传请求不需要添加到pending中,以免路由切换导致文件上传请求被取消
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((res: AxiosResponse<Result>) => {
|
.then((res: AxiosResponse<Result>) => {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<a-cascader
|
<a-cascader
|
||||||
v-if="props.mode === 'MS'"
|
v-if="props.mode === 'MS'"
|
||||||
ref="cascader"
|
ref="cascader"
|
||||||
v-model="innerValue"
|
v-model:model-value="innerValue"
|
||||||
class="ms-cascader"
|
class="ms-cascader"
|
||||||
:options="props.options"
|
:options="props.options"
|
||||||
:trigger-props="{ contentClass: `ms-cascader-popper ms-cascader-popper--${props.optionSize}` }"
|
:trigger-props="{ contentClass: `ms-cascader-popper ms-cascader-popper--${props.optionSize}` }"
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
:placeholder="props.placeholder"
|
:placeholder="props.placeholder"
|
||||||
:loading="props.loading"
|
:loading="props.loading"
|
||||||
:value-key="props.valueKey"
|
:value-key="props.valueKey"
|
||||||
:path-mode="props.pathMode"
|
:path-mode="false"
|
||||||
@change="handleMsCascaderChange"
|
@change="handleMsCascaderChange"
|
||||||
@clear="clearValues"
|
@clear="clearValues"
|
||||||
>
|
>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
<a-cascader
|
<a-cascader
|
||||||
v-else
|
v-else
|
||||||
ref="cascader"
|
ref="cascader"
|
||||||
v-model="innerValue"
|
v-model:model-value="innerValue"
|
||||||
class="ms-cascader"
|
class="ms-cascader"
|
||||||
:options="props.options"
|
:options="props.options"
|
||||||
:trigger-props="{ contentClass: `ms-cascader-popper ms-cascader-popper--${props.optionSize}` }"
|
:trigger-props="{ contentClass: `ms-cascader-popper ms-cascader-popper--${props.optionSize}` }"
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
:virtual-list-props="props.virtualListProps"
|
:virtual-list-props="props.virtualListProps"
|
||||||
:loading="props.loading"
|
:loading="props.loading"
|
||||||
:value-key="props.valueKey"
|
:value-key="props.valueKey"
|
||||||
:path-mode="props.pathMode"
|
:path-mode="false"
|
||||||
@change="(val) => emit('change', val)"
|
@change="(val) => emit('change', val)"
|
||||||
>
|
>
|
||||||
<template v-if="props.prefix" #prefix>
|
<template v-if="props.prefix" #prefix>
|
||||||
|
@ -109,7 +109,8 @@
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
optionSize?: 'small' | 'default';
|
optionSize?: 'small' | 'default';
|
||||||
pathMode?: boolean; // 是否开启路径模式
|
pathMode?: boolean; // 是否开启路径模式,TODO:目前 arco 组件库开启 pathmode 存在 BUG,不开启,实际上值也是 pathmode 格式的
|
||||||
|
labelPathMode?: boolean; // 是否开启回显的 label 是路径模式
|
||||||
valueKey?: string;
|
valueKey?: string;
|
||||||
labelKey?: string; // 传入自定义的 labelKey
|
labelKey?: string; // 传入自定义的 labelKey
|
||||||
}
|
}
|
||||||
|
@ -149,6 +150,7 @@
|
||||||
typeof val[0] === 'string' &&
|
typeof val[0] === 'string' &&
|
||||||
props.levelTop?.includes(val[0])
|
props.levelTop?.includes(val[0])
|
||||||
) {
|
) {
|
||||||
|
// 顶级选项,该级别为单选选项
|
||||||
innerLevel.value = val[0] as string;
|
innerLevel.value = val[0] as string;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -162,13 +164,16 @@
|
||||||
(val) => {
|
(val) => {
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
// 选项变化时,清理一次已选的选项的label对象
|
// 选项变化时,清理一次已选的选项的label对象
|
||||||
const tempObj: Record<string, any> = {};
|
selectedLabelObj = {};
|
||||||
for (let i = 0; i < val.length; i++) {
|
for (let i = 0; i < val.length; i++) {
|
||||||
if (selectedLabelObj[val[i]]) {
|
const item = val[i];
|
||||||
tempObj[val[i]] = selectedLabelObj[val[i]];
|
const value = typeof item === 'object' ? item.value : item;
|
||||||
|
if (!props.labelPathMode) {
|
||||||
|
selectedLabelObj[value] = t((item.label || '').split('/').pop() || '');
|
||||||
|
} else {
|
||||||
|
selectedLabelObj[value] = t(item.label || '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectedLabelObj = { ...tempObj };
|
|
||||||
}
|
}
|
||||||
emit('update:modelValue', val);
|
emit('update:modelValue', val);
|
||||||
if (val === '') {
|
if (val === '') {
|
||||||
|
@ -211,21 +216,21 @@
|
||||||
// TODO: 临时解决 arco-design 的 cascader 组件已选项的label只能是带路径‘/’的 path-mode 的问题
|
// TODO: 临时解决 arco-design 的 cascader 组件已选项的label只能是带路径‘/’的 path-mode 的问题
|
||||||
function getInputLabel(data: CascaderOption) {
|
function getInputLabel(data: CascaderOption) {
|
||||||
const isTagCount = data[props.labelKey].includes('+');
|
const isTagCount = data[props.labelKey].includes('+');
|
||||||
if (!props.pathMode) {
|
if (isTagCount) {
|
||||||
return isTagCount ? data.label : t((data.label || '').split('/').pop() || ''); // 取路径最后一级
|
return data.label;
|
||||||
}
|
}
|
||||||
return isTagCount ? data.label || '' : t(data.label || '');
|
if (!props.labelPathMode) {
|
||||||
|
return t((data.label || '').split('/').pop() || ''); // 取路径最后一级
|
||||||
|
}
|
||||||
|
return t(data.label || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInputLabelTooltip(data: CascaderOption) {
|
function getInputLabelTooltip(data: CascaderOption) {
|
||||||
const isTagCount = data[props.labelKey].includes('+');
|
const isTagCount = data[props.labelKey].includes('+');
|
||||||
|
const label = getInputLabel(data);
|
||||||
if (isTagCount && Array.isArray(innerValue.value)) {
|
if (isTagCount && Array.isArray(innerValue.value)) {
|
||||||
return Object.values(selectedLabelObj).join(',');
|
return Object.values(selectedLabelObj).join(',');
|
||||||
}
|
}
|
||||||
const label = getInputLabel(data);
|
|
||||||
if (data.value && typeof data.value === 'string') {
|
|
||||||
selectedLabelObj[data.value] = label;
|
|
||||||
}
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,10 +208,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-footer">
|
<div class="content-footer">
|
||||||
<div class="mb-[12px] flex items-center">
|
<div class="mb-[12px] flex items-center justify-between">
|
||||||
<div class="font-medium text-[var(--color-text-1)]">
|
<div class="font-medium text-[var(--color-text-1)]">
|
||||||
{{ t('caseManagement.caseReview.startReview') }}
|
{{ t('caseManagement.caseReview.startReview') }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
<a-switch v-model:model-value="autoNext" class="mx-[8px]" size="small" type="line" />
|
<a-switch v-model:model-value="autoNext" class="mx-[8px]" size="small" type="line" />
|
||||||
<div class="text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
<div class="text-[var(--color-text-4)]">{{ t('caseManagement.caseReview.autoNext') }}</div>
|
||||||
<a-tooltip position="right">
|
<a-tooltip position="right">
|
||||||
|
@ -225,6 +226,7 @@
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<reviewForm
|
<reviewForm
|
||||||
:review-id="reviewId"
|
:review-id="reviewId"
|
||||||
:case-id="activeCaseId"
|
:case-id="activeCaseId"
|
||||||
|
@ -334,7 +336,7 @@
|
||||||
reviewId: reviewId.value,
|
reviewId: reviewId.value,
|
||||||
viewFlag: onlyMine.value,
|
viewFlag: onlyMine.value,
|
||||||
keyword: keyword.value,
|
keyword: keyword.value,
|
||||||
current: pageNation.value.current,
|
current: pageNation.value.current || 1,
|
||||||
pageSize: pageNation.value.pageSize,
|
pageSize: pageNation.value.pageSize,
|
||||||
filter: type.value
|
filter: type.value
|
||||||
? {
|
? {
|
||||||
|
@ -355,7 +357,10 @@
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => onlyMine.value,
|
() => onlyMine.value,
|
||||||
() => loadCaseList()
|
() => {
|
||||||
|
pageNation.value.current = 1;
|
||||||
|
loadCaseList();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeCaseId = ref(route.query.caseId as string);
|
const activeCaseId = ref(route.query.caseId as string);
|
||||||
|
@ -502,24 +507,30 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reviewDone() {
|
async function reviewDone() {
|
||||||
if (autoNext.value) {
|
if (autoNext.value) {
|
||||||
// 自动下一个,更改激活的 id会刷新详情
|
// 自动下一个,更改激活的 id会刷新详情
|
||||||
const index = caseList.value.findIndex((e) => e.caseId === activeCaseId.value);
|
const index = caseList.value.findIndex((e) => e.caseId === activeCaseId.value);
|
||||||
if (index < caseList.value.length - 1) {
|
if (index < caseList.value.length - 1) {
|
||||||
activeCaseId.value = caseList.value[index + 1].caseId;
|
activeCaseId.value = caseList.value[index + 1].caseId;
|
||||||
|
} else if (pageNation.value.current * pageNation.value.pageSize < pageNation.value.total) {
|
||||||
|
// 当前页不是最后一页,则加载下一页并激活第一个用例
|
||||||
|
pageNation.value.current += 1;
|
||||||
|
await loadCaseList();
|
||||||
|
activeCaseId.value = caseList.value[0].caseId;
|
||||||
} else {
|
} else {
|
||||||
// 当前是最后一个,刷新数据
|
// 当前是最后一个,刷新数据
|
||||||
loadCaseDetail();
|
loadCaseDetail();
|
||||||
initReviewHistoryList();
|
initReviewHistoryList();
|
||||||
|
loadCaseList();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 不自动下一个才请求详情
|
// 不自动下一个才请求详情
|
||||||
loadCaseDetail();
|
loadCaseDetail();
|
||||||
initReviewHistoryList();
|
initReviewHistoryList();
|
||||||
}
|
|
||||||
loadCaseList();
|
loadCaseList();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const editCaseVisible = ref(false);
|
const editCaseVisible = ref(false);
|
||||||
const editCaseForm = ref<Record<string, any>>({});
|
const editCaseForm = ref<Record<string, any>>({});
|
||||||
|
@ -552,7 +563,7 @@
|
||||||
moduleIds,
|
moduleIds,
|
||||||
} = lastPageParams;
|
} = lastPageParams;
|
||||||
pageNation.value = {
|
pageNation.value = {
|
||||||
total,
|
total: total || 0,
|
||||||
pageSize,
|
pageSize,
|
||||||
current,
|
current,
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
class="mt-[12px]"
|
class="mt-[12px]"
|
||||||
:disabled="submitDisabled"
|
:disabled="submitDisabled"
|
||||||
:submit-review-loading="submitReviewLoading"
|
:loading="submitReviewLoading"
|
||||||
@click="submitReview"
|
@click="submitReview"
|
||||||
>
|
>
|
||||||
{{ t('caseManagement.caseReview.submitReview') }}
|
{{ t('caseManagement.caseReview.submitReview') }}
|
||||||
|
|
|
@ -1009,7 +1009,7 @@
|
||||||
* @param type 文件类型
|
* @param type 文件类型
|
||||||
*/
|
*/
|
||||||
function setAcceptType(type: UploadType) {
|
function setAcceptType(type: UploadType) {
|
||||||
if (isUploading.value) return;
|
if (isUploading.value || acceptType.value === type) return;
|
||||||
acceptType.value = type;
|
acceptType.value = type;
|
||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
<div :key="index" class="storage" @click="setActiveFolder(item.id)">
|
<div :key="index" class="storage" @click="setActiveFolder(item.id)">
|
||||||
<div :class="props.activeFolder === item.id ? 'storage-text storage-text--active' : 'storage-text'">
|
<div :class="props.activeFolder === item.id ? 'storage-text storage-text--active' : 'storage-text'">
|
||||||
<MsIcon type="icon-icon_git" class="storage-icon" />
|
<MsIcon type="icon-icon_git" class="storage-icon" />
|
||||||
<div class="storage-name">{{ item.name }}</div>
|
<a-tooltip :content="item.name">
|
||||||
|
<div class="storage-name one-line-text">{{ item.name }}</div>
|
||||||
|
</a-tooltip>
|
||||||
<div class="storage-count">({{ item.count }})</div>
|
<div class="storage-count">({{ item.count }})</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -151,6 +153,7 @@
|
||||||
import {
|
import {
|
||||||
addRepository,
|
addRepository,
|
||||||
connectRepository,
|
connectRepository,
|
||||||
|
deleteModule,
|
||||||
getRepositories,
|
getRepositories,
|
||||||
getRepositoryInfo,
|
getRepositoryInfo,
|
||||||
updateRepository,
|
updateRepository,
|
||||||
|
@ -264,7 +267,7 @@
|
||||||
* 删除存储库
|
* 删除存储库
|
||||||
* @param item 列表项信息
|
* @param item 列表项信息
|
||||||
*/
|
*/
|
||||||
function deleteStorage(item: any) {
|
function deleteStorage(item: Repository) {
|
||||||
openModal({
|
openModal({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: t('project.fileManagement.deleteStorageTipTitle', { name: item.name }),
|
title: t('project.fileManagement.deleteStorageTipTitle', { name: item.name }),
|
||||||
|
@ -276,7 +279,9 @@
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
|
await deleteModule(item.id);
|
||||||
Message.success(t('project.fileManagement.deleteSuccess'));
|
Message.success(t('project.fileManagement.deleteSuccess'));
|
||||||
|
initRepositories();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -386,7 +391,7 @@
|
||||||
storageFormRef.value?.validateField('url');
|
storageFormRef.value?.validateField('url');
|
||||||
}
|
}
|
||||||
|
|
||||||
function validatePlatformUrl(value: any, callback: (error?: string | undefined) => void) {
|
function validatePlatformUrl(value: string, callback: (error?: string | undefined) => void) {
|
||||||
if (!validateGitUrl(value)) {
|
if (!validateGitUrl(value)) {
|
||||||
callback(t('project.fileManagement.storageUrlError'));
|
callback(t('project.fileManagement.storageUrlError'));
|
||||||
}
|
}
|
||||||
|
@ -394,7 +399,6 @@
|
||||||
|
|
||||||
function handleDrawerCancel() {
|
function handleDrawerCancel() {
|
||||||
showDrawer.value = false;
|
showDrawer.value = false;
|
||||||
storageFormRef.value?.resetFields();
|
|
||||||
isEdit.value = false;
|
isEdit.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +419,7 @@
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
storageFormRef.value?.resetFields();
|
||||||
if (!isContinue) {
|
if (!isContinue) {
|
||||||
handleDrawerCancel();
|
handleDrawerCancel();
|
||||||
}
|
}
|
||||||
|
@ -478,6 +483,7 @@
|
||||||
color: var(--color-text-4);
|
color: var(--color-text-4);
|
||||||
}
|
}
|
||||||
.storage-name {
|
.storage-name {
|
||||||
|
max-width: 170px;
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
}
|
}
|
||||||
.storage-count {
|
.storage-count {
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
:level-top="[...MENU_LEVEL]"
|
:level-top="[...MENU_LEVEL]"
|
||||||
:virtual-list-props="{ height: 200 }"
|
:virtual-list-props="{ height: 200 }"
|
||||||
:loading="rangeLoading"
|
:loading="rangeLoading"
|
||||||
path-mode
|
label-path-mode
|
||||||
class="filter-item"
|
class="filter-item"
|
||||||
/>
|
/>
|
||||||
<a-select v-model:model-value="type" class="filter-item">
|
<a-select v-model:model-value="type" class="filter-item">
|
||||||
|
@ -116,8 +116,12 @@
|
||||||
{{ t(typeOptions.find((e) => e.value === record.type)?.label || '') }}
|
{{ t(typeOptions.find((e) => e.value === record.type)?.label || '') }}
|
||||||
</template>
|
</template>
|
||||||
<template #content="{ record }">
|
<template #content="{ record }">
|
||||||
<div v-if="record.module === 'SYSTEM'">{{ record.content }}</div>
|
<div v-if="record.module === 'SYSTEM'" class="one-line-text">{{ record.content }}</div>
|
||||||
<MsButton v-else @click="handleNameClick(record)">{{ record.content }}</MsButton>
|
<MsButton v-else @click="handleNameClick(record)">
|
||||||
|
<div class="one-line-text">
|
||||||
|
{{ record.content }}
|
||||||
|
</div>
|
||||||
|
</MsButton>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -450,7 +454,6 @@
|
||||||
title: 'system.log.operateName',
|
title: 'system.log.operateName',
|
||||||
dataIndex: 'content',
|
dataIndex: 'content',
|
||||||
slotName: 'content',
|
slotName: 'content',
|
||||||
showTooltip: true,
|
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
:title="t('system.user.invite')"
|
:title="t('system.user.invite')"
|
||||||
title-align="start"
|
title-align="start"
|
||||||
class="ms-modal-form ms-modal-medium"
|
class="ms-modal-form ms-modal-medium"
|
||||||
|
@close="cancelInvite"
|
||||||
>
|
>
|
||||||
<a-form ref="inviteFormRef" class="rounded-[4px]" :model="emailForm" layout="vertical">
|
<a-form ref="inviteFormRef" class="rounded-[4px]" :model="emailForm" layout="vertical">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
:tag-list="record.userRoleList"
|
:tag-list="record.userRoleList"
|
||||||
type="primary"
|
type="primary"
|
||||||
theme="outline"
|
theme="outline"
|
||||||
@click="record.selectUserGroupVisible = true"
|
@click="handleTagClick(record)"
|
||||||
/>
|
/>
|
||||||
<MsSelect
|
<MsSelect
|
||||||
v-else
|
v-else
|
||||||
|
@ -61,7 +61,9 @@
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<template v-if="!record.enable">
|
<template v-if="!record.enable">
|
||||||
<MsButton @click="enableUser(record)">{{ t('system.user.enable') }}</MsButton>
|
<MsButton v-permission="['SYSTEM_USER:READ+UPDATE']" @click="enableUser(record)">
|
||||||
|
{{ t('system.user.enable') }}
|
||||||
|
</MsButton>
|
||||||
<MsButton v-permission="['SYSTEM_USER:READ+DELETE']" @click="deleteUser(record)">
|
<MsButton v-permission="['SYSTEM_USER:READ+DELETE']" @click="deleteUser(record)">
|
||||||
{{ t('system.user.delete') }}
|
{{ t('system.user.delete') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
|
@ -838,6 +840,12 @@
|
||||||
loadList();
|
loadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleTagClick(record: UserListItem & Record<string, any>) {
|
||||||
|
if (hasAnyPermission(['SYSTEM_USER:READ+UPDATE'])) {
|
||||||
|
record.selectUserGroupVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 快捷修改用户组
|
* 快捷修改用户组
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue