2026-06-04 09:08:37 +08:00
|
|
|
import { nextTick } from 'vue'
|
|
|
|
|
|
|
|
|
|
export interface LineTreeLeaves {
|
|
|
|
|
govern: any[]
|
|
|
|
|
portable: any[]
|
|
|
|
|
monitor: any[]
|
|
|
|
|
engineering: any[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface LineTreeDecorators {
|
|
|
|
|
primary: () => string
|
|
|
|
|
statusColor: (comFlag: number) => string
|
|
|
|
|
applyMeta: (
|
|
|
|
|
node: any,
|
|
|
|
|
meta: { icon: string; color?: string; level?: number; disabled?: boolean }
|
|
|
|
|
) => void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function createLineTreeDecorators(getPrimaryColor: () => string): LineTreeDecorators {
|
|
|
|
|
const offlineColor = '#e26257 !important'
|
|
|
|
|
const statusColor = (comFlag: number) => (comFlag === 2 ? getPrimaryColor() : offlineColor)
|
|
|
|
|
|
|
|
|
|
const applyMeta = (
|
|
|
|
|
node: any,
|
|
|
|
|
meta: { icon: string; color?: string; level?: number; disabled?: boolean }
|
|
|
|
|
) => {
|
|
|
|
|
node.icon = meta.icon
|
|
|
|
|
if (meta.color !== undefined) node.color = meta.color
|
|
|
|
|
if (meta.level !== undefined) node.level = meta.level
|
|
|
|
|
if (meta.disabled) node.disabled = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
primary: getPrimaryColor,
|
|
|
|
|
statusColor,
|
|
|
|
|
applyMeta
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type TreeRefKey = 'treeRef1' | 'treeRef2' | 'treeRef3' | 'treeRef4'
|
|
|
|
|
|
2026-06-04 19:06:36 +08:00
|
|
|
/** 线路树可选叶子节点元数据 */
|
|
|
|
|
export const LINE_LEAF_META = { level: 3, type: 'line' as const }
|
|
|
|
|
|
|
|
|
|
/** 是否为线路树可选叶子(监测点/线路) */
|
|
|
|
|
export function isLineTreeLeaf(node: any): boolean {
|
|
|
|
|
if (!node?.id) return false
|
|
|
|
|
return node.type === 'line' || node.level === 3
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 是否为报告/导出可选监测点 */
|
|
|
|
|
export function isReportMonitorPoint(node: any): boolean {
|
|
|
|
|
if (!node?.id) return false
|
|
|
|
|
return isLineTreeLeaf(node) || node.level === 3 || (!node.children?.length && !!node.pid)
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-04 09:08:37 +08:00
|
|
|
export interface DecorateLineTreeOptions {
|
|
|
|
|
/** 是否禁用父级节点(分析树隐藏父节点,测点树不禁用) */
|
|
|
|
|
disableParents?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 装饰线路树节点并收集可选叶子节点 */
|
|
|
|
|
export function decorateLineTree(
|
|
|
|
|
data: any[],
|
|
|
|
|
type: string | undefined,
|
|
|
|
|
decorators: LineTreeDecorators,
|
|
|
|
|
options: DecorateLineTreeOptions = {}
|
|
|
|
|
): LineTreeLeaves {
|
|
|
|
|
const leaves: LineTreeLeaves = { govern: [], portable: [], monitor: [], engineering: [] }
|
|
|
|
|
const { primary, statusColor, applyMeta } = decorators
|
|
|
|
|
const disableParents = options.disableParents ?? true
|
|
|
|
|
const parentDisabled = disableParents ? ({ disabled: true } as const) : {}
|
|
|
|
|
|
|
|
|
|
data.forEach(item => {
|
|
|
|
|
if (type === '2') {
|
|
|
|
|
applyMeta(item, { icon: 'el-icon-HomeFilled', color: primary(), ...parentDisabled })
|
|
|
|
|
item.children?.forEach((child: any) => {
|
|
|
|
|
applyMeta(child, { icon: 'el-icon-List', color: primary(), ...parentDisabled })
|
|
|
|
|
child.children?.forEach((grand: any) => {
|
|
|
|
|
applyMeta(grand, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(grand.comFlag),
|
|
|
|
|
level: 2,
|
|
|
|
|
...parentDisabled
|
|
|
|
|
})
|
|
|
|
|
grand.children?.forEach((leaf: any) => {
|
2026-06-04 19:06:36 +08:00
|
|
|
applyMeta(leaf, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(leaf.comFlag),
|
|
|
|
|
...LINE_LEAF_META
|
|
|
|
|
})
|
2026-06-04 09:08:37 +08:00
|
|
|
leaves.engineering.push(leaf)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.name === '治理设备') {
|
|
|
|
|
item.children?.forEach((l1: any) => {
|
|
|
|
|
applyMeta(l1, { icon: 'el-icon-HomeFilled', color: primary(), level: 1, ...parentDisabled })
|
|
|
|
|
l1.children?.forEach((l2: any) => {
|
|
|
|
|
applyMeta(l2, { icon: 'el-icon-List', color: primary(), level: 1, ...parentDisabled })
|
|
|
|
|
l2.children?.forEach((l3: any) => {
|
|
|
|
|
applyMeta(l3, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(l3.comFlag),
|
|
|
|
|
level: 2,
|
|
|
|
|
...parentDisabled
|
|
|
|
|
})
|
|
|
|
|
l3.children?.forEach((l4: any) => {
|
2026-06-04 19:06:36 +08:00
|
|
|
applyMeta(l4, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(l4.comFlag),
|
|
|
|
|
...LINE_LEAF_META
|
|
|
|
|
})
|
2026-06-04 09:08:37 +08:00
|
|
|
leaves.govern.push(l4)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
} else if (item.name === '便携式设备') {
|
|
|
|
|
item.children?.forEach((l1: any) => {
|
|
|
|
|
applyMeta(l1, { icon: 'el-icon-Platform', color: statusColor(l1.comFlag) })
|
|
|
|
|
l1.children?.forEach((l2: any) => {
|
2026-06-04 19:06:36 +08:00
|
|
|
applyMeta(l2, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(l2.comFlag),
|
|
|
|
|
...LINE_LEAF_META
|
|
|
|
|
})
|
2026-06-04 09:08:37 +08:00
|
|
|
leaves.portable.push(l2)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
} else if (item.name === '监测设备') {
|
|
|
|
|
item.children?.forEach((l1: any) => {
|
|
|
|
|
applyMeta(l1, { icon: 'el-icon-HomeFilled', color: primary(), level: 1, ...parentDisabled })
|
|
|
|
|
l1.children?.forEach((l2: any) => {
|
|
|
|
|
applyMeta(l2, { icon: 'el-icon-List', color: primary(), level: 1, ...parentDisabled })
|
|
|
|
|
l2.children?.forEach((l3: any) => {
|
|
|
|
|
applyMeta(l3, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(l3.comFlag),
|
|
|
|
|
level: 1,
|
|
|
|
|
...parentDisabled
|
|
|
|
|
})
|
|
|
|
|
l3.children?.forEach((l4: any) => {
|
2026-06-04 19:06:36 +08:00
|
|
|
applyMeta(l4, {
|
|
|
|
|
icon: 'el-icon-Platform',
|
|
|
|
|
color: statusColor(l4.comFlag),
|
|
|
|
|
...LINE_LEAF_META
|
|
|
|
|
})
|
2026-06-04 09:08:37 +08:00
|
|
|
leaves.monitor.push(l4)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return leaves
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 从折叠面板树数据中收集叶子节点(与 decorateLineTree 层级一致) */
|
|
|
|
|
export function collectDeviceLeaves(
|
|
|
|
|
governNodes: any[],
|
|
|
|
|
portableNodes: any[],
|
|
|
|
|
monitorNodes: any[]
|
|
|
|
|
): Pick<LineTreeLeaves, 'govern' | 'portable' | 'monitor'> {
|
|
|
|
|
const govern: any[] = []
|
|
|
|
|
const portable: any[] = []
|
|
|
|
|
const monitor: any[] = []
|
|
|
|
|
|
|
|
|
|
governNodes.forEach(l1 => {
|
|
|
|
|
l1.children?.forEach((l2: any) => {
|
|
|
|
|
l2.children?.forEach((l3: any) => {
|
|
|
|
|
l3.children?.forEach((l4: any) => govern.push(l4))
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
portableNodes.forEach(l1 => {
|
|
|
|
|
l1.children?.forEach((l2: any) => portable.push(l2))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
monitorNodes.forEach(l1 => {
|
|
|
|
|
l1.children?.forEach((l2: any) => {
|
|
|
|
|
l2.children?.forEach((l3: any) => {
|
|
|
|
|
l3.children?.forEach((l4: any) => monitor.push(l4))
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return { govern, portable, monitor }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function waitForTreeRef(treRef: any, refKey: TreeRefKey, maxRetries = 20) {
|
|
|
|
|
for (let i = 0; i < maxRetries; i++) {
|
|
|
|
|
await nextTick()
|
|
|
|
|
if (treRef?.[refKey]) return treRef[refKey]
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
|
|
|
}
|
|
|
|
|
return null
|
|
|
|
|
}
|