wuqun 2 years ago
parent
commit
3a916b4763
  1. 11
      api/.vscode/launch.json
  2. 38
      api/Dockerfile
  3. 19
      api/app/lib/controllers/alarm/data.js
  4. 16
      api/app/lib/controllers/alarm/video.js
  5. 17
      api/app/lib/controllers/auth/index.js
  6. 45
      api/app/lib/controllers/control/data.js
  7. 3
      api/app/lib/controllers/project/bind.js
  8. 103
      api/app/lib/controllers/project/index.js
  9. 52
      api/app/lib/controllers/push/config.js
  10. 4
      api/app/lib/index.js
  11. 20
      api/app/lib/models/alarm_push_config.js
  12. 2
      api/app/lib/models/email_send_log.js
  13. 2
      api/app/lib/models/latest_dynamic_list.js
  14. 1280
      api/app/lib/schedule/alarms_push.js
  15. 2
      api/app/lib/utils/alarmHandle.js
  16. 5
      api/config.js
  17. 18
      jenkinsfile_poms_api
  18. 16
      jenkinsfile_poms_web
  19. 16
      script/0.10/schema/1.alter_alarm_push_config.sql
  20. 4
      script/0.11/schema/1.alter_alarm_push_config.sql
  21. 6
      script/0.11/schema/2.alter_email_send_log.sql
  22. 1
      script/0.11/schema/3.alert_latest_dynamic_list.sql
  23. 44
      web/Dockerfile
  24. BIN
      web/client/assets/images/background/B.png
  25. BIN
      web/client/assets/images/background/General.png
  26. 34
      web/client/index.html
  27. 2
      web/client/src/layout/actions/global.js
  28. 6
      web/client/src/layout/reducers/global.js
  29. 66
      web/client/src/sections/control/containers/control.jsx
  30. 4
      web/client/src/sections/control/containers/userCenter.jsx
  31. 28
      web/client/src/sections/facility/containers/monitor.jsx
  32. 12
      web/client/src/sections/facility/index.js
  33. 3
      web/client/src/sections/facility/nav-item.jsx
  34. 2
      web/client/src/sections/install/containers/system.jsx
  35. 24
      web/client/src/sections/problem/actions/problem.jsx
  36. 20
      web/client/src/sections/problem/components/tableData.jsx
  37. 1176
      web/client/src/sections/service/components/pushModal.jsx
  38. 1407
      web/client/src/sections/service/containers/emPush.jsx
  39. 10
      web/client/src/sections/service/containers/reportManagement.jsx
  40. 8
      web/config.js
  41. 2
      web/package.json
  42. 4
      web/routes/attachment/index.js

11
api/.vscode/launch.json

@ -16,13 +16,14 @@
"-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 10.8.30.72:29092,10.8.30.73:29092,10.8.30.74:29092",
"--iotaProxy http://10.8.30.157:17007",
"--redisHost 10.8.30.112",
"--redisHost localhost",
"--redisPort 6379",
"--apMergeDeVeAnxinProjectId 1,2,3",
"--axyApiUrl http://127.0.0.1:4100",
// "--apiEmisUrl http://10.8.30.112:14000",
//
@ -43,11 +44,9 @@
"--clickHouseUrl http://10.8.30.161",
// "--clickHouseUrl https://clickhouse01.anxinyun.cn/play",
"--clickHousePort 30123",
// * 2
// "--clickHouseUser ",
// "--clickHousePassword ",
//
// "--clickHouseAnxincloud anxinyun",
// "--clickHousePepEmis pepca",
@ -55,7 +54,6 @@
// "--clickHouseVcmp video_accrss1",
// "--clickHouseDataAlarm default",
// "--clickHouseIot iot",
//
"--clickHouseAnxincloud anxinyun88",
"--clickHousePepEmis pepca8",
@ -63,7 +61,6 @@
"--clickHouseVcmp video_access_dev",
"--clickHouseDataAlarm default",
"--clickHouseIot iot",
"--confirmAlarmAnxinUserId 1",
"--vcmpAppId 5048b08d-c449-4d7f-b1ec-f741012aefe8",
"--vcmpAppSecret 5ba8c0ab-9fbd-4f07-9817-c48017c3cbad",

38
api/Dockerfile

@ -1,36 +1,36 @@
# FROM repository.anxinyun.cn/devops/node:12-dev as builder
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12-dev as builder
# COPY . /var/app
COPY . /var/app
# WORKDIR /var/app
WORKDIR /var/app
# EXPOSE 8080
EXPOSE 8080
# RUN npm config set registry=http://10.8.30.22:7000
# RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
# RUN npm cache clean -f
# RUN rm -rf package-lock.json
# RUN npm install --registry http://10.8.30.22:7000
RUN npm config set registry=http://10.8.30.22:7000
RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
RUN npm cache clean -f
RUN rm -rf package-lock.json
RUN npm install --registry http://10.8.30.22:7000
# FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12
# COPY --from=builder --chown=node /var/app /home/node/app
COPY --from=builder --chown=node /var/app /home/node/app
# WORKDIR /home/node/app
WORKDIR /home/node/app
# CMD ["node", "server.js"]
CMD ["node", "server.js"]
# 旧版本构建方式
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
# FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
COPY . /var/app
# COPY . /var/app
WORKDIR /var/app
# WORKDIR /var/app
EXPOSE 8080
# EXPOSE 8080
CMD ["-u", "http://localhost:8088"]
# CMD ["-u", "http://localhost:8088"]
ENTRYPOINT [ "node", "server.js" ]
# ENTRYPOINT [ "node", "server.js" ]

19
api/app/lib/controllers/alarm/data.js

@ -8,17 +8,23 @@ async function groupList (ctx) {
const { clickHouse } = ctx.app.fs
const { database: dataAlarm } = clickHouse.dataAlarm.opts.config
const { showAll } = ctx.query
const groupRes = await clickHouse.anxinyun.query(`
SELECT * FROM t_alarm_group
`).toPromise();
let whereOption = []
if (!showAll) {
whereOption.push(` INNER JOIN ${dataAlarm}.alarms
ON t_alarm_group_unit.id = ${dataAlarm}.alarms.AlarmGroupUnit`)
}
for (let g of groupRes) {
g.unit = await await clickHouse.anxinyun.query(`
SELECT DISTINCT
t_alarm_group_unit.id AS id,t_alarm_group_unit.name AS name,t_alarm_group_unit.group_id AS groupId
FROM t_alarm_group_unit
INNER JOIN ${dataAlarm}.alarms
ON t_alarm_group_unit.id = ${dataAlarm}.alarms.AlarmGroupUnit
${whereOption}
WHERE group_id = ${g.id}
`).toPromise();
}
@ -90,7 +96,7 @@ async function list (ctx) {
whereOption.push(`DeviceStatus.Status = ${0}`)
}
}
let alarmQueryOptionStr = `
FROM
alarms
@ -143,7 +149,6 @@ async function list (ctx) {
`).toPromise();
const confirmedAlarm = alarmRes
// TODO: 开发临时注释
.filter(ar => ar.State && ar.State > 2)
.map(ar => "'" + ar.AlarmId + "'")
const confirmedAlarmDetailMax = confirmedAlarm.length ?
@ -218,7 +223,7 @@ async function list (ctx) {
}
}
async function getAlarmGroups(ctx) {
async function getAlarmGroups (ctx) {
try {
const { clickHouse } = ctx.app.fs
const groupRes = await clickHouse.anxinyun.query(`
@ -239,7 +244,7 @@ async function getAlarmGroups(ctx) {
}
}
}
async function exportDataAlarms(ctx, alarmList, groupId) {
async function exportDataAlarms (ctx, alarmList, groupId) {
try {
const { utils: { simpleExcelDown, getExportAlarmHeader } } = ctx.app.fs;
let header = await getExportAlarmHeader(groupId);
@ -303,7 +308,7 @@ async function exportDataAlarms(ctx, alarmList, groupId) {
}
}
}
async function detail(ctx) {
async function detail (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs

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

@ -8,11 +8,18 @@ async function deviceType (ctx) {
const { clickHouse } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
const { utils: { judgeSuper, anxinStrucIdRange } } = ctx.app.fs
const { showAll } = ctx.query
let anxinStruc = await anxinStrucIdRange({
ctx,
})
const anxinStrucIds = anxinStruc.map(a => a.strucId)
let whereOption = []
if (!showAll) {
whereOption.push(`INNER 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(',')})`}`)
}
const kindRes = await clickHouse.vcmp.query(`
SELECT DISTINCT
camera_kind.id AS id,camera_kind.kind AS kind
@ -22,10 +29,7 @@ async function deviceType (ctx) {
INNER JOIN camera_status_alarm
ON camera.channel_no = camera_status_alarm.channel_no
AND camera.serial_no = camera_status_alarm.serial_no
INNER 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(',')})`}
${whereOption}
`).toPromise()
ctx.status = 200;
ctx.body = kindRes
@ -38,7 +42,7 @@ async function deviceType (ctx) {
}
}
async function exceptionType(ctx) {
async function exceptionType (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs

17
api/app/lib/controllers/auth/index.js

@ -10,9 +10,18 @@ async function login (ctx, next) {
const models = ctx.fs.dc.models;
const params = ctx.request.body;
const emisLoginRes = await ctx.app.fs.emisRequest.post('login', {
data: params
})
let emisLoginRes = null
if (params.username && params.password) {
emisLoginRes = await ctx.app.fs.emisRequest.post('login', {
data: { ...params, code: 'POMS' }
})
} else if (params.token) {
emisLoginRes = await ctx.app.fs.emisRequest.get('user-info', {
query: {
token: params.token, code: 'POMS'
}
})
}
if (!emisLoginRes) {
throw "无此用户,请使用正确的登录信息"
@ -70,7 +79,7 @@ async function login (ctx, next) {
await ctx.redis.hmset(emisLoginRes.token, {
expired: moment().add(1, 'day'),
userInfo:JSON.stringify(emisLoginRes)
userInfo: JSON.stringify(emisLoginRes)
});
ctx.status = 200;

45
api/app/lib/controllers/control/data.js

@ -2,7 +2,7 @@
const moment = require('moment');
//BI分析-数据
async function getDataAlarmsAggDay(ctx) {
async function getDataAlarmsAggDay (ctx) {
try {
const { utils: { anxinStrucIdRange } } = ctx.app.fs
const { pepProjectId } = ctx.query
@ -12,10 +12,8 @@ async function getDataAlarmsAggDay(ctx) {
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');//最近一年
@ -41,7 +39,7 @@ async function getDataAlarmsAggDay(ctx) {
}
}
async function queryAlarm(ctx, alarmQueryOptionStr, type) {
async function queryAlarm (ctx, alarmQueryOptionStr, type) {
const { clickHouse } = ctx.app.fs
try {
const alarmRes = await clickHouse.dataAlarm.query(`
@ -76,7 +74,7 @@ async function queryAlarm(ctx, alarmQueryOptionStr, type) {
}
//BI分析-应用异常
async function getAppAlarmsAggDay(ctx) {
async function getAppAlarmsAggDay (ctx) {
try {
const models = ctx.fs.dc.models;
const { utils: { pomsProjectRange } } = ctx.app.fs
@ -129,7 +127,7 @@ async function getAppAlarmsAggDay(ctx) {
}
//BI分析-视频异常
async function getVideoAlarmsAggDay(ctx) {
async function getVideoAlarmsAggDay (ctx) {
try {
const { clickHouse, utils: { anxinStrucIdRange } } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
@ -246,7 +244,7 @@ async function getVideoAlarmsAggDay(ctx) {
}
//BI分析-问题处置效率分析
async function getAlarmsHandleStatistics(ctx) {
async function getAlarmsHandleStatistics (ctx) {
try {
const { projectCorrelationId } = ctx.query
const models = ctx.fs.dc.models;
@ -266,7 +264,7 @@ async function getAlarmsHandleStatistics(ctx) {
}
}
//最新动态
async function getLatestDynamic(ctx) {
async function getLatestDynamic (ctx) {
try {
const { models } = ctx.fs.dc;
const { limit, page, projectCorrelationId, types } = ctx.query;
@ -303,9 +301,9 @@ async function getLatestDynamic(ctx) {
});
//查项目名称 查用户名
let pepPojectIds = new Set(), notedUserIds = new Set();
let pepPojectIds = new Set(), notedUserIds = new Set(), emailSendPomsProjectIds = new Set();
for (let p of news) {
if(p.projectCorrelation && p.projectCorrelation.pepProjectId){
if (p.projectCorrelation && p.projectCorrelation.pepProjectId) {
pepPojectIds.add(p.projectCorrelation.pepProjectId);
}
@ -313,11 +311,28 @@ async function getLatestDynamic(ctx) {
p.emailSendLog.toPepUserIds.map(u => {
notedUserIds.add(u);//通知 接收人
})
p.emailSendLog.projectCorrelationId.forEach(pid => emailSendPomsProjectIds.add(pid))
}
if (p.alarmConfirmLog && p.alarmConfirmLog.pepUserId) {
notedUserIds.add(p.alarmConfirmLog.pepUserId);//确认 操作者
}
}
// EM 推送的特殊处理
// 查找对应的 projectCorrelation
const emailLogProjectCorrelationRes =
emailSendPomsProjectIds.size ?
await models.ProjectCorrelation.findAll({
where: {
id: { $in: [...emailSendPomsProjectIds] }
}
}) : []
for (let { dataValues: p } of emailLogProjectCorrelationRes) {
if (p.pepProjectId) {
pepPojectIds.add(p.pepProjectId)
}
}
let pepProjects = pepPojectIds.size ? await clickHouse.projectManage.query(`
SELECT id, project_name FROM t_pim_project WHERE id IN (${[...pepPojectIds].join(',')},-1)
`).toPromise() : [];
@ -339,7 +354,15 @@ async function getLatestDynamic(ctx) {
if (d.emailSendId) {
notice.push({
userName: userPepRes.filter(u => d.emailSendLog.toPepUserIds.indexOf(u.id) != -1),
projectName,
projectName: d.emailSendLog.projectCorrelationId.map(p => {
let projectName = ''
if (p.pepProjectId) {
projectName = pepProjects.find(pp => pp.id == p.pepProjectId).project_name
} else {
projectName = p.name
}
return projectName
}).join('、'),
...d.emailSendLog.dataValues
});
}

3
api/app/lib/controllers/project/bind.js

@ -105,6 +105,9 @@ async function bindAnxin2pep (ctx) {
// 但是有之前的数据
if (existRes.del) {
// 不过之前的删除了
storageData.createUser = userId
storageData.updateTime = now.format()
storageData.createTime = now.format()
await models.ProjectCorrelation.update(storageData, {
where: {
pepProjectId: pepProjectId

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

@ -57,7 +57,7 @@ async function pomsProject (ctx) {
if (p.pepProjectId) {
pepProjectIds.add(p.pepProjectId)
}
if(p.createUser){
if (p.createUser) {
createUsers.add(p.createUser)
}
for (let ap of p.anxinProjectId) {
@ -66,18 +66,18 @@ async function pomsProject (ctx) {
}
}
}
const pomsUser = await models.User.findAll({
where: {
id: { $in: [...createUsers]}
}
})
let pepUserIds = new Set()
for (let p of pomsUser) {
if (p.pepUserId) {
const pomsUser = await models.User.findAll({
where: {
id: { $in: [...createUsers] }
}
})
let pepUserIds = new Set()
for (let p of pomsUser) {
if (p.pepUserId) {
pepUserIds.add(p.pepUserId)
}
}
const pepcaUser = pepUserIds.size ?
}
}
const pepcaUser = pepUserIds.size ?
await clickHouse.pepEmis.query(
`
SELECT * FROM user
@ -112,7 +112,7 @@ async function pomsProject (ctx) {
for (let p of proRes.rows) {
const corPro = pepProjectRes.find(pp => pp.id == p.pepProjectId) || {}
const pepUserName = (pepcaUser.find(qq => qq.id == (pomsUser.find(oo => oo.id == p.createUser)||{}).pepUserId)||{}).name ||''
const pepUserName = (pepcaUser.find(qq => qq.id == (pomsUser.find(oo => oo.id == p.createUser) || {}).pepUserId) || {}).name || ''
p.dataValues.pepProjectName = corPro.project_name
p.dataValues.pepProjectIsDelete = corPro.isdelete
p.dataValues.constructionStatusId = corPro.construction_status_id
@ -126,7 +126,7 @@ async function pomsProject (ctx) {
ctx.status = 200;
ctx.body = proRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`)
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
@ -210,20 +210,33 @@ async function strucWithPomsProject (ctx) {
const { clickHouse } = ctx.app.fs
const { pomsProjectId } = ctx.query
const bindRes = await models.ProjectCorrelation.findOne({
const bindRes = await models.ProjectCorrelation.findAll({
where: {
id: pomsProjectId
id: { $in: pomsProjectId.split(',') }
}
})
let anxinProjectIds = new Set()
for (let b of bindRes) {
if (b.anxinProjectId.length) {
for (let aid of b.anxinProjectId) {
anxinProjectIds.add(aid)
}
}
}
let undelStruc = []
if (bindRes) {
const undelStrucRes = bindRes.anxinProjectId.length ?
const undelStrucRes = anxinProjectIds.size ?
await clickHouse.anxinyun.query(
`
SELECT
t_structure.id AS strucId,
t_structure.name AS strucName
t_structure.name AS strucName,
t_factor.id AS factorId,
t_factor.name AS factorName,
t_factor.proto AS factorProto,
t_factor_proto_item.name AS factorItemName,
t_factor_proto_item.id AS factorItemId
FROM
t_project
LEFT JOIN
@ -246,20 +259,70 @@ async function strucWithPomsProject (ctx) {
ON t_structure.id = t_project_structure.structure
OR t_structure.id = t_structuregroup_structure.structure
OR t_structure.id = t_structure_site.structid
LEFT JOIN t_structure_factor
ON t_structure_factor.structure = t_structure.id
LEFT JOIN t_factor
ON t_structure_factor.factor = t_factor.id
LEFT JOIN t_factor_proto_item
ON t_factor_proto_item.proto = t_factor.proto
WHERE
project_state != -1
AND
t_project.id IN (${bindRes.anxinProjectId.join(',')})
t_project.id IN (${[...anxinProjectIds].join(',')}, -1)
ORDER BY strucId
`
).toPromise() :
[]
for (let s of undelStrucRes) {
if (!undelStruc.some(us => us.id == s.strucId)) {
let corStrut = undelStruc.find(us => us.id == s.strucId)
if (!corStrut) {
let nextFacor = []
if (s.factorId) {
let nextFactorItem = []
if (s.factorItemId) {
nextFactorItem.push({
id: s.factorItemId,
name: s.factorItemName,
})
}
nextFacor.push({
id: s.factorId,
name: s.factorName,
proto: s.factorProto,
item: nextFactorItem,
})
}
undelStruc.push({
id: s.strucId,
name: s.strucName,
factor: nextFacor
})
} else {
if (s.factorId) {
let corFactor = corStrut.factor.find(v => v.id == s.factorId)
let nextFactorItem = null
if (s.factorItemId) {
nextFactorItem = {
id: s.factorItemId,
name: s.factorItemName,
}
}
if (corFactor) {
if (!corFactor.item.some(fi => fi.id == s.factorItemId) && nextFactorItem) {
corFactor.item.push(nextFactorItem)
}
} else {
corStrut.factor.push({
id: s.factorId,
name: s.factorName,
proto: s.factorProto,
item: nextFactorItem ? [{
id: s.factorItemId,
name: s.factorItemName,
}] : [],
})
}
}
}
}
}

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

@ -8,23 +8,11 @@ async function list (ctx) {
const { clickHouse } = ctx.app.fs
const { utils: { anxinStrucIdRange, pomsProjectRange } } = ctx.app.fs
const { keyword, keywordTarget, alarmType, state, tactics, pomsProjectId } = ctx.query
let projectCorrelationWhere = {
del: false,
}
if (state == 'notYet') {
projectCorrelationWhere.pepProjectId = { $ne: null }
}
let findOption = {
where: {
del: false
},
order: [['id', 'desc']],
include: [{
model: models.ProjectCorrelation,
where: projectCorrelationWhere,
required: true
}]
}
let anxinStrucsRange = await anxinStrucIdRange({
@ -48,7 +36,7 @@ async function list (ctx) {
ctx, pepProjectId: pomsProjectId, keywordTarget, keyword
})
let pomsProjectIds = pomsProjectRes.map(p => p.id)
findOption.where.pomsProjectId = { $in: pomsProjectIds }
findOption.where.pomsProjectId = { $overlap: pomsProjectIds }
if (alarmType) {
findOption.where.alarmType = { $contains: [alarmType] }
@ -65,6 +53,7 @@ async function list (ctx) {
}
const listRes = await models.AlarmPushConfig.findAll(findOption)
// const listRes = await models.AlarmPushConfig.findAll({})
let allStrucIds = new Set()
let allConfigId = []
let allReceiverIds = new Set()
@ -104,17 +93,28 @@ async function list (ctx) {
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
const corBinds = pomsProjectRes.filter(ppj => p.pomsProjectId.includes(ppj.id))
let filterBinds = []
for (let corBind of corBinds) {
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
}
}
} else if (state == 'notYet') {
continue
}
filterBinds.push(corBind)
}
if (!filterBinds.length) {
continue
}
// 结构物信息
@ -129,7 +129,7 @@ async function list (ctx) {
returnStruc.push({
id: sid,
name: structure.name,
unbind: !anxinStrucSeen || !corBind.anxinProjectId.includes(anxinStrucSeen.projectId)
unbind: !anxinStrucSeen || corBinds.every(corBinds => !corBinds.anxinProjectId.includes(anxinStrucSeen.projectId))
})
} else {
// 这个结构物已删
@ -142,7 +142,7 @@ async function list (ctx) {
const corReceiver = userRes.filter(u => p.receiverPepUserId.some(prId => u.id == prId))
returnD.push({
...p,
pomsProject: corBind,
pomsProject: corBinds,
structure: returnStruc,
pushCount: corLogCount ? corLogCount.dataValues.count : 0,
receiverPepUser: corReceiver
@ -165,11 +165,11 @@ async function edit (ctx) {
const models = ctx.fs.dc.models;
const { userId, pepUserId } = ctx.fs.api
const { pushId, name, pomsProjectId, alarmType = [], receiverPepUserId = [], timeType = [], disable,
strucId = [], tactics, tacticsParams } = ctx.request.body
strucId = [], tactics, tacticsParams, alarmSubType = {}, pomsStrucFactorId = {} } = ctx.request.body
let storageData = {
name, pomsProjectId, alarmType, receiverPepUserId, timeType, disable,
strucId, tactics, tacticsParams
strucId, tactics, tacticsParams, alarmSubType, pomsStrucFactorId
}
let repeatOption = {

4
api/app/lib/index.js

@ -77,8 +77,8 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
AppAlarm.belongsTo(App, { foreignKey: 'projectAppId', targetKey: 'id' });
App.hasMany(AppAlarm, { foreignKey: 'projectAppId', sourceKey: 'id' });
AlarmPushConfig.belongsTo(ProjectCorrelation, { foreignKey: 'pomsProjectId', targetKey: 'id' });
ProjectCorrelation.hasMany(AlarmPushConfig, { foreignKey: 'pomsProjectId', sourceKey: 'id' });
// AlarmPushConfig.belongsTo(ProjectCorrelation, { foreignKey: 'pomsProjectId', targetKey: 'id' });
// ProjectCorrelation.hasMany(AlarmPushConfig, { foreignKey: 'pomsProjectId', sourceKey: 'id' });
AlarmAppearRecord.belongsTo(ProjectCorrelation, { foreignKey: 'projectCorrelationId', targetKey: 'id' });
ProjectCorrelation.hasMany(AlarmAppearRecord, { foreignKey: 'projectCorrelationId', sourceKey: 'id' });

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

@ -25,7 +25,7 @@ module.exports = dc => {
autoIncrement: false
},
pomsProjectId: {
type: DataTypes.INTEGER,
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: false,
defaultValue: null,
comment: null,
@ -42,6 +42,24 @@ module.exports = dc => {
field: "alarm_type",
autoIncrement: false
},
alarmSubType: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: "监听的告警类型的子类id的关联",
primaryKey: false,
field: "alarm_sub_type",
autoIncrement: false
},
pomsStrucFactorId: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: null,
comment: "结构物与监测项id的关联",
primaryKey: false,
field: "poms_struc_factor_id",
autoIncrement: false
},
receiverPepUserId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: true,

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

@ -53,7 +53,7 @@ module.exports = dc => {
autoIncrement: false
},
projectCorrelationId: {
type: DataTypes.INTEGER,
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: false,
defaultValue: null,
comment: null,

2
api/app/lib/models/latest_dynamic_list.js

@ -54,7 +54,7 @@ module.exports = dc => {
},
projectCorrelationId: {
type: DataTypes.INTEGER,
allowNull: false,
allowNull: true,
defaultValue: null,
comment: null,
primaryKey: false,

1280
api/app/lib/schedule/alarms_push.js

File diff suppressed because it is too large

2
api/app/lib/utils/alarmHandle.js

@ -110,7 +110,7 @@ module.exports = function (app, opts) {
}
let pepProjects = pepPojectIds.size ? await clickHouse.projectManage.query(`
SELECT id, project_name FROM t_pim_project WHERE id IN (${[...pepPojectIds]}, -1)`
SELECT id, project_name FROM t_pim_project WHERE id IN (${[...pepPojectIds].join(',')}, -1)`
).toPromise() : [];
return { projects, pepProjects };

5
api/config.js

@ -19,6 +19,8 @@ args.option('redisHost', 'redisHost');
args.option('redisPort', 'redisPort');
args.option('redisPswd', 'redisPassword');
args.option('apMergeDeVeAnxinProjectId', '告警推送自定义の合并数据异常(De)视频异常(Ve)的指定的结构物id');
args.option('axyApiUrl', '安心云 api');
args.option('apiEmisUrl', '企业管理 api');
args.option('apiVcmpUrl', '视频平台 api');
@ -67,6 +69,8 @@ const IOTA_REDIS_SERVER_HOST = process.env.IOTA_REDIS_SERVER_HOST || flags.redis
const IOTA_REDIS_SERVER_PORT = process.env.IOTA_REDIS_SERVER_PORT || flags.redisPort || "6379";//redis 端口
const IOTA_REDIS_SERVER_PWD = process.env.IOTA_REDIS_SERVER_PWD || flags.redisPswd || "";//redis 密码
const AP_MERGE_DEVE_ANXINPROJECT_ID = process.env.AP_MERGE_DEVE_ANXINPROJECT_ID || flags.apMergeDeVeAnxinProjectId || "";
// 安心云api
const API_ANXINYUN_URL = process.env.API_ANXINYUN_URL || flags.axyApiUrl;
// 企业管理 api
@ -155,6 +159,7 @@ const product = {
{ p: '/alarm/application/api', o: 'POST' },
{ p: '/alarm/video/added_log', o: 'POST' }
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
apMergeDeVeAnxinProjectId: AP_MERGE_DEVE_ANXINPROJECT_ID,
anxinCloud: {
confirmAlarmAnxinUserId: CONFIRM_ALARM_ANXIN_USER_ID
},

18
jenkinsfile_poms_api

@ -1,19 +1,19 @@
pipeline {
agent {
node{
node{
label 'jnlp-slave'
}
}
}
stages {
stage('Testing poms ......') {
stage('Testing site......') {
steps {
sh 'switch-auth.sh anxinyun'
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}"
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./api'
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}'
buildName "#${BUILD_NUMBER} ~/iot/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "harbor.anxinyun.cn/iot/${JOB_NAME}:${IMAGE_VERSION}"
sh 'nerdctl build -t harbor.anxinyun.cn/iot/${JOB_NAME}:${IMAGE_VERSION} ./api'
sh 'nerdctl push harbor.anxinyun.cn/iot/${JOB_NAME}:${IMAGE_VERSION}'
}
}
}
}
}

16
jenkinsfile_poms_web

@ -2,18 +2,18 @@ pipeline {
agent {
node{
label 'jnlp-slave'
}
}
}
stages {
stage('Testing poms ......') {
stage('Testing site......') {
steps {
sh 'switch-auth.sh anxinyun'
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}"
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./web'
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}'
buildName "#${BUILD_NUMBER} ~/iot/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "harbor.anxinyun.cn/iot/${JOB_NAME}:${IMAGE_VERSION}"
sh 'nerdctl build -t harbor.anxinyun.cn/iot/${JOB_NAME}:${IMAGE_VERSION} ./web'
sh 'nerdctl push harbor.anxinyun.cn/iot/${JOB_NAME}:${IMAGE_VERSION}'
}
}
}
}
}

16
script/0.10/schema/1.alter_alarm_push_config.sql

@ -0,0 +1,16 @@
alter table alarm_push_config
add alarm_sub_type jsonb;
comment on column alarm_push_config.alarm_sub_type is '存对应监听模块(alarm_type)的子类(
alarms.AlarmGroupUnit,
camera.kind_id,
app_alarm.errType
)';
ALTER TABLE alarm_push_config ALTER COLUMN poms_project_id TYPE INTEGER []
USING CASE
WHEN poms_project_id is NULL
then NULL
ELSE array [poms_project_id]
END ::INTEGER [];

4
script/0.11/schema/1.alter_alarm_push_config.sql

@ -0,0 +1,4 @@
alter table alarm_push_config
add poms_struc_factor_id jsonb;
comment on column alarm_push_config.poms_struc_factor_id is '结构物对应监测项 id';

6
script/0.11/schema/2.alter_email_send_log.sql

@ -0,0 +1,6 @@
ALTER TABLE email_send_log ALTER COLUMN project_correlation_id TYPE INTEGER []
USING CASE
WHEN project_correlation_id is NULL
then NULL
ELSE array [project_correlation_id]
END ::INTEGER [];

1
script/0.11/schema/3.alert_latest_dynamic_list.sql

@ -0,0 +1 @@
alter table latest_dynamic_list alter column project_correlation_id drop not null;

44
web/Dockerfile

@ -1,40 +1,40 @@
# FROM repository.anxinyun.cn/devops/node:12-dev as builder
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12-dev as builder
# COPY . /var/app
COPY . /var/app
# WORKDIR /var/app
WORKDIR /var/app
# EXPOSE 8080
EXPOSE 8080
# RUN npm config set registry=http://10.8.30.22:7000
# RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
# RUN npm cache clean -f
# RUN npm install --registry http://10.8.30.22:7000
# RUN npm run build
# RUN rm -rf client/src
# RUN rm -rf node_modules
# RUN npm install --production --registry http://10.8.30.22:7000
RUN npm config set registry=http://10.8.30.22:7000
RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
RUN npm cache clean -f
RUN npm install --registry http://10.8.30.22:7000
RUN npm run build
RUN rm -rf client/src
RUN rm -rf node_modules
RUN npm install --production --registry http://10.8.30.22:7000
# FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node-16:7.22-06-20
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node-16:7.22-06-20
# COPY --from=builder --chown=node /var/app /home/node/app
COPY --from=builder --chown=node /var/app /home/node/app
# WORKDIR /home/node/app
WORKDIR /home/node/app
# CMD ["node", "server.js"]
CMD ["node", "server.js"]
# 旧版本构建方式
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
# FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
COPY . /var/app
# COPY . /var/app
WORKDIR /var/app
# WORKDIR /var/app
EXPOSE 8080
# EXPOSE 8080
CMD ["-u", "http://localhost:8088"]
# CMD ["-u", "http://localhost:8088"]
ENTRYPOINT [ "node", "server.js" ]
# ENTRYPOINT [ "node", "server.js" ]

BIN
web/client/assets/images/background/B.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
web/client/assets/images/background/General.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

34
web/client/index.html

@ -2,26 +2,26 @@
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
<meta charset="UTF-8">
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
<link rel="shortcut icon" href="/assets/images/favicon.ico">
<link rel="shortcut icon" href="/assets/images/favicon.ico">
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
<script>LA.init({ id: "Jo4eTlZVqgx3uwqm", ck: "Jo4eTlZVqgx3uwqm" })</script>
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
<script>LA.init({ id: "Jo4eTlZVqgx3uwqm", ck: "Jo4eTlZVqgx3uwqm" })</script>
<script
src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.559b91c217b8ddc76c0c4b1397d84d48.es5.js"></script>
</head >
<script
src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.559b91c217b8ddc76c0c4b1397d84d48.es5.js"></script>
</head>
<body>
<div id='PomsApp' style="height: 100%;"></div>
<body>
<div id='PomsApp' style="height: 100%;"></div>
<!-- Webpack -->
<script type="text/javascript" src="http://localhost:5601/client/build/app.js"></script>
<!-- Webpack -->
<script type="text/javascript" src="http://localhost:5601/client/build/app.js"></script>
<!-- Vite -->
<!-- <script type="module">
<!-- Vite -->
<!-- <script type="module">
import RefreshRuntime from "http://localhost:5602/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => { }
@ -30,9 +30,9 @@
const global = window
</script>
<script type="module" src="http://localhost:5002/src/index.jsx"></script> -->
<!-- Vite End -->
<!-- Vite End -->
<script>
<script>
//过滤掉一些无用的警告、没有价值的报错
//代理console.warn方法
@ -48,7 +48,7 @@
// _consoleWarn(...rest);
// }
// };
</script>
</script>
</body>
</html>

2
web/client/src/layout/actions/global.js

@ -39,6 +39,8 @@ export function initApiRoot () {
payload: {
apiRoot: res.root,
iotVcmpWeb:res.iotVcmpWeb,
pomsMonitor:res.pomsMonitor,
dcWeb:res.dcWeb,
}
})
});

6
web/client/src/layout/reducers/global.js

@ -12,6 +12,8 @@ function global (state = {
clientWidth: 1024,
apiRoot: '',
iotVcmpWeb: '',
pomsMonitor:'',
dcWeb:'',
}, action) {
const payload = action.payload;
switch (action.type) {
@ -31,7 +33,9 @@ function global (state = {
case INIT_API_ROOT:
return Immutable.fromJS(state).merge({
apiRoot: payload.apiRoot,
iotVcmpWeb: payload.iotVcmpWeb
iotVcmpWeb: payload.iotVcmpWeb,
pomsMonitor:payload.pomsMonitor,
dcWeb:payload.dcWeb,
}).toJS();
case PEPPROJECTID:
return Immutable.fromJS(state).merge({

66
web/client/src/sections/control/containers/control.jsx

@ -8,7 +8,6 @@ import repairFQA from '../../means/containers/repairFQA';
import { Setup, OutHidden } from "$components";
import ReactECharts from 'echarts-for-react';
import moment from "moment";
import { log } from 'ezuikit-js';
let newScrollbar;
let overviewScrollbar;
@ -43,7 +42,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const [videoBI, setVideoBI] = useState([]); //BI-
const [appBI, setAppBI] = useState([]); //BI-
const [efficiencyBI, setEfficiencyBI] = useState({}); //BI-
const [query, setQuery] = useState({ limit: 10, page: 0, projectCorrelationId: '', types: '1' }); //
const [query, setQuery] = useState({ limit: 23, page: 0, projectCorrelationId: '', types: '1' }); //
const [querydata1, setQueryData1] = useState([]); //
const [long, setLong] = useState(''); //
const [pomsList, setPomsList] = useState([]); //
@ -184,7 +183,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
newest.sort((a, b) => (moment(a.time).isBefore(b.time) ? 1 : -1))
querydata.current = [...newest, ...querydata.current]
setQueryData1([...querydata.current])
}
}, [socketData])
useEffect(() => {
@ -398,6 +397,7 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
}))
}
if (exhibition?.current?.dynamic?.find(v => v.key == 'notice')) {
// EM
res.payload.data?.notice?.map(v => data.push({
seed: 'notice',
time: v.time,
@ -444,14 +444,26 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const line = document.getElementById("line")
const news = document.getElementById("news")
if (line && news) {
news.onscroll = () => {
news.onscroll = (e) => {
e.stopPropagation();
if ((line.clientHeight - 578) < news.scrollTop + 10) {
setQuery({ ...query, page: query.page + 1 })
if (exhibition?.current?.dynamic?.length > 0) {
dispatch(control.getLatestDynamic({ ...query, projectCorrelationId: pepProjectId, page: query.page + 1 })).then(res => {
news.scrollTop = news.scrollTop - 640
// news.scrollTop = news.scrollTop - 640
let data = querydata.current
if (res.success) {
let returnJudge = true
for (let k in res.payload.data) {
if (res.payload.data[k].length) {
returnJudge = false
break
}
}
if (returnJudge) {
return
}
if (exhibition?.current?.dynamic?.find(v => v.key == 'discovery')) {
res.payload.data?.appear?.map(v => data.push({
seed: 'discovery',
@ -503,9 +515,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject = document.getElementById("news");
if (domProject) {
// newScrollbar = new PerfectScrollbar("#news", {
// suppressScrollX: true,
// });
if (domProject && newScrollbar) {
newScrollbar.update();
}
@ -513,9 +522,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const pomsList = document.getElementById("pomsList");
if (pomsList) {
// pomsListScrollbar = new PerfectScrollbar("#pomsList", {
// suppressScrollX: true,
// });
if (pomsList && pomsListScrollbar) {
pomsListScrollbar.update();
}
@ -523,9 +529,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject1 = document.getElementById("overviewCalc");
if (domProject1) {
// overviewScrollbar = new PerfectScrollbar("#overviewCalc", {
// suppressScrollY: true,
// });
if (domProject1 && overviewScrollbar) {
overviewScrollbar.update();
}
@ -533,9 +536,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject2 = document.getElementById("member");
if (domProject2) {
// memberScrollbar = new PerfectScrollbar("#member", {
// suppressScrollX: true,
// });
if (domProject2 && memberScrollbar) {
memberScrollbar.update();
}
@ -543,9 +543,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject3 = document.getElementById("equipment");
if (domProject3) {
// equipmentScrollbar = new PerfectScrollbar("#equipment", {
// suppressScrollX: true,
// });
if (domProject3 && equipmentScrollbar) {
equipmentScrollbar.update();
}
@ -553,9 +550,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject4 = document.getElementById("web");
if (domProject4) {
// webScrollbar = new PerfectScrollbar("#web", {
// suppressScrollX: true,
// })
if (domProject4 && webScrollbar) {
webScrollbar.update();
}
@ -563,9 +557,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject5 = document.getElementById("problems");
if (domProject5) {
// problemsScrollbar = new PerfectScrollbar("#problems", {
// suppressScrollX: true,
// });
if (domProject5 && problemsScrollbar) {
problemsScrollbar.update();
}
@ -573,17 +564,11 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
const domProject6 = document.getElementById("alarm");
if (domProject6) {
// alarmScrollbar = new PerfectScrollbar("#alarm", {
// suppressScrollY: true,
// });
if (domProject6 && alarmScrollbar) {
alarmScrollbar.update();
}
}
// ACTION
// dispatch(actions.example.getMembers(user.orgId))
})
const consoleToollink = () => {
@ -625,8 +610,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
let Select = {
overall: ['workbench', 'statistical', 'analyse', 'dynamic', 'tool'],
workbench: ['project', 'data', 'app', 'device'],
@ -672,8 +655,6 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
{ name: 'BI分析模块', sort: 3, key: 'analyse', },
{ name: '最新动态', sort: 4, key: 'dynamic', },
{ name: '我常用的工具', sort: 5, key: 'tool', },
]
useEffect(() => {
@ -1245,8 +1226,8 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
}} />
</div>
</div>
<div id='news' style={{ height: 578, position: 'relative', marginTop: 10, }}>
<div id='line' style={{ width: '100%' }}>
<div id='news' style={{ height: 578, position: 'relative', marginTop: 10, overscrollBehavior: 'contain', }}>
<div id='line' style={{ width: '100%', }}>
<Timeline mode="center" style={{ marginLeft: '-56px', width: 400 }}>
{querydata.current?.map((v, index) => {
let title = ''
@ -1256,8 +1237,13 @@ const Control = ({ dispatch, actions, user, history, loading, socket, pepProject
title = v.userName ? (v.userName + '确认并关闭' + v.project + '【' + v.sources + '】' + v.type + '的问题') :
v.project + '【' + v.sources + '】' + v.type + '已恢复'
} else {
title = '【信鸽-' + v.alarmPushConfig + '】已邮件通知' +
v.userName?.map((u, i) => (i > 0 ? ',' + u : u)) + '【' + v.project + '】【' +
title =
'【信鸽-' + v.alarmPushConfig + '】已邮件通知'
+
v.userName?.map((u, i) => (i > 0 ? ',' + u : u))
+ '【' + v.project
+ '】【'
+
(v.tactics == 'immediately' ?
'发现在' + v.interval + '分钟内,有告警源新增' :
(v.tactics == 'continue' ? '告警源持续产生时间超过' + v.interval + '分钟' : '异常设备数量达到项目或结构物内设备总数量的' +

4
web/client/src/sections/control/containers/userCenter.jsx

@ -16,10 +16,10 @@ const UserCenter = (props) => {
<div style={{ margin: '4px 0px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ color: '#4A4A4A', fontSize: 14 }}>
HI欢迎回来行业服务部
HI欢迎回来{user?.department[0]?.name}
</div>
<div style={{ fontFamily: 'YouSheBiaoTiHei', fontSize: 20, color: '#005ABD', marginLeft: 4 }}>
刘昊然
{user?.name}
</div>
</div>
</div>

28
web/client/src/sections/facility/containers/monitor.jsx

@ -4,7 +4,7 @@ import { connect } from 'react-redux';
const Server = (props) => {
const { dispatch, actions, user, loading, socket } = props
const { dispatch, actions, user, loading, socket, pomsMonitor } = props
useEffect(() => {
@ -13,13 +13,32 @@ const Server = (props) => {
return (
<>
<div>
<img src="/assets/images/install/watting.png" alt="" style={{ width: 'calc(100% + 16px)', position: "relative", top: -12, left: -8, }} />
<div style={{
height: 'calc(100vh - 60px)', width: 'calc(100% + 16px)',
backgroundImage: "url('/assets/images/background/General.png')",
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
position: 'relative',
top: -12, left: -8,
}}>
<div style={{ position: 'absolute', top: 'calc(50%)', left: 'calc(10%)', }}>
<div style={{
width: 184, height: 48, fontWeight: 400, color: '#FFFFFF', lineHeight: '48px', backgroundImage: "url('/assets/images/background/B.png')", textAlign: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
}}>
<a target='_blank' href={pomsMonitor}
style={{width:'100%',height:'100%',display: 'block'}}
> 进入Grafana</a>
</div>
<div style={{ width: 679, height: 40, fontSize: 28, fontWeight: 400, color: '#146AD7', lineHeight: '40px', marginTop: 40 }}>
点击可跳转服务器监控网站Grafana</div>
</div>
{/* <iframe frameBorder="0" src={pomsMonitor} style={{height: 'calc(100vh - 80px)', width: 'calc(100%)'}} /> */}
</div>
</>
)
}
function mapStateToProps (state) {
const { auth, global, members, webSocket } = state;
return {
@ -28,6 +47,7 @@ function mapStateToProps (state) {
// actions: global.actions,
// members: members.data,
// socket: webSocket.socket
pomsMonitor: global.pomsMonitor,
};
}

12
web/client/src/sections/facility/index.js

@ -6,10 +6,10 @@ import actions from './actions';
import { getNavItem } from './nav-item';
export default {
key: 'facility',
name: '设备',
reducers: reducers,
routes: routes,
actions: actions,
getNavItem: getNavItem
key: 'facility',
name: '设备',
reducers: reducers,
routes: routes,
actions: actions,
getNavItem: getNavItem
};

3
web/client/src/sections/facility/nav-item.jsx

@ -40,4 +40,5 @@ export function getNavItem (user, dispatch) {
},
]
);
}
}

2
web/client/src/sections/install/containers/system.jsx

@ -258,7 +258,7 @@ const Example = (props) => {
},
{
title: "管理",
width: "20%",
width: "150px",
dataIndex: "text",
key: 'text',
render: (_, row) => {

24
web/client/src/sections/problem/actions/problem.jsx

@ -64,10 +64,11 @@ export function postApiConfirm (data) { //确认应用接口/元素错误信
});
}
export function getAlarmDataGroup () { //
export function getAlarmDataGroup (query) { //
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query,
actionType: 'GET_ALARM_DATA_GROUP',
url: `${ApiTable.getAlarmDataGroup}`,
msg: { option: '获取数据告警分类' },
@ -138,10 +139,11 @@ export function getAlarmVideoList (query) { //查询视频告警列表
export function getAlarmVideoDeviceKind () { //
export function getAlarmVideoDeviceKind (query) { //
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query,
actionType: 'GET_ALARM_VIDEO_DEVICE_KIND',
url: `${ApiTable.getAlarmVideoDeviceKind}`,
msg: { option: '查询视频设备类型' },
@ -150,15 +152,15 @@ export function getAlarmVideoDeviceKind () { //查询视频设备类型
}
export function getAlarmVideoExceptionType () { //
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_ALARM_VIDEO_EXCEPTION_TYPE',
url: `${ApiTable.getAlarmVideoExceptionType}`,
msg: { option: '查询视频异常类型' },
reducer: { name: '' }
});
}
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_ALARM_VIDEO_EXCEPTION_TYPE',
url: `${ApiTable.getAlarmVideoExceptionType}`,
msg: { option: '查询视频异常类型' },
reducer: { name: '' }
});
}
export function putAlarmVideoConfirm (data) { //
return dispatch => basicAction({

20
web/client/src/sections/problem/components/tableData.jsx

@ -379,12 +379,23 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
placeholder={SkeletonScreen()}
>
{(() => {
// console.log(tableData);
console.log(tableData);
console.log((route == 'useAbnormal' || route == 'videoAbnormal') ?
(tableData?.slice(query.page * query.limit, (query.page + 1) * query.limit) || [])
: tableData);
return <Table
columns={exhibition}
dataSource={route == 'useAbnormal' || route == 'videoAbnormal' ? tableData.slice(query.page * query.limit, (query.page + 1) * query.limit) || [] : tableData}
dataSource={
(route == 'useAbnormal' || route == 'videoAbnormal') ?
(tableData?.slice(query.page * query.limit, (query.page + 1) * query.limit) || [])
: tableData
}
bordered={false}
empty={<div><img src="/assets/images/problem/shield.png" style={{ width: 20 }} />暂无告警数据</div>}
empty={
<div>
<img src="/assets/images/problem/shield.png" style={{ width: 20 }} />暂无告警数据
</div>
}
style={{}}
pagination={false}
onRow={(record, index) => {
@ -457,7 +468,6 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
}}
/>
</div> : ""}
@ -472,7 +482,7 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
}
function mapStateToProps(state) {
function mapStateToProps (state) {
const { auth, global, members } = state;
// console.log(global);
return {

1176
web/client/src/sections/service/components/pushModal.jsx

File diff suppressed because it is too large

1407
web/client/src/sections/service/containers/emPush.jsx

File diff suppressed because it is too large

10
web/client/src/sections/service/containers/reportManagement.jsx

@ -4,7 +4,7 @@ import { connect } from 'react-redux';
const Rest = (props) => {
const { dispatch, actions, user, loading, socket } = props
const { dispatch, actions, user, loading, socket, dcWeb } = props
useEffect(() => {
@ -13,8 +13,9 @@ const Rest = (props) => {
return (
<>
<div>
<img src="/assets/images/install/watting.png" alt="" style={{ width: 'calc(100% + 16px)', position: "relative", top: -12, left: -8, }} />
{/* style={{height: '100%', width: '100%',margin: '8px 12px', padding: '20px 20px 0px 20px'}} */}
<div >
<iframe frameBorder="0" src={`${dcWeb}/dataService/download?pcode=`} style={{ height: 'calc(100vh - 80px)', width: 'calc(100%)' }} />
</div>
</>
)
@ -27,7 +28,8 @@ function mapStateToProps (state) {
// user: auth.user,
// actions: global.actions,
// members: members.data,
// socket: webSocket.socket
// socket: webSocket.socket,
dcWeb: global.dcWeb,
};
}

8
web/config.js

@ -16,6 +16,9 @@ args.option('apiPomsUrl', 'webapi的URL 外网可访问');
args.option('apiAnxinyunUrl', '安心云 api');
args.option('apiEmisUrl', '企业管理 api');
args.option('iotVcmpWeb', 'IOT 视频服务');
args.option('pomsMonitor', '运维监控 web');
args.option('dcWeb', '报表中心web');
// 七牛
args.option('qnak', 'qiniuAccessKey');
@ -30,6 +33,8 @@ const API_POMS_URL = process.env.API_POMS_URL || flags.apiPomsUrl;
const API_EMIS_URL = process.env.API_EMIS_URL || flags.apiEmisUrl;
const API_ANXINYUN_URL = process.env.API_ANXINYUN_URL || flags.apiAnxinyunUrl;
const IOT_VIDEO_WEB = process.env.IOT_VIDEO_WEB || flags.iotVcmpWeb;
const POMS_MONITOR = process.env.POMS_MONITOR || flags.pomsMonitor;
const DC_WEB = process.env.DC_WEB || flags.dcWeb;
// 七牛
const ANXINCLOUD_QINIU_AK = process.env.ANXINCLOUD_QINIU_ACCESSKEY || flags.qnak;
@ -41,6 +46,7 @@ const ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE = process.env.ANXINCLOUD_QINIU_DOMA
if (
!API_URL
|| !API_ANXINYUN_URL
|| !POMS_MONITOR || !DC_WEB
|| !ANXINCLOUD_QINIU_AK || !ANXINCLOUD_QINIU_SK || !ANXINCLOUD_QINIU_BUCKET_RESOURCE || !ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE || !IOT_VIDEO_WEB) {
console.log('缺少启动参数,异常退出');
args.showHelp();
@ -85,6 +91,8 @@ const product = {
opts: {
apiUrl: API_POMS_URL,
iotVcmpWeb: IOT_VIDEO_WEB,
pomsMonitor: POMS_MONITOR,
dcWeb: DC_WEB,
staticRoot: './client',
qiniu: {
fetchUrl: '/_file-server',

2
web/package.json

@ -7,7 +7,7 @@
"test": "mocha",
"start-vite": "cross-env NODE_ENV=developmentVite npm run start-params",
"start": "cross-env NODE_ENV=development npm run start-params",
"start-params": "node server -p 5600 -u http://localhost:4600 --apiPomsUrl http://localhost:4600 --apiAnxinyunUrl http://10.8.30.112:4100 --apiEmisUrl http://10.8.30.112:14000 --qnak XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5 --qnsk yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa --qnbkt dev-highways4good --qndmn http://rhvqdivo5.hn-bkt.clouddn.com --iotVcmpWeb https://mediaconsole.ngaiot.com",
"start-params": "node server -p 5600 -u http://localhost:4600 --apiPomsUrl http://localhost:4600 --apiAnxinyunUrl http://10.8.30.112:4100 --apiEmisUrl http://10.8.30.112:14000 --qnak XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5 --qnsk yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa --qnbkt dev-highways4good --qndmn http://rhvqdivo5.hn-bkt.clouddn.com --iotVcmpWeb https://mediaconsole.ngaiot.com --pomsMonitor https://monitor.anxinyun.cn --dcWeb https://fsiot-oamss.anxinyun.cn",
"deploy": "export NODE_ENV=production&& npm run build && node server",
"build-dev": "cross-env NODE_ENV=development&&webpack --config webpack.config.js",
"build": "cross-env NODE_ENV=production&&webpack --config webpack.config.prod.js"

4
web/routes/attachment/index.js

@ -19,12 +19,14 @@ module.exports = {
entry: function (app, router, opts) {
const getApiRoot = async function (ctx) {
const { apiUrl, iotVcmpWeb } = opts;
const { apiUrl, iotVcmpWeb, pomsMonitor, dcWeb } = opts;
ctx.status = 200;
ctx.body = {
root: apiUrl,
iotVcmpWeb: iotVcmpWeb,
pomsMonitor: pomsMonitor,
dcWeb: dcWeb,
};
};

Loading…
Cancel
Save