From ac503ca81b5d4c7911b263e9d5e2c5e0cc008ae1 Mon Sep 17 00:00:00 2001 From: xudan Date: Thu, 11 Dec 2025 14:12:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(elevator):=20=E4=BF=AE=E5=A4=8D=E7=94=B5?= =?UTF-8?q?=E6=A2=AF=E7=8A=B6=E6=80=81=E5=AE=9E=E6=97=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BC=98=E5=8C=96=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E5=93=8D=E5=BA=94=E5=BC=8F=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=E5=BC=80=E5=8F=91=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/card/point-detail-card.vue | 104 ++++++++++++++++++++-- src/pages/movement-supervision.vue | 72 ++++++++++++++- src/pages/scene-editor.vue | 88 ++++++++++++++++++ src/services/editor/editor-drawers.ts | 72 ++++----------- 电梯状态实时更新修复说明.md | 53 +++++++++++ 5 files changed, 324 insertions(+), 65 deletions(-) create mode 100644 电梯状态实时更新修复说明.md diff --git a/src/components/card/point-detail-card.vue b/src/components/card/point-detail-card.vue index fb9c869..a168915 100644 --- a/src/components/card/point-detail-card.vue +++ b/src/components/card/point-detail-card.vue @@ -17,7 +17,20 @@ type Props = { const props = defineProps(); const editor = inject(props.token)!; -const pen = computed(() => editor.value.getPenById(props.current)); +// 订阅点位集合变化(含设备状态/连接状态),用于触发详情面板的响应式刷新 +const pointsTick = computed(() => + editor.value.points.value + .map((v: any) => `${v.id}:${v?.point?.isConnected ?? ''}:${v?.point?.elevatorDirection ?? ''}:${v?.point?.elevatorFrontDoorStatus ?? ''}:${v?.point?.currentFloor ?? ''}`) + .join('|'), +); + +// 优化 pen 计算属性,确保响应式更新 +const pen = computed(() => { + // 引用 pointsTick 以建立依赖关系 + void pointsTick.value; + return editor.value.getPenById(props.current); +}); + const point = computed(() => { const v = pen.value?.point; if (isNil(v?.type)) return null; @@ -131,6 +144,79 @@ watch(point, (newPoint) => { } }, { immediate: true }); +// 关键修复:创建直接的状态计算,绕过深层响应式问题 +const elevatorStatusText = computed(() => { + // 强制依赖 pointsTick 以确保响应式更新 + void pointsTick.value; + + const pen = editor.value.getPenById(props.current); + const point = pen?.point; + if (!point) return '未知'; + + const { elevatorDirection, elevatorFrontDoorStatus, isConnected } = point; + + // 离线 + if (!isConnected) return '离线'; + + // 优先判断门状态 + if (elevatorFrontDoorStatus === 2) return '开关门中'; + if (elevatorFrontDoorStatus === 3) return '门已开'; + + // 门已关,根据方向判断 + if (elevatorFrontDoorStatus === 1) { + if (elevatorDirection === 2) return '上行中'; + if (elevatorDirection === 3) return '下行中'; + if (elevatorDirection === 1) return '门已关'; + } + + return '未知'; +}); + +const elevatorStatusColor = computed(() => { + // 强制依赖 pointsTick 以确保响应式更新 + void pointsTick.value; + + const pen = editor.value.getPenById(props.current); + const point = pen?.point; + if (!point) return '#1890FF'; + + const { isConnected, elevatorDirection, elevatorFrontDoorStatus } = point; + + // 离线显示灰色 + if (!isConnected) return '#999999'; + + // 优先判断门状态 + if (elevatorFrontDoorStatus === 2) return '#52C41A'; // 开门中 - 绿色 + if (elevatorFrontDoorStatus === 3) return '#52C41A'; // 门已开 - 绿色 + + // 门已关,根据方向判断 + if (elevatorFrontDoorStatus === 1) { + if (elevatorDirection === 2) return '#722ED1'; // 向上 - 紫色 + if (elevatorDirection === 3) return '#13C2C2'; // 向下 - 青色 + if (elevatorDirection === 1) return '#1890FF'; // 停止 - 蓝色 + } + + return '#1890FF'; // 默认 - 蓝色 +}); + +// 电梯连接状态计算属性 +const elevatorIsConnected = computed(() => { + // 强制依赖 pointsTick 以确保响应式更新 + void pointsTick.value; + + const pen = editor.value.getPenById(props.current); + return pen?.point?.isConnected; +}); + +// 电梯当前楼层计算属性 +const elevatorCurrentFloor = computed(() => { + // 强制依赖 pointsTick 以确保响应式更新 + void pointsTick.value; + + const pen = editor.value.getPenById(props.current); + return pen?.point?.currentFloor; +}); + // 获取电梯状态文本(基于后端字段) const getElevatorStatusText = (point: any): string => { const { elevatorDirection, elevatorFrontDoorStatus, isConnected } = point; @@ -226,26 +312,26 @@ const getElevatorStatusColor = (point: any): string => { - {{ point.isConnected ? $t('已连接') : $t('未连接') }} + {{ elevatorIsConnected ? $t('已连接') : $t('未连接') }} - + {{ $t('当前楼层') }} - {{ point.currentFloor }}F + {{ elevatorCurrentFloor }}F - + {{ $t('电梯状态') }} - {{ getElevatorStatusText(point) }} + {{ elevatorStatusText }} diff --git a/src/pages/movement-supervision.vue b/src/pages/movement-supervision.vue index 3d9426d..2db5dc0 100644 --- a/src/pages/movement-supervision.vue +++ b/src/pages/movement-supervision.vue @@ -119,6 +119,10 @@ const isSceneLoading = ref(false); // 电梯模拟数据停止函数 let stopElevatorMock: (() => void) | undefined; +// 电梯模拟数据定时器 +let elevatorMockTimer: number | undefined; +// 电梯状态计数器 +let elevatorMockTick = 0; const playback = usePlaybackWebSocket(editor, async () => { // [关键修复] 只有在收到第一帧机器人数据后才初始化机器人图元 @@ -530,11 +534,69 @@ onMounted(async () => { id: '1998661793706377218', type: 102, elevatorFloor: 5, - elevatorDirection: 3, // 停止 - elevatorFrontDoorStatus: 3, // 正在开关 + elevatorDirection: 2, // 停止 + elevatorFrontDoorStatus: 2, // 正在开关 isConnected: true }); + // 启动电梯状态自动变化的定时器 + console.log('[开发环境] 启动电梯状态自动变化定时器(3秒间隔)'); + + // 定义电梯状态变化序列 + const elevatorStates = [ + { floor: 5, direction: 2, doorStatus: 2 }, // 5楼,停止,正在开关门 + { floor: 5, direction: 2, doorStatus: 3 }, // 5楼,停止,门已开 + { floor: 5, direction: 2, doorStatus: 1 }, // 5楼,停止,门已关 + { floor: 5, direction: 2, doorStatus: 1 }, // 5楼,向上,门已关 + { floor: 6, direction: 2, doorStatus: 1 }, // 6楼,向上,门已关 + { floor: 6, direction: 2, doorStatus: 2 }, // 6楼,向上,正在开关门 + { floor: 6, direction: 2, doorStatus: 3 }, // 6楼,向上,门已开 + { floor: 6, direction: 2, doorStatus: 1 }, // 6楼,向上,门已关 + { floor: 7, direction: 2, doorStatus: 1 }, // 7楼,向上,门已关 + { floor: 7, direction: 2, doorStatus: 2 }, // 7楼,向上,正在开关门 + { floor: 7, direction: 2, doorStatus: 3 }, // 7楼,向上,门已开 + { floor: 7, direction: 2, doorStatus: 1 }, // 7楼,向上,门已关 + { floor: 7, direction: 1, doorStatus: 1 }, // 7楼,停止,门已关 + { floor: 7, direction: 3, doorStatus: 1 }, // 7楼,向下,门已关 + { floor: 6, direction: 3, doorStatus: 1 }, // 6楼,向下,门已关 + { floor: 6, direction: 3, doorStatus: 2 }, // 6楼,向下,正在开关门 + { floor: 6, direction: 3, doorStatus: 3 }, // 6楼,向下,门已开 + { floor: 6, direction: 3, doorStatus: 1 }, // 6楼,向下,门已关 + { floor: 5, direction: 3, doorStatus: 1 }, // 5楼,向下,门已关 + { floor: 5, direction: 1, doorStatus: 1 }, // 5楼,停止,门已关 + ]; + + elevatorMockTimer = window.setInterval(() => { + const stateIndex = elevatorMockTick % elevatorStates.length; + const state = elevatorStates[stateIndex]; + + console.log(`[开发环境] 电梯状态变化 #${elevatorMockTick}:`, { + floor: state.floor, + direction: ['未知', '停止', '向上', '向下'][state.direction], + doorStatus: ['未知', '关', '开关门中', '开'][state.doorStatus] + }); + + elevatorStore.handleElevatorWebSocketData({ + id: '1998661793706377218', + type: 102, + elevatorFloor: state.floor, + elevatorDirection: state.direction, + elevatorFrontDoorStatus: state.doorStatus, + isConnected: true + }); + + elevatorMockTick++; + }, 3000); // 每3秒变化一次 + + // 提供停止函数 + stopElevatorMock = () => { + if (elevatorMockTimer) { + clearInterval(elevatorMockTimer); + elevatorMockTimer = undefined; + console.log('[开发环境] 停止电梯状态模拟数据'); + } + }; + } }); @@ -550,6 +612,12 @@ onUnmounted(() => { doorMockTimer = undefined; } + // 清理电梯模拟数据定时器 + if (elevatorMockTimer) { + clearInterval(elevatorMockTimer); + elevatorMockTimer = undefined; + } + // 移除EditorService事件监听器 if (editor.value) { (editor.value as any).off('customContextMenu', (event: Record) => { diff --git a/src/pages/scene-editor.vue b/src/pages/scene-editor.vue index 51b6775..e87ac9b 100644 --- a/src/pages/scene-editor.vue +++ b/src/pages/scene-editor.vue @@ -1,6 +1,7 @@