|
|
@@ -12,7 +12,7 @@
|
|
|
<div class="left-panel">
|
|
|
<!-- 风门数据列表 -->
|
|
|
<div class="door-list">
|
|
|
- <div class="door-card" v-for="(item, index) in props.data" :key="index">
|
|
|
+ <div class="door-card" v-for="(item, index) in displayData" :key="index">
|
|
|
<div class="door-position">
|
|
|
<div class="position"></div>
|
|
|
<div class="door-name">
|
|
|
@@ -56,7 +56,12 @@
|
|
|
|
|
|
<div class="model-placeholder">
|
|
|
<!-- <img :src="gatePng" alt="风门" class="model-img" /> -->
|
|
|
- <pidaihangSVG :ref="(el) => setChildRef(el, index)" :identify="String(index)" />
|
|
|
+ <template v-if="item.readData?.MBOpen?.value">
|
|
|
+ <pidaihangSVG :ref="(el) => setChildRef(el, index)" :identify="String(index)" />
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <fireDoorSVG :ref="(el) => setChildRef(el, index)" :identify="String(index)" />
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -74,9 +79,10 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { ref, onMounted, watch, inject } from 'vue';
|
|
|
+ import { ref, computed, onMounted, watch, inject } from 'vue';
|
|
|
import { getFormattedText } from '../../hooks/helper';
|
|
|
import pidaihangSVG from '/@/views/vent/monitorManager/fireDoorMonitor/components/pidaihangSVG.vue';
|
|
|
+ import fireDoorSVG from '/@/views/vent/monitorManager/fireDoorMonitor/components/fireDoorSVG.vue';
|
|
|
import HandleModal from '/@/views/vent/monitorManager/gateMonitor/modal.vue';
|
|
|
import { message } from 'ant-design-vue';
|
|
|
import { doorControlApi } from '/@/views/vent/home/configurable/firedoor/configurable.api.fireDoorMonitor';
|
|
|
@@ -110,6 +116,36 @@
|
|
|
const paramcode = ref(''); // 模态框操作代码
|
|
|
const childRefs = ref<(InstanceType<typeof pidaihangSVG> | null)[]>([]);
|
|
|
const selectData = ref<any>({});
|
|
|
+
|
|
|
+ // 模拟数据开关 - 设为 true 启用模拟数据
|
|
|
+ const useMockData = ref(false);
|
|
|
+ // 模拟数据
|
|
|
+ const mockData = ref([
|
|
|
+ {
|
|
|
+ devicePos: '防火门2号(无皮带)',
|
|
|
+ deviceID: 'FD002',
|
|
|
+ systemDeviceId: 'SYS002',
|
|
|
+ deviceType: 'fireDoor',
|
|
|
+ readData: {
|
|
|
+ frontGateOpen: { value: '0' },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // devicePos: '防火门1号(有皮带)',
|
|
|
+ // deviceID: 'FD001',
|
|
|
+ // systemDeviceId: 'SYS001',
|
|
|
+ // deviceType: 'fireDoor',
|
|
|
+ // readData: {
|
|
|
+ // frontGateOpen: { value: '0' },
|
|
|
+ // MBOpen: { value: '0' },
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 实际显示的数据
|
|
|
+ const displayData = computed(() => {
|
|
|
+ return useMockData.value ? mockData.value : props.data;
|
|
|
+ });
|
|
|
const setChildRef = (el, index) => {
|
|
|
if (el) {
|
|
|
childRefs.value[index] = el;
|
|
|
@@ -120,21 +156,31 @@
|
|
|
function executeAnimation(targetIndex: number, code: string) {
|
|
|
if (targetIndex === -1) return;
|
|
|
const isOpen = code.includes('Open');
|
|
|
+ const targetItem = displayData.value[targetIndex];
|
|
|
+ if (!targetItem) return;
|
|
|
+ const hasBelt = targetItem.readData?.MBOpen?.value !== undefined;
|
|
|
|
|
|
// 2D SVG 动画
|
|
|
- if (childRefs.value[targetIndex]) {
|
|
|
- if (code === 'AllOpen_S' || code === 'AllClose_S') {
|
|
|
- childRefs.value[targetIndex].animate(isOpen, isOpen, isOpen);
|
|
|
- } else if (code === 'frontGateOpen_S' || code === 'frontGateClose_S') {
|
|
|
- childRefs.value[targetIndex].animateFireDoor(isOpen);
|
|
|
- } else if (code === 'MBOpen_S' || code === 'MBClose_S') {
|
|
|
- childRefs.value[targetIndex].animateBeltDoor(isOpen);
|
|
|
+ const svgRef = childRefs.value[targetIndex];
|
|
|
+ if (svgRef) {
|
|
|
+ if (hasBelt) {
|
|
|
+ // pidaihangSVG 动画逻辑
|
|
|
+ if (code === 'AllOpen_S' || code === 'AllClose_S') {
|
|
|
+ svgRef.animate(isOpen, isOpen, isOpen);
|
|
|
+ } else if (code === 'frontGateOpen_S' || code === 'frontGateClose_S') {
|
|
|
+ svgRef.animateFireDoor(isOpen);
|
|
|
+ } else if (code === 'MBOpen_S' || code === 'MBClose_S') {
|
|
|
+ svgRef.animateBeltDoor(isOpen);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // fireDoorSVG 动画逻辑
|
|
|
+ svgRef.animate(isOpen, false, false);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 3D 动画:构造期望状态的门数据并触发
|
|
|
- if (props.data && Array.isArray(props.data)) {
|
|
|
- const doors = props.data.map((door: any, i: number) => {
|
|
|
+ if (displayData.value && Array.isArray(displayData.value)) {
|
|
|
+ const doors = displayData.value.map((door: any, i: number) => {
|
|
|
if (i === targetIndex && door.readData) {
|
|
|
const updated = {
|
|
|
...door,
|
|
|
@@ -143,7 +189,8 @@
|
|
|
if (code === 'AllOpen_S' || code === 'AllClose_S' || code === 'frontGateOpen_S' || code === 'frontGateClose_S') {
|
|
|
updated.readData.frontGateOpen = { ...updated.readData.frontGateOpen, value: isOpen ? '1' : '0' };
|
|
|
}
|
|
|
- if (code === 'AllOpen_S' || code === 'AllClose_S' || code === 'MBOpen_S' || code === 'MBClose_S') {
|
|
|
+ // 只有原数据有 MBOpen 时才更新
|
|
|
+ if (hasBelt && (code === 'AllOpen_S' || code === 'AllClose_S' || code === 'MBOpen_S' || code === 'MBClose_S')) {
|
|
|
updated.readData.MBOpen = { ...updated.readData.MBOpen, value: isOpen ? '1' : '0' };
|
|
|
}
|
|
|
return updated;
|
|
|
@@ -158,9 +205,16 @@
|
|
|
if (!selectData?.readData) return;
|
|
|
const frontOpen = selectData.readData?.frontGateOpen?.value === '1';
|
|
|
const beltOpen = selectData.readData?.MBOpen?.value === '1';
|
|
|
- if (childRefs.value[index]) {
|
|
|
- childRefs.value[index].animateFireDoor(frontOpen);
|
|
|
- childRefs.value[index].animateBeltDoor(beltOpen);
|
|
|
+ const svgRef = childRefs.value[index];
|
|
|
+ if (svgRef) {
|
|
|
+ if (selectData.readData?.MBOpen?.value) {
|
|
|
+ // pidaihangSVG 动画逻辑
|
|
|
+ svgRef.animateFireDoor(frontOpen);
|
|
|
+ svgRef.animateBeltDoor(beltOpen);
|
|
|
+ } else {
|
|
|
+ // fireDoorSVG 动画逻辑
|
|
|
+ svgRef.animate(frontOpen, false, false);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -178,6 +232,30 @@
|
|
|
}
|
|
|
|
|
|
function handleOK(passWord, handlerState, value?) {
|
|
|
+ if (useMockData.value) {
|
|
|
+ // 测试模式:跳过 API,直接执行动画
|
|
|
+ modalIsShow.value = false;
|
|
|
+ message.success('【测试模式】动画已触发');
|
|
|
+
|
|
|
+ // 更新模拟数据中的状态
|
|
|
+ const targetItem = displayData.value.find((item: any) => item.deviceID === selectData.value.deviceID);
|
|
|
+ if (targetItem?.readData) {
|
|
|
+ const isOpen = paramcode.value.includes('Open');
|
|
|
+ if (paramcode.value.includes('frontGate') || paramcode.value.includes('All')) {
|
|
|
+ targetItem.readData.frontGateOpen = { value: isOpen ? '1' : '0' };
|
|
|
+ }
|
|
|
+ if (paramcode.value.includes('MB') || paramcode.value.includes('All')) {
|
|
|
+ if (targetItem.readData.MBOpen) {
|
|
|
+ targetItem.readData.MBOpen = { value: isOpen ? '1' : '0' };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const targetIndex = displayData.value.findIndex((item: any) => item.deviceID === selectData.value.deviceID);
|
|
|
+ executeAnimation(targetIndex, paramcode.value);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
if (!passWord && !globalConfig?.simulatedPassword) {
|
|
|
message.warning('请输入密码');
|
|
|
return;
|
|
|
@@ -202,7 +280,7 @@
|
|
|
message.success('指令已下发成功!');
|
|
|
}
|
|
|
|
|
|
- const targetIndex = props.data.findIndex((item) => item.deviceID === selectData.value.deviceID);
|
|
|
+ const targetIndex = displayData.value.findIndex((item: any) => item.deviceID === selectData.value.deviceID);
|
|
|
executeAnimation(targetIndex, paramcode.value);
|
|
|
// 触发刷新事件
|
|
|
emit('refresh');
|
|
|
@@ -221,10 +299,10 @@
|
|
|
}
|
|
|
|
|
|
watch(
|
|
|
- () => props.data,
|
|
|
+ () => displayData.value,
|
|
|
(newData) => {
|
|
|
if (!newData || !newData.length) return;
|
|
|
- newData.forEach((item, index) => {
|
|
|
+ newData.forEach((item: any, index: number) => {
|
|
|
monitorAnimation(item, index);
|
|
|
});
|
|
|
},
|
|
|
@@ -467,6 +545,12 @@
|
|
|
top: -140%;
|
|
|
left: -110%;
|
|
|
}
|
|
|
+ .fire-door-svg {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 100% !important;
|
|
|
+ top: 0 !important;
|
|
|
+ left: 0 !important;
|
|
|
+ }
|
|
|
.model-img {
|
|
|
width: 100%;
|
|
|
display: flex;
|