opt:树形

This commit is contained in:
2026-01-20 16:41:49 +08:00
parent 4a0ef377bb
commit 3b84113d26

View File

@@ -95,9 +95,10 @@
<a-tree-select
v-model:value="formData.parentDetailId"
:tree-data="parentTreeData"
:load-data="handleLoadData"
placeholder="请选择上级类目"
allow-clear
tree-default-expand-all
tree-line
/>
</a-form-item>
</a-col>
@@ -128,7 +129,6 @@
import dayjs from 'dayjs'
import { cloneDeep } from 'lodash-es'
import { required } from '@/utils/formRules'
import projectApi from '@/api/pmm/projectApi'
import stageDetailApi from '@/api/pmm/stageDetailApi'
const open = ref(false)
@@ -183,39 +183,44 @@
]
}
const buildTree = (nodes) => {
const list = Array.isArray(nodes) ? nodes : []
const byId = new Map()
const roots = []
list.forEach((item) => {
const id = item?.detailId
if (!id) return
const titleParts = []
if (item.modelName) titleParts.push(item.modelName)
if (item.modelDetail) titleParts.push(item.modelDetail)
const title = titleParts.length ? titleParts.join(' - ') : String(id)
byId.set(id, { title, value: id, key: id, children: [], raw: item })
})
byId.forEach((node) => {
const parentId = node.raw?.parentDetailId
if (parentId && byId.has(parentId)) {
byId.get(parentId).children.push(node)
} else {
roots.push(node)
}
})
return roots
const toTreeNode = (item = {}) => {
const id = item.detailId
const titleParts = []
if (item.modelName) titleParts.push(item.modelName)
if (item.modelDetail) titleParts.push(item.modelDetail)
const title = titleParts.length ? titleParts.join(' - ') : String(id || '')
return {
title,
value: id,
key: id,
isLeaf: item.isLeaf === true,
children: Array.isArray(item.children) ? item.children.map(toTreeNode) : []
}
}
const loadParentTree = async (projectId) => {
if (!projectId) {
parentTreeData.value = []
return
}
const data = await projectApi.requestDetail({ projectId })
const stages = Array.isArray(data) ? data : []
const flat = stages.flatMap((s) => (Array.isArray(s?.descriptions) ? s.descriptions : []))
parentTreeData.value = buildTree(flat)
const loadRootTree = async () => {
if (!formData.value.stageId) return
const data = await stageDetailApi.loadClass({
stageId: formData.value.stageId,
parentDetailId: 0
})
parentTreeData.value = (Array.isArray(data) ? data : []).map(toTreeNode)
}
const loadSuperiorTree = async (parentDetailId) => {
if (!formData.value.stageId || !parentDetailId) return
const data = await stageDetailApi.superior({
stageId: formData.value.stageId,
parentDetailId
})
parentTreeData.value = (Array.isArray(data) ? data : []).map(toTreeNode)
}
const handleLoadData = async (node) => {
// 展开时走 superior后端会返回包含父链的树结构
const parentId = node?.value
if (!parentId) return
await loadSuperiorTree(parentId)
}
const recomputeEndTime = () => {
@@ -234,9 +239,13 @@
}
)
const onTopChange = () => {
const onTopChange = async () => {
if (formData.value.isTop === true) {
formData.value.parentDetailId = 0
parentTreeData.value = []
} else {
// 顶级新增同级parentId = 0加载根节点
await loadRootTree()
}
}
@@ -250,7 +259,11 @@
if (formData.value.isTop) {
formData.value.parentDetailId = 0
}
await loadParentTree(formData.value.projectId)
if (formData.value.isTop === false) {
await loadRootTree()
} else {
parentTreeData.value = []
}
recomputeEndTime()
}