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

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

parent 30223b18
......@@ -24,7 +24,8 @@ const SingleChart = memo((props) => {
lineDataType,
showBoxOption,
special,
predicateData
predicateData,
emptyOrError
} = props;
const chartRef = useRef();
const timerRef = useRef();
......@@ -57,10 +58,16 @@ const SingleChart = memo((props) => {
return specialTypeChartOptionGenerator({dataSource, config});
}
let _option = optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType, predicateData);
let isEmpty = _option.series.length===0;
if (isEmpty) {
_option.yAxis.max=100;
_option.yAxis.min=0;
if (emptyOrError.empty || emptyOrError.error) {
if (isArray(_option.yAxis)) {
_option.yAxis.forEach(item => {
item.max = 100;
item.min = 0;
})
} else {
_option.yAxis.max = 100;
_option.yAxis.min = 0;
}
}
return _option;
}, [dataSource, smooth, curveCenter, chartType, predicateData]);
......
......@@ -69,7 +69,7 @@ export function getSensorType() {
export function getPredicateSensor(params) {
return request({
url: `${baseUrl}/PandaWater/CityWater/PiZhou/GetPredicateSensor`,
url: `${monitorDeviceUrl}/GetPredicateSensor`,
method: REQUEST_METHOD_GET,
params
})
......@@ -84,9 +84,9 @@ export function getStatisticsInfo(data) {
});
}
export function getSensorsRealName (data) {
export function getSensorsRealName(data) {
return request({
url:`${baseUrl}/PandaMonitor/Monitor/Device/GetStaticRealName`,
url: `${baseUrl}/PandaMonitor/Monitor/Device/GetStaticRealName`,
method: REQUEST_METHOD_POST,
data,
})
......
......@@ -211,17 +211,62 @@ import { MobileHistoryChart } from '../mobile';
];*/
const deviceParams = [
// 新乐,水厂数据异常的问题
{
/* {
"deviceCode": "SC00000004",
"sensors": "进水瞬时流量,1#出水瞬时流量,2#出水瞬时流量",
"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 报警设备
/* {
"deviceCode": "XMYL00000043",
"sensors": "进水压力",
"deviceType": "熊猫压力表"
}*/
{
"deviceCode": "LLJ00000001",
"sensors": "瞬时流量",
"deviceType": "流量计"
}
]
const Demo = () => {
return (
......
......@@ -376,7 +376,11 @@ const HistoryView = (props) => {
const [predicateDevice, setPredicateDevice] = useState(null);
const [predicateData, setPredicateData] = useState([]);
const [predicateTime, setPredicateTime] = useState(null);
// 需要处理默认数据,确保图表能够一直显示坐标轴。用来存储当前的请求状态。
const emptyOrError = useRef({
empty: true,
error: true
})
// 这部分功能有问题,等待解决后上线 2024年3月13日
const [discreteDeviceType, setDiscreteDeviceType] = useState(['水厂'])
// 历史数据相关的特征描述
......@@ -1170,6 +1174,7 @@ const HistoryView = (props) => {
Promise.all(requestArr)
.then((results) => {
setLoading(false);
emptyOrError.current.error = false;
if (results.length) {
let data = [];
let _predicateData = [];
......@@ -1234,6 +1239,9 @@ const HistoryView = (props) => {
}
});
setLoading(false);
if (data.length !== 0) {
emptyOrError.current.empty = false;
}
handleTableData(data)
setChartDataSource(data);
setPredicateData(_predicateData);
......@@ -1356,6 +1364,7 @@ const HistoryView = (props) => {
<div className={`${prefixCls}-content`}>
{grid === true ? (
<GridChart
emptyOrError={emptyOrError.current}
curveCenter={curveCenter}
prefixCls={prefixCls}
dataSource={chartDataSource}
......@@ -1370,6 +1379,7 @@ const HistoryView = (props) => {
/>
) : (
<SingleChart
emptyOrError={emptyOrError.current}
dateRange={dateRange}
showBoxOption={showBoxOption}
lineDataType={lineDataType}
......@@ -1432,29 +1442,29 @@ const HistoryView = (props) => {
// 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示
let _request1 = getPointAddressEntry(_params);
let _request2 = getSensorType();
let _request3 = getPredicateSensor({deviceCode, sensors});
await Promise.all([_request0, _request1, _request2, _request3]).then((result) => {
// let _request3 = getPredicateSensor({deviceCode, sensors});
await Promise.all([_request0, _request1, _request2]).then((result) => {
if (result) {
let _res0 = result[0];
let _res1 = result[1];
let _res2 = result[2];
let _res3 = result[3];
// let _res3 = result[3];
let _checkboxData = [...checkboxData];
// 单设备单曲线时,查询是否配置为预测点
if (_res3.code === 0 && _res3.data) {
/* if (_res3.code === 0 && _res3.data) {
// 1. 如果是单曲线,并且配置了预测,那么默认开启预测;
// 2024年3月11日 物联预测功能支撑后,再开发这部分
/* _checkboxData.push({
_checkboxData.push({
key: 'predicate',
label: '数据预测',
checked: true,
showInCurve: true,
showInTable: true,
})*/
})
setPredicateDevice({..._res3.data, deviceType: '预测'});
} else {
setPredicateDevice(null);
}
}*/
// 查字典配置
if (_res0.code === 0) {
let _opt = _res0.data.reduce((final, cur) => {
......
......@@ -9,11 +9,17 @@ const Demo = () => {
// deviceType: '加压泵站',
// statisticType: '',
// }
const params = {
/* const params = {
deviceCode: 'LLJ00000001',
sensors: '今日水量',
deviceType: '流量计',
statisticType: '',
} */
const params = {
deviceCode: 'EGBF00000023',
sensors: '今日供水量',
deviceType: '二供泵房',
statisticType: '',
}
return (
<>
......
import React, { useState, useEffect, useRef, useContext } from 'react';
import React, {useState, useEffect, useRef, useContext} from 'react';
import classNames from 'classnames';
import moment from 'moment';
import Empty from '@wisdom-components/empty';
import LoadBox from '@wisdom-components/loadbox';
import BasicTable from '@wisdom-components/basictable';
import { ExportExcel } from '@wisdom-components/exportexcel';
import { ConfigProvider, Select, DatePicker, Radio, Table, Button } from 'antd';
import { VerticalAlignBottomOutlined } from '@ant-design/icons';
import { BasicChart } from '@wisdom-components/basicchart';
import { getStatisticsInfo } from './apis';
import {ExportExcel} from '@wisdom-components/exportexcel';
import {ConfigProvider, Select, DatePicker, Radio, Table, Button} from 'antd';
import {VerticalAlignBottomOutlined} from '@ant-design/icons';
import {BasicChart} from '@wisdom-components/basicchart';
import {getStatisticsInfo} from './apis';
import './index.less';
const StatisticalHistoryView = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const {getPrefixCls} = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('ec-statistical-history-view');
const chartRef = useRef(null);
const defaultOptionRef = useRef({
......@@ -49,8 +49,8 @@ const StatisticalHistoryView = (props) => {
yAxis: [
{
type: 'value',
max:100,
min:0,
max: 100,
min: 0,
position: 'left',
alignTicks: true,
axisLine: {
......@@ -61,14 +61,19 @@ const StatisticalHistoryView = (props) => {
},
},
],
series:[{
series: [{
type: 'line',
data:[
[moment(moment().format('YYYY-MM-DD 00:00:00')).valueOf(),null],
[moment(moment().format('YYYY-MM-DD 23:59:59')).valueOf(),null],
data: [
[moment(moment().format('YYYY-MM-DD 00:00:00')).valueOf(), null],
[moment(moment().format('YYYY-MM-DD 23:59:59')).valueOf(), null],
]
}]
});
// 用来判定是否是初始化、是否时报错
const emptyOrError = useRef({
empty: true,
error: true
})
const [loading, setLoading] = useState(false);
const [historyRender, setHistoryRender] = useState(true);
const [historyParams, setHistoryParams] = useState({});
......@@ -85,7 +90,7 @@ const StatisticalHistoryView = (props) => {
const [options, setOptions] = useState({});
const [dateValue, setDateValue] = useState('today');
const [picker, setPicker] = useState('day');
const [time, setTime] = useState({ startTime: '', endTime: '' });
const [time, setTime] = useState({startTime: '', endTime: ''});
const [dateTime, setDateTime] = useState(moment().format('YYYY-MM-DD HH:mm:ss'));
// 时间切换筛选
......@@ -98,7 +103,7 @@ const StatisticalHistoryView = (props) => {
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 });
setTime({startDate: start, endDate: end});
};
// 自定义时间选择
......@@ -106,7 +111,7 @@ const StatisticalHistoryView = (props) => {
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 });
setTime({startDate: start, endDate: end});
};
const exportExcelBtn = (e) => {
......@@ -138,10 +143,64 @@ const StatisticalHistoryView = (props) => {
],
});
};
// 生成对应的数据结构
const returnDataStructure = (dateFrom, dateTo, dateType, dateValue) => {
//
let length = new Array(3).fill(false);
let finalData = [];
if (dateType === 'day') {
let days = length.map((item, index) => {
return moment(dateTo).subtract(index, 'days').format('YYYY-MM-DD')
});
let hours = new Array(24).fill(false).map((item, index) => {
return index < 10 ? `0${index}` : index;
})
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,
}
});
};
const handleDataForEmptyOrError = () => {
let _data = returnDataStructure(time.startDate, time.endDate, picker, dateValue);
dataMenthod({nameDate: _data, dName: props?.deviceParams?.sensors ?? ''});
}
// 获取历史统计数据
const getHistoryData = async () => {
const { deviceCode = '', sensors = '', deviceType = '', statisticType = '' } = historyParams;
const {deviceCode = '', sensors = '', deviceType = '', statisticType = ''} = historyParams;
const nameTypeList = [];
if (!deviceCode || !sensors) return setOptions(null);
nameTypeList.push({
......@@ -162,11 +221,18 @@ const StatisticalHistoryView = (props) => {
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;
......@@ -175,7 +241,10 @@ const StatisticalHistoryView = (props) => {
};
const dataMenthod = (data) => {
const { nameDate } = data;
const {nameDate} = data;
nameDate.forEach(item => {
if (item.value !== null) emptyOrError.current.empty = false;
})
let time0 = '',
time1 = '',
time2 = '';
......@@ -192,9 +261,9 @@ const StatisticalHistoryView = (props) => {
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 });
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 'thisWeek':
......@@ -205,9 +274,9 @@ const StatisticalHistoryView = (props) => {
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 });
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 'thisMonth':
......@@ -218,9 +287,9 @@ const StatisticalHistoryView = (props) => {
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 });
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 'thisYear':
......@@ -231,9 +300,9 @@ const StatisticalHistoryView = (props) => {
nameDate.forEach((item) => {
const times = moment(item.time).format('YYYY');
const pt = moment(item.time).format('MM月');
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
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':
......@@ -246,9 +315,9 @@ const StatisticalHistoryView = (props) => {
nameDate.forEach((item) => {
const times = moment(item.time).format(format);
const pt = moment(item.time).format(style);
if (times === time0) data0.push({ ...item, pt: pt });
if (times === time1) data1.push({ ...item, pt: pt });
if (times === time2) data2.push({ ...item, pt: pt });
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;
}
......@@ -273,12 +342,12 @@ const StatisticalHistoryView = (props) => {
const renderChart = (dataInfo, data) => {
if (!dataInfo) return setOptions(null);
const { unit, dName } = data;
const {unit, dName} = data;
const series = [];
let xData = [];
dataInfo.data.forEach((item, index) => {
const config = !index && dName.indexOf('流量') > -1 ? { areaStyle: {} } : {};
const style = index ? { lineStyle: { normal: { type: 'dashed' } } } : {};
const config = !index && dName.indexOf('流量') > -1 ? {areaStyle: {}} : {};
const style = index ? {lineStyle: {normal: {type: 'dashed'}}} : {};
const list = {
name: dataInfo.name[index],
type: 'line',
......@@ -297,6 +366,7 @@ const StatisticalHistoryView = (props) => {
return arr.pt;
});
});
let showMinMax = emptyOrError.current.empty && emptyOrError.current.error;
const option = {
title: {
show: false,
......@@ -349,6 +419,7 @@ const StatisticalHistoryView = (props) => {
axisLabel: {
formatter: '{value}',
},
...(showMinMax ? {min: 0, max: 100} : {})
},
],
series: series,
......@@ -423,7 +494,11 @@ const StatisticalHistoryView = (props) => {
</Table.Summary.Row>
);
};
useEffect(() => {
if (props?.deviceParams?.sensors) {
handleDataForEmptyOrError()
}
}, [])
useEffect(() => {
setHistoryParams(props.deviceParams || {});
}, [props.deviceParams]);
......@@ -457,7 +532,7 @@ const StatisticalHistoryView = (props) => {
end = moment(dateTime).endOf(picker).format('YYYY-MM-DD 23:59:59');
break;
}
setTime({ startDate: start, endDate: end });
setTime({startDate: start, endDate: end});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dateValue]);
......@@ -488,7 +563,8 @@ const StatisticalHistoryView = (props) => {
onChange={onPickerChange}
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>
......@@ -498,7 +574,7 @@ const StatisticalHistoryView = (props) => {
onClick={exportExcelBtn}
disabled={!dataSource.length}
>
<VerticalAlignBottomOutlined />
<VerticalAlignBottomOutlined/>
下载
</Button>
</div>
......@@ -509,9 +585,9 @@ const StatisticalHistoryView = (props) => {
{
<BasicChart
ref={chartRef}
option={(!options||!options?.series) ? defaultOptionRef.current : options}
option={(!options || !options?.series) ? defaultOptionRef.current : options}
notMerge
style={{ width: '100%', height: '100%' }}
style={{width: '100%', height: '100%'}}
/>
}
</div>
......@@ -545,7 +621,7 @@ const StatisticalHistoryView = (props) => {
}, // 鼠标移出行
};
}}
scroll={{ x: '100%', y: 'calc(100% - 40px)' }}
scroll={{x: '100%', y: 'calc(100% - 40px)'}}
summary={Summary}
/>
</div>
......@@ -555,7 +631,7 @@ const StatisticalHistoryView = (props) => {
</div>
{loading && (
<div className={classNames(`${prefixCls}-load-box`)}>
<LoadBox spinning={loading} />
<LoadBox spinning={loading}/>
</div>
)}
</div>
......
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