运维服务中台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
9.9 KiB

'use strict';
const moment = require('moment');
const { alarmList } = require('../alarm/video');
const { inspectionList } = require('../alarm/app');
//工作台
async function getWorkbench(ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { alarmId, limit, page } = ctx.query
ctx.status = 200;
ctx.body = []
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
//项目概览
async function getProjectsInfo(ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse, utils: { judgeSuper, anxinStrucIdRange } } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
const { alarmId, limit, page, projectCorrelationId, pepProjectId, keywordTarget, keyword } = ctx.query;
const { userInfo } = ctx.fs.api;
// let where = {}
// if (!userInfo.role.includes('SuperAdmin') && !userInfo.role.includes('admin')) {
// where.projectCorrelationId = { $in: userInfo.correlationProject }
// }
// if (projectCorrelationId) {//查指定项目,控制台全局切换
// where.projectCorrelationId = projectCorrelationId
// }
let anxinStruc = await anxinStrucIdRange({
ctx, pepProjectId, keywordTarget, keyword
})
const anxinStrucIds = anxinStruc.map(a => a.strucId);
//先查全部的摄像头
const videoList = anxinStrucIds.length ? await clickHouse.vcmp.query(
`select camera.id,
camera.name,
camera.serial_no from camera where camera.delete=false and camera.recycle_time is null
LEFT JOIN ${anxinyun}.t_video_ipc AS anxinIpc
ON toString(anxinIpc.channel_no) = cameraAlarm.cameraChannelNo
AND anxinIpc.serial_no = cameraAlarm.cameraSerialNo
LEFT JOIN ${anxinyun}.t_structure AS anxinStruc
ON anxinStruc.id = anxinIpc.structure
AND anxinStruc.id IN (${anxinStrucIds.join(',')})
LEFT JOIN ${anxinyun}.t_video_ipc_station AS anxinIpcStation
ON anxinIpcStation.ipc = anxinIpc.id
LEFT JOIN ${anxinyun}.t_sensor AS anxinStation
ON anxinStation.id = anxinIpcStation.station`
).toPromise() : []
ctx.status = 200;
ctx.body = []
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
//BI分析-数据
async function getDataAlarmsAggDay(ctx) {
try {
const { utils: { anxinStrucIdRange } } = ctx.app.fs
const { pepProjectId } = ctx.query
let dataAbnormal = [], dataInterrupt = [], policyHit = [], deviceAbnormal = [];
let anxinStruc = await anxinStrucIdRange({
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');//最近一年
whereOption.push(`alarms.StartTime >= '${start}'`)
let alarmQueryOptionStr = `
FROM alarms
${whereOption.length ? 'WHERE ' + whereOption.join(' AND ') : ''}
`
dataAbnormal = await queryAlarm(ctx, alarmQueryOptionStr, [2]);//数据异常
dataInterrupt = await queryAlarm(ctx, alarmQueryOptionStr, [1]);//数据中断
policyHit = await queryAlarm(ctx, alarmQueryOptionStr, [3]);//策略命中
deviceAbnormal = await queryAlarm(ctx, alarmQueryOptionStr, [4, 5]);//设备异常
}
ctx.status = 200;
ctx.body = { dataAbnormal, dataInterrupt, policyHit, deviceAbnormal };
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function queryAlarm(ctx, alarmQueryOptionStr, type) {
const { clickHouse } = ctx.app.fs
try {
const alarmRes = await clickHouse.dataAlarm.query(`
select days, sum(count) total, sum(done) done from (
SELECT formatDateTime(StartTime,'%F') days, count(AlarmId) count, 0 done from
(SELECT
alarms.AlarmId AS AlarmId,
alarms.State AS State,
StartTime,
AlarmGroup
${alarmQueryOptionStr} and alarms.AlarmGroup in [${type}]) group by days
union all (SELECT formatDateTime(StartTime,'%F') days, 0 count, count(AlarmId) done from
(SELECT
alarms.AlarmId AS AlarmId,
alarms.State AS State,
StartTime,
AlarmGroup
${alarmQueryOptionStr} and alarms.AlarmGroup in [${type}] and alarms.State > 3) group by days)
) group by days ORDER BY days
`).toPromise();
return alarmRes;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
//BI分析-应用异常
async function getAppAlarmsAggDay(ctx) {
try {
let appAlarms = await inspectionList(ctx, 'day');
let aggDayMap = [];
ctx.status = 200;
ctx.body = aggDayMap;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
//BI分析-视频异常
async function getVideoAlarmsAggDay(ctx) {
try {
let videoAlarms = await alarmList(ctx, 'day');
let aggDayMap = [];
for (let a of videoAlarms) {
let exist = aggDayMap.find(ad => ad.day == moment(a.createTime).format('YYYY-MM-DD'));
if (exist) {
exist.total++;//总数
if (a.confirmTime || a.autoRestore) {
exist.done++;//已恢复
}
} else {
aggDayMap.push({ day: moment(a.createTime).format('YYYY-MM-DD'), total: 1, done: a.confirmTime || a.autoRestore ? 1 : 0 });
}
}
ctx.status = 200;
ctx.body = aggDayMap;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
//最新动态
async function getLatestDynamic(ctx) {
try {
const { models } = ctx.fs.dc;
const { limit, page, projectCorrelationId, types } = ctx.query;
const { userInfo } = ctx.fs.api;
const { clickHouse } = ctx.app.fs;
let where = { type: { $in: types.split(',') } }//传类型选择
if (!userInfo.role.includes('SuperAdmin') && !userInfo.role.includes('admin')) {
where.projectCorrelationId = { $in: userInfo.correlationProject }
}
if (projectCorrelationId) {//查指定项目,控制台全局切换
where.projectCorrelationId = projectCorrelationId
}
let news = await models.LatestDynamicList.findAll({//最新动态
include: [{
model: models.ProjectCorrelation,
where: { del: false },
attributes: ['id', 'name', 'pepProjectId'],
}, {
model: models.AlarmAppearRecord
}, {
model: models.EmailSendLog
}, {
model: models.AlarmConfirmLog
}],
where: where,
offset: Number(page) * Number(limit),
limit: Number(limit),
order: [['time', 'desc']],
});
//查项目名称 查用户名
let pepPojectIds = new Set(), notedUserIds = new Set();
for (let p of news) {
pepPojectIds.add(p.projectCorrelation.pepProjectId);
if (p.emailSendLog) {
notedUserIds.add(p.emailSendLog.toPepUserId);//通知 接收人
}
if (p.alarmConfirmLog && p.alarmConfirmLog.pepUserId) {
notedUserIds.add(p.alarmConfirmLog.pepUserId);//确认 操作者
}
}
let pepProjects = pepPojectIds.size ? await clickHouse.projectManage.query(`
SELECT id, project_name FROM t_pim_project WHERE id IN (${[...pepPojectIds]})
`).toPromise() : [];
let userPepRes = notedUserIds.size ? await clickHouse.pepEmis.query(
`SELECT DISTINCT user.id AS id, "user"."name" AS name FROM user WHERE user.id IN (${[...notedUserIds].join(',')})
`).toPromise() : []
let appear = [], notice = [], confirm = [];
news.map(d => {
let projectName = d.projectCorrelation.name || pepProjects.find(pp => pp.id == d.projectCorrelation.pepProjectId).project_name;
if (d.alarmAppearId) {
appear.push({
projectName,
...d.alarmAppearRecord
});
}
if (d.emailSendId) {
notice.push({
userName: userPepRes.find(u => u.id == d.emailSendLog.toPepUserId).name,
projectName,
...d.emailSendLog
});
}
if (d.alarmConfirmId) {
confirm.push({
userName: d.alarmConfirmLog.pepUserId ? userPepRes.find(u => u.id == d.alarmConfirmLog.pepUserId).name : '自动恢复',
projectName,
...d.alarmConfirmLog.dataValues
});
}
})
ctx.status = 200;
ctx.body = {
appear,//发现
notice,//通知
confirm//确认
};
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
getWorkbench,
getProjectsInfo,
getDataAlarmsAggDay,
getAppAlarmsAggDay,
getVideoAlarmsAggDay,
getLatestDynamic
};