Files
yudao-ui-admin-vben/apps/web-ele/src/views/system/dept/components/select-modal.vue
YunaiV 4affc95db4 fix(vben): 修复多端迁移差异与组件适配问题
- 同步 IoT 物模型 Event dataType 类型,并修复 antdv-next 模拟器事件类型展示
- 修复 antdv-next 物模型选项模板字符串和校验规则写法
- 补齐 antdv-next BPM 审批附件上传限制与流程打印业务表单渲染
- 修复 antdv-next 缺失的组件导入、垂直按钮组导出,并删除未引用的部门树遗留文件
- 对齐 BPM 流程配置中 antd/antdv-next 的组件属性写法
- 修复 ele 流程创建跳转、好友拒绝文本框、客服回车发送、公告栏颜色表单项和部门选择弹窗选中状态
- 调整 BPM 流程实例 API 字段顺序,减少三端无意义差异
2026-06-25 22:35:58 -07:00

133 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts" setup>
import type { SystemDeptApi } from '#/api/system/dept';
import { nextTick, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { handleTree } from '@vben/utils';
import { ElCard, ElCol, ElRow, ElTree } from 'element-plus';
import { getSimpleDeptList } from '#/api/system/dept';
defineOptions({ name: 'DeptSelectModal' });
const props = withDefaults(
defineProps<{
cancelText?: string; // 取消按钮文本
checkStrictly?: boolean; // checkable 状态下节点选择完全受控
confirmText?: string; // 确认按钮文本
multiple?: boolean; // 是否支持多选
title?: string; // 标题
}>(),
{
cancelText: '取消',
checkStrictly: false,
confirmText: '确认',
multiple: true,
title: '部门选择',
},
);
const emit = defineEmits<{
confirm: [deptList: SystemDeptApi.Dept[]];
}>();
const deptTree = ref<any[]>([]); // 部门树形结构
const selectedDeptIds = ref<number[]>([]); // 选中的部门 ID 列表
const deptData = ref<SystemDeptApi.Dept[]>([]); // 部门数据
const treeRef = ref(); // Tree 组件引用
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
// 获取选中的部门IDselectedDeptIds 由 handleCheck 实时维护,
// 严格/非严格模式下均与树勾选状态一致,无需依赖 treeRef 是否已挂载)
const selectedIds: number[] = selectedDeptIds.value;
const deptArray = deptData.value.filter((dept) =>
selectedIds.includes(dept.id!),
);
emit('confirm', deptArray);
// 关闭并提示
await modalApi.close();
},
async onOpenChange(isOpen: boolean) {
if (!isOpen) {
deptTree.value = [];
selectedDeptIds.value = [];
return;
}
// 加载数据
const data = modalApi.getData();
if (!data) {
return;
}
modalApi.lock();
try {
deptData.value = await getSimpleDeptList();
deptTree.value = handleTree(deptData.value);
// 等待 DOM 更新后再设置选中的节点
await nextTick();
// 设置已选择的部门
if (data.selectedList?.length) {
const selectedIds = data.selectedList
.map((dept: SystemDeptApi.Dept) => dept.id)
.filter((id: number) => id !== undefined);
selectedDeptIds.value = selectedIds;
treeRef.value.setCheckedKeys(selectedIds);
}
} finally {
modalApi.unlock();
}
},
destroyOnClose: true,
});
/** 处理选中状态变化 */
function handleCheck(
_data: any,
{ checkedKeys }: { checkedKeys: (number | string)[] },
) {
// 确保 checkedKeys 都是 number 类型
const keys = checkedKeys.map((key) =>
typeof key === 'string' ? Number(key) : key,
);
if (props.multiple) {
selectedDeptIds.value = keys;
} else {
// 单选模式下,只保留最后选择的节点
const lastSelectedId = keys[keys.length - 1];
if (lastSelectedId) {
selectedDeptIds.value = [lastSelectedId];
treeRef.value?.setCheckedKeys([lastSelectedId]);
} else {
selectedDeptIds.value = [];
treeRef.value?.setCheckedKeys([]);
}
}
}
</script>
<template>
<Modal :title="title" key="dept-select-modal" class="w-3/5">
<ElRow class="h-full">
<ElCol :span="24">
<ElCard class="h-full">
<ElTree
v-if="deptTree.length > 0"
ref="treeRef"
:data="deptTree"
:props="{ label: 'name', children: 'children' }"
:check-strictly="checkStrictly"
:default-expand-all="true"
show-checkbox
check-on-click-node
node-key="id"
@check="handleCheck"
/>
</ElCard>
</ElCol>
</ElRow>
</Modal>
</template>