删除监测统计并取消显示modbus设备

This commit is contained in:
baiying
2024-07-23 11:33:48 +08:00
parent 9aed2047cb
commit ba47af758f
3 changed files with 1329 additions and 1590 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,225 +0,0 @@
<template>
<div style="padding-left: 20px">
<el-row>
<el-col :span="24">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="75px">
<el-form-item label="请选择设备从机:" label-width="120px" v-if="isSubDev">
<el-select v-model="queryParams.slaveId" placeholder="请选择设备从机" @change="selectSlave">
<el-option v-for="slave in slaveList" :key="slave.slaveId" :label="`${slave.deviceName} (${slave.slaveId})`"
:value="slave.slaveId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="时间范围">
<el-date-picker v-model="daterangeTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getListHistory">查询</el-button>
</el-form-item>
</el-form>
</el-col>
<el-col :span="23">
<div v-for="(item, index) in staticList" :key="index" style="margin-bottom: 30px">
<el-card shadow="hover" :body-style="{ padding: '10px 0px', overflow: 'auto' }" v-loading="loading">
<div ref="statisticMap" style="height: 300px; width: 1080px"></div>
</el-card>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { listHistory } from '@/api/iot/deviceLog';
export default {
name: 'device-statistic',
props: {
device: {
type: Object,
default: null,
},
},
watch: {
// 获取到父组件传递的device后
device: function (newVal, oldVal) {
this.deviceInfo = newVal;
if (this.deviceInfo && this.deviceInfo.deviceId != 0) {
this.isSubDev = this.deviceInfo.subDeviceList && this.deviceInfo.subDeviceList.length > 0;
this.queryParams.slaveId = this.deviceInfo.slaveId;
this.queryParams.serialNumber = this.deviceInfo.serialNumber;
this.slaveList = newVal.subDeviceList;
// 监测数据
if (this.isSubDev) {
this.staticList = this.deviceInfo.cacheThingsModel['properties'].filter((item) => {
return item.tempSlaveId == this.queryParams.slaveId;
});
} else {
this.staticList = this.deviceInfo.staticList;
}
// 加载图表
this.$nextTick(function () {
// 绘制图表
this.getStatistic();
});
}
},
},
data() {
return {
loading: true,
// 设备信息
deviceInfo: {},
// 统计物模型
staticList: [],
// 图表集合
chart: [],
// 激活时间范围
daterangeTime: [this.getTime(), this.getTime()],
// 查询参数
queryParams: {
serialNumber: null,
identity: '',
slaveId: undefined,
},
// 对象数组类型物模型暂存数据
arrayData: [],
// 子设备列表
slaveList: [],
isSubDev: false,
};
},
mounted() {
// 获取统计数据
// this.getListHistory();
},
methods: {
/** 获取当前日期 **/
getTime() {
let date = new Date();
let y = date.getFullYear();
let m = date.getMonth() + 1;
let d = date.getDate();
m = m < 10 ? '0' + m : m;
d = d < 10 ? '0' + d : d;
return y + '-' + m + '-' + d;
},
/* 获取监测历史数据*/
getListHistory() {
this.loading = true;
this.queryParams.serialNumber = this.queryParams.slaveId ? this.deviceInfo.serialNumber + '_' + this.queryParams.slaveId : this.deviceInfo.serialNumber;
if (null != this.daterangeTime && '' != this.daterangeTime) {
this.queryParams.beginTime = this.daterangeTime[0];
this.queryParams.endTime = this.daterangeTime[1] + ' 23:59';
}
listHistory(this.queryParams).then((res) => {
for (let key in res.data) {
for (let i = 0; i < this.staticList.length; i++) {
if (key == this.staticList[i].id) {
// 对象转数组
let dataList = [];
for (let j = 0; j < res.data[key].length; j++) {
let item = [];
item[0] = res.data[key][j].time;
item[1] = res.data[key][j].value;
dataList.push(item);
}
// 图表显示数据
this.chart[i].setOption({
series: [
{
data: dataList,
},
],
});
}
}
}
this.loading = false;
});
},
/**监测统计数据 */
getStatistic() {
let color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
for (let i = 0; i < this.staticList.length; i++) {
// 设置宽度
this.$refs.statisticMap[i].style.width = document.documentElement.clientWidth - 510 + 'px';
this.chart[i] = this.$echarts.init(this.$refs.statisticMap[i]);
var option;
option = {
animationDurationUpdate: 3000,
tooltip: {
trigger: 'axis',
},
title: {
left: 'center',
text: this.staticList[i].name + '统计 (单位 ' + (this.staticList[i].datatype && this.staticList[i].datatype.unit != undefined ? this.staticList[i].datatype.unit : '无') + '',
},
grid: {
top: '80px',
left: '50px',
right: '20px',
bottom: '80px',
// containLabel: true,
},
toolbox: {
feature: {
dataZoom: {
yAxisIndex: 'none',
},
restore: {},
saveAsImage: {},
},
},
xAxis: {
type: 'time',
},
yAxis: {
type: 'value',
},
dataZoom: [
{
type: 'inside',
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
series: [
{
name: this.staticList[i].name,
type: 'line',
symbol: 'none',
sampling: 'lttb',
itemStyle: {
color: i > 9 ? color[0] : color[i],
},
areaStyle: {},
data: [],
},
],
};
option && this.chart[i].setOption(option);
}
},
/*选择从机*/
selectSlave() {
this.staticList = this.deviceInfo.cacheThingsModel['properties'].filter((item) => {
return item.tempSlaveId == this.queryParams.slaveId;
});
// 加载图表
this.$nextTick(function () {
// 绘制图表
this.getStatistic();
// 获取统计数据
this.getListHistory();
});
},
},
};
</script>

View File

@@ -1,211 +1,206 @@
<template> <template>
<div style="padding: 6px"> <div style="padding: 6px">
<el-card style="margin-bottom: 6px"> <el-card style="margin-bottom: 6px">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="75px" style="margin-bottom: -20px"> <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="75px" style="margin-bottom: -20px">
<el-form-item label="设备名称" prop="deviceName"> <el-form-item label="设备名称" prop="deviceName">
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable size="small" <el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable size="small" @keyup.enter.native="handleQuery" style="width: 150px" />
@keyup.enter.native="handleQuery" style="width: 150px" /> </el-form-item>
</el-form-item> <el-form-item label="设备编号" prop="serialNumber">
<el-form-item label="设备编号" prop="serialNumber"> <el-input v-model="queryParams.serialNumber" placeholder="请输入设备编号" clearable size="small" @keyup.enter.native="handleQuery" style="width: 150px" />
<el-input v-model="queryParams.serialNumber" placeholder="请输入设备编号" clearable size="small" </el-form-item>
@keyup.enter.native="handleQuery" style="width: 150px" /> <el-form-item label="设备状态" prop="status">
</el-form-item> <el-select v-model="queryParams.status" placeholder="请选择设备状态" clearable size="small" style="width: 150px">
<el-form-item label="设备状态" prop="status"> <el-option v-for="dict in dict.type.iot_device_status" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-select v-model="queryParams.status" placeholder="请选择设备状态" clearable size="small" style="width: 150px"> </el-select>
<el-option v-for="dict in dict.type.iot_device_status" :key="dict.value" :label="dict.label" </el-form-item>
:value="dict.value" /> <el-form-item label="我的分组">
</el-select> <el-select v-model="queryParams.groupId" placeholder="请选择我的分组" clearable size="small" style="width: 150px">
</el-form-item> <el-option v-for="group in myGroupList" :key="group.groupId" :label="group.groupName" :value="group.groupId" />
<el-form-item label="我的分组"> </el-select>
<el-select v-model="queryParams.groupId" placeholder="请选择我的分组" clearable size="small" style="width: 150px"> </el-form-item>
<el-option v-for="group in myGroupList" :key="group.groupId" :label="group.groupName" <el-form-item>
:value="group.groupId" /> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
</el-select> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item style="float: right">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleEditDevice(0)" v-hasPermi="['iot:device:add']">新增</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> <el-button type="primary" plain icon="el-icon-s-grid" size="mini" @click="handleChangeShowType" v-hasPermi="['iot:device:add']">切换</el-button>
</el-form-item> </el-form-item>
<el-form-item style="float: right"> </el-form>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleEditDevice(0)" </el-card>
v-hasPermi="['iot:device:add']">新增</el-button>
<el-button type="primary" plain icon="el-icon-s-grid" size="mini" @click="handleChangeShowType"
v-hasPermi="['iot:device:add']">切换</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="padding-bottom: 100px" v-if="showType == 'list'"> <el-card style="padding-bottom: 100px" v-if="showType == 'list'">
<el-table v-loading="loading" :data="deviceList" border> <el-table v-loading="loading" :data="deviceList" border>
<el-table-column label="编号" align="center" header-align="center" prop="deviceId" width="50" /> <el-table-column label="编号" align="center" header-align="center" prop="deviceId" width="50" />
<el-table-column label="设备名称" align="center" header-align="center" prop="deviceName" min-width="120" /> <el-table-column label="设备名称" align="center" header-align="center" prop="deviceName" min-width="120" />
<el-table-column label="设备编号" align="center" prop="serialNumber" min-width="130" /> <el-table-column label="设备编号" align="center" prop="serialNumber" min-width="130" />
<el-table-column label="所属产品" align="center" prop="productName" min-width="120" /> <el-table-column label="所属产品" align="center" prop="productName" min-width="120" />
<el-table-column label="协议" align="center" prop="transport" min-width="50" /> <el-table-column label="协议" align="center" prop="transport" min-width="50" />
<el-table-column label="通讯协议" align="center" prop="protocolCode" min-width="100" /> <el-table-column label="通讯协议" align="center" prop="protocolCode" min-width="100" />
<el-table-column label="子设备数" align="center" prop="subDeviceCount" width="80"> <el-table-column label="子设备数" align="center" prop="subDeviceCount" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.subDeviceCount }} {{ scope.row.subDeviceCount }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备影子" align="center" prop="isShadow" width="80"> <el-table-column label="设备影子" align="center" prop="isShadow" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag type="success" size="small" v-if="scope.row.isShadow == 1">启用</el-tag> <el-tag type="success" size="small" v-if="scope.row.isShadow == 1">启用</el-tag>
<el-tag type="info" size="small" v-else>禁用</el-tag> <el-tag type="info" size="small" v-else>禁用</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" align="center" prop="status" width="80"> <el-table-column label="状态" align="center" prop="status" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.iot_device_status" :value="scope.row.status" size="small" /> <dict-tag :options="dict.type.iot_device_status" :value="scope.row.status" size="small" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="信号" align="center" prop="rssi" width="60"> <el-table-column label="信号" align="center" prop="rssi" width="60">
<template slot-scope="scope"> <template slot-scope="scope">
<svg-icon v-if="scope.row.status == 3 && scope.row.rssi >= '-55'" icon-class="wifi_4" /> <svg-icon v-if="scope.row.status == 3 && scope.row.rssi >= '-55'" icon-class="wifi_4" />
<svg-icon v-else-if="scope.row.status == 3 && scope.row.rssi >= '-70' && scope.row.rssi < '-55'" <svg-icon v-else-if="scope.row.status == 3 && scope.row.rssi >= '-70' && scope.row.rssi < '-55'" icon-class="wifi_3" />
icon-class="wifi_3" /> <svg-icon v-else-if="scope.row.status == 3 && scope.row.rssi >= '-85' && scope.row.rssi < '-70'" icon-class="wifi_2" />
<svg-icon v-else-if="scope.row.status == 3 && scope.row.rssi >= '-85' && scope.row.rssi < '-70'" <svg-icon v-else-if="scope.row.status == 3 && scope.row.rssi >= '-100' && scope.row.rssi < '-85'" icon-class="wifi_1" />
icon-class="wifi_2" /> <svg-icon v-else icon-class="wifi_0" />
<svg-icon v-else-if="scope.row.status == 3 && scope.row.rssi >= '-100' && scope.row.rssi < '-85'" </template>
icon-class="wifi_1" /> </el-table-column>
<svg-icon v-else icon-class="wifi_0" /> <el-table-column label="定位方式" align="center" prop="locationWay">
</template> <template slot-scope="scope">
</el-table-column> <dict-tag :options="dict.type.iot_location_way" :value="scope.row.locationWay" size="small" />
<el-table-column label="定位方式" align="center" prop="locationWay"> </template>
<template slot-scope="scope"> </el-table-column>
<dict-tag :options="dict.type.iot_location_way" :value="scope.row.locationWay" size="small" /> <el-table-column label="固件版本" align="center" prop="firmwareVersion">
</template> <template slot-scope="scope">
</el-table-column> <el-tag size="mini" type="info">Ver {{ scope.row.firmwareVersion }}</el-tag>
<el-table-column label="固件版本" align="center" prop="firmwareVersion"> </template>
<template slot-scope="scope"> </el-table-column>
<el-tag size="mini" type="info">Ver {{ scope.row.firmwareVersion }}</el-tag> <el-table-column label="激活时间" align="center" prop="activeTime">
</template> <template slot-scope="scope">
</el-table-column> <span>{{ parseTime(scope.row.activeTime, '{y}-{m}-{d}') }}</span>
<el-table-column label="激活时间" align="center" prop="activeTime"> </template>
<template slot-scope="scope"> </el-table-column>
<span>{{ parseTime(scope.row.activeTime, '{y}-{m}-{d}') }}</span> <el-table-column label="创建时间" align="center" prop="createTime">
</template> <template slot-scope="scope">
</el-table-column> <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
<el-table-column label="创建时间" align="center" prop="createTime"> </template>
<template slot-scope="scope"> </el-table-column>
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="danger" size="small" style="padding: 5px" icon="el-icon-delete" <el-button type="danger" size="small" style="padding: 5px" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['iot:device:remove']">删除</el-button>
@click="handleDelete(scope.row)" v-hasPermi="['iot:device:remove']">删除</el-button> <el-button type="primary" size="small" style="padding: 5px" icon="el-icon-view" @click="handleEditDevice(scope.row)" v-hasPermi="['iot:device:add']">查看</el-button>
<el-button type="primary" size="small" style="padding: 5px" icon="el-icon-view" <el-button type="primary" size="small" style="padding: 5px" @click="openSummaryDialog(scope.row)" v-if="form.deviceId != 0">二维码</el-button>
@click="handleEditDevice(scope.row)" v-hasPermi="['iot:device:add']">查看</el-button> </template>
<el-button type="primary" size="small" style="padding: 5px" @click="openSummaryDialog(scope.row)" </el-table-column>
v-if="form.deviceId != 0">二维码</el-button> </el-table>
</template> <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" :pageSizes="[12, 24, 36, 60]" @pagination="getList" />
</el-table-column> </el-card>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
:pageSizes="[12, 24, 36, 60]" @pagination="getList" />
</el-card> <el-card style="padding-bottom: 100px" v-if="showType == 'card'">
<el-row :gutter="30" v-loading="loading">
<el-card style="padding-bottom: 100px" v-if="showType == 'card'"> <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="6" v-for="(item, index) in deviceList" :key="index" style="margin-bottom: 30px; text-align: center">
<el-row :gutter="30" v-loading="loading"> <el-card :body-style="{ padding: '20px' }" shadow="always" class="card-item">
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="6" v-for="(item, index) in deviceList" :key="index" <el-row type="flex" :gutter="10" justify="space-between">
style="margin-bottom: 30px; text-align: center"> <el-col :span="20" style="text-align: left">
<el-card :body-style="{ padding: '20px' }" shadow="always" class="card-item"> <el-link type="" :underline="false" @click="handleEditDevice(item)" style="font-weight: bold; font-size: 16px; line-height: 32px">
<el-row type="flex" :gutter="10" justify="space-between"> <el-tooltip class="item" effect="dark" content="分享的设备" placement="top-start">
<el-col :span="20" style="text-align: left"> <svg-icon icon-class="share" style="font-size: 20px" v-if="item.isOwner != 1" />
<el-link type="" :underline="false" @click="handleEditDevice(item)" </el-tooltip>
style="font-weight: bold; font-size: 16px; line-height: 32px"> <svg-icon icon-class="device" v-if="item.isOwner == 1" />
<el-tooltip class="item" effect="dark" content="分享的设备" placement="top-start"> <span style="margin: 0 5px">{{ item.deviceName }}</span>
<svg-icon icon-class="share" style="font-size: 20px" v-if="item.isOwner != 1" /> <!-- <el-tag size="mini" type="info">Ver {{item.firmwareVersion}}</el-tag>-->
</el-tooltip> <!-- <el-text v-if="item.protocolCode" type="info" size="mini" style="font-size: 14px; color: #ccc">{{ item.protocolCode }}</el-text> -->
<svg-icon icon-class="device" v-if="item.isOwner == 1" /> </el-link>
<span style="margin: 0 5px">{{ item.deviceName }}</span> </el-col>
<!-- <el-tag size="mini" type="info">Ver {{item.firmwareVersion}}</el-tag>--> <el-col :span="1.5" style="font-size: 20px; padding-top: 5px; cursor: pointer">
<!-- <el-text v-if="item.protocolCode" type="info" size="mini" style="font-size: 14px; color: #ccc">{{ item.protocolCode }}</el-text> --> <svg-icon icon-class="qrcode" @click="openSummaryDialog(item)" />
</el-link> </el-col>
</el-col> <el-col :span="3">
<el-col :span="1.5" style="font-size: 20px; padding-top: 5px; cursor: pointer"> <div style="font-size: 28px; color: #ccc">
<svg-icon icon-class="qrcode" @click="openSummaryDialog(item)" /> <svg-icon v-if="item.status == 3 && item.rssi >= '-55'" icon-class="wifi_4" />
</el-col> <svg-icon v-else-if="item.status == 3 && item.rssi >= '-70' && item.rssi < '-55'" icon-class="wifi_3" />
<el-col :span="3"> <svg-icon v-else-if="item.status == 3 && item.rssi >= '-85' && item.rssi < '-70'" icon-class="wifi_2" />
<div style="font-size: 28px; color: #ccc"> <svg-icon v-else-if="item.status == 3 && item.rssi >= '-100' && item.rssi < '-85'" icon-class="wifi_1" />
<svg-icon v-if="item.status == 3 && item.rssi >= '-55'" icon-class="wifi_4" /> <svg-icon v-else icon-class="wifi_0" />
<svg-icon v-else-if="item.status == 3 && item.rssi >= '-70' && item.rssi < '-55'" icon-class="wifi_3" /> </div>
<svg-icon v-else-if="item.status == 3 && item.rssi >= '-85' && item.rssi < '-70'" icon-class="wifi_2" /> </el-col>
<svg-icon v-else-if="item.status == 3 && item.rssi >= '-100' && item.rssi < '-85'" </el-row>
icon-class="wifi_1" /> <el-row :gutter="10">
<svg-icon v-else icon-class="wifi_0" /> <el-col :span="17">
</div> <div style="text-align: left; line-height: 40px; white-space: nowrap">
</el-col> <dict-tag :options="dict.type.iot_device_status" :value="item.status" size="small" style="display: inline-block" />
</el-row> <span style="display: inline-block; margin: 0 10px">
<el-row :gutter="10"> <!-- <el-tag type="success" size="small" v-if="item.isShadow == 1">影子</el-tag>
<el-col :span="17">
<div style="text-align: left; line-height: 40px; white-space: nowrap">
<dict-tag :options="dict.type.iot_device_status" :value="item.status" size="small"
style="display: inline-block" />
<span style="display: inline-block; margin: 0 10px">
<!-- <el-tag type="success" size="small" v-if="item.isShadow == 1">影子</el-tag>
<el-tag type="info" size="small" v-else>影子</el-tag> --> <el-tag type="info" size="small" v-else>影子</el-tag> -->
<el-tag type="primary" size="small" v-if="item.protocolCode">{{ item.protocolCode }}</el-tag> <el-tag type="primary" size="small" v-if="item.protocolCode">{{ item.protocolCode }}</el-tag>
</span> </span>
<el-tag type="primary" size="small" v-if="item.transport">{{ item.transport }}</el-tag> <el-tag type="primary" size="small" v-if="item.transport">{{ item.transport }}</el-tag>
<!-- <dict-tag :options="dict.type.iot_location_way" :value="item.locationWay" size="small" style="display:inline-block;" /> --> <!-- <dict-tag :options="dict.type.iot_location_way" :value="item.locationWay" size="small" style="display:inline-block;" /> -->
<!-- <dict-tag :options="dict.type.iot_transport_type" :value="item.transport" size="small" style="display: inline-block" /> --> <!-- <dict-tag :options="dict.type.iot_transport_type" :value="item.transport" size="small" style="display: inline-block" /> -->
</div> </div>
<el-descriptions :column="1" size="mini" style="white-space: nowrap"> <el-descriptions :column="1" size="mini" style="white-space: nowrap">
<el-descriptions-item label="编号"> <el-descriptions-item label="编号">
{{ item.serialNumber }} {{ item.serialNumber }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="产品"> <el-descriptions-item label="产品">
{{ item.productName }} {{ item.productName }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="激活时间"> <el-descriptions-item label="激活时间">
{{ parseTime(item.activeTime, '{y}-{m}-{d}') }} {{ parseTime(item.activeTime, '{y}-{m}-{d}') }}
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</el-col> </el-col>
<el-col :span="7"> <el-col :span="7">
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-image style="width: 100%; height: 100px; border-radius: 10px" lazy <el-image
:preview-src-list="[baseUrl + item.imgUrl]" :src="baseUrl + item.imgUrl" fit="cover" style="width: 100%; height: 100px; border-radius: 10px"
v-if="item.imgUrl != null && item.imgUrl != ''"></el-image> lazy
<el-image style="width: 100%; height: 100px; border-radius: 10px" :preview-src-list="[baseUrl + item.imgUrl]"
:preview-src-list="[require('@/assets/images/gateway.png')]" :src="baseUrl + item.imgUrl"
:src="require('@/assets/images/gateway.png')" fit="cover" v-else-if="item.deviceType == 2"></el-image> fit="cover"
<el-image style="width: 100%; height: 100px; border-radius: 10px" v-if="item.imgUrl != null && item.imgUrl != ''"
:preview-src-list="[require('@/assets/images/video.png')]" :src="require('@/assets/images/video.png')" ></el-image>
fit="cover" v-else-if="item.deviceType == 3"></el-image> <el-image
<el-image style="width: 100%; height: 100px; border-radius: 10px" style="width: 100%; height: 100px; border-radius: 10px"
:preview-src-list="[require('@/assets/images/product.png')]" :preview-src-list="[require('@/assets/images/gateway.png')]"
:src="require('@/assets/images/product.png')" fit="cover" v-else></el-image> :src="require('@/assets/images/gateway.png')"
</div> fit="cover"
</el-col> v-else-if="item.deviceType == 2"
></el-image>
<el-image
style="width: 100%; height: 100px; border-radius: 10px"
:preview-src-list="[require('@/assets/images/video.png')]"
:src="require('@/assets/images/video.png')"
fit="cover"
v-else-if="item.deviceType == 3"
></el-image>
<el-image
style="width: 100%; height: 100px; border-radius: 10px"
:preview-src-list="[require('@/assets/images/product.png')]"
:src="require('@/assets/images/product.png')"
fit="cover"
v-else
></el-image>
</div>
</el-col>
</el-row>
<el-button-group style="margin-top: 15px">
<el-button type="danger" size="mini" style="padding: 5px 10px" icon="el-icon-delete" @click="handleDelete(item)" v-hasPermi="['iot:device:remove']">删除</el-button>
<el-button type="primary" size="mini" style="padding: 5px 15px" icon="el-icon-view" @click="handleEditDevice(item, 'basic')" v-hasPermi="['iot:device:add']">查看</el-button>
<el-button type="success" size="mini" style="padding: 5px 15px" icon="el-icon-odometer" @click="handleRunDevice(item)" v-hasPermi="['iot:device:add']">运行状态</el-button>
</el-button-group>
</el-card>
</el-col>
</el-row> </el-row>
<el-button-group style="margin-top: 15px"> <el-empty description="暂无数据,请添加设备" v-if="total == 0"></el-empty>
<el-button type="danger" size="mini" style="padding: 5px 10px" icon="el-icon-delete" <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" :pageSizes="[12, 24, 36, 60]" @pagination="getList" />
@click="handleDelete(item)" v-hasPermi="['iot:device:remove']">删除</el-button> </el-card>
<el-button type="primary" size="mini" style="padding: 5px 15px" icon="el-icon-view" <!-- 二维码 -->
@click="handleEditDevice(item, 'basic')" v-hasPermi="['iot:device:add']">查看</el-button> <el-dialog :visible.sync="openSummary" width="300px" append-to-body>
<el-button type="success" size="mini" style="padding: 5px 15px" icon="el-icon-odometer" <div style="border: 1px solid #ccc; width: 220px; text-align: center; margin: 0 auto; margin-top: -15px">
@click="handleRunDevice(item)" v-hasPermi="['iot:device:add']">运行状态</el-button> <vue-qr :text="qrText" :size="200"></vue-qr>
</el-button-group> <div style="padding-bottom: 10px">设备二维码</div>
</el-card> </div>
</el-col> </el-dialog>
</el-row> </div>
<el-empty description="暂无数据,请添加设备" v-if="total == 0"></el-empty>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
:pageSizes="[12, 24, 36, 60]" @pagination="getList" />
</el-card>
<!-- 二维码 -->
<el-dialog :visible.sync="openSummary" width="300px" append-to-body>
<div style="border: 1px solid #ccc; width: 220px; text-align: center; margin: 0 auto; margin-top: -15px">
<vue-qr :text="qrText" :size="200"></vue-qr>
<div style="padding-bottom: 10px">设备二维码</div>
</div>
</el-dialog>
</div>
</template> </template>
<script> <script>
@@ -215,296 +210,297 @@ import { listGroup } from '@/api/iot/group';
import { delSipDeviceBySipId } from '@/api/iot/sipdevice'; import { delSipDeviceBySipId } from '@/api/iot/sipdevice';
export default { export default {
name: 'Device', name: 'Device',
dicts: ['iot_device_status', 'iot_is_enable', 'iot_location_way', 'iot_transport_type'], dicts: ['iot_device_status', 'iot_is_enable', 'iot_location_way', 'iot_transport_type'],
components: { components: {
vueQr, vueQr,
},
data() {
return {
// 二维码内容
qrText: 'fastbee',
// 打开设备配置对话框
openSummary: false,
// 展示方式
showType: 'card',
// 遮罩层
loading: true,
// 总条数
total: 0,
// 设备列表数据
deviceList: [],
// 我的分组列表数据
myGroupList: [],
// 根路径
baseUrl: process.env.VUE_APP_BASE_API,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 12,
deviceName: null,
productId: null,
groupId: null,
productName: null,
userId: null,
userName: null,
tenantId: null,
tenantName: null,
serialNumber: null,
status: null,
networkAddress: null,
activeTime: null,
},
// 表单参数
form: {
productId: 0,
status: 1,
locationWay: 1,
firmwareVersion: 1.0,
serialNumber: '',
deviceType: 1,
isSimulate: 0,
},
isSubDev: false,
};
},
created() {
// 产品筛选
let productId = this.$route.query.productId;
if (productId != null) {
this.queryParams.productId = Number(productId);
this.queryParams.groupId = null;
this.queryParams.serialNumber = null;
}
// 分组筛选
let groupId = this.$route.query.groupId;
if (groupId != null) {
this.queryParams.groupId = Number(groupId);
this.queryParams.productId = null;
this.queryParams.serialNumber = null;
}
// 设备编号筛选
let sn = this.$route.query.sn;
if (sn != null) {
this.queryParams.serialNumber = sn;
this.queryParams.productId = null;
this.queryParams.groupId = null;
}
this.connectMqtt();
},
activated() {
const time = this.$route.query.t;
if (time != null && time != this.uniqueId) {
this.uniqueId = time;
// 页码筛选
let pageNum = this.$route.query.pageNum;
if (pageNum != null) {
this.queryParams.pageNum = Number(pageNum);
}
// 产品筛选
let productId = this.$route.query.productId;
if (productId != null) {
this.queryParams.productId = Number(productId);
this.queryParams.groupId = null;
this.queryParams.serialNumber = null;
}
// 分组筛选
let groupId = this.$route.query.groupId;
if (groupId != null) {
this.queryParams.groupId = Number(groupId);
this.queryParams.productId = null;
this.queryParams.serialNumber = null;
}
// 设备编号筛选
let sn = this.$route.query.sn;
if (sn != null) {
this.queryParams.serialNumber = sn;
this.queryParams.productId = null;
this.queryParams.groupId = null;
}
this.getList();
}
},
methods: {
/* 连接Mqtt消息服务器 */
async connectMqtt() {
if (this.$mqttTool.client == null) {
await this.$mqttTool.connect();
}
this.mqttCallback();
this.getList();
}, },
/* Mqtt回调处理 */ data() {
mqttCallback() { return {
this.$mqttTool.client.on('message', (topic, message, buffer) => { // 二维码内容
let topics = topic.split('/'); qrText: 'fastbee',
let productId = topics[1]; // 打开设备配置对话框
let deviceNum = topics[2]; openSummary: false,
message = JSON.parse(message.toString()); // 展示方式
if (!message) { showType: 'card',
return; // 遮罩层
loading: true,
// 总条数
total: 0,
// 设备列表数据
deviceList: [],
// 我的分组列表数据
myGroupList: [],
// 根路径
baseUrl: process.env.VUE_APP_BASE_API,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 12,
deviceName: null,
productId: null,
groupId: null,
productName: null,
userId: null,
userName: null,
tenantId: null,
tenantName: null,
serialNumber: null,
status: null,
networkAddress: null,
activeTime: null,
},
// 表单参数
form: {
productId: 0,
status: 1,
locationWay: 1,
firmwareVersion: 1.0,
serialNumber: '',
deviceType: 1,
isSimulate: 0,
},
isSubDev: false,
};
},
created() {
// 产品筛选
let productId = this.$route.query.productId;
if (productId != null) {
this.queryParams.productId = Number(productId);
this.queryParams.groupId = null;
this.queryParams.serialNumber = null;
} }
if (topics[3] == 'status') { // 分组筛选
console.log('接收到【设备状态】主题:', topic); let groupId = this.$route.query.groupId;
console.log('接收到【设备状态】内容:', message); if (groupId != null) {
// 更新列表中设备的状态 this.queryParams.groupId = Number(groupId);
for (let i = 0; i < this.deviceList.length; i++) { this.queryParams.productId = null;
if (this.deviceList[i].serialNumber == deviceNum) { this.queryParams.serialNumber = null;
this.deviceList[i].status = message.status; }
this.deviceList[i].isShadow = message.isShadow; // 设备编号筛选
this.deviceList[i].rssi = message.rssi; let sn = this.$route.query.sn;
return; if (sn != null) {
this.queryParams.serialNumber = sn;
this.queryParams.productId = null;
this.queryParams.groupId = null;
}
this.connectMqtt();
},
activated() {
const time = this.$route.query.t;
if (time != null && time != this.uniqueId) {
this.uniqueId = time;
// 页码筛选
let pageNum = this.$route.query.pageNum;
if (pageNum != null) {
this.queryParams.pageNum = Number(pageNum);
} }
} // 产品筛选
let productId = this.$route.query.productId;
if (productId != null) {
this.queryParams.productId = Number(productId);
this.queryParams.groupId = null;
this.queryParams.serialNumber = null;
}
// 分组筛选
let groupId = this.$route.query.groupId;
if (groupId != null) {
this.queryParams.groupId = Number(groupId);
this.queryParams.productId = null;
this.queryParams.serialNumber = null;
}
// 设备编号筛选
let sn = this.$route.query.sn;
if (sn != null) {
this.queryParams.serialNumber = sn;
this.queryParams.productId = null;
this.queryParams.groupId = null;
}
this.getList();
} }
});
}, },
openSummaryDialog(row) { methods: {
let json = { /* 连接Mqtt消息服务器 */
type: 1, // 1=扫码关联设备 async connectMqtt() {
deviceNumber: row.serialNumber, if (this.$mqttTool.client == null) {
productId: row.productId, await this.$mqttTool.connect();
productName: row.productName, }
}; this.mqttCallback();
this.qrText = JSON.stringify(json); this.getList();
this.openSummary = true; },
}, /* Mqtt回调处理 */
/* 订阅消息 */ mqttCallback() {
mqttSubscribe(list) { this.$mqttTool.client.on('message', (topic, message, buffer) => {
// 订阅当前页面设备状态和实时监测 let topics = topic.split('/');
let topics = []; let productId = topics[1];
for (let i = 0; i < list.length; i++) { let deviceNum = topics[2];
let topicStatus = '/' + '+' + '/' + list[i].serialNumber + '/status/post'; message = JSON.parse(message.toString());
topics.push(topicStatus); if (!message) {
} return;
this.$mqttTool.subscribe(topics); }
}, if (topics[3] == 'status') {
/** 查询设备分组列表 */ console.log('接收到【设备状态】主题:', topic);
getGroupList() { console.log('接收到【设备状态】内容:', message);
this.loading = true; // 更新列表中设备的状态
let queryParams = { for (let i = 0; i < this.deviceList.length; i++) {
pageSize: 30, if (this.deviceList[i].serialNumber == deviceNum) {
pageNum: 1, this.deviceList[i].status = message.status;
userId: this.$store.state.user.userId, this.deviceList[i].isShadow = message.isShadow;
}; this.deviceList[i].rssi = message.rssi;
listGroup(queryParams).then((response) => { return;
this.myGroupList = response.rows; }
}); }
}, }
/** 查询所有简短设备列表 */ });
getList() { },
this.loading = true; openSummaryDialog(row) {
this.queryParams.params = {}; let json = {
this.getGroupList(); type: 1, // 1=扫码关联设备
listDeviceShort(this.queryParams).then((response) => { deviceNumber: row.serialNumber,
this.deviceList = response.rows; productId: row.productId,
this.total = response.total; productName: row.productName,
// 订阅消息 };
if (this.deviceList && this.deviceList.length > 0) { this.qrText = JSON.stringify(json);
this.mqttSubscribe(this.deviceList); this.openSummary = true;
} },
this.loading = false; /* 订阅消息 */
}); mqttSubscribe(list) {
}, // 订阅当前页面设备状态和实时监测
/** 搜索按钮操作 */ let topics = [];
handleQuery() { for (let i = 0; i < list.length; i++) {
this.queryParams.pageNum = 1; let topicStatus = '/' + '+' + '/' + list[i].serialNumber + '/status/post';
this.getList(); topics.push(topicStatus);
}, }
/** 重置按钮操作 */ this.$mqttTool.subscribe(topics);
resetQuery() { },
this.queryParams.productId = null; /** 查询设备分组列表 */
this.queryParams.groupId = null; getGroupList() {
this.queryParams.serialNumber = null; this.loading = true;
this.resetForm('queryForm'); let queryParams = {
this.handleQuery(); pageSize: 30,
}, pageNum: 1,
/** 切换显示方式 */ userId: this.$store.state.user.userId,
handleChangeShowType() { };
this.showType = this.showType == 'card' ? 'list' : 'card'; listGroup(queryParams).then((response) => {
}, this.myGroupList = response.rows;
/** 修改按钮操作 */ });
handleEditDevice(row, activeName) { },
let deviceId = 0; /** 查询所有简短设备列表 */
let isSubDev = 0; getList() {
if (row != 0) { this.loading = true;
deviceId = row.deviceId || this.ids; this.queryParams.params = {};
isSubDev = row.subDeviceCount > 0 ? 1 : 0; this.getGroupList();
} listDeviceShort(this.queryParams).then((response) => {
this.$router.push({ this.deviceList = response.rows;
path: '/iot/device-edit', this.total = response.total;
query: { // 订阅消息
deviceId: deviceId, if (this.deviceList && this.deviceList.length > 0) {
isSubDev: isSubDev, this.mqttSubscribe(this.deviceList);
pageNum: this.queryParams.pageNum, }
activeName: activeName, this.deviceList = this.deviceList.filter((device) => device.deviceId !== 118);
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams.productId = null;
this.queryParams.groupId = null;
this.queryParams.serialNumber = null;
this.resetForm('queryForm');
this.handleQuery();
},
/** 切换显示方式 */
handleChangeShowType() {
this.showType = this.showType == 'card' ? 'list' : 'card';
},
/** 修改按钮操作 */
handleEditDevice(row, activeName) {
let deviceId = 0;
let isSubDev = 0;
if (row != 0) {
deviceId = row.deviceId || this.ids;
isSubDev = row.subDeviceCount > 0 ? 1 : 0;
}
this.$router.push({
path: '/iot/device-edit',
query: {
deviceId: deviceId,
isSubDev: isSubDev,
pageNum: this.queryParams.pageNum,
activeName: activeName,
},
});
},
/** 运行状态按钮操作 */
handleRunDevice(row) {
let deviceId = 0;
let isSubDev = 0;
if (row != 0) {
deviceId = row.deviceId || this.ids;
isSubDev = row.subDeviceCount > 0 ? 1 : 0;
}
if (row.deviceType === 3) {
this.$router.push({
path: '/iot/device-edit',
query: {
deviceId: deviceId,
isSubDev: isSubDev,
pageNum: this.queryParams.pageNum,
activeName: 'sipChannel',
},
});
} else {
this.$router.push({
path: '/iot/device-edit',
query: {
deviceId: deviceId,
isSubDev: isSubDev,
pageNum: this.queryParams.pageNum,
activeName: 'runningStatus',
},
});
}
},
/** 删除按钮操作 */
handleDelete(row) {
const deviceIds = row.deviceId || this.ids;
this.$modal
.confirm('是否确认删除设备编号为"' + deviceIds + '"的数据项?')
.then(function () {
if (row.deviceType === 3) {
delSipDeviceBySipId(row.serialNumber);
}
return delDevice(deviceIds);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
/** 未启用设备影子*/
shadowUnEnable(device, thingsModel) {
// 1-未激活2-禁用3-在线4-离线
if (device.status != 3 && device.isShadow == 0) {
return true;
}
if (thingsModel.isReadonly) {
return true;
}
return false;
}, },
});
}, },
/** 运行状态按钮操作 */
handleRunDevice(row) {
let deviceId = 0;
let isSubDev = 0;
if (row != 0) {
deviceId = row.deviceId || this.ids;
isSubDev = row.subDeviceCount > 0 ? 1 : 0;
}
if (row.deviceType === 3) {
this.$router.push({
path: '/iot/device-edit',
query: {
deviceId: deviceId,
isSubDev: isSubDev,
pageNum: this.queryParams.pageNum,
activeName: 'sipChannel',
},
});
} else {
this.$router.push({
path: '/iot/device-edit',
query: {
deviceId: deviceId,
isSubDev: isSubDev,
pageNum: this.queryParams.pageNum,
activeName: 'runningStatus',
},
});
}
},
/** 删除按钮操作 */
handleDelete(row) {
const deviceIds = row.deviceId || this.ids;
this.$modal
.confirm('是否确认删除设备编号为"' + deviceIds + '"的数据项?')
.then(function () {
if (row.deviceType === 3) {
delSipDeviceBySipId(row.serialNumber);
}
return delDevice(deviceIds);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => { });
},
/** 未启用设备影子*/
shadowUnEnable(device, thingsModel) {
// 1-未激活2-禁用3-在线4-离线
if (device.status != 3 && device.isShadow == 0) {
return true;
}
if (thingsModel.isReadonly) {
return true;
}
return false;
},
},
}; };
</script> </script>
<style scoped> <style scoped>
.card-item { .card-item {
border-radius: 15px; border-radius: 15px;
} }
</style> </style>