'use strict'; const moment = require('moment'); async function personnelApp (ctx) { try { const models = ctx.fs.dc.models; const { clickHouse } = ctx.app.fs const sequelize = ctx.fs.dc.orm; const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api const { pepId } = ctx.query const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime'] let findOption = { attributes: { exclude: excludeField, // include: [[sequelize.fn('array_length', sequelize.col('role')), 'roleCount']] }, where: { deleted: false, $or: [{ $not: { role: { $contained: ['SuperAdmin', 'admin'] } } }, sequelize.where(sequelize.fn('cardinality', sequelize.col('role')), 0)], // $not: { // role: { $contained: ['SuperAdmin', 'admin'] } // } }, order: [['updateTime', 'DESC']] } const userRes = await models.User.findAndCountAll(findOption) const adminRes = await models.User.findAll({ where: { role: { $contains: ['admin'] } }, attributes: { exclude: excludeField, }, order: [['updateTime', 'DESC']] }) let userIds = new Set() let pomsProjectIds = new Set() for (let u of userRes.rows.concat(adminRes)) { userIds.add(u.pepUserId) for (let pid of u.correlationProject) { pomsProjectIds.add(pid) } } // 查用户所属的项企pep的部门、人员信息 let userPepRes = userIds.size ? await clickHouse.pepEmis.query(` SELECT DISTINCT user.id AS id, "user"."name" AS name, department.name AS depName, department.id AS depId FROM department_user LEFT JOIN user ON department_user.user=user.id LEFT JOIN department ON department.id=department_user.department WHERE user.id IN (${[...userIds].join(',')}, -1) AND department.delete='0'` ).toPromise() : [] // 查用户绑定的当前系统的项目 id let pomsProjectRes = await models.ProjectCorrelation.findAll({ where: { id: { $in: [...pomsProjectIds] }, // del: false } }) // 获取响应的绑定的 项企项目的 id let pepPojectIds = new Set() for (let p of pomsProjectRes) { if (p.pepProjectId && !isNaN(p.pepProjectId)) { pepPojectIds.add(p.pepProjectId) } } // 查对应的项企项目信息 let pepProjectRes = pepPojectIds.size ? await clickHouse.projectManage.query(` SELECT id, project_name, isdelete FROM t_pim_project WHERE id IN (${[...pepPojectIds].join(',')}, -1) `).toPromise() : [] // 遍历用户并将查到的信息拼合 for (let u of userRes.rows.concat(adminRes)) { // 用户信息 const corUsers = userPepRes.filter(up => up.id == u.pepUserId) u.dataValues.name = corUsers.length ? corUsers[0].name : '' u.dataValues.departments = corUsers.length ? corUsers.map(cu => { return { name: cu.depName, id: cu.depId } }) : [] // pep项目信息 u.dataValues.correlationProject = u.dataValues.correlationProject.map(cpid => { let returnData = { id: cpid, } const corPomsProject = pomsProjectRes.find(ppr => ppr.id == cpid) if (corPomsProject) { returnData.name = corPomsProject.name returnData.del = corPomsProject.del if (corPomsProject.pepProjectId) { returnData.pepProjectId = corPomsProject.pepProjectId const corPepProject = pepProjectRes.find(ppr => ppr.id == corPomsProject.pepProjectId) if (corPepProject) { returnData.pepProjectName = corPepProject.project_name returnData.pepIsdelete = corPepProject.isdelete } } } return returnData }) } let findOptions = { where: { del: false }, order: [['updateTime', 'desc']], attributes: ['id', 'pepProjectId', 'name', 'anxinProjectId'], distinct: true, include: { model: models.App, } } if (!userInfo.role.includes('SuperAdmin') && !userInfo.role.includes('admin')) { findOptions.where.id = { $in: userInfo.correlationProject } } if (pepId) { findOptions.where.id = pepId } const proRes = await models.ProjectCorrelation.findAndCountAll(findOptions) let pepProjectIds = new Set() let anxinProjectIds = new Set() for (let p of proRes.rows) { if (p.pepProjectId) { pepProjectIds.add(p.pepProjectId) } for (let ap of p.anxinProjectId) { if (ap) { anxinProjectIds.add(ap) } } } const pepProjectRess = pepProjectIds.size ? await clickHouse.projectManage.query( ` SELECT t_pim_project.id AS id, t_pim_project.project_name AS project_name, t_pim_project.isdelete AS isdelete, t_pim_project_construction.construction_status_id AS construction_status_id, t_pim_project_state.construction_status AS construction_status FROM t_pim_project LEFT JOIN t_pim_project_construction ON t_pim_project.id = t_pim_project_construction.project_id LEFT JOIN t_pim_project_state ON t_pim_project_construction.construction_status_id = t_pim_project_state.id WHERE id IN (${[...pepProjectIds].join(',')}, -1) ` ).toPromise() : [] for (let p of proRes.rows) { const corPro = pepProjectRess.find(pp => pp.id == p.pepProjectId) || {} p.dataValues.pepProjectName = corPro.project_name p.dataValues.pepProjectIsDelete = corPro.isdelete delete p.dataValues.anxinProjectId } let webApp = [] let appproRes = proRes.rows.filter(v => v.dataValues.pepProjectIsDelete != 1).map(r => { if (r.dataValues.apps.length > 0) { r.dataValues.apps.map(vv => { if (!webApp.map(n => n.name).includes(vv.dataValues.name)) { webApp.push({ name: vv.dataValues.name, url: vv.dataValues.url }) } }) } }) let personnel = userRes.rows.filter(r => r.correlationProject.length > 0) if (pepId) { personnel = personnel.filter(r => r.dataValues.correlationProject.map(v => v.id).includes(Number(pepId))) } ctx.status = 200 ctx.body = { personnel: personnel.map(v => ({ name: v.dataValues.name, department: v.dataValues.departments.map(r => r.name) })), webApp: webApp } } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { } } } async function problem (ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs const { utils: { pomsProjectRange, anxinStrucIdRange } } = ctx.app.fs const { database: anxinyun } = clickHouse.anxinyun.opts.config const { pepProjectId, limit = 50, page = 0 } = ctx.query let anxinStruc = await anxinStrucIdRange({ ctx, pepProjectId }) let pomsProject = await pomsProjectRange({ ctx, pepProjectId, }) const pomsProjectIds = pomsProject.map(p => p.id) let whereOption = [] if (anxinStruc.length) { const anxinStrucIds = anxinStruc.map(a => a.strucId) whereOption.push(`alarms.StructureId IN (${anxinStrucIds.join(",")}, -1)`) const alarmRes = await clickHouse.dataAlarm.query(` SELECT AlarmId,State,AlarmGroup,AlarmGroupUnit,SourceName,StartTime,${anxinyun}.t_alarm_group_unit.name AS typeName FROM alarms LEFT JOIN ${anxinyun}.t_alarm_group_unit ON ${anxinyun}.t_alarm_group_unit.id = alarms.AlarmGroupUnit ${whereOption.length ? 'WHERE ' + whereOption.join(' AND ') + ' AND ' + 'alarms.State < 3' : ''} ${limit ? 'LIMIT ' + limit : ''} ${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} `).toPromise(); alarmRes.forEach(ar => { switch (ar.AlarmGroup) { case 1: ar.groupName = '数据中断' ar.url = '/problem/dataAlarm/dataLnterrupt' break; case 2: ar.groupName = '数据异常' ar.url = '/problem/dataAlarm/dataAbnormal' break; case 3: ar.groupName = '策略命中' ar.url = '/problem/dataAlarm/strategyHit' break; default: ar.groupName = '设备异常' ar.url = '/problem/deviceAlarm/deviceAbnormal' break; } }) const video = anxinStrucIds.length ? await clickHouse.vcmp.query( ` SELECT cameraAlarm.cameraId AS cameraId, cameraAlarm.cameraName AS cameraName, cameraAlarm.alarmId AS alarmId, cameraAlarm.createTime AS createTime, cameraAlarm.confirmTime AS confirmTime FROM ( SELECT camera.id AS cameraId, camera.name AS cameraName, camera_status_alarm.id AS alarmId, camera_status_alarm.create_time AS createTime, camera_status_alarm.platform AS platform, camera_status_alarm.status_id AS statusId, camera_status_alarm.serial_no AS cameraSerialNo, camera_status_alarm.channel_no AS cameraChannelNo, camera_status_alarm.confirm_time AS confirmTime FROM camera_status_alarm INNER JOIN camera ON camera.serial_no = camera_status_alarm.serial_no AND camera.channel_no = camera_status_alarm.channel_no WHERE camera.delete = '0' AND camera.recycle_time is null AND alarmId IN ( SELECT camera_status_alarm.id AS alarmId FROM camera_status_alarm RIGHT JOIN ${anxinyun}.t_video_ipc ON toString(${anxinyun}.t_video_ipc.channel_no) = camera_status_alarm.channel_no AND ${anxinyun}.t_video_ipc.serial_no = camera_status_alarm.serial_no ${`WHERE ${anxinyun}.t_video_ipc.structure IN (${anxinStrucIds.join(',')}, -1)`} ) ${limit ? 'LIMIT ' + limit : ''} ${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} ) AS cameraAlarm LEFT JOIN camera_status ON cameraAlarm.platform = camera_status.platform AND cameraAlarm.statusId = camera_status.id LEFT JOIN camera_status_resolve ON camera_status_resolve.status_id = camera_status.id 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_video_ipc_station AS anxinIpcStation ON anxinIpcStation.ipc = anxinIpc.id WHERE cameraAlarm.confirmTime is null ` ).toPromise() : [] let returnD = [] let positionD = {} // 每个设备一个告警 for (let a of video) { if (!positionD[a.cameraId]) { let d = { cameraId: a.cameraId, SourceName: a.cameraName, StartTime: a.createTime, alarmId: a.alarmId, } returnD.push(d) positionD[a.cameraId] = { positionReturnD: returnD.length - 1 } } } returnD.forEach(v => { v.groupName = '视频异常' v.url = '/problem/dataAlarm/videoAbnormal' }) let findOption = { where: { '$app->projectCorrelations.id$': { $in: pomsProjectIds }, confirmTime: null }, attributes: ['createTime', 'type'], include: [{ model: models.App, where: { }, attributes: ['id', 'name'], include: [{ model: models.ProjectCorrelation, where: { }, attributes: ['id'], }] }] } const listRes = await models.AppAlarm.findAndCountAll(findOption) let app = listRes.rows.map(v => ({ StartTime: v.createTime, SourceName: v.app.name, type: v.type })) let typeData = { element: '元素异常', apiError: "接口报错", timeout: '加载超时' } app.forEach(v => { v.groupName = '应用异常' v.url = '/problem/useAlarm/useAbnormal', v.typeName = typeData[v.type] }) let sum = [...alarmRes, ...returnD, ...app] sum.sort((a, b) => { if (moment(a.StartTime).isBefore(b.StartTime)) { return 1 } else { return -1 } }) ctx.status = 200; ctx.body = sum } else { ctx.body = [] } ctx.status = 200; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } module.exports = { personnelApp, problem }