lint 自动格式化:长签名/标题换行、import 顺序、空元素展开; 顺手移除 new Set(undefined) 无意义的 `?? []` 兜底。无行为变更。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
109 lines
2.8 KiB
Vue
109 lines
2.8 KiB
Vue
<script lang="ts" setup>
|
||
import type { SystemUserApi } from '#/api/system/user';
|
||
|
||
import { computed, ref } from 'vue';
|
||
|
||
import { useVbenModal } from '@vben/common-ui';
|
||
|
||
import { message, Select, Spin } from 'ant-design-vue';
|
||
|
||
import { getSimpleUserList } from '#/api/system/user';
|
||
import { addProjectUsers } from '#/api/system/user-project';
|
||
import { $t } from '#/locales';
|
||
|
||
interface AddUserModalData {
|
||
projectId: number;
|
||
projectName?: string;
|
||
excludedUserIds: number[];
|
||
}
|
||
|
||
const emit = defineEmits(['success']);
|
||
|
||
const allUsers = ref<SystemUserApi.User[]>([]);
|
||
const selectedUserIds = ref<number[]>([]);
|
||
const loading = ref(false);
|
||
const currentData = ref<AddUserModalData | null>(null);
|
||
|
||
/** 可选项:全量用户 - 已是成员的用户 */
|
||
const selectOptions = computed(() => {
|
||
const excluded = new Set(currentData.value?.excludedUserIds);
|
||
return allUsers.value
|
||
.filter((u) => u.id && !excluded.has(u.id))
|
||
.map((u) => ({
|
||
value: u.id,
|
||
label: `${u.nickname || u.username}(${u.username})`,
|
||
}));
|
||
});
|
||
|
||
const [Modal, modalApi] = useVbenModal({
|
||
async onConfirm() {
|
||
if (!currentData.value?.projectId) return;
|
||
if (selectedUserIds.value.length === 0) {
|
||
message.warning('请至少选择一个用户');
|
||
return;
|
||
}
|
||
modalApi.lock();
|
||
try {
|
||
await addProjectUsers({
|
||
projectId: currentData.value.projectId,
|
||
userIds: selectedUserIds.value,
|
||
});
|
||
message.success($t('ui.actionMessage.operationSuccess'));
|
||
await modalApi.close();
|
||
emit('success');
|
||
} finally {
|
||
modalApi.unlock();
|
||
}
|
||
},
|
||
async onOpenChange(isOpen: boolean) {
|
||
if (!isOpen) {
|
||
allUsers.value = [];
|
||
selectedUserIds.value = [];
|
||
currentData.value = null;
|
||
return;
|
||
}
|
||
const data = modalApi.getData<AddUserModalData>();
|
||
if (!data) return;
|
||
currentData.value = data;
|
||
loading.value = true;
|
||
try {
|
||
allUsers.value = await getSimpleUserList();
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
},
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<Modal
|
||
:title="
|
||
currentData?.projectName
|
||
? `添加用户到项目 - ${currentData.projectName}`
|
||
: '添加用户'
|
||
"
|
||
class="w-[560px]"
|
||
>
|
||
<Spin :spinning="loading">
|
||
<div class="px-4 py-2">
|
||
<div class="mb-2 text-sm">
|
||
选择要加入项目的用户(已在项目中的用户会自动过滤)
|
||
</div>
|
||
<Select
|
||
v-model:value="selectedUserIds"
|
||
mode="multiple"
|
||
placeholder="请选择用户"
|
||
:options="selectOptions"
|
||
:filter-option="
|
||
(input: string, option: any) =>
|
||
option.label.toLowerCase().includes(input.toLowerCase())
|
||
"
|
||
show-search
|
||
allow-clear
|
||
class="w-full"
|
||
/>
|
||
</div>
|
||
</Spin>
|
||
</Modal>
|
||
</template>
|