'use strict'; const moment = require("moment"); async function findPatrolRecord(ctx, next) { let rslt = []; let error = { name: 'FindError', message: '获取巡检记录失败' }; try { const models = ctx.fs.dc.models; const { startTime, endTime, alarm, patrolPlanId, pointId } = ctx.params; // patrolPlanId传all查所有 let generalInclude = [{ model: models.PatrolPlan, attributes: ['name'] }, { model: models.PatrolRecordIssueHandle } ] if (patrolPlanId == 'all') { /* 如果有startTime && endTime,查询所有符合条件的数据 */ if (startTime !== 'null' && endTime !== 'null') { if (pointId !== 'null') { if (alarm == 'null') { rslt = await models.PatrolRecord.findAll({ where: { inspectionTime: { $between: [startTime, endTime] }, pointId: { $in: pointId.split(',') } }, include: generalInclude }); } else { rslt = await models.PatrolRecord.findAll({ where: { alarm, inspectionTime: { $between: [startTime, endTime] }, pointId: { $in: pointId.split(',') } }, include: generalInclude }); } } else { if (alarm == 'null') { rslt = await models.PatrolRecord.findAll({ where: { inspectionTime: { $between: [startTime, endTime] } }, include: generalInclude.concat([{ model: models.Point, attributes: ['id', 'name'] }]) }); } else { rslt = await models.PatrolRecord.findAll({ where: { alarm, inspectionTime: { $between: [startTime, endTime] } }, include: generalInclude }); } } } else { /* 如果没有startTime && endTime,查询每个点位最新一条符合条件的数据 */ let a = [] if (pointId !== 'null') { a = await models.PatrolRecord.findAll({ where: { pointId: { $in: pointId.split(',') } }, include: generalInclude }); } rslt = pointId.split(',').map(i => { return a.filter(t => t.pointId == i).sort((a, b) => b.id - a.id)[0] || null }) } } else { if (startTime !== 'null' && endTime !== 'null') { if (pointId !== 'null') { rslt = await models.PatrolRecord.findAll({ where: { patrolPlanId: { $in: patrolPlanId.split(',') }, alarm, inspectionTime: { $between: [startTime, endTime] }, pointId: { $in: pointId.split(',') } }, include: generalInclude }); } else { rslt = await models.PatrolRecord.findAll({ where: { patrolPlanId: { $in: patrolPlanId.split(',') }, alarm, inspectionTime: { $between: [startTime, endTime] } }, include: generalInclude }); } } else { let a = [] /* 如果没有startTime && endTime,查询每个点位最新一条符合条件的数据 */ if (pointId !== 'null') { a = await models.PatrolRecord.findAll({ where: { patrolPlanId: { $in: patrolPlanId.split(',') }, pointId: { $in: pointId.split(',') } }, include: generalInclude }); } else { a = await models.PatrolRecord.findAll({ where: { patrolPlanId: { $in: patrolPlanId.split(',') } }, include: generalInclude }); } rslt = pointId.split(',').map(i => { return a.filter(t => t.pointId == i).sort((a, b) => b.id - a.id)[0] || null }) } } let userInfo = ctx.fs.api.userInfo; rslt = rslt.filter(f => f) if (userInfo.username != 'SuperAdmin') { if (userInfo.structure) { rslt = rslt.filter(s => userInfo.structure.find(x => x == s.points.project.id)) } else { rslt = [] } } ctx.status = 200; ctx.body = rslt; error = null } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { "message": "获取巡检记录失败" } } } async function findPatrolRecordUnlicensed(ctx, next) { let rslt = []; let error = { name: 'FindError', message: '获取巡检记录失败' }; try { const models = ctx.fs.dc.models; const { startTime, endTime } = ctx.query; const options = { where: {} } if (startTime && endTime) { options.where.inspectionTime = { $between: [startTime, endTime] }; } rslt = await models.PatrolRecord.findAll(options); ctx.status = 200; ctx.body = rslt; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { "message": "获取巡检记录失败" } } } async function findPointCurPatrolRecord(ctx, next) { let rslt = []; let error = { name: 'FindError', message: '获取巡检记录失败' }; try { const models = ctx.fs.dc.models; const { pointId } = ctx.params; const options = { where: { pointId }, order: [['inspectionTime', 'desc']], limit: 1, } rslt = await models.PatrolRecord.findAll(options); ctx.status = 200; ctx.body = rslt; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { "message": "获取巡检记录失败" } } } async function addPatrolRecord(ctx, next) { let error = { name: 'addError', message: '新增巡检记录失败' }; const transaction = await ctx.fs.dc.orm.transaction(); try { const models = ctx.fs.dc.models; const data = ctx.request.body; let { patrolPlanId, inspectionTime, points, alarm, pointId, projectId } = data const pointRecord = await models.PatrolRecord.findAll({ where: { pointId: pointId }, order: [['inspectionTime', 'desc']], attributes: ['inspectionTime'], }); const lastInspectionTime = pointRecord.length ? pointRecord[0].dataValues.inspectionTime : null; const recordRes = await models.PatrolRecord.create( // record { patrolPlanId: patrolPlanId, lastInspectionTime, inspectionTime, points, alarm, pointId: pointId, projectId } , { transaction }); if (alarm) { await models.PatrolRecordIssueHandle.create({ patrolRecordId: recordRes.id, state: 1, }, { transaction }); } // 更新巡检次数统计 const curPlanRecord = await models.PatrolRecord.findAndCountAll({ where: { patrolPlanId: patrolPlanId } }); const patrolCount = curPlanRecord.count + 1; // 更新下次巡检时间 const curPatrolPlan = await models.PatrolPlan.findOne({ where: { id: patrolPlanId } }); const frequency = Number(curPatrolPlan.frequency.split('次')[0]); const unit = curPatrolPlan.frequency.split('/')[1]; const sTime = moment().startOf(unit === '天' ? 'day' : unit === '周' ? 'isoWeek' : 'month'); const eTime = moment().endOf(unit === '天' ? 'day' : unit === '周' ? 'isoWeek' : 'month'); const filterRecord = curPlanRecord.rows.filter(r => moment(r.inspectionTime).diff(sTime) >= 0 && moment(r.inspectionTime).diff(eTime) <= 0); const groupRecord = filterRecord.group(({ pointId }) => pointId); let isComplete = true; for (const p of curPatrolPlan.points) { if (!groupRecord[p.id]) { if (pointId === p.id && frequency === 1) { continue; } else { isComplete = false; continue; } } else { if ((pointId === p.id ? groupRecord[p.id].length + 1 : groupRecord[p.id].length) < frequency) { isComplete = false; continue; } } } await models.PatrolPlan.update({ patrolCount, nextTime: isComplete ? eTime.format() : sTime.format() }, { where: { id: patrolPlanId }, transaction }) await transaction.commit(); ctx.status = 204; error = null } catch (error) { await transaction.rollback(); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { "message": '新增巡检记录失败' } } } async function getPatrolRecordIssueHandle(ctx) { try { const { models } = ctx.fs.dc; const { userId, userInfo } = ctx.fs.api const { type, pointId, startTime, endTime } = ctx.query let findOption = { where: { $or: [] }, include: [{ model: models.PatrolRecord, where: { } }] } if (pointId) { findOption.include[0].where.pointId = { $in: pointId.split(',') } } if (startTime && endTime) { findOption.where.createTime = { $between: [moment(parseInt(startTime)).format(), moment(parseInt(endTime)).format()] } } let isSuperA = userInfo.username == 'SuperAdmin' let focusStruct = userInfo.structure || [] if (!isSuperA) { findOption.include[0].where.points = { project: { id: { $in: focusStruct } } } } if (type == 'backlog') { // 待办 if (userInfo && userInfo.userResources.includes('ZHIDINGJIHUA')) { findOption.where['$or'].push({ state: 1 }) findOption.where['$or'].push({ state: 3 }) } // 有审批权限且关注此结构物 if (userInfo && userInfo.userResources.includes('SHENHE')) { findOption.where['$or'].push({ state: 2 }) } findOption.where['$or'].push({ state: 4, repairPerson: { id: userId } }) findOption.where['$or'].push({ state: 5, checkPerson: { id: userId } }) findOption.where['$or'].push({ state: 7, repairPerson: { id: userId } }) } else if (type == 'haveDone') { // 已办 findOption.where['$or'].push({ state: { $notIn: [1, 2] }, creator: { id: userId } }) findOption.where['$or'].push({ state: { $gt: 2 }, approvePerson: { id: userId } }) findOption.where['$or'].push({ state: { $gt: 4, $ne: 7 }, repairPerson: { id: userId } }) findOption.where['$or'].push({ state: { $gt: 5 }, checkPerson: { id: userId } }) } const res = await models.PatrolRecordIssueHandle.findAll(findOption) ctx.status = 200; ctx.body = res } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function getPatrolRecordIssueHandleById(ctx) { try { const { models } = ctx.fs.dc; const { id } = ctx.params const res = await models.PatrolRecordIssueHandle.findOne({ where: { id }, include: [{ model: models.PatrolRecord }] }) ctx.status = 200; ctx.body = res } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } // 新建维修处理计划成功 function addPatrolRecordIssueHandle(opts) { return async function (ctx, next) { const models = ctx.fs.dc.models; try { let rslt = ctx.request.body; await models.PatrolRecordIssueHandle.create(Object.assign({}, rslt)) ctx.status = 204; ctx.body = { message: '新建维修处理计划成功' } } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '新建修处理计划失败' } } } } // 修改维修处理计划 function editPatrolRecordIssueHandle(opts) { return async function (ctx, next) { try { const models = ctx.fs.dc.models; const { id } = ctx.params; const body = ctx.request.body; await models.PatrolRecordIssueHandle.update( body, { where: { id: id, } } ) ctx.status = 204; ctx.body = { message: '修改维修处理计划成功' } } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '修改维修处理计划失败' } } } } //查询子系统的当月的巡检和维修 function getSubSystemPatrolAbout(opts) { return async function (ctx, next) { try { let rslt = [] const models = ctx.fs.dc.models; const { STime, ETime, keywords } = ctx.query let generalInclude = [{ model: models.PatrolRecordIssueHandle }, { model: models.Project, where: { subType: { $like: `%${keywords}%` } } }] rslt = await models.PatrolRecord.findAll({ where: { inspectionTime: { $between: [STime, ETime] } }, include: generalInclude }) let userInfo = ctx.fs.api.userInfo; rslt = rslt.filter(f => f) if (userInfo.username != 'SuperAdmin') { if (userInfo.structure) { rslt = rslt.filter(s => userInfo.structure.find(x => x == s.points.project.id)) } else { rslt = [] } } ctx.status = 200; ctx.body = rslt } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '子系统查询巡检记录失败' } } } } /** * 查询故障风险统计 * @param structures {String} 结构物id, example: 1,2,3 */ function getPatrolRecordStatistic(opts) { return async function (ctx, next) { try { let rslt = { monthAlarmCount: 0, // 本月上报风险 monthHandleCount: 0, // 本月处理风险 historyTrend: [], // 历史风险趋势 monthDeviceAlarm: [], // 设备故障统计 }; const models = ctx.fs.dc.models; const sequelize = ctx.fs.dc.orm; const { structures } = ctx.query; const monthStartTime = moment().startOf("month").format('YYYY-MM-DD HH:mm:ss'); const historyStartTime = moment().startOf("month").subtract(11, 'months').format('YYYY-MM-DD HH:mm:ss'); const endTime = moment().endOf("month").format('YYYY-MM-DD HH:mm:ss'); const monthAlarm = await models.PatrolRecord.findAndCountAll({ where: { inspectionTime: { $between: [monthStartTime, endTime] }, projectId: { $in: structures.split(',') }, alarm: true }, include: [{ model: models.Project, where: { type: '管廊' } }], }) rslt.monthAlarmCount = monthAlarm.count; let abnormalDevice = []; for (const r of monthAlarm.rows) { if (Array.isArray(r.points.inspectContent)) { for (const d of r.points.inspectContent) { if (d.deviceName && d.alarm) { let abnormalCount = 0, abnormalScore = 0, slight = 0, middle = 0, severity = 0, itemsCount = []; const index = abnormalDevice.findIndex(e => e.deviceId === d.deviceId); if (index !== -1) { itemsCount = abnormalDevice[index].itemsCount; slight = abnormalDevice[index].slight; middle = abnormalDevice[index].middle; severity = abnormalDevice[index].severity; } for (const item of d.checkItems) { if (item.isNormal === false) { abnormalCount += 1; switch (item.level) { case '轻微': slight += 1; abnormalScore += 1; break; case '中度': middle += 1; abnormalScore += 3; break; case '严重': severity += 1; abnormalScore += 5; break; default: break; } const itemIndex = itemsCount.findIndex(i => i.name === item.name); if (itemIndex === -1) { itemsCount.push({ name: item.name, count: 1 }); } else { itemsCount[itemIndex].count += 1; } } } if (index !== -1) { abnormalDevice[index].abnormalCount += abnormalCount; abnormalDevice[index].abnormalScore += abnormalScore; abnormalDevice[index].itemsCount = itemsCount; abnormalDevice[index].slight = slight; abnormalDevice[index].middle = middle; abnormalDevice[index].severity = severity; } else { abnormalDevice.push({ deviceId: d.deviceId, deviceName: d.deviceName, project: r.points.project.name, abnormalCount, abnormalScore, itemsCount, slight, middle, severity, }) } } } } } rslt.monthDeviceAlarm = abnormalDevice; rslt.monthHandleCount = await models.PatrolRecord.count({ where: { inspectionTime: { $between: [monthStartTime, endTime] }, projectId: { $in: structures.split(',') }, alarm: true }, include: [{ model: models.PatrolRecordIssueHandle, where: { state: 6 } // 验收通过 }, { model: models.Project, where: { type: '管廊' } }], }) // rslt.historyTrend = await sequelize.query( // `select to_char(inspection_time::DATE, 'YYYY-MM') as month, COUNT(*) as num from patrol_record INNER JOIN "project" ON "patrol_record"."project_id" = "project"."id" AND "project"."type" = '管廊' where inspection_time >= '${historyStartTime}' and inspection_time <= '${endTime}' group by month order by month;` // ); const monthFn = sequelize.fn('to_char', sequelize.col('inspection_time'), 'YYYY-MM'); rslt.historyTrend = await models.PatrolRecord.findAll({ attributes: [ [monthFn, 'month'], [sequelize.fn('COUNT', sequelize.col('*')), 'count'], ], group: [monthFn], order: [monthFn], where: { inspectionTime: { $between: [historyStartTime, endTime] }, projectId: { $in: structures.split(',') }, alarm: true }, include: [{ attributes: [], model: models.Project, where: { type: '管廊' } }], }) ctx.status = 200; ctx.body = rslt } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '查询故障风险统计失败' } } } } //根据子系统查询点位信息 function getPointInfo(opts) { return async function (ctx, next){ try{ let rslt=[] const models = ctx.fs.dc.models; const {projectId}=ctx.query let generalInclude = [{model:models.Project,where:{id :projectId}},{model:models.Device}] rslt=await models.Point.findAll({ include:generalInclude }) let userInfo = ctx.fs.api.userInfo; rslt = rslt.filter(f => f) if (userInfo.username != 'SuperAdmin') { if (userInfo.structure) { rslt = rslt.filter(s => userInfo.structure.find(x => x == s.project.userId)) } else { rslt = [] } } ctx.status = 200; ctx.body = rslt }catch(error){ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '根据子系统查询点位信息失败' } } } } //根据结构物查询对应巡检计划的模板 function getTemplate(opts){ return async function (ctx, next){ try{ let rslt=[] const models = ctx.fs.dc.models; const {projectId}=ctx.query rslt=await models.PatrolPlan.findAll({ include:[ {model:models.Project, where:{id:projectId}}, {model:models.PatrolTemplate}] }) let userInfo = ctx.fs.api.userInfo; rslt = rslt.filter(f => f) if (userInfo.username != 'SuperAdmin') { if (userInfo.structure) { rslt = rslt.filter(s => userInfo.structure.find(x => x == s.project.userId)) } else { rslt = [] } } ctx.status = 200; ctx.body = rslt }catch(error){ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '根据结构物查询对应巡检计划的模板失败' } } } } //上报问题和发现问题接口 function reportQuest(opts){ return async function (ctx, next){ try{ const transaction = await ctx.fs.dc.orm.transaction(); const models = ctx.fs.dc.models; const data = ctx.request.body; let { patrolPlanId, inspectionTime, points, alarm, pointId, projectId } = data const pointRecord = await models.PatrolRecord.findAll({ where: { pointId: pointId }, order: [['inspectionTime', 'desc']], attributes: ['inspectionTime'], }); const lastInspectionTime = pointRecord.length ? pointRecord[0].dataValues.inspectionTime : null; const recordRes = await models.PatrolRecord.create( // record { patrolPlanId: patrolPlanId, lastInspectionTime, inspectionTime, points, alarm, pointId: pointId, projectId },{transaction} ); if (alarm) { await models.PatrolRecordIssueHandle.create({ patrolRecordId: recordRes.id, state: 1, }, { transaction }); } await transaction.commit(); ctx.status = 204; }catch(error){ await transaction.rollback(); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '上报问题失败' } } } } // 查询子系统每日巡检 function getSubSystemPatrol(opts) { return async function (ctx, next) { try { let rslt = { dayPatrolPlan: [], // 当日需要巡检的巡检计划 }; const models = ctx.fs.dc.models; const { day, subType } = ctx.query; let userInfo = ctx.fs.api.userInfo; let projectWhere = { subType }; if (userInfo.username !== 'SuperAdmin') { if (userInfo.structure) { projectWhere.id = { $in: userInfo.structure }; } else { projectWhere.id = { $in: [] }; } } rslt.dayPatrolPlan = await models.PatrolPlan.findAll({ where: { startTime: { $lte: day + ' 23:59:59' }, endTime: { $gte: day + ' 00:00:00' } }, include: [{ attributes: ['id', 'name'], model: models.Project, where: projectWhere, }], }); ctx.status = 200; ctx.body = rslt; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: '查询子系统每日巡检失败' } } } } //根据子系统查询点位信息 // function getPointInfo(opts) { // return async function (ctx, next){ // } // } Array.prototype.group = function (callback, thisArg = null) { // 参数合法性判断 if (typeof callback !== "function") { throw new TypeError(`${callback} is not a function`); } const arr = this; const length = this.length; const grouper = Object.create(null); for (let i = 0; i < length; i++) { const key = callback.call(thisArg, arr[i], i, arr) if (!grouper[key]) { grouper[key] = [arr[i]] } else { grouper[key].push(arr[i]) } } return grouper; }; module.exports = { findPatrolRecord, findPatrolRecordUnlicensed, findPointCurPatrolRecord, addPatrolRecord, getPatrolRecordIssueHandle, getPatrolRecordIssueHandleById, addPatrolRecordIssueHandle, editPatrolRecordIssueHandle, getSubSystemPatrolAbout, getPatrolRecordStatistic, getPointInfo, getTemplate, reportQuest, getSubSystemPatrol }