From 4fd1b0ccc023a08d7242e1e23cce46488adfd008 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 28 Oct 2022 15:53:38 +0800 Subject: [PATCH 1/8] =?UTF-8?q?(*)=E5=91=8A=E8=AD=A6=E5=A4=84=E7=BD=AE?= =?UTF-8?q?=E6=95=88=E7=8E=87=E6=95=B0=E6=8D=AE=E8=AE=A1=E7=AE=97=E5=85=A5?= =?UTF-8?q?=E5=BA=93=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E4=BF=AE=E6=94=B9?= =?UTF-8?q?-=E6=95=B0=E6=8D=AE=E7=B1=BB=E5=91=8A=E8=AD=A6=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/schedule/alarms_handle_statistics.js | 233 +++++++++++------- 1 file changed, 150 insertions(+), 83 deletions(-) diff --git a/api/app/lib/schedule/alarms_handle_statistics.js b/api/app/lib/schedule/alarms_handle_statistics.js index 04fab12..b63293f 100644 --- a/api/app/lib/schedule/alarms_handle_statistics.js +++ b/api/app/lib/schedule/alarms_handle_statistics.js @@ -7,7 +7,7 @@ module.exports = function (app, opts) { const { database: anxinyun } = clickHouse.anxinyun.opts.config const alarmHandleStatistics = app.fs.scheduleInit( { - interval: '0 58 9 * * *', + interval: '0 48 1 ? * MON',//0 48 1 ? * MON 每周一凌晨1点48开始执行 // immediate: true, //proRun: true, }, @@ -16,18 +16,18 @@ module.exports = function (app, opts) { let anxinStruc = await getAxyStructs() let pomsProject = await pomsProjectRange() if (anxinStruc.length) { - let dataAlarms = await getDataAlarms(anxinStruc);//数据告警 + let { dataSum, dataMaps } = await getDataAlarms(anxinStruc);//数据告警 let appAlarms = await getAppAlarms(pomsProject);//应用告警 let videoAlarms = await getVideoAlarms(anxinStruc);//视频告警 let time = moment().format() //算全局 - let dataArrToSave = [] - let dataMap = calculate(dataAlarms, appAlarms, videoAlarms) - let sum = dataAlarms.length + appAlarms.length + videoAlarms.length; + //let dataArrToSave = [] + let dataMap = calculate(dataMaps, appAlarms, videoAlarms) + let sum = dataSum + appAlarms.length + videoAlarms.length; if (sum) { - dataArrToSave.push({ + let data = { time: time, projectCorrelationId: null,//全局 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)), day30: parseFloat((100 * dataMap.day30 / 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 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)), - }) + //let pid = 11 + let pAnxinStruc = await getAxyStructs(pid) + let pPomsProject = await pomsProjectRange(pid) + if (pAnxinStruc.length) { + let { dataSum, dataMaps } = await getDataAlarms(pAnxinStruc);//数据告警 + let pAppAlarms = await getAppAlarms(pPomsProject);//应用告警 + let pVideoAlarms = await getVideoAlarms(pAnxinStruc);//视频告警 + let pDataMap = calculate(dataMaps, pAppAlarms, pVideoAlarms) + let sm = dataSum + pAppAlarms.length + pVideoAlarms.length; + if (sm) { + let data = { + time: time, + projectCorrelationId: pid,//单个项目 + day1: parseFloat((100 * pDataMap.day1 / sm).toFixed(2)), + day3: parseFloat((100 * pDataMap.day3 / sm).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) { console.error(error); @@ -69,33 +97,34 @@ module.exports = function (app, opts) { } ) - function calculate(dataAlarms, appAlarms, videoAlarms) { + function calculate(dataMaps, appAlarms, videoAlarms) { try { + let { day1, day3, day7, day15, day30, day30m } = dataMaps; //算全局 let dataMap = { - day1: 0,//当日处理 - day3: 0,//3日内 - day7: 0,//7日内 - day15: 0,//15日内 - day30: 0,//30日内 - day30m: 0//超过30日 + day1: day1[0].count,//当日处理 + day3: day3[0].count,//3日内 + day7: day7[0].count,//7日内 + day15: day15[0].count,//15日内 + day30: day30[0].count,//30日内 + day30m: day30m[0].count//超过30日 } - dataAlarms.filter(d => d.State > 3).map(da => { - let range = moment(da.confirmTime).diff(moment(da.StartTime), 'day') - if (range <= 1) { - dataMap.day1++ - } else if (range > 1 && range <= 3) { - dataMap.day3++ - } else if (range > 3 && range <= 7) { - dataMap.day7++ - } else if (range > 7 && range <= 15) { - dataMap.day15++ - } else if (range > 15 && range <= 30) { - dataMap.day30++ - } else if (range > 30) { - dataMap.day30m++ - } - }) + // dataAlarms.filter(d => d.State > 3).map(da => { + // let range = moment(da.confirmTime).diff(moment(da.StartTime), 'day') + // if (range <= 1) { + // dataMap.day1++ + // } else if (range > 1 && range <= 3) { + // dataMap.day3++ + // } else if (range > 3 && range <= 7) { + // dataMap.day7++ + // } else if (range > 7 && range <= 15) { + // dataMap.day15++ + // } else if (range > 15 && range <= 30) { + // dataMap.day30++ + // } else if (range > 30) { + // dataMap.day30m++ + // } + // }) appAlarms.filter(d => d.confirmTime).map(da => { let range = moment(da.confirmTime).diff(moment(da.createTime), 'day') 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) { try { const anxinStrucIds = anxinStruc.map(a => a.strucId) @@ -158,35 +198,53 @@ module.exports = function (app, opts) { StartTime, EndTime ${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 day1 = await clickHouse.dataAlarm.query(day1Str).toPromise(); - // 最新告警详情 - 确认信息 - let corConfirmedData = (confirmedAlarmDetailMax.find(cdm => cdm.AlarmId == ar.AlarmId) || {}); - ar.confirmTime = corConfirmedData.Time || ar.EndTime - }) - return alarmRes; + let day3Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)>1 and Date(EndTime) - Date(StartTime)<=3'); + 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.length, dataMaps: { day1, day3, day7, day15, day30, day30m } }; } catch (error) { console.error(error); } @@ -318,9 +376,9 @@ module.exports = function (app, opts) { console.error(error); } } - async function pomsProjectRange() { + async function pomsProjectRange(pepProjectId) { try { - const { pepProjectRes, bindRes } = await pomsWithPepRangeParams() + const { pepProjectRes, bindRes } = await pomsWithPepRangeParams(pepProjectId) let pomsProject = [] for (let b of bindRes) { if (b.pepProjectId) { @@ -341,9 +399,18 @@ module.exports = function (app, opts) { } } - async function pomsWithPepRangeParams() { + async function pomsWithPepRangeParams(pepProjectId) { 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 let pepProjectIds = [] for (let b of bindRes) { @@ -379,9 +446,9 @@ module.exports = function (app, opts) { } } - async function getAxyStructs() { + async function getAxyStructs(pepProjectId) { try { - const { pepProjectRes, bindRes } = await pomsWithPepRangeParams() + const { pepProjectRes, bindRes } = await pomsWithPepRangeParams(pepProjectId) // 获取不重复的 安心云项目 id const anxinProjectIds = [ ...(bindRes).reduce( From 6aa7dcd343c9dd16b840b6f6f3c34f866c888b45 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 28 Oct 2022 15:56:04 +0800 Subject: [PATCH 2/8] =?UTF-8?q?(*)=E5=91=8A=E8=AD=A6=E5=A4=84=E7=BD=AE?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1proRun:true?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/schedule/alarms_handle_statistics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/app/lib/schedule/alarms_handle_statistics.js b/api/app/lib/schedule/alarms_handle_statistics.js index b63293f..e2fe67f 100644 --- a/api/app/lib/schedule/alarms_handle_statistics.js +++ b/api/app/lib/schedule/alarms_handle_statistics.js @@ -9,7 +9,7 @@ module.exports = function (app, opts) { { interval: '0 48 1 ? * MON',//0 48 1 ? * MON 每周一凌晨1点48开始执行 // immediate: true, - //proRun: true, + proRun: true, }, async () => { try { From c8d59856c9fcecf6e5e7f6752f59e3160d8d6e45 Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 28 Oct 2022 16:02:26 +0800 Subject: [PATCH 3/8] =?UTF-8?q?(*)=E6=95=B0=E6=8D=AE=E5=91=8A=E8=AD=A6?= =?UTF-8?q?=E5=A4=84=E7=BD=AE=E6=95=88=E7=8E=87=E6=9F=A5=E8=AF=A2=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/schedule/alarms_handle_statistics.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/app/lib/schedule/alarms_handle_statistics.js b/api/app/lib/schedule/alarms_handle_statistics.js index e2fe67f..dcfa55d 100644 --- a/api/app/lib/schedule/alarms_handle_statistics.js +++ b/api/app/lib/schedule/alarms_handle_statistics.js @@ -191,12 +191,13 @@ module.exports = function (app, opts) { console.log('开始查数据-数据-数据类告警---' + moment().format('YYYY-MM-DD HH:mm:ss')) const alarmRes = await clickHouse.dataAlarm.query(` - SELECT + select count(AlarmId) count from + (SELECT alarms.AlarmId AS AlarmId, alarms.State AS State, alarms.StructureId AS StructureId, StartTime, EndTime - ${alarmQueryOptionStr}`).toPromise(); + ${alarmQueryOptionStr})`).toPromise(); let day1Str = getStr(alarmQueryOptionStr, 'Date(EndTime) - Date(StartTime)<=1'); let day1 = await clickHouse.dataAlarm.query(day1Str).toPromise(); @@ -244,7 +245,7 @@ module.exports = function (app, opts) { // let corConfirmedData = (confirmedAlarmDetailMax.find(cdm => cdm.AlarmId == ar.AlarmId) || {}); // ar.confirmTime = corConfirmedData.Time || ar.EndTime // }) - return { dataSum: alarmRes.length, dataMaps: { day1, day3, day7, day15, day30, day30m } }; + return { dataSum: alarmRes[0].count, dataMaps: { day1, day3, day7, day15, day30, day30m } }; } catch (error) { console.error(error); } From ab6f9fbd288633c3d8b6534becffe83f88fc593a Mon Sep 17 00:00:00 2001 From: deartibers <947466799@qq.com> Date: Fri, 28 Oct 2022 17:28:15 +0800 Subject: [PATCH 4/8] =?UTF-8?q?em=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/client/index.ejs | 2 +- web/client/index.html | 2 +- web/client/src/sections/install/containers/system.jsx | 2 +- web/client/src/sections/service/components/pushModal.jsx | 4 ++-- web/client/src/sections/service/containers/emPush.jsx | 3 ++- web/client/src/sections/service/nav-item.jsx | 2 +- web/client/src/sections/service/style.less | 8 -------- 7 files changed, 8 insertions(+), 15 deletions(-) diff --git a/web/client/index.ejs b/web/client/index.ejs index 9cbe876..71b028e 100644 --- a/web/client/index.ejs +++ b/web/client/index.ejs @@ -11,7 +11,7 @@ - + diff --git a/web/client/index.html b/web/client/index.html index 162fe74..302a7e4 100644 --- a/web/client/index.html +++ b/web/client/index.html @@ -11,7 +11,7 @@ + src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.559b91c217b8ddc76c0c4b1397d84d48.es5.js"> diff --git a/web/client/src/sections/install/containers/system.jsx b/web/client/src/sections/install/containers/system.jsx index b33458f..69a80d1 100644 --- a/web/client/src/sections/install/containers/system.jsx +++ b/web/client/src/sections/install/containers/system.jsx @@ -273,7 +273,7 @@ const Example = (props) => { 修改 {//获取项企(PEP)全部部门及其下用户 + dispatch(service.postPush({ pushId: editObj.id, ...obj, msg: '编辑推送配置' })).then((res) => {//获取项企(PEP)全部部门及其下用户 if (res.success) { close(); } @@ -567,7 +567,7 @@ function pushModal (props) { placeholder="请选择通知时效" style={{ width: 285 }} rules={[{ required: true, message: "请选择通知时效" }]} - initValue={editObj?.timeType.length > 0 ? editObj?.timeType : timeTypePOMS.current} + initValue={editObj?.timeType?.length > 0 ? editObj?.timeType : timeTypePOMS.current} disabled={timeTypeDis} multiple maxTagCount={3} diff --git a/web/client/src/sections/service/containers/emPush.jsx b/web/client/src/sections/service/containers/emPush.jsx index 3772b80..1e1354a 100644 --- a/web/client/src/sections/service/containers/emPush.jsx +++ b/web/client/src/sections/service/containers/emPush.jsx @@ -662,6 +662,7 @@ const EmPush = (props) => { marginLeft: 32 }} onClick={() => { + setEditObj({}) setPushModal(true); setPushEdit(false); }} @@ -688,7 +689,7 @@ const EmPush = (props) => { hideExpandedColumn={false} empty="暂无数据" expandedRowRender={expandRowRender} - pagination={false} + // pagination={false} onRow={handleRow} /> diff --git a/web/client/src/sections/service/nav-item.jsx b/web/client/src/sections/service/nav-item.jsx index 694b817..cd770ad 100644 --- a/web/client/src/sections/service/nav-item.jsx +++ b/web/client/src/sections/service/nav-item.jsx @@ -30,7 +30,7 @@ export function getNavItem (user, dispatch) { }, { itemKey: 'carrierPigeon', text: '信鸽服务', - icon: , + icon: , to: '/service/carrierPigeon/emPush', items: [{ itemKey: 'emPush', to: '/service/carrierPigeon/emPush', text: 'EM推送' diff --git a/web/client/src/sections/service/style.less b/web/client/src/sections/service/style.less index 7f2491d..d26536b 100644 --- a/web/client/src/sections/service/style.less +++ b/web/client/src/sections/service/style.less @@ -2,12 +2,4 @@ .semi-input-wrapper{ margin-bottom: 0px !important; } -} -.emPushTable{ - // .semi-table-row-cell:first-child{ - // display: flex !important; - // } - // .semi-table-row-cell{ - // display: flex !important; - // } } \ No newline at end of file From 132827722334dcc9cd6e95d34cf0e4f2571e6a74 Mon Sep 17 00:00:00 2001 From: wenlele Date: Mon, 31 Oct 2022 10:48:20 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=8F=B0=20=E9=97=AE?= =?UTF-8?q?=E9=A2=98&=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/.vscode/launch.json | 2 +- api/app/lib/controllers/control/analysis.js | 273 +++++++++++++++++- api/app/lib/routes/control/index.js | 7 +- .../src/sections/control/actions/control.js | 16 +- .../sections/control/containers/control.jsx | 22 +- .../sections/problem/components/tableData.jsx | 1 - web/client/src/utils/webapi.js | 4 +- 7 files changed, 300 insertions(+), 25 deletions(-) diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index 3388416..f9f2031 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -56,7 +56,7 @@ // "--clickHouseDataAlarm default", // 测试 - "--clickHouseAnxincloud Anxinyun22", + "--clickHouseAnxincloud Anxinyun23", "--clickHousePepEmis pepca8", "--clickHouseProjectManage peppm8", "--clickHouseVcmp video_access_dev", diff --git a/api/app/lib/controllers/control/analysis.js b/api/app/lib/controllers/control/analysis.js index b83048d..e097bfb 100644 --- a/api/app/lib/controllers/control/analysis.js +++ b/api/app/lib/controllers/control/analysis.js @@ -1,7 +1,6 @@ 'use strict'; const moment = require('moment'); - async function dataList (ctx) { try { const { models } = ctx.fs.dc; @@ -82,12 +81,12 @@ async function dataList (ctx) { } } -async function userlist (ctx) { +async function personnelApp (ctx) { try { const models = ctx.fs.dc.models; const { clickHouse } = ctx.app.fs const sequelize = ctx.fs.dc.orm; - + const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api const { pepId } = ctx.query 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) if (pepId) { @@ -210,7 +283,8 @@ async function userlist (ctx) { ctx.status = 200 ctx.body = { - personnel: personnel.map(v => v.dataValues.name) + personnel: personnel.map(v => v.dataValues.name), + webApp: webApp } } catch (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 = { dataList, - userlist -}; \ No newline at end of file + personnelApp, + problem +} \ No newline at end of file diff --git a/api/app/lib/routes/control/index.js b/api/app/lib/routes/control/index.js index 39f71f4..c8962b1 100644 --- a/api/app/lib/routes/control/index.js +++ b/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 }; router.get('/analysis/dataList', analysis.dataList); - app.fs.api.logAttr['GET/analysis/userlist'] = { content: '查询关联人员', visible: true }; - router.get('/analysis/userlist', analysis.userlist); + app.fs.api.logAttr['GET/analysis/userlist'] = { content: '查询关联人员,web应用', visible: true }; + router.get('/analysis/userlist', analysis.personnelApp); + + app.fs.api.logAttr['GET/analysis/problem'] = { content: '查询异常&问题', visible: true }; + router.get('/analysis/problem', analysis.problem); diff --git a/web/client/src/sections/control/actions/control.js b/web/client/src/sections/control/actions/control.js index 83db79c..edcf54f 100644 --- a/web/client/src/sections/control/actions/control.js +++ b/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({ type: 'get', dispatch: dispatch, query, actionType: 'GET_CONSLE_COUNT', - url: `${ApiTable.geteteConsoleCount}`, + url: `${ApiTable.getConsoleCount}`, msg: { option: '工作台数量查询' }, 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: '' } + }); } \ No newline at end of file diff --git a/web/client/src/sections/control/containers/control.jsx b/web/client/src/sections/control/containers/control.jsx index 3f14e79..952ed0a 100644 --- a/web/client/src/sections/control/containers/control.jsx +++ b/web/client/src/sections/control/containers/control.jsx @@ -63,9 +63,12 @@ const Control = (props) => { }, []) useEffect(() => { - dispatch(control.geteteConsoleCount({ pepProjectId: pepProjectId })).then(res => { + dispatch(control.getConsoleCount({ pepProjectId: pepProjectId })).then(res => { if (res.success) setWorkData(res.payload.data) }) + dispatch(getConsoleAbnormal({ pepProjectId: pepProjectId })).then(res => { + if (res.success) setProblemsList(...res.payload.data,...res.payload.data) + }) }, [pepProjectId]) useEffect(() => { @@ -145,7 +148,6 @@ const Control = (props) => { // dispatch(actions.example.getMembers(user.orgId)) }) - const consoleToollink = () => { dispatch(control.getConsoleToollink()).then(res => { if (res.success) setToolShow(res.payload.data) @@ -177,13 +179,13 @@ const Control = (props) => { { name: '关联web应用', sort: 4, key: 'web', }, { name: '异常&问题', sort: 5, key: 'problem', }, - { name: '数据中断', sort: 5, key: 'dataInterrupt', }, - { name: '数据异常', sort: 5, key: 'dataAnomaly', }, - { name: '策略命中', sort: 5, key: 'strategyHit', }, - { name: '视频异常', sort: 5, key: 'videoException', }, + { name: '数据中断', sort: 1, key: 'dataInterrupt', }, + { name: '数据异常', sort: 2, key: 'dataAnomaly', }, + { name: '策略命中', sort: 3, key: 'strategyHit', }, + { name: '视频异常', sort: 4, key: 'videoException', }, { name: '应用异常', sort: 5, key: 'appAbnormal', }, - { name: '设备异常', sort: 5, key: 'unitException', }, - { name: '问题处置效率分析', sort: 5, key: 'problemAnalysis', }, + { name: '设备异常', sort: 6, key: 'unitException', }, + { name: '问题处置效率分析', sort: 7, key: 'problemAnalysis', }, ] useEffect(() => { @@ -202,12 +204,11 @@ const Control = (props) => { TableDisplay.sort((a, b) => a.sort - b.sort) exhibition.current = { ...exhibition.current, [title]: TableDisplay } setTableSetup([{ list: data }]) - } return ( - 11 ? : + // 11 ? : <>
{/* 头部 */} @@ -516,7 +517,6 @@ const Control = (props) => {
{exhibition.current?.analyse?.map((v, index) => { - console.log(exhibition.current?.analyse); return
{ if (res.success) { - let routeData = { dataLnterrupt: '数据中断', dataAbnormal: '数据异常', strategyHit: '策略命中', deviceAbnormal: '' } let data if (route == 'dataLnterrupt') data = res.payload.data?.filter(v => v.desc == '数据中断') if (route == 'dataAbnormal') data = res.payload.data?.filter(v => v.desc == '数据异常') diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js index ca385b4..f937fcb 100644 --- a/web/client/src/utils/webapi.js +++ b/web/client/src/utils/webapi.js @@ -54,9 +54,9 @@ export const ApiTable = { //控制台 consoleToollink: 'console/toollink', //常用工具 deleteConsoleToollink: 'console/toollink/{linkId}', //删除常用工具 - geteteConsoleCount: 'console/count', //工作台数量查询 + getConsoleCount: 'console/count', //工作台数量查询 + getConsoleAbnormal: 'analysis/problem', //项目概览异常查询 - }; export const RouteTable = { apiRoot: "/api/root", From e2628098edf1a8e522683962e7ee69d8879aa27c Mon Sep 17 00:00:00 2001 From: wuqun Date: Mon, 31 Oct 2022 10:51:54 +0800 Subject: [PATCH 6/8] =?UTF-8?q?(*)=E5=91=8A=E8=AD=A6=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=8E=A8=E9=80=81=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/.vscode/launch.json | 2 +- api/app/lib/controllers/alarm/alarmConfirmLog.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index f58978c..69a9028 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -56,7 +56,7 @@ // "--clickHouseDataAlarm default", // 测试 - "--clickHouseAnxincloud Anxinyun22", + "--clickHouseAnxincloud Anxinyun23", "--clickHousePepEmis pepca8", "--clickHouseProjectManage peppm8", "--clickHouseVcmp video_access_dev", diff --git a/api/app/lib/controllers/alarm/alarmConfirmLog.js b/api/app/lib/controllers/alarm/alarmConfirmLog.js index 5a91aea..378c584 100644 --- a/api/app/lib/controllers/alarm/alarmConfirmLog.js +++ b/api/app/lib/controllers/alarm/alarmConfirmLog.js @@ -32,7 +32,8 @@ async function alarmConfirmLog(ctx, confirmPost, content) { }) await models.LatestDynamicList.bulkCreate(dynamics); - //TODO 消息推送到前端 + //消息推送到前端 + //ctx.app.socket.emit('TEST', { someProperty: '【广播】呼叫青铜时代号!!!', }) } catch (error) { From 38c57457ef07cbc0227d15eb3b4f1b368b86aa34 Mon Sep 17 00:00:00 2001 From: wenlele Date: Mon, 31 Oct 2022 10:54:08 +0800 Subject: [PATCH 7/8] =?UTF-8?q?getConsoleAbnormal=20=20=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/client/src/sections/control/containers/control.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/client/src/sections/control/containers/control.jsx b/web/client/src/sections/control/containers/control.jsx index 952ed0a..801caad 100644 --- a/web/client/src/sections/control/containers/control.jsx +++ b/web/client/src/sections/control/containers/control.jsx @@ -66,8 +66,9 @@ const Control = (props) => { dispatch(control.getConsoleCount({ pepProjectId: pepProjectId })).then(res => { if (res.success) setWorkData(res.payload.data) }) - dispatch(getConsoleAbnormal({ pepProjectId: pepProjectId })).then(res => { - if (res.success) setProblemsList(...res.payload.data,...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]) From 01333be4e86be44da466536dbe6c190ea7c28e70 Mon Sep 17 00:00:00 2001 From: deartibers <947466799@qq.com> Date: Mon, 31 Oct 2022 11:16:38 +0800 Subject: [PATCH 8/8] =?UTF-8?q?em=E6=8E=A8=E9=80=81=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/sections/service/actions/emPush.js | 2 +- .../sections/service/components/pushModal.jsx | 1 - .../sections/service/containers/emPush.jsx | 99 ++++++------------- 3 files changed, 29 insertions(+), 73 deletions(-) diff --git a/web/client/src/sections/service/actions/emPush.js b/web/client/src/sections/service/actions/emPush.js index cadbb00..b560310 100644 --- a/web/client/src/sections/service/actions/emPush.js +++ b/web/client/src/sections/service/actions/emPush.js @@ -10,7 +10,7 @@ export function getPush (query) { //获取推送配置列表 actionType: 'GET_PUSH', url: `${ApiTable.getPush}`, msg: { error: '获取推送配置列表失败' }, - reducer: { name: '' } + reducer: { name: "getPush", params: { noClear: true } }, }); } diff --git a/web/client/src/sections/service/components/pushModal.jsx b/web/client/src/sections/service/components/pushModal.jsx index 3c089c9..d271001 100644 --- a/web/client/src/sections/service/components/pushModal.jsx +++ b/web/client/src/sections/service/components/pushModal.jsx @@ -378,7 +378,6 @@ function pushModal (props) { labelAlign="right" labelWidth="120px" onValueChange={(values, field) => { - console.log('values', values); for (var key in field) { if (key == 'tactics') { if (values.tactics == 'abnormal_rate') { diff --git a/web/client/src/sections/service/containers/emPush.jsx b/web/client/src/sections/service/containers/emPush.jsx index 1e1354a..8a4795d 100644 --- a/web/client/src/sections/service/containers/emPush.jsx +++ b/web/client/src/sections/service/containers/emPush.jsx @@ -7,7 +7,6 @@ import moment from "moment"; import PushModal from '../components/pushModal' import '../style.less' import { Setup } from "$components"; -// import { set } from 'nprogress'; const EmPush = (props) => { const form = useRef();//表单 @@ -15,22 +14,13 @@ const EmPush = (props) => { const { service } = actions; const [setup, setSetup] = useState(false); //表格设置是否显现 const [setupp, setSetupp] = useState([]);//实际显示的表格列表 - const [tableSetup, setTableSetup] = useState([]); //单一表格设置信息 const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息 const [limits, setLimits] = useState()//每页实际条数 const mylimits = useRef(); //每页实际条数 const [pushModal, setPushModal] = useState(false) //信鸽弹框 const [pushEdit, setPushEdit] = useState(false) //是否是修改 - const [anxincloudList, setAnxincloudList] = useState([]) //安心云列表 - const [peplist, setPeplist] = useState([]) //PEP项目管理项目列表 - 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 [change, setChange] = useState(false) //是否改变 + const [allTableData, setAllTableData] = useState([]) //获取到的所有表格信息 const [editObj, setEditObj] = useState({});//管理员弹框修改内容 const [projectStatus, setProjectStatus] = useState([]); //获取项目状态列表 const page = useRef(query.page);//哪一页 @@ -82,16 +72,6 @@ const EmPush = (props) => { const [tableData, setTableData] = useState([]) //表格数据 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.setItem( EMPUSH, @@ -99,23 +79,28 @@ const EmPush = (props) => { ) : ""; getProjectStatusList() + getPushList(query); }, []) useEffect(() => { - getPushList(); - }, [query]); + let showTableData = JSON.parse(JSON.stringify(allTableData)).slice(query.page * query.limit, (query.page + 1) * query.limit) + setTableData(showTableData) + mylimits.current = showTableData.length + }, [change]); - function getPushList () { + function getPushList (query) { let val = form.current.getValues() - // , ...query dispatch(service.getPush({ ...val })).then((res) => {//获取已绑定项目 if (res.success) { let mytableData = JSON.parse(JSON.stringify(res.payload.data)); for (let index = 0; index < mytableData.length; index++) { 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) - mylimits.current = res.payload.data.length + mylimits.current = showTableData.length } }) } @@ -138,37 +123,9 @@ const EmPush = (props) => {