iot-ui-app/pages/iots/device/device-detail.vue

1185 lines
31 KiB
Vue
Raw 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>
<view class="device-detail-box">
<view class="menu-list">
<view class="menu-item" @click="goDeviceAbility">
<view class="iconfont icon-appstore"></view>
<view class="menu-txt">
设备功能
</view>
</view>
<view class="menu-item" @click="goDeviceAlarm">
<view class="iconfont icon-bell"></view>
<view class="menu-txt">
设备报警
</view>
</view>
</view>
<view class="device-title-box">
<view class="title-box-left">
<view class="title-txt" @click="openDeviceModel">
<text>{{deviceName}}</text>
<text class="title-name-detail">详情</text>
</view>
<view class="time-txt">
{{deviceTime?deviceTime:''}}
</view>
</view>
<view v-if="wsStatus" class="title-right color-blue" @click="refreshSocket">
<view class="iconfont icon-reload"></view>点击刷新
</view>
<view v-else class="title-right color-red" @click="refreshSocket">
<view class="iconfont icon-disconnect"></view>点击重连
</view>
<!-- <view class="title-right" @click="refreshSocket">
<view class="iconfont icon-reload"></view>{{wsStatus?'刷新':'已断连'}}
</view> -->
</view>
<view class="group-list">
<view class="group-list-label">
属性分组:
</view>
<uni-data-select
style="min-width: 200rpx;max-width: 500rpx;"
v-model="selectGroup"
:localdata="groupList"
:clear="false"
@change="changeGroup"
></uni-data-select>
</view>
<view class="attr-list">
<view class="attr-list-item" v-for="(item,index) in dataList" :key="index">
<!-- 选择器 -->
<iots-select
v-if="item.viewType == 'select'"
:disabled="true"
:name="item.name"
v-model="item.value"
:selectList="item.ioObj.enums"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-select>
<!-- 时间选择器 -->
<iots-select-time
v-else-if="item.viewType == 'text' && item.formType == 'time_picker'"
:disabled="true"
:name="item.name"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-select-time>
<!-- 颜色选择 -->
<iots-color-select
v-else-if="item.viewType == 'color-select'"
:name="item.name"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-color-select>
<!-- 开关 -->
<iots-switch
v-else-if="item.viewType == 'switch'"
:name="item.name"
:disabled="true"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-switch>
<!-- 开关按钮 -->
<iots-switch-btn
v-else-if="item.viewType == 'switch-btn'"
:name="item.name"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-switch-btn>
<!-- 滑块 -->
<iots-slider
v-else-if="item.viewType == 'slider'"
:disabled="true"
:name="item.name"
:min="parseFloat(item.ioObj.IoDeployForm.min || 0)"
:max="parseFloat(item.ioObj.IoDeployForm.max || 100)"
:step="parseFloat(item.ioObj.IoDeployForm.step || 1)"
:unit="item.ioObj.unit"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-slider>
<!-- 文字展示 -->
<!-- <iots-text
v-else-if="item.viewType == 'text'"
:name="item.name"
:value="getParseText(item.value)"
@clickLog="clickLog(index)"
></iots-text> -->
<!-- 柱状图 -->
<iots-bar
v-else-if="item.viewType == 'bar'"
:name="item.name"
:dataList="item.dataList"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-bar>
<!-- 折线图 -->
<iots-line
v-else-if="item.viewType == 'charts_line'"
:name="item.name"
:time="item.time"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-line>
<!-- 饼图 -->
<!-- <iots-pie
v-else-if="item.viewType == 'charts_pie'"
:name="item.name"
:dataList="item.dataList"
:value="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-pie> -->
<!-- 仪表盘 -->
<iots-gauge
v-else-if="item.viewType == 'charts_dashboard'"
:name="item.name"
:dataList="getChartData('charts_dashboard',item)"
v-model="item.value"
:min="parseFloat(item.ioObj.IoDeployForm.min || 0)"
:max="parseFloat(item.ioObj.IoDeployForm.max || 100)"
:unit="item.ioObj.unit"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-gauge>
<!-- 步进器 -->
<iots-number-box
v-else-if="item.viewType == 'text' && item.formType == 'number'"
:disabled="true"
:name="item.name"
:min="parseFloat(item.ioObj.IoDeployForm.min || 0)"
:max="parseFloat(item.ioObj.IoDeployForm.max || 100)"
:step="parseFloat(item.ioObj.IoDeployForm.step || 1)"
:unit="item.ioObj.unit"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-number-box>
<!-- 输入框 -->
<iots-input
v-else-if="item.viewType == 'text'"
:disabled="true"
:name="item.name"
v-model="item.value"
:unit="item.ioObj?item.ioObj.unit?item.ioObj.unit:'':''"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-input>
<iots-img
v-else-if="item.viewType == 'image'"
:disabled="true"
:name="item.name"
v-model="item.value"
@change="downData($event,index)"
@clickLog="clickLog(index)"
></iots-img>
<view v-else class="attr-item">
<view class="attr-item-left">
<view class="iconfont" :class="item.icon?item.icon:'icon-file-unknown2'"></view>
<view class="attr-name">{{item.name}}</view>
<view class="iconfont icon-unordered-list" @click="clickLog(index)"></view>
</view>
<view class="attr-item-right">
<view class="">
<!-- 未适配属性 -->
</view>
<!-- <view v-if="item.viewType == 'img'" class="attr-value item-border item-img-box" >
<u-upload ref="uPloadimgRef" width="120" height="120" :action="imgUploadUrl" :file-list="imgList" max-count="1" @on-change="changeUploadImg"></u-upload>
<view class="iconfont icon-xiangyou1"></view>
</view> -->
</view>
</view>
</view>
<view v-if="dataList.length == 0" class="attr-empty">
<u-empty text="设备属性为空,请添加属性" src="setting"></u-empty>
</view>
<!-- 数据日志 -->
<!-- <view class="iconfont icon-shuaxin" @click="resetLog"></view> -->
<!-- <view class="attr-value item-border item-log">
<view class="item-log-header">
<text class="item-log-header-label">数据日志</text>
<view class="item-log-header-right">
<view class="iconfont icon-shanchu" @click="clearLog"></view>
</view>
</view>
<scroll-view scroll-y="true" :scroll-top="scrollTop" class="item-log-box" :scroll-with-animation="true">
<view id="scroll-view-content">
<view class="log-item" v-for="(logItem,index) in logList" :key="index">
<view v-if="logItem.type == 'up'" class="iconfont icon-arrow-up color-red"></view>
<view v-else class="iconfont icon-arrow-down color-green"></view>
<view class="log-item-content">
<text class="log-item-time">
{{logItem.time}}
</text>
<text class="log-item-txt">
{{logItem.txt}}
</text>
</view>
</view>
<view v-if="logList.length==0" class="log-item">
数据日志监听中···
</view>
</view>
</scroll-view>
</view> -->
<view class="btn-box" @click="goDeviceControl">
<button>设备控制</button>
</view>
</view>
<!-- <u-select mode="single-column" :default-value="selectDefaultValue" v-model="selectShow" :list="selectList" @confirm="confirm"></u-select>
<u-popup v-model="colorShow" closeable="true" mode="bottom" border-radius="10" safe-area-inset-bottom="true">
<view class="">
<view class="" style="display: flex;justify-content: center;align-items: center;height: 40rpx;margin: 24rpx 0;font-weight: bold;font-size: 34rpx;">
选择颜色
</view>
<zebra-color-picker v-model="colors" @input="inputColor"></zebra-color-picker>
</view>
</u-popup> -->
<u-modal v-model="detailShow" title="设备详情" :mask-close-able="true">
<view class="detail-model">
<view class="content-item">
<view class="item-label">
设备ID
</view>
<view class="item-value">
{{deviceInfo.devId}}
</view>
</view>
<view class="content-item">
<view class="item-label">
设备名称:
</view>
<view class="item-value">
{{deviceInfo.devName}}
</view>
</view>
<view class="content-item">
<view class="item-label">
产品名称:
</view>
<view class="item-value">
{{deviceInfo.product.prodName}}
</view>
</view>
<view class="content-item">
<view class="item-label">
设备类型:
</view>
<view class="item-value">
{{getDeviceTypeName('deviceType',deviceInfo.product.prodType)}}
</view>
</view>
<view class="content-item">
<view class="item-label">
在线状态:
</view>
<view class="item-value" :style="{color:deviceInfo.devState==1?'#10CC70':deviceInfo.devState==2?'#FF2B38':'#999999'}">
{{getDeviceTypeName('deviceStatus',deviceInfo.devState)}}
</view>
</view>
<view class="content-item">
<view class="item-label">
创建时间:
</view>
<view class="item-value">
{{deviceInfo.createdAt}}
</view>
</view>
<view class="content-item">
<view class="item-label">
激活时间:
</view>
<view class="item-value">
{{deviceInfo.activateTime}}
</view>
</view>
<view class="content-item">
<view class="item-label">
最后上线时间:
</view>
<view class="item-value">
{{deviceInfo.lastOnlineTime}}
</view>
</view>
</view>
</u-modal>
</view>
</template>
<script>
import IotsSelect from '@/components/iot-components/select/iots-select.vue'
import IotsNumberBox from "@/components/iot-components/number-box/iots-number-box.vue"
import IotsColorSelect from "@/components/iot-components/color/iots-color-select.vue"
import IotsSwitch from '@/components/iot-components/switch/iots-switch.vue'
import IotsSlider from '@/components/iot-components/slider/iots-slider.vue'
import IotsSwitchBtn from '@/components/iot-components/switch-btn/iots-switch-btn.vue'
import IotsText from '@/components/iot-components/text/iots-text.vue'
import IotsBar from '@/components/iot-components/chart/bar/iots-bar.vue'
import IotsLine from '@/components/iot-components/chart/line/iots-line.vue'
import IotsPie from '@/components/iot-components/chart/pie/iots-pie.vue'
import IotsGauge from '@/components/iot-components/chart/gauge/iots-gauge.vue'
import IotsInput from '@/components/iot-components/input/iots-input.vue'
import IotsSelectTime from '@/components/iot-components/select-time/iots-select-time.vue'
import IotsImg from '@/components/iot-components/img/iots-img.vue'
import uniDataSelect from "@/components/iot-components/uni-data-select/uni-data-select.vue"
export default{
data(){
return{
wsUrl:null,
socketTask: null,
wsStatus:false,
deviceId:null,
deviceName:null,
deviceTime:null,
deviceInfo:{
devId:'',
devName:'',
devState:'',
createdAt:'',
activateTime:'',
lastOnlineTime:'',
token:'',
tokenTs:'',
pk:'',
product:{
prodName:'',
prodType:'',
},
},
scrollTop:0,
selectGroup:0,
// 属性分组
groupList:[{
value:0,
label:'全部',
groupKey:'all',
groupName:'全部',
groupRel:[]
}],
// 全部设备属性用于属性分组(不变)
dataAllData:[],
// 设备属性用于属性分组后数据(会变)
dataList:[],
dataIndex: 0,
// 设备功能
abilityList:[],
selectShow: false,
selectList: [{
value: '0',
label: '正常'
},
{
value: '1',
label: '异常'
}
],
selectDefaultValue:[0],
selectIndex: 0,
selectItemIndex: 0,
imgUploadUrl: 'http://www.example.com/upload',
imgList: [],
logList:[],
colors:{
hex: '#7ED321'
},
colorShow:false,
detailShow:false,
deviceTypeList:[
{
label: '直连设备',
value: 'dev',
},
{
label: '网关子设备',
value: 'childrenDevice',
},
{
label: '网关设备',
value: 'gateway',
}
],
deviceStatusList:[
{
label: '未激活',
value: 0
},
{
label: '在线',
value: 1,
},
{
label: '离线',
value: 2,
}
],
}
},
components: {
IotsSelect,
IotsSelectTime,
IotsNumberBox,
IotsColorSelect,
IotsSwitch,
IotsSlider,
IotsSwitchBtn,
IotsText,
IotsBar,
IotsLine,
IotsPie,
IotsGauge,
IotsInput,
IotsImg,
uniDataSelect
},
onLoad(option) {
console.log("option",option)
this.deviceId = option.id;
this.deviceName = option.devName;
if(option.devName){
// 修改页面标题
uni.setNavigationBarTitle({
title: option.devName
});
}
this.getDeviceInfo(option.id);
// this.logList = logList;
let configList = uni.getStorageSync('configList');
let configIndex = uni.getStorageSync('configIndex');
this.wsUrl = (configList[configIndex].protocol == 'http://' ?'ws://':'wss://' ) + configList[configIndex].address
},
// 关闭websocket【必须在实例销毁之前关闭,否则会是underfined错误】
beforeDestroy() {
this.closeSocket();
},
watch:{
logList(){
this.scrollToBottom();
}
},
methods:{
goDeviceControl(){
console.log("设备值",this.dataList);
let dataList = encodeURIComponent(JSON.stringify(this.dataList).replace(/%/g, '%25'))
uni.navigateTo({
url:'./device-control?dataList=' + dataList + '&devId=' + this.deviceInfo.devId + '&pk=' + this.deviceInfo.pk + '&devName=' + this.deviceInfo.devName
})
},
// 选择分组
changeGroup(e){
if(e != 0){
const identifierMap = new Map();
this.dataAllData.forEach(val => {
identifierMap.set(val.identifier, val);
});
const attrArr = this.groupList[e].groupRel.map(item => identifierMap.get(item.ioRelKey));
this.dataList = attrArr;
}else{
this.dataList = this.dataAllData;
}
},
getChartData(type,data){
if(type == 'charts_dashboard'){
let min = 0;
let max = 100;
if(data.ioObj.IoDeployForm.min != undefined){
min = parseFloat(data.ioObj.IoDeployForm.min);
}
if(data.ioObj.IoDeployForm.max != undefined){
max = parseFloat(data.ioObj.IoDeployForm.max);
}
let percentage = (data.value/(max - min)).toFixed(2);
return {series: [{name: data.name,data: percentage}]}
}
},
getDeviceTypeName(type,key){
// console.log("getDeviceTypeName",type,key)
let label = '';
if(type == 'deviceType'){
this.deviceTypeList.forEach(item=>{
if(key === item.value){
label = item.label;
}
})
}else if(type == 'deviceStatus'){
this.deviceStatusList.forEach(item=>{
if(key == item.value){
label = item.label;
}
})
}
return label;
},
getDeviceInfo(deviceId){
this.$api.iotsApi.getDeviceInfo({id:deviceId}).then(res => {
console.log("获取设备详情",res)
if(res.code == 0 && res.data){
this.deviceInfo = res.data;
if(res.data.product.thingModel){
let thingModel = JSON.parse(res.data.product.thingModel);
if(thingModel.contents.prop.length){
this.dataList = thingModel.contents.prop.map(item=>{
if(item.dataType=='int'){
if(item.ioObj.IoDeployForm.min!=undefined){
item.value = parseFloat(item.ioObj.IoDeployForm.min);
}else{
item.ioObj.IoDeployForm.min = 0;
item.value = 0;
}
}else if(item.viewType == 'slider' || item.viewType == 'charts_dashboard' || (item.viewType == 'text' && item.formType == 'number')){
console.log("item.ioObj.IoDeployForm.min",item.ioObj);
if(item.ioObj && item.ioObj.IoDeployForm && item.ioObj.IoDeployForm.min!=undefined && item.ioObj.IoDeployForm.min!= null){
item.value = parseFloat(item.ioObj.IoDeployForm.min);
}else{
// 确保ioObj对象存在于item内
if (!item.ioObj) {
item.ioObj = {};
}
// 确保IoDeployForm对象存在于item.ioObj内
if (!item.ioObj.IoDeployForm) {
item.ioObj.IoDeployForm = {};
}
// 现在可以安全地给min赋值
item.ioObj.IoDeployForm.min = 0;
if(item.ioObj.IoDeployForm.max == undefined){
item.ioObj.IoDeployForm.max = 100;
}
item.value = 0;
}
}else{
item.value = '';
}
item.time = 0;
return item;
})
this.dataAllData = this.dataList;
}else{
this.dataList = [];
this.dataAllData = [];
}
if(thingModel.contents.groups.length){
let groupList = [{
value:0,
label:'全部',
groupKey:'all',
groupName:'全部',
ioRelKey:[]
}];
thingModel.contents.groups.forEach((item,index)=>{
groupList.push({
value:index+1,
label:item.groupName,
...item
})
})
this.groupList = groupList;
// this.$nextTick(()=>{
// this.$set(this,'groupList',groupList)
// })
}else{
this.groupList = [{
value:0,
label:'全部',
groupKey:'all',
groupName:'全部',
ioRelKey:[]
}];
}
if(thingModel.contents.server.length){
this.abilityList = thingModel.contents.server;
}else{
this.abilityList = [];
}
if(thingModel.contents.server.length){
this.abilityList = thingModel.contents.server;
}else{
this.abilityList = [];
}
console.log("属性列表",this.dataList)
this.connectSocketInit()
}else{
this.$u.toast('获取设备属性失败');
}
}else{
this.$u.toast(res.message);
}
}, error => {
})
},
openDeviceModel(){
this.detailShow = true;
},
goDeviceAbility(){
let abilityList = encodeURIComponent(JSON.stringify(this.abilityList))
uni.navigateTo({
url:'./device-ability-list?abilityList=' + abilityList + '&deviceName=' + this.deviceName + '&devId=' + this.deviceInfo.devId + '&pk=' + this.deviceInfo.pk
})
},
goDeviceAlarm(){
// this.$u.toast('功能未完成')
uni.navigateTo({
url:'/pages/iots/notice/list?devId=' + this.deviceInfo.devId + '&devName=' + this.deviceName
})
},
clickLog(index){
console.log("当前点击日志",this.dataList[index]);
let obj = this.dataList[index];
let devState = this.getDeviceTypeName('deviceStatus',this.deviceInfo.devState);
uni.navigateTo({
url:'./device-data?devId=' + this.deviceInfo.devId + '&devName=' + this.deviceInfo.devName + '&devState=' + devState + '&fields=' + obj.identifier
})
// h5 页不刷新
// #ifdef H5
location.reload()
// #endif
},
downData(e,index){
let params = {
ac:'write',
d:this.deviceInfo.devId,
pk:this.deviceInfo.pk,
p:{
[this.dataList[index].identifier]:e
}
}
console.log("下发数据JSON",params)
// this.addLog('down',params);
this.$api.iotsApi.downDeviceProp(params).then(res => {
console.log("下发数据成功",res)
if(res.code !=0){
this.$u.toast(res.message)
}
}, error => {
})
},
// 解析显示字段
getParseText(e){
// let textList = [];
// try {
// if(e){
// textList = JSON.parse(e)
// return textList;
// }else{
// return textList;
// }
// } catch (error) {
// // 捕获异常并处理
// console.log("文字列表解析失败" + error.message);
// return textList;
// }
return [{"name":"今日用电","value":e,"unit":""}];
},
// 格式化select数据
formatSelect(value, index){
// 先格式化数据
let reg = /\\/g;
let str = value.funObj.replace(reg, '');
let obj = JSON.parse(str)
let selectList = [];
for (let i in obj) {
var obj1 = {
value: i,
label: obj[i]
}
selectList.push(obj1)
}
return selectList;
},
// 颜色选择变化
inputColor(color){
console.log("当前选择颜色为",color)
},
// 样式转换
getVlaue(value) {
let reg = /\\/g;
let str = value.funObj.replace(reg, '');
let obj = JSON.parse(str)
if (value.funDataType == 'TEXT') {
return value.lastValue;
}else {
return obj[value.lastValue];
}
},
// 点击选择框
changeSelect(value, index) {
this.selectIndex = index;
// 先格式化数据
let reg = /\\/g;
let str = value.funObj.replace(reg, '');;
let obj = JSON.parse(str)
this.selectList = [];
for (let i in obj) {
var obj1 = {
value: i,
label: obj[i]
}
this.selectList.push(obj1)
}
this.selectShow = true;
// console.log("格式化之后的数据",this.selectList)
},
// 选择完成
confirm(e) {
if(this.dataList[this.selectIndex].funDataType=="TEXT"){
this.$nextTick(() => {
this.dataList[this.selectIndex].lastValue = e[0].label;
this.selectDefaultValue = [this.selectList.findIndex(item => item.value === e[0].value)] || [0];
})
}else{
this.$nextTick(() => {
this.dataList[this.selectIndex].lastValue = e[0].value;
this.selectDefaultValue = [this.selectList.findIndex(item => item.value === e[0].value)] || [0];
})
}
},
// 点击步进器
changeNumber(e, index) {
this.dataList[index].lastValue = e;
},
// 上传图片完成
changeUploadImg(e){
console.log("上传图片",e);
},
upLoadImg(){
this.$refs.uPloadimgRef.upload();
},
scrollToBottom(){
this.$nextTick(()=>{
uni.createSelectorQuery().in(this).select('#scroll-view-content').boundingClientRect((res)=>{
if(res){
let top = res.height-195;
if(top>0){
this.scrollTop=top;
}
}
}).exec()
})
},
// 添加日志
addLog(type,txt){
this.logList.push({
id:this.$u.guid(20),
time:this.$u.timeFormat(new Date(), 'hh:MM:ss'),
type,
txt:JSON.stringify(txt),
})
},
// 刷新数据日志
resetLog(){
this.logList = logList;
},
// 清理日志
clearLog(){
this.logList=[]
},
refresh(){
console.log("点击刷新")
},
// 进入这个页面的时候创建websocket连接【整个页面随时使用】
connectSocketInit() {
// let ip = uni.getStorageSync('ipAddress');
// 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】
this.socketTask = uni.connectSocket({
// 【非常重要】必须确保你的服务器是成功的,如果是手机测试千万别使用ws://127.0.0.1:9099【特别容易犯的错误】
url: this.wsUrl + '/iot/device/ws/prop/' + this.deviceInfo.devId + '/' + this
.deviceInfo.token + '?ts=' + this.deviceInfo.tokenTs,
success(data) {
console.log("websocket连接成功", data);
},
});
// 消息的发送和接收必须在正常连接打开中,才能发送或接收【否则会失败】
this.socketTask.onOpen((res) => {
console.log("WebSocket连接正常打开中...");
this.wsStatus = true;
// 注:只有连接正常打开中 ,才能正常成功发送消息
// this.socketTask.send({
// data: "uni-app发送一条消息",
// async success() {
// console.log("消息发送成功");
// },
// });
// 注:只有连接正常打开中 ,才能正常收到消息
this.socketTask.onMessage((res) => {
console.log("收到服务器内容:" + res.data);
let obj = JSON.parse(res.data)
// this.addLog('up',obj);
this.deviceTime = this.$u.timeFormat(obj.fg_device_ts, 'yyyy-mm-dd hh:MM:ss');
if (obj) {
let dataList = JSON.parse(JSON.stringify(this.dataList));
// 这是连接的第一次获取,虽然进页面已经获取一次最新数据,但是可能存在断开之后的请求,所以需要遍历覆盖
for (let i = 0; i < dataList.length; i++) {
for (let key in obj) {
if (key == dataList[i].identifier) {
if(dataList[i].viewType == 'slider' || (dataList[i].viewType == 'text' && dataList[i].formType == 'number')){
dataList[i].value = parseFloat(obj[key]);
}else{
dataList[i].value = obj[key];
}
dataList[i].time = obj.fg_device_ts;
break;
}
}
}
this.$nextTick(()=>{
this.$set(this,'dataList',dataList)
this.$forceUpdate()
})
}
});
})
// 这里仅是事件监听【如果socket关闭了会执行】
this.socketTask.onClose(() => {
this.wsStatus = false;
console.log("已经被关闭了")
})
},
// 关闭websocket【离开这个页面的时候执行关闭】
closeSocket() {
let that = this;
if(this.wsStatus){
this.socketTask.close({
success(res) {
that.wsStatus = false;
console.log("关闭成功", res)
},
fail(err) {
console.log("关闭失败", err)
}
})
}
},
refreshSocket(){
if(this.wsStatus){
this.closeSocket();
setTimeout(()=>{
this.connectSocketInit();
},500)
}else if(this.dataList.length == 0){
this.$u.toast('设备属性为空,无法刷新')
}else{
this.connectSocketInit();
}
}
}
}
</script>
<style>
page{
background: #f5f5f5;
}
</style>
<style lang="scss" scoped>
.device-detail-box{
padding-bottom: 160rpx;
}
.menu-list{
display: flex;
.menu-item{
flex: 1;
margin: 20rpx;
background-color: #fff;
border-radius: 20rpx;
height: 130rpx;
display: flex;
align-items: center;
justify-content: space-around;
padding: 0 30rpx;
box-shadow: 0px 0px 15rpx 0px rgba(201,201,201,0.4);
.iconfont{
font-size: 60rpx;
background-image: -webkit-linear-gradient(90deg, #3BBCFF, #006CFF);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.menu-txt{
font-size: 46rpx;
font-family: Georgia, 'Times New Roman', Times, serif;
font-weight: bold;
}
}
}
.attr-empty{
margin: 20rpx 0;
background-color: #fff;
border-radius: 20rpx;
padding: 250rpx 0;
}
.device-title-box{
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 20rpx;
padding: 20rpx;
background-color: #fff;
border-radius: 20rpx;
.title-box-left{
.title-txt{
font-size: 30rpx;
font-weight: bold;
margin-bottom: 10rpx;
display: flex;
align-items: center;
.title-name-detail{
padding: 4rpx 12rpx;
color: #006CFF;
border: 1px solid #006CFF;
border-radius: 10rpx;
font-size: 26rpx;
margin-left: 10rpx;
}
}
.time-txt{
font-size: 24rpx;
color: #999;
}
}
.title-right{
display: flex;
align-items: center;
font-size: 30rpx;
.iconfont{
margin-right: 10rpx;
}
}
}
.group-list{
display: flex;
// justify-content: space-between;
align-items: center;
margin: 0 20rpx;
margin-top: 20rpx;
padding: 20rpx;
background-color: #fff;
border-radius: 20rpx;
.group-list-label{
margin-right: 10rpx;
font-weight: bold;
}
}
// 设备详情弹窗
.detail-model{
padding: 30rpx;
.content-item{
display: flex;
align-items: center;
margin-top: 10rpx;
font-size: 28rpx;
.item-label{
margin-right: 10rpx;
}
}
}
.attr-list{
padding: 0 20rpx 30rpx 20rpx;
.attr-item{
padding: 20rpx 20rpx;
background: #fff;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 20rpx;
border-radius: 10rpx;
.attr-item-left{
display: flex;
align-items: center;
font-size: 28rpx;
color: #000;
.iconfont{
margin-right: 20rpx;
font-size: 40rpx;
}
.icon-unordered-list{
margin-left: 16rpx;
margin-right: 0rpx;
font-size: 36rpx;
color: #0b7bff;
}
}
.attr-item-right{
flex: 1;
// height: 70rpx;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
.attr-value{
display: flex;
align-items: center;
justify-content: flex-end;
height: 70rpx;
flex: 1;
&.item-select {
padding: 0 20rpx;
display: flex;
align-items: center;
justify-content: flex-end;
color: #ccc;
.iconfont{
margin-left: 10rpx;
}
}
&.item-input{
// width: 250rpx;
// border: 1px solid #dcdfe6;
// border-radius: 8rpx;
// background: #fafafa;
input{
flex: 1;
height: 70rpx;
}
}
&.item-img-box{
height: 120rpx;
color: #ccc;
}
&.item-number{
flex: 0 1 auto;
width: 250rpx;
display: flex;
align-items: center;
justify-content: flex-end;
color: #ccc;
border: 1px solid #dcdfe6;
border-radius: 8rpx;
/deep/.number-box {
.minus {
border: none;
border-right: 1px solid #dcdfe6;
}
.plus {
border: none;
border-left: 1px solid #dcdfe6;
}
}
}
}
}
}
// 数据日志
.item-log{
background: #fff;
margin-top: 20rpx;
border-radius: 10rpx;
overflow: hidden;
.item-log-header{
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx;
line-height: 50rpx;
background: $mainColor;
color: #fff;
.item-log-header-right{
display: flex;
align-items: center;
.iconfont{
padding: 10rpx 15rpx;
// margin-left: 30rpx;
font-size: 30rpx;
}
}
}
.item-log-box{
height: 200px;
padding: 10rpx;
box-sizing: border-box;
.log-item{
position: relative;
margin-bottom: 10rpx;
// display: flex;
.iconfont{
position: absolute;
top:2rpx;
left:0;
font-weight: bold;
}
.log-item-content{
// display: inline-block;
padding-right: 10rpx;
word-wrap: break-word;
white-space: pre-line;
.log-item-time{
color: $mainColor;
margin: 0 10rpx 0 36rpx;
}
.log-item-txt{
}
}
}
}
}
}
/deep/ .u-add-btn{
display: none;
}
/deep/ .u-add-tips{
margin-top: 0 !important;
}
// 设置颜色选择器宽为100%
/deep/ .zebra-chrome{
width: 100%;
}
.color-red{
color: red;
}
.color-green{
color: green;
}
.color-blue{
color: #006CFF;
}
.btn-box{
display: flex;
align-items: center;
justify-content: center;
background: #fff;
height: 140rpx;
padding-bottom: 10rpx;
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
button{
width: 690rpx;
height: 90rpx;
background: #3683FD;
border-radius: 43rpx;
font-size: 32rpx;
color: #FFFFFF;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>