607 lines
17 KiB
Vue
607 lines
17 KiB
Vue
<template>
|
|
<div class="e-object-device-manage-table">
|
|
<el-form
|
|
:model="queryParams"
|
|
ref="queryForm"
|
|
:inline="true"
|
|
label-width="68px"
|
|
v-show="showChildrenView === false"
|
|
>
|
|
<el-row>
|
|
<el-col :span="5">
|
|
<el-form-item label="型号名称" prop="prodKey">
|
|
<el-select
|
|
v-model="queryParams.prodKey"
|
|
placeholder="请选择项目类型"
|
|
clearable
|
|
size="small"
|
|
>
|
|
<el-option
|
|
v-for="dict in projectModelList"
|
|
:key="dict.prodKey"
|
|
:label="dict.modelName"
|
|
:value="dict.prodKey"
|
|
></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="5">
|
|
<el-form-item label="设备名称" prop="deviceName">
|
|
<el-input
|
|
v-model="queryParams.deviceName"
|
|
placeholder="请输入设备名称"
|
|
clearable
|
|
size="small"
|
|
/>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="5">
|
|
<el-form-item label="设备状态" prop="deviceState">
|
|
<el-select
|
|
v-model="queryParams.deviceState"
|
|
placeholder="请选择设备状态"
|
|
clearable
|
|
size="small"
|
|
>
|
|
<el-option
|
|
:label="keys"
|
|
v-for="(keys, vals) in deviceStatusOpt"
|
|
:key="vals"
|
|
:value="vals"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-col>
|
|
<!-- <el-col :span="5">
|
|
<el-form-item label="设备类型" prop="deviceStatus">
|
|
<el-input
|
|
v-model="queryParams.deviceStatus"
|
|
placeholder="请输入设备类型"
|
|
clearable
|
|
size="small"
|
|
/>
|
|
</el-form-item>
|
|
</el-col> -->
|
|
|
|
<el-col :span="4">
|
|
<el-form-item class="query-foot">
|
|
<el-button
|
|
type="primary"
|
|
icon="el-icon-search"
|
|
size="small"
|
|
@click="handleQuery"
|
|
>搜索</el-button
|
|
>
|
|
<el-button icon="el-icon-refresh" size="small" @click="resetQuery"
|
|
>重置</el-button
|
|
>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</el-form>
|
|
<div class="table-container" v-show="showChildrenView === false">
|
|
<e-simple-card
|
|
title=""
|
|
extra=""
|
|
class="object-device-card"
|
|
v-for="(devItem, idx) in list"
|
|
:key="idx"
|
|
>
|
|
<template slot="cardHeader" class="card-custom-head">
|
|
<div
|
|
:class="
|
|
devItem['deviceState'] == 'ONLINE'
|
|
? 'card-left'
|
|
: 'card-left off-line'
|
|
"
|
|
>
|
|
<icon
|
|
v-if="devItem['deviceState'] == 'ONLINE'"
|
|
class="iconfont iconSYS_STA_1"
|
|
/>
|
|
<icon v-else class="iconfont iconlixian" />
|
|
<span style="margin-left: 8px">{{
|
|
devItem["deviceState"] == "ONLINE" ? "在线" : "离线"
|
|
}}</span>
|
|
</div>
|
|
<div class="card-right">
|
|
<span class="c-label">线路数:</span>
|
|
<span class="c-number">{{ devItem.routeCount || 0 }}</span>
|
|
|
|
<el-dropdown>
|
|
<icon class="el-icon-s-operation card-opt-i" />
|
|
<el-dropdown-menu slot="dropdown">
|
|
<el-dropdown-item @click.native="handleChildrenDevice(devItem)"
|
|
>查看线路列表</el-dropdown-item
|
|
>
|
|
<!-- <el-dropdown-item>修改服务指向</el-dropdown-item>
|
|
<el-dropdown-item>设备巡检记录</el-dropdown-item> -->
|
|
<el-dropdown-item @click.native="handleLinkToDeviceDetails(devItem)">设备参数调整</el-dropdown-item>
|
|
<!-- <el-dropdown-item>内置定时配置</el-dropdown-item> -->
|
|
</el-dropdown-menu>
|
|
</el-dropdown>
|
|
</div>
|
|
</template>
|
|
<template slot="cardBody">
|
|
<div class="object-device-body">
|
|
<div class="card-body-info">
|
|
<div class="card-body-left">
|
|
<img
|
|
:src="
|
|
devItem['deviceImage']
|
|
? getIotFileUrl(devItem['deviceImage'])
|
|
: '/images/devcie_default.png'
|
|
"
|
|
/>
|
|
</div>
|
|
<div class="card-body-right">
|
|
<span :title="devItem.deviceName">{{
|
|
devItem.deviceName
|
|
}}</span>
|
|
<span :title="devItem.deviceKey">{{ devItem.deviceKey }}</span>
|
|
<span :title="devItem.deviceAddress">{{
|
|
devItem.deviceAddress
|
|
}}</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-body-footer">
|
|
<!-- {{ renderCardFooter(devItem) }} -->
|
|
<div
|
|
:class="
|
|
devItem.alarmProcessStatus == 1
|
|
? 'card-footer'
|
|
: 'card-footer dev-error'
|
|
"
|
|
>
|
|
<icon class="iconfont icontongzhi"></icon>
|
|
<span stle="margin-left: 10px;" class="footer-title">{{
|
|
devItem.alarmProcessStatus == 1
|
|
? "正常"
|
|
: `时间:${devItem.alarmTime} ${
|
|
devItem.alarmTypeName || "--"
|
|
}`
|
|
}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</e-simple-card>
|
|
<div
|
|
v-if="!list || list.length <= 0"
|
|
style="
|
|
width: 100%;
|
|
height: 300px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
"
|
|
>
|
|
暂无数据
|
|
</div>
|
|
</div>
|
|
<div v-if="showChildrenView">
|
|
<e-device-children
|
|
:gatewayDevice="showGatewayInfo"
|
|
:sourceId="sourceId"
|
|
:deviceType="deviceType"
|
|
@handleLinkToHome="handleLinkToHome"
|
|
></e-device-children>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import ESimpleCard from "@/components/Cards/index";
|
|
import EDeviceChildren from "./EDeviceChildren";
|
|
import { webSocketProjectGatewayUrl } from "@/config/env";
|
|
import { listProjectDevice, listProjectModel } from "@/api/iot/project_new";
|
|
import { getIotFileUrl } from "@/utils/hciot";
|
|
const deviceStatusOpt = {
|
|
ONLINE: "在线",
|
|
OFFLINE: "离线",
|
|
OUTLINE: "脱线",
|
|
UNACTIVE: "未激活",
|
|
};
|
|
export default {
|
|
name: "EDeviceTable",
|
|
components: {
|
|
ESimpleCard,
|
|
EDeviceChildren,
|
|
},
|
|
props: {
|
|
sourceId: {
|
|
type: [String, Number],
|
|
require: true,
|
|
},
|
|
deviceType: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
deviceStatusOpt,
|
|
queryParams: {
|
|
prodKey: undefined,
|
|
deviceName: undefined,
|
|
deviceStatus: undefined,
|
|
},
|
|
showChildrenView: false,
|
|
list: [],
|
|
mockerList: [
|
|
{
|
|
createTime: "2022-07-27 16:33:58",
|
|
deviceAddress: "福建省福州市闽侯县甘蔗街道闽侯榕新工艺有限公司",
|
|
deviceId: "821d1121a4bf426883a5266f12f8b758",
|
|
deviceKey: "ceshixinzeng",
|
|
deviceName: "ceshixinzeng",
|
|
deviceSecret: "bc6eafae957b43f682d6eaef56aac988",
|
|
deviceState: "UNACTIVE",
|
|
deviceStatus: "0",
|
|
deviceType: "GATEWAY_CONTROLLER",
|
|
deviceTypeName: "物联网网关",
|
|
modelId: "03e27dec4cb6464c809906fa41ddf7dc",
|
|
modelName: "网关-测试型号0513",
|
|
prodKey: "testpk220513",
|
|
updateTime: "2022-07-27 16:33:59",
|
|
parentId: "0",
|
|
},
|
|
{
|
|
createTime: "2022-07-27 16:33:58",
|
|
deviceAddress: "福建省福州市闽侯县甘蔗街道闽侯榕新工艺有限公司",
|
|
deviceId: "821d1121a4bf426883a5266f12f8b758",
|
|
deviceKey: "ceshixinzeng",
|
|
deviceName: "ceshixinzeng",
|
|
deviceSecret: "bc6eafae957b43f682d6eaef56aac988",
|
|
deviceState: "UNACTIVE",
|
|
deviceStatus: "1",
|
|
deviceType: "GATEWAY_CONTROLLER",
|
|
deviceTypeName: "物联网网关",
|
|
modelId: "03e27dec4cb6464c809906fa41ddf7dc",
|
|
modelName: "网关-测试型号0513",
|
|
prodKey: "testpk220513",
|
|
updateTime: "2022-07-27 16:33:59",
|
|
parentId: "0",
|
|
},
|
|
{
|
|
createTime: "2022-07-27 16:33:58",
|
|
deviceAddress: "福建省福州市闽侯县甘蔗街道闽侯榕新工艺有限公司",
|
|
deviceId: "821d1121a4bf426883a5266f12f8b758",
|
|
deviceKey: "ceshixinzeng",
|
|
deviceName: "ceshixinzeng",
|
|
deviceSecret: "bc6eafae957b43f682d6eaef56aac988",
|
|
deviceState: "ONLINE",
|
|
deviceStatus: "0",
|
|
deviceType: "GATEWAY_CONTROLLER",
|
|
deviceTypeName: "物联网网关",
|
|
modelId: "03e27dec4cb6464c809906fa41ddf7dc",
|
|
modelName: "网关-测试型号0513",
|
|
prodKey: "testpk220513",
|
|
updateTime: "2022-07-27 16:33:59",
|
|
parentId: "0",
|
|
},
|
|
],
|
|
showGatewayInfo: {},
|
|
projectModelList: [],
|
|
stompClient: null,
|
|
socket_flag: true,
|
|
timeout_flag: null,
|
|
};
|
|
},
|
|
watch: {
|
|
sourceId(val) {
|
|
if (val) {
|
|
this.initHTML();
|
|
this.showChildrenView = false;
|
|
}
|
|
},
|
|
deviceType(val) {
|
|
if (val) {
|
|
this.initHTML();
|
|
}
|
|
},
|
|
},
|
|
created() {
|
|
this.initHTML();
|
|
},
|
|
methods: {
|
|
getIotFileUrl,
|
|
// init html
|
|
initHTML() {
|
|
this.getGatewayList();
|
|
this.getProjectModelList();
|
|
},
|
|
// 查看子设备列表信息
|
|
handleChildrenDevice(gatewayDevice) {
|
|
this.showChildrenView = true;
|
|
this.showGatewayInfo = gatewayDevice;
|
|
this.$forceUpdate();
|
|
},
|
|
// 子设备列表 返回 网关设备列表
|
|
handleLinkToHome() {
|
|
this.showChildrenView = false;
|
|
},
|
|
// 内容部分
|
|
renderCardContent(item) {
|
|
return (
|
|
<template>
|
|
<div class="card-body-left">
|
|
<image
|
|
src={
|
|
item["deviceImage"]
|
|
? item["deviceImage"]
|
|
: "/images/devcie_default.png"
|
|
}
|
|
></image>
|
|
</div>
|
|
<div class="card-body-right">
|
|
<span>{item.deviceId}</span>
|
|
<span>{item.deviceSecret}</span>
|
|
<span>{item.deviceAddress}</span>
|
|
</div>
|
|
</template>
|
|
);
|
|
},
|
|
// 卡片 底部 报警状态
|
|
renderCardFooter(item) {
|
|
return (
|
|
<template>
|
|
<div
|
|
class={
|
|
item.deviceStatus == 0 ? "card-footer" : "card-footer dev-error"
|
|
}
|
|
>
|
|
<icon class="iconfont icontongzhi"></icon>
|
|
<span>
|
|
{item.deviceStatus == 0 ? "正常" : "card-footer dev-error"}
|
|
</span>
|
|
</div>
|
|
</template>
|
|
);
|
|
},
|
|
handleQuery() {
|
|
this.getGatewayList();
|
|
},
|
|
resetQuery() {
|
|
this.resetForm("queryForm");
|
|
this.getGatewayList();
|
|
},
|
|
// 获取 项目 型号列表
|
|
getProjectModelList() {
|
|
listProjectModel({
|
|
projectId: this.sourceId,
|
|
deviceTags: this.deviceType || "",
|
|
}).then((res) => {
|
|
this.projectModelList = res.data;
|
|
});
|
|
},
|
|
// 获取 项目网关设备列表
|
|
getGatewayList() {
|
|
this.list = [];
|
|
listProjectDevice(
|
|
Object.assign(
|
|
{
|
|
projectId: this.sourceId,
|
|
deviceTags: this.deviceType || "",
|
|
},
|
|
this.queryParams
|
|
)
|
|
).then((res) => {
|
|
this.list = res.rows;
|
|
if (this.stompClient) {
|
|
this.closeSocket();
|
|
}
|
|
this.connection();
|
|
});
|
|
},
|
|
// 创建一个ws 监听获取报警实时数据
|
|
connection() {
|
|
if (this.stompClient) {
|
|
return;
|
|
}
|
|
if (!webSocketProjectGatewayUrl) {
|
|
return;
|
|
}
|
|
if (!this.list || this.length <= 0) {
|
|
return;
|
|
}
|
|
let deviceIds = this.list.map((v) => v["deviceId"]);
|
|
this.stompClient = new WebSocket(
|
|
`${webSocketProjectGatewayUrl}/${this.getGuid()}/${deviceIds.toString()}`
|
|
);
|
|
this.stompClient.onmessage = this.socket_message;
|
|
this.stompClient.onclose = this.socket_onclose;
|
|
},
|
|
socket_message(evt) {
|
|
console.log("wsljcg:=", evt);
|
|
const data = JSON.parse(evt.data);
|
|
|
|
// this.actualEnergyCensus = data.params || {};
|
|
console.log("socket-message:", data);
|
|
this.handleDeviceInfo(data);
|
|
this.$forceUpdate();
|
|
},
|
|
// 处理 socket 数据返回 赋值问题
|
|
handleDeviceInfo(param) {
|
|
if (this.list && this.list.length > 0) {
|
|
this.list = this.list.map((v) => {
|
|
if (v["deviceId"] === param["deviceId"]) {
|
|
return Object.assign(v, param);
|
|
} else {
|
|
return v;
|
|
}
|
|
});
|
|
}
|
|
},
|
|
socket_onclose(e) {
|
|
this.stompClient = null;
|
|
if (this.socket_flag) {
|
|
this.socket_flag = false;
|
|
let _this = this;
|
|
this.timeout_flag = setTimeout(function () {
|
|
_this.socket_flag = true;
|
|
_this.connection();
|
|
}, 10000);
|
|
}
|
|
},
|
|
closeSocket() {
|
|
if (this.stompClient) {
|
|
this.stompClient.close();
|
|
}
|
|
this.socket_flag = false;
|
|
this.stompClient = null;
|
|
clearTimeout(this.timeout_flag);
|
|
},
|
|
getGuid() {
|
|
return "xxxxxxx_xxxxx_4xxx_yxxx_xxxxxxxxxxxx".replace(
|
|
/[xy]/g,
|
|
function (c) {
|
|
var r = (Math.random() * 16) | 0,
|
|
v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
return v.toString(16);
|
|
}
|
|
);
|
|
},
|
|
/**
|
|
* 跳转 设备 详情
|
|
*/
|
|
handleLinkToDeviceDetails(row) {
|
|
this.$router.push({ path:'/device/device', query: { 'deviceId': row.deviceId, 'tempType': 'details' } })
|
|
}
|
|
},
|
|
destroyed() {
|
|
this.closeSocket();
|
|
},
|
|
};
|
|
</script>
|
|
<style lang="scss">
|
|
.e-object-device-manage-table {
|
|
.el-form-item--medium .el-form-item__content {
|
|
width: calc(100% - 70px);
|
|
}
|
|
.query-foot.el-form-item--medium .el-form-item__content {
|
|
width: 100%;
|
|
}
|
|
.table-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: auto;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: start;
|
|
.object-device-card {
|
|
width: 285px;
|
|
height: 164px;
|
|
background: #ffffff;
|
|
border: 1px solid #e4ebf4;
|
|
box-shadow: 0px 0px 8px 0px rgba(17, 76, 157, 0.26);
|
|
border-radius: 5px;
|
|
margin: 5px;
|
|
.card-left {
|
|
font-size: 14px;
|
|
font-family: Source Han Sans CN;
|
|
font-weight: 400;
|
|
color: #00c805;
|
|
}
|
|
.off-line {
|
|
color: #da2710;
|
|
}
|
|
.card-right {
|
|
display: flex;
|
|
font-size: 14px;
|
|
font-family: Source Han Sans CN;
|
|
font-weight: 400;
|
|
color: #6b778c;
|
|
align-items: baseline;
|
|
.c-label {
|
|
}
|
|
.c-number {
|
|
color: #344567;
|
|
margin: 0 8px;
|
|
}
|
|
.card-opt-i {
|
|
font-size: 18px;
|
|
-ms-transform: rotate(90deg); /* IE 9 */
|
|
-webkit-transform: rotate(90deg); /* Safari and Chrome */
|
|
transform: rotate(90deg);
|
|
}
|
|
.card-opt-i:hover {
|
|
color: #46a6ff;
|
|
}
|
|
}
|
|
.e-simple-card__header {
|
|
width: 100%;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.e-simple-card__body {
|
|
padding: 10px;
|
|
}
|
|
|
|
.object-device-body {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
.card-body-info {
|
|
width: 100%;
|
|
height: 85px;
|
|
display: flex;
|
|
.card-body-left {
|
|
width: 40%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
> img {
|
|
width: 93px;
|
|
height: 52px;
|
|
}
|
|
}
|
|
.card-body-right {
|
|
width: 60%;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
font-size: 14px;
|
|
font-family: Source Han Sans CN;
|
|
font-weight: 300;
|
|
color: #344567;
|
|
> span {
|
|
display: block;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
}
|
|
.card-body-footer {
|
|
width: 100%;
|
|
display: flex;
|
|
.card-footer {
|
|
font-size: 14px;
|
|
font-family: Source Han Sans CN;
|
|
font-weight: 400;
|
|
color: #344567;
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.footer-title {
|
|
width: 100%;
|
|
margin-left: 3px;
|
|
display: block;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
.dev-error {
|
|
color: #dc3520;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|