feat(系统设置): 系统用户组管理接口对接
This commit is contained in:
parent
cc2a6b9140
commit
3a9ef7bef1
|
@ -37,7 +37,7 @@
|
|||
"@7polo/kity": "2.0.8",
|
||||
"@7polo/kityminder-core": "1.4.53",
|
||||
"@arco-design/web-vue": "^2.47.0",
|
||||
"@arco-themes/vue-ms-theme-default": "^0.0.14",
|
||||
"@arco-themes/vue-ms-theme-default": "^0.0.15",
|
||||
"@form-create/arco-design": "^3.1.21",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"ace-builds": "^1.22.0",
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
import MSR from '@/api/http/index';
|
||||
import { updateUserGroupU, getUserGroupU, addUserGroupU, deleteUserGroupU } from '@/api/requrls/system/usergroup';
|
||||
// import { QueryParams, CommonList } from '@/models/common';
|
||||
import { UserGroupItem } from '@/models/system/usergroup';
|
||||
import {
|
||||
updateUserGroupU,
|
||||
getUserGroupU,
|
||||
addUserGroupU,
|
||||
deleteUserGroupU,
|
||||
getGlobalUSettingUrl,
|
||||
editGlobalUSettingUrl,
|
||||
postUserByUserGroupUrl,
|
||||
deleteUserFromUserGroupUrl,
|
||||
} from '@/api/requrls/system/usergroup';
|
||||
import { TableQueryParams, CommonList } from '@/models/common';
|
||||
import { UserGroupItem, UserGroupAuthSeting, SaveGlobalUSettingData, UserTableItem } from '@/models/system/usergroup';
|
||||
|
||||
export function updateOrAddUserGroup(data: Partial<UserGroupItem>) {
|
||||
return MSR.post<UserGroupItem>({
|
||||
|
@ -28,3 +37,19 @@ export function deleteUserGroup(id: string) {
|
|||
export function getUsergroupInfo(id: string) {
|
||||
return MSR.get<UserGroupItem>({ url: `${getUserGroupU}${id}` });
|
||||
}
|
||||
|
||||
export function getGlobalUSetting(id: string) {
|
||||
return MSR.get<UserGroupAuthSeting[]>({ url: `${getGlobalUSettingUrl}${id}` });
|
||||
}
|
||||
|
||||
export function saveGlobalUSetting(data: SaveGlobalUSettingData) {
|
||||
return MSR.post<UserGroupAuthSeting[]>({ url: editGlobalUSettingUrl, data });
|
||||
}
|
||||
|
||||
export function postUserByUserGroup(data: TableQueryParams) {
|
||||
return MSR.post<CommonList<UserTableItem[]>>({ url: postUserByUserGroupUrl, data });
|
||||
}
|
||||
|
||||
export function deleteUserFromUserGroup(id: string) {
|
||||
return MSR.get<string>({ url: `${deleteUserFromUserGroupUrl}${id}` });
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/** 修改用户组 */
|
||||
export const updateUserGroupU = `/user/role/global/update`;
|
||||
/** 编辑用户组对应的权限配置 */
|
||||
export const editGlobalUSetting = `/user/role/global/permission/update`;
|
||||
export const editGlobalUSettingUrl = `/user/role/global/permission/update`;
|
||||
/** 添加用户组 */
|
||||
export const addUserGroupU = `/user/role/global/add`;
|
||||
/** 获取用户组对应的权限配置 */
|
||||
export const getGlobalUSetting = `/user/role/global/permission/list`;
|
||||
export const getGlobalUSettingUrl = `/user/role/global/permission/setting/`;
|
||||
/** 获取用户组 */
|
||||
export const getUserGroupU = `/user/role/global/list`;
|
||||
/** 获取单个用户组信息 */
|
||||
|
@ -14,8 +14,8 @@ export const getUsergroupInfoU = `/user/role/global/get/`;
|
|||
export const deleteUserGroupU = `/user/role/global/delete/`;
|
||||
|
||||
/** 根据用户组获取用户列表 */
|
||||
export const getUserByUserGroupU = `/user/role/relation/global/list/`;
|
||||
export const postUserByUserGroupUrl = `/user/role/relation/global/list`;
|
||||
/** 创建用户组添加用户 */
|
||||
export const addUserToUserGroupU = `/user/role/relation/global/add/`;
|
||||
/** 删除用户组用户 */
|
||||
export const deleteUserFromUserGroupU = `/user/role/relation/global/delete/`;
|
||||
export const deleteUserFromUserGroupUrl = `/user/role/relation/global/delete/`;
|
||||
|
|
|
@ -121,7 +121,7 @@ export default function useTableProps(
|
|||
|
||||
// 设置请求参数,如果出了分页参数还有搜索参数,在模板页面调用此方法,可以加入参数
|
||||
const loadListParams = ref<object>({});
|
||||
const setLoadPaListrams = (params?: object) => {
|
||||
const setLoadListParams = (params?: object) => {
|
||||
loadListParams.value = params || {};
|
||||
};
|
||||
|
||||
|
@ -140,6 +140,7 @@ export default function useTableProps(
|
|||
sort: sortItem.value,
|
||||
filter: filterItem.value,
|
||||
keyword: keyword.value,
|
||||
...loadListParams.value,
|
||||
});
|
||||
const tmpArr = data.list as unknown as MsTableData;
|
||||
propsRes.value.data = tmpArr.map((item: TableData) => {
|
||||
|
@ -155,8 +156,8 @@ export default function useTableProps(
|
|||
return data;
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(err);
|
||||
// TODO 表格异常放到solt的empty
|
||||
console.log(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
@ -213,7 +214,7 @@ export default function useTableProps(
|
|||
setLoading,
|
||||
loadList,
|
||||
setPagination,
|
||||
setLoadPaListrams,
|
||||
setLoadListParams,
|
||||
setKeyword,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -39,3 +39,63 @@ export interface UserGroupItem {
|
|||
// 自定义排序
|
||||
pos: number;
|
||||
}
|
||||
|
||||
export interface UserGroupPermissionItem {
|
||||
id: string;
|
||||
name: string;
|
||||
enable: boolean;
|
||||
license: boolean;
|
||||
}
|
||||
|
||||
export type AuthScopeType = 'SYSTEM' | 'PROJECT' | 'ORGANIZATION';
|
||||
|
||||
// 用户组对应的权限配置
|
||||
export interface UserGroupAuthSeting {
|
||||
// 菜单项ID
|
||||
id: AuthScopeType;
|
||||
// 菜单所属类型
|
||||
type?: string;
|
||||
// 菜单项名称
|
||||
name: string;
|
||||
// 是否企业版
|
||||
license: boolean;
|
||||
// 是否全选
|
||||
enable: boolean;
|
||||
// 菜单下的权限列表
|
||||
permissions?: UserGroupPermissionItem[];
|
||||
// 子菜单
|
||||
children?: UserGroupAuthSeting[];
|
||||
}
|
||||
|
||||
// 权限表格DataItem
|
||||
export interface AuthTableItem {
|
||||
id: string;
|
||||
name?: string;
|
||||
enable: boolean;
|
||||
license: boolean;
|
||||
ability?: string | undefined;
|
||||
permissions?: UserGroupPermissionItem[];
|
||||
// 对应表格权限的复选框组的绑定值
|
||||
perChecked?: string[];
|
||||
operationObject?: string;
|
||||
isSystem?: boolean;
|
||||
isOrganization?: boolean;
|
||||
isProject?: boolean;
|
||||
indeterminate?: boolean;
|
||||
}
|
||||
export interface SavePermissions {
|
||||
id: string;
|
||||
enable: boolean;
|
||||
}
|
||||
export interface SaveGlobalUSettingData {
|
||||
userRoleId: string;
|
||||
permissions: SavePermissions[];
|
||||
}
|
||||
|
||||
export interface UserTableItem {
|
||||
id: string;
|
||||
userId: string;
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import type { LoginData } from '@/models/user';
|
|||
import type { UserState } from './types';
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
// 开启数据持久化
|
||||
persist: true,
|
||||
state: (): UserState => ({
|
||||
name: undefined,
|
||||
avatar: undefined,
|
||||
|
|
|
@ -1,16 +1,62 @@
|
|||
<template>
|
||||
<div class="relative">
|
||||
<a-table
|
||||
:span-method="dataSpanMethod"
|
||||
:scroll="{ y: '860px', x: '1440px' }"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:data="tableData"
|
||||
:loading="loading"
|
||||
:bordered="{ wrapper: true, cell: true }"
|
||||
size="small"
|
||||
:pagination="false"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column :width="100" :title="t('system.userGroup.function')" data-index="ability" />
|
||||
<a-table-column :width="150" :title="t('system.userGroup.operationObject')" data-index="operationObject" />
|
||||
<a-table-column :title="t('system.userGroup.auth')">
|
||||
<template #cell="{ record, rowIndex }">
|
||||
<a-checkbox-group v-model="record.perChecked" @change="(v) => handleAuthChange(v, rowIndex)">
|
||||
<a-checkbox v-for="item in record.permissions" :key="item.id" :disabled="item.license" :value="item.id">{{
|
||||
t(item.name)
|
||||
}}</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column :width="50" fixed="right" align="center" :bordered="false">
|
||||
<template #title>
|
||||
<a-checkbox
|
||||
v-if="tableData && tableData?.length > 0"
|
||||
:model-value="allChecked"
|
||||
:indeterminate="allIndeterminate"
|
||||
@change="handleAllChangeByCheckbox"
|
||||
></a-checkbox>
|
||||
</template>
|
||||
<template #cell="{ record, rowIndex }">
|
||||
<a-checkbox
|
||||
:model-value="record.enable"
|
||||
:indeterminate="record.indeterminate"
|
||||
@change="(value) => handleActionChangeAll(value, rowIndex)"
|
||||
/>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
<div class="action">
|
||||
<ms-button class="btn" @click="handleReset">{{ t('system.userGroup.reset') }}</ms-button>
|
||||
<a-button class="btn" :disabled="!canSave" type="primary" @click="handleSave">{{
|
||||
t('system.userGroup.save')
|
||||
}}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TableData } from '@arco-design/web-vue';
|
||||
import { RenderFunction, VNodeChild } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { RenderFunction, VNodeChild, ref, watchEffect } from 'vue';
|
||||
import { type TableColumnData, type TableData } from '@arco-design/web-vue';
|
||||
import useUserGroupStore from '@/store/modules/system/usergroup';
|
||||
import { getGlobalUSetting, saveGlobalUSetting } from '@/api/modules/system/usergroup';
|
||||
import { UserGroupAuthSeting, AuthTableItem, type AuthScopeType, SavePermissions } from '@/models/system/usergroup';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
|
||||
export declare type OperationName = 'selection-checkbox' | 'selection-radio' | 'expand' | 'drag-handle';
|
||||
|
||||
|
@ -23,59 +69,229 @@
|
|||
isLastLeftFixed?: boolean;
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Salary',
|
||||
dataIndex: 'salary',
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
dataIndex: 'email',
|
||||
},
|
||||
];
|
||||
const data = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'Jane Doe',
|
||||
salary: 23000,
|
||||
address: '32 Park Road, London',
|
||||
email: 'jane.doe@example.com',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'Alisa Ross',
|
||||
salary: 25000,
|
||||
address: '35 Park Road, London',
|
||||
email: 'alisa.ross@example.com',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'Kevin Sandra',
|
||||
salary: 22000,
|
||||
address: '31 Park Road, London',
|
||||
email: 'kevin.sandra@example.com',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
name: 'Ed Hellen',
|
||||
salary: 17000,
|
||||
address: '42 Park Road, London',
|
||||
email: 'ed.hellen@example.com',
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
name: 'William Smith',
|
||||
salary: 27000,
|
||||
address: '62 Park Road, London',
|
||||
email: 'william.smith@example.com',
|
||||
},
|
||||
];
|
||||
const loading = ref(false);
|
||||
const store = useUserGroupStore();
|
||||
|
||||
const systemSpan = ref(1);
|
||||
const projectSpan = ref(1);
|
||||
const organizationSpan = ref(1);
|
||||
// 表格的总全选
|
||||
const allChecked = ref(false);
|
||||
const allIndeterminate = ref(false);
|
||||
|
||||
const tableData = ref<AuthTableItem[]>();
|
||||
// 是否可以保存
|
||||
const canSave = ref(false);
|
||||
|
||||
const dataSpanMethod = (data: {
|
||||
record: TableData;
|
||||
column: TableColumnData | TableOperationColumn;
|
||||
rowIndex: number;
|
||||
columnIndex: number;
|
||||
}) => {
|
||||
const { record, column } = data;
|
||||
if ((column as TableColumnData).dataIndex === 'ability') {
|
||||
if (record.isSystem) {
|
||||
return {
|
||||
rowspan: 2,
|
||||
};
|
||||
}
|
||||
if (record.isOrganization) {
|
||||
return {
|
||||
rowspan: organizationSpan.value,
|
||||
};
|
||||
}
|
||||
if (record.isProject) {
|
||||
return {
|
||||
rowspan: projectSpan.value,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
/**
|
||||
* 生成数据
|
||||
* @param type
|
||||
* @param idx
|
||||
*/
|
||||
const makeData = (item: UserGroupAuthSeting, type: AuthScopeType) => {
|
||||
const result: AuthTableItem[] = [];
|
||||
item.children?.forEach((child, index) => {
|
||||
const perChecked =
|
||||
child?.permissions?.reduce((acc: string[], cur) => {
|
||||
if (cur.enable) {
|
||||
acc.push(cur.id);
|
||||
}
|
||||
return acc;
|
||||
}, []) || [];
|
||||
result.push({
|
||||
id: child?.id,
|
||||
license: child?.license,
|
||||
enable: child?.enable,
|
||||
permissions: child?.permissions,
|
||||
indeterminate: perChecked?.length > 0,
|
||||
perChecked,
|
||||
ability: index === 0 ? t(`system.userGroup.${type}`) : undefined,
|
||||
operationObject: t(child.name),
|
||||
isSystem: index === 0 && type === 'SYSTEM',
|
||||
isOrganization: index === 0 && type === 'ORGANIZATION',
|
||||
isProject: index === 0 && type === 'PROJECT',
|
||||
});
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const transformData = (data: UserGroupAuthSeting[]) => {
|
||||
const result: AuthTableItem[] = [];
|
||||
data.forEach((item) => {
|
||||
if (item.type === 'SYSTEM') {
|
||||
systemSpan.value = item.children?.length || 0;
|
||||
}
|
||||
if (item.type === 'PROJECT') {
|
||||
projectSpan.value = item.children?.length || 0;
|
||||
}
|
||||
if (item.type === 'ORGANIZATION') {
|
||||
organizationSpan.value = item.children?.length || 0;
|
||||
}
|
||||
result.push(...makeData(item, item.id));
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const initData = async (id: string) => {
|
||||
try {
|
||||
let tmpArr = [];
|
||||
loading.value = true;
|
||||
const res = await getGlobalUSetting(id);
|
||||
tmpArr = transformData(res);
|
||||
tableData.value = tmpArr;
|
||||
} catch (error) {
|
||||
tableData.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
// 表格总全选change事件
|
||||
const handleAllChangeByCheckbox = () => {
|
||||
if (!tableData.value) return;
|
||||
allChecked.value = !allChecked.value;
|
||||
allIndeterminate.value = false;
|
||||
const tmpArr = tableData.value;
|
||||
tmpArr.forEach((item) => {
|
||||
item.enable = allChecked.value;
|
||||
item.indeterminate = false;
|
||||
item.perChecked = allChecked.value ? item.permissions?.map((ele) => ele.id) : [];
|
||||
});
|
||||
};
|
||||
|
||||
// 表格总全选联动触发事件
|
||||
const handleAllChange = () => {
|
||||
if (!tableData.value) return;
|
||||
const tmpArr = tableData.value;
|
||||
const { length: allLength } = tmpArr;
|
||||
const { length } = tmpArr.filter((item) => item.enable);
|
||||
if (length === allLength) {
|
||||
allChecked.value = true;
|
||||
allIndeterminate.value = false;
|
||||
} else if (length === 0) {
|
||||
allChecked.value = false;
|
||||
allIndeterminate.value = false;
|
||||
} else {
|
||||
allChecked.value = false;
|
||||
allIndeterminate.value = true;
|
||||
}
|
||||
if (!canSave.value) canSave.value = true;
|
||||
};
|
||||
|
||||
// 表格最后一列的复选框change事件
|
||||
const handleActionChangeAll = (value: boolean | (string | number | boolean)[], rowIndex: number) => {
|
||||
if (!tableData.value) return;
|
||||
const tmpArr = tableData.value;
|
||||
tmpArr[rowIndex].indeterminate = false;
|
||||
if (value) {
|
||||
tmpArr[rowIndex].enable = true;
|
||||
tmpArr[rowIndex].perChecked = tmpArr[rowIndex].permissions?.map((item) => item.id);
|
||||
} else {
|
||||
tmpArr[rowIndex].enable = false;
|
||||
tmpArr[rowIndex].perChecked = [];
|
||||
}
|
||||
tableData.value = [...tmpArr];
|
||||
handleAllChange();
|
||||
if (!canSave.value) canSave.value = true;
|
||||
};
|
||||
|
||||
// 表格第三列的复选框change事件
|
||||
const handleAuthChange = (values: (string | number | boolean)[], rowIndex: number) => {
|
||||
if (!tableData.value) return;
|
||||
const tmpArr = tableData.value;
|
||||
const length = tmpArr[rowIndex].permissions?.length || 0;
|
||||
if (values.length === length) {
|
||||
tmpArr[rowIndex].enable = true;
|
||||
tmpArr[rowIndex].indeterminate = false;
|
||||
handleAllChange();
|
||||
} else if (values.length === 0) {
|
||||
tmpArr[rowIndex].enable = false;
|
||||
tmpArr[rowIndex].indeterminate = false;
|
||||
handleAllChange();
|
||||
} else {
|
||||
tmpArr[rowIndex].enable = false;
|
||||
tmpArr[rowIndex].indeterminate = true;
|
||||
}
|
||||
if (!canSave.value) canSave.value = true;
|
||||
};
|
||||
|
||||
// 保存
|
||||
const handleSave = async () => {
|
||||
if (!tableData.value) return;
|
||||
const permissions: SavePermissions[] = [];
|
||||
|
||||
const tmpArr = tableData.value;
|
||||
tmpArr.forEach((item) => {
|
||||
item.permissions?.forEach((ele) => {
|
||||
ele.enable = item.perChecked?.includes(ele.id) || false;
|
||||
permissions.push({
|
||||
id: ele.id,
|
||||
enable: ele.enable,
|
||||
});
|
||||
});
|
||||
});
|
||||
try {
|
||||
await saveGlobalUSetting({
|
||||
userRoleId: store.currentId,
|
||||
permissions,
|
||||
});
|
||||
initData(store.currentId);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('error', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 恢复默认值
|
||||
const handleReset = () => {
|
||||
if (store.currentId) {
|
||||
initData(store.currentId);
|
||||
}
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
if (store.currentId) {
|
||||
initData(store.currentId);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.action {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
bottom: 0;
|
||||
left: 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: calc(100% - 24px);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
v-model="searchKey"
|
||||
class="w-[252px]"
|
||||
:placeholder="t('system.userGroup.searchHolder')"
|
||||
@press-enter="searchData"
|
||||
@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]">
|
||||
|
@ -109,6 +110,33 @@
|
|||
eventTag: 'delete',
|
||||
},
|
||||
];
|
||||
|
||||
// 点击用户组列表
|
||||
const handleListItemClick = (element: UserGroupItem) => {
|
||||
const { id, name, type } = element;
|
||||
currentId.value = id;
|
||||
store.setInfo({ currentName: name, currentTitle: type, currentId: id });
|
||||
};
|
||||
|
||||
// 用户组数据初始化
|
||||
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;
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
// 新增用户组
|
||||
const addUserGroup = () => {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -139,6 +167,7 @@
|
|||
try {
|
||||
await deleteUserGroup(id);
|
||||
Message.success(t('system.user.deleteUserSuccess'));
|
||||
initData();
|
||||
return true;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -151,39 +180,12 @@
|
|||
}
|
||||
};
|
||||
|
||||
// 点击用户组列表
|
||||
const handleListItemClick = (element: UserGroupItem) => {
|
||||
const { id, name, type } = element;
|
||||
currentId.value = id;
|
||||
store.setInfo({ currentName: name, currentTitle: type });
|
||||
};
|
||||
|
||||
// 用户组数据初始化
|
||||
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;
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
// 关闭confirm 弹窗
|
||||
const handlePopConfirmCancel = (id: string) => {
|
||||
popVisible.value = { ...popVisible.value, [id]: false };
|
||||
};
|
||||
// 修改用户组名字,权限范围
|
||||
const handlePopConfirmSubmit = async (item: CustomMoreActionItem, id: string) => {
|
||||
popVisible.value = { ...popVisible.value, [id]: false };
|
||||
if (item.eventKey === 'rename') {
|
||||
// 修改用户组名字
|
||||
try {
|
||||
|
@ -207,10 +209,11 @@
|
|||
console.error(error);
|
||||
}
|
||||
}
|
||||
popVisible.value = { ...popVisible.value, [id]: false };
|
||||
initData();
|
||||
};
|
||||
|
||||
function searchData(eve: Event) {
|
||||
function enterData(eve: Event) {
|
||||
if (!(eve.target as HTMLInputElement).value) {
|
||||
initData();
|
||||
return;
|
||||
|
@ -219,6 +222,15 @@
|
|||
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 handleAddUserGroup = async (value: Partial<UserGroupItem>) => {
|
||||
try {
|
||||
|
@ -226,6 +238,7 @@
|
|||
const res = await updateOrAddUserGroup(value);
|
||||
if (res) {
|
||||
Message.success(t('system.userGroup.addUserGroupSuccess'));
|
||||
addUserGroupVisible.value = false;
|
||||
initData();
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
:popup-visible="renameVisible"
|
||||
:ok-text="t('system.userGroup.confirm')"
|
||||
:cancel-text="t('system.userGroup.cancel')"
|
||||
@ok="handleSubmit"
|
||||
@before-ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
@popup-visible-change="() => (form.name = '')"
|
||||
>
|
||||
|
@ -29,13 +29,13 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { watchEffect, reactive, ref, computed, onUnmounted } from 'vue';
|
||||
import { watchEffect, ref, computed, onUnmounted } from 'vue';
|
||||
import { CustomMoreActionItem, RenameType, UserGroupItem } from '@/models/system/usergroup';
|
||||
import { ValidatedError } from '@arco-design/web-vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const formRef = ref();
|
||||
const form = reactive({
|
||||
const form = ref({
|
||||
name: '',
|
||||
});
|
||||
|
||||
|
@ -46,9 +46,9 @@
|
|||
list: UserGroupItem[];
|
||||
}>();
|
||||
|
||||
const validateName = (value: string, callback: (error?: string) => void) => {
|
||||
const validateName = (value: string | undefined, callback: (error?: string) => void) => {
|
||||
if (props.type === 'rename') {
|
||||
if (value === '') {
|
||||
if (value === undefined || value === '') {
|
||||
callback(t('system.userGroup.userGroupNameIsNotNone'));
|
||||
} else {
|
||||
if (value === props.defaultName) {
|
||||
|
@ -88,20 +88,22 @@
|
|||
|
||||
const renameVisible = ref(props.visible);
|
||||
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate((errors: undefined | Record<string, ValidatedError>) => {
|
||||
const handleSubmit = async () => {
|
||||
await formRef.value.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||
if (!errors) {
|
||||
emit('submit', { eventKey: props.type, name: form.name });
|
||||
emit('submit', { eventKey: props.type, name: form.value.name });
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
};
|
||||
const handleCancel = () => {
|
||||
form.name = '';
|
||||
form.value.name = '';
|
||||
emit('cancel');
|
||||
};
|
||||
watchEffect(() => {
|
||||
renameVisible.value = props.visible;
|
||||
form.name = props.defaultName;
|
||||
form.value.name = props.defaultName;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
|
|
@ -1,94 +1,45 @@
|
|||
<template>
|
||||
<MsBaseTable v-bind="propsRes" v-on="propsEvent"> </MsBaseTable>
|
||||
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
|
||||
<template #action="{ record }">
|
||||
<ms-button type="link" @click="handleRemove(record)">{{ t('system.userGroup.remove') }}</ms-button>
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getTableList } from '@/api/modules/api-test/index';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import { onMounted } from 'vue';
|
||||
import useUserGroupStore from '@/store/modules/system/usergroup';
|
||||
import { watchEffect } from 'vue';
|
||||
import { postUserByUserGroup, deleteUserFromUserGroup } from '@/api/modules/system/usergroup';
|
||||
import { UserTableItem } from '@/models/system/usergroup';
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useUserGroupStore();
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'num',
|
||||
filterable: {
|
||||
filters: [
|
||||
{
|
||||
text: '> 20000',
|
||||
value: '20000',
|
||||
},
|
||||
{
|
||||
text: '> 30000',
|
||||
value: '30000',
|
||||
},
|
||||
],
|
||||
filter: (value, record) => record.salary > value,
|
||||
multiple: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '接口名称',
|
||||
title: 'system.userGroup.name',
|
||||
dataIndex: 'name',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '请求类型',
|
||||
dataIndex: 'method',
|
||||
title: 'system.userGroup.email',
|
||||
dataIndex: 'email',
|
||||
},
|
||||
{
|
||||
title: '责任人',
|
||||
dataIndex: 'username',
|
||||
title: 'system.userGroup.phone',
|
||||
dataIndex: 'email',
|
||||
},
|
||||
{
|
||||
title: '路径',
|
||||
dataIndex: 'path',
|
||||
},
|
||||
{
|
||||
title: '标签',
|
||||
dataIndex: 'tags',
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '用例数',
|
||||
dataIndex: 'caseTotal',
|
||||
},
|
||||
{
|
||||
title: '用例状态',
|
||||
dataIndex: 'caseStatus',
|
||||
},
|
||||
{
|
||||
title: '用例通过率',
|
||||
dataIndex: 'casePassingRate',
|
||||
},
|
||||
{
|
||||
title: '接口状态',
|
||||
dataIndex: 'status',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
slotName: 'createTime',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'description',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: 'system.userGroup.operation',
|
||||
slotName: 'action',
|
||||
fixed: 'right',
|
||||
width: 200,
|
||||
},
|
||||
];
|
||||
const { propsRes, propsEvent, loadList } = useTable(getTableList, {
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(postUserByUserGroup, {
|
||||
columns,
|
||||
scroll: { y: 750, x: 2000 },
|
||||
selectable: true,
|
||||
|
@ -96,7 +47,14 @@
|
|||
const fetchData = async () => {
|
||||
await loadList();
|
||||
};
|
||||
onMounted(() => {
|
||||
const handleRemove = async (record: UserTableItem) => {
|
||||
await deleteUserFromUserGroup(record.id);
|
||||
await fetchData();
|
||||
};
|
||||
watchEffect(() => {
|
||||
if (store.currentId) {
|
||||
setLoadListParams({ roleId: store.currentId });
|
||||
fetchData();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<template>
|
||||
<div class="user-group flex flex-row bg-white">
|
||||
<div class="user-group-left">
|
||||
<UserGroupLeft />
|
||||
<user-group-left v-if="collapse" />
|
||||
<div class="usergroup-collapse">
|
||||
<icon-double-left v-if="collapse" class="icon" @click="collapse = false" />
|
||||
<icon-double-right v-else class="icon" @click="collapse = true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="grow-1 w-[100%] overflow-x-scroll p-[24px]">
|
||||
<div class="grow-1 flex flex-row items-center justify-between">
|
||||
|
@ -35,6 +39,7 @@
|
|||
import AuthTable from './components/authTable.vue';
|
||||
|
||||
const currentTable = ref('auth');
|
||||
const collapse = ref(true);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -52,5 +57,21 @@
|
|||
position: relative;
|
||||
padding: 24px;
|
||||
border-right: 1px solid var(--color-border);
|
||||
.usergroup-collapse {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: -16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 16px;
|
||||
height: 36px;
|
||||
background-color: var(--color-text-n8);
|
||||
cursor: pointer;
|
||||
.icon {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-brand);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export default {
|
||||
system: {
|
||||
userGroup: {
|
||||
addUserGroupSuccess: 'Add user group success',
|
||||
searchHolder: 'Please input user group name',
|
||||
inSystem: 'In system',
|
||||
customUserGroup: 'Custom user group',
|
||||
|
@ -40,6 +41,34 @@ export default {
|
|||
beforeDeleteUserGroup:
|
||||
'After deletion, the project data under the organization will be deleted together. Please operate with caution!',
|
||||
confirmDelete: 'Confirm delete',
|
||||
function: 'Function',
|
||||
operationObject: 'Operation object',
|
||||
system: 'System',
|
||||
project: 'Project',
|
||||
organization: 'Organization',
|
||||
save: 'Save',
|
||||
reset: 'Restore default',
|
||||
name: 'Name',
|
||||
email: 'Email',
|
||||
operation: 'Operation',
|
||||
phone: 'Phone',
|
||||
remove: 'Remove',
|
||||
},
|
||||
},
|
||||
permission: {
|
||||
system_user_role: {
|
||||
name: 'Name',
|
||||
read: 'Read',
|
||||
add: 'Add',
|
||||
update: 'Update',
|
||||
delete: 'Delete',
|
||||
},
|
||||
system_test_resource_pool: {
|
||||
name: 'Name',
|
||||
read: 'Read',
|
||||
add: 'Add',
|
||||
update: 'Update',
|
||||
delete: 'Delete',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export default {
|
||||
system: {
|
||||
userGroup: {
|
||||
addUserGroupSuccess: '添加用户组成功',
|
||||
global: '全局用户组',
|
||||
searchHolder: '请输入用户组名称',
|
||||
inSystem: '系统内置',
|
||||
|
@ -39,6 +40,34 @@ export default {
|
|||
isDeleteUserGroup: '是否删除: {name}?',
|
||||
beforeDeleteUserGroup: '删除后,该组织下的项目数据将一起删除,请谨慎操作!',
|
||||
confirmDelete: '确认删除',
|
||||
function: '功能',
|
||||
operationObject: '操作对象',
|
||||
system: '系统',
|
||||
project: '项目',
|
||||
organization: '组织',
|
||||
save: '保存',
|
||||
reset: '恢复默认',
|
||||
name: '姓名',
|
||||
email: '邮箱',
|
||||
operation: '操作',
|
||||
phone: '手机',
|
||||
remove: '移除',
|
||||
},
|
||||
},
|
||||
permission: {
|
||||
system_user_role: {
|
||||
name: '系统用户',
|
||||
read: '读取',
|
||||
add: '添加',
|
||||
update: '更新',
|
||||
delete: '删除',
|
||||
},
|
||||
system_test_resource_pool: {
|
||||
name: '系统测试资源池',
|
||||
read: '读取',
|
||||
add: '添加',
|
||||
update: '更新',
|
||||
delete: '删除',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue