feat:优化 dept、menu 支持选择“当前层级”

This commit is contained in:
YunaiV
2025-12-23 21:22:40 +08:00
parent e2689661c9
commit f82b1aa47c
3 changed files with 67 additions and 30 deletions

View File

@@ -4,6 +4,8 @@
:label="label"
label-width="180rpx"
:columns="deptColumns"
value-key="id"
label-key="name"
:column-change="handleColumnChange"
:display-format="displayFormat"
@confirm="handleConfirm"
@@ -64,17 +66,25 @@ function initFirstColumn() {
if (props.showRoot) {
deptColumns.value = [
[
{ label: '顶级部门', value: 0 },
...topDepts.map(item => ({ value: item.id, label: item.name })),
{ id: 0, name: '顶级部门' },
...topDepts,
],
]
} else {
deptColumns.value = [
topDepts.map(item => ({ value: item.id, label: item.name })),
]
deptColumns.value = [topDepts]
}
}
/** 构建带"选择当前"选项的子列表 */
function buildChildrenWithCurrent(parentId: number) {
const children = deptList.value.filter(item => item.parentId === parentId)
// 添加"选择当前"选项,使用父节点 ID 的负数作为标识
return [
{ id: -parentId, name: '✓ 选择当前' },
...children,
]
}
/** 加载部门列表 */
async function loadDeptList() {
deptList.value = await getSimpleDeptList()
@@ -122,7 +132,7 @@ function buildColumnsForPath(path: number[]) {
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 })))
columns.push(children)
}
}
deptColumns.value = columns
@@ -130,13 +140,14 @@ function buildColumnsForPath(path: number[]) {
/** 列变化 */
function handleColumnChange({ selectedItem, resolve, finish }: any) {
if (selectedItem.value === 0) {
// 选择顶级部门或"选择当前",结束
if (selectedItem.id === 0 || selectedItem.id < 0) {
finish()
return
}
const children = deptList.value.filter(item => item.parentId === selectedItem.value)
const children = deptList.value.filter(item => item.parentId === selectedItem.id)
if (children.length > 0) {
resolve(children.map(item => ({ value: item.id, label: item.name })))
resolve(buildChildrenWithCurrent(selectedItem.id))
} else {
finish()
}
@@ -144,13 +155,23 @@ function handleColumnChange({ selectedItem, resolve, finish }: any) {
/** 格式化显示 */
function displayFormat(selectedItems: any[]) {
return selectedItems.map(item => item.label).join('/')
// 过滤掉"选择当前"选项
return selectedItems
.filter(item => item.id >= 0)
.map(item => item.name)
.join('/')
}
/** 确认选择 */
function handleConfirm({ value }: { value: number[] }) {
if (value && value.length > 0) {
emit('update:modelValue', value[value.length - 1])
const lastValue = value[value.length - 1]
// 如果选择的是"选择当前"(负数 ID取其绝对值作为实际选中的部门 ID
if (lastValue < 0) {
emit('update:modelValue', Math.abs(lastValue))
} else {
emit('update:modelValue', lastValue)
}
} else {
// 如果允许 root默认顶级 0否则 undefined
emit('update:modelValue', props.showRoot ? 0 : undefined)

View File

@@ -4,6 +4,8 @@
label="上级菜单"
label-width="180rpx"
:columns="menuColumns"
value-key="id"
label-key="name"
:column-change="handleColumnChange"
:display-format="displayFormat"
@confirm="handleConfirm"
@@ -50,8 +52,8 @@ async function loadMenuList() {
// 构建第一列数据(主类目 + 顶级菜单)
const topMenus = menuList.value.filter(item => item.parentId === 0)
menuColumns.value = [[
{ value: 0, label: '主类目' },
...topMenus.map(item => ({ value: item.id, label: item.name })),
{ id: 0, name: '主类目' },
...topMenus,
]]
// 如果有初始值,回显
if (props.modelValue !== undefined && props.modelValue !== 0) {
@@ -101,22 +103,32 @@ function buildColumnsForPath(path: number[]) {
}
const children = menuList.value.filter(item => item.parentId === parentId)
if (children.length > 0) {
columns.push(children.map(item => ({ value: item.id, label: item.name })))
columns.push(children)
}
}
menuColumns.value = columns
}
/** 构建带"选择当前"选项的子列表 */
function buildChildrenWithCurrent(parentId: number) {
const children = menuList.value.filter(item => item.parentId === parentId)
// 添加"选择当前"选项,使用父节点 ID 的负数作为标识
return [
{ id: -parentId, name: '✓ 选择当前' },
...children,
]
}
/** 列变化 */
function handleColumnChange({ selectedItem, resolve, finish }: any) {
if (selectedItem.value === 0) {
// 选择主类目,结束
// 选择主类目或"选择当前",结束
if (selectedItem.id === 0 || selectedItem.id < 0) {
finish()
return
}
const children = menuList.value.filter(item => item.parentId === selectedItem.value)
const children = menuList.value.filter(item => item.parentId === selectedItem.id)
if (children.length > 0) {
resolve(children.map(item => ({ value: item.id, label: item.name })))
resolve(buildChildrenWithCurrent(selectedItem.id))
} else {
finish()
}
@@ -124,13 +136,23 @@ function handleColumnChange({ selectedItem, resolve, finish }: any) {
/** 格式化显示 */
function displayFormat(selectedItems: any[]) {
return selectedItems.map(item => item.label).join(' / ')
// 过滤掉"选择当前"选项
return selectedItems
.filter(item => item.id >= 0)
.map(item => item.name)
.join(' / ')
}
/** 确认选择 */
function handleConfirm({ value }: { value: number[] }) {
if (value && value.length > 0) {
emit('update:modelValue', value[value.length - 1])
const lastValue = value[value.length - 1]
// 如果选择的是"选择当前"(负数 ID取其绝对值作为实际选中的菜单 ID
if (lastValue < 0) {
emit('update:modelValue', Math.abs(lastValue))
} else {
emit('update:modelValue', lastValue)
}
} else {
emit('update:modelValue', 0)
}

View File

@@ -3,7 +3,9 @@
v-model="selectedIds"
label="岗位"
label-width="180rpx"
:columns="columns"
:columns="postList"
value-key="id"
label-key="name"
type="checkbox"
filterable
@confirm="handleConfirm"
@@ -12,7 +14,7 @@
<script lang="ts" setup>
import type { Post } from '@/api/system/post'
import { computed, onMounted, ref, watch } from 'vue'
import { onMounted, ref, watch } from 'vue'
import { getSimplePostList } from '@/api/system/post'
const props = defineProps<{
@@ -26,14 +28,6 @@ const emit = defineEmits<{
const postList = ref<Post[]>([])
const selectedIds = ref<number[]>([])
/** 构建 columns 数据 */
const columns = computed(() => {
return postList.value.map(item => ({
label: item.name,
value: item.id,
}))
})
watch(
() => props.modelValue,
(val) => {