智能照明系统APP-本地串口
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
LightingSystemApp-serial/.svn/pristine/f9/f9ec48790b0b1dfcf57ff55f0d6...

972 lines
22 KiB

<template>
<view class="page">
<u-navbar back-icon-name="list-dot" back-text="项目概览" :custom-back="menu" />
<view class="content">
<view class="productInfo" style="padding-left: 0">
<view>
<view class="imgBox">
<image v-if = "deviceimgurl != ''" :src="deviceimgurl" class="img"/>
<view v-else class="img">暂无图片</view>
</view>
</view>
<view>
<view class="product-title">{{ product.text }}</view>
<view>项目名称:{{ product.text }}</view>
<view>
监控网关:
<view class="deviceBtn" @tap="showDevice = true">
<view>{{ device.text }}</view>
<u-icon name="arrow-right" />
</view>
<text style="color: #4e73df">{{ device.online }}</text>
</view>
<view>
创建时间:
{{ product.createtime }}
</view>
</view>
</view>
<view>
<view class="charts-title">
<text class="left">项目设备统计</text>
<text class="right" v-if="statistics !== undefined">
设备总数:{{
statistics.n_switch1 +
statistics.n_lamp1 +
statistics.n_sensor1 +
statistics.f_switch1 +
statistics.f_lamp1 +
statistics.f_sensor1
}}
</text>
</view>
<canvas
v-if="statistics !== undefined"
canvas-id="statisticsCharts"
class="charts"
@touchstart="touchCharts(0, $event)"
/>
<u-empty v-else class="charts" />
</view>
<view style="padding-right: 0">
<view class="charts-title">
<text class="left">项目运行情况</text>
</view>
<view class="operationCharts" v-if="operation !== undefined">
<canvas canvas-id="operationCharts" class="charts" @touchstart="touchCharts(1, $event)" />
<view>
<view>
<view class="dot" style="background-color: #55ff00" />
通信正常 ({{ operation.normal2 }}个)
</view>
<view>
<view class="dot" style="background-color: #37b9cc" />
通信失联 ({{ operation.miss2 }}个)
</view>
<view>
<view class="dot" style="background-color: #f7c23f" />
灯具故障 ({{ operation.lampfault2 }}个)
</view>
<view>
<view class="dot" style="background-color: #ec6a56" />
回路故障 ({{ operation.loopfault2 }}个)
</view>
<view>
<view class="dot" style="background-color: #4e73df" />
其他 ({{ operation.otherfault2 }}个)
</view>
</view>
</view>
<u-empty v-else class="charts" style="padding-right: 20rpx" />
</view>
<view>
<view class="charts-title">
<text class="left">光照度变化情况</text>
</view>
<canvas
v-if="illuminanceList.length > 0"
canvas-id="illuminanceCharts"
class="charts"
@touchstart="touch"
@touchmove="move"
@touchend="touchEnd"
/>
<u-empty v-else class="charts" />
</view>
</view>
<view class="placeholder" />
<view class="tabBar">
<view class="tabBar-item" @tap="tapTabBar(0)">
<u-image width="60" height="60" src="@/static/img/tabBar/energy.png" :show-loading="false" />
<view>能效分析</view>
</view>
<view class="tabBar-item" @tap="tapTabBar(1)">
<u-image
width="60"
height="60"
src="@/static/img/tabBar/control.png"
:show-loading="false"
/>
<view>设备管控</view>
</view>
<view class="tabBar-item" @tap="tapTabBar(2)">
<u-image
width="60"
height="60"
src="@/static/img/tabBar/faultlog.png"
:show-loading="false"
/>
<view>故障日志</view>
</view>
<view class="tabBar-item" @tap="tapTabBar(3)">
<u-image
width="60"
height="60"
src="@/static/img/tabBar/maintenance.png"
:show-loading="false"
/>
<view>设备维护</view>
</view>
</view>
<u-popup v-model="showProduct" class="popup" width="66%">
<view class="popup-header">
<text>项目列表</text>
</view>
<scroll-view scroll-y="true" class="popup-content">
<view
v-for="item in productList"
:key="item.prodid"
class="item"
@tap="switchProduct(item)"
>
<u-image :src="item.prod_img_url || 'fake'" width="48" height="48" border-radius="4">
<u-loading slot="loading" mode="flower" />
<u-image
slot="error"
src="@/static/img/default.png"
width="48"
height="48"
border-radius="4"
/>
</u-image>
{{ item.text }}
</view>
</scroll-view>
<view class="popup-footer">
<u-image :src="myprofile.head_img_url || 'fake'" width="180" height="180" shape="circle">
<u-loading slot="loading" mode="flower" />
<u-image
slot="error"
src="@/static/img/default.png"
width="180"
height="180"
shape="circle"
/>
</u-image>
<u-button
class="logout"
size="medium"
shape="circle"
:hair-line="false"
plain
@click="logout"
>退出登录</u-button>
</view>
</u-popup>
<u-modal
v-model="showDevice"
:show-title="false"
confirm-text="确定"
confirm-color="#4E73DF"
cancel-color="#4E73DF"
show-cancel-button
@confirm="confirm"
@cancel="cancel"
>
<view class="model-title">
<text>选择监控网关</text>
</view>
<picker-view
v-if="deviceList.length > 0"
class="switchDevice"
indicator-class="indicator"
:value="deviceIndex"
@change="deviceIndexChange"
>
<picker-view-column>
<view v-for="item in deviceList" :key="item.deviceid">
{{
item.text
}}
</view>
</picker-view-column>
</picker-view>
<view v-else class="undefined">请先添加网关</view>
</u-modal>
<u-modal
v-model="showMask"
:show-title="false"
content="还未添加项目"
confirm-text="去添加"
@confirm="toProduct"
/>
<u-toast ref="uToast" />
</view>
</template>
<script>
import { getProductAll } from "@/common/network/equipment/product";
import {
getDeviceAll,
getDeviceStatus,
} from "@/common/network/equipment/device";
import {
getDeviceInfoEchart,
getDeviceErrorEchart,
getDeviceImg,
getIlluminanceinfoEchart,
} from "@/common/network/equipment/device";
import uCharts from "@/components/u-charts/u-charts";
export default {
data() {
return {
showMask: false,
intervalID: {
getDeviceStatus: undefined,
getIlluminanceList: undefined,
},
showProduct: false,
showDevice: false,
myprofile: {},
product: {},
productList: [],
deviceIndex: [0],
device: {},
deviceList: [],
statistics: {},
operation: {},
illuminanceList: [],
charts: [{}, {}, {}],
deviceimgurl:'',
};
},
created() {},
mounted() {},
methods: {
getDeviceImg(data){
var that=this;
getDeviceImg(data)
.then((res) => {
if(res.successed == true){
that.deviceimgurl = res.data.url;
}
else{
that.deviceimgurl = '';
}
})
},
getProductAll() {
var that=this;
getProductAll()
.then((res) => {
if (res.data.totalCount > 0) {
that.productList = res.data.list;
let change = true;
for (let item of res.data.list) {
if (that.product.value === item.value) {
that.product = item;
change = false;
break;
}
}
if (change) {
that.product = res.data.list[0];
}
that.getDeviceAll(that.product);
} else {
that.showMask = true;
}
})
},
getDeviceAll(data) {
var that=this;
this.device = {};
this.deviceList = [];
getDeviceAll(data.text)
.then((res) => {
if (res.data.totalCount > 0) {
that.deviceList = res.data.list;
if (
that.device.deviceid === undefined ||
res.data.list[that.deviceIndex[0]] === undefined ||
that.device.deviceid !== res.data.list[that.deviceIndex[0]].value
) {
that.deviceIndex = [0];
that.device = res.data.list[0] || {
name: "还未添加网关",
online: "",
};
} else {getDeviceStatus
that.device = res.data.list[that.deviceIndex[0]];
}
if (that.deviceList.length > 0) {
that.deviceimgurl = ''
this.getDeviceImg(that.device.value);
this.getDeviceStatus(that.device.terminalId);
this.getechartvalue1(that.device.terminalId);
this.getechartvalue2(that.device.terminalId);
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24* 30 );
this.device.endtime = this.FormatDate(end, "yyyy-MM-dd")
this.device.starttime = this.FormatDate(start, "yyyy-MM-dd")
this.getechartvalue3(that.device);
} else {
that.statistics = undefined;
that.operation = undefined;
that.illuminanceList = [];
}
} else {
console.log(res);
}
})
.catch((err) => {
console.log(err);
});
},
getDeviceStatus(data) {
var that=this;
getDeviceStatus(data)
.then((res) => {
var data = res.data.entity[0];
if (data != '' || data != null) {
that.device.online = data.onlinestate ? "在线" : "离线";
} else {
console.log(data);
}
})
.catch((err) => {
console.log(err);
});
},
getechartvalue1(data){
this.statistics = {};
const _self = this;
getDeviceInfoEchart(data)
.then((res) => {
if(res.successed == true)
{
_self.statistics = res.data.entity;
_self.charts[0] = new uCharts({
$this: _self,
canvasId: "statisticsCharts",
type: "column",
colors: ["#4E73DF", "#EC6A56"],
padding: [0, 15, 4, 0],
legend: {
position: "top",
float: "right",
margin: 10,
},
categories: ["灯杆", "回路", "传感器"],
series: [
{
textSize: 9,
legendShape: "circle",
name: "正常",
data: [
_self.statistics.n_lamp1,
_self.statistics.n_switch1,
_self.statistics.n_sensor1,
],
},
{
textSize: 9,
legendShape: "circle",
name: "异常",
data: [
_self.statistics.f_lamp1,
_self.statistics.f_switch1,
_self.statistics.f_sensor1,
],
},
],
extra: { column: { width: 15 } },
xAxis: {
disableGrid: true,
fontSize: uni.upx2px(26),
},
yAxis: {
format:(val)=>{return val.toFixed(2)},
},
animation: true,
width: uni.upx2px(677),
height: 180,
});
}
})
.catch((err) => {
console.log(err);
});
},
getechartvalue2(data){
this.operation = {};
const _self = this;
getDeviceErrorEchart(data)
.then((res) => {
if(res.successed == true)
{
_self.operation = res.data.entity;
_self.operation.total2 = _self.operation.lampfault2 + _self.operation.normal2 + _self.operation.miss2 + _self.operation.loopfault2 + _self.operation.otherfault2;
_self.charts[1] = new uCharts({
$this: _self,
canvasId: "operationCharts",
type: "ring",
padding: [0, 0, 0, 0],
colors: ["#55ff00", "#37B9CC", "#F7C23F", "#EC6A56", "#4E73DF"],
title: {
name: _self.operation.total2,
fontSize: uni.upx2px(50),
},
subtitle: {
name: "共计",
color: "#AFB5CF",
fontSize: uni.upx2px(30),
offsetY: -3,
},
series: [
{
textSize: 12,
name: "通信正常",
data: _self.operation.normal2,
},
{
textSize: 12,
name: "通信失联",
data: _self.operation.miss2,
},
{
textSize: 12,
name: "灯具故障",
data: _self.operation.lampfault2,
},
{
textSize: 12,
name: "回路故障",
data: _self.operation.loopfault2,
},
{
textSize: 12,
name: "其他",
data: _self.operation.otherfault2,
},
],
legend: { show: false },
extra: { pie: { labelWidth: 5 } },
animation: true,
width: uni.upx2px(409),
height: 180,
});
}
})
},
getechartvalue3(data){
const _self = this;
getIlluminanceinfoEchart(data)
.then((res) => {
if(res.data.totalCount > 0)
{
_self.illuminanceList = res.data.list;
_self.charts[2] = new uCharts({
$this: _self,
canvasId: "illuminanceCharts",
type: "area",
enableScroll: true,
dataLabel: false,
dataPointShape: false,
padding: [15, 5, 0, 0],
colors: ["#4E73DF"],
legend: {
show: false,
},
categories: _self.illuminanceList.map((item) =>
//_self.$u.timeFormat(item.ts, "hh:MM")
item.time
),
series: [
{
data: _self.illuminanceList.map((item) => item.value),
name: "光照度",
}
],
animation: true,
xAxis: {
disableGrid: true,
itemCount: 20,
calibration:true,
labelCount:2,
margin: 20,//刻度标签与轴线之间的距离。
},
yAxis: {
gridType: 'dash',
format:(val)=>{return val.toFixed(2)}
},
width: uni.upx2px(677),
height: 170,
extra: {
area: {
type: "curve",
addLine: true,
width: 1,
opacity: 0.5,
gradient: true,
},
},
});
}
})
},
touchCharts(index, e) {
this.charts[index].showToolTip(e, {
format: function (item, category) {
return item.name + ":" + item.data;
},
});
},
touch(e) {
this.charts[2].scrollStart(e);
},
move(e) {
this.charts[2].scroll(e);
},
touchEnd(e) {
this.charts[2].scrollEnd(e);
this.touchCharts(2, e);
},
menu() {
this.showProduct = true;
},
tapTabBar(index) {
if (this.deviceList.length > 0) {
let url;
switch (index) {
case 0:
url = "/pages/energy/energy";
break;
case 1:
url = "/pages/control/control";
break;
case 2:
url = "/pages/faultlog/faultlog";
break;
case 3:
url = "/pages/maintenance/index/index";
break;
}
uni.setStorageSync("product", this.product);
uni.setStorageSync("device", this.device);
url =
url +
"?prodid=" +
this.product.text +
"&deviceid=" +
this.device.value +
"&terminalId=" +
this.device.terminalId;
uni.navigateTo({
url,
});
} else {
this.$refs.uToast.show({
title: "请先选择网关",
type: "warning",
});
}
},
toProduct() {
this.showProduct = false;
uni.navigateTo({
url: "/pages/product/index/index",
});
},
switchProduct(product) {
this.statistics = {};
this.operation = {};
this.illuminanceList = {};
this.product = product;
this.getDeviceAll(this.product);
this.showProduct = false;
},
deviceIndexChange(e) {
this.deviceIndex = e.detail.value;
this.getDeviceImg(this.deviceList[this.deviceIndex].value);
},
confirm() {
debugger
if((this.deviceList != null) && (this.deviceList != ''))
{
this.device = this.deviceList[this.deviceIndex[0]];
this.getDeviceStatus(this.device.terminalId);
this.getechartvalue1(this.device.terminalId);
this.getechartvalue2(this.device.terminalId);
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24* 30 );
this.device.endtime = this.FormatDate(end, "yyyy-MM-dd")
this.device.starttime = this.FormatDate(start, "yyyy-MM-dd")
this.getechartvalue3(this.device);
}
else
{
this.statistics = {};
this.operation = {};
this.illuminanceList = {};
}
//this.getStatistics();
//this.getOperation();
//this.getIlluminanceList();
},
cancel() {
for (let i in this.deviceList) {
if (this.device.deviceid === this.deviceList[i].deviceid) {
this.deviceIndex = [parseInt(i)];
return;
}
}
},
logout() {
clearInterval(this.intervalID.getDeviceStatus);
clearInterval(this.intervalID.getIlluminanceList);
this.intervalID.getDeviceStatus = null;
this.intervalID.getIlluminanceList = null;
uni.removeStorageSync("role");
uni.reLaunch({
url: "/pages/user/login/login",
});
},
},
onShow() {
if(JSON.stringify(this.product) == "{}")
{
this.getProductAll();
}
else{
this.product = uni.getStorageSync('product');
this.device = uni.getStorageSync("device");
}
if((this.intervalID.getDeviceStatus == null) && (this.device.terminalId != null) ){
this.intervalID.getDeviceStatus = setInterval(() => {
this.getDeviceStatus(this.device.terminalId);
}, 1000 * 30);
}
//this.intervalID.getIlluminanceList = setInterval(() => {
//this.getIlluminanceList();
//}, 1000 * 60 * 15);
},
onHide() {
clearInterval(this.intervalID.getDeviceStatus);
clearInterval(this.intervalID.getIlluminanceList);
this.intervalID.getDeviceStatus = null;
this.intervalID.getIlluminanceList = null;
},
};
</script>
<style scoped>
.page {
background: linear-gradient(
180deg,
rgba(235, 241, 255, 0.5) 0%,
#e4ebff 100%
);
}
.content > uni-view {
margin: 20px 10px;
padding: 10px;
background-color: #ffffff;
border-radius: 5px;
}
.productInfo {
display: flex;
align-items: center;
}
.productInfo > view:first-child {
width: 35%;
font-size: 16px;
text-align: center;
}
.productInfo .imgBox {
margin: 0 auto 10rpx;
position: relative;
width: 80%;
height: 0;
padding-top: 80%;
}
.productInfo .imgBox uni-image,
.productInfo .imgBox .img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 110%;
}
.productInfo .imgBox .img {
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
background-color: #ebeef5;
}
.productInfo .imgBox + * {
margin: 0 auto;
width: 80%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: bolder;
}
.productInfo > view:last-child {
width: 70%;
color: #8d92a6;
font-size: 28rpx;
line-height: 2em;
}
.product-title {
color: #121212;
font-size: 40rpx;
font-weight: bolder;
}
.deviceBtn {
display: inline-flex;
padding: 5rpx 5px;
margin-right: 5px;
color: #ffffff;
background-color: #a9b7ee;
border-radius: 15px;
}
.deviceBtn > uni-view:first-child {
display: inline-block;
max-width: 190rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.charts-title {
display: flex;
justify-content: space-between;
}
.charts-title > .left {
font-size: 30rpx;
font-weight: bolder;
}
.charts-title > .right {
color: #afb5cf;
}
.charts {
width: 100%;
height: 180px;
}
.operationCharts {
display: flex;
}
.operationCharts > uni-view {
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 20rpx;
width: 65%;
line-height: 2em;
}
.dot {
display: inline-block;
margin-right: 5px;
width: 0.7em;
height: 0.7em;
background-color: aqua;
border-radius: 100%;
}
.undefined {
margin: 40rpx 0;
color: #8d92a6;
text-align: center;
}
.placeholder {
height: 60px;
}
.tabBar {
width: 100%;
display: flex;
padding: 5px 0;
position: fixed;
left: 0;
right: 0;
bottom: 0;
color: #8d92a6;
text-align: center;
border-top: 1px solid #dcdfe6;
background-color: #ffffff;
}
.tabBar-item {
flex: 1;
font-size: 14rpx;
}
.tabBar-item > .u-image {
margin: 0 auto;
}
.popup >>> .u-drawer-left {
padding-top: var(--status-bar-height);
}
.popup >>> .uni-scroll-view-content {
display: flex;
flex-direction: column;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 32rpx;
height: 120rpx;
line-height: 120rpx;
background: rgba(78, 115, 223, 0.09);
}
.popup-header :first-child {
font-size: 36rpx;
font-weight: bold;
}
.popup-header > .u-btn {
margin: 0;
padding: 0 24rpx;
height: 2em;
font-size: 28rpx;
}
.popup-content {
flex: 1;
height: calc(100% - 544rpx);
}
.popup-content .item {
display: flex;
align-items: center;
margin-left: 32rpx;
margin-right: 44rpx;
height: 104rpx;
line-height: 104rpx;
font-size: 32rpx;
font-weight: bold;
border-bottom: 1px solid rgba(141, 146, 166, 0.1);
}
.popup-content .item > .u-image {
margin-right: 12rpx;
line-height: normal;
}
.popup-footer {
margin-top: 36rpx;
text-align: center;
}
.popup-footer > .u-image {
margin: 0 auto;
}
.logout {
width: 180rpx;
height: 56rpx;
margin-top: 36rpx;
margin-bottom: 72rpx;
color: #0082ff;
border-color: #0082ff;
font-size: 28rpx;
}
.model-title {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 28rpx;
height: 106rpx;
background: rgba(78, 115, 223, 0.09);
}
.model-title :first-child {
font-size: 36rpx;
font-weight: bold;
}
.model-title > .u-btn {
margin: 0;
padding: 0 24rpx;
height: 2em;
font-size: 28rpx;
}
.switchDevice {
height: 540rpx;
text-align: center;
font-size: 40rpx;
color: #5c70e3;
line-height: 120rpx;
}
.switchDevice >>> .indicator {
height: 120rpx;
}
</style>