Browse Source

feat:设备状态+寿命预警数据接入

master
zhaobing’ 1 year ago
parent
commit
263f1c4cd3
  1. 4
      api/app/lib/controllers/patrolManage/patrolRecord.js
  2. 267
      weapp/package/deviceBigdataGraph/deviceBigdataGraph.js
  3. 2
      weapp/package/deviceBigdataGraph/deviceBigdataGraph.wxml
  4. 395
      weapp/package/deviceBigdataGraph/statusDetail/statusDetail.js
  5. 6
      weapp/package/deviceBigdataGraph/statusDetail/statusDetail.wxml
  6. 66
      weapp/package/report/report.js
  7. 5
      weapp/package/subSystem/subSystem.js
  8. 3
      weapp/utils/getApiUrl.js

4
api/app/lib/controllers/patrolManage/patrolRecord.js

@ -655,12 +655,12 @@ function reportQuest(opts){
order: [['inspectionTime', 'desc']],
attributes: ['inspectionTime'],
});
const lastInspectionTime = pointRecord.length ? pointRecord[0].dataValues.inspectionTime : null;
// const lastInspectionTime = pointRecord.length ? pointRecord[0].dataValues.inspectionTime : null;
const recordRes = await models.PatrolRecord.create(
// record
{
patrolPlanId: patrolPlanId,
lastInspectionTime,
// lastInspectionTime,
inspectionTime,
points,
alarm,

267
weapp/package/deviceBigdataGraph/deviceBigdataGraph.js

@ -1,9 +1,13 @@
// package/riskManagement/riskCalendar/riskCalendar.js
import * as echarts from '../components/ec-canvas/echarts';
import {
getAllPatrol,getDevices,getProjectList
getPatrolRecord,
getDevices,
getProjectList
} from "../../utils/getApiUrl";
import { Request } from "../../common";
import {
Request
} from "../../common";
const moment = require("../../utils/moment");
Page({
@ -35,133 +39,196 @@ Page({
* 页面的初始数据
*/
data: {
ec:{},
dataList:[],//巡检记录的列表
guaranteedRate:0,//过保率
warrantyPeriod:0,//质保期
projectList:[],//结构物列表
ec: {},
dataList: [], //巡检记录的列表
guaranteedRate: 0, //过保率
warrantyPeriod: 0, //质保期
projectList: [], //结构物列表
count: 0, //设备总数
deviceList:[],//设备列表
// normalCount: 0, //正常数量
// abnormalCount: 0, //异常数量
// unknownCount: 0, //未知数量
},
navigator(e) {
const res = JSON.stringify(this.data.deviceList)
const patrolRecord=JSON.stringify(this.data.dataList)
wx.navigateTo({
url: '/package/deviceBigdataGraph/statusDetail/statusDetail',
url: `/package/deviceBigdataGraph/statusDetail/statusDetail?arrayData=${encodeURIComponent(res)}&patrolRecord=${encodeURIComponent(patrolRecord)}`,
})
},
navigatorToLifeWarning(e) {
const res=JSON.stringify(this.data.projectList.rows)
},
navigatorToLifeWarning(e) {
const res = JSON.stringify(this.data.projectList.rows)
wx.navigateTo({
url: `/package/deviceBigdataGraph/lifeWarning/lifeWarning?arrayData=${encodeURIComponent(res)}`,
url: `/package/deviceBigdataGraph/lifeWarning/lifeWarning?arrayData=${encodeURIComponent(res)}`,
})
},
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
const that = this
that.ecComponent = that.selectComponent('#mychart-dom-pie');
that.ecDeviceComponent=that.selectComponent('#mychart-device-pie');
var option = {
backgroundColor: "#ffffff",
legend: {
bottom: 10,
left: 'center',
},
series: [{
label: {
normal: {
fontSize: 14
}
},
type: 'pie',
center: ['50%', '50%'],
radius: ['20%', '40%'],
data: [{
name: '类型一',
value: 1
},
{
name: '类型二',
value: 2
},
{
name: '类型三',
value: 3
},
{
name: '类型四',
value: 4
that.ecDeviceComponent = that.selectComponent('#mychart-device-pie');
const date1 = new Date('1970-01-01 00:00:00');
Request.get(getPatrolRecord('all', moment(date1).format('YYYY-MM-DD') + ' 00:00:00', moment('2099-12-31').format('YYYY-MM-DD') + ' 23:59:59', 'null', 'null')).then(res => {
if (res) {
let normal = 0;
let abnormal = 0;
let unknown = 0;
// 创建一个对象来存储每个pointId的最大inspectionTime
const maxInspectionTimeByPointId = {};
// 遍历数据并更新maxInspectionTimeByPointId
res.forEach((item) => {
const {pointId,inspectionTime} = item;
if (pointId in maxInspectionTimeByPointId) {
if (inspectionTime > maxInspectionTimeByPointId[pointId]) {
maxInspectionTimeByPointId[pointId] = inspectionTime;
}
} else {
maxInspectionTimeByPointId[pointId] = inspectionTime;
}
]
}]
};
var optionDevice = {
backgroundColor: "#ffffff",
legend: {
bottom: 10,
left: 'center',
},
series: [{
label: {
normal: {
fontSize: 14
});
// 过滤数据以获取相同pointId中inspectionTime最大的记录
const filteredData = res.filter((item) => {
const {pointId,inspectionTime} = item;
return inspectionTime === maxInspectionTimeByPointId[pointId];
});
filteredData.forEach((item) => {
const inspectContent =item.alarm?(item?.points?.inspectContent || []):[];
if (inspectContent && inspectContent.length&&Array.isArray(inspectContent)) {
inspectContent.forEach((p) => {
// 如果设备有报警
if (p.alarm) {
if (item.patrolRecordIssueHandles.length) {
const state = item.patrolRecordIssueHandles[0].state;
if (state === 6) {
// 正常
normal += 1;
} else if (state === 5) {
// 未知
unknown += 1;
}else {
// 异常
abnormal += 1;
}
}
} else {
// 正常
normal += 1;
}
});
}
},
type: 'pie',
center: ['50%', '50%'],
radius: ['20%', '40%'],
data: [{
name: '正常',
value: 1
},
{
name: '未知',
value: 2
});
that.setData({dataList:res})
var optionDevice = {
tooltip: {
trigger: 'item'
},
{
name: '异常',
value: 3
backgroundColor: "#ffffff",
legend: {
bottom: 10,
left: 'center',
},
]
}]
};
that.initECharts(option);
that.initDeviceECharts(optionDevice);
Request.get(getAllPatrol()).then(res=>{
if(res){
that.setData({dataList:res})
const rslt=res.filter(item=>{
console.log('dsadasda',item)
})
console.log('resss',rslt)
}else{
series: [{
label: {
normal: {
fontSize: 14
}
},
type: 'pie',
center: ['50%', '50%'],
radius: ['20%', '40%'],
data: [{
name: '正常',
value: normal
},
{
name: '未知',
value: unknown
},
{
name: '异常',
value: abnormal
},
]
}]
};
setTimeout(() => {
that.initDeviceECharts(optionDevice);
}, 1000)
} else {
wx.hideLoading()
}
})
Request.get(getProjectList()).then(res=>{
if(res){
Request.get(getProjectList()).then(res => {
if (res) {
that.setData({
projectList:res
projectList: res
})
}else{
} else {
wx.hideLoading()
}
})
Request.get(getDevices()).then(res=>{
if(res&&res.length){
Request.get(getDevices()).then(res => {
if (res && res.length) {
//总的
const count=res.length
const count = res.length
//过期的
const guaranteedRate=res.filter(item=>moment(item.dateGuarantee).isBefore(moment()))?.length||0
const guaranteedRate = res.filter(item => moment(item.dateGuarantee).isBefore(moment()))?.length || 0
//没过期的
const warrantyPeriod=res.filter(item=>moment(item.dateGuarantee).isAfter(moment()))?.length||0
const warrantyPeriod = res.filter(item => moment(item.dateGuarantee).isAfter(moment()))?.length || 0
that.setData({
guaranteedRate: Math.round((guaranteedRate/count)*100),
warrantyPeriod: Math.round((warrantyPeriod/count)*100),
guaranteedRate: Math.round((guaranteedRate / count) * 100),
warrantyPeriod: Math.round((warrantyPeriod / count) * 100),
count: res.length,
deviceList:res
})
}else{
const typeGroups = {};
res.forEach((item) => {
const type = item.type;
// 如果 typeGroups 中没有这个类型的数组,就初始化一个空数组
if (!typeGroups[type]) {
typeGroups[type] = [];
}
// 将对象添加到相应类型的数组中
typeGroups[type].push(item);
});
// 格式转换成指定格式
const result = Object.keys(typeGroups).map((type) => ({
name: type,
value: typeGroups[type].length,
}));
var option = {
tooltip: {
trigger: 'item'
},
backgroundColor: "#ffffff",
legend: {
bottom: 10,
left: 'center',
},
series: [{
label: {
normal: {
fontSize: 14
}
},
type: 'pie',
center: ['50%', '50%'],
radius: ['20%', '40%'],
data: result
}]
};
setTimeout(() => {
that.initECharts(option);
}, 1000)
} else {
wx.hideLoading()
}
})

2
weapp/package/deviceBigdataGraph/deviceBigdataGraph.wxml

@ -54,7 +54,7 @@
<text class="fontStyle">设备类型</text>
</view>
<view class="countStyle">
总数:
总数:{{count}}
</view>
</view>
<view style="height: 250px;">

395
weapp/package/deviceBigdataGraph/statusDetail/statusDetail.js

@ -1,143 +1,276 @@
// package/deviceBigdataGraph/detail/detail.js
import * as echarts from '../../components/ec-canvas/echarts';
function setOption(chart, data1,data2) {
const option = {
legend: {
data: ['设备故障率', '设备完好率'],
top:'-5px'
},
title:{
text:'单位%',
top:'-5px',
textStyle:{
fontSize:'10px',
fontWeight:'normal'
const moment = require("../../../utils/moment");
function setOption(chart, data1, data2,xdata) {
const option = {
legend: {
data:['设备故障率', '设备完好率'],
top: '-5px'
},
title: {
text: '单位%',
top: '-5px',
textStyle: {
fontSize: '10px',
fontWeight: 'normal'
}
},
grid: {
top: '5%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data:xdata
},
yAxis: {
type: 'value',
},
series: [{
name: '设备完好率',
data: data1,
type: 'line'
},
{
name: '设备故障率',
data: data2,
type: 'line'
}
]
};
chart.setOption(option);
}
Page({
/**
* 页面的初始数据
*/
data: {
ec: {
// onInit: initChart,
lazyLoad: true, // 将 lazyLoad 设为 true 后,需要手动初始化图表
},
isLoaded: false,
list: [1, 2, 3],
count: 0, //设备总数
deviceList: [], //设备列表
equipmentFailureRate: 0, //设备故障率
equipmentIntegrityRate: 0, //设备完好率
normalCount: 0, //正常数量
abnormalCount: 0, //异常数量
unknownCount: 0, //未知数量
},
/**
* 生命周期函数--监听页面加载
*/
initChart: function (data1, data2,xData) {
this.ecComponent = this.selectComponent('#device-status-chart');
this.ecComponent.init((canvas, width, height, dpr) => {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // new
});
setOption(chart, data1, data2,xData);
// 将图表实例绑定到 this 上,可以在其他成员函数中访问
this.chart = chart;
this.setData({
isLoaded: true,
});
// 注意这里一定要返回 chart 实例,否则会影响事件处理等
return chart;
});
},
onLoad(options) {
const that = this
//上次菜单传入设备列表
const complexArray = JSON.parse(decodeURIComponent(options.arrayData));
//上级菜单传入巡检记录
const patrolRecord = JSON.parse(decodeURIComponent(options.patrolRecord))
const today = moment();
// 创建一个对象来存储每个pointId的最大inspectionTime
const maxInspectionTimeByPointId = {};
const sevenDaysAgo = moment().subtract(7, 'days'); // 获取七天前的日期
// 过滤出近七天内的最新记录(同点位+同一天的最新记录)
const latestRecords = patrolRecord.filter((record) => {
const inspectionDate = moment(record.inspectionTime).format('YYYY-MM-DD');
const isWithin7Days = moment(today).diff(inspectionDate, 'days') <= 7;
if (!isWithin7Days) {
return false;
}
return patrolRecord.every((r) => {
if (r.pointId === record.pointId && moment(r.inspectionTime).isSame(moment(record.inspectionTime), 'day')) {
return moment(r.inspectionTime).isSameOrBefore(moment(record.inspectionTime));
}
return true;
});
});
//调用每天的函数处理每天的正常-异常-未知的个数
const sevenDays= that.calculateDailyDeviceStatusCounts(latestRecords)
// 遍历数据并更新maxInspectionTimeByPointId
patrolRecord.forEach((item) => {
const {pointId,inspectionTime} = item;
if (pointId in maxInspectionTimeByPointId) {
if (inspectionTime > maxInspectionTimeByPointId[pointId]) {
maxInspectionTimeByPointId[pointId] = inspectionTime;
}
} else {
maxInspectionTimeByPointId[pointId] = inspectionTime;
}
});
// 过滤数据以获取相同pointId中inspectionTime最大的记录
const filteredData = patrolRecord.filter((item) => {
const { pointId,inspectionTime} = item;
const inspectionDate = moment(inspectionTime);
if (inspectionDate.isBetween(sevenDaysAgo, today, null, '[]')) {
return inspectionTime === maxInspectionTimeByPointId[pointId];
}
return false;
});
//七天内最新的数据(正常)
const statusCounts =that.classifiedStatistics(filteredData)
const {unknown,normal,abnormal}=statusCounts
const deviceCount=complexArray.length
that.setData({
count: complexArray.length || 0,
deviceList: complexArray,
equipmentFailureRate:deviceCount?Math.round(((unknown+abnormal)/deviceCount)*100):0,
quipmentIntegrityRate:deviceCount?Math.round((normal/deviceCount)*100):0
})
//正常数据
const data1=Object.values(sevenDays).map(item=>Number(Math.round((item.normal/complexArray.length)*100)))
//故障数据
const data2=Object.values(sevenDays).map(item=>Number(Math.round((item.abnormal+item.unknown/complexArray.length)*100)))
const xData=Object.keys(sevenDays)
setTimeout(() => {
that.initChart(data1,data2,xData)
}, 1000)
},
//分类统计设备,异常-正常-未知个数
classifiedStatistics:function(list){
let normal = 0;
let abnormal = 0;
let unknown = 0;
list.forEach((item) => {
const inspectContent = item.alarm ? (item?.points?.inspectContent || []) : [];
if (inspectContent && inspectContent.length && Array.isArray(inspectContent)) {
inspectContent.forEach((p) => {
// 如果设备有报警
if (p.alarm) {
if (item.patrolRecordIssueHandles.length) {
const state = item.patrolRecordIssueHandles[0].state;
if (state === 6) {
// 正常
normal += 1;
} else if (state === 5) {
// 未知
unknown += 1;
} else {
// 异常
abnormal += 1;
}
}
} else {
// 正常
normal += 1;
}
});
}
});
return {normal,unknown,abnormal}
},
//统计每天异常-正常-未知个数
calculateDailyDeviceStatusCounts:function(data) {
const dateRange = []
const today = moment()
for (let i = 6; i >= 0; i--) {
dateRange.push(today.clone().subtract(i, 'days').format('YYYY-MM-DD'));
}
const dailyCounts = {};
// 初始化每一天的统计为零
dateRange.forEach((date) => {
dailyCounts[date] = {
normal: 0,
unknown: 0,
abnormal: 0
};
});
// 遍历数据,根据日期统计
data.forEach((item) => {
const inspectionDate = moment(item.inspectionTime).format('YYYY-MM-DD');
if (dailyCounts[inspectionDate] !== undefined) {
const status = item.patrolRecordIssueHandles.length ? item.patrolRecordIssueHandles[0].state : 6;
if (status === 6) {
dailyCounts[inspectionDate].normal += 1;
} else if (status === 5) {
dailyCounts[inspectionDate].unknown += 1;
} else {
dailyCounts[inspectionDate].abnormal += 1;
}
}
});
return dailyCounts;
},
grid: {
top: '5%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
this.ecComponent = this.selectComponent('#device-status-chart');
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
yAxis: {
type: 'value',
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
series: [
{
name:'设备完好率',
data: data1,
type: 'line'
},
{
name:'设备故障率',
data: data2,
type: 'line'
}
]
};
chart.setOption(option);
}
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
Page({
},
/**
* 页面的初始数据
*/
data: {
ec: {
// onInit: initChart,
lazyLoad: true, // 将 lazyLoad 设为 true 后,需要手动初始化图表
},
isLoaded: false,
list: [1,2,3]
},
/**
* 生命周期函数--监听页面加载
*/
initChart: function (data1,data2) {
this.ecComponent = this.selectComponent('#device-status-chart');
this.ecComponent.init((canvas, width, height, dpr) => {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // new
});
setOption(chart, data1,data2);
// 将图表实例绑定到 this 上,可以在其他成员函数中访问
this.chart = chart;
this.setData({
isLoaded: true,
});
// 注意这里一定要返回 chart 实例,否则会影响事件处理等
return chart;
});
},
onLoad(options) {
setTimeout(() => {
this.initChart([1,2,3,4,5,6],[1,2,3,10,1])
}, 1000)
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
this.ecComponent = this.selectComponent('#device-status-chart');
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

6
weapp/package/deviceBigdataGraph/statusDetail/statusDetail.wxml

@ -8,18 +8,18 @@
<image src='/images/rectangle.png' style="width: 61px;height:31.86px;"></image>
<view class="icon-text">设备总数</view>
</view>
<view class="fontStyle">300个</view>
<view class="fontStyle">{{count}}个</view>
</view>
<image src="/images/deviceStatus.png" style="width:161.05px;height:166.86px;position: absolute;right: 15px;"></image>
</view>
<view style="display: flex; justify-content: space-between;align-items: center;padding: 0 10px;">
<view class="title-item flex flex-col">
<view>设备故障率</view>
<view><text class="title-num">{{86}}%</text></view>
<view><text class="title-num">{{equipmentFailureRate}}%</text></view>
</view>
<view class="title-item flex flex-col">
<view>完好率</view>
<view><text class="title-num">{{300}}%</text></view>
<view><text class="title-num">{{quipmentIntegrityRate}}%</text></view>
</view>
</view>
</view>

66
weapp/package/report/report.js

@ -24,39 +24,39 @@ Page({
checkItems: [], // 检查项
inspectContentArr: [], // 巡检内容
isCommitting: false,
planList: null, // 巡检计划列表
// planList: null, // 巡检计划列表
structListVisible: true,
scenePointId: null, // 当前点位id
},
//巡检计划
getPatrolPlan: function (scenePointId) {
let that = this;
wx.showLoading({
title: '加载中',
})
Request.get(getPatrolPlan()).then(res => {
wx.hideLoading();
let pointPlan = res.rows.filter(plan => {
for (const point of plan.points) {
if (point.id == scenePointId) {
return true;
}
}
return false;
}).map(p => ({
label: p.name,
value: p.name,
...p
}))
that.setData({
planList: pointPlan
})
})
},
// //巡检计划
// getPatrolPlan: function (scenePointId) {
// let that = this;
// wx.showLoading({
// title: '加载中',
// })
// Request.get(getPatrolPlan()).then(res => {
// wx.hideLoading();
// let pointPlan = res.rows.filter(plan => {
// for (const point of plan.points) {
// if (point.id == scenePointId) {
// return true;
// }
// }
// return false;
// }).map(p => ({
// label: p.name,
// value: p.name,
// ...p
// }))
// that.setData({
// planList: pointPlan
// })
// })
// },
//点位改变函数
pointChange(e){
const that = this
that.getPatrolPlan(that.data.data[e.detail.value].id)
// that.getPatrolPlan(that.data.data[e.detail.value].id)
that.setData({
inspectContentArr:[],
pointIndex:e.detail.value,
@ -245,8 +245,14 @@ Page({
}
}
const { id, name, departmentId, deptName } = wx.getStorageSync('userInfo');
const curPlan = that.data.planList.find(item=>item.id==patrolTemplate[patrolTemplateIndex].id)
const nextItemData = curPlan.points.find(p => p.id == this.data.scenePointId)
const newData = that.data.data.map((item) => {
// 使用对象的解构赋值去掉 project 和 devices 属性
const { project, devices, ...newItem } = item;
return newItem;
});
const nextItemData=newData.find(item=>item.id===pointList[pointIndex].id)
// const curPlan = that.data.planList.find(item=>item.id==patrolTemplate[patrolTemplateIndex].id)
// const nextItemData = curPlan.points.find(p => p.id == this.data.scenePointId)
const aboutSend=templateData.find(item=>item.patrolTemplate.id===patrolTemplate[patrolTemplateIndex].id)
let datas = {
patrolPlanId: -1,
@ -255,7 +261,7 @@ Page({
points: {
user: { id, name, department: { id: departmentId, name: deptName } },
project: aboutSend.project,
frequency: aboutSend.frequency,
// frequency: aboutSend.frequency,
itemData:nextItemData,
inspectContent: reportArr,
address: address

5
weapp/package/subSystem/subSystem.js

@ -120,7 +120,7 @@ Page({
filterLevelCount:function(list,level){
return list?.filter(i => {
const content = i?.points?.inspectContent
if (content) {
if (content&&content.length) {
for (let key in content) {
if (content.hasOwnProperty(key)) {
const subObject = content[key];
@ -131,6 +131,7 @@ Page({
})?.length
},
getSubSystemPatrolAbout: function (options) {
// const userInfo=wx.getStorageSync('userInfo');
let that = this;
//当月开始时间
const STime = moment().startOf('month').format('YYYY-MM-DD')
@ -145,8 +146,10 @@ Page({
keywords
}
Request.get(getSubSystemPatrolAbout(query)).then(res => {
if (res) {
//巡查内容
// const list=res?.filter(item=>item?.points?.user.id===userInfo.id)||[]
that.setData({
currentRepairCount: res?.filter(i =>i.patrolRecordIssueHandles.length>0 ).length || 0,
currentPatrolCount: res.length,

3
weapp/utils/getApiUrl.js

@ -43,9 +43,6 @@ exports.reportQuest = () => {
exports.getPatrolRecord = (patrolPlanId, startTime, endTime, alarm, pointId) => {
return `/patrolRecord/${patrolPlanId}/${startTime}/${endTime}/${alarm}/${pointId}`
}
exports.getAllPatrol = () => {
return `/allPatrol`
}
//设备
exports.getDevices = () => {
return `/devices`

Loading…
Cancel
Save