Browse Source

大屏接口对接

cuiHe 1 year ago
parent
commit
4b1ade2eec

+ 6 - 0
.eslintrc.js

@@ -13,18 +13,22 @@
     "effectScope": true,
     "equipmentMaintainType": true,
     "equipmentType": true,
+    "filterTime": true,
+    "filterTimeY_M_D": true,
     "formatGears": true,
     "formatValue": true,
     "formatWeightLight": true,
     "getActivePinia": true,
     "getCurrentInstance": true,
     "getCurrentScope": true,
+    "getM_S": true,
     "h": true,
     "inject": true,
     "isProxy": true,
     "isReactive": true,
     "isReadonly": true,
     "isRef": true,
+    "isTrue": true,
     "mapActions": true,
     "mapGetters": true,
     "mapState": true,
@@ -46,7 +50,9 @@
     "onRenderTriggered": true,
     "onScopeDispose": true,
     "onServerPrefetch": true,
+    "onSubscribe": true,
     "onUnmounted": true,
+    "onUnsubscribe": true,
     "onUpdated": true,
     "provide": true,
     "reactive": true,

+ 30 - 0
package-lock.json

@@ -25,6 +25,7 @@
         "vue-cropperjs": "^5.0.0",
         "vue-router": "^4.1.3",
         "vue-schart": "^2.0.0",
+        "vue3-seamless-scroll": "^2.0.1",
         "wangeditor": "^4.7.15"
       },
       "devDependencies": {
@@ -4719,6 +4720,14 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/throttle-debounce": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
+      "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==",
+      "engines": {
+        "node": ">=12.22"
+      }
+    },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -5309,6 +5318,14 @@
         "typescript": "*"
       }
     },
+    "node_modules/vue3-seamless-scroll": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/vue3-seamless-scroll/-/vue3-seamless-scroll-2.0.1.tgz",
+      "integrity": "sha512-mI3BaDU3pjcPUhVSw3/xNKdfPBDABTi/OdZaZqKysx4cSdNfGRbVvGNDzzptBbJ5S7imv5T55l6x/SqgnxKreg==",
+      "dependencies": {
+        "throttle-debounce": "5.0.0"
+      }
+    },
     "node_modules/wangeditor": {
       "version": "4.7.15",
       "resolved": "https://registry.npmmirror.com/wangeditor/-/wangeditor-4.7.15.tgz",
@@ -8472,6 +8489,11 @@
       "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
       "dev": true
     },
+    "throttle-debounce": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
+      "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg=="
+    },
     "to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -8846,6 +8868,14 @@
         "@volar/vue-typescript": "0.38.9"
       }
     },
+    "vue3-seamless-scroll": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/vue3-seamless-scroll/-/vue3-seamless-scroll-2.0.1.tgz",
+      "integrity": "sha512-mI3BaDU3pjcPUhVSw3/xNKdfPBDABTi/OdZaZqKysx4cSdNfGRbVvGNDzzptBbJ5S7imv5T55l6x/SqgnxKreg==",
+      "requires": {
+        "throttle-debounce": "5.0.0"
+      }
+    },
     "wangeditor": {
       "version": "4.7.15",
       "resolved": "https://registry.npmmirror.com/wangeditor/-/wangeditor-4.7.15.tgz",

+ 3 - 1
package.json

@@ -25,7 +25,9 @@
     "vue-cropperjs": "^5.0.0",
     "vue-router": "^4.1.3",
     "vue-schart": "^2.0.0",
-    "wangeditor": "^4.7.15"
+    "vue3-seamless-scroll": "^2.0.1",
+    "wangeditor": "^4.7.15",
+    "moment": "^2.30.1"
   },
   "devDependencies": {
     "@types/node": "^18.11.9",

+ 4 - 0
src/api/bigScreen/index.ts

@@ -99,3 +99,7 @@ export const getDeviceAreaMapData = (params: any) => request.get('api/services/a
 
 // ----------------------------综合显示END------------------------------------
 
+
+export const getRealtime = (params: any) => request.get('api/services/app/SingleDeviceDashboard/GetRealtimeData', { params })
+
+export const getAlertRecordsByDevice = (params: any) => request.get('api/services/app/SingleDeviceDashboard/GetAlertRecordsByDevice', { params })

+ 3 - 3
src/components/base-equipment-state/index.vue

@@ -28,7 +28,7 @@
             </el-tooltip>
           </el-carousel-item>
         </el-carousel>
-        <div class="big_screen_display" @click.native.stop="bigScreen(row)">
+        <div class="big_screen_display"  @click.native.stop="bigScreen(row)">
           <img src="../../assets/img/device_list_screen_icon.png" />
           <div class="big_screen_text">大屏显示</div>
         </div>
@@ -53,8 +53,8 @@
     4: '报警'
   }
 
-  const bigScreen = (item: any) => {
-    router.push(`/big-screen/single?id=${item.id}`)
+  const bigScreen = async (item: any) => {
+    router.push(`/big-screen/single?id=${item.id}&code=${item.code}`)
   }
 </script>
 

+ 32 - 0
src/utils/dateUtil.ts

@@ -0,0 +1,32 @@
+import moment from "moment";
+/**
+ * 
+ * @param time 时间字符串
+ * @returns 
+ */
+export const filterTime = (time: any) => {
+    if (!time) {
+        return ''
+    }
+    return moment(new Date(time).getTime()).format('YYYY-MM-DD HH:mm:ss')
+}
+
+/**
+ * 
+ * @param time 时间字符串
+ * @returns 
+ */
+export const filterTimeY_M_D = (time: any) => {
+    if (!time) {
+        return ''
+    }
+    return moment(new Date(time).getTime()).format('YYYY-MM-DD')
+}
+
+/**
+ * 分秒
+ * @returns 
+ */
+export const getM_S = () => {
+    return moment(new Date().getTime()).format('mm:ss')
+}

+ 1 - 0
src/utils/hooks.ts

@@ -110,6 +110,7 @@ export const mqttMessageCallback = (callback: any) => {
  */
 export const useMqtt = () => {
   const userInfo = JSON.parse(localStorage.getItem('user') as string)
+  console.log(userInfo)
   const { userId, securityCode } = userInfo
   const { mqtt } = window as any
   const mqttOptions = {

+ 1 - 1
src/utils/request.ts

@@ -5,7 +5,7 @@ import qs from 'qs'
 import { recordValueTrim } from './tools'
 
 const service: AxiosInstance = axios.create({
-  timeout: 5000,
+  timeout: 40000,
   baseURL: 'https://apinew.hldcloud.cn'
 })
 // 请求拦截

+ 118 - 1
src/utils/tools.ts

@@ -1,4 +1,92 @@
-import { multiply, round } from 'lodash'
+import '../../public/mqtt/dist/mqtt.min'
+declare const window: any
+var _mqttMessageCallback: any = null
+
+/**
+ * mqtt订阅
+ * @param topics 主题['a','b']
+ * @param callback 消息回调
+ */
+export const onSubscribe = (topics: string[], callback: any) => {
+  console.log(topics)
+  _mqttMessageCallback = callback
+  if (window.client == null) {
+    useMqtt()
+  }
+  topics.forEach(topic => {
+    window.client?.subscribe(topic, () => { })
+  })
+  window.client?.on('message', (topic: string, payload: any) => {
+    if (_mqttMessageCallback != null) {
+      _mqttMessageCallback(topic, payload)
+    }
+  })
+}
+
+/**
+ * mqtt取消订阅
+ * @param topic 主题
+ */
+export const onUnsubscribe = (topic: string) => {
+  window.client?.unsubscribe(topic, () => {
+    _mqttMessageCallback = null
+  })
+}
+
+/**
+ * 实时数据
+ */
+export const useMqtt = () => {
+  const userInfo = JSON.parse(localStorage.getItem('gdyt_user') as string)
+  const { userId, securityCode } = userInfo
+  const { mqtt } = window as any
+  const mqttOptions = {
+    clean: true,
+    connectTimeout: 10000,
+    port: 80,
+    clientId: `2${Date.now()}`, //提取到配置文件
+    username: `${userId}`, //提取到配置文件
+    password: securityCode //提取到配置文件
+  }
+  console.log(mqttOptions)
+  if (window.client == null) {
+    //console.log('初始化mqtt')
+    window.client = mqtt.connect('ws://cloud-mqtt.gd-yt.cn/mqtt', mqttOptions)
+  }
+  window.client.on('connect', () => {
+    console.log('mqtt连接成功')
+  })
+
+  window.client.on('reconnect', () => {
+    console.log('mqtt正在重连')
+  })
+
+  window.client.on('disconnect', () => {
+    console.log('mqtt断开连接disconnect')
+  })
+
+  window.client.on('close', () => {
+    console.log('mqtt断开连接close')
+  })
+
+  window.client.on('error', (e: any) => {
+    console.log('mqtt无法连接error' + e.message)
+    if (e.code == 4) {
+      //用户名密码错误
+      window.client.end()
+      window.client = null
+      alert("该账号在多个设备上登录,为避免部分功能无法使用,请退出账号重新登录")
+    }
+  })
+
+}
+
+export function isTrue(e: any) {
+  if (e === true || e === 'true') {
+    return true
+  }
+  return false
+}
 
 /**
  * 清除对象中的字符串前后空格
@@ -39,6 +127,9 @@ export const recordValueTrim = (target: Record<string, any>) => {
 //格式化档位
 export function formatGears(gear: any) {
   let gears = gear.gears
+  if(gears == null){
+    gears = []
+  }
   if (gear.variableType == 1) {
     if (gears.length == 0) {
       return '零位'
@@ -76,6 +167,32 @@ export const formatValue = (value: any, translate: any) => {
 
 }
 
+//解析档位
+export function parseGear(gear: any, code: any, value: any) {
+  if (gear != null) {
+    //取出当前档位
+    let option = gear.options.find((f: any) => f.variableCode == code)
+    if (option != null) {
+      //当前档位
+      let currentGearName = option.displayName
+
+      if (value === true || value === 'true') {
+        //不存在添加(加档)
+        let g = gear.gears.find((f: any) => f == currentGearName)
+        if (g == null) {
+          gear.gears.push(currentGearName)
+        }
+      } else {
+        //存在删除(减档)
+        gear.gears = gear.gears.filter((f: any) => f != currentGearName)
+      }
+      return true
+    }
+    return false
+  }
+  return false
+}
+
 /**
  *
  * @param light 处理载荷 灯

+ 251 - 258
src/views/big-screen/single.vue

@@ -11,55 +11,42 @@
         <span style="margin-left: 45px;color: #C8DEFE;font-size: 18px;font-weight: normal;font-family: Alibaba-PuHuiTi-R;">
           大车机构
         </span>
-        <div style="display: flex;padding:30px 30px;margin-top: 30px;align-items: center;border-bottom: 1px solid #306AF7;">
+        <div style="display: flex;padding:30px 40px;margin-top: 30px;align-items: center;border-bottom: 1px solid #306AF7;">
           <div style="display: flex;flex-direction: column;">
             <span style="font-family: Alibaba-PuHuiTi-R;font-weight: normal;font-size: 16px;color: #ABC0E0;">
               大车行程
             </span>
             <div style="margin-top: 5px;">
               <span style="font-family: Alibaba-PuHuiTi-R;font-size: 36px;color: #4F80F8;">
-                00.00
+                {{ craneStrokeData.value}}
               </span>
               <span style="margin-left: -5px;font-family: Alibaba-PuHuiTi-R;font-size: 24px;color: #4F80F8;">
                 m
               </span>
             </div>
-            <div style="display: flex;margin-top: 50px;">
-              <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
-                <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
-                <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
-                  方向
-                </span>
-              </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
-                <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  左行
-                </span>
-              </div>
-            </div>
-            <div style="display: flex;margin-top: 10px;">
+            <div style="display: flex;margin-top: 40px;flex-direction: column;">
               <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
                 <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
                   挡位
                 </span>
               </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
+              <div style="height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;margin-top: 5px;">        
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  一档
+                  {{ formatGears(craneGearData) }}
                 </span>
               </div>
             </div>
-            <div style="display: flex;margin-top: 10px;">
+            <div style="display: flex;margin-top: 10px;flex-direction: column;">
               <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
                 <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
                   制动器
                 </span>
               </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
+              <div style="height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;margin-top: 5px;">        
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  闭合
+                  {{ craneBrakeData.length > 0 ? craneBrakeData.value : '未知' }}
                 </span>
               </div>
             </div>
@@ -71,7 +58,7 @@
             </span>
             <div style="margin-top: 5px;">
               <span style="font-family: Alibaba-PuHuiTi-R;font-size: 24px;color: #4F80F8;">
-                00.00
+                {{ craneFrequencyData.length > 0 ? craneFrequencyData.value : '0.00'}}
               </span>
               <span style="margin-left: -5px;font-family: Alibaba-PuHuiTi-R;font-size: 14px;color: #4F80F8;">
                 Hz
@@ -82,7 +69,7 @@
             </span>
             <div style="margin-top: 5px;">
               <span style="font-family: Alibaba-PuHuiTi-R;font-size: 24px;color: #4F80F8;">
-                00.00
+                {{craneCurrentData.length > 0 ? craneCurrentData.value : '0.00'}}
               </span>
               <span style="margin-left: -5px;font-family: Alibaba-PuHuiTi-R;font-size: 14px;color: #4F80F8;">
                 A
@@ -91,8 +78,8 @@
           </div>
         </div>
         <div class="left_bottom_grid">
-          <div v-for="item in left_bottom_list" :key="item.id" class="left_bottom_grid_item">
-            <span>{{ item.name }}</span>
+          <div v-for="item in craneSwitchVariablesData" :key="item.id" class="left_bottom_grid_item" :class="getColor(item)">
+            <span>{{ item.variableName }}</span>
           </div>
         </div>
       </div>
@@ -115,8 +102,8 @@
         </div>
         <div style="display: flex;align-items: center;justify-content: space-between;padding: 50px 30px 30px 30px;">
           <div style="display: flex;align-items: center">
-            <img style="width: 41px;height: 234px;" src="../../assets/img/screen_middle_bottom_left.png">
-            <div style="display: flex;flex-direction: column;margin-left: 10px;">
+            <!-- <img style="width: 41px;height: 234px;" src="../../assets/img/screen_middle_bottom_left.png"> -->
+            <div style="display: flex;flex-direction: column;margin-left: 20px;">
             <span style="font-family: Alibaba-PuHuiTi-R;font-weight: normal;font-size: 16px;color: #ABC0E0;">
               起升高度
             </span>
@@ -128,40 +115,27 @@
                 m
               </span>
             </div>
-            <div style="display: flex;margin-top: 20px;">
-              <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
-                <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
-                <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
-                  方向
-                </span>
-              </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
-                <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  左行
-                </span>
-              </div>
-            </div>
-            <div style="display: flex;margin-top: 10px;">
+            <div style="display: flex;margin-top: 20px;flex-direction: column;">
               <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
                 <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
                   挡位
                 </span>
               </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
+              <div style="height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;margin-top: 5px;">        
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  一档
+                  左行一档
                 </span>
               </div>
             </div>
-            <div style="display: flex;margin-top: 10px;">
+            <div style="display: flex;margin-top: 10px;flex-direction: column;">
               <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
                 <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
                   制动器
                 </span>
               </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
+              <div style="height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;margin-top: 5px;">        
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
                   闭合
                 </span>
@@ -295,7 +269,7 @@
         <span style="margin-right: 45px;color: #C8DEFE;font-size: 18px;font-weight: normal;font-family: Alibaba-PuHuiTi-R;">
           小车机构
         </span>
-        <div style="display: flex;padding:30px 30px;margin-top: 30px;align-items: center;border-bottom: 1px solid #306AF7;">
+        <div style="display: flex;padding:30px 40px;margin-top: 30px;align-items: center;border-bottom: 1px solid #306AF7;">
           <div style="height: 100%;display: flex;flex-direction: column;justify-content: flex-end;">
             <span style="font-family: Alibaba-PuHuiTi-R;font-weight: normal;font-size: 16px;color: #ABC0E0;">
               频率
@@ -323,7 +297,7 @@
           <div style="width: 1px;height: 100%;background-color: #306AF7;margin: 0px 42px;" />
           <div style="display: flex;flex-direction: column;">
             <span style="font-family: Alibaba-PuHuiTi-R;font-weight: normal;font-size: 16px;color: #ABC0E0;">
-              车行程
+              车行程
             </span>
             <div style="margin-top: 5px;">
               <span style="font-family: Alibaba-PuHuiTi-R;font-size: 36px;color: #4F80F8;">
@@ -333,49 +307,35 @@
                 m
               </span>
             </div>
-            <div style="display: flex;margin-top: 50px;">
-              <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
-                <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
-                <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
-                  方向
-                </span>
-              </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
-                <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  左行
-                </span>
-              </div>
-            </div>
-            <div style="display: flex;margin-top: 10px;">
+            <div style="display: flex;margin-top: 50px;flex-direction: column;">
               <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
                 <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
                   挡位
                 </span>
               </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
+              <div style="height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;margin-top: 5px;">        
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
-                  一档
+                  左行一档
                 </span>
               </div>
             </div>
-            <div style="display: flex;margin-top: 10px;">
+            <div style="display: flex;margin-top: 10px;flex-direction: column;">
               <div style="width: 70px;height: 28px;background-color: #294587;display: flex;align-items: center;">
                 <div style="width: 5px;height: 5px;background-color: #4F80F8;margin: 0px 5px;"></div>
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #ABC0E0;">
                   制动器
                 </span>
               </div>
-              <div style="width: 57px;height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;">        
+              <div style="height: 28px;background-color: rgba(41, 69, 135, 0.3);display: flex;align-items: center;justify-content: center;margin-top: 5px';">        
                 <span style="font-family: Alibaba-PuHuiTi-R;font-size: 16px;color: #FFFFFF;">
                   闭合
                 </span>
               </div>
             </div>
           </div>
-
         </div>
-        <div style="width: 100%;display: flex;justify-content: center;">
+        <div style="height: 200px;width: 100%;display: flex;justify-content: center;align-items: center">
           <div class="right_small_grid">
             <div v-for="item in right_samll_list" :key="item.id" class="right_small_grid_item">
               <span>{{ item.name }}</span>
@@ -394,182 +354,210 @@
   </div>
 </template>
 <script setup lang="ts">
+  import {getRealtime, getAlertRecordsByDevice} from '@/api/bigScreen';
+  import { filterTime } from '@/utils/dateUtil'
+  import { onSubscribe, onUnsubscribe, formatGears, formatValue, isTrue,parseGear} from '@/utils/tools';
   import router from '@/router';
-  const left_bottom_list = [
-    {
-      'id':0,
-      'name':'左行限位'
-    },
-    {
-      'id':1,
-      'name':'左防撞减速限位'
-    },
-    {
-      'id':2,
-      'name':'右行限位'
-    },
-    {
-      'id':3,
-      'name':'右防撞减速限位'
-    },
-    {
-      'id':4,
-      'name':'有梯侧翻板夹轨器限位'
-    },
-    {
-      'id':5,
-      'name':'有梯侧定位器'
-    },
-    {
-      'id':6,
-      'name':'无梯侧翻板夹轨器限位'
-    },
-    {
-      'id':7,
-      'name':'无梯侧定位器'
-    },
-    {
-      'id':8,
-      'name':'有梯侧油泵夹轮限位'
-    },
-    {
-      'id':9,
-      'name':'无梯侧油泵夹轮限位'
-    },
-  ]
-  const right_samll_list = [
-    {
-      'id':0,
-      'name':'前行限位'
-    },
-    {
-      'id':1,
-      'name':'前极限限位'
-    },
-    {
-      'id':2,
-      'name':'热继保护'
-    },
-    {
-      'id':3,
-      'name':'后行限位'
-    },
-    {
-      'id':4,
-      'name':'后极限限位'
-    },
-    {
-      'id':5,
-      'name':'小车锚定'
+  const deviceId = ref(0)
+  const deviceCode = ref('')
+
+  const deviceData: any = ref({})
+  const craneData: any = ref({})
+  const craneStrokeData: any = ref({})
+  const craneGearData: any = ref({})
+  const craneBrakeData: any = ref({})
+  const craneFrequencyData: any = ref({})
+  const craneCurrentData: any = ref({})
+  const craneSwitchVariablesData: any = ref([])
+
+  const switchVariableArr: any = ref([])
+
+  const workingCurrentArr: any = ref([])
+
+  const alarmRecordArr: any = ref([]);
+
+  const valueVariableArr: any = ref([]);
+
+  /**
+   * 拆分数组
+   * @param array 数组
+   * @param size 拆分的数量
+   */
+  const chunkArray = (array: any, size: number) => {
+      const arr: any = []
+      for (let index = 0; index < array.length; index += size) {
+          arr.push(array.slice(index, index + size));
+      }
+      return arr;
+  }
+
+
+  onMounted(async () => {
+    deviceId.value = parseInt(useQuery('id'))
+    deviceCode.value = useQuery('code')
+    getData()
+  })
+
+  onUnmounted(() => {
+
+  })
+
+  const getColor = (item:any) => {
+    if(item.value){
+      return item.trueLight
+    }else{
+      return item.falseLight
     }
-  ]
-  const right_bottom_list = [
-    {
-      'id':0,
-      'name':'前行限位'
-    },
-    {
-      'id':1,
-      'name':'前极限限位'
-    },
-    {
-      'id':2,
-      'name':'热继保护'
-    },
-    {
-      'id':3,
-      'name':'后行限位'
-    },
-    {
-      'id':4,
-      'name':'后极限限位'
-    },
-    {
-      'id':5,
-      'name':'小车锚定'
+  }
+
+  const getData = async () => {
+    const res: any = await getRealtime({ deviceId: deviceId.value })
+    deviceData.value = res
+    //大车数据
+    craneData.value = deviceData.value.crane
+    //大车行程
+    craneStrokeData.value = craneData.value.stroke
+    //大车挡位
+    craneGearData.value = craneData.value.gear
+    //大车制动器
+    if(craneData.value.brake){
+      craneBrakeData.value = craneData.value.brake  
     }
-  ]
-  const right_alert = [
-  {
-      'id':0,
-      'name':'设备超载',
-      'type':'报警',
-      'time':'2024-01-01 14:33'
-    },
-    {
-      'id':1,
-      'name':'设备超速',
-      'type':'报警',
-      'time':'2024-01-01 14:33'
-    },
-    {
-      'id':2,
-      'name':'设备故障',
-      'type':'报警',
-      'time':'2024-01-01 14:33'
-    },
-    {
-      'id':3,
-      'name':'设备损坏',
-      'type':'报警',
-      'time':'2024-01-01 14:33'
+    //大车频率
+    if(craneData.value.frequency){
+      craneFrequencyData.value = craneData.value.frequency
     }
-  ]
-  const middle_bottom_right_grid_list = [
-  {
-      'id':0,
-      'name':'上升限位'
-    },
-    {
-      'id':1,
-      'name':'上升预限位'
-    },
-    {
-      'id':2,
-      'name':'右行限位'
-    },
-    {
-      'id':3,
-      'name':'右防撞减速'
-    },
-    {
-      'id':4,
-      'name':'有梯侧翻板'
-    },
-    {
-      'id':5,
-      'name':'有梯侧定位器'
-    },
-    {
-      'id':6,
-      'name':'无梯侧翻板夹'
-    },
-    {
-      'id':7,
-      'name':'无梯侧定位器'
-    },
-    {
-      'id':8,
-      'name':'有梯侧油泵夹'
-    },
-    {
-      'id':9,
-      'name':'无梯侧油泵'
-    },
-    {
-      'id':10,
-      'name':'无梯侧油泵'
-    },
-    {
-      'id':11,
-      'name':'无梯侧油泵'
-    },
-  ]
-  onMounted(async () => {
-  })
+    //大车电流
+    if(craneData.value.current){
+      craneCurrentData.value = craneData.value.current
+    }
+    //大车开关量
+    craneSwitchVariablesData.value = craneData.value.switchVariables
 
+    const record = await getAlertRecordsByDevice({ deviceId: deviceId.value, maxCount: 10 })
+    alarmRecordArr.value = record
+
+    onSubscribe([`Json/${deviceCode.value}`], (topic: string, payload: any) => {
+        console.log('1111'+JSON.stringify(JSON.parse(payload)))
+        const jsonArray = JSON.parse(payload).Items
+        parseMqttData(jsonArray)
+    })
+  }
+
+  //解析数据
+  const parseMqttData = (jsonArray: any) => {
+      jsonArray.forEach((res: any) => {
+          const { Value, Code } = res
+          //大车档位
+          const craneGear = craneGearData.value
+          if (craneGear) {
+              if (parseGear(craneGear, Code, Value)) {
+                  return
+              }
+          }
+          //大车行程
+          const craneStroke = craneStrokeData.value
+          if(craneStroke) {
+            if (craneStroke.code == Code) {
+                craneStroke.value = formatValue(Value, craneStroke.translate)
+                return
+            }
+          }
+          //大车制动器
+          const craneBrake = craneBrakeData.value
+          if(craneBrake) {
+            if (craneBrake.code == Code) {
+                craneBrake.value = formatValue(Value, craneBrake.translate)
+                return
+            }
+          }
+          //大车频率
+          const craneFrequency = craneFrequencyData.value
+          if(craneFrequency) {
+            if (craneFrequency.code == Code) {
+                craneFrequency.value = formatValue(Value, craneFrequency.translate)
+                return
+            }
+          }
+          //大车电流
+          const craneCurrent = craneCurrentData.value
+          if(craneCurrent) {
+            if (craneCurrent.code == Code) {
+              craneCurrent.value = formatValue(Value, craneCurrent.translate)
+                return
+            }
+          }
+          //大车开关量
+          craneSwitchVariablesData.value.forEach((item: any) => {
+              const result = item.find((item: any) => item.code == Code)
+              if (result) {
+                  result.value = result.isReverse != Value
+                  return
+              }
+          })
+          //小车
+          // deviceData.value.trolleys.forEach((item: any) => {
+          //     //档位
+          //     if (parseGear(item.gear, Code, Value)) {
+          //         return
+          //     }
+          //     //吊钩
+          //     item.hoists.forEach((item: any) => {
+          //         //档位
+          //         if (parseGear(item.gear, Code, Value)) {
+          //             return
+          //         }
+          //         //重量
+          //         const weight = item.weight
+          //         if (weight?.code == Code) {
+          //             weight.value = formatValue(Value, weight.translate)
+          //             return
+          //         }
+          //         //超载
+          //         const light = weight?.light
+          //         if (light?.code == Code) {
+          //             light.value = light.isReverse != Value
+          //             return
+          //         }
+          //     })
+          // })
+
+          //开关量
+          switchVariableArr.value.forEach((item: any) => {
+              const result = item.find((item: any) => item.code == Code)
+              if (result) {
+                  result.value = result.isReverse != Value
+                  return
+              }
+          })
+
+          //工作电流
+          workingCurrentArr.value.forEach((item: any) => {
+              const result = item.find((item: any) => item.code == Code)
+              if (result) {
+                  console.log(res)
+                  result.value = formatValue(Value, result.translate)
+                  return
+              }
+          })
+
+          //模拟量
+          valueVariableArr.value.forEach((item: any) => {
+              const result = item.find((item: any) => item.code == Code)
+              if (result) {
+                  if (result.variableType == 10) {
+                      result.value = Value === true ? '开启' : '闭合'
+                  } else {
+                      result.value = formatValue(Value, result.translate)
+                  }
+                  return
+              }
+          })
+      })
+  }
 
   onUnmounted(() => {
+      onUnsubscribe(`Json/${deviceCode.value}`)
   })
 
   const backMainPage = () => {
@@ -588,25 +576,25 @@
     position: relative;
   }
   .top-bg {
-  width: 100%;
-  height: 77px;
-  background-image: url(../../assets/img/big_screen_top_bg.png);
-  background-repeat: no-repeat;
-  background-size: 100% 100%;
-  position: absolute;
-  cursor: pointer;
-    .device-name {
-      color: white;
-      font-size: 30px;
-      position: absolute;
-      left: 50%;
-      top: 35%;
-      font-weight: bold;
-      transform: translateX(-50%) translateY(-35%);
-      font-family: Alibaba-PuHuiTi-R;
-      font-style: normal;
-      text-transform: none;
-    }
+    width: 100%;
+    height: 77px;
+    background-image: url(../../assets/img/big_screen_top_bg.png);
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    position: absolute;
+    cursor: pointer;
+      .device-name {
+        color: white;
+        font-size: 30px;
+        position: absolute;
+        left: 50%;
+        top: 35%;
+        font-weight: bold;
+        transform: translateX(-50%) translateY(-35%);
+        font-family: Alibaba-PuHuiTi-R;
+        font-style: normal;
+        text-transform: none;
+      }
   }
   .left {
     top: 77px;
@@ -644,8 +632,6 @@
     gap: 11px;
   }
   .left_bottom_grid_item {
-    background-color: #334A6C;
-    border: 1px solid #455A7A;
     border-radius: 5px;
     display: flex;
     align-items: center;
@@ -654,6 +640,14 @@
     font-size: 16px;
     font-family: Alibaba-PuHuiTi-R;
   }
+  .red{
+    background-color: red;
+    border: 1px solid #455A7A;
+  }
+  .green{
+    background-color: green;
+    border: 1px solid #455A7A;
+  }
   .middle {
     top: 77px;
     left: 50%;
@@ -751,7 +745,6 @@
     padding: 10px 39px;
   }
   .right_small_grid {
-    margin-top: 36px;
     display: grid;
     grid-template-rows: 32px 32px;
     grid-template-columns: 110px 110px 110px;

+ 53 - 118
src/views/big-screen/synthesis.vue

@@ -6,22 +6,22 @@
         <div class="device_count_bg_item">
           <img src="../../assets/img/online.png" />
           <div style="color: #ABC0E0;font-size: 16px;margin: 0px 5px;">在线设备</div>
-          <div class="device_count_text">12191</div>
+          <div class="device_count_text">{{deviceStateData.onlineCount}}</div>
         </div>
         <div class="device_count_bg_item">
           <img src="../../assets/img/alarm.png" />
           <div style="color: #ABC0E0;font-size: 16px;margin: 0px 5px;">故障设备</div>
-          <div class="device_count_text">1219</div>
+          <div class="device_count_text">{{deviceStateData.alarmCount}}</div>
         </div>
         <div class="device_count_bg_item">
           <img src="../../assets/img/offline.png" />
           <div style="color: #ABC0E0;font-size: 16px;margin: 0px 5px;">离线设备</div>
-          <div class="device_count_text">1219</div>
+          <div class="device_count_text">{{deviceStateData.offlineCount}}</div>
         </div>
         <div class="device_count_bg_item">
           <img src="../../assets/img/repair.png" />
           <div style="color: #ABC0E0;font-size: 16px;margin: 0px 5px;">维修设备</div>
-          <div class="device_count_text">1219</div>
+          <div class="device_count_text">{{deviceStateData.repairCount}}</div>
         </div>
       </div>
       <div class="right_top">
@@ -48,27 +48,25 @@
       </div>
       <div class="left">
         <div style="display: flex;justify-content: center;color: white;font-size: 18px;font-weight: bold;font-family:Alibaba-PuHuiTi, Alibaba-PuHuiTi;">
-          <span>设备故障监控</span>
+          <span>设备数量监控</span>
         </div>
         <div class="client_list_title">
-          <div style="color: #ABC0E0;font-size: 16px;font-weight: normal;width: 30%">故障时间</div>
-          <div style="color: #ABC0E0;font-size: 16px;font-weight: normal;width: 30%">故障内容</div>
-          <div style="color: #ABC0E0;font-size: 16px;font-weight: normal;width: 40%">客户名称</div>
+          <div style="color: #ABC0E0;font-size: 16px;font-weight: normal;width: 70%">客户名称</div>
+          <div style="color: #ABC0E0;font-size: 16px;font-weight: normal;width: 30%">设备数量</div>
         </div>
         <div style="height: 1px;background-color: #417CC4;margin-top: 3px;"/>
         <div class="client-scroll">
-          <vue3-seamless-scroll :list="companyDevicesData" :step="0.3" :hover="true">
-            <template v-for="(item,index) in companyDevicesData">
+          <Vue3SeamlessScroll class="scrollClass" :list="companyDevicesData" step="0.3" hover="true">
+            <template v-for="(item,index) in companyDevicesData" :key="index">
               <div class="item" :class="{ 'active': 0 != index }">
-                <div style="display: flex;align-items: center;width: 30%;">
+                <div style="display: flex;align-items: center;width: 70%;">
                   <div style="background: #4F80F8;width: 3px;height: 13px;border-radius: 2px;"></div>
-                  <div style="color: #608BF3;font-size: 14px;margin-left: 5px;">{{ item.time }}</div>
+                  <div style="color: #608BF3;font-size: 14px;margin-left: 15px;">{{ item.companyName }}</div>
                 </div>
-                <div style="color: #608BF3;font-size: 14px;min-width:30%;">{{ item.content }}</div>
-                <div style="color: #608BF3;font-size: 14px;min-width:40%;">{{ item.name }}</div>
+                <div style="color: #608BF3;font-size: 14px;min-width:30%;">{{ item.count }}</div>
               </div>
             </template>
-          </vue3-seamless-scroll>
+          </Vue3SeamlessScroll>
         </div>
       </div>
       <div class="right">
@@ -251,6 +249,7 @@ import {
 } from '@/api/bigScreen';
 import router from '@/router';
 import * as echarts from 'echarts'
+import { Vue3SeamlessScroll } from "vue3-seamless-scroll";
 // import echartGauge from '@/components/echart-gauge/index.vue'
 // import echartMapEffects from '@/components/echart-map-effects/index.vue'
 import { url } from 'inspector';
@@ -277,7 +276,7 @@ const mapTypeIndex = ref(0)
 const mapTypeArray = ['china', '广东']
 
 //设备报警、活跃度菜单
-const alarmCountTabs = ['本年', '本季度', '本月', '本日']
+const alarmCountTabs = ['本年', '本月', '本周', '本日']
 const alarmCountTabsIndex = ref(0)
 const alarmCountTabsIndexChart = ref(0)
 
@@ -321,11 +320,12 @@ onMounted(async () => {
       alarmCountTabClick(c)
     }
   }, 1000 * 10)
+
   mapTimer.value = setInterval(() => {
     if (coordData.value.length > 0) {
-      // let a = mapTypeIndex.value
-      // let b = a + 1
-      // let c = b == 2 ? 0 : b
+      let a = mapTypeIndex.value
+      let b = a + 1
+      let c = b == 2 ? 0 : b
       mapTabClick(0)
     }
   }, 1000 * 60 * 30)
@@ -364,51 +364,13 @@ const getDeviceStateData = async () => {
 
 
 const getCompanyDevicesData = async () => {
-  // let data = await getCompanyDevices()
-  // companyDevicesData.value = data
-  companyDevicesData.value = [
-        {
-            "time": '2024-01-01',
-            "content": "主钩超载",
-            "name": '河南升起'
-        },
-        {
-            "time": '2024-01-01',
-            "content": "主钩超载",
-            "name": '河南升起'
-        }
-      ]
+  let data = await getCompanyDevices()
+  companyDevicesData.value = data
 }
 
 const getDeviceAreaStatisticsData = async () => {
-  // let data = await getDeviceAreaStatistics()
-  // deviceAreaStatisticsData.value = data
-  deviceAreaStatisticsData.value = {
-        "deviceCount": 92,
-        "monthNewCount": 2,
-        "data": [
-            {
-                "province": "广东省",
-                "count": 82
-            },
-            {
-                "province": "未知",
-                "count": 7
-            },
-            {
-                "province": "河南省",
-                "count": 1
-            },
-            {
-                "province": "内蒙古自治区",
-                "count": 1
-            },
-            {
-                "province": "新疆维吾尔自治区",
-                "count": 1
-            }
-        ]
-    }
+  let data = await getDeviceAreaStatistics()
+  deviceAreaStatisticsData.value = data
 
   let array: any = []
   deviceAreaStatisticsData.value.data.forEach((element: any) => {
@@ -420,7 +382,7 @@ const getDeviceAreaStatisticsData = async () => {
 
 
 const getDeviceStateStatisticsData = async () => {
-  // let data: any = await GetDeviceStateStatistics()
+  //let data: any = await GetDeviceStateStatistics()
   let data: any = {
         "keyDatas": [
             "10月",
@@ -524,25 +486,25 @@ const getDeviceActivityAndFaultCurvesData = async () => {
   alarmCountChart.value.setOption(alarmCountOption)
 }
 const getRepairOrderData = async () => {
-  // let data: any = await getRepairStateStatistics()
-  let data: any = [
-        {
-            "state": 1,
-            "count": 10
-        },
-        {
-            "state": 2,
-            "count": 8
-        },
-        {
-            "state": 3,
-            "count": 4
-        },
-        {
-            "state": 4,
-            "count": 1
-        }
-    ]
+  let data: any = await getRepairStateStatistics()
+  // let data: any = [
+  //       {
+  //           "state": 1,
+  //           "count": 10
+  //       },
+  //       {
+  //           "state": 2,
+  //           "count": 8
+  //       },
+  //       {
+  //           "state": 3,
+  //           "count": 4
+  //       },
+  //       {
+  //           "state": 4,
+  //           "count": 1
+  //       }
+  //   ]
   if (data.length > 3) {
     repairOrderData.value = {
       waitSend: data.find((res: any) => res.state == 1).count,
@@ -554,12 +516,12 @@ const getRepairOrderData = async () => {
 }
 
 const getMonthAddDeviceProgressData = async () => {
-  // let data: any = await getMonthAddDeviceProgress()
-  let data: any = {
-        "currentMonthAddCount": 3,
-        "growthProgress": 100,
-        "monthGrowth": 0
-    }
+  let data: any = await getMonthAddDeviceProgress()
+  // let data: any = {
+  //       "currentMonthAddCount": 3,
+  //       "growthProgress": 100,
+  //       "monthGrowth": 0
+  //   }
   monthAddDeviceProgressData.value = data
 }
 
@@ -602,36 +564,9 @@ const getDeviceTypeData = async () => {
 
 const getDeviceMapData = async () => {
   coordData.value = []
-  // let data: any = await getDeviceAreaMapData({
-  //   code: mapTypeTabs[mapTypeIndex.value] == '广东' ? '440000' : ''
-  // })
-
-  let data: any =  [
-        {
-            "area": "佛山",
-            "latitude": 23.027707,
-            "longitude": 113.128432,
-            "deviceCount": 1
-        },
-        {
-            "area": "呼和浩特",
-            "latitude": 40.847461,
-            "longitude": 111.758518,
-            "deviceCount": 1
-        },
-        {
-            "area": "克拉玛依",
-            "latitude": 45.585765,
-            "longitude": 84.89587,
-            "deviceCount": 1
-        },
-        {
-            "area": "郑州",
-            "latitude": 34.753488,
-            "longitude": 113.631349,
-            "deviceCount": 1
-        }
-    ]
+  let data: any = await getDeviceAreaMapData({
+    code: mapTypeTabs[mapTypeIndex.value] == '广东' ? '440000' : ''
+  })
 
   coordData.value = data.map((item: any) => {
     return {
@@ -1129,7 +1064,7 @@ let alarmCountOption = {
     position: absolute;
     display: flex;
     flex-direction: column;
-    padding: 28px 35px 0px 35px;
+    padding: 28px 35px 25px 35px;
   }
   .client_list_title {
     width: 100%;