feat(项目管理): 项目管理成员本地联调&封装公共组件tag&tagGroup
This commit is contained in:
parent
2a24e2938d
commit
c1108b48db
|
@ -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<CommonList<ProjectMemberItem>>({ 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 });
|
||||||
|
}
|
|
@ -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';
|
|
@ -618,18 +618,6 @@
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 标签 **/
|
|
||||||
.arco-tag {
|
|
||||||
.arco-icon {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.arco-tag-close-btn {
|
|
||||||
.arco-icon {
|
|
||||||
color: var(--color-text-brand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 虚拟列表 **/
|
/** 虚拟列表 **/
|
||||||
.arco-virtual-list {
|
.arco-virtual-list {
|
||||||
.ms-scroll-bar();
|
.ms-scroll-bar();
|
||||||
|
|
|
@ -3,33 +3,28 @@
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ batchTitle }}
|
{{ batchTitle }}
|
||||||
<div class="text-[var(--color-text-4)]">
|
<div class="text-[var(--color-text-4)]">
|
||||||
{{ t('msbatchmodal.batchModalSubTitle', { count: props.tableSelected.length }) }}
|
{{ t('msBatchModal.batchModalSubTitle', { count: props.tableSelected.length }) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<a-alert v-if="props.action === 'batchAddProject'" class="mb-[16px]">
|
<a-spin :loading="loading">
|
||||||
{{ t('msbatchmodal.batchModalTip') }}
|
<a-alert v-if="props.action === 'batchAddProject'" class="mb-[16px]">
|
||||||
</a-alert>
|
{{ t('msBatchModal.batchModalTip') }}
|
||||||
<a-transfer
|
</a-alert>
|
||||||
v-model="target"
|
<MsTransfer
|
||||||
:title="[t('msbatchmodal.batchOptional'), t('msbatchmodal.batchChosen')]"
|
v-model="target"
|
||||||
:data="transferData"
|
:data="treeList"
|
||||||
show-search
|
:tree-filed="{
|
||||||
>
|
key: 'id',
|
||||||
<template #source="{ data, selectedKeys, onSelect }">
|
title: 'name',
|
||||||
<a-tree
|
children: 'children',
|
||||||
:checkable="true"
|
disabled: 'disabled',
|
||||||
checked-strategy="child"
|
}"
|
||||||
:checked-keys="selectedKeys"
|
/>
|
||||||
:data="getTreeData(data)"
|
</a-spin>
|
||||||
block-node
|
|
||||||
@check="onSelect"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</a-transfer>
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-button type="secondary" @click="cancelBatch">{{ t('msbatchmodal.batchModalCancel') }}</a-button>
|
<a-button type="secondary" @click="cancelBatch">{{ t('msBatchModal.batchModalCancel') }}</a-button>
|
||||||
<a-button type="primary" :loading="batchLoading" @click="confirmBatch">
|
<a-button type="primary" :loading="batchLoading" :disabled="target.length < 1" @click="confirmBatch">
|
||||||
{{ t('msbatchmodal.batchModalConfirm') }}
|
{{ t('msBatchModal.batchModalConfirm') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
@ -40,6 +35,7 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import type { BatchModel } from './types';
|
import type { BatchModel } from './types';
|
||||||
|
import MsTransfer from '@/components/pure/ms-transfer/index.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -49,18 +45,11 @@
|
||||||
children?: TreeDataItem[];
|
children?: TreeDataItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TransferDataItem {
|
|
||||||
value: string;
|
|
||||||
label: string;
|
|
||||||
disabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
tableSelected: (string | number)[];
|
tableSelected: (string | number)[];
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
action: string;
|
action: string;
|
||||||
treeData: TreeDataItem[];
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
visible: false,
|
visible: false,
|
||||||
|
@ -70,7 +59,7 @@
|
||||||
(e: 'update:visible', val: boolean): void;
|
(e: 'update:visible', val: boolean): void;
|
||||||
(e: 'addProject', targetValue: string[], type: string): void;
|
(e: 'addProject', targetValue: string[], type: string): void;
|
||||||
(e: 'addUserGroup', 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);
|
const showBatchModal = ref(false);
|
||||||
|
@ -78,6 +67,7 @@
|
||||||
const batchTitle = ref('');
|
const batchTitle = ref('');
|
||||||
const target = ref<string[]>([]);
|
const target = ref<string[]>([]);
|
||||||
const treeList = ref<TreeDataItem[]>([]);
|
const treeList = ref<TreeDataItem[]>([]);
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
function handleTableBatch(action: string) {
|
function handleTableBatch(action: string) {
|
||||||
switch (action) {
|
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() {
|
function cancelBatch() {
|
||||||
showBatchModal.value = false;
|
showBatchModal.value = false;
|
||||||
target.value = [];
|
target.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const batchRequestFun = async (reqFun: any, params: BatchModel) => {
|
const batchRequestFun = async (reqFun: any, params: BatchModel) => {
|
||||||
batchLoading.value = true;
|
batchLoading.value = true;
|
||||||
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
await reqFun(params);
|
await reqFun(params);
|
||||||
Message.success(t('organization.member.batchModalSuccess'));
|
Message.success(t('msBatchModal.batchModalSuccess'));
|
||||||
showBatchModal.value = false;
|
showBatchModal.value = false;
|
||||||
target.value = [];
|
target.value = [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
batchLoading.value = false;
|
batchLoading.value = false;
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmBatch = async () => {
|
const confirmBatch = async () => {
|
||||||
batchLoading.value = true;
|
|
||||||
if (target.value.length < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
switch (props.action) {
|
switch (props.action) {
|
||||||
case 'batchAddProject':
|
case 'batchAddProject':
|
||||||
emit('addProject', target.value, 'project');
|
emit('addProject', target.value, 'project');
|
||||||
break;
|
break;
|
||||||
case 'batchAddUserGroup':
|
case 'batchAddUserGroup':
|
||||||
emit('addUserGroup', target.value, 'usergroup');
|
emit('addUserGroup', target.value, 'userGroup');
|
||||||
break;
|
break;
|
||||||
case 'batchAddOrganization':
|
case 'batchAddOrganization':
|
||||||
emit('addOrgnization', target.value, 'orgnization');
|
emit('addOrganization', target.value, 'organization');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -195,17 +145,21 @@
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
watch(
|
|
||||||
() => props.treeData,
|
const getTreeList = async (callBack: (orgId: string) => Promise<any>, orgId: string) => {
|
||||||
(newVal) => {
|
loading.value = true;
|
||||||
treeList.value = newVal;
|
try {
|
||||||
transferData = getTransferData(treeList.value, []);
|
treeList.value = await callBack(orgId);
|
||||||
},
|
loading.value = false;
|
||||||
{ deep: true, immediate: true }
|
} catch (error) {
|
||||||
);
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
batchLoading,
|
batchLoading,
|
||||||
batchRequestFun,
|
batchRequestFun,
|
||||||
|
getTreeList,
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
export default {
|
export default {
|
||||||
'msbatchmodal.batchModalSubTitle': '(Selected {count} users)',
|
'msBatchModal.batchModalSubTitle': '(Selected {count} users)',
|
||||||
'msbatchmodal.batchModalTip': 'Add project member usergroup as member by default',
|
'msBatchModal.batchModalTip': 'Add project member userGroup as member by default',
|
||||||
'msbatchmodal.batchOptional': 'Optional',
|
'msBatchModal.batchOptional': 'Optional',
|
||||||
'msbatchmodal.batchChosen': 'Chosen',
|
'msBatchModal.batchChosen': 'Chosen',
|
||||||
'msbatchmodal.batchModalCancel': 'Cancel',
|
'msBatchModal.batchModalCancel': 'Cancel',
|
||||||
'msbatchmodal.batchModalConfirm': 'Add',
|
'msBatchModal.batchModalConfirm': 'Add',
|
||||||
|
'msBatchModal.batchModalEmpty': 'The selection can not be empty',
|
||||||
|
'msBatchModal.batchModalSuccess': 'Successfully added',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
export default {
|
export default {
|
||||||
'msbatchmodal.batchModalSubTitle': '已选 {count} 个用户)',
|
'msBatchModal.batchModalSubTitle': '已选 {count} 个用户)',
|
||||||
'msbatchmodal.batchModalTip': '默认为成员添加项目成员用户组',
|
'msBatchModal.batchModalTip': '默认为成员添加项目成员用户组',
|
||||||
'msbatchmodal.batchOptional': '可选',
|
'msBatchModal.batchOptional': '可选',
|
||||||
'msbatchmodal.batchChosen': '已选',
|
'msBatchModal.batchChosen': '已选',
|
||||||
'msbatchmodal.batchModalCancel': '取消',
|
'msBatchModal.batchModalCancel': '取消',
|
||||||
'msbatchmodal.batchModalConfirm': '添加',
|
'msBatchModal.batchModalConfirm': '添加',
|
||||||
|
'msBatchModal.batchModalEmpty': '选择内容不能为空',
|
||||||
|
'msBatchModal.batchModalSuccess': '添加成功',
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, useAttrs, watch } from 'vue';
|
import { ref, useAttrs, watch, watchEffect } from 'vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -94,7 +94,11 @@
|
||||||
|
|
||||||
// 单独的开关
|
// 单独的开关
|
||||||
const switchEnable = ref<boolean>(false);
|
const switchEnable = ref<boolean>(false);
|
||||||
const dialogVisible = ref<boolean>(props.visible);
|
const dialogVisible = ref<boolean>(false);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
dialogVisible.value = props.visible;
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
|
@ -102,6 +106,12 @@
|
||||||
dialogVisible.value = val;
|
dialogVisible.value = val;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
watch(
|
||||||
|
() => dialogVisible.value,
|
||||||
|
(val) => {
|
||||||
|
emits('update:visible', val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.switchProps?.enable,
|
() => props.switchProps?.enable,
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<a-tooltip :content="(props.tagList||[]).map((e: any) => e.name).join(',')">
|
||||||
|
<div class="float-left flex min-h-[22px] max-w-[456px]">
|
||||||
|
<MsTag v-for="tag of props.tagList.slice(0, props.showNum)" :key="tag.id" v-bind="attrs">
|
||||||
|
<slot :tag="tag"> </slot>
|
||||||
|
</MsTag>
|
||||||
|
<MsTag v-if="props.tagList.length > props.showNum" v-bind="attrs"> +{{ props.showNum }}</MsTag>
|
||||||
|
</div>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useAttrs } from 'vue';
|
||||||
|
import MsTag from './ms-tag.vue';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
tagList: any;
|
||||||
|
showNum?: number;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
showNum: 2,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<template>
|
||||||
|
<a-tag
|
||||||
|
v-bind="attrs"
|
||||||
|
:type="props.type"
|
||||||
|
defer
|
||||||
|
:style="{ ...typeStyle, 'margin': tagMargin, 'max-width': '144px' }"
|
||||||
|
:size="props.size"
|
||||||
|
class="my-1"
|
||||||
|
>
|
||||||
|
<slot name="icon"></slot>
|
||||||
|
<span class="one-line-text"> <slot></slot></span>
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, useAttrs, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
export type TagType = 'default' | 'primary' | 'danger' | 'warning' | 'success';
|
||||||
|
export type Size = 'small' | 'medium' | 'large';
|
||||||
|
export type Theme = 'dark' | 'light' | 'outline' | 'lightOutLine';
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
type?: TagType; // tag类型
|
||||||
|
size?: Size; // tag尺寸
|
||||||
|
theme?: Theme; // tag主题
|
||||||
|
selfStyle?: any; // 自定义样式
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
type: 'default',
|
||||||
|
theme: 'dark',
|
||||||
|
size: 'medium',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 标签之间的间距
|
||||||
|
const tagMargin = computed(() => {
|
||||||
|
switch (props.size) {
|
||||||
|
case 'medium':
|
||||||
|
return '3px';
|
||||||
|
case 'large':
|
||||||
|
return '4px';
|
||||||
|
default:
|
||||||
|
return '2px';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算标签的颜色和背景颜色
|
||||||
|
const typeList: any = {
|
||||||
|
dark: {
|
||||||
|
'color': 'white',
|
||||||
|
'border-color': 'rgb(var(--#{}-5))',
|
||||||
|
'background': 'rgb(var(--#{}-5))',
|
||||||
|
},
|
||||||
|
light: {
|
||||||
|
color: 'rgb(var(--#{}-5))',
|
||||||
|
background: 'rgb(var(--#{}-1)',
|
||||||
|
},
|
||||||
|
outline: {
|
||||||
|
'border-color': 'rgb(var(--#{}-5))',
|
||||||
|
'color': 'rgb(var(--#{}-5))',
|
||||||
|
'background': 'transparent',
|
||||||
|
},
|
||||||
|
lightOutLine: {
|
||||||
|
'border-color': 'rgb(var(--#{}-5))',
|
||||||
|
'color': 'rgb(var(--#{}-5))',
|
||||||
|
'background': 'rgb(var(--#{}-1)',
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
'color': 'var(--color-text-1)',
|
||||||
|
'background': props.theme !== 'outline' ? 'var(--color-text-n8)' : 'white',
|
||||||
|
'border-color':
|
||||||
|
props.theme === 'lightOutLine' || props.theme === 'outline'
|
||||||
|
? 'var(--color-text-input-border)'
|
||||||
|
: 'var(--color-text-n8)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeConst = ref<string>('');
|
||||||
|
const typeStyle = ref<string[]>();
|
||||||
|
// 样式优先级: 自定义样式 > default 样式 > 主题和类型样式
|
||||||
|
const getTagType = (type: string, theme: string) => {
|
||||||
|
if (props.selfStyle && Object.keys(props.selfStyle).length > 0) {
|
||||||
|
typeStyle.value = props.selfStyle;
|
||||||
|
} else {
|
||||||
|
if (type === 'default') {
|
||||||
|
typeStyle.value = typeList.default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 主题色
|
||||||
|
if (type === 'primary') {
|
||||||
|
typeConst.value = 'primary';
|
||||||
|
// 非主题色
|
||||||
|
} else {
|
||||||
|
typeConst.value = type;
|
||||||
|
}
|
||||||
|
// 返回非主题色style
|
||||||
|
if (theme !== 'default' && type !== 'default') {
|
||||||
|
const themeStyle = typeList[theme];
|
||||||
|
Object.keys(themeStyle).forEach((item) => {
|
||||||
|
themeStyle[item] = themeStyle[item].replace('#{}', typeConst.value);
|
||||||
|
});
|
||||||
|
typeStyle.value = themeStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (props.type && props.theme) {
|
||||||
|
getTagType(props.type, props.theme);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
:deep(.arco-icon) {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-brand);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -159,6 +159,51 @@ export const pathMap = [
|
||||||
route: RouteEnum.PROJECT_MANAGEMENT,
|
route: RouteEnum.PROJECT_MANAGEMENT,
|
||||||
permission: [],
|
permission: [],
|
||||||
level: MENU_LEVEL[2],
|
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],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -3,3 +3,55 @@ export interface ProjectTreeData {
|
||||||
title: string;
|
title: string;
|
||||||
children?: ProjectTreeData[];
|
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: '';
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ export interface UserState {
|
||||||
certification?: number;
|
certification?: number;
|
||||||
role: RoleType;
|
role: RoleType;
|
||||||
lastOrganizationId?: string;
|
lastOrganizationId?: string;
|
||||||
|
lastProjectId?: string;
|
||||||
// 盐
|
// 盐
|
||||||
salt: string;
|
salt: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
</MsTableMoreAction>
|
</MsTableMoreAction>
|
||||||
</div>
|
</div>
|
||||||
<div class="project-info mb-6 h-[112px] bg-white p-1">
|
<div class="project-info mb-6 h-[112px] bg-white p-1">
|
||||||
<div class="inner-wrapper p-4">
|
<div class="inner-wrapper rounded-md p-4">
|
||||||
<div class="detail-info flex flex-col justify-between p-4">
|
<div class="detail-info flex flex-col justify-between rounded-md p-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="mr-1 font-medium text-[var(--color-text-000)]">具体的项目名称</span>
|
<span class="mr-1 font-medium text-[var(--color-text-000)]">具体的项目名称</span>
|
||||||
<span v-if="!isDelete" class="button enable-button mr-1">{{ t('project.basicInfo.enable') }}</span>
|
<span v-if="!isDelete" class="button enable-button mr-1">{{ t('project.basicInfo.enable') }}</span>
|
||||||
|
@ -55,6 +55,10 @@
|
||||||
label: 'project.basicInfo.edit',
|
label: 'project.basicInfo.edit',
|
||||||
eventTag: 'edit',
|
eventTag: 'edit',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'project.basicInfo.enable',
|
||||||
|
eventTag: 'enable',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'project.basicInfo.finish',
|
label: 'project.basicInfo.finish',
|
||||||
eventTag: 'finish',
|
eventTag: 'finish',
|
||||||
|
|
|
@ -3,30 +3,30 @@
|
||||||
v-model:visible="visible"
|
v-model:visible="visible"
|
||||||
dialog-size="medium"
|
dialog-size="medium"
|
||||||
title="project.member.addMember"
|
title="project.member.addMember"
|
||||||
:close="closeHandler"
|
|
||||||
:confirm="confirmFunHandler"
|
|
||||||
ok-text="project.member.add"
|
ok-text="project.member.add"
|
||||||
|
:confirm="confirmHandler"
|
||||||
|
:close="closeHandler"
|
||||||
>
|
>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<a-form ref="memberFormRef" :model="form" size="large" layout="vertical">
|
<a-form ref="memberFormRef" :model="form" size="large" layout="vertical">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="memberIds"
|
field="userIds"
|
||||||
:label="t('project.member.member')"
|
:label="t('project.member.member')"
|
||||||
asterisk-position="end"
|
asterisk-position="end"
|
||||||
:rules="[{ required: true, message: t('project.member.selectMemberEmptyTip') }]"
|
:rules="[{ required: true, message: t('project.member.selectMemberEmptyTip') }]"
|
||||||
>
|
>
|
||||||
<a-select v-model="form.memberIds" multiple :placeholder="t('project.member.selectMemberScope')" allow-clear>
|
<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-option v-for="item of memberList" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
field="userRoleIds"
|
field="roleIds"
|
||||||
:label="t('project.member.tableColumnUserGroup')"
|
:label="t('project.member.tableColumnUserGroup')"
|
||||||
asterisk-position="end"
|
asterisk-position="end"
|
||||||
:rules="[{ required: true, message: t('project.member.selectUserEmptyTip') }]"
|
:rules="[{ required: true, message: t('project.member.selectUserEmptyTip') }]"
|
||||||
>
|
>
|
||||||
<a-select v-model="form.userRoleIds" multiple allow-clear :placeholder="t('project.member.selectUserScope')">
|
<a-select v-model="form.roleIds" multiple allow-clear :placeholder="t('project.member.selectUserScope')">
|
||||||
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
<a-option v-for="item of props.userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
@ -35,49 +35,87 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import MsDialog from '@/components/pure/ms-dialog/index.vue';
|
import MsDialog from '@/components/pure/ms-dialog/index.vue';
|
||||||
|
import { getProjectMemberOptions, addOrUpdateProjectMember } from '@/api/modules/project-management/projectMember';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||||
|
import type { ProjectUserOption, ActionProjectMember } from '@/models/projectManagement/projectAndPermission';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const lastProjectId = userStore.$state?.lastProjectId;
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
userGroupOptions: ProjectUserOption[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
(e: 'success'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const initFormValue = {
|
|
||||||
userRoleIds: [],
|
|
||||||
memberIds: [],
|
|
||||||
};
|
|
||||||
const form = ref({ ...initFormValue });
|
|
||||||
|
|
||||||
const memberList = ref([
|
const initFormValue: ActionProjectMember = {
|
||||||
{
|
roleIds: ['project_member'],
|
||||||
id: '',
|
userIds: [],
|
||||||
name: '全部',
|
projectId: lastProjectId,
|
||||||
},
|
};
|
||||||
]);
|
|
||||||
const userGroupOptions = ref([
|
const form = ref<ActionProjectMember>({ ...initFormValue });
|
||||||
{
|
|
||||||
id: '',
|
|
||||||
name: '全部',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const memberFormRef = ref<FormInstance | null>(null);
|
const memberFormRef = ref<FormInstance | null>(null);
|
||||||
|
|
||||||
const confirmFunHandler = async () => {
|
const closeHandler = () => {
|
||||||
|
memberFormRef.value?.resetFields();
|
||||||
|
visible.value = false;
|
||||||
|
form.value = { ...initFormValue };
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加项目成员
|
||||||
|
const confirmHandler = async () => {
|
||||||
await memberFormRef.value?.validate().then(async (error) => {
|
await memberFormRef.value?.validate().then(async (error) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
console.log(error);
|
try {
|
||||||
|
await addOrUpdateProjectMember(form.value);
|
||||||
|
Message.success(t('project.member.batchModalSuccess'));
|
||||||
|
closeHandler();
|
||||||
|
emits('success');
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeHandler = () => {
|
const memberList = ref<ProjectUserOption[]>([]);
|
||||||
memberFormRef.value?.resetFields();
|
|
||||||
visible.value = false;
|
// 初始化项目成员
|
||||||
|
const initProjectMemberOptions = async () => {
|
||||||
|
try {
|
||||||
|
if (lastProjectId) {
|
||||||
|
const result = await getProjectMemberOptions(lastProjectId);
|
||||||
|
memberList.value = result;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(val) => {
|
||||||
|
emits('update:visible', val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
initProjectMemberOptions,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
><a-button class="mr-3" type="primary" @click="addMember">{{ t('project.member.addMember') }}</a-button></div
|
><a-button class="mr-3" type="primary" @click="addMember">{{ t('project.member.addMember') }}</a-button></div
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<a-select v-model="searchParams.userId">
|
<a-select v-model="roleIds" allow-search @change="changeSelect">
|
||||||
<a-option v-for="item of userGroupListOptions" :key="item.value" :value="item.value">{{
|
<a-option v-for="item of userGroupAll" :key="item.id" :value="item.id">{{ t(item.name) }}</a-option>
|
||||||
t(item.name)
|
|
||||||
}}</a-option>
|
|
||||||
<template #prefix
|
<template #prefix
|
||||||
><span>{{ t('project.member.tableColumnUserGroup') }}</span></template
|
><span>{{ t('project.member.tableColumnUserGroup') }}</span></template
|
||||||
>
|
>
|
||||||
|
@ -15,6 +13,7 @@
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
|
v-model="searchParams.keyword"
|
||||||
:max-length="250"
|
:max-length="250"
|
||||||
:placeholder="t('project.member.searchMember')"
|
:placeholder="t('project.member.searchMember')"
|
||||||
allow-clear
|
allow-clear
|
||||||
|
@ -31,25 +30,33 @@
|
||||||
@batch-action="handleTableBatch"
|
@batch-action="handleTableBatch"
|
||||||
>
|
>
|
||||||
<template #userRole="{ record }">
|
<template #userRole="{ record }">
|
||||||
<a-tooltip :content="(record.userRoleIdNameMap||[]).map((e: any) => e.name).join(',')">
|
<a-tooltip :content="(record.userRoles||[]).map((e: any) => e.name).join(',')">
|
||||||
<div v-if="!record.showUserSelect">
|
<div v-if="!record.showUserSelect">
|
||||||
<a-tag
|
<a-tag
|
||||||
v-for="org of (record.userRoleIdNameMap || []).slice(0, 3)"
|
v-for="org of (record.userRoles || []).slice(0, 3)"
|
||||||
:key="org"
|
:key="org"
|
||||||
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
||||||
bordered
|
bordered
|
||||||
|
@click="changeUser(record)"
|
||||||
>
|
>
|
||||||
{{ org.name }}
|
{{ org.name }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag
|
<a-tag
|
||||||
v-if="record.userRoleIdNameMap.length > 3"
|
v-if="(record.userRoles || []).length > 3"
|
||||||
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
||||||
bordered
|
bordered
|
||||||
|
@click="changeUser(record)"
|
||||||
>
|
>
|
||||||
+{{ record.userRoleIdNameMap.length - 3 }}
|
+{{ (record.userRoles || []).length - 3 }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</div>
|
</div>
|
||||||
<a-select v-else v-model="record.selectUserList" multiple :max-tag-count="2">
|
<a-select
|
||||||
|
v-else
|
||||||
|
v-model="record.selectUserList"
|
||||||
|
multiple
|
||||||
|
:max-tag-count="2"
|
||||||
|
@popup-visible-change="(value) => userGroupChange(value, record)"
|
||||||
|
>
|
||||||
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
@ -69,28 +76,40 @@
|
||||||
position="br"
|
position="br"
|
||||||
:title="t('project.member.deleteMemberTip', { name: characterLimit(record.name) })"
|
:title="t('project.member.deleteMemberTip', { name: characterLimit(record.name) })"
|
||||||
:sub-title-tip="t('project.member.subTitle')"
|
:sub-title-tip="t('project.member.subTitle')"
|
||||||
|
@ok="removeMember(record)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
<AddMemberModal v-model:visible="addMemberVisible" />
|
<AddMemberModal
|
||||||
|
ref="projectMemberRef"
|
||||||
|
v-model:visible="addMemberVisible"
|
||||||
|
:user-group-options="userGroupOptions"
|
||||||
|
@success="loadList()"
|
||||||
|
/>
|
||||||
<MSBatchModal
|
<MSBatchModal
|
||||||
ref="batchModalRef"
|
ref="batchModalRef"
|
||||||
v-model:visible="batchVisible"
|
v-model:visible="batchVisible"
|
||||||
:table-selected="tableSelected"
|
:table-selected="tableSelected"
|
||||||
:action="batchAction"
|
:action="batchAction"
|
||||||
:tree-data="treeData"
|
|
||||||
:select-data="selectData"
|
:select-data="selectData"
|
||||||
@add-user-group="addUserGroup"
|
@add-user-group="addUserGroup"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onBeforeMount } from 'vue';
|
import { ref, onBeforeMount, onMounted } from 'vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
||||||
import { getMemberList } from '@/api/modules/setting/member';
|
import {
|
||||||
|
getProjectMemberList,
|
||||||
|
getProjectUserGroup,
|
||||||
|
addOrUpdateProjectMember,
|
||||||
|
batchRemoveMember,
|
||||||
|
removeProjectMember,
|
||||||
|
addProjectUserGroup,
|
||||||
|
} from '@/api/modules/project-management/projectMember';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
import { useTableStore, useUserStore } from '@/store';
|
import { useTableStore, useUserStore } from '@/store';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
|
@ -98,27 +117,22 @@
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
import AddMemberModal from './components/addMemberModal.vue';
|
import AddMemberModal from './components/addMemberModal.vue';
|
||||||
import MSBatchModal from '@/components/business/ms-batch-modal/index.vue';
|
import MSBatchModal from '@/components/business/ms-batch-modal/index.vue';
|
||||||
import type { ProjectTreeData } from '@/models/projectManagement/projectAndPermission';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import type {
|
||||||
|
ProjectTreeData,
|
||||||
|
ProjectUserOption,
|
||||||
|
ActionProjectMember,
|
||||||
|
ProjectMemberItem,
|
||||||
|
SearchParams,
|
||||||
|
} from '@/models/projectManagement/projectAndPermission';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
|
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const lastOrganizationId = userStore?.$state.lastOrganizationId;
|
const lastProjectId = userStore?.$state?.lastProjectId;
|
||||||
|
|
||||||
const userGroupListOptions = ref([
|
|
||||||
{
|
|
||||||
id: '',
|
|
||||||
name: '全部',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '1001',
|
|
||||||
name: '用户组1',
|
|
||||||
value: '1001',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: 'project.member.tableColumnEmail',
|
title: 'project.member.tableColumnEmail',
|
||||||
|
@ -180,7 +194,7 @@
|
||||||
tableSelected.value = selectArr;
|
tableSelected.value = selectArr;
|
||||||
};
|
};
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getMemberList, {
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getProjectMemberList, {
|
||||||
tableKey: TableKeyEnum.PROJECT_MEMBER,
|
tableKey: TableKeyEnum.PROJECT_MEMBER,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
showSetting: true,
|
showSetting: true,
|
||||||
|
@ -189,19 +203,31 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const searchParams = ref<SearchParams>({
|
||||||
|
filter: {
|
||||||
|
roleIds: [],
|
||||||
|
},
|
||||||
|
projectId: lastProjectId as string,
|
||||||
|
keyword: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const roleIds = ref<string>('');
|
||||||
const initData = async () => {
|
const initData = async () => {
|
||||||
setLoadListParams({ organizationId: lastOrganizationId });
|
setLoadListParams({ ...searchParams.value });
|
||||||
await loadList();
|
await loadList();
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchParams = ref({
|
const searchHandler = () => {
|
||||||
userId: '',
|
initData();
|
||||||
});
|
};
|
||||||
|
|
||||||
const searchHandler = () => {};
|
const changeSelect = () => {
|
||||||
|
searchParams.value.filter.roleIds = roleIds.value ? [roleIds.value] : [];
|
||||||
|
initData();
|
||||||
|
};
|
||||||
|
|
||||||
// 批量移除成员
|
// 批量移除项目成员
|
||||||
const batchRemoveMember = () => {
|
const batchRemoveHandler = () => {
|
||||||
openModal({
|
openModal({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: t('project.member.batchRemoveTip', { number: tableSelected.value.length }),
|
title: t('project.member.batchRemoveTip', { number: tableSelected.value.length }),
|
||||||
|
@ -211,44 +237,128 @@
|
||||||
okButtonProps: {
|
okButtonProps: {
|
||||||
status: 'danger',
|
status: 'danger',
|
||||||
},
|
},
|
||||||
onBeforeOk: async () => {},
|
onBeforeOk: async () => {
|
||||||
|
try {
|
||||||
|
const params: ActionProjectMember = {
|
||||||
|
projectId: lastProjectId,
|
||||||
|
userIds: tableSelected.value,
|
||||||
|
};
|
||||||
|
await batchRemoveMember(params);
|
||||||
|
Message.success(t('project.member.deleteMemberSuccess'));
|
||||||
|
loadList();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
hideCancel: false,
|
hideCancel: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 移除项目成员
|
||||||
|
const removeMember = async (record: ProjectMemberItem) => {
|
||||||
|
try {
|
||||||
|
if (lastProjectId && record.id) {
|
||||||
|
await removeProjectMember(lastProjectId, record.id);
|
||||||
|
Message.success(t('project.member.deleteMemberSuccess'));
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const batchVisible = ref<boolean>(false);
|
const batchVisible = ref<boolean>(false);
|
||||||
const selectData = ref<string[]>([]);
|
const selectData = ref<string[]>([]);
|
||||||
const batchAction = ref('');
|
const batchAction = ref('');
|
||||||
const treeData = ref<ProjectTreeData[]>([]);
|
const treeData = ref<ProjectTreeData[]>([]);
|
||||||
|
const userGroupOptions = ref<ProjectUserOption[]>([]);
|
||||||
|
const batchModalRef = ref();
|
||||||
|
|
||||||
// 添加到用户组
|
// 添加到用户组
|
||||||
const addUserGroup = () => {};
|
const addUserGroup = async (target: string[]) => {
|
||||||
|
const params = {
|
||||||
|
projectId: lastProjectId,
|
||||||
|
userIds: tableSelected.value,
|
||||||
|
roleIds: target,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
await batchModalRef.value.batchRequestFun(addProjectUserGroup, params);
|
||||||
|
loadList();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格批量处理
|
||||||
const handleTableBatch = (actionItem: any) => {
|
const handleTableBatch = (actionItem: any) => {
|
||||||
if (actionItem.eventTag === 'batchActionRemove') {
|
if (actionItem.eventTag === 'batchActionRemove') {
|
||||||
batchRemoveMember();
|
batchRemoveHandler();
|
||||||
}
|
}
|
||||||
if (actionItem.eventTag === 'batchAddUserGroup') {
|
if (actionItem.eventTag === 'batchAddUserGroup') {
|
||||||
batchVisible.value = true;
|
batchVisible.value = true;
|
||||||
addUserGroup();
|
batchAction.value = actionItem.eventTag;
|
||||||
|
batchModalRef.value.getTreeList(getProjectUserGroup, lastProjectId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const userGroupOptions = ref([
|
// 添加项目成员
|
||||||
{
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const addMemberVisible = ref<boolean>(false);
|
const addMemberVisible = ref<boolean>(false);
|
||||||
|
const projectMemberRef = ref();
|
||||||
|
|
||||||
const addMember = () => {
|
const addMember = () => {
|
||||||
addMemberVisible.value = true;
|
addMemberVisible.value = true;
|
||||||
|
projectMemberRef.value.initProjectMemberOptions();
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
// 编辑项目成员
|
||||||
|
const editProjectMember = async (record: ProjectMemberItem) => {
|
||||||
|
const params: ActionProjectMember = {
|
||||||
|
projectId: lastProjectId,
|
||||||
|
userId: record.id,
|
||||||
|
roleIds: record.selectUserList,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
await addOrUpdateProjectMember(params);
|
||||||
|
Message.success(t('project.member.batchUpdateSuccess'));
|
||||||
|
record.showUserSelect = false;
|
||||||
|
loadList();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 项目用户组改变回调
|
||||||
|
const changeUser = (record: ProjectMemberItem) => {
|
||||||
|
if (record.enable) {
|
||||||
|
record.showUserSelect = true;
|
||||||
|
record.selectUserList = (record.userRoles || []).map((item) => item.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 面板改变的回调
|
||||||
|
const userGroupChange = (visible: boolean, record: ProjectMemberItem) => {
|
||||||
|
if (visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((record.selectUserList || []).length < 1) {
|
||||||
|
Message.warning(t('project.member.selectUserEmptyTip'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editProjectMember(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const userGroupAll = ref<ProjectUserOption[]>([]);
|
||||||
|
|
||||||
|
onBeforeMount(async () => {
|
||||||
initData();
|
initData();
|
||||||
|
userGroupOptions.value = await getProjectUserGroup(lastProjectId as string);
|
||||||
|
userGroupAll.value = [
|
||||||
|
{
|
||||||
|
id: '',
|
||||||
|
name: '全部',
|
||||||
|
},
|
||||||
|
...userGroupOptions.value,
|
||||||
|
];
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ export default {
|
||||||
'project.member.remove': 'Remove',
|
'project.member.remove': 'Remove',
|
||||||
'project.member.edit': 'Edit',
|
'project.member.edit': 'Edit',
|
||||||
'project.member.add': 'Add',
|
'project.member.add': 'Add',
|
||||||
'project.member.batchActionAddProject': 'Add to project',
|
|
||||||
'project.member.batchActionAddUserGroup': 'Add to usergroup',
|
'project.member.batchActionAddUserGroup': 'Add to usergroup',
|
||||||
'project.member.tableEnable': 'Enabled',
|
'project.member.tableEnable': 'Enabled',
|
||||||
'project.member.tableDisable': 'Disabled',
|
'project.member.tableDisable': 'Disabled',
|
||||||
|
@ -28,7 +27,7 @@ export default {
|
||||||
'system.user.deleteUserTip': 'Are you sure to delete the user `{name}` ?',
|
'system.user.deleteUserTip': 'Are you sure to delete the user `{name}` ?',
|
||||||
'project.member.deleteMemberConfirm': 'Delete',
|
'project.member.deleteMemberConfirm': 'Delete',
|
||||||
'project.member.deleteMemberCancel': 'Cancel',
|
'project.member.deleteMemberCancel': 'Cancel',
|
||||||
'project.member.deleteMemberSuccess': 'Delete successful',
|
'project.member.deleteMemberSuccess': 'Remove successful',
|
||||||
'project.member.batchModalSuccess': 'Successfully added',
|
'project.member.batchModalSuccess': 'Successfully added',
|
||||||
'project.member.batchUpdateSuccess': 'Successfully updated',
|
'project.member.batchUpdateSuccess': 'Successfully updated',
|
||||||
'project.member.project': 'Project',
|
'project.member.project': 'Project',
|
||||||
|
|
|
@ -5,7 +5,6 @@ export default {
|
||||||
'project.member.remove': '移除',
|
'project.member.remove': '移除',
|
||||||
'project.member.edit': '编辑',
|
'project.member.edit': '编辑',
|
||||||
'project.member.add': '添加',
|
'project.member.add': '添加',
|
||||||
'project.member.batchActionAddProject': '添加至项目',
|
|
||||||
'project.member.batchActionAddUserGroup': '添加至用户组',
|
'project.member.batchActionAddUserGroup': '添加至用户组',
|
||||||
'project.member.tableEnable': '正常',
|
'project.member.tableEnable': '正常',
|
||||||
'project.member.tableDisable': '禁用',
|
'project.member.tableDisable': '禁用',
|
||||||
|
@ -27,7 +26,7 @@ export default {
|
||||||
'project.member.deleteMemberTip': '确认移除 {name} 这个成员吗?',
|
'project.member.deleteMemberTip': '确认移除 {name} 这个成员吗?',
|
||||||
'project.member.deleteMemberConfirm': '确认删除',
|
'project.member.deleteMemberConfirm': '确认删除',
|
||||||
'project.member.deleteMemberCancel': '取消',
|
'project.member.deleteMemberCancel': '取消',
|
||||||
'project.member.deleteMemberSuccess': '删除成功',
|
'project.member.deleteMemberSuccess': '移除成功',
|
||||||
'project.member.batchModalSuccess': '添加成功',
|
'project.member.batchModalSuccess': '添加成功',
|
||||||
'project.member.batchUpdateSuccess': '更新成功',
|
'project.member.batchUpdateSuccess': '更新成功',
|
||||||
'project.member.project': '项目',
|
'project.member.project': '项目',
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
class="ms-modal-form ms-modal-medium"
|
class="ms-modal-form ms-modal-medium"
|
||||||
:ok-text="t('organization.member.Confirm')"
|
:ok-text="t('organization.member.Confirm')"
|
||||||
:cancel-text="t('organization.member.Cancel')"
|
:cancel-text="t('organization.member.Cancel')"
|
||||||
|
@close="handleCancel"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
{{
|
{{
|
||||||
|
|
|
@ -24,71 +24,52 @@
|
||||||
@batch-action="handleTableBatch"
|
@batch-action="handleTableBatch"
|
||||||
>
|
>
|
||||||
<template #project="{ record }">
|
<template #project="{ record }">
|
||||||
<a-tooltip :content="(record.projectIdNameMap||[]).map((e: any) => e.name).join(',')">
|
<MsTagGroup
|
||||||
<div v-if="!record.showProjectSelect">
|
v-if="!record.showProjectSelect"
|
||||||
<a-tag
|
:tag-list="record.projectIdNameMap || []"
|
||||||
v-for="pro of (record.projectIdNameMap || []).slice(0, 3)"
|
:show-num="2"
|
||||||
:key="pro.id"
|
theme="outline"
|
||||||
class="mr-[4px] bg-transparent"
|
@click="changeUserOrProject(record, 'project')"
|
||||||
bordered
|
>
|
||||||
@click="changeUserOrProject(record, 'project')"
|
<template #default="{ tag }">
|
||||||
>
|
{{ tag.name }}
|
||||||
{{ pro.name }}
|
</template>
|
||||||
</a-tag>
|
</MsTagGroup>
|
||||||
<a-tag
|
<a-select
|
||||||
v-if="(record.projectIdNameMap || []).length > 3"
|
v-else
|
||||||
class="mr-[4px] bg-transparent"
|
v-model="record.selectProjectList"
|
||||||
bordered
|
multiple
|
||||||
@click="changeUserOrProject(record, 'project')"
|
:max-tag-count="2"
|
||||||
>
|
size="small"
|
||||||
+{{ (record.projectIdNameMap || []).length - 3 }}
|
@change="(value) => selectUserOrProject(value, record, 'project')"
|
||||||
</a-tag>
|
@popup-visible-change="visibleChange($event, record, 'project')"
|
||||||
</div>
|
>
|
||||||
<a-select
|
<a-option v-for="item of projectOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
v-else
|
</a-select>
|
||||||
v-model="record.selectProjectList"
|
|
||||||
multiple
|
|
||||||
:max-tag-count="2"
|
|
||||||
size="small"
|
|
||||||
@change="(value) => selectUserOrProject(value, record, 'project')"
|
|
||||||
@popup-visible-change="visibleChange($event, record, 'project')"
|
|
||||||
>
|
|
||||||
<a-option v-for="item of projectOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
</template>
|
||||||
<template #userRole="{ record }">
|
<template #userRole="{ record }">
|
||||||
<a-tooltip :content="(record.userRoleIdNameMap||[]).map((e: any) => e.name).join(',')">
|
<MsTagGroup
|
||||||
<div v-if="!record.showUserSelect">
|
v-if="!record.showUserSelect"
|
||||||
<a-tag
|
:tag-list="record.userRoleIdNameMap || []"
|
||||||
v-for="org of (record.userRoleIdNameMap || []).slice(0, 3)"
|
:show-num="2"
|
||||||
:key="org"
|
type="primary"
|
||||||
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
theme="outline"
|
||||||
bordered
|
@click="changeUserOrProject(record, 'user')"
|
||||||
@click="changeUserOrProject(record, 'user')"
|
>
|
||||||
>
|
<template #default="{ tag }">
|
||||||
{{ org.name }}
|
{{ tag.name }}
|
||||||
</a-tag>
|
</template>
|
||||||
<a-tag
|
</MsTagGroup>
|
||||||
v-if="record.userRoleIdNameMap.length > 3"
|
<a-select
|
||||||
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
|
v-else
|
||||||
bordered
|
v-model="record.selectUserList"
|
||||||
@click="changeUserOrProject(record, 'user')"
|
multiple
|
||||||
>
|
:max-tag-count="2"
|
||||||
+{{ record.userRoleIdNameMap.length - 3 }}
|
@change="(value) => selectUserOrProject(value, record, 'user')"
|
||||||
</a-tag>
|
@popup-visible-change="(value) => visibleChange(value, record, 'user')"
|
||||||
</div>
|
>
|
||||||
<a-select
|
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||||
v-else
|
</a-select>
|
||||||
v-model="record.selectUserList"
|
|
||||||
multiple
|
|
||||||
:max-tag-count="2"
|
|
||||||
@change="(value) => selectUserOrProject(value, record, 'user')"
|
|
||||||
@popup-visible-change="(value) => visibleChange(value, record, 'user')"
|
|
||||||
>
|
|
||||||
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
</template>
|
||||||
<template #enable="{ record }">
|
<template #enable="{ record }">
|
||||||
<div v-if="record.enable" class="flex items-center">
|
<div v-if="record.enable" class="flex items-center">
|
||||||
|
@ -119,12 +100,10 @@
|
||||||
@success="initData()"
|
@success="initData()"
|
||||||
/>
|
/>
|
||||||
<MSBatchModal
|
<MSBatchModal
|
||||||
v-if="treeData.length > 0"
|
|
||||||
ref="batchModalRef"
|
ref="batchModalRef"
|
||||||
v-model:visible="showBatchModal"
|
v-model:visible="showBatchModal"
|
||||||
:table-selected="tableSelected"
|
:table-selected="tableSelected"
|
||||||
:action="batchAction"
|
:action="batchAction"
|
||||||
:tree-data="treeData"
|
|
||||||
:select-data="selectData"
|
:select-data="selectData"
|
||||||
@add-project="addProjectOrAddUserGroup"
|
@add-project="addProjectOrAddUserGroup"
|
||||||
@add-user-group="addProjectOrAddUserGroup"
|
@add-user-group="addProjectOrAddUserGroup"
|
||||||
|
@ -154,19 +133,14 @@
|
||||||
import MSBatchModal from '@/components/business/ms-batch-modal/index.vue';
|
import MSBatchModal from '@/components/business/ms-batch-modal/index.vue';
|
||||||
import { useTableStore, useUserStore } from '@/store';
|
import { useTableStore, useUserStore } from '@/store';
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import type {
|
import type { MemberItem, AddorUpdateMemberModel, LinkList, BatchAddProjectModel } from '@/models/setting/member';
|
||||||
MemberItem,
|
|
||||||
AddorUpdateMemberModel,
|
|
||||||
LinkList,
|
|
||||||
LinkItem,
|
|
||||||
BatchAddProjectModel,
|
|
||||||
} from '@/models/setting/member';
|
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
import MsTagGroup from '@/components/pure/ms-tag/ms-tag-group.vue';
|
||||||
|
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const lastOrganizationId = userStore.$state?.lastOrganizationId as string;
|
const lastOrganizationId = userStore.$state?.lastOrganizationId;
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
|
@ -237,13 +211,6 @@
|
||||||
const tableSelected = ref<(string | number)[]>([]);
|
const tableSelected = ref<(string | number)[]>([]);
|
||||||
const selectData = ref<string[]>([]);
|
const selectData = ref<string[]>([]);
|
||||||
|
|
||||||
interface TreeDataItem {
|
|
||||||
key: string;
|
|
||||||
title: string;
|
|
||||||
children?: TreeDataItem[];
|
|
||||||
}
|
|
||||||
const batchAction = ref('');
|
|
||||||
|
|
||||||
const initData = async () => {
|
const initData = async () => {
|
||||||
setLoadListParams({ keyword: keyword.value, organizationId: lastOrganizationId });
|
setLoadListParams({ keyword: keyword.value, organizationId: lastOrganizationId });
|
||||||
await loadList();
|
await loadList();
|
||||||
|
@ -264,7 +231,7 @@
|
||||||
};
|
};
|
||||||
const deleteMember = async (record: MemberItem) => {
|
const deleteMember = async (record: MemberItem) => {
|
||||||
try {
|
try {
|
||||||
await deleteMemberReq(lastOrganizationId, record.id);
|
if (lastOrganizationId) await deleteMemberReq(lastOrganizationId, record.id);
|
||||||
Message.success(t('organization.member.deleteMemberSuccess'));
|
Message.success(t('organization.member.deleteMemberSuccess'));
|
||||||
initData();
|
initData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -275,23 +242,12 @@
|
||||||
tableSelected.value = selectArr;
|
tableSelected.value = selectArr;
|
||||||
};
|
};
|
||||||
|
|
||||||
const treeData = ref<TreeDataItem[]>([]);
|
const batchModalRef = ref();
|
||||||
const getData = async (callBack: any) => {
|
|
||||||
try {
|
const getData = (callBack: any) => {
|
||||||
const links = await callBack(lastOrganizationId);
|
batchModalRef.value.getTreeList(callBack, lastOrganizationId);
|
||||||
treeData.value = links.map((item: LinkItem) => {
|
|
||||||
return {
|
|
||||||
title: item.name,
|
|
||||||
key: item.id,
|
|
||||||
id: item.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const batchModalRef = ref();
|
|
||||||
const showBatchModal = ref(false);
|
const showBatchModal = ref(false);
|
||||||
|
|
||||||
const batchList = [
|
const batchList = [
|
||||||
|
@ -300,10 +256,13 @@
|
||||||
request: batchAddProject,
|
request: batchAddProject,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'usergroup',
|
type: 'userGroup',
|
||||||
request: batchAddUserGroup,
|
request: batchAddUserGroup,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const batchAction = ref('');
|
||||||
|
|
||||||
// 添加到项目和用户组
|
// 添加到项目和用户组
|
||||||
const addProjectOrAddUserGroup = async (target: string[], type: string) => {
|
const addProjectOrAddUserGroup = async (target: string[], type: string) => {
|
||||||
const currentType = batchList.find((item) => item.type === type);
|
const currentType = batchList.find((item) => item.type === type);
|
||||||
|
@ -322,7 +281,6 @@
|
||||||
// 批量操作
|
// 批量操作
|
||||||
const handleTableBatch = (actionItem: any) => {
|
const handleTableBatch = (actionItem: any) => {
|
||||||
showBatchModal.value = true;
|
showBatchModal.value = true;
|
||||||
treeData.value = [];
|
|
||||||
batchAction.value = actionItem.eventTag;
|
batchAction.value = actionItem.eventTag;
|
||||||
if (actionItem.eventTag === 'batchAddProject') getData(getProjectList);
|
if (actionItem.eventTag === 'batchAddProject') getData(getProjectList);
|
||||||
if (actionItem.eventTag === 'batchAddUserGroup') getData(getGlobalUserGroup);
|
if (actionItem.eventTag === 'batchAddUserGroup') getData(getGlobalUserGroup);
|
||||||
|
@ -383,8 +341,10 @@
|
||||||
const userGroupOptions = ref<LinkList>([]);
|
const userGroupOptions = ref<LinkList>([]);
|
||||||
const projectOptions = ref<LinkList>([]);
|
const projectOptions = ref<LinkList>([]);
|
||||||
const getLinkList = async () => {
|
const getLinkList = async () => {
|
||||||
userGroupOptions.value = await getGlobalUserGroup(lastOrganizationId);
|
if (lastOrganizationId) {
|
||||||
projectOptions.value = await getProjectList(lastOrganizationId);
|
userGroupOptions.value = await getGlobalUserGroup(lastOrganizationId);
|
||||||
|
projectOptions.value = await getProjectList(lastOrganizationId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
initData();
|
initData();
|
||||||
|
|
Loading…
Reference in New Issue