const moment = require('moment') const fs = require('fs') async function getStructures(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs const { pomsProjectId } = ctx.query let bindRes = [] //选择全局就是查询所有项目下的结构物,有选择项目就只查询对应项目的结构物 if (pomsProjectId) { bindRes = await models.ProjectCorrelation.findAll({ where: { id: { $in: pomsProjectId.split(',') } } }) } else { bindRes = await models.ProjectCorrelation.findAll() } let anxinProjectIds = new Set() for (let b of bindRes) { if (b.anxinProjectId.length) { for (let aid of b.anxinProjectId) { anxinProjectIds.add(aid) } } } let undelStrucRes = [] if (bindRes) { undelStrucRes = anxinProjectIds.size ? await clickHouse.anxinyun.query( ` SELECT t_structure.id AS strucId, t_structure.name AS strucName FROM t_project LEFT JOIN t_project_structure ON t_project_structure.project = t_project.id LEFT JOIN t_project_structuregroup ON t_project_structuregroup.project = t_project.id LEFT JOIN t_structuregroup_structure ON t_structuregroup_structure.structuregroup = t_project_structuregroup.structuregroup LEFT JOIN t_project_construction ON t_project_construction.project = t_project.id LEFT JOIN t_structure_site ON t_structure_site.siteid = t_project_construction.construction RIGHT JOIN t_structure ON t_structure.id = t_project_structure.structure OR t_structure.id = t_structuregroup_structure.structure OR t_structure.id = t_structure_site.structid WHERE project_state != -1 AND t_project.id IN (${[...anxinProjectIds].join(',')}, -1) AND t_structure.external_platform is not null ORDER BY strucId ` ).toPromise() : [] } // undelStrucRes.push({ strucId: 4036, strucName: '象山港大桥' }) // undelStrucRes.push({ strucId: 1, strucName: '象山港大' }) ctx.status = 200; ctx.body = undelStrucRes } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function getFactors(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs const { structId, cacl } = ctx.query let list = [] if (cacl) { const factorList = await clickHouse.alarmLocal.query(`select distinct SafetyFactorTypeId, SafetyFactorTypeName from sensors where PlatformStructureId =${structId}`).toPromise() let fList = factorList.map(m => m.SafetyFactorTypeId) list = await clickHouse.alarmLocal.query(`select distinct FactorID, Name,Items,ItemNames from factors where FactorID in (${[...fList, -1].join(',')})`).toPromise() } else { list = await clickHouse.alarmLocal.query(`select distinct SafetyFactorTypeId, SafetyFactorTypeName from sensors where PlatformStructureId =${structId}`).toPromise() } ctx.body = list 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 } } } //查询设备 async function getSensors(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse } = ctx.app.fs const { structId, SafetyFactorTypeId } = ctx.query const list = await clickHouse.alarmLocal.query(` select distinct SensorId,SensorLocationDescription,Project from sensors where PlatformStructureId =${structId} and SafetyFactorTypeId=${SafetyFactorTypeId}`).toPromise() ctx.body = list 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 } } } //根据设备id和监测因素id查询监测数据 async function getMonitorData(ctx) { try { const { clickHouse } = ctx.app.fs const { factorId, sensorId, startTime, endTime,toExport } = ctx.query const projectId = sensorId.split('-')[0] const factorsList = await clickHouse.alarmLocal.query(`SELECT FactorID,Items,ItemNames,ItemUnits FROM factors WHERE FactorID=${factorId} AND Project='${projectId}' `).toPromise() || [] const dataArray = sensorId.split(',') const transformedArray = dataArray.map(item => { return item.replace('-', ':') + '' }) const id = `(${transformedArray.map(id => `'${id}'`).join(',')})` const monitorData = await clickHouse.alarmLocal.query(`SELECT distinct SensorId,CollectTime,Values FROM themes WHERE SensorId in ${id} AND CollectTime >= toDate('${startTime}') AND CollectTime <= toDate('${endTime}') `).toPromise() || [] const sensor = await clickHouse.alarmLocal.query(`SELECT distinct ID, SensorId,SensorLocationDescription FROM sensors WHERE ID in ${id}`).toPromise() //监测项 let items = {} if (factorsList && factorsList.length > 0) { //因素解释 let factors = [] //因素名词 let factorNames = [] //单位 let c = [] factorsList.map(item => { factors = item.ItemNames.split(',') factorNames = item.Items.split(',') c = item.ItemUnits.split(',') factorNames.map((child, index) => { items[factorNames[index]] = { name: factors[index], unit: c[index] } }) }) } //设备数据+数据 let sensors = [] let data = [] if (sensor && monitorData && sensor.length && monitorData.length) { sensor.forEach((item) => { // 过滤与当前传感器相关的数据 const sensorDataArray = monitorData.filter((d) => d.SensorId == item.ID) // 构建最终的传感器数据结构 const sensorDataItem = { id: item.ID, name: item.SensorLocationDescription, data: sensorDataArray.map((d) => { // 根据 item 对象进行映射 const values = {}; itemKeys = Object.keys(items) itemKeys.forEach((key, index) => { values[key] = d.Values[index]; }); return { time: d.CollectTime, values: values }; }) }; data.push(sensorDataItem) }) } //导出相关 if (toExport) { let arr=items let columns = [] columns.push({ title: '设备位置', dataIndex: 'position', key: 'position', }); for (let index in arr) { columns.push({ title: arr[index].name + '(' + arr[index].unit + ')', dataIndex: index, sorter: (a, b) => b[index] - a[index], key: index, }) }; columns.push({ title: '采集时间', dataIndex: 'acqTime', sorter: (a, b) => b['realTime'] - a['realTime'], key: 'acqTime', }); //设备 let data1 = [] let themeStations = data for (let i = 0; i < themeStations.length; i++) { for (let k = 0; k < themeStations[i].data.length; k++) { let cdataT = {} let startT = ""; let endT = ""; let dataTS = themeStations[i].data[k]; cdataT.key = `station-${themeStations[i].id}-${k}`; cdataT.position = themeStations[i].name; cdataT.acqTime = moment(dataTS.time).format('YYYY-MM-DD HH:mm:ss'); cdataT.realTime = moment(dataTS.time).valueOf(); if (startT == "") { startT = dataTS.time; endT = dataTS.time; } else { if (moment(startT) >= moment(dataTS.time)) startT = dataTS.time; if (moment(endT) <= moment(dataTS.time)) endT = dataTS.time; } //动态列的值 for (let themeItem in arr) { cdataT[themeItem] = dataTS.values[themeItem]; } data1.push(cdataT) } } await exportMaterialEnterList(ctx, data1, columns) } if(!toExport){ ctx.body = { items, sensors: data } 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 } } } async function exportMaterialEnterList(ctx, data, columns) { try { let header = [] columns.forEach(item => { header.push({ title: item.title, key: item.key }) }) const { utils: { simpleExcelDown } } = ctx.app.fs // let exportData = [] // let item={} // console.log(dataList[0].dataValues) let siteName = '数据监控' // for (let item of data) { // for(let child of item){ // if(child!=key){ // item[child]= // } // } // // item.outTime = moment(item.outTime).format('YYYY-MM-DD HH:mm:ss'); // // item.branchId = item.siteProcessBranch && item.siteProcessBranch.name ? item.siteProcessBranch.name : '-' // // item.subItemId = item.siteProcessSubItem && item.siteProcessSubItem.name ? item.siteProcessSubItem.name : '-' // // item.type = item.materialItem && item.materialItem.name ? item.materialItem.name : '-' // // item.name = item.materialItem && item.materialItem.name ? item.materialItem.name : '-' // // item.model = item.materialItem && item.materialItem.model ? item.materialItem.model : '-' // // item.unit = item.materialItem && item.materialItem.unit ? item.materialItem.unit : '-' // // item.providerId = item.materialProvider && item.materialProvider.name ? item.materialProvider.name : '-' // // item.status = (item.status || item.status == 0) && data[item.status] // exportData.push(item) // } const fileName = `${siteName}` + '.xls' const filePath = await simpleExcelDown({ data: data, header, fileName: fileName, needIndexCell: false }) const fileData = fs.readFileSync(filePath) ctx.status = 200 ctx.set('Content-Type', 'application/x-xls') ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName)) ctx.body = fileData } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) ctx.status = 400 ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function exportFile(ctx) { try { const { data, columns } = ctx.query await exportMaterialEnterList(ctx, data, columns) } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) ctx.status = 400 ctx.body = { message: typeof error == 'string' ? error : undefined } } } module.exports = { getStructures, getFactors, getSensors, getMonitorData, exportFile }