diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json
index 1c34d46..42d30dc 100644
--- a/api/.vscode/launch.json
+++ b/api/.vscode/launch.json
@@ -16,9 +16,9 @@
"-p 4600",
"-f http://localhost:4600",
// 研发
- // "-g postgres://postgres:123@10.8.30.32:5432/orational_service",
+ "-g postgres://postgres:123@10.8.30.32:5432/orational_service",
// 测试
- "-g postgres://FashionAdmin:123456@10.8.30.156:5432/POMS",
+ //"-g postgres://FashionAdmin:123456@10.8.30.156:5432/POMS",
"-k node35:6667,node36:6667,node37:6667",
"--iotaProxy http://10.8.30.157:17007",
"--redisHost 10.8.30.112",
diff --git a/api/app/lib/controllers/alarm/app.js b/api/app/lib/controllers/alarm/app.js
index 43d73fc..5279241 100644
--- a/api/app/lib/controllers/alarm/app.js
+++ b/api/app/lib/controllers/alarm/app.js
@@ -2,7 +2,7 @@
const moment = require('moment')
-async function inspection (ctx) {
+async function inspection(ctx) {
// 巡查
try {
const models = ctx.fs.dc.models;
@@ -31,7 +31,7 @@ async function inspection (ctx) {
}
}
-async function inspectionList (ctx) {
+async function inspectionList(ctx) {
try {
const models = ctx.fs.dc.models;
const { clickHouse } = ctx.app.fs
@@ -116,7 +116,7 @@ async function inspectionList (ctx) {
}
}
-async function notedInspection (ctx) {
+async function notedInspection(ctx) {
try {
const models = ctx.fs.dc.models;
const { inspectionId } = ctx.request.body
@@ -141,7 +141,7 @@ async function notedInspection (ctx) {
}
}
-async function apiError (ctx) {
+async function apiError(ctx) {
try {
const models = ctx.fs.dc.models;
const { projectAppId, alarmContent, router, statusCode, screenshot = '', type } = ctx.request.body
@@ -212,7 +212,7 @@ async function apiError (ctx) {
}
}
-async function apiErrorList (ctx) {
+async function apiErrorList(ctx) {
try {
const models = ctx.fs.dc.models;
const { clickHouse } = ctx.app.fs
@@ -324,11 +324,11 @@ async function apiErrorList (ctx) {
}
}
-async function confirmApiError (ctx) {
+async function confirmApiError(ctx) {
try {
const models = ctx.fs.dc.models;
- const { confirm, appAlarmId = [] } = ctx.request.body
-
+ const { confirm, appAlarmId = [], confirmPost } = ctx.request.body
+ const { pepUserId, projectCorrelationIds, alarmInfo } = confirmPost
await models.AppAlarm.update({
confirm,
confirmTime: moment().format()
@@ -338,6 +338,30 @@ async function confirmApiError (ctx) {
}
})
+ //存日志
+ let logDatas = projectCorrelationIds.map(id => {
+ return {
+ pepUserId,
+ projectCorrelationId: id,
+ alarmInfo,//包含告警id,type,source
+ confirmTime: moment().format(),
+ confirmContent: confirm
+ }
+ })
+ let rslt = await models.AlarmConfirmLog.bulkCreate(logDatas, { returning: true });
+
+ //存最新动态
+ let dynamics = rslt.map(r => {
+ return {
+ time: r.confirmTime,
+ alarmConfirmId: r.id,
+ projectCorrelationId: r.projectCorrelationId,
+ type: 4//告警确认
+ }
+ })
+ await models.LatestDynamicList.bulkCreate(dynamics);
+
+
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
diff --git a/api/app/lib/controllers/alarm/data.js b/api/app/lib/controllers/alarm/data.js
index ae135b5..595cd60 100644
--- a/api/app/lib/controllers/alarm/data.js
+++ b/api/app/lib/controllers/alarm/data.js
@@ -247,7 +247,8 @@ function confirm (opts) {
const { models } = ctx.fs.dc;
const { utils: { kfkSendAsync } } = ctx.app.fs
const { clickHouse } = ctx.app.fs
- const { content = '', alarmId } = ctx.request.body
+ const { content = '', alarmId, confirmPost } = ctx.request.body;
+ const { pepUserId, projectCorrelationIds, alarmInfo } = confirmPost;
// 发送告警恢复通知
// Topic: alarm
/*
diff --git a/api/app/lib/controllers/alarm/video.js b/api/app/lib/controllers/alarm/video.js
index 1263203..007b176 100644
--- a/api/app/lib/controllers/alarm/video.js
+++ b/api/app/lib/controllers/alarm/video.js
@@ -21,7 +21,7 @@ async function deviceType (ctx) {
}
}
-async function alarmList (ctx) {
+async function alarmList(ctx, agg) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
@@ -69,7 +69,7 @@ async function alarmList (ctx) {
}
const alarmRes = anxinStrucIds.length ? await clickHouse.vcmp.query(
`
- SELECT
+ SELECT
cameraAlarm.cameraId AS cameraId,
cameraAlarm.cameraName AS cameraName,
cameraAlarm.cameraKindId AS cameraKindId,
@@ -250,8 +250,12 @@ async function alarmList (ctx) {
}
}
- ctx.status = 200;
- ctx.body = returnD
+ if (agg == 'day') {//控制台 按日聚集
+ return returnD
+ } else {
+ ctx.status = 200;
+ ctx.body = returnD
+ }
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
@@ -264,8 +268,8 @@ async function alarmList (ctx) {
async function confirm (ctx) {
try {
const { models } = ctx.fs.dc;
- const { alarmId, content } = ctx.request.body;
-
+ const { alarmId, content, confirmPost } = ctx.request.body;
+ const { pepUserId, projectCorrelationIds, alarmInfo } = confirmPost;
// TODO: 以视频·应用的秘钥进行鉴权
await ctx.app.fs.vcmpRequest.put('status/alarm/confirm', {
data: {
@@ -273,6 +277,29 @@ async function confirm (ctx) {
}
})
+ //存日志
+ let logDatas = projectCorrelationIds.map(id => {
+ return {
+ pepUserId,
+ projectCorrelationId: id,
+ alarmInfo,//包含告警id,type,source
+ confirmTime: moment().format(),
+ confirmContent: content
+ }
+ })
+ let rslt = await models.AlarmConfirmLog.bulkCreate(logDatas, { returning: true });
+
+ //存最新动态
+ let dynamics = rslt.map(r => {
+ return {
+ time: r.confirmTime,
+ alarmConfirmId: r.id,
+ projectCorrelationId: r.projectCorrelationId,
+ type: 4//告警确认
+ }
+ })
+ await models.LatestDynamicList.bulkCreate(dynamics);
+
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
diff --git a/api/app/lib/controllers/control/data.js b/api/app/lib/controllers/control/data.js
new file mode 100644
index 0000000..d875b5e
--- /dev/null
+++ b/api/app/lib/controllers/control/data.js
@@ -0,0 +1,195 @@
+'use strict';
+const moment = require('moment');
+const { alarmList } = require('../alarm/video');
+//工作台
+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 getBiAnalysis(ctx) {
+ try {
+ const { models } = ctx.fs.dc;
+ const { clickHouse } = ctx.app.fs
+ const { alarmId, limit, page } = ctx.query;
+ 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.number++
+ } else {
+ aggDayMap.push({ day: moment(a.createTime).format('YYYY-MM-DD'), number: 1 })
+ }
+ }
+ 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,
+ getBiAnalysis,
+ getLatestDynamic
+};
\ No newline at end of file
diff --git a/api/app/lib/index.js b/api/app/lib/index.js
index bd5cde2..10a1b33 100644
--- a/api/app/lib/index.js
+++ b/api/app/lib/index.js
@@ -58,7 +58,7 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
});
const {
- AppInspection, ProjectApp, ProjectCorrelation, AppAlarm, App
+ AppInspection, ProjectApp, ProjectCorrelation, AppAlarm, App, AlarmAppearRecord, AlarmConfirmLog, EmailSendLog, LatestDynamicList
} = dc.models;
AppInspection.belongsTo(App, { foreignKey: 'projectAppId', targetKey: 'id' });
@@ -76,4 +76,27 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
AppAlarm.belongsTo(App, { foreignKey: 'projectAppId', targetKey: 'id' });
App.hasMany(AppAlarm, { foreignKey: 'projectAppId', sourceKey: 'id' });
+
+
+
+ AlarmAppearRecord.belongsTo(ProjectCorrelation, { foreignKey: 'projectCorrelationId', targetKey: 'id' });
+ ProjectCorrelation.hasMany(AlarmAppearRecord, { foreignKey: 'projectCorrelationId', sourceKey: 'id' });
+
+ AlarmConfirmLog.belongsTo(ProjectCorrelation, { foreignKey: 'projectCorrelationId', targetKey: 'id' });
+ ProjectCorrelation.hasMany(AlarmConfirmLog, { foreignKey: 'projectCorrelationId', sourceKey: 'id' });
+
+ EmailSendLog.belongsTo(ProjectCorrelation, { foreignKey: 'projectCorrelationId', targetKey: 'id' });
+ ProjectCorrelation.hasMany(EmailSendLog, { foreignKey: 'projectCorrelationId', sourceKey: 'id' });
+
+ LatestDynamicList.belongsTo(AlarmAppearRecord, { foreignKey: 'alarmAppearId', targetKey: 'id' });
+ AlarmAppearRecord.hasMany(LatestDynamicList, { foreignKey: 'alarmAppearId', sourceKey: 'id' });
+
+ LatestDynamicList.belongsTo(EmailSendLog, { foreignKey: 'emailSendId', targetKey: 'id' });
+ EmailSendLog.hasMany(LatestDynamicList, { foreignKey: 'emailSendId', sourceKey: 'id' });
+
+ LatestDynamicList.belongsTo(AlarmConfirmLog, { foreignKey: 'alarmConfirmId', targetKey: 'id' });
+ AlarmConfirmLog.hasMany(LatestDynamicList, { foreignKey: 'alarmConfirmId', sourceKey: 'id' });
+
+ LatestDynamicList.belongsTo(ProjectCorrelation, { foreignKey: 'projectCorrelationId', targetKey: 'id' });
+ ProjectCorrelation.hasMany(LatestDynamicList, { foreignKey: 'projectCorrelationId', sourceKey: 'id' });
};
diff --git a/api/app/lib/models/alarm_appear_record.js b/api/app/lib/models/alarm_appear_record.js
new file mode 100644
index 0000000..3a6dcfa
--- /dev/null
+++ b/api/app/lib/models/alarm_appear_record.js
@@ -0,0 +1,62 @@
+/* eslint-disable*/
+
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const AlarmAppearRecord = sequelize.define("alarmAppearRecord", {
+ id: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "id",
+ autoIncrement: true,
+ unique: "alarm_appear_record_id_uindex"
+ },
+ projectCorrelationId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "project_correlation_id",
+ autoIncrement: false
+ },
+ alarmInfo: {
+ type: DataTypes.JSON,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "alarm_info",
+ autoIncrement: false
+ },
+ time: {
+ type: DataTypes.DATE,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "time",
+ autoIncrement: false
+ },
+ type: {
+ type: DataTypes.STRING,
+ allowNull: true,
+ defaultValue: null,
+ comment: "数据告警:data,设备告警:device,应用告警:application",
+ primaryKey: false,
+ field: "type",
+ autoIncrement: false
+ }
+ }, {
+ tableName: "alarm_appear_record",
+ comment: "",
+ indexes: []
+ });
+ dc.models.AlarmAppearRecord = AlarmAppearRecord;
+ return AlarmAppearRecord;
+};
\ No newline at end of file
diff --git a/api/app/lib/models/alarm_confirm_log.js b/api/app/lib/models/alarm_confirm_log.js
new file mode 100644
index 0000000..f850a83
--- /dev/null
+++ b/api/app/lib/models/alarm_confirm_log.js
@@ -0,0 +1,71 @@
+/* eslint-disable*/
+
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const AlarmConfirmLog = sequelize.define("alarmConfirmLog", {
+ id: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "id",
+ autoIncrement: true,
+ unique: "alarm_confirm_log_id_uindex"
+ },
+ pepUserId: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "pep_user_id",
+ autoIncrement: false
+ },
+ projectCorrelationId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "project_correlation_id",
+ autoIncrement: false
+ },
+ alarmInfo: {
+ type: DataTypes.JSON,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "alarm_info",
+ autoIncrement: false
+ },
+ confirmTime: {
+ type: DataTypes.DATE,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "confirm_time",
+ autoIncrement: false
+ },
+ confirmContent: {
+ type: DataTypes.STRING,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "confirm_content",
+ autoIncrement: false
+ }
+ }, {
+ tableName: "alarm_confirm_log",
+ comment: "",
+ indexes: []
+ });
+ dc.models.AlarmConfirmLog = AlarmConfirmLog;
+ return AlarmConfirmLog;
+};
\ No newline at end of file
diff --git a/api/app/lib/models/email_send_log.js b/api/app/lib/models/email_send_log.js
new file mode 100644
index 0000000..7f75ea1
--- /dev/null
+++ b/api/app/lib/models/email_send_log.js
@@ -0,0 +1,62 @@
+/* eslint-disable*/
+
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const EmailSendLog = sequelize.define("emailSendLog", {
+ id: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "id",
+ autoIncrement: true,
+ unique: "email_send_log_id_uindex"
+ },
+ projectCorrelationId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "project_correlation_id",
+ autoIncrement: false
+ },
+ toPepUserId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "to_pep_user_id",
+ autoIncrement: false
+ },
+ by: {
+ type: DataTypes.STRING,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "by",
+ autoIncrement: false
+ },
+ time: {
+ type: DataTypes.DATE,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "time",
+ autoIncrement: false
+ }
+ }, {
+ tableName: "email_send_log",
+ comment: "",
+ indexes: []
+ });
+ dc.models.EmailSendLog = EmailSendLog;
+ return EmailSendLog;
+};
\ No newline at end of file
diff --git a/api/app/lib/models/latest_dynamic_list.js b/api/app/lib/models/latest_dynamic_list.js
new file mode 100644
index 0000000..5b53051
--- /dev/null
+++ b/api/app/lib/models/latest_dynamic_list.js
@@ -0,0 +1,80 @@
+/* eslint-disable*/
+
+'use strict';
+
+module.exports = dc => {
+ const DataTypes = dc.ORM;
+ const sequelize = dc.orm;
+ const LatestDynamicList = sequelize.define("latestDynamicList", {
+ id: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: true,
+ field: "id",
+ autoIncrement: true,
+ unique: "latest_dynamic_list_id_uindex"
+ },
+ time: {
+ type: DataTypes.DATE,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "time",
+ autoIncrement: false
+ },
+ alarmAppearId: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "alarm_appear_id",
+ autoIncrement: false
+ },
+ emailSendId: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "email_send_id",
+ autoIncrement: false
+ },
+ alarmConfirmId: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "alarm_confirm_id",
+ autoIncrement: false
+ },
+ projectCorrelationId: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: null,
+ comment: null,
+ primaryKey: false,
+ field: "project_correlation_id",
+ autoIncrement: false
+ },
+ type: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: null,
+ comment: '1:发现,2:通知,3:处置,4:确认',
+ primaryKey: false,
+ field: "type",
+ autoIncrement: false
+ }
+ }, {
+ tableName: "latest_dynamic_list",
+ comment: "",
+ indexes: []
+ });
+ dc.models.LatestDynamicList = LatestDynamicList;
+ return LatestDynamicList;
+};
\ No newline at end of file
diff --git a/api/app/lib/routes/control/index.js b/api/app/lib/routes/control/index.js
index eb4da40..1fa7fd5 100644
--- a/api/app/lib/routes/control/index.js
+++ b/api/app/lib/routes/control/index.js
@@ -2,6 +2,7 @@
const toolLink = require('../../controllers/control/toolLink');
const analysis = require('../../controllers/control/analysis');
+const csData = require('../../controllers/control/data');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/console/toollink'] = { content: '获取常用工具', visible: true };
@@ -18,4 +19,18 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/analysis/dataList'] = { content: '查询数据告警产生,确认数量', visible: true };
router.get('/analysis/dataList', analysis.dataList);
+
+
+
+ //项目概览
+ app.fs.api.logAttr['GET/projects/info'] = { content: '查询项目概览', visible: false };
+ router.get('/projects/info', csData.getProjectsInfo);
+
+ //BI分析模块
+ app.fs.api.logAttr['GET/bi/analysis'] = { content: '查询BI分析数据', visible: false };
+ router.get('/bi/analysis', csData.getBiAnalysis);
+
+ //最新动态
+ app.fs.api.logAttr['GET/latest/dynamic'] = { content: '查询最新动态', visible: false };
+ router.get('/latest/dynamic', csData.getLatestDynamic);
};
\ No newline at end of file
diff --git a/web/client/src/sections/problem/components/tableData.jsx b/web/client/src/sections/problem/components/tableData.jsx
index a074e1d..1f4fa02 100644
--- a/web/client/src/sections/problem/components/tableData.jsx
+++ b/web/client/src/sections/problem/components/tableData.jsx
@@ -26,8 +26,8 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
let typeData = { element: "元素异常", apiError: "接口报错 ", timeout: "加载超时" }
let tableDatas = res.payload.data?.rows.map(v => ({
key: v.id,
- projectName: v.app?.projectCorrelations?.map(r => (r.name ? { name: r.name, state: 'PMOS' } : {
- name: r.pepProject?.projectName, state: r.pepProject?.constructionStatus
+ projectName: v.app?.projectCorrelations?.map(r => (r.name ? { id: r.id, name: r.name, state: 'PMOS' } : {
+ id: r.id, name: r.pepProject?.projectName, state: r.pepProject?.constructionStatus
}))?.filter(c => c),
appName: v.app?.name,
url: v.app?.url,
@@ -59,8 +59,8 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
let tableDatas = res.payload.data?.map(v => ({
key: v.alarmId,
StructureName: v.struc,
- projectName: v.pomsProject?.map(r => (r.name ? { name: r.name, state: 'PMOS' } : {
- name: r.pepProject?.projectName, state: r.pepProject?.constructionStatus
+ projectName: v.pomsProject?.map(r => (r.name ? { id: r.id, name: r.name, state: 'PMOS' } : {
+ id: r.id, name: r.pepProject?.projectName, state: r.pepProject?.constructionStatus
}))?.filter(c => c),
createTime: v.createTime ? moment(v.createTime).format("YYYY-MM-DD HH:mm:ss") : "",
updateTime: v.updateTime ? moment(v.updateTime).format("YYYY-MM-DD HH:mm:ss") : "",
@@ -107,8 +107,8 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
let tableDatas = res.payload.data?.rows?.map(v => ({
key: v.AlarmId,
StructureName: v.StructureName,
- projectName: v.pomsProject?.map(r => (r.name ? { name: r.name, state: 'PMOS' } : {
- name: r.pepProject?.projectName, state: r.pepProject?.constructionStatus
+ projectName: v.pomsProject?.map(r => (r.name ? { id: r.id, name: r.name, state: 'PMOS' } : {
+ id: r.id, name: r.pepProject?.projectName, state: r.pepProject?.constructionStatus
}))?.filter(c => c),
createTime: v.StartTime ? moment(v.StartTime).format("YYYY-MM-DD HH:mm:ss") : "",
updateTime: v.EndTime ? moment(v.EndTime).format("YYYY-MM-DD HH:mm:ss") : "",
diff --git a/web/client/src/sections/problem/containers/dataAlarm.jsx b/web/client/src/sections/problem/containers/dataAlarm.jsx
index f249321..92689e8 100644
--- a/web/client/src/sections/problem/containers/dataAlarm.jsx
+++ b/web/client/src/sections/problem/containers/dataAlarm.jsx
@@ -37,7 +37,7 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
const [videoModal, setVideoModal] = useState(false) //视频播放弹框
const [videoData, setVideoData] = useState({}) //视频播放参数
const [videoToken, setVideoToken] = useState() //视频token
-
+ const [alarmToConfirm, setAlarmToConfirm] = useState(null) //告警确认
const TextAreaApi = useRef('')
@@ -309,6 +309,7 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
: r.State == 3 || r.autoRestore || r.confirmAuto ?
:
@@ -383,7 +384,19 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
// console.log(selected);
-
+ const getAlarmConfirmItem = () => {
+ let source = route == 'useAbnormal' ? alarmToConfirm.appName : alarmToConfirm.SourceName;
+ let type = route == 'useAbnormal' ? alarmToConfirm.type : route == 'videoAbnormal' ? alarmToConfirm.AlarmContent : alarmToConfirm.AlarmGroupUnit;
+ return {
+ pepUserId: user.pomsUserInfo.pepUserId,
+ projectCorrelationIds: alarmToConfirm?.projectName?.map(p => p.id),
+ alarmInfo: {
+ id: alarmToConfirm.key,
+ source: source,//告警源
+ type: type,//异常类型
+ }
+ };
+ }
return (
// route=='dataLnterrupt'|| route=='dataAbnormal'|| route=='strategyHit'?
@@ -444,10 +457,10 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
width={600}
onCancel={() => setConfirm(false)}
onOk={() => {
-
+ let confirmPost = getAlarmConfirmItem();
if (route == 'useAbnormal') {
TextAreaApi.current.validate().then((v) => {
- dispatch(problem.postApiConfirm({ appAlarmId: selected, confirm: content })).then(res => {
+ dispatch(problem.postApiConfirm({ appAlarmId: selected, confirm: content, confirmPost })).then(res => {
if (res.success) {
setConfirm(false)
setSelected([])
@@ -457,7 +470,7 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
})
} else if (route == 'videoAbnormal') {
TextAreaApi.current.validate().then((v) => {
- dispatch(problem.putAlarmVideoConfirm({ alarmId: selected, content: content })).then(res => {
+ dispatch(problem.putAlarmVideoConfirm({ alarmId: selected, content: content, confirmPost })).then(res => {
if (res.success) {
setConfirm(false)
setSelected([])
@@ -476,7 +489,7 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
})
} else {
TextAreaApi.current.validate().then((v) => {
- dispatch(problem.putAlarmdataConfirm({ alarmId: selected, content: content })).then(res => {
+ dispatch(problem.putAlarmdataConfirm({ alarmId: selected, content: content, confirmPost })).then(res => {
if (res.success) {
setConfirm(false)
let data = tableData?.map(v => {
@@ -580,7 +593,7 @@ const DataAlarm = ({ match, dispatch, actions, user, loading, socket, iotVcmpWeb
)
}
-function mapStateToProps (state) {
+function mapStateToProps(state) {
const { auth, global, members, webSocket } = state
return {
// loading: members.isRequesting,