| | |
| | | ref="tree" |
| | | :data="tree" |
| | | node-key="id" |
| | | default-expand-all |
| | | v-loading="loading" |
| | | lazy |
| | | :load="loadNode" |
| | | show-checkbox |
| | | check-strictly |
| | | :filter-node-method="filterNode" |
| | |
| | | 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() { |
| | |
| | | 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('同一故障只能选择同一个X号下的设备') |
| | | this.syncSelected() |
| | | this.$message.warning('同一故障只能选择同一个rk_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) { |
| | |
| | | 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() { |
| | |
| | | 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('同一故障只能选择同一个X号下的设备') |
| | | return this.$message.warning('同一故障只能选择同一个rk_X号下的设备') |
| | | } |
| | | this.$emit('select', selected) |
| | | this.localVisible = false |