refactor(系统设置): 重构系统用户组
This commit is contained in:
parent
409f1538a3
commit
7c12e2560d
|
@ -315,6 +315,13 @@
|
||||||
border: 1px solid var(--color-text-input-border);
|
border: 1px solid var(--color-text-input-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.arco-checkbox-indeterminate .arco-checkbox-icon {
|
||||||
|
border-color: rgba(var(--primary-7));
|
||||||
|
background-color: rgba(var(--primary-1));
|
||||||
|
&::after {
|
||||||
|
background-color: rgb(var(--primary-7));
|
||||||
|
}
|
||||||
|
}
|
||||||
.arco-checkbox-disabled,
|
.arco-checkbox-disabled,
|
||||||
.arco-checkbox-disabled:hover {
|
.arco-checkbox-disabled:hover {
|
||||||
.arco-checkbox-icon {
|
.arco-checkbox-icon {
|
||||||
|
|
|
@ -73,11 +73,9 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
color: var(--color-text-4);
|
color: var(--color-text-4);
|
||||||
background-color: rgb(var(--primary-3));
|
|
||||||
}
|
}
|
||||||
.dropdown-icon:hover {
|
.dropdown-icon:hover {
|
||||||
color: rgb(var(--primary-5));
|
color: rgb(var(--primary-5));
|
||||||
background-color: transparent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,11 +13,9 @@ export interface CustomMoreActionItem {
|
||||||
eventKey: string;
|
eventKey: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
export interface PopVisibleItem {
|
|
||||||
[key: string]: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RenameType = 'rename' | 'auth';
|
export type RenameType = 'rename' | 'auth';
|
||||||
|
export type AuthScopeType = 'SYSTEM' | 'PROJECT' | 'ORGANIZATION';
|
||||||
|
|
||||||
export interface UserGroupItem {
|
export interface UserGroupItem {
|
||||||
// 组ID
|
// 组ID
|
||||||
|
@ -29,7 +27,7 @@ export interface UserGroupItem {
|
||||||
// 是否是内置用户组
|
// 是否是内置用户组
|
||||||
internal: true;
|
internal: true;
|
||||||
// 所属类型
|
// 所属类型
|
||||||
type: string;
|
type: AuthScopeType;
|
||||||
createTime: number;
|
createTime: number;
|
||||||
updateTime: number;
|
updateTime: number;
|
||||||
// 创建人
|
// 创建人
|
||||||
|
@ -59,8 +57,6 @@ export interface UserGroupPermissionItem {
|
||||||
license: boolean;
|
license: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AuthScopeType = 'SYSTEM' | 'PROJECT' | 'ORGANIZATION';
|
|
||||||
|
|
||||||
// 用户组对应的权限配置
|
// 用户组对应的权限配置
|
||||||
export interface UserGroupAuthSetting {
|
export interface UserGroupAuthSetting {
|
||||||
// 菜单项ID
|
// 菜单项ID
|
||||||
|
@ -122,3 +118,15 @@ export interface UserTableItem {
|
||||||
deleted: boolean;
|
deleted: boolean;
|
||||||
[key: string]: string | boolean | number;
|
[key: string]: string | boolean | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MoreActionType = 'rename' | 'addMember' | 'create';
|
||||||
|
|
||||||
|
export interface PopVisibleItem {
|
||||||
|
id?: string;
|
||||||
|
visible: boolean;
|
||||||
|
authScope: AuthScopeType;
|
||||||
|
defaultName: string;
|
||||||
|
}
|
||||||
|
export interface PopVisible {
|
||||||
|
[key: string]: PopVisibleItem;
|
||||||
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted, computed } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { PopVisibleItem, RenameType, UserGroupItem } from '@/models/setting/usergroup';
|
import { RenameType, UserGroupItem } from '@/models/setting/usergroup';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import AddUserModal from './addUserModal.vue';
|
import AddUserModal from './addUserModal.vue';
|
||||||
|
@ -94,6 +94,10 @@
|
||||||
import { getOrgUserGroupList, deleteOrgUserGroup } from '@/api/modules/setting/usergroup';
|
import { getOrgUserGroupList, deleteOrgUserGroup } from '@/api/modules/setting/usergroup';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
|
interface PopVisibleItem {
|
||||||
|
[key: string]: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const store = useUserGroupStore();
|
const store = useUserGroupStore();
|
||||||
|
|
|
@ -163,4 +163,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@/store/modules/setting/system/usergroup
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
<template>
|
|
||||||
<a-modal
|
|
||||||
v-model:visible="currentVisible"
|
|
||||||
width="680px"
|
|
||||||
:ok-text="t('system.userGroup.create')"
|
|
||||||
unmount-on-close
|
|
||||||
@cancel="handleCancel(false)"
|
|
||||||
>
|
|
||||||
<template #title> {{ t('system.userGroup.createUserGroup') }} </template>
|
|
||||||
<div class="form">
|
|
||||||
<a-form ref="formRef" :model="form" size="large" :style="{ width: '600px' }" layout="vertical">
|
|
||||||
<a-form-item
|
|
||||||
field="name"
|
|
||||||
required
|
|
||||||
:label="t('system.userGroup.userGroupName')"
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: t('system.userGroup.userGroupNameIsNotNone') },
|
|
||||||
{ validator: validateName },
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<a-input v-model="form.name" :placeholder="t('system.userGroup.pleaseInputUserGroupName')" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
field="type"
|
|
||||||
:label="t('system.userGroup.authScope')"
|
|
||||||
:rules="[{ required: true, message: t('system.userGroup.authScopeIsNotNone') }]"
|
|
||||||
>
|
|
||||||
<a-select v-model="form.type" :placeholder="t('system.userGroup.pleaseSelectAuthScope')">
|
|
||||||
<a-option value="SYSTEM">{{ t('system.userGroup.SYSTEM') }}</a-option>
|
|
||||||
<a-option value="ORGANIZATION">{{ t('system.userGroup.ORGANIZATION') }}</a-option>
|
|
||||||
<a-option value="PROJECT">{{ t('system.userGroup.PROJECT') }}</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<a-button type="secondary" :disabled="loading" @click="handleCancel(false)">
|
|
||||||
{{ t('common.cancel') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button type="primary" :loading="loading" :disabled="form.name.length === 0" @click="handleOK">
|
|
||||||
{{ t('common.add') }}
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</a-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
import { reactive, ref, watchEffect } from 'vue';
|
|
||||||
import { UserGroupItem } from '@/models/setting/usergroup';
|
|
||||||
import { Message, type FormInstance, type ValidatedError } from '@arco-design/web-vue';
|
|
||||||
import { updateOrAddUserGroup } from '@/api/modules/setting/usergroup';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const props = defineProps<{
|
|
||||||
visible: boolean;
|
|
||||||
list: UserGroupItem[];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const formRef = ref<FormInstance>();
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'cancel', shouldSearch: boolean): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const form = reactive({
|
|
||||||
name: '',
|
|
||||||
type: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const currentVisible = ref(props.visible);
|
|
||||||
|
|
||||||
const validateName = (value: string, callback: (error?: string) => void) => {
|
|
||||||
if (value !== '') {
|
|
||||||
const isExist = props.list.some((item) => item.name === value);
|
|
||||||
if (isExist) {
|
|
||||||
callback(t('system.userGroup.userGroupNameIsExist', { name: value }));
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
currentVisible.value = props.visible;
|
|
||||||
});
|
|
||||||
const handleCancel = (shouldSearch: boolean) => {
|
|
||||||
form.name = '';
|
|
||||||
form.type = '';
|
|
||||||
emit('cancel', shouldSearch);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleOK = () => {
|
|
||||||
formRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
|
||||||
if (errors) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
loading.value = true;
|
|
||||||
const res = await updateOrAddUserGroup(form);
|
|
||||||
if (res) {
|
|
||||||
Message.success(t('system.userGroup.addUserGroupSuccess'));
|
|
||||||
loading.value = false;
|
|
||||||
handleCancel(true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
<template>
|
||||||
|
<a-popover :popup-visible="currentVisible" position="bl" trigger="click" class="w-[276px]">
|
||||||
|
<template #content>
|
||||||
|
<div class="form">
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
size="large"
|
||||||
|
layout="vertical"
|
||||||
|
:label-col-props="{ span: 0 }"
|
||||||
|
:wrapper-col-props="{ span: 24 }"
|
||||||
|
>
|
||||||
|
<a-form-item>
|
||||||
|
<div class="text-[14px] text-[var(--color-text-1)]">{{
|
||||||
|
props.id ? t('system.userGroup.rename') : t('system.userGroup.createUserGroup')
|
||||||
|
}}</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="name" :rules="[{ validator: validateName }]">
|
||||||
|
<a-input
|
||||||
|
v-model="form.name"
|
||||||
|
class="w-[228px]"
|
||||||
|
:placeholder="t('system.userGroup.pleaseInputUserGroupName')"
|
||||||
|
@press-enter="handleBeforeOk"
|
||||||
|
@keyup.esc="handleCancel"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row flex-nowrap justify-end gap-2">
|
||||||
|
<a-button type="secondary" size="mini" :disabled="loading" @click="handleCancel">
|
||||||
|
{{ t('common.cancel') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
size="mini"
|
||||||
|
:loading="loading"
|
||||||
|
:disabled="form.name.length === 0"
|
||||||
|
@click="handleBeforeOk"
|
||||||
|
>
|
||||||
|
{{ props.id ? t('common.rename') : t('common.create') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<slot></slot>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { reactive, ref, watchEffect } from 'vue';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||||
|
import { updateOrAddUserGroup } from '@/api/modules/setting/usergroup';
|
||||||
|
import { UserGroupItem, AuthScopeType } from '@/models/setting/usergroup';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<{
|
||||||
|
id?: string;
|
||||||
|
list: UserGroupItem[];
|
||||||
|
visible: boolean;
|
||||||
|
defaultName?: string;
|
||||||
|
// 权限范围
|
||||||
|
authScope: AuthScopeType;
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'cancel', value: boolean): void;
|
||||||
|
(e: 'submit', currentId: string): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const currentVisible = ref(props.visible);
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const validateName = (value: string | undefined, callback: (error?: string) => void) => {
|
||||||
|
if (value === undefined || value === '') {
|
||||||
|
callback(t('system.userGroup.userGroupNameIsNotNone'));
|
||||||
|
} else {
|
||||||
|
if (value === props.defaultName) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
const isExist = props.list.some((item) => item.name === value);
|
||||||
|
if (isExist) {
|
||||||
|
callback(t('system.userGroup.userGroupNameIsExist', { name: value }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
form.name = '';
|
||||||
|
loading.value = false;
|
||||||
|
emit('cancel', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBeforeOk = () => {
|
||||||
|
formRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||||
|
if (errors) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const res = await updateOrAddUserGroup({ id: props.id, name: form.name, type: props.authScope });
|
||||||
|
if (res) {
|
||||||
|
Message.success(
|
||||||
|
props.id ? t('system.userGroup.updateUserGroupSuccess') : t('system.userGroup.addUserGroupSuccess')
|
||||||
|
);
|
||||||
|
emit('submit', res.id);
|
||||||
|
handleCancel();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
watchEffect(() => {
|
||||||
|
currentVisible.value = props.visible;
|
||||||
|
form.name = props.defaultName || '';
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,241 +0,0 @@
|
||||||
<template>
|
|
||||||
<a-input-search
|
|
||||||
allow-clear
|
|
||||||
class="w-[252px]"
|
|
||||||
:placeholder="t('system.userGroup.searchHolder')"
|
|
||||||
@press-enter="enterData"
|
|
||||||
@search="searchData"
|
|
||||||
/>
|
|
||||||
<div class="mt-2 flex flex-col">
|
|
||||||
<div class="flex h-[38px] items-center justify-between px-[8px] leading-[24px]">
|
|
||||||
<div class="text-[var(--color-text-input-border)]"> {{ t('system.userGroup.global') }}</div>
|
|
||||||
<div class="cursor-pointer text-[rgb(var(--primary-5))]"
|
|
||||||
><icon-plus-circle-fill style="font-size: 20px" @click="addUserGroup"
|
|
||||||
/></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-for="element in userGroupList"
|
|
||||||
:key="element.id"
|
|
||||||
class="flex h-[38px] cursor-pointer items-center"
|
|
||||||
:class="{ 'bg-[rgb(var(--primary-1))]': element.id === currentId }"
|
|
||||||
@click="handleListItemClick(element)"
|
|
||||||
>
|
|
||||||
<popconfirm
|
|
||||||
:visible="popVisible[element.id]"
|
|
||||||
:loading="popLoading[element.id]"
|
|
||||||
:type="popType"
|
|
||||||
:default-name="popDefaultName"
|
|
||||||
:list="userGroupList"
|
|
||||||
@cancel="() => handlePopConfirmCancel(element.id)"
|
|
||||||
@submit="(value: CustomMoreActionItem) => handlePopConfirmSubmit(value,element.id)"
|
|
||||||
>
|
|
||||||
<div class="flex grow flex-row justify-between px-[8px]">
|
|
||||||
<a-tooltip :content="element.name">
|
|
||||||
<div class="flex flex-row flex-nowrap">
|
|
||||||
<div class="one-line-text max-w-[156px] text-[var(--color-text-1)]">{{ element.name }}</div>
|
|
||||||
<div v-if="element.type" class="text-[var(--color-text-4)]"
|
|
||||||
>({{ t(`system.userGroup.${element.type}`) }})</div
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</a-tooltip>
|
|
||||||
<div v-if="element.id === currentId && !element.internal">
|
|
||||||
<MsTableMoreAction :list="customAction" @select="(value) => handleMoreAction(value, element.id)" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</popconfirm>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<AddUserModal :visible="addUserVisible" @cancel="addUserVisible = false" />
|
|
||||||
<AddUserGroupModal :list="userGroupList" :visible="addUserGroupVisible" @cancel="handleAddUserGroupModalCancel" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, onMounted } from 'vue';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
import { CustomMoreActionItem, PopVisibleItem, RenameType, UserGroupItem } from '@/models/setting/usergroup';
|
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
|
||||||
import AddUserModal from './addUserModal.vue';
|
|
||||||
import AddUserGroupModal from './addUserGroupModal.vue';
|
|
||||||
import useModal from '@/hooks/useModal';
|
|
||||||
import { Message } from '@arco-design/web-vue';
|
|
||||||
import popconfirm from './popconfirm.vue';
|
|
||||||
import useUserGroupStore from '@/store/modules/setting/system/usergroup';
|
|
||||||
import { getUserGroupList, updateOrAddUserGroup, deleteUserGroup } from '@/api/modules/setting/usergroup';
|
|
||||||
import { characterLimit } from '@/utils';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const store = useUserGroupStore();
|
|
||||||
const { openModal } = useModal();
|
|
||||||
// 请求loading
|
|
||||||
const currentId = ref('');
|
|
||||||
const addUserVisible = ref(false);
|
|
||||||
const addUserGroupVisible = ref(false);
|
|
||||||
// 修改用户组名字,权限范围
|
|
||||||
const popVisible = ref<PopVisibleItem>({});
|
|
||||||
const popLoading = ref<PopVisibleItem>({});
|
|
||||||
// 用户组和权限范围的状态
|
|
||||||
const popType = ref<RenameType>('rename');
|
|
||||||
const popDefaultName = ref('');
|
|
||||||
// 用户列表
|
|
||||||
const userGroupList = ref<UserGroupItem[]>([]);
|
|
||||||
|
|
||||||
const customAction: ActionsItem[] = [
|
|
||||||
{
|
|
||||||
label: 'system.userGroup.rename',
|
|
||||||
danger: false,
|
|
||||||
eventTag: 'rename',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isDivider: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'system.userGroup.delete',
|
|
||||||
danger: true,
|
|
||||||
eventTag: 'delete',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// 点击用户组列表
|
|
||||||
const handleListItemClick = (element: UserGroupItem) => {
|
|
||||||
const { id, name, type, internal } = element;
|
|
||||||
currentId.value = id;
|
|
||||||
store.setInfo({
|
|
||||||
currentName: name,
|
|
||||||
currentTitle: type,
|
|
||||||
currentId: id,
|
|
||||||
currentType: type,
|
|
||||||
currentInternal: internal,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 用户组数据初始化
|
|
||||||
const initData = async () => {
|
|
||||||
try {
|
|
||||||
const res = await getUserGroupList();
|
|
||||||
if (res.length > 0) {
|
|
||||||
userGroupList.value = res;
|
|
||||||
handleListItemClick(res[0]);
|
|
||||||
// 弹窗赋值
|
|
||||||
const tmpObj: PopVisibleItem = {};
|
|
||||||
res.forEach((element) => {
|
|
||||||
tmpObj[element.id] = false;
|
|
||||||
});
|
|
||||||
popVisible.value = { ...tmpObj };
|
|
||||||
popLoading.value = { ...tmpObj };
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 新增用户组
|
|
||||||
const addUserGroup = () => {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
addUserGroupVisible.value = true;
|
|
||||||
};
|
|
||||||
// 点击更多操作
|
|
||||||
const handleMoreAction = (item: ActionsItem, id: string) => {
|
|
||||||
if (item.eventTag !== 'delete') {
|
|
||||||
popType.value = item.eventTag as RenameType;
|
|
||||||
const tmpObj = userGroupList.value.filter((ele) => ele.id === id)[0];
|
|
||||||
popVisible.value = { ...popVisible.value, [id]: true };
|
|
||||||
if (item.eventTag === 'rename') {
|
|
||||||
popDefaultName.value = tmpObj.name;
|
|
||||||
} else {
|
|
||||||
popDefaultName.value = tmpObj.scopeId;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
openModal({
|
|
||||||
type: 'error',
|
|
||||||
title: t('system.userGroup.isDeleteUserGroup', { name: characterLimit(store.currentName) }),
|
|
||||||
content: t('system.userGroup.beforeDeleteUserGroup'),
|
|
||||||
okText: t('system.userGroup.confirmDelete'),
|
|
||||||
cancelText: t('system.userGroup.cancel'),
|
|
||||||
okButtonProps: {
|
|
||||||
status: 'danger',
|
|
||||||
},
|
|
||||||
onBeforeOk: async () => {
|
|
||||||
try {
|
|
||||||
await deleteUserGroup(id);
|
|
||||||
Message.success(t('system.user.deleteUserSuccess'));
|
|
||||||
initData();
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hideCancel: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭confirm 弹窗
|
|
||||||
const handlePopConfirmCancel = (id: string) => {
|
|
||||||
popVisible.value = { ...popVisible.value, [id]: false };
|
|
||||||
};
|
|
||||||
// 修改用户组名字,权限范围
|
|
||||||
const handlePopConfirmSubmit = async (item: CustomMoreActionItem, id: string) => {
|
|
||||||
if (item.eventKey === 'rename') {
|
|
||||||
// 修改用户组名字
|
|
||||||
try {
|
|
||||||
popLoading.value = { ...popLoading.value, [id]: true };
|
|
||||||
const res = await updateOrAddUserGroup({ id, name: item.name });
|
|
||||||
if (res) {
|
|
||||||
initData();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
} finally {
|
|
||||||
popLoading.value = { ...popLoading.value, [id]: false };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 修改权限范围
|
|
||||||
try {
|
|
||||||
const res = await updateOrAddUserGroup({ id, scopeId: item.name });
|
|
||||||
if (res) {
|
|
||||||
initData();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
popVisible.value = { ...popVisible.value, [id]: false };
|
|
||||||
initData();
|
|
||||||
};
|
|
||||||
|
|
||||||
function enterData(eve: Event) {
|
|
||||||
if (!(eve.target as HTMLInputElement).value) {
|
|
||||||
initData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const keyword = (eve.target as HTMLInputElement).value;
|
|
||||||
const tmpArr = userGroupList.value.filter((ele) => ele.name.includes(keyword));
|
|
||||||
userGroupList.value = tmpArr;
|
|
||||||
}
|
|
||||||
function searchData(value: string) {
|
|
||||||
if (!value) {
|
|
||||||
initData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const keyword = value;
|
|
||||||
const tmpArr = userGroupList.value.filter((ele) => ele.name.includes(keyword));
|
|
||||||
userGroupList.value = tmpArr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAddUserGroupModalCancel = (shouldSearch: boolean) => {
|
|
||||||
addUserGroupVisible.value = false;
|
|
||||||
if (shouldSearch) {
|
|
||||||
initData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
initData();
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -0,0 +1,454 @@
|
||||||
|
<template>
|
||||||
|
<a-input-search
|
||||||
|
class="w-[252px]"
|
||||||
|
:placeholder="t('system.userGroup.searchHolder')"
|
||||||
|
allow-clear
|
||||||
|
@press-enter="enterData"
|
||||||
|
@search="searchData"
|
||||||
|
/>
|
||||||
|
<div class="mt-2">
|
||||||
|
<CreateUserGroupPopup
|
||||||
|
:list="systemUserGroupList"
|
||||||
|
:visible="systemUserGroupVisible"
|
||||||
|
auth-scope="SYSTEM"
|
||||||
|
@cancel="systemUserGroupVisible = false"
|
||||||
|
@submit="handleCreateUserGroup"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between px-[4px] py-[7px]">
|
||||||
|
<div class="flex flex-row items-center gap-1 text-[var(--color-text-4)]">
|
||||||
|
<MsIcon
|
||||||
|
v-if="systemToggle"
|
||||||
|
class="cursor-pointer"
|
||||||
|
type="icon-icon_expand-down_filled"
|
||||||
|
size="12"
|
||||||
|
@click="systemToggle = false"
|
||||||
|
/>
|
||||||
|
<MsIcon
|
||||||
|
v-else
|
||||||
|
class="cursor-pointer"
|
||||||
|
type="icon-icon_expand-right_filled"
|
||||||
|
size="12"
|
||||||
|
@click="systemToggle = true"
|
||||||
|
/>
|
||||||
|
<div class="text-[14px]">
|
||||||
|
{{ t('system.userGroup.systemUserGroup') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<MsMoreAction :list="createSystemUGActionItem" @select="systemUserGroupVisible = true">
|
||||||
|
<icon-plus-circle-fill class="text-[rgb(var(--primary-7))]" size="20" />
|
||||||
|
</MsMoreAction>
|
||||||
|
</div>
|
||||||
|
</CreateUserGroupPopup>
|
||||||
|
<Transition>
|
||||||
|
<div v-if="systemToggle">
|
||||||
|
<div
|
||||||
|
v-for="element in systemUserGroupList"
|
||||||
|
:key="element.id"
|
||||||
|
class="flex h-[38px] cursor-pointer items-center py-[7px] pl-[20px] pr-[4px]"
|
||||||
|
:class="{ 'bg-[rgb(var(--primary-1))]': element.id === currentId }"
|
||||||
|
@click="handleListItemClick(element)"
|
||||||
|
>
|
||||||
|
<CreateUserGroupPopup
|
||||||
|
:list="systemUserGroupList"
|
||||||
|
v-bind="popVisible[element.id]"
|
||||||
|
@cancel="handleRenameCancel(element)"
|
||||||
|
@submit="handleRenameCancel(element, element.id)"
|
||||||
|
>
|
||||||
|
<div class="flex grow flex-row items-center justify-between">
|
||||||
|
<a-tooltip :content="element.name">
|
||||||
|
<div
|
||||||
|
class="one-line-text max-w-[156px] text-[var(--color-text-1)]"
|
||||||
|
:class="{ 'text-[rgb(var(--primary-7))]': element.id === currentId }"
|
||||||
|
>{{ element.name }}</div
|
||||||
|
>
|
||||||
|
</a-tooltip>
|
||||||
|
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
||||||
|
<MsMoreAction :list="addMemberActionItem" @select="handleAddMember">
|
||||||
|
<div class="icon-button">
|
||||||
|
<MsIcon type="icon-icon_add_outlined" size="16" />
|
||||||
|
</div>
|
||||||
|
</MsMoreAction>
|
||||||
|
<MsMoreAction :list="moreAction" @select="(value) => handleMoreAction(value, element.id, 'SYSTEM')">
|
||||||
|
<div class="icon-button">
|
||||||
|
<MsIcon type="icon-icon_more_outlined" size="16" />
|
||||||
|
</div>
|
||||||
|
</MsMoreAction>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CreateUserGroupPopup>
|
||||||
|
</div>
|
||||||
|
<a-divider class="my-[0px] mt-[6px]" />
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<CreateUserGroupPopup
|
||||||
|
:list="orgUserGroupList"
|
||||||
|
:visible="orgUserGroupVisible"
|
||||||
|
auth-scope="ORGANIZATION"
|
||||||
|
@cancel="orgUserGroupVisible = false"
|
||||||
|
@submit="handleCreateUserGroup"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between px-[4px] py-[7px]">
|
||||||
|
<div class="flex flex-row items-center gap-1 text-[var(--color-text-4)]">
|
||||||
|
<MsIcon
|
||||||
|
v-if="orgToggle"
|
||||||
|
class="cursor-pointer"
|
||||||
|
type="icon-icon_expand-down_filled"
|
||||||
|
size="12"
|
||||||
|
@click="orgToggle = false"
|
||||||
|
/>
|
||||||
|
<MsIcon
|
||||||
|
v-else
|
||||||
|
class="cursor-pointer"
|
||||||
|
type="icon-icon_expand-right_filled"
|
||||||
|
size="12"
|
||||||
|
@click="orgToggle = true"
|
||||||
|
/>
|
||||||
|
<div class="text-[14px]">
|
||||||
|
{{ t('system.userGroup.orgUserGroup') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<MsMoreAction :list="createOrgUGActionItem" @select="orgUserGroupVisible = true">
|
||||||
|
<icon-plus-circle-fill class="text-[rgb(var(--primary-7))]" size="20" />
|
||||||
|
</MsMoreAction>
|
||||||
|
</div>
|
||||||
|
</CreateUserGroupPopup>
|
||||||
|
<Transition>
|
||||||
|
<div v-if="orgToggle">
|
||||||
|
<div
|
||||||
|
v-for="element in orgUserGroupList"
|
||||||
|
:key="element.id"
|
||||||
|
class="flex h-[38px] cursor-pointer items-center py-[7px] pl-[20px] pr-[4px]"
|
||||||
|
:class="{ 'bg-[rgb(var(--primary-1))]': element.id === currentId }"
|
||||||
|
@click="handleListItemClick(element)"
|
||||||
|
>
|
||||||
|
<CreateUserGroupPopup
|
||||||
|
:list="orgUserGroupList"
|
||||||
|
v-bind="popVisible[element.id]"
|
||||||
|
@cancel="handleRenameCancel(element)"
|
||||||
|
@submit="handleRenameCancel(element, element.id)"
|
||||||
|
>
|
||||||
|
<div class="flex grow flex-row items-center justify-between">
|
||||||
|
<a-tooltip :content="element.name">
|
||||||
|
<div
|
||||||
|
class="one-line-text max-w-[156px] text-[var(--color-text-1)]"
|
||||||
|
:class="{ 'text-[rgb(var(--primary-7))]': element.id === currentId }"
|
||||||
|
>{{ element.name }}</div
|
||||||
|
>
|
||||||
|
</a-tooltip>
|
||||||
|
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
||||||
|
<MsMoreAction :list="addMemberActionItem" @select="handleAddMember">
|
||||||
|
<div class="icon-button">
|
||||||
|
<MsIcon type="icon-icon_add_outlined" size="16" />
|
||||||
|
</div>
|
||||||
|
</MsMoreAction>
|
||||||
|
<MsMoreAction
|
||||||
|
:list="moreAction"
|
||||||
|
@select="(value) => handleMoreAction(value, element.id, 'ORGANIZATION')"
|
||||||
|
>
|
||||||
|
<div class="icon-button">
|
||||||
|
<MsIcon type="icon-icon_more_outlined" size="16" />
|
||||||
|
</div>
|
||||||
|
</MsMoreAction>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CreateUserGroupPopup>
|
||||||
|
</div>
|
||||||
|
<a-divider class="my-[0px] mt-[6px]" />
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2">
|
||||||
|
<CreateUserGroupPopup
|
||||||
|
:list="projectUserGroupList"
|
||||||
|
:visible="projectUserGroupVisible"
|
||||||
|
auth-scope="PROJECT"
|
||||||
|
@cancel="projectUserGroupVisible = false"
|
||||||
|
@submit="handleCreateUserGroup"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between px-[4px] py-[7px]">
|
||||||
|
<div class="flex flex-row items-center gap-1 text-[var(--color-text-4)]">
|
||||||
|
<MsIcon
|
||||||
|
v-if="projectToggle"
|
||||||
|
class="cursor-pointer"
|
||||||
|
type="icon-icon_expand-down_filled"
|
||||||
|
size="12"
|
||||||
|
@click="projectToggle = false"
|
||||||
|
/>
|
||||||
|
<MsIcon
|
||||||
|
v-else
|
||||||
|
class="cursor-pointer"
|
||||||
|
type="icon-icon_expand-right_filled"
|
||||||
|
size="12"
|
||||||
|
@click="projectToggle = true"
|
||||||
|
/>
|
||||||
|
<div class="text-[14px]">
|
||||||
|
{{ t('system.userGroup.projectUserGroup') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<MsMoreAction :list="createProjectUGActionItem" @select="projectUserGroupVisible = true">
|
||||||
|
<icon-plus-circle-fill class="text-[rgb(var(--primary-7))]" size="20" />
|
||||||
|
</MsMoreAction>
|
||||||
|
</div>
|
||||||
|
</CreateUserGroupPopup>
|
||||||
|
<Transition>
|
||||||
|
<div v-if="projectToggle">
|
||||||
|
<div
|
||||||
|
v-for="element in projectUserGroupList"
|
||||||
|
:key="element.id"
|
||||||
|
class="flex h-[38px] cursor-pointer items-center py-[7px] pl-[20px] pr-[4px]"
|
||||||
|
:class="{ 'bg-[rgb(var(--primary-1))]': element.id === currentId }"
|
||||||
|
@click="handleListItemClick(element)"
|
||||||
|
>
|
||||||
|
<CreateUserGroupPopup
|
||||||
|
:list="projectUserGroupList"
|
||||||
|
v-bind="popVisible[element.id]"
|
||||||
|
@cancel="handleRenameCancel(element)"
|
||||||
|
@submit="handleRenameCancel(element, element.id)"
|
||||||
|
>
|
||||||
|
<div class="flex grow flex-row items-center justify-between">
|
||||||
|
<a-tooltip :content="element.name">
|
||||||
|
<div
|
||||||
|
class="one-line-text max-w-[156px] text-[var(--color-text-1)]"
|
||||||
|
:class="{ 'text-[rgb(var(--primary-7))]': element.id === currentId }"
|
||||||
|
>{{ element.name }}</div
|
||||||
|
>
|
||||||
|
</a-tooltip>
|
||||||
|
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
||||||
|
<MsMoreAction :list="addMemberActionItem" @select="handleAddMember">
|
||||||
|
<div class="icon-button">
|
||||||
|
<MsIcon type="icon-icon_add_outlined" size="16" />
|
||||||
|
</div>
|
||||||
|
</MsMoreAction>
|
||||||
|
<MsMoreAction :list="moreAction" @select="(value) => handleMoreAction(value, element.id, 'PROJECT')">
|
||||||
|
<div class="icon-button">
|
||||||
|
<MsIcon type="icon-icon_more_outlined" size="16" />
|
||||||
|
</div>
|
||||||
|
</MsMoreAction>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CreateUserGroupPopup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<AddUserModal :visible="userModalVisible" @cancel="userModalVisible = false" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import MsMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
|
import { UserGroupItem, PopVisible, PopVisibleItem, AuthScopeType } from '@/models/setting/usergroup';
|
||||||
|
import { getUserGroupList, deleteUserGroup } from '@/api/modules/setting/usergroup';
|
||||||
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
import CreateUserGroupPopup from './createOrUpdateUserGroup.vue';
|
||||||
|
import AddUserModal from './addUserModal.vue';
|
||||||
|
import useUserGroupStore from '@/store/modules/setting/system/usergroup';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import useModal from '@/hooks/useModal';
|
||||||
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const store = useUserGroupStore();
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
// 用户组列表
|
||||||
|
const userGroupList = ref<UserGroupItem[]>([]);
|
||||||
|
|
||||||
|
const currentId = ref('');
|
||||||
|
|
||||||
|
const userModalVisible = ref(false);
|
||||||
|
|
||||||
|
// 气泡弹窗
|
||||||
|
const popVisible = ref<PopVisible>({});
|
||||||
|
|
||||||
|
// 系统用户创建用户组visible
|
||||||
|
const systemUserGroupVisible = ref(false);
|
||||||
|
// 组织用户创建用户组visible
|
||||||
|
const orgUserGroupVisible = ref(false);
|
||||||
|
// 项目用户创建用户组visible
|
||||||
|
const projectUserGroupVisible = ref(false);
|
||||||
|
|
||||||
|
// 系统用户组Toggle
|
||||||
|
const systemToggle = ref(true);
|
||||||
|
// 组织用户组Toggle
|
||||||
|
const orgToggle = ref(true);
|
||||||
|
// 项目用户组Toggle
|
||||||
|
const projectToggle = ref(true);
|
||||||
|
|
||||||
|
// 系统用户组列表
|
||||||
|
const systemUserGroupList = computed(() => {
|
||||||
|
return userGroupList.value.filter((ele) => ele.type === 'SYSTEM');
|
||||||
|
});
|
||||||
|
// 组织用户组列表
|
||||||
|
const orgUserGroupList = computed(() => {
|
||||||
|
return userGroupList.value.filter((ele) => ele.type === 'ORGANIZATION');
|
||||||
|
});
|
||||||
|
// 项目用户组列表
|
||||||
|
const projectUserGroupList = computed(() => {
|
||||||
|
return userGroupList.value.filter((ele) => ele.type === 'PROJECT');
|
||||||
|
});
|
||||||
|
|
||||||
|
const createSystemUGActionItem: ActionsItem[] = [
|
||||||
|
{ label: 'system.userGroup.addSysUserGroup', eventTag: 'createUserGroup' },
|
||||||
|
];
|
||||||
|
const createOrgUGActionItem: ActionsItem[] = [
|
||||||
|
{ label: 'system.userGroup.addOrgUserGroup', eventTag: 'createUserGroup' },
|
||||||
|
];
|
||||||
|
const createProjectUGActionItem: ActionsItem[] = [
|
||||||
|
{ label: 'system.userGroup.addProjectUserGroup', eventTag: 'createUserGroup' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const addMemberActionItem: ActionsItem[] = [{ label: 'system.userGroup.addMember', eventTag: 'addMember' }];
|
||||||
|
const moreAction: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.rename',
|
||||||
|
danger: false,
|
||||||
|
eventTag: 'rename',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.delete',
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 点击用户组列表
|
||||||
|
const handleListItemClick = (element: UserGroupItem) => {
|
||||||
|
const { id, name, type, internal } = element;
|
||||||
|
currentId.value = id;
|
||||||
|
store.setInfo({
|
||||||
|
currentName: name,
|
||||||
|
currentTitle: type,
|
||||||
|
currentId: id,
|
||||||
|
currentType: type,
|
||||||
|
currentInternal: internal,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用户组数据初始化
|
||||||
|
const initData = async (id?: string) => {
|
||||||
|
try {
|
||||||
|
const res = await getUserGroupList();
|
||||||
|
if (res.length > 0) {
|
||||||
|
userGroupList.value = res;
|
||||||
|
let tmpItem = res[0];
|
||||||
|
if (id) {
|
||||||
|
tmpItem = res.find((i) => i.id === id) || res[0];
|
||||||
|
}
|
||||||
|
handleListItemClick(tmpItem);
|
||||||
|
// 弹窗赋值
|
||||||
|
const tmpObj: PopVisible = {};
|
||||||
|
res.forEach((element) => {
|
||||||
|
tmpObj[element.id] = { visible: false, authScope: element.type, defaultName: '', id: element.id };
|
||||||
|
});
|
||||||
|
popVisible.value = tmpObj;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击更多操作
|
||||||
|
const handleMoreAction = (item: ActionsItem, id: string, authScope: AuthScopeType) => {
|
||||||
|
if (item.eventTag === 'rename') {
|
||||||
|
const tmpObj = userGroupList.value.filter((ele) => ele.id === id)[0];
|
||||||
|
const visibleItem: PopVisibleItem = { visible: true, authScope, defaultName: tmpObj.name, id };
|
||||||
|
popVisible.value[id] = visibleItem;
|
||||||
|
}
|
||||||
|
if (item.eventTag === 'delete') {
|
||||||
|
openModal({
|
||||||
|
type: 'error',
|
||||||
|
title: t('system.userGroup.isDeleteUserGroup', { name: characterLimit(store.currentName) }),
|
||||||
|
content: t('system.userGroup.beforeDeleteUserGroup'),
|
||||||
|
okText: t('system.userGroup.confirmDelete'),
|
||||||
|
cancelText: t('system.userGroup.cancel'),
|
||||||
|
okButtonProps: {
|
||||||
|
status: 'danger',
|
||||||
|
},
|
||||||
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
await deleteUserGroup(id);
|
||||||
|
Message.success(t('system.user.deleteUserSuccess'));
|
||||||
|
initData();
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideCancel: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击添加成员
|
||||||
|
const handleAddMember = () => {
|
||||||
|
userModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
function enterData(eve: Event) {
|
||||||
|
if (!(eve.target as HTMLInputElement).value) {
|
||||||
|
initData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const keyword = (eve.target as HTMLInputElement).value;
|
||||||
|
const tmpArr = userGroupList.value.filter((ele) => ele.name.includes(keyword));
|
||||||
|
userGroupList.value = tmpArr;
|
||||||
|
}
|
||||||
|
function searchData(value: string) {
|
||||||
|
if (!value) {
|
||||||
|
initData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const keyword = value;
|
||||||
|
const tmpArr = userGroupList.value.filter((ele) => ele.name.includes(keyword));
|
||||||
|
userGroupList.value = tmpArr;
|
||||||
|
}
|
||||||
|
const handleCreateUserGroup = (id: string) => {
|
||||||
|
initData(id);
|
||||||
|
};
|
||||||
|
const handleRenameCancel = (element: UserGroupItem, id?: string) => {
|
||||||
|
if (id) {
|
||||||
|
initData(id);
|
||||||
|
}
|
||||||
|
popVisible.value[element.id].visible = false;
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
initData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.icon-increase {
|
||||||
|
background-color: rgb(var(--primary-7));
|
||||||
|
}
|
||||||
|
.icon-button {
|
||||||
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: rgb(var(--primary-7));
|
||||||
|
}
|
||||||
|
.icon-button:hover {
|
||||||
|
background-color: rgb(var(--primary-9));
|
||||||
|
}
|
||||||
|
.v-enter-active,
|
||||||
|
.v-leave-active {
|
||||||
|
transition: opacity 0.5s ease;
|
||||||
|
}
|
||||||
|
.v-enter-from,
|
||||||
|
.v-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,142 +0,0 @@
|
||||||
<template>
|
|
||||||
<a-popconfirm
|
|
||||||
:popup-visible="renameVisible"
|
|
||||||
:ok-text="t('system.userGroup.confirm')"
|
|
||||||
:cancel-text="t('system.userGroup.cancel')"
|
|
||||||
:ok-loading="props.loading"
|
|
||||||
:cancel-button-props="{ disabled: loading }"
|
|
||||||
class="w-[276px]"
|
|
||||||
position="bl"
|
|
||||||
@before-ok="handleSubmit"
|
|
||||||
@cancel="handleCancel"
|
|
||||||
@popup-visible-change="() => (form.name = '')"
|
|
||||||
>
|
|
||||||
<template #icon>{{ null }}</template>
|
|
||||||
<template #content>
|
|
||||||
<a-form ref="formRef" :model="form" :label-col-props="{ span: 0 }" :wrapper-col-props="{ span: 24 }">
|
|
||||||
<a-form-item>
|
|
||||||
<div class="title">{{ message.title }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="name" :rules="[{ validator: validateName }]">
|
|
||||||
<a-input v-if="props.type === 'rename'" v-model="form.name" class="w-[234px]" />
|
|
||||||
<a-select v-else v-model="form.name" class="w-[176px]">
|
|
||||||
<a-option value="SYSTEM">{{ t('system.userGroup.SYSTEM') }}</a-option>
|
|
||||||
<a-option value="ORGANIZATION">{{ t('system.userGroup.ORGANIZATION') }}</a-option>
|
|
||||||
<a-option value="PROJECT">{{ t('system.userGroup.PROJECT') }}</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</template>
|
|
||||||
<slot></slot>
|
|
||||||
</a-popconfirm>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
import { watchEffect, ref, computed, onUnmounted } from 'vue';
|
|
||||||
import { CustomMoreActionItem, RenameType, UserGroupItem } from '@/models/setting/usergroup';
|
|
||||||
import { ValidatedError } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const formRef = ref();
|
|
||||||
const form = ref({
|
|
||||||
name: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
visible: boolean;
|
|
||||||
defaultName: string;
|
|
||||||
type: RenameType;
|
|
||||||
list: UserGroupItem[];
|
|
||||||
loading: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const validateName = (value: string | undefined, callback: (error?: string) => void) => {
|
|
||||||
if (props.type === 'rename') {
|
|
||||||
if (value === undefined || value === '') {
|
|
||||||
callback(t('system.userGroup.userGroupNameIsNotNone'));
|
|
||||||
} else {
|
|
||||||
if (value === props.defaultName) {
|
|
||||||
callback();
|
|
||||||
} else {
|
|
||||||
const isExist = props.list.some((item) => item.name === value);
|
|
||||||
if (isExist) {
|
|
||||||
callback(t('system.userGroup.userGroupNameIsExist', { name: value }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
} else if (value === '') {
|
|
||||||
callback(t('system.userGroup.userGroupAuthScopeIsNotNone'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const message = computed(() => {
|
|
||||||
if (props.type === 'rename') {
|
|
||||||
return {
|
|
||||||
rule: t('system.userGroup.userGroupNameIsNotNone'),
|
|
||||||
title: t('system.userGroup.rename'),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
rule: t('system.userGroup.userGroupAuthScopeIsNotNone'),
|
|
||||||
title: t('system.userGroup.changeAuthScope'),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'submit', value: CustomMoreActionItem): Promise<void>;
|
|
||||||
(e: 'cancel'): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const renameVisible = ref(props.visible);
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
await formRef.value.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
|
||||||
if (!errors) {
|
|
||||||
emit('submit', { eventKey: props.type, name: form.value.name });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
|
||||||
form.value.name = '';
|
|
||||||
emit('cancel');
|
|
||||||
};
|
|
||||||
watchEffect(() => {
|
|
||||||
renameVisible.value = props.visible;
|
|
||||||
form.value.name = props.defaultName;
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
handleCancel();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.title {
|
|
||||||
color: var(--color-text-1);
|
|
||||||
}
|
|
||||||
.error-6 {
|
|
||||||
color: rgb(var(--danger-6));
|
|
||||||
&:hover {
|
|
||||||
color: rgb(var(--danger-6));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:deep(.arco-form-item) {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
.button-icon {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
color: rgb(var(--primary-5));
|
|
||||||
background-color: rgb(var(--primary-9));
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@/models/setting/usergroup
|
|
|
@ -52,7 +52,7 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
import useUserGroupStore from '@/store/modules/setting/system/usergroup';
|
import useUserGroupStore from '@/store/modules/setting/system/usergroup';
|
||||||
import UserGroupLeft from './components/index.vue';
|
import UserGroupLeft from './components/ms-usergroup-list.vue';
|
||||||
import UserTable from './components/userTable.vue';
|
import UserTable from './components/userTable.vue';
|
||||||
import AuthTable from './components/authTable.vue';
|
import AuthTable from './components/authTable.vue';
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
|
|
@ -4,11 +4,14 @@ export default {
|
||||||
addUserGroupSuccess: 'Add user group success',
|
addUserGroupSuccess: 'Add user group success',
|
||||||
updateUserGroupSuccess: 'Update user group success',
|
updateUserGroupSuccess: 'Update user group success',
|
||||||
searchHolder: 'Please input user group name',
|
searchHolder: 'Please input user group name',
|
||||||
|
systemUserGroup: 'System user group',
|
||||||
inSystem: 'In system',
|
inSystem: 'In system',
|
||||||
customUserGroup: 'Custom user group',
|
customUserGroup: 'Custom user group',
|
||||||
addSystemUserGroup: 'Add system user group',
|
addSystemUserGroup: 'Add system user group',
|
||||||
addSystemUser: 'Add system user',
|
addSystemUser: 'Add system user',
|
||||||
addUser: 'Add user',
|
addUser: 'Add user',
|
||||||
|
addMember: 'Add member',
|
||||||
|
createUserGroup: 'Create user group',
|
||||||
emptyUserGroup:
|
emptyUserGroup:
|
||||||
'There are currently no custom user groups available. Please click "Create" or "+" above to create a user group',
|
'There are currently no custom user groups available. Please click "Create" or "+" above to create a user group',
|
||||||
rename: 'Rename',
|
rename: 'Rename',
|
||||||
|
@ -18,7 +21,6 @@ export default {
|
||||||
add: 'Add',
|
add: 'Add',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
create: 'Create',
|
create: 'Create',
|
||||||
createUserGroup: 'create user group',
|
|
||||||
userGroupName: 'User group name',
|
userGroupName: 'User group name',
|
||||||
authScope: 'Auth scope',
|
authScope: 'Auth scope',
|
||||||
auth: 'Auth',
|
auth: 'Auth',
|
||||||
|
@ -58,6 +60,11 @@ export default {
|
||||||
removeName: 'Confirm to remove {name} this user',
|
removeName: 'Confirm to remove {name} this user',
|
||||||
removeTip: 'After removal, the User Group permission will be lost',
|
removeTip: 'After removal, the User Group permission will be lost',
|
||||||
custom: 'Custom user group',
|
custom: 'Custom user group',
|
||||||
|
projectUserGroup: 'Project user group',
|
||||||
|
orgUserGroup: 'Organization user group',
|
||||||
|
addSysUserGroup: 'Add system user group',
|
||||||
|
addOrgUserGroup: 'Add organization user group',
|
||||||
|
addProjectUserGroup: 'Add project user group',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
|
|
|
@ -3,6 +3,7 @@ export default {
|
||||||
userGroup: {
|
userGroup: {
|
||||||
addUserGroupSuccess: '添加用户组成功',
|
addUserGroupSuccess: '添加用户组成功',
|
||||||
updateUserGroupSuccess: '更新用户组成功',
|
updateUserGroupSuccess: '更新用户组成功',
|
||||||
|
systemUserGroup: '系统用户组',
|
||||||
global: '全局用户组',
|
global: '全局用户组',
|
||||||
searchHolder: '请输入用户组名称',
|
searchHolder: '请输入用户组名称',
|
||||||
inSystem: '系统内置',
|
inSystem: '系统内置',
|
||||||
|
@ -10,6 +11,7 @@ export default {
|
||||||
addSystemUserGroup: '添加系统用户组',
|
addSystemUserGroup: '添加系统用户组',
|
||||||
addSystemUser: '添加系统用户',
|
addSystemUser: '添加系统用户',
|
||||||
addUser: '添加成员',
|
addUser: '添加成员',
|
||||||
|
addMember: '添加成员',
|
||||||
emptyUserGroup: '暂无自定义用户组,请点击上方创建或 “+” 创建用户组',
|
emptyUserGroup: '暂无自定义用户组,请点击上方创建或 “+” 创建用户组',
|
||||||
rename: '重命名',
|
rename: '重命名',
|
||||||
changeAuthScope: '修改权限范围',
|
changeAuthScope: '修改权限范围',
|
||||||
|
@ -57,6 +59,11 @@ export default {
|
||||||
removeName: '确认移除 {name} 这个用户吗',
|
removeName: '确认移除 {name} 这个用户吗',
|
||||||
removeTip: '移除后,将失去用户组权限',
|
removeTip: '移除后,将失去用户组权限',
|
||||||
custom: '自定义用户组',
|
custom: '自定义用户组',
|
||||||
|
projectUserGroup: '项目用户组',
|
||||||
|
orgUserGroup: '组织用户组',
|
||||||
|
addSysUserGroup: '添加系统用户组',
|
||||||
|
addOrgUserGroup: '添加组织用户组',
|
||||||
|
addProjectUserGroup: '添加项目用户组',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
|
|
Loading…
Reference in New Issue