feat(系统管理): 成员和项目添加下拉检索
This commit is contained in:
parent
aef40e0a8d
commit
99fd8437c7
|
@ -46,6 +46,6 @@ export function getProjectUserGroup(projectId: string) {
|
|||
}
|
||||
|
||||
// 项目成员下拉选项
|
||||
export function getProjectMemberOptions(projectId: string) {
|
||||
return MSR.get({ url: ProjectMemberOptions, params: projectId });
|
||||
export function getProjectMemberOptions(projectId: string, keyword?: string) {
|
||||
return MSR.get({ url: `${ProjectMemberOptions}/${projectId}`, params: { keyword } });
|
||||
}
|
||||
|
|
|
@ -40,10 +40,10 @@ export function getGlobalUserGroup(organizationId: string) {
|
|||
return MSR.get({ url: getUserGroupList, params: organizationId });
|
||||
}
|
||||
// 获取系统用户下拉
|
||||
export function getUser(organizationId: string) {
|
||||
return MSR.get<LinkItem[]>({ url: getUserList, params: organizationId });
|
||||
export function getUser(organizationId: string, keyword: string) {
|
||||
return MSR.get<LinkItem[]>({ url: `${getUserList}/${organizationId}`, params: { keyword } });
|
||||
}
|
||||
// 获取组织下边的项目
|
||||
export function getProjectList(organizationId: string) {
|
||||
return MSR.get<LinkItem[]>({ url: getProjectListUrl, params: organizationId });
|
||||
export function getProjectList(organizationId: string, keyword?: string) {
|
||||
return MSR.get<LinkItem[]>({ url: `${getProjectListUrl}/${organizationId}`, params: { keyword } });
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import {
|
|||
getUserByProjectByOrg,
|
||||
} from '@/api/modules/setting/organizationAndProject';
|
||||
import { getOrgUserGroupOption, getSystemUserGroupOption } from '@/api/modules/setting/usergroup';
|
||||
import { getUser, getProjectList } from '@/api/modules/setting/member';
|
||||
import { getProjectMemberOptions } from '@/api/modules/project-management/projectMember';
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
export enum UserRequesetTypeEnum {
|
||||
|
@ -17,6 +19,9 @@ export enum UserRequesetTypeEnum {
|
|||
ORGANIZATION_USER_GROUP_ADMIN = 'ORGANIZATION_USER_GROUP_ADMIN',
|
||||
ORGANIZATION_PROJECT = 'ORGANIZATION_PROJECT',
|
||||
ORGANIZATION_PROJECT_ADMIN = 'ORGANIZATION_PROJECT_ADMIN',
|
||||
SYSTEM_ORGANIZATION_PROJECT = 'SYSTEM_ORGANIZATION_PROJECT',
|
||||
SYSTEM_ORGANIZATION_MEMBER = 'SYSTEM_ORGANIZATION_MEMBER',
|
||||
PROJECT_PERMISSION_MEMBER = 'PROJECT_PERMISSION_MEMBER',
|
||||
}
|
||||
export default function initOptionsFunc(type: string, params: Record<string, any>) {
|
||||
if (type === UserRequesetTypeEnum.SYSTEM_USER_GROUP) {
|
||||
|
@ -43,4 +48,16 @@ export default function initOptionsFunc(type: string, params: Record<string, any
|
|||
// 组织 - 项目-添加管理员-下拉选项
|
||||
return getAdminByProjectByOrg(params.organizationId, params.keyword);
|
||||
}
|
||||
if (type === UserRequesetTypeEnum.SYSTEM_ORGANIZATION_PROJECT) {
|
||||
// 系统-组织-组织项目
|
||||
return getProjectList(params.organizationId, params.keyword);
|
||||
}
|
||||
if (type === UserRequesetTypeEnum.SYSTEM_ORGANIZATION_MEMBER) {
|
||||
// 系统-组织-组织成员
|
||||
return getUser(params.organizationId, params.keyword);
|
||||
}
|
||||
if (type === UserRequesetTypeEnum.PROJECT_PERMISSION_MEMBER) {
|
||||
// 系统-组织-项目成员
|
||||
return getProjectMemberOptions(params.projectId, params.keyword);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -416,6 +416,9 @@
|
|||
border-color: rgb(var(--primary-5));
|
||||
background: rgb(var(--primary-1));
|
||||
}
|
||||
.arco-icon-hover:hover::before {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
:deep(.ms-table-select-all) {
|
||||
.arco-checkbox {
|
||||
|
@ -426,5 +429,14 @@
|
|||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 2px;
|
||||
&:hover {
|
||||
border-color: rgb(var(--primary-5));
|
||||
}
|
||||
&::before {
|
||||
background: none !important;
|
||||
}
|
||||
}
|
||||
:deep(.arco-checkbox:hover .arco-checkbox-icon-hover::before) {
|
||||
background: none !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -15,9 +15,13 @@
|
|||
asterisk-position="end"
|
||||
:rules="[{ required: true, message: t('project.member.selectMemberEmptyTip') }]"
|
||||
>
|
||||
<a-select v-model="form.userIds" multiple :placeholder="t('project.member.selectMemberScope')" allow-clear>
|
||||
<a-option v-for="item of memberList" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||
</a-select>
|
||||
<MsUserSelector
|
||||
v-model:value="form.userIds"
|
||||
:load-option-params="{ projectId: lastProjectId }"
|
||||
:type="UserRequesetTypeEnum.PROJECT_PERMISSION_MEMBER"
|
||||
placeholder="project.member.selectMemberScope"
|
||||
disabled-key="memberFlag"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="roleIds"
|
||||
|
@ -40,8 +44,14 @@
|
|||
import { getProjectMemberOptions, addOrUpdateProjectMember } from '@/api/modules/project-management/projectMember';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useUserStore } from '@/store';
|
||||
import MsUserSelector from '@/components/business/ms-user-selector/index.vue';
|
||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||
import type { ProjectUserOption, ActionProjectMember } from '@/models/projectManagement/projectAndPermission';
|
||||
import type {
|
||||
ProjectUserOption,
|
||||
ActionProjectMember,
|
||||
AddProjectMember,
|
||||
} from '@/models/projectManagement/projectAndPermission';
|
||||
import { UserRequesetTypeEnum } from '@/components/business/ms-user-selector/utils';
|
||||
|
||||
const { t } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
|
@ -58,13 +68,13 @@
|
|||
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
const initFormValue: ActionProjectMember = {
|
||||
const initFormValue: AddProjectMember = {
|
||||
roleIds: ['project_member'],
|
||||
userIds: [],
|
||||
projectId: lastProjectId,
|
||||
projectId: lastProjectId as string,
|
||||
};
|
||||
|
||||
const form = ref<ActionProjectMember>({ ...initFormValue });
|
||||
const form = ref<AddProjectMember>({ ...initFormValue });
|
||||
|
||||
const memberFormRef = ref<FormInstance | null>(null);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
v-else
|
||||
v-model="record.selectUserList"
|
||||
multiple
|
||||
class="w-[260px]"
|
||||
:max-tag-count="2"
|
||||
@popup-visible-change="(value) => userGroupChange(value, record)"
|
||||
>
|
||||
|
@ -62,6 +63,7 @@
|
|||
position="br"
|
||||
:title="t('project.member.deleteMemberTip', { name: characterLimit(record.name) })"
|
||||
:sub-title-tip="t('project.member.subTitle')"
|
||||
:loading="deleteLoading"
|
||||
@ok="removeMember(record)"
|
||||
/>
|
||||
</template>
|
||||
|
@ -157,7 +159,7 @@
|
|||
title: 'project.member.tableColumnActions',
|
||||
slotName: 'action',
|
||||
fixed: 'right',
|
||||
width: 80,
|
||||
width: 100,
|
||||
showInTable: true,
|
||||
},
|
||||
];
|
||||
|
@ -244,7 +246,10 @@
|
|||
};
|
||||
|
||||
// 移除项目成员
|
||||
const deleteLoading = ref<boolean>(false);
|
||||
|
||||
const removeMember = async (record: ProjectMemberItem) => {
|
||||
deleteLoading.value = true;
|
||||
try {
|
||||
if (lastProjectId && record.id) {
|
||||
await removeProjectMember(lastProjectId, record.id);
|
||||
|
@ -253,6 +258,8 @@
|
|||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
deleteLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
</template>
|
||||
<div class="form">
|
||||
<a-form ref="memberFormRef" :model="form" size="large" layout="vertical">
|
||||
<!-- 编辑项目 -->
|
||||
<a-form-item v-if="type === 'edit'" :label="t('organization.member.project')" asterisk-position="end">
|
||||
<a-select
|
||||
v-model="form.projectIds"
|
||||
multiple
|
||||
:placeholder="t('organization.member.selectProjectScope')"
|
||||
allow-clear
|
||||
>
|
||||
<a-option v-for="item of props.projectList" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||
</a-select>
|
||||
<MsUserSelector
|
||||
v-model:value="form.projectIds"
|
||||
:load-option-params="{ organizationId: lastOrganizationId }"
|
||||
:type="UserRequesetTypeEnum.SYSTEM_ORGANIZATION_PROJECT"
|
||||
placeholder="organization.member.selectProjectScope"
|
||||
/>
|
||||
</a-form-item>
|
||||
<!-- 添加成员 -->
|
||||
<a-form-item
|
||||
v-else
|
||||
field="memberIds"
|
||||
|
@ -33,14 +33,12 @@
|
|||
asterisk-position="end"
|
||||
:rules="[{ required: true, message: t('organization.member.selectMemberEmptyTip') }]"
|
||||
>
|
||||
<a-select
|
||||
v-model="form.memberIds"
|
||||
multiple
|
||||
:placeholder="t('organization.member.selectMemberScope')"
|
||||
allow-clear
|
||||
>
|
||||
<a-option v-for="item of memberList" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||
</a-select>
|
||||
<MsUserSelector
|
||||
v-model:value="form.memberIds"
|
||||
:load-option-params="{ organizationId: lastOrganizationId }"
|
||||
:type="UserRequesetTypeEnum.SYSTEM_ORGANIZATION_MEMBER"
|
||||
placeholder="organization.member.selectMemberScope"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="userRoleIds"
|
||||
|
@ -72,9 +70,11 @@
|
|||
import { ref, watchEffect, watch } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
|
||||
import { addOrUpdate, getUser } from '@/api/modules/setting/member';
|
||||
import { addOrUpdate } from '@/api/modules/setting/member';
|
||||
import { useUserStore } from '@/store';
|
||||
import type { AddorUpdateMemberModel, MemberItem, LinkList } from '@/models/setting/member';
|
||||
import MsUserSelector from '@/components/business/ms-user-selector/index.vue';
|
||||
import type { MemberItem, LinkList } from '@/models/setting/member';
|
||||
import { UserRequesetTypeEnum } from '@/components/business/ms-user-selector/utils';
|
||||
|
||||
const { t } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
|
@ -82,10 +82,8 @@
|
|||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
userGroupOptions: LinkList;
|
||||
projectList: LinkList;
|
||||
}>();
|
||||
const dialogVisible = ref<boolean>(false);
|
||||
const memberList = ref<LinkList>([]);
|
||||
const title = ref<string>('');
|
||||
const type = ref<string>('');
|
||||
const emits = defineEmits<{
|
||||
|
@ -95,13 +93,20 @@
|
|||
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
const memberFormRef = ref<FormInstance | null>(null);
|
||||
const initFormValue = {
|
||||
export interface InitFromType {
|
||||
organizationId?: string;
|
||||
userRoleIds: string[];
|
||||
memberIds: string[];
|
||||
projectIds: string[];
|
||||
}
|
||||
|
||||
const initFormValue: InitFromType = {
|
||||
organizationId: userStore.$state?.lastOrganizationId,
|
||||
userRoleIds: ['org_member'],
|
||||
memberIds: [],
|
||||
projectIds: [],
|
||||
};
|
||||
const form = ref<AddorUpdateMemberModel>({ ...initFormValue });
|
||||
const form = ref({ ...initFormValue });
|
||||
const handleCancel = () => {
|
||||
memberFormRef.value?.resetFields();
|
||||
form.value = { ...initFormValue };
|
||||
|
@ -157,12 +162,9 @@
|
|||
}
|
||||
});
|
||||
};
|
||||
const getUserOptions = async () => {
|
||||
memberList.value = await getUser(lastOrganizationId);
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
dialogVisible.value = props.visible;
|
||||
if (props.visible) getUserOptions();
|
||||
});
|
||||
watch(
|
||||
() => dialogVisible.value,
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
multiple
|
||||
:max-tag-count="2"
|
||||
size="small"
|
||||
class="w-[260px]"
|
||||
@change="(value) => selectUserOrProject(value, record, 'project')"
|
||||
@popup-visible-change="visibleChange($event, record, 'project')"
|
||||
>
|
||||
|
@ -57,6 +58,7 @@
|
|||
v-model="record.selectUserList"
|
||||
multiple
|
||||
:max-tag-count="2"
|
||||
class="w-[260px]"
|
||||
@change="(value) => selectUserOrProject(value, record, 'user')"
|
||||
@popup-visible-change="(value) => visibleChange(value, record, 'user')"
|
||||
>
|
||||
|
@ -79,6 +81,7 @@
|
|||
position="br"
|
||||
:title="t('organization.member.deleteMemberTip', { name: characterLimit(record.name) })"
|
||||
:sub-title-tip="t('organization.member.subTitle')"
|
||||
:loading="deleteLoading"
|
||||
@ok="deleteMember(record)"
|
||||
/>
|
||||
</template>
|
||||
|
@ -126,7 +129,7 @@
|
|||
import { useTableStore, useUserStore } from '@/store';
|
||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import type { MemberItem, AddorUpdateMemberModel, LinkList, BatchAddProjectModel } from '@/models/setting/member';
|
||||
import { characterLimit } from '@/utils';
|
||||
import { characterLimit, findNodeByKey } from '@/utils';
|
||||
import MsTagGroup from '@/components/pure/ms-tag/ms-tag-group.vue';
|
||||
|
||||
const tableStore = useTableStore();
|
||||
|
@ -230,13 +233,18 @@
|
|||
AddMemberRef.value.edit(record);
|
||||
}
|
||||
};
|
||||
|
||||
const deleteLoading = ref<boolean>(false);
|
||||
const deleteMember = async (record: MemberItem) => {
|
||||
deleteLoading.value = true;
|
||||
try {
|
||||
if (lastOrganizationId) await deleteMemberReq(lastOrganizationId, record.id);
|
||||
Message.success(t('organization.member.deleteMemberSuccess'));
|
||||
initData();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
deleteLoading.value = false;
|
||||
}
|
||||
};
|
||||
const handleTableSelect = (selectArr: (string | number)[]) => {
|
||||
|
|
Loading…
Reference in New Issue