From d565fd6a5fd7557c780572b0efa817cda19a2225 Mon Sep 17 00:00:00 2001 From: yangsy Date: Thu, 18 Dec 2025 20:47:00 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=94=B1=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E5=B1=9E=E6=80=A7=E5=AF=BC=E8=87=B4=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=A0=91=E5=9C=A8=E7=89=B9=E5=AE=9A=E5=9C=BA=E6=99=AF=E4=B8=8B?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=87=AA=E8=A1=8C=E6=BB=9A=E5=8A=A8=E5=8F=8A?= =?UTF-8?q?=E5=B1=95=E5=BC=80=E8=8A=82=E7=82=B9=E5=A4=B1=E6=95=88=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 当选中的设备所属车站在设备树的视口外时,定位操作无效,且节点无法点击展开,解决方案是在定位逻辑中切换Tree组件的animated状态 --- .../device/device-tree/device-tree.vue | 70 +++++++++++-------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/components/device/device-tree/device-tree.vue b/src/components/device/device-tree/device-tree.vue index 0686a64..a546100 100644 --- a/src/components/device/device-tree/device-tree.vue +++ b/src/components/device/device-tree/device-tree.vue @@ -4,7 +4,6 @@ import { useDeviceTree } from '@/composables'; import { DEVICE_TYPE_NAMES, DEVICE_TYPE_LITERALS, tryGetDeviceType, type DeviceType } from '@/enums'; import { isNvrCluster } from '@/helpers'; import { useDeviceStore, useStationStore } from '@/stores'; -import { sleep } from '@/utils'; import { watchImmediate } from '@vueuse/core'; import destr from 'destr'; import { isFunction } from 'es-toolkit'; @@ -28,7 +27,7 @@ import { type TreeProps, } from 'naive-ui'; import { storeToRefs } from 'pinia'; -import { computed, h, onBeforeUnmount, ref, toRefs, useTemplateRef, watch, type CSSProperties } from 'vue'; +import { computed, h, nextTick, onBeforeUnmount, ref, toRefs, useTemplateRef, watch, type CSSProperties } from 'vue'; const props = defineProps<{ station?: Station; // 支持渲染指定车站的设备树 @@ -325,7 +324,7 @@ const lineDeviceTreeData = computed>(() => const device = dev as NdmDeviceResultVO; return { label: `${device.name}`, - key: device.id ?? `${device.name}`, + key: `${device.id}`, prefix: () => renderDeviceNodePrefix(device, stationCode), suffix: () => `${device.ipAddress}`, // 当选择设备时,能获取到设备的所有信息,以及设备所属的车站 @@ -359,13 +358,13 @@ const stationDeviceTreeData = computed(() => { children: clusters.map((device) => { return { label: `${device.name}`, - key: device.id ?? `${device.name}`, + key: `${device.id}`, prefix: () => renderDeviceNodePrefix(device, stationCode), suffix: () => `${device.ipAddress}`, children: singletons.map((device) => { return { label: `${device.name}`, - key: device.id ?? `${device.name}`, + key: `${device.id}`, prefix: () => renderDeviceNodePrefix(device, stationCode), suffix: () => `${device.ipAddress}`, stationCode, @@ -387,7 +386,7 @@ const stationDeviceTreeData = computed(() => { children: stationDevices[deviceType].map((device) => { return { label: `${device.name}`, - key: device.id ?? `${device.name}`, + key: `${device.id}`, prefix: () => renderDeviceNodePrefix(device, stationCode), suffix: () => `${device.ipAddress}`, stationCode, @@ -421,39 +420,46 @@ const searchFilter = (pattern: string, node: TreeOption): boolean => { }; // ========== 设备树交互 ========== -const expandedKeys = ref(); +const animated = ref(true); +const expandedKeys = ref([]); const deviceTreeInst = useTemplateRef('deviceTreeInst'); const onFoldDeviceTree = () => { expandedKeys.value = []; }; -const onLocateDeviceTree = () => { - const stationCode = selectedStationCode.value; - const device = selectedDevice.value; - if (!stationCode || !device?.id) return; - const deviceTypeVal = tryGetDeviceType(device.deviceType); - if (!!deviceTypeVal) { - activeTab.value = deviceTypeVal; - } +const onLocateDeviceTree = async () => { + if (!selectedStationCode.value) return; + if (!selectedDevice.value) return; + const deviceType = tryGetDeviceType(selectedDevice.value.deviceType); + if (!deviceType) return; + if (!deviceTreeInst.value) return; - const expanded = [stationCode]; - if (activeTab.value === DEVICE_TYPE_LITERALS.ndmNvr) { - const nvrs = lineDevices.value[stationCode]?.[DEVICE_TYPE_LITERALS.ndmNvr]; - if (nvrs) { - const clusterKeys = nvrs.filter((nvr) => !!nvr.clusterList?.trim() && nvr.clusterList !== nvr.ipAddress).map((nvr) => String(nvr.id)); - expanded.push(...clusterKeys); + animated.value = false; + + // 定位设备类型 + activeTab.value = deviceType; + + // 展开选择的车站 + expandedKeys.value = [selectedStationCode.value]; + + // 当选择录像机时,如果不是集群,进一步展开该录像机所在的集群节点 + if (deviceType === DEVICE_TYPE_LITERALS.ndmNvr) { + const stationDevices = lineDevices.value[selectedStationCode.value]; + if (stationDevices) { + const selectedNvr = selectedDevice.value as NdmNvrResultVO; + if (!isNvrCluster(selectedNvr)) { + const nvrs = stationDevices[DEVICE_TYPE_LITERALS.ndmNvr]; + const clusters = nvrs.filter((nvr) => isNvrCluster(nvr) && nvr.clusterList?.includes(selectedNvr.clusterList ?? '')); + expandedKeys.value.push(...clusters.map((nvr) => `${nvr.id}`)); + } } } - expandedKeys.value = expanded; - // 由于数据量大所以开启虚拟滚动, - // 但是无法知晓NTree内部的虚拟列表容器何时创建完成,所以使用setTimeout延迟固定时间后执行滚动 - scrollDeviceTreeToSelectedDevice(); + // 等待设备树展开完成,滚动到选择的设备 + await nextTick(); + deviceTreeInst.value.scrollTo({ key: `${selectedDevice.value.id}`, behavior: 'smooth' }); + + animated.value = true; }; -async function scrollDeviceTreeToSelectedDevice() { - await sleep(350); - const inst = deviceTreeInst.value; - inst?.scrollTo({ key: selectedDevice?.value?.id ?? `${selectedDevice.value?.name}`, behavior: 'smooth' }); -}