Explorar el Código

Merge branch 'develop__ll'

allen hace 2 días
padre
commit
108228a27c
Se han modificado 50 ficheros con 3071 adiciones y 7 borrados
  1. 1 0
      main.js
  2. 44 0
      pages.json
  3. BIN
      pages/cb/shuifeizsFirst/assets/autoBtn.png
  4. BIN
      pages/cb/shuifeizsFirst/assets/backwashControl.png
  5. BIN
      pages/cb/shuifeizsFirst/assets/basicSetting.png
  6. BIN
      pages/cb/shuifeizsFirst/assets/beijing.png
  7. BIN
      pages/cb/shuifeizsFirst/assets/borderBottomGray.png
  8. BIN
      pages/cb/shuifeizsFirst/assets/borderRadius.png
  9. BIN
      pages/cb/shuifeizsFirst/assets/bucket.png
  10. BIN
      pages/cb/shuifeizsFirst/assets/bucketClose.png
  11. BIN
      pages/cb/shuifeizsFirst/assets/bucketClose1.png
  12. BIN
      pages/cb/shuifeizsFirst/assets/bucketCloseTop.png
  13. BIN
      pages/cb/shuifeizsFirst/assets/bucketOpen.png
  14. BIN
      pages/cb/shuifeizsFirst/assets/bucketOpen1.png
  15. BIN
      pages/cb/shuifeizsFirst/assets/bucketOpenTop.png
  16. BIN
      pages/cb/shuifeizsFirst/assets/controlbg.png
  17. BIN
      pages/cb/shuifeizsFirst/assets/fan.png
  18. BIN
      pages/cb/shuifeizsFirst/assets/fanRun.png
  19. BIN
      pages/cb/shuifeizsFirst/assets/fertTopBottom.png
  20. BIN
      pages/cb/shuifeizsFirst/assets/fertTopBottomRadius.png
  21. BIN
      pages/cb/shuifeizsFirst/assets/fertilizationFormula.png
  22. BIN
      pages/cb/shuifeizsFirst/assets/fertilizationValve.png
  23. BIN
      pages/cb/shuifeizsFirst/assets/lastBorder.png
  24. BIN
      pages/cb/shuifeizsFirst/assets/line.png
  25. BIN
      pages/cb/shuifeizsFirst/assets/lineTopAndBottom.png
  26. BIN
      pages/cb/shuifeizsFirst/assets/lineTopBottom.png
  27. BIN
      pages/cb/shuifeizsFirst/assets/manualControl.png
  28. BIN
      pages/cb/shuifeizsFirst/assets/masterStop.png
  29. BIN
      pages/cb/shuifeizsFirst/assets/operatingRecord.png
  30. BIN
      pages/cb/shuifeizsFirst/assets/rotate.png
  31. BIN
      pages/cb/shuifeizsFirst/assets/solenoidValve.png
  32. BIN
      pages/cb/shuifeizsFirst/assets/stir.png
  33. BIN
      pages/cb/shuifeizsFirst/assets/timing.png
  34. BIN
      pages/cb/shuifeizsFirst/assets/water.png
  35. BIN
      pages/cb/shuifeizsFirst/assets/wheelIrrigation.png
  36. 433 0
      pages/cb/shuifeizsFirst/automation.vue
  37. 72 0
      pages/cb/shuifeizsFirst/components/base.vue
  38. 397 0
      pages/cb/shuifeizsFirst/components/facilitystate.vue
  39. 127 0
      pages/cb/shuifeizsFirst/components/irrigatedArea.vue
  40. 169 0
      pages/cb/shuifeizsFirst/components/rotationBottom.vue
  41. 113 0
      pages/cb/shuifeizsFirst/components/rotationCard.vue
  42. 203 0
      pages/cb/shuifeizsFirst/components/rotationItems.vue
  43. 261 0
      pages/cb/shuifeizsFirst/control.vue
  44. 314 0
      pages/cb/shuifeizsFirst/history.vue
  45. 562 0
      pages/cb/shuifeizsFirst/rotationflow.vue
  46. 258 0
      pages/cb/shuifeizsFirst/shuifeizs.vue
  47. 103 0
      pages/cb/shuifeizsFirst/test.js
  48. 9 2
      pages/equipList/index.vue
  49. 3 3
      pages/equipList/seabox/modification.vue
  50. 2 2
      util/api.js

+ 1 - 0
main.js

@@ -20,6 +20,7 @@ Vue.prototype.$QueryPermission = QueryPermission;
 import customCard from './components/customCard/customCard.vue';
 Vue.component('customCard', customCard);
 Vue.filter('timeFormat', function (time,fmt = 'yyyy-MM-dd hh:mm:ss') {
+  if(!time)return '';
   function fun(a) {
     return String(a).length == 1 ? '0' + a : a;
   }

+ 44 - 0
pages.json

@@ -103,6 +103,50 @@
 		},
 
 		{
+			"root": "pages/cb/shuifeizsFirst",
+			"pages": [{
+					"path": "shuifeizs",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "control",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "automation",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "rotationflow",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "history",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false,
+						"navigationStyle": "custom"
+					}
+				}
+			]
+		},
+		{
 			"root": "pages/cb/wenshizs",
 			"pages": [{
 				"path": "wenshizs",

BIN
pages/cb/shuifeizsFirst/assets/autoBtn.png


BIN
pages/cb/shuifeizsFirst/assets/backwashControl.png


BIN
pages/cb/shuifeizsFirst/assets/basicSetting.png


BIN
pages/cb/shuifeizsFirst/assets/beijing.png


BIN
pages/cb/shuifeizsFirst/assets/borderBottomGray.png


BIN
pages/cb/shuifeizsFirst/assets/borderRadius.png


BIN
pages/cb/shuifeizsFirst/assets/bucket.png


BIN
pages/cb/shuifeizsFirst/assets/bucketClose.png


BIN
pages/cb/shuifeizsFirst/assets/bucketClose1.png


BIN
pages/cb/shuifeizsFirst/assets/bucketCloseTop.png


BIN
pages/cb/shuifeizsFirst/assets/bucketOpen.png


BIN
pages/cb/shuifeizsFirst/assets/bucketOpen1.png


BIN
pages/cb/shuifeizsFirst/assets/bucketOpenTop.png


BIN
pages/cb/shuifeizsFirst/assets/controlbg.png


BIN
pages/cb/shuifeizsFirst/assets/fan.png


BIN
pages/cb/shuifeizsFirst/assets/fanRun.png


BIN
pages/cb/shuifeizsFirst/assets/fertTopBottom.png


BIN
pages/cb/shuifeizsFirst/assets/fertTopBottomRadius.png


BIN
pages/cb/shuifeizsFirst/assets/fertilizationFormula.png


BIN
pages/cb/shuifeizsFirst/assets/fertilizationValve.png


BIN
pages/cb/shuifeizsFirst/assets/lastBorder.png


BIN
pages/cb/shuifeizsFirst/assets/line.png


BIN
pages/cb/shuifeizsFirst/assets/lineTopAndBottom.png


BIN
pages/cb/shuifeizsFirst/assets/lineTopBottom.png


BIN
pages/cb/shuifeizsFirst/assets/manualControl.png


BIN
pages/cb/shuifeizsFirst/assets/masterStop.png


BIN
pages/cb/shuifeizsFirst/assets/operatingRecord.png


BIN
pages/cb/shuifeizsFirst/assets/rotate.png


BIN
pages/cb/shuifeizsFirst/assets/solenoidValve.png


BIN
pages/cb/shuifeizsFirst/assets/stir.png


BIN
pages/cb/shuifeizsFirst/assets/timing.png


BIN
pages/cb/shuifeizsFirst/assets/water.png


BIN
pages/cb/shuifeizsFirst/assets/wheelIrrigation.png


+ 433 - 0
pages/cb/shuifeizsFirst/automation.vue

@@ -0,0 +1,433 @@
+<template>
+  <view class="automation">
+    <custom-card>
+      <block slot="backText">自动控制</block>
+    </custom-card>
+    <view
+      class="automation-content"
+      :class="{ 'automation-content-rever': activeIndex === 1 }"
+    >
+      <view class="automation-header">
+        <view
+          class="automation-header-item"
+          :class="{ 'automation-header-item-active': activeIndex === 0 }"
+          @click="clickHeaderItem(0)"
+          >灌溉
+          <view
+            :class="
+              activeIndex == '0'
+                ? 'automation-header-item-icon'
+                : 'automation-header-item-icon-bottom'
+            "
+          ></view>
+        </view>
+        <view
+          class="automation-header-item"
+          @click="clickHeaderItem(1)"
+          :class="{ 'automation-header-item-active': activeIndex === 1 }"
+          >水肥
+          <view
+            :class="
+              activeIndex == '1'
+                ? 'automation-header-item-icon'
+                : 'automation-header-item-icon-bottom'
+            "
+          ></view>
+        </view>
+      </view>
+      <view class="automation-body">
+        <rotation-items
+          :formData="formData"
+          :tktype="tktype"
+          @formDataHandler="updateFormData"
+        />
+        <view class="automation-body-title">灌区选择</view>
+        <rotation-bottom
+          :activeIndex="activeIndex"
+          :irrigatedAreaList="irrigatedAreaList"
+          :alreadyList="alreadyList"
+          @updateList="updateListHandler"
+          :tktype="tktype"
+        />
+      </view>
+    </view>
+    <view class="automation-footer">
+      <view class="automation-footer-left">
+        已选<text class="automation-footer-left-num">{{ selectNum }}</text
+        >个灌区
+      </view>
+      <view class="automation-footer-right" @click="immediateExecution"
+        >立即执行</view
+      >
+    </view>
+  </view>
+</template>
+<script>
+import rotationItems from './components/rotationItems.vue';
+import rotationBottom from './components/rotationBottom.vue';
+export default {
+  name: 'automation',
+  data() {
+    return {
+      activeIndex: 0,
+      devBid: '',
+      devName: '',
+      devStatus: '',
+      irrigatedAreaList: [],
+      alreadyList: [],
+      formData: {
+        lgjg: '',
+        fqcx: '',
+        fhcx: '',
+        lgcs: 1,
+      },
+      tktype: 1,
+      selectNum: 0,
+    };
+  },
+  components: {
+    rotationBottom,
+    rotationItems,
+  },
+  watch: {
+    alreadyList: {
+      handler(val) {
+        this.selectNum = 0;
+        val.forEach((item) => {
+          if (item.isChecked) {
+            this.selectNum++;
+          }
+        });
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  onLoad(options) {
+    this.devBid = options.devBid;
+    this.devName = options.devName;
+    this.devStatus = options.devStatus;
+
+    // 检测是否有运行中的任务
+    this.getRunStatus().then((hasRunningTask) => {
+      if (hasRunningTask) {
+        setTimeout(() => {
+          uni.redirectTo({
+            url: `/pages/cb/shuifeizsFirst/rotationflow?devBid=${this.devBid}&devName=${this.devName}&devStatus=${this.devStatus}`,
+          });
+        }, 1000);
+      } else {
+        this.getdeviceSfStatus();
+        this.getAlreadyList();
+      }
+    });
+  },
+  methods: {
+    updateListHandler(list) {
+      this.alreadyList = list;
+    },
+    updateFormData(options) {
+      this.formData[options.key] = options.value;
+    },
+    async getAlreadyList() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/group/already/list/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+
+      console.log(res, '-------------------- get already list');
+      res?.forEach((item) => {
+        item.isChecked = false;
+      });
+      this.alreadyList = res;
+    },
+    async getdeviceSfStatus() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/status/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+      this.dataList = [];
+      this.irrigatedAreaList = [];
+      this.alreadyfertilizerBucketList = [];
+
+      console.log('get device sf status', res);
+      res.forEach((item) => {
+        if (item.sfType === '7') {
+          this.irrigatedAreaList.push(item);
+        }
+      });
+    },
+    clickHeaderItem(index) {
+      this.activeIndex = index;
+      this.tktype = index == 0 ? 1 : 2;
+    },
+    // 获取运行状态
+    async getRunStatus() {
+      try {
+        const res = await this.$myRequest({
+          url: '/api/v2/iot/mobile/device/sf/zsrf/task/run/status/',
+          method: 'post',
+          data: {
+            devBid: this.devBid,
+          },
+        });
+        console.log(res, 'resresresres');
+
+        return Promise.resolve(res.status && res.status / 1 === 1);
+      } catch (error) {
+        return Promise.resolve(false);
+      }
+    },
+    // iot/mobile/device/sf/zsrf/task/ctl/
+    async postTaskCtl(payload) {
+      // loading
+      uni.showLoading({
+        title: '正在执行',
+      });
+      console.log(payload, 'payloadpayload');
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/zsrf/task/ctl/',
+        method: 'post',
+        data: payload,
+        header: {
+          'Content-Type': 'application/json',
+        },
+      });
+      uni.hideLoading();
+      console.log(res, 'resresres');
+      if (res?.code === '000000') {
+        uni.showToast({
+          title: '操作成功',
+        });
+        setTimeout(() => {
+          uni.redirectTo({
+            url: `/pages/cb/shuifeizsFirst/rotationflow?devBid=${this.devBid}&devName=${this.devName}&devStatus=${this.devStatus}`,
+          });
+        }, 1000);
+      } else {
+        uni.showToast({
+          icon: 'none',
+          title: res.msg,
+        });
+      }
+    },
+    immediateExecution() {
+      console.log(this.formData, 'formDataformDataformData');
+      if (!this.formData['lgjg']) {
+        uni.showToast({
+          title: '请输入轮灌间隔时间',
+          icon: 'none',
+        });
+        return;
+      }
+      if (this.tktype == 2 && !this.formData['fqcx']) {
+        uni.showToast({
+          title: '请输入肥前水时间',
+          icon: 'none',
+        });
+        return;
+      }
+      if (this.tktype == 2 && !this.formData['fhcx']) {
+        uni.showToast({
+          title: '请输入肥后水时间',
+          icon: 'none',
+        });
+        return;
+      }
+      if (this.tktype == 2 && !this.formData['sfmode']) {
+        uni.showToast({
+          title: '请选择模式',
+          icon: 'none',
+        });
+        return;
+      }
+      if (this.selectNum === 0) {
+        uni.showToast({
+          title: '请选择灌区',
+          icon: 'none',
+        });
+        return;
+      }
+      const fqList = [];
+      for (let i = 0; i < this.alreadyList.length; i++) {
+        const item = this.alreadyList[i];
+        if (item.isChecked && !item.ti) {
+          uni.showToast({
+            title: `请输入${item.sfDisplayname || item.sfName}的时长`,
+            icon: 'none',
+          });
+          return;
+        } else if (item.isChecked && this.tktype == 2 && !item.pfCode) {
+          uni.showToast({
+            title: `请输入${item.sfDisplayname || item.sfName}的配方`,
+            icon: 'none',
+          });
+          return;
+        }
+        if (item.isChecked) {
+          fqList.push({
+            fqCode: item.sfCode,
+            ti: item.ti || '',
+            pfCode: item.pfCode || '',
+          });
+        }
+      }
+      const payload = {
+        devBid: this.devBid,
+        tktype: this.tktype,
+        tkid: 0,
+        status: 1,
+        ...this.formData,
+        fqList,
+        sfmode: this.tktype !== 1 ? this.formData.sfmode || 1 : '',
+      };
+      this.postTaskCtl(payload);
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+uni-page-body,
+uni-page-wrapper {
+  position: relative;
+  height: 100%;
+}
+.automation {
+  background: linear-gradient(180deg, #ffffff00 0%, #fff 23.64%, #fff 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  width: 100%;
+  height: calc(100% - 100rpx);
+  overflow: hidden;
+  .automation-content {
+    border-bottom: none;
+    border-radius: 16rpx 16rpx 0 0;
+    position: relative;
+    overflow: hidden;
+    &::before {
+      position: absolute;
+      content: '';
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background: url('https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/newindex/controlbg.png')
+        no-repeat;
+      background-size: cover;
+    }
+  }
+  .automation-content-rever {
+    border-bottom: none;
+    border-radius: 16rpx 16rpx 0 0;
+    position: relative;
+    &::before {
+      position: absolute;
+      content: '';
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background: url('https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/newindex/controlbg.png')
+        no-repeat;
+      background-size: cover;
+      transform: rotateY(180deg);
+      transform-origin: center center;
+    }
+  }
+  .automation-header {
+    width: 100%;
+    display: flex;
+    .automation-header-item {
+      width: 50%;
+      height: 80rpx;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-size: 36rpx;
+      color: #687a74;
+      text-align: center;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 32rpx;
+      font-weight: 400;
+      position: relative;
+    }
+    .automation-header-item-active {
+      color: #042118;
+      text-align: center;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 32rpx;
+      font-weight: 500;
+      position: relative;
+    }
+    .automation-header-item-icon {
+      width: 28rpx;
+      height: 4rpx;
+      border-radius: 4rpx;
+      background-color: #14a478;
+      position: absolute;
+      bottom: 0;
+    }
+    .automation-header-item-icon-bottom {
+      background-color: transparent;
+    }
+  }
+  .automation-body {
+    height: calc(100vh - 250rpx);
+    overflow: hidden;
+    .automation-body-title {
+      position: relative;
+      color: #042118;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 28rpx;
+      font-weight: 500;
+      margin: 48rpx 32rpx 16rpx 32rpx;
+    }
+  }
+  .automation-footer {
+    position: fixed;
+    width: 100%;
+    padding: 16rpx 0;
+    background: #fff;
+    box-shadow: 0 -4rpx 8rpx 0 #0000001a;
+    bottom: 0;
+    height: 80rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .automation-footer-left {
+      width: 50%;
+      margin-left: 32rpx;
+      color: #9ba6a3;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 28rpx;
+      font-weight: 400;
+      .automation-footer-left-num {
+        color: #14a478;
+        text-align: center;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-style: normal;
+        font-weight: 700;
+        margin: 0 8rpx;
+      }
+    }
+    .automation-footer-right {
+      width: 224rpx;
+      border-radius: 16rpx;
+      background-color: #14a478;
+      color: #ffffff;
+      text-align: center;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 32rpx;
+      font-weight: 400;
+      padding: 16rpx 0;
+      margin-right: 32rpx;
+    }
+  }
+}
+</style>

+ 72 - 0
pages/cb/shuifeizsFirst/components/base.vue

@@ -0,0 +1,72 @@
+<template>
+  <view class="base-container" v-if="dataList.length">
+    <view class="base-list">
+      <view class="base-item" v-for="(item, index) in dataList" :key="index">
+        <view class="base-item-value">{{ item.value }}</view>
+        <view class="base-item-label">{{
+          item.sfDisplayname || item.sfName
+        }}</view>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  props: {
+    dataList: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  data() {
+    return {};
+  },
+};
+</script>
+<style scoped lang="scss">
+.base-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: calc(100% - 64rpx);
+  padding: 16rpx 0;
+  margin: 0 32rpx;
+  justify-content: space-between;
+  border-radius: 16rpx;
+  background: linear-gradient(180deg, #edfbfb 0%, #d2f2ed 100%);
+  margin-bottom: 30rpx;
+  .base-list {
+    width: calc(100% - 32rpx);
+    padding: 0 16px;
+    display: grid;
+    grid-template-columns: repeat(4, 1fr);
+    .base-item {
+      text-align: center;
+      .base-item-value {
+        width: 150rpx;
+        color: #042118;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 32rpx;
+        font-weight: 500;
+        text-align: center;
+        // 超出隐藏
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+      .base-item-label {
+        width: 150rpx;
+        color: #687a74;
+        font-family: 'Source Han Sans CN VF';
+        text-align: center;
+        font-size: 28rpx;
+        font-weight: 400;
+        // 超出隐藏
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+    }
+  }
+}
+</style>

+ 397 - 0
pages/cb/shuifeizsFirst/components/facilitystate.vue

@@ -0,0 +1,397 @@
+<template>
+  <view class="facilitystate-container">
+    <view class="facilitystate-title-warp">
+      <view class="facilitystate-title">
+        <view class="radius-user"></view>使用中
+      </view>
+      <view class="facilitystate-subtitle">
+        <view class="radius-close"></view>
+      已关闭</view>
+    </view>
+    <view class="facilitystate-list">
+      <image :src="ggbCurrent.value == 1?bucketOpenTop:bucketCloseTop" class="bucketOpenTop" />
+      <image :src="sfbCurrent.value == 1?bucketOpenTop:bucketCloseTop" class="bucketOpenTop2"/>
+      <view class="facilitystate-list__left-label">
+        <view class="facilitystate-item__left-label-text" style="margin-bottom: 2rpx;">瞬时 L/min :</view>
+        <view class="facilitystate-item__left-label-text">累计L:</view>
+      </view>
+      <view class="facilitystate-list__left">
+        <view
+          class="facilitystate-item"
+          :style="{width:100/(alreadyfertilizerBucketList.length)+'%'}"
+          :class="index == alreadyfertilizerBucketList.length - 1?'facilitystate-item--last':''"
+          v-for="(item, index) in alreadyfertilizerBucketList"
+          :key="index"
+        >
+          <view class="facilitystate-item__label">
+            <view class="facilitystate-item__label-text">{{getTopDeviceName(item.childrenList)}}</view>
+            <view class="facilitystate-item__label-value">{{getBottomDeviceName(item.childrenList)}}</view>
+          </view>
+          <view class="facilitystate-item__image">
+            <image :src="getJSCurrentValue(item.childrenList)?bucketOpen:bucketClose" class="bucketClose"/>
+            <view  v-if="index == alreadyfertilizerBucketList.length - 1? false:true">
+              <image :src="lineTopBottom" class="facilitystate-item__bg"/>
+              <image :src="lineTopAndBottom" class="facilitystate-item__line"/>
+            </view>
+            <view  v-else>
+              <image :src="lineTopBottom" class="facilitystate-item__bg2"/>
+              <image :src="lastBorder" class="facilitystate-item__line2"/>
+            </view>
+            <view class="facilitystate-item-fan">
+              <view class="fertTopBottom">
+              <text class="fertTopBottom-text">{{item.sfDisplayname || item.sfName}}</text>
+              <image :src="getJBCurrentValue(item.childrenList)? fanRun : fan" class="fan" :class="{'fan-run': getJBCurrentValue(item.childrenList)}" />
+              </view>
+            </view>
+            <image :src="getXSCurrentValue(item.childrenList)?bucketOpen:bucketClose" class="bucketClose1" />
+          </view>
+        </view>
+      </view>
+      </view>
+      <irrigatedArea :irrigatedAreaList="irrigatedAreaList"/>
+    </view>
+  </view>
+</template>
+<script>
+import fertTopBottom from '../assets/fertTopBottom.png';
+import lineTopAndBottom from '../assets/lineTopAndBottom.png';
+import lineTopBottom from '../assets/lineTopBottom.png';
+import fertTopBottomRadius from '../assets/fertTopBottomRadius.png';
+import lastBorder from '../assets/lastBorder.png';
+import irrigatedArea from './irrigatedArea.vue';
+import fan from '../assets/fan.png';
+import fanRun from '../assets/fanRun.png';
+import bucketOpenTop from '../assets/bucketOpenTop.png';
+import bucketCloseTop from '../assets/bucketCloseTop.png';
+import bucketClose from '../assets/bucketClose.png';
+import bucketOpen from '../assets/bucketOpen.png';
+
+export default {
+  props:{
+    irrigatedAreaList:{
+      type:Array,
+      default:()=>[]
+    },
+    alreadyfertilizerBucketList:{
+      type:Array,
+      default:()=>[]
+    },
+    ggbCurrent:{
+      type:Object,
+      default:()=>{}
+    },
+    sfbCurrent:{
+      type:Object,
+      default:()=>{}
+    }
+  },
+  components:{
+    irrigatedArea
+  },
+  data() {
+    return {
+      fan,
+      fanRun,
+      lastBorder,
+      lineTopBottom,
+      fertTopBottom,
+      lineTopAndBottom,
+      bucketOpenTop,
+      bucketOpenTopStatus:false,
+      bucketOpenTopStatus2:false,
+      bucketCloseTop,
+      bucketClose,
+      bucketOpen,
+      fertTopBottomRadius,
+    };
+  },
+  methods:{
+    getTopDeviceName(list){
+      let current = {}
+      list?.forEach(item =>{
+        if(item.sfType === '6'){
+          const name = item.sfDisplayname || item.sfName;
+          if(name.indexOf('瞬时') != -1){
+            current = item
+          }
+        }
+      })
+      return current?.value || '0'
+    },
+    getBottomDeviceName(list){
+      let current = {}
+      list?.forEach(item =>{
+        if(item.sfType === '6'){
+          const name = item.sfDisplayname || item.sfName;
+         if(name.indexOf('累计') != -1){
+            current = item
+          }
+        }
+      })
+      return current?.value || '0'
+    },
+    getJSCurrentValue(list){
+      // 进水阀
+      let current = {};
+      list?.forEach(item =>{
+        if(item.sfType === '8'){
+          const name = item.sfCode;
+          current = item;
+        }
+      })
+      return current?.value == 1
+    },
+    getJBCurrentValue(list){
+      // 搅拌机
+      let current = {};
+      list?.forEach(item =>{
+        if(item.sfType === '3'){
+          const name = item.sfCode;
+            current = item
+        }
+      })
+      return current?.value == 1
+    },
+    getXSCurrentValue(list){
+      // 吸水泵
+      let current = {};
+      list?.forEach(item =>{
+        if(item.sfType === '2'){
+          const name = item.sfCode;
+            current = item
+        }
+      })
+      return current?.value == 1
+    },
+    handleClick(item){
+      item.fan = !item.fan;
+    },
+    handleOpenClick(){
+      this.bucketOpenTopStatus = !this.bucketOpenTopStatus;
+    },
+    handleOpenClick1(){
+      this.bucketOpenTopStatus2 = !this.bucketOpenTopStatus2;
+    },
+    handleBucketCloseClick(item){
+      item.isTopStatus = !item.isTopStatus;
+    },
+    handleBucketCloseClick1(item){
+      item.isBottomStatus = !item.isBottomStatus;
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.facilitystate-container {
+  padding: 16rpx 32rpx;
+  justify-content: space-between;
+  border-radius: 16rpx;
+  position: relative;
+  .facilitystate-title-warp{
+    position: absolute;
+    right: 32rpx;
+    top: 10rpx;
+    display: flex;
+    align-items: center;
+    color: #374d59;
+    font-family: "Source Han Sans CN VF";
+    font-size: 24rpx;
+    font-weight: 400;
+    .facilitystate-title{
+      display: flex;
+      align-items: center;
+      margin-right: 32rpx;
+      .radius-user{
+        width: 16rpx;
+        height: 16rpx;
+        border-radius: 50%;
+        background: #14A478;
+        margin-right:8rpx;
+      }
+    }
+    .facilitystate-subtitle{
+      display: flex;
+      align-items: center;
+      .radius-close{
+        width: 16rpx;
+        height: 16rpx;
+        border-radius: 50%;
+        background: #7A8291;
+        margin-right:8rpx;
+      }
+    }
+  }
+  .facilitystate-list {
+    background: url('https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/newindex/beijing.png') no-repeat;
+    background-size: 100%;
+    height: 376rpx;
+    width: 690rpx;
+    display: flex;
+    margin-bottom: 16rpx;
+    position: relative;
+    &__left-label{
+      align-self: stretch;
+      color: #687a74;
+      text-align: right;
+      font-family: "Source Han Sans CN VF";
+      font-size: 24rpx;
+      font-weight: 400;
+      position: absolute;
+      left: 30rpx;
+      top: 120rpx;
+    }
+    .bucketOpenTop{
+      width: 20rpx;
+      height: 20rpx;
+      position: absolute;
+      left: 120rpx;
+      top: 328rpx;
+    }
+    .bucketOpenTop2{
+      width: 20rpx;
+      height: 20rpx;
+      position: absolute;
+      left: 200rpx;
+      top: 72rpx;
+    }
+    &__left{
+      height: 100%;
+      display: flex;
+      margin-left: 160rpx;
+      justify-content: space-between;
+      width: 100%;
+    }
+    .facilitystate-item {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      height: 228rpx;
+      margin-top: 112rpx;
+      &__label{
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        width: 100%;
+        text-align: center;
+        margin-bottom: 5rpx;
+      }
+      &__label-text,&__label-value {
+        color: #042118;
+        font-family: "Source Han Sans CN VF";
+        font-size: 24rpx;
+        font-weight: 400;
+        height: 36rpx;
+        width:90%;
+        margin: 0 auto;
+        // 超出隐藏
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+      &__image {
+        width: 100%;
+        height: 140rpx;
+
+        position: relative;
+        .facilitystate-item-fan{
+          position: absolute;
+          top: 20rpx;
+          left:0;
+          bottom:0;
+          right:0;
+          margin: auto;
+          z-index:100;
+        }
+        .bucketClose{
+          position: absolute;
+          width: 20rpx;
+          height: 20rpx;
+          left: 50%;
+          transform: translateX(-25%);
+          top: 6rpx;
+          z-index:100;
+        }
+        .bucketClose1{
+          position: absolute;
+          width: 20rpx;
+          height: 20rpx;
+          left: 50%;
+          transform: translateX(-25%);
+          bottom: -6rpx;
+          z-index:100;
+        }
+      }
+      &__bg{
+        width: 100%;
+        height: 153rpx;
+        top: 0rpx;
+      }
+      &__line{
+        position: absolute;
+        width: 8rpx;
+        height: 152rpx;
+        left: 50%;
+        top: 0;
+        transform: translateX(-50%);
+      }
+      &__bg2{
+        width: 50%;
+        height: 153rpx;
+        left: -4rpx;
+      }
+      &__line2{
+        position: absolute;
+        width: 16rpx;
+        height: 153rpx;
+        top: -1rpx;
+        margin-left: -6rpx;
+        transform: translateX(-50%);
+      }
+      .fertTopBottom{
+        width: 70rpx;
+        height: 94rpx;
+        margin: 0 auto;
+        margin-top: 12rpx;
+        background: url('https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/newindex/bucket.png')  no-repeat center center;
+        background-size: 100% 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        .fertTopBottom-text{
+          width: 70rpx;
+          font-size: 24rpx;
+          color: #FFB800;
+          text-align: center;
+          // 超出隐藏
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        .fan{
+          width: 40rpx;
+          height:40rpx;
+          margin-left: 10rpx;
+        }
+        .fan-run{
+          animation: rotate .5s linear infinite;
+          @keyframes rotate {
+            from {
+              transform: rotate(0deg);
+            }
+            to {
+              transform: rotate(360deg);
+            }
+          }
+        }
+      }
+    }
+    .facilitystate-item--last{
+      width: 100rpx;
+      display: flex;
+    }
+  }
+}
+</style>

+ 127 - 0
pages/cb/shuifeizsFirst/components/irrigatedArea.vue

@@ -0,0 +1,127 @@
+<template>
+  <view class="irrigated-area">
+    <view class="irrigated-area-list">
+      <view
+        class="irrigated-area-item"
+        v-for="(item, index) in irrigatedAreaList"
+        :key="index"
+      >
+        <view class="irrigated-area-item-title">
+          <view class="irrigated-area-item-title-text">{{
+            item.sfDisplayname || item.sfName
+          }}</view>
+          <view class="irrigated-area-item-title-time"></view>
+        </view>
+        <view class="irrigated-area-item-content">
+          <view
+            class="irrigated-area-item-content-item"
+            v-for="(i, n) in item.childrenList"
+            :key="n"
+          >
+            <view class="irrigated-area-item-content-item-title">{{
+              i.sfDisplayname || i.sfName || '暂无数据'
+            }}</view>
+            <view class="irrigated-area-item-content-item-icon">
+              <image
+                :src="i.value !== '0' ? bucketOpen1 : bucketClose1"
+                class="bucket-icon"
+              />
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+import bucketOpen1 from '../assets/bucketOpen1.png';
+import bucketClose1 from '../assets/bucketClose1.png';
+export default {
+  props: {
+    irrigatedAreaList: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  data() {
+    return {
+      bucketOpen1,
+      bucketClose1,
+    };
+  },
+  methods: {
+    formartDate(date) {
+      return date.slice(0, 10);
+    },
+  },
+  components: {},
+  mounted() {},
+};
+</script>
+<style scoped lang="scss">
+.irrigated-area {
+  .irrigated-area-list {
+    .irrigated-area-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 10px;
+      background: #f5f7fa;
+      margin-bottom: 8rpx;
+      .irrigated-area-item-title {
+        width: 120rpx;
+        .irrigated-area-item-title-text {
+          color: #042118;
+          text-align: left;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 24rpx;
+          font-weight: 500;
+          // 超出隐藏
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        .irrigated-area-item-title-time {
+          color: #14a478;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 24rpx;
+          font-weight: 500;
+          text-align: left;
+          margin-top: 8rpx;
+          height: 30rpx;
+        }
+      }
+      .irrigated-area-item-content {
+        display: flex;
+        width: calc(100% - 120rpx);
+        justify-content: start;
+        .irrigated-area-item-content-item {
+          width: 20%;
+          .irrigated-area-item-content-item-title {
+            width: 100%;
+            color: #333333;
+            font-family: 'Source Han Sans CN VF';
+            font-size: 24rpx;
+            font-weight: 400;
+            margin-bottom: 20rpx;
+            // 超出隐藏
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            text-align: center;
+          }
+          .irrigated-area-item-content-item-icon {
+            display: flex;
+            justify-content: center;
+            .bucket-icon {
+              width: 24rpx;
+              height: 24rpx;
+              margin-right: 10rpx;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 169 - 0
pages/cb/shuifeizsFirst/components/rotationBottom.vue

@@ -0,0 +1,169 @@
+<template>
+  <view
+    class="rotation-wraper"
+    :style="{
+      height:
+        tktype == 1
+          ? `calc(100% - 256rpx - 168rpx)`
+          : `calc(100% - 256rpx - 440rpx)`,
+    }"
+  >
+    <view class="rotation-wraper-left">
+      <view
+        class="rotation-wraper-left__item"
+        v-for="(item, index) in listData"
+        :key="item.sfBid"
+        @click="clickHandler(item, index)"
+        :class="{ active: index === currentIndex }"
+        >{{ item.sfDisplayname || item.sfName }}
+        <image
+          :src="borderBottomGray"
+          class="border-bottom-gray"
+          v-if="index === currentIndex"
+        />
+      </view>
+    </view>
+    <view class="rotation-wraper-right">
+      <scroll-view
+        scroll-y="true"
+        enable-flex="true"
+        scroll-with-animation
+        class="server-page__list-scroll"
+        :scroll-into-view="activeMenuId"
+      >
+        <rotationCard
+          v-for="item in listData"
+          :item="item"
+          :tktype="tktype"
+          :key="item.sfBid"
+          @actionChecked="actionCheckedHandler"
+          @changeTi="changeTiHandler"
+          :id="'tab' + item.sfBid"
+        />
+      </scroll-view>
+    </view>
+  </view>
+</template>
+<script>
+import rotationCard from './rotationCard.vue';
+import borderBottomGray from '../assets/borderBottomGray.png';
+export default {
+  name: 'rotationBottom',
+  props: {
+    alreadyList: {
+      type: Array,
+      default: () => [],
+    },
+    tktype: {
+      type: Number,
+      default: 1,
+    },
+    activeIndex: {
+      type: Number,
+      default: 0,
+    },
+  },
+  data() {
+    return {
+      listData: [],
+      borderBottomGray,
+      currentIndex: 0,
+      currentItem: {},
+      activeMenuId: '',
+    };
+  },
+  watch: {
+    activeIndex() {
+      this.currentIndex = 0;
+      const firstItem = this.alreadyList[0];
+      this.activeMenuId = `tab${firstItem?.sfBid}`;
+    },
+    alreadyList(value) {
+      this.listData = value;
+    },
+  },
+  components: {
+    rotationCard,
+  },
+  methods: {
+    changeTiHandler(item) {
+      const index = this.getItemBySfBid(item.sfBid);
+      this.$set(this.listData, index, {
+        ...item,
+        ti: item.ti,
+      });
+      this.$emit('updateList', this.listData);
+    },
+    // 通过sfBid查到某个item的index
+    getItemBySfBid(sfBid) {
+      return this.listData.findIndex((item) => item.sfBid === sfBid);
+    },
+    actionCheckedHandler(item) {
+      const index = this.getItemBySfBid(item.sfBid);
+      this.$set(this.listData, index, {
+        ...item,
+        isChecked: !item.isChecked,
+      });
+      this.$emit('updateList', this.listData);
+    },
+
+    clickHandler(item, index) {
+      this.currentItem = item;
+      this.currentIndex = index;
+      this.activeMenuId = `tab${item.sfBid}`;
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.server-page__list-scroll {
+  height: 100%;
+  overflow: hidden;
+}
+.rotation-wraper {
+  display: flex;
+  justify-content: space-between;
+  position: relative;
+  height: calc(100% - 256rpx - 168rpx);
+  padding-bottom: 128rpx;
+  overflow-y: hidden;
+  .rotation-wraper-left {
+    width: 240rpx;
+    border-radius: 16rpx;
+    background-color: #ffffff;
+    height: 100%;
+    background: #ffffff;
+    overflow-y: auto;
+    padding-top: 12rpx;
+    &__item {
+      height: 96rpx;
+      line-height: 96rpx;
+      padding: 0 32rpx;
+      color: #364d46;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 28rpx;
+      font-weight: 400;
+      position: relative;
+      .border-bottom-gray {
+        position: absolute;
+        width: 40rpx;
+        height: 40rpx;
+        bottom: -30rpx;
+        right: 0;
+      }
+    }
+  }
+  .active {
+    background: #f5f6fa;
+    color: #14a478;
+    font-family: 'Source Han Sans CN VF';
+    font-size: 28rpx;
+    font-weight: 700;
+  }
+  .rotation-wraper-right {
+    width: calc(100% - 240rpx - 64rpx);
+    margin-right: 32rpx;
+    overflow-y: scroll;
+  }
+}
+</style>

+ 113 - 0
pages/cb/shuifeizsFirst/components/rotationCard.vue

@@ -0,0 +1,113 @@
+<template>
+  <view class="rotation-card" @click="actionChecked">
+    <view class="rotation-card__header">
+      {{ item.sfDisplayname || item.sfName }}
+      <u-icon
+        name="checkmark-circle-fill"
+        :color="item.isChecked ? '#14A478' : '#C9CDD4'"
+        size="30rpx"
+      ></u-icon>
+    </view>
+    <view class="rotation-card__content" v-if="tktype === 2">
+      <view class="rotation-card__content-left">配方</view>
+      <view class="rotation-card__content-right">
+        <u-input
+          maxlength="36"
+          v-model="item.pfCode"
+          placeholder="请输入配方"
+          :border="false"
+          input-align="right"
+        />
+      </view>
+    </view>
+    <view class="rotation-card__footer">
+      <view class="rotation-card__footer-left">时长(分钟)</view>
+      <view class="rotation-card__footer-right">
+        <u-input
+          type="number"
+          maxlength="6"
+          :max="999999"
+          :value="item.ti"
+          @input="changeTi"
+          v-model="item.ti"
+          placeholder="请输入时长"
+          :border="false"
+          input-align="right"
+        /> </view
+    ></view>
+  </view>
+</template>
+<script>
+export default {
+  props: {
+    item: {
+      type: Object,
+      default: () => {},
+    },
+    tktype: {
+      type: Number,
+      default: 1,
+    },
+  },
+  data() {
+    return {
+      value: '',
+      action: true,
+    };
+  },
+  methods: {
+    actionChecked() {
+      this.$emit('actionChecked', this.item);
+    },
+    changeTi(value) {
+      this.$emit('changeTi', this.item);
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.rotation-card {
+  border-radius: 16rpx;
+  background-color: #fff;
+  margin-bottom: 22rpx;
+  &__header {
+    height: 64rpx;
+    line-height: 64rpx;
+    border-bottom: 2rpx solid #e4e7ed;
+    color: #333333;
+    font-family: 'Source Han Sans CN VF';
+    font-size: 28rpx;
+    font-weight: 500;
+    padding-left: 32rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 32rpx;
+  }
+  &__content {
+    display: flex;
+    justify-content: space-between;
+    padding: 20rpx 30rpx;
+    height: 40rpx;
+  }
+  &__content-left {
+    width: 250rpx;
+    font-size: 28rpx;
+  }
+  &__content-right {
+  }
+  &__footer {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20rpx 30rpx;
+    height: 40rpx;
+  }
+  &__footer-left {
+    width: 250rpx;
+    font-size: 28rpx;
+  }
+  &__footer-right {
+  }
+}
+</style>

+ 203 - 0
pages/cb/shuifeizsFirst/components/rotationItems.vue

@@ -0,0 +1,203 @@
+<template>
+  <view
+    class="rotation-wrapper"
+    :style="{ height: tktype === 1 ? '176rpx' : '450rpx' }"
+  >
+    <view class="rotation-item" v-for="(item, index) in list" :key="index">
+      <view class="rotation-item__label">{{ item.label }}</view>
+      <view class="rotation-item__value">
+        <u-number-box
+          v-model="item.value"
+          :min="1"
+          :max="9999"
+          maxlength="4"
+          @change="() => valChange(item)"
+          v-if="item.isNumber"
+        ></u-number-box>
+        <view class="rotation-item__value__input">
+          <u-input
+            v-model="item.value"
+            type="number"
+            maxlength="6"
+            :max="999999"
+            input-align="right"
+            @blur="valChange(item)"
+            v-if="!item.isNumber && !item.isSelect"
+          />
+          <text
+            style="margin-left: 16rpx; width: 80rpx"
+            v-if="!item.isNumber && !item.isSelect"
+            >分钟</text
+          >
+        </view>
+        <view
+          v-if="!item.isNumber && item.isSelect"
+          class="rotation-item__value__select"
+          @click="show = true"
+        >
+          <text
+            style="color: #9ba6a3; margin-right: 16rpx"
+            :style="{ color: formData.sfmode ? '#666' : '#9ba6a3' }"
+            >{{ selectText }}</text
+          >
+          <u-icon name="arrow-right" color="#4E5969" size="24rpx"></u-icon>
+        </view>
+      </view>
+    </view>
+    <u-action-sheet
+      :list="actionSheetList"
+      v-model="show"
+      @click="actionSheetCallback"
+    ></u-action-sheet>
+  </view>
+</template>
+<script>
+export default {
+  name: 'rotationItem',
+  props: {
+    formData: {
+      type: Object,
+      default: () => {},
+    },
+    tktype: {
+      type: Number,
+      default: 1,
+    },
+  },
+  watch: {
+    tktype: {
+      handler(val) {
+        if (val !== 1) {
+          this.list = [
+            {
+              label: '轮灌次数',
+              isNumber: true,
+              value: this.formData['lgcs'] || 1,
+              key: 'lgcs',
+            },
+            {
+              label: '轮灌间隔',
+              isNumber: false,
+              value: this.formData['lgjg'] || '',
+              key: 'lgjg',
+            },
+            {
+              label: '肥前水',
+              isNumber: false,
+              value: this.formData['fqcx'] || '',
+              key: 'fqcx',
+            },
+            {
+              label: '肥后水',
+              isNumber: false,
+              value: this.formData['fhcx'] || '',
+              key: 'fhcx',
+            },
+            {
+              label: '模式选择',
+              isNumber: false,
+              value: this.formData['sfmode'] || '',
+              key: 'sfmode',
+              isSelect: true,
+            },
+          ];
+        } else {
+          this.list = [
+            {
+              label: '轮灌次数',
+              isNumber: true,
+              value: this.formData['lgcs'] || 1,
+              key: 'lgcs',
+            },
+            {
+              label: '轮灌间隔',
+              isNumber: false,
+              value: this.formData['lgjg'] || '',
+              key: 'lgjg',
+            },
+          ];
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+    formData: {
+      handler(val) {},
+      deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      list: [],
+      selectText: '请选择',
+      show: false,
+      actionSheetList: [
+        {
+          text: '定时',
+          id: 1,
+        },
+        {
+          text: '定量',
+          id: 2,
+        },
+        {
+          text: 'EC调配',
+          id: 3,
+        },
+        {
+          text: '混肥比例',
+          id: 4,
+        },
+      ],
+    };
+  },
+  methods: {
+    valChange(item) {
+      this.formData[item.key] = item.value;
+      this.$emit('formDataHandler', { key: [item.key], value: item.value });
+    },
+    actionSheetCallback(index) {
+      this.formData['sfmode'] = this.actionSheetList[index].id;
+      this.selectText = this.actionSheetList[index].text;
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.rotation-wrapper {
+  height: 450rpx;
+  border-radius: 16rpx;
+  background-color: #ffffff;
+  position: relative;
+  width: calc(100% - 64rpx);
+  margin: 0 32rpx;
+  margin-top: 32rpx;
+  .rotation-item {
+    height: 88rpx;
+    width: calc(100% - 32rpx);
+    margin: 0 32rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    border-bottom: 4rpx solid #f0f0f0;
+    .rotation-item__label {
+      width: 50%;
+      text-align: left;
+      color: #042118;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 28rpx;
+      font-weight: 400;
+    }
+    .rotation-item__value {
+      width: 50%;
+      text-align: right;
+      padding-right: 16rpx;
+      .rotation-item__value__input {
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
+}
+</style>

+ 261 - 0
pages/cb/shuifeizsFirst/control.vue

@@ -0,0 +1,261 @@
+<template>
+  <view class="control-container">
+    <custom-card>
+      <block slot="backText">{{ title }}</block>
+    </custom-card>
+    <view class="control-content" v-if="leftList.length > 0">
+      <view class="control-list-left">
+        <view
+          class="control-list-left-item"
+          v-for="(item, index) in leftList"
+          :key="index"
+          @click="controlClick(index)"
+          :class="{ 'control-list-left-item-active': index === activeIndex }"
+        >
+          <image
+            :src="borderRadius"
+            class="borderTopRadius"
+            v-if="index === activeIndex"
+          />
+          {{ item.sfDisplayname }}
+          <image
+            :src="borderRadius"
+            class="borderBottomRadius"
+            v-if="index === activeIndex"
+          />
+        </view>
+      </view>
+      <view class="control-list-right">
+        <view
+          class="control-list-right-item"
+          v-for="(item, index) in deviceList"
+          :key="index"
+        >
+          <view class="control-list-right-item-icon">
+            <image
+              :src="item.sfType == '3' ? stir : solenoidValve"
+              class="solenoid-valve"
+            />
+          </view>
+          <view class="control-list-right-item-title">{{
+            item.sfDisplayname || item.sfName
+          }}</view>
+          <view class="control-list-right-item-action">
+            <u-switch
+              :value="item.value == 1 ? true : false"
+              @change="changeSwitch(item)"
+              activeColor="#14A478"
+              size="40"
+              inactiveColor="rgb(230, 230, 230)"
+            ></u-switch>
+          </view>
+        </view>
+        <u-empty v-if="deviceList.length === 0" text="暂无数据"></u-empty>
+      </view>
+    </view>
+    <u-empty v-else text="暂无数据"></u-empty>
+  </view>
+</template>
+<script>
+import solenoidValve from './assets/solenoidValve.png';
+import stir from './assets/stir.png';
+import borderRadius from './assets/borderRadius.png';
+
+export default {
+  name: 'control',
+  data() {
+    return {
+      activeIndex: 0,
+      value: false,
+      solenoidValve,
+      stir,
+      borderRadius,
+      title: '控制面板',
+      leftList: [],
+      deviceList: [],
+      devBid: '',
+    };
+  },
+  methods: {
+    getChecked(item) {
+      return item.value == 1 ? true : false;
+    },
+    async changeSwitch(item) {
+      item.value = item.value == 1 ? 0 : 1;
+      const sfCode = item.sfCode;
+      const params = {};
+      params[sfCode] = item.value;
+      const payload = {
+        data: params,
+      };
+      const data = {
+        devBid: this.devBid,
+        data: params,
+      };
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/devctl/',
+        method: 'post',
+        data,
+        header: {
+          'Content-Type': 'application/json',
+        },
+      });
+      if (res.code !== '000000') {
+        item.value = item.value == 1 ? 0 : 1;
+      }
+      uni.showToast({
+        title: res.msg,
+        icon: 'none',
+      });
+    },
+    controlClick(index) {
+      this.activeIndex = index;
+      this.deviceList = this.leftList[this.activeIndex]?.childrenList || [];
+    },
+    /*
+      0	水源	泵类	负责水源进入管道的总泵或者阀
+      1	肥料	泵类	负责肥料进入管道的总阀或者泵
+      2	吸肥	泵类	控制肥料桶出肥的阀或者泵,每个肥料桶一个
+      3	搅拌	泵类	肥料桶的搅拌电机或者泵 每个肥料桶一个
+      4	肥料桶	泵类	肥料桶,每个施肥机有多个或者没有,不一定真实存在,只是逻辑上的概念
+      5	电磁阀	无	管道最末端每个田地里控制出水的阀门
+      6	传感器	无	水肥机上的 温度,压力,流速,PH EC等监测类要素
+      7	灌区    无	逻辑区域,电磁阀的分组
+      */
+    async getdeviceSfStatus() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/status/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+      this.deviceList = [];
+      const sfCurrent = [
+        {
+          sfDisplayname: '水肥机',
+          childrenList: [],
+        },
+      ];
+      const irrigatedAreaList = [];
+      res?.forEach((item) => {
+        if (item.sfType === '0' || item.sfType === '1' || item.sfType === '2') {
+          sfCurrent[0].childrenList.push(item);
+        } else if (item.sfType === '4') {
+          const childrenList = item?.childrenList || [];
+          childrenList.forEach((child) => {
+            if (
+              child.sfType === '3' ||
+              child.sfType === '2' ||
+              child.sfType === '8'
+            ) {
+              sfCurrent[0].childrenList.push(child);
+            }
+          });
+        } else if (item.sfType === '7') {
+          irrigatedAreaList.push(item);
+        }
+      });
+      this.leftList = [...sfCurrent, ...irrigatedAreaList];
+      this.deviceList = this.leftList[this.activeIndex]?.childrenList || [];
+    },
+  },
+  onLoad(options) {
+    const { devBid } = options;
+    this.devBid = devBid;
+    this.getdeviceSfStatus();
+  },
+};
+</script>
+<style scoped lang="scss">
+uni-page-body {
+  position: relative;
+  height: 100%;
+}
+.control-container {
+  background: linear-gradient(180deg, #ffffff00 0%, #fff 23.64%, #fff 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  height: 100%;
+  width: 100%;
+  overflow-x: hidden;
+  overflow-y: hidden;
+  .control-content {
+    display: flex;
+    width: 100%;
+    height: calc(100% - 102rpx);
+    overflow-x: hidden;
+    overflow-y: auto;
+    padding: 8px 0;
+    border-radius: 8px 8px 0 0;
+    background: #fff;
+    .control-list-left {
+      width: 250rpx;
+      position: fixed;
+      height: calc(100% - 90rpx);
+      overflow-x: hidden;
+      overflow-y: auto;
+      .control-list-left-item {
+        width: 240rpx;
+        height: 96rpx;
+        line-height: 96rpx;
+        background: #f5f7fa;
+        padding-left: 24rpx;
+        color: #364d46;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 32rpx;
+        font-weight: 400;
+        position: relative;
+      }
+      .control-list-left-item-active {
+        background: #ffffff;
+        border-radius: 0 -16rpx -16rpx 0;
+      }
+      .borderTopRadius {
+        position: absolute;
+        width: 40rpx;
+        height: 40rpx;
+        right: 10rpx;
+        top: -32rpx;
+        transform: rotate(90deg);
+        z-index: 100;
+      }
+      .borderBottomRadius {
+        position: absolute;
+        z-index: 100;
+        width: 40rpx;
+        height: 40rpx;
+        bottom: -32rpx;
+        right: 10rpx;
+      }
+    }
+    .control-list-right {
+      width: calc(100% - 250rpx);
+      margin: 0 32rpx;
+      margin-left: 280rpx;
+      .control-list-right-item {
+        height: 96rpx;
+        display: flex;
+        padding: 0rpx 16rpx;
+        align-items: center;
+        border-radius: 8rpx;
+        background: #f5f7fa;
+        margin-bottom: 22rpx;
+        position: relative;
+        .control-list-right-item-icon {
+          .solenoid-valve {
+            width: 40rpx;
+            height: 40rpx;
+          }
+        }
+        .control-list-right-item-title {
+          margin-left: 8rpx;
+        }
+        .control-list-right-item-action {
+          position: absolute;
+          right: 16rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 314 - 0
pages/cb/shuifeizsFirst/history.vue

@@ -0,0 +1,314 @@
+<template>
+  <view class="history-container">
+    <custom-card>
+      <block slot="backText">{{ title }}</block>
+    </custom-card>
+    <view class="calendar" @click="handleCalendarClick">
+      <view class="calendar__label">选择日期</view>
+      <view class="calendar__content">
+        <text>{{ startTime }}</text>
+        <text class="separate">-</text>
+        <text>{{ endTime }} </text>
+      </view>
+      <view class="calendar__link">
+        <u-icon name="arrow-right" color="#4e5969"></u-icon>
+      </view>
+    </view>
+    <view class="history-form-container">
+      <view class="form-header">
+        <view class="form-header__title">设备名称</view>
+        <view class="form-header__title">操作内容</view>
+        <view class="form-header__title">操作人</view>
+        <view class="form-header__title">操作时间</view>
+      </view>
+      <view class="scroll-container">
+        <scroll-view
+          class="main__right"
+          v-if="historyList.length !== 0"
+          scroll-y="true"
+          style="height: 100%"
+          @scrolltolower="scrolltolower"
+          :show-scrollbar="true"
+        >
+          <view
+            class="form-content"
+            v-for="(item, index) in historyList"
+            :key="index"
+          >
+            <view class="form-content__item form-content__item--text">{{
+              item.oprecdName
+            }}</view>
+            <view class="form-content__item">
+              <view class="item-open" v-if="item.oprecdContent == '打开'"
+                >打开</view
+              >
+              <view class="item-close" v-else>{{ item.oprecdContent }}</view>
+            </view>
+            <view class="form-content__item">{{ item.oprcdCreatorName }}</view>
+            <view class="form-content__item">
+              <view class="item-time">{{
+                getTopTime(item.oprcdCreateddate)
+              }}</view>
+              <view class="item-date">{{
+                getYearTime(item.oprcdCreateddate)
+              }}</view>
+            </view>
+          </view>
+        </scroll-view>
+        <u-empty v-else style="height: 80%"
+      /></view>
+    </view>
+    <u-calendar
+      v-model="show"
+      mode="range"
+      @change="handleConfirm"
+    ></u-calendar>
+    <!-- <wu-calendar
+      ref="calendar"
+      mode="range"
+      :insert="false"
+      :maskClick="true"
+      :rangeSameDay="true"
+      :itemHeight="55"
+      @confirm="handleConfirm"
+    ></wu-calendar> -->
+  </view>
+</template>
+<script>
+import solenoidValve from './assets/solenoidValve.png';
+export default {
+  name: 'actionHistory',
+  data() {
+    return {
+      title: '操作记录',
+      devBid: '',
+      pageSize: 20,
+      pageNum: 1,
+      show: false,
+      // 获取当前日期向前3个月
+      startTime: this.formartDate(3),
+      endTime: this.formartDate(),
+      historyList: [],
+      total: 0,
+    };
+  },
+  computed: {
+    hasMore() {
+      return this.total > 0 && this.total > this.pageNum * this.pageSize;
+    },
+  },
+  methods: {
+    getTopTime(date) {
+      return date.split(' ')[1];
+    },
+    getYearTime(date) {
+      return date.split(' ')[0];
+    },
+    async getHistory() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/op/record/list/',
+        method: 'post',
+        header: {
+          'Content-Type': 'application/x-www-form-urlencoded',
+        },
+        data: {
+          pageSize: this.pageSize,
+          pageNum: this.pageNum,
+          startTime: this.startTime + ' 00:00:00',
+          endTime: this.endTime + ' 23:59:59',
+          devBid: this.devBid,
+        },
+        sfType: true,
+      });
+      this.historyList = this.historyList.concat(res.data);
+      this.total = res.total;
+    },
+    formartDate(month = 0) {
+      const time = month * 30 * 24 * 60 * 60 * 1000;
+      const timeStamp = new Date(new Date().getTime() - time);
+      const year = timeStamp.getFullYear();
+      const monthDate = timeStamp.getMonth() + 1;
+      const monthStr = monthDate < 10 ? `0${monthDate}` : monthDate;
+      const day = new Date().getDate();
+      const dayStr = day < 10 ? `0${day}` : day;
+      return `${year}-${monthStr}-${dayStr}`;
+    },
+    handleCalendarClick() {
+      this.show = true;
+      // this.$refs.calendar.open();
+    },
+    handleClose() {
+      this.show = false;
+    },
+    scrolltolower() {
+      if (this.hasMore) {
+        this.pageNum++;
+        this.getHistory();
+      }
+    },
+    handleConfirm(e) {
+      const startDate = e.startDate;
+      const endDate = e.endDate;
+      this.pageNum = 1;
+      this.historyList = [];
+      this.startTime = startDate;
+      this.endTime = endDate;
+      this.getHistory();
+    },
+  },
+  onLoad(options) {
+    const { devBid } = options;
+    this.devBid = devBid;
+    this.getHistory();
+  },
+};
+</script>
+<style scoped lang="scss">
+uni-page-body {
+  position: relative;
+  height: 100%;
+}
+::v-deep .u-calendar__action {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+::v-deep .u-hover-class {
+  opacity: 0.6;
+}
+.scroll-container {
+  height: calc(100vh - 420rpx);
+}
+.history-container {
+  background: linear-gradient(180deg, #ffffff00 0%, #fff 23.64%, #fff 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  height: 100%;
+  width: 100%;
+  overflow-x: hidden;
+  overflow-y: hidden;
+  .calendar {
+    position: relative;
+    display: flex;
+    align-items: center;
+    padding: 0 32rpx;
+    line-height: 64rpx;
+    border-radius: 16rpx;
+    background-color: #fff;
+    margin: 0 32rpx;
+    &__icon {
+      margin-right: 12rpx;
+    }
+
+    &__label {
+      font-size: 28rpx;
+      color: #666;
+      margin-right: 10rpx;
+    }
+
+    &__content {
+      font-size: 28rpx;
+      color: #666;
+      margin-left: 64rpx;
+      .separate {
+        margin: 0 6rpx;
+      }
+    }
+
+    &__link {
+      position: absolute;
+      right: 20rpx;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+  }
+  .history-form-container {
+    width: calc(100% - 64rpx);
+    height: calc(100vh - 300rpx);
+    margin: 32rpx;
+    border-radius: 16rpx;
+    background: #fff;
+    overflow: hidden;
+    .form-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      height: 80rpx;
+      width: 100%;
+      border-bottom: 2rpx solid #e4e7ed;
+      &__title {
+        width: 25%;
+        text-align: center;
+        font-size: 28rpx;
+        color: #042118;
+        font-family: 'Source Han Sans CN VF';
+        font-style: normal;
+        font-weight: 400;
+        line-height: normal;
+      }
+    }
+    .form-content {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      height: 96rpx;
+      width: 100%;
+      border-bottom: 2rpx solid #e4e7ed;
+      &__item {
+        width: 25%;
+        text-align: center;
+        font-size: 28rpx;
+        font-family: 'Source Han Sans CN VF';
+        font-style: normal;
+        color: #042118;
+        .item-open {
+          display: inline-flex;
+          height: 40rpx;
+          padding: 4rpx 16rpx;
+          justify-content: center;
+          align-items: center;
+          border-radius: 20rpx;
+          background: #14a47824;
+          color: #14a478;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 24rpx;
+          font-weight: 400;
+        }
+        .item-close {
+          display: inline-flex;
+          height: 40rpx;
+          padding: 4rpx 16rpx;
+          justify-content: center;
+          align-items: center;
+          border-radius: 20rpx;
+          background: #7a82911a;
+          color: #7a8291;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 24rpx;
+          font-weight: 400;
+        }
+        .item-time {
+          color: #042118;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 28rpx;
+          font-weight: 400;
+        }
+        .item-date {
+          color: #042118;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 24rpx;
+          font-weight: 400;
+        }
+      }
+      &__item--text {
+        width: 20%;
+        margin-left: 5%;
+        // 超出隐藏
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        text-align: left;
+      }
+    }
+  }
+}
+</style>

+ 562 - 0
pages/cb/shuifeizsFirst/rotationflow.vue

@@ -0,0 +1,562 @@
+<template>
+  <view class="rotationflow">
+    <custom-card>
+      <block slot="backText">自动控制</block>
+    </custom-card>
+    <view class="rotationflow-top">
+      <view class="rotationflow-top-list">
+        <image :src="autoBtn" class="rotate-autoBtn" />
+        <image :src="rotate" class="rotate-rotate" />
+        <image :src="water" class="rotate-water" />
+        <view class="rotationflow-time">
+          <view class="rotationflow-time-title" style="font-size: 28px">{{
+            currentFq.name || '--'
+          }}</view>
+          <!-- <view class="rotationflow-time-content"> {{ time }}</view> -->
+          <view class="rotationflow-time-label">{{ label }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="rotationflow-middle">
+      <view
+        class="rotationflow-middle-item"
+        v-for="item in list"
+        :key="item.label"
+      >
+        <view class="rotationflow-middle-item-value">{{ item.value }}</view>
+        <view class="rotationflow-middle-item-title">{{
+          item.sfDisplayname || item.sfName
+        }}</view>
+      </view>
+    </view>
+    <view class="rotationflow-content">
+      <view class="rotationflow-content-top">
+        <view
+          :class="
+            tktype == '1'
+              ? 'rotationflow-content-top-title'
+              : 'rotationflow-content-top-title-rever'
+          "
+        >
+          {{ tktype == '1' ? '灌溉' : '水肥' }}
+        </view>
+        <view class="rotationflow-content-top-desc">已选灌区</view>
+      </view>
+      <view class="rotationflow-content-list">
+        <view class="rotationflow-content-list-wrapper" v-if="tktype == 1">
+          <view class="rotationflow-content-num">
+            <view class="rotationflow-content-num-title"
+              >轮灌次数:{{ currentFq.lgcs || 0 }}</view
+            >
+            <view class="rotationflow-content-num-title"
+              >轮灌间隔:{{ currentFq.lgjg || 0 }} 分钟</view
+            >
+          </view>
+        </view>
+        <view class="rotationflow-content-list-wrapper" v-else>
+          <view class="rotationflow-content-num">
+            <view class="rotationflow-content-num-title"
+              >轮灌次数:{{ currentFq.lgcs || 0 }}</view
+            >
+            <view class="rotationflow-content-num-title"
+              >肥前水:{{ currentFq.fqcx || 0 }} 分钟</view
+            > </view
+          ><view class="rotationflow-content-num">
+            <view class="rotationflow-content-num-title"
+              >轮灌间隔:{{ currentFq.lgjg || 0 }} 分钟</view
+            >
+            <view class="rotationflow-content-num-title"
+              >肥后水:{{ currentFq.fhcx || 0 }} 分钟</view
+            > </view
+          ><view class="rotationflow-content-num">
+            <view class="rotationflow-content-num-title"
+              >模式选择:{{ getsfmode(currentFq.sfmode) }}</view
+            >
+            <view class="rotationflow-content-num-title"></view>
+          </view>
+        </view>
+        <view
+          class="rotationflow-content-list-item"
+          v-for="(item, index) in fqList"
+          :class="item.value === '2' ? 'haveYet' : ''"
+          :key="index"
+        >
+          <view
+            class="rotationflow-content-list-item-title"
+            :class="
+              item.value === '1' ? 'rotationflow-content-list-item-current' : ''
+            "
+            >{{ item.name }}</view
+          >
+          <view
+            class="rotationflow-content-list-item-desc"
+            :class="
+              item.value === '1' ? 'rotationflow-content-list-item-current' : ''
+            "
+            >{{ item.value == '2' ? '已灌溉' : item.ggsj + '分钟' }}</view
+          >
+        </view>
+      </view>
+    </view>
+    <view class="rotationflow-footer">
+      <view class="rotationflow-footer-item" @click="rotationflowEnd"
+        >结束灌溉</view
+      >
+    </view>
+  </view>
+</template>
+<script>
+import rotate from './assets/rotate.png';
+import water from './assets/water.png';
+import autoBtn from './assets/autoBtn.png';
+import json from './test.js';
+
+export default {
+  name: 'rotationflow',
+  data() {
+    return {
+      rotate,
+      water,
+      autoBtn,
+      time: '-',
+      list: [],
+      timer: null,
+      devBid: '',
+      tktype: 1,
+      lgcs: 0,
+      lgjg: 0,
+      fqList: [],
+      currentFq: {},
+      label: '灌溉中.',
+      devName: '',
+      devStatus: '',
+    };
+  },
+  components: {},
+  methods: {
+    formartTime(time) {
+      if (!time) {
+        return '-';
+      }
+      let hours = time * 60 * 1000;
+      let h = Math.floor(hours / (60 * 60 * 1000));
+      let m = Math.floor((hours % (60 * 60 * 1000)) / (60 * 1000));
+      let s = Math.floor(((hours % (60 * 60 * 1000)) % (60 * 1000)) / 1000);
+      this.time = `${h < 10 ? '0' + h : h}:${m < 10 ? '0' + m : m}:${
+        s < 10 ? '0' + s : s
+      }`;
+    },
+    setTime(time) {
+      if (!time) {
+        return '-';
+      }
+      let hours = time * 60 * 1000;
+      this.timer = setInterval(() => {
+        if (hours <= 0) {
+          clearInterval(this.timer);
+          return;
+        }
+        hours -= 1000;
+        let h = Math.floor(hours / (60 * 60 * 1000));
+        let m = Math.floor((hours % (60 * 60 * 1000)) / (60 * 1000));
+        let s = Math.floor(((hours % (60 * 60 * 1000)) % (60 * 1000)) / 1000);
+        this.time = `${h < 10 ? '0' + h : h}:${m < 10 ? '0' + m : m}:${
+          s < 10 ? '0' + s : s
+        }`;
+      }, 1000);
+    },
+    getsfmode(m) {
+      const mode = String(m);
+      switch (mode) {
+        case '1':
+          return '定时';
+        case '2':
+          return '定量';
+        case '3':
+          return 'EC调配';
+        case '4':
+          return '混肥比例';
+        default:
+          return '-';
+      }
+    },
+    async getRunStatus() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/zsrf/task/run/status/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+
+      const data = res || {};
+      if (data.status === undefined || data.status / 1 !== 1) {
+        clearInterval(this.timer);
+        clearInterval(this.labelTimer);
+        clearInterval(this.taskTimer);
+        uni.showLoading({
+          title: '灌溉任务已结束',
+        });
+
+        setTimeout(() => {
+          uni.hideLoading();
+          uni.redirectTo({
+            url: `/pages/cb/shuifeizsFirst/shuifeizs?devBid=${this.devBid}&devName=${this.devName}&devStatus=${this.devStatus}`,
+          });
+        }, 1000);
+        return;
+      }
+
+      this.list = data?.sensorList || [];
+
+      this.tktype = data?.tktype;
+      this.lgjg = data?.lgjg || 0;
+      this.lgcs = data?.lgcs || 0;
+      this.fqList = data?.fqList || [];
+      // value 0 未灌溉 1 灌溉中 2 灌溉完成
+      this.fqList.forEach((item) => {
+        if (item.value === '1') {
+          this.currentFq = item;
+        }
+      });
+      this.formartTime(this.currentFq.lgjg);
+      // this.setTime(this.currentFq.lgjg);
+    },
+    rotationflowEnd() {
+      const payload = {
+        devBid: this.devBid,
+        tkid: 0,
+        status: 0,
+        tktype: this.tktype,
+      };
+      this.postTaskCtl(payload);
+    },
+    async postTaskCtl(payload) {
+      uni.showLoading({
+        title: '正在执行',
+      });
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/zsrf/task/ctl/',
+        method: 'post',
+        data: payload,
+        header: {
+          'Content-Type': 'application/json',
+        },
+      });
+      uni.hideLoading();
+      if (res.code === '000000') {
+        uni.showToast({
+          title: '操作成功',
+        });
+        setTimeout(() => {
+          uni.navigateTo({
+            url: `/pages/cb/shuifeizsFirst/shuifeizs?devBid=${this.devBid}&devName=${this.devName}&devStatus=${this.devStatus}`,
+          });
+        }, 1000);
+      } else {
+        uni.showToast({
+          icon: 'none',
+          title: res.msg,
+        });
+      }
+    },
+  },
+  onLoad(options) {
+    const { devBid, devName, devStatus } = options;
+    this.devBid = devBid;
+    this.devName = devName;
+    this.devStatus = devStatus;
+    this.getRunStatus();
+    this.labelTimer = setInterval(() => {
+      if (this.label === '灌溉中.') {
+        this.label = '灌溉中..';
+      } else if (this.label === '灌溉中..') {
+        this.label = '灌溉中...';
+      } else {
+        this.label = '灌溉中.';
+      }
+    }, 500);
+
+    this.taskTimer = setInterval(() => {
+      this.getRunStatus();
+    }, 30000);
+  },
+  onUnload() {
+    clearInterval(this.timer);
+    clearInterval(this.labelTimer);
+    clearInterval(this.taskTimer);
+  },
+  beforeDestroy() {
+    if (this.timer) {
+      clearInterval(this.timer);
+    }
+
+    if (this.taskTimer) {
+      clearInterval(this.taskTimer);
+    }
+
+    if (this.labelTimer) {
+      clearInterval(this.labelTimer);
+    }
+  },
+};
+</script>
+<style scoped lang="scss">
+uni-page-body,
+uni-page-wrapper {
+  position: relative;
+  height: 100%;
+}
+@keyframes rotate {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+.rotationflow {
+  background: linear-gradient(
+      180deg,
+      #f5f6fa00 0%,
+      #f5f6fa 23.64%,
+      #f5f6fa 100%
+    ),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  width: 100%;
+  height: calc(100vh - 100rpx);
+  overflow: hidden;
+  overflow-y: scroll;
+  margin-bottom: 140rpx;
+  position: relative;
+  .rotationflow-top {
+    height: 500rpx;
+    width: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    .rotationflow-top-list {
+      display: flex;
+      position: relative;
+      align-items: center;
+      justify-content: center;
+      width: 100%;
+      height: 100%;
+      .rotate-autoBtn {
+        position: absolute;
+        width: 360rpx;
+        height: 360rpx;
+        z-index: 1;
+      }
+      .rotate-rotate {
+        position: absolute;
+        width: 320rpx;
+        height: 320rpx;
+        left: 215rpx;
+        top: 92rpx;
+        z-index: 2;
+        // 循环滚动
+        animation: rotate 20s linear infinite;
+      }
+      .rotate-water {
+        position: absolute;
+        width: 550rpx;
+        height: 600rpx;
+        margin-left: 220rpx;
+        margin-top: 100rpx;
+      }
+      .rotationflow-time {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        position: relative;
+        z-index: 3;
+        top: -5rpx;
+        .rotationflow-time-title {
+          width: 200rpx;
+          color: #042118;
+          text-align: center;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 32rpx;
+          font-weight: 500;
+        }
+        .rotationflow-time-content {
+          width: 200rpx;
+          color: #042118;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 40rpx;
+          font-weight: 700;
+          margin: 8rpx 0;
+          text-align: center;
+        }
+        .rotationflow-time-label {
+          width: 140rpx;
+          color: #687a74;
+          text-align: left;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 32rpx;
+          font-weight: 400;
+        }
+      }
+    }
+  }
+  .rotationflow-middle {
+    display: flex;
+    padding: 0 48rpx;
+    margin: 32rpx 0;
+    .rotationflow-middle-item {
+      width: 25%;
+      text-align: center;
+      .rotationflow-middle-item-value {
+        color: #042118;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 32rpx;
+        font-weight: 500;
+      }
+      .rotationflow-middle-item-title {
+        color: #687a74;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-style: normal;
+        font-weight: 400;
+        line-height: normal;
+        // 超出隐藏
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        overflow: hidden;
+      }
+    }
+  }
+  .rotationflow-content {
+    border-bottom: none;
+    position: relative;
+    overflow: hidden;
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 32rpx;
+    width: calc(100% - 128rpx);
+    margin-left: 32rpx;
+    margin-bottom: 140rpx;
+    &::before {
+      position: absolute;
+      content: '';
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background-size: cover;
+    }
+    .rotationflow-content-top {
+      display: flex;
+      .rotationflow-content-top-title {
+        border-radius: 8rpx;
+        background: #1890ff1a;
+        color: #1890ff;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-style: normal;
+        font-weight: 400;
+        line-height: normal;
+        padding: 4rpx 16rpx;
+      }
+      .rotationflow-content-top-title-rever {
+        border-radius: 8rpx;
+        background: #f3a72f1a;
+        color: #f3a72f;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-style: normal;
+        font-weight: 400;
+        line-height: normal;
+        padding: 4rpx 16rpx;
+      }
+      .rotationflow-content-top-desc {
+        color: #333333;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-weight: 700;
+        margin-left: 16rpx;
+      }
+    }
+    .rotationflow-content-list {
+      width: 100%;
+      .rotationflow-content-list-wrapper {
+        width: 100%;
+        border-radius: 8rpx;
+        background: #f5f6fa;
+        padding: 8rpx 0;
+        margin-top: 16rpx;
+      }
+      .rotationflow-content-num {
+        display: flex;
+        padding: 8rpx 16rpx;
+        .rotationflow-content-num-title {
+          width: 50%;
+          color: #687a74;
+          font-family: 'Source Han Sans CN VF';
+          font-size: 28rpx;
+          font-style: normal;
+          font-weight: 400;
+          margin: 0 8rpx;
+        }
+      }
+      .rotationflow-content-list-item {
+        display: flex;
+        justify-content: space-between;
+        margin: 16rpx 0;
+        color: #042118;
+        text-align: right;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-weight: 400;
+        .rotationflow-content-list-item-desc {
+        }
+        .rotationflow-content-list-item-current {
+          color: #14a478;
+        }
+      }
+      .haveYet {
+        color: #9ba6a3;
+        text-align: right;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-weight: 400;
+      }
+      .currentYet {
+        color: #14a478;
+        text-align: right;
+        font-family: 'Source Han Sans CN VF';
+        font-size: 28rpx;
+        font-weight: 400;
+      }
+    }
+  }
+  .rotationflow-footer {
+    position: fixed;
+    width: 100%;
+    bottom: 0;
+    left: 0;
+    display: flex;
+    height: 128rpx;
+    align-items: center;
+    background: #fff;
+    box-shadow: 0 -4rpx 8rpx 0 #00000026;
+    z-index: 9999;
+    .rotationflow-footer-item {
+      width: calc(100% - 64rpx);
+      margin: 0 32rpx;
+      text-align: center;
+      font-size: 32rpx;
+      height: 80rpx;
+      line-height: 80rpx;
+      color: #ffffff;
+      font-family: 'PingFang SC';
+      font-size: 32rpx;
+      font-weight: 500;
+      border-radius: 16rpx;
+      background: #ff3546;
+    }
+  }
+}
+</style>

+ 258 - 0
pages/cb/shuifeizsFirst/shuifeizs.vue

@@ -0,0 +1,258 @@
+<template>
+  <view class="facilitystate-page">
+    <custom-card>
+      <block slot="backText">
+        <view class="facilitystate-top__title">
+          <text :class="devStatus == '1' ? 'online' : 'offline'">{{
+            devStatus == '1' ? '在线' : '离线'
+          }}</text>
+          {{ devName }}
+        </view>
+      </block>
+    </custom-card>
+    <view class="facilitystate-top">
+      <view
+        class="facilitystate-top__item"
+        v-for="(item, index) in deviceList"
+        :key="index"
+        @click="nativeTo(item)"
+      >
+        <image class="item-icon" :src="item.icon" />
+        <view class="facilitystate-top__item-text">{{ item.title }}</view>
+      </view>
+    </view>
+    <Base :dataList="dataList" />
+    <facilitystate
+      :ggbCurrent="ggbCurrent"
+      :sfbCurrent="sfbCurrent"
+      :irrigatedAreaList="irrigatedAreaList"
+      :alreadyfertilizerBucketList="alreadyfertilizerBucketList"
+    />
+  </view>
+</template>
+
+<script>
+import manualControl from './assets/manualControl.png';
+import wheelIrrigation from './assets/wheelIrrigation.png';
+import timing from './assets/timing.png';
+import masterStop from './assets/masterStop.png';
+import fertilizationFormula from './assets/fertilizationFormula.png';
+import backwashControl from './assets/backwashControl.png';
+import basicSetting from './assets/basicSetting.png';
+import operatingRecord from './assets/operatingRecord.png';
+import Base from './components/base.vue';
+import facilitystate from './components/facilitystate.vue';
+export default {
+  data() {
+    return {
+      title: '水肥一体机',
+      manualControl,
+      devBid: '',
+      devName: '',
+      devStatus: '1',
+      dataList: [],
+      irrigatedAreaList: [],
+      alreadyfertilizerBucketList: [],
+      deviceList: [
+        {
+          icon: manualControl,
+          title: '手动控制',
+          url: '/pages/cb/shuifeizsFirst/control',
+        },
+        // {
+        //   icon: wheelIrrigation,
+        //   title: '自动控制',
+        //   url: '',
+        // },
+        {
+          icon: operatingRecord,
+          title: '操作记录',
+          url: '/pages/cb/shuifeizsFirst/history',
+        },
+        // {
+        //   icon: timing,
+        //   title: '定时计划',
+        //   url: '',
+        // },
+        // {
+        //   icon: masterStop,
+        //   title: '总停',
+        //   url: '',
+        // },
+        // {
+        //   icon: fertilizationFormula,
+        //   title: '施肥配方',
+        //   url: '',
+        // },
+        // {
+        //   icon: backwashControl,
+        //   title: '反冲洗控制',
+        //   url: '',
+        // },
+        // {
+        //   icon: basicSetting,
+        //   title: '基础设置',
+        //   url: '',
+        // },
+      ],
+      ggbCurrent: {},
+      sfbCurrent: {},
+    };
+  },
+  components: {
+    Base,
+    facilitystate,
+  },
+  onLoad(options) {
+    console.log(options, 'optionsoptions');
+    /*
+      0	水源	泵类	负责水源进入管道的总泵或者阀
+      1	肥料	泵类	负责肥料进入管道的总阀或者泵
+      2	吸肥	泵类	控制肥料桶出肥的阀或者泵,每个肥料桶一个
+      3	搅拌	泵类	肥料桶的搅拌电机或者泵 每个肥料桶一个
+      4	肥料桶	泵类	肥料桶,每个施肥机有多个或者没有,不一定真实存在,只是逻辑上的概念
+      5	电磁阀	无	管道最末端每个田地里控制出水的阀门
+      6	传感器	无	水肥机上的 温度,压力,流速,PH EC等监测类要素
+      7	灌区    无	逻辑区域,电磁阀的分组
+      */
+    const { devBid, devName, devStatus } = options;
+    this.devBid = devBid;
+    this.devName = devName;
+    this.devStatus = devStatus;
+    this.deviceList[0].url = `/pages/cb/shuifeizsFirst/control?devBid=${options.devBid}`;
+    this.deviceList[
+      this.deviceList.length - 1
+    ].url = `/pages/cb/shuifeizsFirst/history?devBid=${options.devBid}`;
+    if (devBid) {
+      this.init();
+    }
+  },
+  methods: {
+    async init() {
+      this.getdeviceSfStatus();
+      await this.getpeifangRefresh();
+      await this.getRunStatus();
+    },
+    // iot/mobile/device/sf/peifang/refresh/
+    async getpeifangRefresh() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/peifang/refresh/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+    },
+    async getRunStatus() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/zsrf/task/run/status/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+      const data = JSON.stringify(res || {});
+
+      if (data == '{}') {
+        this.isRun = true;
+        this.deviceList[1].url = `/pages/cb/shuifeizsFirst/automation?devBid=${this.devBid}&devName=${this.devName}&devStatus=${this.devStatus}`;
+      } else {
+        this.isRun = false;
+        this.deviceList[1].url = `/pages/cb/shuifeizsFirst/rotationflow?devBid=${this.devBid}&devName=${this.devName}&devStatus=${this.devStatus}`;
+      }
+    },
+    async getdeviceSfStatus() {
+      const res = await this.$myRequest({
+        url: '/api/v2/iot/mobile/device/sf/status/',
+        method: 'post',
+        data: {
+          devBid: this.devBid,
+        },
+      });
+      this.dataList = [];
+      this.irrigatedAreaList = [];
+      this.alreadyfertilizerBucketList = [];
+      res?.forEach((item) => {
+        if (item.sfType === '0') {
+          this.ggbCurrent = item;
+        } else if (item.sfType === '1') {
+          this.sfbCurrent = item;
+        } else if (item.sfType === '4') {
+          this.alreadyfertilizerBucketList.push(item);
+        } else if (item.sfType === '6') {
+          this.dataList.push(item);
+        } else if (item.sfType === '7') {
+          this.irrigatedAreaList.push(item);
+        }
+      });
+    },
+    nativeTo(item) {
+      uni.navigateTo({
+        url: item.url,
+      });
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+uni-page-body {
+  position: relative;
+  height: 100%;
+}
+.online {
+  height: 32rpx;
+  line-height: 32rpx;
+  padding: 0 8rpx;
+  border-radius: 4rpx;
+  background: #14a478;
+  color: #ffffff;
+  font-family: 'Source Han Sans CN';
+  font-size: 20rpx;
+  font-weight: 500;
+  margin-right: 8rpx;
+  top: -4rpx;
+  position: relative;
+}
+.offline {
+  height: 32rpx;
+  line-height: 32rpx;
+  padding: 0 8rpx;
+  border-radius: 4rpx;
+  background: #ff4d4f;
+  color: #ffffff;
+  font-family: 'Source Han Sans CN';
+  font-size: 20rpx;
+  font-weight: 500;
+  margin-right: 8rpx;
+  top: -4rpx;
+  position: relative;
+}
+.facilitystate-page {
+  background: linear-gradient(180deg, #ffffff00 0%, #fff 23.64%, #fff 100%),
+    linear-gradient(102deg, #bfeadd 6.77%, #b8f1e7 40.15%, #b9eef5 84.02%);
+  height: 100%;
+  width: 100%;
+  overflow-x: hidden;
+  overflow-y: scroll;
+  .facilitystate-top {
+    display: grid;
+    grid-template-columns: repeat(4, 1fr);
+    text-align: center;
+    margin-top: 18rpx;
+    &__item {
+      margin-bottom: 32rpx;
+      .item-icon {
+        width: 96rpx;
+        height: 96rpx;
+      }
+    }
+    &__item-text {
+      color: #042118;
+      font-family: 'Source Han Sans CN VF';
+      font-size: 28rpx;
+      font-weight: 400;
+      margin-top: 16rpx;
+    }
+  }
+}
+</style>

+ 103 - 0
pages/cb/shuifeizsFirst/test.js

@@ -0,0 +1,103 @@
+export default {
+  code: '000000',
+  msg: '\u64cd\u4f5c\u6210\u529f',
+  data: {
+    tkid: 0,
+    tktype: 1,
+    status: 0,
+    cufq: 1,
+    cufa: '2,4,6,9,12',
+    nextfq: 1,
+    sensorList: [
+      {
+        sfBid: null,
+        devBid: null,
+        sfType: '6',
+        sfName: '\u4e3b\u7ba1\u9053\u77ac\u65f6\u6d41\u91cf',
+        sfDisplayname: '\u4e3b\u7ba1\u9053\u77ac\u65f6\u6d41\u91cf',
+        sfCode: 'lszg',
+        sfParentBid: null,
+        sfSequence: 0,
+        sfCreatedDate: null,
+        sfCreator: null,
+        sfModifieddate: null,
+        sfModifier: null,
+        sfLat: null,
+        sfLng: null,
+        sfAddress: null,
+        childrenList: null,
+        value: 20.3,
+      },
+      {
+        sfBid: null,
+        devBid: null,
+        sfType: '6',
+        sfName: '\u4e3b\u7ba1\u9053\u7d2f\u8ba1\u6d41\u91cf',
+        sfDisplayname: '\u4e3b\u7ba1\u9053\u7d2f\u8ba1\u6d41\u91cf',
+        sfCode: 'llzg',
+        sfParentBid: null,
+        sfSequence: 0,
+        sfCreatedDate: null,
+        sfCreator: null,
+        sfModifieddate: null,
+        sfModifier: null,
+        sfLat: null,
+        sfLng: null,
+        sfAddress: null,
+        childrenList: null,
+        value: 210.3,
+      },
+      {
+        sfBid: null,
+        devBid: null,
+        sfType: '6',
+        sfName: 'EC',
+        sfDisplayname: 'EC',
+        sfCode: 'ec',
+        sfParentBid: null,
+        sfSequence: 0,
+        sfCreatedDate: null,
+        sfCreator: null,
+        sfModifieddate: null,
+        sfModifier: null,
+        sfLat: null,
+        sfLng: null,
+        sfAddress: null,
+        childrenList: null,
+        value: 23.809,
+      },
+      {
+        sfBid: null,
+        devBid: null,
+        sfType: '6',
+        sfName: 'PH',
+        sfDisplayname: 'PH',
+        sfCode: 'ph',
+        sfParentBid: null,
+        sfSequence: 0,
+        sfCreatedDate: null,
+        sfCreator: null,
+        sfModifieddate: null,
+        sfModifier: null,
+        sfLat: null,
+        sfLng: null,
+        sfAddress: null,
+        childrenList: null,
+        value: 7.5,
+      },
+    ],
+    fqList: [
+      {
+        fqid: '1',
+        name: '1\u533a',
+        lgcs: '',
+        lgjg: 10,
+        value: '1',
+        fqcx: '',
+        fhcx: '',
+        sfmode: '',
+        pfid: 0,
+      },
+    ],
+  },
+};

+ 9 - 2
pages/equipList/index.vue

@@ -339,9 +339,10 @@ export default {
       this.width = '90%';
     },
     modification(item) {
+      console.log(item,'itemitmeimteimtei')
       uni.navigateTo({
         url:
-          './modification?data=' + JSON.stringify(item) + '&id=' + this.type_id,
+          './seabox/modification?data=' + JSON.stringify(item) + '&id=' + this.type_id,
       });
     },
     top() {
@@ -628,7 +629,6 @@ export default {
           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}`,
           });
@@ -639,6 +639,13 @@ export default {
             url: `../cb/wenshizs/wenshizs?devBid=${item.devBid}&devName=${item.device_name}&devStatus=${item.devStatus}`,
           });
           break;
+        case 45:
+          item.addtime = item.uptime;
+          console.log(item,'itemitmeimtie')
+          uni.navigateTo({
+            url: `../cb/shuifeizsFirst/shuifeizs?devBid=${item.d_id}&devName=${item.device_name}&devStatus=${item.is_online}`,
+          });
+          break;
       }
     },
     search() {

+ 3 - 3
pages/equipList/seabox/modification.vue

@@ -42,7 +42,7 @@
 	export default {
 		data() {
 			return {
-				moddata: [],
+				moddata: {},
 				city: "",
 				selectcityTF: false,
 				quanxian:{
@@ -108,7 +108,7 @@
 						device_id: imei,
 					}
 				})
-				this.moddata = res.data[0]
+				this.moddata = res.data[0] || {};
 				console.log(res)
 				this.selectaddress(this.moddata.lng, this.moddata.lat)
 			},
@@ -120,7 +120,7 @@
 					}
 				})
 				console.log(res)
-				this.moddata = res.data[0]
+				this.moddata = res.data[0] || {};
 				this.selectaddress(this.moddata.lng, this.moddata.lat)
 			},
 			btn() {

+ 2 - 2
util/api.js

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