527 lines
14 KiB
Vue
527 lines
14 KiB
Vue
<template>
|
||
<div class="device-select-nav">
|
||
<el-card
|
||
:body-style="{ padding: '0px', width: '220px' }"
|
||
:style="
|
||
deviceInfo.deviceId === checkobxDeviceId
|
||
? 'border: 1px solid #1890ff; margin: 5px; width: 220px; flex-shrink: 0;'
|
||
: ' margin: 5px; width: 220px; flex-shrink: 0;'
|
||
"
|
||
>
|
||
<div class="nav-p-dev">
|
||
<div
|
||
style="
|
||
height: 25px;
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding-right: 10px;
|
||
padding-top: 5px;
|
||
"
|
||
>
|
||
<div style="width: 60px; display: flex; justify-content: center" v-if="deviceInfo.stype === 'LAN'">
|
||
<i
|
||
class="iconfont iconkuandai"
|
||
style="color: black; font-size: 20px"
|
||
></i>
|
||
</div>
|
||
<div style="width: 60px; display: flex; justify-content: center" v-else>
|
||
<i
|
||
class="iconfont iconwifi"
|
||
style="color: black; font-size: 20px"
|
||
v-if="deviceInfo.stype === 'WIFI'"
|
||
></i>
|
||
<i
|
||
:class="signalType(deviceInfo.stype)"
|
||
style="color: black; font-size: 20px"
|
||
v-else
|
||
></i>
|
||
<signal-intensity
|
||
:intensityNumber="deviceInfo.signal"
|
||
></signal-intensity>
|
||
</div>
|
||
<i
|
||
v-if="deviceInfo.deviceId === checkobxDeviceId"
|
||
class="el-icon-success"
|
||
style="font-size: 25px; color: #1890ff"
|
||
></i>
|
||
</div>
|
||
<div class="dev-info">
|
||
<span class="dev-info-title" :title="deviceInfo.deviceName">{{
|
||
deviceInfo.deviceName
|
||
}}</span>
|
||
<div class="dev-info-state">
|
||
<el-tag type="success" v-if="deviceInfo.deviceState === 'ONLINE'"
|
||
>在线</el-tag
|
||
>
|
||
<el-tag
|
||
type="danger"
|
||
v-else-if="deviceInfo.deviceState === 'OFFLINE'"
|
||
>离线</el-tag
|
||
>
|
||
<el-tag
|
||
type="danger"
|
||
v-else-if="deviceInfo.deviceState === 'OUTLINE'"
|
||
>脱线</el-tag
|
||
>
|
||
<el-tag
|
||
type="info"
|
||
v-else-if="deviceInfo.deviceState === 'UNACTIVE'"
|
||
>未激活</el-tag
|
||
>
|
||
<el-button
|
||
type="primary"
|
||
size="mini"
|
||
@click="viewDeviceChange(deviceInfo.deviceId)"
|
||
>查看</el-button
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
|
||
<el-card
|
||
:body-style="{ padding: '0px', width: '220px' }"
|
||
:style="
|
||
item.deviceId === checkobxDeviceId
|
||
? 'border: 1px solid #1890ff; margin: 5px; width: 220px; flex-shrink: 0;'
|
||
: ' margin: 5px; width: 220px; flex-shrink: 0;'
|
||
"
|
||
v-for="item in childDeviceList"
|
||
:key="item.deviceId"
|
||
>
|
||
<div class="nav-c-dev">
|
||
<div
|
||
style="
|
||
height: 25px;
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding-right: 10px;
|
||
padding-top: 5px;
|
||
"
|
||
>
|
||
<!-- <div style="
|
||
width: 60px;
|
||
display: flex;
|
||
justify-content: center;
|
||
">
|
||
<i :class="signalType(item.stype)" style="color: black; font-size: 20px;" ></i>
|
||
<signal-intensity :intensityNumber="item.signal" ></signal-intensity>
|
||
</div> -->
|
||
<i
|
||
v-if="item.deviceId === checkobxDeviceId"
|
||
class="el-icon-success"
|
||
style="font-size: 25px; color: #1890ff"
|
||
></i>
|
||
</div>
|
||
<div class="dev-info">
|
||
<span class="dev-info-title" :title="item.deviceName">{{
|
||
item.deviceName
|
||
}}</span>
|
||
<div
|
||
class="dev-info-state"
|
||
v-show="item.deviceId !== checkobxDeviceId"
|
||
>
|
||
<el-tag type="success" v-if="item.deviceState === 'ONLINE'"
|
||
>在线</el-tag
|
||
>
|
||
<el-tag type="danger" v-else-if="item.deviceState === 'OFFLINE'"
|
||
>离线</el-tag
|
||
>
|
||
<el-tag type="danger" v-else-if="item.deviceState === 'OUTLINE'"
|
||
>脱线</el-tag
|
||
>
|
||
<el-tag type="info" v-else-if="item.deviceState === 'UNACTIVE'"
|
||
>未激活</el-tag
|
||
>
|
||
<el-button
|
||
type="primary"
|
||
size="mini"
|
||
@click="viewDeviceChange(item.deviceId)"
|
||
>查看</el-button
|
||
>
|
||
</div>
|
||
<div
|
||
class="dev-info-state"
|
||
v-show="item.deviceId === checkobxDeviceId"
|
||
>
|
||
<el-switch
|
||
size="mini"
|
||
v-model="item.switch"
|
||
active-text="开启"
|
||
disabled
|
||
inactive-text="关闭"
|
||
active-value="1"
|
||
inactive-value="0"
|
||
active-color="#13ce66"
|
||
inactive-color="#dcdfe6"
|
||
class="switch-wrap"
|
||
>
|
||
</el-switch>
|
||
<el-button
|
||
size="mini"
|
||
v-if="item.switch === '1'"
|
||
:disabled="item.deviceId !== checkobxDeviceId"
|
||
@click="submitChildStatus('false', item)"
|
||
type="success"
|
||
>关闭</el-button
|
||
>
|
||
<el-button
|
||
size="mini"
|
||
v-else
|
||
:disabled="item.deviceId !== checkobxDeviceId"
|
||
@click="submitChildStatus('true', item)"
|
||
type="danger"
|
||
>开启</el-button
|
||
>
|
||
|
||
<el-button
|
||
type="primary"
|
||
size="mini"
|
||
@click="viewDeviceChange(item.deviceId)"
|
||
>查看</el-button
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { listDevice, setSwitchControl } from "@/api/iot/device";
|
||
import { iotWebSocketBaseUrl, devLiveWebSocketBaseUrl } from "@/config/env";
|
||
import SignalIntensity from "./signalIntensity";
|
||
export default {
|
||
name: "DeviceSelectNav",
|
||
components: {
|
||
SignalIntensity,
|
||
},
|
||
props: {
|
||
deviceInfo: {
|
||
type: Object,
|
||
default: () => {
|
||
return {};
|
||
},
|
||
},
|
||
wsDeviceInfo: {
|
||
type: Object,
|
||
default: () => {
|
||
return {};
|
||
},
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
checkobxDeviceId: "",
|
||
childDeviceList: [],
|
||
stompClient: null,
|
||
socket_flag: true,
|
||
setTimeOut_flag: null,
|
||
timingPingWs_flag: null,
|
||
// wsDeviceInfo: null?
|
||
};
|
||
},
|
||
created() {
|
||
this.checkobxDeviceId = this.deviceInfo.deviceId || null;
|
||
},
|
||
watch: {
|
||
wsDeviceInfo: {
|
||
handler: function () {
|
||
this.timingPingWs(this.wsDeviceInfo);
|
||
if (this.deviceInfo.deviceId !== this.wsDeviceInfo.deviceId) {
|
||
for (let i = 0; i < this.childDeviceList.length; i++) {
|
||
if (
|
||
this.childDeviceList[i]["deviceId"] ===
|
||
this.wsDeviceInfo["deviceId"]
|
||
) {
|
||
this.childDeviceList[i]["switch"] =
|
||
this.wsDeviceInfoswitch?.switch.toString();
|
||
this.$forceUpdate();
|
||
break;
|
||
}
|
||
}
|
||
// this.timingPingWs(this.wsDeviceInfo);
|
||
// 更换设备 开启ws
|
||
this.connection();
|
||
} else {
|
||
this.connection();
|
||
}
|
||
},
|
||
deep: true,
|
||
},
|
||
deviceInfo: {
|
||
handler: function () {
|
||
this.checkobxDeviceId = this.deviceInfo.deviceId || null;
|
||
this.getList();
|
||
},
|
||
deep: true,
|
||
},
|
||
},
|
||
methods: {
|
||
signalType(val) {
|
||
switch (val) {
|
||
case "5G":
|
||
return "iconfont icona-5G";
|
||
case "4G":
|
||
return "iconfont icon4g";
|
||
case "3G":
|
||
return "iconfont icon3g";
|
||
case "2G":
|
||
return "iconfont icong";
|
||
default:
|
||
return "iconfont icong";
|
||
}
|
||
},
|
||
// ws 获取子设备 状态
|
||
connection() {
|
||
if (this.stompClient) {
|
||
return;
|
||
}
|
||
if (!this.wsDeviceInfo) {
|
||
return;
|
||
}
|
||
if (!devLiveWebSocketBaseUrl) {
|
||
return;
|
||
}
|
||
let headers = {
|
||
clientid: this.wsDeviceInfo.wsClientId,
|
||
username: this.wsDeviceInfo.wsUsername,
|
||
sign: this.wsDeviceInfo.wsSign,
|
||
};
|
||
// console.log("connection:--");
|
||
this.stompClient = new WebSocket(
|
||
`${devLiveWebSocketBaseUrl}${headers.clientid}/${headers.username}/${headers.sign}`
|
||
);
|
||
this.socket_flag = true;
|
||
this.stompClient.onopen = this.socket_open;
|
||
this.stompClient.onmessage = this.socket_onmsg;
|
||
this.stompClient.onclose = this.socket_onclose;
|
||
},
|
||
socket_open(evt) {
|
||
console.log("ws-open:", evt);
|
||
},
|
||
socket_onmsg(evt) {
|
||
this.handlerWsMsgData(JSON.parse(evt.data));
|
||
},
|
||
handlerWsMsgData(evt) {
|
||
// console.log("msg:", evt);
|
||
this.$emit("wsRealTImeMsg", JSON.stringify(evt))
|
||
if (this.deviceInfo.deviceId !== this.wsDeviceInfo.deviceId) {
|
||
for (let i = 0; i < this.childDeviceList.length; i++) {
|
||
if (this.childDeviceList[i]["deviceKey"] === evt["devId"]) {
|
||
this.childDeviceList[i]["switch"] = evt["params"]["switch"] ? evt["params"]["switch"].toString() : '0';
|
||
this.$forceUpdate();
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
this.deviceInfo["stype"] = evt["params"]["stype"] ? evt["params"]["stype"].toString() : '0';
|
||
this.deviceInfo["signal"] = evt["params"]["signal"] ? evt["params"]["signal"].toString() : '0';
|
||
}
|
||
},
|
||
socket_onclose(e) {
|
||
// console.log("socket_onclose:--", e, this.stompClient);
|
||
this.stompClient = null;
|
||
if (this.socket_flag) {
|
||
this.socket_flag = false;
|
||
let this_ = this;
|
||
this_.setTimeOut_flag = setTimeout(function () {
|
||
this_.socket_flag = true;
|
||
this_.connection();
|
||
}, 10000);
|
||
}
|
||
},
|
||
// 销毁事件
|
||
closeWebscoket() {
|
||
// console.log(this.stompClient);
|
||
this.socket_flag = false;
|
||
if (this.stompClient) {
|
||
console.log("we-close---");
|
||
this.stompClient.close();
|
||
}
|
||
this.stompClient = null;
|
||
clearInterval(this.timingPingWs_flag);
|
||
clearTimeout(this.setTimeOut_flag);
|
||
},
|
||
// 定时 ping ws
|
||
timingPingWs(row) {
|
||
this.extenSubmit(row)
|
||
const _this = this;
|
||
this.timingPingWs_flag = setInterval(function () {
|
||
_this.extenSubmit(row)
|
||
}, 110000);
|
||
},
|
||
extenSubmit(row) {
|
||
let params = {
|
||
data: {
|
||
cmd: "set_live_time",
|
||
params: {
|
||
ltime: 15, // 上报间隔(0.1秒)
|
||
dtime: 1200, //上报时长(0.1秒)
|
||
},
|
||
},
|
||
deviceId: row.deviceId,
|
||
};
|
||
setSwitchControl(params).then((res) => {
|
||
console.log(res)
|
||
// this.msgSuccess("成功");
|
||
});
|
||
},
|
||
// 点击子设备 线路开关
|
||
submitChildStatus(type, row) {
|
||
this.$prompt("请输入登录密码", "提示", {
|
||
confirmButtonText: "确定",
|
||
cancelButtonText: "取消",
|
||
inputPattern: /^[a-z A-z 0-9 $.]+/,
|
||
inputType: "password",
|
||
inputErrorMessage: "登录密码不能为空",
|
||
}).then(({ value }) => {
|
||
let params = {
|
||
data: {
|
||
cmd: "set_switch",
|
||
params: {
|
||
switch: type === "true" ? 1 : 0,
|
||
},
|
||
},
|
||
deviceId: row.deviceId,
|
||
verifyKey: value,
|
||
};
|
||
|
||
setSwitchControl(params).then((res) => {
|
||
// console.log(res);
|
||
this.msgSuccess("修改成功");
|
||
});
|
||
});
|
||
},
|
||
// 勾选设备
|
||
viewDeviceChange(id) {
|
||
if (this.checkobxDeviceId !== id) {
|
||
this.checkobxDeviceId = id;
|
||
// 销毁当前ws
|
||
this.closeWebscoket();
|
||
this.$emit("changeEvent", { val: id });
|
||
}
|
||
},
|
||
/** 查询设备列表 */
|
||
getList() {
|
||
listDevice({
|
||
parentId: this.deviceInfo.deviceId,
|
||
}).then((response) => {
|
||
this.childDeviceList = response.rows;
|
||
});
|
||
},
|
||
},
|
||
destroyed() {
|
||
this.closeWebscoket()
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.device-select-nav {
|
||
height: 130px;
|
||
width: 100%;
|
||
display: flex;
|
||
overflow-y: auto;
|
||
background-color: #e4eaf3;
|
||
.nav-p-dev {
|
||
display: flex;
|
||
-ms-flex-wrap: wrap;
|
||
flex-wrap: wrap;
|
||
-webkit-box-pack: end;
|
||
-ms-flex-pack: end;
|
||
justify-content: flex-end;
|
||
// padding-top: 10px;
|
||
flex-shrink: 0;
|
||
.dev-info {
|
||
padding: 10px;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: flex-end;
|
||
width: 100%;
|
||
.dev-info-title {
|
||
display: block;
|
||
width: 100%;
|
||
text-overflow: ellipsis;
|
||
height: 30px;
|
||
font-size: 18px;
|
||
line-height: 30px;
|
||
white-space: nowrap;
|
||
display: inline-block;
|
||
width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.dev-info-state {
|
||
width: 100%;
|
||
height: 50px;
|
||
justify-content: center;
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
justify-content: space-between;
|
||
}
|
||
}
|
||
}
|
||
.nav-c-dev {
|
||
display: flex;
|
||
-ms-flex-wrap: wrap;
|
||
flex-wrap: wrap;
|
||
-webkit-box-pack: end;
|
||
-ms-flex-pack: end;
|
||
justify-content: flex-end;
|
||
// padding-top: 10px;
|
||
flex-shrink: 0;
|
||
.dev-info {
|
||
padding: 10px;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: flex-end;
|
||
width: 100%;
|
||
.dev-info-title {
|
||
display: block;
|
||
width: 100%;
|
||
text-overflow: ellipsis;
|
||
height: 30px;
|
||
font-size: 18px;
|
||
line-height: 30px;
|
||
white-space: nowrap;
|
||
display: inline-block;
|
||
width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.dev-info-state {
|
||
width: 100%;
|
||
height: 50px;
|
||
justify-content: center;
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
justify-content: space-between;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.device-select-nav::-webkit-scrollbar {
|
||
/*滚动条整体样式*/
|
||
width: 8px; /*高宽分别对应横竖滚动条的尺寸*/
|
||
height: 5px;
|
||
}
|
||
.device-select-nav::-webkit-scrollbar-thumb {
|
||
/*滚动条里面小方块*/
|
||
border-radius: 10px;
|
||
// box-shadow: inset 0 0 5px #c4c4c4;
|
||
background: #929292a6;
|
||
}
|
||
.device-select-nav::-webkit-scrollbar-track {
|
||
/*滚动条里面轨道*/
|
||
// -webkit-box-shadow:
|
||
box-shadow: inset 0 0 5px #f6f6f6;
|
||
border-radius: 10px;
|
||
background: #ffffff;
|
||
}
|
||
</style>
|