From ffe06be91f95ffd2459ebdb2f9130d1e38d53ea7 Mon Sep 17 00:00:00 2001
From: zzw <228544128@qq.com>
Date: 星期二, 06 十月 2026 18:32:34 +0800
Subject: [PATCH] fix: preserve manually edited menu names
---
emergency-repair-web/src/components/ProductTreePicker.vue | 98 +++++++++++++++++++++++++++++++++----------------
1 files changed, 66 insertions(+), 32 deletions(-)
diff --git a/emergency-repair-web/src/components/ProductTreePicker.vue b/emergency-repair-web/src/components/ProductTreePicker.vue
index 2e82ab6..021bbea 100644
--- a/emergency-repair-web/src/components/ProductTreePicker.vue
+++ b/emergency-repair-web/src/components/ProductTreePicker.vue
@@ -7,7 +7,9 @@
ref="tree"
:data="tree"
node-key="id"
- default-expand-all
+ v-loading="loading"
+ lazy
+ :load="loadNode"
show-checkbox
check-strictly
:filter-node-method="filterNode"
@@ -51,7 +53,7 @@
selectedIds: { type: Array, default: () => [] }
},
data() {
- return { localVisible: false, keyword: '', tree: [], checkedCount: 0, selectedDevices: [] }
+ return { localVisible: false, keyword: '', tree: [], checkedCount: 0, selectedDevices: [], selectedMap: {}, loading: false }
},
computed: {
treeProps() {
@@ -74,52 +76,82 @@
methods: {
load() {
const lockedXNo = String(this.xNo || '').trim()
- api.get('/system/tree', { params: { type: 'product' } }).then(res => {
- const source = res.data || []
- this.tree = lockedXNo ? this.filterTreeByXNo(source, lockedXNo) : source
+ this.loading = true
+ const ids = (this.selectedIds || []).map(String).filter(Boolean)
+ const treeRequest = lockedXNo
+ ? api.get('/system/tree/product/side-roots', { params: { xNo: lockedXNo } })
+ : api.get('/system/tree/product/roots')
+ const selectedRequest = ids.length
+ ? api.get('/system/tree/product/selected', { params: { ids: ids.join(',') } })
+ : Promise.resolve({ data: [] })
+ Promise.all([treeRequest, selectedRequest]).then(([treeRes, selectedRes]) => {
+ this.tree = treeRes.data || []
+ this.selectedMap = (selectedRes.data || []).reduce((map, node) => {
+ map[String(node.id)] = node
+ return map
+ }, {})
this.keyword = ''
- this.$nextTick(this.restoreChecked)
+ this.$nextTick(() => {
+ this.expandLockedRoots(lockedXNo)
+ this.restoreChecked()
+ this.syncSelected()
+ })
+ }).finally(() => { this.loading = false })
+ },
+ expandLockedRoots(lockedXNo) {
+ if (!lockedXNo || !this.$refs.tree) return
+ this.tree.forEach(node => {
+ const treeNode = this.$refs.tree.getNode(node.id)
+ if (treeNode) treeNode.expand()
})
},
- filterTreeByXNo(nodes, xNo) {
- const result = []
- ;(nodes || []).forEach(node => {
- if (Number(node.nodeLevel) === 2) {
- if (String(node.name || '').trim() === xNo) result.push(node)
- return
- }
- const children = this.filterTreeByXNo(node.children || [], xNo)
- if (children.length || node.nodeType === 'DEVICE') {
- result.push(children.length ? { ...node, children } : node)
- }
- })
- return result
+ loadNode(node, resolve) {
+ if (!node || !node.data || !node.data.id) {
+ resolve([])
+ return
+ }
+ api.get('/system/tree/product/children', { params: { parentId: node.data.id } })
+ .then(res => {
+ resolve(res.data || [])
+ this.$nextTick(this.restoreChecked)
+ })
+ .catch(() => resolve([]))
},
restoreChecked() {
if (!this.$refs.tree) return
- const ids = (this.selectedIds || []).map(String).filter(Boolean)
+ const ids = Object.keys(this.selectedMap).filter(id => Boolean(this.$refs.tree.getNode(id)))
this.$refs.tree.setCheckedKeys(ids)
this.syncSelected()
},
handleCheck(node) {
const tree = this.$refs.tree
const treeNode = tree && tree.getNode(node.id)
+ this.syncSelected()
if (treeNode && treeNode.checked) {
- const selected = this.deviceNodes().map(item => this.decorateNode(item))
- const xNos = Array.from(new Set(selected.map(item => item.xNo).filter(Boolean)))
+ const xNos = Array.from(new Set(this.selectedDevices.map(item => item.xNo).filter(Boolean)))
if (xNos.length > 1) {
tree.setChecked(node.id, false, true)
- this.$message.warning('鍚屼竴鏁呴殰鍙兘閫夋嫨鍚屼竴涓猉鍙蜂笅鐨勮澶�')
+ this.syncSelected()
+ this.$message.warning('鍚屼竴鏁呴殰鍙兘閫夋嫨鍚屼竴涓猺k_X鍙蜂笅鐨勮澶�')
}
}
- this.syncSelected()
},
syncSelected() {
- const selected = this.deviceNodes().map(node => this.decorateNode(node))
- this.selectedDevices = selected
- this.checkedCount = selected.length
+ const tree = this.$refs.tree
+ if (!tree) return
+ const selectedMap = { ...this.selectedMap }
+ const checked = tree.getCheckedNodes().filter(node => node.nodeType === 'DEVICE')
+ const checkedIds = new Set(checked.map(node => String(node.id)))
+ Object.keys(selectedMap).forEach(id => {
+ if (tree.getNode(id) && !checkedIds.has(id)) delete selectedMap[id]
+ })
+ checked.forEach(node => { selectedMap[String(node.id)] = this.decorateNode(node) })
+ this.selectedMap = selectedMap
+ this.selectedDevices = Object.values(selectedMap)
+ this.checkedCount = this.selectedDevices.length
},
decorateNode(node) {
+ if (!this.$refs.tree) return { ...node }
const pathNodes = []
let current = this.$refs.tree.getNode(node.id)
while (current && current.data) {
@@ -134,8 +166,10 @@
return { ...node, pathNames: pathNodes.map(item => item.name), parentPathNames, xNo: xNode ? xNode.name : '' }
},
removeSelected(device) {
- if (!this.$refs.tree) return
- this.$refs.tree.setChecked(device.id, false, true)
+ const selectedMap = { ...this.selectedMap }
+ delete selectedMap[String(device.id)]
+ this.selectedMap = selectedMap
+ if (this.$refs.tree && this.$refs.tree.getNode(device.id)) this.$refs.tree.setChecked(device.id, false, true)
this.syncSelected()
},
deviceNodes() {
@@ -147,12 +181,12 @@
return (data.name || '').includes(value) || (data.code || '').includes(value)
},
confirm() {
- const nodes = this.deviceNodes()
+ const nodes = this.selectedDevices
if (!nodes.length) return this.$message.warning('璇烽�夋嫨璁惧')
- const selected = nodes.map(node => this.decorateNode(node))
+ const selected = nodes
const xNos = Array.from(new Set(selected.map(item => item.xNo).filter(Boolean)))
if (xNos.length > 1) {
- return this.$message.warning('鍚屼竴鏁呴殰鍙兘閫夋嫨鍚屼竴涓猉鍙蜂笅鐨勮澶�')
+ return this.$message.warning('鍚屼竴鏁呴殰鍙兘閫夋嫨鍚屼竴涓猺k_X鍙蜂笅鐨勮澶�')
}
this.$emit('select', selected)
this.localVisible = false
--
Gitblit v1.9.1