leo пре 1 недеља
родитељ
комит
317c2b3a13
34 измењених фајлова са 3742 додато и 248 уклоњено
  1. 128 0
      components/customCard/cu-custom.vue
  2. 15 7
      main.js
  3. 221 222
      manifest.json
  4. 43 7
      pages.json
  5. 121 0
      pages/deviceDetails/weatherStation/charts.vue
  6. 157 0
      pages/deviceDetails/weatherStation/devControl.vue
  7. 350 0
      pages/deviceDetails/weatherStation/devRepair.vue
  8. 807 0
      pages/deviceDetails/weatherStation/eleDetail.vue
  9. 868 0
      pages/deviceDetails/weatherStation/index.vue
  10. 342 0
      pages/deviceDetails/weatherStation/simDetail.vue
  11. 21 12
      pages/equipList/index.vue
  12. 3 0
      static/images/device/HUMIA-default.svg
  13. 3 0
      static/images/device/HUMIA-warning.svg
  14. 7 0
      static/images/device/ILLUA-default.svg
  15. 7 0
      static/images/device/ILLUA-warning.svg
  16. 5 0
      static/images/device/PRECA-default.svg
  17. 5 0
      static/images/device/PRECA-warning.svg
  18. 4 0
      static/images/device/PRESA-default.svg
  19. 4 0
      static/images/device/PRESA-warning.svg
  20. 3 0
      static/images/device/SM01A-default.svg
  21. 3 0
      static/images/device/STEMC-default.svg
  22. 3 0
      static/images/device/TEMPA-default.svg
  23. 3 0
      static/images/device/TEMPA-warning.svg
  24. 3 0
      static/images/device/WDIRA-default.svg
  25. 3 0
      static/images/device/WDIRA-warning.svg
  26. 3 0
      static/images/device/WSPDA-default.svg
  27. 3 0
      static/images/device/WSPDA-warning.svg
  28. 3 0
      static/images/device/copy.svg
  29. 10 0
      static/images/device/date-active.svg
  30. 10 0
      static/images/device/date.svg
  31. 559 0
      static/images/device/dev-station.svg
  32. 4 0
      static/images/device/edit.svg
  33. 3 0
      static/images/device/smile.svg
  34. 18 0
      static/images/device/冻土.svg

+ 128 - 0
components/customCard/cu-custom.vue

@@ -0,0 +1,128 @@
+<template>
+  <view>
+    <view class="cu-custom" :style="[{ height: CustomBar + 'px' }]">
+      <view
+        class="cu-bar fixed"
+        :style="style"
+        :class="[bgImage != '' ? 'none-bg text-white bg-img' : '', bgColor]"
+      >
+        <view class="action" @tap="BackPage" v-if="isBack">
+          <u-icon name="arrow-left" color="#020305" size="32rpx" />
+          <slot name="backText"></slot>
+        </view>
+        <view class="content" :style="[{ top: StatusBar + 'px' }]">
+          <slot name="content"></slot>
+        </view>
+        <view class="cu-bar-right">
+          <slot name="right"></slot>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      StatusBar: this.StatusBar,
+      CustomBar: this.CustomBar,
+    };
+  },
+  name: "cu-custom",
+  computed: {
+    style() {
+      var StatusBar = this.StatusBar;
+      var CustomBar = this.CustomBar;
+      var bgImage = this.bgImage;
+      var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
+      if (this.bgImage) {
+        style = `${style}background-image:url(${bgImage});`;
+      }
+      if (this.textColor) {
+        style = `${style}color: ${this.textColor}`;
+      }
+      return style;
+    },
+  },
+  props: {
+    bgColor: {
+      type: String,
+
+      default: "",
+    },
+    isBack: {
+      type: [Boolean, String],
+      default: false,
+    },
+    bgImage: {
+      type: String,
+      default: "",
+    },
+    textColor: {
+      type: String,
+      default: "",
+    },
+    isGoWater: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  methods: {
+    BackPage() {
+      if (this.isGoWater) {
+        uni.switchTab({
+          url: "/waterPages/index",
+        });
+      } else {
+        if (getCurrentPages().length < 2 && "undefined" !== typeof __wxConfig) {
+          let url = "/" + __wxConfig.pages[0];
+          return uni.redirectTo({ url });
+        }
+        // uni.navigateBack({
+        //   delta: 1
+        // })
+        if (getCurrentPages().length === 1) {
+          uni.switchTab({
+            url: "/pages/index",
+          });
+        } else {
+          uni.navigateBack({
+            delta: 1,
+          });
+        }
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.cu-bar {
+  display: flex;
+  align-items: center;
+  position: relative;
+  &.bg-transparent {
+    background-color: transparent;
+  }
+
+  &.bg-gray {
+    background-color: #f7f7f7;
+  }
+
+  .cu-bar-right {
+    position: relative;
+    z-index: 10;
+    right: 32rpx;
+  }
+  .content {
+    position: absolute;
+    left: 50%;
+    transform: translateX(-50%);
+    color: #020305;
+    font-family: "Source Han Sans CN VF";
+    font-weight: 700;
+    font-size: 32rpx;
+  }
+}
+</style>

+ 15 - 7
main.js

@@ -11,7 +11,7 @@ App.mpType = 'app';
 
 import config from './util/neutral.js';
 Vue.prototype.$isneutral = config.isneutral;
-Vue.prototype.$imageURL = config.imageURL;// 线上图片服务器路径常量
+Vue.prototype.$imageURL = config.imageURL; // 线上图片服务器路径常量
 
 import { QueryPermission } from './util/QueryPermission.js';
 
@@ -19,11 +19,15 @@ Vue.prototype.$QueryPermission = QueryPermission;
 // 自定义卡片
 import customCard from './components/customCard/customCard.vue';
 Vue.component('customCard', customCard);
-Vue.filter('timeFormat', function (time,fmt = 'yyyy-MM-dd hh:mm:ss') {
+
+import cuCustom from './components/customCard/cu-custom.vue';
+Vue.component('cu-custom', cuCustom);
+
+Vue.filter('timeFormat', function (time, fmt = 'yyyy-MM-dd hh:mm:ss') {
   function fun(a) {
     return String(a).length == 1 ? '0' + a : a;
   }
-  let $this = new Date(time*1000);
+  let $this = new Date(time * 1000);
   let o = {
     'M+': $this.getMonth() + 1,
     'd+': $this.getDate(),
@@ -36,14 +40,16 @@ Vue.filter('timeFormat', function (time,fmt = 'yyyy-MM-dd hh:mm:ss') {
   if (/(y+)/.test(fmt)) {
     fmt = fmt.replace(
       RegExp.$1,
-      ($this.getFullYear() + '').substr(4 - RegExp.$1.length)
+      ($this.getFullYear() + '').substr(4 - RegExp.$1.length),
     );
   }
   for (var k in o) {
     if (new RegExp('(' + k + ')').test(fmt)) {
       fmt = fmt.replace(
         RegExp.$1,
-        RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
+        RegExp.$1.length === 1
+          ? o[k]
+          : ('00' + o[k]).substr(('' + o[k]).length),
       );
     }
   }
@@ -64,14 +70,16 @@ Vue.prototype.formatTime = function (thistime, fmt = 'yyyy-MM-dd hh:mm:ss') {
   if (/(y+)/.test(fmt)) {
     fmt = fmt.replace(
       RegExp.$1,
-      ($this.getFullYear() + '').substr(4 - RegExp.$1.length)
+      ($this.getFullYear() + '').substr(4 - RegExp.$1.length),
     );
   }
   for (var k in o) {
     if (new RegExp('(' + k + ')').test(fmt)) {
       fmt = fmt.replace(
         RegExp.$1,
-        RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
+        RegExp.$1.length === 1
+          ? o[k]
+          : ('00' + o[k]).substr(('' + o[k]).length),
       );
     }
   }

+ 221 - 222
manifest.json

@@ -1,239 +1,239 @@
 {
-    "name" : "智控",
-    "appid" : "__UNI__DBA6730",
-    "description" : "",
-    "versionName" : "1.15.8",
-    "versionCode" : 11508,
-    "transformPx" : false,
-    "sassImplementationName" : "node-sass",
-    /* 5+App特有相关 */
-    "app-plus" : {
-        "softinput" : {
-            "mode" : "adjustPan",
-            "softinputMode" : "adjustResize"
-        },
-        "usingComponents" : true,
-        "nvueCompiler" : "uni-app",
-        "compilerVersion" : 3,
-        "splashscreen" : {
-            "alwaysShowBeforeRender" : true,
-            "waiting" : true,
-            "autoclose" : true,
-            "delay" : 0
-        },
-        "compatible" : {
-            "ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
-        },
-        /* 模块配置 */
-        "modules" : {
-            "Webview-x5" : {},
-            "Maps" : {},
-            "VideoPlayer" : {},
-            "LivePusher" : {},
-            "Geolocation" : {},
-            "Camera" : {},
-            "wasm" : {
-                "enabled" : true,
-                "preload" : false
-            }
-        },
-        /* 应用发布信息 */
-        "distribute" : {
-            /* android打包配置 */
-            "android" : {
-                "permissions" : [
-                    "<uses-feature android:name=\"android.hardware.camera\"/>",
-                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
-                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
-                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
-                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
-                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.CHANGE_COMPONENT_ENABLED_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.DISABLE_KEYGUARD\"/>",
-                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
-                    "<uses-permission android:name=\"android.permission.INSTALL_LOCATION_PROVIDER\"/>",
-                    "<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
-                    "<uses-permission android:name=\"android.permission.INSTALL_SHORTCUT\"/>",
-                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
-                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
-                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
-                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
-                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
-                    "<uses-permission android:name=\"android.permission.UPDATE_DEVICE_STATS\"/>",
-                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
-                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
-                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
-                ],
-                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
-                "targetSdkVersion" : 30
-            },
-            /* ios打包配置 */
-            "ios" : {
-                "dSYMs" : false
-            },
-            /* SDK配置 */
-            "sdkConfigs" : {
-                "geolocation" : {
-                    "amap" : {
-                        "__platform__" : [ "ios", "android" ],
-                        "appkey_ios" : "25716a10d462140d75820fd9f5b342a5",
-                        "appkey_android" : "25716a10d462140d75820fd9f5b342a5"
-                    }
-                },
-                "maps" : {
-                    "amap" : {
-                        "appkey_ios" : "25716a10d462140d75820fd9f5b342a5",
-                        "appkey_android" : "25716a10d462140d75820fd9f5b342a5"
-                    }
-                },
-                "ad" : {}
-            },
-            "icons" : {
-                "android" : {
-                    "hdpi" : "unpackage/res/icons/72x72.png",
-                    "xhdpi" : "unpackage/res/icons/96x96.png",
-                    "xxhdpi" : "unpackage/res/icons/144x144.png",
-                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
-                },
-                "ios" : {
-                    "appstore" : "unpackage/res/icons/1024x1024.png",
-                    "ipad" : {
-                        "app" : "unpackage/res/icons/76x76.png",
-                        "app@2x" : "unpackage/res/icons/152x152.png",
-                        "notification" : "unpackage/res/icons/20x20.png",
-                        "notification@2x" : "unpackage/res/icons/40x40.png",
-                        "proapp@2x" : "unpackage/res/icons/167x167.png",
-                        "settings" : "unpackage/res/icons/29x29.png",
-                        "settings@2x" : "unpackage/res/icons/58x58.png",
-                        "spotlight" : "unpackage/res/icons/40x40.png",
-                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
-                    },
-                    "iphone" : {
-                        "app@2x" : "unpackage/res/icons/120x120.png",
-                        "app@3x" : "unpackage/res/icons/180x180.png",
-                        "notification@2x" : "unpackage/res/icons/40x40.png",
-                        "notification@3x" : "unpackage/res/icons/60x60.png",
-                        "settings@2x" : "unpackage/res/icons/58x58.png",
-                        "settings@3x" : "unpackage/res/icons/87x87.png",
-                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
-                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
-                    }
-                }
-            },
-            "splashscreen" : {
-                "androidStyle" : "default"
-            }
-        },
-        "uniStatistics" : {
-            "enable" : true,
-            "version" : "2"
-        }
-    },
-    /* 快应用特有相关 */
-    "quickapp" : {},
-    /* 小程序特有相关 */
-    "mp-weixin" : {
-        "appid" : "wx1cabf67f460e3a14",
-        "setting" : {
-            "urlCheck" : false,
-            "minified" : true,
-            "postcss" : false,
-            "es6" : true
-        },
-        "usingComponents" : true,
-        "uniStatistics" : {
-            "enable" : true
-        }
-    },
-    "mp-alipay" : {
-        "usingComponents" : true,
-        "uniStatistics" : {
-            "enable" : true
-        }
+  "name": "智控",
+  "appid": "__UNI__DBA6730",
+  "description": "",
+  "versionName": "1.15.9",
+  "versionCode": 11509,
+  "transformPx": false,
+  "sassImplementationName": "node-sass",
+  /* 5+App特有相关 */
+  "app-plus": {
+    "softinput": {
+      "mode": "adjustPan",
+      "softinputMode": "adjustResize"
     },
-    "mp-baidu" : {
-        "usingComponents" : true,
-        "uniStatistics" : {
-            "enable" : true
-        }
+    "usingComponents": true,
+    "nvueCompiler": "uni-app",
+    "compilerVersion": 3,
+    "splashscreen": {
+      "alwaysShowBeforeRender": true,
+      "waiting": true,
+      "autoclose": true,
+      "delay": 0
     },
-    "mp-toutiao" : {
-        "usingComponents" : true,
-        "uniStatistics" : {
-            "enable" : true
-        }
+    "compatible": {
+      "ignoreVersion": true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
     },
-    "uniStatistics" : {
-        "enable" : true,
-        "version" : "2"
+    /* 模块配置 */
+    "modules": {
+      "Webview-x5": {},
+      "Maps": {},
+      "VideoPlayer": {},
+      "LivePusher": {},
+      "Geolocation": {},
+      "Camera": {},
+      "wasm": {
+        "enabled": true,
+        "preload": false
+      }
     },
-    "h5" : {
-        "devServer" : {
-            "port" : 8000,
-            "disableHostCheck" : true,
-            "proxy" : {
-                "/ksy" : {
-                    "target" : "http://dev.hnyfwlw.com",
-                    "changeOrigin" : true,
-                    "ws" : true,
-                    "pathRewrite" : {
-                        "^/ksy" : "ksy"
-                    }
-                }
-            }
+    /* 应用发布信息 */
+    "distribute": {
+      /* android打包配置 */
+      "android": {
+        "permissions": [
+          "<uses-feature android:name=\"android.hardware.camera\"/>",
+          "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+          "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+          "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+          "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+          "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+          "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.CHANGE_COMPONENT_ENABLED_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.DISABLE_KEYGUARD\"/>",
+          "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+          "<uses-permission android:name=\"android.permission.INSTALL_LOCATION_PROVIDER\"/>",
+          "<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
+          "<uses-permission android:name=\"android.permission.INSTALL_SHORTCUT\"/>",
+          "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+          "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+          "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+          "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+          "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+          "<uses-permission android:name=\"android.permission.UPDATE_DEVICE_STATS\"/>",
+          "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+          "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+          "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+        ],
+        "abiFilters": ["armeabi-v7a", "arm64-v8a", "x86"],
+        "targetSdkVersion": 30
+      },
+      /* ios打包配置 */
+      "ios": {
+        "dSYMs": false
+      },
+      /* SDK配置 */
+      "sdkConfigs": {
+        "geolocation": {
+          "amap": {
+            "__platform__": ["ios", "android"],
+            "appkey_ios": "25716a10d462140d75820fd9f5b342a5",
+            "appkey_android": "25716a10d462140d75820fd9f5b342a5"
+          }
         },
-        "template" : "static/tempalate.html",
-        "sdkConfigs" : {
-            "maps" : {
-                "qqmap" : {
-                    "key" : "XGQBZ-MSGW6-KNDSO-MVOIJ-OM6LO-JXBKB"
-                },
-                "amap" : {
-                    "key" : "bd1582190896ab05afb30aa8161d14c2",
-                    "securityJsCode" : "",
-                    "serviceHost" : ""
-                }
-            }
+        "maps": {
+          "amap": {
+            "appkey_ios": "25716a10d462140d75820fd9f5b342a5",
+            "appkey_android": "25716a10d462140d75820fd9f5b342a5"
+          }
         },
-        "uniStatistics" : {
-            "enable" : true
-        }
-    },
-    "mp-jd" : {
-        "uniStatistics" : {
-            "enable" : true
-        }
-    },
-    "mp-kuaishou" : {
-        "uniStatistics" : {
-            "enable" : true
+        "ad": {}
+      },
+      "icons": {
+        "android": {
+          "hdpi": "unpackage/res/icons/72x72.png",
+          "xhdpi": "unpackage/res/icons/96x96.png",
+          "xxhdpi": "unpackage/res/icons/144x144.png",
+          "xxxhdpi": "unpackage/res/icons/192x192.png"
+        },
+        "ios": {
+          "appstore": "unpackage/res/icons/1024x1024.png",
+          "ipad": {
+            "app": "unpackage/res/icons/76x76.png",
+            "app@2x": "unpackage/res/icons/152x152.png",
+            "notification": "unpackage/res/icons/20x20.png",
+            "notification@2x": "unpackage/res/icons/40x40.png",
+            "proapp@2x": "unpackage/res/icons/167x167.png",
+            "settings": "unpackage/res/icons/29x29.png",
+            "settings@2x": "unpackage/res/icons/58x58.png",
+            "spotlight": "unpackage/res/icons/40x40.png",
+            "spotlight@2x": "unpackage/res/icons/80x80.png"
+          },
+          "iphone": {
+            "app@2x": "unpackage/res/icons/120x120.png",
+            "app@3x": "unpackage/res/icons/180x180.png",
+            "notification@2x": "unpackage/res/icons/40x40.png",
+            "notification@3x": "unpackage/res/icons/60x60.png",
+            "settings@2x": "unpackage/res/icons/58x58.png",
+            "settings@3x": "unpackage/res/icons/87x87.png",
+            "spotlight@2x": "unpackage/res/icons/80x80.png",
+            "spotlight@3x": "unpackage/res/icons/120x120.png"
+          }
         }
+      },
+      "splashscreen": {
+        "androidStyle": "default"
+      }
     },
-    "mp-lark" : {
-        "uniStatistics" : {
-            "enable" : true
-        }
+    "uniStatistics": {
+      "enable": true,
+      "version": "2"
+    }
+  },
+  /* 快应用特有相关 */
+  "quickapp": {},
+  /* 小程序特有相关 */
+  "mp-weixin": {
+    "appid": "wx1cabf67f460e3a14",
+    "setting": {
+      "urlCheck": false,
+      "minified": true,
+      "postcss": false,
+      "es6": true
     },
-    "mp-qq" : {
-        "uniStatistics" : {
-            "enable" : true
+    "usingComponents": true,
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-alipay": {
+    "usingComponents": true,
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-baidu": {
+    "usingComponents": true,
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-toutiao": {
+    "usingComponents": true,
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "uniStatistics": {
+    "enable": true,
+    "version": "2"
+  },
+  "h5": {
+    "devServer": {
+      "port": 8000,
+      "disableHostCheck": true,
+      "proxy": {
+        "/ksy": {
+          "target": "http://dev.hnyfwlw.com",
+          "changeOrigin": true,
+          "ws": true,
+          "pathRewrite": {
+            "^/ksy": "ksy"
+          }
         }
+      }
     },
-    "quickapp-webview-huawei" : {
-        "uniStatistics" : {
-            "enable" : true
+    "template": "static/tempalate.html",
+    "sdkConfigs": {
+      "maps": {
+        "qqmap": {
+          "key": "XGQBZ-MSGW6-KNDSO-MVOIJ-OM6LO-JXBKB"
+        },
+        "amap": {
+          "key": "bd1582190896ab05afb30aa8161d14c2",
+          "securityJsCode": "",
+          "serviceHost": ""
         }
+      }
     },
-    "quickapp-webview-union" : {
-        "uniStatistics" : {
-            "enable" : true
-        }
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-jd": {
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-kuaishou": {
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-lark": {
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "mp-qq": {
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "quickapp-webview-huawei": {
+    "uniStatistics": {
+      "enable": true
+    }
+  },
+  "quickapp-webview-union": {
+    "uniStatistics": {
+      "enable": true
     }
+  }
 }
 // "sdkConfigs" : {
 //     "maps" : {
@@ -242,4 +242,3 @@
 //         }
 //     }
 // }
-

+ 43 - 7
pages.json

@@ -339,13 +339,13 @@
         "enablePullDownRefresh": false
       }
     },
-	{
-	  "path": "pages/cb/cbd/equip-set/equip-set-sy2",
-	  "style": {
-	    "navigationBarTitleText": "设备控制",
-	    "enablePullDownRefresh": false
-	  }
-	},
+    {
+      "path": "pages/cb/cbd/equip-set/equip-set-sy2",
+      "style": {
+        "navigationBarTitleText": "设备控制",
+        "enablePullDownRefresh": false
+      }
+    },
     {
       "path": "pages/cb/cbd/equip-set/photo",
       "style": {
@@ -964,8 +964,44 @@
       "style": {
         "navigationBarTitleText": "历史数据"
       }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation/index",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation/devControl",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation/simDetail",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation/devRepair",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation/eleDetail",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
     }
   ],
+
   "condition": {
     //模式配置,仅开发期间生效
     "current": 3, //当前激活的模式(list 的索引项)

+ 121 - 0
pages/deviceDetails/weatherStation/charts.vue

@@ -0,0 +1,121 @@
+<template>
+  <view>
+    <canvas
+      canvas-id="orIfOOkumJYtFcnuJkjxcySENqRtXceW"
+      id="orIfOOkumJYtFcnuJkjxcySENqRtXceW"
+      class="charts"
+      @touchstart="touchstart"
+      @touchmove="touchmove"
+      @touchend="touchend"
+    />
+  </view>
+</template>
+
+<script>
+import uCharts from "../../../components/js_sdk/u-charts/u-charts/u-charts.js";
+var uChartsInstance = {};
+export default {
+  data() {
+    return {
+      cWidth: 320,
+      cHeight: 200,
+    };
+  },
+  onReady() {
+    //这里的 750 对应 css .charts 的 width
+    // this.cWidth = uni.upx2px(340);
+    //这里的 500 对应 css .charts 的 height
+    // this.cHeight = uni.upx2px(200);
+    this.getServerData();
+  },
+  methods: {
+    getServerData() {
+      //模拟从服务器获取数据时的延时
+      setTimeout(() => {
+        //模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
+        let res = {
+          categories: ["2018", "2019", "2020", "2021", "2022", "2023"],
+          series: [
+            {
+              name: "成交量A",
+              linearColor: [
+                [0, "#1890FF"],
+                [0.25, "#00B5FF"],
+                [0.5, "#00D1ED"],
+                [0.75, "#00E6BB"],
+                [1, "#90F489"],
+              ],
+              data: [35, 8, 25, 37, 4, 20],
+            },
+          ],
+        };
+        this.drawCharts("orIfOOkumJYtFcnuJkjxcySENqRtXceW", res);
+      }, 500);
+    },
+    drawCharts(id, data) {
+      const ctx = uni.createCanvasContext(id, this);
+      uChartsInstance[id] = new uCharts({
+        type: "line",
+        context: ctx,
+        width: this.cWidth,
+        height: this.cHeight,
+        categories: data.categories,
+        series: data.series,
+        animation: true,
+        background: "#FFFFFF",
+        color: [
+          "#1890FF",
+          "#91CB74",
+          "#FAC858",
+          "#EE6666",
+          "#73C0DE",
+          "#3CA272",
+          "#FC8452",
+          "#9A60B4",
+          "#ea7ccc",
+        ],
+        padding: [10, 10, 10, 10],
+        enableScroll: true,
+        legend: {
+          position: "top",
+        },
+        xAxis: {
+          disableGrid: true,
+          scrollShow: true,
+          itemCount: 4,
+        },
+        yAxis: {
+          gridType: "dash",
+          dashLength: 2,
+        },
+        dataLabel: false,
+        extra: {
+          line: {
+            type: "curve",
+            width: 2,
+            activeType: "hollow",
+          },
+        },
+      });
+    },
+    touchstart(e) {
+      uChartsInstance[e.target.id].scrollStart(e);
+    },
+    touchmove(e) {
+      uChartsInstance[e.target.id].scroll(e);
+    },
+    touchend(e) {
+      uChartsInstance[e.target.id].scrollEnd(e);
+      uChartsInstance[e.target.id].touchLegend(e);
+      uChartsInstance[e.target.id].showToolTip(e);
+    },
+  },
+};
+</script>
+
+<style scoped>
+.charts {
+  width: 750rpx;
+  height: 500rpx;
+}
+</style>

+ 157 - 0
pages/deviceDetails/weatherStation/devControl.vue

@@ -0,0 +1,157 @@
+<template>
+  <view class="device-details-page">
+    <cu-custom :isBack="true">
+      <template slot="content">
+        <view class="nav-title">设备控制</view>
+      </template>
+    </cu-custom>
+    <view class="control-board">
+      <view class="title">操作</view>
+      <div style="margin-bottom: 48rpx;">
+        <u-button type="success" class="reload-btn" @click="handleControl('RESET')">重启</u-button>
+      </div>
+      <u-button type="success" class="reload-btn" @click="handleControl('FWUPDATE')">升级</u-button>
+      <view class="title date-title">本地存储间隔(min)</view>
+      <view class="date-slider">
+        <slider
+          :value="storageVal"
+          show-value="true"
+          :min="1"
+          :max="240"
+          block-color="#57C878"
+          activeColor="#57C878"
+          step="1"
+        />
+      </view>
+      <view class="title date-title">数据传输间隔(min)</view>
+      <view class="date-slider">
+        <slider
+          :value="dataInterval"
+          show-value="true"
+          :min="1"
+          :max="240"
+          block-color="#57C878"
+          activeColor="#57C878"
+          step="1"
+        />
+      </view>
+    </view>
+    <view class="footer-board">
+      <u-button type="success" class="sub-btn" @click="handleSubmit()">确定</u-button>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  onLoad(options) {
+    this.loading = true
+    const deviceInfo = JSON.parse(decodeURIComponent(options.deviceInfo));
+    console.log(deviceInfo, "deviceInfo");
+    this.deviceInfo = deviceInfo;
+    this.getDevControlParams();
+  },
+  data() {
+    return {
+      deviceInfo: {},
+      storageVal: "",
+      dataInterval: "",
+    };
+  },
+  methods: {
+    // 获取设备控制参数信息
+    async getDevControlParams() {
+      this.loading = true
+      await this.$myRequest({
+        url: '/api/api_gateway?method=qxz.device.control_args',
+        data: {
+          device_id: this.deviceInfo.devBid,
+        }
+      }).then(res => {
+        console.log('设备控制参数信息', res)
+        this.storageVal = res.storage_inr
+        this.dataInterval = res.interval
+      })
+    },
+    async handleControl(cmd) {
+      const params = {
+        device_id: this.deviceInfo.devBid,
+        cmd,
+        interval: cmd === 'INTERVAL' ? this.dataInterval : undefined,
+        storage_inr: cmd === 'STORAGE_INR' ? this.storageVal : undefined,
+        stnid: cmd === 'STNID' ? this.stnidVal : undefined
+      };
+      await this.$myRequest({
+        url: '/api/api_gateway?method=qxz.device.control',
+        data: params
+      }).then(res => {
+        console.log('设备控制参数信息', res)
+      })
+    },
+    handleSubmit() {
+      this.handleControl('STORAGE_INR');
+      this.handleControl('INTERVAL');
+      uni.showToast({
+        title: "操作成功",
+        icon: "none",
+      });
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.device-details-page {
+  background: linear-gradient(
+      180deg,
+      #ffffff00 0%,
+      #f5f6fa 23.64%,
+      #f5f6fa 100%
+    ),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  min-height: 100vh;
+  padding: 0 32rpx;
+  padding-top: 98rpx;
+}
+
+.control-board {
+  border-radius: 16rpx;
+  background: #fff;
+  padding: 32rpx;
+  margin-top: 46rpx;
+  .title {
+    margin-bottom: 16rpx;
+    color: #303133;
+    font-size: 28rpx;
+    font-weight: 400;
+  }
+  .date-title {
+    margin-bottom: 52rpx;
+  }
+  .reload-btn {
+    width: 100%;
+    background: #0bbc58;
+    margin-bottom: 48rpx;
+    border-radius: 16rpx;
+  }
+  .date-slider {
+    
+  }
+}
+
+.footer-board {
+  border-top: 2rpx solid #e4e7ed;
+  background: #fff;
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 164rpx;
+  padding: 16rpx 32rpx 0 32rpx;
+  .sub-btn {
+    width: 100%;
+    background: #0bbc58;
+    border-radius: 16rpx;
+  }
+}
+</style>

+ 350 - 0
pages/deviceDetails/weatherStation/devRepair.vue

@@ -0,0 +1,350 @@
+<template>
+  <view class="device-repair-page">
+    <cu-custom :isBack="true">
+      <template slot="content">
+        <view class="nav-title">设备报修</view>
+      </template>
+    </cu-custom>
+    <view class="form-board">
+      <u-form
+        ref="baseFormRef"
+        :model="baseForm"
+        labelWidth="162"
+        :rules="rules"
+        errorType="toast"
+      >
+        <view class="repaid-board">
+          <view class="title">基本信息</view>
+          <u-form-item label="设备ID" prop="device_id" required>
+            <u-input
+              v-model="baseForm.device_id"
+              placeholder="设备ID"
+              disabled
+            ></u-input>
+          </u-form-item>
+          <u-form-item label="设备名称" prop="devName" required>
+            <u-input
+              v-model="baseForm.devName"
+              placeholder="请输入设备名称"
+              disabled
+            ></u-input>
+          </u-form-item>
+          <u-form-item label="联系人" prop="user" required>
+            <u-input
+              v-model="baseForm.user"
+              placeholder="请输入"
+            ></u-input>
+          </u-form-item>
+          <u-form-item label="联系人电话" prop="userphone" required>
+            <u-input
+              v-model="baseForm.userphone"
+              placeholder="请输入"
+              type="number"
+            ></u-input>
+          </u-form-item>
+          <u-form-item label="联系人地址" prop="addr" required>
+            <u-input
+              v-model="baseForm.addr"
+              placeholder="请输入"
+            ></u-input>
+          </u-form-item>
+        </view>
+        <view class="repaid-board">
+          <view class="title">保修详情</view>
+          <u-input
+            v-model="baseForm.errordesc"
+            placeholder="请描述设备问题"
+            type="textarea"
+            :height="216"
+            maxlength="140"
+            show-word-limit
+          ></u-input>
+
+          <view class="upload-section">
+            <view class="upload-title"
+              >设备照片<text class="info">(最多4张)</text></view
+            >
+            <u-upload
+              :file-list="fileList"
+              :max-count="4"
+              @on-choose-complete="onChooseComplete"
+              @on-remove="onRemove"
+              name="upload"
+              :max-size="5 * 1024 * 1024"
+              accept="image/*"
+              :auto-upload="false"
+              :show-progress="false"
+            >
+              <view slot="addBtn" class="add-btn">
+                <u-icon name="plus" size="56" color="#909399"></u-icon>
+              </view>
+            </u-upload>
+          </view>
+        </view>
+      </u-form>
+    </view>
+
+    <view class="footer-board">
+      <u-button type="success" class="sub-btn" @click="submitForm"
+        >确定</u-button
+      >
+    </view>
+  </view>
+</template>
+
+<script>
+import uInput from "../../../uview-ui/components/u-input/u-input.vue";
+export default {
+  components: { uInput },
+  onLoad(options) {
+    const deviceInfo = JSON.parse(decodeURIComponent(options.deviceInfo));
+    console.log("deviceInfo:", deviceInfo);
+    this.baseForm.device_id = deviceInfo.devBid
+    this.baseForm.devName = deviceInfo.devName
+  },
+  data() {
+    return {
+      baseForm: {
+        device_id: "",
+        devName: "",
+        user: "",
+        userphone: "",
+        addr: "",
+        errordesc: "",
+      },
+      rules: {
+        devName: [
+          {
+            required: true,
+            message: "请输入设备名称",
+            trigger: ["blur", "change"],
+          },
+        ],
+        user: [
+          {
+            required: true,
+            message: "请输入联系人",
+            trigger: ["blur", "change"],
+          },
+        ],
+        userphone: [
+          {
+            required: true,
+            message: "请输入联系人电话",
+            trigger: ["blur", "change"],
+          },
+          {
+            pattern: /^1[3-9]\d{9}$/,
+            message: "请输入正确的手机号",
+            trigger: ["blur", "change"],
+          },
+        ],
+        addr: [
+          {
+            required: true,
+            message: "请输入联系人地址",
+            trigger: ["blur", "change"],
+          },
+        ],
+        errordesc: [
+          {
+            required: true,
+            message: "请描述设备问题",
+            trigger: ["blur", "change"],
+          },
+        ],
+      },
+      fileList: [],
+    };
+  },
+  methods: {
+    onChooseComplete(lists) {
+      const newFiles = lists.filter(
+        (item) => !this.fileList.some((f) => f.url === item.url)
+      );
+      newFiles.forEach((file) => {
+        const item = {
+          url: file.url,
+          status: "uploading",
+        };
+        this.fileList.push(item);
+        const index = this.fileList.length - 1;
+        uni.uploadFile({
+          url: "https://wx.hnyfwlw.com/api/api_gateway?method=base.bases.base_photo",
+          filePath: file.url,
+          name: "img_file",
+          formData: {
+            user: "test",
+          },
+          success: (uploadFileRes) => {
+            const data = JSON.parse(uploadFileRes.data);
+            if (data.data && data.data.src) {
+              this.fileList[index].status = "success";
+              this.fileList[index].src = data.data.src;
+              this.$forceUpdate();
+              console.log("上传成功,图片地址:", data.data.src);
+            } else {
+              this.fileList[index].status = "failed";
+              uni.showToast({
+                title: data.msg || "上传失败",
+                icon: "none",
+              });
+            }
+          },
+          fail: (err) => {
+            this.fileList[index].status = "failed";
+            uni.showToast({
+              title: "上传失败",
+              icon: "none",
+            });
+            console.error("上传失败:", err);
+          },
+        });
+      });
+    },
+    onRemove(index) {
+      this.fileList.splice(index, 1);
+    },
+    submitForm() {
+      const hasUploading = this.fileList.some((f) => f.status === "uploading");
+      if (hasUploading) {
+        uni.showToast({
+          title: "请等待图片上传完成",
+          icon: "none",
+        });
+        return;
+      }
+      const hasFailed = this.fileList.some((f) => f.status === "failed");
+      if (hasFailed) {
+        uni.showToast({
+          title: "有图片上传失败,请重新上传",
+          icon: "none",
+        });
+        return;
+      }
+      this.$refs.baseFormRef
+        .validate()
+        .then((res) => {
+          const uploadedImages = this.fileList
+            .filter((f) => f.status === "success" && f.src)
+            .map((f) => f.src);
+          const params = {
+            ...this.baseForm,
+            errorimg: uploadedImages,
+          };
+          console.log("提交参数:", params);
+          // 
+          this.$myRequest({
+            url: "/api/api_gateway?method=after_sale.after_sale_manage.aftersale_apply",
+            data: params,
+          }).then(res => {
+            console.log("aftersale_apply:", res);
+            if(res){
+              uni.showToast({
+                  title: '提交成功',
+                  duration: 2000,
+              });
+              setTimeout(()=>{
+                uni.navigateBack({
+                  delta:1
+                })
+              },1000)
+            }else{
+              uni.showToast({
+                  title: '提交失败',
+                  duration: 2000,
+                icon:"none"
+              });
+            }
+          })
+        })
+        .catch((errors) => {
+          console.log("表单验证失败", errors);
+        });
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.device-repair-page {
+  background:
+    linear-gradient(180deg, #ffffff00 0%, #f5f6fa 23.64%, #f5f6fa 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  min-height: 100vh;
+  padding: 0 32rpx;
+  padding-top: 98rpx;
+  padding-bottom: 200rpx;
+}
+
+.form-board {
+  margin-top: 46rpx;
+}
+.repaid-board {
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 32rpx;
+  margin-bottom: 24rpx;
+
+  .title {
+    color: #020305;
+    font-size: 32rpx;
+    font-weight: bold;
+  }
+}
+
+.upload-section {
+  padding: 20rpx 0;
+
+  .upload-title {
+    font-size: 28rpx;
+    color: #303133;
+    margin-bottom: 16rpx;
+    .info {
+      color: #999;
+    }
+  }
+
+  .add-btn {
+    background: #f1f4f8;
+    width: 160rpx;
+    height: 160rpx;
+    border-radius: 12rpx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+}
+
+// 使所有输入框文本右对齐
+::v-deep .uni-input-input,
+::v-deep .uni-input-placeholder {
+  text-align: right !important;
+}
+::v-deep .u-add-wrap {
+  display: none !important;
+}
+::v-deep .u-input__textarea {
+  background: #f1f4f8 !important;
+  border-radius: 8rpx;
+  margin-top: 24rpx;
+  padding: 17rpx 24rpx !important;
+}
+
+.footer-board {
+  border-top: 2rpx solid #e4e7ed;
+  background: #fff;
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 164rpx;
+  padding: 16rpx 32rpx 0 32rpx;
+
+  .sub-btn {
+    width: 100%;
+    background: #0bbc58;
+    border-radius: 16rpx;
+  }
+}
+</style>

+ 807 - 0
pages/deviceDetails/weatherStation/eleDetail.vue

@@ -0,0 +1,807 @@
+<template>
+  <view class="ele-details-page">
+    <cu-custom :isBack="true">
+      <template slot="content">
+        <view class="nav-title">小气候监测站II监测要素</view>
+      </template>
+    </cu-custom>
+    <view class="date-picker" @click="openDatePicker">
+      <text>{{ startDate }}</text>
+      <text class="separator">-</text>
+      <text>{{ endDate }}</text>
+      <image class="date-icon" src="/static/images/device/date-active.svg" />
+    </view>
+    <u-calendar
+      v-model="show"
+      :mode="mode"
+      @change="onDateChange"
+      ref="calendar"
+    ></u-calendar>
+    <view class="echarts-board">
+      <view class="period-tabs">
+        <view
+          class="tab-item"
+          :class="{ active: activePeriod === '24h' }"
+          @click="changePeriod('24h')"
+          >24小时</view
+        >
+        <view
+          class="tab-item"
+          :class="{ active: activePeriod === '7d' }"
+          @click="changePeriod('7d')"
+          >一周</view
+        >
+        <view
+          class="tab-item"
+          :class="{ active: activePeriod === '30d' }"
+          @click="changePeriod('30d')"
+          >一月</view
+        >
+      </view>
+
+      <view class="element-tabs" v-if="hasData">
+        <view class="ele-board">
+          <view
+            v-for="(item, index) in eleTabs"
+            :key="index"
+            class="ele-item"
+            :class="{ 'ele-active': eleActive === index }"
+            @click="changeElement(index)"
+            >{{ item.name }}</view
+          >
+        </view>
+        <view class="fold-icon" @click="toggleFold">
+          <u-icon :name="isFolded ? 'arrow-down' : 'arrow-up'"></u-icon>
+        </view>
+      </view>
+      <!-- 展开后的所有要素 -->
+      <view v-if="!isFolded && hasData" class="expanded-elements">
+        <view
+          class="expanded-item"
+          v-for="(item, index) in eleTabs"
+          :key="index"
+          :class="{ 'ele-active': eleActive === index }"
+          @click="changeElement(index)"
+        >
+          {{ item.name }}
+        </view>
+      </view>
+
+      <view class="chart-container" v-if="hasData">
+        <canvas
+          canvas-id="temperatureChart"
+          id="temperatureChart"
+          class="chart"
+          @touchstart="touchLineA($event)"
+          @touchmove="moveLineA($event)"
+          @touchend="touchEndLineA($event)"
+          disable-scroll="true"
+        ></canvas>
+      </view>
+      <view class="no-data" v-else>
+        <text>暂无数据</text>
+      </view>
+
+      <!-- <view class="stats-panel">
+        <view class="stat-item">
+          <text class="value">27<text class="unit">°C</text></text>
+          <text class="label">最低值</text>
+        </view>
+        <view class="stat-item">
+          <text class="value">32<text class="unit">°C</text></text>
+          <text class="label">平均值</text>
+        </view>
+        <view class="stat-item">
+          <text class="value red">42<text class="unit red">°C</text></text>
+          <text class="label">最高值</text>
+        </view>
+      </view> -->
+    </view>
+
+    <view class="history-section">
+      <view class="section-title">历史数据</view>
+      <view class="table-wrap">
+        <view class="fixed-column">
+          <view class="table-cell header">上报时间</view>
+          <view class="table-cell" v-for="(item, idx) in tableList" :key="idx">
+            {{ item.uptime }}
+          </view>
+        </view>
+        <view class="table-bg"></view>
+        <scroll-view class="scroll-column" scroll-x="true">
+          <view class="scroll-content">
+            <view class="table-row">
+              <view class="table-cell header">{{
+                activeChartInfo.name + "(" + activeChartInfo.unit + ")"
+              }}</view>
+            </view>
+            <view class="table-row" v-for="(item, idx) in tableList" :key="idx">
+              <view class="table-cell">{{ item[activeChartInfo.title] }}</view>
+            </view>
+          </view>
+        </scroll-view>
+      </view>
+
+      <view class="pagination">
+        <view
+          class="page-item prev"
+          @click="prevPage"
+          :class="{ disabled: currentPage === 1 }"
+          >上一页</view
+        >
+        <view class="page-info">
+          <text class="curret-page">{{ currentPage }}</text>
+          <text>/</text>
+          <text>{{ totalPages }}</text>
+        </view>
+        <view
+          class="page-item next"
+          @click="nextPage"
+          :class="{ disabled: currentPage >= totalPages }"
+          >下一页</view
+        >
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import uCharts from "../../../components/js_sdk/u-charts/u-charts/u-charts.js";
+import baseCharts from "./charts.vue";
+export default {
+  components: { baseCharts },
+  onLoad(options) {
+    const deviceInfo = JSON.parse(decodeURIComponent(options.deviceInfo));
+    console.log(deviceInfo, "deviceInfo");
+    this.eleKey = options.eleKey || "";
+    this.initDateRange(deviceInfo.uptime);
+    this.deviceInfo = deviceInfo;
+    this.getChartData();
+    this.getObData();
+  },
+  data() {
+    return {
+      temperatureChart: null,
+      activePeriod: "",
+      activeElement: "temperature",
+      show: false,
+      mode: "range",
+      startDate: "",
+      endDate: "",
+      isFolded: true, // 控制要素是否收起
+      eleTabs: [],
+      eleActive: 0,
+      hasData: true,
+      tableList: [],
+      currentPage: 1,
+      pageSize: 9,
+      total: 0,
+      chartData: {
+        categories: [],
+        series: [],
+      },
+      activeChartInfo: {},
+      eleKey: "",
+    };
+  },
+  computed: {
+    totalPages() {
+      return Math.ceil(this.total / this.pageSize);
+    },
+  },
+  methods: {
+    initDateRange(timestamp) {
+      if (!timestamp) {
+        const today = new Date();
+        this.endDate = this.formatDate(today);
+        const startDate = new Date(today);
+        startDate.setDate(startDate.getDate() - 7);
+        this.startDate = this.formatDate(startDate);
+        return;
+      }
+      const date = new Date(Number(timestamp) * 1000);
+      this.endDate = this.formatDate(date);
+      const startDate = new Date(date);
+      startDate.setDate(startDate.getDate() - 7);
+      this.startDate = this.formatDate(startDate);
+    },
+    formatDate(date) {
+      const year = date.getFullYear();
+      const month = String(date.getMonth() + 1).padStart(2, "0");
+      const day = String(date.getDate()).padStart(2, "0");
+      return `${year}-${month}-${day}`;
+    },
+    initChart() {
+      const ctx = uni.createCanvasContext("temperatureChart", this);
+      const currentEle = this.eleTabs[this.eleActive];
+      console.log(currentEle, "currentEle");
+      currentEle.data.forEach((item) => {
+        if (item.value === "/") {
+          item.value = "0";
+        }
+      });
+      const series = [
+        {
+          name: currentEle.name,
+          data: currentEle.data,
+          lineWidth: 3,
+          pointShape: "circle",
+          pointSize: 12,
+          pointColor: currentEle.color,
+          pointBorderColor: "#fff",
+          pointBorderWidth: 2,
+          symbol: "emptyCircle",
+          symbolSize: 6,
+          legendShape: "circle",
+        },
+      ];
+      const xData = currentEle.data.map((item) => item.time);
+
+      this.temperatureChart = new uCharts({
+        $this: this,
+        canvasId: "temperatureChart",
+        type: "line",
+        context: ctx,
+        width: 340,
+        height: 180,
+        categories: xData,
+        series: series,
+        legend: {
+          position: "top",
+          show: true,
+          padding: 5,
+          fontColor: "#303133",
+          fontSize: 12,
+          itemType: "circle",
+          itemShape: "emptyCircle",
+          itemWidth: 12,
+          itemHeight: 12,
+          lineWidth: 2,
+        },
+        xAxis: {
+          axisLineColor: "#E4E7ED",
+          disableGrid: true,
+          fontColor: "#656565",
+          fontSize: 10,
+          itemCount: 5,
+          scrollShow: true,
+        },
+        yAxis: {
+          splitNumber: 4,
+          axisLineColor: "#E4E7ED",
+          fontColor: "#656565",
+          gridColor: "#E4E7ED",
+          dashLength: 4,
+          disableGrid: false,
+          fontSize: 10,
+        },
+        dataLabel: false,
+        enableScroll: true,
+        background: "#FFFFFF",
+        extra: {
+          line: {
+            type: "curve",
+            width: 2,
+            activeType: "hollow",
+          },
+        },
+      });
+    },
+    touchLineA(e) {
+      this.temperatureChart.scrollStart(e);
+    },
+    moveLineA(e) {
+      this.temperatureChart.scroll(e);
+    },
+    touchEndLineA(e) {
+      this.temperatureChart.scrollEnd(e);
+      //下面是toolTip事件,如果滚动后不需要显示,可不填写
+      // this.temperatureChart.showToolTip(e, {
+      //   format: function(item, category) {
+      //     console.log(item, 'iyee', e)
+      //     return category + ' ' + item.name + ':' + item.data
+      //   }
+      // });
+    },
+
+    // 打开日期选择器
+    openDatePicker() {
+      this.show = true;
+      // 延迟设置日期,确保组件已经初始化
+      this.$nextTick(() => {
+        if (this.$refs.calendar) {
+          // 直接设置组件内部的日期状态
+          const calendar = this.$refs.calendar;
+          calendar.startDate = this.startDate;
+          calendar.endDate = this.endDate;
+
+          // 如果有选中的日期范围,设置对应的年、月、日
+          if (this.startDate) {
+            const startParts = this.startDate.split("-");
+            calendar.startYear = parseInt(startParts[0]);
+            calendar.startMonth = parseInt(startParts[1]);
+            calendar.startDay = parseInt(startParts[2]);
+          }
+          if (this.endDate) {
+            const endParts = this.endDate.split("-");
+            calendar.endYear = parseInt(endParts[0]);
+            calendar.endMonth = parseInt(endParts[1]);
+            calendar.endDay = parseInt(endParts[2]);
+          }
+
+          // 如果有开始日期,设置日历当前显示的年月为开始日期的年月
+          if (this.startDate) {
+            const startParts = this.startDate.split("-");
+            calendar.year = parseInt(startParts[0]);
+            calendar.month = parseInt(startParts[1]);
+            calendar.changeData();
+          }
+        }
+      });
+    },
+
+    // 日期选择变化事件
+    onDateChange(e) {
+      this.startDate = e.startDate;
+      this.endDate = e.endDate;
+      this.activePeriod = "custom"; // 设置为自定义周期
+      this.show = false;
+      this.getChartData();
+    },
+
+    // 切换时间周期
+    changePeriod(period) {
+      this.activePeriod = period;
+
+      // 根据选择的周期自动计算日期范围
+      const now = new Date();
+      const endDate = now.toISOString().split("T")[0];
+      const startDate = new Date();
+
+      if (period === "24h") {
+        startDate.setDate(now.getDate());
+      } else if (period === "7d") {
+        startDate.setDate(now.getDate() - 7);
+      } else if (period === "30d") {
+        startDate.setMonth(now.getMonth() - 1);
+      }
+
+      this.startDate = startDate.toISOString().split("T")[0];
+      this.endDate = endDate;
+      this.getChartData();
+    },
+
+    // 切换要素标签
+    changeElement(index) {
+      if (this.eleTabs.length === 0) return;
+      this.eleActive = index;
+      this.activeChartInfo = this.eleTabs[index];
+      this.isFolded = true; // 关闭展开面板
+      this.$nextTick(() => {
+        this.initChart();
+      });
+    },
+
+    // 切换要素展开/收起状态
+    toggleFold() {
+      this.isFolded = !this.isFolded;
+    },
+    // 上一页
+    prevPage() {
+      if (this.currentPage > 1) {
+        this.currentPage--;
+        this.getObData();
+      }
+    },
+    // 下一页
+    nextPage() {
+      if (this.currentPage < this.totalPages) {
+        this.currentPage++;
+        this.getObData();
+      }
+    },
+    // 折线图数据
+    getChartData() {
+      this.$myRequest({
+        url: "/api/api_gateway?method=qxz.data.qxz_ob_data_map",
+        data: {
+          device_id: this.deviceInfo.devBid,
+          start: String(
+            Math.floor(new Date(this.startDate + " 00:00:00").getTime() / 1000),
+          ),
+          end: String(
+            Math.floor(new Date(this.endDate + " 23:59:59").getTime() / 1000),
+          ),
+          page: 1,
+          page_size: 999,
+        },
+      }).then((res) => {
+        console.log("getChartData:", res);
+        if (res && Array.isArray(res) && res.length > 0) {
+          this.eleTabs = res;
+          this.hasData = true;
+          this.activeChartInfo =
+            this.eleTabs.find((item) => item.title === this.eleKey) ||
+            this.eleTabs[0];
+          this.eleActive = this.eleTabs.indexOf(this.activeChartInfo);
+          console.log(this.activeChartInfo, "activeChartInfo");
+          this.$nextTick(() => {
+            this.initChart();
+          });
+        } else {
+          this.eleTabs = [];
+          this.hasData = false;
+        }
+      });
+    },
+    // 历史数据
+    getObData() {
+      this.$myRequest({
+        url: "/api/api_gateway?method=qxz.data.qxz_ob_data",
+        data: {
+          device_id: this.deviceInfo.devBid,
+          start: String(
+            Math.floor(new Date(this.startDate + " 00:00:00").getTime() / 1000),
+          ),
+          end: String(
+            Math.floor(new Date(this.endDate + " 23:59:59").getTime() / 1000),
+          ),
+          page: this.currentPage,
+          page_size: this.pageSize,
+        },
+      }).then((res) => {
+        console.log("getObData:", res);
+        const columns = res.title;
+        const data = res.data;
+        const newData = data.map((item) => {
+          return this.processData(item);
+        });
+        const resCol = this.convertDynamic(columns, (prop, val) =>
+          Array.isArray(val) ? `${val[1]}${val[3] || ""}` : val,
+        );
+        this.columns = resCol;
+        this.tableList = newData;
+        this.total = res.count;
+        console.log("tableList:", this.columns);
+        console.log("tableList", this.tableList);
+      });
+    },
+    convertDynamic(data, getLabelValue) {
+      if (!data || typeof data !== "object") return [];
+      const result = [];
+      const keys = Object.keys(data);
+      for (const prop of keys) {
+        const arr = data[prop];
+        const value = getLabelValue(prop, arr, data);
+        if (value !== undefined && value !== null) {
+          result.push({
+            label: String(value),
+            prop,
+            align: "center",
+          });
+        }
+      }
+      return result;
+    },
+    processData(data) {
+      return Object.entries(data).reduce((acc, [key, value]) => {
+        acc[key] = Array.isArray(value) ? value[0] : value;
+        return acc;
+      }, {});
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.ele-details-page {
+  background:
+    linear-gradient(180deg, #ffffff00 0%, #f5f6fa 23.64%, #f5f6fa 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  min-height: 100vh;
+  padding: 0 32rpx;
+  padding-top: 98rpx;
+}
+
+.date-picker {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  background-color: #fff;
+  border-radius: 40rpx;
+  padding: 16rpx 24rpx;
+  margin-bottom: 36rpx;
+  font-size: 28rpx;
+  color: #999;
+  margin-top: 46rpx;
+  .date-icon {
+    width: 32rpx;
+    height: 32rpx;
+  }
+}
+
+.separator {
+  margin: 0 16rpx;
+}
+.echarts-board {
+  padding: 32rpx;
+  border-radius: 16rpx;
+  background: #fff;
+  margin-bottom: 24rpx;
+  position: relative;
+  .period-tabs {
+    width: 350rpx;
+    height: 64rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin: auto;
+    margin-bottom: 12rpx;
+    border-radius: 32rpx;
+    background: #f1f4f8;
+    padding: 8rpx 10rpx;
+    color: #303133;
+    font-family: "Source Han Sans CN VF";
+    font-size: 26rpx;
+    font-style: normal;
+    font-weight: 400;
+    line-height: normal;
+    .tab-item {
+      padding: 5rpx 24rpx;
+      height: 48rpx;
+      line-height: 48rpx;
+      border-radius: 32rpx;
+    }
+    .active {
+      background: #fff;
+    }
+  }
+  .element-tabs {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    overflow-x: auto;
+    white-space: nowrap;
+    .ele-board {
+      flex: 1;
+      display: flex;
+      align-items: center;
+      overflow-x: auto;
+      overflow-y: hidden;
+      white-space: nowrap;
+    }
+    .ele-item {
+      position: relative;
+      color: #999999;
+      font-size: 28rpx;
+      font-weight: 400;
+      white-space: nowrap;
+      margin-right: 16rpx;
+      padding: 14rpx 16rpx;
+      cursor: pointer;
+    }
+    .ele-active {
+      color: #303133;
+      font-weight: 500;
+      &::after {
+        content: "";
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        bottom: 4rpx;
+        display: block;
+        width: 30rpx;
+        height: 8rpx;
+        border-radius: 4rpx;
+        background: #1fc676;
+      }
+    }
+    .fold-icon {
+      width: 48rpx;
+      border-left: 2px solid #999;
+      padding-left: 16rpx;
+      margin-left: 16rpx;
+      cursor: pointer;
+    }
+  }
+  /* 展开后的要素容器样式 */
+  .expanded-elements {
+    position: absolute;
+    top: 126rpx;
+    left: 0;
+    right: 0;
+    background: #f5f7fa;
+    border-radius: 12rpx;
+    padding: 16rpx;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16rpx;
+    z-index: 10;
+    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+  }
+
+  .expanded-item {
+    flex: 0 0 calc(33.33% - 16rpx);
+    text-align: center;
+    padding: 16rpx 0;
+    border-radius: 8rpx;
+    color: #999999;
+    font-size: 26rpx;
+    background: #ffffff;
+    cursor: pointer;
+    transition: all 0.3s ease;
+  }
+
+  .expanded-item.ele-active {
+    color: #1fc676;
+    background: #e6f7ef;
+    font-weight: 500;
+  }
+
+  .chart-container {
+    border-radius: 16rpx;
+    margin-bottom: 24rpx;
+    position: relative;
+    padding: 10rpx;
+    overflow: hidden;
+    .chart {
+      width: 100%;
+      height: 336rpx;
+    }
+  }
+
+  .no-data {
+    border-radius: 16rpx;
+    margin-bottom: 24rpx;
+    padding: 10rpx;
+    height: 336rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #f9f9f9;
+    text {
+      color: #999;
+      font-size: 32rpx;
+    }
+  }
+
+  .stats-panel {
+    display: flex;
+    justify-content: space-between;
+    background-color: #f1f4f8;
+    border-radius: 16rpx;
+    padding: 24rpx 64rpx;
+    .stat-item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      .label {
+        color: #656565;
+        font-size: 24rpx;
+        font-weight: 400;
+      }
+      .value {
+        font-size: 40rpx;
+        font-weight: bold;
+      }
+      .unit {
+        color: #999999;
+        font-size: 20rpx;
+      }
+      .red {
+        color: #fb4e52;
+      }
+    }
+  }
+}
+
+.history-section {
+  background-color: #fff;
+  border-radius: 16rpx;
+  padding: 24rpx 32rpx;
+  .section-title {
+    font-size: 28rpx;
+    font-weight: bold;
+    margin-bottom: 16rpx;
+    color: #303133;
+  }
+  .table-wrap {
+    display: flex;
+    width: 100%;
+    box-sizing: border-box;
+    margin: 20rpx 0;
+    color: #042118;
+    font-family: "Source Han Sans CN VF";
+    font-size: 24rpx;
+    font-style: normal;
+    font-weight: 400;
+    line-height: normal;
+    .fixed-column {
+      width: 250rpx;
+      .table-cell {
+        width: 100%;
+        white-space: nowrap;
+      }
+    }
+    .table-bg {
+      width: 16rpx;
+      background: linear-gradient(270deg, #ffffff33 0%, #9598a433 100%);
+    }
+    .scroll-column {
+      flex: 1;
+      height: auto;
+      overflow: hidden;
+      margin-left: -10rpx;
+    }
+    .scroll-content {
+      min-width: 100%;
+      width: fit-content;
+      display: flex;
+      flex-direction: column;
+      .table-row {
+        display: flex;
+        .table-cell {
+          flex: 1;
+        }
+      }
+    }
+    .table-cell {
+      width: 160rpx;
+      height: 64rpx;
+      line-height: 64rpx;
+      text-align: center;
+      border-bottom: 2px solid #e4e7ed;
+      box-sizing: border-box;
+    }
+    .table-cell.header {
+      background: #f6f8fc;
+    }
+  }
+
+  .pagination {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-top: 24rpx;
+    .page-item {
+      width: 104rpx;
+      height: 48rpx;
+      color: #656565;
+      font-size: 24rpx;
+      line-height: 48rpx;
+      text-align: center;
+      border: 2rpx solid #e4e7ed;
+      border-radius: 8rpx;
+    }
+    .page-item.disabled {
+      color: #999;
+      border-color: #e4e7ed;
+      background-color: #f5f7fa;
+    }
+    .next {
+      color: #0bbc58;
+      border: 2rpx solid #0bbc58;
+    }
+    .next.disabled {
+      color: #999;
+      border-color: #e4e7ed;
+      background-color: #f5f7fa;
+    }
+    .page-info {
+      color: #999999;
+      font-family: "Source Han Sans CN VF";
+      font-size: 24rpx;
+      font-style: normal;
+      font-weight: 400;
+      line-height: normal;
+      .curret-page {
+        color: #303133;
+      }
+    }
+  }
+}
+::v-deep .u-calendar__action {
+  display: flex;
+  justify-content: center;
+}
+</style>

+ 868 - 0
pages/deviceDetails/weatherStation/index.vue

@@ -0,0 +1,868 @@
+<template>
+  <view class="device-details-page">
+    <cu-custom :isBack="true">
+      <template slot="content">
+        <view class="nav-title">{{ deviceInfo.devName }}</view>
+      </template>
+    </cu-custom>
+
+    <!-- 设备基本信息 -->
+    <view class="device-info">
+      <view @click="copy(deviceInfo.devBid)" class="info-item">
+        <text class="info-label">设备ID</text>
+        <text class="info-value">{{ deviceInfo.devBid }}</text>
+        <image
+          src="/static/images/device/copy.svg"
+          mode=""
+          class="info-img"
+        ></image>
+      </view>
+      <view class="info-item">
+        <text class="info-label">设备位置</text>
+        <text class="info-value">{{ deviceInfo.address }}</text>
+      </view>
+      <view class="info-item">
+        <text class="info-label">上报时间</text>
+        <text class="info-value">{{ formatTimestamp(deviceInfo.uptime) }}</text>
+      </view>
+      <view class="dev-status">{{
+        deviceInfo.devStatus == "1" ? "在线" : "离线"
+      }}</view>
+    </view>
+
+    <!-- 标签页切换 -->
+    <view class="tab-container">
+      <view class="tab-top">
+        <view
+          class="tab-item"
+          :class="{ active: activeTab === 'monitoring' }"
+          @click="switchTab('monitoring')"
+        >
+          <text class="tab-text">监测要素</text>
+          <image
+            v-if="activeTab === 'monitoring'"
+            src="/static/images/device/smile.svg"
+            mode=""
+            class="smile"
+          ></image>
+        </view>
+        <view
+          class="tab-item"
+          :class="{ active: activeTab === 'details' }"
+          @click="switchTab('details')"
+        >
+          <text class="tab-text">设备详情</text>
+          <image
+            v-if="activeTab === 'details'"
+            src="/static/images/device/smile.svg"
+            mode=""
+            class="smile"
+          ></image>
+        </view>
+      </view>
+    </view>
+
+    <!-- 标签页内容 -->
+    <view class="tab-content">
+      <!-- 监测要素页面 -->
+      <view v-if="activeTab === 'monitoring'" class="monitoring-page">
+        <view
+          class="data-card"
+          v-for="(item, index) in monitorList"
+          :key="index"
+          @click="goPage('eleDetail', item)"
+        >
+          <view class="card-title">{{ item.factorName }}</view>
+          <view class="data-value-row">
+            <view>
+              <text v-if="item.yData && item.yData.length" class="data-value">{{ item.yData[0] }}</text>
+              <text class="data-unit">{{ item.factorUnit }}</text>
+            </view>
+            <image
+              class="device-img"
+              :src="`/static/images/device/${item.key}-default.svg`"
+              mode="aspectFit"
+            ></image>
+          </view>
+          <view class="card-thrid">
+            <text>{{ item.alias }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 设备详情页面 -->
+      <view v-if="activeTab === 'details'" class="details-page">
+        <!-- 设备参数 -->
+        <view class="device-params">
+          <view class="device-control">
+            <!-- <view class="control-left">
+              <view>2025-12-28 08:00:00</view>
+              <u-icon name="reload" class="reload-img"></u-icon>
+            </view> -->
+            <view class="control-right">
+              <image
+                class="control-img"
+                src="/static/images/cb/control.svg"
+                mode="aspectFit"
+                @click="goPage('devControl')"
+              ></image>
+              <image
+                class="control-img"
+                src="/static/images/cb/setting.svg"
+                mode="aspectFit"
+                @click="goPage('devRepair')"
+              ></image>
+              <image
+                class="control-img"
+                src="/static/images/cb/sim.svg"
+                mode="aspectFit"
+                @click="goPage('simDetail')"
+              ></image>
+            </view>
+          </view>
+          <view class="params-board">
+            <view class="params-left">
+              <view
+                v-for="(item, index) in statusList"
+                :key="index"
+                class="params-item"
+              >
+                <view class="params-val">{{ item.val }}</view>
+                <view class="params-label">{{ item.label }}</view>
+              </view>
+            </view>
+            <view class="params-right">
+              <image
+                class="device-img"
+                src="/static/images/device/dev-station.svg"
+                mode="aspectFit"
+              ></image>
+            </view>
+          </view>
+        </view>
+
+        <!-- 设备数据表格 -->
+        <view class="table-container">
+          <view class="table-control">
+            <view class="title">设备数据</view>
+            <view class="date-board" @click="openDatePicker">
+              <text>{{ startDate }}</text>
+              <text class="line">至</text>
+              <text>{{ endDate }}</text>
+              <image class="date-icon" src="/static/images/device/date.svg" />
+            </view>
+          </view>
+          <u-calendar
+            v-model="show"
+            :mode="mode"
+            @change="onDateChange"
+            ref="calendar"
+          ></u-calendar>
+          <view class="table-wrap" v-if="tableData && tableData.length > 0">
+            <view class="fixed-column">
+              <view class="table-cell header">上报时间</view>
+              <view
+                class="table-cell"
+                v-for="(item, idx) in tableData"
+                :key="idx"
+              >
+                {{ item.uptime }}
+              </view>
+            </view>
+            <view class="table-bg"></view>
+            <scroll-view class="scroll-column" scroll-x="true">
+              <view class="scroll-content">
+                <view class="table-row">
+                  <view
+                    class="table-cell header"
+                    v-for="(item, index) in tableColumn"
+                    :key="index"
+                    >{{ item.label }}</view
+                  >
+                </view>
+                <view
+                  class="table-row"
+                  v-for="(item, idx) in tableData"
+                  :key="idx"
+                >
+                  <view
+                    class="table-cell"
+                    v-for="(item1, index1) in tableColumn"
+                    :key="index1"
+                    >{{ item[item1.prop] }}</view
+                  >
+                </view>
+              </view>
+            </scroll-view>
+          </view>
+          <view class="empty-state" v-else>
+            <u-empty text="暂无数据" mode="list"></u-empty>
+          </view>
+
+          <view class="pagination" v-if="tableData && tableData.length > 0">
+            <view 
+              class="page-item prev" 
+              :class="{ disabled: page <= 1 }"
+              @click="prevPage"
+            >上一页</view>
+            <view class="page-info">
+              <text class="curret-page">{{ page }}</text>
+              <text>/</text>
+              <text>{{ totalPages }}</text>
+            </view>
+            <view 
+              class="page-item next" 
+              :class="{ disabled: page >= totalPages }"
+              @click="nextPage"
+            >下一页</view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  onLoad(options) {
+    console.log(options, "optionsss");
+    this.deviceInfo = options;
+    this.initDateRange(options.uptime);
+    this.getQxzObData();
+    this.getDeviceStatus();
+    this.getDeviceData();
+  },
+  data() {
+    return {
+      deviceInfo: {},
+      activeTab: "monitoring",
+      monitorList: [],
+      statusList: [],
+      show: false,
+      mode: "range",
+      startDate: "",
+      endDate: "",
+      page: 1,
+      pageSize: 9,
+      total: 0,
+      tableData: [],
+      tableColumn: [],
+    };
+  },
+  computed: {
+    totalPages() {
+      return Math.ceil(this.total / this.pageSize) || 1;
+    },
+  },
+  methods: {
+    formatTimestamp(timestamp) {
+      if (!timestamp) return "";
+      const date = new Date(Number(timestamp) * 1000);
+      const year = date.getFullYear();
+      const month = String(date.getMonth() + 1).padStart(2, "0");
+      const day = String(date.getDate()).padStart(2, "0");
+      const hours = String(date.getHours()).padStart(2, "0");
+      const minutes = String(date.getMinutes()).padStart(2, "0");
+      const seconds = String(date.getSeconds()).padStart(2, "0");
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+    },
+    formatDate(date) {
+      const year = date.getFullYear();
+      const month = String(date.getMonth() + 1).padStart(2, "0");
+      const day = String(date.getDate()).padStart(2, "0");
+      return `${year}-${month}-${day}`;
+    },
+    initDateRange(timestamp) {
+      if (!timestamp) {
+        const today = new Date();
+        this.endDate = this.formatDate(today);
+        const startDate = new Date(today);
+        startDate.setDate(startDate.getDate() - 7);
+        this.startDate = this.formatDate(startDate);
+        return;
+      }
+      const date = new Date(Number(timestamp) * 1000);
+      this.endDate = this.formatDate(date);
+      const startDate = new Date(date);
+      startDate.setDate(startDate.getDate() - 7);
+      this.startDate = this.formatDate(startDate);
+    },
+    switchTab(tab) {
+      this.activeTab = tab;
+    },
+    copy(item) {
+      console.log(item);
+      uni.setClipboardData({
+        data: item,
+        success: function () {
+          console.log("success");
+        },
+      });
+    },
+    goPage(type, eleItem) {
+      let url = ''
+      if (eleItem && eleItem.key) {
+        url = `/pages/deviceDetails/weatherStation/${type}?deviceInfo=${encodeURIComponent(JSON.stringify(this.deviceInfo))}&eleKey=${eleItem.key}`
+      } else {
+        url = `/pages/deviceDetails/weatherStation/${type}?deviceInfo=${encodeURIComponent(JSON.stringify(this.deviceInfo))}`
+      }
+      uni.navigateTo({
+        url
+      });
+    },
+    openDatePicker() {
+      this.show = true;
+    },
+    onDateChange(event) {
+      if (event && event.startDate && event.endDate) {
+        this.startDate = event.startDate;
+        this.endDate = event.endDate;
+        this.show = false;
+        this.page = 1;
+        this.getDeviceData();
+      }
+    },
+    prevPage() {
+      if (this.page <= 1) return;
+      this.page--;
+      this.getDeviceData();
+    },
+    nextPage() {
+      if (this.page >= this.totalPages) return;
+      this.page++;
+      this.getDeviceData();
+    },
+    // 获取设备最新监测数据
+    async getQxzObData() {
+      const res = await this.$myRequest({
+        url: "/api/api_gateway?method=qxz.data.qxz_ob_last_data",
+        data: {
+          device_id: this.deviceInfo.devBid,
+        },
+      });
+      console.log("设备最新监测数据:", res);
+      const title = res.title
+      const data = res.data
+      const alias = res.alias
+      this.monitorList = this.formatChartData(title, data, alias)
+    },
+    formatChartData(obj, data, alias) {
+      const keys = Object.keys(obj);
+      const result = [];
+      console.log(data, 'datadata');
+      for (const prop of keys) {
+        const objArr = obj[prop];
+        if (objArr[4] == 1) {
+          result.push({
+            factorName: objArr[1],
+            key: prop,
+            yData: data[prop],
+            factorUnit: objArr[3],
+            newData: objArr[5],
+            alias: alias[prop]
+          });
+        }
+      }
+      console.log(result, 'real-time data');
+      return result;
+    },
+    convertDynamic(data, getLabelValue) {
+      if (!data || typeof data !== 'object') return [];
+      const result = [];
+      const keys = Object.keys(data);
+      for (const prop of keys) {
+        const arr = data[prop];
+        const value = getLabelValue(prop, arr, data);
+        if (value !== undefined && value !== null) {
+          result.push({
+            label: String(value),
+            prop,
+            align: 'center'
+          });
+        }
+      }
+      return result;
+    },
+    // 获取设备状态数据
+    async getDeviceStatus() {
+      const res = await this.$myRequest({
+        url: "/api/api_gateway?method=qxz.data.qxz_status",
+        data: {
+          device_id: this.deviceInfo.devBid,
+        },
+      });
+      console.log("getDeviceStatus:", res);
+      const newArr = this.transformObjectToArray(res);
+      this.statusList = newArr;
+      console.log(this.statusList, "getDevStatus");
+    },
+    transformObjectToArray(originalData) {
+      if (
+        typeof originalData !== "object" ||
+        originalData === null ||
+        Array.isArray(originalData)
+      ) {
+        return [];
+      }
+
+      return Object.keys(originalData).map((key) => {
+        const [val = "", label = ""] = originalData[key] || [];
+        return {
+          label,
+          val,
+          key,
+        };
+      });
+    },
+    // 设备数据列表
+    async getDeviceData() {
+      const data = await this.$myRequest({
+        url: "/api/api_gateway?method=qxz.data.qxz_device_data",
+        data: {
+          device_id: this.deviceInfo.devBid,
+          page: String(this.page),
+          page_size: String(this.pageSize),
+          start: String(Math.floor(new Date(this.startDate + " 00:00:00").getTime() / 1000)),
+          end: String(Math.floor(new Date(this.endDate + " 23:59:59").getTime() / 1000)),
+        },
+      });
+      console.log(data, "resss");
+      
+      if (Array.isArray(data) && data.length > 0) {
+        this.total = data[0]?.count || 0;
+        this.tableData = data[0].data || [];
+        const title = data[0].title;
+        this.tableColumn = title
+          .map((item) => {
+            return {
+              label: item[1],
+              prop: item[0],
+            };
+          })
+          .filter((item) => item.prop !== "uptime");
+      } else {
+        // 没数据时,设置为空
+        this.total = 0;
+        this.tableData = [];
+        this.tableColumn = [];
+      }
+      console.log(this.tableColumn, "tableCol");
+      console.log(this.tableData, "tableData");
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.device-details-page {
+  background:
+    linear-gradient(180deg, #ffffff00 0%, #f5f6fa 23.64%, #f5f6fa 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  min-height: 100vh;
+  padding: 0 32rpx;
+  padding-top: 98rpx;
+}
+
+/* 设备基本信息 */
+.device-info {
+  background-color: #ffffff;
+  margin: 46rpx 0 24rpx 0;
+  padding: 32rpx 24rpx;
+  border-radius: 16rpx;
+  background: linear-gradient(180deg, #eff 0%, #fff 23.56%);
+  position: relative;
+  .info-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 16rpx;
+  }
+  .info-item:last-child {
+    margin-bottom: 0;
+  }
+
+  .info-label {
+    width: 116rpx;
+    color: #999999;
+    text-align: right;
+    font-family: "Source Han Sans CN VF";
+    font-size: 28rpx;
+    font-style: normal;
+    font-weight: 400;
+    line-height: normal;
+    margin-right: 32rpx;
+    white-space: nowrap;
+  }
+
+  .info-value {
+    color: #333333;
+    font-family: "Source Han Sans CN VF";
+    font-size: 28rpx;
+    font-style: normal;
+    font-weight: 400;
+    line-height: normal;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
+  }
+  .info-img {
+    width: 32rpx;
+    height: 32rpx;
+    margin-left: 16rpx;
+    background: #0bbc581a;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .tishi {
+    width: 24rpx;
+    height: 24rpx;
+  }
+  .dev-status {
+    position: absolute;
+    right: 0;
+    top: 0;
+    border: 2rpx solid #ffffff;
+    background: #0bbc581a;
+    width: 152rpx;
+    height: 56rpx;
+    color: #0bbc58;
+    text-align: center;
+    font-size: 28rpx;
+    font-weight: 400;
+    line-height: 52rpx;
+    border-radius: 0 16rpx 0 64rpx;
+  }
+}
+
+/* 标签页切换 */
+.tab-container {
+  background-color: #ffffff;
+  border-radius: 16rpx;
+  overflow: hidden;
+  padding: 0 32rpx;
+  margin-bottom: 24rpx;
+  .tab-top {
+    display: flex;
+  }
+  .tab-item {
+    flex: 1;
+    height: 80rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    position: relative;
+    color: #666666;
+    text-align: center;
+    font-family: "Source Han Sans CN VF";
+    font-size: 28rpx;
+    font-style: normal;
+    font-weight: 400;
+    line-height: normal;
+    .tab-text {
+      margin-top: 16rpx;
+    }
+    .smile {
+      width: 24rpx;
+      height: 18rpx;
+    }
+  }
+
+  .tab-item.active {
+    color: #333333;
+    font-weight: 700;
+  }
+
+  .time-board {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 16rpx;
+  }
+  .time-filter {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 256rpx;
+    height: 48rpx;
+    padding: 6rpx 8rpx;
+    border-radius: 32rpx;
+    background: #f1f4f8;
+    color: #303133;
+    font-size: 20rpx;
+    font-weight: 400;
+    .filter-item {
+      padding: 4rpx 16rpx;
+      height: 36rpx;
+      line-height: 36rpx;
+    }
+    .active {
+      border-radius: 32rpx;
+      background: #fff;
+    }
+  }
+}
+
+/* 监测要素页面 */
+.monitoring-page {
+  padding-bottom: 20px;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  .data-card {
+    width: calc(50% - 8rpx);
+    margin-bottom: 16rpx;
+    background-color: #ffffff;
+    border-radius: 16rpx;
+    padding: 16rpx 24rpx;
+    height: 186rpx;
+    font-family: "Source Han Sans CN VF";
+    font-size: 28rpx;
+    font-weight: 400;
+    box-sizing: border-box;
+    .card-title {
+      color: #042118;
+      margin-bottom: 6rpx;
+    }
+    .data-value-row {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      color: #042118;
+      font-family: "Source Han Sans CN VF";
+      font-weight: 400;
+      .data-value {
+        font-size: 40rpx;
+        font-weight: 700;
+        margin-right: 8rpx;
+      }
+      .data-unit {
+        font-size: 24rpx;
+      }
+      .device-img {
+        width: 52rpx;
+        height: 52rpx;
+      }
+    }
+    .card-thrid {
+      color: #687a74;
+      margin-top: 6rpx;
+    }
+  }
+}
+/* 设备详情页面 */
+.details-page {
+  .device-params {
+    background-color: #ffffff;
+    border-radius: 16rpx;
+    padding: 32rpx;
+    margin-bottom: 24rpx;
+    .device-control {
+      position: relative;
+      z-index: 3;
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      margin-bottom: 24rpx;
+      .control-left {
+        color: #999999;
+        font-family: "Source Han Sans CN VF";
+        font-size: 28rpx;
+        display: flex;
+        align-items: center;
+        .reload-img {
+          font-size: 32rpx;
+          color: #0bbc58;
+          margin-left: 14rpx;
+        }
+      }
+      .control-right {
+        display: flex;
+        align-items: center;
+        .control-img {
+          width: 48rpx;
+          height: 48rpx;
+          margin-left: 24rpx;
+        }
+      }
+    }
+    .params-board {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      position: relative;
+      .params-left {
+        display: flex;
+        flex-wrap: wrap;
+        .params-item {
+          display: flex;
+          flex-direction: column;
+          width: 100%;
+          // width: calc(50% - 20rpx);
+          margin-bottom: 24rpx;
+          .params-val {
+            color: #303133;
+            font-size: 28rpx;
+            font-weight: 700;
+          }
+          .params-label {
+            color: #999999;
+            font-size: 24rpx;
+            font-weight: 400;
+          }
+        }
+      }
+      .params-right {
+        position: absolute;
+        right: 0;
+        .device-img {
+          width: 150rpx;
+        }
+      }
+    }
+  }
+
+  .table-container {
+    padding: 16rpx 32rpx 32rpx 32rpx;
+    border-radius: 16rpx;
+    background: #fff;
+    .table-control {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 16rpx;
+      .title {
+        color: #042118;
+        font-family: "Source Han Sans CN VF";
+        font-size: 28rpx;
+        font-style: normal;
+        font-weight: 700;
+        line-height: normal;
+      }
+      .date-board {
+        display: flex;
+        align-items: center;
+        color: #020305;
+        font-family: "Source Han Sans CN VF";
+        font-size: 24rpx;
+        font-weight: 400;
+        border-radius: 32rpx;
+        background: #f1f4f8;
+        padding: 7rpx 24rpx;
+        .line {
+          color: #656565;
+          margin: 0 10rpx;
+        }
+        .date-icon {
+          width: 32rpx;
+          height: 32rpx;
+          margin-left: 16rpx;
+        }
+      }
+    }
+    .table-wrap {
+      display: flex;
+      width: 100%;
+      height: 788rpx;
+      box-sizing: border-box;
+      margin: 20rpx 0;
+      color: #042118;
+      font-family: "Source Han Sans CN VF";
+      font-size: 24rpx;
+      font-style: normal;
+      font-weight: 400;
+      line-height: normal;
+      .fixed-column {
+        width: 250rpx;
+        .table-cell {
+          width: 100%;
+          white-space: nowrap;
+        }
+      }
+      .table-bg {
+        width: 16rpx;
+        background: linear-gradient(270deg, #ffffff33 0%, #9598a433 100%);
+      }
+      .scroll-column {
+        flex: 1;
+        height: auto;
+        overflow: hidden;
+        margin-left: -10rpx;
+      }
+      .scroll-content {
+        min-width: 100%;
+        width: fit-content;
+        display: flex;
+        flex-direction: column;
+        .table-row {
+          display: flex;
+          .table-cell {
+            flex: 1;
+          }
+        }
+      }
+      .table-cell {
+        width: 160rpx;
+        height: 80rpx;
+        line-height: 80rpx;
+        text-align: center;
+        border-bottom: 2px solid #e4e7ed;
+        box-sizing: border-box;
+        overflow: hidden;
+        padding: 0 4rpx;
+        text-overflow: ellipsis;
+      }
+      .table-cell.header {
+        background: #f6f8fc;
+      }
+    }
+
+    .pagination {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-top: 24rpx;
+      .page-item {
+        width: 104rpx;
+        height: 48rpx;
+        color: #656565;
+        font-size: 24rpx;
+        line-height: 48rpx;
+        text-align: center;
+        border: 2rpx solid #e4e7ed;
+        border-radius: 8rpx;
+      }
+      .prev.disabled {
+        color: #c0c4cc;
+        border-color: #e4e7ed;
+      }
+      .next {
+        color: #0bbc58;
+        border: 2px solid #0bbc58;
+      }
+      .next.disabled {
+        color: #c0c4cc;
+        border-color: #e4e7ed;
+      }
+      .page-info {
+        color: #999999;
+        font-family: "Source Han Sans CN VF";
+        font-size: 24rpx;
+        font-style: normal;
+        font-weight: 400;
+        line-height: normal;
+        .curret-page {
+          color: #303133;
+        }
+      }
+    }
+
+    .empty-state {
+      padding: 80rpx 0;
+    }
+  }
+}
+::v-deep .u-calendar__action {
+  display: flex;
+  justify-content: center;
+}
+</style>

+ 342 - 0
pages/deviceDetails/weatherStation/simDetail.vue

@@ -0,0 +1,342 @@
+<template>
+  <view class="sim-details-page">
+    <cu-custom :isBack="true">
+      <template slot="content">
+        <view class="nav-title">SIM卡详情</view>
+      </template>
+    </cu-custom>
+    <!-- 加载动画 -->
+    <view v-if="loading" class="loading-container">
+      <u-loading mode="circle"></u-loading>
+      <text class="loading-text">加载中...</text>
+    </view>
+    <!-- 页面内容 -->
+    <view v-else>
+      <view class="sim-first sim-board">
+        <view class="title">数据SIM卡流量</view>
+        <view class="sim-item">
+          <text class="label">ICCID:</text>
+          <span class="val">{{ simData.iccid }}</span>
+          <image
+            @click="copy(simData.iccid)"
+            src="/static/images/device/copy.svg"
+            mode=""
+            class="info-img"
+          ></image>
+        </view>
+        <view class="sim-item">
+          <text class="label">总流量:</text>
+          <span class="val">{{ simData.total }}</span>
+        </view>
+        <view class="sim-item">
+          <text class="label">状态:</text>
+          <text class="val">{{ simData.status }}</text>
+        </view>
+        <view class="sim-item">
+          <text class="label">到期时间:</text>
+          <text class="val">{{ simData.expire }}</text>
+        </view>
+        <view class="sim-item">
+          <text class="label">厂商名称:</text>
+          <text class="val">{{ simData.company }}</text>
+        </view>
+        <view class="sim-info-count">
+          <view class="sim-item">
+            <text class="label">已使用:</text
+            ><text
+              :style="{
+                color:
+                  simData.used > parseInt(simData.total) ? '#f56c6c' : '#14A478',
+              }"
+              >{{ simData.used.toFixed(2) }}M</text
+            >/{{ simData.total }}
+          </view>
+          <view class="sim-item">
+            <text class="label">剩余:</text>
+            <text
+              class="val"
+              :style="{
+                color: '#14A478',
+              }"
+              >{{ (parseInt(simData.total) - simData.used).toFixed(2) }}M</text
+            >
+          </view>
+        </view>
+      </view>
+      <view v-if="simIccidObj.photo_iccid || simIccidObj.is_editor" class="sim-board sim-second">
+        <view class="title">图片SIM卡流量</view>
+        <view class="sim-item">
+          <text class="label">ICCID:</text>
+          <span v-if="!isEditing" class="val">{{ simData.iccid }}</span>
+          <input
+            v-else
+            v-model="editingIccid"
+            type="text"
+            class="edit-input"
+            placeholder="请输入新的ICCID"
+          />
+          <image
+            @click="copy(isEditing ? editingIccid : simData.iccid)"
+            src="/static/images/device/copy.svg"
+            mode=""
+            class="info-img"
+          ></image>
+          <image
+            v-if="!isEditing"
+            @click="toggleEdit"
+            src="/static/images/device/edit.svg"
+            mode=""
+            class="info-img"
+          ></image>
+          <button v-else @click="saveEditIccid" class="save-btn">确定</button>
+        </view>
+      </view>
+      <view class="footer-board">
+        <u-button type="success" class="sub-btn" @click="goBack"
+          >确定</u-button
+        >
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  onLoad(options) {
+    this.loading = true
+    const deviceInfo = JSON.parse(decodeURIComponent(options.deviceInfo));
+    console.log(deviceInfo, "deviceInfo");
+    this.deviceInfo = deviceInfo;
+    this.getIccidByd_id();
+  },
+  data() {
+    return {
+      deviceInfo: {},
+      simData: {
+        iccid: "",
+        total: "",
+        status: "",
+        expire: "",
+        company: "",
+        used: 0,
+      },
+      isEditing: false,
+      editingIccid: "",
+      showSimData: false,
+      empty: false,
+      simIccidObj: {},
+      loading: false,
+    };
+  },
+  methods: {
+    getIccidByd_id() {
+      this.$myRequest({
+        url: "/api/api_gateway?method=forecast.send_control.device_sim_new",
+        data: {
+          d_id: this.deviceInfo.d_id,
+        },
+      }).then((res) => {
+        console.log('getIccidByd_id:', res);
+        if (
+          res.data_iccid ||
+          res.photo_iccid ||
+          res.is_editor
+        ) {
+          console.log(res, '1111')
+          this.empty = false;
+          this.simIccidObj = res;
+          if (res.data_iccid) {
+            this.active = "data_iccid";
+            console.log(222)
+            this.getSimData(res.data_iccid);
+          } else {
+            if (res.photo_iccid || res.is_editor) {
+              this.active = "photo_iccid";
+              if (res.photo_iccid) {
+                this.getSimData(res.photo_iccid);
+              } else {
+                this.loading = false;
+              }
+            }
+          }
+        } else {
+          this.empty = true;
+          this.loading = false;
+        }
+      });
+    },
+    getSimData(iccid) {
+      this.$myRequest({
+        url: "/api/api_gateway?method=forecast.send_control.sim_query_new",
+        data: {
+          iccid: iccid
+        }
+      }).then(res => {
+        console.log('simData:', res)
+        this.loading = false
+        this.simData = res
+        if (res.code) {
+          this.showSimData = false
+          // this.$message.error(res.data.data.msg)
+        } else {
+          this.showSimData = true
+          this.simData = res
+          this.editIccid = res.iccid
+        }
+      })
+    },
+    copy(item) {
+      console.log(item);
+      uni.setClipboardData({
+        data: item,
+        success: function () {
+          console.log("success");
+        },
+      });
+    },
+    toggleEdit() {
+      this.isEditing = !this.isEditing;
+      if (this.isEditing) {
+        this.editingIccid = this.simData.iccid;
+      }
+    },
+    saveIccid() {
+      this.simData.iccid = this.editingIccid;
+      this.isEditing = false;
+    },
+    saveEditIccid() {
+      this.$myRequest({
+        url: '/api/api_gateway?method=forecast.send_control.device_sim_update',
+        data: {
+          d_id: this.deviceInfo.d_id,
+          simid: this.editingIccid
+        }
+      }).then(res => {
+        if (res.code) {
+          this.isEditSim = false
+          this.loading = true
+          // this.$message.success(res.data.data.msg)
+          this.simIccidObj.photo_iccid = this.editingIccid
+          this.getSimData(this.editingIccid)
+        } else {
+          // this.$message.error(res.data.data.msg)
+        }
+        this.isEditing = false;
+      })
+    },
+    goBack() {
+      uni.navigateBack({
+        delta: 1,
+      })
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.sim-details-page {
+  background:
+    linear-gradient(180deg, #ffffff00 0%, #f5f6fa 23.64%, #f5f6fa 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  min-height: 100vh;
+  padding: 0 32rpx;
+  padding-top: 98rpx;
+  box-sizing: border-box;
+}
+/* 加载动画样式 */
+.loading-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 60vh;
+  width: 100%;
+}
+.loading-text {
+  font-size: 28rpx;
+  color: #666;
+  margin-top: 32rpx;
+}
+.sim-board {
+  padding: 32rpx;
+  border-radius: 16rpx;
+  background: #fff;
+  margin-top: 46rpx;
+  margin-bottom: 24rpx;
+  .title {
+    color: #020305;
+    font-size: 32rpx;
+    font-weight: 500;
+    margin-bottom: 24rpx;
+  }
+  .sim-item {
+    font-size: 28rpx;
+    display: flex;
+    align-items: center;
+    margin-bottom: 24rpx;
+    .label {
+      color: #999999;
+    }
+    .val {
+      color: #303133;
+    }
+    .copy-icon,
+    .edit-icon {
+      width: 32rpx;
+      height: 32rpx;
+    }
+  }
+  .sim-info-count {
+    display: flex;
+    justify-content: space-between;
+  }
+}
+.footer-board {
+  border-top: 2rpx solid #e4e7ed;
+  background: #fff;
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 164rpx;
+  padding: 16rpx 32rpx 0 32rpx;
+  .sub-btn {
+    width: 100%;
+    background: #0bbc58;
+    border-radius: 16rpx;
+  }
+}
+.info-img {
+  width: 32rpx;
+  height: 32rpx;
+  margin-left: 16rpx;
+  background: #0bbc581a;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+.edit-input {
+  flex: 1;
+  height: 48rpx;
+  border: 2rpx solid #0bbc58;
+  border-radius: 8rpx;
+  padding: 0 16rpx;
+  font-size: 28rpx;
+  color: #303133;
+  background-color: #f5f7fa;
+}
+.save-btn {
+  margin-left: 16rpx;
+  padding: 8rpx 20rpx;
+  background-color: #0bbc58;
+  color: #fff;
+  border: none;
+  border-radius: 8rpx;
+  font-size: 24rpx;
+  height: 48rpx;
+  line-height: 28rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+</style>

+ 21 - 12
pages/equipList/index.vue

@@ -55,7 +55,8 @@
               <p class="p1">
                 <image
                   :src="
-                    $imageURL+'/bigdata_app/image/fourMoodBase/' +
+                    $imageURL +
+                    '/bigdata_app/image/fourMoodBase/' +
                     type_id +
                     '.png'
                   "
@@ -123,7 +124,8 @@
     <view class="top" v-if="isTop" @click="top">
       <image
         :src="
-          $imageURL+ '/bigdata_app' +
+          $imageURL +
+          '/bigdata_app' +
           '/image/6209a98f0cb3b5086f2ca36152c9269.png'
         "
         mode=""
@@ -396,23 +398,25 @@ export default {
           uni.navigateTo({
             url:
               '/pages/webview?device_id=' +
-              item.imei +
-              '&accessToken=' +uni
-              .getStorageSync('session_key') ||
-              this.accessToken,
+                item.imei +
+                '&accessToken=' +
+                uni.getStorageSync('session_key') || this.accessToken,
           });
           break;
         case 43:
           uni.navigateTo({
-            url: "/pages/fmSys/details?info=" + JSON.stringify(item)
-          })
+            url: '/pages/fmSys/details?info=' + JSON.stringify(item),
+          });
           break;
         case 44:
           uni.navigateTo({
-            url: "/pages/webviewdgp?device_id=" + item.imei + "&accessToken=" +  uni
-              .getStorageSync('session_key') +
-              '&type=dgp'
-          })
+            url:
+              '/pages/webviewdgp?device_id=' +
+              item.imei +
+              '&accessToken=' +
+              uni.getStorageSync('session_key') +
+              '&type=dgp',
+          });
           break;
         case 3:
           item.addtime = item.uptime;
@@ -625,6 +629,11 @@ export default {
             url: `../cb/wenshizs/detail?devBid=${item.devBid}&devName=${item.device_name}&devStatus=${item.devStatus}`,
           });
           break;
+        case 46:
+          uni.navigateTo({
+            url: `../deviceDetails/weatherStation/index?devBid=${item.imei}&devName=${item.device_name}&devStatus=${item.is_online}&address=${item.address}&uptime=${item.uptime}&d_id=${item.d_id}`,
+          });
+          break;
         // case 45:
         //   item.addtime = item.uptime;
         //    uni.navigateTo({

Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/HUMIA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/HUMIA-warning.svg


Разлика између датотеке није приказан због своје велике величине
+ 7 - 0
static/images/device/ILLUA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 7 - 0
static/images/device/ILLUA-warning.svg


Разлика између датотеке није приказан због своје велике величине
+ 5 - 0
static/images/device/PRECA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 5 - 0
static/images/device/PRECA-warning.svg


Разлика између датотеке није приказан због своје велике величине
+ 4 - 0
static/images/device/PRESA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 4 - 0
static/images/device/PRESA-warning.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/SM01A-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/STEMC-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/TEMPA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/TEMPA-warning.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/WDIRA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/WDIRA-warning.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/WSPDA-default.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 0
static/images/device/WSPDA-warning.svg


+ 3 - 0
static/images/device/copy.svg

@@ -0,0 +1,3 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="design-iconfont">
+  <path fill-rule="evenodd" clip-rule="evenodd" d="M12.6667 2.66634H6.66667V1.33301H12.6667C13.403 1.33301 14 1.92996 14 2.66634V9.99967H12.6667V2.66634ZM2 5.33301C2 4.59663 2.59695 3.99967 3.33333 3.99967H10C10.735 3.99967 11.3333 4.59415 11.3333 5.33193V13.3358C11.3333 14.0748 10.7347 14.6663 10.0009 14.6663H3.33184C2.59351 14.6663 2 14.0674 2 13.333V5.33301ZM10 5.33301H3.33333V13.333H10V5.33301Z" fill="#0BBC58"/>
+</svg>

Разлика између датотеке није приказан због своје велике величине
+ 10 - 0
static/images/device/date-active.svg


Разлика између датотеке није приказан због своје велике величине
+ 10 - 0
static/images/device/date.svg


Разлика између датотеке није приказан због своје велике величине
+ 559 - 0
static/images/device/dev-station.svg


+ 4 - 0
static/images/device/edit.svg

@@ -0,0 +1,4 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="design-iconfont">
+  <path d="M0 2C0 0.895431 0.895431 0 2 0H14C15.1046 0 16 0.895431 16 2V14C16 15.1046 15.1046 16 14 16H2C0.895431 16 0 15.1046 0 14V2Z" fill="#0BBC58" fill-opacity=".1"/>
+  <path fill-rule="evenodd" clip-rule="evenodd" d="M11.1044 1.2627L14.4043 4.56253L5.01663 13.9502H1.7168V10.6503L11.1044 1.2627ZM3.05013 11.2026V12.6168H4.46434L10.8687 6.21244L9.45453 4.79823L3.05013 11.2026ZM10.3973 3.85542L11.8116 5.26963L12.5187 4.56253L11.1044 3.14831L10.3973 3.85542Z" fill="#1FC676"/>
+</svg>

+ 3 - 0
static/images/device/smile.svg

@@ -0,0 +1,3 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 5" class="design-iconfont">
+  <path d="M1.2002 1.2002C1.2002 1.2002 2.86054 3.32795 6.18716 3.32795C9.51379 3.32795 11.2002 1.2002 11.2002 1.2002" stroke="#0BBC58" stroke-width="2.4" stroke-linecap="round"/>
+</svg>

Разлика између датотеке није приказан због своје велике величине
+ 18 - 0
static/images/device/冻土.svg