Commit 6c311207 authored by 陈龙's avatar 陈龙

feat:升级历史曲线、统计曲线的错误空值交互;剔除预测值的曲线

parent 30223b18
...@@ -24,7 +24,8 @@ const SingleChart = memo((props) => { ...@@ -24,7 +24,8 @@ const SingleChart = memo((props) => {
lineDataType, lineDataType,
showBoxOption, showBoxOption,
special, special,
predicateData predicateData,
emptyOrError
} = props; } = props;
const chartRef = useRef(); const chartRef = useRef();
const timerRef = useRef(); const timerRef = useRef();
...@@ -57,10 +58,16 @@ const SingleChart = memo((props) => { ...@@ -57,10 +58,16 @@ const SingleChart = memo((props) => {
return specialTypeChartOptionGenerator({dataSource, config}); return specialTypeChartOptionGenerator({dataSource, config});
} }
let _option = optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType, predicateData); let _option = optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType, predicateData);
let isEmpty = _option.series.length===0; if (emptyOrError.empty || emptyOrError.error) {
if (isEmpty) { if (isArray(_option.yAxis)) {
_option.yAxis.max=100; _option.yAxis.forEach(item => {
_option.yAxis.min=0; item.max = 100;
item.min = 0;
})
} else {
_option.yAxis.max = 100;
_option.yAxis.min = 0;
}
} }
return _option; return _option;
}, [dataSource, smooth, curveCenter, chartType, predicateData]); }, [dataSource, smooth, curveCenter, chartType, predicateData]);
......
...@@ -69,7 +69,7 @@ export function getSensorType() { ...@@ -69,7 +69,7 @@ export function getSensorType() {
export function getPredicateSensor(params) { export function getPredicateSensor(params) {
return request({ return request({
url: `${baseUrl}/PandaWater/CityWater/PiZhou/GetPredicateSensor`, url: `${monitorDeviceUrl}/GetPredicateSensor`,
method: REQUEST_METHOD_GET, method: REQUEST_METHOD_GET,
params params
}) })
...@@ -84,10 +84,10 @@ export function getStatisticsInfo(data) { ...@@ -84,10 +84,10 @@ export function getStatisticsInfo(data) {
}); });
} }
export function getSensorsRealName (data) { export function getSensorsRealName(data) {
return request({ return request({
url:`${baseUrl}/PandaMonitor/Monitor/Device/GetStaticRealName`, url: `${baseUrl}/PandaMonitor/Monitor/Device/GetStaticRealName`,
method: REQUEST_METHOD_POST, method: REQUEST_METHOD_POST,
data, data,
}) })
} }
\ No newline at end of file
...@@ -211,17 +211,62 @@ import { MobileHistoryChart } from '../mobile'; ...@@ -211,17 +211,62 @@ import { MobileHistoryChart } from '../mobile';
];*/ ];*/
const deviceParams = [ const deviceParams = [
// 新乐,水厂数据异常的问题 // 新乐,水厂数据异常的问题
{ /* {
"deviceCode": "SC00000004", "deviceCode": "SC00000004",
"sensors": "进水瞬时流量,1#出水瞬时流量,2#出水瞬时流量", "sensors": "进水瞬时流量,1#出水瞬时流量,2#出水瞬时流量",
"deviceType": "水厂" "deviceType": "水厂"
} }*/
/* {
"deviceCode": "EGJZ00000073",
"sensors": "进水压力",
"deviceType": "二供机组"
}*/
/* {
"deviceCode": "EGJZ00000006",
"sensors": "进水压力",
"deviceType": "二供机组"
}*/
/* {
"deviceCode": "EGBF00000002",
"deviceType": "二供泵房",
"sensors": "进水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000005",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000001",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000004",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000003",
"sensors": "出水压力"
},
{
"deviceType": "二供机组",
"deviceCode": "EGJZ00000002",
"sensors": "出水压力"
}*/
// 182:8088 报警设备 // 182:8088 报警设备
/* { /* {
"deviceCode": "XMYL00000043", "deviceCode": "XMYL00000043",
"sensors": "进水压力", "sensors": "进水压力",
"deviceType": "熊猫压力表" "deviceType": "熊猫压力表"
}*/ }*/
{
"deviceCode": "LLJ00000001",
"sensors": "瞬时流量",
"deviceType": "流量计"
}
] ]
const Demo = () => { const Demo = () => {
return ( return (
......
...@@ -376,7 +376,11 @@ const HistoryView = (props) => { ...@@ -376,7 +376,11 @@ const HistoryView = (props) => {
const [predicateDevice, setPredicateDevice] = useState(null); const [predicateDevice, setPredicateDevice] = useState(null);
const [predicateData, setPredicateData] = useState([]); const [predicateData, setPredicateData] = useState([]);
const [predicateTime, setPredicateTime] = useState(null); const [predicateTime, setPredicateTime] = useState(null);
// 需要处理默认数据,确保图表能够一直显示坐标轴。用来存储当前的请求状态。
const emptyOrError = useRef({
empty: true,
error: true
})
// 这部分功能有问题,等待解决后上线 2024年3月13日 // 这部分功能有问题,等待解决后上线 2024年3月13日
const [discreteDeviceType, setDiscreteDeviceType] = useState(['水厂']) const [discreteDeviceType, setDiscreteDeviceType] = useState(['水厂'])
// 历史数据相关的特征描述 // 历史数据相关的特征描述
...@@ -1170,6 +1174,7 @@ const HistoryView = (props) => { ...@@ -1170,6 +1174,7 @@ const HistoryView = (props) => {
Promise.all(requestArr) Promise.all(requestArr)
.then((results) => { .then((results) => {
setLoading(false); setLoading(false);
emptyOrError.current.error = false;
if (results.length) { if (results.length) {
let data = []; let data = [];
let _predicateData = []; let _predicateData = [];
...@@ -1234,6 +1239,9 @@ const HistoryView = (props) => { ...@@ -1234,6 +1239,9 @@ const HistoryView = (props) => {
} }
}); });
setLoading(false); setLoading(false);
if (data.length !== 0) {
emptyOrError.current.empty = false;
}
handleTableData(data) handleTableData(data)
setChartDataSource(data); setChartDataSource(data);
setPredicateData(_predicateData); setPredicateData(_predicateData);
...@@ -1356,6 +1364,7 @@ const HistoryView = (props) => { ...@@ -1356,6 +1364,7 @@ const HistoryView = (props) => {
<div className={`${prefixCls}-content`}> <div className={`${prefixCls}-content`}>
{grid === true ? ( {grid === true ? (
<GridChart <GridChart
emptyOrError={emptyOrError.current}
curveCenter={curveCenter} curveCenter={curveCenter}
prefixCls={prefixCls} prefixCls={prefixCls}
dataSource={chartDataSource} dataSource={chartDataSource}
...@@ -1370,6 +1379,7 @@ const HistoryView = (props) => { ...@@ -1370,6 +1379,7 @@ const HistoryView = (props) => {
/> />
) : ( ) : (
<SingleChart <SingleChart
emptyOrError={emptyOrError.current}
dateRange={dateRange} dateRange={dateRange}
showBoxOption={showBoxOption} showBoxOption={showBoxOption}
lineDataType={lineDataType} lineDataType={lineDataType}
...@@ -1432,29 +1442,29 @@ const HistoryView = (props) => { ...@@ -1432,29 +1442,29 @@ const HistoryView = (props) => {
// 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示 // 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示
let _request1 = getPointAddressEntry(_params); let _request1 = getPointAddressEntry(_params);
let _request2 = getSensorType(); let _request2 = getSensorType();
let _request3 = getPredicateSensor({deviceCode, sensors}); // let _request3 = getPredicateSensor({deviceCode, sensors});
await Promise.all([_request0, _request1, _request2, _request3]).then((result) => { await Promise.all([_request0, _request1, _request2]).then((result) => {
if (result) { if (result) {
let _res0 = result[0]; let _res0 = result[0];
let _res1 = result[1]; let _res1 = result[1];
let _res2 = result[2]; let _res2 = result[2];
let _res3 = result[3]; // let _res3 = result[3];
let _checkboxData = [...checkboxData]; let _checkboxData = [...checkboxData];
// 单设备单曲线时,查询是否配置为预测点 // 单设备单曲线时,查询是否配置为预测点
if (_res3.code === 0 && _res3.data) { /* if (_res3.code === 0 && _res3.data) {
// 1. 如果是单曲线,并且配置了预测,那么默认开启预测; // 1. 如果是单曲线,并且配置了预测,那么默认开启预测;
// 2024年3月11日 物联预测功能支撑后,再开发这部分 // 2024年3月11日 物联预测功能支撑后,再开发这部分
/* _checkboxData.push({ _checkboxData.push({
key: 'predicate', key: 'predicate',
label: '数据预测', label: '数据预测',
checked: true, checked: true,
showInCurve: true, showInCurve: true,
showInTable: true, showInTable: true,
})*/ })
setPredicateDevice({..._res3.data, deviceType: '预测'}); setPredicateDevice({..._res3.data, deviceType: '预测'});
} else { } else {
setPredicateDevice(null); setPredicateDevice(null);
} }*/
// 查字典配置 // 查字典配置
if (_res0.code === 0) { if (_res0.code === 0) {
let _opt = _res0.data.reduce((final, cur) => { let _opt = _res0.data.reduce((final, cur) => {
......
...@@ -9,11 +9,17 @@ const Demo = () => { ...@@ -9,11 +9,17 @@ const Demo = () => {
// deviceType: '加压泵站', // deviceType: '加压泵站',
// statisticType: '', // statisticType: '',
// } // }
const params = { /* const params = {
deviceCode: 'LLJ00000001', deviceCode: 'LLJ00000001',
sensors: '今日水量', sensors: '今日水量',
deviceType: '流量计', deviceType: '流量计',
statisticType: '', statisticType: '',
} */
const params = {
deviceCode: 'EGBF00000023',
sensors: '今日供水量',
deviceType: '二供泵房',
statisticType: '',
} }
return ( return (
<> <>
...@@ -24,4 +30,4 @@ const Demo = () => { ...@@ -24,4 +30,4 @@ const Demo = () => {
); );
}; };
export default Demo; export default Demo;
\ No newline at end of file
import React, { useState, useEffect, useRef, useContext } from 'react'; import React, {useState, useEffect, useRef, useContext} from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import moment from 'moment'; import moment from 'moment';
import Empty from '@wisdom-components/empty'; import Empty from '@wisdom-components/empty';
import LoadBox from '@wisdom-components/loadbox'; import LoadBox from '@wisdom-components/loadbox';
import BasicTable from '@wisdom-components/basictable'; import BasicTable from '@wisdom-components/basictable';
import { ExportExcel } from '@wisdom-components/exportexcel'; import {ExportExcel} from '@wisdom-components/exportexcel';
import { ConfigProvider, Select, DatePicker, Radio, Table, Button } from 'antd'; import {ConfigProvider, Select, DatePicker, Radio, Table, Button} from 'antd';
import { VerticalAlignBottomOutlined } from '@ant-design/icons'; import {VerticalAlignBottomOutlined} from '@ant-design/icons';
import { BasicChart } from '@wisdom-components/basicchart'; import {BasicChart} from '@wisdom-components/basicchart';
import { getStatisticsInfo } from './apis'; import {getStatisticsInfo} from './apis';
import './index.less'; import './index.less';
const StatisticalHistoryView = (props) => { const StatisticalHistoryView = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const {getPrefixCls} = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('ec-statistical-history-view'); const prefixCls = getPrefixCls('ec-statistical-history-view');
const chartRef = useRef(null); const chartRef = useRef(null);
const defaultOptionRef = useRef({ const defaultOptionRef = useRef({
title: { title: {
show: false, show: false,
text: '', text: '',
},
tooltip: false,
grid: {
containLabel: true,
left: 20,
right: 20,
// top: 20,
bottom: 10,
},
toolbox: {
show: false,
},
xAxis: [
{
type: 'time',
axisTick: {
alignWithLabel: true,
}, },
boundaryGap: false, tooltip: false,
splitLine: { grid: {
show: true, containLabel: true,
lineStyle: { left: 20,
type: 'dashed', right: 20,
}, // top: 20,
bottom: 10,
}, },
}, toolbox: {
], show: false,
yAxis: [
{
type: 'value',
max:100,
min:0,
position: 'left',
alignTicks: true,
axisLine: {
show: true,
}, },
axisLabel: { xAxis: [
formatter: '{value}', {
}, type: 'time',
}, axisTick: {
], alignWithLabel: true,
series:[{ },
type: 'line', boundaryGap: false,
data:[ splitLine: {
[moment(moment().format('YYYY-MM-DD 00:00:00')).valueOf(),null], show: true,
[moment(moment().format('YYYY-MM-DD 23:59:59')).valueOf(),null], lineStyle: {
] type: 'dashed',
}] },
}); },
const [loading, setLoading] = useState(false); },
const [historyRender, setHistoryRender] = useState(true); ],
const [historyParams, setHistoryParams] = useState({}); yAxis: [
const [columns, setColumns] = useState([ {
{ type: 'value',
title: '时间', max: 100,
dataIndex: 'pt', min: 0,
align: 'center', position: 'left',
width: 100, alignTicks: true,
fixed: 'left', axisLine: {
}, show: true,
]); },
const [dataSource, setDataSource] = useState([]); axisLabel: {
const [options, setOptions] = useState({}); formatter: '{value}',
const [dateValue, setDateValue] = useState('today'); },
const [picker, setPicker] = useState('day'); },
const [time, setTime] = useState({ startTime: '', endTime: '' }); ],
const [dateTime, setDateTime] = useState(moment().format('YYYY-MM-DD HH:mm:ss')); series: [{
type: 'line',
// 时间切换筛选 data: [
const onTimeChange = (e) => { [moment(moment().format('YYYY-MM-DD 00:00:00')).valueOf(), null],
setDateValue(e.target.value); [moment(moment().format('YYYY-MM-DD 23:59:59')).valueOf(), null],
}; ]
}]
// 自定义时间类型
const onPickerChange = (value) => {
setPicker(value);
let start = moment(dateTime).subtract(2, value).startOf(value).format('YYYY-MM-DD 00:00:00');
let end = moment(dateTime).endOf(value).format('YYYY-MM-DD 23:59:59');
setTime({ startDate: start, endDate: end });
};
// 自定义时间选择
const onDateChange = (value, dateString) => {
setDateTime(dateString);
const start = moment(value).subtract(2, picker).startOf(picker).format('YYYY-MM-DD 00:00:00');
const end = moment(value).endOf(picker).format('YYYY-MM-DD 23:59:59');
setTime({ startDate: start, endDate: end });
};
const exportExcelBtn = (e) => {
if (!dataSource.length) return false;
const sheetFilter = columns.map((item) => {
return item.dataIndex;
});
const sheetHeader = columns.map((item) => {
return item.title;
});
const sheetData = dataSource.map((item) => {
return {
pt: item.pt,
value0: String(item.value0),
value1: String(item.value1),
value2: String(item.value2),
};
}); });
ExportExcel({ // 用来判定是否是初始化、是否时报错
name: `${props?.deviceParams?.sensors || ''}指标数据`, const emptyOrError = useRef({
content: [ empty: true,
error: true
})
const [loading, setLoading] = useState(false);
const [historyRender, setHistoryRender] = useState(true);
const [historyParams, setHistoryParams] = useState({});
const [columns, setColumns] = useState([
{ {
sheetData: sheetData, title: '时间',
sheetName: 'sheet1', dataIndex: 'pt',
sheetFilter: sheetFilter, align: 'center',
sheetHeader: sheetHeader, width: 100,
columnWidths: [10, 10, 10, 10], fixed: 'left',
}, },
], ]);
}); const [dataSource, setDataSource] = useState([]);
}; const [options, setOptions] = useState({});
const [dateValue, setDateValue] = useState('today');
const [picker, setPicker] = useState('day');
const [time, setTime] = useState({startTime: '', endTime: ''});
const [dateTime, setDateTime] = useState(moment().format('YYYY-MM-DD HH:mm:ss'));
// 获取历史统计数据 // 时间切换筛选
const getHistoryData = async () => { const onTimeChange = (e) => {
const { deviceCode = '', sensors = '', deviceType = '', statisticType = '' } = historyParams; setDateValue(e.target.value);
const nameTypeList = []; };
if (!deviceCode || !sensors) return setOptions(null);
nameTypeList.push({ // 自定义时间类型
name: sensors, const onPickerChange = (value) => {
type: statisticType || 'Sub', setPicker(value);
}); let start = moment(dateTime).subtract(2, value).startOf(value).format('YYYY-MM-DD 00:00:00');
const params = { let end = moment(dateTime).endOf(value).format('YYYY-MM-DD 23:59:59');
pageIndex: 1, setTime({startDate: start, endDate: end});
pageSize: 999,
nameTypeList: nameTypeList,
accountName: deviceType,
dateFrom: time.startDate,
dateTo: time.endDate,
deviceCode: deviceCode,
dateType: picker,
}; };
setLoading(true);
let results = null;
try {
results = await getStatisticsInfo(params);
} catch (err) {
return setLoading(false);
}
setLoading(false);
const list = results?.data?.list || [];
const dataList = list.length ? list[0] : {};
const dNameDataList = dataList.dNameDataList ? dataList.dNameDataList : [];
const data = dNameDataList.length ? dNameDataList[0] : null;
if (!data) return setOptions(null);
dataMenthod(data);
};
const dataMenthod = (data) => { // 自定义时间选择
const { nameDate } = data; const onDateChange = (value, dateString) => {
let time0 = '', setDateTime(dateString);
time1 = '', const start = moment(value).subtract(2, picker).startOf(picker).format('YYYY-MM-DD 00:00:00');
time2 = ''; const end = moment(value).endOf(picker).format('YYYY-MM-DD 23:59:59');
let data0 = [], setTime({startDate: start, endDate: end});
data1 = [], };
data2 = [];
let timeName = []; const exportExcelBtn = (e) => {
switch (dateValue) { if (!dataSource.length) return false;
case 'today': const sheetFilter = columns.map((item) => {
time0 = moment(time.endDate).subtract(0, 'day').format('YYYY-MM-DD'); return item.dataIndex;
time1 = moment(time.endDate).subtract(1, 'day').format('YYYY-MM-DD');
time2 = moment(time.endDate).subtract(2, 'day').format('YYYY-MM-DD');
timeName = [].concat(dayName);
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY-MM-DD');
const pt = moment(item.time).format('HH时');
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
}); });
break; const sheetHeader = columns.map((item) => {
case 'thisWeek': return item.title;
time0 = moment(time.endDate).subtract(0, 'week').format('WW');
time1 = moment(time.endDate).subtract(1, 'week').format('WW');
time2 = moment(time.endDate).subtract(2, 'week').format('WW');
timeName = [].concat(weekName);
nameDate.forEach((item) => {
const times = moment(item.time).format('WW');
const pt = getWeek(item.time);
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
}); });
break; const sheetData = dataSource.map((item) => {
case 'thisMonth': return {
time0 = moment(time.endDate).subtract(0, 'month').format('YYYY-MM'); pt: item.pt,
time1 = moment(time.endDate).subtract(1, 'month').format('YYYY-MM'); value0: String(item.value0),
time2 = moment(time.endDate).subtract(2, 'month').format('YYYY-MM'); value1: String(item.value1),
timeName = [].concat(monthName); value2: String(item.value2),
nameDate.forEach((item) => { };
const times = moment(item.time).format('YYYY-MM');
const pt = moment(item.time).format('DD日');
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
}); });
break; ExportExcel({
case 'thisYear': name: `${props?.deviceParams?.sensors || ''}指标数据`,
time0 = moment(time.endDate).subtract(0, 'year').format('YYYY'); content: [
time1 = moment(time.endDate).subtract(1, 'year').format('YYYY'); {
time2 = moment(time.endDate).subtract(2, 'year').format('YYYY'); sheetData: sheetData,
timeName = [].concat(yearName); sheetName: 'sheet1',
nameDate.forEach((item) => { sheetFilter: sheetFilter,
const times = moment(item.time).format('YYYY'); sheetHeader: sheetHeader,
const pt = moment(item.time).format('MM月'); columnWidths: [10, 10, 10, 10],
if (times === time0) data0.push({ ...item, pt: pt }); },
if (times === time1) data1.push({ ...item, pt: pt }); ],
if (times === time2) data2.push({ ...item, pt: pt });
}); });
break; };
case 'customer': // 生成对应的数据结构
const style = picker === 'day' ? 'HH时' : picker === 'month' ? 'DD日' : 'MM月'; const returnDataStructure = (dateFrom, dateTo, dateType, dateValue) => {
const format = picker === 'day' ? 'YYYY-MM-DD' : picker === 'month' ? 'YYYY-MM' : 'YYYY'; //
time0 = moment(time.endDate).subtract(0, picker).format(format); let length = new Array(3).fill(false);
time1 = moment(time.endDate).subtract(1, picker).format(format); let finalData = [];
time2 = moment(time.endDate).subtract(2, picker).format(format); if (dateType === 'day') {
timeName = [].concat([time0, time1, time2]); let days = length.map((item, index) => {
nameDate.forEach((item) => { return moment(dateTo).subtract(index, 'days').format('YYYY-MM-DD')
const times = moment(item.time).format(format); });
const pt = moment(item.time).format(style); let hours = new Array(24).fill(false).map((item, index) => {
if (times === time0) data0.push({ ...item, pt: pt }); return index < 10 ? `0${index}` : index;
if (times === time1) data1.push({ ...item, pt: pt }); })
if (times === time2) data2.push({ ...item, pt: pt }); days.forEach(day => {
hours.forEach(hour => {
finalData.push(`${day} ${hour}`);
})
})
}
if (dateType === 'month') {
let months = length.map((item, index) => {
return moment(dateTo).subtract(index, 'months').format('YYYY-MM')
});
let days = new Array(31).fill(false).map((item, index) => {
return index < 9 ? `0${index + 1}` : index + 1;
})
months.forEach(month => {
days.forEach(day => {
finalData.push(`${month} ${day}`);
})
})
}
if (dateType === 'year') {
let years = length.map((item, index) => {
return moment(dateTo).subtract(index, 'years').format('YYYY')
});
let months = new Array(12).fill(false).map((item, index) => {
return index < 9 ? `0${index + 1}` : index + 1;
})
years.forEach(year => {
months.forEach(month => {
finalData.push(`${year} ${month}`);
})
})
}
return finalData.map(item => {
return {
time: item,
value: null,
}
}); });
break; };
const handleDataForEmptyOrError = () => {
let _data = returnDataStructure(time.startDate, time.endDate, picker, dateValue);
dataMenthod({nameDate: _data, dName: props?.deviceParams?.sensors ?? ''});
} }
const dataChart = { // 获取历史统计数据
data: [data0, data1, data2], const getHistoryData = async () => {
name: timeName, const {deviceCode = '', sensors = '', deviceType = '', statisticType = ''} = historyParams;
const nameTypeList = [];
if (!deviceCode || !sensors) return setOptions(null);
nameTypeList.push({
name: sensors,
type: statisticType || 'Sub',
});
const params = {
pageIndex: 1,
pageSize: 999,
nameTypeList: nameTypeList,
accountName: deviceType,
dateFrom: time.startDate,
dateTo: time.endDate,
deviceCode: deviceCode,
dateType: picker,
};
setLoading(true);
let results = null;
try {
results = await getStatisticsInfo(params);
emptyOrError.current.error = false;
} catch (err) {
if (historyParams.sensors) {
handleDataForEmptyOrError()
}
return setLoading(false);
}
setLoading(false);
const list = results?.data?.list || [];
if (list.length === 0) {
handleDataForEmptyOrError()
}
const dataList = list.length ? list[0] : {};
const dNameDataList = dataList.dNameDataList ? dataList.dNameDataList : [];
const data = dNameDataList.length ? dNameDataList[0] : null;
if (!data) return setOptions(null);
dataMenthod(data);
}; };
const _data = [data0, data1, data2].sort((a, b) => {
return b.length - a.length;
})
const dataTable = _data[0].map((item, index) => {
return {
...item,
value0: data0[index] ? data0[index]?.value === 0 || data0[index]?.value ? data0[index]?.value : '-' : '',
value1: data1[index] ? data1[index]?.value === 0 || data1[index]?.value ? data1[index]?.value : '-' : '',
value2: data2[index] ? data2[index]?.value === 0 || data2[index]?.value ? data2[index]?.value : '-' : '',
};
});
renderChart(dataChart, data);
renderTable(dataTable, timeName);
};
const renderChart = (dataInfo, data) => { const dataMenthod = (data) => {
if (!dataInfo) return setOptions(null); const {nameDate} = data;
const { unit, dName } = data; nameDate.forEach(item => {
const series = []; if (item.value !== null) emptyOrError.current.empty = false;
let xData = []; })
dataInfo.data.forEach((item, index) => { let time0 = '',
const config = !index && dName.indexOf('流量') > -1 ? { areaStyle: {} } : {}; time1 = '',
const style = index ? { lineStyle: { normal: { type: 'dashed' } } } : {}; time2 = '';
const list = { let data0 = [],
name: dataInfo.name[index], data1 = [],
type: 'line', data2 = [];
smooth: true, let timeName = [];
...config, switch (dateValue) {
...style, case 'today':
data: item.map((arr) => { time0 = moment(time.endDate).subtract(0, 'day').format('YYYY-MM-DD');
return { time1 = moment(time.endDate).subtract(1, 'day').format('YYYY-MM-DD');
name: arr.pt, time2 = moment(time.endDate).subtract(2, 'day').format('YYYY-MM-DD');
value: arr.value, timeName = [].concat(dayName);
}; nameDate.forEach((item) => {
}), const times = moment(item.time).format('YYYY-MM-DD');
}; const pt = moment(item.time).format('HH时');
series.push(list); if (times === time0) data0.push({...item, pt: pt});
xData = item.map((arr) => { if (times === time1) data1.push({...item, pt: pt});
return arr.pt; if (times === time2) data2.push({...item, pt: pt});
}); });
}); break;
const option = { case 'thisWeek':
title: { time0 = moment(time.endDate).subtract(0, 'week').format('WW');
show: false, time1 = moment(time.endDate).subtract(1, 'week').format('WW');
text: '', time2 = moment(time.endDate).subtract(2, 'week').format('WW');
}, timeName = [].concat(weekName);
tooltip: { nameDate.forEach((item) => {
trigger: 'axis', const times = moment(item.time).format('WW');
axisPointer: { const pt = getWeek(item.time);
type: 'cross', if (times === time0) data0.push({...item, pt: pt});
}, if (times === time1) data1.push({...item, pt: pt});
}, if (times === time2) data2.push({...item, pt: pt});
grid: { });
containLabel: true, break;
left: 20, case 'thisMonth':
right: 20, time0 = moment(time.endDate).subtract(0, 'month').format('YYYY-MM');
// top: 20, time1 = moment(time.endDate).subtract(1, 'month').format('YYYY-MM');
bottom: 10, time2 = moment(time.endDate).subtract(2, 'month').format('YYYY-MM');
}, timeName = [].concat(monthName);
toolbox: { nameDate.forEach((item) => {
show: false, const times = moment(item.time).format('YYYY-MM');
}, const pt = moment(item.time).format('DD日');
legend: { if (times === time0) data0.push({...item, pt: pt});
left: 'center', if (times === time1) data1.push({...item, pt: pt});
}, if (times === time2) data2.push({...item, pt: pt});
xAxis: [ });
{ break;
type: 'category', case 'thisYear':
axisTick: { time0 = moment(time.endDate).subtract(0, 'year').format('YYYY');
alignWithLabel: true, time1 = moment(time.endDate).subtract(1, 'year').format('YYYY');
}, time2 = moment(time.endDate).subtract(2, 'year').format('YYYY');
boundaryGap: false, timeName = [].concat(yearName);
splitLine: { nameDate.forEach((item) => {
show: true, const times = moment(item.time).format('YYYY');
lineStyle: { const pt = moment(item.time).format('MM月');
type: 'dashed', if (times === time0) data0.push({...item, pt: pt});
}, if (times === time1) data1.push({...item, pt: pt});
}, if (times === time2) data2.push({...item, pt: pt});
data: xData, });
}, break;
], case 'customer':
yAxis: [ const style = picker === 'day' ? 'HH时' : picker === 'month' ? 'DD日' : 'MM月';
{ const format = picker === 'day' ? 'YYYY-MM-DD' : picker === 'month' ? 'YYYY-MM' : 'YYYY';
type: 'value', time0 = moment(time.endDate).subtract(0, picker).format(format);
name: unit, time1 = moment(time.endDate).subtract(1, picker).format(format);
position: 'left', time2 = moment(time.endDate).subtract(2, picker).format(format);
alignTicks: true, timeName = [].concat([time0, time1, time2]);
axisLine: { nameDate.forEach((item) => {
show: true, const times = moment(item.time).format(format);
}, const pt = moment(item.time).format(style);
axisLabel: { if (times === time0) data0.push({...item, pt: pt});
formatter: '{value}', if (times === time1) data1.push({...item, pt: pt});
}, if (times === time2) data2.push({...item, pt: pt});
}, });
], break;
series: series, }
const dataChart = {
data: [data0, data1, data2],
name: timeName,
};
const _data = [data0, data1, data2].sort((a, b) => {
return b.length - a.length;
})
const dataTable = _data[0].map((item, index) => {
return {
...item,
value0: data0[index] ? data0[index]?.value === 0 || data0[index]?.value ? data0[index]?.value : '-' : '',
value1: data1[index] ? data1[index]?.value === 0 || data1[index]?.value ? data1[index]?.value : '-' : '',
value2: data2[index] ? data2[index]?.value === 0 || data2[index]?.value ? data2[index]?.value : '-' : '',
};
});
renderChart(dataChart, data);
renderTable(dataTable, timeName);
}; };
setOptions(option);
};
const renderTable = (dataInfo, timeName) => { const renderChart = (dataInfo, data) => {
const dataIndex = ['value0', 'value1', 'value2']; if (!dataInfo) return setOptions(null);
const column1 = [ const {unit, dName} = data;
{ const series = [];
title: '时间', let xData = [];
dataIndex: 'pt', dataInfo.data.forEach((item, index) => {
align: 'center', const config = !index && dName.indexOf('流量') > -1 ? {areaStyle: {}} : {};
width: 100, const style = index ? {lineStyle: {normal: {type: 'dashed'}}} : {};
fixed: 'left', const list = {
}, name: dataInfo.name[index],
]; type: 'line',
const column2 = timeName.map((item, index) => { smooth: true,
return { ...config,
title: item, ...style,
dataIndex: dataIndex[index], data: item.map((arr) => {
align: 'center', return {
}; name: arr.pt,
}); value: arr.value,
const column = column1.concat(column2); };
setColumns(column); }),
setDataSource(dataInfo); };
}; series.push(list);
xData = item.map((arr) => {
return arr.pt;
});
});
let showMinMax = emptyOrError.current.empty && emptyOrError.current.error;
const option = {
title: {
show: false,
text: '',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
grid: {
containLabel: true,
left: 20,
right: 20,
// top: 20,
bottom: 10,
},
toolbox: {
show: false,
},
legend: {
left: 'center',
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true,
},
boundaryGap: false,
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
},
},
data: xData,
},
],
yAxis: [
{
type: 'value',
name: unit,
position: 'left',
alignTicks: true,
axisLine: {
show: true,
},
axisLabel: {
formatter: '{value}',
},
...(showMinMax ? {min: 0, max: 100} : {})
},
],
series: series,
};
setOptions(option);
};
const getWeek = (date) => { const renderTable = (dataInfo, timeName) => {
const weekTime = moment(date).day(); const dataIndex = ['value0', 'value1', 'value2'];
switch (weekTime) { const column1 = [
case 1: {
return '周一'; title: '时间',
break; dataIndex: 'pt',
case 2: align: 'center',
return '周二'; width: 100,
break; fixed: 'left',
case 3: },
return '周三'; ];
break; const column2 = timeName.map((item, index) => {
case 4: return {
return '周四'; title: item,
break; dataIndex: dataIndex[index],
case 5: align: 'center',
return '周五'; };
break; });
case 6: const column = column1.concat(column2);
return '周六'; setColumns(column);
break; setDataSource(dataInfo);
case 0: };
return '周日';
break;
}
};
const Summary = (currentData) => { const getWeek = (date) => {
return ( const weekTime = moment(date).day();
<Table.Summary.Row> switch (weekTime) {
{columns.map((item, index) => { case 1:
let sum = 0; return '周一';
currentData.reduce((prev, next) => { break;
sum += next[item.dataIndex] === '-' || next[item.dataIndex] === '' ? 0 : next[item.dataIndex]; case 2:
}, 0); return '周二';
return ( break;
<Table.Summary.Cell key={item.dataIndex} index={index} align={'center'}> case 3:
{index === 0 ? '总计' : sum.toFixed(0)} return '周三';
</Table.Summary.Cell> break;
); case 4:
})} return '周四';
</Table.Summary.Row> break;
); case 5:
}; return '周五';
break;
case 6:
return '周六';
break;
case 0:
return '周日';
break;
}
};
useEffect(() => { const Summary = (currentData) => {
setHistoryParams(props.deviceParams || {}); return (
}, [props.deviceParams]); <Table.Summary.Row>
{columns.map((item, index) => {
let sum = 0;
currentData.reduce((prev, next) => {
sum += next[item.dataIndex] === '-' || next[item.dataIndex] === '' ? 0 : next[item.dataIndex];
}, 0);
return (
<Table.Summary.Cell key={item.dataIndex} index={index} align={'center'}>
{index === 0 ? '总计' : sum.toFixed(0)}
</Table.Summary.Cell>
);
})}
</Table.Summary.Row>
);
};
useEffect(() => {
if (props?.deviceParams?.sensors) {
handleDataForEmptyOrError()
}
}, [])
useEffect(() => {
setHistoryParams(props.deviceParams || {});
}, [props.deviceParams]);
useEffect(() => { useEffect(() => {
let start = '', let start = '',
end = ''; end = '';
switch (dateValue) { switch (dateValue) {
case 'today': case 'today':
start = moment().subtract(2, 'day').format('YYYY-MM-DD 00:00:00'); start = moment().subtract(2, 'day').format('YYYY-MM-DD 00:00:00');
end = moment().format('YYYY-MM-DD 23:59:59'); end = moment().format('YYYY-MM-DD 23:59:59');
setPicker('day'); setPicker('day');
break; break;
case 'thisWeek': case 'thisWeek':
start = moment().startOf('week').subtract(2, 'week').format('YYYY-MM-DD 00:00:00'); start = moment().startOf('week').subtract(2, 'week').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('week').format('YYYY-MM-DD 23:59:59'); end = moment().endOf('week').format('YYYY-MM-DD 23:59:59');
setPicker('month'); setPicker('month');
break; break;
case 'thisMonth': case 'thisMonth':
start = moment().startOf('month').subtract(2, 'month').format('YYYY-MM-DD 00:00:00'); start = moment().startOf('month').subtract(2, 'month').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('month').format('YYYY-MM-DD 23:59:59'); end = moment().endOf('month').format('YYYY-MM-DD 23:59:59');
setPicker('month'); setPicker('month');
break; break;
case 'thisYear': case 'thisYear':
start = moment().startOf('year').subtract(2, 'year').format('YYYY-MM-DD 00:00:00'); start = moment().startOf('year').subtract(2, 'year').format('YYYY-MM-DD 00:00:00');
end = moment().endOf('year').format('YYYY-MM-DD 23:59:59'); end = moment().endOf('year').format('YYYY-MM-DD 23:59:59');
setPicker('year'); setPicker('year');
break; break;
case 'customer': case 'customer':
start = moment(dateTime).startOf(picker).subtract(2, picker).format('YYYY-MM-DD 00:00:00'); start = moment(dateTime).startOf(picker).subtract(2, picker).format('YYYY-MM-DD 00:00:00');
end = moment(dateTime).endOf(picker).format('YYYY-MM-DD 23:59:59'); end = moment(dateTime).endOf(picker).format('YYYY-MM-DD 23:59:59');
break; break;
} }
setTime({ startDate: start, endDate: end }); setTime({startDate: start, endDate: end});
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [dateValue]); }, [dateValue]);
useEffect(() => { useEffect(() => {
getHistoryData(); getHistoryData();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [time, historyParams, picker]); }, [time, historyParams, picker]);
return ( return (
<div className={classNames(prefixCls)}> <div className={classNames(prefixCls)}>
<div className={classNames(`${prefixCls}-box`)}> <div className={classNames(`${prefixCls}-box`)}>
<div className={classNames(`${prefixCls}-header`)}> <div className={classNames(`${prefixCls}-header`)}>
<div className={classNames(`${prefixCls}-time`)}> <div className={classNames(`${prefixCls}-time`)}>
<span>时间选择:</span> <span>时间选择:</span>
<Radio.Group value={dateValue} defaultValue={dateList[0].key} onChange={onTimeChange}> <Radio.Group value={dateValue} defaultValue={dateList[0].key} onChange={onTimeChange}>
{dateList.map((item) => ( {dateList.map((item) => (
<Radio.Button key={item.key} value={item.key}> <Radio.Button key={item.key} value={item.key}>
{item.name} {item.name}
</Radio.Button> </Radio.Button>
))} ))}
</Radio.Group> </Radio.Group>
{dateValue === 'customer' && ( {dateValue === 'customer' && (
<> <>
<Select <Select
defaultValue="day" defaultValue="day"
value={picker} value={picker}
options={timeList} options={timeList}
onChange={onPickerChange} onChange={onPickerChange}
className={classNames(`${prefixCls}-select`)} className={classNames(`${prefixCls}-select`)}
/> />
<DatePicker onChange={onDateChange} value={moment(dateTime)} picker={picker} allowClear={false}/> <DatePicker onChange={onDateChange} value={moment(dateTime)} picker={picker}
</> allowClear={false}/>
</>
)}
</div>
<Button
className={classNames(`${prefixCls}-down-load`)}
type="primary"
onClick={exportExcelBtn}
disabled={!dataSource.length}
>
<VerticalAlignBottomOutlined/>
下载
</Button>
</div>
<div className={classNames(`${prefixCls}-content`)}>
{
<>
<div className={classNames(`${prefixCls}-chart`)}>
{
<BasicChart
ref={chartRef}
option={(!options || !options?.series) ? defaultOptionRef.current : options}
notMerge
style={{width: '100%', height: '100%'}}
/>
}
</div>
<div className={classNames(`${prefixCls}-table`)}>
<BasicTable
dataSource={dataSource}
columns={columns}
pagination={false}
bordered={true}
onRow={(record, index) => {
return {
onMouseEnter: (event) => {
let seriesIndex = 0;
const dataIndex = ['value0', 'value1', 'value2'];
seriesIndex = dataIndex.findIndex((item) => {
return record[item] !== '-';
});
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'showTip',
seriesIndex: seriesIndex,
dataIndex: index,
});
}, // 鼠标移入行
onMouseLeave: (event) => {
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'hideTip',
dataIndex: index,
});
}, // 鼠标移出行
};
}}
scroll={{x: '100%', y: 'calc(100% - 40px)'}}
summary={Summary}
/>
</div>
</>
}
</div>
</div>
{loading && (
<div className={classNames(`${prefixCls}-load-box`)}>
<LoadBox spinning={loading}/>
</div>
)} )}
</div>
<Button
className={classNames(`${prefixCls}-down-load`)}
type="primary"
onClick={exportExcelBtn}
disabled={!dataSource.length}
>
<VerticalAlignBottomOutlined />
下载
</Button>
</div> </div>
<div className={classNames(`${prefixCls}-content`)}> );
{
<>
<div className={classNames(`${prefixCls}-chart`)}>
{
<BasicChart
ref={chartRef}
option={(!options||!options?.series) ? defaultOptionRef.current : options}
notMerge
style={{ width: '100%', height: '100%' }}
/>
}
</div>
<div className={classNames(`${prefixCls}-table`)}>
<BasicTable
dataSource={dataSource}
columns={columns}
pagination={false}
bordered={true}
onRow={(record, index) => {
return {
onMouseEnter: (event) => {
let seriesIndex = 0;
const dataIndex = ['value0', 'value1', 'value2'];
seriesIndex = dataIndex.findIndex((item) => {
return record[item] !== '-';
});
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'showTip',
seriesIndex: seriesIndex,
dataIndex: index,
});
}, // 鼠标移入行
onMouseLeave: (event) => {
chartRef?.current?.getEchartsInstance() &&
chartRef?.current?.getEchartsInstance().dispatchAction({
type: 'hideTip',
dataIndex: index,
});
}, // 鼠标移出行
};
}}
scroll={{ x: '100%', y: 'calc(100% - 40px)' }}
summary={Summary}
/>
</div>
</>
}
</div>
</div>
{loading && (
<div className={classNames(`${prefixCls}-load-box`)}>
<LoadBox spinning={loading} />
</div>
)}
</div>
);
}; };
export default StatisticalHistoryView; export default StatisticalHistoryView;
const dateList = [ const dateList = [
{ {
key: 'today', key: 'today',
name: '今日', name: '今日',
}, },
// { // {
// key: 'thisWeek', // key: 'thisWeek',
// name: '本周', // name: '本周',
// }, // },
{ {
key: 'thisMonth', key: 'thisMonth',
name: '本月', name: '本月',
}, },
{ {
key: 'thisYear', key: 'thisYear',
name: '今年', name: '今年',
}, },
{ {
key: 'customer', key: 'customer',
name: '自定义', name: '自定义',
}, },
]; ];
const timeList = [ const timeList = [
{ {
value: 'day', value: 'day',
label: '日', label: '日',
}, },
{ {
value: 'month', value: 'month',
label: '月', label: '月',
}, },
{ {
value: 'year', value: 'year',
label: '年', label: '年',
}, },
]; ];
const dayName = ['今日', '昨日', '前日']; const dayName = ['今日', '昨日', '前日'];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment