Files
aiot-uniapp/src/pages-system/user/form/components/dept-picker.vue

130 lines
3.3 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.

<!-- TODO @芋艿优化看看后续要不要抽成组件 -->
<template>
<wd-col-picker
v-model="selectedValue"
label="归属部门"
label-width="180rpx"
:columns="deptColumns"
:column-change="handleColumnChange"
:display-format="displayFormat"
@confirm="handleConfirm"
/>
</template>
<script lang="ts" setup>
import type { Dept } from '@/api/system/dept'
import { onMounted, ref, watch } from 'vue'
import { getSimpleDeptList } from '@/api/system/dept'
const props = defineProps<{
modelValue?: number
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: number | undefined): void
}>()
const deptList = ref<Dept[]>([])
const deptColumns = ref<any[]>([])
const selectedValue = ref<number[]>([])
/** 监听外部值变化,回显选中值 */
watch(
() => props.modelValue,
(val) => {
if (val && deptList.value.length > 0) {
const path = findDeptPath(val)
selectedValue.value = path
// 构建列数据以支持回显
buildColumnsForPath(path)
}
else {
selectedValue.value = []
}
},
)
/** 加载部门列表 */
async function loadDeptList() {
deptList.value = await getSimpleDeptList()
// 构建第一列数据(顶级部门)
const topDepts = deptList.value.filter(item => item.parentId === 0)
deptColumns.value = [topDepts.map(item => ({ value: item.id, label: item.name }))]
// 如果有初始值,回显
if (props.modelValue) {
const path = findDeptPath(props.modelValue)
selectedValue.value = path
buildColumnsForPath(path)
}
}
/** 查找部门路径 */
function findDeptPath(targetId: number): number[] {
const path: number[] = []
const findPath = (parentId: number, id: number): boolean => {
const items = deptList.value.filter(d => d.parentId === parentId)
for (const item of items) {
if (item.id === id) {
path.push(item.id)
return true
}
if (findPath(item.id, id)) {
path.unshift(item.id)
return true
}
}
return false
}
findPath(0, targetId)
return path
}
/** 根据路径构建列数据 */
function buildColumnsForPath(path: number[]) {
if (path.length === 0) {
return
}
// 第一列已经有了,从第二列开始构建
const columns = [deptColumns.value[0]]
for (let i = 0; i < path.length - 1; i++) {
const parentId = path[i]
const children = deptList.value.filter(item => item.parentId === parentId)
if (children.length > 0) {
columns.push(children.map(item => ({ value: item.id, label: item.name })))
}
}
deptColumns.value = columns
}
/** 列变化 */
function handleColumnChange({ selectedItem, resolve, finish }: any) {
const children = deptList.value.filter(item => item.parentId === selectedItem.value)
if (children.length > 0) {
resolve(children.map(item => ({ value: item.id, label: item.name })))
}
else {
finish()
}
}
/** 格式化显示 */
function displayFormat(selectedItems: any[]) {
return selectedItems.map(item => item.label).join('/')
}
/** 确认选择 */
function handleConfirm({ value }: { value: number[] }) {
if (value && value.length > 0) {
emit('update:modelValue', value[value.length - 1])
}
else {
emit('update:modelValue', undefined)
}
}
/** 初始化 */
onMounted(() => {
loadDeptList()
})
</script>