巴林闲侠 2 years ago
parent
commit
a5e17f145b
  1. 3
      api/app/lib/controllers/alarm/alarmConfirmLog.js
  2. 273
      api/app/lib/controllers/control/analysis.js
  3. 7
      api/app/lib/routes/control/index.js
  4. 242
      api/app/lib/schedule/alarms_handle_statistics.js
  5. 2
      web/client/index.ejs
  6. 2
      web/client/index.html
  7. 16
      web/client/src/sections/control/actions/control.js
  8. 23
      web/client/src/sections/control/containers/control.jsx
  9. 2
      web/client/src/sections/install/containers/system.jsx
  10. 1
      web/client/src/sections/problem/components/tableData.jsx
  11. 2
      web/client/src/sections/service/actions/emPush.js
  12. 5
      web/client/src/sections/service/components/pushModal.jsx
  13. 98
      web/client/src/sections/service/containers/emPush.jsx
  14. 2
      web/client/src/sections/service/nav-item.jsx
  15. 8
      web/client/src/sections/service/style.less
  16. 4
      web/client/src/utils/webapi.js

3
api/app/lib/controllers/alarm/alarmConfirmLog.js

@ -32,7 +32,8 @@ async function alarmConfirmLog(ctx, confirmPost, content) {
}) })
await models.LatestDynamicList.bulkCreate(dynamics); await models.LatestDynamicList.bulkCreate(dynamics);
//TODO 消息推送到前端 //消息推送到前端
//ctx.app.socket.emit('TEST', { someProperty: '【广播】呼叫青铜时代号!!!', })
} catch (error) { } catch (error) {

273
api/app/lib/controllers/control/analysis.js

@ -1,7 +1,6 @@
'use strict'; 'use strict';
const moment = require('moment'); const moment = require('moment');
async function dataList (ctx) { async function dataList (ctx) {
try { try {
const { models } = ctx.fs.dc; const { models } = ctx.fs.dc;
@ -82,12 +81,12 @@ async function dataList (ctx) {
} }
} }
async function userlist (ctx) { async function personnelApp (ctx) {
try { try {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { clickHouse } = ctx.app.fs const { clickHouse } = ctx.app.fs
const sequelize = ctx.fs.dc.orm; const sequelize = ctx.fs.dc.orm;
const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api
const { pepId } = ctx.query const { pepId } = ctx.query
const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime'] const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime']
@ -202,6 +201,80 @@ async function userlist (ctx) {
}) })
} }
let findOptions = {
where: {
del: false
},
order: [['updateTime', 'desc']],
attributes: ['id', 'pepProjectId', 'name', 'anxinProjectId'],
distinct: true,
include: {
model: models.App,
}
}
if (!userInfo.role.includes('SuperAdmin') && !userInfo.role.includes('admin')) {
findOptions.where.id = { $in: userInfo.correlationProject }
}
if (pepId) {
findOption.where.id = pepId
}
const proRes = await models.ProjectCorrelation.findAndCountAll(findOptions)
let pepProjectIds = new Set()
let anxinProjectIds = new Set()
for (let p of proRes.rows) {
if (p.pepProjectId) {
pepProjectIds.add(p.pepProjectId)
}
for (let ap of p.anxinProjectId) {
if (ap) {
anxinProjectIds.add(ap)
}
}
}
const pepProjectRess = pepProjectIds.size ?
await clickHouse.projectManage.query(
`
SELECT
t_pim_project.id AS id,
t_pim_project.project_name AS project_name,
t_pim_project.isdelete AS isdelete,
t_pim_project_construction.construction_status_id AS construction_status_id,
t_pim_project_state.construction_status AS construction_status
FROM t_pim_project
LEFT JOIN t_pim_project_construction
ON t_pim_project.id = t_pim_project_construction.project_id
LEFT JOIN t_pim_project_state
ON t_pim_project_construction.construction_status_id = t_pim_project_state.id
WHERE id IN (${[...pepProjectIds].join(',')})
`
).toPromise() :
[]
for (let p of proRes.rows) {
const corPro = pepProjectRess.find(pp => pp.id == p.pepProjectId) || {}
p.dataValues.pepProjectName = corPro.project_name
p.dataValues.pepProjectIsDelete = corPro.isdelete
delete p.dataValues.anxinProjectId
}
let webApp = []
let appproRes = proRes.rows.filter(v => v.dataValues.pepProjectIsDelete != 1).map(r => {
if (r.dataValues.apps.length > 0) {
r.dataValues.apps.map(vv => {
if (webApp.map(n => n.name).indexOf(vv.dataValues.name)) {
webApp.push({ name: vv.dataValues.name, url: vv.dataValues.url })
}
})
}
})
let personnel = userRes.rows.filter(r => r.correlationProject.length > 0) let personnel = userRes.rows.filter(r => r.correlationProject.length > 0)
if (pepId) { if (pepId) {
@ -210,7 +283,8 @@ async function userlist (ctx) {
ctx.status = 200 ctx.status = 200
ctx.body = { ctx.body = {
personnel: personnel.map(v => v.dataValues.name) personnel: personnel.map(v => v.dataValues.name),
webApp: webApp
} }
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
@ -221,10 +295,197 @@ async function userlist (ctx) {
} }
} }
async function problem (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { utils: { pomsProjectRange, anxinStrucIdRange } } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
const { pepProjectId, limit = 50, page = 0 } = ctx.query
let anxinStruc = await anxinStrucIdRange({
ctx, pepProjectId
})
let pomsProject = await pomsProjectRange({
ctx, pepProjectId,
})
const pomsProjectIds = pomsProject.map(p => p.id)
let whereOption = []
if (anxinStruc.length) {
const anxinStrucIds = anxinStruc.map(a => a.strucId)
whereOption.push(`alarms.StructureId IN (${anxinStrucIds.join(",")})`)
const alarmRes = await clickHouse.dataAlarm.query(`
SELECT
AlarmId,State,AlarmGroup,AlarmGroupUnit,SourceName,StartTime,${anxinyun}.t_alarm_group_unit.name AS typeName
FROM alarms
LEFT JOIN ${anxinyun}.t_alarm_group_unit
ON ${anxinyun}.t_alarm_group_unit.id = alarms.AlarmGroupUnit
${whereOption.length ? 'WHERE ' + whereOption.join(' AND ') + ' AND ' + 'alarms.State < 3' : ''}
${limit ? 'LIMIT ' + limit : ''}
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''}
`).toPromise();
alarmRes.forEach(ar => {
switch (ar.AlarmGroup) {
case 1:
ar.groupName = '数据中断'
ar.url = '/problem/dataAlarm/dataLnterrupt'
break;
case 2:
ar.groupName = '数据异常'
ar.url = '/problem/dataAlarm/dataAbnormal'
break;
case 3:
ar.groupName = '策略命中'
ar.url = '/problem/dataAlarm/strategyHit'
break;
default:
ar.groupName = '设备异常'
ar.url = '/problem/deviceAlarm/deviceAbnormal'
break;
}
})
const video = anxinStrucIds.length ? await clickHouse.vcmp.query(
`
SELECT
cameraAlarm.cameraId AS cameraId,
cameraAlarm.cameraName AS cameraName,
cameraAlarm.alarmId AS alarmId,
cameraAlarm.createTime AS createTime,
cameraAlarm.confirmTime AS confirmTime
FROM
(
SELECT
camera.id AS cameraId,
camera.name AS cameraName,
camera_status_alarm.id AS alarmId,
camera_status_alarm.create_time AS createTime,
camera_status_alarm.platform AS platform,
camera_status_alarm.status_id AS statusId,
camera_status_alarm.serial_no AS cameraSerialNo,
camera_status_alarm.channel_no AS cameraChannelNo,
camera_status_alarm.confirm_time AS confirmTime
FROM camera_status_alarm
INNER JOIN camera
ON camera.serial_no = camera_status_alarm.serial_no
AND camera.channel_no = camera_status_alarm.channel_no
WHERE
camera.delete = false
AND camera.recycle_time is null
AND alarmId IN (
SELECT camera_status_alarm.id AS alarmId
FROM camera_status_alarm
RIGHT JOIN ${anxinyun}.t_video_ipc
ON toString(${anxinyun}.t_video_ipc.channel_no) = camera_status_alarm.channel_no
AND ${anxinyun}.t_video_ipc.serial_no = camera_status_alarm.serial_no
${`WHERE ${anxinyun}.t_video_ipc.structure IN (${anxinStrucIds.join(',')})`}
)
${limit ? 'LIMIT ' + limit : ''}
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''}
) AS cameraAlarm
LEFT JOIN camera_status
ON cameraAlarm.platform = camera_status.platform
AND cameraAlarm.statusId = camera_status.id
LEFT JOIN camera_status_resolve
ON camera_status_resolve.status_id = camera_status.id
LEFT JOIN ${anxinyun}.t_video_ipc AS anxinIpc
ON toString(anxinIpc.channel_no) = cameraAlarm.cameraChannelNo
AND anxinIpc.serial_no = cameraAlarm.cameraSerialNo
LEFT JOIN ${anxinyun}.t_video_ipc_station AS anxinIpcStation
ON anxinIpcStation.ipc = anxinIpc.id
WHERE
cameraAlarm.confirmTime is null
`
).toPromise() : []
let returnD = []
let positionD = {}
// 每个设备一个告警
for (let a of video) {
if (!positionD[a.cameraId]) {
let d = {
cameraId: a.cameraId,
SourceName: a.cameraName,
StartTime: a.createTime,
alarmId: a.alarmId,
}
returnD.push(d)
positionD[a.cameraId] = {
positionReturnD: returnD.length - 1
}
}
}
returnD.forEach(v => {
v.groupName = '视频异常'
v.url = '/problem/dataAlarm/videoAbnormal'
})
let findOption = {
where: {
'$app->projectCorrelations.id$': {
$in: pomsProjectIds
},
confirmTime: null
},
attributes: ['createTime', 'type'],
include: [{
model: models.App,
where: {
},
attributes: ['id', 'name'],
include: [{
model: models.ProjectCorrelation,
where: {
},
attributes: ['id'],
}]
}]
}
const listRes = await models.AppAlarm.findAndCountAll(findOption)
let app = listRes.rows.map(v => ({ StartTime: v.createTime, SourceName: v.app.name, type: v.type }))
let typeData = { element: '元素异常', apiError: "接口报错", timeout: '加载超时' }
app.forEach(v => {
v.groupName = '应用异常'
v.url = '/problem/useAlarm/useAbnormal',
v.typeName = typeData[v.type]
})
let sum = [...alarmRes, ...returnD, ...app]
sum.sort((a, b) => {
if (moment(a.StartTime).isBefore(b.StartTime)) {
return 1
} else {
return -1
}
})
ctx.status = 200;
ctx.body = sum
} else {
ctx.body =[]
}
ctx.status = 200;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`)
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = { module.exports = {
dataList, dataList,
userlist personnelApp,
}; problem
}

7
api/app/lib/routes/control/index.js

@ -20,8 +20,11 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/analysis/dataList'] = { content: '查询数据告警产生,确认数量', visible: true }; app.fs.api.logAttr['GET/analysis/dataList'] = { content: '查询数据告警产生,确认数量', visible: true };
router.get('/analysis/dataList', analysis.dataList); router.get('/analysis/dataList', analysis.dataList);
app.fs.api.logAttr['GET/analysis/userlist'] = { content: '查询关联人员', visible: true }; app.fs.api.logAttr['GET/analysis/userlist'] = { content: '查询关联人员,web应用', visible: true };
router.get('/analysis/userlist', analysis.userlist); router.get('/analysis/userlist', analysis.personnelApp);
app.fs.api.logAttr['GET/analysis/problem'] = { content: '查询异常&问题', visible: true };
router.get('/analysis/problem', analysis.problem);
//BI分析模块 //BI分析模块

242
api/app/lib/schedule/alarms_handle_statistics.js

@ -7,27 +7,27 @@ module.exports = function (app, opts) {
const { database: anxinyun } = clickHouse.anxinyun.opts.config const { database: anxinyun } = clickHouse.anxinyun.opts.config
const alarmHandleStatistics = app.fs.scheduleInit( const alarmHandleStatistics = app.fs.scheduleInit(
{ {
interval: '0 58 9 * * *', interval: '0 48 1 ? * MON',//0 48 1 ? * MON 每周一凌晨1点48开始执行
// immediate: true, // immediate: true,
//proRun: true, proRun: true,
}, },
async () => { async () => {
try { try {
let anxinStruc = await getAxyStructs() let anxinStruc = await getAxyStructs()
let pomsProject = await pomsProjectRange() let pomsProject = await pomsProjectRange()
if (anxinStruc.length) { if (anxinStruc.length) {
let dataAlarms = await getDataAlarms(anxinStruc);//数据告警 let { dataSum, dataMaps } = await getDataAlarms(anxinStruc);//数据告警
let appAlarms = await getAppAlarms(pomsProject);//应用告警 let appAlarms = await getAppAlarms(pomsProject);//应用告警
let videoAlarms = await getVideoAlarms(anxinStruc);//视频告警 let videoAlarms = await getVideoAlarms(anxinStruc);//视频告警
let time = moment().format() let time = moment().format()
//算全局 //算全局
let dataArrToSave = [] //let dataArrToSave = []
let dataMap = calculate(dataAlarms, appAlarms, videoAlarms) let dataMap = calculate(dataMaps, appAlarms, videoAlarms)
let sum = dataAlarms.length + appAlarms.length + videoAlarms.length; let sum = dataSum + appAlarms.length + videoAlarms.length;
if (sum) { if (sum) {
dataArrToSave.push({ let data = {
time: time, time: time,
projectCorrelationId: null,//全局 projectCorrelationId: null,//全局
day1: parseFloat((100 * dataMap.day1 / sum).toFixed(2)), day1: parseFloat((100 * dataMap.day1 / sum).toFixed(2)),
@ -36,32 +36,60 @@ module.exports = function (app, opts) {
day15: parseFloat((100 * dataMap.day15 / sum).toFixed(2)), day15: parseFloat((100 * dataMap.day15 / sum).toFixed(2)),
day30: parseFloat((100 * dataMap.day30 / sum).toFixed(2)), day30: parseFloat((100 * dataMap.day30 / sum).toFixed(2)),
day30m: parseFloat((100 * dataMap.day30m / sum).toFixed(2)), day30m: parseFloat((100 * dataMap.day30m / sum).toFixed(2)),
}) }
await models.AlarmHandleStatistics.create(data)
} }
//算单个项目 //算单个项目
pomsProject.map(p => { pomsProject.map(async p => {
let pid = p.id; let pid = p.id;
let pDataAlarms = dataAlarms.filter(da => da.pomsProject.indexOf(pid) != -1) //let pid = 11
let pAppAlarms = appAlarms.filter(aa => aa.app.projectCorrelations.map(ap => ap.id).indexOf(pid) != -1) let pAnxinStruc = await getAxyStructs(pid)
let pVideoAlarms = videoAlarms.filter(va => va.pomsProject.indexOf(pid) != -1) let pPomsProject = await pomsProjectRange(pid)
if (pAnxinStruc.length) {
let pDataMap = calculate(pDataAlarms, pAppAlarms, pVideoAlarms) let { dataSum, dataMaps } = await getDataAlarms(pAnxinStruc);//数据告警
let sm = pDataAlarms.length + pAppAlarms.length + pVideoAlarms.length; let pAppAlarms = await getAppAlarms(pPomsProject);//应用告警
if (sm) { let pVideoAlarms = await getVideoAlarms(pAnxinStruc);//视频告警
dataArrToSave.push({ let pDataMap = calculate(dataMaps, pAppAlarms, pVideoAlarms)
time: time, let sm = dataSum + pAppAlarms.length + pVideoAlarms.length;
projectCorrelationId: pid,//单个项目 if (sm) {
day1: parseFloat((100 * pDataMap.day1 / sum).toFixed(2)), let data = {
day3: parseFloat((100 * pDataMap.day3 / sum).toFixed(2)), time: time,
day7: parseFloat((100 * pDataMap.day7 / sum).toFixed(2)), projectCorrelationId: pid,//单个项目
day15: parseFloat((100 * pDataMap.day15 / sum).toFixed(2)), day1: parseFloat((100 * pDataMap.day1 / sm).toFixed(2)),
day30: parseFloat((100 * pDataMap.day30 / sum).toFixed(2)), day3: parseFloat((100 * pDataMap.day3 / sm).toFixed(2)),
day30m: parseFloat((100 * pDataMap.day30m / sum).toFixed(2)), day7: parseFloat((100 * pDataMap.day7 / sm).toFixed(2)),
}) day15: parseFloat((100 * pDataMap.day15 / sm).toFixed(2)),
day30: parseFloat((100 * pDataMap.day30 / sm).toFixed(2)),
day30m: parseFloat((100 * pDataMap.day30m / sm).toFixed(2)),
}
await models.AlarmHandleStatistics.create(data)
}
} }
}) })
await models.AlarmHandleStatistics.bulkCreate(dataArrToSave) //算单个项目
// pomsProject.map(p => {
// let pid = p.id;
// let pDataAlarms = dataAlarms.filter(da => da.pomsProject.indexOf(pid) != -1)
// let pAppAlarms = appAlarms.filter(aa => aa.app.projectCorrelations.map(ap => ap.id).indexOf(pid) != -1)
// let pVideoAlarms = videoAlarms.filter(va => va.pomsProject.indexOf(pid) != -1)
// let pDataMap = calculate(pDataAlarms, pAppAlarms, pVideoAlarms)
// let sm = pDataAlarms.length + pAppAlarms.length + pVideoAlarms.length;
// if (sm) {
// dataArrToSave.push({
// time: time,
// projectCorrelationId: pid,//单个项目
// day1: parseFloat((100 * pDataMap.day1 / sum).toFixed(2)),
// day3: parseFloat((100 * pDataMap.day3 / sum).toFixed(2)),
// day7: parseFloat((100 * pDataMap.day7 / sum).toFixed(2)),
// day15: parseFloat((100 * pDataMap.day15 / sum).toFixed(2)),
// day30: parseFloat((100 * pDataMap.day30 / sum).toFixed(2)),
// day30m: parseFloat((100 * pDataMap.day30m / sum).toFixed(2)),
// })
// }
// })
//await models.AlarmHandleStatistics.bulkCreate(dataArrToSave)
} }
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -69,33 +97,34 @@ module.exports = function (app, opts) {
} }
) )
function calculate(dataAlarms, appAlarms, videoAlarms) { function calculate(dataMaps, appAlarms, videoAlarms) {
try { try {
let { day1, day3, day7, day15, day30, day30m } = dataMaps;
//算全局 //算全局
let dataMap = { let dataMap = {
day1: 0,//当日处理 day1: day1[0].count,//当日处理
day3: 0,//3日内 day3: day3[0].count,//3日内
day7: 0,//7日内 day7: day7[0].count,//7日内
day15: 0,//15日内 day15: day15[0].count,//15日内
day30: 0,//30日内 day30: day30[0].count,//30日内
day30m: 0//超过30日 day30m: day30m[0].count//超过30日
} }
dataAlarms.filter(d => d.State > 3).map(da => { // dataAlarms.filter(d => d.State > 3).map(da => {
let range = moment(da.confirmTime).diff(moment(da.StartTime), 'day') // let range = moment(da.confirmTime).diff(moment(da.StartTime), 'day')
if (range <= 1) { // if (range <= 1) {
dataMap.day1++ // dataMap.day1++
} else if (range > 1 && range <= 3) { // } else if (range > 1 && range <= 3) {
dataMap.day3++ // dataMap.day3++
} else if (range > 3 && range <= 7) { // } else if (range > 3 && range <= 7) {
dataMap.day7++ // dataMap.day7++
} else if (range > 7 && range <= 15) { // } else if (range > 7 && range <= 15) {
dataMap.day15++ // dataMap.day15++
} else if (range > 15 && range <= 30) { // } else if (range > 15 && range <= 30) {
dataMap.day30++ // dataMap.day30++
} else if (range > 30) { // } else if (range > 30) {
dataMap.day30m++ // dataMap.day30m++
} // }
}) // })
appAlarms.filter(d => d.confirmTime).map(da => { appAlarms.filter(d => d.confirmTime).map(da => {
let range = moment(da.confirmTime).diff(moment(da.createTime), 'day') let range = moment(da.confirmTime).diff(moment(da.createTime), 'day')
if (range < 1) { if (range < 1) {
@ -134,6 +163,17 @@ module.exports = function (app, opts) {
} }
} }
function getStr(alarmQueryOptionStr, paramStr) {
return `
select count(AlarmId) count from
(SELECT
alarms.AlarmId AS AlarmId,
alarms.State AS State,
alarms.StructureId AS StructureId,
StartTime, EndTime
${alarmQueryOptionStr}) where State>3 and ${paramStr}`
}
async function getDataAlarms(anxinStruc) { async function getDataAlarms(anxinStruc) {
try { try {
const anxinStrucIds = anxinStruc.map(a => a.strucId) const anxinStrucIds = anxinStruc.map(a => a.strucId)
@ -151,42 +191,61 @@ module.exports = function (app, opts) {
console.log('开始查数据-数据-数据类告警---' + moment().format('YYYY-MM-DD HH:mm:ss')) console.log('开始查数据-数据-数据类告警---' + moment().format('YYYY-MM-DD HH:mm:ss'))
const alarmRes = await clickHouse.dataAlarm.query(` const alarmRes = await clickHouse.dataAlarm.query(`
SELECT select count(AlarmId) count from
(SELECT
alarms.AlarmId AS AlarmId, alarms.AlarmId AS AlarmId,
alarms.State AS State, alarms.State AS State,
alarms.StructureId AS StructureId, alarms.StructureId AS StructureId,
StartTime, EndTime StartTime, EndTime
${alarmQueryOptionStr}`).toPromise(); ${alarmQueryOptionStr})`).toPromise();
console.log('数据-数据-数据告警查询结束---' + moment().format('YYYY-MM-DD HH:mm:ss') + `---一共${alarmRes.length}`)
const confirmedAlarm = alarmRes.filter(ar => ar.State && ar.State > 2).map(ar => "'" + ar.AlarmId + "'");
const confirmedAlarmDetailMax = confirmedAlarm.length ?
await clickHouse.dataAlarm.query(`
SELECT
max(Time) AS Time, AlarmId
FROM
alarm_details
WHERE
AlarmId IN (${confirmedAlarm.join(',')})
GROUP BY AlarmId
`).toPromise() : [];
alarmRes.forEach(ar => {
ar.pomsProject = (
anxinStruc.find(as => as.strucId == ar.StructureId) ||
{
pomsProject: [
// TODO: 开发临时添加
]
}
).pomsProject.map(p => p.id)
// 最新告警详情 - 确认信息 let day1Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)<=1');
let corConfirmedData = (confirmedAlarmDetailMax.find(cdm => cdm.AlarmId == ar.AlarmId) || {}); let day1 = await clickHouse.dataAlarm.query(day1Str).toPromise();
ar.confirmTime = corConfirmedData.Time || ar.EndTime
}) let day3Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)>1 and Date(EndTime) - Date(StartTime)<=3');
return alarmRes; let day3 = await clickHouse.dataAlarm.query(day3Str).toPromise();
let day7Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)>3 and Date(EndTime) - Date(StartTime)<=7');
let day7 = await clickHouse.dataAlarm.query(day7Str).toPromise();
let day15Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)>7 and Date(EndTime) - Date(StartTime)<=15');
let day15 = await clickHouse.dataAlarm.query(day15Str).toPromise();
let day30Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)>15 and Date(EndTime) - Date(StartTime)<=30');
let day30 = await clickHouse.dataAlarm.query(day30Str).toPromise();
let day30mStr = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)>30');
let day30m = await clickHouse.dataAlarm.query(day30mStr).toPromise();
// console.log('数据-数据-数据告警查询结束---' + moment().format('YYYY-MM-DD HH:mm:ss') + `---一共${alarmRes.length}条`)
// const confirmedAlarm = alarmRes.filter(ar => ar.State && ar.State > 2).map(ar => "'" + ar.AlarmId + "'");
// const confirmedAlarmDetailMax = confirmedAlarm.length ?
// await clickHouse.dataAlarm.query(`
// SELECT
// max(Time) AS Time, AlarmId
// FROM
// alarm_details
// WHERE
// AlarmId IN (${confirmedAlarm.join(',')})
// GROUP BY AlarmId
// `).toPromise() : [];
// alarmRes.forEach(ar => {
// ar.pomsProject = (
// anxinStruc.find(as => as.strucId == ar.StructureId) ||
// {
// pomsProject: [
// // TODO: 开发临时添加
// ]
// }
// ).pomsProject.map(p => p.id)
// // 最新告警详情 - 确认信息
// let corConfirmedData = (confirmedAlarmDetailMax.find(cdm => cdm.AlarmId == ar.AlarmId) || {});
// ar.confirmTime = corConfirmedData.Time || ar.EndTime
// })
return { dataSum: alarmRes[0].count, dataMaps: { day1, day3, day7, day15, day30, day30m } };
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -318,9 +377,9 @@ module.exports = function (app, opts) {
console.error(error); console.error(error);
} }
} }
async function pomsProjectRange() { async function pomsProjectRange(pepProjectId) {
try { try {
const { pepProjectRes, bindRes } = await pomsWithPepRangeParams() const { pepProjectRes, bindRes } = await pomsWithPepRangeParams(pepProjectId)
let pomsProject = [] let pomsProject = []
for (let b of bindRes) { for (let b of bindRes) {
if (b.pepProjectId) { if (b.pepProjectId) {
@ -341,9 +400,18 @@ module.exports = function (app, opts) {
} }
} }
async function pomsWithPepRangeParams() { async function pomsWithPepRangeParams(pepProjectId) {
try { try {
const bindRes = await models.ProjectCorrelation.findAll({ where: { del: false } }); let findOption = {
where: {
del: false
}
}
if (pepProjectId) {
// 有 特定的项目id 就按此查询
findOption.where.id = pepProjectId
}
const bindRes = await models.ProjectCorrelation.findAll(findOption);
// 获取不重复的 项企项目id // 获取不重复的 项企项目id
let pepProjectIds = [] let pepProjectIds = []
for (let b of bindRes) { for (let b of bindRes) {
@ -379,9 +447,9 @@ module.exports = function (app, opts) {
} }
} }
async function getAxyStructs() { async function getAxyStructs(pepProjectId) {
try { try {
const { pepProjectRes, bindRes } = await pomsWithPepRangeParams() const { pepProjectRes, bindRes } = await pomsWithPepRangeParams(pepProjectId)
// 获取不重复的 安心云项目 id // 获取不重复的 安心云项目 id
const anxinProjectIds = [ const anxinProjectIds = [
...(bindRes).reduce( ...(bindRes).reduce(

2
web/client/index.ejs

@ -11,7 +11,7 @@
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></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>LA.init({ id: "Jo4eTlZVqgx3uwqm", ck: "Jo4eTlZVqgx3uwqm" })</script>
<script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_10.1efd80a22a5e53e48737fd5ab150ffd2.es5.js"></script> <script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.559b91c217b8ddc76c0c4b1397d84d48.es5.js"></script>
</head> </head>
<body> <body>

2
web/client/index.html

@ -11,7 +11,7 @@
<script>LA.init({ id: "Jo4eTlZVqgx3uwqm", ck: "Jo4eTlZVqgx3uwqm" })</script> <script>LA.init({ id: "Jo4eTlZVqgx3uwqm", ck: "Jo4eTlZVqgx3uwqm" })</script>
<script <script
src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.27aacefc59cea1cbc86236576463a6d2.es5.js"></script> src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.559b91c217b8ddc76c0c4b1397d84d48.es5.js"></script>
</head > </head >
<body> <body>

16
web/client/src/sections/control/actions/control.js

@ -35,14 +35,26 @@ export function deleteConsoleToollink (orgId) { //删除常用工具
}); });
} }
export function geteteConsoleCount (query) { //工作台数量查询 export function getConsoleCount (query) { //工作台数量查询
return dispatch => basicAction({ return dispatch => basicAction({
type: 'get', type: 'get',
dispatch: dispatch, dispatch: dispatch,
query, query,
actionType: 'GET_CONSLE_COUNT', actionType: 'GET_CONSLE_COUNT',
url: `${ApiTable.geteteConsoleCount}`, url: `${ApiTable.getConsoleCount}`,
msg: { option: '工作台数量查询' }, msg: { option: '工作台数量查询' },
reducer: { name: '' } reducer: { name: '' }
}); });
}
export function getConsoleAbnormal (query) { //项目概览异常查询
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query,
actionType: 'GET_CONSLE_ABNORMAL',
url: `${ApiTable.getConsoleAbnormal}`,
msg: { option: '项目概览异常查询' },
reducer: { name: '' }
});
} }

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

@ -63,9 +63,13 @@ const Control = (props) => {
}, []) }, [])
useEffect(() => { useEffect(() => {
dispatch(control.geteteConsoleCount({ pepProjectId: pepProjectId })).then(res => { dispatch(control.getConsoleCount({ pepProjectId: pepProjectId })).then(res => {
if (res.success) setWorkData(res.payload.data) if (res.success) setWorkData(res.payload.data)
}) })
dispatch(control.getConsoleAbnormal({ pepProjectId: pepProjectId })).then(res => {
console.log(res.payload.data);
if (res.success) setProblemsList([...res.payload.data,...res.payload.data])
})
}, [pepProjectId]) }, [pepProjectId])
useEffect(() => { useEffect(() => {
@ -145,7 +149,6 @@ const Control = (props) => {
// dispatch(actions.example.getMembers(user.orgId)) // dispatch(actions.example.getMembers(user.orgId))
}) })
const consoleToollink = () => { const consoleToollink = () => {
dispatch(control.getConsoleToollink()).then(res => { dispatch(control.getConsoleToollink()).then(res => {
if (res.success) setToolShow(res.payload.data) if (res.success) setToolShow(res.payload.data)
@ -177,13 +180,13 @@ const Control = (props) => {
{ name: '关联web应用', sort: 4, key: 'web', }, { name: '关联web应用', sort: 4, key: 'web', },
{ name: '异常&问题', sort: 5, key: 'problem', }, { name: '异常&问题', sort: 5, key: 'problem', },
{ name: '数据中断', sort: 5, key: 'dataInterrupt', }, { name: '数据中断', sort: 1, key: 'dataInterrupt', },
{ name: '数据异常', sort: 5, key: 'dataAnomaly', }, { name: '数据异常', sort: 2, key: 'dataAnomaly', },
{ name: '策略命中', sort: 5, key: 'strategyHit', }, { name: '策略命中', sort: 3, key: 'strategyHit', },
{ name: '视频异常', sort: 5, key: 'videoException', }, { name: '视频异常', sort: 4, key: 'videoException', },
{ name: '应用异常', sort: 5, key: 'appAbnormal', }, { name: '应用异常', sort: 5, key: 'appAbnormal', },
{ name: '设备异常', sort: 5, key: 'unitException', }, { name: '设备异常', sort: 6, key: 'unitException', },
{ name: '问题处置效率分析', sort: 5, key: 'problemAnalysis', }, { name: '问题处置效率分析', sort: 7, key: 'problemAnalysis', },
] ]
useEffect(() => { useEffect(() => {
@ -202,12 +205,11 @@ const Control = (props) => {
TableDisplay.sort((a, b) => a.sort - b.sort) TableDisplay.sort((a, b) => a.sort - b.sort)
exhibition.current = { ...exhibition.current, [title]: TableDisplay } exhibition.current = { ...exhibition.current, [title]: TableDisplay }
setTableSetup([{ list: data }]) setTableSetup([{ list: data }])
} }
return ( return (
11 ? <img src="/assets/images/install/watting.png" alt="" style={{ width: 'calc(100% + 16px)', position: "relative", top: -12, left: -8, }} /> : // 11 ? <img src="/assets/images/install/watting.png" alt="" style={{ width: 'calc(100% + 16px)', position: "relative", top: -12, left: -8, }} /> :
<> <>
<div style={{ padding: '0px 40px', width: '100%' }} className='console'> <div style={{ padding: '0px 40px', width: '100%' }} className='console'>
{/* 头部 */} {/* 头部 */}
@ -516,7 +518,6 @@ const Control = (props) => {
</div> </div>
<div style={{ width: '100%', height: '100%' }}> <div style={{ width: '100%', height: '100%' }}>
{exhibition.current?.analyse?.map((v, index) => { {exhibition.current?.analyse?.map((v, index) => {
console.log(exhibition.current?.analyse);
return <div id={'ReactECharts' + index} style={{ marginTop: 20, padding: 10, width: '50%', display: "inline-block" }}> return <div id={'ReactECharts' + index} style={{ marginTop: 20, padding: 10, width: '50%', display: "inline-block" }}>
<ReactECharts <ReactECharts
option={{ option={{

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

@ -273,7 +273,7 @@ const Example = (props) => {
修改 修改
</Button> </Button>
<Popconfirm <Popconfirm
title="删除后对应的项目全局将无法进入和显示,对应的信鸽服务也会被禁用" title="删除后对应的项目全局将无法进入和显示,对应的信鸽服务也会被删除"
arrowPointAtCenter={false} arrowPointAtCenter={false}
showArrow={true} showArrow={true}
position="topRight" position="topRight"

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

@ -87,7 +87,6 @@ const TableData = ({ route, dispatch, actions, collectData, setSetup, exhibition
default: default:
dispatch(problem.getAlarmDataGroup()).then((res) => { dispatch(problem.getAlarmDataGroup()).then((res) => {
if (res.success) { if (res.success) {
let routeData = { dataLnterrupt: '数据中断', dataAbnormal: '数据异常', strategyHit: '策略命中', deviceAbnormal: '' }
let data let data
if (route == 'dataLnterrupt') data = res.payload.data?.filter(v => v.desc == '数据中断') if (route == 'dataLnterrupt') data = res.payload.data?.filter(v => v.desc == '数据中断')
if (route == 'dataAbnormal') data = res.payload.data?.filter(v => v.desc == '数据异常') if (route == 'dataAbnormal') data = res.payload.data?.filter(v => v.desc == '数据异常')

2
web/client/src/sections/service/actions/emPush.js

@ -10,7 +10,7 @@ export function getPush (query) { //获取推送配置列表
actionType: 'GET_PUSH', actionType: 'GET_PUSH',
url: `${ApiTable.getPush}`, url: `${ApiTable.getPush}`,
msg: { error: '获取推送配置列表失败' }, msg: { error: '获取推送配置列表失败' },
reducer: { name: '' } reducer: { name: "getPush", params: { noClear: true } },
}); });
} }

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

@ -224,7 +224,7 @@ function pushModal (props) {
}) })
} }
} }
dispatch(service.postPush({ pushId: pushId, ...obj, msg: '编辑推送配置' })).then((res) => {//(PEP) dispatch(service.postPush({ pushId: editObj.id, ...obj, msg: '编辑推送配置' })).then((res) => {//(PEP)
if (res.success) { if (res.success) {
close(); close();
} }
@ -378,7 +378,6 @@ function pushModal (props) {
labelAlign="right" labelAlign="right"
labelWidth="120px" labelWidth="120px"
onValueChange={(values, field) => { onValueChange={(values, field) => {
console.log('values', values);
for (var key in field) { for (var key in field) {
if (key == 'tactics') { if (key == 'tactics') {
if (values.tactics == 'abnormal_rate') { if (values.tactics == 'abnormal_rate') {
@ -567,7 +566,7 @@ function pushModal (props) {
placeholder="请选择通知时效" placeholder="请选择通知时效"
style={{ width: 285 }} style={{ width: 285 }}
rules={[{ required: true, message: "请选择通知时效" }]} rules={[{ required: true, message: "请选择通知时效" }]}
initValue={editObj?.timeType.length > 0 ? editObj?.timeType : timeTypePOMS.current} initValue={editObj?.timeType?.length > 0 ? editObj?.timeType : timeTypePOMS.current}
disabled={timeTypeDis} disabled={timeTypeDis}
multiple multiple
maxTagCount={3} maxTagCount={3}

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

@ -7,7 +7,6 @@ import moment from "moment";
import PushModal from '../components/pushModal' import PushModal from '../components/pushModal'
import '../style.less' import '../style.less'
import { Setup } from "$components"; import { Setup } from "$components";
// import { set } from 'nprogress';
const EmPush = (props) => { const EmPush = (props) => {
const form = useRef();// const form = useRef();//
@ -15,22 +14,13 @@ const EmPush = (props) => {
const { service } = actions; const { service } = actions;
const [setup, setSetup] = useState(false); // const [setup, setSetup] = useState(false); //
const [setupp, setSetupp] = useState([]);// const [setupp, setSetupp] = useState([]);//
const [tableSetup, setTableSetup] = useState([]); //
const [query, setQuery] = useState({ limit: 10, page: 0 }); // const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [limits, setLimits] = useState()// const [limits, setLimits] = useState()//
const mylimits = useRef(); // const mylimits = useRef(); //
const [pushModal, setPushModal] = useState(false) // const [pushModal, setPushModal] = useState(false) //
const [pushEdit, setPushEdit] = useState(false) // const [pushEdit, setPushEdit] = useState(false) //
const [anxincloudList, setAnxincloudList] = useState([]) // const [change, setChange] = useState(false) //
const [peplist, setPeplist] = useState([]) //PEP const [allTableData, setAllTableData] = useState([]) //
const [appList, setAppList] = useState([]) //
const [pepProjectId, setPepProjectId] = useState() //id
const [anxincloudArr, setAnxincloudArr] = useState([]) //
const [pepname, setPepname] = useState() //
const [anxinDelete, setAnxinDelete] = useState([]) //,
const [appArr, setAppArr] = useState([]) //
const [bindId, setBindId] = useState() //id
const [tableKey, setTableKey] = useState([]) //id
const [editObj, setEditObj] = useState({});// const [editObj, setEditObj] = useState({});//
const [projectStatus, setProjectStatus] = useState([]); // const [projectStatus, setProjectStatus] = useState([]); //
const page = useRef(query.page);// const page = useRef(query.page);//
@ -82,16 +72,6 @@ const EmPush = (props) => {
const [tableData, setTableData] = useState([]) // const [tableData, setTableData] = useState([]) //
useEffect(() => { useEffect(() => {
// dispatch(service.getPush(query)).then((res) => {//
// console.log('res.payload.datares.payload.data',res.payload.data);
// setAnxincloudList(res.payload.data)
// })
// dispatch(install.getProjectPmanage(query)).then((res) => {//PEP
// setPeplist(res.payload.data)
// })
// dispatch(install.getProjectAppList(query)).then((res) => {//
// setAppList(res.payload.data)
// })
localStorage.getItem(EMPUSH) == null localStorage.getItem(EMPUSH) == null
? localStorage.setItem( ? localStorage.setItem(
EMPUSH, EMPUSH,
@ -99,23 +79,28 @@ const EmPush = (props) => {
) )
: ""; : "";
getProjectStatusList() getProjectStatusList()
getPushList(query);
}, []) }, [])
useEffect(() => { useEffect(() => {
getPushList(); let showTableData = JSON.parse(JSON.stringify(allTableData)).slice(query.page * query.limit, (query.page + 1) * query.limit)
}, [query]); setTableData(showTableData)
mylimits.current = showTableData.length
}, [change]);
function getPushList () { function getPushList (query) {
let val = form.current.getValues() let val = form.current.getValues()
// , ...query
dispatch(service.getPush({ ...val })).then((res) => {// dispatch(service.getPush({ ...val })).then((res) => {//
if (res.success) { if (res.success) {
let mytableData = JSON.parse(JSON.stringify(res.payload.data)); let mytableData = JSON.parse(JSON.stringify(res.payload.data));
for (let index = 0; index < mytableData.length; index++) { for (let index = 0; index < mytableData.length; index++) {
mytableData[index].key = String(mytableData[index].id) mytableData[index].key = String(mytableData[index].id)
} }
setTableData(mytableData) setAllTableData(mytableData)
let showTableData = mytableData.slice(query.page * query.limit, (query.page + 1) * query.limit)
setTableData(showTableData)
setQuery(query)
setLimits(res.payload.data.length) setLimits(res.payload.data.length)
mylimits.current = res.payload.data.length mylimits.current = showTableData.length
} }
}) })
} }
@ -138,37 +123,9 @@ const EmPush = (props) => {
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<Button <Button
theme="borderless" theme="borderless"
// disabled={row.pepProjectIsDelete == 1}
onClick={() => { onClick={() => {
setEditObj(row) setEditObj(row)
setPushModal(true); setPushModal(true);
// setPepname(row.name)
// if (!row.name) {
// setPepProjectId(row.pepProjectId)
// }
// else {
// setPepProjectId()
// }
// let myanxinArr = []
// let anxinErrorList = []
// for (let i = 0; i < row.anxinProject.length; i++) {
// if (row.anxinProject[i].projectState !== -1) {
// myanxinArr.push(row.anxinProject[i].id)
// }
// else {
// anxinErrorList.push(row.anxinProject[i].name)
// }
// }
// setAnxinDelete(anxinErrorList)
// let myapparr = []
// let myarrarrList = JSON.parse(JSON.stringify(row.apps))
// for (let j = 0; j < row.apps.length; j++) {
// delete myarrarrList[j].projectApp
// myapparr.push(JSON.stringify(myarrarrList[j]))
// }
// setAppArr(myapparr)
// setAnxincloudArr(myanxinArr)
// setBindId(row.id)
setPushEdit(true) setPushEdit(true)
}} }}
> >
@ -180,7 +137,7 @@ const EmPush = (props) => {
style={{ color: '#F31C1C' }} style={{ color: '#F31C1C' }}
onClick={() => { onClick={() => {
dispatch(service.putPushPushId({ pushId: row?.id, del: false, disable: false, msg: '更改推送配置状态' })).then(() => { dispatch(service.putPushPushId({ pushId: row?.id, del: false, disable: false, msg: '更改推送配置状态' })).then(() => {
// setQuery({ limit: 10, page: page.current }) getPushList({ limit: query.limit, page: page.current });
}) })
}} }}
> >
@ -194,7 +151,7 @@ const EmPush = (props) => {
position="topRight" position="topRight"
onConfirm={() => { onConfirm={() => {
dispatch(service.putPushPushId({ pushId: row?.id, del: false, disable: true, msg: '更改推送配置状态' })).then(() => { dispatch(service.putPushPushId({ pushId: row?.id, del: false, disable: true, msg: '更改推送配置状态' })).then(() => {
// setQuery({ limit: 10, page: page.current }) getPushList({ limit: query.limit, page: page.current });
}) })
}} }}
> >
@ -208,11 +165,11 @@ const EmPush = (props) => {
position="topRight" position="topRight"
onConfirm={() => { onConfirm={() => {
dispatch(service.putPushPushId({ pushId: row?.id, del: true, disable: false, msg: '删除推送配置' })).then(() => { dispatch(service.putPushPushId({ pushId: row?.id, del: true, disable: false, msg: '删除推送配置' })).then(() => {
// if (page.current > 0 && mylimits.current < 2) { if (page.current > 0 && mylimits.current < 2) {
// setQuery({ limit: 10, page: page.current - 1 }) getPushList({ limit: query.limit, page: page.current - 1 });
// } else { } else {
// setQuery({ limit: 10, page: page.current }) getPushList({ limit: query.limit, page: page.current });
// } }
}) })
}} }}
> >
@ -577,7 +534,6 @@ const EmPush = (props) => {
<div style={{ marginRight: 20, display: 'flex', alignItems: 'center' }} className='myempush'> <div style={{ marginRight: 20, display: 'flex', alignItems: 'center' }} className='myempush'>
<Form <Form
onSubmit={(values) => console.log(values)} onSubmit={(values) => console.log(values)}
// onValueChange={values=>console.log(values)}
getFormApi={(formApi) => (form.current = formApi)} getFormApi={(formApi) => (form.current = formApi)}
layout="horizontal" layout="horizontal"
style={{ position: "relative", width: "100%", flex: 1 }} style={{ position: "relative", width: "100%", flex: 1 }}
@ -644,7 +600,7 @@ const EmPush = (props) => {
border: '1px solid #005ABD' border: '1px solid #005ABD'
}} }}
onClick={() => { onClick={() => {
getPushList() getPushList({ limit: query.limit, page: 0 })
}} }}
> >
查询 查询
@ -662,6 +618,7 @@ const EmPush = (props) => {
marginLeft: 32 marginLeft: 32
}} }}
onClick={() => { onClick={() => {
setEditObj({})
setPushModal(true); setPushModal(true);
setPushEdit(false); setPushEdit(false);
}} }}
@ -675,8 +632,8 @@ const EmPush = (props) => {
</div> </div>
<div style={{ marginTop: 20 }}> <div style={{ marginTop: 20 }}>
<Skeleton <Skeleton
// loading={loading} loading={loading}
loading={false} // loading={false}
active={true} active={true}
placeholder={SkeletonScreen()} placeholder={SkeletonScreen()}
> >
@ -714,6 +671,7 @@ const EmPush = (props) => {
onChange={(currentPage, pageSize) => { onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 }); setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1 page.current = currentPage - 1
setChange(!change)
}} }}
/> />
</div> </div>
@ -731,7 +689,7 @@ const EmPush = (props) => {
}} }}
close={() => { close={() => {
setPushModal(false); setPushModal(false);
getPushList() getPushList(query)
}} > }} >
</PushModal> : '' </PushModal> : ''
} }
@ -752,9 +710,9 @@ const EmPush = (props) => {
} }
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth, global, ProjectPoms } = state; const { auth, global, getPush } = state;
return { return {
// loading: ProjectPoms.isRequesting, loading: getPush.isRequesting,
user: auth.user, user: auth.user,
actions: global.actions, actions: global.actions,
// members: members.data, // members: members.data,

2
web/client/src/sections/service/nav-item.jsx

@ -30,7 +30,7 @@ export function getNavItem (user, dispatch) {
}, { }, {
itemKey: 'carrierPigeon', itemKey: 'carrierPigeon',
text: '信鸽服务', text: '信鸽服务',
icon: <iconpark-icon style={{ width: 20, height: 20 }} name="iconjianshezhong"></iconpark-icon>, icon: <iconpark-icon style={{ width: 20, height: 20 }} name="xingefuwu"></iconpark-icon>,
to: '/service/carrierPigeon/emPush', to: '/service/carrierPigeon/emPush',
items: [{ items: [{
itemKey: 'emPush', to: '/service/carrierPigeon/emPush', text: 'EM推送' itemKey: 'emPush', to: '/service/carrierPigeon/emPush', text: 'EM推送'

8
web/client/src/sections/service/style.less

@ -2,12 +2,4 @@
.semi-input-wrapper{ .semi-input-wrapper{
margin-bottom: 0px !important; margin-bottom: 0px !important;
} }
}
.emPushTable{
// .semi-table-row-cell:first-child{
// display: flex !important;
// }
// .semi-table-row-cell{
// display: flex !important;
// }
} }

4
web/client/src/utils/webapi.js

@ -59,9 +59,9 @@ export const ApiTable = {
//控制台 //控制台
consoleToollink: 'console/toollink', //常用工具 consoleToollink: 'console/toollink', //常用工具
deleteConsoleToollink: 'console/toollink/{linkId}', //删除常用工具 deleteConsoleToollink: 'console/toollink/{linkId}', //删除常用工具
geteteConsoleCount: 'console/count', //工作台数量查询 getConsoleCount: 'console/count', //工作台数量查询
getConsoleAbnormal: 'analysis/problem', //项目概览异常查询
}; };
export const RouteTable = { export const RouteTable = {
apiRoot: "/api/root", apiRoot: "/api/root",

Loading…
Cancel
Save