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.
 
 
 
 
 

629 lines
25 KiB

<template>
<view class="switch-manage">
<store-name></store-name>
<view class="sm-tit">{{pageInfo.name || '-'}}</view>
<view class="sm-list">
<view class="sl-item" v-for="(e, i) in deviceList" :key="i" :style="{width:getViewWidth()}">
<view class="si-top" >
<image mode="aspectFit" :src="getIcon()" ></image>
<view class="st-right">
<view class="sr-name">{{e.hardware_name || '-'}}</view>
<!-- 门闸没有状态查询 -->
<!-- 请求接口自定义字段设备状态 1->在线,0->离线 -->
<view class="sr-bot-router" v-if="pageInfo.name =='物联卡管理'">
sim状态: <text>{{getLotStatus(e)}}</text>
</view>
<view class="sr-bot" v-else-if="pageInfo.id !=5">
<view :class="[e.defineStatusCode == 1?'active':'']">
<text>{{ e.defineStatusCode == 1 ? '设备在线' : e.defineStatusCode == 0?'设备离线' : '-' }}</text>
</view>
<image mode="aspectFit" src="/subpackage/device/static/images/refresh.png" @click="refreshStatusBtn({switchInfo:e, index:i})"></image>
</view>
</view>
</view>
<!-- 不同设备的可操作按钮区分,目前无明显规律,so 按需求单独 if 判断 -->
<view class="si-bottom" v-if="pageInfo.isOpen || pageInfo.isClose || pageInfo.isDetail||pageInfo.isTiming">
<view v-if="pageInfo.isOpen" @click="operateBtn({ switchInfo: e, status: 1 })" :style="{width:getIconWidth()}">
<image mode="aspectFit" :src="pageInfo.openIcon || ''"></image>
<view>{{pageInfo.openName || '-'}}</view>
</view>
<view v-if="pageInfo.isClose" @click="operateBtn({ switchInfo: e, status: 0 })" :style="{width:getIconWidth()}">
<image mode="aspectFit" :src="pageInfo.closeIcon || ''"></image>
<view>{{pageInfo.closeName || '-'}}</view>
</view>
<view v-if="pageInfo.isLongOpen" @click="operateBtn({ switchInfo: e, status: 2 })" :style="{width:getIconWidth()}">
<image mode="aspectFit" :src="pageInfo.longOpenIcon || ''"></image>
<view>{{pageInfo.longOpenName || '-'}}</view>
</view>
<view v-if="pageInfo.isTiming" @click="operateBtn({ switchInfo: e, status: 3 })" :style="{width:getIconWidth()}">
<image mode="aspectFit" :src="pageInfo.timingIcon || ''"></image>
<view>{{pageInfo.timingName || '-'}}</view>
</view>
<view v-if="pageInfo.isDetail" @click="operateBtn({ switchInfo: e, status: 4 })" class="btn-detail">
<view >{{pageInfo.detailName || '-'}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
// 门闸暂时没有查询状态
import store_name from '../../components/store_name/store_name';
import deviceServer from '../../js/device_server';
import deviceApi from '../../js/device_api';
const showArr = {
's1': {
id: 1, name: '照明管理', isOpen: true, isClose: true, isLongOpen:true, isTiming:true,
openIcon: '/subpackage/device/static/images/open.png',closeIcon: '/subpackage/device/static/images/close.png',
longOpenIcon: '/subpackage/device/static/images/longOpen.png',timingIcon: '/subpackage/device/static/images/timing.png',
openName: '开', closeName: '关', longOpenName: '长开', timingName: '定时', hardware_type: 'Light',iconNum:4
},
's2': {
id: 2, name: '空调管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关', hardware_type: 'Air',iconNum:2
},
's3': {
id: 3, name: '风扇管理', isOpen: true, isClose: true, isLongOpen:true, isTiming:true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
longOpenIcon: '/subpackage/device/static/images/longOpen.png',timingIcon: '/subpackage/device/static/images/timing.png',
openName: '开', closeName: '关', hardware_type: 'Fan',longOpenName: '长开', timingName: '定时',iconNum:4,
},
's4': {
id: 4, name: '门禁管理', isOpen: true, isClose: false,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关', hardware_type: 'AccessControl',iconNum:2
},
's5': {
id: 5, name: '门闸管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/in.png',
closeIcon: '/subpackage/device/static/images/out.png',
openName: '进', closeName: '出', hardware_type: 'GateControl',iconNum:2
},
's6': {//TODO 等待接口
id: 6, name: '平板管理', isOpen: false, isClose: false,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关', hardware_type: 'Router4G',iconNum:2
},
's11': {
id: 11, name: '水阀管理', isOpen: true, isClose: true,isLongOpen:true, isTiming:true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
longOpenIcon: '/subpackage/device/static/images/longOpen.png',timingIcon: '/subpackage/device/static/images/timing.png',
openName: '开', closeName: '关', hardware_type: 'WaterValve',longOpenName: '长开', timingName: '定时',iconNum:4,
},
's12': {
id: 12, name: '互动设备管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关', hardware_type: '',iconNum:2
},
's13': {//TODO 等待接口
id: 13, name: '监控管理', isOpen: false, isClose: false, isDetail:true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',detailName:"详情", hardware_type: 'IotSim',iconNum:2
},
's17': {//TODO 等待接口
id: 17, name: '窗帘管理', isOpen: false, isClose: false, isDetail:true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',detailName:"详情", hardware_type: 'Router4G',iconNum:2
},
's18': {
id: 18, name: '路由器管理', isOpen: false, isClose: false, isDetail:true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',detailName:"详情", hardware_type: 'Router4G',iconNum:2
},
's19': {
id: 19, name: '物联卡管理', isOpen: false, isClose: false, isDetail:true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',detailName:"详情", hardware_type: 'IotSim',iconNum:2
},
}
import { mapState } from 'vuex';
import util from '../../../../utils/util';
export default {
components: {
'store-name': store_name
},
computed: {
...mapState({
curStoreInfo: state => state.device.curStoreInfo,
}),
getIconWidth(){//计算操作icon的宽度
return ()=>{
return 100/this.pageInfo.iconNum+'%'
}
},
getLotStatus(){//sim卡状态, 0 : 华为文档中没有
return (e)=>{
return ["未知","注册","重启","在线","离线"][e.extension['HWC'].device_status]
}
},
getViewWidth(){//计算按钮区域的宽度
return ()=>{
let widthViewArr = ["照明管理","水阀管理","风扇管理"]
return (widthViewArr.indexOf(this.pageInfo.name)>=0)?'710rpx':'';
}
}
},
watch: {
curStoreInfo(newVal, oldVal){
this.deviceList = [];
this.getDeviceList({
stadium_id: newVal.id,
hardware_type: this.pageInfo.hardware_type
})
}
},
data(){
return {
pageInfo: {},
deviceList: [],
}
},
onLoad(options){
let _pageInfo = showArr[`s${options.sid}`] || {};
this.pageInfo = _pageInfo;
uni.setNavigationBarTitle({ title: _pageInfo.name });
this.getDeviceList({
stadium_id: this.curStoreInfo.id,
hardware_type: this.pageInfo.hardware_type
})
},
methods: {
getDeviceList({
stadium_id,
hardware_type,
limit = 100,
page = 1
}){
util.showLoad();
let reqListData = {
'filter[hardware_type]': hardware_type,
'filter[stadium_id]': stadium_id,
'limit': limit,
'page': page,
}
if(hardware_type=="WaterValve") reqListData.operating_status = 1; //0723 按测试要求 水阀这里加多一个状态
deviceServer.get({
url: deviceApi.hardwareList,
data: reqListData,
failMsg: '加载失败!'
})
.then(res=>{
util.hideLoad();
let _list = res.list || [];
if(hardware_type=="Router4G"){ //路由器在线状态设置
_list = _list.map((e,i)=>{
e['defineStatusCode'] = e.extension.online? 1 : 0;
return e
})
}
this.deviceList = _list;
console.log(res)
})
.catch(util.hideLoad)
},
controlDevice(e){
util.routeTo(`/subpackage/device/pages/index/lot_manage?mac=${switchInfo.hardware_standard}`, 'nT');
},
// 按钮操作, status 0 -> 关(左), 1 -> 开(右) ,2 -> 长开 ,3 -> 定时, 4 ->详情(自定义)
operateBtn: util.debounce(function({ switchInfo, status }){
console.log("icon tap status: ",status,switchInfo)
let _data = this.getOperateReqData({ switchInfo, status })
//针对门禁没有关按钮发两条命令->开&关 20201224 后端: 直接发两条 关的那条这里填5 然后你那边不用管返回
//新增定时/长按拦截判断
if(status == 2) return util.showNone("该功能暂未开放")
if(status == 4){
// if(this.pageInfo.name=='监控管理')return util.routeTo(`/subpackage/device/pages/monitor_manage/monitor_manage?mac=${switchInfo.hardware_standard}`, 'nT');
if(this.pageInfo.name=='窗帘管理')return util.routeTo(`/subpackage/device/pages/index/sunblind_manage?mac=${switchInfo.hardware_standard}`, 'nT');
if(this.pageInfo.hardware_type=='Router4G')return util.routeTo(`/subpackage/device/pages/index/router_manage?mac=${switchInfo.hardware_standard}`, 'nT');
if(this.pageInfo.hardware_type=='IotSim')return util.routeTo(`/subpackage/device/pages/index/lot_manage?mac=${switchInfo.hardware_standard}`, 'nT');
}
if(status == 3) return (()=>{
switchInfo.switchData = _data;//将中控组合数据传递到下层
let timing_setting = `/subpackage/device/pages/timing/timing_setting?switchInfo=${encodeURIComponent(JSON.stringify(switchInfo))}`
util.routeTo(`${timing_setting}`, 'nT');
})()
if(switchInfo.hardware_type === 'AccessControl'&&status == 1){
this.operateReq({data: this.getOperateReqData({ switchInfo, status: 0 }), isTip: false, isLoad: false});
}
this.operateReq({ data: _data });
}, 300, 300),
// 获取接口参数结构
getOperateReqData({ switchInfo, status }){
let { curStoreInfo } = this;
let _query = switchInfo.hardware_type === 'GateControl' ?
this.getGateQuery({ switchInfo, status}) :
this.getSwitchQuery({ switchInfo, status });
let _data = {
device: curStoreInfo.device_name, // 中控名,
data: _query, // 后端数据结构, 参考src\subpackage\device\js\ouxuanac.md
};
//针对门禁没有关按钮发两条命令->开&关 20201224 后端: 直接发两条 关的那条这里填5 然后你那边不用管返回
if(switchInfo.hardware_type === 'AccessControl'&&status == 0)_data['delay'] = '5';
return _data;
},
// 操作接口请求
operateReq({data, isTip=true, isLoad=true}){
if(isLoad)util.showLoad();
deviceServer.post({
url: deviceApi.ouxuanac,
data: data,
isDefaultGet: false,
})
.then(res=>{
if(isLoad)util.hideLoad();
if(res.data.code == 0){
if(isTip)util.showNone(res.data.message || '操作成功!');
}else{
if(isTip)util.showNone(res.data.message || '操作失败!');
}
})
.catch(err=>{if(isLoad)util.hideLoad()})
},
// 门闸数据结构 // 门闸数据结构不统一
getGateQuery({ switchInfo, status }){
let { enter_id, leave_id, hardware_net_addr } = switchInfo;
// 进出控制ID |进入-> enter_id 离开-> leave_id|
let _cid = status === 1 ? enter_id :
status === 0 ? leave_id : '';
return {
name: 'gate',
value: {
tcp: hardware_net_addr + '',
cid: _cid + ''
},
is_delay: true,
queue_group: 'gate'
}
},
//
refreshStatusBtn: util.debounce(function({switchInfo, index}){
if(switchInfo.hardware_type == "Router4G"){
return this.getDeviceList({
stadium_id: this.curStoreInfo.id,
hardware_type: this.pageInfo.hardware_type
})
}
this.getStatusReq({
data: this.getSwitchStatusQuery(switchInfo),
index,
})
},300,300),
// 获取设备状态
getStatusReq({data, index}){
let _deviceList = this.deviceList.slice();
util.showLoad();
deviceServer.post({
url: deviceApi.ouxuanac,
data: data,
isDefaultGet: false,
})
.then(res=>{
util.hideLoad();
let _data = res.data || {};
console.log(this.changeLowerCase(_data.data))
if(_data.code == 504 || this.changeLowerCase(_data.data).indexOf('timeout')!=-1){
_deviceList[index]['defineStatusCode'] = 0;
}else if(_data.code == 0&&this.changeLowerCase(_data.data).indexOf('timeout')==-1){
_deviceList[index]['defineStatusCode'] = 1;
}else{
util.showNone(_data.message || '操作失败!');
}
this.deviceList = _deviceList;
// if(res.data.code == 0){
// if(isTip)util.showNone(res.data.message || '操作成功!');
// }else{
// if(isTip)util.showNone(res.data.message || '操作失败!');
// }
})
.catch(util.hideLoad)
},
// 咖啡机和门闸暂时没有状态
// 设备状态请求参数数据结构
getSwitchStatusQuery(switchInfo){
let { curStoreInfo } = this;
let {
hardware_connect_method,
hardware_type,
hardware_id,
node_id,
hardware_net_addr
} = switchInfo;
const _query = {
name: this.getStatusQueryName(switchInfo),
value: { id: hardware_id + '', } // value 内值全为String
};
if (this.changeLowerCase(hardware_connect_method) === 'tcp') _query.value['tcp'] = hardware_net_addr + '';
let _flag = this.changeLowerCase(hardware_connect_method) === 'serialport485' || this.changeLowerCase(hardware_connect_method) === 'tcp';
if (_flag){
if(hardware_type === 'Air'){ // 空调开关状态 key为 op
_query.value['op'] = 'status'
_query['name'] = this.getAirQueryName(switchInfo)
}else{
_query.value['p'] = node_id + ''; // 硬件子id
// postData.value['o'] = this.getRelayStatus(status); // 开关状态
}
}
return {
device: curStoreInfo.device_name, // 中控名,
data: _query, // 后端数据结构, 参考src\subpackage\device\js\ouxuanac.md
}
// this.getStatusReq({
// index,
// data: {
// device: curStoreInfo.device_name, // 中控名,
// data: _query, // 后端数据结构, 参考src\subpackage\device\js\ouxuanac.md
// }
// })
},
// switchInfo -> 当前开关信息
// status -> 开关状态 0 -> 关(右), 1 -> 开(左)
// 数据结构参考 src\subpackage\device\js\ouxuanac.md
// 空调开关数据结构独立判断处理 hardware_type === 'Air'
getSwitchQuery({ switchInfo, status }){
let {
hardware_connect_method,
hardware_type,
hardware_id,
node_id,
hardware_net_addr
} = switchInfo;
const postData = {
name: this.getQueryName(switchInfo),
value: { id: hardware_id + '', } // value 内值全为String
};
if (this.changeLowerCase(hardware_connect_method) === 'gpio') postData.value['status'] = this.getRelayStatus(status);
// tcp 连接需要 hardware_net_addr
if (this.changeLowerCase(hardware_connect_method) === 'tcp') postData.value['tcp'] = hardware_net_addr + '';
let _flag = this.changeLowerCase(hardware_connect_method) === 'serialport485' || this.changeLowerCase(hardware_connect_method) === 'tcp';
if (_flag){
if(hardware_type === 'Air'){ // 空调开关状态 key为 op
postData.value['op'] = this.getAirRelayStatus(status);
postData['name'] = this.getAirQueryName(switchInfo)
}else{
// 空调设备不需要以下两个字段
postData.value['p'] = node_id + ''; // 硬件子id
postData.value['o'] = this.getRelayStatus(status); // 开关状态
}
}
return postData;
},
changeLowerCase(str){
return str.toString().toLocaleLowerCase();
},
// 常规开关状态
// Low = "low", // 低电位,为开启
// High = "high", // 高电位, 为关闭
// status 0 -> 关(左), 1 -> 开(右) ,2 -> 长开 ,3 -> 定时, 4 ->详情(自定义)
getRelayStatus(status){
return [ 'high', 'low', '', 'high', ''][status] || ''
},
// 空调状态
// status = "status",
// on = "on",
// off = "off",
getAirRelayStatus(status){
return [ 'off', 'on' ][status] || ''
},
// 非空调获取状态name
getStatusQueryName(switchInfo){
let { hardware_connect_method } = switchInfo;
let _obj = {
'Gpio': 'get-rpio', // 全设备
'SerialPort485': 'zzio404d-gpio-status',
'Tcp': 'zzio404d-gpio-status-tcp',
};
return _obj[hardware_connect_method] || ''
},
// 非空调获取设置name
getQueryName(switchInfo){
let { hardware_connect_method } = switchInfo;
let _obj = {
'Gpio': 'set-rpio', // 全设备
'SerialPort485': 'zzio404d-gpio',
'Tcp': 'zzio404d-gpio-tcp',
};
return _obj[hardware_connect_method] || ''
},
// 空调name获取
getAirQueryName(switchInfo){
let { hardware_connect_method, hardware_model } = switchInfo;
let _flag = this.changeLowerCase(hardware_connect_method) === 'tcp'&&this.changeLowerCase(hardware_model) === 'jianda';
if(_flag)return 'ray-air-rs-tcp';
let _obj = {
'acmelec': 'acmelec',
'zhongnan': 'zhongnan',
'jianda': 'ray-air-rs'
};
return _obj[this.changeLowerCase(hardware_model)] || '';
},
getIcon(){
let { pageInfo } = this;
if(!pageInfo.id)return '';
return `/subpackage/device/static/images/devices/${pageInfo.id}.png`
}
}
}
</script>
<style lang="scss">
@import '~style/public.scss';
.sm-tit{
padding-left: 40upx;
padding-top: 52upx;
padding-bottom: 30upx;
line-height: 60upx;
font-size: 44upx;
font-weight: 500;
color: #333;
}
.sm-list{
padding: 0 32upx;
display: flex;
justify-content: space-between;
flex-wrap: wrap ;
.sl-item{
margin-bottom: 30upx;
width: 328upx;
border-radius: 10upx;
background-color: #fff;
.si-top{
padding: 20upx 20upx 30upx;
display: flex;
flex-wrap: nowrap;
>image{
flex-shrink: 0;
flex-grow: 0;
margin-right: 20upx;
width: 80upx;
height: 80upx;
}
.st-right{
flex-grow: 1;
>.sr-name{
margin-bottom: 8upx;
line-height: 44upx;
font-size: 32upx;
color: #333;
@include textHide(1);
}
.sr-bot-router{
font-size: 20rpx;
color: #9C9C9F;
text{
margin-left: 15rpx;
color: black;
}
}
.sr-bot{
display: flex;
align-items: center;
>view{
margin-right: 8upx;
padding: 0 12upx;
font-size: 20upx;
line-height: 28upx;
border-radius: 28upx;
border: 2upx solid #9A9A9D;
color: #9A9A9D;
&::before{
content: '';
margin-right: 12upx;
margin-top: -4upx;
display: inline-block;
vertical-align: middle;
width: 8upx;
height: 8upx;
border-radius: 50%;
background-color: #9A9A9D;
}
&.active{
color: #333333;
&::before{
background-color: $themeColor;
}
}
}
>image{
flex-shrink: 0;
flex-grow: 0;
width: 32upx;
height: 32upx;
}
}
}
}
.si-bottom{
padding-top: 30upx;
padding-bottom: 30upx;
display: flex;
justify-content: center;
border-top: 2upx solid #F2F2F7;
>view{
flex-shrink: 0;
flex-grow: 0;
width: 50%;
>image{
display: block;
margin: 0 auto 20upx;
width: 100upx;
height: 100upx;
}
>view{
font-size: 24upx;
line-height: 34upx;
text-align: center;
color: #9a9a9d;
}
}
.btn-detail{
width:auto;
> view{
width: 204rpx;
height: 88rpx;
background: #009874;
border-radius: 10rpx;
text-align: center;
line-height: 88rpx;
color: white;
}
}
}
}
}
</style>