From 9d9e9c6c4abcdeba05f47ca3db116870427c367a Mon Sep 17 00:00:00 2001 From: wuqun Date: Tue, 1 Nov 2022 16:02:53 +0800 Subject: [PATCH] =?UTF-8?q?(*)=E5=91=8A=E8=AD=A6=E4=BA=A7=E7=94=9F=20?= =?UTF-8?q?=E5=91=8A=E8=AD=A6=E7=A1=AE=E8=AE=A4=20=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=88=B0=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/controllers/alarm/alarmConfirmLog.js | 106 +++++++++++++++++- api/app/lib/controllers/alarm/app.js | 7 +- api/app/lib/controllers/alarm/video.js | 17 ++- api/app/lib/service/kafka.js | 15 ++- .../sections/control/containers/control.jsx | 19 +++- 5 files changed, 151 insertions(+), 13 deletions(-) diff --git a/api/app/lib/controllers/alarm/alarmConfirmLog.js b/api/app/lib/controllers/alarm/alarmConfirmLog.js index 378c584..6707ab8 100644 --- a/api/app/lib/controllers/alarm/alarmConfirmLog.js +++ b/api/app/lib/controllers/alarm/alarmConfirmLog.js @@ -5,6 +5,7 @@ const moment = require('moment') async function alarmConfirmLog(ctx, confirmPost, content) { try { const { models } = ctx.fs.dc; + const { clickHouse } = ctx.app.fs; //存日志 let logDatas = []; confirmPost.map(cp => { @@ -33,9 +34,9 @@ async function alarmConfirmLog(ctx, confirmPost, content) { await models.LatestDynamicList.bulkCreate(dynamics); //消息推送到前端 - //ctx.app.socket.emit('TEST', { someProperty: '【广播】呼叫青铜时代号!!!', }) - - + if (logDatas.length) { + await sendConfirmToWeb(ctx.app, models, clickHouse, logDatas, false); + } } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; @@ -45,6 +46,103 @@ async function alarmConfirmLog(ctx, confirmPost, content) { } } +let constAlarmGroups = { + 1: '数据中断', + 2: '数据异常', + 3: '策略命中', + 4: '设备异常', + 5: '设备异常', + 'video': '视频异常', + 'app': '应用异常' +} +async function sendAppearToWeb(app, models, clickHouse, datas, ttype) { + try { + //告警类型 + let alarmGroup = null + + //项目信息 + let { projects, pepProjects } = await getProjectsInfo(models, clickHouse, datas); + + //数据类区分alarmGroup + if (ttype == 'data') { + let alarm_group = await clickHouse.anxinyun.query( + `SELECT alarm_group FROM t_alarm_code WHERE code='${datas[0].alarmInfo.alarmTypeCode}'`).toPromise(); + + alarmGroup = alarm_group.length ? constAlarmGroups[alarm_group[0].alarm_group] : null + } else { + alarmGroup = constAlarmGroups[ttype] + } + + let sendData = [] + datas.map(ld => { + let pepPId = projects.find(p => p.id == ld.projectCorrelationId).pepProjectId; + sendData.push({ + project: projects.find(p => p.id == ld.projectCorrelationId).name || pepProjects.find(pp => pp.id == pepPId).project_name,//前者为自定义项目名称 + source: ld.alarmInfo.sourceName, + type: ld.type, + time: ld.time, + alarmGroup//告警类型 + }) + }) + app.socket.emit('alarmSendSocket', { type: 'alarmAppear', sendData }) + } catch (err) { + console.log(`告警(发现)推送失败, error: ${err}`); + } +} + +async function getProjectsInfo(models, clickHouse, logDatas) { + try { + let pIds = logDatas.map(l => l.projectCorrelationId);//所有的项目的id + let projects = await models.ProjectCorrelation.findAll({ + where: { id: { $in: pIds } }, + attributes: ['id', 'name', 'pepProjectId'] + }); + + let pepPojectIds = new Set(); + for (let p of projects) { + pepPojectIds.add(p.pepProjectId); + } + + let pepProjects = pepPojectIds.size ? await clickHouse.projectManage.query(` + SELECT id, project_name FROM t_pim_project WHERE id IN (${[...pepPojectIds]})`).toPromise() : []; + + return { projects, pepProjects }; + } catch (err) { + console.log(`获取项目信息失败, error: ${err}`); + } +} +async function sendConfirmToWeb(app, models, clickHouse, logDatas, isAuto) { + try { + //用户信息 + let userName = null + if (!isAuto) { + let userPepRes = await clickHouse.pepEmis.query( + `SELECT DISTINCT user.id AS id, "user"."name" AS name FROM user WHERE user.id=${logDatas[0].pepUserId}`).toPromise(); + userName = userPepRes.length ? userPepRes[0].name : null + } + + //项目信息 + let { projects, pepProjects } = await getProjectsInfo(models, clickHouse, logDatas); + let sendData = [] + logDatas.map(ld => { + let pepPId = projects.find(p => p.id == ld.projectCorrelationId).pepProjectId; + sendData.push({ + user: userName, + project: projects.find(p => p.id == ld.projectCorrelationId).name || pepProjects.find(pp => pp.id == pepPId).project_name,//前者为自定义项目名称 + source: ld.alarmInfo.source, + type: ld.alarmInfo.type, + time: ld.confirmTime, + isAuto//是否为自动恢复,自动恢复时user为null + }) + }) + app.socket.emit('alarmSendSocket', { type: 'alarmConfirm', sendData })//小飞(处理人) 确认并关闭了A项目(项目) DTU设备(告警源) 状态异常(异常类型)的问题 + } catch (err) { + console.log(`告警(确认)推送失败, error: ${err}`); + } +} + module.exports = { - alarmConfirmLog + alarmConfirmLog, + sendAppearToWeb, + sendConfirmToWeb }; \ No newline at end of file diff --git a/api/app/lib/controllers/alarm/app.js b/api/app/lib/controllers/alarm/app.js index d5e217b..89a5896 100644 --- a/api/app/lib/controllers/alarm/app.js +++ b/api/app/lib/controllers/alarm/app.js @@ -1,7 +1,7 @@ 'use strict'; const moment = require('moment') -const { alarmConfirmLog } = require('./alarmConfirmLog'); +const { alarmConfirmLog, sendAppearToWeb } = require('./alarmConfirmLog'); async function inspection(ctx) { // 巡查 try { @@ -143,6 +143,7 @@ async function notedInspection(ctx) { async function apiError(ctx) { try { + const { clickHouse } = ctx.app.fs const models = ctx.fs.dc.models; const { projectAppId, alarmContent, router, statusCode, screenshot = '', type } = ctx.request.body const now = moment().format() @@ -233,6 +234,10 @@ async function apiError(ctx) { type: 1//发现 } await models.LatestDynamicList.create(dynamic); + + + //消息推送到前端 + await sendAppearToWeb(ctx.app, models, clickHouse, [data], 'app'); } } diff --git a/api/app/lib/controllers/alarm/video.js b/api/app/lib/controllers/alarm/video.js index 02c59c7..8fd296b 100644 --- a/api/app/lib/controllers/alarm/video.js +++ b/api/app/lib/controllers/alarm/video.js @@ -1,7 +1,7 @@ 'use strict'; const moment = require('moment') -const { alarmConfirmLog } = require('./alarmConfirmLog'); -async function deviceType (ctx) { +const { alarmConfirmLog, sendAppearToWeb } = require('./alarmConfirmLog'); +async function deviceType(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs @@ -21,7 +21,7 @@ async function deviceType (ctx) { } } -async function alarmList (ctx) { +async function alarmList(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs @@ -262,7 +262,7 @@ async function alarmList (ctx) { } } -async function confirm (ctx) { +async function confirm(ctx) { try { const { alarmId, content, confirmPost } = ctx.request.body; // TODO: 以视频·应用的秘钥进行鉴权 @@ -284,7 +284,7 @@ async function confirm (ctx) { } } -async function alarmAdded (ctx) { +async function alarmAdded(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs @@ -318,6 +318,11 @@ async function alarmAdded (ctx) { } }) await models.LatestDynamicList.bulkCreate(dynamics); + + //消息推送到前端 + if (datas.length) { + await sendAppearToWeb(ctx.app, models, clickHouse, datas, 'video'); + } } ctx.status = 200; } catch (error) { @@ -329,7 +334,7 @@ async function alarmAdded (ctx) { } } -async function vcmpAppAuthToken (ctx) { +async function vcmpAppAuthToken(ctx) { try { const { models } = ctx.fs.dc; const { utils: { vcmpAuth } } = ctx.app.fs diff --git a/api/app/lib/service/kafka.js b/api/app/lib/service/kafka.js index cc0bb85..3e2d7e2 100644 --- a/api/app/lib/service/kafka.js +++ b/api/app/lib/service/kafka.js @@ -1,7 +1,7 @@ 'use strict'; const moment = require('moment'); const Kafka = require('kafka-node'); - +const { sendAppearToWeb, sendConfirmToWeb } = require('../controllers/alarm/alarmConfirmLog') module.exports = async function factory(app, opts) { try { const client = new Kafka.KafkaClient({ kafkaHost: opts.kafka.rootURL, fromOffset: true }); @@ -123,6 +123,13 @@ module.exports = async function factory(app, opts) { } }) await models.LatestDynamicList.bulkCreate(dynamics); + + //消息推送到前端 + if (datas.length) { + await sendAppearToWeb(app, models, clickHouse, datas, 'data'); + } + + } else if (messageMode == 'AlarmAutoElimination') {//告警自动恢复------------------------------------2 let datas = projects.map(d => { return { @@ -143,6 +150,12 @@ module.exports = async function factory(app, opts) { } }) await models.LatestDynamicList.bulkCreate(dynamics); + + + //消息推送到前端 + if (datas.length) { + await sendConfirmToWeb(app, models, clickHouse, datas, true); + } } } } else { diff --git a/web/client/src/sections/control/containers/control.jsx b/web/client/src/sections/control/containers/control.jsx index 801caad..78f4867 100644 --- a/web/client/src/sections/control/containers/control.jsx +++ b/web/client/src/sections/control/containers/control.jsx @@ -48,6 +48,23 @@ const Control = (props) => { const exhibition = useRef({ workbench: [], statistical: [] }) //页面结构 const FormApi = useRef() + // websocket 使用测试 + useEffect(() => { + if (socket) { + socket.on('alarmSendSocket', function (msg) { + //console.info(msg); + if (msg.type == "alarmAppear") {//告警出现 + + } else if (msg.type == "alarmConfirm") {//告警确认 + + } + }); + return () => { + socket.off("alarmSendSocket"); + } + } + }, [socket]) + useEffect(() => { consoleToollink() @@ -770,7 +787,7 @@ function mapStateToProps (state) { actions: global.actions, pepProjectId: global.pepProjectId, // members: members.data, - // socket: webSocket.socket + socket: webSocket.socket }; }