jsy-app/utils/indexUtil/dc.js
2024-12-03 12:38:13 +08:00

961 lines
24 KiB
JavaScript
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.

import valveAngleConfig from "@/utils/valveAngleConfig.json"
import ValveControlParam from "./ValveControlParam"
const dcMsgType = {
default: 0, //默认
ok: 1, //成功
err: -1, //失败
}
const dcEventType = {
interface: 0, // 界面操作
send: 1, // 命令控制设备
refresh: 2, // 命令刷新设备
refreshApi: 3, // 接口刷新阀门
}
/**
* 设备控制
*/
class deviceControl {
/**
* @param {Object} 初始化方法
*/
constructor(eventHandler) {
this.eventHandler = eventHandler;
// this.onEventHandler({
// success: dcMsgType.ok,
// message: "初始化成功"
// });
};
get topic() {
if (this.topics.newV.length && this.topics.newV.length) {
const newV = new Set(this.topics.newV);
const oldV = this.topics.oldV.filter(x => !newV.has(x));
return {
oldV: oldV,
newV: this.topics.newV,
}
} else {
return this.topics;
}
}
// #region 变量
/**
* @param {landData} 地块信息
*/
land = null;
/**
* @param {valves} 阀门列表
*/
wo = [];
/**
* @param {valves} 未绑定阀门列表
*/
valves = [];
/**
* @param {valves} 是所有设备的通讯信息
*/
dataObj = {};
/**
* @param {stations} 基站列表
*/
stations = [];
/**
* @param {others} 其他列表
*/
others = {
header: null,
agricultural: null,
deviceMp: null,
}
/**
* @param {topics} 订阅topic
*/
topics = {
oldV: [],
newV: [],
};
/**
* 数据筛选
*/
forward = false;
screenKey = "";
screen = {
all: 0,
online: 0,
offline: 0,
watering: 0,
unwater: 0,
error: 0,
};
// #endregion
// #region 初始化数据
/**
* 设置数据
* @param {Object} land 地块
* @param {Object} data 数据集合
*/
setData(land, data) {
this.land = land;
this.dataObj = data.deviceData;
this.setWaterOutlet(land.id, data.wo); //出水口数据
this.setValves(data.valve); //未绑定的阀门数据
this.setStations(data.station); //设置基站
let obj = {
header: data.header, //首部
agricultural: data.agricultural, //农情设备
deviceMp: data.mp, //墒情
}
this.setOtherDevices(obj); //设置设备数据(除阀门外的设备)
}
/**
* 设置阀门数据
* @param {Object} landId 地块id
* @param {Object} wo 数据集合
*/
setWaterOutlet(landId, wo) {
const that = this;
let topic = [],
loadData = [];
if (wo && wo.length) {
// 数据排序
wo.sort(commonUtil.compareDataNew("landGroup", "branchCanalCode"));
wo.forEach((item, i) => {
item.isHidden = false; // 隐藏
item.isOpened = false; // 是否有打开的阀门
// 阀门数据设置
if (item.device) {
item.dataKey = item.device.deviceCode;
topic.push("jsy/iot/push/" + item.device.deviceCode);
that.checkValveState(item.device); //设置阀门的状态
}
//便利出水口设备
if (item.children && item.children.length) {
item.children.sort(commonUtil.compareDataNew("outletCode", "multiPortCode"));
item.children.forEach((x, j) => {
x.isHidden = false; // 隐藏
// 阀门数据设置
if (x.device) {
x.dataKey = x.device.deviceCode;
topic.push("jsy/iot/push/" + x.device.deviceCode);
that.checkValveState(x.device); //设置阀门的状态
}
});
}
});
if (that.wo && that.wo.length && landId == that.land.id) {
// 更新数据
if (wo.length == that.wo.length) {
for (var i = 0; i < that.wo.length; i++) {
let item = that.wo[i];
if (item.id == wo[i].id) {
item.device = wo[i].device;
item.dataKey = wo[i]?.device?.deviceCode;
item.children = wo[i].children;
}
that.wo[i] = item;
}
} else {
// 替换数据
that.wo = wo;
that.onEventHandler({
success: dcMsgType.ok,
message: "数据变动,重新加载"
});
}
} else {
// 替换数据
that.wo = wo;
}
} else {
that.wo = [];
}
that.addTopics(topic);
that.screenDataByType();
// that.startRunningTimer();
// // 如果数据有效,查询相关数据
// if(that.valves.length){
// //给设备匹配时间
// this.matchTime("all");
// }
}
/**
* 设置阀门数据
* @param {Object} data
*/
setValves(data) {
let topic = [];
if (data && data.length) {
data.forEach(item => {
topic.push("jsy/iot/push/" + item.deviceCode);
});
this.valves = data;
} else {
this.valves = []
}
this.addTopics(topic);
}
/**
* 设置基站数据
* @param {Object} data
*/
setStations(data) {
let topic = [];
if (data && data.length) {
data.forEach(item => {
topic.push("jsy/iot/push/" + item.deviceCode);
item["hidden"] = false;
});
this.stations = data;
} else {
this.stations = []
}
this.addTopics(topic);
}
/**
* 设置设备数据(除阀门外的设备)
* @param {Object} data {key,date}
*/
setOtherDevices(data) {
for (const key in data) {
this.others[key] = data[key];
// if (data[key] && data[key].length) {
// this.others[key] = data[key];
// } else {
// this.others[key] = null;
// }
}
}
/**
* 添加tioic
* @param {Object} topic
*/
addTopics(topic) {
topic = [...new Set([...this.topics.newV, ...topic])];
this.topics.newV = topic;
}
// #endregion
// #region 自动刷新
runningTimer = false;
/**
* 自动刷新页面数据
*/
startRunningTimer() {
// if (this.runningTimer) return;
// const that = this;
// that.runningTimer = true;
// setTimeout(() => {
// that.onEventHandler(that.eventType.refreshApi, that.land.item.id)
// }, 20 * 1000);
}
// #endregion
// #region 数据筛选
/**
* 判断阀门数据状态
* @param {Object} device
*/
checkValveState(device) {
if (!device || !this.dataObj[device.deviceCode] || !this.dataObj[device.deviceCode].btnObj) {
return;
}
for (const key in this.dataObj[device.deviceCode].btnObj) {
if (!this.dataObj[device.deviceCode].btnObj[key]) {
break;
}
if (this.dataObj[device.deviceCode].btnObj[key]?.work) {
switch (device.deviceTypeKey) {
case "butterflyValve":
case "valve":
this.setCountdown(device.deviceCode, this.dataObj[device.deviceCode].btnObj[key].ct);
break;
case "fiveValve":
this.setCountdown(`${device.deviceCode}_${key}`, this.dataObj[device.deviceCode].btnObj[key]
.ct);
break;
}
}
}
}
/**
* 筛选设备数据
* isSort 是否需要排序默认false
*/
screenDataByType(isSort = false) {
// 如果在线就显示 不在线就隐藏
const that = this;
let all = 0,
online = 0,
offline = 0,
watering = 0,
unwater = 0,
error = 0;
let screenKey = that.screenKey;
let forward = that.forward;
that.wo.forEach(item => {
item.isHidden = false; //行是否隐藏
item.isOpened = false; //是否有打开的阀门
if (item.children && item.children.length) {
item.children.forEach(item2 => {
item2.isOpened = false;
let keys = [];
// 状态数据统计
if (item2.device) {
all++;
const data = this.dataObj[item2.dataKey];
if (data) {
if (data.online) {
online++;
keys.push('online');
} else {
offline++;
error++;
keys.push('offline');
keys.push('error');
}
if (data.valveOpen || data.valveWork) {
item2.isOpened = true;
item.isOpened = true;
watering++;
keys.push('watering');
} else {
unwater++;
keys.push('unwater');
}
} else {
offline++;
unwater++;
error++;
keys = ['offline', 'unwater', 'error'];
}
}
// 显示状态判断
if (screenKey == "") {
item2.isHidden = false;
} else if (screenKey == "all") {
if (item2.device) {
item2.isHidden = false;
} else {
item2.isHidden = true;
}
} else if (keys.includes(screenKey)) {
item2.isHidden = false;
} else {
item2.isHidden = true;
}
});
// 如果阀门全部都不在线 就隐藏阀门组的折叠
// if (item.children.every(j => j.isHidden == true) && item.isHidden) {
if (item.children.every(j => j.isHidden == true)) {
item.isHidden = true;
} else {
item.isHidden = false;
}
if (isSort) {
if (forward) {
item.children.sort((a, b) => Number(!a.isOpened) - Number(!b.isOpened));
} else {
item.children.sort(commonUtil.compareDataNew("outletCode", "multiPortCode"));
}
}
} else {
if (screenKey == "") {
item.isHidden = false;
} else {
item.isHidden = true;
}
}
})
if (isSort) {
if (forward) {
that.wo.sort((a, b) => Number(!a.isOpened) - Number(!b.isOpened));
} else {
that.wo.sort(commonUtil.compareDataNew("landGroup", "branchCanalCode"));
}
}
this.screen.all = all;
this.screen.online = online;
this.screen.offline = offline;
this.screen.watering = watering;
this.screen.unwater = unwater;
this.screen.error = error;
}
/**
* 通过字符串筛选数据
*/
screenDataByString(screenValue) {
// 如果在线就显示 不在线就隐藏
const that = this;
that.screenKey = "";
that.forward = false;
if (screenValue) {
that.wo.forEach(item => {
if (item.children && item.children.length) {
item.children.forEach(item2 => {
// if (item2.showName.includes(screenValue) || item2.dataKey.includes(screenValue)) {}
if (item2.showName.includes(screenValue)) {
item2.isHidden = false;
} else {
item2.isHidden = true;
}
});
if (item.children.every(j => j.isHidden == true)) {
item.isHidden = true;
} else {
item.isHidden = false;
}
}
})
} else {
that.wo.forEach(item => {
item.isHidden = false;
if (item.children && item.children.length) {
item.children.forEach(item2 => {
item2.isHidden = false;
});
}
})
}
}
/**
* @param {Object} type 筛选状态1在线 2离线 3警告 0/其他 全部
*/
showType(key = "") {
if (this.screenKey == key) return;
this.screenKey = key;
this.screenDataByType();
}
/**
* 工作阀门
*/
workingForward(value) {
if (this.forward == value) return;
this.forward = value;
this.screenDataByType(true);
}
// #endregion
// #region 控制
/**
* 刷新设备
* @param {Object} mark
* @param {Object} device
*/
refreshDeviceItem(mark, device) {
if (!this.dbClickHandle(`refresh-${mark}`)) return;
if (device.deviceTypeId == 1 || ["valve", "fiveValve", "butterflyValve"].includes(device.deviceTypeKey)) {
this.onEventHandler({
deviceCode: device.deviceCode,
deviceTypeId: device.deviceTypeId,
}, dcEventType.refresh, device);
if (this.dataObj[mark]) {
this.dataObj[mark].refresh = true;
} else {
this.dataObj[mark] = {
online: false, //在线状态
refresh: true, //刷新状态
warning: []
}
}
// 设置刷新状态重置倒计时
this.setRefreshCountdown(mark);
console.error("this.refreshObj:", this.refreshObj);
} else {
// this.onEventHandler({
// deviceCode: device.deviceCode,
// deviceTypeId: device.deviceTypeId,
// }, dcEventType.refresh, device);
// if (device?.data) {
// device.data.refresh = true;
// } else {
// device["data"] = {
// online: false, //在线状态
// refresh: true, //刷新状态
// }
// }
}
}
/**
* 控制按钮事件
* @param {Object} item
* @param {Object} index
* @param {Object} value
*/
deviceControlHandle(item, index) {
if (!this.dbClickHandle(`${item.dataKey}-${index}`)) return;
this.buildCommand(item, index);
}
/**
* 组织命令
* @param {Object} item 当前对象
* @param {Object} index 蝶阀0关 1开子设备索引默认都是1;三通阀为开关索引1①开 2②开 3全开 4全关;五通阀为阀口1234对应1234口;
* @param {Object} value 蝶阀:无需此参数,三通/五通:角度百分比
*/
buildCommand(item, index, value = null) {
let deviceTypeKey = item.device.deviceTypeKey;
// 配置的角度参数
const config = valveAngleConfig[deviceTypeKey];
switch (item.device.deviceTypeKey) {
case "butterflyValve":
const params = new ValveControlParam();
params.deviceTypeId = item.device.deviceTypeId;
params.deviceCode = item.device.deviceCode;
params.valveNo = 1; //现在默认都是1;
params.angleKey = config[index].key;
this.setBtnPreloading(item, config[index].key, index, value);
this.onEventHandler(params.get(), dcEventType.send, item);
break;
case "valve":
//value大于等于0或者索引为3(全开)4(全关)则直接发送命令,否则打开弹框
if (value != null && value >= 0 || (index == 3 || index == 4)) {
let keyIndex = null;
if (index == 1) {
if (value == 0) {
keyIndex = 0;
} else if (value == 100) {
keyIndex = 2;
} else {
keyIndex = 3;
}
} else if (index == 2) {
if (value == 0) {
keyIndex = 0;
} else if (value == 100) {
keyIndex = 4;
} else {
keyIndex = 5;
}
} else if (index == 3) {
keyIndex = 1;
} else if (index == 4) {
keyIndex = 0;
}
const params = new ValveControlParam();
params.deviceTypeId = item.device.deviceTypeId; //设备类型id
params.deviceCode = item.device.deviceCode; //设备编码
params.valveNo = index;
params.angleKey = config[keyIndex].key;
params.anglePercent = value;
this.setBtnPreloading(item, config[keyIndex].key, index, value);
this.onEventHandler(params.get(), dcEventType.send, item);
} else {
this.onEventHandler({
title: item.showName,
extra: `${index}`,
value: this.dataObj[item.dataKey].btnObj[`open${index}`].openAngle,
other: {
item: item,
index: index,
}
}, dcEventType.interface, item);
}
break;
case "fiveValve":
//value大于等于0则直接发送命令否则打开弹框
if (value != null && value >= 0) {
let keyIndex = null;
if (value == 0) {
keyIndex = 0;
} else if (value == 100) {
keyIndex = 1;
} else {
keyIndex = 2;
}
const params = new ValveControlParam();
params.deviceTypeId = item.device.deviceTypeId; //设备类型id
params.deviceCode = item.device.deviceCode; //设备编码
params.valveNo = index;
params.angleKey = config[keyIndex].key;
params.anglePercent = value;
this.setBtnPreloading(item, config[keyIndex].key, index, value);
this.onEventHandler(params.get(), dcEventType.send, item);
} else {
this.onEventHandler({
title: item.showName,
extra: `${index}`,
value: this.dataObj[item.dataKey].btnObj[`open${index}`].openAngle,
other: {
item: item,
index: index,
}
}, dcEventType.interface, item);
}
break;
default:
this.onEventHandler({
success: dcMsgType.err,
message: "未知的设备类型"
});
break;
}
}
/**
* 设置按钮的预加载状态
* @param {Object} item 当前对象
* @param {Object} angleKey 操作key
* @param {Object} index 蝶阀0关 1开子设备索引默认都是1;三通阀为开关索引1①开 2②开 3全开 4全关;五通阀为阀口1234对应1234口;
* @param {Object} value 蝶阀:无需此参数,三通/五通:角度百分比
*/
setBtnPreloading(item, angleKey, index, value = null) {
let deviceTypeKey = item.device.deviceTypeKey;
// 配置的角度参数
const config = valveAngleConfig[deviceTypeKey];
let btnkey = "";
switch (item.device.deviceTypeKey) {
case "butterflyValve":
// 计时状态
this.clearCountdown(item.dataKey);
if (angleKey == config[0].key) {
this.dataObj[item.dataKey].btnObj.close.work = true;
this.dataObj[item.dataKey].btnObj.open.work = false;
}
if (angleKey == config[1].key) {
this.dataObj[item.dataKey].btnObj.close.work = false;
this.dataObj[item.dataKey].btnObj.open.work = true;
}
break;
case "valve":
// 删除超时状态
this.clearCountdown(item.dataKey);
if (index == 1) {
if (angleKey == config[0].key) {
btnkey = "close";
} else {
btnkey = "open1";
}
} else if (index == 2) {
if (angleKey == config[0].key) {
btnkey = "close";
} else {
btnkey = "open2";
}
} else if (index == 3) {
btnkey = "open";
} else if (index == 4) {
btnkey = "close";
} else {
btnkey = "close";
}
for (const key in this.dataObj[item.dataKey].btnObj) {
if (!this.dataObj[item.dataKey].btnObj[key]) {
return;
}
if (key == btnkey) {
this.dataObj[item.dataKey].btnObj[key].work = true
this.dataObj[item.dataKey].btnObj[key].openAngle = value;
} else {
this.dataObj[item.dataKey].btnObj[key].work = false;
}
}
break;
case "fiveValve":
btnkey = `open${index}`;
// 删除超时状态
this.clearCountdown(`${item.dataKey}_${btnkey}`);
if (angleKey == config[0].key) {
this.dataObj[item.dataKey].btnObj[btnkey].switchOn = false;
} else {
this.dataObj[item.dataKey].btnObj[btnkey].switchOn = true;
}
this.dataObj[item.dataKey].btnObj[btnkey].work = true;
this.dataObj[item.dataKey].btnObj[btnkey].openAngle = value;
break;
}
}
/**
* 其他设备的双击事件
* @param {Object} mark
* @param {Object} callBack
*/
othersClickHandle(mark, callBack) {
if (!this.dbClickHandle(mark)) return;
if (typeof callBack === 'function') {
callBack();
}
}
// #endregion
// #region 倒计时
refreshObj = {} //刷新的倒计时对象
countdownObj = {} //倒计时对象
timeoutObj = {} //超时对象
timingInProgress = false; //倒计时状态
/**
* 设置倒计时-刷新倒计时
* @param {Object} key 主键
*/
setRefreshCountdown(key) {
this.refreshObj[key] = 30;
if (!this.timingInProgress) {
this.timingInProgress = true;
this.countdownHandle();
}
}
/**
* 清理倒计时
* @param {Object} key 主键
*/
clearRefreshCountdown(key) {
if (this.refreshObj[key]) {
delete this.refreshObj[key];
this.dataObj[key].refresh = false;
}
}
/**
* 设置倒计时-控制倒计时
* @param {Object} key 主键
* @param {Object} ct 倒计时
*/
setCountdown(key, ct) {
if (ct && ct != 0) {
this.countdownObj[key] = parseInt(ct);
if (!this.timingInProgress) {
this.timingInProgress = true;
this.countdownHandle();
}
}
}
/**
* 清理倒计时-控制倒计时
* @param {Object} key 主键
*/
clearCountdown(key) {
if (Object.keys(this.countdownObj).length != 0) {
delete this.countdownObj[key];
}
if (Object.keys(this.timeoutObj).length != 0) {
delete this.timeoutObj[key];
}
}
/**
* 倒计时处理
*/
countdownHandle() {
let refreshObj = this.refreshObj;
let countdownObj = this.countdownObj;
if (Object.keys(refreshObj).length === 0 && Object.keys(countdownObj).length === 0) {
this.timingInProgress = false;
} else {
if (Object.keys(refreshObj).length) {
for (let key in refreshObj) {
if (refreshObj[key] > 0) {
this.refreshObj[key] = (refreshObj[key] - 1);
} else {
delete this.refreshObj[key];
this.dataObj[key].refresh = false;
}
}
}
if (Object.keys(countdownObj).length) {
for (let key in countdownObj) {
if (countdownObj[key] > 0) {
this.countdownObj[key] = (countdownObj[key] - 1);
} else {
delete this.countdownObj[key];
this.timeoutObj[key] = "超时"
}
}
}
setTimeout(() => {
this.countdownHandle();
}, 1000);
}
}
// #endregion
// #region 数据解析
/**
* 解析数据
* @param {Object} topic
* @param {Object} data
*/
handleMessage(topic, data) {
console.error("data:", data);
const that = this;
if (data.time < that.dataObj[data.deviceCode].time) {
return;
}
that.dataObj[data.deviceCode] = data;
if (data.btnObj) {
for (const key in data.btnObj) {
if (!data.btnObj[key]) {
break;
}
if (data.btnObj[key].work) {
switch (data.deviceTypeKey) {
case "butterflyValve":
case "valve":
that.setCountdown(data.deviceCode, data.btnObj[key].ct);
break;
case "fiveValve":
that.setCountdown(`${data.deviceCode}_${key}`, data.btnObj[key].ct);
break;
}
}
}
}
}
/**
* 按钮样式
* @param {Object} appType 应用类型 1web 2手机
* @param {Object} mark 数据主键
* @param {Object} key 按钮key
*/
// 判断按钮的状态
getBtnType(appType, mark, key) {
const obj = this.dataObj[mark];
if (obj.btnObj[key].warning) {
return 'warning';
}
if (obj.deviceTypeKey == "valve" || obj.deviceTypeKey == "butterflyValve") {
if (obj.btnObj[key].switchOn || obj.btnObj[key].work) {
if (key == "close") {
return appType == 1 ? 'danger' : "error";
} else {
return 'success';
}
} else {
return 'info';
}
}
if (obj.deviceTypeKey == "fiveValve") {
if (obj.btnObj[key].switchOn || obj.btnObj[key].work) {
return 'success';
} else {
return appType == 1 ? 'danger' : "error";
}
}
}
// #endregion
// #region 双击操作
// 双击操作
doubleClick = true;
// 双击参数
dblClickThreshold = 500;
dblClicObj = {
time: 0,
type: undefined
};
/**
* 验证双击
* @param type 按钮类型
*/
dbClickHandle(type) {
const that = this;
if (!that.doubleClick) {
return true;
}
const timestamp = new Date().getTime();
if (that.dblClicObj.type === type) {
if ((timestamp - that.dblClicObj.time) < that.dblClickThreshold) {
that.dblClicObj.type = undefined;
that.dblClicObj.time = 0;
return true;
} else {
that.dblClicObj.type = type;
that.dblClicObj.time = timestamp;
return false;
}
} else {
that.dblClicObj.type = type;
that.dblClicObj.time = timestamp;
return false;
}
}
// #endregion
// #region 消息回调
//应用类型 type:0打开操作界面1控制命令发送2刷新命令发送 3接口刷新阀门数据
onEventHandler(params, type = null, item = null) {
if (typeof this.eventHandler === 'function') {
this.eventHandler(type, params, item);
}
}
// #endregion
};
export {
deviceControl,
dcMsgType,
dcEventType
};
/***************************** 公共方法 *****************************/
var commonUtil = {
// 数据排序
compareDataNew(file1, file2) {
return function(b, a) {
if (b[file1] < a[file1]) {
return -1;
} else if (b[file1] > a[file1]) {
return 1;
} else {
if (b[file2] < a[file2]) {
return -1;
} else if (b[file2] > a[file2]) {
return 1;
} else {
return 0;
}
}
}
},
// 服务商
facilitator(type) {
if (type) {
if (type == "1") {
return "移动"
} else if (type == "2") {
return "电信"
} else if (type == "3") {
return "联通"
}
} else {
return "未知"
}
},
//格式化时间戳
getYMDHMS(timestamp) {
let date = new Date(parseInt(timestamp))
let Year = date.getFullYear()
let Moth = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1
let Day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate()
let Hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours()
let Minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()
let Sechond = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()
let GMT = Year + "-" + Moth + "-" + Day + " " + Hour + ":" + Minute + ":" + Sechond
return GMT
},
findIndexByCode(arr, code) {
if (arr.length) {
var index1 = arr.findIndex(x => x.device && x.device.deviceCode == code);
if (index1 != -1) {
return [index1];
} else {
let arrIndex = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i].children && arr[i].children.length) {
var j = arr[i].children.findIndex(x => x.device && x.device.deviceCode == code);
if (j != -1) {
arrIndex = [i, j];
break;
}
}
}
return arrIndex;
}
} else {
return [];
}
}
}