diff --git a/api/app/lib/controllers/control/data.js b/api/app/lib/controllers/control/data.js index 4b09bcd..5cdd5ad 100644 --- a/api/app/lib/controllers/control/data.js +++ b/api/app/lib/controllers/control/data.js @@ -2,7 +2,7 @@ const moment = require('moment'); //BI分析-数据 -async function getDataAlarmsAggDay(ctx) { +async function getDataAlarmsAggDay (ctx) { try { const { utils: { anxinStrucIdRange } } = ctx.app.fs const { pepProjectId } = ctx.query @@ -12,10 +12,8 @@ async function getDataAlarmsAggDay(ctx) { ctx, pepProjectId }) let whereOption = [] - // ! 1 开发临时增加 if (anxinStruc.length) { const anxinStrucIds = anxinStruc.map(a => a.strucId) - // ! 开发临时注释 whereOption.push(`alarms.StructureId IN (${anxinStrucIds.join(",")})`) let start = moment().add(-1, 'year').format('YYYY-MM-DD HH:mm:ss');//最近一年 @@ -41,7 +39,7 @@ async function getDataAlarmsAggDay(ctx) { } } -async function queryAlarm(ctx, alarmQueryOptionStr, type) { +async function queryAlarm (ctx, alarmQueryOptionStr, type) { const { clickHouse } = ctx.app.fs try { const alarmRes = await clickHouse.dataAlarm.query(` @@ -76,7 +74,7 @@ async function queryAlarm(ctx, alarmQueryOptionStr, type) { } //BI分析-应用异常 -async function getAppAlarmsAggDay(ctx) { +async function getAppAlarmsAggDay (ctx) { try { const models = ctx.fs.dc.models; const { utils: { pomsProjectRange } } = ctx.app.fs @@ -129,7 +127,7 @@ async function getAppAlarmsAggDay(ctx) { } //BI分析-视频异常 -async function getVideoAlarmsAggDay(ctx) { +async function getVideoAlarmsAggDay (ctx) { try { const { clickHouse, utils: { anxinStrucIdRange } } = ctx.app.fs const { database: anxinyun } = clickHouse.anxinyun.opts.config @@ -246,7 +244,7 @@ async function getVideoAlarmsAggDay(ctx) { } //BI分析-问题处置效率分析 -async function getAlarmsHandleStatistics(ctx) { +async function getAlarmsHandleStatistics (ctx) { try { const { projectCorrelationId } = ctx.query const models = ctx.fs.dc.models; @@ -266,7 +264,7 @@ async function getAlarmsHandleStatistics(ctx) { } } //最新动态 -async function getLatestDynamic(ctx) { +async function getLatestDynamic (ctx) { try { const { models } = ctx.fs.dc; const { limit, page, projectCorrelationId, types } = ctx.query; @@ -303,9 +301,9 @@ async function getLatestDynamic(ctx) { }); //查项目名称 查用户名 - let pepPojectIds = new Set(), notedUserIds = new Set(); + let pepPojectIds = new Set(), notedUserIds = new Set(), emailSendPomsProjectIds = new Set(); for (let p of news) { - if(p.projectCorrelation && p.projectCorrelation.pepProjectId){ + if (p.projectCorrelation && p.projectCorrelation.pepProjectId) { pepPojectIds.add(p.projectCorrelation.pepProjectId); } @@ -313,11 +311,28 @@ async function getLatestDynamic(ctx) { p.emailSendLog.toPepUserIds.map(u => { notedUserIds.add(u);//通知 接收人 }) + p.emailSendLog.projectCorrelationId.forEach(pid => emailSendPomsProjectIds.add(pid)) } if (p.alarmConfirmLog && p.alarmConfirmLog.pepUserId) { notedUserIds.add(p.alarmConfirmLog.pepUserId);//确认 操作者 } } + + // EM 推送的特殊处理 + // 查找对应的 projectCorrelation + const emailLogProjectCorrelationRes = + emailSendPomsProjectIds.size ? + await models.ProjectCorrelation.findAll({ + where: { + id: { $in: [...emailSendPomsProjectIds] } + } + }) : [] + + for (let { dataValues: p } of emailLogProjectCorrelationRes) { + if (p.pepProjectId) { + pepPojectIds.add(p.pepProjectId) + } + } let pepProjects = pepPojectIds.size ? await clickHouse.projectManage.query(` SELECT id, project_name FROM t_pim_project WHERE id IN (${[...pepPojectIds].join(',')},-1) `).toPromise() : []; @@ -339,7 +354,15 @@ async function getLatestDynamic(ctx) { if (d.emailSendId) { notice.push({ userName: userPepRes.filter(u => d.emailSendLog.toPepUserIds.indexOf(u.id) != -1), - projectName, + projectName: d.emailSendLog.projectCorrelationId.map(p => { + let projectName = '' + if (p.pepProjectId) { + projectName = pepProjects.find(pp => pp.id == p.pepProjectId).project_name + } else { + projectName = p.name + } + return projectName + }).join('、'), ...d.emailSendLog.dataValues }); } diff --git a/api/app/lib/index.js b/api/app/lib/index.js index dcc655c..84559e9 100644 --- a/api/app/lib/index.js +++ b/api/app/lib/index.js @@ -77,8 +77,8 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq AppAlarm.belongsTo(App, { foreignKey: 'projectAppId', targetKey: 'id' }); App.hasMany(AppAlarm, { foreignKey: 'projectAppId', sourceKey: 'id' }); - AlarmPushConfig.belongsTo(ProjectCorrelation, { foreignKey: 'pomsProjectId', targetKey: 'id' }); - ProjectCorrelation.hasMany(AlarmPushConfig, { foreignKey: 'pomsProjectId', sourceKey: 'id' }); + // AlarmPushConfig.belongsTo(ProjectCorrelation, { foreignKey: 'pomsProjectId', targetKey: 'id' }); + // ProjectCorrelation.hasMany(AlarmPushConfig, { foreignKey: 'pomsProjectId', sourceKey: 'id' }); AlarmAppearRecord.belongsTo(ProjectCorrelation, { foreignKey: 'projectCorrelationId', targetKey: 'id' }); ProjectCorrelation.hasMany(AlarmAppearRecord, { foreignKey: 'projectCorrelationId', sourceKey: 'id' }); diff --git a/api/app/lib/models/email_send_log.js b/api/app/lib/models/email_send_log.js index e1d95b6..da0a97f 100644 --- a/api/app/lib/models/email_send_log.js +++ b/api/app/lib/models/email_send_log.js @@ -53,7 +53,7 @@ module.exports = dc => { autoIncrement: false }, projectCorrelationId: { - type: DataTypes.INTEGER, + type: DataTypes.ARRAY(DataTypes.INTEGER), allowNull: false, defaultValue: null, comment: null, diff --git a/api/app/lib/models/latest_dynamic_list.js b/api/app/lib/models/latest_dynamic_list.js index 5b53051..320191a 100644 --- a/api/app/lib/models/latest_dynamic_list.js +++ b/api/app/lib/models/latest_dynamic_list.js @@ -54,7 +54,7 @@ module.exports = dc => { }, projectCorrelationId: { type: DataTypes.INTEGER, - allowNull: false, + allowNull: true, defaultValue: null, comment: null, primaryKey: false, diff --git a/api/app/lib/schedule/alarms_push.js b/api/app/lib/schedule/alarms_push.js index c8bd06b..44eca5e 100644 --- a/api/app/lib/schedule/alarms_push.js +++ b/api/app/lib/schedule/alarms_push.js @@ -20,18 +20,22 @@ module.exports = function (app, opts) { disable: false }, order: ['id'], - include: [{ - model: models.ProjectCorrelation, - where: { - del: false, - }, - required: true - }], }) + let pomsProjectId = new Set() let pepProjectIds = new Set() for (let { dataValues: c } of configListRes) { - if (c.projectCorrelation.pepProjectId) { - pepProjectIds.add(c.projectCorrelation.pepProjectId) + if (c.pomsProjectId) { + c.pomsProjectId.forEach(pid => pomsProjectId.add(pid)) + } + } + const pomsProjectRes = pomsProjectId.size ? await models.ProjectCorrelation.findAll({ + where: { + id: { $in: [...pomsProjectId] } + } + }) : [] + for (let { dataValues: c } of pomsProjectRes) { + if (c.pepProjectId) { + pepProjectIds.add(c.pepProjectId) } } const pepProjectRes = pepProjectIds.size ? @@ -55,29 +59,44 @@ module.exports = function (app, opts) { for (let { dataValues: c } of configListRes) { if (c.tacticsParams && c.tactics) { - const { projectCorrelation, strucId, pomsProjectId, } = c + // pomsProjectId 是个数组 [] + const { strucId, pomsProjectId, } = c const { interval, deviceProportion } = c.tacticsParams if ( curMinOfYear % parseInt(interval) == 0 ) { - const corPepProject = projectCorrelation.pepProjectId ? - pepProjectRes.find(p => p.id == projectCorrelation.pepProjectId) - : null - if ( - !projectCorrelation.pepProjectId - || ( - corPepProject - && c.timeType.some(ct => ct == corPepProject.construction_status_id) - ) - ) { - const { anxinProjectId, pepProjectId } = projectCorrelation - // 查当前 poms 下的结构物 并把不包含的去掉 - // 可能有结构物已解绑 - const strucListRes = strucId.length && anxinProjectId.length ? - await clickHouse.anxinyun.query( - ` + const corPomsProject = pomsProjectRes.filter(poms => pomsProjectId.includes(poms.id)) + let curAnxinProjectId = new Set() + let pepProjectName_ = [] + for (let { dataValues: poms } of corPomsProject) { + if (poms.pepProjectId) { + // 找对应的项企项目 + const corPepProject = + pepProjectRes.find(p => p.id == poms.pepProjectId) + if (corPepProject && c.timeType.some(ct => ct == corPepProject.construction_status_id)) { + pepProjectName_.push(corPepProject.project_name) + } else { + // 不符合当前项目的时间节点 + continue + } + } else { + // 是自定义项目 + poms.name ? pepProjectName_.push(poms.name) : null + } + // 筛选全部的 anxinProjectId pepProjectId + for (let axId of poms.anxinProjectId) { + curAnxinProjectId.add(axId) + } + } + + const anxinProjectId = [...curAnxinProjectId] + // 查当前 poms 下的结构物 并把不包含的去掉 + // 可能有结构物已解绑 + const strucListRes = strucId.length && anxinProjectId.length ? + await clickHouse.anxinyun.query( + ` SELECT DISTINCT id, t_structure.id AS id, @@ -109,125 +128,136 @@ module.exports = function (app, opts) { project_state != -1 AND t_project.id IN (${anxinProjectId.join(',')}) AND t_structure.id IN (${strucId.join(',')}) - ` - ).toPromise() : - [] - let strucThingId = [] - let searchStrucIds = strucListRes.map(s => { - if (s.iotaThingId) { - strucThingId.push(s.iotaThingId) - } - return s.id - }) + ).toPromise() : + [] + let strucThingId = [] + let searchStrucIds = strucListRes.map(s => { + if (s.iotaThingId) { + strucThingId.push(s.iotaThingId) + } + return s.id + }) - // 开发测试用的数据 - // searchStrucIds = searchStrucIds.concat([991, 1052, 700]) + // !开发测试用的数据 + // searchStrucIds = searchStrucIds.concat([991, 1052, 700]) - if (searchStrucIds.length) { - searchStrucIds.unshift(-1) - } - let pepProjectName = pepProjectId ? - pepProjectRes.find(p => p.id == pepProjectId).project_name - : projectCorrelation.name - let emailTitle = `${pepProjectName}-${c.name}-` - let emailSubTitle = '' - - let dataAlarmOption = [] - let dataAlarmGroupOption = [] - let dataAlarmSubType = [] - let dataAlarms = [] - - let videoAlarmWhereOption = [] - let videoAlarms = [] - - let appAlarmWhereOption = { - confirmTime: null, - } - let appAlarms = [] - - let deviceCount = 0 - let alarmDeviceCount = 0 - let cameraCount = 0 - let alarmCameraCount = 0 - // 判断推送策略 - let nowTime = moment().startOf('minute') - let pointTime = - moment() - .subtract( - parseInt(interval), - // + 1440 * 365, - 'minute' - ) - .startOf('minute') - .format('YYYY-MM-DD HH:mm:ss') - - let newAddStartTime = pointTime - let newAddEndTime = nowTime.clone() - if (c.tactics == 'immediately') { - // !查所有未解决告警 所以时间范围大可不必 - // dataAlarmOption.push(`StartTime >= '${pointTime}'`); - // appAlarmWhereOption.createTime = { $gte: pointTime } - // videoAlarmWhereOption.push(`camera_status_alarm.create_time >= '${pointTime}'`) - emailTitle += `即时推送服务` - emailSubTitle += `截止${moment(pointTime).format('YYYY年MM月DD日 HH时mm分')}-${moment(nowTime).format('HH时mm分')}:` - } else if (c.tactics == 'continue' || c.tactics == 'abnormal_rate') { - // 新增的应该是上一个时间节点到上上个节点之间 - dataAlarmOption.push(`StartTime <= '${pointTime}'`); - appAlarmWhereOption.createTime = { $lte: pointTime } - videoAlarmWhereOption.push(`camera_status_alarm.create_time <= '${pointTime}'`) - // 新增的应该是上一个时间节点到上上个节点之间 - newAddStartTime = moment(pointTime).subtract(parseInt(interval)).format('YYYY-MM-DD HH:mm:ss') - newAddEndTime = pointTime - - if (c.tactics == 'continue') { - emailTitle += `持续时长推送服务` - emailSubTitle += `告警持续时长超${interval}分钟的告警源,详情如下:` - } else { - if (c.alarmType.includes('data_outages') || c.alarmType.includes('data_exception')) { - // 查了设备异常率 去安心云查当前项目下的设备数量 - let deviceCountRes = - strucThingId.length ? - await clickHouse.iot.query(` + if (searchStrucIds.length) { + searchStrucIds.unshift(-1) + } else { + // 没有结构物可查 + continue + } + let pepProjectName = + pepProjectName_.length ? + pepProjectName_.join('
') + : '' + + let emailTitle = `${pepProjectName_.length ? + pepProjectName_.join('、') + : ''}-${c.name}-` + let emailSubTitle = '' + + let dataAlarmOption = [] + let dataAlarmGroupOption = [] + let dataAlarmSubType = [] + let dataAlarms = [] + + let videoAlarmWhereOption = [] + let videoAlarms = [] + + let appAlarmWhereOption = { + confirmTime: null, + } + let appAlarms = [] + + let deviceCount = 0 + let alarmDeviceCount = 0 + let cameraCount = 0 + let alarmCameraCount = 0 + // 判断推送策略 + let nowTime = moment().startOf('minute') + let pointTime = + moment() + .subtract( + parseInt(interval), + // + 1440 * 365, + 'minute' + ) + .startOf('minute') + .format('YYYY-MM-DD HH:mm:ss') + + let newAddStartTime = pointTime + let newAddEndTime = nowTime.clone() + if (c.tactics == 'immediately') { + // !查所有未解决告警 所以时间范围大可不必 + // dataAlarmOption.push(`StartTime >= '${pointTime}'`); + // appAlarmWhereOption.createTime = { $gte: pointTime } + // videoAlarmWhereOption.push(`camera_status_alarm.create_time >= '${pointTime}'`) + emailTitle += `即时推送服务` + emailSubTitle += `截止${moment(pointTime).format('YYYY年MM月DD日 HH时mm分')}-${moment(nowTime).format('HH时mm分')}:` + } else if (c.tactics == 'continue' || c.tactics == 'abnormal_rate') { + // 新增的应该是上一个时间节点到上上个节点之间 + dataAlarmOption.push(`StartTime <= '${pointTime}'`); + appAlarmWhereOption.createTime = { $lte: pointTime } + videoAlarmWhereOption.push(`camera_status_alarm.create_time <= '${pointTime}'`) + // 新增的应该是上一个时间节点到上上个节点之间 + newAddStartTime = moment(pointTime).subtract(parseInt(interval)).format('YYYY-MM-DD HH:mm:ss') + newAddEndTime = pointTime + + if (c.tactics == 'continue') { + emailTitle += `持续时长推送服务` + emailSubTitle += `告警持续时长超${interval}分钟的告警源,详情如下:` + } else { + if (c.alarmType.includes('data_outages') || c.alarmType.includes('data_exception')) { + // 查了设备异常率 去安心云查当前项目下的设备数量 + let deviceCountRes = + strucThingId.length ? + await clickHouse.iot.query(` SELECT count(DeviceId) AS count FROM device WHERE ThingId IN (${strucThingId.map(t => `'${t}'`).join(',')}, '-1') `).toPromise() - : [] - deviceCount = deviceCountRes.length ? deviceCountRes[0].count : 0 - } - if (c.alarmType.includes('video_exception')) { - // 查了视频异常 去安心云查 接入的 萤石 设备数量 - cameraCount = searchStrucIds.length ? - (await clickHouse.anxinyun.query(` + : [] + deviceCount = deviceCountRes.length ? deviceCountRes[0].count : 0 + } + if (c.alarmType.includes('video_exception')) { + // 查了视频异常 去安心云查 接入的 萤石 设备数量 + cameraCount = searchStrucIds.length ? + (await clickHouse.anxinyun.query(` SELECT count(*) AS count FROM t_video_ipc WHERE structure IN (${searchStrucIds.join(',')}) `).toPromise())[0].count - : 0 - } - emailTitle += `异常率推送服务` - emailSubTitle += `持续产生时间超过${interval}分钟的异常设备数量${interval}个,异常率达到项目或结构物内设备总数量${parseInt(deviceCount) + parseInt(cameraCount)}个的 --%,详情如下` + : 0 } + emailTitle += `异常率推送服务` + emailSubTitle += `持续产生时间超过${interval}分钟的异常设备数量${interval}个,异常率达到项目或结构物内设备总数量${parseInt(deviceCount) + parseInt(cameraCount)}个的 --%,详情如下` } - emailTitle += '——POMS飞尚运维中台' - - // 判断告警数据范围 - if (c.alarmType.includes('data_outages')) { - dataAlarmGroupOption.push(1) - if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['data_outages']) - } - if (c.alarmType.includes('data_exception')) { - dataAlarmGroupOption.push(2) - if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['data_exception']) + } + emailTitle += '——POMS飞尚运维中台' + // 判断告警数据范围 + if (c.alarmType.includes('data_outages')) { + dataAlarmGroupOption.push(1) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['data_outages']) + } + if (c.alarmType.includes('data_exception')) { + dataAlarmGroupOption.push(2) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['data_exception']) + } + if (c.alarmType.includes('strategy_hit')) { + dataAlarmGroupOption.push(3) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['strategy_hit']) + } + if (c.alarmType.includes('video_exception')) { + let videoAlarmSubType = c.alarmSubType ? c.alarmSubType['video_exception'] : [] + if (videoAlarmSubType.length == 1) { + videoAlarmSubType.push(-1) } - if (c.alarmType.includes('strategy_hit')) { - dataAlarmGroupOption.push(3) - if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['strategy_hit']) - } - if (c.alarmType.includes('video_exception')) { - let videoAlarmSubType = c.alarmSubType ? c.alarmSubType['data_exception'] : [] - if (videoAlarmSubType.length == 1) videoAlarmSubType.push(-1) - videoAlarms = searchStrucIds.length && videoAlarmSubType.length ? await clickHouse.vcmp.query( - ` + videoAlarms = + searchStrucIds.length && ( + !c.alarmSubType || videoAlarmSubType.length > 0 + ) ? + await clickHouse.vcmp.query( + ` SELECT cameraAlarm.cameraId AS cameraId, cameraAlarm.cameraName AS cameraName, @@ -270,7 +300,7 @@ module.exports = function (app, opts) { AND camera.channel_no = camera_status_alarm.channel_no AND camera.delete = false AND camera.recycle_time is null - ${!c.alarmSubType ? `AND camera.kind_id in (${videoAlarmSubType.join(',')})` : ""} + ${c.alarmSubType ? `AND camera.kind_id in (${videoAlarmSubType.join(',')})` : ""} WHERE camera_status_alarm.confirm_time IS null ${videoAlarmWhereOption.length ? ` AND ${videoAlarmWhereOption.join(' AND ')}` : ''} @@ -294,107 +324,107 @@ module.exports = function (app, opts) { ON anxinStation.id = anxinIpcStation.station ORDER BY cameraAlarm.createTime DESC ` - ).toPromise() : [] - - let returnD = [] - let positionD = {} - // 每个设备一个告警 - for (let a of videoAlarms) { - if (positionD[a.cameraId]) { - let curD = returnD[positionD[a.cameraId].positionReturnD] - - if (a.strucId && !curD.struc.some(s => s.id == a.strucId)) { - curD.struc.push({ - id: a.strucId, - projectId: a.projectId, - name: a.strucName - }) - } - if (a.anxinStationId && !curD.station.some(s => s.id == a.anxinStationId)) { - curD.station.push({ - id: a.anxinStationId, - name: a.anxinStationName, - position: a.anxinIpcPosition - }) - } - } else { - let d = { - cameraId: a.cameraId, - cameraName: a.cameraName, - camerOnline: a.cameraOnline, - cameraSerialNo: a.cameraSerialNo, - cameraChannelNo: a.cameraChannelNo, - autoRestore: a.autoRestore, - createTime: a.createTime, - updateTime: a.updateTime, - platform: a.platform, - statusDescribe: a.statusDescribe, - alarmId: a.alarmId, - confirmContent: a.confirmContent, - confirmTime: a.confirmTime, - cameraKind: a.cameraKind, - struc: [], - station: [] - } - - if (a.strucId) { - d.struc.push({ - id: a.strucId, - projectId: a.projectId, - name: a.strucName - }) - } - if (a.anxinStationId) { - d.station.push({ - id: a.anxinStationId, - name: a.anxinStationName, - position: a.anxinIpcPosition - }) - } - returnD.push(d) - positionD[a.cameraId] = { - positionReturnD: returnD.length - 1 - } + ).toPromise() : [] + + let returnD = [] + let positionD = {} + // 每个设备一个告警 + for (let a of videoAlarms) { + if (positionD[a.cameraId]) { + let curD = returnD[positionD[a.cameraId].positionReturnD] + + if (a.strucId && !curD.struc.some(s => s.id == a.strucId)) { + curD.struc.push({ + id: a.strucId, + projectId: a.projectId, + name: a.strucName + }) + } + if (a.anxinStationId && !curD.station.some(s => s.id == a.anxinStationId)) { + curD.station.push({ + id: a.anxinStationId, + name: a.anxinStationName, + position: a.anxinIpcPosition + }) + } + } else { + let d = { + cameraId: a.cameraId, + cameraName: a.cameraName, + camerOnline: a.cameraOnline, + cameraSerialNo: a.cameraSerialNo, + cameraChannelNo: a.cameraChannelNo, + autoRestore: a.autoRestore, + createTime: a.createTime, + updateTime: a.updateTime, + platform: a.platform, + statusDescribe: a.statusDescribe, + alarmId: a.alarmId, + confirmContent: a.confirmContent, + confirmTime: a.confirmTime, + cameraKind: a.cameraKind, + struc: [], + station: [] + } + + if (a.strucId) { + d.struc.push({ + id: a.strucId, + projectId: a.projectId, + name: a.strucName + }) + } + if (a.anxinStationId) { + d.station.push({ + id: a.anxinStationId, + name: a.anxinStationName, + position: a.anxinIpcPosition + }) + } + returnD.push(d) + positionD[a.cameraId] = { + positionReturnD: returnD.length - 1 } } - let p = 1 - videoAlarms = returnD } - if (c.alarmType.includes('app_exception')) { - if (c.alarmSubType) { - appAlarmWhereOption.type = { $in: c.alarmSubType['app_exception'] || [] } - } - appAlarms = c.alarmSubType && c.alarmSubType['app_exception'].length ? await models.AppAlarm.findAll({ - where: appAlarmWhereOption, - order: [['createTime', 'DESC']], + let p = 1 + videoAlarms = returnD + } + if (c.alarmType.includes('app_exception')) { + if (c.alarmSubType) { + appAlarmWhereOption.type = { $in: c.alarmSubType['app_exception'] || [] } + } + appAlarms = c.alarmSubType && c.alarmSubType['app_exception'].length ? await models.AppAlarm.findAll({ + where: appAlarmWhereOption, + order: [['createTime', 'DESC']], + include: [{ + model: models.App, + required: true, include: [{ - model: models.App, + model: models.ProjectApp, + where: { + projectId: { $in: pomsProjectId } + }, required: true, - include: [{ - model: models.ProjectApp, - where: { - projectId: pomsProjectId - }, - required: true, - }] }] - }) : [] - } - if (c.alarmType.includes('device_exception')) { - dataAlarmGroupOption.push(4) - dataAlarmGroupOption.push(5) - if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['device_exception']) - } + }] + }) : [] + } + if (c.alarmType.includes('device_exception')) { + dataAlarmGroupOption.push(4) + dataAlarmGroupOption.push(5) + if (c.alarmSubType) dataAlarmSubType = dataAlarmSubType.concat(c.alarmSubType['device_exception']) + } - // 查数据告警 三警合一 - if (dataAlarmGroupOption.length && searchStrucIds.length) { - dataAlarmGroupOption.push(-1) - dataAlarmOption.push(`AlarmGroup IN (${dataAlarmGroupOption.join(',')})`) - if (c.alarmSubType && dataAlarmSubType.length) { - dataAlarmSubType.push(-1) - dataAlarmOption.push(`AlarmGroupUnit IN (${dataAlarmSubType.join(',')})`) - } - dataAlarms = (!c.alarmSubType || dataAlarmSubType.length) ? await clickHouse.dataAlarm.query(` + // 查数据告警 三警合一 + if (dataAlarmGroupOption.length && searchStrucIds.length) { + dataAlarmGroupOption.push(-1) + dataAlarmOption.push(`AlarmGroup IN (${dataAlarmGroupOption.join(',')})`) + if (c.alarmSubType && dataAlarmSubType.length) { + dataAlarmSubType.push(-1) + dataAlarmOption.push(`AlarmGroupUnit IN (${dataAlarmSubType.join(',')})`) + } + dataAlarms = (!c.alarmSubType || dataAlarmSubType.length) ? await clickHouse.dataAlarm.query(` SELECT * FROM alarms WHERE ${`State NOT IN (3, 4) AND `} @@ -402,235 +432,235 @@ module.exports = function (app, opts) { ${dataAlarmOption.length ? ' AND ' + dataAlarmOption.join(' AND ') : ''} ORDER BY StartTime DESC `).toPromise() : [] - console.log(dataAlarms); - } + console.log(dataAlarms); + } - let dataAlarmTitle = [{ - n: '项目', - k: '', - v: pepProjectName - }, { - n: '结构物', - k: '', - f: (d) => { - return (strucListRes.find(s => s.id == d.StructureId) || { name: '' }).name - } - }, { - n: '告警源名称', - k: 'SourceName' - }, { - n: '告警源类型', - k: '', - f: (d) => { - switch (d.SourceTypeId) { - case 0: - return 'DTU' - case 1: - return '传感器' - case 2: - return '测点' - default: - return '' - } - } - }, { - n: '告警信息', - k: 'AlarmContent' - }, { - n: '告警等级(当前)', - k: '', - f: (d) => { - switch (d.CurrentLevel) { - case 1: - return '一级' - case 2: - return '二级' - case 3: - return '三级' - default: - return '' - } - } - }, { - n: '持续时间', - k: '', - f: (d) => { - return d.StartTime ? - '超过' + moment().diff(moment(d.StartTime), 'minutes') + '分钟' : '' - } - },] - - let videoAlarmTitle = [{ - n: '项目', - k: '', - v: pepProjectName - }, { - n: '结构物', - k: '', - f: (d) => { - return d.struc.map(ds => ds.name).join('、') - } - }, { - n: '告警源名称', - k: 'cameraName' - }, { - n: '告警源类型', - k: 'cameraKind' - }, { - n: '序列号', - k: 'cameraSerialNo' - }, { - n: '通道号', - k: 'cameraChannelNo' - }, { - n: '测点', - k: '', - f: (d) => { - return d.station.map(ds => ds.name).join('、') - } - }, { - n: '位置', - k: '', - f: (d) => { - return d.station.map(ds => ds.position).join('、') - } - }, { - n: '告警信息', - k: 'statusDescribe' - }, { - n: '持续时间', - k: '', - f: (d) => { - return d.createTime ? - '超过' + moment().diff(moment(d.createTime), 'minutes') + '分钟' : '' - } - },] - - let appAlarmTitle = [{ - n: '项目', - k: '', - v: pepProjectName - }, { - n: '应用名称', - k: '', - f: (d) => { - return d.app ? d.app.name : '' - } - }, { - n: '异常类型', - k: '', - f: (d) => { - if (d.type == 'element') { - return '元素异常' - } else if (d.type == 'apiError') { - return '接口报错' - } else { + let dataAlarmTitle = [{ + n: '项目', + k: '', + v: pepProjectName + }, { + n: '结构物', + k: '', + f: (d) => { + return (strucListRes.find(s => s.id == d.StructureId) || { name: '' }).name + } + }, { + n: '告警源名称', + k: 'SourceName' + }, { + n: '告警源类型', + k: '', + f: (d) => { + switch (d.SourceTypeId) { + case 0: + return 'DTU' + case 1: + return '传感器' + case 2: + return '测点' + default: return '' - } } - }, { - n: '异常信息', - k: 'alarmContent' - }, { - n: 'URL地址', - k: 'cameraName', - f: (d) => { - return d.app && d.app.url ? `${d.app.url}` : '' + } + }, { + n: '告警信息', + k: 'AlarmContent' + }, { + n: '告警等级(当前)', + k: '', + f: (d) => { + switch (d.CurrentLevel) { + case 1: + return '一级' + case 2: + return '二级' + case 3: + return '三级' + default: + return '' } - }, { - n: '持续时间', - k: '', - f: (d) => { - return d.createTime ? - '超过' + moment().diff(moment(d.createTime), 'minutes') + '分钟' : '' + } + }, { + n: '持续时间', + k: '', + f: (d) => { + return d.StartTime ? + '超过' + moment().diff(moment(d.StartTime), 'minutes') + '分钟' : '' + } + },] + + let videoAlarmTitle = [{ + n: '项目', + k: '', + v: pepProjectName + }, { + n: '结构物', + k: '', + f: (d) => { + return d.struc.map(ds => ds.name).join('、') + } + }, { + n: '告警源名称', + k: 'cameraName' + }, { + n: '告警源类型', + k: 'cameraKind' + }, { + n: '序列号', + k: 'cameraSerialNo' + }, { + n: '通道号', + k: 'cameraChannelNo' + }, { + n: '测点', + k: '', + f: (d) => { + return d.station.map(ds => ds.name).join('、') + } + }, { + n: '位置', + k: '', + f: (d) => { + return d.station.map(ds => ds.position).join('、') + } + }, { + n: '告警信息', + k: 'statusDescribe' + }, { + n: '持续时间', + k: '', + f: (d) => { + return d.createTime ? + '超过' + moment().diff(moment(d.createTime), 'minutes') + '分钟' : '' + } + },] + + let appAlarmTitle = [{ + n: '项目', + k: '', + v: pepProjectName + }, { + n: '应用名称', + k: '', + f: (d) => { + return d.app ? d.app.name : '' + } + }, { + n: '异常类型', + k: '', + f: (d) => { + if (d.type == 'element') { + return '元素异常' + } else if (d.type == 'apiError') { + return '接口报错' + } else { + return '' } - },] + } + }, { + n: '异常信息', + k: 'alarmContent' + }, { + n: 'URL地址', + k: 'cameraName', + f: (d) => { + return d.app && d.app.url ? `${d.app.url}` : '' + } + }, { + n: '持续时间', + k: '', + f: (d) => { + return d.createTime ? + '超过' + moment().diff(moment(d.createTime), 'minutes') + '分钟' : '' + } + },] - let ifEmailSend = false - let tableTitlePostfix = ',详情如下:' + let ifEmailSend = false + let tableTitlePostfix = ',详情如下:' - function packageTableTitle (titleArr) { - let tableTitle = '' - for (let t of titleArr) { - tableTitle += `${t.n}` - } - tableTitle += '' - return tableTitle + function packageTableTitle (titleArr) { + let tableTitle = '' + for (let t of titleArr) { + tableTitle += `${t.n}` } - function packageTableData (data, titleArr) { - let tableData = '' - for (let t of titleArr) { - if (t.v) { - tableData += `${t.v}` - } else if (t.f) { - tableData += `${t.f(data)}` - } else if (t.k) { - tableData += `${data[t.k]}` - } else { - tableData += `` - } + tableTitle += '' + return tableTitle + } + function packageTableData (data, titleArr) { + let tableData = '' + for (let t of titleArr) { + if (t.v) { + tableData += `${t.v}` + } else if (t.f) { + tableData += `${t.f(data)}` + } else if (t.k) { + tableData += `${data[t.k]}` + } else { + tableData += `` } - tableData += '' - return tableData } + tableData += '' + return tableData + } - function packageAlarmData2Table (titlePrefix, alarmData, alarmTitleArr, keyOfStartTime = 'StartTime') { - if (!alarmData.length) { - return '' - } - ifEmailSend = true - let tableTitlePrefix = titlePrefix + '告警源' - let newAddCount = 0 - let alarmHtml = '' - let alarmContent = '' - let alarmHtmlTitle = packageTableTitle(alarmTitleArr) - - for (let a of alarmData) { - alarmContent += packageTableData(a, alarmTitleArr) - if (a[keyOfStartTime] && moment(a[keyOfStartTime]).isBetween(newAddStartTime, newAddEndTime)) { - newAddCount++ - } - } - tableTitlePrefix += - c.tactics == 'abnormal_rate' ? - `${alarmData.length}个` : - `新增${newAddCount}个,未解决累计${alarmData.length}个` + tableTitlePostfix - alarmHtml += `' - alarmHtml += alarmHtmlTitle - alarmHtml += alarmContent - alarmHtml += '
` + tableTitlePrefix + '

' - - return alarmHtml + function packageAlarmData2Table (titlePrefix, alarmData, alarmTitleArr, keyOfStartTime = 'StartTime') { + if (!alarmData.length) { + return '' } - - let dataAlarmG1 = []; - let dataAlarmG2 = []; - let dataAlarmG3 = []; - let dataAlarmG45 = []; - let deviceStatistic = new Set() - for (let d of dataAlarms) { - if (d.AlarmGroup == 1) { - dataAlarmG1.push(d) - } else if (d.AlarmGroup == 2) { - dataAlarmG2.push(d) - } else if (d.AlarmGroup == 3) { - dataAlarmG3.push(d) - } else if (d.AlarmGroup == 4 || d.AlarmGroup == 5) { - dataAlarmG45.push(d) + ifEmailSend = true + let tableTitlePrefix = titlePrefix + '告警源' + let newAddCount = 0 + let alarmHtml = '' + let alarmContent = '' + let alarmHtmlTitle = packageTableTitle(alarmTitleArr) + + for (let a of alarmData) { + alarmContent += packageTableData(a, alarmTitleArr) + if (a[keyOfStartTime] && moment(a[keyOfStartTime]).isBetween(newAddStartTime, newAddEndTime)) { + newAddCount++ } - deviceStatistic.add(d.SourceId) } - if (c.tactics == 'abnormal_rate') { - let rate = ((deviceStatistic.size + videoAlarms.length) / (parseInt(deviceCount) + parseInt(cameraCount))); + tableTitlePrefix += + c.tactics == 'abnormal_rate' ? + `${alarmData.length}个` : + `新增${newAddCount}个,未解决累计${alarmData.length}个` + tableTitlePostfix + alarmHtml += `' + alarmHtml += alarmHtmlTitle + alarmHtml += alarmContent + alarmHtml += '
` + tableTitlePrefix + '

' + + return alarmHtml + } - if (rate < parseFloat(deviceProportion)) { - continue - } + let dataAlarmG1 = []; + let dataAlarmG2 = []; + let dataAlarmG3 = []; + let dataAlarmG45 = []; + let deviceStatistic = new Set() + for (let d of dataAlarms) { + if (d.AlarmGroup == 1) { + dataAlarmG1.push(d) + } else if (d.AlarmGroup == 2) { + dataAlarmG2.push(d) + } else if (d.AlarmGroup == 3) { + dataAlarmG3.push(d) + } else if (d.AlarmGroup == 4 || d.AlarmGroup == 5) { + dataAlarmG45.push(d) + } + deviceStatistic.add(d.SourceId) + } + if (c.tactics == 'abnormal_rate') { + let rate = ((deviceStatistic.size + videoAlarms.length) / (parseInt(deviceCount) + parseInt(cameraCount))); - emailSubTitle = emailSubTitle.replace('--%', rate.toFixed(1) + '%') + if (rate < parseFloat(deviceProportion)) { + continue } - let html = ` + + emailSubTitle = emailSubTitle.replace('--%', rate.toFixed(1) + '%') + } + let html = ` @@ -649,99 +679,99 @@ module.exports = function (app, opts) {
${emailSubTitle}
` - if (c.alarmType.includes('data_outages')) { - html += packageAlarmData2Table( - '数据中断', - dataAlarmG1, - dataAlarmTitle, - ) - } - if (c.alarmType.includes('data_exception')) { - html += packageAlarmData2Table( - '数据异常', - dataAlarmG2, - dataAlarmTitle, - ) - } - if (c.alarmType.includes('strategy_hit')) { - html += packageAlarmData2Table( - '策略命中', - dataAlarmG3, - dataAlarmTitle, - ) - } - if (c.alarmType.includes('video_exception')) { - html += packageAlarmData2Table( - '视频异常', - videoAlarms, - videoAlarmTitle, - 'createTime', - ) - } - if (c.alarmType.includes('app_exception')) { - html += packageAlarmData2Table( - '应用异常', - appAlarms, - appAlarmTitle, - 'createTime', - ) - } - if (c.alarmType.includes('device_exception')) { - html += packageAlarmData2Table( - '设备异常', - dataAlarmG45, - dataAlarmTitle, - ) - } + if (c.alarmType.includes('data_outages')) { + html += packageAlarmData2Table( + '数据中断', + dataAlarmG1, + dataAlarmTitle, + ) + } + if (c.alarmType.includes('data_exception')) { + html += packageAlarmData2Table( + '数据异常', + dataAlarmG2, + dataAlarmTitle, + ) + } + if (c.alarmType.includes('strategy_hit')) { + html += packageAlarmData2Table( + '策略命中', + dataAlarmG3, + dataAlarmTitle, + ) + } + if (c.alarmType.includes('video_exception')) { + html += packageAlarmData2Table( + '视频异常', + videoAlarms, + videoAlarmTitle, + 'createTime', + ) + } + if (c.alarmType.includes('app_exception')) { + html += packageAlarmData2Table( + '应用异常', + appAlarms, + appAlarmTitle, + 'createTime', + ) + } + if (c.alarmType.includes('device_exception')) { + html += packageAlarmData2Table( + '设备异常', + dataAlarmG45, + dataAlarmTitle, + ) + } - if (ifEmailSend) { - // 查接收人的信息 - const receiverRes = - c.receiverPepUserId.length ? - await clickHouse.pepEmis.query(` + if (ifEmailSend) { + // 查接收人的信息 + const receiverRes = + c.receiverPepUserId.length ? + await clickHouse.pepEmis.query(` SELECT id, name, email FROM user WHERE id IN (${c.receiverPepUserId.join(',')},-1) `).toPromise() - : [] - let receiverId = [] - const emails = receiverRes.reduce((arr, r) => { - if (r.email) { - arr.push(r.email) - receiverId.push({ id: r.id, name: r.name }) - } - return arr - }, []) - if (emails.length) { - await pushByEmail({ - email: emails, - title: emailTitle, - text: '', - html: html - }) - - //存日志 存动态 socket到前端 - let dataToSave = { - time: moment().format(), - pushConfigId: c.id, - cfgName: c.name,//策略名称 - tactics: c.tactics, - tacticsParams: c.tacticsParams, - projectCorrelationId: pomsProjectId, - toPepUserIds: receiverId.map(r => r.id) - } - let r = await models.EmailSendLog.create(dataToSave, { returning: true }) - - let dynamic = { - time: r.dataValues.time, - emailSendId: r.dataValues.id, - projectCorrelationId: r.dataValues.projectCorrelationId, - type: 2//通知 - } - await models.LatestDynamicList.create(dynamic); - + : [] + let receiverId = [] + let emails = receiverRes.reduce((arr, r) => { + if (r.email) { + arr.push(r.email) + receiverId.push({ id: r.id, name: r.name }) + } + return arr + }, []) + // !开发测试用的数据 + // emails = ['1650192445@qq.com'] + if (emails.length) { + await pushByEmail({ + email: emails, + title: emailTitle, + text: '', + html: html + }) + + //存日志 存动态 socket到前端 + let dataToSave = { + time: moment().format(), + pushConfigId: c.id, + cfgName: c.name,//策略名称 + tactics: c.tactics, + tacticsParams: c.tacticsParams, + projectCorrelationId: pomsProjectId, + toPepUserIds: receiverId.map(r => r.id) + } + let r = await models.EmailSendLog.create(dataToSave, { returning: true }) - //消息推送到前端 - await sendNoticeToWeb(receiverId, dataToSave); + let dynamic = { + time: r.dataValues.time, + emailSendId: r.dataValues.id, + // projectCorrelationId: r.dataValues.projectCorrelationId, + type: 2//通知 } + await models.LatestDynamicList.create(dynamic); + + //消息推送到前端 + await sendNoticeToWeb(receiverId, dataToSave); } } } diff --git a/script/0.11/schema/1.alter_email_send_log.sql b/script/0.11/schema/1.alter_email_send_log.sql new file mode 100644 index 0000000..b6ea2b4 --- /dev/null +++ b/script/0.11/schema/1.alter_email_send_log.sql @@ -0,0 +1,6 @@ +ALTER TABLE email_send_log ALTER COLUMN project_correlation_id TYPE INTEGER [] + USING CASE + WHEN project_correlation_id is NULL + then NULL + ELSE array [project_correlation_id] + END ::INTEGER []; \ No newline at end of file diff --git a/web/client/index.html b/web/client/index.html index 302a7e4..3ee9392 100644 --- a/web/client/index.html +++ b/web/client/index.html @@ -2,26 +2,26 @@ - - + + - + - - + + - - + + - -
+ +
- - + + - - + - + - + \ No newline at end of file diff --git a/web/client/src/sections/control/containers/control.jsx b/web/client/src/sections/control/containers/control.jsx index c4857d2..acba920 100644 --- a/web/client/src/sections/control/containers/control.jsx +++ b/web/client/src/sections/control/containers/control.jsx @@ -8,7 +8,6 @@ import repairFQA from '../../means/containers/repairFQA'; import { Setup, OutHidden } from "$components"; import ReactECharts from 'echarts-for-react'; import moment from "moment"; -import { log } from 'ezuikit-js'; let newScrollbar; let overviewScrollbar; @@ -43,7 +42,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const [videoBI, setVideoBI] = useState([]); //查询BI分析数据-视频 const [appBI, setAppBI] = useState([]); //查询BI分析数据-应用 const [efficiencyBI, setEfficiencyBI] = useState({}); //查询BI分析数据-问题处置 - const [query, setQuery] = useState({ limit: 10, page: 0, projectCorrelationId: '', types: '1' }); //最新动态 + const [query, setQuery] = useState({ limit: 23, page: 0, projectCorrelationId: '', types: '1' }); //最新动态 const [querydata1, setQueryData1] = useState([]); //最新动态数据 const [long, setLong] = useState(''); //最新动态设置 const [pomsList, setPomsList] = useState([]); //项目 @@ -184,7 +183,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject newest.sort((a, b) => (moment(a.time).isBefore(b.time) ? 1 : -1)) querydata.current = [...newest, ...querydata.current] setQueryData1([...querydata.current]) - + } }, [socketData]) useEffect(() => { @@ -398,6 +397,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject })) } if (exhibition?.current?.dynamic?.find(v => v.key == 'notice')) { + // EM 推送 res.payload.data?.notice?.map(v => data.push({ seed: 'notice', time: v.time, @@ -444,14 +444,26 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const line = document.getElementById("line") const news = document.getElementById("news") if (line && news) { - news.onscroll = () => { + news.onscroll = (e) => { + e.stopPropagation(); if ((line.clientHeight - 578) < news.scrollTop + 10) { setQuery({ ...query, page: query.page + 1 }) if (exhibition?.current?.dynamic?.length > 0) { dispatch(control.getLatestDynamic({ ...query, projectCorrelationId: pepProjectId, page: query.page + 1 })).then(res => { - news.scrollTop = news.scrollTop - 640 + // news.scrollTop = news.scrollTop - 640 let data = querydata.current if (res.success) { + let returnJudge = true + for (let k in res.payload.data) { + if (res.payload.data[k].length) { + returnJudge = false + break + } + } + if (returnJudge) { + return + } + if (exhibition?.current?.dynamic?.find(v => v.key == 'discovery')) { res.payload.data?.appear?.map(v => data.push({ seed: 'discovery', @@ -503,9 +515,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject = document.getElementById("news"); if (domProject) { - // newScrollbar = new PerfectScrollbar("#news", { - // suppressScrollX: true, - // }); if (domProject && newScrollbar) { newScrollbar.update(); } @@ -513,9 +522,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const pomsList = document.getElementById("pomsList"); if (pomsList) { - // pomsListScrollbar = new PerfectScrollbar("#pomsList", { - // suppressScrollX: true, - // }); if (pomsList && pomsListScrollbar) { pomsListScrollbar.update(); } @@ -523,9 +529,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject1 = document.getElementById("overviewCalc"); if (domProject1) { - // overviewScrollbar = new PerfectScrollbar("#overviewCalc", { - // suppressScrollY: true, - // }); if (domProject1 && overviewScrollbar) { overviewScrollbar.update(); } @@ -533,9 +536,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject2 = document.getElementById("member"); if (domProject2) { - // memberScrollbar = new PerfectScrollbar("#member", { - // suppressScrollX: true, - // }); if (domProject2 && memberScrollbar) { memberScrollbar.update(); } @@ -543,9 +543,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject3 = document.getElementById("equipment"); if (domProject3) { - // equipmentScrollbar = new PerfectScrollbar("#equipment", { - // suppressScrollX: true, - // }); if (domProject3 && equipmentScrollbar) { equipmentScrollbar.update(); } @@ -553,9 +550,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject4 = document.getElementById("web"); if (domProject4) { - // webScrollbar = new PerfectScrollbar("#web", { - // suppressScrollX: true, - // }) if (domProject4 && webScrollbar) { webScrollbar.update(); } @@ -563,9 +557,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject5 = document.getElementById("problems"); if (domProject5) { - // problemsScrollbar = new PerfectScrollbar("#problems", { - // suppressScrollX: true, - // }); if (domProject5 && problemsScrollbar) { problemsScrollbar.update(); } @@ -573,17 +564,11 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject const domProject6 = document.getElementById("alarm"); if (domProject6) { - // alarmScrollbar = new PerfectScrollbar("#alarm", { - // suppressScrollY: true, - // }); if (domProject6 && alarmScrollbar) { alarmScrollbar.update(); } } - - // ACTION 示例 - // dispatch(actions.example.getMembers(user.orgId)) }) const consoleToollink = () => { @@ -625,8 +610,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject - - let Select = { overall: ['workbench', 'statistical', 'analyse', 'dynamic', 'tool'], workbench: ['project', 'data', 'app', 'device'], @@ -672,8 +655,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject { name: 'BI分析模块', sort: 3, key: 'analyse', }, { name: '最新动态', sort: 4, key: 'dynamic', }, { name: '我常用的工具', sort: 5, key: 'tool', }, - - ] useEffect(() => { @@ -1245,8 +1226,8 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject }} /> -
-
+
+
{querydata.current?.map((v, index) => { let title = '' @@ -1256,8 +1237,13 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject title = v.userName ? (v.userName + '确认并关闭' + v.project + '【' + v.sources + '】' + v.type + '的问题') : v.project + '【' + v.sources + '】' + v.type + '已恢复' } else { - title = '【信鸽-' + v.alarmPushConfig + '】已邮件通知' + - v.userName?.map((u, i) => (i > 0 ? ',' + u : u)) + '【' + v.project + '】【' + + title = + '【信鸽-' + v.alarmPushConfig + '】已邮件通知' + + + v.userName?.map((u, i) => (i > 0 ? ',' + u : u)) + + '【' + v.project + + '】【' + + (v.tactics == 'immediately' ? '发现在' + v.interval + '分钟内,有告警源新增' : (v.tactics == 'continue' ? '告警源持续产生时间超过' + v.interval + '分钟' : '异常设备数量达到项目或结构物内设备总数量的' +