1276 lines
44 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">
<!-- 设备信息 -->
<view class="device-info" v-if="tabbarIndex === 0 && deviceForm.deviceType !== 3">
<view class="top-wrap">
<view class="nav-bar">
<navbar color="#ffffff">{{ navTitle }}</navbar>
</view>
<view class="sub-wrap" :style="{width: '85%'}">
<u-subsection :list="baseTabList" :current="baseTabIndex" bgColor=" rgba(255,255,255,0.2)"
activeColor="#3378FE" inactiveColor="#FFFFFF" @change="handleBaseTabsClick"></u-subsection>
</view>
</view>
<view class="content-wrap">
<!-- 设备 -->
<view class="device-content">
<view>
<!-- 设备运行状态 -->
<running-status v-if="deviceForm.deviceId" v-show="baseTabIndex === 0" ref="runningStatus"
:device="deviceForm"></running-status>
<!-- 设备实时监测 -->
<!-- <device-monitor v-show="baseTabIndex == 1" ref="deviceMonitor" :show="baseTabIndex == 1"
:device="deviceForm">
</device-monitor> -->
<!-- 视频监控 -->
<!-- <video-monitor v-show="baseTabIndex == 2" ref="videoMonitor"
:device="deviceForm"></video-monitor> -->
<!-- 告警记录 -->
<device-alertLog v-show="baseTabIndex == 3" ref="deviceAlertLog"
:device="deviceForm"></device-alertLog>
</view>
<!-- 设备删除提示 -->
<u-modal :show="show" :title="modalTitle" :content="content" showCancelButton @confirm="confirm"
@cancel="cancel"></u-modal>
</view>
</view>
</view>
<view class="device-info-video" v-if="tabbarIndex === 0 && deviceForm.deviceType === 3">
<view class="top-wrap">
<view class="nav-bar">
<navbar color="#ffffff">{{ navTitle }}</navbar>
</view>
<view class="sub-wrap" :style="{width: '85%'}" v-if="deviceForm.deviceType !== 3">
<u-subsection :list="baseTabList" :current="baseTabIndex" bgColor=" rgba(255,255,255,0.2)"
activeColor="#3378FE" inactiveColor="#FFFFFF" @change="handleBaseTabsClick"></u-subsection>
</view>
<view class="sub-wrap" :style="{width: '44%'}" v-else>
<u-subsection :list="videoTabList" :current="videotabIndex" bgColor=" rgba(255,255,255,0.2)"
activeColor="#3378FE" inactiveColor="#FFFFFF" @change="handleVideoTabsClick"></u-subsection>
</view>
</view>
<view class="content-wrap">
<!-- 设备 -->
<view class="device-content">
<!-- 视频监控设备 -->
<view>
<!-- 设备通道 -->
<view class="channel_wrap" v-show="videotabIndex == 0">
<view class="item_body" v-for="(item, i) in channelList" :key="i"
@click="gotoDevicePlayer(item.deviceSipId, item.channelSipId, item.status)">
<view class="img">
<u-icon name="play-circle" color="#2979ff" size="28"></u-icon>
</view>
<view>
<u--text lines="2" lineHeight="24" size="16" :text="item.channelName"></u--text>
<view style="display:flex;margin-top:6px;">
<view style="margin-right:20px;">
<u--text prefixIcon="info-circle"
iconStyle="color:#606266;font-size:14px;margin-right:3px;" size="12"
color="#606266" mode="name" :text="item.model"></u--text>
</view>
</view>
<view class="status">
<u-tag v-if="item.statusInfo" :type="item.statusInfo.type" :plain="true"
size="mini" :text="item.statusInfo.name"></u-tag>
</view>
</view>
</view>
<u-empty mode="list" :show="channelTotal === 0" marginTop="30"></u-empty>
<u-loadmore :status="channelLoadStatus" v-if="channelTotal > channelQueryParams.pageSize"
marginTop="20" />
</view>
<view class="base-info" v-show="videotabIndex === 1">
<u--form labelPosition="left" :model="deviceForm" :rules="deviceRules" ref="deviceForm"
labelWidth="90" labelAlign="left">
<view class="card-wrap">
<view class="title-wrap">
<u--text :text="$tt('deviceDetail.basicMsg')" bold color="#606266"></u--text>
</view>
<u-form-item :label="$tt('deviceDetail.deviceName')" prop="deviceName" borderBottom>
<view class="item-right" slot="right">
<u--input v-model="deviceForm.deviceName" clearable border="none"
inputAlign="right"></u--input>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.longitude')"
v-if="deviceForm.locationWay === 3" borderBottom>
<view class="item-right" slot="right">
<u--input v-model="deviceForm.longitude" type="digit"
:placeholder="$tt('deviceDetail.inputLongitude')" border="none"
inputAlign="right"></u--input>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.latitude')"
v-if="deviceForm.locationWay === 3" borderBottom>
<view class="item-right" slot="right">
<u--input v-model="deviceForm.latitude" type="digit"
:placeholder="$tt('deviceDetail.inputLatitude')" border="none"
inputAlign="right"></u--input>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.address')"
v-if="deviceForm.locationWay === 3" borderBottom>
<view class="item-right" slot="right">
<u--input v-model="deviceForm.networkAddress" border="none"
inputAlign="right"></u--input>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.remark')"></u-form-item>
<u-textarea v-model="deviceForm.remark" height="40" fontSize="14"
:placeholder="$tt('deviceDetail.inputMsg')" style="background-color: #F7F7F7;"
confirmType="done"></u-textarea>
<view style="margin-top: 20px; display: flex; gap: 10px;">
<u-button v-if="!profile.deptId" @tap="gotoShare" size="small" :plain="true"
type="primary"
:customStyle="{fontSize: '30rpx',height: '88rpx',borderRadius: '10rpx'}">{{$tt('deviceDetail.share')}}</u-button>
<u-button type="primary" @tap="submitForm" size="small"
:customStyle="{fontSize: '30rpx',height: '88rpx',borderRadius: '10rpx'}">{{$tt('deviceDetail.preserve')}}</u-button>
</view>
</view>
<!-- 设备状态 -->
<view class="card-wrap">
<u-form-item borderBottom>
<view style="display: flex;">
<u-row>
<u-col :span="7.5">
<u--text :text="$tt('deviceDetail.deviceStatus')" bold
color="#000000"></u--text>
</u-col>
<u-col :span="2">
<u-button :text="$tt('home.notActive')" type="warning" size="mini"
plain v-if="deviceForm.status == 1"
customStyle="width:50px;margin-left:12rpx;"></u-button>
<u-button :text="$tt('home.disabled')" type="error" size="mini"
plain v-if="deviceForm.status == 2"
customStyle="width:50px;margin-left:12rpx;"></u-button>
<u-button :text="$tt('home.onLine')" type="success" size="mini"
plain v-if="deviceForm.status == 3"
customStyle="width:50px;margin-left:12rpx;"></u-button>
<u-button :text="$tt('home.offline')" type="info" size="mini" plain
v-if="deviceForm.status == 4"
customStyle="width:50px;margin-left:12rpx;"></u-button>
</u-col>
</u-row>
</view>
<view slot="right" @click="handleDeleteDevice">
<u-icon name="trash" color="#f85959" size="23"></u-icon>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.serialNumber')" borderBottom>
<view class="item-right" slot="right"><u--text
:text="deviceForm.serialNumber"></u--text></view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.belongingProducts')" borderBottom>
<view class="item-right" slot="right"><u--text
:text="deviceForm.productName"></u--text>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.firmwareVersion')" borderBottom>
<view class="item-right" slot="right"><u--text
:text="formatVersion(deviceForm.firmwareVersion)"></u--text></view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.positionMethod')" borderBottom
v-if="deviceForm.deviceType === 3">
<view class="item-right" slot="right"><u--text
:text="deviceForm.locationWayInfo.name"></u--text></view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.longitude')" borderBottom
v-if="deviceForm.longitude && deviceForm.locationWay !== 3">
<view class="item-right" slot="right"><u--text
:text="deviceForm.longitude"></u--text>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.latitude')" borderBottom
v-if="deviceForm.latitude && deviceForm.locationWay !== 3">
<view class="item-right" slot="right"><u--text
:text="deviceForm.latitude"></u--text>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.equipmentSignal')" borderBottom>
<view class="item-right" slot="right"><u--text
:text="$tt('deviceDetail.veryGood')" type="success"
v-if="deviceForm.rssi >= '-55'"></u--text>
<u--text :text="$tt('deviceDetail.excellent')" type="success"
v-else-if="deviceForm.rssi >= '-70' && deviceForm.rssi < '-55'"></u--text>
<u--text :text="$tt('deviceDetail.good')" type="success"
v-else-if="deviceForm.rssi >= '-85' && deviceForm.rssi < '-70'"></u--text>
<u--text :text="$tt('deviceDetail.average')" type="warning"
v-else-if="deviceForm.rssi >= '-100' && deviceForm.rssi < '-85'"></u--text>
<u--text :text="$tt('deviceDetail.poor')" type="error" v-else></u--text>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.address')"
v-if="deviceForm.networkAddress && deviceForm.locationWay !== 3" borderBottom>
<view class="item-right" slot="right"><u--text
:text="deviceForm.networkAddress"></u--text>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.networkAddress')" borderBottom>
<view class="item-right" slot="right"><u--text
:text="deviceForm.networkIp"></u--text>
</view>
</u-form-item>
<u-form-item :label="$tt('deviceDetail.activationTime')">
<view class="item-right" slot="right"><u--text
:text="deviceForm.activeTime"></u--text>
</view>
</u-form-item>
<u--image :src="imageUrl" radius="10" mode="aspectFill" width="100%" height="200">
<view slot="error" style="font-size: 18rpx;">{{$tt('deviceDetail.loadingFail')}}
</view>
<template v-slot:loading>
<u-loading-icon></u-loading-icon>
</template>
</u--image>
</view>
</u--form>
</view>
</view>
<!-- 设备删除提示 -->
<u-modal :show="show" :title="modalTitle" :content="content" showCancelButton @confirm="confirm"
@cancel="cancel"></u-modal>
</view>
</view>
</view>
<!-- 设备定时 -->
<!-- <device-timing v-if="tabbarIndex === 1" ref="deviceTiming" :device="deviceForm"></device-timing> -->
<!-- 设备日志 -->
<device-log v-if="tabbarIndex === 2" ref="deviceLog" :device="deviceForm"></device-log>
<!-- 设备统计 -->
<!-- <device-statistic v-show="tabbarIndex === 3" :device="deviceForm" :type="tabbarIndex"
ref="deviceStatistic"></device-statistic> -->
<device-history v-if="tabbarIndex === 3" ref="deviceHistory" :device="deviceForm"></device-history>
<!-- 设备组态 -->
<!-- <device-scada v-show="tabbarIndex === 4" :show="tabbarIndex === 4" :device="deviceForm"
ref="deviceScada"></device-scada> -->
<u-tabbar :value="tabbarIndex" @change="tabbarChange" :fixed="true" :placeholder="true"
:safeAreaInsetBottom="true" :border="false" activeColor="#3378FE" v-if="deviceForm.deviceType !==3">
<u-tabbar-item :text="$tt('deviceDetail.device')" @click="tabbarClick(0)">
<image style="width:18px;height:18px;" slot="active-icon" src="/static/home/tabBar/device_blue.png">
</image>
<image style="width:18px;height:18px;" slot="inactive-icon" src="/static/home/tabBar/device_black.png">
</image>
</u-tabbar-item>
<!-- <u-tabbar-item :text="$tt('deviceDetail.timing')" @click="tabbarClick(1)">
<image style="width:18px;height:18px;" slot="active-icon" src="/static/home/tabBar/time_blue.png">
</image>
<image style="width:18px;height:18px;" slot="inactive-icon" src="/static/home/tabBar/time_black.png">
</image>
</u-tabbar-item> -->
<u-tabbar-item :text="$tt('deviceDetail.journal')" @click="tabbarClick(2)">
<image style="width:18px;height:18px;" slot="active-icon" src="/static/home/tabBar/log_blue.png">
</image>
<image style="width:18px;height:18px;" slot="inactive-icon" src="/static/home/tabBar/log_black.png">
</image>
</u-tabbar-item>
<u-tabbar-item :text="$tt('deviceDetail.static')" @click="tabbarClick(3)">
<image style="width:18px;height:18px;" slot="active-icon" src="/static/home/tabBar/statistic_blue.png">
</image>
<image style="width:18px;height:18px;" slot="inactive-icon"
src="/static/home/tabBar/statistic_black.png">
</image>
</u-tabbar-item>
<!-- <u-tabbar-item :text="$tt('deviceDetail.scada')" @click="tabbarClick(4)">
<image style="width:18px;height:18px;" slot="active-icon" src="/static/home/tabBar/scada_blue.png">
</image>
<image style="width:18px;height:18px;" slot="inactive-icon" src="/static/home/tabBar/scada_black.png">
</image>
</u-tabbar-item> -->
</u-tabbar>
<!-- <u-modal :show="showScada" content="暂无组态,请先去网页端配置模板组态" @confirm="() => showScada = false"
@cancel="() => showScada = false" showCancelButton></u-modal> -->
<!-- 选择直播还是回放 -->
<u-popup :show="isSelect" :round="5" mode="bottom" :closeOnClickOverlay="true" @close="isSelect = false">
<view class="trigger-popup-wrap">
<view class="cell-group-wrap">
<u-cell-group :border="false">
<view class="cell-wrap">
<u-cell title="实时视频" icon="/static/home/video/play.png"
:iconStyle="{ marginRight: '10rpx' }" :border="false" isLink
@click="gotoPlayer"></u-cell>
</view>
<view class="cell-wrap">
<u-cell title="录像回放" icon="/static/home/video/record.png"
:iconStyle="{ marginRight: '10rpx' }" :border="false" isLink
@click="gotoDeviceVideo"></u-cell>
</view>
</u-cell-group>
</view>
</view>
</u-popup>
<!-- 选择录像时间 -->
<u-calendar :show="showcalendar" :minDate="minDate" :maxDate="maxDate" month-num="7" :defaultDate="defaultDate"
@confirm="confirmCalendar" @close="closeCalendar"></u-calendar>
</view>
</template>
<script>
import projectConfig from '@/env.config.js';
import navbar from '@/components/navBar/index.vue';
// import videoMonitor from './video/index.vue';
import deviceAlertLog from './log/alertLog.vue';
import runningStatus from './status/index.vue';
import deviceLog from './log/index.vue';
import deviceHistory from './statistic/history.vue';
// import deviceMonitor from './monitor/index.vue';
// import deviceTiming from './timing/index.vue';
// import deviceScada from './scada.vue';
import {
listChannel
} from '@/apis/modules/sip';
import {
getDevice,
getRunningStatus,
cacheJsonThingsModel,
deviceSynchronization,
updateDevice,
delDevice
} from '@/apis/modules/device';
import {
getSipStatusInfo,
getLocationWayInfo
} from '@/helpers/common.js'
export default {
components: {
navbar,
runningStatus,
deviceLog,
// deviceMonitor,
// deviceTiming,
// videoMonitor,
deviceAlertLog,
deviceHistory,
// deviceScada
},
data() {
return {
navTitle: this.$tt('navBar.deviceDetails'),
deviceId: 0,
baseTabIndex: 0, // 基础设备tab index
videotabIndex: 0,
tabbarIndex: 0,
baseTabList: [{
name: this.$tt('deviceDetail.overview')
}, {
name: this.$tt('deviceDetail.alert')
}],
videoTabList: [{
name: this.$tt('deviceDetail.channel')
}, {
name: this.$tt('deviceDetail.deviceDetail')
}],
show: false, // 删除设备模态框
modalTitle: '删除警告', // 对话框标题
content: '', // 对话框内容
deviceForm: {
isShadow: 0, // 避免u-switch报错初始化
deviceName: '',
locationWay: 1,
protocolCode: '',
}, // 设备详情
deviceDisable: 0, // 设备状态1=禁用0=不禁用)
isSubDev: false, // 是否有子设备
imageUrl: '', // 图片地址
deviceSipId: '',
channelSipId: '',
deviceRules: { // 表单校验
deviceName: [{
required: true,
message: this.$tt('deviceDetail.deviceCheck'),
trigger: ['blur', 'change']
}]
},
isSelect: false,
// 设备通道
channelLoadStatus: 'nomore',
channelQueryParams: {
pageNum: 1,
pageSize: 10,
deviceSipId: '',
},
channelTotal: 0,
channelList: [],
// showScada: false,
showcalendar: false, //录像时间选择弹出框
minDate: "",
maxDate: "",
defaultDate: "",
};
},
onLoad: function(option) {
this.deviceId = Number(option.deviceId);
this.deviceForm.protocolCode = option.protocolCode;
this.connectMqtt(); // 连接mqtt
},
onHide() {
this.isSelect = false;
},
onUnload() {
this.mqttUnSubscribe(this.deviceForm); // 取消订阅主题
},
onShow() {
// uni.$off('re-device-timing-list');
// uni.$once('re-device-timing-list', (dat) => {
// if (dat) {
// this.$refs.deviceTiming.dataList = [];
// this.$refs.deviceTiming.queryParams.pageNum = 1;
// this.$refs.deviceTiming.getList();
// }
// });
},
mounted() {
this.initCalendar();
},
methods: {
// 基础tab点击事件
handleBaseTabsClick(index) {
this.baseTabIndex = index;
},
// 视频tab点击事件
handleVideoTabsClick(index) {
this.videotabIndex = index;
},
/* 连接Mqtt消息服务器 */
async connectMqtt() {
if (this.$mqttTool.client === null) {
await this.$mqttTool.connect(this.vuex_token);
}
this.mqttCallback();
// 获取设备信息并订阅主题
this.getDevice();
},
/* Mqtt回调处理 */
mqttCallback() {
this.$mqttTool.client.on('message', (topic, message, buffer) => {
let topics = topic.split('/');
let productId = topics[1];
let deviceNum = topics[2];
message = JSON.parse(message.toString());
if (!message) {
return;
};
if (topics[3] == 'status' || topics[2] == 'status') {
console.log('接收到【设备状态-详情】主题:', topic);
console.log('接收到【设备状态-详情】内容:', message);
// 更新列表中设备的状态
if (this.deviceForm.serialNumber == deviceNum) {
this.deviceForm.status = message.status;
this.deviceForm.isShadow = message.isShadow;
this.deviceForm.rssid = message.rssid;
}
};
//不是modbus不转发到子页面其他设备的页面有回调方法
if (this.isSubDev) {
/*发送设备上报到子模块*/
if (topic.endsWith('ws/service')) {
console.log('接收到【设备数据上报】主题:', topic)
console.log('接收到【设备数据上报】主题:', message)
this.$bus.$emit("updateDeviceStatus", {
serialNumber: topics[2],
productId: this.deviceForm.productId,
data: message.message,
})
}
}
});
},
/** Mqtt订阅主题 */
mqttSubscribe(device) {
// 订阅当前设备状态和实时监测
let topicStatus = '/' + device.productId + '/' + device.serialNumber + '/status/post';
let topicMonitor = '/' + device.productId + '/' + device.serialNumber + '/monitor/post';
let topicReply = '/' + device.productId + '/' + device.serialNumber + '/service/reply';
let topicService = '/' + device.productId + '/' + device.serialNumber + '/ws/service';
let topics = [];
topics.push(topicStatus);
topics.push(topicMonitor);
topics.push(topicReply);
topics.push(topicService);
this.$mqttTool.subscribe(topics);
},
/** Mqtt取消订阅主题 */
mqttUnSubscribe(device) {
// 订阅当前设备状态和实时监测
let topicStatus = '/' + device.productId + '/' + device.serialNumber + '/status/post';
let topicMonitor = '/' + device.productId + '/' + device.serialNumber + '/monitor/post';
let topicReply = '/' + device.productId + '/' + device.serialNumber + '/service/reply';
let topicService = '/' + device.productId + '/' + device.serialNumber + '/ws/service';
let topics = [];
topics.push(topicStatus);
topics.push(topicMonitor);
topics.push(topicReply);
topics.push(topicService);
this.$mqttTool.unsubscribe(topics);
console.log('取消订阅', topics);
},
// 导航栏改变
tabbarChange() {},
// 导航栏单击
tabbarClick(index) {
this.tabbarIndex = index;
},
// 格式化版本显示
formatVersion(version) {
return `Version ${version}`;
},
// 刷新设备
onPullDownRefresh() {
if (this.tabbarIndex == 0) {
if (this.baseTabIndex == 0) {
// 设备运行状态
this.getDevice();
this.$refs.runningStatus.baseStatusRefresh();
} else if (this.baseTabIndex == 1) {
// 告警记录
this.getDevice();
} else {
uni.stopPullDownRefresh();
}
} else if (this.tabbarIndex == 1) {
// 设备定时
// this.$refs.deviceTiming.deviceTimerRefresh();
uni.stopPullDownRefresh();
} else if (this.tabbarIndex == 3) {
// 设备统计
// this.$refs.deviceStatistic.getCacheThingsModdel();
uni.stopPullDownRefresh();
} else {
uni.stopPullDownRefresh();
}
},
/**获取设备详情*/
getDevice() {
getDevice(this.deviceId).then(async response => {
try {
let data = response.data;
if (data.deviceType !== 3) {
// 获取缓存物模型
data.cacheThingsModel = await this.getCacheThingsModdel(data.productId);
// 获取设备运行状态
data.thingsModels = await this.getRunningStatusInfo(this.deviceId, data.slaveId);
// 格式化物模型,拆分出监测值,数组添加前缀
this.formatThingsModel(data);
} else {
// 获取通道列表
this.channelList = await this.getChannelList(data.serialNumber);
}
this.navTitle = data.deviceName;
// this.isSubDev = data.subDeviceList.length > 0;
this.imageUrl = data.imgUrl;
if (this.imageUrl != null && this.imageUrl != '') {
this.imageUrl = projectConfig.BASE_URL + this.imageUrl;
} else {
this.imageUrl = '/static/common/device.png';
}
// 禁用状态
if (data.status == 2) {
this.deviceDisable = 1;
}
// 获取定位方式
data.locationWayInfo = getLocationWayInfo(data.locationWay);
//Mqtt订阅
uni.stopPullDownRefresh();
this.mqttSubscribe(data);
//增加协议字段为后面数据采集做判断
data.protocolCode = this.deviceForm.protocolCode;
this.deviceForm = data;
} catch (e) {
console.log(e);
}
});
},
// 重组数据
setdeviceValue(data) {
let restart = true;
while (restart) {
restart = false; // 默认不重启循环
let model = {
id: '',
name: '',
isMonitor: 0,
isHistory: 0,
isChart: 0,
isReadonly: 0,
isApp: 0,
order: 8,
type: 1,
datatype: {
type: '',
falseText: '',
trueText: '',
min: 0,
max: 100,
step: 1,
unit: '',
arrayType: '',
arrayCount: 0,
showWay: null,
maxLength: 1024,
enumList: null,
params: [],
arrayParams: [],
arrayModel: []
},
};
// 检查是否存在需要分组的元素
const hasElementsToProcess = data.thingsModels.some((item) => item.id.includes('array_'));
if (!hasElementsToProcess) {
// console.log('所有分组已处理,结束循环');
break;
}
// 组合数据
for (let i = 0; i < data.thingsModels.length; i++) {
if (!data.thingsModels[i].id.includes('array_')) continue;
//整体判断所有的data.thingsModels,里面的id是否含有下划线
if (data.thingsModels[i].id.includes('array_')) {
// console.log('存在下划线', data.thingsModels[i].id);
//判断存在下划线的个数为1
const thingsModelId = data.thingsModels[i].id.split('_');
const thingsModelName = data.thingsModels[i].name?.includes('array_') ? data.thingsModels[i]
.name
?.split('_') : [data.thingsModels[i].name];
if (thingsModelId.length >= 2 && thingsModelId[0] !== 'array' && thingsModelName.length >= 2) {
//找到一个对象
if (model.id === '') {
model.id = thingsModelId[0];
model.name = thingsModelName[0];
model.datatype.type = 'object';
}
if (model.id === thingsModelId[0]) {
model.isReadonly = data.thingsModels[i].isReadonly;
const name = thingsModelName.slice(1);
data.thingsModels[i].name = name.length > 1 ? name.join('_') : thingsModelName[1];
if (data.thingsModels[i].name === '' || data.thingsModels[i].name === null) {
//此时没有名字
data.thingsModels[i].name = model.name;
}
model.datatype.params.push(data.thingsModels[i]);
data.thingsModels.splice(i, 1);
i--;
}
}
if (thingsModelId.length === 3 && thingsModelId[0] === 'array') {
//找到一个数组
if (model.id === '') {
model.id = thingsModelId[2];
model.datatype.type = 'array';
}
if (model.id === thingsModelId[2]) {
model.value = model.value ? model.value + ',' + data.thingsModels[i].value : data
.thingsModels[i].value;
model.shadow = model.shadow ? model.shadow + ',' + data.thingsModels[i].shadow : data
.thingsModels[i].shadow;
model.isReadonly = data.thingsModels[i].isReadonly;
model.datatype.arrayType = data.thingsModels[i].datatype.type;
const name = data.thingsModels[i].name.match(/(.*)\d$/);
if (model.name === '') {
model.name = name[1];
}
model.datatype.arrayModel.push({
id: data.thingsModels[i].id,
name: data.thingsModels[i].name
})
data.thingsModels.splice(i, 1);
i--;
model.datatype.arrayCount++;
}
//console.log('model', model);
}
if (thingsModelId.length >= 4 && thingsModelId[0] === 'array') {
//找到一个数组对象
if (model.id === '') {
//model.id = id.join('_');
model.id = thingsModelId[2];
model.datatype.type = 'array';
}
// 对象
if (model.id === thingsModelId[2]) {
model.isReadonly = data.thingsModels[i].isReadonly;
model.datatype.arrayType = 'object';
const matchedIndex = thingsModelName.findIndex((item) => item.match(/(.*)\d$/));
const matchedName = matchedIndex !== -1 ? thingsModelName.slice(0, matchedIndex + 1) :
undefined;
const modelName = matchedIndex !== -1 ? thingsModelName.slice(matchedIndex + 1) :
undefined;
const name = matchedName.length > 1 ? matchedName.join('_') : matchedName[0];
if (model.name === '') {
model.name = name ? name : '';
//console.log(model.name);
}
data.thingsModels[i].name = modelName.length > 1 ? modelName.join('_') : modelName[0];
//data.thingsModels[i].id = id.join('_');
if (data.thingsModels[i].name === '' || data.thingsModels[i].name === null) {
//此时没有名字
data.thingsModels[i].name = model.name;
}
if (model.datatype.arrayParams.length === 0) {
//尚未赋值
//console.log('内部未赋值');
this.$set(model.datatype.arrayParams, 0, [data.thingsModels[i]]);
} else {
//已经赋值
let hasMatched = false; // 标记是否找到匹配的子数组
// 遍历所有子数组
model.datatype.arrayParams.some((subArray) => {
// 检查当前子数组是否包含匹配的 param
const isMatch = subArray.some((param) => {
const obj = param.id.split('_');
//console.log('obj', thingsModelId[1]);
return obj[1] === thingsModelId[1];
});
if (isMatch) {
// 向匹配的子数组末尾添加元素
this.$set(subArray, subArray.length, data.thingsModels[i]);
hasMatched = true;
return true; // 终止遍历
}
return false;
});
// 若未找到匹配的子数组,创建新子数组
if (!hasMatched) {
const newIndex = model.datatype.arrayParams.length;
this.$set(model.datatype.arrayParams, newIndex, [data.thingsModels[i]]);
}
}
data.thingsModels.splice(i, 1);
i--;
model.datatype.arrayCount++;
}
//console.log('model', model);
}
}
}
// 将组合后的 model 加入列表
if (model.id !== '') {
data.thingsModels.push(model);
restart = true; // 强制重新检查是否有更多分组
}
}
console.log("重组后", data)
return data
},
// 设置设备的状态1-未激活2-禁用3-在线4-离线)
setDeviceStatus() {
if (this.deviceDisable == 1) {
this.deviceForm.status = 2;
} else {
// 禁用状态,启用后状态是离线
if (this.deviceForm.status == 2) {
this.deviceForm.status = 4;
}
}
},
// 设备数据同步
deviceSynchronization() {
deviceSynchronization(this.deviceForm.serialNumber).then(async response => {
try {
let data = response.data;
if (data.deviceType !== 3) {
// 获取缓存物模型
data.cacheThingsModel = await this.getCacheThingsModdel(data.productId);
// 获取设备运行状态
data.thingsModels = await this.getRunningStatusInfo(this.deviceId, data.slaveId);
// 格式化物模型,拆分出监测值,数组添加前缀
this.formatThingsModel(data);
}
this.navTitle = data.deviceName;
this.imageUrl = data.imgUrl;
if (this.imageUrl != null && this.imageUrl != '') {
this.imageUrl = projectConfig.BASE_URL + this.imageUrl;
} else {
this.imageUrl = '/static/common/device.png';
}
// 禁用状态
if (data.status == 2) {
this.deviceDisable = 1;
}
this.deviceForm = response.data;
} catch (e) {
console.log(e);
}
});
},
/** 删除设备按钮操作 */
handleDeleteDevice() {
this.content = '是否确认删除 ' + this.deviceForm.deviceName + ' ';
this.show = true;
},
// 确认删除设备
confirm() {
this.show = false;
delDevice(this.deviceForm.deviceId).then(res => {
if (res.code == 200) {
// 跳转主页,通过globalData传递参数
getApp().globalData.operate = 'operate';
uni.switchTab({
url: '/pages/tabBar/home/index'
});
} else if (res.code == 500) {
uni.showToast({
icon: 'none',
title: res.msg
});
}
});
},
// 取消
cancel() {
this.show = false;
},
/** 提交按钮 */
submitForm() {
if (!this.deviceForm.locationWay) {
uni.showToast({
icon: 'none',
title: this.$tt('deviceDetail.positionCheck')
});
return;
}
this.$refs.deviceForm.validate().then(e => {
if (this.deviceForm.deviceId !== 0) {
this.setDeviceStatus(); // 设置设备状态
let device = {
deviceId: this.deviceForm.deviceId,
deviceName: this.deviceForm.deviceName,
isShadow: this.deviceForm.isShadow,
status: this.deviceForm.status,
remark: this.deviceForm.remark,
locationWay: this.deviceForm.locationWay,
longitude: this.deviceForm.longitude,
latitude: this.deviceForm.latitude,
networkAddress: this.deviceForm.networkAddress
};
updateDevice(device).then(res => {
if (res.code === 200) {
uni.showToast({
icon: 'success',
title: this.$tt('deviceDetail.updateSuccess')
});
}
});
}
});
},
//分享监控设备
gotoShare() {
uni.$u.route('/pagesA/device/share/list', {
deviceId: this.deviceForm.deviceId,
productId: this.deviceForm.productId,
deviceName: this.deviceForm.deviceName
});
},
/** 获取缓存物模型*/
getCacheThingsModdel(productId) {
return new Promise((resolve, reject) => {
cacheJsonThingsModel(productId).then(res => {
resolve(JSON.parse(res.data));
}).catch(err => {
reject(err);
})
})
},
// 获取设备运行状态
getRunningStatusInfo(deviceId, slaveId) {
return new Promise((resolve, reject) => {
getRunningStatus(deviceId, slaveId).then(res => {
resolve(res.data.thingsModels);
}).catch(err => {
reject(err);
})
});
},
// 物模型格式化
formatThingsModel(data) {
if (data && data.length !== 0) {
data.chartList = [];
data.monitorList = [];
data.statisticList = [];
data = this.setdeviceValue(data);
for (let i = 0; i < data.thingsModels.length; i++) {
if (data.thingsModels[i].datatype.type === "array") {
if (data.thingsModels[i].datatype.arrayType === "object") {
for (let k = 0; k < data.thingsModels[i].datatype.arrayParams.length; k++) {
for (let j = 0; j < data.thingsModels[i].datatype.arrayParams[k].length; j++) {
// 数组元素中参数ID添加前缀例如array_00_
// let index = k > 9 ? String(k) : '0' + k;
// let prefix = 'array_' + index + '_';
// data.thingsModels[i].datatype.arrayParams[k][j].id = prefix + data.thingsModels[i]
// .datatype.arrayParams[k][j].id;
// 图表、实时监测、监测统计分类放置
if (data.thingsModels[i].datatype.arrayParams[k][j].isChart === 1) {
data.thingsModels[i].datatype.arrayParams[k][j].name = "[" + data.thingsModels[
i].name + (k + 1) + "] " + data.thingsModels[i].datatype.arrayParams[k]
[j].name;
data.thingsModels[i].datatype.arrayParams[k][j].datatype.arrayType = "object";
data.chartList.push(data.thingsModels[i].datatype.arrayParams[k][j]);
// 监测统计
if (data.thingsModels[i].datatype.arrayParams[k][j].isHistory == 1) {
data.statisticList.push(data.thingsModels[i].datatype.arrayParams[k][j]);
}
// 实时监测
if (data.thingsModels[i].datatype.arrayParams[k][j].isMonitor == 1) {
data.monitorList.push(data.thingsModels[i].datatype.arrayParams[k][j]);
}
data.thingsModels[i].datatype.arrayParams[k].splice(j--, 1);
}
}
}
} else {
// 字符串拆分为物模型数组 model=id/name/type/isReadonly/value/shadow
let values = data.thingsModels[i].value && data.thingsModels[i].value != "" ? data
.thingsModels[i].value.split(',') : [];
let shadows = data.thingsModels[i].shadow && data.thingsModels[i].shadow != "" ? data
.thingsModels[i].shadow.split(',') : [];
for (let j = 0; j < data.thingsModels[i].datatype.arrayCount; j++) {
if (!data.thingsModels[i].datatype.arrayModel) {
data.thingsModels[i].datatype.arrayModel = [];
}
// 数组里面的ID需要添加前缀和索引例如array_00_temperature
let index = j > 9 ? String(j) : '0' + j;
let prefix = 'array_' + index + '_';
data.thingsModels[i].datatype.arrayModel[j] = {
...data.thingsModels[i].datatype.arrayModel[j],
//id: prefix + data.thingsModels[i].id,
//name: data.thingsModels[i].name,
type: data.thingsModels[i].type,
isReadonly: data.thingsModels[i].isReadonly,
value: values[j] ? values[j] : "",
shadow: shadows[j] ? shadows[j] : ""
}
}
}
} else if (data.thingsModels[i].datatype.type === "object") {
for (let j = 0; j < data.thingsModels[i].datatype.params.length; j++) {
// 图表、实时监测、监测统计分类放置
if (data.thingsModels[i].datatype.params[j].isChart === 1) {
// 图表
data.thingsModels[i].datatype.params[j].name = "[" + data.thingsModels[i].name + "] " +
data.thingsModels[i].datatype.params[j].name;
data.chartList.push(data.thingsModels[i].datatype.params[j]);
// 监测统计
if (data.thingsModels[i].datatype.params[j].isHistory == 1) {
data.statisticList.push(data.thingsModels[i].datatype.params[j]);
}
// 实时监测
if (data.thingsModels[i].datatype.params[j].isMonitor == 1) {
data.monitorList.push(data.thingsModels[i].datatype.params[j]);
}
data.thingsModels[i].datatype.params.splice(j--, 1);
}
}
} else if (data.thingsModels[i].isChart === 1) {
// 图表、实时监测、监测统计分类放置
data.chartList.push(data.thingsModels[i]);
// 监测统计
if (data.thingsModels[i].isHistory == 1) {
data.statisticList.push(data.thingsModels[i]);
}
// 实时监测
if (data.thingsModels[i].isMonitor == 1) {
data.monitorList.push(data.thingsModels[i]);
}
// 使用i--解决索引变更问题
data.thingsModels.splice(i--, 1);
}
}
// 整理数据
for (let i = 0; i < data.thingsModels.length; i++) {
// 物模型分类放置
if (data.thingsModels[i].datatype.type == 'array') {
if (data.thingsModels[i].datatype.arrayType == 'object' && data.thingsModels[i].datatype
.arrayParams.length > 0) {
// 此时遍历删除
data.thingsModels[i].datatype.arrayParams = data.thingsModels[i].datatype.arrayParams
.filter((item) => item.length > 0);
if (data.thingsModels[i].datatype.arrayParams.length === 0) {
data.thingsModels.splice(i--, 1);
}
}
} else if (data.thingsModels[i].datatype.type == 'object') {
if (data.thingsModels[i].datatype.params.length === 0) {
data.thingsModels.splice(i--, 1);
}
}
}
}
},
// 设备通道
getChannelList(serialNumber) {
this.channelQueryParams.deviceSipId = serialNumber;
return new Promise((resolve, reject) => {
listChannel(this.channelQueryParams).then(response => {
this.channelTotal = response.total;
response.rows.map(item => {
item.statusInfo = getSipStatusInfo(item.status);
return item;
})
resolve(response.rows);
}).catch(error => {
reject(error);
});
});
},
gotoDevicePlayer(deviceSipId, channelSipId, status) {
this.deviceSipId = deviceSipId;
this.channelSipId = channelSipId;
let statusInfo = getSipStatusInfo(status)
if (status !== 3) {
uni.showToast({
icon: 'none',
title: `无法查看${getSipStatusInfo(status).name}数据`
});
return;
}
// #ifdef H5
uni.$u.route('/pages_player/list/devicePlayer', {
deviceId: deviceSipId,
channelSipId: channelSipId,
});
//#endif
// #ifdef APP-PLUS
uni.$u.route('/pages_player/list/devicePlayerWebView', {
deviceId: deviceSipId,
channelSipId: channelSipId,
});
//#endif
// #ifdef MP-WEIXIN
this.isSelect = true;
//#endif
},
gotoPlayer() {
uni.$u.route('/pages_player/list/devicePlayerMpWeixin', {
deviceId: this.deviceSipId,
channelSipId: this.channelSipId,
});
},
//选择时间
gotoDeviceVideo() {
this.showcalendar = true;
},
//录像控制
initCalendar() {
this.defaultDate = new Date();
let minstamp = new Date().getTime() - 1000 * 3600 * 24 * 28 * 6;
let maxstamp = new Date().getTime();
var mindate = new Date(minstamp);
let minmonth = mindate.getMonth() + 1;
let minday = mindate.getDate();
if (minmonth <= 9) {
minmonth = '0' + minmonth;
}
if (minday <= 9) {
minday = '0' + minday;
}
var maxdate = new Date(maxstamp);
let maxmonth = maxdate.getMonth() + 1;
let maxday = maxdate.getDate();
if (maxmonth <= 9) {
maxmonth = '0' + maxmonth;
}
if (maxday <= 9) {
maxday = '0' + maxday;
}
this.minDate = mindate.getFullYear() + '-' + minmonth + '-' + minday;
this.maxDate = maxdate.getFullYear() + '-' + maxmonth + '-' + maxday;
},
// 返回监听
onBackPress(options) {
if (options.from === 'navigateBack') {
return false;
}
uni.switchTab({
url: '/pages/tabBar/home/index'
});
return true;
},
confirmCalendar(n) {
this.playbackDate = n[0];
this.showcalendar = false;
this.queryDate = n;
// this.loadDevRecord();
uni.$u.route('/pages_player/list/devicePlayerMpWeixin', {
deviceId: this.deviceSipId,
channelSipId: this.channelSipId,
videoVod: true,
});
},
closeCalendar(n) {
this.showcalendar = false;
},
}
};
</script>
<style lang="scss">
page {
background: $uni-bg-color-grey;
}
</style>
<style lang="scss" scoped>
.device-detail {
height: 100vh;
width: 100%;
overflow: hidden;
.device-info {
// #ifdef MP-WEIXIN
height: calc(100vh - 168rpx);
// #endif
// #ifndef MP-WEIXIN
height: calc(100vh - 100rpx);
// #endif
}
.device-info-video {
height: 100vh;
}
.device-info-video,
.device-info {
display: flex;
flex-direction: column;
overflow-y: hidden;
.top-wrap {
position: relative;
background-size: cover;
background-image: url('@/static/common/bg.png');
// #ifdef MP-WEIXIN
min-height: 480rpx;
// #endif
// #ifdef H5
min-height: 480rpx;
// #endif
// #ifdef APP-PLUS
min-height: 550rpx;
// #endif
z-index: 0;
.sub-wrap {
//width: 80%;
padding: 32rpx 34rpx;
::v-deep .u-subsection--button {
height: 68rpx;
padding: 8rpx;
}
}
}
.content-wrap {
flex: 1 1 auto;
background: $uni-bg-color-grey;
z-index: 1;
border-top-left-radius: 40rpx;
border-top-right-radius: 40rpx;
//padding: 0 30rpx;
display: flex;
flex-direction: column;
overflow-y: auto;
margin-top: -256rpx;
// #ifndef H5 || APP-PLUS || MP-ALIPAY
margin-top: -178rpx;
// #endif
z-index: 1;
overflow-y: auto;
.device-content {
padding: 28rpx;
.channel_wrap {
.item_body {
position: relative;
display: flex;
align-items: center;
margin-bottom: 15px;
background: #fff;
border-radius: 20rpx;
.img {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 5px;
width: 90px;
height: 60px;
background: #e5e5e5;
margin: 10px;
}
.status {
position: absolute;
right: 13px;
top: 13px;
}
}
}
.base-info {
.card-wrap {
background-color: #fff;
padding: 29rpx 32rpx;
border-radius: 20rpx;
margin-bottom: 24rpx;
.item-right {
display: flex;
flex-direction: row;
}
::v-deep .u-form-item__body {
height: 80rpx;
}
.title-wrap {
display: flex;
padding: 20rpx 0;
border-bottom: 1px solid #efefef;
}
}
}
}
}
}
.trigger-popup-wrap {
padding: 30rpx;
.title {
font-size: 32rpx;
text-align: center;
margin-bottom: 30rpx;
}
.cell-group-wrap {
.cell-wrap {
padding: 6rpx 0;
}
}
}
}
</style>