修改全局列问题了,联调设备升级mqtt

This commit is contained in:
guanj
2026-07-23 11:32:42 +08:00
parent b4c706407f
commit 88a500a387
27 changed files with 2682 additions and 1359 deletions

View File

@@ -33,16 +33,28 @@
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
<!-- <Icon
@click="onMenuCollapse"
:name="menuCollapse ? 'el-icon-Expand' : 'el-icon-Fold'"
:class="menuCollapse ? 'unfold' : ''"
size="18px"
class="fold ml10 menu-collapse"
style="cursor: pointer"
v-if="props.canExpand"
/> -->
</div>
<div class="comm-tabs mb10">
<el-tooltip
v-for="tab in commTabs"
:key="tab.key"
:content="tab.label"
placement="top"
:show-after="200"
>
<button
type="button"
class="comm-tab"
:class="[
`is-${tab.key}`,
{ 'is-active': commFilter === tab.key }
]"
@click="onCommFilter(tab.key)"
>
<Icon :name="tab.icon" :size="12" class="comm-tab__icon" />
<span class="comm-tab__count">{{ tab.count }}</span>
</button>
</el-tooltip>
</div>
<el-collapse
@@ -67,9 +79,10 @@
:filter-node-method="filterNode"
node-key="id"
:default-expand-all="false"
v-bind="$attrs"
v-bind="treeAttrs"
:data="zlDevList"
class="collapse-tree"
@node-click="onTreeNodeClick"
>
<template #default="{ node, data: nodeData }">
<span class="custom-tree-node">
@@ -95,8 +108,9 @@
:filter-node-method="filterNode"
node-key="id"
:data="bxsDeviceData"
v-bind="$attrs"
v-bind="treeAttrs"
class="collapse-tree"
@node-click="onTreeNodeClick"
>
<template #default="{ node, data: nodeData }">
<span class="custom-tree-node">
@@ -122,8 +136,9 @@
:filter-node-method="filterNode"
node-key="id"
:data="frontDeviceData"
v-bind="$attrs"
v-bind="treeAttrs"
class="collapse-tree"
@node-click="onTreeNodeClick"
>
<template #default="{ node, data: nodeData }">
<span class="custom-tree-node">
@@ -147,10 +162,11 @@
highlight-current
:filter-node-method="filterNode"
node-key="id"
v-bind="$attrs"
v-bind="treeAttrs"
:data="props.data"
class="engineering-tree"
:default-expand-all="false"
@node-click="onTreeNodeClick"
>
<template #default="{ node, data: nodeData }">
<span class="custom-tree-node">
@@ -172,7 +188,7 @@
<script lang="ts" setup>
import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree, type CollapseModelValue } from 'element-plus'
import { ref, watch, onMounted, nextTick } from 'vue'
import { ref, watch, onMounted, nextTick, computed, useAttrs } from 'vue'
import { collectDeviceLeaves } from './govern/lineTreeUtils'
import { collectDeviceApiLeaves } from './govern/deviceTreeUtils'
@@ -194,6 +210,8 @@ interface Props {
leafMode?: 'line' | 'device'
}
type CommFilter = 'all' | 'normal' | 'abnormal'
const props = withDefaults(defineProps<Props>(), {
width: '280px',
canExpand: true,
@@ -211,11 +229,20 @@ const options = [
]
const { proxy } = useCurrentInstance()
const attrs = useAttrs()
/** 去掉 node-click避免与本地处理重复/覆盖 */
const treeAttrs = computed(() => {
const { onNodeClick: _onNodeClick, ...rest } = attrs as Record<string, any>
return rest
})
const menuCollapse = ref(false)
const activeName = ref('0')
const filterText = ref('')
const process = ref('')
const loading = ref(false)
const commFilter = ref<CommFilter>('all')
const defaultProps = { label: 'name', value: 'id' }
@@ -231,6 +258,67 @@ const treeRef4 = ref<InstanceType<typeof ElTree>>()
defineExpose({ treeRef1, treeRef2, treeRef3, treeRef4 })
const isCommNormal = (node: any) => Number(node?.comFlag) === 2
/** 设备叶子Platform 且无子节点,或 type=device */
function isDeviceLeaf(data: any): boolean {
if (!data) return false
if (data.type === 'device') return true
if (data.icon === 'el-icon-Platform' && (!data.children || !data.children.length)) return true
if (data.level === 2 && data.icon === 'el-icon-Platform') return true
return false
}
function collectDevices(nodes: any[], out: any[] = []): any[] {
nodes?.forEach(n => {
if (isDeviceLeaf(n)) out.push(n)
if (n.children?.length) collectDevices(n.children, out)
})
return out
}
const deviceList = computed(() => {
if (treeType.value === '2') return collectDevices(props.data || [])
const collectLeaves = props.leafMode === 'device' ? collectDeviceApiLeaves : collectDeviceLeaves
const { govern, portable, monitor } = collectLeaves(
zlDevList.value,
bxsDeviceData.value,
frontDeviceData.value
)
return [...govern, ...portable, ...monitor]
})
const deviceStats = computed(() => {
const list = deviceList.value
const total = list.length
const normal = list.filter(isCommNormal).length
return { total, normal, abnormal: total - normal }
})
const commTabs = computed(() => [
{ key: 'all' as const, label: '全部设备', count: deviceStats.value.total, icon: 'el-icon-Platform' },
{ key: 'normal' as const, label: '通讯正常', count: deviceStats.value.normal, icon: 'el-icon-Platform' },
{ key: 'abnormal' as const, label: '通讯异常', count: deviceStats.value.abnormal, icon: 'el-icon-Platform' }
])
function applyTreeFilter() {
nextTick(() => {
const val = filterText.value
if (treeType.value === '1') {
treeRef1.value?.filter(val)
treeRef2.value?.filter(val)
treeRef3.value?.filter(val)
} else {
treeRef4.value?.filter(val)
}
})
}
const onCommFilter = (key: CommFilter) => {
commFilter.value = key
applyTreeFilter()
}
function splitTreeData(val: any[]) {
zlDeviceData.value = []
bxsDeviceData.value = []
@@ -270,6 +358,17 @@ function getActiveTreeRef() {
return treeRef3.value
}
function forwardNodeClick(data: any, node: any, ev?: any) {
const handler = (attrs as any).onNodeClick
if (!handler) return
if (Array.isArray(handler)) handler.forEach((fn: any) => fn?.(data, node, ev))
else handler(data, node, ev)
}
function onTreeNodeClick(data: any, node: any, ev?: any) {
forwardNodeClick(data, node, ev)
}
function resolveActiveName() {
if (zlDeviceData.value.length) return '0'
if (bxsDeviceData.value.length) return '1'
@@ -323,12 +422,13 @@ watch(
if (treeType.value === '1') {
nextTick(() => setActiveName())
}
applyTreeFilter()
},
{ immediate: true, deep: true }
)
watch(filterText, val => {
getActiveTreeRef()?.filter(val)
watch(filterText, () => {
applyTreeFilter()
})
watch(process, () => {
@@ -336,6 +436,11 @@ watch(process, () => {
if (activeName.value === '0') {
nextTick(() => changeDevice(activeName.value))
}
applyTreeFilter()
})
watch(treeType, () => {
applyTreeFilter()
})
const onMenuCollapse = () => {
@@ -343,10 +448,20 @@ const onMenuCollapse = () => {
proxy.eventBus.emit('cnTreeCollapse', menuCollapse)
}
const filterNode = (value: string, data: any, node: any): boolean => {
if (!value) return true
if (!data.name) return false
return chooseNode(value, data, node)
const filterNode = (_value: string, data: any, node: any): boolean => {
if (filterText.value) {
if (!data.name) return false
if (!chooseNode(filterText.value, data, node)) return false
}
if (commFilter.value === 'all') return true
if (isDeviceLeaf(data)) {
const normal = isCommNormal(data)
return commFilter.value === 'normal' ? normal : !normal
}
return !!filterText.value
}
const chooseNode = (value: string, data: any, node: any): boolean => {
@@ -413,6 +528,115 @@ onMounted(() => {
flex-shrink: 0;
}
.comm-tabs {
display: flex;
align-items: center;
// justify-content: flex-end;
gap: 6px;
flex-shrink: 0;
}
.comm-tab {
display: inline-flex;
align-items: center;
gap: 4px;
height: 22px;
padding: 0 4px 0 6px;
border-radius: 6px;
border: 1px solid #e5eaf3;
background: #fff;
color: #4e5969;
cursor: pointer;
transition: all 0.15s ease;
line-height: 1;
&__icon {
font-size: 12px;
}
&.is-all .comm-tab__icon,
&.is-all :deep(.comm-tab__icon),
&.is-all :deep(svg),
&.is-all :deep(i) {
color: var(--el-color-primary) !important;
}
&.is-normal .comm-tab__icon,
&.is-normal :deep(.comm-tab__icon),
&.is-normal :deep(svg),
&.is-normal :deep(i) {
color: #2ab914 !important;
}
&.is-abnormal .comm-tab__icon,
&.is-abnormal :deep(.comm-tab__icon),
&.is-abnormal :deep(svg),
&.is-abnormal :deep(i) {
color: #e26257 !important;
}
&__count {
min-width: 20px;
height: 16px;
padding: 0 4px;
border-radius: 4px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 600;
font-variant-numeric: tabular-nums;
color: #1d2129;
}
&:hover:not(.is-active) {
border-color: var(--el-color-primary-light-5);
color: var(--el-color-primary);
}
&.is-active {
color: #fff;
.comm-tab__icon,
:deep(.comm-tab__icon),
:deep(svg),
:deep(i) {
color: #fff !important;
}
.comm-tab__count {
background: #fff;
}
}
&.is-all.is-active {
background: var(--el-color-primary);
border-color: var(--el-color-primary);
.comm-tab__count {
color: var(--el-color-primary);
}
}
&.is-normal.is-active {
background: #2ab914;
border-color: #2ab914;
.comm-tab__count {
color: #2ab914;
}
}
&.is-abnormal.is-active {
background: #e26257;
border-color: #e26257;
.comm-tab__count {
color: #e26257;
}
}
}
.device-collapse {
flex: 1;
min-height: 0;