diff --git a/api/app/lib/controllers/project/group.js b/api/app/lib/controllers/project/group.js index bead78f..ad09485 100644 --- a/api/app/lib/controllers/project/group.js +++ b/api/app/lib/controllers/project/group.js @@ -255,6 +255,8 @@ async function groupStatisticOnline (ctx) { // 查在线率 const strucOnlineClient = ctx.app.fs.esclient.strucOnline + console.log('es数据,', strucOnlineClient) + const onlineRes = await strucOnlineClient.search({ index: strucOnlineClient.config.index, type: strucOnlineClient.config.type, @@ -288,6 +290,7 @@ async function groupStatisticOnline (ctx) { ] } }) + console.log('es数据,', onlineRes.hits.hits.length,onlineRes) for (let struc of strucRes) { let curOnline = @@ -318,10 +321,153 @@ async function groupStatisticOnline (ctx) { } } +async function groupStatisticAlarm (ctx) { + try { + const { models } = ctx.fs.dc; + + const { groupId } = ctx.query + const sequelize = ctx.fs.dc.orm + const { clickHouse } = ctx.app.fs + + const pomsProjectRes = await sequelize.query(` + SELECT project_correlation.anxin_project_id + FROM project_group + JOIN project_correlation + ON project_correlation.id = ANY(project_group.poms_project_ids) + WHERE project_group.id = ${groupId}; + `) + + const anxinProjectIds = new Set() + for (let pomsProject of (pomsProjectRes[0] || [])) { + for (let pid of pomsProject.anxin_project_id) + anxinProjectIds.add(pid) + } + + const strucIdRes = anxinProjectIds.size ? await clickHouse.anxinyun.query( + ` + SELECT * + FROM t_project_structure + WHERE project IN (${[...anxinProjectIds].join(',')}, -1) + ` + ).toPromise() : [] + let strucIds = new Set() + for (let struc of strucIdRes) { + strucIds.add(struc.structure) + } + let strucIdArr = Array.from(strucIds) + + const strucRes = strucIdArr.length ? await clickHouse.anxinyun.query( + ` + SELECT name, id FROM t_structure WHERE id IN (${[...strucIdArr].join(',')}); + ` + ).toPromise() : [] + + // 查一周内超阈值告警的个数 + // strucIdArr = [1] + const alarmRes = strucIdArr.length ? await clickHouse.dataAlarm.query( + ` + SELECT StructureId,count(StructureId) AS alarmCount + FROM alarms + WHERE StructureId IN (${[...strucIdArr].join(',')}) + AND AlarmGroupUnit = 8 + AND StartTime >= '${moment().subtract(7, 'days').format('YYYY-MM-DD HH:mm:ss')}' + group by StructureId + ` + ).toPromise() : [] + + const alarmDealRes = strucIdArr.length ? await clickHouse.dataAlarm.query( + ` + SELECT StructureId,count(StructureId) AS alarmCount + FROM alarms + WHERE StructureId IN (${[...strucIdArr].join(',')}) + AND AlarmGroupUnit = 8 + AND State = 4 + AND StartTime >= '${moment().subtract(30, 'days').format('YYYY-MM-DD HH:mm:ss')}' + group by StructureId + ` + ).toPromise() : [] + + for (let struc of strucRes) { + let corAlarm = alarmRes.find((o) => o.StructureId == struc.id) + let corDealAlarm = alarmDealRes.find((o) => o.StructureId == struc.id) + struc.alarmCount = corAlarm ? corAlarm.alarmCount : 0 + struc.dealAlarmCount = corDealAlarm ? corDealAlarm.alarmCount : 0 + } + strucRes.sort((a, b) => b.alarmCount - a.alarmCount) + + ctx.status = 200; + ctx.body = strucRes; + // ctx.body = [{ + // id: 1, + // name: '测试结构物1', + // alarmCount: 128, + // dealAlarmCount: 23 + // }]; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } +} + +async function groupProject (ctx) { + try { + const { models } = ctx.fs.dc; + + const { groupId } = ctx.query + const { clickHouse } = ctx.app.fs + const findOne = await models.ProjectGroup.findOne({ where: { id: groupId } }) + const proRes = await models.ProjectCorrelation.findAll({ where: { id: { $in: findOne.pomsProjectIds } } }) + let pepProjectIds = new Set() + + for (let p of proRes) { + if (p.pepProjectId) { + pepProjectIds.add(p.pepProjectId) + } + } + + const pepProjectRes = 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(',')}, -1) + ` + ).toPromise() : + [] + + for (let p of proRes) { + const corPro = pepProjectRes.find(pp => pp.id == p.pepProjectId) || {} + p.dataValues.pepProjectName = corPro.project_name + } + ctx.status = 200; + ctx.body = proRes; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } +} + module.exports = { groupList, editGroup, delGroup, groupStatistic, groupStatisticOnline, + groupStatisticAlarm, + groupProject }; \ No newline at end of file diff --git a/script/3.1/schema/3.updata_struc_off .sql b/script/3.1/schema/3.updata_struc_off .sql new file mode 100644 index 0000000..8f61563 --- /dev/null +++ b/script/3.1/schema/3.updata_struc_off .sql @@ -0,0 +1,11 @@ + + alter table t_structure_off + add totnum integer; + +comment on column t_structure_off.totnum is '测点总数'; + +alter table t_structure_off + add offnum integer; + +comment on column t_structure_off.offnum is '离线个数'; + diff --git a/web/client/src/sections/projectGroup/containers/bigscreen.jsx b/web/client/src/sections/projectGroup/containers/bigscreen.jsx index af0f43b..fcb6ad3 100644 --- a/web/client/src/sections/projectGroup/containers/bigscreen.jsx +++ b/web/client/src/sections/projectGroup/containers/bigscreen.jsx @@ -28,7 +28,6 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou const [biggest, setBiggest] = useState()//最大的刻度值 const [mockData, setMockData] = useState()//所有的告警数据 const [xData, setXData] = useState([])//横坐标 - const self = useRef({ myChart: null }); @@ -64,7 +63,188 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou } }, []) - + // const mockData=[ + // { + // "name": "西腰墩水库", + // "id": 2957, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "智慧排涝-雄溪河绿新桥南侧智能分流井排口", + // "id": 2966, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "智慧排涝-雄溪河东侧绿地山庄红色廊厅排口", + // "id": 2967, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "鲍家湖水库", + // "id": 2973, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "长春市九台区水旱灾害防御中心小型水库", + // "id": 2975, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "重庆观音峡项目", + // "id": 2977, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "杭州宝坞口隧道监测", + // "id": 2988, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "大湖湾水库", + // "id": 3004, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "上高高情远韵驿站智慧公厕", + // "id": 3007, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "后头湖水库", + // "id": 3008, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "灵宝边坡项目", + // "id": 3010, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "大河峡水库", + // "id": 3023, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "公家墩水库", + // "id": 3024, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "黑达坂水库", + // "id": 3025, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "白家明塘湖水库", + // "id": 3033, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "天城湖水库", + // "id": 3034, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "马尾湖水库", + // "id": 3035, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "芦湾墩上库", + // "id": 3036, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "寺沟水库", + // "id": 3037, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "北台子水库", + // "id": 3038, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "流水口水库", + // "id": 3039, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "三十六道沟水库", + // "id": 3040, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "三坝水库", + // "id": 3041, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "瓷窑口水库", + // "id": 3042, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "大香沟水库", + // "id": 3043, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "小香沟水库", + // "id": 3044, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "芦湾墩下库", + // "id": 3045, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "刘家深湖水库", + // "id": 3047, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "古城水库", + // "id": 3048, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // { + // "name": "水关河水库", + // "id": 3049, + // "alarmCount": 0, + // "dealAlarmCount": 0 + // }, + // ] useEffect(() => { const overview = document.getElementById("alarmRank"); if (overview) { @@ -87,6 +267,7 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou interrupt.update(); } }) + useEffect(() => { const maxCombinedValue = mockData?.reduce((max, item) => { const combinedMax = Math.max(item.alarmCount, item.dealAlarmCount); @@ -95,7 +276,6 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou } return max; }, -Infinity) - console.log('setAlarmData4',maxCombinedValue) const bigD= Math.ceil(maxCombinedValue/50)*50 if(bigD==0){ setXData([5,4,3,2,1,0,1,2,3,4,5])//最大值为0,默认横坐标 @@ -103,7 +283,16 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou setXData([bigD,(bigD-bigD/5),(bigD-bigD*2/5),(bigD-bigD*3/5),(bigD-bigD*4/5),0,(bigD-bigD*4/5),(bigD-bigD*3/5),(bigD-bigD*2/5),(bigD-bigD/5),bigD]) } setBiggest(bigD) - },[]) + if (mockData && mockData.length > 3 && mockData.length < 21) { + const newArray = mockData.slice(3) + setAlarmData(newArray) + } + if (mockData && mockData.length > 21) { + //数据大于20的话,取前20 + const newArray = mockData.slice(3, 20) + setAlarmData(newArray) + } + },[mockData]) // const mockData=[ // {id: 1,name: '测试结构物测试结构物',alarmCount: 200,dealAlarmCount: 23}, @@ -130,21 +319,6 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou // {id: 22,name: '测试结构物22',alarmCount: 27,dealAlarmCount: 22}, // {id: 23,name: '测试结构物23',alarmCount: 26,dealAlarmCount: 21}, // ] - useEffect(() => { - if (mockData && mockData.length > 3 && mockData.length < 21) { - const newArray = mockData.slice(3) - setAlarmData(newArray) - } - if (mockData && mockData.length > 21) { - //数据大于20的话,取前20 - const newArray = mockData.slice(3, 20) - setAlarmData(newArray) - } - - }, []) - - - let statisticOnline = (groupId) => { dispatch(actions.projectGroup.groupStatisticOnline({ groupId })).then(res => { if (res.success) { @@ -179,13 +353,11 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou // }) // } // }) - // } - function formatDate (date) { var year = date.getFullYear(); var month = String(date.getMonth() + 1).padStart(2, '0'); @@ -246,10 +418,6 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou }; }, [proportion]); - -// console.log('setAlarmData3',alarmData) - // console.log(groupStatisticOnline); - return (
@@ -444,6 +612,7 @@ const Bigscreen = ({ dispatch, actions, user, match, history, clientHeight, grou
+ {mockData && mockData[0] ? (
@@ -562,4 +731,4 @@ function mapStateToProps (state) { }; } -export default connect(mapStateToProps)(Bigscreen); +export default connect(mapStateToProps)(Bigscreen); \ No newline at end of file