jsy-app/pages/index.vue
2024-09-30 15:34:20 +08:00

853 lines
22 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 顶部导航栏 -->
<uni-nav-bar :statusBar="true" :fixed="true" backgroundColor="#39ac4f" :border="false" color="#fff">
<block v-slot:left>
<view @click="openLand">地块</view>
</block>
<view>{{ indexData.selectItem ? indexData.selectItem.name:"田间" }}</view>
<block v-slot:right>
<view class="fixed">
<view align="right" class="icon iconfont icon-liebiao" @click="toList"></view>
<view align="right" class="icon iconfont icon-scan" @click="toQRCode"></view>
</view>
</block>
</uni-nav-bar>
<!-- 内容 -->
<view class="content">
<!-- 顶部搜索框 -->
<view class="header-section">
<u-row justify="space-between" gutter="10">
<u-col span="8">
<u-search shape="square" :animation="true" :showAction="false"></u-search>
</u-col>
<u-col span="4">
<view class="demo-layout bg-purple-light">
<u-checkbox-group placement="row">
<u-checkbox :checked="false" label="工作(256)" labelColor="#ffffff"></u-checkbox>
</u-checkbox-group>
</view>
</u-col>
</u-row>
</view>
<view class="content-section">
<!-- 统计吸顶效果 -->
<view v-if="isSticky" class="grey-box ceiling"
:style="[isSticky ? 'position: sticky;':'','z-index: 10','top: 50px']">
<u-grid :border="false" col="4">
<u-grid-item class="click">
<view class="flex">
<view class="iconfont icon-threshold"></view>
<u-badge numberType="overflow" type="success" max="999" value="155"></u-badge>
</view>
</u-grid-item>
<u-grid-item>
<view class="flex">
<view class="iconfont icon-jizhan"></view>
<u-badge numberType="overflow" type="success" max="999" value="15"></u-badge>
</view>
</u-grid-item>
<u-grid-item>
<view class="flex">
<view class="iconfont icon-lixian"></view>
<u-badge numberType="overflow" type="success" max="999" value="15"></u-badge>
</view>
</u-grid-item>
<u-grid-item>
<view class="flex">
<view class="iconfont icon-shangqing"></view>
<u-badge numberType="overflow" type="success" max="999" value="15"></u-badge>
</view>
</u-grid-item>
</u-grid>
</view>
<view v-else class="grey-box normal">
<u-grid :border="false" col="4">
<u-grid-item class="click">
<view class="iconfont icon-threshold"></view>
<u-badge numberType="overflow" type="success" max="999" value="155"></u-badge>
<text class="text">总设备</text>
</u-grid-item>
<u-grid-item>
<view class="iconfont icon-jizhan"></view>
<u-badge numberType="overflow" type="success" max="999" value="15"></u-badge>
<text class="text">在线设备</text>
</u-grid-item>
<u-grid-item>
<view class="iconfont icon-lixian"></view>
<u-badge numberType="overflow" type="success" max="999" value="15"></u-badge>
<text class="text">离线设备</text>
</u-grid-item>
<u-grid-item>
<view class="iconfont icon-shangqing"></view>
<u-badge numberType="overflow" type="success" max="999" value="15"></u-badge>
<text class="text">土壤墒情</text>
</u-grid-item>
</u-grid>
</view>
<!-- 列表 -->
<view class="grey-box" style="border-radius: 0 0 15px 15px;">
<!-- 基站 -->
<view class="card">
<u-collapse accordion>
<u-collapse-item>
<template #title>
<view class="jz-title fixed">
<view style="width:30%;">
<view class="iconfont icon-plume icon"></view>
<text>基站</text>
</view>
<view class="fixed" style="width:calc(100% - 30%); justify-content: flex-end;">
<view class="iconfont icon-xh icon"
:class="[ mqtt.connected ? 'font-green':'font-red' ]">
</view>
<view @click.stop="">
<u-button type="success" size="small" text="一键刷新" />
</view>
<view @click.stop="">
<u-button type="success" size="small" text="批量控制" />
</view>
</view>
</view>
</template>
<view class="u-collapse-content">
<u-row v-for="item in dc.stations">
<u-col span="3">
<view class="fixed">
<text :class="[item.online ? 'font-green':'font-red']">●</text>
<view>{{ item.deviceCode }}</view>
</view>
</u-col>
<u-col span="4" style="align-items: center;">
<view class="fixed">
<!-- <view class="signal" v-if="item.signalValue > 110"> -->
<view class="signal" v-if="item.signalValue > 0">
<view v-for="(_,i) in 4"
:class="['bar',item.signalValue > (8 * i) ? 'green':'']"></view>
<view :class="['bar',item.signalValue > 30 ? 'green':'']"></view>
</view>
<view class="signal" v-else>
<view class="bar" v-for="i in 5"></view>
<view class="bar-no">
<u-icon name="close"></u-icon>
</view>
</view>
<text>({{ item.signalValue }})</text>
<view class="battery-container">
<text>{{ item.currentBatteryCapacity }} </text>
<view class="battery-level"
:style="[`width:${item.currentBatteryCapacity}%`]" />
</view>
</view>
</u-col>
<u-col span="5">
<view class="fixed">
<u-button type="success" size="mini" text="手持基站"></u-button>
<u-button type="success" size="mini" text="刷新" icon="reload"></u-button>
</view>
</u-col>
</u-row>
</view>
</u-collapse-item>
</u-collapse>
</view>
<!-- <button @click="mqttLink">mqttLink</button>
<button @click="mqttEnd">mqttEnd</button>
<button @click="mqttSubscribes">订阅</button> -->
<!-- 阀门列表 -->
<view class="card">
<u-collapse accordion>
<u-collapse-item v-for="item in dc.valves">
<template #title>
<view class="sf-title fixed">
<view class="iconfont icon-diefa icon"></view>
<view class="text">{{ item.rowKey }}</view>
<view style="margin:0 10px;">出水口数量</view>
<u-badge numberType="overflow" type="info" showZero max="999"
:value="item.children.length" />
</view>
</template>
<view class="u-collapse-content">
<!-- 蝶阀 -->
<u-row v-if="item.deviceId">
<u-col span="4">
<view class="fixed">
<text
:class="[item.device.custom.online ? 'font-green':'font-red']">●</text>
{{ item.rowKey }}
</view>
</u-col>
<u-col span="5">
<view class="battery-container">
<text>{{ item.device.custom.battery.value }}</text>
<view class="battery-level"
:style="[`width:${item.device.custom.battery.value}%`]" />
</view>
</u-col>
<u-col span="3" style="align-items: flex-end;">
<u-switch v-model="value" @change="flapValveChange" size="20"
activeColor="#39ac4f"></u-switch>
</u-col>
</u-row>
<!-- 阀门 -->
<view v-for="item2 in item.children">
<view v-if="item2.deviceId" class="card-grey">
<view class="card-title">
<u-row>
<u-col span="2">
<view>
<text
:class="[item2.device.custom.online ? 'font-green':'font-red']">●</text>
{{ item2.rowKey }}
</view>
</u-col>
<u-col span="5">
<view class="fixed">
<view class="battery-container">
<text>{{ item2.device.custom.battery.value }}</text>
<view class="battery-level"
:style="[`width:${item2.device.custom.battery.value}%`]" />
</view>
<view>
<view class="iconfont icon-wendu icon" />
{{ item2.device.custom.t }}
</view>
</view>
</u-col>
<u-col span="5" style="align-items: flex-end;">
<view class="fixed">
<u-button type="success" size="mini" text="刷新"
icon="reload"></u-button>
</view>
</u-col>
</u-row>
</view>
<view class="control">
<!-- 三通阀 -->
<u-row
v-if="item2.device.deviceTypeId == 2 || item2.device.deviceTypeId == 3">
<u-col span="3" style=" align-items: flex-end;"
@click="angleSliderShow">
<view class="buttons">
<view class="btn v-btn fixed active ">
<text>①</text>
<text class="load-text">(999)</text>
<text class="load-text"
v-if="!item2.device.custom.btnPreload && item2.device.custom.btnState.closeAll.loading && item2.device.custom.ct.endS >= 0"
:class="item2.device.custom.ct.endS > 0 ? '' : 'loading-time-red'">
{{ item2.device.custom.ct.endS > 0 ? `(${item2.device.custom.ct.endS})` : "超时" }}
</text>
<view v-if="!item2.device.custom.btnControllable.open1"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
<u-line-progress height="8" :showText="false" :percentage="60"
activeColor="#74ffd4" inactiveColor="#c7c7c7"
style="width: 75px;margin-top: 5px;">
</u-line-progress>
</u-col>
<u-col span="6">
<view class="valve">
<view>
<view class="btn v-btn2 fixed">
<text>全开</text>
<text class="load-text">(超时)</text>
<view
v-if="!item2.device.custom.btnControllable.openAll"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
<view class="btn-img">
<view class="text">
<view class="left">{{ item2.device.custom.p1 }}</view>
<view class="top"></view>
<view class="middle"
v-show="!item2.device.custom.online">
{{ item2.device.custom.showMask.text }}
</view>
<view class="right">{{ item2.device.custom.p2 }}</view>
<view class="bottom"></view>
</view>
<image :src="item2.device.custom.showImg" mode="widthFix" />
</view>
<view>
<view class="btn v-btn2 fixed">
<text>全关</text>
<text class="load-text">(超时)</text>
<view
v-if="!item2.device.custom.btnControllable.closeAll"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
</view>
</u-col>
<u-col span="3">
<view class="buttons">
<view class="btn v-btn fixed activeing">
<text>②</text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open2"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
</u-col>
</u-row>
<!-- 五通阀 -->
<u-row v-if="item2.device.deviceTypeId == 13">
<u-col span="3" style=" align-items: flex-end;">
<view class="buttons">
<view class="btn v-btn fixed active">
<text>①</text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open1"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
</u-col>
<u-col span="6">
<view class="valve">
<view>
<view class="btn v-btn fixed">
<text>②</text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open2"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
<view class="btn-img">
<view class="text5">
<view class="left">{{ item2.device.custom.p[0] }}</view>
<view class="top">{{ item2.device.custom.p[1] }}</view>
<view class="middle"
v-show="!item2.device.custom.online">
{{ item2.device.custom.showMask.text }}
</view>
<view class="right">{{ item2.device.custom.p[2] }}
</view>
<view class="bottom">{{ item2.device.custom.p[3] }}
</view>
</view>
<image :src="item2.device.custom.showImg" mode="widthFix" />
</view>
<view>
<view class="btn v-btn fixed">
<text>④</text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open4"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
</view>
</u-col>
<u-col span="3">
<view class="buttons">
<view class="btn v-btn fixed">
<text>③</text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open3"
class="iconfont icon-suoding icon">
</view>
</view>
</view>
</u-col>
</u-row>
<view class="font-red" v-if="item2.device.custom.showMask.show">
<view class="iconfont icon-guzhang icon">
{{item2.device.custom.showMask.text}}
</view>
</view>
</view>
</view>
<view v-else class="card-grey">
{{ item2.rowKey }}
</view>
</view>
</view>
</u-collapse-item>
</u-collapse>
</view>
</view>
</view>
</view>
<!-- 弹窗 -->
<view>
<!-- 地块选择 -->
<custom-select-land ref="refLand" @select="landChange"></custom-select-land>
<!-- 角度 -->
<custom-angle-slider ref="refAngleSlider" mode="bottom" @close="" @confirm="angleSliderConfirm" />
</view>
</template>
<script>
import store from "@/store"
export default {
data() {
return {
user: store.state.user.user,
isSticky: false, //吸顶状态
value: false,
indexData: getApp().indexData,
dc: getApp().dc,
mqtt: getApp().mqtt,
isLandChange: false,
}
},
onLoad() {
console.error("onLoad")
// uni.$emit("mqtt-link", this.user.userId);
// getApp().mqttLink(this.user.userId);
uni.$off("notify-update-land");
uni.$on("notify-update-land", (data) => {
console.error("index监听地块更新", data)
this.isLandChange = true;
});
},
onShow() {
// #ifdef APP-PLUS
plus.screen.lockOrientation("portrait-primary");
plus.navigator.setFullscreen(false);
// #endif
this.getDevice();
},
onPageScroll(e) { // 页面滚动触发事件的处理函数
// console.log(e.scrollTop); // 输出滚动位置的垂直距离
if (e.scrollTop >= 75) {
this.isSticky = true;
} else {
this.isSticky = false;
}
},
methods: {
mqttLink() {
getApp().mqttLink(this.user.userId);
},
mqttEnd() {
getApp().mqttEnd();
},
mqttSubscribes() {
console.error("mqtt", this.mqtt)
let topics = ["jsy/iot/push/1H8ngznmV50GzutYS8rIk01pd8"]
getApp().mqttSubscribes(topics);
},
//打开地块
openLand() {
this.$refs.refLand.open();
},
//地块选择回调
landChange(e) {
this.isLandChange = true;
this.getDevice();
},
//更新设备列表
getDevice() {
if (this.isLandChange) {
console.error('getDevice_index_开始更新地块');
uni.showLoading();
getApp().indexData.getNewDeviceList();
this.isLandChange = false;
}
},
//蝶阀按钮切换
flapValveChange(e) {
console.error('flapValveChange', e);
},
//去列表
toList() {
uni.navigateTo({
url: `/pages/index-list`
})
},
//去扫码
toQRCode() {},
//显示角度弹框
angleSliderShow() {
this.$refs.refAngleSlider.show("1-1", "①开", 10, {
// item: e.row,
// index: e.index,
});
},
//显示角度弹框确认
angleSliderConfirm(e) {
console.error("angleSliderConfirm:", e);
},
},
}
</script>
<style lang="scss" scoped>
// .content {
// display: flex;
// flex-direction: column;
// align-items: center;
// justify-content: center;
// }
page {
background-color: #ffffff;
}
// 箭头隐藏
::v-deep.u-cell__right-icon-wrap {
display: none;
}
// nav
::v-deep.uni-navbar__header-container {
align-items: center;
justify-content: center;
&>view {
font-size: 36rpx;
}
}
::v-deep.uni-navbar__header-btns-left {
font-size: 27rpx;
}
::v-deep.uni-navbar__header-btns-right .icon {
font-size: 44rpx;
margin-left: 10px;
}
.header-section {
padding: 0px 10px 102px 10px;
background-color: #39ac4f;
color: white;
border-radius: 0 0 30px 30px;
::v-deep.u-search__content,
::v-deep.u-search__content__input {
background-color: white !important;
border-radius: 8px !important;
.u-icon__icon {
color: #39ac4f !important;
}
}
// 复选框
::v-deep .u-checkbox__icon-wrap {
background-color: transparent !important;
border-color: #ffffff !important;
}
}
.content {
background-color: #fff;
min-height: 100%;
}
.content-section {
position: relative;
top: -92px;
.grey-box.normal {
border-radius: 15px 15px 0 0;
padding-bottom: 0;
.u-grid {
margin-bottom: 0;
}
}
.grey-box.ceiling {
border-radius: 0;
padding-bottom: 0px;
margin: 0;
box-shadow: 0 1px 9px rgba(209, 209, 209, 0.5);
.u-grid {
padding-bottom: 10px;
.u-grid-item {
padding-bottom: 5px;
box-shadow: none;
.flex {
&>view {
margin: -2px 5px 0 0;
color: #39ac4f;
font-size: 50rpx;
}
::v-deep.u-badge {
position: relative;
right: auto;
top: auto;
height: 10px;
}
}
}
.click {
.flex {
&>view {
color: #fff;
}
}
}
}
}
.grey-box {
background-color: #f3f3f3;
margin: 0 10px;
border-radius: 15px;
padding: 15px 10px;
.u-grid {
margin-bottom: 15px;
.u-grid-item {
margin: auto 5px;
width: calc(25% - 10px) !important;
background-color: #ffffff !important;
padding: 10px 0;
border-radius: 10px;
box-shadow: 0 1px 9px rgb(209, 209, 209, 0.5);
&>view {
color: #39ac4f;
font-size: 60rpx;
}
&>.text {
color: #999999;
display: block;
font-size: 28rpx;
margin-top: 8px;
}
::v-deep.u-badge {
position: absolute;
right: 3px;
top: 3px;
}
}
.click {
background-color: #39ac4f !important;
&>view {
color: #fff;
}
&>.text {
color: #fff;
}
::v-deep.u-badge {
background-color: #ffffff !important;
color: #39ac4f;
}
}
}
}
.card {
::v-deep.u-cell__body {
padding: 10px;
}
::v-deep.u-collapse-item__content__text {
padding: 10px 10px 0;
.u-collapse-content {
.u-row {
margin-bottom: 10px;
}
.btn.v-btn {
width: 80px;
}
.btn.v-btn2 {
font-size: 12px;
width: 90px;
}
.buttons .load-text {
font-size: 12px;
}
}
}
.u-button {
margin: 0 0 0 5px;
}
.jz-title {
.icon {
vertical-align: top;
margin-right: 5px;
font-size: 44rpx;
color: #39ac4f;
}
text {
font-size: 32rpx;
}
// .icon-xh.xh_green {
// color: #39ac4f
// }
// .icon-xh.xh_red {
// color: #e60012
// }
}
.sf-title {
font-size: 24rpx;
color: #999999;
.text {
font-size: 32rpx;
color: #333;
}
.icon {
vertical-align: top;
margin-right: 5px;
font-size: 44rpx;
color: #39ac4f;
}
}
}
}
// 信号
.signal {
position: relative;
display: flex;
align-items: flex-end;
height: 17px;
.bar {
width: 2px;
background-color: #999;
border-radius: 2px;
margin-right: 2px;
}
.bar:nth-child(1) {
height: 4px;
}
.bar:nth-child(2) {
height: 7px;
}
.bar:nth-child(3) {
height: 10px;
}
.bar:nth-child(4) {
height: 13px;
}
.bar:nth-child(5) {
height: 16px;
}
.bar.red {
background-color: #e60012;
}
.bar.orange {
background-color: #ffa200;
}
.bar.green {
background-color: #39ac4f;
}
.bar-no {
position: absolute;
left: -2px;
bottom: 3px;
::v-deep.u-icon__icon {
font-weight: bold;
font-size: 18rpx !important;
}
}
}
// 电池
.battery-container {
margin: 0 0 0 10px;
position: relative;
width: 31px;
height: 16px;
line-height: 14px;
background-color: #fff;
border-radius: 3px;
border: 1px solid #333;
text-align: center;
text {
position: relative;
z-index: 2;
}
}
.battery-container::after {
content: "";
position: absolute;
top: 4px;
right: -2px;
width: 1px;
height: 5px;
background-color: #333;
border-radius: 4px;
}
.battery-level {
height: 12px;
position: absolute;
top: 1px;
bottom: 0;
left: 1px;
width: 90%;
max-width: 90%;
background-color: #4CAF50;
border-radius: 2px;
transition: width 0.5s;
}
.font-green {
color: #39ac4f !important;
}
.font-red {
color: #e60012 !important;
}
</style>