Преглед изворни кода

feat(weatherStation1): add weather station device pages and adjust config

1. 新增气象站设备详情相关页面:charts、devControl、simDetail、devRepair、eleDetail
2. 调整应用名称从“云飞智控”改为“智控”
3. 切换到非云飞智控模式,修改环境配置为测试/生产环境
4. 更新设备列表跳转路径至新的气象站页面
5. 添加qxz_low.png设备图片资源
allen пре 9 часа
родитељ
комит
2f176f8967

+ 1 - 1
manifest.json

@@ -1,5 +1,5 @@
 {
-    "name" : "云飞智控",
+    "name" : "智控",
     "appid" : "__UNI__DBA6730",
     "description" : "",
     "versionName" : "1.15.20",

+ 36 - 0
pages.json

@@ -1280,6 +1280,42 @@
         "navigationStyle": "custom"
       }
     },
+    
+    {
+      "path": "pages/deviceDetails/weatherStation1/index",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation1/devControl",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation1/simDetail",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation1/devRepair",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/deviceDetails/weatherStation1/eleDetail",
+      "style": {
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/warning/index",
       "style": {

+ 121 - 0
pages/deviceDetails/weatherStation1/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/weatherStation1/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('RC_LOC')">定位</u-button>
+      </div>
+      <u-button type="success" class="reload-btn" @click="handleControl('RC_IN')">长在线</u-button>
+      <view class="title date-title">数据传输间隔(min)</view>
+      <view class="date-slider">
+        <slider
+          v-model="interval"
+          show-value="true"
+          :min="1"
+          :max="240"
+          @change="changeDataInterval"
+          block-color="#57C878"
+          activeColor="#57C878"
+          step="1"
+        />
+      </view>
+       <u-button type="success" class="sub-btn" @click="handleControl('interval')">确定</u-button>
+    </view>
+    <!-- <view class="footer-board">
+      <u-button type="success" class="sub-btn" @click="handleSubmit()">确定</u-button>
+    </view> -->
+  </view>
+</template>
+
+<script>
+export default {
+  onLoad(options) {
+    const deviceInfo = JSON.parse(decodeURIComponent(options.deviceInfo));
+    console.log(deviceInfo, "deviceInfo");
+    this.deviceInfo = deviceInfo;
+    this.getDevControlParams();
+  },
+  data() {
+    return {
+      deviceInfo: {},
+      interval: "",
+    };
+  },
+  methods: {
+    changeDataInterval(v){
+      this.interval = v.detail.value
+    },
+    // 获取设备控制参数信息
+    async getDevControlParams() {
+      await this.$myRequest({
+        url: '/api/api_gateway?method=greenhouse.env_first.control_device',
+        data: {
+          device_id: this.deviceInfo.devBid,
+        }
+      }).then(res => {
+        console.log('设备控制参数信息', res)
+        this.interval = res.interval
+      })
+    },
+    async handleControl(cmd) {
+      let params = {};
+      if(cmd == 'interval'){
+        params = {
+          device_id: this.deviceInfo.devBid,
+          interval: this.interval,
+        };
+      }else{
+        params = {
+          device_id: this.deviceInfo.devBid,
+          order: cmd,
+        };
+      }
+      await this.$myRequest({
+        url: '/api/api_gateway?method=greenhouse.env_first.send_control',
+        data: params
+      }).then(res => {
+        console.log('设备控制参数信息', res)
+        uni.showToast({
+          title: "操作成功",
+          icon: "none",
+        });
+      })
+    },
+    async handleSubmit() {
+      await this.handleControl('STORAGE_INR');
+      await 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;
+}
+.nav-title{
+  text-align: center;
+}
+.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/weatherStation1/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>

+ 837 - 0
pages/deviceDetails/weatherStation1/eleDetail.vue

@@ -0,0 +1,837 @@
+<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" 
+      range-color="#999"
+      btn-type="success"
+      active-bg-color="#0BBC58"
+      range-bg-color="rgba(11,188,88,0.13)"
+    ></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
+          v-show="!show"
+          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.time }}
+          </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.key] }}</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));
+    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: [],
+      titles: [],
+      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");
+      // u-charts 的 series.data 必须是数字数组;原数据 value 为字符串(含 "/"、"NA"),
+      // 直接传对象数组会导致 Y 轴 min/max 计算异常,刻度全部相同
+      const seriesData = currentEle.data.map((item) => {
+        const val = item.value;
+        if (val === "/" || val === "NA" || val === null || val === undefined || val === "") {
+          return 0;
+        }
+        const num = Number(val);
+        return isNaN(num) ? 0 : num;
+      });
+      const series = [
+        {
+          name: currentEle.name,
+          data: seriesData,
+          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: {
+          tofix: 2,
+          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];
+      const key = this.activeChartInfo.unit ? this.activeChartInfo.name + '(' + this.activeChartInfo.unit + ')' : this.activeChartInfo.name
+      const keyValue = this.getKeyByName(key)
+      this.activeChartInfo.key = keyValue
+      this.isFolded = true; // 关闭展开面板
+      this.$nextTick(() => {
+        this.initChart();
+      });
+    },
+    getKeyByName(key){
+      const titles = [...this.titles]
+      let k
+      titles.forEach(title => {
+        if(title.name === key){
+          k = title.key
+        }
+      })
+      return k
+    },
+    // 切换要素展开/收起状态
+    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=greenhouse.env_first.monitor_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: 1,
+          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.name === this.eleKey) ||
+            this.eleTabs[0];
+          this.eleActive = this.eleTabs.indexOf(this.activeChartInfo);
+          const key = this.activeChartInfo.unit ? this.activeChartInfo.name + '(' + this.activeChartInfo.unit + ')' : this.activeChartInfo.name
+          const keyValue = this.getKeyByName(key)
+          this.activeChartInfo.key = keyValue
+          this.$nextTick(() => {
+            this.initChart();
+          });
+        } else {
+          this.eleTabs = [];
+          this.hasData = false;
+        }
+      });
+    },
+    // 历史数据
+    getObData() {
+      this.$myRequest({
+        url: "/api/api_gateway?method=greenhouse.env_first.history_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.table;
+        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.titles = res?.title || [];
+        this.tableList = newData;
+        this.total = res.total;
+        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;
+}
+.nav-title{
+  text-align: center;
+}
+.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;
+      display: none;
+    }
+  }
+  /* 展开后的要素容器样式 */
+  .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;
+    height: 336rpx;
+    z-index:0;
+    .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>

Разлика између датотеке није приказан због своје велике величине
+ 1009 - 0
pages/deviceDetails/weatherStation1/index.vue


+ 345 - 0
pages/deviceDetails/weatherStation1/simDetail.vue

@@ -0,0 +1,345 @@
+<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 }}M</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' : '#0bbc58',
+              }"
+              >{{ simData.used.toFixed(2) }}M</text
+            >/{{ simData.total }}M
+          </view>
+          <view class="sim-item">
+            <text class="label">剩余:</text>
+            <text
+              class="val"
+              :style="{
+                color: '#0bbc58',
+              }"
+              >{{ (parseInt(simData.total || 0) - 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;
+}
+.nav-title{
+  text-align: center;
+}
+.sim-board {
+  padding: 32rpx;
+  border-radius: 16rpx;
+  background: #fff;
+  margin-top: 46rpx;
+  margin-bottom: 24rpx;
+  .title {
+    color: #020305;
+    font-size: 32rpx;
+    font-weight: 700;
+    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>

+ 12 - 9
pages/equipList2/index.vue

@@ -362,17 +362,20 @@
 						}
 						break;
 					case 38:
-						var obj = {};
-						obj.d_id = item.d_id;
-						obj.equip_id = item.id;
-						obj.is_online = item.status;
-						obj.lat = item.lat;
-						obj.lng = item.lng;
-						obj.equip_name = item.name;
-						obj.uptime = item.uptime;
 						uni.navigateTo({
-							url: '../environment/equipment-new?shebei=' + JSON.stringify(obj),
+							url: `../deviceDetails/weatherStation1/index?devBid=${item.id}&devName=${item.name}&devStatus=${item.status}&address=${item.address}&uptime=${item.uptime}&d_id=${item.d_id}&deviceType=46`,
 						});
+						// var obj = {};
+						// obj.d_id = item.d_id;
+						// obj.equip_id = item.id;
+						// obj.is_online = item.status;
+						// obj.lat = item.lat;
+						// obj.lng = item.lng;
+						// obj.equip_name = item.name;
+						// obj.uptime = item.uptime;
+						// uni.navigateTo({
+						// 	url: '../environment/equipment-new?shebei=' + JSON.stringify(obj),
+						// });
 						break;
 					case 5:
 						var obj = {};

BIN
static/images/device/qxz_low.png


+ 2 - 2
util/neutral.js

@@ -1,6 +1,6 @@
 export default {
-  isneutral:true,//云飞智控
-  // isneutral: false, //智控
+  // isneutral:true,//云飞智控
+  isneutral: false, //智控
   developAPI:'https://uat.hnyfwlw.com',//测试环境访问地址
   // productAPI:'http://8.136.98.49:8002',//生产环境
   productAPI:'https://web.hnyfwlw.com',//生产环境