From c1108b48dbf8052a6817bf48def8b84db2a4ac5b Mon Sep 17 00:00:00 2001 From: "xinxin.wu" Date: Fri, 1 Sep 2023 18:06:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=A1=B9=E7=9B=AE=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=AE=A1=E7=90=86=E6=88=90=E5=91=98=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E8=81=94=E8=B0=83&=E5=B0=81=E8=A3=85=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E7=BB=84=E4=BB=B6tag&tagGroup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project-management/projectMember.ts | 51 +++++ .../project-management/projectMember.ts | 8 + frontend/src/assets/style/arco-reset.less | 12 -- .../business/ms-batch-modal/index.vue | 126 ++++------- .../business/ms-batch-modal/locale/en-US.ts | 14 +- .../business/ms-batch-modal/locale/zh-CN.ts | 14 +- .../src/components/pure/ms-dialog/index.vue | 14 +- .../components/pure/ms-tag/ms-tag-group.vue | 29 +++ .../src/components/pure/ms-tag/ms-tag.vue | 121 +++++++++++ frontend/src/config/pathMap.ts | 47 +++- .../projectManagement/projectAndPermission.ts | 52 +++++ frontend/src/store/modules/user/types.ts | 1 + .../projectAndPermission/basicInfos/index.vue | 8 +- .../member/components/addMemberModal.vue | 98 ++++++--- .../projectAndPermission/member/index.vue | 204 ++++++++++++++---- .../member/locale/en-US.ts | 3 +- .../member/locale/zh-CN.ts | 3 +- .../member/components/addMemberModal.vue | 1 + .../setting/organization/member/index.vue | 160 ++++++-------- 19 files changed, 670 insertions(+), 296 deletions(-) create mode 100644 frontend/src/api/modules/project-management/projectMember.ts create mode 100644 frontend/src/api/requrls/project-management/projectMember.ts create mode 100644 frontend/src/components/pure/ms-tag/ms-tag-group.vue create mode 100644 frontend/src/components/pure/ms-tag/ms-tag.vue diff --git a/frontend/src/api/modules/project-management/projectMember.ts b/frontend/src/api/modules/project-management/projectMember.ts new file mode 100644 index 0000000000..075c7fc794 --- /dev/null +++ b/frontend/src/api/modules/project-management/projectMember.ts @@ -0,0 +1,51 @@ +import MSR from '@/api/http/index'; +import { + GetProjectMemberListUrl, + AddMemberToProjectUrl, + EditProjectMemberUrl, + BatchAddUserGroup, + BatchRemoveMemberUrl, + RemoveProjectMemberUrl, + ProjectUserGroupUrl, + ProjectMemberOptions, +} from '@/api/requrls/project-management/projectMember'; +import type { ProjectMemberItem, ActionProjectMember } from '@/models/projectManagement/projectAndPermission'; +import type { TableQueryParams, CommonList } from '@/models/common'; + +// 获取项目成员列表 +export function getProjectMemberList(data: TableQueryParams) { + return MSR.post>({ url: GetProjectMemberListUrl, data }); +} + +// 添加项目成员&编辑项目成员 +export function addOrUpdateProjectMember(data: ActionProjectMember) { + if (data.userId) { + return MSR.post({ url: EditProjectMemberUrl, data }); + } + return MSR.post({ url: AddMemberToProjectUrl, data }); +} + +// 添加项目成员到用户组 +export function addProjectUserGroup(data: ActionProjectMember) { + return MSR.post({ url: BatchAddUserGroup, data }); +} + +// 批量移除项目成员 +export function batchRemoveMember(data: ActionProjectMember) { + return MSR.post({ url: BatchRemoveMemberUrl, data }); +} + +// 移除项目成员 +export function removeProjectMember(projectId: string, userId: string) { + return MSR.get({ url: RemoveProjectMemberUrl, params: `${projectId}/${userId}` }); +} + +// 获取用户组下拉 +export function getProjectUserGroup(projectId: string) { + return MSR.get({ url: ProjectUserGroupUrl, params: projectId }); +} + +// 项目成员下拉选项 +export function getProjectMemberOptions(projectId: string) { + return MSR.get({ url: ProjectMemberOptions, params: projectId }); +} diff --git a/frontend/src/api/requrls/project-management/projectMember.ts b/frontend/src/api/requrls/project-management/projectMember.ts new file mode 100644 index 0000000000..e2ca60a91c --- /dev/null +++ b/frontend/src/api/requrls/project-management/projectMember.ts @@ -0,0 +1,8 @@ +export const GetProjectMemberListUrl = '/project/member/list'; +export const AddMemberToProjectUrl = '/project/member/add'; +export const EditProjectMemberUrl = '/project/member/update'; +export const BatchRemoveMemberUrl = '/project/member/batch/remove'; +export const RemoveProjectMemberUrl = '/project/member/remove'; +export const BatchAddUserGroup = '/project/member/add-role'; +export const ProjectUserGroupUrl = '/project/member/get-role/option'; +export const ProjectMemberOptions = '/project/member/get-member/option'; diff --git a/frontend/src/assets/style/arco-reset.less b/frontend/src/assets/style/arco-reset.less index e09c0c08d2..9a274381ed 100644 --- a/frontend/src/assets/style/arco-reset.less +++ b/frontend/src/assets/style/arco-reset.less @@ -618,18 +618,6 @@ font-weight: 500; } -/** 标签 **/ -.arco-tag { - .arco-icon { - font-size: 14px; - } - .arco-tag-close-btn { - .arco-icon { - color: var(--color-text-brand); - } - } -} - /** 虚拟列表 **/ .arco-virtual-list { .ms-scroll-bar(); diff --git a/frontend/src/components/business/ms-batch-modal/index.vue b/frontend/src/components/business/ms-batch-modal/index.vue index 3e573c0e60..60ee1385bd 100644 --- a/frontend/src/components/business/ms-batch-modal/index.vue +++ b/frontend/src/components/business/ms-batch-modal/index.vue @@ -3,33 +3,28 @@ - - {{ t('msbatchmodal.batchModalTip') }} - - - - + + + {{ t('msBatchModal.batchModalTip') }} + + + @@ -40,6 +35,7 @@ import { useI18n } from '@/hooks/useI18n'; import { Message } from '@arco-design/web-vue'; import type { BatchModel } from './types'; + import MsTransfer from '@/components/pure/ms-transfer/index.vue'; const { t } = useI18n(); @@ -49,18 +45,11 @@ children?: TreeDataItem[]; } - interface TransferDataItem { - value: string; - label: string; - disabled: boolean; - } - const props = withDefaults( defineProps<{ tableSelected: (string | number)[]; visible: boolean; action: string; - treeData: TreeDataItem[]; }>(), { visible: false, @@ -70,7 +59,7 @@ (e: 'update:visible', val: boolean): void; (e: 'addProject', targetValue: string[], type: string): void; (e: 'addUserGroup', targetValue: string[], type: string): void; - (e: 'addOrgnization', targetValue: string[], type: string): void; + (e: 'addOrganization', targetValue: string[], type: string): void; }>(); const showBatchModal = ref(false); @@ -78,6 +67,7 @@ const batchTitle = ref(''); const target = ref([]); const treeList = ref([]); + const loading = ref(false); function handleTableBatch(action: string) { switch (action) { @@ -115,78 +105,38 @@ } ); - /** - * 获取穿梭框数据,根据树结构获取 - * @param _treeData 树结构 - * @param transferDataSource 穿梭框数组 - */ - const getTransferData = (_treeData: TreeDataItem[], transferDataSource: TransferDataItem[]) => { - _treeData.forEach((item) => { - if (item.children) getTransferData(item.children, transferDataSource); - else transferDataSource.push({ label: item.title, value: item.key, disabled: false }); - }); - return transferDataSource; - }; - - /** - * 获取树结构数据,根据穿梭框过滤的数据获取 - */ - const getTreeData = (data: TransferDataItem[]) => { - const values = data.map((item) => item.value); - - const travel = (_treeData: TreeDataItem[]) => { - const treeDataSource: TreeDataItem[] = []; - _treeData.forEach((item) => { - // 需要判断当前父节点下的子节点是否全部选中,若选中则不会 push 进穿梭框数组内,否则会出现空的节点无法选中 - const allSelected = item.children?.every((child) => target.value.includes(child.key)); - if (!allSelected && (item.children || values.includes(item.key))) { - treeDataSource.push({ - title: item.title, - key: item.key, - children: item.children ? travel(item.children) : [], - }); - } - }); - return treeDataSource; - }; - - return travel(treeList.value); - }; - let transferData: TransferDataItem[] = []; - function cancelBatch() { showBatchModal.value = false; target.value = []; } + const batchRequestFun = async (reqFun: any, params: BatchModel) => { batchLoading.value = true; + loading.value = true; try { await reqFun(params); - Message.success(t('organization.member.batchModalSuccess')); + Message.success(t('msBatchModal.batchModalSuccess')); showBatchModal.value = false; target.value = []; } catch (error) { console.log(error); } finally { batchLoading.value = false; + loading.value = false; } }; const confirmBatch = async () => { - batchLoading.value = true; - if (target.value.length < 1) { - return; - } try { switch (props.action) { case 'batchAddProject': emit('addProject', target.value, 'project'); break; case 'batchAddUserGroup': - emit('addUserGroup', target.value, 'usergroup'); + emit('addUserGroup', target.value, 'userGroup'); break; case 'batchAddOrganization': - emit('addOrgnization', target.value, 'orgnization'); + emit('addOrganization', target.value, 'organization'); break; default: break; @@ -195,17 +145,21 @@ console.log(error); } }; - watch( - () => props.treeData, - (newVal) => { - treeList.value = newVal; - transferData = getTransferData(treeList.value, []); - }, - { deep: true, immediate: true } - ); + + const getTreeList = async (callBack: (orgId: string) => Promise, orgId: string) => { + loading.value = true; + try { + treeList.value = await callBack(orgId); + loading.value = false; + } catch (error) { + console.log(error); + } + }; + defineExpose({ batchLoading, batchRequestFun, + getTreeList, }); diff --git a/frontend/src/components/business/ms-batch-modal/locale/en-US.ts b/frontend/src/components/business/ms-batch-modal/locale/en-US.ts index 908d36e615..e227d29d5f 100644 --- a/frontend/src/components/business/ms-batch-modal/locale/en-US.ts +++ b/frontend/src/components/business/ms-batch-modal/locale/en-US.ts @@ -1,8 +1,10 @@ export default { - 'msbatchmodal.batchModalSubTitle': '(Selected {count} users)', - 'msbatchmodal.batchModalTip': 'Add project member usergroup as member by default', - 'msbatchmodal.batchOptional': 'Optional', - 'msbatchmodal.batchChosen': 'Chosen', - 'msbatchmodal.batchModalCancel': 'Cancel', - 'msbatchmodal.batchModalConfirm': 'Add', + 'msBatchModal.batchModalSubTitle': '(Selected {count} users)', + 'msBatchModal.batchModalTip': 'Add project member userGroup as member by default', + 'msBatchModal.batchOptional': 'Optional', + 'msBatchModal.batchChosen': 'Chosen', + 'msBatchModal.batchModalCancel': 'Cancel', + 'msBatchModal.batchModalConfirm': 'Add', + 'msBatchModal.batchModalEmpty': 'The selection can not be empty', + 'msBatchModal.batchModalSuccess': 'Successfully added', }; diff --git a/frontend/src/components/business/ms-batch-modal/locale/zh-CN.ts b/frontend/src/components/business/ms-batch-modal/locale/zh-CN.ts index 7879793b94..aecdae797e 100644 --- a/frontend/src/components/business/ms-batch-modal/locale/zh-CN.ts +++ b/frontend/src/components/business/ms-batch-modal/locale/zh-CN.ts @@ -1,8 +1,10 @@ export default { - 'msbatchmodal.batchModalSubTitle': '已选 {count} 个用户)', - 'msbatchmodal.batchModalTip': '默认为成员添加项目成员用户组', - 'msbatchmodal.batchOptional': '可选', - 'msbatchmodal.batchChosen': '已选', - 'msbatchmodal.batchModalCancel': '取消', - 'msbatchmodal.batchModalConfirm': '添加', + 'msBatchModal.batchModalSubTitle': '已选 {count} 个用户)', + 'msBatchModal.batchModalTip': '默认为成员添加项目成员用户组', + 'msBatchModal.batchOptional': '可选', + 'msBatchModal.batchChosen': '已选', + 'msBatchModal.batchModalCancel': '取消', + 'msBatchModal.batchModalConfirm': '添加', + 'msBatchModal.batchModalEmpty': '选择内容不能为空', + 'msBatchModal.batchModalSuccess': '添加成功', }; diff --git a/frontend/src/components/pure/ms-dialog/index.vue b/frontend/src/components/pure/ms-dialog/index.vue index d149f5c724..57dab23102 100644 --- a/frontend/src/components/pure/ms-dialog/index.vue +++ b/frontend/src/components/pure/ms-dialog/index.vue @@ -49,7 +49,7 @@ + + diff --git a/frontend/src/components/pure/ms-tag/ms-tag.vue b/frontend/src/components/pure/ms-tag/ms-tag.vue new file mode 100644 index 0000000000..ed41b76707 --- /dev/null +++ b/frontend/src/components/pure/ms-tag/ms-tag.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/frontend/src/config/pathMap.ts b/frontend/src/config/pathMap.ts index 26c4df1a08..6dd58df7a8 100644 --- a/frontend/src/config/pathMap.ts +++ b/frontend/src/config/pathMap.ts @@ -159,6 +159,51 @@ export const pathMap = [ route: RouteEnum.PROJECT_MANAGEMENT, permission: [], level: MENU_LEVEL[2], - children: [], + children: [ + { + key: 'PROJECT_MANAGEMENT_PERMISSION', // 项目管理-项目与权限 + locale: 'menu.projectManagement.projectPermission', + route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION, + permission: [], + level: MENU_LEVEL[0], + children: [ + { + key: 'PROJECT_MANAGEMENT_PERMISSION_BASIC_INFO', // 项目管理-项目与权限-基本信息 + locale: 'project.permission.basicInfo', + route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_BASIC_INFO, + permission: [], + level: MENU_LEVEL[0], + }, + { + key: 'PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT', // 项目管理-项目与权限-菜单管理 + locale: 'project.permission.menuManagement', + route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT, + permission: [], + level: MENU_LEVEL[0], + }, + { + key: 'PROJECT_MANAGEMENT_PERMISSION_VERSION', // 项目管理-项目与权限-项目版本 + locale: 'project.permission.projectVersion', + route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_VERSION, + permission: [], + level: MENU_LEVEL[0], + }, + { + key: 'PROJECT_MANAGEMENT_PERMISSION_MEMBER', // 项目管理-项目与权限-成员 + locale: 'project.permission.member', + route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_MEMBER, + permission: [], + level: MENU_LEVEL[0], + }, + { + key: 'PROJECT_MANAGEMENT_PERMISSION_USER_GROUP', // 项目管理-项目与权限-用户组 + locale: 'project.permission.userGroup', + route: RouteEnum.PROJECT_MANAGEMENT_PERMISSION_USER_GROUP, + permission: [], + level: MENU_LEVEL[0], + }, + ], + }, + ], }, ]; diff --git a/frontend/src/models/projectManagement/projectAndPermission.ts b/frontend/src/models/projectManagement/projectAndPermission.ts index a4cb4ed7ae..d3ef30d483 100644 --- a/frontend/src/models/projectManagement/projectAndPermission.ts +++ b/frontend/src/models/projectManagement/projectAndPermission.ts @@ -3,3 +3,55 @@ export interface ProjectTreeData { title: string; children?: ProjectTreeData[]; } + +export interface UserGroupItem { + id: string; + name: string; + description: string; + internal: boolean; + type: string; + createTime: number | string; + updateTime: number | string; + createUser: string; + scopeId: string; +} +export interface ProjectMemberItem { + id?: string; + name: string; + email: string; + password: string; + enable: boolean; // 是否启用 + createTime: number | string; + updateTime: number | string; + language: string; + lastOrganizationId: string; // 组织id + phone: string; + source: string; + lastProjectId: string; // 项目id + createUser: string; + updateUser: string; + deleted: true; // 是否被删除 + userRoles: UserGroupItem[]; + showUserSelect?: boolean; // 是否可以选择 + selectUserList?: string[]; // 已选择项目用户组 +} + +export interface ActionProjectMember { + userId?: string; + projectId?: string; // 项目ID + userIds?: (string | number)[]; // 用户ID集合 + roleIds?: string[]; // 用户组ID集合 +} + +export interface ProjectUserOption { + id: string; + name: string; +} + +export interface SearchParams { + filter: { + roleIds: string[]; + }; + projectId: string; + keyword: ''; +} diff --git a/frontend/src/store/modules/user/types.ts b/frontend/src/store/modules/user/types.ts index eaa283f842..c5d5b8540a 100644 --- a/frontend/src/store/modules/user/types.ts +++ b/frontend/src/store/modules/user/types.ts @@ -17,6 +17,7 @@ export interface UserState { certification?: number; role: RoleType; lastOrganizationId?: string; + lastProjectId?: string; // 盐 salt: string; } diff --git a/frontend/src/views/project-management/projectAndPermission/basicInfos/index.vue b/frontend/src/views/project-management/projectAndPermission/basicInfos/index.vue index ac2abf2fab..62c986b87d 100644 --- a/frontend/src/views/project-management/projectAndPermission/basicInfos/index.vue +++ b/frontend/src/views/project-management/projectAndPermission/basicInfos/index.vue @@ -9,8 +9,8 @@
-
-
+
+
具体的项目名称 {{ t('project.basicInfo.enable') }} @@ -55,6 +55,10 @@ label: 'project.basicInfo.edit', eventTag: 'edit', }, + { + label: 'project.basicInfo.enable', + eventTag: 'enable', + }, { label: 'project.basicInfo.finish', eventTag: 'finish', diff --git a/frontend/src/views/project-management/projectAndPermission/member/components/addMemberModal.vue b/frontend/src/views/project-management/projectAndPermission/member/components/addMemberModal.vue index 5c989939b6..85ae133287 100644 --- a/frontend/src/views/project-management/projectAndPermission/member/components/addMemberModal.vue +++ b/frontend/src/views/project-management/projectAndPermission/member/components/addMemberModal.vue @@ -3,30 +3,30 @@ v-model:visible="visible" dialog-size="medium" title="project.member.addMember" - :close="closeHandler" - :confirm="confirmFunHandler" ok-text="project.member.add" + :confirm="confirmHandler" + :close="closeHandler" >
- + {{ item.name }} - - {{ item.name }} + + {{ item.name }} @@ -35,49 +35,87 @@ diff --git a/frontend/src/views/project-management/projectAndPermission/member/index.vue b/frontend/src/views/project-management/projectAndPermission/member/index.vue index d75134a034..dd793e097d 100644 --- a/frontend/src/views/project-management/projectAndPermission/member/index.vue +++ b/frontend/src/views/project-management/projectAndPermission/member/index.vue @@ -4,10 +4,8 @@ >{{ t('project.member.addMember') }}
- - {{ - t(item.name) - }} + + {{ t(item.name) }} @@ -15,6 +13,7 @@ >
- + diff --git a/frontend/src/views/project-management/projectAndPermission/member/locale/en-US.ts b/frontend/src/views/project-management/projectAndPermission/member/locale/en-US.ts index 6ff1557094..ef95bd42ce 100644 --- a/frontend/src/views/project-management/projectAndPermission/member/locale/en-US.ts +++ b/frontend/src/views/project-management/projectAndPermission/member/locale/en-US.ts @@ -5,7 +5,6 @@ export default { 'project.member.remove': 'Remove', 'project.member.edit': 'Edit', 'project.member.add': 'Add', - 'project.member.batchActionAddProject': 'Add to project', 'project.member.batchActionAddUserGroup': 'Add to usergroup', 'project.member.tableEnable': 'Enabled', 'project.member.tableDisable': 'Disabled', @@ -28,7 +27,7 @@ export default { 'system.user.deleteUserTip': 'Are you sure to delete the user `{name}` ?', 'project.member.deleteMemberConfirm': 'Delete', 'project.member.deleteMemberCancel': 'Cancel', - 'project.member.deleteMemberSuccess': 'Delete successful', + 'project.member.deleteMemberSuccess': 'Remove successful', 'project.member.batchModalSuccess': 'Successfully added', 'project.member.batchUpdateSuccess': 'Successfully updated', 'project.member.project': 'Project', diff --git a/frontend/src/views/project-management/projectAndPermission/member/locale/zh-CN.ts b/frontend/src/views/project-management/projectAndPermission/member/locale/zh-CN.ts index b8e5eb0ff6..68294a208f 100644 --- a/frontend/src/views/project-management/projectAndPermission/member/locale/zh-CN.ts +++ b/frontend/src/views/project-management/projectAndPermission/member/locale/zh-CN.ts @@ -5,7 +5,6 @@ export default { 'project.member.remove': '移除', 'project.member.edit': '编辑', 'project.member.add': '添加', - 'project.member.batchActionAddProject': '添加至项目', 'project.member.batchActionAddUserGroup': '添加至用户组', 'project.member.tableEnable': '正常', 'project.member.tableDisable': '禁用', @@ -27,7 +26,7 @@ export default { 'project.member.deleteMemberTip': '确认移除 {name} 这个成员吗?', 'project.member.deleteMemberConfirm': '确认删除', 'project.member.deleteMemberCancel': '取消', - 'project.member.deleteMemberSuccess': '删除成功', + 'project.member.deleteMemberSuccess': '移除成功', 'project.member.batchModalSuccess': '添加成功', 'project.member.batchUpdateSuccess': '更新成功', 'project.member.project': '项目', diff --git a/frontend/src/views/setting/organization/member/components/addMemberModal.vue b/frontend/src/views/setting/organization/member/components/addMemberModal.vue index 3d7bf547f2..07a0c70d37 100644 --- a/frontend/src/views/setting/organization/member/components/addMemberModal.vue +++ b/frontend/src/views/setting/organization/member/components/addMemberModal.vue @@ -5,6 +5,7 @@ class="ms-modal-form ms-modal-medium" :ok-text="t('organization.member.Confirm')" :cancel-text="t('organization.member.Cancel')" + @close="handleCancel" >