diff --git a/api/app/lib/controllers/analysis/network.js b/api/app/lib/controllers/analysis/network.js index e726941..db4a5a6 100644 --- a/api/app/lib/controllers/analysis/network.js +++ b/api/app/lib/controllers/analysis/network.js @@ -1,5 +1,8 @@ 'use strict'; const moment = require('moment') +const RAW_DATA = 'rawData'; +const VBRAW_DATA = 'vbRawData'; +const ALARM = 'alarm'; async function getMaintenceRecordRank(ctx) { const sequelize = ctx.fs.dc.orm @@ -313,7 +316,7 @@ async function getOrganizationsStruc(ctx) { } } -async function getThingsDeploy (ctx) { +async function getThingsDeploy(ctx) { let error = { name: 'FindError', message: '获取设备部署信息失败' }; let rslt = null, errStatus = null; let { thingId } = ctx.params; @@ -323,7 +326,7 @@ async function getThingsDeploy (ctx) { throw '缺少参数 thingId' } let iotaResponse = await ctx.app.fs.iotRequest.get(`things/${thingId}/deploys`) - rslt = iotaResponse + rslt = JSON.parse(iotaResponse) error = null; } catch (err) { @@ -347,115 +350,238 @@ async function getThingsDeploy (ctx) { } + +async function findDeviceMetaDeployed(ctx, next) { + let rslt = null; + const { iotaThingId } = ctx.params; + try { + let iotaResponse = await ctx.app.fs.iotRequest.get(`meta/things/${iotaThingId}/devices`) + rslt = JSON.parse(iotaResponse) + ctx.status = 200; + ctx.body = rslt; + } catch (err) { + ctx.status = 400; + ctx.body = { + "name": "FindError", + "message": "设备部署原型获取失败" + } + } + +}; + async function findDeviceLastData(ctx, deviceIds) { let rslt = []; const clientRaws = ctx.app.fs.esclient[RAW_DATA]; const clientVbraws = ctx.app.fs.esclient[VBRAW_DATA]; if (deviceIds) { - for (let id of deviceIds) { - let params = { - index: clientRaws.config.index, - type: clientRaws.config.type, - body: { - query: { - constant_score: { - filter: { - bool: { - must: [ - { term: { "iota_device": id } }, - { range: { "collect_time": { lte: moment().toISOString() } } } - ] - } - } - } - }, - sort: [ - { - "collect_time": { - order: "desc" - } - } - ], - size: 1 - } - }; - let res = await clientRaws.search(params); - if (res.hits.hits.length == 0) { - params.index = clientVbraws.config.index; - params.type = clientVbraws.config.type; - res = await clientVbraws.search(params); - } - - let data = res.hits.hits.map(h => { - let source = h._source; - let data_ = source.data; - if (params.index == clientVbraws.config.index) { - let tempData = { "最大幅值": '_' }; - if (data_.raw && data_.raw.length) { - let maxAmplitude = data_.raw[0]; - for (let v of data_.raw) { - if (maxAmplitude < v) { - maxAmplitude = v; - } - } - tempData['最大幅值'] = maxAmplitude + '(gal)'; - } - data_ = tempData; - } - return { - collectTime: source.collect_time, - iotaDevice: source.iota_device, - iotaDeviceName: source.iota_device_name, - data: data_ + for (let id of deviceIds) { + let params = { + index: clientRaws.config.index, + type: clientRaws.config.type, + body: { + query: { + constant_score: { + filter: { + bool: { + must: [ + { term: { "iota_device": id } }, + { range: { "collect_time": { lte: moment().toISOString() } } } + ] + } + } + } + }, + sort: [ + { + "collect_time": { + order: "desc" + } + } + ], + size: 1 + } + }; + let res = await clientRaws.search(params); + if (res.hits.hits.length == 0) { + params.index = clientVbraws.config.index; + params.type = clientVbraws.config.type; + res = await clientVbraws.search(params); + } + + let data = res.hits.hits.map(h => { + let source = h._source; + let data_ = source.data; + if (params.index == clientVbraws.config.index) { + let tempData = { "最大幅值": '_' }; + if (data_.raw && data_.raw.length) { + let maxAmplitude = data_.raw[0]; + for (let v of data_.raw) { + if (maxAmplitude < v) { + maxAmplitude = v; + } + } + tempData['最大幅值'] = maxAmplitude + '(gal)'; } - }); - rslt.push({ - sensorId: id, - data: data - }); - } + data_ = tempData; + } + return { + collectTime: source.collect_time, + iotaDevice: source.iota_device, + iotaDeviceName: source.iota_device_name, + data: data_ + } + }); + rslt.push({ + sensorId: id, + data: data + }); + } } return rslt; } -async function getDeviceLists(ctx) { + +async function findSensorLastData(ctx) { try { const sensorIds = ctx.request.body.sensorIds; - let rslt = await findDeviceLastData(ctx, sensorIds); + let rslt = await findDeviceLastData(ctx, sensorIds); + // let rslt = [{ sensorId: "2aa1cad1-a52d-4132-8d84-2475034d5bc8", data: [] }, + // { sensorId: "9f1702ff-560d-484e-8572-ef188ef73916", data: [] }, + // { + // sensorId: "360d9098-f2a5-4e1a-ab2b-0bcd3ddcef87", data: [{ + // collectTime: "2021-07-12T05:30:44.000Z", data: { readingNumber: 228 }, + // iotaDevice: "360d9098-f2a5-4e1a-ab2b-0bcd3ddcef87", iotaDeviceName: "水表" + // }] + // }, + // { sensorId: "8c3a636b-9b62-4486-bf54-4ac835aee094", data: [] }, + // { + // sensorId: "9ea4d6cd-f0dc-4604-bb85-112f2591d644", data: [{ + // collectTime: "2021-07-17T05:53:35.783Z", data: { DI4: 0, DI7: 0, DI5: 0, DI1: 1, DI6: 0, DI2: 1, DI8: 0, DI3: 1 }, + // iotaDevice: "9ea4d6cd-f0dc-4604-bb85-112f2591d644", iotaDeviceName: "控制器" + // }] + // }, + // { sensorId: "e18060b4-3c7f-4fad-8a1a-202b5c0bf00c", data: [] } + // ] + ctx.status = 200; + ctx.body = rslt; + } catch (error) { + ctx.status = 400; + ctx.body = { + "name": "FindError", + "message": "原始数据查询失败" + } + } +} + + +async function findAlarmsDevices(ctx, next) { + let rslt = [] + const deviceIds = ctx.request.body + const { limit, state } = ctx.query + try { + if (deviceIds.length) { + for (let deviceId of deviceIds) { + // es search + const client = ctx.app.fs.esclient[ALARM];//准备查询 + let params = { + index: client.config.index, + type: client.config.type, + size: limit || 9999, + body: { + "query": { + "bool": { + "must": [ + { + "match": { + "source_id": deviceId + } + }, + { + "terms": { + "state": [] + } + } + ] + } + }, + "sort": [ + { + "start_time": { + "order": "desc" + } + } + ] + } + } + if (state == 'new') { + let newState = [AlarmState.Creation, AlarmState.CountUpgrade, AlarmState.LevelUpgrade]; + params.body.query.bool.must[1].terms.state = newState; + } + let alarms = await client.search(params); + const timer = ctx.app.fs.timer; + function filterAlarmMsg(oriMsg) { + let msg = []; + for (let s of oriMsg) { + msg.push({ + alarmContent: s._source.alarm_content, + alarmCount: s._source.alarm_count, + deviceId: s._source.source_id, + startTime: timer.toCSTString(s._source.start_time), + endTime: timer.toCSTString(s._source.end_time), + }) + } + return msg; + } + rslt = rslt.concat(filterAlarmMsg(alarms.hits.hits)); + } + } + ctx.status = 200; ctx.body = rslt; - } catch (error) { + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { - "name": "FindError", - "message": "原始数据查询失败" + message: '告警信息查询失败' + } + } +} + +async function findDevicesCardStatus(ctx, next) { + + try { + let rlst = [] + const { clickHouse } = ctx.app.fs + const { deviceIds } = ctx.request.body + if (deviceIds && deviceIds.length) { + const id = `(${deviceIds.map(id => `'${id}'`).join(',')})` + rlst = await clickHouse.dataAlarm.query(` + SELECT cs.DeviceId,cs.Status,MAX(cs.Time) + FROM alarm.CardStatus cs + WHERE cs.DeviceId in ${id} + GROUP BY cs.DeviceId,cs.Status`).toPromise() } - } + ctx.status = 200; + ctx.body = rlst; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: '物联网卡状态查询失败' + } + } } -// try { -// const { clickHouse } = ctx.app.fs -// const { thingIds } = ctx.params -// // const res = thingIds ? await clickHouse.iot.query( -// // `SELECT distinct dv.name,dv.thingId,dv.id,dv.deviceMetaId,re.properties -// // FROM iota.Device dv -// // LEFT JOIN iota.FilteredResource re -// // ON dv.deviceMetaId=re.key -// // WHERE thing_id in (${thingIds})`).toPromise() : [] -// } catch { -// ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); -// ctx.status = 400; -// ctx.body = { -// message: '查询设备列表失败' -// } -// } module.exports = { getOrganizationsStruc, getThingsDeploy, - getDeviceLists + findSensorLastData, + findDeviceMetaDeployed, + findAlarmsDevices, + findDevicesCardStatus } \ No newline at end of file diff --git a/api/app/lib/routes/analysis/network.js b/api/app/lib/routes/analysis/network.js index 94a55ef..c2035df 100644 --- a/api/app/lib/routes/analysis/network.js +++ b/api/app/lib/routes/analysis/network.js @@ -8,10 +8,17 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/things/:thingId/deploy'] = { content: '获取设备部署信息', visible: true }; router.get('/things/:thingId/deploy', network.getThingsDeploy) - + app.fs.api.logAttr['GET/meta/things/:iotaThingId/devices'] = { content: '原始数据查询失败', visible: false }; + router.get('/meta/things/:iotaThingId/devices', network.findDeviceMetaDeployed) + app.fs.api.logAttr['POST/sensors/last/data'] = { content: '原始数据查询失败', visible: true }; - router.post('/sensors/last/data', network.getDeviceLists) + router.post('/sensors/last/data', network.findSensorLastData) + + app.fs.api.logAttr['POST/devices/alarms'] = { content: '获取多个设备的告警信息', visible: false }; + router.post('/devices/alarms', network.findAlarmsDevices) + app.fs.api.logAttr['POST/devices/cardStatus'] = { content: '获取物联网卡状态', visible: false }; + router.post('/devices/cardStatus', network.findDevicesCardStatus); // app.fs.api.logAttr['GET/systemAvailability'] = { content: '获取系统可用性', visible: true }; // router.get('/systemAvailability', operationData.getSystemAvailability) diff --git a/api/config.js b/api/config.js index fe04db6..f582137 100644 --- a/api/config.js +++ b/api/config.js @@ -361,6 +361,21 @@ const product = { index: `${ES_CONTINUITY_NAME}_continue`, type: flags.esType ? flags.esType : '_doc' }, + rawData: { + rootURL: ANXINCLOUD_ES_NODES_REST.split(','), + index: `${PLATFORM_NAME}_raws`, + type: flags.esType ? flags.esType : '_doc' + }, + vbRawData: { + rootURL: ANXINCLOUD_ES_NODES_REST.split(','), + index: `${PLATFORM_NAME}_vbraws`, + type: flags.esType ? flags.esType : '_doc' + }, + alarm: { + rootURL: ANXINCLOUD_ES_NODES_REST.split(','), + index: `${PLATFORM_NAME}_alarms`, + type: flags.esType ? flags.esType : '_doc' + }, } } } diff --git a/web/client/src/layout/containers/layout/index.jsx b/web/client/src/layout/containers/layout/index.jsx index 58e7a78..2a772a6 100644 --- a/web/client/src/layout/containers/layout/index.jsx +++ b/web/client/src/layout/containers/layout/index.jsx @@ -114,7 +114,7 @@ const LayoutContainer = props => { } setAllItems(nextItems) setHeaderItems(topItems) - console.log('topItems',topItems) + // console.log('topItems',topItems) if (lastSelectedKeys) {//如果有缓存 for (let i = 0; i < nextItems.length; i++) { if (JSON.parse(lastSelectedKeys)[0] == nextItems[i].itemKey) { diff --git a/web/client/src/sections/analysis/actions/network.js b/web/client/src/sections/analysis/actions/network.js index 0e4e47b..f049135 100644 --- a/web/client/src/sections/analysis/actions/network.js +++ b/web/client/src/sections/analysis/actions/network.js @@ -27,6 +27,63 @@ export function getThingsDeploy (id) { } +export function findDeviceMetaDeployed (id) { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'FIND_DEVICE_META_DEPLOYED', + url: `${ApiTable.findDeviceMetaDeployed.replace('{iotaThingId}', id)}`, + msg: { error: '获取单个结构物的设备信息失败' }, + reducer: { name: 'deviceMetaDeployed',params: { noClear: true } }, + + }) +} + +export function findSensorLastData (data) { + return dispatch => basicAction({ + type: 'post', + data, + dispatch: dispatch, + actionType: 'FIND_SENSOR_LAST_DATA', + url: `${ApiTable.findSensorLastData}`, + msg: { error: '原始数据查询失败' }, + reducer: { name: 'sensorLastData' } + }) +} + +export function getDevicesAlarms(deviceIds,query) { + return dispatch => basicAction({ + type: 'post', + dispatch: dispatch, + data: deviceIds, + query: query, + actionType: 'REQUEST_POST_DEVICES_ALARMS', + url: `${ApiTable.getDevicesAlarms}?state=new`, + msg: { + error: '获取设备告警信息失败' + }, + reducer: { + name: 'deviceListAlarms' + } + }); +} + + +export function findDevicesCardStatus(deviceIds) { + return dispatch => basicAction({ + type: 'post', + dispatch: dispatch, + data: deviceIds, + actionType: 'FIND_DEVICES_CARD_STATUS', + url: `${ApiTable.findDevicesCardStatus}`, + msg: { + error: '获取物联网卡信息失败' + }, + reducer: { + name: 'devicesCardStatus' + } + }); +} // export function getSystemAvailability() { diff --git a/web/client/src/sections/analysis/components/export-data.jsx b/web/client/src/sections/analysis/components/export-data.jsx new file mode 100644 index 0000000..f610676 --- /dev/null +++ b/web/client/src/sections/analysis/components/export-data.jsx @@ -0,0 +1,582 @@ +'use strict'; +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { Button, Notification } from "@douyinfe/semi-ui"; +import moment from 'moment'; +import XLSX from 'xlsx'; +import { fromJS } from 'immutable'; +import { Request } from '@peace/utils'; +import FileSaver from 'file-saver'; +import { IconArrowDown } from '@douyinfe/semi-icons'; + +//通用前端导出组件 使用方法查看底部propTypes +const ExportData = ({...props}) => { + //const [form] = Form.useForm(); + const [exportLoading, setExportLoading] = useState(false); + const { customRender, title, exportType, style, showIcon } = props; + + + const loop = (data, keypath, values) => { // deal with array + let dkey = keypath.slice(0, 1)[0]; + if (dkey) { + let dvalue = data[dkey]; + let otherKeypath = keypath.slice(1); + if (Array.isArray(dvalue)) { + if (otherKeypath.length) { + let immutableData = fromJS(data); + for (let index = 0; index < dvalue.length; index++) { + let tmp = immutableData.getIn([dkey, index]).toJS(); + loop(tmp, otherKeypath, values); + } + } + } else { + values.push(dvalue); + } + } + return values; + }; + const getColumnData = (opts) => { + const { data, keypath, render, spliter, rawdata, valueEnum } = opts; + let v = null; + let outer = data[keypath[0]]; + if (Array.isArray(outer)) { + let values = loop(data, keypath, []); + v = rawdata ? values : values.join(spliter || ','); + } else { + v = fromJS(data).getIn(keypath) + } + //处理proTable 枚举 + if(valueEnum && valueEnum[v]?.text){ + v = valueEnum[v]?.text; + } + //处理render + // if (render && typeof render === 'function') { + // v = render(outer, data); + + // } + return v; + }; + const getDataSource = (attrs, filterData) => { + debugger + let dataSource = filterData.map(item => { + let record = {}; + attrs.forEach(attr => { + const { key, dataIndex, render, child, valueEnum } = attr; + if (child) { + + record[key] = getDataSource(child, item[key] || []); + } else { + let v = getColumnData({ + data: item, + keypath: Array.isArray(dataIndex) ? dataIndex : [dataIndex], + render: render || null, + valueEnum: valueEnum + }); + record[key] = v; + } + + + }); + + return record; + }); + return dataSource; + + + }; + + const getNewColumns = (attrs) => { + return attrs.filter(f=> f.dataIndex).map(v=>{ + const { dataIndex } = v; + return { + ...v, + key: Array.isArray(dataIndex) ? dataIndex.reduce((p,c)=>{ + p = `${p}${c.trim().replace(c[0], c[0].toUpperCase())}`; + return p + },'') : dataIndex + } + }) + } + //暂时只处理两层 + const getFlatData = (attrs, filterData, dataToAoa, deep = 0) => { + + filterData.map(item => { + let cur = dataToAoa[deep] + if (!cur) { + cur = dataToAoa[deep] = [] + } + attrs.map((attr, index) => { + const { key, child } = attr; + if (child) { + if (Array.isArray(item[key])) { + //getFlatData(child,item[key],dataToAoa,deep) + + item[key].map((s, i) => { + if (i == 0) { + child.map(c => { + cur.push(s[c.key]); + }) + } else { + deep++ + let childCur = dataToAoa[deep] = [] + pushNull(childCur, index); + child.map(c => { + childCur.push(s[c.key]); + }); + } + + }) + + } + } else { + cur.push(item[key]); + } + + }); + deep++ + }); + + + }; + + const getHeader = (headers, excelHeader, deep, perOffset) => { + let offset = 0 + let cur = excelHeader[deep] + if (!cur) { + cur = excelHeader[deep] = [] + } + pushNull(cur, perOffset - cur.length) + for (let i = 0; i < headers.length; i++) { + let head = headers[i] + cur.push(head.name) + if (head.hasOwnProperty('child') && Array.isArray(head.child) && head.child.length > 0) { + let childOffset = getHeader(head.child, excelHeader, deep + 1, cur.length - 1) + pushNull(cur, childOffset - 1) + offset += childOffset + } else { + offset++ + } + } + return offset; + } + + const pushNull = (arr, count) => { + for (let i = 0; i < count; i++) { + arr.push(null) + } + } + const fillNull = (arr) => { + let max = Math.max(...(arr.map(a => a.length))) + arr.filter(e => e.length < max).forEach(e => pushNull(e, max - e.length)) + } + const doMerges = (arr) => { + // 要么横向合并 要么纵向合并 + let deep = arr.length; + let merges = []; + for (let y = 0; y < deep; y++) { + // 先处理横向合并 + let row = arr[y]; + let colSpan = 0 + for (let x = 0; x < row.length; x++) { + if (row[x] === null) { + colSpan++ + if (((x + 1) === row.length) && (colSpan > 0 && x > colSpan)) { + merges.push({ s: { r: y, c: x - colSpan }, e: { r: y, c: x } }) + } + } else if (colSpan > 0 && x > colSpan) { + merges.push({ s: { r: y, c: x - colSpan - 1 }, e: { r: y, c: x - 1 } }) + colSpan = 0 + } else { + colSpan = 0 + } + } + } + // 再处理纵向合并 + let colLength = arr[0].length + for (let x = 0; x < colLength; x++) { + let rowSpan = 0 + for (let y = 0; y < deep; y++) { + if (arr[y][x] != null) { + rowSpan = 0 + } else { + rowSpan++; + } + } + if (rowSpan > 0) { + merges.push({ s: { r: deep - rowSpan - 1, c: x }, e: { r: deep - 1, c: x } }) + } + } + return merges; + } + + //内容暂只出了纵向合并 + const doContetMerges = (arr, headerLength) => { + let deep = arr.length; + let merges = []; + //处理纵向合并 + let colLength = arr[0].length + for (let x = 0; x < colLength; x++) { + let rowSpan = 0; + let mergY = 0; + for (let y = 0; y < deep; y++) { + if (rowSpan > 0) { + //如果还有null 继续加 + if (arr[y][x] === null) { + rowSpan = rowSpan + 1 + } else { + //不为null 增加merge + merges.push({ s: { r: headerLength + (y - rowSpan - 1), c: x }, e: { r: headerLength + y - 1, c: x } }); + rowSpan = 0; + } + } else { + if (arr[y][x] === null) { + rowSpan = rowSpan + 1 + } + } + + } + if (rowSpan > 0) { + merges.push({ s: { r: headerLength + (deep - rowSpan - 1), c: x }, e: { r: headerLength + deep - 1, c: x } }) + rowSpan = 0; + } + } + return merges; + } + + //导出可以纵向合并单元格的数据 不建议使用 + const exportMergeExcel = async () => { + setExportLoading(true) + const { columns, data, fileName, exportUrl, exportQuery, exportBody, requestType, header, showYearMouth } = props || {}; + + let resultData = []; + if (exportUrl) { + + resultData = requestType == 'post' ? await Request.post(exportUrl, exportBody || {}, exportQuery || {}).then(data => { + //数据接口返回的结果 如果是对象 必须把返回数组放入rows + if (typeof data === 'object' && data.rows) { + + return data.rows + + } else { + return data; + } + }, err => { + Notification.error({ + content: '获取数据失败,导出失败!', + duration: 3, + }) + }) : await Request.get(exportUrl, exportQuery || {}).then(data => { + if (typeof data === 'object' && data.rows) { + + return data.rows + + } else { + return data; + } + }, err => { + Notification.error({ + content: '获取数据失败,导出失败!', + duration: 3, + }) + }); + if (!resultData) { + return; + } + + } else { + resultData = data + } + let excelHeader = []; + const newColumns = getNewColumns(columns); + getHeader(newColumns, excelHeader, 0, 0); + fillNull(excelHeader); + + //console.log(excelHeader); + + let loopData = getDataSource(newColumns, resultData); + //console.log(loopData) + + let dataToAoa = []; + getFlatData(newColumns, loopData, dataToAoa, 0); + fillNull(dataToAoa); + //console.log(dataToAoa); + + let aoa = [].concat(excelHeader, dataToAoa); + //console.log(aoa) + + let headerMerges = doMerges(excelHeader); + let contentMerages = doContetMerges(dataToAoa, excelHeader.length); + let merges = [].concat(headerMerges, contentMerages); + // console.log(contentMerages) + + // let opts = { + // defaultCellStyle: { + // font: { name: "宋体", sz: 11, color: { auto: 1 } }, + // border: { + // color: { auto: 1 } + // }, + // alignment: { + // /// 自动换行 + // wrapText: 1, + // // 居中 + // horizontal: "center", + // vertical: "center", + // indent: 0 + // } + // } + // } + let sheet = XLSX.utils.aoa_to_sheet(aoa); + // let newSheet = {}; + // for (let [key, value] of Object.entries(sheet)) { + // if(key == '!ref'){ + // newSheet[key] = value + // }else if(typeof value === 'object'){ + // newSheet[key] = { + // ...value, + // s: opts.defaultCellStyle + // } + // } + // } + const wpx = columns.map(c => { + return { + wpx: Number.parseInt(c.wpx) ? Number.parseInt(c.wpx) : 100 + } + }) + sheet['!cols'] = wpx; + sheet['!merges'] = merges; + + // 构建 workbook 对象 + const workbook = XLSX.utils.book_new(); + + const time = moment().format('YYYY-MM-DD'); + + + XLSX.utils.book_append_sheet(workbook, sheet, 'mySheet'); + // 导出 Excel + XLSX.writeFile(workbook, fileName ? `${fileName}-${time}.xlsx` : `导出数据-${time}.xlsx`); + setExportLoading(false); + Notification.success({ + content: `成功导出了 ${loopData.length || 0} 条数据`, + duration: 3, + }) + } + //FileSaver 方式导出可以自定义样式 columns可定义 headStyle, rowStyle + const exportFileSaver = async () => { + setExportLoading(true) + const { columns, data, fileName, exportUrl, exportQuery, exportBody, requestType } = props || {}; + let resultData = []; + if (exportUrl) { + resultData = requestType == 'post' ? await Request.post(exportUrl, exportBody || {}, exportQuery || {}).then(data => { + //数据接口返回的结果 如果是对象 必须把返回数组放入rows + if (typeof data === 'object') { + return data.data ? data.data : data.rows + } else { + return data; + } + }, err => { + Notification.error({ + content: '获取数据失败,导出失败!', + duration: 3, + }) + }) : await Request.get(exportUrl, exportQuery || {}).then(data => { + + if (typeof data === 'object' && data.rows) { + return data.rows + } else { + return data; + } + }, err => { + Notification.error({ + content: '获取数据失败,导出失败!', + duration: 3, + }) + }); + if (!resultData) { + return; + } + + } else { + resultData = data + } + const newColumns = getNewColumns(columns); + + const loopData = getDataSource(newColumns, resultData); + + let content = ''; + let header = '