diff --git a/api/app/lib/controllers/analysis/network.js b/api/app/lib/controllers/analysis/network.js new file mode 100644 index 0000000..18c9e0c --- /dev/null +++ b/api/app/lib/controllers/analysis/network.js @@ -0,0 +1,320 @@ +'use strict'; +const moment = require('moment') + +async function getMaintenceRecordRank (ctx) { + const sequelize = ctx.fs.dc.orm + const Sequelize = ctx.fs.dc.ORM; + const { clickHouse } = ctx.app.fs + const models = ctx.fs.dc.models + const { startTime, endTime } = ctx.query + + console.log(startTime, endTime, ctx.query, '1212312') + try { + const res = await sequelize.query(` + SELECT emrp.project_id,count(1) +FROM equipment_maintenance_record + RIGHT JOIN equipment_maintenance_record_project emrp + on equipment_maintenance_record.id = emrp.equipment_maintenance_record_id + where report_time BETWEEN :startTime AND :endTime +GROUP BY emrp.project_id + ` + , { + replacements: { + startTime: moment(startTime).format('YYYY-MM-DD HH:mm:ss'), + endTime: moment(endTime).format('YYYY-MM-DD HH:mm:ss ') + } + //, type: sequelize.QueryTypes.SELECT + } + ) + //查询equipment_maintenance_record返回的结果[{project_id: 22, count: 1}] + let projectList = [] + //存project的id + let projectIdList = [] + // console.log('resssss', res) + if (res.length > 0) { + res[0].forEach((item) => { + projectList.push({ project_id: item.project_id, count: Number(item.count) }) + projectIdList.push(item.project_id) + }) + } + const projectNameList = await models.ProjectCorrelation.findAll({ + attributes: + ['id', 'name'], + where: { + id: { $in: projectIdList }, + name: { + [Sequelize.Op.not]: null//有name的结果 + } + // del: false + } + }) || [] + //在ProjectCorrelation中查不到名字,去clickHouse中去查 + const projectNameList1 = await models.ProjectCorrelation.findAll({ + attributes: + ['id', 'name', 'pepProjectId'], + where: { + id: { $in: projectIdList }, + name: { + [Sequelize.Op.eq]: null//无name的结果 + } + // del: false + } + }) + //存放需要去查询clickHouse的id + let idList = new Set() + if (projectNameList1.length) { + projectNameList1.forEach((item) => { + idList.add(item.pepProjectId) + }) + } + //pepProject名称 + const projectManageName = idList.size ? await clickHouse.projectManage.query(` + SELECT id,project_name FROM t_pim_project + WHERE id IN (${[...idList].join(',')}, -1) + `).toPromise() : [] + // if (projectList.length) { + // projectList.forEach((item) => { + // projectManageName + // }) + // } + //存的是{id,projectName} + let project = [] + if (projectNameList1.length && projectManageName.length) { + projectManageName.forEach((item) => { + const pepObj = projectNameList1.find((item1) => { return item1.pepProjectId === item.id }) + project.push({ id: pepObj.id, projectName: item.project_name }) + }) + } + const resAll = project.concat(projectNameList) + let mergedArray = [] + if (resAll.length && projectList) { + mergedArray = projectList.map(obj1 => { + const matchingObj = resAll.find(obj2 => obj2.id === obj1.project_id); + return { id: obj1.project_id, pepProjectId: matchingObj.id, projectName: matchingObj.projectName || matchingObj.dataValues.name, count: obj1.count }; + }); + } + // console.log('ididididid', resAll) + // console.log('ididididid', project) + // console.log('ididididid', projectManageName) + // console.log('ididididid', projectNameList) + // console.log('ididididid', projectList) + + ctx.status = 200 + ctx.body = mergedArray + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: '查询维修记录排名失败' + } + } +} + + +async function getMaintenceTotal (ctx) { + const sequelize = ctx.fs.dc.orm + const Sequelize = ctx.fs.dc.ORM; + const { clickHouse } = ctx.app.fs + const models = ctx.fs.dc.models + const { startTime, endTime } = ctx.query + try { + //所有维修记录 + const res = await sequelize.query(` + SELECT emrp.project_id, + count(case when record.status in ('维修中','待维修','维修完成') then record.id end) incomplete, + count(case when record.status in ('维修完成') then record.id end) completed + FROM equipment_maintenance_record record + RIGHT JOIN equipment_maintenance_record_project emrp + on record.id = emrp.equipment_maintenance_record_id + where report_time BETWEEN :startTime AND :endTime + GROUP BY emrp.project_id + ` + , { + replacements: { + startTime: moment(startTime).format('YYYY-MM-DD HH:mm:ss '), + endTime: moment(endTime).format('YYYY-MM-DD HH:mm:ss ') + } + //, type: sequelize.QueryTypes.SELECT + } + ) + //查询equipment_maintenance_record返回的结果[{project_id: 22,status:'' count: 1}] + let projectList = [] + //存project的id + let projectIdList = new Set() + // console.log('resssss', res) + if (res.length > 0) { + res[0].forEach((item) => { + projectList.push({ project_id: item.project_id, 'incomplete': Number(item.incomplete), completed: Number(item.completed) }) + projectIdList.add(item.project_id) + }) + } + // const result = projectList.reduce((acc, curr) => { + // if (curr.status === '待维修' || curr.status === '维修中') { + // const existingItem = acc.find(item => item.project_id === curr.project_id && item.status === '异常数'); + // if (existingItem) { + // existingItem.count += curr.count; + // } else { + // acc.push({ project_id: curr.project_id, status: '异常数', count: curr.count }); + // } + // } else if (curr.status === '维修完成') { + // const existingItem = acc.find(item => item.project_id === curr.project_id && item.status === '维修数'); + // if (existingItem) { + // existingItem.count += curr.count; + // } else { + // acc.push({ project_id: curr.project_id, status: '维修数', count: curr.count }); + // } + // } + // return acc; + // }, []) + //console.log('resssssresult', result) + const projectNameList = await models.ProjectCorrelation.findAll({ + attributes: + ['id', 'name'], + where: { + id: { $in: [...projectIdList] }, + name: { + [Sequelize.Op.not]: null//有name的结果 + } + // del: false + } + }) || [] + //在ProjectCorrelation中查不到名字,去clickHouse中去查 + const projectNameList1 = await models.ProjectCorrelation.findAll({ + attributes: + ['id', 'name', 'pepProjectId'], + where: { + id: { $in: [...projectIdList] }, + name: { + [Sequelize.Op.eq]: null//无name的结果 + } + // del: false + } + }) + //存放需要去查询clickHouse的id + let idList = new Set() + if (projectNameList1.length) { + projectNameList1.forEach((item) => { + idList.add(item.pepProjectId) + }) + } + //pepProject名称 + const projectManageName = idList.size ? await clickHouse.projectManage.query(` + SELECT id,project_name FROM t_pim_project + WHERE id IN (${[...idList].join(',')}, -1) + `).toPromise() : [] + let project = [] + if (projectNameList1.length && projectManageName.length) { + projectManageName.forEach((item) => { + const pepObj = projectNameList1.find((item1) => { return item1.pepProjectId === item.id }) + project.push({ id: pepObj.id, projectName: item.project_name }) + }) + } + //pg的数据和clcikHouse的数据(名字)合并 + const resAll = project.concat(projectNameList) + let mergedArray = [] + if (resAll.length && projectList) { + mergedArray = projectList.map(obj1 => { + const matchingObj = resAll.find(obj2 => obj2.id === obj1.project_id) + return { + id: obj1.project_id, incomplete: obj1.incomplete, completed: obj1.completed, pepProjectId: matchingObj.id, + projectName: matchingObj.projectName || matchingObj.dataValues.name + } + }); + } + + // console.log('ididididid', resAll) + // console.log('ididididid', project) + // console.log('ididididid', projectManageName) + // console.log('ididididid', projectNameList) + // console.log('ididididid', projectList) + ctx.status = 200 + ctx.body = mergedArray + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: '查询维修记录统计失败' + } + } + + +} +async function getEquipmentCategory (ctx) { + const { startTime, endTime } = ctx.query + const Sequelize = ctx.fs.dc.ORM + const models = ctx.fs.dc.models + try { + const res = await models.EquipmentMaintenanceRecord.findAll({ + attributes: [ + 'equipment_category', + [Sequelize.fn('COUNT', Sequelize.col('equipment_category')), 'count'] + ], + where: { reportTime: { $between: [moment(startTime).format('YYYY-MM-DD HH:mm:ss '), moment(endTime).format('YYYY-MM-DD HH:mm:ss ')] } }, + group: ['equipment_category'] + }) + ctx.status = 200 + ctx.body = res + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: '查询设备类型失败' + } + } +} + + +async function getStatus (ctx) { + const { startTime, endTime } = ctx.query + const Sequelize = ctx.fs.dc.ORM + const models = ctx.fs.dc.models + try { + const res = await models.EquipmentMaintenanceRecord.findAll({ + attributes: [ + 'status', + [Sequelize.fn('COUNT', Sequelize.col('status')), 'count'] + ], + where: { reportTime: { $between: [moment(startTime).format('YYYY-MM-DD HH:mm:ss '), moment(endTime).format('YYYY-MM-DD HH:mm:ss ')] } }, + group: ['status'] + }) + ctx.status = 200 + ctx.body = res + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: '查询设备类型失败' + } + } +} + +async function getOrganizationsStruc (ctx) { + try { + const { utils: { anxinStrucIdRange } } = ctx.app.fs + const { pepProjectId } = ctx.params + + if (!pepProjectId) { + throw '缺少参数 pepProjectId' + } + let anxinStruc = await anxinStrucIdRange({ + ctx, pepProjectId + }) || [] + ctx.status = 200 + ctx.body = anxinStruc + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: '查询设备类型失败' + } + } +} + + + +module.exports = { + getOrganizationsStruc, +} \ No newline at end of file diff --git a/api/app/lib/controllers/operationData/index.js b/api/app/lib/controllers/analysis/operationData.js similarity index 100% rename from api/app/lib/controllers/operationData/index.js rename to api/app/lib/controllers/analysis/operationData.js diff --git a/api/app/lib/controllers/problemData/index.js b/api/app/lib/controllers/analysis/problemData.js similarity index 100% rename from api/app/lib/controllers/problemData/index.js rename to api/app/lib/controllers/analysis/problemData.js diff --git a/api/app/lib/index.js b/api/app/lib/index.js index 8f9cf17..f6cffa3 100644 --- a/api/app/lib/index.js +++ b/api/app/lib/index.js @@ -35,7 +35,7 @@ module.exports.entry = function (app, router, opts) { es(app, opts) - kafka(app, opts) + // kafka(app, opts) // clickHouse 数据库 client clickHouseClient(app, opts) diff --git a/api/app/lib/routes/analysis/network.js b/api/app/lib/routes/analysis/network.js new file mode 100644 index 0000000..b252af9 --- /dev/null +++ b/api/app/lib/routes/analysis/network.js @@ -0,0 +1,16 @@ +'use strict'; +const network = require('../../controllers/analysis/network'); + +module.exports = function (app, router, opts) { + app.fs.api.logAttr['GET/organizations/:pepProjectId/struc'] = { content: '获取项目下的结构物信息', visible: true }; + router.get('/organizations/:pepProjectId/struc', network.getOrganizationsStruc) + + // app.fs.api.logAttr['GET/systemAvailability'] = { content: '获取系统可用性', visible: true }; + // router.get('/systemAvailability', operationData.getSystemAvailability) + + // app.fs.api.logAttr['GET/problemType'] = { content: '获取故障类型', visible: true }; + // router.get('/problemType', operationData.getProblemType) + + // app.fs.api.logAttr['GET/operationsPersonnel'] = { content: '获取运维人员', visible: true }; + // router.get('/operationsPersonnel', operationData.getOperationsPersonnel) +} \ No newline at end of file diff --git a/api/app/lib/routes/operationData/index.js b/api/app/lib/routes/analysis/operationData.js similarity index 90% rename from api/app/lib/routes/operationData/index.js rename to api/app/lib/routes/analysis/operationData.js index 4021ab0..db345df 100644 --- a/api/app/lib/routes/operationData/index.js +++ b/api/app/lib/routes/analysis/operationData.js @@ -1,5 +1,5 @@ 'use strict'; -const operationData = require('../../controllers/operationData'); +const operationData = require('../../controllers/analysis/operationData'); module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/failureTime'] = { content: '获取故障发生时间', visible: true }; diff --git a/api/app/lib/routes/problemData/index.js b/api/app/lib/routes/analysis/problemData.js similarity index 91% rename from api/app/lib/routes/problemData/index.js rename to api/app/lib/routes/analysis/problemData.js index 29a548f..c8ed24f 100644 --- a/api/app/lib/routes/problemData/index.js +++ b/api/app/lib/routes/analysis/problemData.js @@ -1,5 +1,5 @@ 'use strict'; -const problemData = require('../../controllers/problemData'); +const problemData = require('../../controllers/analysis/problemData'); module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/maintenceRecordRank'] = { content: '获取维修记录排名', visible: true }; diff --git a/api/app/lib/routes/project/index.js b/api/app/lib/routes/project/index.js index c232299..4201f7b 100644 --- a/api/app/lib/routes/project/index.js +++ b/api/app/lib/routes/project/index.js @@ -29,7 +29,7 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/project/structure'] = { content: '获取绑定项目下结构物', visible: true }; router.get('/project/structure', project.strucWithPomsProject); - // + // app.fs.api.logAttr['GET/project/group'] = { content: '获取项目分组', visible: true }; router.get('/project/group', projectGroup.groupList); diff --git a/web/client/src/sections/analysis/actions/index.js b/web/client/src/sections/analysis/actions/index.js index d41346a..369c6f6 100644 --- a/web/client/src/sections/analysis/actions/index.js +++ b/web/client/src/sections/analysis/actions/index.js @@ -3,6 +3,7 @@ import * as console from './console' import * as operation from './operationData' import * as maintenceRecord from './maintenceRecordTotal' +import * as network from './network' export default { - ...console, ...operation, ...maintenceRecord + ...console, ...operation, ...maintenceRecord, ...network } \ No newline at end of file diff --git a/web/client/src/sections/analysis/actions/network.js b/web/client/src/sections/analysis/actions/network.js new file mode 100644 index 0000000..bd6edc6 --- /dev/null +++ b/web/client/src/sections/analysis/actions/network.js @@ -0,0 +1,50 @@ +'use strict'; + +import { ApiTable, basicAction } from '$utils' + + +export function getOrganizationsStruc (id) { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_ORGANIZATIONS_STRUC', + url: `${ApiTable.organizationsStruc.replace('{pepProjectId}', id)}`, + msg: { error: '获取项目下的结构物信息失败' }, + reducer: { name: 'organizationsStruc' } + }) +} + +// export function getSystemAvailability() { +// return dispatch => basicAction({ +// type: 'get', +// dispatch: dispatch, +// actionType: 'GET_SYSTEM_AVAILABILITY', +// url: ApiTable.getSystemAvailability, +// msg: { error: '获取可用性分析' }, +// reducer: { name: 'systemAvailability' } +// }) +// } + + +// export function getProblemType() { +// return dispatch => basicAction({ +// type: 'get', +// dispatch: dispatch, +// actionType: 'GET_PROBLEM_TYPE', +// url: ApiTable.getProblemType, +// msg: { error: '获取故障类型' }, +// reducer: { name: 'probleType' } +// }) +// } + + +// export function getOperationsPersonnel() { +// return dispatch => basicAction({ +// type: 'get', +// dispatch: dispatch, +// actionType: 'GET_OPERATIONS_PERSONNEL', +// url: ApiTable.getOperationsPersonnel, +// msg: { error: '获取故障类型' }, +// reducer: { name: 'operationsPersonnel' } +// }) +// } diff --git a/web/client/src/sections/analysis/containers/network.jsx b/web/client/src/sections/analysis/containers/network.jsx index 4995c38..dd4c1bb 100644 --- a/web/client/src/sections/analysis/containers/network.jsx +++ b/web/client/src/sections/analysis/containers/network.jsx @@ -8,18 +8,57 @@ import TreeShow from './treeShow'; -const Network = (props) => { - const { dispatch, actions, user, clientHeight } = props +const Network = ({ + dispatch, actions, user, clientHeight, + projectPoms, pepProjectId, organizationsStruc +}) => { + const { analysis } = actions const [show, setShow] = useState('tree') + const [projectList, setProjectList] = useState([]) //项目列表 + const [projectValue, setProjectValue] = useState() //选中的项目 + const [thingId, setThingId] = useState() //结构物thingId const form = useRef();//表单 + useEffect(() => { + let projectData = [] + let project = projectPoms.filter(v => v.pepProjectIsDelete != 1) + if (projectPoms?.length) { + if (pepProjectId) { + if (pepProjectId?.length) { + let projectId = pepProjectId + ',-1' + projectData = project?.filter(d => projectId?.includes(d.id?.toString())) + } else { + projectData = project?.filter(d => d.id == pepProjectId) + } + } else { + projectData = [...project] + } + } + setProjectList(projectData?.map(d => ({ value: d.id, label: d.name || d.pepProjectName }))) + setProjectValue(projectData[0]?.id) + form.current.setValue('projectId', projectData[0]?.id) + }, [projectPoms, pepProjectId]) - }, []) + useEffect(() => { + //获取当前选中项目的结构物列表 + if (projectValue) dispatch(analysis.getOrganizationsStruc(projectValue)) + }, [projectValue]) + useEffect(() => { + //获取当前选中项目的结构物列表 + if (organizationsStruc?.length) { + setThingId(organizationsStruc[0]?.thingId) + form.current.setValue('thingId', organizationsStruc[0]?.thingId) + } else { + setThingId("") + form.current.setValue('thingId', "") + } + }, [organizationsStruc]) +console.log(thingId); return ( <> @@ -41,29 +80,32 @@ const Network = (props) => { filter showClear label='项目选择' - field="keywordTarget" + field="projectId" labelPosition="left" placeholder="请选择项目选择" style={{ width: 200, marginRight: 10, }} - // initValue={""} - > -