| | |
| | | "EnumEnterpriseCostType": true, |
| | | "EnumEnterpriseRealMethod": true, |
| | | "EnumEnterpriseType": true, |
| | | "EnumEnterpriseTypeText": true, |
| | | "EnumEnterpriseWalletAccess": true, |
| | | "EnumEnterpriseWalletAccessText": true, |
| | | "EnumEnterpriseWalletAccessTextForSettle": true, |
| | |
| | | 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'] |
| | |
| | | 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']> |
| | |
| | | [EnumUserType.Operation]: '运营', |
| | | }; |
| | | |
| | | export const EnumEnterpriseTypeText = { |
| | | [EnumEnterpriseType.Supplier]: '承揽', |
| | | [EnumEnterpriseType.PartyA]: '甲方', |
| | | }; |
| | | |
| | | export const EnumRoleWebApiDataPowerText = { |
| | | [EnumRoleWebApiDataPower.Custom]: '自定义', |
| | | [EnumRoleWebApiDataPower.Creator]: '个人数据', |
| | |
| | | }, |
| | | }, |
| | | { |
| | | 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, |
| | |
| | | ], |
| | | }, |
| | | |
| | | { |
| | | 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', |
| | |
| | | import { TreeNodeData } from 'element-plus/es/components/tree/src/tree.type'; |
| | | |
| | | export function getTree( |
| | | data: API.ModuleDto[], |
| | | root?: string, |
| | |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | |
| | | </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> |
| | |
| | | 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, |
| | |
| | | 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: { |
| | |
| | | </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">批量解约</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" |
| | | >批量解约</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" |
| | |
| | | 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'; |
| | |
| | | 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), |
| | | }, |
| | |
| | | ), |
| | | }, |
| | | }, |
| | | { |
| | | data: { |
| | | enCode: 'inviteSignBtn', |
| | | name: '邀请签约', |
| | | }, |
| | | inviteSignBtn: { |
| | | emits: { |
| | | onClick: (role) => handleInviteSign(role), |
| | | }, |
| | |
| | | ), |
| | | }, |
| | | }, |
| | | { |
| | | data: { |
| | | enCode: 'unSignBtn', |
| | | name: '解约', |
| | | }, |
| | | unSignBtn: { |
| | | emits: { |
| | | onClick: (role) => handleUnSign(role), |
| | | }, |
| | |
| | | ), |
| | | }, |
| | | }, |
| | | // { |
| | | // data: { |
| | | // enCode: 'delBtn', |
| | | // name: '删除', |
| | | // }, |
| | | // props: { type: 'danger' }, |
| | | // emits: { |
| | | // onClick: (role) => handleDelete(role), |
| | | // }, |
| | | // }, |
| | | ]); |
| | | }; |
| | | |
| | | const { checkSubModuleItemShow, column, operationBtns } = useAccess({ |
| | | operationBtnMap, |
| | | }); |
| | | |
| | | const router = useRouter(); |
| | | |
| New file |
| | |
| | | <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> |
| New file |
| | |
| | | <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> |
| New file |
| | |
| | | <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> |
| | |
| | | </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" |
| | |
| | | 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'; |
| | |
| | | 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', |
| | | }, |
| | |
| | | onClick: (role) => openResetPasswordDialog(role), |
| | | }, |
| | | }, |
| | | { |
| | | data: { |
| | | enCode: 'resetOperatorPasswordBtn', |
| | | name: '重置操作密码', |
| | | }, |
| | | resetOperatorPasswordBtn: { |
| | | props: { |
| | | type: 'danger', |
| | | }, |
| | |
| | | onClick: (role) => openResetOperatorPasswordDialog(role), |
| | | }, |
| | | }, |
| | | ]); |
| | | }; |
| | | |
| | | const { checkSubModuleItemShow, column, operationBtns } = useAccess({ |
| | | operationBtnMap, |
| | | }); |
| | | |
| | | const router = useRouter(); |
| | | const BaseState = { |