瀏覽代碼

fix afc 电扶梯 台数 演示调整

zhanghaijun 2 年之前
父節點
當前提交
eefab9f1e3

+ 8 - 8
train-web/src/api/device.ts

@@ -1,26 +1,26 @@
 import request from "@/api/http";
-import {AxiosPromise} from 'axios';
-import {DeviceItem} from '@/types/device'
+import { AxiosPromise } from 'axios';
+import { DeviceItem } from '@/types/device'
 
 export function deviceAll(): AxiosPromise<Array<DeviceItem>> {
-  return request({url: '/device/all', method: 'get'})
+  return request({ url: '/device/all', method: 'get' })
 }
 
 export function addDevice(data: DeviceItem): AxiosPromise<any> {
-  return request({url: '/device/add', method: 'post', data})
+  return request({ url: '/device/add', method: 'post', data })
 }
 
 // 态势的数据
-export function situationDevice(): AxiosPromise<any> {
-  return request({url: '/device/situation/devices', method: 'get'})
+export function situationDevice(): AxiosPromise<Array<DeviceItem>> {
+  return request({ url: '/device/situation/devices', method: 'get' })
 }
 
 // 客流进站速度控制
 export function situationClientControl(speed: number): AxiosPromise<any> {
-  return request({url: '/device/situation/client/' + speed, method: 'get'})
+  return request({ url: '/device/situation/client/' + speed, method: 'get' })
 }
 
 // 水灾强度控制
 export function situationWaterControl(isOpen: boolean, strength: number): AxiosPromise<any> {
-  return request({url: '/device/situation/water/' + isOpen + '/' + strength, method: 'get'})
+  return request({ url: '/device/situation/water/' + isOpen + '/' + strength, method: 'get' })
 }

+ 47 - 8
train-web/src/components/Device.vue

@@ -1,27 +1,66 @@
 <template>
   <div class="box" :style="{ backgroundImage: `url(${imgUrl})` }">
     <slot>
-      <div class="device" v-for="(item, index) in devices" :key="index" :style="item.style">
-        <span>{{ item.name }}</span>
-        <el-tooltip :content="item.statusTitle" placement="bottom">
-          <icon-svg :icon-class="item.icon" :size="item.size + 'px'" :color="item.statusColor || '#000'" />
+      <div class="device" v-for="(item, index) in deviceList" :key="index" :style="item.style">
+        <el-tooltip placement="bottom">
+          <div>
+            <icon-svg :icon-class="item.icon" :size="item.size + 'px'" :color="getDeviceColor(item.device)" />
+          </div>
+          <template #content>
+            <div>{{ '标识 :' + item.id }}</div>
+            <div>{{ '编码 :' + item.device?.code }}</div>
+            <div>{{ '状态 :' + getDeviceStatusTitle(item.device) }}</div>
+          </template>
         </el-tooltip>
       </div>
     </slot>
   </div>
 </template>
 <script setup lang="ts">
-
-import { DeviceIcon } from "@/types/device";
+import { StoreDevices } from '@/store/modules/devices.ts'
+import { DeviceIcon, DeviceItem, deviceTypeArray } from "@/types/device";
 
 interface PropsType {
   imgUrl: string,
   devices: DeviceIcon[],
 }
-withDefaults(defineProps<PropsType>(), {
+const pops = withDefaults(defineProps<PropsType>(), {
   imgUrl: '',
   devices: () => [],
 });
+
+// 设备集合
+const deviceList: Ref<DeviceIcon[]> = computed(() => {
+  const reslut: DeviceIcon[] = [];
+  const deviceList: DeviceItem[] = StoreDevices().getDeviceArray;
+  for (let i = 0; i < pops.devices.length; i++) {
+    const deviceItem: DeviceIcon = pops.devices[i];
+    const device = deviceList.find(item => item?.id == deviceItem.id);
+    reslut.push({ ...deviceItem, ...{ device } })
+  }
+  return reslut;
+});
+// 获取设备颜色
+const getDeviceColor = (device: DeviceItem | undefined): string => {
+  if (!device) {
+    return "#000";
+  }
+  const deviceType = deviceTypeArray.find(item => item.command == device.command);
+  const statusOptions = deviceType?.statusOptions || [];
+  const status = statusOptions.find(item => item.key == device.status);
+  return status?.color || (statusOptions.length > 0 ? statusOptions[0].color : "#000");
+}
+// 获取设备状态
+const getDeviceStatusTitle = (device: DeviceItem | undefined): string => {
+  if (!device) {
+    return "无效";
+  }
+  const deviceType = deviceTypeArray.find(item => item.command == device.command);
+  const statusOptions = deviceType?.statusOptions || [];
+  const status = statusOptions.find(item => item.key == device.status);
+  return status?.value || (statusOptions.length > 0 ? statusOptions[0].value : "无效");
+}
+
 </script>
 <style scoped lang="scss">
 .box {
@@ -38,4 +77,4 @@ withDefaults(defineProps<PropsType>(), {
     position: absolute;
   }
 }
-</style>
+</style>

+ 19 - 40
train-web/src/pages/device/DeviceAfc.vue

@@ -3,45 +3,24 @@
 </template>
 <script setup lang="ts">
 import imageUrl from '@/assets/images/backage-afc.png'
-import { DeviceIcon, DeviceItem, AFC_GATE_MACHINE, AFC_TICKETING_AUTO } from "@/types/device";
-import { StoreDevices } from '@/store/modules/devices.ts'
+import { DeviceIcon } from "@/types/device";
+
 const devices = reactive<DeviceIcon[]>([
-  { icon: "客服中心", name: "", size: 30, statusColor: "#000", style: "left: 216px;top: 276px;" },
-  { icon: "客服中心", name: "", size: 30, statusColor: "#000", style: "left: 216px;top: 310px;" },
-  { icon: "客服中心", name: "", size: 30, statusColor: "#000", style: "left: 1056px;top: 280px;" },
-  { icon: "客服中心", name: "", size: 30, statusColor: "#000", style: "left: 1056px;top: 316px;" },
-  { command: AFC_TICKETING_AUTO, icon: "售票机", code: "TVM0201", name: "TVM0201", size: 30, statusColor: "#40BE00", style: "left: 50px;top: 220px;display:flex;flex-direction:column-reverse;" },
-  { command: AFC_TICKETING_AUTO, icon: "售票机", code: "TVM0202", name: "TVM0202", size: 30, statusColor: "#40BE00", style: "left: 50px;top: 280px;display:flex;flex-direction:column-reverse;" },
-  { command: AFC_TICKETING_AUTO, icon: "售票机", code: "TVM0203", name: "TVM0203", size: 30, statusColor: "#40BE00", style: "right: 80px;top: 220px;display:flex;flex-direction:column-reverse;" },
-  { command: AFC_TICKETING_AUTO, icon: "售票机", code: "TVM0204", name: "TVM0204", size: 30, statusColor: "#40BE00", style: "right: 80px;top: 280px;display:flex;flex-direction:column-reverse;" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0201", size: 30, statusColor: "#00FF00", style: "left: 476px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0202", size: 30, statusColor: "#00FF00", style: "left: 504px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0203", size: 30, statusColor: "#00FF00", style: "left: 533px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0204", size: 30, statusColor: "#00FF00", style: "left: 562px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0208", size: 30, statusColor: "#00FF00", style: "left: 710px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0207", size: 30, statusColor: "#00FF00", style: "left: 740px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0206", size: 30, statusColor: "#00FF00", style: "left: 770px;top:362px" },
-  { command: AFC_GATE_MACHINE, icon: "闸机", code: "AGM0205", size: 30, statusColor: "#00FF00", style: "left: 798px;top:362px" },
+  { id: 133005, icon: "客服中心", size: 30, style: "left: 216px;top: 276px;" },
+  { id: 133006, icon: "客服中心", size: 30, style: "left: 216px;top: 310px;" },
+  { id: 133007, icon: "客服中心", size: 30, style: "left: 1056px;top: 280px;" },
+  { id: 133008, icon: "客服中心", size: 30, style: "left: 1056px;top: 316px;" },
+  { id: 132005, icon: "售票机", size: 30, style: "left: 50px;top: 220px;" },
+  { id: 132006, icon: "售票机", size: 30, style: "left: 50px;top: 280px;" },
+  { id: 132007, icon: "售票机", size: 30, style: "right: 80px;top: 220px;" },
+  { id: 132008, icon: "售票机", size: 30, style: "right: 80px;top: 280px;" },
+  { id: 131009, icon: "闸机", size: 30, style: "left: 476px;top:362px" },
+  { id: 131010, icon: "闸机", size: 30, style: "left: 504px;top:362px" },
+  { id: 131011, icon: "闸机", size: 30, style: "left: 533px;top:362px" },
+  { id: 131012, icon: "闸机", size: 30, style: "left: 562px;top:362px" },
+  { id: 131013, icon: "闸机", size: 30, style: "left: 710px;top:362px" },
+  { id: 131014, icon: "闸机", size: 30, style: "left: 740px;top:362px" },
+  { id: 131015, icon: "闸机", size: 30, style: "left: 770px;top:362px" },
+  { id: 131016, icon: "闸机", size: 30, style: "left: 798px;top:362px" },
 ]);
-
-const getDevice = function () {
-  const deviceList: DeviceItem[] = StoreDevices().getDeviceArray;
-  for (let i = 0; i < devices.length; i++) {
-    const deviceItem = devices[i];
-    const matchedDevice = deviceList.find(item => item.code === deviceItem.code);
-    const statusOptions = deviceItem.command?.statusOptions || [];
-    if (matchedDevice && statusOptions) {
-      const status = statusOptions.find(option => option.key == matchedDevice.status);
-      if (status) {
-        deviceItem.statusColor = status?.color || statusOptions[0].color || '#000';
-        deviceItem.statusTitle = status?.value || statusOptions[0].value || '';
-        continue;
-      }
-    }
-    deviceItem.statusColor = statusOptions[0]?.color || '#000';
-    deviceItem.statusTitle = statusOptions[0]?.value || '';
-  }
-}
-onMounted(getDevice);
-watch(() => StoreDevices().getDeviceArray, () => { getDevice(); })
-</script>
+</script>

+ 9 - 31
train-web/src/pages/device/DeviceElevator.vue

@@ -3,37 +3,15 @@
 </template>
 <script setup lang="ts">
 import imageUrl from '@/assets/images/backage-elevator.png'
-import { DeviceIcon, DeviceItem, ELEVATOR_HAND_COMMAND } from "@/types/device";
-import { StoreDevices } from '@/store/modules/devices.ts'
+import { DeviceIcon } from "@/types/device";
 
 const devices = reactive<DeviceIcon[]>([
-  { command: ELEVATOR_HAND_COMMAND, icon: "电梯", size: 90, code: "DT-0201", statusColor: "#000", style: "left: 622px;top: 400px;" },
-  { command: ELEVATOR_HAND_COMMAND, icon: "电扶梯左", size: 90, code: "FT-02A1", statusColor: "#000", style: "left: 920px;top: 0px;" },
-  { command: ELEVATOR_HAND_COMMAND, icon: "电扶梯左", size: 90, code: "FT-02B1", statusColor: "#000", style: "left: 830px;top: 38px;" },
-  { command: ELEVATOR_HAND_COMMAND, icon: "电扶梯左", size: 120, code: "FT-0201", statusColor: "#000", style: "left: 122px;top: 260px;" },
-  { command: ELEVATOR_HAND_COMMAND, icon: "电扶梯右", size: 120, code: "FT-0202", statusColor: "#000", style: "left: 1160px;top: 260px;" },
-  { command: ELEVATOR_HAND_COMMAND, icon: "电扶梯右", size: 100, code: "FT-0203", statusColor: "#000", style: "left: 500px;top: 390px;" },
-  { command: ELEVATOR_HAND_COMMAND, icon: "电扶梯左", size: 100, code: "FT-0204", statusColor: "#000", style: "left: 720px;top: 390px;" },
+  { id: 134002, icon: "电梯", size: 90, style: "left: 622px;top: 400px;" },
+  { id: 135007, icon: "电扶梯左", size: 90, style: "left: 920px;top: 0px;" },
+  { id: 135008, icon: "电扶梯左", size: 90, style: "left: 830px;top: 38px;" },
+  { id: 135009, icon: "电扶梯左", size: 120, style: "left: 122px;top: 260px;" },
+  { id: 135010, icon: "电扶梯右", size: 120, style: "left: 1160px;top: 260px;" },
+  { id: 135011, icon: "电扶梯右", size: 100, style: "left: 500px;top: 390px;" },
+  { id: 135012, icon: "电扶梯左", size: 100, style: "left: 720px;top: 390px;" },
 ]);
-
-const getDevice = async function () {
-  const deviceList: DeviceItem[] = StoreDevices().getDeviceArray;
-  for (let i = 0; i < devices.length; i++) {
-    const deviceItem = devices[i];
-    const matchedDevice = deviceList.find(item => item.code === deviceItem.code);
-    const statusOptions = deviceItem.command?.statusOptions || [];
-    if (matchedDevice && statusOptions) {
-      const status = statusOptions.find(option => option.key == matchedDevice.status);
-      if (status) {
-        deviceItem.statusColor = status?.color || statusOptions[0].color || '#000';
-        deviceItem.statusTitle = status?.value || statusOptions[0].value || '';
-        continue;
-      }
-    }
-    deviceItem.statusColor = statusOptions[0].color || '#000';
-    deviceItem.statusTitle = statusOptions[0].value || '';
-  }
-}
-onMounted(getDevice);
-watch(() => StoreDevices().getDeviceArray, () => { getDevice(); })
-</script>
+</script>

+ 12 - 10
train-web/src/pages/device/DeviceTestItem.vue

@@ -51,9 +51,9 @@
 </template>
 
 <script lang="ts" setup>
-import {DeviceItem, DeviceType} from "@/types/device";
-import {deviceAll, addDevice} from "@/api/device";
-import {useStoreSocket} from "@/store/socket";
+import { DeviceItem, DeviceType } from "@/types/device";
+import { deviceAll, addDevice } from "@/api/device";
+import { useStoreSocket } from "@/store/socket";
 
 // 状态选择
 const pops = withDefaults(defineProps<{ deviceType: DeviceType }>(), {});
@@ -63,7 +63,7 @@ const addData = async () => {
   console.log(formData);
   const result: any = await addDevice(formData);
   if (result?.code == 200) {
-    ElNotification({title: '系统通知', message: '添加设备成功!', type: 'success'})
+    ElNotification({ title: '系统通知', message: '添加设备成功!', type: 'success' })
   }
   loadDeviceData();
 }
@@ -73,10 +73,12 @@ const formData = reactive<DeviceItem>({
   status: '0',
   jsonStr: '',
   stationId: 104002,
+  isNew: false,
+  message: ''
 });
 const formRules = reactive({
   code: [
-    {required: true, message: '请输入标识编码', trigger: 'blur'},
+    { required: true, message: '请输入标识编码', trigger: 'blur' },
   ],
   jsonStr: [
     {
@@ -111,21 +113,21 @@ const saveDeviceSatus = function (item: DeviceItem, notice = true) {
   const data: any = {};
   data[pops.deviceType.keyName] = item.code;
   data[pops.deviceType.keyStatus] = item.status;
-  const message = JSON.stringify({"cmd": pops.deviceType.command, "data": data});
+  const message = JSON.stringify({ "cmd": pops.deviceType.command, "data": data });
   console.log("发送消息", message);
   socketClient.sendMessage(message);
-  notice && ElNotification({title: '系统通知', message: '设备(' + item.code + ')状态更新成功!', type: 'success'})
+  notice && ElNotification({ title: '系统通知', message: '设备(' + item.code + ')状态更新成功!', type: 'success' })
 }
 // 保存当前全部设备的状态
 const saveAllDeviceSatus = function () {
   if (deviceList.value.length === 0) {
-    ElNotification({title: '系统通知', message: '当前没有设备数据!', type: 'error'});
+    ElNotification({ title: '系统通知', message: '当前没有设备数据!', type: 'error' });
     return;
   }
   for (let i = 0; i < deviceList.value.length; i++) {
     saveDeviceSatus(deviceList.value[i], false);
   }
-  ElNotification({title: '系统通知', message: '状态更新成功!', type: 'success'});
+  ElNotification({ title: '系统通知', message: '状态更新成功!', type: 'success' });
   return;
 }
 onMounted(loadDeviceData);
@@ -145,4 +147,4 @@ onMounted(loadDeviceData);
 .device-form .el-select {
   --el-select-width: 120px;
 }
-</style>
+</style>

+ 125 - 82
train-web/src/pages/situation/index.vue

@@ -7,17 +7,18 @@
       <el-row :gutter="20">
         <el-col :span="6">{{ '态势级别' }}</el-col>
         <el-col :span="18">
-          <div :class="{[waterLevel]:true,'level-box':true}" v-if="clientLevel=='low'">低级别:影响较小</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else-if="clientLevel=='medium'">中级别:影响适中</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else-if="clientLevel=='high'">高级别:影响较大</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else-if="clientLevel=='critical'">紧急级别:影响非常严重</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else></div>
+          <div :class="{ [clientLevel]: true, 'level-box': true }" v-if="clientLevel == 'low'">低级别:影响较小</div>
+          <div :class="{ [clientLevel]: true, 'level-box': true }" v-else-if="clientLevel == 'medium'">中级别:影响适中</div>
+          <div :class="{ [clientLevel]: true, 'level-box': true }" v-else-if="clientLevel == 'high'">高级别:影响较大</div>
+          <div :class="{ [clientLevel]: true, 'level-box': true }" v-else-if="clientLevel == 'critical'">紧急级别:影响非常严重
+          </div>
+          <div :class="{ [clientLevel]: true, 'level-box': true }" v-else></div>
         </el-col>
       </el-row>
       <el-row :gutter="20">
         <el-col :span="6">{{ '客流速度' }}</el-col>
         <el-col :span="18">
-          <el-slider v-model="clientSpeed" @change="clientControl"/>
+          <el-slider v-model="clientSpeed" @change="clientControl" />
         </el-col>
       </el-row>
       <el-row :gutter="20">
@@ -26,121 +27,165 @@
       <el-row :gutter="20">
         <el-col :span="6">{{ '态势级别' }}</el-col>
         <el-col :span="18">
-          <div :class="{[waterLevel]:true,'level-box':true}" v-if="waterLevel=='low'">低级别:影响较小</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else-if="waterLevel=='medium'">中级别:影响适中</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else-if="waterLevel=='high'">高级别:影响较大</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else-if="waterLevel=='critical'">紧急级别:影响非常严重</div>
-          <div :class="{[waterLevel]:true,'level-box':true}" v-else></div>
+          <div :class="{ [waterLevel]: true, 'level-box': true }" v-if="waterLevel == 'low'">低级别:影响较小</div>
+          <div :class="{ [waterLevel]: true, 'level-box': true }" v-else-if="waterLevel == 'medium'">中级别:影响适中</div>
+          <div :class="{ [waterLevel]: true, 'level-box': true }" v-else-if="waterLevel == 'high'">高级别:影响较大</div>
+          <div :class="{ [waterLevel]: true, 'level-box': true }" v-else-if="waterLevel == 'critical'">紧急级别:影响非常严重</div>
+          <div :class="{ [waterLevel]: true, 'level-box': true }" v-else></div>
         </el-col>
       </el-row>
       <el-row :gutter="20">
         <el-col :span="6">{{ '水灾控制' }}</el-col>
         <el-col :span="18">
-          <el-slider v-model="waterSpeed" :format-tooltip="(val: number) => val / 100" @change="waterControl"/>
+          <el-slider v-model="waterSpeed" :format-tooltip="(val: number) => val / 100" @change="waterControl" />
         </el-col>
       </el-row>
     </div>
-    <template v-for="item in deviceData">
-      <el-popover placement="top-start" :title="item.postion" :width="80" :visible=true>
-        <template #reference>
-          <div class="point-box" :style="{ top: item.top, left: item.left }">{{ item.postion }}</div>
-        </template>
-        <div>
-          <div v-if="item.command == 20501">
-            <span style="text-align: right;display: inline-block;min-width: 30px;margin-right: 6px;">{{ '大客流: ' }}</span>
-            <span>{{ item.value.toFixed(4) }}</span><span>{{ '人/m2' }}</span>
-          </div>
-          <div v-if="item.command == 20601">
-            <span style="text-align: right;display: inline-block;min-width: 30px;margin-right: 6px;">{{ '水位: ' }}</span>
-            <span>{{ item.value.toFixed(2) }}</span><span>{{ 'm' }}</span>
-          </div>
-        </div>
-      </el-popover>
-    </template>
+    <div class="point-box" v-for="(item, index) in levelArray" :key="index" :style="item.style">
+      <div>
+        <div class="point-name" :value="item.value">{{ item.postion }}</div>
+      </div>
+      <div class="point-level-box">
+        <div>{{ '位置 :' + item.postion }}</div>
+        <div v-if="item.command == 20501">{{ '客流 :' + item.value.toFixed(2) + '人/m2' }}</div>
+        <div v-if="item.command == 20601">{{ '水位 :' + item.value.toFixed(2) + 'm' }}</div>
+      </div>
+    </div>
   </device>
 </template>
 <script lang="ts" setup>
 import imageUrl from '@/assets/images/backage-situation.png'
-import {ElPopover} from 'element-plus';
-import {situationClientControl, situationDevice, situationWaterControl} from '@/api/device.ts'
-import {Arrayable} from "@vueuse/core";
+import { situationClientControl, situationDevice, situationWaterControl } from '@/api/device.ts'
+import { Arrayable } from "@vueuse/core";
+import { DeviceItem } from "@/types/device";
+import { useStoreSocket } from "@/store/socket";
+import { StoreSituation } from "@/store/modules/situation";
 
+const storeSituation = new StoreSituation();
 // 客流进站速度
-const clientSpeed = ref(0);
+const clientSpeed = ref(storeSituation.clientSpeed);
 const clientLevel = ref<'low' | 'medium' | 'high' | 'critical'>('low');
 // 水流速度
-const waterSpeed = ref(0);
+const waterSpeed = ref(storeSituation.waterSpeed);
 const waterLevel = ref<'low' | 'medium' | 'high' | 'critical'>('low');
 
-// 态势数据
-const deviceData = ref<{ command: number, postion: string, value: number, top: string, left: string }[]>([]);
 // 定时器
 let intervalId: number | undefined = undefined;
 onMounted(function () {
-  intervalId = setInterval(getDevice, 1000) as unknown as number;
+  intervalId = setInterval(loadData, 1000) as unknown as number;
 })
 onBeforeUnmount(() => {
   if (intervalId) {
     clearInterval(intervalId);
   }
 });
-const getDevice = function () {
-  situationDevice().then(({data}) => {
-    let resultArray: { command: number, postion: string, value: number, top: string, left: string }[] = [];
-    for (let i = 0; i < data.length; i++) {
-      const device: any = data[i];
-      resultArray = [...resultArray, ...((JSON.parse(device.message) || []).map((item: any) => {
-        switch (item.postion.trim()) {
-          case "站厅":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '18vh', left: '110vh'}
-          case "站台":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '62vh', left: '110vh'}
-          case "1出口":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '28vh', left: '10vh'}
-          case "2出口":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '38vh', left: '10vh'}
-          case "站厅A端":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '8vh', left: '10vh'}
-          case "站厅B端":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '18vh', left: '10vh'}
-          case "站台A端":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '18vh', left: '20vh'}
-          case "站台B端":
-            return {...item, command: device.command, postion: item.postion.trim(), top: '18vh', left: '20vh'}
-          default:
-            return undefined;
-        }
-      })).filter((item: any) => item)]
-    }
-    console.log(JSON.stringify(resultArray));
-    deviceData.value = resultArray;
+// 获取原始数据
+const deviceArray = ref<DeviceItem[]>();
+const loadData = async () => {
+  const { data } = await situationDevice();
+  deviceArray.value = data;
+}
+// 水位数据
+interface LevelItem {
+  command: number;
+  postion: string;
+  value: number;
+  style?: string;
+}
+const levelArray: Ref<LevelItem[]> = computed(() => {
+  const list = deviceArray.value;
+  if (!list) {
+    return [];
+  }
+  let dataList: any[] = [];
+  for (let i = 0; i < list.length; i++) {
+    const device = list[i];
+    const message: { postion: string, value: number }[] = (JSON.parse(device.message) || []);
+    dataList = dataList.concat(message.map((item) => {
+      return {
+        command: device.command,
+        postion: item.postion,
+        value: item.value,
+      }
+    }));
+  }
+  return [
+    { command: 20501, postion: "站厅", value: 0.0, style: "left: 730px;top: 120px;" },
+    { command: 20501, postion: "站台", value: 0.0, style: "left: 730px;top: 420px;" },
+    { command: 20601, postion: "1出口", value: 0.0, style: "left: 1150px;top: 120px;" },
+    { command: 20601, postion: "2出口", value: 0.0, style: "left: 106px;top: 276px;" },
+    { command: 20601, postion: "站厅A端", value: 0.0, style: "left: 460px;top: 120px;" },
+    { command: 20601, postion: "站厅B端", value: 0.0, style: "left: 1000px;top: 180px;" },
+    { command: 20601, postion: "站台A端", value: 0.0, style: "left: 366px;top: 320px;" },
+    { command: 20601, postion: "站台B端", value: 0.0, style: "left: 1100px;top: 520px;" },
+  ].map((item) => {
+    return { ...item, value: dataList.find(device => device.command == item.command && device.postion == item.postion)?.value || 0.0 };
   });
-};
+});
+
 const clientControl = (value: Arrayable<number>): void => {
   const actualValue = Array.isArray(value) ? value[0] : value;
+  storeSituation.setClientSpeed(actualValue);
   situationClientControl(actualValue).then(() => {
-    ElNotification({title: '系统通知', message: '客流控制成功', type: 'success'})
+    ElNotification({ title: '系统通知', message: '客流控制成功', type: 'success' })
   });
 }
+const socketClient = useStoreSocket();
 const waterControl = function (value: Arrayable<number>): void {
-  const actualValue = Array.isArray(value) ? value[0] : value; // 获取实际的数值
+  const actualValue = Array.isArray(value) ? value[0] : value;
+  storeSituation.setWaterSpeed(actualValue);
   situationWaterControl(actualValue != 0, actualValue / 100).then(() => {
-    ElNotification({title: '系统通知', message: actualValue != 0 ? '水灾控制成功' : '关闭水灾成功', type: 'success'})
+    ElNotification({ title: '系统通知', message: actualValue != 0 ? '水灾控制成功' : '关闭水灾成功', type: 'success' })
   });
+  if (actualValue == 0) {
+    setTimeout(() => {
+      socketClient.sendMessage(JSON.stringify({
+        "cmd": 20601, "data": { "kvp": [{ "postion": "1出口", "value": 0 }] }
+      }));
+    }, 500);
+  }
 };
 
 </script>
 <style lang="scss" scoped>
 .point-box {
-  min-width: 6vh;
-  height: 3vh;
-  text-align: center;
-  padding: 2px 3px;
-  background-color: blue;
-  border-radius: 1vh;
-  color: white;
   position: absolute;
-  cursor: pointer;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+
+  .point-name {
+    min-width: 6vh;
+    height: 3vh;
+    text-align: center;
+    padding: 2px 3px;
+    background-color: blue;
+    border-radius: 1vh;
+    color: white;
+    cursor: pointer;
+  }
+
+  .point-level-box {
+    width: 160px;
+    height: 60px;
+    margin-top: 10px;
+    background-color: #eee;
+    padding: 8px 12px;
+    border-radius: 8px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    border: 1px solid rgb(136, 0, 255);
+
+    &::after {
+      content: '';
+      width: 0;
+      height: 0;
+      border: 12px solid;
+      position: absolute;
+      top: 16px;
+      left: 70px;
+      border-color: transparent transparent #aeb2e3;
+    }
+  }
 }
 
 .situation-box {
@@ -174,6 +219,4 @@ const waterControl = function (value: Arrayable<number>): void {
     background-color: #c0392b;
   }
 }
-
-
-</style>
+</style 0.0, style>

+ 1 - 1
train-web/src/store/modules/situation.ts

@@ -1,4 +1,4 @@
-import {defineStore} from "pinia";
+import { defineStore } from "pinia";
 
 export const StoreSituation = defineStore("situation", {
   state: (): { clientSpeed: number, waterSpeed: number } => {

+ 2 - 2
train-web/src/store/socket.ts

@@ -1,7 +1,7 @@
 import { defineStore } from "pinia";
 import SocketClient from "@/types/WebSocketClient";
 import { CommandEnum, RouteItem, TrainItem } from '@/types/train-travel'
-import { deviceCammandList, PLATFORM_DOOR_LOCK } from '@/types/device';
+import { deviceCommandList, PLATFORM_DOOR_LOCK } from '@/types/device';
 import { StoreDevices } from '@/store/modules/devices.ts';
 import { StoreDoor } from '@/store/modules/door.ts'
 
@@ -53,7 +53,7 @@ export const useStoreSocket = defineStore("websocket", {
               break;
             default:
               // 通用的设备控制
-              if (deviceCammandList.indexOf(result.cmd) !== -1) {
+              if (deviceCommandList.indexOf(result.cmd) !== -1) {
                 StoreDevices().loadDeviceAll();
               } else {
                 console.log("未知的消息类型:" + result.cmd + ", message: " + JSON.stringify(result));

+ 1 - 0
train-web/src/types/components.d.ts

@@ -20,6 +20,7 @@ declare module 'vue' {
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
+    ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadio: typeof import('element-plus/es')['ElRadio']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']

+ 7 - 8
train-web/src/types/device.ts

@@ -5,6 +5,8 @@ export interface DeviceItem {
   status: string; // 状态
   jsonStr: string; // 其他信息
   stationId: number; // 所属站台
+  isNew: boolean;// 是否是新建的
+  message: string;
 }
 
 export interface StatusItem {
@@ -346,18 +348,15 @@ export const deviceTypeArray: DeviceType[] = [
   ELEVATOR_HAND_COMMAND,
 ];
 
-export const deviceCammandList = deviceTypeArray.map((item) => item.command);
+export const deviceCommandList = deviceTypeArray.map((item) => item.command);
 
 export const deviceTypeSocket = deviceTypeArray.filter((item) => item.command.toString().startsWith("2"));
 
 
 export interface DeviceIcon {
-  command?: DeviceType;
+  id?: number;
   icon: string;
-  code?: string; //设备标识
-  name?: string; // 设备名称
-  size: number;
-  statusColor: string;
-  statusTitle?: string;
-  style: string;
+  size: number;     // 图片大小
+  style: string;    // 自定义样式
+  device?: DeviceItem, // 后台数据
 }