|
@@ -0,0 +1,451 @@
|
|
|
|
|
+<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 }"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ item.title }}
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="control-list-right">
|
|
|
|
|
+ <view class="action-container" v-if="deviceList.length > 0">
|
|
|
|
|
+ <view class="action-button" @click="openAll">一键开启</view>
|
|
|
|
|
+ <view class="action-button action-button-plain" @click="closeAll">一键关闭</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(item, index) in deviceList"
|
|
|
|
|
+ class="control-list-right-item"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view style="display: flex; align-items: center;" v-if="item.sfType != '10'">
|
|
|
|
|
+ <view class="control-list-right-item-icon">
|
|
|
|
|
+ <image
|
|
|
|
|
+ :src="solenoidValve"
|
|
|
|
|
+ class="solenoid-valve"
|
|
|
|
|
+ />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="control-list-right-item-title">{{
|
|
|
|
|
+ item.device_name
|
|
|
|
|
+ }}</view>
|
|
|
|
|
+ <view class="control-list-right-item-action">
|
|
|
|
|
+ <u-switch
|
|
|
|
|
+ :value="item.device_status == 1 ? true : false"
|
|
|
|
|
+ activeColor="#0BBC58"
|
|
|
|
|
+ size="40"
|
|
|
|
|
+ inactiveColor="rgb(230, 230, 230)"
|
|
|
|
|
+ ></u-switch>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <u-empty v-if="deviceList.length === 0" text="暂无数据"></u-empty>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <u-empty v-else text="暂无数据"></u-empty>
|
|
|
|
|
+ <u-popup v-model="showPopup" mode="bottom">
|
|
|
|
|
+ <u-form :model="form" label-width="160rpx" :label-style="{marginLeft:'20rpx'}">
|
|
|
|
|
+ <u-form-item label="开启状态">
|
|
|
|
|
+ <u-radio-group v-model="value">
|
|
|
|
|
+ <u-radio
|
|
|
|
|
+ @change="radioChange"
|
|
|
|
|
+ v-for="(item, index) in radioList" :key="index"
|
|
|
|
|
+ :name="item.value"
|
|
|
|
|
+ active-color="#0BBC58"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{item.name}}
|
|
|
|
|
+ </u-radio>
|
|
|
|
|
+ </u-radio-group>
|
|
|
|
|
+ </u-form-item>
|
|
|
|
|
+ <u-form-item label="开阀时间" v-if="value == 1">
|
|
|
|
|
+ <view @click="show1 = true" class="hour">{{hour}} 小时</view>
|
|
|
|
|
+ </u-form-item>
|
|
|
|
|
+ <u-form-item label="开度数值">
|
|
|
|
|
+ <view class="slider-row" style="display:flex;align-items:center;"><view class="slider-container">
|
|
|
|
|
+ <view class="slider-min-value">10</view>
|
|
|
|
|
+ <view
|
|
|
|
|
+ class="custom-progress"
|
|
|
|
|
+ @touchstart.stop="onSliderTouchStart($event, 'openingValue', 10, 100)"
|
|
|
|
|
+ @touchmove="onSliderTouchMove($event, 10, 100)"
|
|
|
|
|
+ @touchend.stop="onSliderTouchEnd"
|
|
|
|
|
+>
|
|
|
|
|
+ <view class="progress-track">
|
|
|
|
|
+ <view class="progress-fill" :style="{ width: getProgressWidth(equipContrlForm.openingValue, 10, 100) + '%' }"></view>
|
|
|
|
|
+ <view class="progress-thumb" :style="{ left: getProgressWidth(equipContrlForm.openingValue, 10, 100) + '%' }"></view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="slider-max-value">100</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text style="margin-left: 20rpx">{{equipContrlForm.openingValue}}</text></view>
|
|
|
|
|
+ </u-form-item>
|
|
|
|
|
+ <u-button type="success" style="width: 94%;margin-left: 3%;margin-bottom: 40rpx" @click="submit">提交</u-button>
|
|
|
|
|
+ </u-form>
|
|
|
|
|
+ </u-popup>
|
|
|
|
|
+ <u-modal v-model="show2" :title="'提示'" :content="content" @confirm="confirmHandle" @cancel="show2 = false"></u-modal>
|
|
|
|
|
+ <u-select v-model="show1" :list="hours" @confirm="changeHour"></u-select>
|
|
|
|
|
+ <u-popup v-model="show4" mode="center" width="80%" :mask-close-able="false">
|
|
|
|
|
+ <view class="progress-container">
|
|
|
|
|
+ <u-line-progress :percent="percentage" style="width: 90%;"></u-line-progress>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </u-popup>
|
|
|
|
|
+ </view>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script>
|
|
|
|
|
+import solenoidValve from './assets/solenoidValve.png';
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'control',
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ show1: false,
|
|
|
|
|
+ show2: false,
|
|
|
|
|
+ show4: false,
|
|
|
|
|
+ percentage: 0,
|
|
|
|
|
+ activeIndex: 0,
|
|
|
|
|
+ showPopup: false,
|
|
|
|
|
+ content:'确定一键关闭所有阀门吗?',
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ sliderField: '',
|
|
|
|
|
+ sliderMin: 0,
|
|
|
|
|
+ hours: [],
|
|
|
|
|
+ sliderMax: 0,
|
|
|
|
|
+ sliderRect: {},
|
|
|
|
|
+ hour: 1,
|
|
|
|
|
+ minute: 0,
|
|
|
|
|
+ form: {},
|
|
|
|
|
+ radioList:[{
|
|
|
|
|
+ name:'常开',
|
|
|
|
|
+ value:0
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name:'定时',
|
|
|
|
|
+ value:1
|
|
|
|
|
+ }],
|
|
|
|
|
+ equipContrlForm: {
|
|
|
|
|
+ openingValue: 60,
|
|
|
|
|
+ },
|
|
|
|
|
+ solenoidValve,
|
|
|
|
|
+ title: '分组控制',
|
|
|
|
|
+ leftList: [],
|
|
|
|
|
+ deviceList: [],
|
|
|
|
|
+ timer: null,
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ changeHour(e){
|
|
|
|
|
+ this.hour = e[0].value
|
|
|
|
|
+ },
|
|
|
|
|
+ setPercentage(msg){
|
|
|
|
|
+ this.timer = setInterval(() => {
|
|
|
|
|
+ this.percentage += 1;
|
|
|
|
|
+ if(this.percentage >= 100){
|
|
|
|
|
+ this.percentage = 100;
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: msg,
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ });
|
|
|
|
|
+ clearInterval(this.timer);
|
|
|
|
|
+ this.show4 = false;
|
|
|
|
|
+ this.percentage = 0;
|
|
|
|
|
+ this.getdeviceSfStatus();
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 125);
|
|
|
|
|
+ },
|
|
|
|
|
+ getHours(){
|
|
|
|
|
+ for(let i = 0; i < 24; i++){
|
|
|
|
|
+ this.hours.push({
|
|
|
|
|
+ label: i + ' 时',
|
|
|
|
|
+ value: i,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async confirmHandle(){
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ group_id: this.leftList[this.activeIndex].id,
|
|
|
|
|
+ control_type:'close',
|
|
|
|
|
+ };
|
|
|
|
|
+ const res = await this.$myRequest({
|
|
|
|
|
+ url: '/api/api_gateway?method=irrigation_system.valvecontrol.control_huapu_valve_group',
|
|
|
|
|
+ method: 'post',
|
|
|
|
|
+ data
|
|
|
|
|
+ });
|
|
|
|
|
+ if(res.code == 0){
|
|
|
|
|
+ this.show4 = true;
|
|
|
|
|
+ this.setPercentage(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.showPopup = false;
|
|
|
|
|
+ this.show2 = false;
|
|
|
|
|
+ },
|
|
|
|
|
+ async submit(){
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ group_id: this.leftList[this.activeIndex].id,
|
|
|
|
|
+ control_type:'open',
|
|
|
|
|
+ valve_delayed: this.value == 0 ? 0 : this.hour * 60 + this.minute,
|
|
|
|
|
+ var_value: this.equipContrlForm.openingValue,
|
|
|
|
|
+ };
|
|
|
|
|
+ const res = await this.$myRequest({
|
|
|
|
|
+ url: '/api/api_gateway?method=irrigation_system.valvecontrol.control_huapu_valve_group',
|
|
|
|
|
+ method: 'post',
|
|
|
|
|
+ data
|
|
|
|
|
+ });
|
|
|
|
|
+ if(res.code == 0){
|
|
|
|
|
+ this.show4 = true;
|
|
|
|
|
+ this.setPercentage(res.msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.showPopup = false;
|
|
|
|
|
+ this.show2 = false;
|
|
|
|
|
+ },
|
|
|
|
|
+ getProgressWidth(value, min, max) {
|
|
|
|
|
+ if (max === min) return 0
|
|
|
|
|
+ return ((value - min) / (max - min)) * 100
|
|
|
|
|
+ },
|
|
|
|
|
+ getModel(value){
|
|
|
|
|
+ return value == 0 ? false : true
|
|
|
|
|
+ },
|
|
|
|
|
+ controlClick(index) {
|
|
|
|
|
+ this.activeIndex = index;
|
|
|
|
|
+ this.deviceList = this.leftList[this.activeIndex]?.device_list || [];
|
|
|
|
|
+ },
|
|
|
|
|
+ onSliderTouchStart(e, field, min, max) {
|
|
|
|
|
+ const clientX = e.touches[0].clientX
|
|
|
|
|
+ this.sliderField = field
|
|
|
|
|
+ this.sliderMin = min
|
|
|
|
|
+ this.sliderMax = max
|
|
|
|
|
+ const query = uni.createSelectorQuery().in(this)
|
|
|
|
|
+ query.selectAll('.custom-progress').boundingClientRect(rects => {
|
|
|
|
|
+ const list = Array.isArray(rects) ? rects : []
|
|
|
|
|
+ this.sliderRect = list.find(r => r && r.width > 0) || list[0] || null
|
|
|
|
|
+ this.updateSliderValue(clientX, field, min, max)
|
|
|
|
|
+ }).exec()
|
|
|
|
|
+ },
|
|
|
|
|
+ onSliderTouchMove(e, min, max) {
|
|
|
|
|
+ if (!this.sliderField || !this.sliderRect) return
|
|
|
|
|
+ this.updateSliderValue(e.touches[0].clientX, this.sliderField, min, max)
|
|
|
|
|
+ },
|
|
|
|
|
+ onSliderTouchEnd() {
|
|
|
|
|
+ this.sliderField = ''
|
|
|
|
|
+ },
|
|
|
|
|
+ onSliderTap(e, field, min, max) {
|
|
|
|
|
+ const query = uni.createSelectorQuery().in(this)
|
|
|
|
|
+ query.select('.custom-progress').boundingClientRect(rect => {
|
|
|
|
|
+ this.sliderRect = rect
|
|
|
|
|
+ this.updateSliderValue(e.detail.x + rect.left, field, min, max)
|
|
|
|
|
+ }).exec()
|
|
|
|
|
+ },
|
|
|
|
|
+ updateSliderValue(clientX, field, min, max) {
|
|
|
|
|
+ if (!this.sliderRect || !this.sliderRect.width) return
|
|
|
|
|
+ let ratio = (clientX - this.sliderRect.left) / this.sliderRect.width
|
|
|
|
|
+ ratio = Math.max(0, Math.min(1, ratio))
|
|
|
|
|
+ const value = Math.round(min + ratio * (max - min))
|
|
|
|
|
+ this.$set(this.equipContrlForm, field, value)
|
|
|
|
|
+ },
|
|
|
|
|
+ openAll(){
|
|
|
|
|
+ this.showPopup = true;
|
|
|
|
|
+ },
|
|
|
|
|
+ closeAll(){
|
|
|
|
|
+ this.show2 = true;
|
|
|
|
|
+ },
|
|
|
|
|
+ initData(res){
|
|
|
|
|
+ this.deviceList = [];
|
|
|
|
|
+ this.leftList = [];
|
|
|
|
|
+ res?.forEach((item) => {
|
|
|
|
|
+ this.leftList.push(item);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ async getdeviceSfStatus() {
|
|
|
|
|
+ this.activeIndex = 0;
|
|
|
|
|
+ const res = await this.$myRequest({
|
|
|
|
|
+ url: '/api/api_gateway?method=irrigation_system.valvecontrol.get_huapu_valve_group_list',
|
|
|
|
|
+ method: 'post',
|
|
|
|
|
+ });
|
|
|
|
|
+ this.initData(res?.data || []);
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ onLoad() {
|
|
|
|
|
+ this.getHours();
|
|
|
|
|
+ this.getdeviceSfStatus();
|
|
|
|
|
+ },
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+uni-page-body {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+.progress-container{
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ height:100%;
|
|
|
|
|
+}
|
|
|
|
|
+.hour,.minute{
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #999999;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ border: 2rpx solid #aaa;
|
|
|
|
|
+ padding: 4rpx 8rpx;
|
|
|
|
|
+ margin-right: 8rpx;
|
|
|
|
|
+ height: 40rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ width: 160rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.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;
|
|
|
|
|
+ //超出隐藏
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+ .control-list-left-item-active {
|
|
|
|
|
+ background: #0bbc581a;
|
|
|
|
|
+ color:#0BBC58;
|
|
|
|
|
+ font-family: "Source Han Sans CN VF";
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .control-list-right {
|
|
|
|
|
+ width: calc(100% - 250rpx);
|
|
|
|
|
+ margin: 0 32rpx;
|
|
|
|
|
+ margin-left: 280rpx;
|
|
|
|
|
+ .action-container {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 22rpx;
|
|
|
|
|
+ gap: 22rpx;
|
|
|
|
|
+ .action-button{
|
|
|
|
|
+ flex:1;
|
|
|
|
|
+ height: 80rpx;
|
|
|
|
|
+ line-height: 80rpx;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+ background: #0bbc58;
|
|
|
|
|
+ color:#ffffff;
|
|
|
|
|
+ font-family: "Source Han Sans CN VF";
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ }
|
|
|
|
|
+ .action-button-plain{
|
|
|
|
|
+ background: #ffffff;
|
|
|
|
|
+ border:2rpx solid #0bbc58;
|
|
|
|
|
+ color:#0bbc58;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .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 {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ .solenoid-valve {
|
|
|
|
|
+ width: 40rpx;
|
|
|
|
|
+ height: 40rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .control-list-right-item-title {
|
|
|
|
|
+ margin-left: 8rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ .control-list-right-item-action {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 16rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .slider-container{
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ margin-top: 10rpx;
|
|
|
|
|
+ .slider-min-value{
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ top: -60rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ .slider{
|
|
|
|
|
+ width: 600rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ .slider-max-value{
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ top: -60rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .custom-progress{
|
|
|
|
|
+ width: 500rpx;
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ .progress-track{
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ height: 12rpx;
|
|
|
|
|
+ background-color: #ebedf0;
|
|
|
|
|
+ border-radius: 6rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ .progress-fill{
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background-color: #0BBC58;
|
|
|
|
|
+ border-radius: 6rpx;
|
|
|
|
|
+ transition: width 0.2s;
|
|
|
|
|
+ }
|
|
|
|
|
+ .progress-thumb{
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 50%;
|
|
|
|
|
+ width: 28rpx;
|
|
|
|
|
+ height: 28rpx;
|
|
|
|
|
+ margin-left: -14rpx;
|
|
|
|
|
+ margin-top: -14rpx;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+ box-shadow: 0 1px 4px rgba(0,0,0,0.3);
|
|
|
|
|
+ transition: left 0.2s;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|