From 7f4fd9a7d182b8da1a7130355c718914cc086293 Mon Sep 17 00:00:00 2001
From: zhengyiming <540361168@qq.com>
Date: 星期二, 11 十一月 2025 16:41:55 +0800
Subject: [PATCH] feat: s
---
src/views/FlexJobManage/FlexJobManage.vue | 95 ++--
src/views/Permission/RoleManage.vue | 276 ++++++++++++++
src/views/Permission/components/AddOrEditRoleDialog.vue | 142 +++++++
src/views/Permission/components/dialogAuthorizeV2.vue | 356 ++++++++++++++++++
src/views/CustomerManage/CustomerManage.vue | 34
src/constants/apiEnumText.ts | 5
.eslintrc-auto-import.json | 1
src/views/EmploymentManage/TaskManageList.vue | 36 +
auto-imports.d.ts | 2
src/router/index.ts | 106 -----
src/utils/common/tree.ts | 26 +
src/views/UserManage/UserManageList.vue | 42 -
12 files changed, 926 insertions(+), 195 deletions(-)
diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json
index ba6ef6d..4938c3b 100644
--- a/.eslintrc-auto-import.json
+++ b/.eslintrc-auto-import.json
@@ -41,6 +41,7 @@
"EnumEnterpriseCostType": true,
"EnumEnterpriseRealMethod": true,
"EnumEnterpriseType": true,
+ "EnumEnterpriseTypeText": true,
"EnumEnterpriseWalletAccess": true,
"EnumEnterpriseWalletAccessText": true,
"EnumEnterpriseWalletAccessTextForSettle": true,
diff --git a/auto-imports.d.ts b/auto-imports.d.ts
index 77c382f..1cea0e6 100644
--- a/auto-imports.d.ts
+++ b/auto-imports.d.ts
@@ -44,6 +44,7 @@
const EnumEnterpriseCostType: typeof import('./src/constants/apiEnum')['EnumEnterpriseCostType']
const EnumEnterpriseRealMethod: typeof import('./src/constants/apiEnum')['EnumEnterpriseRealMethod']
const EnumEnterpriseType: typeof import('./src/constants/apiEnum')['EnumEnterpriseType']
+ const EnumEnterpriseTypeText: typeof import('./src/constants/apiEnumText')['EnumEnterpriseTypeText']
const EnumEnterpriseWalletAccess: typeof import('./src/constants/apiEnum')['EnumEnterpriseWalletAccess']
const EnumEnterpriseWalletAccessText: typeof import('./src/constants/enterpriseWallet')['EnumEnterpriseWalletAccessText']
const EnumEnterpriseWalletAccessTextForSettle: typeof import('./src/constants/task')['EnumEnterpriseWalletAccessTextForSettle']
@@ -373,6 +374,7 @@
readonly EnumEnterpriseCostType: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumEnterpriseCostType']>
readonly EnumEnterpriseRealMethod: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumEnterpriseRealMethod']>
readonly EnumEnterpriseType: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumEnterpriseType']>
+ readonly EnumEnterpriseTypeText: UnwrapRef<typeof import('./src/constants/apiEnumText')['EnumEnterpriseTypeText']>
readonly EnumEnterpriseWalletAccess: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumEnterpriseWalletAccess']>
readonly EnumEnterpriseWalletAccessText: UnwrapRef<typeof import('./src/constants/enterpriseWallet')['EnumEnterpriseWalletAccessText']>
readonly EnumEnterpriseWalletAccessTextForSettle: UnwrapRef<typeof import('./src/constants/task')['EnumEnterpriseWalletAccessTextForSettle']>
diff --git a/src/constants/apiEnumText.ts b/src/constants/apiEnumText.ts
index 392c27d..bee081a 100644
--- a/src/constants/apiEnumText.ts
+++ b/src/constants/apiEnumText.ts
@@ -11,6 +11,11 @@
[EnumUserType.Operation]: '杩愯惀',
};
+export const EnumEnterpriseTypeText = {
+ [EnumEnterpriseType.Supplier]: '鎵挎徑',
+ [EnumEnterpriseType.PartyA]: '鐢叉柟',
+};
+
export const EnumRoleWebApiDataPowerText = {
[EnumRoleWebApiDataPower.Custom]: '鑷畾涔�',
[EnumRoleWebApiDataPower.Creator]: '涓汉鏁版嵁',
diff --git a/src/router/index.ts b/src/router/index.ts
index 8020e3f..908eab2 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -96,84 +96,6 @@
},
},
{
- path: '/CustomerManage',
- redirect: 'noRedirect',
- component: Layout,
- hidden: false,
- alwaysShow: true,
- meta: {
- rank: 10010,
- title: '瀹㈡埛绠$悊',
- rootMenu: true,
- icon: 'home',
- },
- children: [
- {
- path: '/CustomerManage',
- name: 'CustomerManage',
- hidden: false,
- alwaysShow: true,
- component: () => import('@/views/CustomerManage/CustomerManage.vue'),
- meta: {
- rank: 10011,
- title: '瀹㈡埛绠$悊',
- // rootMenu: true,
- icon: 'home',
- },
- },
- {
- path: '/AddOrEditCustomer/:id?',
- name: 'AddOrEditCustomer',
- hidden: true,
- alwaysShow: false,
- component: () => import('@/views/CustomerManage/AddOrEditCustomer.vue'),
- meta: {
- rank: 10011,
- title: '鏂板瀹㈡埛',
- },
- },
- {
- path: '/CustomerDetail/:id',
- name: 'CustomerDetail',
- hidden: true,
- alwaysShow: false,
- component: () => import('@/views/CustomerManage/CustomerDetail.vue'),
- meta: {
- rank: 10011,
- title: '瀹㈡埛璇︽儏',
- },
- },
- ],
- },
- {
- path: '/FlexJobManage',
- redirect: 'noRedirect',
- component: Layout,
- hidden: false,
- alwaysShow: true,
- meta: {
- rank: 10010,
- title: '鐏靛伐绠$悊',
- rootMenu: true,
- icon: 'home',
- },
- children: [
- {
- path: '/FlexJobManageList',
- name: 'FlexJobManageList',
- hidden: false,
- alwaysShow: true,
- component: () => import('@/views/FlexJobManage/FlexJobManage.vue'),
- meta: {
- rank: 10011,
- title: '鐏靛伐绠$悊',
- // rootMenu: true,
- icon: 'home',
- },
- },
- ],
- },
- {
path: '/EmploymentManage',
redirect: 'noRedirect',
component: Layout,
@@ -484,34 +406,6 @@
],
},
- {
- path: '/UserManage',
- redirect: 'noRedirect',
- component: Layout,
- hidden: false,
- alwaysShow: true,
- meta: {
- rank: 10100,
- title: '鐢ㄦ埛绠$悊',
- rootMenu: true,
- icon: 'home',
- },
- children: [
- {
- path: '/UserManageList',
- name: 'UserManageList',
- hidden: false,
- alwaysShow: true,
- component: () => import('@/views/UserManage/UserManageList.vue'),
- meta: {
- rank: 10101,
- title: '鐢ㄦ埛绠$悊',
- // rootMenu: true,
- icon: 'home',
- },
- },
- ],
- },
{
path: '/Login',
name: 'Login',
diff --git a/src/utils/common/tree.ts b/src/utils/common/tree.ts
index c1f171c..8f5241f 100644
--- a/src/utils/common/tree.ts
+++ b/src/utils/common/tree.ts
@@ -1,3 +1,5 @@
+import { TreeNodeData } from 'element-plus/es/components/tree/src/tree.type';
+
export function getTree(
data: API.ModuleDto[],
root?: string,
@@ -44,3 +46,27 @@
return result;
}
+
+type TreeCallback<T extends TreeNodeData, R> = (
+ data: T,
+ index: number,
+ array: T[],
+ parent?: T
+) => R;
+
+export function treeEach<T extends TreeNodeData>(
+ treeData: T[],
+ callback: TreeCallback<T, void>,
+ getChildren: (data: T) => T[],
+ parent?: T
+) {
+ for (let i = 0; i < treeData.length; i++) {
+ const data = treeData[i];
+ callback(data, i, treeData, parent);
+
+ const children = getChildren(data);
+ if (Array.isArray(children)) {
+ treeEach(children, callback, getChildren, data);
+ }
+ }
+}
diff --git a/src/views/CustomerManage/CustomerManage.vue b/src/views/CustomerManage/CustomerManage.vue
index 90acbda..b73db10 100644
--- a/src/views/CustomerManage/CustomerManage.vue
+++ b/src/views/CustomerManage/CustomerManage.vue
@@ -32,14 +32,16 @@
</QueryFilterItem>
</template>
<template #btn>
- <el-button @click="goAddOrEdit()" icon="Plus" type="primary">鏂板瀹㈡埛</el-button>
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'addBtn')"
+ @click="goAddOrEdit()"
+ icon="Plus"
+ type="primary"
+ >鏂板瀹㈡埛</el-button
+ >
</template>
</ProTableQueryFilterBar>
- <ProTableV2
- v-bind="proTableProps"
- :columns="CustomerManageColumns"
- :operationBtns="operationBtns"
- >
+ <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
</ProTableV2>
</AppContainer>
</LoadingLayout>
@@ -69,26 +71,22 @@
name: 'CustomerManage',
});
-const operationBtns = defineOperationBtns([
- {
- data: {
- enCode: 'detailBtn',
- name: '鏌ョ湅',
- },
+const operationBtnMap: Record<string, OperationBtnType> = {
+ detailBtn: {
emits: {
onClick: (role) => goDetail(role),
},
},
- {
- data: {
- enCode: 'editBtn',
- name: '缂栬緫',
- },
+ editBtn: {
emits: {
onClick: (role) => goAddOrEdit(role),
},
},
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+ operationBtnMap,
+});
const BaseState = {
loading: true,
diff --git a/src/views/EmploymentManage/TaskManageList.vue b/src/views/EmploymentManage/TaskManageList.vue
index e015140..e3a9b20 100644
--- a/src/views/EmploymentManage/TaskManageList.vue
+++ b/src/views/EmploymentManage/TaskManageList.vue
@@ -87,6 +87,42 @@
name: 'TaskManageList',
});
+const operationBtnMap: Record<string, OperationBtnType> = {
+ // editBtn: {
+ // emits: {
+ // onClick: (role) => goAddOrEdit(role),
+ // },
+ // extraProps: {
+ // hide: (row: API.GetTaskInfosQueryResultItem) => row.status === EnumTaskStatus.Complete,
+ // },
+ // },
+ detailBtn: {
+ emits: {
+ onClick: (row: API.GetTaskInfosQueryResultItem) => goDetail(row),
+ },
+ },
+ // publishBtn: {
+ // emits: {
+ // onClick: (row: API.GetTaskInfosQueryResultItem) =>
+ // setTaskInfoReleaseStatus(row, EnumTaskReleaseStatus.InProcess),
+ // },
+ // extraProps: {
+ // hide: (row: API.GetTaskInfosQueryResultItem) =>
+ // row.releaseStatus === EnumTaskReleaseStatus.InProcess,
+ // },
+ // },
+ // unPublishBtn: {
+ // emits: {
+ // onClick: (row: API.GetTaskInfosQueryResultItem) =>
+ // setTaskInfoReleaseStatus(row, EnumTaskReleaseStatus.Stopped),
+ // },
+ // extraProps: {
+ // hide: (row: API.GetTaskInfosQueryResultItem) =>
+ // row.releaseStatus === EnumTaskReleaseStatus.Stopped,
+ // },
+ // },
+};
+
const operationBtns = defineOperationBtns([
// {
// data: {
diff --git a/src/views/FlexJobManage/FlexJobManage.vue b/src/views/FlexJobManage/FlexJobManage.vue
index b4522c1..67a3486 100644
--- a/src/views/FlexJobManage/FlexJobManage.vue
+++ b/src/views/FlexJobManage/FlexJobManage.vue
@@ -79,17 +79,48 @@
</QueryFilterItem>
</template>
<template #btn>
- <el-button @click="handleDownloadTemplate()" type="primary" link>妯℃澘涓嬭浇</el-button>
- <el-button @click="handleBatchImportAdd()" type="primary">鎵归噺瀵煎叆</el-button>
- <el-button @click="handleBatchUnSign()" type="primary">鎵归噺瑙g害</el-button>
- <el-button @click="handleSendShotMessage()" type="primary">鐭俊鍙戦��</el-button>
- <el-button @click="handleBatchSign()" type="primary">鎵归噺绛剧害</el-button>
- <el-button @click="handleEnterpriseBatchSign()" type="primary">鎵归噺浼佷笟绛剧害</el-button>
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'importBtn')"
+ @click="handleDownloadTemplate()"
+ type="primary"
+ link
+ >妯℃澘涓嬭浇</el-button
+ >
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'importBtn')"
+ @click="handleBatchImportAdd()"
+ type="primary"
+ >鎵归噺瀵煎叆</el-button
+ >
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'batchUnSignBtn')"
+ @click="handleBatchUnSign()"
+ type="primary"
+ >鎵归噺瑙g害</el-button
+ >
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'sendShotBtn')"
+ @click="handleSendShotMessage()"
+ type="primary"
+ >鐭俊鍙戦��</el-button
+ >
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'batchSignBtn')"
+ @click="handleBatchSign()"
+ type="primary"
+ >鎵归噺绛剧害</el-button
+ >
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'enterpriseBatchSignBtn')"
+ @click="handleEnterpriseBatchSign()"
+ type="primary"
+ >鎵归噺浼佷笟绛剧害</el-button
+ >
</template>
</ProTableQueryFilterBar>
<ProTableV2
v-bind="proTableProps"
- :columns="FlexJobManageColumns"
+ :columns="column"
:operationBtns="operationBtns"
show-column-check
ref="proTable"
@@ -123,12 +154,10 @@
FieldDatePicker,
FieldRadio,
FieldSelect,
- defineOperationBtns,
useFormDialog,
UploadUserFile,
XLSXUtils,
} from '@bole-core/components';
-import { FlexJobManageColumns } from './constants';
import { EnumTaskUserHireStatusText, EnumTaskUserSignContractStatusText } from '@/constants';
import { Message } from '@bole-core/core';
import { convertApi2FormUrlOnlyOne, downloadFileByUrl, format } from '@/utils';
@@ -145,31 +174,19 @@
name: 'FlexJobManageList',
});
-const operationBtns = defineOperationBtns([
- {
- data: {
- enCode: 'editBtn',
- name: '缂栬緫',
- },
+const operationBtnMap: Record<string, OperationBtnType> = {
+ editBtn: {
emits: {
onClick: (role) => openDialog(role),
},
},
- {
- data: {
- enCode: 'detailBtn',
- name: '璇︽儏',
- },
+ detailBtn: {
emits: {
onClick: (role: API.GetEnterpriseEmployeesQueryResultItem) =>
handleStaffDetailEdit({ id: role.id, tabType: 'info' }),
},
},
- {
- data: {
- enCode: 'enterpriseSignBtn',
- name: '浼佷笟绛剧害',
- },
+ enterpriseSignBtn: {
emits: {
onClick: (role) => handleEnterpriseSign(role),
},
@@ -181,11 +198,7 @@
),
},
},
- {
- data: {
- enCode: 'inviteSignBtn',
- name: '閭�璇风绾�',
- },
+ inviteSignBtn: {
emits: {
onClick: (role) => handleInviteSign(role),
},
@@ -197,11 +210,7 @@
),
},
},
- {
- data: {
- enCode: 'unSignBtn',
- name: '瑙g害',
- },
+ unSignBtn: {
emits: {
onClick: (role) => handleUnSign(role),
},
@@ -213,17 +222,11 @@
),
},
},
- // {
- // data: {
- // enCode: 'delBtn',
- // name: '鍒犻櫎',
- // },
- // props: { type: 'danger' },
- // emits: {
- // onClick: (role) => handleDelete(role),
- // },
- // },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+ operationBtnMap,
+});
const router = useRouter();
diff --git a/src/views/Permission/RoleManage.vue b/src/views/Permission/RoleManage.vue
new file mode 100644
index 0000000..887b4f1
--- /dev/null
+++ b/src/views/Permission/RoleManage.vue
@@ -0,0 +1,276 @@
+<template>
+ <LoadingLayout :loading="state.loading">
+ <AppContainer>
+ <ProTableQueryFilterBar @on-reset="reset">
+ <template #query>
+ <QueryFilterItem>
+ <SearchInput
+ v-model="extraParamState.queryCondition"
+ style="width: 200px"
+ placeholder="瑙掕壊鍚嶇О"
+ @on-click-search="getList"
+ @keyup.enter="getList()"
+ >
+ </SearchInput>
+ </QueryFilterItem>
+ </template>
+ <template #btn>
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'addBtn')"
+ @click="openDialog()"
+ icon="Plus"
+ type="primary"
+ >鏂板</el-button
+ >
+ </template>
+ </ProTableQueryFilterBar>
+ <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+ </ProTableV2>
+ </AppContainer>
+ <AddOrEditRoleDialog v-bind="dialogProps" />
+ <DialogAuthorizeV2 v-bind="dialogAuthorizeProps" authorizeType="Role" />
+ <!-- <DialogMember v-model:visibleId="rowState.setMemberRoleId" /> -->
+ </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+ ProTableQueryFilterBar,
+ OperationBtnType,
+ ProTableV2,
+ SearchInput,
+ LoadingLayout,
+ AppContainer,
+ QueryFilterItem,
+ useTable,
+ useFormDialog,
+ FieldRadio,
+} from '@bole-core/components';
+import { useAccess } from '@/hooks';
+import { Message } from '@bole-core/core';
+import AddOrEditRoleDialog from './components/AddOrEditRoleDialog.vue';
+import { EnumUserType } from '@/constants';
+import DialogAuthorizeV2 from './components/dialogAuthorizeV2.vue';
+import * as roleServices from '@/services/api/role';
+
+defineOptions({
+ name: 'RoleManage',
+});
+
+const operationBtnMap: Record<string, OperationBtnType> = {
+ editBtn: { emits: { onClick: (role) => openDialog(role) } },
+ delBtn: { emits: { onClick: (role) => handleDeleteRole(role) }, props: { type: 'danger' } },
+ authorize: { emits: { onClick: (role) => openAuthorizeDialog(role) } },
+ // member: { emits: { onClick: (role) => openMemberDialog(role) } },
+ disabledBtn: {
+ emits: { onClick: (role) => roleEnableOrForbid(role) },
+ props: { type: 'danger' },
+ extraProps: {
+ hide: (row) => row.isDisabled,
+ },
+ },
+ enableBtn: {
+ emits: { onClick: (role) => roleEnableOrForbid(role) },
+ extraProps: {
+ hide: (row) => !row.isDisabled,
+ },
+ },
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+ operationBtnMap,
+});
+
+const BaseState = {
+ loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+onMounted(async () => {
+ await getList();
+ state.loading = false;
+});
+
+const {
+ getDataSource: getList,
+ proTableProps,
+ paginationState,
+ extraParamState,
+ reset,
+} = useTable(
+ async ({ pageIndex, pageSize }, extraParamState) => {
+ try {
+ let params: API.GetRolesQuery = {
+ pageModel: {
+ rows: pageSize,
+ page: pageIndex,
+ orderInput: extraParamState.orderInput,
+ },
+ userType: AppLocalConfig.userType,
+ clientType: AppLocalConfig.clientType,
+ enterpriseType: AppLocalConfig.enterpriseType,
+ keywords: extraParamState.queryCondition,
+ };
+ let res = await roleServices.getRoles(params, {
+ showLoading: !state.loading,
+ });
+ return res;
+ } catch (error) {}
+ },
+ {
+ defaultExtraParams: {
+ queryCondition: '',
+ orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
+ },
+ queryKey: ['roleServices/getRoles'],
+ columnsRenderProps: {
+ dataPower: { type: 'enum', valueEnum: EnumRoleWebApiDataPowerText },
+ },
+ }
+);
+
+async function openDialog(row?: API.GetRolesQueryResultItem) {
+ try {
+ if (row) {
+ const detail = await roleServices.getRole({ id: row.id });
+ handleEdit({
+ id: row.id,
+ name: row.name,
+ remark: row.remark,
+ userType: row.userType,
+ clientType: row.clientType,
+ dataRange: row.dataPower,
+ detail: detail,
+ minLevel: row.minLevel,
+ enterpriseType: row.enterpriseType,
+ });
+ } else {
+ handleAdd({
+ userType: AppLocalConfig.userType,
+ clientType: AppLocalConfig.clientType,
+ });
+ }
+ } catch (error) {}
+}
+
+const { dialogProps, handleAdd, handleEdit, editForm, dialogState } = useFormDialog({
+ onConfirm: handleAddOrEdit,
+ defaultFormParams: {
+ id: '',
+ name: '',
+ remark: '',
+ userType: AppLocalConfig.userType,
+ clientType: AppLocalConfig.clientType,
+ dataRange: EnumRoleWebApiDataPower.All,
+ detail: null as API.GetRoleQueryResult,
+ minLevel: 1,
+ enterpriseType: AppLocalConfig.enterpriseType,
+ },
+});
+
+async function handleAddOrEdit() {
+ try {
+ const isEdit = editForm.id;
+ let params: API.SaveRoleCommand = {
+ name: editForm.name,
+ remark: editForm.remark,
+ dataPower: editForm.dataRange,
+ userType: editForm.userType,
+ clientType: editForm.clientType,
+ minLevel: editForm.minLevel,
+ };
+ if (editForm.userType === EnumUserType.Enterprise) {
+ params.enterpriseType = editForm.enterpriseType;
+ }
+ if (isEdit) {
+ params = {
+ ...editForm.detail,
+ ...params,
+ };
+ }
+ let res = await roleServices.saveRole(params);
+ if (res) {
+ Message.successMessage('鎿嶄綔鎴愬姛');
+ getList(isEdit ? paginationState.pageIndex : 1);
+ }
+ } catch (error) {}
+}
+
+async function handleDeleteRole(row: API.GetRolesQueryResultItem) {
+ try {
+ await Message.deleteMessage();
+ let params: API.DeleteRoleCommand = {
+ ids: [row.id],
+ };
+ let res = await roleServices.deleteRole(params);
+ if (res) {
+ Message.successMessage('鎿嶄綔鎴愬姛');
+ getList(paginationState.pageIndex);
+ }
+ } catch (error) {}
+}
+
+async function roleEnableOrForbid(row: API.GetRolesQueryResultItem) {
+ try {
+ await Message.tipMessage(`鏄惁${row.isDisabled ? '鍚敤' : '绂佺敤'}瑙掕壊`);
+ let res = await roleServices.setRoleIsDisabled({
+ ids: [row.id],
+ isDisabled: !row.isDisabled,
+ });
+ if (res) {
+ Message.successMessage('鎿嶄綔鎴愬姛');
+ getList(paginationState.pageIndex);
+ return !!res;
+ }
+ } catch (error) {}
+}
+
+const rowState = reactive({
+ authorizeId: '',
+ setMemberRoleId: '',
+});
+
+const {
+ dialogProps: dialogAuthorizeProps,
+ handleAdd: handleAuthorizeAdd,
+ editForm: authorizeForm,
+} = useFormDialog({
+ onConfirm: handleAuthorize,
+ defaultFormParams: {
+ detail: null as API.GetRoleQueryResult,
+ },
+});
+
+async function openAuthorizeDialog(row: API.GetRolesQueryResultItem) {
+ try {
+ const detail = await roleServices.getRole({ id: row.id });
+ handleAuthorizeAdd({
+ detail: detail,
+ });
+ } catch (error) {}
+}
+
+async function handleAuthorize(selectedMenuIds: string[]) {
+ console.log('selectedMenuIds: ', selectedMenuIds);
+ try {
+ let params: API.SaveRoleCommand = {
+ ...authorizeForm.detail,
+ menuIds: selectedMenuIds,
+ // resources: resourceIds.map((x) => ({
+ // resourceId: x,
+ // dataPower: EnumRoleWebApiDataPower.All,
+ // })),
+ };
+ let res = await roleServices.saveRole(params);
+ if (res) {
+ Message.successMessage('鎿嶄綔鎴愬姛');
+ getList(paginationState.pageIndex);
+ }
+ } catch (error) {}
+}
+
+// function openMemberDialog(row: API.IdentityRoleDto) {
+// rowState.setMemberRoleId = row.id;
+// }
+</script>
diff --git a/src/views/Permission/components/AddOrEditRoleDialog.vue b/src/views/Permission/components/AddOrEditRoleDialog.vue
new file mode 100644
index 0000000..023f3bc
--- /dev/null
+++ b/src/views/Permission/components/AddOrEditRoleDialog.vue
@@ -0,0 +1,142 @@
+<template>
+ <ProDialog
+ :title="innerForm.title"
+ v-model="innerVisible"
+ @close="onDialogClose"
+ destroy-on-close
+ draggable
+ >
+ <ProForm :rules="rules" :model="innerForm" ref="dialogForm" label-width="110px">
+ <ProFormItemV2 label="瑙掕壊鍚嶇О" prop="name">
+ <ProFormText placeholder="璇疯緭鍏ヨ鑹插悕绉�" v-model.trim="innerForm.name"></ProFormText>
+ </ProFormItemV2>
+ <ProFormItemV2 label="绛夌骇" prop="minLevel">
+ <ProFormInputNumber
+ v-model="innerForm.minLevel"
+ :min="1"
+ :max="100"
+ :controls="false"
+ ></ProFormInputNumber>
+ </ProFormItemV2>
+ <!-- <ProFormItemV2
+ label="浼佷笟绫诲瀷"
+ prop="enterpriseType"
+ v-if="form.userType === EnumUserType.Enterprise"
+ >
+ <ProFormRadio
+ v-model="form.enterpriseType"
+ :value-enum="EnumEnterpriseTypeText"
+ :buttonStyle="false"
+ ></ProFormRadio>
+ </ProFormItemV2> -->
+ <ProFormItemV2 label="鏁版嵁鍙鑼冨洿" prop="dataRange">
+ <ProFormRadio
+ v-model="form.dataRange"
+ :value-enum="EnumRoleWebApiDataPowerTextForFilter"
+ :buttonStyle="false"
+ ></ProFormRadio>
+ </ProFormItemV2>
+ <ProFormItemV2 label="澶囨敞:" prop="remark">
+ <ProFormTextArea
+ v-model="innerForm.remark"
+ placeholder="璇疯緭鍏ュ娉�"
+ show-word-limit
+ :maxlength="2000"
+ ></ProFormTextArea>
+ </ProFormItemV2>
+ </ProForm>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="emit('onCancel')">鍙� 娑�</el-button>
+ <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
+ </span>
+ </template>
+ </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { FormRules, FormInstance } from 'element-plus';
+import {
+ ProDialog,
+ ProForm,
+ ProFormItemV2,
+ ProFormText,
+ ProFormRadio,
+ ProFormTextArea,
+ ProFormInputNumber,
+} from '@bole-core/components';
+import {
+ EnumRoleWebApiDataPowerTextForFilter,
+ EnumEnterpriseTypeText,
+ EnumUserType,
+} from '@/constants';
+
+defineOptions({
+ name: 'AddOrEditRoleDialog',
+});
+
+type Props = {
+ modelValue: boolean;
+ form: {
+ id: string;
+ title?: string;
+ name: string;
+ remark: string;
+ dataRange: EnumRoleWebApiDataPower;
+ minLevel: number;
+ enterpriseType: EnumEnterpriseType;
+ userType: EnumUserType;
+ };
+};
+
+const props = withDefaults(defineProps<Props>(), {
+ modelValue: false,
+});
+
+const emit = defineEmits<{
+ (e: 'update:modelValue', value: boolean): void;
+ (e: 'update:form', value: Props['form']): void;
+ (e: 'onConfirm'): void;
+ (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+const innerVisible = computed({
+ get() {
+ return props.modelValue;
+ },
+ set(val) {
+ emit('update:modelValue', val);
+ },
+});
+
+const innerForm = computed({
+ get() {
+ return props.form;
+ },
+ set(val) {
+ emit('update:form', val);
+ },
+});
+
+const rules = reactive<FormRules>({
+ name: [{ required: true, message: '璇疯緭鍏ュ悕绉�', trigger: 'blur' }],
+});
+
+function onDialogClose() {
+ if (!dialogForm.value) return;
+ dialogForm.value.resetFields();
+}
+
+function handleConfirm() {
+ if (!dialogForm.value) return;
+ dialogForm.value.validate((valid) => {
+ if (valid) {
+ emit('onConfirm');
+ } else {
+ return;
+ }
+ });
+}
+</script>
diff --git a/src/views/Permission/components/dialogAuthorizeV2.vue b/src/views/Permission/components/dialogAuthorizeV2.vue
new file mode 100644
index 0000000..71bfb25
--- /dev/null
+++ b/src/views/Permission/components/dialogAuthorizeV2.vue
@@ -0,0 +1,356 @@
+<template>
+ <ProDialog
+ class="custom-dialog"
+ width="55%"
+ :title="dialogTitle"
+ v-model="visible"
+ :top="'10vh'"
+ :close-on-click-modal="false"
+ :close-on-press-escape="false"
+ >
+ <div class="authorize-wrapper">
+ <div class="container-wrapper left-wrapper">
+ <el-scrollbar>
+ <el-tree
+ class="companyTree"
+ :data="menusTree"
+ :props="{
+ children: 'children',
+ label: 'name',
+ }"
+ node-key="id"
+ :expand-on-click-node="false"
+ :highlight-current="true"
+ default-expand-all
+ show-checkbox
+ ref="moduleTree"
+ :default-checked-keys="defaultCheckedKeys"
+ @check="handleModuleCheck"
+ >
+ <template #default="{ node }">
+ <div class="custom-tree-node">
+ <type-tip :isMenu="node.data.type === EnumMenuType.Menu" />
+ <div class="node-text" @click="handleSelectModule(node.data)">
+ {{ node.label }}
+ </div>
+ </div>
+ </template>
+ </el-tree>
+ </el-scrollbar>
+ </div>
+
+ <div class="container-wrapper">
+ <div class="type-wrapper">
+ {{ SubModuleTitle[SubModuleType.PageButton] }}
+ </div>
+ <el-scrollbar>
+ <el-tree
+ v-show="!!state.currentMenuId"
+ :data="[
+ {
+ name: '鍏ㄩ��',
+ id: 'pageButtonAll',
+ children: menuPageButtons,
+ },
+ ]"
+ :props="{
+ children: 'children',
+ label: 'name',
+ }"
+ node-key="id"
+ :expand-on-click-node="false"
+ :highlight-current="true"
+ default-expand-all
+ show-checkbox
+ ref="pageButtonTree"
+ :default-checked-keys="defaultCheckedKeys"
+ @check="handlePageButtonCheck"
+ >
+ <template #default="{ node }">
+ <div class="custom-tree-node">
+ <span>{{ node.label }}</span>
+ </div>
+ </template>
+ </el-tree>
+ </el-scrollbar>
+ </div>
+
+ <div class="container-wrapper">
+ <div class="type-wrapper">
+ {{ SubModuleTitle[SubModuleType.DataButton] }}
+ </div>
+ <el-scrollbar>
+ <el-tree
+ v-show="!!state.currentMenuId"
+ :data="[
+ {
+ name: '鍏ㄩ��',
+ id: 'dataButtonAll',
+ children: menuDataButtons,
+ },
+ ]"
+ :props="{
+ children: 'children',
+ label: 'name',
+ }"
+ node-key="id"
+ :expand-on-click-node="false"
+ :highlight-current="true"
+ default-expand-all
+ show-checkbox
+ ref="dataButtonTree"
+ :default-checked-keys="defaultCheckedKeys"
+ @check="handleDataButtonCheck"
+ >
+ <template #default="{ node }">
+ <div class="custom-tree-node">
+ <span>{{ node.label }}</span>
+ </div>
+ </template>
+ </el-tree>
+ </el-scrollbar>
+ </div>
+
+ <div class="container-wrapper">
+ <div class="type-wrapper">
+ {{ SubModuleTitle[SubModuleType.Column] }}
+ </div>
+ <el-scrollbar>
+ <el-tree
+ v-show="!!state.currentMenuId"
+ :data="[
+ {
+ name: '鍏ㄩ��',
+ id: 'dataColumnAll',
+ children: menuFields,
+ },
+ ]"
+ :props="{
+ children: 'children',
+ label: 'name',
+ }"
+ node-key="id"
+ :expand-on-click-node="false"
+ :highlight-current="true"
+ default-expand-all
+ show-checkbox
+ ref="dataColumnTree"
+ :default-checked-keys="defaultCheckedKeys"
+ @check="handleDataColumnCheck"
+ >
+ <template #default="{ node }">
+ <div class="custom-tree-node">
+ <span>{{ node.label }}</span>
+ </div>
+ </template>
+ </el-tree>
+ </el-scrollbar>
+ </div>
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="visible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="handleConfirm" class="btn-submit"> 纭畾 </el-button>
+ </span>
+ </template>
+ </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { Message } from '@bole-core/core';
+import { SubModuleType, SubModuleTitle, EnumMenuType } from '@/constants';
+import { getTree, treeEach } from '@/utils';
+import { TreeInstance } from 'element-plus';
+import { ProDialog } from '@bole-core/components';
+import { useMenus, useMenu } from '@/hooks';
+import data from '@iconify-icons/ep/tickets';
+
+const TypeTip = defineComponent({
+ name: 'TypeTip',
+ props: ['isMenu'],
+ render() {
+ const { isMenu } = this;
+ const tipText = isMenu ? `鑿滃崟` : '椤甸潰';
+ return h(
+ 'span',
+ {
+ class: 'tip-text',
+ style: {
+ color: '#EB6100',
+ },
+ },
+ '[' + tipText + ']'
+ );
+ },
+});
+
+type Props = {
+ authorizeType: 'Role' | 'User';
+};
+
+const props = withDefaults(defineProps<Props>(), {});
+
+const visible = defineModel({ type: Boolean });
+
+type Form = {
+ title?: string;
+ detail: API.GetRoleQueryResult;
+};
+
+const form = defineModel<Form>('form');
+
+const emit = defineEmits<{
+ (e: 'onConfirm', selectedMenuIds: string[]): void;
+ (e: 'onCancel'): void;
+}>();
+
+type CheckedResourceItem = {
+ resourceId: string;
+ menuId: string;
+ resourceType: SubModuleType;
+};
+
+const state = reactive({
+ currentMenuId: '',
+ selectedMenuIds: [] as string[],
+});
+
+const defaultCheckedKeys = computed(() => Array.from(state.selectedMenuIds));
+
+watch(visible, (newVal) => {
+ if (newVal) {
+ state.currentMenuId = '';
+ const menuIds = form.value.detail?.menuIds ?? [];
+ // menuIds.forEach((id) => state.selectedMenuIds.add(id));
+ state.selectedMenuIds = [...menuIds];
+ }
+});
+
+const dialogTitle = computed(() =>
+ props.authorizeType === 'Role' ? '瑙掕壊鍔熻兘鎺堟潈' : '璐﹀彿鍔熻兘鎺堟潈'
+);
+
+const moduleTree = useTemplateRef<TreeInstance>('moduleTree');
+const pageButtonTree = useTemplateRef<TreeInstance>('pageButtonTree');
+const dataButtonTree = useTemplateRef<TreeInstance>('dataButtonTree');
+const dataColumnTree = useTemplateRef<TreeInstance>('dataColumnTree');
+
+type TreeRef = ReturnType<typeof useTemplateRef<TreeInstance>>;
+
+const { menusTree, getMenuById } = useMenus({
+ params: computed(() => ({
+ userType: form.value.detail?.userType,
+ clientType: form.value.detail?.clientType,
+ enterpriseType: form.value.detail?.enterpriseType,
+ roleId: form.value.detail?.id,
+ })),
+ enabled: computed(() => !!form.value.detail?.id),
+});
+
+const { menuFields, menuPageButtons, menuDataButtons } = useMenu({
+ params: computed(() => ({
+ id: state.currentMenuId,
+ roleId: form.value.detail?.id,
+ })),
+ enabled: computed(() => !!state.currentMenuId),
+});
+
+function handleSelectModule(menu: API.GetMenusQueryResultItem) {
+ state.currentMenuId = menu.id;
+}
+
+function handleModuleCheck(data, params) {
+ handleCheck(data, params, moduleTree);
+}
+
+function handlePageButtonCheck(data, params) {
+ handleCheck(data, params, pageButtonTree);
+}
+
+function handleDataButtonCheck(data, params) {
+ handleCheck(data, params, dataButtonTree);
+}
+
+function handleDataColumnCheck(data, params) {
+ handleCheck(data, params, dataColumnTree);
+}
+
+function handleCheck(data, params, treeRef: TreeRef) {
+ const dataMap = {};
+ treeEach(
+ [treeRef.value.store.root],
+ (node) => (dataMap[node.key] = node),
+ (node) => node.childNodes
+ );
+
+ const uncachedCheckedKeys = params.checkedKeys.filter(
+ (item) => !['pageButtonAll', 'dataButtonAll', 'dataColumnAll'].includes(item)
+ );
+ const cachedKeys = state.selectedMenuIds.filter(
+ (item) => !(item in dataMap) && !uncachedCheckedKeys.includes(item)
+ );
+ state.selectedMenuIds = cachedKeys.concat(uncachedCheckedKeys);
+}
+
+function handleConfirm() {
+ emit('onConfirm', state.selectedMenuIds);
+}
+</script>
+
+<style lang="scss" scoped>
+:deep(.custom-dialog) {
+ min-width: 900px;
+}
+
+.authorize-wrapper {
+ display: flex;
+
+ height: 500px;
+ border-bottom: 2px solid #f5f5f5;
+ background: #dddddd;
+
+ .container-wrapper {
+ width: calc(25%);
+ border-right: 2px solid #f5f5f5;
+ // margin-right: 7px;
+ background: #ffffff;
+
+ .type-wrapper {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ padding: 10px 16px;
+ border-bottom: 2px solid #f5f5f5;
+ color: #333333;
+ }
+
+ &:last-of-type {
+ margin-right: 0px;
+ }
+
+ &.left-wrapper {
+ margin-right: 7px;
+ padding-top: 10px;
+ width: calc(35% - 7px);
+
+ :deep(.el-scrollbar) {
+ width: 100%;
+ height: 98%;
+ }
+ }
+
+ :deep(.el-scrollbar) {
+ width: 100%;
+ height: calc(98% - 43px);
+
+ .el-scrollbar__wrap {
+ overflow: auto;
+
+ .custom-tree-node {
+ display: flex;
+ }
+ }
+ }
+ }
+}
+</style>
diff --git a/src/views/UserManage/UserManageList.vue b/src/views/UserManage/UserManageList.vue
index 10d42bb..2402aa5 100644
--- a/src/views/UserManage/UserManageList.vue
+++ b/src/views/UserManage/UserManageList.vue
@@ -14,14 +14,16 @@
</QueryFilterItem>
</template>
<template #btn>
- <el-button @click="openDialog()" icon="Plus" type="primary">鏂板</el-button>
+ <el-button
+ v-if="checkSubModuleItemShow('pageButton', 'addBtn')"
+ @click="openDialog()"
+ icon="Plus"
+ type="primary"
+ >鏂板</el-button
+ >
</template>
</ProTableQueryFilterBar>
- <ProTableV2
- v-bind="proTableProps"
- :columns="UserManageColumns"
- :operationBtns="operationBtns"
- >
+ <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
<template #status="{ row }">
<FieldSwitch
v-model="row.status"
@@ -52,11 +54,9 @@
QueryFilterItem,
useTable,
useFormDialog,
- defineOperationBtns,
FieldSwitch,
} from '@bole-core/components';
import * as userServices from '@/services/api/user';
-import { UserManageColumns } from './constants';
import { EnumUserStatus, EnumUserStatusText } from '@/constants';
import { ModelValueType } from 'element-plus';
import { Message } from '@bole-core/core';
@@ -68,21 +68,13 @@
name: 'UserManageList',
});
-const operationBtns = defineOperationBtns([
- {
- data: {
- enCode: 'editBtn',
- name: '缂栬緫',
- },
+const operationBtnMap: Record<string, OperationBtnType> = {
+ editBtn: {
emits: {
onClick: (role) => openDialog(role),
},
},
- {
- data: {
- enCode: 'resetPasswordBtn',
- name: '閲嶇疆瀵嗙爜',
- },
+ resetPasswordBtn: {
props: {
type: 'danger',
},
@@ -90,11 +82,7 @@
onClick: (role) => openResetPasswordDialog(role),
},
},
- {
- data: {
- enCode: 'resetOperatorPasswordBtn',
- name: '閲嶇疆鎿嶄綔瀵嗙爜',
- },
+ resetOperatorPasswordBtn: {
props: {
type: 'danger',
},
@@ -102,7 +90,11 @@
onClick: (role) => openResetOperatorPasswordDialog(role),
},
},
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+ operationBtnMap,
+});
const router = useRouter();
const BaseState = {
--
Gitblit v1.9.1