Sfoglia il codice sorgente

feat(设备管理): 新增设备详情、控制及图片查看功能

- 添加设备详情页面,包含害虫分析、查看图片和设备数据三个标签页
- 实现设备控制页面,支持联网模块、板子设置和强制操作功能
- 新增图片查看页面,支持日期筛选、图片预览和害虫识别结果展示
- 添加多个SVG图标资源用于界面展示
- 更新pages.json配置新增相关页面路由
- 优化设备卡片组件,增加在线状态显示和复制设备ID功能
- 使用uCharts实现害虫数据分析图表
allen 13 ore fa
parent
commit
a09e7e3843

+ 31 - 4
pages.json

@@ -23,11 +23,12 @@
 		// 	}
 		// },
 		{
-			"path": "pages/equipList/index",
+			"path": "pages/equipList2/index",
 			"style": {
 				"navigationBarTitleText": "设备列表",
 				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#00B075"
+				"navigationBarBackgroundColor": "#00B075",
+				"navigationStyle": "custom"
 			}
 		},
 		{
@@ -58,6 +59,32 @@
 			]
 		},
 		{
+			"root": "pages/cbd",
+			"pages": [{
+					"path": "detail", 
+					"style": {
+						"navigationBarTitleText": "设备详情",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				},{
+					"path": "deviceControl",
+					"style": {
+						"navigationBarTitleText": "设备控制",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				},{
+					"path": "devicePhoto",
+					"style": {
+						"navigationBarTitleText": "查看图片",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				}
+			]
+		},
+		{
 			"root": "pages/cb/shuifeizs",
 			"pages": [{
 					"path": "shuifeizs",
@@ -810,7 +837,7 @@
 			]
 		},
 		{
-			"root": "pages/equipList/seabox",
+			"root": "pages/equipList2/seabox",
 			"pages": [{
 					"path": "search",
 					"style": {
@@ -1379,7 +1406,7 @@
 				"text": "首页"
 			},
 			{
-				"pagePath": "pages/equipList/index",
+				"pagePath": "pages/equipList2/index",
 				"iconPath": "static/images/tabBar/device.png",
 				"selectedIconPath": "static/images/tabBar/devicesel.png",
 				"text": "设备列表"

File diff suppressed because it is too large
+ 3 - 0
pages/assets/album.svg


File diff suppressed because it is too large
+ 3 - 0
pages/assets/analyze.svg


BIN
pages/assets/camera.png


+ 18 - 0
pages/assets/gate-close.svg

@@ -0,0 +1,18 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 33" class="design-iconfont">
+  <path d="M6.8999 0.564453H26.1001C29.4135 0.564453 32.1 3.25006 32.1001 6.56348V25.7637C32.1001 29.0772 29.4136 31.7637 26.1001 31.7637H6.8999C3.58648 31.7635 0.900879 29.0771 0.900879 25.7637V6.56348C0.901009 3.25014 3.58656 0.564585 6.8999 0.564453Z" fill="url(#j6a32c69d__paint0_linear_5004_276254)"/>
+  <path d="M6.8999 0.564453H26.1001C29.4135 0.564453 32.1 3.25006 32.1001 6.56348V25.7637C32.1001 29.0772 29.4136 31.7637 26.1001 31.7637H6.8999C3.58648 31.7635 0.900879 29.0771 0.900879 25.7637V6.56348C0.901009 3.25014 3.58656 0.564585 6.8999 0.564453Z" stroke="url(#j6a32c69d__paint1_linear_5004_276254)" stroke-width=".799957"/>
+  <path fill="#14A478" d="M10.9004 16.9648H22.1004V24.1648H10.9004z"/>
+  <path fill="#14A478" d="M10.1006 8.16406H22.9006V9.764059999999999H10.1006z"/>
+  <path fill="#14A478" d="M8.50049 8.16406H10.100489999999999V24.16406H8.50049z"/>
+  <path fill="#14A478" d="M22.9004 8.16406H24.500400000000003V24.16406H22.9004z"/>
+  <defs>
+    <linearGradient id="j6a32c69d__paint0_linear_5004_276254" x1="16.5001" y1=".164062" x2="16.5001" y2="32.1634" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#B4E7D7" stop-opacity=".68"/>
+      <stop offset="1" stop-color="#fff"/>
+    </linearGradient>
+    <linearGradient id="j6a32c69d__paint1_linear_5004_276254" x1="16.5001" y1=".164062" x2="16.5001" y2="32.1634" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#fff"/>
+      <stop offset="1" stop-color="#fff" stop-opacity=".21"/>
+    </linearGradient>
+  </defs>
+</svg>

+ 18 - 0
pages/assets/gate-open.svg

@@ -0,0 +1,18 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 33" class="design-iconfont">
+  <rect x=".900955" y=".564041" width="31.1983" height="31.1983" rx="5.99968" fill="url(#3l8fw57bd__paint0_linear_5004_276244)"/>
+  <rect x=".900955" y=".564041" width="31.1983" height="31.1983" rx="5.99968" stroke="url(#3l8fw57bd__paint1_linear_5004_276244)" stroke-width=".799957"/>
+  <path fill="#14A478" d="M10.9004 10.5645H22.099800000000002V17.764120000000002H10.9004z"/>
+  <path fill="#14A478" d="M10.1001 8.16406H22.8994V9.763969999999999H10.1001z"/>
+  <path fill="#14A478" d="M8.50049 8.16406H10.100399999999999V24.163159999999998H8.50049z"/>
+  <path fill="#14A478" d="M22.8994 8.16406H24.49931V24.163159999999998H22.8994z"/>
+  <defs>
+    <linearGradient id="3l8fw57bd__paint0_linear_5004_276244" x1="16.5001" y1=".164062" x2="16.5001" y2="32.1624" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#B4E7D7" stop-opacity=".68"/>
+      <stop offset="1" stop-color="#fff"/>
+    </linearGradient>
+    <linearGradient id="3l8fw57bd__paint1_linear_5004_276244" x1="16.5001" y1=".164062" x2="16.5001" y2="32.1624" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#fff"/>
+      <stop offset="1" stop-color="#fff" stop-opacity=".21"/>
+    </linearGradient>
+  </defs>
+</svg>

+ 56 - 0
pages/assets/gate.svg

@@ -0,0 +1,56 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 57" class="design-iconfont">
+  <rect y=".664062" width="56" height="56" rx="28" fill="url(#g6vggbifn__paint0_linear_5004_276232)"/>
+  <path transform="matrix(.83856 .54482 0 1 22.5479 25.5352)" fill="#979EA4" d="M0 0H1.52947V22.1281H0z"/>
+  <path transform="matrix(.83856 .54482 0 1 31.6895 19.7344)" fill="#7A8086" d="M0 0H1.42664V22.0973H0z"/>
+  <path transform="matrix(.83856 -.54482 0 1 32.8857 20.4863)" fill="#BFC5CA" d="M0 0H0.639175V22.1247H0z"/>
+  <path transform="matrix(.83856 .54482 -.83856 .54482 32.1357 19.3008)" fill="#DEE1E4" d="M0 0H1.53455V11.4378H0z"/>
+  <path transform="matrix(.83856 .54482 -.83856 .54482 32.2231 31.2305)" fill="#E5E5E5" d="M0 0H0.297755V9.80764H0z"/>
+  <path transform="matrix(.83856 -.54482 0 1 24.2451 36.7363)" fill="url(#g6vggbifn__paint1_linear_5004_276232)" d="M0 0H9.80447V10.8096H0z"/>
+  <path transform="matrix(.83856 -.54482 0 1 23.8301 26.3691)" fill="#BFC5CA" d="M0 0H0.639175V22.1247H0z"/>
+  <path d="M25.9795 19.7969L26.3604 20.0443V34.6162L25.9795 34.3688V19.7969Z" fill="#979EA4"/>
+  <path transform="matrix(.79922 -.60104 0 1 26.27 34.3672)" fill="#E7E6EB" d="M0 0H0.0951997V1.05036H0z"/>
+  <path transform="matrix(.79922 .60104 -.79922 .60104 26.0713 34.1016)" fill="#C0C0CD" d="M0 0H0.345489V0.0970162H0z"/>
+  <path d="M25.9941 34.1602L26.2701 34.3677V35.4031L25.9941 35.1956V34.1602Z" fill="#AAAAB7"/>
+  <path transform="matrix(.79922 -.60104 0 1 27.1377 33.8066)" fill="#E7E6EB" d="M0 0H0.0951997V1.05036H0z"/>
+  <path transform="matrix(.79922 .60104 -.79922 .60104 26.939 33.541)" fill="#C0C0CD" d="M0 0H0.345489V0.0970162H0z"/>
+  <path d="M26.8613 33.5996L27.1373 33.8071V34.8426L26.8613 34.6351V33.5996Z" fill="#AAAAB7"/>
+  <path transform="matrix(.83856 -.54482 0 1 26.3604 20.041)" fill="#BFC5CA" d="M0 0H0.943443V14.577H0z"/>
+  <path d="M28.6152 18.1152L28.9961 18.3627V32.9346L28.6152 32.6871V18.1152Z" fill="#979EA4"/>
+  <path transform="matrix(.79922 -.60104 0 1 28.9058 32.6836)" fill="#E7E6EB" d="M0 0H0.0951997V1.05036H0z"/>
+  <path transform="matrix(.79922 .60104 -.79922 .60104 28.707 32.418)" fill="#C0C0CD" d="M0 0H0.345489V0.0970162H0z"/>
+  <path d="M28.6299 32.4785L28.9058 32.686V33.7215L28.6299 33.514V32.4785Z" fill="#AAAAB7"/>
+  <path transform="matrix(.79922 -.60104 0 1 29.7734 32.123)" fill="#E7E6EB" d="M0 0H0.0951997V1.05036H0z"/>
+  <path transform="matrix(.79922 .60104 -.79922 .60104 29.5747 31.8594)" fill="#C0C0CD" d="M0 0H0.345489V0.0970162H0z"/>
+  <path d="M29.4976 31.918L29.7735 32.1255V33.1609L29.4976 32.9534V31.918Z" fill="#AAAAB7"/>
+  <path transform="matrix(.83856 -.54482 0 1 28.9966 18.3574)" fill="#BFC5CA" d="M0 0H0.943443V14.577H0z"/>
+  <path transform="matrix(.83856 .54482 -.83856 .54482 31.5435 12.498)" fill="#E5E5E5" d="M0 0H1.48491V10.1552H0z"/>
+  <path transform="matrix(.83856 .54482 0 1 23.0293 18.0332)" fill="url(#g6vggbifn__paint2_linear_5004_276232)" d="M0 0H1.48267V7.2432H0z"/>
+  <path transform="matrix(.83856 -.54482 0 1 24.2729 18.8398)" fill="url(#g6vggbifn__paint3_linear_5004_276232)" d="M0 0H10.1476V7.24373H0z"/>
+  <path transform="matrix(.83856 -.54482 0 1 23.8301 26.3691)" fill="#BFC5CA" d="M0 0H11.4381V1.09272H0z"/>
+  <path d="M25.7559 11.125L26.1361 11.3721V17.231L25.7559 16.9839V11.125Z" fill="#979EA4"/>
+  <path transform="matrix(.83856 .54482 -.83856 .54482 26.5488 10.6094)" fill="#DEE1E3" d="M0 0H0.454464V0.94455H0z"/>
+  <path d="M26.1357 11.3691L26.9269 10.8551V16.721L26.1357 17.235V11.3691Z" fill="#BFC5CA"/>
+  <path d="M28.3306 9.41797L28.7108 9.66502V15.524L28.3306 15.2769V9.41797Z" fill="#979EA4"/>
+  <path transform="matrix(.83856 .54482 -.83856 .54482 29.124 8.90234)" fill="#DEE1E3" d="M0 0H0.454464V0.94455H0z"/>
+  <path d="M28.7109 9.66406L29.5021 9.15006V15.0159L28.7109 15.5299V9.66406Z" fill="#BFC5CA"/>
+  <defs>
+    <linearGradient id="g6vggbifn__paint0_linear_5004_276232" x1="28" y1=".664062" x2="28" y2="56.6641" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#E7EAF3"/>
+      <stop offset="1" stop-color="#F9F9FA"/>
+    </linearGradient>
+    <linearGradient id="g6vggbifn__paint1_linear_5004_276232" x1="1.8e-7" y1="5.17548" x2="10.0844" y2="4.65227" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#88898C"/>
+      <stop offset=".5" stop-color="#E7E7E7"/>
+      <stop offset="1" stop-color="#A5A5A5"/>
+    </linearGradient>
+    <linearGradient id="g6vggbifn__paint2_linear_5004_276232" x1=".741333" y1="0" x2=".741333" y2="7.2432" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#929394"/>
+      <stop offset="1" stop-color="#929394"/>
+    </linearGradient>
+    <linearGradient id="g6vggbifn__paint3_linear_5004_276232" x1="1.8e-7" y1="3.4682" x2="10.3986" y2="2.63494" gradientUnits="userSpaceOnUse">
+      <stop stop-color="#ABABAB"/>
+      <stop offset=".5" stop-color="#D3D3D3"/>
+      <stop offset="1" stop-color="#A5A5A5"/>
+    </linearGradient>
+  </defs>
+</svg>

File diff suppressed because it is too large
+ 10 - 0
pages/assets/identification.svg


File diff suppressed because it is too large
+ 3 - 0
pages/assets/location.svg


File diff suppressed because it is too large
+ 4 - 0
pages/assets/phone.svg


+ 4 - 0
pages/assets/powerOff.svg

@@ -0,0 +1,4 @@
+<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M64 104C86.0914 104 104 86.0914 104 64C104 41.9086 86.0914 24 64 24C41.9086 24 24 41.9086 24 64C24 86.0914 41.9086 104 64 104ZM64 112C90.5097 112 112 90.5097 112 64C112 37.4903 90.5097 16 64 16C37.4903 16 16 37.4903 16 64C16 90.5097 37.4903 112 64 112Z" fill="#14A478"/>
+<path d="M83 59C85.7614 59 88 61.2386 88 64C88 66.7614 85.7614 69 83 69H45C42.2386 69 40 66.7614 40 64C40 61.2386 42.2386 59 45 59H83Z" fill="#14A478"/>
+</svg>

+ 4 - 0
pages/assets/powerOn.svg

@@ -0,0 +1,4 @@
+<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M64 104C86.0914 104 104 86.0914 104 64C104 41.9086 86.0914 24 64 24C41.9086 24 24 41.9086 24 64C24 86.0914 41.9086 104 64 104ZM64 112C90.5097 112 112 90.5097 112 64C112 37.4903 90.5097 16 64 16C37.4903 16 16 37.4903 16 64C16 90.5097 37.4903 112 64 112Z" fill="#14A478"/>
+<path d="M59 45C59 42.2386 61.2386 40 64 40C66.7614 40 69 42.2386 69 45V83C69 85.7614 66.7614 88 64 88C61.2386 88 59 85.7614 59 83V45Z" fill="#14A478"/>
+</svg>

File diff suppressed because it is too large
+ 3 - 0
pages/assets/restart.svg


BIN
pages/cbd/assets/offline.png


BIN
pages/cbd/assets/online.png


+ 130 - 0
pages/cbd/components/DeviceCard.vue

@@ -0,0 +1,130 @@
+<template>
+  <view class="device-card__body">
+    <view class="device-card">
+      <view class="online-status">在线</view>
+      <view class="device-card__title">设备ID</view>
+      <view class="device-card__content">
+        <text class="device-id-text">{{ deviceId }}</text>
+        <text class="copy-icon" @tap="copyDeviceId">&#xe628;</text>
+      </view>
+    </view>
+    <view class="device-card">
+      <view class="device-card__title">上报时间</view>
+      <view class="device-card__content">2026-02-22 14:20:00</view>
+    </view>
+    <view class="device-card">
+      <view class="device-card__title">设备位置</view>
+      <view class="device-card__content address">位置信息此处展示16个字超出省略省略省略…</view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  props: {
+    deviceId: {
+      type: String,
+      default: '2255666666666125'
+    }
+  },
+  data() {
+    return {
+      title: ''
+    }
+  },
+  methods: {
+    copyDeviceId() {
+      uni.setClipboardData({
+        data: this.deviceId,
+        success: () => {
+          uni.showToast({
+            title: '复制成功',
+            icon: 'success'
+          })
+        }
+      })
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.device-card__body {
+  display: flex;
+  padding: 16px 12px;
+  flex-direction: column;
+  align-items: flex-start;
+  gap: 8px;
+  border-radius: 8px;
+  background: linear-gradient(180deg, #EFF 0%, #FFF 23.56%);
+  margin-top: 34rpx;
+  position: relative;
+  .device-card {
+    display: flex;
+    gap: 16px;
+    .device-card__title {
+      width: 136rpx;
+      color: #4E5969;
+      font-size: 14px;
+      font-style: normal;
+      font-weight: 400;
+      text-align: right;
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+    }
+    .online-status {
+      width: 136rpx;
+      height: 56rpx;
+      line-height: 56rpx;
+      position: absolute;
+      text-align: center;
+      top: 0;
+      right: 0;
+      background: url('../assets/online.png') no-repeat center center;
+      background-size: 100% 100%;
+      color: #0bbc58;
+      font-family: "Source Han Sans CN VF";
+      font-size: 28rpx;
+    }
+    .offline-status{
+      width: 136rpx;
+      height: 56rpx;
+      line-height: 56rpx;
+      position: absolute;
+      text-align: center;
+      top: 0;
+      right: 0;
+      background: url('../assets/offline.png') no-repeat center center;
+      background-size: 100% 100%;
+      color: #ff3546;
+      font-family: "Source Han Sans CN VF";
+      font-size: 28rpx;
+    }
+    .device-card__content {
+      color: #4E5969;
+      font-size: 14px;
+      font-style: normal;
+      font-weight: 400;
+      display: flex;
+      align-items: center;
+      gap: 8rpx;
+      .device-id-text {
+        flex: 1;
+      }
+      .copy-icon {
+        font-family: 'iconfont';
+        font-size: 32rpx;
+        color: #86909C;
+        cursor: pointer;
+        &:active {
+          opacity: 0.6;
+        }
+      }
+    }
+    .address {
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+  }
+}
+</style>

+ 48 - 0
pages/cbd/components/DeviceControl.vue

@@ -0,0 +1,48 @@
+<template>
+  <view class="device-control-container">
+    <view class="device-status">
+      <view class="status-item">
+        <text class="status-label">环境温度</text>
+        <text class="status-value">{{ deviceStatus.temp }}°C</text>
+      </view>
+      <view class="status-item">
+        <text class="status-label">环境湿度</text>
+        <text class="status-value">{{ deviceStatus.humidity }}%</text>
+      </view>
+      <view class="status-item">
+        <text class="status-label">环境光照</text>
+        <text class="status-value">{{ deviceStatus.light }}Lux</text>
+      </view>
+      <view class="status-item">
+        <text class="status-label">环境湿度</text>
+        <text class="status-value">{{ deviceStatus.moisture }}%</text>
+      </view>
+      <view class="status-item">
+        <text class="status-label">环境湿度</text>
+        <text class="status-value">{{ deviceStatus.pest }}%</text>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      deviceStatus: {
+        temp: 25,
+        humidity: 50,
+        light: 800,
+        moisture: 300,
+        pest: 10
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.device-control-container {
+  padding: 24rpx;
+  background-color: #F7F8FA;
+  border-radius: 12rpx;
+}
+</style>

+ 730 - 0
pages/cbd/components/deviceData.vue

@@ -0,0 +1,730 @@
+<template>
+  <view class="device-data-container">
+    <!-- 顶部时间戳和图标区域 -->
+    <view class="device-data-wraper">
+      <view class="top-bar">
+        <text class="timestamp">2025-12-28 08:00:00
+          <u-icon name="reload" color="#0BBC58" style="margin-left: 12rpx"></u-icon>
+        </text>
+        <view class="icon-group">
+          <view class="icon-item refresh-icon" @click="refreshData">
+            <text class="iconfont">&#xe6aa;</text>
+          </view>
+          <view class="icon-item settings-icon" @click="openSettings">
+            <text class="iconfont">&#xe634;</text>
+          </view>
+          <view class="icon-item info-icon">
+            <text class="iconfont">&#xe604;</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 主要数据面板 -->
+      <view class="main-data-panel">
+        <view class="data-column-left">
+          <view class="data-item">
+            <text class="data-value">84%</text>
+            <text class="data-label">电量</text>
+          </view>
+          <view class="data-item">
+            <text class="data-value">时控</text>
+            <text class="data-label">电压</text>
+          </view>
+          <view class="data-item">
+            <text class="data-value temp-value">25°C</text>
+            <text class="data-label">环境湿度</text>
+          </view>
+          <view class="data-item">
+            <text class="data-value">70min</text>
+            <text class="data-label">数据上传间隔</text>
+          </view>
+        </view>
+        <view class="data-column-left">
+          <view class="data-item">
+            <text class="data-value">时控</text>
+            <text class="data-label">定时模式</text>
+          </view>
+          <view class="data-item">
+            <text class="data-value">220V</text>
+            <text class="data-label">信号强度</text>
+          </view>
+          <view class="data-item">
+            <text class="data-value">70%RH</text>
+            <text class="data-label">环境湿度</text>
+          </view>
+          <view class="data-item">
+            <text class="data-value">1.54.40(2000W)-2.11.1</text>
+            <text class="data-label">设备版本</text>
+          </view>
+        </view>
+        <view class="data-column-right">
+          <view class="device-image-container">
+            <view class="device-glow"></view>
+            <image class="device-image" src="../assets/online.png" mode="aspectFit"></image>
+          </view>
+        </view>
+      </view>
+    </view>
+    <!-- 图表区域 -->
+    <view class="chart-section">
+      <view class="chart-header">
+        <view class="chart-tabs">
+          <view
+            v-for="(tab, index) in chartTabs"
+            :key="index"
+            class="chart-tab-item"
+            :class="{ active: activeChartTab === index }"
+            @click="switchChartTab(index)"
+          >
+            {{ tab.name }}
+          </view>
+        </view>
+        <view class="chart-dropdown">
+          <text class="iconfont dropdown-icon">&#xe606;</text>
+        </view>
+      </view>
+      <view class="chart-content">
+        <view class="chart-canvas-container">
+          <canvas
+            canvas-id="tempChart"
+            id="tempChart"
+            class="chart-canvas"
+            @touchstart="chartTouchStart"
+            @touchmove="chartTouchMove"
+            @touchend="chartTouchEnd"
+          />
+        </view>
+      </view>
+    </view>
+
+    <!-- 历史数据表格 -->
+    <view class="history-section">
+      <view class="history-header">
+        <text class="history-title">历史数据</text>
+      </view>
+      <view class="history-table">
+        <view class="table-container">
+          <!-- 固定列 -->
+          <view class="fixed-column">
+            <view class="fixed-header">
+              <text class="header-cell fixed">上报时间</text>
+            </view>
+            <view class="fixed-body">
+              <view
+                v-for="(item, index) in historyData"
+                :key="index"
+                class="fixed-row"
+                :class="{ even: index % 2 === 0 }"
+              >
+                <text class="body-cell fixed">{{ item.time }}</text>
+              </view>
+            </view>
+          </view>
+          <!-- 可滑动列 -->
+          <view class="scrollable-column">
+            <view class="scrollable-header">
+              <text class="header-cell">环境温度(°C)</text>
+              <text class="header-cell">环境湿度(%)</text>
+              <text class="header-cell">环境湿度(%)</text>
+              <text class="header-cell">环境湿度(%)</text>
+              <text class="header-cell">环境湿度(%)</text>
+              <text class="header-cell">环境湿度(%)</text>
+            </view>
+            <view class="scrollable-body">
+              <view
+                v-for="(item, index) in historyData"
+                :key="index"
+                class="scrollable-row"
+                :class="{ even: index % 2 === 0 }"
+              >
+                <text class="body-cell">{{ item.temp }}</text>
+                <text class="body-cell">{{ item.humidity }}</text>
+                <text class="body-cell">{{ item.humidity }}</text>
+                <text class="body-cell">{{ item.humidity }}</text>
+                <text class="body-cell">{{ item.humidity }}</text>
+                <text class="body-cell">{{ item.humidity }}</text>
+                <text class="body-cell">{{ item.humidity }}</text>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="pagination">
+        <text class="pagination-btn prev-btn">上一页</text>
+        <text class="pagination-info">1/6</text>
+        <text class="pagination-btn next-btn">下一页</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import uCharts from '@/components/js_sdk/u-charts/u-charts/u-charts.js';
+
+let chartInstance = null;
+
+export default {
+  name: 'DeviceData',
+  data() {
+    return {
+      chartTabs: [
+        { name: '温度', id: 'temp' },
+        { name: '湿度', id: 'humidity' },
+        { name: '加热仓温度', id: 'heatingTemp' },
+        { name: '雨量累计', id: 'rainfall' }
+      ],
+      activeChartTab: 0,
+      chartData: {
+        categories: ['05-29/00:00', '05-29/00:00', '05-29/00:00', '05-29/00:00', '05-29/00:00', '05-29/00:00'],
+        series: [
+          {
+            name: '大气温度',
+            data: [2, 4, 6, 8, 10, 8]
+          }
+        ]
+      },
+      cWidth: 320,
+      cHeight: 180,
+      historyData: [
+        { time: '2025-12-28 08:00', temp: '25', humidity: '70' },
+        { time: '2025-12-28 07:00', temp: '24', humidity: '68' },
+        { time: '2025-12-28 06:00', temp: '23', humidity: '65' },
+        { time: '2025-12-28 05:00', temp: '22', humidity: '63' },
+        { time: '2025-12-28 04:00', temp: '21', humidity: '60' },
+        { time: '2025-12-28 03:00', temp: '20', humidity: '58' },
+        { time: '2025-12-28 02:00', temp: '19', humidity: '55' }
+      ],
+      currentPage: 1,
+      totalPages: 6
+    };
+  },
+  mounted() {
+    this.initChart();
+  },
+  methods: {
+    openSettings(){
+      this.$router.push({
+        path: '/pages/cbd/deviceControl',
+        query: {
+          deviceId: this.deviceId
+        }
+      });
+    },
+    initChart() {
+      this.cWidth = uni.upx2px(640);
+      this.cHeight = uni.upx2px(360);
+      this.$nextTick(() => {
+        this.drawChart();
+      });
+    },
+    drawChart() {
+      const ctx = uni.createCanvasContext('tempChart', this);
+
+      chartInstance = new uCharts({
+        type: 'area',
+        context: ctx,
+        width: this.cWidth,
+        height: this.cHeight,
+        categories: this.chartData.categories,
+        series: this.chartData.series,
+        animation: true,
+        background: '#FFFFFF',
+        color: ['#0BBC58'],
+        padding: [20, 10, 10, 0],
+        dataLabel: false,
+        dataPointShape: true,
+        enableScroll: false,
+        legend: {
+          show: false
+        },
+        xAxis: {
+          disableGrid: true,
+          boundaryGap: 'center',
+          fontSize: 10,
+          fontColor: '#999999',
+          scrollShow: false
+        },
+        yAxis: {
+          gridType: 'dash',
+          splitNumber: 4,
+          min: 0,
+          max: 12,
+          fontSize: 10,
+          fontColor: '#999999'
+        },
+        extra: {
+          area: {
+            type: 'curve',
+            width: 2,
+            addLine: true,
+            gradient: true,
+            activeType: 'hollow',
+            linearType: 'custom',
+            shadowColor: 'rgba(11, 188, 88, 0.3)',
+            tension: 0.4
+          }
+        }
+      });
+    },
+    switchChartTab(index) {
+      this.activeChartTab = index;
+      // 根据不同标签切换数据
+      this.$nextTick(() => {
+        this.drawChart();
+      });
+    },
+    chartTouchStart(e) {
+      if (chartInstance) {
+        chartInstance.scrollStart(e);
+      }
+    },
+    chartTouchMove(e) {
+      if (chartInstance) {
+        chartInstance.scroll(e);
+      }
+    },
+    chartTouchEnd(e) {
+      if (chartInstance) {
+        chartInstance.scrollEnd(e);
+        chartInstance.showToolTip(e);
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.device-data-container {
+  width: 100%;
+  min-height: 100vh;
+}
+.device-data-wraper{
+  padding: 16rpx;
+  background: #ffffff;
+  border-radius: 16rpx;
+}
+/* 顶部时间戳和图标区域 */
+.top-bar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 16rpx 0;
+  .timestamp {
+    font-size: 28rpx;
+    font-family: 'Source Han Sans CN VF', sans-serif;
+    font-weight: 400;
+    color: #999999;
+  }
+
+  .icon-group {
+    display: flex;
+    gap: 24rpx;
+
+    .icon-item {
+      width: 48rpx;
+      height: 48rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border-radius: 50%;
+
+      .iconfont {
+        font-size: 36rpx;
+      }
+
+      &.refresh-icon .iconfont {
+        color: #0BBC58;
+      }
+
+      &.settings-icon .iconfont {
+        color: #999999;
+      }
+
+      &.info-icon .iconfont {
+        color: #999999;
+      }
+    }
+  }
+}
+
+/* 主要数据面板 */
+.main-data-panel {
+  display: flex;
+  background: #FFFFFF;
+  border-radius: 16rpx;
+  margin-bottom: 16rpx;
+
+  .data-column-left {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 24rpx;
+
+    .data-item {
+      display: flex;
+      flex-direction: column;
+      gap: 8rpx;
+
+      .data-label {
+        font-size: 24rpx;
+        font-family: 'Source Han Sans CN VF', sans-serif;
+        font-weight: 400;
+        color: #999999;
+      }
+
+      .data-value {
+        font-size: 24rpx;
+        font-family: 'Source Han Sans CN VF', sans-serif;
+        font-weight: 700;
+        color: #042118;
+
+        &.temp-value {
+          color: #FF6B6B;
+        }
+      }
+
+      .data-unit {
+        font-size: 24rpx;
+        font-family: 'Source Han Sans CN VF', sans-serif;
+        font-weight: 400;
+        color: #999999;
+      }
+    }
+  }
+
+  .data-column-right {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 16rpx;
+
+    .device-image-container {
+      position: relative;
+      width: 200rpx;
+      height: 200rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      .device-glow {
+        position: absolute;
+        width: 180rpx;
+        height: 180rpx;
+        background: radial-gradient(circle, rgba(11, 188, 88, 0.3) 0%, rgba(11, 188, 88, 0) 70%);
+        border-radius: 50%;
+      }
+
+      .device-image {
+        position: relative;
+        width: 160rpx;
+        height: 160rpx;
+        z-index: 1;
+      }
+    }
+
+    .device-info {
+      display: flex;
+      flex-direction: column;
+      gap: 12rpx;
+      width: 100%;
+
+      .info-row {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .info-label {
+          font-size: 24rpx;
+          font-family: 'Source Han Sans CN VF', sans-serif;
+          font-weight: 400;
+          color: #999999;
+        }
+
+        .info-value {
+          font-size: 36rpx;
+          font-family: 'Source Han Sans CN VF', sans-serif;
+          font-weight: 700;
+          color: #042118;
+        }
+
+        .info-version {
+          font-size: 24rpx;
+          font-family: 'Source Han Sans CN VF', sans-serif;
+          font-weight: 400;
+          color: #999999;
+        }
+
+        .info-label-small {
+          font-size: 24rpx;
+          font-family: 'Source Han Sans CN VF', sans-serif;
+          font-weight: 400;
+          color: #999999;
+        }
+      }
+    }
+  }
+}
+
+/* 图表区域 */
+.chart-section {
+  background: #FFFFFF;
+  border-radius: 16rpx;
+  padding: 24rpx 32rpx 32rpx;
+  margin: 24rpx 0;
+
+  .chart-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 24rpx;
+
+    .chart-tabs {
+      display: flex;
+      gap: 32rpx;
+      overflow-x: auto;
+      white-space: nowrap;
+
+      .chart-tab-item {
+        font-size: 28rpx;
+        font-family: 'Source Han Sans CN VF', sans-serif;
+        font-weight: 500;
+        color: #999999;
+        position: relative;
+        padding-bottom: 8rpx;
+        transition: all 0.3s;
+
+        &.active {
+          color: #0BBC58;
+          font-weight: 700;
+
+          &::after {
+            content: '';
+            position: absolute;
+            bottom: 0;
+            left: 0;
+            right: 0;
+            height: 4rpx;
+            background: #0BBC58;
+            border-radius: 2rpx;
+          }
+        }
+      }
+    }
+
+    .chart-dropdown {
+      .dropdown-icon {
+        font-size: 28rpx;
+        color: #999999;
+      }
+    }
+  }
+
+  .chart-content {
+    .chart-legend {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 16rpx;
+
+      .legend-item {
+        display: flex;
+        align-items: center;
+        gap: 8rpx;
+
+        .legend-dot {
+          width: 16rpx;
+          height: 16rpx;
+          background: #0BBC58;
+          border-radius: 50%;
+        }
+
+        .legend-text {
+          font-size: 24rpx;
+          font-family: 'Source Han Sans CN VF', sans-serif;
+          font-weight: 400;
+          color: #042118;
+        }
+      }
+
+      .legend-average {
+        .average-text {
+          font-size: 24rpx;
+          font-family: 'Source Han Sans CN VF', sans-serif;
+          font-weight: 400;
+          color: #999999;
+        }
+      }
+    }
+
+    .chart-canvas-container {
+      width: 100%;
+      height: 360rpx;
+
+      .chart-canvas {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+}
+
+/* 历史数据表格 */
+.history-section {
+  background: #FFFFFF;
+  border-radius: 16rpx;
+  padding: 24rpx 32rpx 32rpx;
+
+  .history-header {
+    margin-bottom: 24rpx;
+
+    .history-title {
+      font-size: 32rpx;
+      font-family: 'Source Han Sans CN VF', sans-serif;
+      font-weight: 700;
+      color: #042118;
+    }
+  }
+
+  .history-table {
+    margin-bottom: 24rpx;
+
+    .table-container {
+      display: flex;
+      position: relative;
+
+      /* 固定列 */
+      .fixed-column {
+        width: 180rpx;
+        position: relative;
+        z-index: 2;
+        background: #FFFFFF;
+
+        .fixed-header {
+          border-bottom: 2rpx solid #F0F0F0;
+          padding: 16rpx 0;
+
+          .header-cell.fixed {
+            font-size: 24rpx;
+            font-family: 'Source Han Sans CN VF', sans-serif;
+            font-weight: 500;
+            color: #666666;
+            text-align: left;
+            padding-left: 0;
+          }
+        }
+
+        .fixed-body {
+          .fixed-row {
+            padding: 16rpx 0;
+            border-bottom: 1rpx solid #F5F5F5;
+            height: 80rpx;
+            display: flex;
+            align-items: center;
+
+            &.even {
+              background: #FAFAFA;
+            }
+
+            .body-cell.fixed {
+              font-size: 24rpx;
+              font-family: 'Source Han Sans CN VF', sans-serif;
+              font-weight: 400;
+              color: #042118;
+              text-align: left;
+              padding-left: 0;
+            }
+          }
+        }
+      }
+
+      /* 可滑动列 */
+      .scrollable-column {
+        flex: 1;
+        overflow-x: auto;
+        white-space: nowrap;
+
+        /* 隐藏滚动条 */
+        &::-webkit-scrollbar {
+          display: none;
+        }
+        scrollbar-width: none;
+
+        .scrollable-header {
+          display: flex;
+          border-bottom: 2rpx solid #F0F0F0;
+          padding: 20rpx 0;
+
+          .header-cell {
+            min-width: 140rpx;
+            font-size: 24rpx;
+            font-family: 'Source Han Sans CN VF', sans-serif;
+            font-weight: 500;
+            color: #666666;
+            text-align: center;
+            // 超出隐藏
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+          }
+        }
+
+        .scrollable-body {
+          .scrollable-row {
+            display: flex;
+            padding: 16rpx 0;
+            border-bottom: 1rpx solid #F5F5F5;
+            height: 80rpx;
+            align-items: center;
+
+            &.even {
+              background: #FAFAFA;
+            }
+
+            .body-cell {
+              min-width: 120rpx;
+              font-size: 24rpx;
+              font-family: 'Source Han Sans CN VF', sans-serif;
+              font-weight: 400;
+              color: #042118;
+              text-align: center;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .pagination {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .pagination-btn {
+      font-size: 24rpx;
+      font-family: 'Source Han Sans CN VF', sans-serif;
+      font-weight: 400;
+      padding: 6rpx 18rpx;
+      border-radius: 8rpx;
+      transition: all 0.3s;
+
+      &.prev-btn {
+        color: #656565;
+        border: 1px solid #E4E7ED;
+      }
+
+      &.next-btn {
+        color: #0BBC58;
+        border: 1px solid #0BBC58;
+      }
+    }
+
+    .pagination-info {
+      font-size: 28rpx;
+      font-family: 'Source Han Sans CN VF', sans-serif;
+      font-weight: 400;
+      color: #999999;
+    }
+  }
+}
+</style>

+ 224 - 0
pages/cbd/components/pestArchive.vue

@@ -0,0 +1,224 @@
+<template>
+  <view class="pest-archive">
+    <view class="pest-archive__header">
+      <view class="pest-archive__title">虫害档案</view>
+    </view>
+
+      <view
+        class="pest-card"
+        @tap="handleCardClick(item)"
+      >
+        <view class="pest-card__image">
+          <image :src="item.image" mode="aspectFill" class="pest-img"></image>
+        </view>
+        <view class="pest-card__info">
+          <view class="pest-card__top">
+            <view class="pest-card__name">
+              名称
+            </view>
+            <view class="pest-card__status">
+              叶蝉
+            </view>
+          </view>
+          <view class="pest-card__top">
+            <view class="pest-card__name">
+              科目
+            </view>
+            <view class="pest-card__status">
+              叶蝉
+            </view>
+          </view>
+          <view class="pest-card__top">
+            <view class="pest-card__name">
+              别名
+            </view>
+            <view class="pest-card__status">
+              叶蝉
+            </view>
+          </view>
+          <view class="pest-card__top">
+            <view class="pest-card__name">
+              危害作物
+            </view>
+            <view class="pest-card__status">
+              叶蝉科半翅目
+            </view>
+          </view>
+        </view>
+      </view>
+  </view>
+</template>
+
+<script>
+export default {
+  props: {
+    scrollHeight: {
+      type: String,
+      default: '500rpx'
+    }
+  },
+  data() {
+    return {
+      item: {
+        name: '小菜蛾',
+        status: '已防治',
+        statusType: 'handled',
+        time: '2025-06-15',
+        description: '采用生物防治方法,投放赤眼蜂进行防治',
+        image: 'https://via.placeholder.com/120x120/4CAF50/FFFFFF?text=小菜蛾'
+      },
+    }
+  },
+  methods: {
+    handleCardClick(item) {
+      this.$emit('click', item)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.pest-archive {
+  width: 100%;
+  padding: 32rpx;
+  margin-top: 24rpx;
+  box-sizing: border-box;
+  background: #fff;
+  border-radius: 16rpx;
+}
+
+.pest-archive__header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 24rpx;
+}
+
+.pest-archive__title {
+  font-size: 36rpx;
+  color: #042118;
+  font-family: 'Source Han Sans CN VF';
+  font-weight: 700;
+}
+
+.pest-archive__add {
+  width: 56rpx;
+  height: 56rpx;
+  border-radius: 50%;
+  background: linear-gradient(135deg, #00D26A 0%, #00B55A 100%);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 4rpx 12rpx rgba(0, 210, 106, 0.3);
+
+  .add-icon {
+    font-size: 40rpx;
+    color: #fff;
+    line-height: 1;
+    font-weight: 300;
+  }
+}
+
+.pest-archive__list {
+  width: 100%;
+}
+
+.pest-card {
+  display: flex;
+  padding: 24rpx;
+  margin-bottom: 16rpx;
+  background: #F7F8F9;
+  border-radius: 16rpx;
+  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+
+  &:active {
+    opacity: 0.8;
+  }
+}
+
+.pest-card__image {
+  width: 200rpx;
+  height: 200rpx;
+  border-radius: 12rpx;
+  overflow: hidden;
+  flex-shrink: 0;
+  margin-right: 20rpx;
+  background: #e0e0e0;
+
+  .pest-img {
+    width: 100%;
+    height: 100%;
+  }
+}
+
+.pest-card__info {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  padding: 4rpx 0;
+}
+
+.pest-card__top {
+  display: flex;
+  align-items: center;
+}
+
+.pest-card__name {
+  font-size: 24rpx;
+  color: #042118;
+  color: #999999;
+  font-family: "Source Han Sans CN VF";
+  font-size: 24rpx;
+  font-weight: 400;
+}
+
+.pest-card__status {
+  padding: 6rpx 16rpx;
+  border-radius: 20rpx;
+  font-size: 24rpx;
+  font-weight: 500;
+  // 超出隐藏
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+
+  &.status--handled {
+    background: rgba(0, 210, 106, 0.15);
+    color: #00B55A;
+  }
+
+  &.status--handling {
+    background: rgba(255, 149, 0, 0.15);
+    color: #FF9500;
+  }
+
+  &.status--pending {
+    background: rgba(255, 53, 70, 0.15);
+    color: #FF3546;
+  }
+}
+
+.pest-card__time {
+  font-size: 24rpx;
+  color: #86909C;
+  margin-top: 8rpx;
+}
+
+.pest-card__desc {
+  font-size: 26rpx;
+  color: #4E5969;
+  margin-top: 12rpx;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  line-clamp: 2;
+  -webkit-box-orient: vertical;
+  line-height: 1.5;
+}
+</style>

+ 101 - 0
pages/cbd/components/pestDiscern.vue

@@ -0,0 +1,101 @@
+<template>
+  <view class="pest-discern">
+    <view class="pest-discern__header">
+      <view class="pest-discern__title">
+        虫害识别
+      </view>
+    </view>
+    <view class="pest-discern__content">
+      <view class="pest-discern__item" v-for="(item,index) in pests" :key="index">
+        <view class="pest-discern__item-title">
+          {{ item.name }}
+        </view>
+        <view class="pest-discern__item-content">
+          <u-line-progress :active-color="item.color" :percent="item.percent" :show-percent="false" height="8"></u-line-progress>
+        </view>
+        <view class="pest-discern__item-count">
+          6521
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      pests: [
+        {
+          color:'#FF3546',
+          name: '叶蝉',
+          percent: 90
+        },
+        {
+          color:'#F69B47',
+          name: '稻飞虱',
+          percent: 80
+        },
+        {
+          color:'#EEAC19',
+          name: '水龟虫',
+          percent: 70
+        },
+        {
+          color:'#0085FF',
+          name: '蝼蛄',
+          percent: 60
+        }
+      ]
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.pest-discern {
+  width: 100%;
+  padding: 32rpx;
+  box-sizing: border-box;
+  background: #fff;
+  border-radius: 16rpx;
+}
+.pest-discern__header {
+  padding: 20rpx 0rpx;
+  font-size: 32rpx;
+  color: #042118;
+  font-family: 'Source Han Sans CN VF';
+  font-weight: 700;
+}
+.pest-discern__title {
+  font-size: 32rpx;
+  color: #042118;
+  font-family: 'Source Han Sans CN VF';
+  font-weight: 700;
+}
+.pest-discern__item {
+  display: flex;
+  width: 100%;
+  margin-bottom: 20rpx;
+  align-items: center;
+  .pest-discern__item-title{
+    width: 120rpx;
+    font-size: 28rpx;
+    color: #042118;
+    font-family: 'Source Han Sans CN VF';
+    font-weight: 400;
+    // 超出隐藏
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .pest-discern__item-content{
+    flex: 1;
+    margin: 0 20rpx;
+  }
+  .pest-discern__item-count{
+    width: 80rpx;
+    font-size: 28rpx;
+    color: #042118;
+    text-align: right;
+  }
+}
+</style>

+ 357 - 0
pages/cbd/components/pestEchart.vue

@@ -0,0 +1,357 @@
+<template>
+  <view class="pest-echart">
+    <view class="pest-echart__header">
+      <view class="tab-list">
+        <view
+          v-for="(tab, index) in tabs"
+          :key="index"
+          class="tab-item"
+          :class="{ active: activeTab === index }"
+          @click="switchTab(index)"
+        >
+          {{ tab.name }}
+        </view>
+      </view>
+    </view>
+
+    <view class="pest-echart__content">
+      <!-- 三个关键时期 -->
+      <view class="period-section">
+        <view class="period-item">
+          <view class="period-label">始见期</view>
+          <view class="period-value">{{ periodData.firstDate }}</view>
+        </view>
+        <view class="period-item">
+          <view class="period-label">高峰期</view>
+          <view class="period-value">{{ periodData.peakDate }}</view>
+        </view>
+        <view class="period-item">
+          <view class="period-label">终见期</view>
+          <view class="period-value">{{ periodData.lastDate }}</view>
+        </view>
+      </view>
+
+      <!-- 图表区域 -->
+      <view class="chart-container">
+        <canvas
+          canvas-id="pestChart"
+          id="pestChart"
+          class="chart-canvas"
+          @touchstart="touchStart"
+          @touchmove="touchMove"
+          @touchend="touchEnd"
+        />
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import uCharts from '@/components/js_sdk/u-charts/u-charts/u-charts.js';
+
+let chartInstance = null;
+
+export default {
+  name: 'PestEchart',
+  data() {
+    return {
+      tabs: [
+        { name: '叶蝉', id: 'yechan' },
+        { name: '水龟虫', id: 'shuigui' },
+        { name: '稻飞虱', id: 'daofeishi' },
+        { name: '蝼蛄', id: 'lougou' },
+        { name: '叶蝉', id: 'yechan' },
+        { name: '蝼蛄', id: 'lougou' },
+        { name: '叶蝉', id: 'yechan' },
+        { name: '蝼蛄', id: 'lougou' },
+        { name: '叶蝉', id: 'yechan' },
+        { name: '甜菜', id: 'tiancai' }
+      ],
+      activeTab: 0,
+      // 三个关键时期数据
+      periodData: {
+        firstDate: '2025-05-24',
+        peakDate: '2025-06-24',
+        lastDate: '2025-07-24'
+      },
+      chartData: {
+        categories: ['05-29/00:00', '05-29/00:00', '05-29/00:00'],
+        series: [
+          {
+            name: '虫量',
+            data: [3, 7, 9]
+          }
+        ]
+      },
+      cWidth: 320,
+      cHeight: 200,
+      // 每个标签对应的数据
+      tabData: [
+        {
+          periodData: {
+            firstDate: '2025-05-24',
+            peakDate: '2025-06-24',
+            lastDate: '2025-07-24'
+          },
+          chartData: {
+            categories: ['05-29/00:00', '05-29/00:00', '05-29/00:00'],
+            series: [
+              {
+                name: '虫量',
+                data: [3, 7, 9]
+              }
+            ]
+          }
+        },
+        {
+          periodData: {
+            firstDate: '2025-06-01',
+            peakDate: '2025-07-01',
+            lastDate: '2025-08-01'
+          },
+          chartData: {
+            categories: ['06-05', '06-12', '06-19', '06-26', '07-03', '07-10', '07-17', '07-24', '07-31'],
+            series: [
+              {
+                name: '虫量',
+                data: [1, 3, 6, 10, 12, 8, 5, 3, 2]
+              }
+            ]
+          }
+        },
+        {
+          periodData: {
+            firstDate: '2025-05-15',
+            peakDate: '2025-06-15',
+            lastDate: '2025-07-15'
+          },
+          chartData: {
+            categories: ['05-20', '05-27', '06-03', '06-10', '06-17', '06-24', '07-01', '07-08', '07-15'],
+            series: [
+              {
+                name: '虫量',
+                data: [3, 5, 7, 9, 11, 8, 6, 4, 2]
+              }
+            ]
+          }
+        },
+        {
+          periodData: {
+            firstDate: '2025-05-20',
+            peakDate: '2025-06-20',
+            lastDate: '2025-07-20'
+          },
+          chartData: {
+            categories: ['05-25', '06-01', '06-08', '06-15', '06-22', '06-29', '07-06', '07-13', '07-20'],
+            series: [
+              {
+                name: '虫量',
+                data: [1, 2, 5, 8, 10, 7, 5, 3, 1]
+              }
+            ]
+          }
+        },
+        {
+          periodData: {
+            firstDate: '2025-06-05',
+            peakDate: '2025-07-05',
+            lastDate: '2025-08-05'
+          },
+          chartData: {
+            categories: ['06-10', '06-17', '06-24', '07-01', '07-08', '07-15', '07-22', '07-29', '08-05'],
+            series: [
+              {
+                name: '虫量',
+                data: [2, 4, 6, 9, 12, 10, 7, 4, 2]
+              }
+            ]
+          }
+        }
+      ]
+    };
+  },
+  mounted() {
+    this.initChart();
+  },
+  methods: {
+    initChart() {
+      this.cWidth = uni.upx2px(680);
+      this.cHeight = uni.upx2px(400);
+      this.$nextTick(() => {
+        this.drawChart();
+      });
+    },
+    drawChart() {
+      const ctx = uni.createCanvasContext('pestChart', this);
+
+      chartInstance = new uCharts({
+        type: 'line',
+        context: ctx,
+        width: this.cWidth,
+        height: this.cHeight,
+        categories: this.chartData.categories,
+        series: this.chartData.series,
+        animation: true,
+        background: '#FFFFFF',
+        color: ['#0085FF'],
+        padding: [10, 20, 10, 0],
+        dataLabel: false,
+        dataPointShape: true,
+        enableScroll: false,
+        legend: {
+          show: false
+        },
+        xAxis: {
+          disableGrid: true,
+          boundaryGap: 'center',
+          fontSize: 11,
+          fontColor: '#999999',
+          scrollShow: false
+        },
+        yAxis: {
+          gridType: 'none',
+          splitNumber: 4,
+          min: 0,
+          max: 12,
+          fontSize: 11,
+          fontColor: '#999999'
+        },
+        extra: {
+          line: {
+            type: 'curve',
+            width: 2,
+            activeType: 'hollow',
+            linearType: 'none',
+            onShadow: false,
+            shadowColor: 'rgba(0, 133, 255, 0.3)',
+            tension: 0.4
+          }
+        }
+      });
+    },
+    switchTab(index) {
+      this.activeTab = index;
+      // 更新数据
+      this.periodData = this.tabData[index].periodData;
+      this.chartData = this.tabData[index].chartData;
+      // 重新绘制图表
+      this.$nextTick(() => {
+        this.drawChart();
+      });
+    },
+    touchStart(e) {
+      if (chartInstance) {
+        chartInstance.scrollStart(e);
+      }
+    },
+    touchMove(e) {
+      if (chartInstance) {
+        chartInstance.scroll(e);
+      }
+    },
+    touchEnd(e) {
+      if (chartInstance) {
+        chartInstance.scrollEnd(e);
+        chartInstance.showToolTip(e);
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.pest-echart {
+  overflow: hidden;
+  margin-top: 24rpx;
+}
+
+.pest-echart__header {
+  padding-top: 24rpx;
+}
+
+.tab-list {
+  width: 100%;
+  padding-bottom: 24rpx;
+  overflow-x: scroll;
+  white-space: nowrap;
+  overflow-y: hidden;
+  box-sizing: border-box;
+  // 去掉滚动条
+  -ms-overflow-style: none;
+  scrollbar-width: none;
+}
+
+.tab-item {
+  margin-right: 16rpx;
+  font-size: 28rpx;
+  font-family: 'Source Han Sans CN VF', sans-serif;
+  font-weight: 500;
+  color: #999999;
+  display: inline-block;
+  box-sizing: border-box;
+  background: #ffffff;
+  font-family: "Source Han Sans CN VF";
+  font-size: 28rpx;
+  padding: 10rpx 32rpx;
+  border-radius: 8rpx;
+  &:last-child {
+    margin-right: 0;
+  }
+  &.active {
+    color: #0BBC58;
+    font-weight: 700;
+  }
+  &:first-child.active {
+    color: #0BBC58;
+  }
+}
+
+.pest-echart__content {
+  background: #FFFFFF;
+  border-radius: 16rpx;
+  padding: 0 32rpx 32rpx;
+}
+
+.period-section {
+  display: flex;
+  justify-content: space-between;
+  padding: 24rpx;
+  background: #ffffff;
+  border-radius: 12rpx;
+}
+
+.period-item {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.period-label {
+  font-size: 28rpx;
+  color: #303133;
+  font-family: 'Source Han Sans CN VF', sans-serif;
+  font-weight: 700;
+  margin-bottom: 8rpx;
+}
+
+.period-value {
+  font-size: 24rpx;
+  color: #999999;
+  font-family: 'Source Han Sans CN VF', sans-serif;
+  font-weight: 400;
+}
+
+.chart-container {
+  position: relative;
+  width: 100%;
+  height: 400rpx;
+  border-radius: 12rpx;
+  overflow: hidden;
+}
+
+.chart-canvas {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 158 - 0
pages/cbd/components/photoImage.vue

@@ -0,0 +1,158 @@
+<template>
+  <view class="photo-image">
+    <view class="photo-image__tabs">
+      <view
+        class="photo-image__tab"
+        v-for="(tab, index) in tabs"
+        :key="index"
+        :class="{ active: activeTab === index }"
+        @click="activeTab = index"
+      >
+        <text class="tab-text">{{ tab }}</text>
+      </view>
+    </view>
+    <view class="photo-image__content">
+      <view class="photo-image__grid">
+        <view class="photo-image__item" v-for="(item, index) in images" :key="index" @click="handleClick(item)">
+          <view class="photo-image__item-img-container">
+            <image
+              class="photo-image__item-img"
+              src="https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20a%20white%20surface&image_size=square"
+              mode="aspectFill"
+            />
+          </view>
+          <view class="photo-image__item-time">
+            2025-12-28 08:00:00
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      activeTab: 0,
+      tabs: ['全部', '稻飞虱', '水龟虫', '蝼蛄', '系统','全部', '稻飞虱', '水龟虫', '蝼蛄', '系统'],
+      images: Array(12).fill(0) // 生成12个图片项
+    };
+  },
+  methods: {
+    handleClick(item) {
+      uni.navigateTo({
+        url: '/pages/cbd/devicePhoto?devicePhoto=' + item
+      })
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.photo-image {
+  width: 100%;
+  box-sizing: border-box;
+
+  &__header {
+    margin-bottom: 32rpx;
+    white-space: nowrap;
+
+    &::-webkit-scrollbar {
+      display: none;
+    }
+  }
+
+  &__tabs {
+    box-sizing: border-box;
+    width: 100%;
+    overflow-x: auto;
+    overflow-y: hidden;
+    white-space: nowrap;
+    // 去掉滚动条
+    -ms-overflow-style: none;
+    scrollbar-width: none;
+  }
+
+  .photo-image__content{
+    padding: 30rpx;
+    background: #ffffff;
+    border-radius: 16rpx;
+    margin-top: 30rpx;
+  }
+  &__tab {
+    position: relative;
+    display: inline-block;
+    box-sizing: border-box;
+    margin-right: 16rpx;
+    background: #ffffff;
+    color: #999999;
+    font-family: "Source Han Sans CN VF";
+    font-size: 28rpx;
+    padding: 10rpx 32rpx;
+    border-radius: 8rpx;
+    &:last-child {
+      margin-right: 0;
+    }
+
+    .tab-text {
+      margin-right: 8rpx;
+    }
+
+    .tab-check {
+      color: #4CAF50;
+      font-weight: bold;
+    }
+
+    &.active {
+      color: #0BBC58;
+      font-weight: 500;
+    }
+
+    .tab-underline {
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      height: 4rpx;
+      background: #4CAF50;
+      border-radius: 2rpx;
+    }
+  }
+  &__item {
+    position: relative;
+    width: 33.33%;
+    padding: 0 10rpx;
+    box-sizing: border-box;
+    display: inline-block;
+    margin-bottom: 24rpx;
+
+    &-img-container {
+      width: 100%;
+      padding-bottom: 100%;
+      position: relative;
+      border-radius: 8rpx;
+      overflow: hidden;
+      background-color: #f5f5f5;
+      border: 2rpx solid #333;
+    }
+
+    &-img {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+    }
+
+    &-time {
+      position: absolute;
+      bottom: 10rpx;
+      margin-top: 12rpx;
+      font-size: 22rpx;
+      color: #666;
+      text-align: center;
+    }
+  }
+}
+</style>

+ 210 - 0
pages/cbd/detail.vue

@@ -0,0 +1,210 @@
+<template>
+  <view class="device-detail">
+    <view class="device-detail__header">
+      <u-icon
+        size="36"
+        class="arrow-left"
+        name="arrow-left"
+        @click="handleBack"
+      ></u-icon>
+      {{ title }}
+    </view>
+    <view class="device-detail__body">
+      <DeviceCard
+        :dataSource="deviceInfo"
+        :collectTime="time"
+        :title="title"
+        :deviceType="deviceType"
+      />
+      <view class="tabs">
+        <view class="tab-container">
+          <view class="tab-item" :class="activeTab === 'pestAnalysis'?'active':''" @click="handleTabClick('pestAnalysis')">
+            害虫分析
+          </view>
+          <view class="tab-item" :class="activeTab === 'viewImage'?'active':''" @click="handleTabClick('viewImage')">
+            查看图片
+          </view>
+          <view class="tab-item" :class="activeTab === 'deviceData'?'active':''" @click="handleTabClick('deviceData')">
+            设备数据
+          </view>
+        </view>
+        <view class="tabs-timer-container">
+          <view class="tabs-timer-item">
+            2023-08-01
+          </view>
+          至
+          <view class="tabs-timer-item">
+            2023-08-01
+          </view>
+          <u-icon name="calendar" size="36" class="calendar-icon"></u-icon>
+        </view>
+      </view>
+      <view v-if="activeTab === 'pestAnalysis'" class="tab-content">
+        <PestDiscern />
+        <PestEchart />
+        <PestArchive />
+      </view>
+      <view v-if="activeTab === 'viewImage'">
+        <photoImage :images="imageList" />
+      </view>
+      <view v-if="activeTab === 'deviceData'">
+        <DeviceData />
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+import DeviceCard from './components/DeviceCard.vue';
+import PestDiscern from './components/pestDiscern.vue';
+import PestEchart from './components/pestEchart.vue';
+import PestArchive from './components/pestArchive.vue';
+import photoImage from './components/photoImage.vue';
+import DeviceData from './components/deviceData.vue';
+
+export default {
+  components: {
+    DeviceCard,
+    PestDiscern,  
+    PestEchart,
+    PestArchive,
+    photoImage,
+    DeviceData
+  },
+  data(){
+    return {
+      imageList: [],
+      deviceInfo: {},
+      time: '',
+      activeTab: 'pestAnalysis',
+      title: '虫情测报灯详情',
+      deviceType: '',
+      location: ''
+    }
+  },
+  methods: {
+    handleBack() {
+      uni.navigateBack({
+        delta: 1
+      });
+    },
+    handleTabClick(tab) {
+      this.activeTab = tab;
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.device-detail {
+  display: flex;
+  width: 100%;
+  height: 100vh;
+  padding-top: 112rpx;
+  flex-direction: column;
+  align-items: center;
+  background: linear-gradient(180deg, #ffffff00 0%, #F5F6FA 23.64%, #F5F6FA 100%), linear-gradient(102deg, #BFEADD 6.77%, #B8F1E7 40.15%, #B9EEF5 84.02%);
+  .device-detail__header {
+    width: 100%;
+    font-size: 28rpx;
+    color: #999;
+    color: #042118;
+    font-family: 'Source Han Sans CN VF';
+    font-weight: 700;
+    position: relative;
+    text-align: center;
+    .arrow-left {
+      position: absolute;
+      left: 32rpx;
+      margin-right: 12rpx;
+    }
+  }
+  .device-detail__body {
+    width: calc(100% - 64rpx);
+    margin: 0 auto;
+    border-radius: 16rpx;
+    overflow-x: hidden;
+    overflow-y: auto;
+    // 隐藏滚动条
+    -ms-overflow-style: none;
+    scrollbar-width: none;
+  }
+  .tab-content{
+    width: 100%;
+    padding-bottom: 32rpx;
+  }
+  .tabs {
+    background: #ffffff;
+    margin: 24rpx 0;
+    border-radius: 16rpx;
+    padding: 16rpx 0;
+    padding-top: 0;
+    .tab-container{
+      display: flex;
+      width: 100%;
+      height: 88rpx;
+      line-height: 88rpx;
+      text-align: center;
+      font-size: 28rpx;
+      font-weight: 700;
+      color: #042118;
+      font-family: 'Source Han Sans CN VF';
+    }
+    .tabs-timer-container{
+      display: flex;
+      width: calc(100% - 128rpx);
+      height: 64rpx;
+      line-height: 64rpx;
+      text-align: center;
+      font-size: 24rpx;
+      font-weight: 500;
+      font-family: 'Source Han Sans CN VF';
+      border-radius: 32rpx;
+      background: #F1F4F8;
+      padding: 0 32rpx;
+      color: #656565;
+      margin: 16rpx 32rpx;
+      position: relative;
+      .tabs-timer-item{
+        width: 40%;
+        text-align: center;
+        color: #656565;
+        text-align: center;
+        font-family: "Source Han Sans CN VF";
+        font-size: 24rpx;
+        font-weight: 400;
+      }
+      .calendar-icon{
+        position: absolute;
+        right: 78rpx;
+        margin-top: 4rpx;
+        top: 12rpx;
+        right: 24rpx;
+      }
+    }
+    .tab-item {
+      flex: 1;
+    }
+    .active{
+      position: relative;
+      color: #303133;
+      text-align: center;
+      font-family: "Source Han Sans CN VF";
+      font-size: 28rpx;
+      font-weight: 700;
+      &::after {
+        content: '';
+        position: absolute;
+        bottom: 0;
+        left: 50%;
+        -webkit-transform: translateX(-50%);
+        transform: translateX(-50%);
+        width: 36rpx;
+        height: 36rpx;
+        border: 6rpx solid #0BBC58;
+        border-radius: 50%;
+        border-color: transparent;
+        border-bottom-color: #0BBC58;
+      }
+    }
+  }
+}
+</style>

+ 281 - 0
pages/cbd/deviceControl.vue

@@ -0,0 +1,281 @@
+<template>
+  <view class="device-detail">
+    <view class="device-detail__header">
+      <u-icon
+        size="36"
+        class="arrow-left"
+        name="arrow-left"
+        @click="handleBack"
+      ></u-icon>
+      {{ title }}
+    </view>
+    <view class="device-detail__body">
+      <view class="tabs">
+        <view class="tab-container">
+          <view class="tab-item" :class="activeTab === 'pestAnalysis'?'active':''" @click="handleTabClick('pestAnalysis')">
+            管理员
+          </view>
+          <view class="tab-item" :class="activeTab === 'viewImage'?'active':''" @click="handleTabClick('viewImage')">
+            设置
+          </view>
+        </view>
+      </view>
+      <view class="device-detail-content" v-if="activeTab === 'pestAnalysis'">
+        <view class="device-detail-item">
+          <text class="device-detail-label">联网模块</text>
+          <view class="device-detail-btn-container">
+            <view class="device-detail-btn">升级</view>
+            <view class="device-detail-btn">重启</view>
+            <view class="device-detail-btn">MQTT配置</view>
+          </view>
+        </view>
+        <view class="device-detail-item">
+          <text class="device-detail-label">板子设置</text>
+          <view class="device-detail-btn-container">
+            <view class="device-detail-btn">查看原始IMEI</view>
+            <view class="device-detail-btn">更改IMEI</view>
+          </view>
+        </view>
+        <view class="device-detail-item">
+          <text class="device-detail-label">强制操作</text>
+          <view class="device-detail-btn-container">
+            <view class="device-detail-btn force-btn">拍照</view>
+            <view class="device-detail-btn force-btn">升级</view>
+            <view class="device-detail-btn force-btn">重启</view>
+            <view class="device-detail-btn force-btn">震动关闭</view>
+            <view class="device-detail-btn force-btn">震动开启</view>
+          </view>
+        </view>
+      </view>
+      <view class="device-detail-content" style="padding-bottom: 50rpx" v-if="activeTab === 'viewImage'">
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">联网模块</text>
+          <u-switch v-model="checked" size="40" active-color="#0BBC58"></u-switch>
+        </view>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">定时模式</text>
+        </view>
+        <u-radio-group v-model="value" @change="radioGroupChange" active-color="#0BBC58">
+          <u-radio 
+            :name="0"
+          >光控
+          </u-radio>
+          <u-radio 
+            :name="1"
+          >时控
+          </u-radio>
+        </u-radio-group>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">落虫时间(min)</text>
+        </view>
+        <u-slider v-model="value" style="width:100%" max="100" active-color="#0BBC58"></u-slider>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">加热时间(min)</text>
+        </view>
+        <u-slider v-model="value" style="width:100%" max="100" active-color="#0BBC58"></u-slider>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">加热温度(℃)</text>
+        </view>
+        <u-slider v-model="value" style="width:100%" max="100" active-color="#0BBC58"></u-slider>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">高温保护阀值(℃)</text>
+        </view>
+        <u-slider v-model="value" style="width:100%" max="100" active-color="#0BBC58"></u-slider>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">低温保护阀值(℃)</text>
+        </view>
+        <u-slider v-model="value" style="width:100%" max="100" active-color="#0BBC58"></u-slider>
+        <view class="device-detail-viewImage">
+          <text class="device-detail-label">数据上传间隔(min)</text>
+        </view>
+        <u-slider v-model="value" style="width:100%;" max="100" active-color="#0BBC58"></u-slider>
+      </view>
+    </view>
+    <view class="device-detail-btn-footer">
+      <view class="device-detail-btn">保存</view>
+    </view>
+  </view>
+</template>
+<script>
+
+export default {
+  data(){
+    return {
+      value: 10,
+      imageList: [],
+      deviceInfo: {},
+      time: '',
+      activeTab: 'pestAnalysis',
+      title: '设置控制',
+      deviceType: '',
+      location: '',
+      checked: false
+    }
+  },
+  methods: {
+    handleBack() {
+      uni.navigateBack({
+        delta: 1
+      });
+    },
+    handleTabClick(tab) {
+      this.activeTab = tab;
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.device-detail {
+  display: flex;
+  width: 100%;
+  height: calc(100vh - 112rpx);
+  padding-top: 112rpx;
+  flex-direction: column;
+  align-items: center;
+  background: linear-gradient(180deg, #ffffff00 0%, #F5F6FA 23.64%, #F5F6FA 100%), linear-gradient(102deg, #BFEADD 6.77%, #B8F1E7 40.15%, #B9EEF5 84.02%);
+  .device-detail__header {
+    width: 100%;
+    font-size: 28rpx;
+    color: #999;
+    color: #042118;
+    font-family: 'Source Han Sans CN VF';
+    font-weight: 700;
+    position: relative;
+    text-align: center;
+    .arrow-left {
+      position: absolute;
+      left: 32rpx;
+      margin-right: 12rpx;
+    }
+  }
+  .device-detail__body {
+    width: calc(100% - 64rpx);
+    margin: 0 auto;
+    border-radius: 16rpx;
+    overflow-x: hidden;
+    overflow-y: auto;
+    // 隐藏滚动条
+    -ms-overflow-style: none;
+    scrollbar-width: none;
+  }
+  .tabs {
+    margin: 24rpx 0;
+    border-radius: 16rpx;
+    padding: 16rpx 0;
+    padding-top: 0;
+    .tab-container{
+      display: flex;
+      width: 100%;
+      height: 88rpx;
+      line-height: 88rpx;
+      text-align: center;
+      font-size: 28rpx;
+      font-weight: 700;
+      color: #042118;
+      font-family: 'Source Han Sans CN VF';
+    }
+    .tab-item {
+      margin-right: 40rpx;
+      color:#999999;
+    }
+    .active{
+      position: relative;
+      color: #303133;
+      text-align: center;
+      font-family: "Source Han Sans CN VF";
+      font-size: 28rpx;
+      font-weight: 700;
+      &::after {
+        content: '';
+        position: absolute;
+        bottom: 10rpx;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 100%;
+        height: 36rpx;
+        border-bottom: 6rpx solid #303133;
+      }
+    }
+  }
+  .device-detail-content{
+    display: flex;
+    padding: 24rpx 32rpx;
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 20rpx;
+    border-radius: 16rpx;
+    background: #FFF;
+    .device-detail-item{
+      .device-detail-label{
+        color: #303133;
+        font-family: "Source Han Sans CN VF";
+        font-size: 28rpx;
+        font-weight: 400;
+      }
+      .device-detail-btn-container{
+        display: flex;
+        gap: 24rpx;
+        margin-top: 12rpx;
+      }
+      .device-detail-btn{
+        display: flex;
+        padding: 10rpx 16rpx;
+        justify-content: center;
+        align-items: center;
+        gap: 16rpx;
+        border-radius: 16rpx;
+        background: #0BBC58;
+        color: #ffffff;
+        font-family: "Source Han Sans CN VF";
+        font-size: 24rpx;
+        font-weight: 400;
+      }
+      .force-btn{
+        background: #FB4E52;
+      }
+    }
+    .device-detail-viewImage{
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding-bottom: 20rpx;
+    }
+  }
+  .device-detail-btn-footer{
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 112rpx;
+    line-height: 112rpx;
+    text-align: center;
+    font-size: 28rpx;
+    font-weight: 700;
+    color: #042118;
+    font-family: 'Source Han Sans CN VF';
+    background: #ffffff;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    .device-detail-btn{
+      display: flex;
+      height: 80rpx;
+      width: 90%;
+      margin: 0 auto;
+      padding: 0rpx 20rpx;
+      justify-content: center;
+      align-items: center;
+      gap: 8rpx;
+      border-radius: 16rpx;
+      background:#0BBC58;
+      color: #ffffff;
+      text-align: center;
+      font-family: "Source Han Sans CN VF";
+      font-size: 14px;
+      font-style: normal;
+      font-weight: 500;
+    }
+  }
+}
+</style>

+ 397 - 0
pages/cbd/devicePhoto.vue

@@ -0,0 +1,397 @@
+<template>
+  <view class="device-photo-page">
+    <!-- 顶部导航栏 -->
+    <view class="device-detail__header">
+      <u-icon
+        size="36"
+        class="arrow-left"
+        name="arrow-left"
+        @click="handleBack"
+      ></u-icon>
+      {{ title }}
+    </view>
+
+    <!-- 日期选择器 -->
+    <view class="date-picker">
+      <view class="date-input">
+        <text class="date-label">开始日期</text>
+      </view>
+      <view class="date-separator">-</view>
+      <view class="date-input">
+        <text class="date-label">结束日期</text>
+      </view>
+      <u-icon name="calendar" class="calendar"></u-icon>
+    </view>
+
+    <!-- 主图片区域 -->
+    <view class="main-photo">
+      <image 
+        src="https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20a%20white%20surface%20with%20markers&image_size=portrait_4_3" 
+        class="main-photo-image"
+      />
+      <view class="photo-timestamp">2025-12-28 08:00:00</view>
+    </view>
+
+    <!-- 缩略图预览 -->
+    <view class="thumbnail-preview">
+      <view  class="thumbnail-scroll">
+        <view 
+          class="thumbnail-item" 
+          v-for="(item, index) in thumbnails" 
+          :key="index"
+          :class="{ active: index === currentThumbnail }"
+          @click="selectThumbnail(index)"
+        >
+          <image 
+            :src="item.src" 
+            class="thumbnail-image"
+          />
+        </view>
+      </view>
+    </view>
+
+    <!-- 识别结果 -->
+    <view class="recognition-result">
+      <view class="result-title">当前图片识别结果</view>
+      
+      <!-- 一类害虫 -->
+      <view class="pest-category">
+        <view class="category-header">
+          <text class="category-title">一类害虫</text>
+          <text class="category-count">数量</text>
+        </view>
+        <view class="pest-item" v-for="(pest, index) in category1Pests" :key="index">
+          <view class="pest-info">
+            <view class="pest-color" :style="{ backgroundColor: pest.color }"></view>
+            <text class="pest-name">{{ pest.name }}</text>
+          </view>
+          <text class="pest-count">{{ pest.count }}</text>
+        </view>
+      </view>
+
+      <!-- 二类害虫 -->
+      <view class="pest-category">
+        <view class="category-header">
+          <text class="category-title">二类害虫</text>
+          <text class="category-count">数量</text>
+        </view>
+        <view class="pest-item" v-for="(pest, index) in category2Pests" :key="index">
+          <view class="pest-info">
+            <view class="pest-color" :style="{ backgroundColor: pest.color }"></view>
+            <text class="pest-name">{{ pest.name }}</text>
+          </view>
+          <text class="pest-count">{{ pest.count }}</text>
+        </view>
+      </view>
+
+      <!-- 三类害虫 -->
+      <view class="pest-category">
+        <view class="category-header">
+          <text class="category-title">三类害虫</text>
+          <text class="category-count">数量</text>
+        </view>
+        <view class="pest-item" v-for="(pest, index) in category3Pests" :key="index">
+          <view class="pest-info">
+            <view class="pest-color" :style="{ backgroundColor: pest.color }"></view>
+            <text class="pest-name">{{ pest.name }}</text>
+          </view>
+          <text class="pest-count">{{ pest.count }}</text>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      title: '查看图片',
+      currentThumbnail: 2,
+      thumbnails: [
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" },
+        { src: "https://trae-api-cn.mchost.guru/api/ide/v1/text_to_image?prompt=insects%20on%20white%20surface&image_size=square" }
+      ],
+      category1Pests: [
+        { name: '蚜虫', color: '#FF9933', count: 3 },
+        { name: '松墨天牛', color: '#FF3333', count: 3 },
+        { name: '夜蛾', color: '#3366FF', count: 3 }
+      ],
+      category2Pests: [
+        { name: '蚜虫', color: '#FF9933', count: 3 },
+        { name: '松墨天牛', color: '#FF3333', count: 3 },
+        { name: '夜蛾', color: '#3366FF', count: 3 }
+      ],
+      category3Pests: [
+        { name: '蚜虫', color: '#FF9933', count: 3 },
+        { name: '松墨天牛', color: '#FF3333', count: 3 },
+        { name: '夜蛾', color: '#3366FF', count: 3 }
+      ]
+    };
+  },
+  methods: {
+    goBack() {
+      uni.navigateBack();
+    },
+    selectThumbnail(index) {
+      this.currentThumbnail = index;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.device-photo-page {
+  background-color: #F5F5F5;
+  min-height: 100vh;
+  width: 100%;
+  padding-top: 112rpx;
+  background: linear-gradient(180deg, #ffffff00 0%, #F5F6FA 23.64%, #F5F6FA 100%), linear-gradient(102deg, #BFEADD 6.77%, #B8F1E7 40.15%, #B9EEF5 84.02%);
+  .device-detail__header {
+    width: 100%;
+    font-size: 28rpx;
+    color: #999;
+    color: #042118;
+    font-family: 'Source Han Sans CN VF';
+    font-weight: 700;
+    position: relative;
+    text-align: center;
+    .arrow-left {
+      position: absolute;
+      left: 32rpx;
+      margin-right: 12rpx;
+    }
+  }
+
+  /* 顶部导航栏 */
+  .nav-bar {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 24rpx;
+    background-color: #E6F7EF;
+
+    .nav-left {
+      .back-icon {
+        font-size: 36rpx;
+        color: #042118;
+      }
+    }
+
+    .nav-title {
+      font-size: 32rpx;
+      font-weight: 700;
+      color: #042118;
+    }
+
+    .nav-right {
+      display: flex;
+      align-items: center;
+
+      .more-icon {
+        font-size: 32rpx;
+        color: #042118;
+        margin-right: 24rpx;
+      }
+
+      .eye-icon {
+        font-size: 32rpx;
+      }
+    }
+  }
+
+  /* 日期选择器 */
+  .date-picker {
+    display: flex;
+    align-items: center;
+    padding: 20rpx 24rpx;
+    background-color: #FFFFFF;
+    margin-bottom: 24rpx;
+    width: 90%;
+    margin:20rpx auto;
+    border-radius: 48rpx;
+    position: relative;
+    .date-input {
+      display: flex;
+      flex-direction: column;
+      width: 35%;
+      .date-label {
+        font-size: 24rpx;
+        color: #999999;
+        margin-bottom: 8rpx;
+      }
+
+      .date-value {
+        font-size: 28rpx;
+        color: #042118;
+        font-weight: 500;
+      }
+    }
+    .calendar {
+      position: absolute;
+      right: 24rpx;
+      top: 50%;
+      transform: translateY(-50%);
+      font-size: 32rpx;
+      color: #999999;
+    }
+    .date-separator {
+      margin: 0 24rpx;
+      font-size: 28rpx;
+      color: #999999;
+    }
+  }
+
+  /* 主图片区域 */
+  .main-photo {
+    position: relative;
+    margin: 0 24rpx 24rpx;
+    background-color: #FFFFFF;
+    border-radius: 16rpx;
+    padding: 0;
+    overflow: hidden;
+
+    .main-photo-image {
+      width: 100%;
+      height: 400rpx;
+      object-fit: cover;
+      border-radius: 8rpx;
+    }
+
+    .photo-timestamp {
+      position: absolute;
+      bottom: 0rpx;
+      left: 0rpx;
+      width:100%;
+      background-color: rgba(0, 0, 0, 0.6);
+      color: #FFFFFF;
+      padding: 8rpx 16rpx;
+      border-radius: 8rpx;
+      font-size: 24rpx;
+    }
+  }
+
+  /* 缩略图预览 */
+  .thumbnail-preview {
+    margin: 0 24rpx 24rpx;
+
+    .thumbnail-scroll {
+      gap: 16rpx;
+      padding-bottom: 16rpx;
+      box-sizing: border-box;
+      white-space: nowrap;
+      overflow-x: auto;
+      overflow-y: hidden;
+      width: 100%;
+      // 隐藏滚动条
+      -ms-overflow-style: none;
+      scrollbar-width: none;
+      .thumbnail-item {
+        width: 120rpx;
+        height: 120rpx;
+        border-radius: 8rpx;
+        overflow: hidden;
+        border: 2rpx solid transparent;
+        display: inline-block;
+        box-sizing: border-box;
+        margin-right: 10rpx;
+        &.active {
+          border-color: #0BBC58;
+        }
+
+        .thumbnail-image {
+          width: 100%;
+          height: 100%;
+          object-fit: cover;
+        }
+      }
+    }
+  }
+
+  /* 识别结果 */
+  .recognition-result {
+    margin: 0 24rpx 24rpx;
+    background-color: #FFFFFF;
+    border-radius: 16rpx;
+    padding: 24rpx;
+
+    .result-title {
+      font-size: 28rpx;
+      font-weight: 700;
+      color: #042118;
+      margin-bottom: 24rpx;
+    }
+
+    /* 害虫类别 */
+    .pest-category {
+      margin-bottom: 32rpx;
+      border: 1px solid #E4E7ED;
+      border-radius: 16rpx;
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .category-header {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 16rpx;
+        background: #F6F8FC;
+        padding: 18rpx 24rpx;
+        .category-title {
+          font-size: 24rpx;
+          font-weight: 500;
+          color: #042118;
+        }
+
+        .category-count {
+          font-size: 24rpx;
+          color: #999999;
+        }
+      }
+
+      .pest-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 12rpx;
+        padding: 6rpx 24rpx;
+        &:last-child {
+          margin-bottom: 0;
+        }
+
+        .pest-info {
+          display: flex;
+          align-items: center;
+
+          .pest-color {
+            width: 16rpx;
+            height: 16rpx;
+            border-radius: 50%;
+            margin-right: 12rpx;
+          }
+
+          .pest-name {
+            font-size: 24rpx;
+            color: #042118;
+          }
+        }
+
+        .pest-count {
+          font-size: 24rpx;
+          color: #042118;
+        }
+      }
+    }
+  }
+}
+</style>

+ 977 - 0
pages/equipList2/index copy.vue

@@ -0,0 +1,977 @@
+<template>
+	<view>
+		<view class="textbox">
+			<view class="inputs">
+				<u-search placeholder="请输入设备名称/编号" v-model="device_id" placeholder-color="#909696" :show-action="false"
+					search-icon-color="#909696" @input="searchinput">
+				</u-search>
+			</view>
+				<view class="tab">
+					<view class="tab-content">
+						<view class="tab-box">
+							<view v-for="(item,index) in menuList" :key="index" @click="change(index,item)"
+								:class="['tab-item',current==index?'active':'']">
+								<image class="img-icon" :src="item.app_menu_icon" mode=""></image>
+								<view class="text">{{item.purview_name}}</view>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="listbox">
+				<view class="second-tab">
+					<view class="tab-box">
+						<view v-for="(item,index) in list" :key="index" @click="changeDevice(item,index)"
+							:class="['tab-item',currents==index?'active':'']">
+							<text>{{item.purview_name}}</text>
+						</view>
+					</view>
+				</view>
+				<view class="third-tab">
+					<view class="third-tab-item" @click="changeStatus('')" :class="{'active-tab':device_status == ''}">总计{{ counts }}</view>
+					<view class="third-tab-item" @click="changeStatus('1')" :class="{'active-tab':device_status == '1'}">在线{{ online_counts }}</view>
+					<view class="third-tab-item" @click="changeStatus('0')" :class="{'active-tab':device_status == '0'}">离线{{ offline_counts }}</view>
+				</view>
+				<scroll-view :scroll-top="0" :scroll-y="true" class="list scroll-Y" @scrolltoupper="upper"
+					@scrolltolower="lower" @scroll="scroll">
+					<view class="list_item" v-for="(item, index) in eqlistdata" :key="index" @click="historys(item)">
+						<view class="list_item_top">
+							<p class="p1"> <span class="title">{{ (item.device_name || '--' )}}</span><span class="sub-title">{{ item.only_for_show || item.device_id }}</span></p>
+							<p class="online-status">
+								<image v-if="item.device_status == 1 || item.is_online" :src="$imageURL+'/bigdata_app/newImg/home/online.png'" mode=""></image>
+								<image v-else :src="$imageURL+'/bigdata_app/newImg/home/outline.png'" mode=""></image>
+							</p>
+						</view>
+						<view class="list_item_text">
+							<p><span class="label">上报时间</span>{{ item.uptime | timeFormat() }}</p>
+							<p>
+								<span class="label">设备位置</span>{{ (item.address|| '无') }}
+							</p>
+						</view>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
+		<view class="loading" v-if="loadingtf">
+			<image src="../../static/images/ajax-loader.gif" mode="" class="img"></image>
+		</view>
+		<view class="top" v-if="isTop" @click="top">
+			<image :src="
+          $imageURL+'/bigdata_app' +
+          '/image/6209a98f0cb3b5086f2ca36152c9269.png'
+        " mode=""></image>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		Debounce,
+		Throttle
+	} from '../../util/anitthro.js';
+	export default {
+		data() {
+			return {
+				list: [],
+        pur_id: '',
+        device_status: '',
+        counts:0,
+        online_counts:0,
+        offline_counts:0,
+				current: 0,
+				currents: 0,
+				page: 1,
+				size: 10,
+				eqlistdata: [],
+				isTop: false,
+				device_model: 0,
+				infoalter: false, // 权限设置,
+				type_id: 0, //设备类型,
+				imgpath: [],
+				loadingtf: false,
+				width: 0, //顶部搜索栏宽度
+				device_id: '', //搜索设备ID
+				menuList: []
+			};
+		},
+		methods: {
+      changeStatus(status){
+        this.device_status = status;
+        this.page = 1;
+        if (this.type_id == 10) {
+          this.xyeqlist(true);
+        } else {
+          this.eqlist(true);
+        }
+      },
+			async getUserlogin() {
+        this.list = [];
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=user.login.user_login_info',
+					method: 'POST',
+					data: {
+						is_app: 1,
+					},
+				});
+        res.forEach(item=>{
+          item.icon = '/bigdata_app/newImg/home/sqjd.png'
+        })
+        const menulist = res || [];
+        const menuItem = menulist.find(item => item.purview_name == '智慧物联')
+        this.menuList = menuItem.children || [];
+        this.list = this.menuList[0].children || []
+        this.pur_id = this.menuList[0].pur_id || '';
+        if(this.list[0].purview_name != '全部'){
+          this.list.unshift({
+            device_type_id: 'yfkj',
+            purview_name: '全部'
+          })
+        }
+        this.type_id = this.list[0].device_type_id;
+        this.initPage();
+      },
+			// 大棚
+			async getDpDeviceList(tf) {
+				const res = await this.$myRequest({
+					url: '/api/v2/iot/mobile/device/dpkzg/yf/list/',
+					method: 'post',
+					data: {
+						pageSize: this.size,
+						pageNum: this.page,
+					},
+				});
+				this.loadingtf = false;
+				const eqlistdata = res || [];
+				eqlistdata.forEach((item) => {
+					const newtime = +new Date() / 1000;
+					const days = (newtime - item.addtime) / 60 / 60 / 24;
+					item.days = Math.round(days);
+					item.device_id = item.devCode;
+					item.uptime = item.devUpdateddate || item.uptime;
+					item.device_name = item.devName;
+					item.is_online = item.device_status == 1 ? true : false;
+				});
+				this.eqlistdata = eqlistdata;
+			},
+			// 水肥
+			async getDeviceList(tf) {
+				const res = await this.$myRequest({
+					url: '/api/v2/iot/mobile/device/sf/zsrf/list/',
+					method: 'post',
+					data: {
+						pageSize: this.size,
+						pageNum: this.page,
+					},
+				});
+				this.loadingtf = false;
+				const eqlistdata = res || [];
+				eqlistdata.forEach((item) => {
+					const newtime = +new Date() / 1000;
+					const days = (newtime - item.addtime) / 60 / 60 / 24;
+					item.days = Math.round(days);
+					item.device_id = item.devCode;
+					item.uptime = item.devUpdateddate;
+					item.addtime = item.devCreateddate;
+					item.device_name = item.devName;
+					item.is_online = item.device_status == 1 ? true : false;
+				});
+				this.eqlistdata = eqlistdata;
+			},
+			async eqlist(tf) {
+				//设备列表
+				this.loadingtf = true;
+				if (this.type_id == 42) {
+					this.getDpDeviceList(tf);
+					return;
+				}
+				if (this.type_id == 40) {
+					this.getDeviceList(tf);
+					return;
+				}
+        let data = {}
+        if(this.type_id == 'yfkj'){
+          data = {
+						device_type_id: this.type_id,
+						page: this.page,
+						page_size: this.size,
+            pur_id: this.pur_id,
+						device_status: this.device_status,
+						device_id: this.device_id,
+						device_model: this.device_model
+          }
+        }else{
+          data = {
+						device_type_id: this.type_id,
+						page: this.page,
+						page_size: this.size,
+						device_status: this.device_status,
+						device_id: this.device_id,
+						device_model: this.device_model
+          }
+        }
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=forecast.worm_lamp.lamp_list',
+					data: data,
+				});
+				this.loadingtf = false;
+        this.counts = res.counts || 0;
+        this.online_counts = res.device_online_count || 0;
+        this.offline_counts = res.device_offline_count || 0;
+				if (tf) {
+					this.eqlistdata = this.eqlistdata.concat(res.data);
+				} else {
+					this.eqlistdata = res.data;
+				}
+			},
+			async xyeqlist(tf) {
+				//设备列表
+				this.loadingtf = true;
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=sex_lure_nl.sex_lure.nl_device_list',
+					data: {
+						device_type_id: this.type_id,
+						page: this.page,
+						device_status: this.device_status,
+						page_size: this.size,
+            pur_id: this.type_id == 'yfkj' ? this.pur_id : '',
+						device_id: this.device_id,
+					},
+				});
+				this.loadingtf = false;
+				var newtime = +new Date() / 1000;
+				if (tf) {
+					this.eqlistdata = this.eqlistdata.concat(res.data);
+				} else {
+					this.eqlistdata = res.data;
+				}
+				for (var i = 0; i < this.eqlistdata.length; i++) {
+					var days = (newtime - this.eqlistdata[i].addtime) / 60 / 60 / 24;
+					this.eqlistdata[i].days = Math.round(days);
+				}
+			},
+			async camera() {
+				//监控
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=camera.camera_manage.list_camera',
+					data: {
+						page_size: 1,
+					},
+				});
+				this.accessToken = res.accessToken;
+			},
+			// async usertype() {
+			// 	//设备列表
+			// 	const res = await this.$myRequest({
+			// 		url: '/api/api_gateway?method=home.homes.user_device_type',
+			// 	});
+			// 	for (var i = 0; i < res.length; i++) {
+			// 		if (res[i].type_name == '温室大棚') {
+			// 			continue;
+			// 		}
+			// 		var obj = {
+			// 			name: res[i].type_name,
+			// 			id: res[i].id,
+			// 			device_model: res[i].device_model,
+			// 			pur_id: res[i].pur_id,
+			// 		};
+			// 		this.list.push(obj);
+			// 	}
+			// 	if (res.length) {
+			// 		this.type_id = this.list[0].id;
+			// 		this.device_model = this.list[0].device_model;
+			// 		if (this.list[0].id == 10) {
+			// 			this.xyeqlist();
+			// 		} else {
+			// 			this.eqlist();
+			// 		}
+			// 	}
+			// },
+			change(index,itemData) {
+        this.list = this.menuList[index].children || []
+        if(this.list[0].purview_name != '全部'){
+          this.list.unshift({
+            device_type_id: 'yfkj',
+            purview_name: '全部'
+          })
+        }
+        this.current = index;
+        const item = this.list[0];
+        this.pur_id = itemData.pur_id || '';
+        this.changeDevice(item,0);
+			},
+      changeDevice(item,index){
+				this.currents = index;
+				this.page = 1;
+				this.eqlistdata = [];
+				this.type_id = item.device_type_id;
+				if (this.type_id == 10) {
+					this.xyeqlist();
+				} else {
+					this.eqlist();
+				}
+      },
+			clickRight() {
+				//搜索
+				this.width = '90%';
+			},
+			modification(item) {
+				uni.navigateTo({
+					url: './modification?data=' + JSON.stringify(item) + '&id=' + this.type_id,
+				});
+			},
+			top() {
+				uni.pageScrollTo({
+					scrollTop: 0,
+					duration: 500,
+				});
+			},
+      initPage(){
+        this.eqlistdata = [];
+        // this.camera();
+        this.current = 0;
+        this.currents = 0;
+        this.page = 1;
+        if (this.type_id == 10) {
+          this.xyeqlist(true);
+        } else {
+          this.eqlist(true);
+        }
+        this.width = 0;
+      },
+			historys(itemOld) {
+				let item = JSON.parse(JSON.stringify(itemOld));
+				switch (this.type_id) {
+					// 水肥新设备
+					case 22:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						uni.navigateTo({
+							url: '../waterandfernew/details?shebei=' + JSON.stringify(obj),
+						});
+						break;
+						// 病虫害可视监测
+					case 14:
+						item.addtime = item.uptime;
+						uni.navigateTo({
+							url: '../cb/sy/detail?detail=' + JSON.stringify(item),
+						});
+						break;
+					case 2:
+						item.addtime = item.uptime;
+						uni.navigateTo({
+							url: '../prevention/equipmentdetails?shebei=' + JSON.stringify(item),
+						});
+						break;
+					case 38:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.equip_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						uni.navigateTo({
+							url: '../environment/equipment-new?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 5:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.equip_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						uni.navigateTo({
+							url: '../environment/equipment?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 6:
+						uni.navigateTo({
+							url: '/pages/webview/webview?device_id=' +
+								item.imei +
+								'&accessToken=' +
+								this.accessToken,
+						});
+						break;
+					case 3:
+						item.addtime = item.uptime;
+						item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cbd/detail?info=' + JSON.stringify(item),
+						});
+						break;
+					case 28:
+						item.addtime = item.uptime;
+						item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/smallPest/smallPest?info=' + JSON.stringify(item),
+						});
+						break;
+					case 4:
+						item.addtime = item.uptime;
+						item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/equip-detail/equip-detail?info=' + JSON.stringify(item),
+						});
+						break;
+					case 32:
+					case 33:
+					case 34:
+					case 35:
+						item.addtime = item.uptime;
+						item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/equip-detail/equip-detail-new?info=' +
+								JSON.stringify(item),
+						});
+						break;
+					case 7:
+						item.addtime = item.uptime;
+						item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/equip-detail/equip-detail?info=' + JSON.stringify(item),
+						});
+						break;
+					case 8:
+						// item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/thxydetail/thxydetail?imei=' + item.imei,
+						});
+						break;
+					case 29:
+						// item.type = this.type_id;
+						uni.navigateTo({
+							url: `../cb/nlNewXy/nlNewXy?imei=${item.imei}&showId=${item.only_for_show}`,
+						});
+						break;
+					case 24:
+						// item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/zjxydetail/thxydetail?imei=' + item.imei,
+						});
+						break;
+					case 12:
+						item.addtime = item.uptime;
+						uni.navigateTo({
+							url: '../cb/xctdetail/xctdetail?info=' + JSON.stringify(item),
+						});
+						break;
+					case 13:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						uni.navigateTo({
+							url: '../waterandfer/datails?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 15:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						uni.navigateTo({
+							url: '../environment/gsequipment?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 17:
+						break;
+					case 18:
+						var obj = {};
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						uni.navigateTo({
+							url: '../cb/shuifeiL/shuifeiL?detail=' + JSON.stringify(obj),
+						});
+						break;
+          case 43:
+            uni.navigateTo({
+              url: "/pages/fmSys/details?info=" + JSON.stringify(item)
+            })
+          break;
+          case 44:
+            uni.navigateTo({
+              url: "/pages/webviewdgp/webview?device_id=" + item.imei + "&accessToken=" + this.accessToken || uni
+                .getStorageSync('session_key') +
+                '&type=dgp'
+            })
+          break;
+					case 11:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						obj.location = item.address;
+						obj.type = 11;
+						uni.navigateTo({
+							url: '../disease/cmb?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 19:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						obj.location = item.address;
+						obj.type = 19;
+						uni.navigateTo({
+							url: '../disease/cmb?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 20:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						obj.location = item.address;
+						obj.type = 20;
+						uni.navigateTo({
+							url: '../disease/cmb?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 21:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						obj.location = item.address;
+						obj.type = 21;
+						uni.navigateTo({
+							url: '../disease/cmb?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 26:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						obj.location = item.address;
+						obj.type = 26;
+						uni.navigateTo({
+							url: '../disease/cmb?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 27:
+						var obj = {};
+						obj.d_id = item.d_id;
+						obj.device_id = item.imei;
+						obj.is_online = item.is_online;
+						obj.lat = item.lat;
+						obj.lng = item.lng;
+						obj.equip_name = item.device_name;
+						obj.uptime = item.uptime;
+						obj.location = item.address;
+						obj.type = 26;
+						uni.navigateTo({
+							url: '../disease/mls/mls?shebei=' + JSON.stringify(obj),
+						});
+						break;
+					case 25:
+						item.addtime = item.uptime;
+						uni.navigateTo({
+							url: '../cb/xylps/detail?detail=' + JSON.stringify(item),
+						});
+						break;
+					default:
+						item.addtime = item.uptime;
+						item.type = this.type_id;
+						uni.navigateTo({
+							url: '../cb/xy2.0/particulars?info=' + JSON.stringify(item),
+						});
+						break;
+					case 40:
+						item.addtime = item.uptime;
+						uni.navigateTo({
+							url: `../cb/shuifeizs/shuifeizs?devBid=${item.devBid}&devName=${item.devName}&devStatus=${item.devStatus}`,
+						});
+						break;
+					case 42:
+						item.addtime = item.uptime;
+						uni.navigateTo({
+							url: `../cb/wenshizs/wenshizs?devBid=${item.devBid}&devName=${item.device_name}&devStatus=${item.devStatus}`,
+						});
+						break;
+				}
+			},
+			search() {
+				this.eqlistdata = [];
+				this.page = 1;
+				if (this.list[this.currents].id == 10) {
+					this.xyeqlist();
+				} else {
+					this.eqlist();
+				}
+			},
+			searchinput() {
+				Debounce(() => {
+					this.eqlistdata = [];
+					this.page = 1;
+					if (this.list[this.currents].id == 10) {
+						this.xyeqlist();
+					} else {
+						this.eqlist();
+					}
+				}, 1000)();
+			},
+			scrollTop(e) {},
+			upper() {},
+			lower() {
+				this.page++;
+				if (this.type_id == 10) {
+					this.xyeqlist(true);
+				} else {
+					this.eqlist(true);
+				}
+			},
+			scroll() {},
+		},
+		onLoad() {
+			this.getUserlogin();
+		},
+		onTabItemTap(e) {
+		},
+		onReachBottom() {
+			this.page++;
+			if (this.type_id == 10) {
+				this.xyeqlist(true);
+			} else {
+				this.eqlist(true);
+			}
+		},
+		onPageScroll(e) {
+			//nvue暂不支持滚动监听,可用bindingx代替
+			if (e.scrollTop > 200) {
+				//距离大于200时显示
+				this.isTop = true;
+			} else {
+				//距离小于200时隐藏
+				this.isTop = false;
+			}
+		},
+	};
+</script>
+<style lang="scss">
+	page {
+		background: linear-gradient(180deg, #ffffff00 0%, #F5F6FA 23.64%, #F5F6FA 100%), linear-gradient(102deg, #BFEADD 6.77%, #B8F1E7 40.15%, #B9EEF5 84.02%);
+	}
+
+	/deep/.uni-icons {
+		font-size: 40rpx !important;
+	}
+  input{
+    background: transparent !important;
+  }
+	.textbox {
+		width: 100%;
+		height: 100vh;
+		padding-top: 102rpx;
+		box-sizing: border-box;
+
+	}
+
+	.inputs {
+		width: 55%;
+		margin-left: 12rpx;
+
+		/deep/.u-content {
+			background-color: #fff !important;
+		}
+
+		/deep/.uni-input-wrapper {
+			background-color: #fff !important;
+		}
+
+	}
+
+	.utabs_box {
+		width: 100%;
+		position: fixed;
+		top: 88px;
+		background-color: #ffffff;
+		z-index: 100;
+
+		.utabs {
+			width: 95%;
+			margin: 0 auto;
+		}
+	}
+
+	.loading {
+		position: fixed;
+		top: 440px;
+		width: 95%;
+		left: 2.5%;
+		text-align: center;
+
+		.img {
+			width: 300rpx;
+			height: 40rpx;
+		}
+	}
+
+  .active-tab{
+    border-radius: 8px;
+    background: #F1F4F8;
+  }
+
+	.tab-box {
+		font-size: 30rpx;
+		// padding: 32rpx;
+		box-sizing: border-box;
+		width: 100%;
+		height: 100%;
+		overflow-y: hidden;
+		overflow-x: auto;
+		white-space: nowrap;
+
+		.tab-item {
+			cursor: pointer;
+			position: relative;
+			text-align: center;
+			display: inline-block;
+			padding: 16rpx 24rpx;
+			box-sizing: border-box;
+
+			span {
+				display: inline-block;
+			}
+		}
+	}
+
+	.tab {
+		// background-color: #0BBC58;
+		margin-top: 42rpx;
+		margin-bottom: 38rpx;
+		padding: 0 32rpx;
+		
+		.img-icon {
+			width: 80rpx;
+			height: 80rpx;
+			margin-bottom: 12rpx;
+		}
+		
+		.text {
+			color: #303133;
+			font-size: 24rpx;
+		}
+		.tab-content {
+			width: 100%;
+		
+			height: 162rpx;
+		
+		}
+
+		.tab-item.active {
+
+			border-radius: 24rpx;
+		
+			background: linear-gradient(0deg, #0bbc580f 0%, #0bbc580f 100%), #00000005;
+
+		}
+		
+	}
+
+	.second-tab {
+		height: 80rpx;
+		.tab-item{
+			font-size: 28rpx;
+			color: #999999;
+		}
+		.tab-item.active {
+			color: #303133;
+			font-weight: 700;
+			
+		}
+		.tab-item.active::after {
+		  content: '';
+		  position: absolute;
+		  bottom: 0;
+		  left: 50%;
+		  transform: translateX(-50%);
+		  width: 18px; /* 比文字略宽 */
+		  height: 18px;
+		  border: 3px solid #0BBC58;
+		  border-radius: 50%;
+			border-color: transparent; /* 隐藏其他部分 */
+
+		    border-bottom-color: #0BBC58; /* 组合成45度角 */
+		    // transform: rotate(0deg); /* 调整角度 */
+		}
+	}
+
+	.third-tab {
+		margin: 8rpx 0;
+		height: 64rpx;
+		line-height: 64rpx;
+		display: flex;
+		justify-content: space-between;
+
+		.third-tab-item {
+			flex: 1;
+			text-align: center;
+		}
+	}
+
+	.list {
+		width: 100%;
+		background-color: #F5F6FA;
+		// margin-bottom: 100rpx;
+		overflow-y: auto;
+		padding: 0 32rpx;
+		box-sizing: border-box;
+
+		.list_item {
+			width: 100%;
+			margin: 0 auto 24rpx;
+			padding: 32rpx;
+			box-sizing: border-box;
+			position: relative;
+			background-color: #ffffff;
+			border-radius: 16rpx;
+
+			.list_item_top {
+		
+
+				.p1 {
+					width: 86%;
+
+					height: 60rpx;
+					line-height: 60rpx;
+					font-size: 28rpx;
+					overflow: hidden;
+
+				
+
+					.title{
+						 color: #333333;
+						 
+						 font-size: 28rpx;
+						
+						 font-weight: 700;
+						margin-right: 8rpx;
+					}
+					
+					.sub-title{
+						 color: #666666;
+						 
+						 font-size: 28rpx;
+						
+						 font-weight: 400;
+						
+					}
+				}
+
+				
+			}
+			.online-status{
+				font-size: 28rpx;
+				position: absolute;
+				top:0rpx;
+				text-align: center;
+				right: 0rpx;
+				width: 76px;
+				height: 28px;
+				// line-height: 28px;
+				// border-radius: 0px 0px 0px 26px;
+				
+				// border: 1px solid #ffffff;
+				image{
+					width: 152rpx;
+					height: 56rpx;
+				}
+	
+			}
+			// .p2 {
+					
+			// 	color: #0BBC58;
+			// 	background: #0bbc581a;
+			// }
+			
+			// .p_out {
+					
+			// 	color: #FB4E52;
+			// 	background: #fb4e521a;
+			// }
+			.list_item_text {
+				margin-top: 20rpx;
+				
+				p {
+					font-size: 24rpx;
+					color: #303133;
+					margin-top: 10rpx;
+					word-break: break-all;
+				}
+				
+
+				.label{
+					 color: #999999;
+					 text-align: right;
+					margin-right: 32rpx;
+					 font-size: 24rpx;
+				}
+			}
+
+			.list_item_btn {
+				width: 126rpx;
+				color: #42b983;
+				height: 40rpx;
+				text-align: center;
+				border: 1rpx solid #42b983;
+				border-radius: 25rpx;
+				font-size: 24rpx;
+				line-height: 35rpx;
+				position: absolute;
+				bottom: 15rpx;
+				right: 20rpx;
+			}
+		}
+	}
+
+	.top {
+		position: fixed;
+		right: 30px;
+		bottom: 100px;
+		z-index: 100;
+
+		image {
+			width: 100rpx;
+			height: 100rpx;
+		}
+	}
+</style>

+ 149 - 303
pages/equipList2/index.vue

@@ -1,86 +1,99 @@
 <template>
 	<view>
-
-
 		<view class="textbox">
 			<view class="inputs">
-
-				<u-search placeholder="请输入设备ID" v-model="imports" placeholder-color="#909696" :show-action="false"
+				<u-search placeholder="请输入设备名称/编号" v-model="device_id" placeholder-color="#909696" :show-action="false"
 					search-icon-color="#909696" @input="searchinput">
 				</u-search>
-
 			</view>
-			
 				<view class="tab">
 					<view class="tab-content">
 						<view class="tab-box">
-							<view v-for="(item,index) in menuList" :key="index" @click="change(index)"
-								:class="['tab-item',currents==index?'active':'']">
-								<image class="img-icon" :src="$imageURL+item.icon" mode=""></image>
-								<view class="text">{{item.name}}</view>
+							<view v-for="(item,index) in menuList" :key="index" @click="change(index,item)"
+								:class="['tab-item',current==index?'active':'']">
+								<image class="img-icon" :src="item.app_menu_icon" mode=""></image>
+								<view class="text">{{item.purview_name}}</view>
 							</view>
-
 						</view>
 					</view>
 				</view>
 				<view class="listbox">
 				<view class="second-tab">
 					<view class="tab-box">
-						<view v-for="(item,index) in list" :key="index" @click="change(index)"
-							:class="['tab-item',currents==index?'active':'']">
-							<text>{{item.name}}</text>
-
+						<view
+              v-for="(item,index) in list"
+              :key="index"
+              @click="changeDevice(item,index)"
+							:class="['tab-item',currents==index?'active':'']"
+            >
+							<text>{{item.purview_name}}</text>
 						</view>
-
 					</view>
 				</view>
 				<view class="third-tab">
-					<view class="third-tab-item">总计</view>
-					<view class="third-tab-item">在线</view>
-					<view class="third-tab-item">离线</view>
+					<view 
+            class="third-tab-item"
+            @click="changeStatus('')" 
+            :class="{'active-tab' : device_status == ''}"
+          >总计{{ counts }}</view>
+					<view 
+            class="third-tab-item"
+            @click="changeStatus('1')" 
+            :class="{'active-tab' : device_status == '1'}"
+          >在线{{ online_counts }}</view>
+					<view 
+            class="third-tab-item"
+            @click="changeStatus('0')" 
+            :class="{'active-tab' : device_status == '0'}"
+          >离线{{ offline_counts }}</view>
 				</view>
-				<scroll-view :scroll-top="0" :scroll-y="true" class="list scroll-Y" @scrolltoupper="upper"
-					@scrolltolower="lower" @scroll="scroll">
+				<scroll-view 
+          :scroll-top="0"
+          :scroll-y="true"
+          class="list scroll-Y"
+          @scrolltoupper="upper"
+					@scrolltolower="lower"
+          @scroll="scroll"
+        >
 					<view class="list_item" v-for="(item, index) in eqlistdata" :key="index" @click="historys(item)">
 						<view class="list_item_top">
-							<p class="p1"> <span class="title">{{ (item.device_name || '--' )| yfEllipsis(7)}}</span><span class="sub-title">{{ item.only_for_show || item.device_id }}</span></p>
-							
-							<p v-if="![11, 19, 20].includes(type_id)"  class="online-status">
-								<!-- {{ item.is_online ? '在线' : '离线' }} -->
-								<image v-if="item.is_online" :src="$imageURL+'/bigdata_app/newImg/home/online.png'" mode=""></image>
-								<image v-else :src="$imageURL+'/bigdata_app/newImg/home/outline.png'" mode=""></image>
+							<p class="p1">
+                <span class="title">{{ (item.name || '--' )}}</span>
+                <span class="sub-title">{{ item.id || item.device_id }}</span>
+              </p>
+							<p class="online-status">
+								<image
+                  v-if="item.status == 1 || item.is_online" 
+                  :src="$imageURL+'/bigdata_app/newImg/home/online.png'" 
+                  mode=""
+                ></image>
+								<image
+                  v-else
+                  :src="$imageURL+'/bigdata_app/newImg/home/outline.png'"
+                  mode=""
+                ></image>
 							</p>
 						</view>
 						<view class="list_item_text">
-							
-							<p v-if="type_id == 40 || type_id == 42">
-								<span class="label">上报时间</span> {{ item.uptime }}
-							</p>
-							<p v-else><span class="label">上报时间</span>{{ item.uptime | timeFormat() }}</p>
 							<p>
-								<span class="label">设备位置</span>{{ (item.address|| '无') | yfEllipsis(16)}}
+                <span class="label">上报时间</span>{{ item.uptime | timeFormat() }}
+              </p>
+							<p>
+								<span class="label">设备位置</span>{{ (item.address|| '无') }}
 							</p>
 						</view>
 					</view>
 				</scroll-view>
-
-				<!-- </view> -->
 			</view>
 		</view>
-
-		<!-- <view class="utabs_box">
-			<view class="utabs">
-				<u-tabs :list="list" :is-scroll="true" :current="currents" @change="change" item-width="140"
-					font-size="24" gutter="20" bar-width="60" active-color="#42b983" v-if="list.length"></u-tabs>
-			</view>
-		</view> -->
 		<view class="loading" v-if="loadingtf">
 			<image src="../../static/images/ajax-loader.gif" mode="" class="img"></image>
 		</view>
 		<view class="top" v-if="isTop" @click="top">
-			<image :src="
-          $imageURL+'/bigdata_app' +
-          '/image/6209a98f0cb3b5086f2ca36152c9269.png'
+			<image 
+        :src="
+        $imageURL+'/bigdata_app' +
+        '/image/6209a98f0cb3b5086f2ca36152c9269.png'
         " mode=""></image>
 		</view>
 	</view>
@@ -95,6 +108,11 @@
 		data() {
 			return {
 				list: [],
+        pur_id: '',
+        device_status: '',
+        counts:0,
+        online_counts:0,
+        offline_counts:0,
 				current: 0,
 				currents: 0,
 				page: 1,
@@ -107,233 +125,104 @@
 				imgpath: [],
 				loadingtf: false,
 				width: 0, //顶部搜索栏宽度
-				imports: '', //搜索设备ID
-				menuList: [{
-					icon: '/bigdata_app/newImg/home/sqjd.png',
-					name: '四情基地',
-
-				}, {
-					icon: '/bigdata_app/newImg/home/zngg.png',
-					name: '智能灌溉',
-
-				}, {
-					icon: '/bigdata_app/newImg/home/yhgl.png',
-					name: '用户管理',
-				}, {
-					icon: '/bigdata_app/newImg/home/shfw.png',
-					name: '售后服务',
-
-				}, {
-					icon: '/bigdata_app/newImg/home/more.png',
-					name: '更多功能'
-				}, {
-					icon: '/bigdata_app/newImg/home/more.png',
-					name: '更多功能'
-				}]
+				device_id: '', //搜索设备ID
+				menuList: []
 			};
 		},
 		methods: {
-			// 大棚
-			async getDpDeviceList(tf) {
-				const res = await this.$myRequest({
-					url: '/api/v2/iot/mobile/device/dpkzg/yf/list/',
-					method: 'post',
-					data: {
-						pageSize: this.size,
-						pageNum: this.page,
-					},
-				});
-				this.loadingtf = false;
-				const eqlistdata = res || [];
-				eqlistdata.forEach((item) => {
-					const newtime = +new Date() / 1000;
-					const days = (newtime - item.addtime) / 60 / 60 / 24;
-					item.days = Math.round(days);
-					item.device_id = item.devCode;
-					item.uptime = item.devUpdateddate;
-					item.addtime = item.devCreateddate;
-					item.device_name = item.devName;
-					item.real_name = item.realName;
-					item.is_online = item.devStatus == 1 ? true : false;
-				});
-				this.eqlistdata = eqlistdata;
-			},
-			// 水肥
-			async getDeviceList(tf) {
+      changeStatus(status){
+        this.device_status = status;
+        this.page = 1;
+        this.eqlist();
+      },
+			async getUserlogin() {
+        this.list = [];
 				const res = await this.$myRequest({
-					url: '/api/v2/iot/mobile/device/sf/zsrf/list/',
-					method: 'post',
+					url: '/api/api_gateway?method=user.login.user_login_info',
+					method: 'POST',
 					data: {
-						pageSize: this.size,
-						pageNum: this.page,
+						is_app: 1,
 					},
 				});
-				this.loadingtf = false;
-				const eqlistdata = res || [];
-				eqlistdata.forEach((item) => {
-					const newtime = +new Date() / 1000;
-					const days = (newtime - item.addtime) / 60 / 60 / 24;
-					item.days = Math.round(days);
-					item.device_id = item.devCode;
-					item.uptime = item.devUpdateddate;
-					item.addtime = item.devCreateddate;
-					item.device_name = item.devName;
-					item.real_name = item.realName;
-					item.is_online = item.devStatus == 1 ? true : false;
-				});
-				this.eqlistdata = eqlistdata;
-			},
+        res.forEach(item=>{
+          item.icon = '/bigdata_app/newImg/home/sqjd.png'
+        })
+        const menulist = res || [];
+        const menuItem = menulist.find(item => item.purview_name == '智慧物联')
+        this.menuList = menuItem.children || [];
+        this.list = this.menuList[0].children || []
+        this.pur_id = this.menuList[0].pur_id || '';
+        if(this.list[0].purview_name != '全部'){
+          this.list.unshift({
+            device_type_id: '',
+            purview_name: '全部'
+          })
+        }
+        this.type_id = this.list[0].device_type_id;
+        this.initPage();
+      },
 			async eqlist(tf) {
-				//设备列表
-				this.loadingtf = true;
-				console.log(this.type_id, 'type_idtype_id');
-				if (this.type_id == 42) {
-					this.getDpDeviceList(tf);
-					return;
-				}
-				if (this.type_id == 40) {
-					this.getDeviceList(tf);
-					return;
-				}
-				const res = await this.$myRequest({
-					url: '/api/api_gateway?method=forecast.worm_lamp.lamp_list',
-					data: {
-						device_type_id: this.type_id,
-						page: this.page,
-						page_size: this.size,
-						device_id: this.imports,
-						device_model: this.device_model,
-					},
-				});
-				this.loadingtf = false;
-				if ([11, 19, 20].includes(Number(this.type_id))) {
-					var newtime = +new Date() / 1000;
-				} else {
-					var newtime = +new Date() / 1000;
-				}
-				res.data.forEach((item) => {
-					let {
-						uptime,
-						addtime
-					} = item;
-					item.uptime = addtime;
-					item.addtime = uptime;
-					var days = (newtime - item.addtime) / 60 / 60 / 24;
-					item.days = Math.round(days);
-				});
-				if (tf) {
-					this.eqlistdata = this.eqlistdata.concat(res.data);
-				} else {
-					this.eqlistdata = res.data;
-				}
-				console.log(this.eqlistdata);
-				// for (var i = 0; i < this.eqlistdata.length; i++) {
-				//   var days = (newtime - this.eqlistdata[i].addtime) / 60 / 60 / 24;
-				//   this.eqlistdata[i].days = Math.round(days);
-				// }
-			},
-			async xyeqlist(tf) {
-				//设备列表
 				this.loadingtf = true;
+        let data = {
+          device_type_id: this.type_id,
+          page: this.page,
+          page_size: this.size,
+          pur_id: this.pur_id,
+          device_status: this.device_status,
+          device_id: this.device_id,
+          device_model: this.device_model
+        }
 				const res = await this.$myRequest({
-					url: '/api/api_gateway?method=sex_lure_nl.sex_lure.nl_device_list',
-					data: {
-						device_type_id: this.type_id,
-						page: this.page,
-						page_size: this.size,
-						device_id: this.imports,
-					},
+					url: '/api/api_gateway?method=device.app_device.app_device_list',
+					data: data,
 				});
 				this.loadingtf = false;
-				var newtime = +new Date() / 1000;
+        const status = res?.status || {};
+        this.online_counts = status.online || 0;
+        this.offline_counts = status.offline || 0;
+        this.counts = (status.online || 0) + (status.offline || 0);
 				if (tf) {
 					this.eqlistdata = this.eqlistdata.concat(res.data);
 				} else {
 					this.eqlistdata = res.data;
 				}
-				for (var i = 0; i < this.eqlistdata.length; i++) {
-					var days = (newtime - this.eqlistdata[i].addtime) / 60 / 60 / 24;
-					this.eqlistdata[i].days = Math.round(days);
-				}
-				console.log(res);
 			},
-			//camera.camera_manage.list_camera
-			async camera() {
-				//监控
-				const res = await this.$myRequest({
-					url: '/api/api_gateway?method=camera.camera_manage.list_camera',
-					data: {
-						page_size: 1,
-					},
-				});
-				this.accessToken = res.accessToken;
+			change(index,itemData) {
+        this.list = this.menuList[index].children || []
+        if(this.list[0].purview_name != '全部'){
+          this.list.unshift({
+            device_type_id: '',
+            purview_name: '全部'
+          })
+        }
+        this.current = index;
+        const item = this.list[0];
+        this.pur_id = itemData.pur_id || '';
+        this.changeDevice(item,0);
 			},
-			// homes.user_device_type
-			async usertype() {
-				//设备列表
-				const res = await this.$myRequest({
-					url: '/api/api_gateway?method=home.homes.user_device_type',
-				});
-				console.log(res);
-				for (var i = 0; i < res.length; i++) {
-					if (res[i].type_name == '温室大棚') {
-						continue;
-					}
-					var obj = {
-						name: res[i].type_name,
-						id: res[i].id,
-						device_model: res[i].device_model,
-						pur_id: res[i].pur_id,
-					};
-					this.list.push(obj);
-				}
-				console.log('设备列表11111111111111', this.list);
-				if (res.length) {
-					this.type_id = this.list[0].id;
-					this.device_model = this.list[0].device_model;
-					if (this.list[0].id == 10) {
-						this.xyeqlist();
-					} else {
-						this.eqlist();
-					}
-				}
-			},
-			change(index) {
-				console.log(index);
-				//头部导航栏的点击
-				this.imports = '';
-				this.current = index;
+      changeDevice(item,index){
 				this.currents = index;
 				this.page = 1;
 				this.eqlistdata = [];
-				this.type_id = this.list[index].id;
-				this.device_model = this.list[index].device_model;
-				console.log(this.type_id);
-				if (this.list[index].id == 10) {
-					this.xyeqlist();
-				} else {
-					this.eqlist();
-				}
-			},
-			clickRight() {
-				//搜索
-				this.width = '90%';
-			},
-			modification(item) {
-				uni.navigateTo({
-					url: './modification?data=' + JSON.stringify(item) + '&id=' + this.type_id,
-				});
-			},
+				this.type_id = item.device_type_id;
+				this.eqlist();
+      },
 			top() {
 				uni.pageScrollTo({
 					scrollTop: 0,
 					duration: 500,
 				});
 			},
+      initPage(){
+        this.eqlistdata = [];
+        this.current = 0;
+        this.currents = 0;
+        this.page = 1;
+        this.eqlist(true);
+        this.width = 0;
+      },
 			historys(itemOld) {
 				let item = JSON.parse(JSON.stringify(itemOld));
-				console.log('item', item, this.type_id);
-				item.pur_id = this.list[this.current].pur_id;
 				switch (this.type_id) {
 					// 水肥新设备
 					case 22:
@@ -363,7 +252,6 @@
 						});
 						break;
 					case 38:
-						// console.log(item);
 						var obj = {};
 						obj.d_id = item.d_id;
 						obj.equip_id = item.imei;
@@ -377,7 +265,6 @@
 						});
 						break;
 					case 5:
-						console.log(item);
 						var obj = {};
 						obj.d_id = item.d_id;
 						obj.equip_id = item.imei;
@@ -402,7 +289,7 @@
 						item.addtime = item.uptime;
 						item.type = this.type_id;
 						uni.navigateTo({
-							url: '../cb/equip-detail/equip-detail?info=' + JSON.stringify(item),
+							url: '../cbd/detail?info=' + JSON.stringify(item),
 						});
 						break;
 					case 28:
@@ -456,14 +343,12 @@
 						});
 						break;
 					case 12:
-						console.log(item);
 						item.addtime = item.uptime;
 						uni.navigateTo({
 							url: '../cb/xctdetail/xctdetail?info=' + JSON.stringify(item),
 						});
 						break;
 					case 13:
-						console.log(item);
 						var obj = {};
 						obj.d_id = item.d_id;
 						obj.device_id = item.imei;
@@ -477,7 +362,6 @@
 						});
 						break;
 					case 15:
-						console.log(item);
 						var obj = {};
 						obj.d_id = item.d_id;
 						obj.device_id = item.imei;
@@ -617,7 +501,6 @@
 						break;
 					case 40:
 						item.addtime = item.uptime;
-						console.log(item, 'itemmtiemtiemtiemtie');
 						uni.navigateTo({
 							url: `../cb/shuifeizs/shuifeizs?devBid=${item.devBid}&devName=${item.devName}&devStatus=${item.devStatus}`,
 						});
@@ -630,68 +513,29 @@
 						break;
 				}
 			},
-			search() {
-				//搜索
-				this.eqlistdata = [];
-				this.page = 1;
-				if (this.list[this.currents].id == 10) {
-					this.xyeqlist();
-				} else {
-					this.eqlist();
-				}
-			},
 			searchinput() {
 				Debounce(() => {
 					this.eqlistdata = [];
 					this.page = 1;
-					if (this.list[this.currents].id == 10) {
-						this.xyeqlist();
-					} else {
-						this.eqlist();
-					}
+					this.eqlist();
 				}, 1000)();
 			},
-			scrollTop(e) {
-				console.log(e);
-			},
+			scrollTop(e) {},
 			upper() {},
 			lower() {
 				this.page++;
-				if (this.type_id == 10) {
-					this.xyeqlist(true);
-				} else {
-					this.eqlist(true);
-				}
+				this.eqlist(true);
 			},
 			scroll() {},
 		},
 		onLoad() {
-			// this.list = [];
-			// this.camera();
-			// this.current = 0;
-			// this.currents = 0;
-			// this.page = 1;
-			// this.usertype();
-			// this.width = 0;
+			this.getUserlogin();
 		},
 		onTabItemTap(e) {
-			// console.log(e);
-			this.eqlistdata = [];
-			this.list = [];
-			this.camera();
-			this.current = 0;
-			this.currents = 0;
-			this.page = 1;
-			this.usertype();
-			this.width = 0;
 		},
 		onReachBottom() {
 			this.page++;
-			if (this.type_id == 10) {
-				this.xyeqlist(true);
-			} else {
-				this.eqlist(true);
-			}
+			this.eqlist(true);
 		},
 		onPageScroll(e) {
 			//nvue暂不支持滚动监听,可用bindingx代替
@@ -713,17 +557,19 @@
 	/deep/.uni-icons {
 		font-size: 40rpx !important;
 	}
-
+  input{
+    background: transparent !important;
+  }
 	.textbox {
 		width: 100%;
 		height: 100vh;
-		padding-top: 112rpx;
+		padding-top: 102rpx;
 		box-sizing: border-box;
 
 	}
 
 	.inputs {
-		width: 55%;
+		width: 65%;
 		margin-left: 12rpx;
 
 		/deep/.u-content {
@@ -762,22 +608,22 @@
 		}
 	}
 
-
-	.listbox{
-		// background: #F1F4F8;
-	}
-
+  .active-tab{
+    border-radius: 8rpx;
+    background: linear-gradient(0deg, #0bbc580f 0%, #0bbc580f 100%), #00000005;
+  }
 
 	.tab-box {
 		font-size: 30rpx;
-		// padding: 32rpx;
 		box-sizing: border-box;
 		width: 100%;
 		height: 100%;
 		overflow-y: hidden;
 		overflow-x: auto;
 		white-space: nowrap;
-
+    // 去掉滚动条
+    -ms-overflow-style: none;
+    scrollbar-width: none;
 		.tab-item {
 			cursor: pointer;
 			position: relative;

+ 4 - 0
pages/index/index.vue

@@ -226,6 +226,10 @@
 			async getUserlogin() {
 				const res = await this.$myRequest({
 					url: '/api/api_gateway?method=user.login.user_login_info',
+					method: 'POST',
+					data: {
+						is_app: 1,
+					},
 				});
 				// this.jurisdiction = {
 				// 	cbtf: false,

+ 4 - 0
pages/my/index/index.vue

@@ -77,6 +77,10 @@ export default {
 
       const res = await this.$myRequest({
         url: '/api/api_gateway?method=user.login.user_login_info',
+        method: 'POST',
+        data: {
+          is_app: 1,
+        },
       });
       console.log(res.children);
       this.usernames = res.username;

+ 2 - 2
util/api.js

@@ -1,8 +1,8 @@
 // let BASE_URL = 'http://114.55.0.7:8002';
 // const BASE_URL='http://8.136.98.49:8002'
-// let BASE_URL = 'http://218.28.198.186:10505'
+let BASE_URL = 'http://218.28.198.186:10505'
 // let BASE_URL = 'https://wx.hnyfwlw.com'
-let BASE_URL = 'http://192.168.1.107:8000';
+// let BASE_URL = 'http://192.168.1.107:8000';
 // let BASE_URL = 'http://218.28.198.186:10508';
 // let BASE_URL = 'https://uat.hnyfwlw.com'
 export const myRequest = (options) => {