Commit d35c48a5 authored by 陈龙's avatar 陈龙

feat: 新增箱线图、置信区间功能

parent c180e1d5
import React, { memo, useEffect, useMemo, useRef } from 'react'; import React, {memo, useEffect, useMemo, useRef} from 'react';
import { BasicChart } from '@wisdom-components/basicchart'; import {BasicChart} from '@wisdom-components/basicchart';
import PandaEmpty from '@wisdom-components/empty'; import PandaEmpty from '@wisdom-components/empty';
import optionGenerator, { alarmMarkLine, minMaxMarkPoint, offlineArea } from './utils'; import optionGenerator, {alarmMarkLine, minMaxMarkPoint, offlineArea} from './utils';
import { isArray, cloneDeep } from 'lodash'; import {isArray, cloneDeep} from 'lodash';
const SimgleChart = memo((props) => { const SimgleChart = memo((props) => {
const { const {
...@@ -13,6 +13,8 @@ const SimgleChart = memo((props) => { ...@@ -13,6 +13,8 @@ const SimgleChart = memo((props) => {
curveCenter, curveCenter,
showGridLine = false, showGridLine = false,
deviceAlarmSchemes, deviceAlarmSchemes,
chartType,
justLine
} = props; } = props;
const chartRef = useRef(); const chartRef = useRef();
...@@ -24,6 +26,8 @@ const SimgleChart = memo((props) => { ...@@ -24,6 +26,8 @@ const SimgleChart = memo((props) => {
deviceAlarmSchemes, deviceAlarmSchemes,
showMarkLine: true, showMarkLine: true,
showPoint: true, showPoint: true,
chartType,
justLine
}; };
return optionGenerator(dataSource, null, contrast, contrastOption, smooth, config); return optionGenerator(dataSource, null, contrast, contrastOption, smooth, config);
}, [dataSource, smooth, curveCenter]); }, [dataSource, smooth, curveCenter]);
...@@ -33,7 +37,7 @@ const SimgleChart = memo((props) => { ...@@ -33,7 +37,7 @@ const SimgleChart = memo((props) => {
const chart = chartRef.current?.getEchartsInstance?.(); const chart = chartRef.current?.getEchartsInstance?.();
function hander(params) { function hander(params) {
const { selected } = params; const {selected} = params;
const count = Object.values(selected || {}).filter((item) => item).length; const count = Object.values(selected || {}).filter((item) => item).length;
const option = cloneDeep(chart.getOption()); const option = cloneDeep(chart.getOption());
const needMarkLine = count === 1; const needMarkLine = count === 1;
...@@ -58,6 +62,7 @@ const SimgleChart = memo((props) => { ...@@ -58,6 +62,7 @@ const SimgleChart = memo((props) => {
}); });
chart.setOption(option, true); chart.setOption(option, true);
} }
if (!chart) return; if (!chart) return;
chart.on('legendselectchanged', hander); chart.on('legendselectchanged', hander);
return () => { return () => {
...@@ -95,7 +100,7 @@ const SimgleChart = memo((props) => { ...@@ -95,7 +100,7 @@ const SimgleChart = memo((props) => {
}; };
let yAxis = axisConfig; let yAxis = axisConfig;
if (isArray(option.yAxis)) { if (isArray(option.yAxis)) {
yAxis = option.yAxis.map((item) => ({ ...axisConfig })); yAxis = option.yAxis.map((item) => ({...axisConfig}));
} }
let xAxis = axisConfig; let xAxis = axisConfig;
chart.setOption({ chart.setOption({
...@@ -115,9 +120,9 @@ const SimgleChart = memo((props) => { ...@@ -115,9 +120,9 @@ const SimgleChart = memo((props) => {
); );
return isEmpty ? ( return isEmpty ? (
<PandaEmpty /> <PandaEmpty/>
) : ( ) : (
<BasicChart ref={chartRef} option={option} notMerge style={{ width: '100%', height: '100%' }} /> <BasicChart ref={chartRef} option={option} notMerge style={{width: '100%', height: '100%'}}/>
); );
}); });
......
...@@ -2,7 +2,7 @@ import React from 'react'; ...@@ -2,7 +2,7 @@ import React from 'react';
import HistoryView from '../index'; import HistoryView from '../index';
const deviceParams = [ const deviceParams = [
{ /* {
deviceCode: 'EGBF00000146', deviceCode: 'EGBF00000146',
sensors: '进水压力,出水瞬时流量,出水累计流量', sensors: '进水压力,出水瞬时流量,出水累计流量',
deviceType: '二供泵房', deviceType: '二供泵房',
...@@ -13,7 +13,7 @@ const deviceParams = [ ...@@ -13,7 +13,7 @@ const deviceParams = [
sensors: '进水压力,出水瞬时流量,出水累计流量', sensors: '进水压力,出水瞬时流量,出水累计流量',
deviceType: '二供泵房', deviceType: '二供泵房',
pointAddressID: 4, pointAddressID: 4,
}, },*/
{ {
deviceCode: 'EGBF00000002', deviceCode: 'EGBF00000002',
sensors: '进水压力,出水瞬时流量,出水累计流量', sensors: '进水压力,出水瞬时流量,出水累计流量',
......
...@@ -3,17 +3,20 @@ import HistoryView from '../index'; ...@@ -3,17 +3,20 @@ import HistoryView from '../index';
const deviceParams = [ const deviceParams = [
{ {
deviceCode: 'EGBF00000146', deviceCode: 'EGBF00000082',
sensors: '进水压力,出水瞬时流量,出水累计流量', sensors: '进水压力',
// sensors: '出水瞬时流量',
// sensors: '出水累计流量',
// sensors: '进水压力,出水瞬时流量,出水累计流量',
deviceType: '二供泵房', deviceType: '二供泵房',
pointAddressID: 4, pointAddressID: 4,
}, },
{ /* {
deviceCode: 'EGJZ00001113', deviceCode: 'EGBF00000083',
sensors: '出水瞬时流量,出水压力,泵1状态', sensors: '出水瞬时流量,出水压力,泵1状态',
deviceType: '二供机组', deviceType: '二供机组',
pointAddressID: 4, pointAddressID: 4,
}, },*/
// { // {
// deviceCode: 'EGJZ00001113', // deviceCode: 'EGJZ00001113',
// sensors: '出水压力', // sensors: '出水压力',
...@@ -24,7 +27,7 @@ const deviceParams = [ ...@@ -24,7 +27,7 @@ const deviceParams = [
const Demo = () => { const Demo = () => {
return ( return (
<div style={{ height: 700 }}> <div style={{ height: 700 }}>
<HistoryView deviceParams={deviceParams} defaultModel="table" /> <HistoryView deviceParams={deviceParams} defaultModel="curve" />
</div> </div>
); );
}; };
......
import React, { useContext, useEffect, useMemo, useState } from 'react'; import React, {useContext, useEffect, useMemo, useState} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { import {
...@@ -23,14 +23,14 @@ import _ from 'lodash'; ...@@ -23,14 +23,14 @@ import _ from 'lodash';
import TimeRangePicker from '@wisdom-components/timerangepicker'; import TimeRangePicker from '@wisdom-components/timerangepicker';
import PandaEmpty from '@wisdom-components/empty'; import PandaEmpty from '@wisdom-components/empty';
import BasicTable from '@wisdom-components/basictable'; import BasicTable from '@wisdom-components/basictable';
import { getHistoryInfo, getDeviceAlarmScheme, getExportDeviceHistoryUrl } from './apis'; import {getHistoryInfo, getDeviceAlarmScheme, getExportDeviceHistoryUrl} from './apis';
import SimgleChart from './SingleChart'; import SimgleChart from './SingleChart';
import GridChart from './GridChart'; import GridChart from './GridChart';
import './index.less'; import './index.less';
import { globalConfig } from 'antd/lib/config-provider'; import {globalConfig} from 'antd/lib/config-provider';
const { RangePicker } = DatePicker; const {RangePicker} = DatePicker;
const { Option } = Select; const {Option} = Select;
const startFormat = 'YYYY-MM-DD 00:00:00'; const startFormat = 'YYYY-MM-DD 00:00:00';
const endFormat = 'YYYY-MM-DD 23:59:59'; const endFormat = 'YYYY-MM-DD 23:59:59';
...@@ -80,6 +80,14 @@ const CheckboxData = [ ...@@ -80,6 +80,14 @@ const CheckboxData = [
showInTable: true, showInTable: true,
tooltip: '数据滤波针对与样本平均值相差2个标准差以上的值进行过滤。', tooltip: '数据滤波针对与样本平均值相差2个标准差以上的值进行过滤。',
}, },
{
key: 'justLine',
label: '仅查看曲线',
type: '',
checked: false,
showInCurve: false,
showInTable: false,
},
{ {
key: 'dataThin', key: 'dataThin',
label: '数据抽稀', label: '数据抽稀',
...@@ -212,7 +220,7 @@ const timeColumn = { ...@@ -212,7 +220,7 @@ const timeColumn = {
}; };
const HistoryView = (props) => { const HistoryView = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const {getPrefixCls} = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('history-view'); const prefixCls = getPrefixCls('history-view');
const { const {
...@@ -225,7 +233,7 @@ const HistoryView = (props) => { ...@@ -225,7 +233,7 @@ const HistoryView = (props) => {
showModels, showModels,
needMarkLine, needMarkLine,
} = props; } = props;
const isBoxPlots = deviceParams?.length === 1 && deviceParams[0]?.sensors?.split(',').length === 1;
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [activeTabKey, setActiveTabKey] = useState(defaultModel); const [activeTabKey, setActiveTabKey] = useState(defaultModel);
...@@ -247,6 +255,7 @@ const HistoryView = (props) => { ...@@ -247,6 +255,7 @@ const HistoryView = (props) => {
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
const [chartDataSource, setChartDataSource] = useState([]); const [chartDataSource, setChartDataSource] = useState([]);
const [chartType, setChartType] = useState('lineChart');
// 选择的时间范围值 // 选择的时间范围值
const dateRange = useMemo(() => { const dateRange = useMemo(() => {
if (timeValue === 'customer') { if (timeValue === 'customer') {
...@@ -379,7 +388,7 @@ const HistoryView = (props) => { ...@@ -379,7 +388,7 @@ const HistoryView = (props) => {
)} )}
{timeValue === 'contrast' && ( // 同期对比 {timeValue === 'contrast' && ( // 同期对比
<> <>
<Select value={contrastOption} style={{ width: 60 }} onChange={onContrastChange}> <Select value={contrastOption} style={{width: 60}} onChange={onContrastChange}>
<Option value="day"></Option> <Option value="day"></Option>
<Option value="month"></Option> <Option value="month"></Option>
</Select> </Select>
...@@ -396,7 +405,7 @@ const HistoryView = (props) => { ...@@ -396,7 +405,7 @@ const HistoryView = (props) => {
className={classNames(`${prefixCls}-contrast-delete`)} className={classNames(`${prefixCls}-contrast-delete`)}
onClick={() => handleDeleteDatePicker(index)} onClick={() => handleDeleteDatePicker(index)}
> >
<CloseCircleFilled /> <CloseCircleFilled/>
</div> </div>
)} )}
</div> </div>
...@@ -405,7 +414,7 @@ const HistoryView = (props) => { ...@@ -405,7 +414,7 @@ const HistoryView = (props) => {
)} )}
</div> </div>
))} ))}
{datePickerArr.length < 5 && <PlusCircleOutlined onClick={handleAddDatePicker} />} {datePickerArr.length < 5 && <PlusCircleOutlined onClick={handleAddDatePicker}/>}
</> </>
)} )}
</div> </div>
...@@ -415,11 +424,22 @@ const HistoryView = (props) => { ...@@ -415,11 +424,22 @@ const HistoryView = (props) => {
// 曲线设置项选择/取消 // 曲线设置项选择/取消
const onCheckboxChange = (e, key) => { const onCheckboxChange = (e, key) => {
let data = [...checkboxData]; let data = [...checkboxData];
let _index = data.findIndex(item => item.key === 'justLine'); // 仅查看曲线会在勾选了数据滤波后展示
let _index1 = data.findIndex(item => item.key === 'ignoreOutliers'); // 仅查看曲线会在勾选了数据滤波后展示
data.forEach((item) => { data.forEach((item) => {
if (item.key === key) { if (item.key === key) {
item.checked = e.target.checked; item.checked = e.target.checked;
} }
}); });
if (key === 'ignoreOutliers') {
data[_index].showInCurve = e.target.checked;
data[_index].checked = e.target.checked;
}
if (key === 'chartType') {
data[_index1].showInCurve = e.target.value;
data[_index1].checked = false;
}
debugger
setCheckboxData(data); setCheckboxData(data);
}; };
...@@ -442,7 +462,7 @@ const HistoryView = (props) => { ...@@ -442,7 +462,7 @@ const HistoryView = (props) => {
</Checkbox> </Checkbox>
{child.tooltip && ( {child.tooltip && (
<Tooltip title={child.tooltip}> <Tooltip title={child.tooltip}>
<QuestionCircleFilled className={`${prefixCls}-question`} /> <QuestionCircleFilled className={`${prefixCls}-question`}/>
</Tooltip> </Tooltip>
)} )}
</> </>
...@@ -450,9 +470,21 @@ const HistoryView = (props) => { ...@@ -450,9 +470,21 @@ const HistoryView = (props) => {
); );
}; };
const renderCurveOption = () => { const renderCurveOption = (isChart, isSingle) => {
return ( return (
<div className={classNames(`${prefixCls}-cover`)}> <div className={classNames(`${prefixCls}-cover`)}>
{
isChart && isSingle ? <>
<div className={classNames(`${prefixCls}-label`)}>曲线形态</div>
<Radio.Group value={chartType} onChange={(e) => {
let _value = e.target.value;
setChartType(_value);
onCheckboxChange({target: {value: _value !== 'boxChart'}}, 'chartType')
}}>
<Radio.Button value={'lineChart'}>线形图</Radio.Button>
<Radio.Button value={'boxChart'}>箱线图</Radio.Button>
</Radio.Group></> : ''
}
<div className={classNames(`${prefixCls}-label`)}>曲线设置</div> <div className={classNames(`${prefixCls}-label`)}>曲线设置</div>
{checkboxData.map((child) => { {checkboxData.map((child) => {
const box = renderCheckbox(child); const box = renderCheckbox(child);
...@@ -466,7 +498,7 @@ const HistoryView = (props) => { ...@@ -466,7 +498,7 @@ const HistoryView = (props) => {
{activeTabKey === 'table' && ( {activeTabKey === 'table' && (
<Select <Select
value={dataThinKey} value={dataThinKey}
style={{ width: 90 }} style={{width: 90}}
onChange={onTimeIntervalChange} onChange={onTimeIntervalChange}
disabled={!dataConfig.dataThin} disabled={!dataConfig.dataThin}
> >
...@@ -504,14 +536,15 @@ const HistoryView = (props) => { ...@@ -504,14 +536,15 @@ const HistoryView = (props) => {
aDom.click(); aDom.click();
aDom.remove(); aDom.remove();
}) })
.catch((err) => {}); .catch((err) => {
});
}); });
}; };
const handleTableData = (data) => { const handleTableData = (data) => {
const ignoreOutliers = checkboxData.find((item) => item.key === 'ignoreOutliers').checked; const ignoreOutliers = checkboxData.find((item) => item.key === 'ignoreOutliers').checked;
const dataIndexAccess = (dataItem, index) => { const dataIndexAccess = (dataItem, index) => {
const { stationCode, sensorName } = dataItem; const {stationCode, sensorName} = dataItem;
return `${stationCode}-${sensorName}-${index}`; return `${stationCode}-${sensorName}-${index}`;
}; };
...@@ -522,7 +555,7 @@ const HistoryView = (props) => { ...@@ -522,7 +555,7 @@ const HistoryView = (props) => {
// 处理表头数据 // 处理表头数据
const columnsData = data.map((item, index) => { const columnsData = data.map((item, index) => {
const { stationCode, equipmentName, sensorName, unit, dataModel } = item; const {stationCode, equipmentName, sensorName, unit, dataModel} = item;
const dataIndex = dataIndexAccess(item, index); const dataIndex = dataIndexAccess(item, index);
let col = { let col = {
title: `${equipmentName}-${sensorName}${unit ? `(${unit})` : ''}`, title: `${equipmentName}-${sensorName}${unit ? `(${unit})` : ''}`,
...@@ -545,7 +578,7 @@ const HistoryView = (props) => { ...@@ -545,7 +578,7 @@ const HistoryView = (props) => {
const timeData = {}; const timeData = {};
const buildDefaultData = (time) => { const buildDefaultData = (time) => {
const obj = { key: time, time: time }; const obj = {key: time, time: time};
data.forEach((item, index) => { data.forEach((item, index) => {
const dataIndex = dataIndexAccess(item, index); const dataIndex = dataIndexAccess(item, index);
obj[dataIndex] = ''; obj[dataIndex] = '';
...@@ -553,7 +586,7 @@ const HistoryView = (props) => { ...@@ -553,7 +586,7 @@ const HistoryView = (props) => {
return obj; return obj;
}; };
data.forEach((item, index) => { data.forEach((item, index) => {
const { stationCode, sensorName, dataModel } = item; const {stationCode, sensorName, dataModel} = item;
dataModel.forEach((data) => { dataModel.forEach((data) => {
const formatTime = moment(data.pt).format(format); const formatTime = moment(data.pt).format(format);
...@@ -568,7 +601,7 @@ const HistoryView = (props) => { ...@@ -568,7 +601,7 @@ const HistoryView = (props) => {
// 处理表格数据 // 处理表格数据
data.forEach((child, index) => { data.forEach((child, index) => {
const { dataModel } = child; const {dataModel} = child;
const dataIndex = dataIndexAccess(child, index); const dataIndex = dataIndexAccess(child, index);
dataModel.forEach((value, j) => { dataModel.forEach((value, j) => {
const formatTime = moment(value.pt).format(format); const formatTime = moment(value.pt).format(format);
...@@ -618,19 +651,23 @@ const HistoryView = (props) => { ...@@ -618,19 +651,23 @@ const HistoryView = (props) => {
const handleDataThinKey = (diffDays) => { const handleDataThinKey = (diffDays) => {
// edit by zy 根据选择的时长控制抽稀频度 // edit by zy 根据选择的时长控制抽稀频度
if (diffDays >= 7 && diffDays < 15) { if (diffDays >= 7 && diffDays < 15) {
return { unit: 'h', zoom: '2' }; return {unit: 'h', zoom: '2'};
} else if (diffDays >= 15 && diffDays < 30) { } else if (diffDays >= 15 && diffDays < 30) {
return { unit: 'h', zoom: '4' }; return {unit: 'h', zoom: '4'};
} else if (diffDays >= 30) { } else if (diffDays >= 30) {
return { unit: 'h', zoom: '6' }; return {unit: 'h', zoom: '6'};
} else if (diffDays < 7 && diffDays >= 2) {
return {unit: 'min', zoom: '40'};
} else if (diffDays < 2 && diffDays >= 1) {
return {unit: 'min', zoom: '30'};
} else { } else {
return {}; return {unit: 'min', zoom: '10'};
} }
}; };
// 处理接口服务参数的变化 // 处理接口服务参数的变化
const onChangeParams = (value = {}) => { const onChangeParams = (value = {}) => {
const { dateRange, isDilute, ignoreOutliers, zoom, unit } = value; const {dateRange, isDilute, ignoreOutliers, zoom, unit} = value;
const requestArr = []; const requestArr = [];
const acrossTables = []; const acrossTables = [];
deviceParams.forEach((i) => { deviceParams.forEach((i) => {
...@@ -643,6 +680,7 @@ const HistoryView = (props) => { ...@@ -643,6 +680,7 @@ const HistoryView = (props) => {
return; return;
} }
dateRange.forEach((item) => { dateRange.forEach((item) => {
let _showLine = checkboxData.find(item => item.key === 'justLine');
const param = { const param = {
isDilute, isDilute,
zoom, zoom,
...@@ -652,17 +690,18 @@ const HistoryView = (props) => { ...@@ -652,17 +690,18 @@ const HistoryView = (props) => {
dateFrom: item.dateFrom, dateFrom: item.dateFrom,
dateTo: item.dateTo, dateTo: item.dateTo,
acrossTables, acrossTables,
isBoxPlots: isBoxPlots
}; };
let diffDays = moment(item.dateTo).diff(moment(item.dateFrom), 'days'); let diffDays = moment(item.dateTo).diff(moment(item.dateFrom), 'days');
let zoomParam = activeTabKey === 'curve' ? handleDataThinKey(diffDays) : {}; let zoomParam = activeTabKey === 'curve' ? handleDataThinKey(diffDays) : {};
requestArr.push(getHistoryInfo({ ...param, ...zoomParam })); requestArr.push(getHistoryInfo({...param, ...zoomParam}));
}); });
setLoading(true); setLoading(true);
Promise.all(requestArr).then((results) => { Promise.all(requestArr).then((results) => {
if (results.length) { if (results.length) {
let data = []; let data = [];
results.forEach((res, index) => { results.forEach((res, index) => {
const { dateFrom, dateTo } = dateRange?.[index] ?? {}; const {dateFrom, dateTo} = dateRange?.[index] ?? {};
if (res.code === 0 && res.data.length) { if (res.code === 0 && res.data.length) {
res.data.forEach((d) => { res.data.forEach((d) => {
d.dateFrom = dateFrom; d.dateFrom = dateFrom;
...@@ -691,7 +730,7 @@ const HistoryView = (props) => { ...@@ -691,7 +730,7 @@ const HistoryView = (props) => {
}; };
useEffect(() => { useEffect(() => {
const { dataThin, ignoreOutliers, zoom, unit } = dataConfig; const {dataThin, ignoreOutliers, zoom, unit} = dataConfig;
beforChangeParams().finally(() => { beforChangeParams().finally(() => {
onChangeParams({ onChangeParams({
isDilute: dataThin, isDilute: dataThin,
...@@ -699,9 +738,10 @@ const HistoryView = (props) => { ...@@ -699,9 +738,10 @@ const HistoryView = (props) => {
zoom, zoom,
unit, unit,
dateRange, dateRange,
isBoxPlots: isBoxPlots
}); });
}); });
}, [dateRange, dataConfig, deviceParams]); }, [dateRange, dataConfig, deviceParams, chartType]);
const renderPanel = (model) => { const renderPanel = (model) => {
if (model === 'curve') { if (model === 'curve') {
...@@ -709,11 +749,11 @@ const HistoryView = (props) => { ...@@ -709,11 +749,11 @@ const HistoryView = (props) => {
<> <>
<div className={`${prefixCls}-options`}> <div className={`${prefixCls}-options`}>
{renderTimeOption()} {renderTimeOption()}
{renderCurveOption()} {renderCurveOption(true, (deviceParams?.length === 1 && deviceParams[0]?.sensors?.split(',').length === 1))}
</div> </div>
<div className={`${prefixCls}-content`}> <div className={`${prefixCls}-content`}>
{!chartDataSource.length ? ( {!chartDataSource.length ? (
<PandaEmpty /> <PandaEmpty/>
) : grid === true ? ( ) : grid === true ? (
<GridChart <GridChart
curveCenter={curveCenter} curveCenter={curveCenter}
...@@ -729,6 +769,8 @@ const HistoryView = (props) => { ...@@ -729,6 +769,8 @@ const HistoryView = (props) => {
showGridLine={chartGrid} showGridLine={chartGrid}
prefixCls={prefixCls} prefixCls={prefixCls}
dataSource={chartDataSource} dataSource={chartDataSource}
justLine={!!checkboxData.find(item => item.key === 'justLine' && item.checked)}
chartType={isBoxPlots ? chartType : null}
contrast={timeValue === 'contrast'} contrast={timeValue === 'contrast'}
contrastOption={contrastOption} contrastOption={contrastOption}
deviceAlarmSchemes={deviceAlarmSchemes} deviceAlarmSchemes={deviceAlarmSchemes}
...@@ -752,10 +794,11 @@ const HistoryView = (props) => { ...@@ -752,10 +794,11 @@ const HistoryView = (props) => {
columns={columns} columns={columns}
{...tableProps} {...tableProps}
pagination={false} pagination={false}
onChange={() => {}} onChange={() => {
}}
/> />
) : ( ) : (
<PandaEmpty /> <PandaEmpty/>
)} )}
</div> </div>
</> </>
...@@ -780,7 +823,7 @@ const HistoryView = (props) => { ...@@ -780,7 +823,7 @@ const HistoryView = (props) => {
<div className={`${prefixCls}-extra-right`}> <div className={`${prefixCls}-extra-right`}>
{activeTabKey === 'table' && ( {activeTabKey === 'table' && (
<Button type="link" onClick={exportExcelBtn}> <Button type="link" onClick={exportExcelBtn}>
<DownloadOutlined /> <DownloadOutlined/>
下载 下载
</Button> </Button>
)} )}
......
...@@ -13,7 +13,7 @@ const axisWidth = 40; ...@@ -13,7 +13,7 @@ const axisWidth = 40;
* @returns * @returns
*/ */
const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => { const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => {
const { equipmentName, sensorName, unit, dataModel, dateFrom, dateTo } = data; const {equipmentName, sensorName, unit, dataModel, dateFrom, dateTo} = data;
let name = nameWithSensor ? `${equipmentName}-${sensorName}` : equipmentName; let name = nameWithSensor ? `${equipmentName}-${sensorName}` : equipmentName;
if (contrast) { if (contrast) {
const time = dateFrom.slice(0, contrastOption === 'day' ? 10 : 7).replace(/-/g, ''); const time = dateFrom.slice(0, contrastOption === 'day' ? 10 : 7).replace(/-/g, '');
...@@ -31,7 +31,7 @@ const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => { ...@@ -31,7 +31,7 @@ const nameFormatter = (data, contrast, contrastOption, nameWithSensor) => {
* @returns 图表系列数据, [[DateTime, value]] * @returns 图表系列数据, [[DateTime, value]]
*/ */
const dataAccessor = (data, contrast, contrastOption) => { const dataAccessor = (data, contrast, contrastOption) => {
const { dataModel } = data; const {dataModel} = data;
const formatStr = contrastOption === 'day' ? '2020-01-01 HH:mm:00' : '2020-01-DD HH:mm:00'; const formatStr = contrastOption === 'day' ? '2020-01-01 HH:mm:00' : '2020-01-DD HH:mm:00';
return dataModel.map((item) => { return dataModel.map((item) => {
const time = contrast ? moment(item.pt).format(formatStr) : item.pt; const time = contrast ? moment(item.pt).format(formatStr) : item.pt;
...@@ -46,7 +46,7 @@ const dataAccessor = (data, contrast, contrastOption) => { ...@@ -46,7 +46,7 @@ const dataAccessor = (data, contrast, contrastOption) => {
* @returns Null/areaStyle, 为null显示曲线图, 为areaStyle对象显示为面积图. * @returns Null/areaStyle, 为null显示曲线图, 为areaStyle对象显示为面积图.
*/ */
const areaStyleFormatter = (data) => { const areaStyleFormatter = (data) => {
const { sensorName } = data; const {sensorName} = data;
return sensorName && sensorName.indexOf('流量') > -1 ? {} : null; return sensorName && sensorName.indexOf('流量') > -1 ? {} : null;
}; };
...@@ -57,7 +57,7 @@ const areaStyleFormatter = (data) => { ...@@ -57,7 +57,7 @@ const areaStyleFormatter = (data) => {
* @returns * @returns
*/ */
const minMax = (data) => { const minMax = (data) => {
const { dataModel } = data; const {dataModel} = data;
let min = Number.MAX_SAFE_INTEGER; let min = Number.MAX_SAFE_INTEGER;
let max = Number.MIN_SAFE_INTEGER; let max = Number.MIN_SAFE_INTEGER;
dataModel.forEach((item) => { dataModel.forEach((item) => {
...@@ -88,7 +88,7 @@ const markLineItem = (name, value, color) => { ...@@ -88,7 +88,7 @@ const markLineItem = (name, value, color) => {
export const alarmMarkLine = (dataItem, index, dataSource, schemes) => { export const alarmMarkLine = (dataItem, index, dataSource, schemes) => {
// 只有一个数据曲线时显示markline // 只有一个数据曲线时显示markline
if (!dataItem || !schemes || dataSource.length !== 1) return {}; if (!dataItem || !schemes || dataSource.length !== 1) return {};
const { deviceType, stationCode, sensorName, decimalPoint } = dataItem; const {deviceType, stationCode, sensorName, decimalPoint} = dataItem;
const curSchemes = schemes.filter( const curSchemes = schemes.filter(
(item) => (item) =>
item.deviceCode === stationCode && item.deviceCode === stationCode &&
...@@ -97,7 +97,7 @@ export const alarmMarkLine = (dataItem, index, dataSource, schemes) => { ...@@ -97,7 +97,7 @@ export const alarmMarkLine = (dataItem, index, dataSource, schemes) => {
); );
const data = []; const data = [];
curSchemes.forEach((scheme) => { curSchemes.forEach((scheme) => {
const { hLimit, hhLimit, lLimit, llLimit } = scheme; const {hLimit, hhLimit, lLimit, llLimit} = scheme;
lLimit !== null && lLimit !== void 0 && data.push(markLineItem('低限', lLimit, '#fa8c16')); lLimit !== null && lLimit !== void 0 && data.push(markLineItem('低限', lLimit, '#fa8c16'));
hLimit !== null && hLimit !== void 0 && data.push(markLineItem('高限', hLimit, '#fa8c16')); hLimit !== null && hLimit !== void 0 && data.push(markLineItem('高限', hLimit, '#fa8c16'));
llLimit !== null && llLimit !== void 0 && data.push(markLineItem('低低限', llLimit, '#FF0000')); llLimit !== null && llLimit !== void 0 && data.push(markLineItem('低低限', llLimit, '#FF0000'));
...@@ -128,8 +128,8 @@ export const minMaxMarkPoint = (dataItem, index, dataSource) => { ...@@ -128,8 +128,8 @@ export const minMaxMarkPoint = (dataItem, index, dataSource) => {
// 只有一个数据曲线时显示markline // 只有一个数据曲线时显示markline
if (!dataItem || dataSource.length !== 1) return {}; if (!dataItem || dataSource.length !== 1) return {};
const data = []; const data = [];
data.push({ type: 'min', name: '最小: ' }); data.push({type: 'min', name: '最小: '});
data.push({ type: 'max', name: '最大: ' }); data.push({type: 'max', name: '最大: '});
return { return {
symbolSize: 1, symbolSize: 1,
symbolOffset: [0, '50%'], symbolOffset: [0, '50%'],
...@@ -199,7 +199,7 @@ export const decorateAxisGridLine = (axis, showGrid) => { ...@@ -199,7 +199,7 @@ export const decorateAxisGridLine = (axis, showGrid) => {
*/ */
export const offlineArea = (dataItem) => { export const offlineArea = (dataItem) => {
if (!dataItem) return {}; if (!dataItem) return {};
const { dataModel } = dataItem; const {dataModel} = dataItem;
let datas = new Array(); let datas = new Array();
let offlineData = []; let offlineData = [];
let hasOffline = false; let hasOffline = false;
...@@ -247,14 +247,15 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth ...@@ -247,14 +247,15 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth
const showMarkLine = _.get(config, 'showMarkLine', false); const showMarkLine = _.get(config, 'showMarkLine', false);
const showPoint = _.get(config, 'showPoint', false); const showPoint = _.get(config, 'showPoint', false);
const deviceAlarmSchemes = _.get(config, 'deviceAlarmSchemes', []); const deviceAlarmSchemes = _.get(config, 'deviceAlarmSchemes', []);
const chartType = _.get(config, 'chartType', null);
const justLine = _.get(config, 'justLine', false);
// 自定义属性 // 自定义属性
const restOption = _.pick(cusOption, ['title', 'legend']); const restOption = _.pick(cusOption, ['title', 'legend']);
// 一种指标一个y轴 // 一种指标一个y轴
const yAxisMap = new Map(); const yAxisMap = new Map();
dataSource.forEach((item, index) => { dataSource.forEach((item, index) => {
const { sensorName, unit } = item; const {sensorName, unit} = item;
const key = sensorName; const key = sensorName;
if (!yAxisMap.has(key)) { if (!yAxisMap.has(key)) {
...@@ -300,7 +301,7 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth ...@@ -300,7 +301,7 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth
const axis = yAxisMap.get(key); const axis = yAxisMap.get(key);
decorateAxisGridLine(axis, showGridLine); decorateAxisGridLine(axis, showGridLine);
}); });
const yAxis = yAxisMap.size > 0 ? [...yAxisMap.values()] : { type: 'value' }; const yAxis = yAxisMap.size > 0 ? [...yAxisMap.values()] : {type: 'value'};
// 根据y轴个数调整边距 // 根据y轴个数调整边距
const leftNum = Math.ceil(yAxisMap.size / 2); const leftNum = Math.ceil(yAxisMap.size / 2);
...@@ -316,11 +317,10 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth ...@@ -316,11 +317,10 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth
const map = new Map(); const map = new Map();
let current = -1; let current = -1;
const get = (name) => (map.has(name) ? map.get(name) : map.set(name, ++current).get(name)); const get = (name) => (map.has(name) ? map.get(name) : map.set(name, ++current).get(name));
return { get }; return {get};
})(); })();
let series = dataSource.map((item, index) => {
const series = dataSource.map((item, index) => { const {sensorName, unit} = item;
const { sensorName, unit } = item;
const name = nameFormatter(item, contrast, contrastOption, nameWithSensor); const name = nameFormatter(item, contrast, contrastOption, nameWithSensor);
const data = dataAccessor(item, contrast, contrastOption); const data = dataAccessor(item, contrast, contrastOption);
const type = 'line'; const type = 'line';
...@@ -358,7 +358,7 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth ...@@ -358,7 +358,7 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth
.map((item) => item.data?.[item.data.length - 1]?.[0]) .map((item) => item.data?.[item.data.length - 1]?.[0])
.filter((item) => item !== undefined), .filter((item) => item !== undefined),
); );
const xAxis = { type: 'time', min, max }; let xAxis = {type: 'time', min, max};
decorateAxisGridLine(xAxis, showGridLine); decorateAxisGridLine(xAxis, showGridLine);
const tooltipTimeFormat = !contrast const tooltipTimeFormat = !contrast
...@@ -373,7 +373,65 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth ...@@ -373,7 +373,65 @@ const optionGenerator = (dataSource, cusOption, contrast, contrastOption, smooth
// type: 'cross' // type: 'cross'
// } // }
}; };
// 增加箱线图的逻辑,单曲线才存在
if (!justLine && chartType) {
if (chartType === 'boxChart') {
const otherData = dataSource?.[0]?.dataModel.map(item => {
const {firstPV, lastPV, maxPV, minPV} = item;
return [firstPV, lastPV, minPV, maxPV]
}) || []; //当存在othersData的时候,只是单曲线
series = series.map(item => {
let _item = {...item, symbol: false};
_item.data = _item?.data?.map(d => {
return d[1] || null
}) || [];
return _item;
})
series.push({
type: 'candlestick',
name: '箱线图',
symbol: false,
data: otherData
});
} else {
let _maxData = [];
let _minData = [];
dataSource?.[0]?.dataModel.forEach(item => {
const {firstPV, lastPV, maxPV, minPV} = item;
_maxData.push(maxPV);
_minData.push(minPV);
}); //当存在othersData的时候,只是单曲线
series = series.map(item => {
let _item = {...item, symbol: false};
_item.data = _item?.data?.map(d => {
return d[1] || null
}) || [];
return _item;
});
[[..._minData], [..._maxData]].forEach((item, index) => {
series.push({
name: index === 0 ? '最小值' : '最大值',
type: 'line',
data: item,
lineStyle: {
opacity: 0
},
...(index !== 0 ? {
areaStyle: {
color: '#ccc'
}
} : {}),
stack: 'confidence-band',
symbol: 'none'
});
})
}
xAxis = {type: 'category', data: series[0].data.map(item => moment(item[0]).format('YYYY-MM-DD'))};
tooltip.formatter = (e) => {
console.log(e);
}
}
debugger
return { return {
yAxis, yAxis,
grid, grid,
......
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