diff --git a/api/app/lib/controllers/alarm/video.js b/api/app/lib/controllers/alarm/video.js index a7084a1..e8ab1b0 100644 --- a/api/app/lib/controllers/alarm/video.js +++ b/api/app/lib/controllers/alarm/video.js @@ -284,47 +284,75 @@ async function confirm(ctx) { } } +let structsAche = { + dataList: [], + expireTime: null//10分钟更新一次结构物列表 +} +async function getStructsAche(ctx) { + const { utils: { getAxyStructs } } = ctx.app.fs + try { + if (!structsAche.dataList.length || moment() > moment(structsAche.expireTime)) { + let structList = await getAxyStructs(); + structsAche.dataList = structList; + structsAche.expireTime = moment().add(10, 'minute').format('YYYY-MM-DD HH:mm:ss'); + } + return structsAche; + } catch (err) { + console.log(`获取结构物列表失败, error: ${err}`); + } +} + async function alarmAdded(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs - const { utils: { anxinStrucIdRange, sendAppearToWeb } } = ctx.app.fs - let anxinStruc = await anxinStrucIdRange({ ctx }) + const { utils: { sendAppearToWeb } } = ctx.app.fs - const { serial_no, channel_no, create_time, description, status_id } = ctx.request.body; + let structsAche = await getStructsAche(ctx); + if (structsAche) { + let anxinStruc = structsAche.dataList;//结构物列表 + const { serial_no, channel_no, create_time, description, status_id } = ctx.request.body; - let belongToStruct = await clickHouse.anxinyun.query( - `SELECT name, structure FROM t_video_ipc WHERE serial_no='${serial_no}' and channel_no='${channel_no}'`).toPromise() - let structId = belongToStruct.length ? belongToStruct[0].structure : null + let belongToStruct = await clickHouse.anxinyun.query( + `SELECT name, structure FROM t_video_ipc WHERE serial_no='${serial_no}' and channel_no=${parseInt(channel_no)}`).toPromise() + let structId = belongToStruct.length ? belongToStruct[0].structure : null - if (structId) { - let exist = anxinStruc.find(s => s.strucId == structId); - let projects = exist.pomsProject.filter(d => !d.del).map(p => p.id); - let datas = projects.map(d => {//需要 项目,告警源,异常类型,时间 - return { - projectCorrelationId: d, - alarmInfo: { messageMode: 'AlarmGeneration', sourceName: belongToStruct[0].name, status_id, content: description },//AlarmGeneration代表告警首次产生 - time: create_time, - type: description - } - }) - let rslt = await models.AlarmAppearRecord.bulkCreate(datas, { returning: true }); - let dynamics = rslt.map(r => { - return { - time: r.time, - alarmAppearId: r.id, - projectCorrelationId: r.projectCorrelationId, - type: 1//发现 - } - }) - await models.LatestDynamicList.bulkCreate(dynamics); + if (structId) { + let exist = anxinStruc.find(s => s.strucId == structId); + if (exist) { + let projects = exist.pomsProject.filter(d => !d.del).map(p => p.id); + let datas = projects.map(d => {//需要 项目,告警源,异常类型,时间 + return { + projectCorrelationId: d, + alarmInfo: { messageMode: 'AlarmGeneration', sourceName: belongToStruct[0].name, status_id, content: description },//AlarmGeneration代表告警首次产生 + time: create_time, + type: description + } + }) + let rslt = await models.AlarmAppearRecord.bulkCreate(datas, { returning: true }); + let dynamics = rslt.map(r => { + return { + time: r.time, + alarmAppearId: r.id, + projectCorrelationId: r.projectCorrelationId, + type: 1//发现 + } + }) + await models.LatestDynamicList.bulkCreate(dynamics); - //消息推送到前端 - if (datas.length) { - await sendAppearToWeb(datas, 'video'); + //消息推送到前端 + if (datas.length) { + await sendAppearToWeb(datas, 'video'); + } + } + } + ctx.status = 200; + } else { + ctx.status = 400; + ctx.body = { + message: `获取结构物列表失败` } } - ctx.status = 200; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.status = 400; diff --git a/api/app/lib/schedule/alarms_handle_statistics.js b/api/app/lib/schedule/alarms_handle_statistics.js index dcfa55d..91f9ef6 100644 --- a/api/app/lib/schedule/alarms_handle_statistics.js +++ b/api/app/lib/schedule/alarms_handle_statistics.js @@ -7,7 +7,7 @@ module.exports = function (app, opts) { const { database: anxinyun } = clickHouse.anxinyun.opts.config const alarmHandleStatistics = app.fs.scheduleInit( { - interval: '0 48 1 ? * MON',//0 48 1 ? * MON 每周一凌晨1点48开始执行 + interval: '0 18 1 ? * 1',//每周一1点18触发 // immediate: true, proRun: true, }, diff --git a/api/app/lib/utils/alarmHandle.js b/api/app/lib/utils/alarmHandle.js index c3b8a67..34fef95 100644 --- a/api/app/lib/utils/alarmHandle.js +++ b/api/app/lib/utils/alarmHandle.js @@ -1,4 +1,5 @@ 'use strict'; +const moment = require('moment') module.exports = function (app, opts) { const { models } = app.fs.dc @@ -43,7 +44,8 @@ module.exports = function (app, opts) { alarmGroup//告警类型 }) }) - app.socket.emit('alarmSendSocket', { type: 'alarmAppear', sendData }) + //app.socket.emit('alarmSendSocket', { type: 'alarmAppear', sendData }) + await socketThrottle('appear', sendData); } catch (err) { console.log(`告警(发现)推送失败, error: ${err}`); } @@ -74,7 +76,8 @@ module.exports = function (app, opts) { isAuto//是否为自动恢复,自动恢复时user为null }) }) - app.socket.emit('alarmSendSocket', { type: 'alarmConfirm', sendData })//小飞(处理人) 确认并关闭了A项目(项目) DTU设备(告警源) 状态异常(异常类型)的问题 + //app.socket.emit('alarmSendSocket', { type: 'alarmConfirm', sendData })//小飞(处理人) 确认并关闭了A项目(项目) DTU设备(告警源) 状态异常(异常类型)的问题 + await socketThrottle('confirm', sendData); } catch (err) { console.log(`告警(确认)推送失败, error: ${err}`); } @@ -110,20 +113,55 @@ module.exports = function (app, opts) { let pepPId = projects.find(p => p.id == projectCorrelationId).pepProjectId; //需要 策略名称 处理人 项目 策略和参数 时间 - let sendData = { + let sendData = [{ pushConfig: { cfgName, tactics, tacticsParams },//策略信息 pepUsers, projectCorrelationId: projectCorrelationId, project: projects.find(p => p.id == projectCorrelationId).name || pepProjects.find(pp => pp.id == pepPId).project_name,//前者为自定义项目名称 time - } + }] - app.socket.emit('alarmSendSocket', { type: 'alarmNotice', sendData }) + //app.socket.emit('alarmSendSocket', { type: 'alarmNotice', sendData }) + await socketThrottle('notice', sendData); } catch (err) { console.log(`推送通知失败, error: ${err}`); } } + async function socketThrottle(type, dataList) { + try { + if (!msgSendObj.time || moment() > moment(msgSendObj.time).add(1, 'minute')) {//首次 || 跟上次时间间隔大于1分钟 直接发送 + msgSendObj.dataMap[type] = dataList; + app.socket.emit('alarmSendSocket', { msgDataMap: msgSendObj.dataMap });//发送到前端 + + msgSendObj.time = moment().format();//记录本次发送时间 + msgSendObj.dataMap = { appear: [], confirm: [], notice: [] } + msgSendObj.toSend = false + } else {//放进队列 + msgSendObj.dataMap[type] = msgSendObj.dataMap[type].concat(dataList); + msgSendObj.toSend = true;//有待发送 + } + } catch (err) { + console.log(`推送节流失败, error: ${err}`); + } + } + + //全局变量 + let msgSendObj = { + time: null, + dataMap: { appear: [], confirm: [], notice: [] }, + toSend: false//有待发送 + } + setInterval(async () => { + if (msgSendObj.toSend) {//有待发送 + app.socket.emit('alarmSendSocket', { msgDataMap: msgSendObj.dataMap })//发送到前端 + + msgSendObj.time = moment().format() + msgSendObj.dataMap = { appear: [], confirm: [], notice: [] } + msgSendObj.toSend = false + } + }, 60 * 1000)//1分钟 + return { sendAppearToWeb,//推送告警发现 sendConfirmToWeb,//推送告警确认 diff --git a/web/client/src/sections/control/containers/control.jsx b/web/client/src/sections/control/containers/control.jsx index 0b8b3f3..0aefc4b 100644 --- a/web/client/src/sections/control/containers/control.jsx +++ b/web/client/src/sections/control/containers/control.jsx @@ -62,6 +62,8 @@ const Control = (props) => { } else if (msg.type == "alarmNotice") {//通知 } + //console.info(msg); + let a = msg; }); return () => { socket.off("alarmSendSocket");