Browse Source

获取推送配置

dev
巴林闲侠 2 years ago
parent
commit
50ebf6e493
  1. 4
      api/.vscode/launch.json
  2. 12
      api/app/lib/controllers/alarm/video.js
  3. 24
      api/app/lib/controllers/organization/index.js
  4. 93
      api/app/lib/controllers/project/index.js
  5. 149
      api/app/lib/controllers/push/config.js
  6. 42
      api/app/lib/models/alarm_push_config.js
  7. 30
      api/app/lib/models/email_send_log.js
  8. 3
      api/app/lib/routes/organization/index.js
  9. 6
      api/app/lib/routes/project/index.js
  10. 2
      api/app/lib/routes/push/index.js
  11. 2
      api/sequelize-automate.config.js
  12. 15
      script/0.0.7/schema/1.update_alarm_push.sql

4
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",

12
api/app/lib/controllers/alarm/video.js

@ -21,7 +21,7 @@ async function deviceType (ctx) {
}
}
async function alarmList(ctx, agg) {
async function alarmList (ctx, agg) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
@ -67,8 +67,8 @@ async function alarmList(ctx, agg) {
)
`)
}
const alarmRes = anxinStrucIds.length ? await clickHouse.vcmp.query(
`
const queryStr = `
SELECT
cameraAlarm.cameraId AS cameraId,
cameraAlarm.cameraName AS cameraName,
@ -129,7 +129,7 @@ async function alarmList(ctx, agg) {
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
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(',')})`}
)
@ -158,8 +158,10 @@ async function alarmList(ctx, agg) {
LEFT JOIN ${anxinyun}.t_sensor AS anxinStation
ON anxinStation.id = anxinIpcStation.station
`
const alarmRes = anxinStrucIds.length ? await clickHouse.vcmp.query(
queryStr
).toPromise() : []
console.log(queryStr);
let returnD = []
let positionD = {}
// 每个设备一个告警

24
api/app/lib/controllers/organization/index.js

@ -22,6 +22,27 @@ async function allDeps (ctx) {
}
}
async function allUsers (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const userRes = await clickHouse.pepEmis.query(`
SELECT id, name FROM user
WHERE delete = false
`).toPromise()
ctx.status = 200;
ctx.body = userRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function editUser (ctx) {
try {
const models = ctx.fs.dc.models;
@ -254,7 +275,7 @@ async function user (ctx) {
// 查对应的项企项目信息
let pepProjectRes = pepPojectIds.size ?
await clickHouse.projectManage.query(`
SELECT id, project_name, isdelete FROM t_pim_project WHERE id IN (${[...pepPojectIds]})
SELECT id, project_name isdelete FROM t_pim_project WHERE id IN (${[...pepPojectIds]})
`).toPromise() :
[]
@ -311,4 +332,5 @@ module.exports = {
putUser,
delAdmin,
user,
allUsers,
};

93
api/app/lib/controllers/project/index.js

@ -145,9 +145,102 @@ async function projectPManage (ctx) {
}
}
async function pepProjectConstrictionState (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const cRes = await clickHouse.projectManage.query(`
SELECT * FROM t_pim_project_state ORDER BY id
`).toPromise()
ctx.status = 200;
ctx.body = cRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function strucWithPomsProject (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { pomsProjectId } = ctx.query
const bindRes = await models.ProjectCorrelation.findOne({
where: {
id: pomsProjectId
}
})
let undelStruc = []
if (bindRes) {
const undelStrucRes = bindRes.anxinProjectId.length ?
await clickHouse.anxinyun.query(
`
SELECT
t_structure.id AS strucId,
t_structure.name AS strucName
FROM
t_project
LEFT JOIN
t_project_structure
ON t_project_structure.project = t_project.id
LEFT JOIN
t_project_structuregroup
ON t_project_structuregroup.project = t_project.id
LEFT JOIN
t_structuregroup_structure
ON t_structuregroup_structure.structuregroup = t_project_structuregroup.structuregroup
LEFT JOIN
t_project_construction
ON t_project_construction.project = t_project.id
LEFT JOIN
t_structure_site
ON t_structure_site.siteid = t_project_construction.construction
RIGHT JOIN
t_structure
ON t_structure.id = t_project_structure.structure
OR t_structure.id = t_structuregroup_structure.structure
OR t_structure.id = t_structure_site.structid
WHERE
project_state != -1
AND
t_project.id IN (${ bindRes.anxinProjectId.join(',')})
ORDER BY strucId
`
).toPromise() :
[]
for (let s of undelStrucRes) {
if (!undelStruc.some(us => us.id == s.strucId)) {
undelStruc.push({
id: s.strucId,
name: s.strucName,
})
}
}
}
ctx.status = 200;
ctx.body = undelStruc
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
appList,
projectAnxincloud,
projectPManage,
pomsProject,
pepProjectConstrictionState,
strucWithPomsProject,
};

149
api/app/lib/controllers/push/config.js

@ -4,21 +4,40 @@ const moment = require('moment')
async function list (ctx) {
try {
const models = ctx.fs.dc.models;
const { keyword, alarmType, state, } = ctx.request.body
const sequelize = ctx.fs.dc.ORM;
const { clickHouse } = ctx.app.fs
const { utils: { anxinStrucIdRange, pomsProjectRange } } = ctx.app.fs
const { keyword, keywordTarget, alarmType, state, tactics, pomsProjectId } = ctx.request.body
let findOption = {
where: {
del: false
}
}
if (keyword) {
findOption.where.$or = [
{
name: { $like: `%${keyword}%` }
},
]
}
let anxinStrucsRange = await anxinStrucIdRange({
ctx, pepProjectId: pomsProjectId, keywordTarget, keyword
})
if (keywordTarget && keyword) {
if (keywordTarget == 'tactics') {
findOption.where.name = { $like: `%${keyword}%` }
} else if (keywordTarget == 'struc') {
let bindAnixinStrucRes = await clickHouse.anxinyun.query(`
SELECT id, name FROM t_structure
WHERE name LIKE '%${keyword}%'
`).toPromise()
let bindAnixinStrucIds = bindAnixinStrucRes.map(s => s.id)
findOption.where.strucId = { $contains: bindAnixinStrucIds }
} else if (keywordTarget == 'pepProject') {
}
}
const pomsProjectRes = await pomsProjectRange({
ctx, pepProjectId: pomsProjectId, keywordTarget, keyword
})
let pomsProjectIds = pomsProjectRes.map(p => p.id)
findOption.where.pomsProjectId = { $in: pomsProjectIds }
if (alarmType) {
findOption.where.alarmType = { $contains: [alarmType] }
}
@ -27,15 +46,99 @@ async function list (ctx) {
findOption.where.disable = false
} else if (state == 'disable') {
findOption.where.disable = true
} else if (state == 'overtime') {
}
}
if (tactics) {
findOption.where.tactics = tactics
}
const listRes = await models.AlarmPushConfig.findAll(findOption)
let allStrucIds = new Set()
let allConfigId = []
let allReceiverIds = new Set()
for (let p of listRes) {
for (let sid of p.strucId) {
allStrucIds.add(sid)
}
allConfigId.push(p.id)
for (let uid of p.receiverPepUserId) {
allReceiverIds.add(uid)
}
}
// 查配置所包含的所有结构物
const allStrucRes = allStrucIds.size ? await clickHouse.anxinyun.query(`
SELECT id, name FROM t_structure
WHERE id IN (${[...allStrucIds].join(',')})
`).toPromise() : []
const listRes = await models.AlarmPushConfig.findAndCountAll(findOption)
// 查所有配置的推送的次数
const pushLogCountRes = await models.EmailSendLog.findAll({
attributes: [
'pushConfigId',
[sequelize.fn('COUNT', sequelize.col('push_config_id')), 'count']
],
where: {
pushConfigId: { $in: allConfigId }
},
group: ['pushConfigId']
})
// 查询所有的用户信息
const userRes = allReceiverIds.size ? await clickHouse.pepEmis.query(`
SELECT id, name, delete FROM user
WHERE id IN (${[...allReceiverIds].join(',')})
`).toPromise() : []
let returnD = []
for (let { dataValues: p } of listRes) {
// 查对应的 poms 绑定的结构物绑定关系
const corBind = pomsProjectRes.find(ppj => ppj.id == p.pomsProjectId)
if (corBind.pepProjectId) {
if (state == 'notYet') {
if (corBind.pepProject && p.timeType.some(pt => pt == corBind.pepProject.constructionStatusId)) {
continue
}
} else if (state == 'takeEffect') {
if (!corBind.pepProject || !p.timeType.some(pt => pt == corBind.pepProject.constructionStatusId)) {
continue
}
}
}
// 结构物信息
let returnStruc = []
for (let sid of p.strucId) {
// 查这个结构物的信息
let structure = allStrucRes.find(asr => asr.id == sid)
if (structure) {
// 检查当前结构物有没有从已绑定的项目里解绑
// 查对应的可见的结构物信息
const anxinStrucSeen = anxinStrucsRange.find(axs => axs.strucId == sid)
returnStruc.push({
id: sid,
name: structure.name,
unbind: !anxinStrucSeen || !corBind.anxinProjectId.includes(anxinStrucSeen.projectId)
})
} else {
// 这个结构物已删
}
}
// 查找日志数量
const corLogCount = pushLogCountRes.find(plc => plc.pushConfigId == p.id)
// 查找接收人数据
const corReceiver = userRes.filter(u => p.receiverPepUserId.some(prId => u.id == prId))
returnD.push({
...p,
pomsProject: corBind,
structure: returnStruc,
pushCount: corLogCount ? corLogCount.count : 0,
receiverPepUser: corReceiver
})
}
ctx.status = 200;
ctx.body = listRes
ctx.body = returnD
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
@ -49,10 +152,12 @@ async function edit (ctx) {
try {
const models = ctx.fs.dc.models;
const { userId, pepUserId } = ctx.fs.api
const { pushId, name, pepProjectId = [], alarmType = [], receiverPepUserId = [], timeType = [], disable } = ctx.request.body
const { pushId, name, pomsProjectId, alarmType = [], receiverPepUserId = [], timeType = [], disable,
strucId = [], tactics, tacticsParams } = ctx.request.body
let storageData = {
name, pepProjectId, alarmType, receiverPepUserId, timeType, disable
name, pomsProjectId, alarmType, receiverPepUserId, timeType, disable,
strucId, tactics, tacticsParams
}
if (pushId) {
await models.AlarmPushConfig.update(storageData, {
@ -63,6 +168,7 @@ async function edit (ctx) {
} else {
storageData.createTime = moment().format()
storageData.createUserId = userId
storageData.del = false
await models.AlarmPushConfig.create(storageData)
}
@ -82,21 +188,16 @@ async function state (ctx) {
const { pushId } = ctx.params
const { disable = undefined, del = undefined, } = ctx.request.body
if (del) {
await models.AlarmPushConfig.destroy({
where: {
id: pushId
}
})
} else {
await models.AlarmPushConfig.update({
let updateData = {
disable,
}, {
del,
}
await models.AlarmPushConfig.update(updateData, {
where: {
id: pushId
}
})
}
ctx.status = 204;
} catch (error) {

42
api/app/lib/models/alarm_push_config.js

@ -24,13 +24,13 @@ module.exports = dc => {
field: "name",
autoIncrement: false
},
pepProjectId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
pomsProjectId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "pep_project_id",
field: "poms_project_id",
autoIncrement: false
},
alarmType: {
@ -86,6 +86,42 @@ module.exports = dc => {
primaryKey: false,
field: "disable",
autoIncrement: false
},
strucId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "struc_id",
autoIncrement: false
},
tactics: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "immediately 即时 / continue 持续 / abnormal_rate 异常率",
primaryKey: false,
field: "tactics",
autoIncrement: false
},
tacticsParams: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: "推送策略 tactics 的参数",
primaryKey: false,
field: "tactics_params",
autoIncrement: false
},
del: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "del",
autoIncrement: false
}
}, {
tableName: "alarm_push_config",

30
api/app/lib/models/email_send_log.js

@ -1,5 +1,4 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
@ -16,40 +15,49 @@ module.exports = dc => {
autoIncrement: true,
unique: "email_send_log_id_uindex"
},
projectCorrelationId: {
toPepUserId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "project_correlation_id",
field: "to_pep_user_id",
autoIncrement: false
},
toPepUserId: {
time: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "time",
autoIncrement: false
},
pushConfigId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "to_pep_user_id",
field: "push_config_id",
autoIncrement: false
},
by: {
tactics: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "by",
field: "tactics",
autoIncrement: false
},
time: {
type: DataTypes.DATE,
allowNull: false,
tacticsParams: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,
field: "time",
field: "tactics_params",
autoIncrement: false
}
}, {

3
api/app/lib/routes/organization/index.js

@ -5,6 +5,9 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/organization/deps'] = { content: '获取全部部门及其下用户', visible: true };
router.get('/organization/deps', organization.allDeps);
app.fs.api.logAttr['GET/organization/users'] = { content: '获取全部未删除用户', visible: true };
router.get('/organization/users', organization.allUsers);
app.fs.api.logAttr['POST/organization/user'] = { content: '编辑成员', visible: true };
router.post('/organization/user', organization.editUser);

6
api/app/lib/routes/project/index.js

@ -21,4 +21,10 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/project/poms'] = { content: '获取已绑定项目', visible: true };
router.get('/project/poms', project.pomsProject);
app.fs.api.logAttr['GET/project/status'] = { content: '获取项目状态列表', visible: true };
router.get('/project/status', project.pepProjectConstrictionState);
app.fs.api.logAttr['GET/project/structure'] = { content: '获取绑定项目下结构物', visible: true };
router.get('/project/structure', project.strucWithPomsProject);
};

2
api/app/lib/routes/push/index.js

@ -7,7 +7,7 @@ module.exports = function (app, router, opts) {
router.get('/push', push.list);
app.fs.api.logAttr['POST/push'] = { content: '新增/编辑推送配置', visible: true };
router.get('/push', push.edit);
router.post('/push', push.edit);
app.fs.api.logAttr['PUT/push/:pushId'] = { content: '更改推送配置状态(禁用或删除)', visible: true };
router.put('/push/:pushId', push.state);

2
api/sequelize-automate.config.js

@ -26,7 +26,7 @@ module.exports = {
dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: ['quick_link'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
tables: ['alarm_push_config'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面

15
script/0.0.7/schema/1.update_alarm_push.sql

@ -0,0 +1,15 @@
alter table alarm_push_config
add struc_id int[] not null;
alter table alarm_push_config
add tactics varchar(32);
comment on column alarm_push_config.tactics is 'immediately 即时 / continue 持续 / abnormal_rate 异常率';
alter table alarm_push_config
add tactics_params jsonb;
comment on column alarm_push_config.tactics_params is '推送策略 tactics 的参数';
alter table alarm_push_config
add del bool default false not null;
Loading…
Cancel
Save