Commit 4b15851b authored by 陈龙's avatar 陈龙

feat: 新增预测曲线功能;新增统计曲线功能

parent a2ebc0ae
......@@ -22,7 +22,7 @@ path: /
## 单图表
<code src="./demos/index.js"></code>
[//]: # (<code src="./demos/index.js"></code>)
## 单图表-状态
......@@ -37,7 +37,7 @@ path: /
## 多图表
[//]: # (<code src="./demos/GridDemo.js"></code>)
<code src="./demos/GridDemo.js"></code>
## API
......
import React, {memo, useMemo} from 'react';
import _ from 'lodash';
import React, {memo, useEffect, useMemo, useState} from 'react';
import _, {cloneDeep} from 'lodash';
import {BasicChart} from '@wisdom-components/basicchart';
import PandaEmpty from '@wisdom-components/empty';
import optionGenerator from './utils';
import {getPointAddress, getPointAddressEntry, getSensorsRealName, getSensorType, getStatisticsInfo} from "./apis";
import moment from "moment";
import {isString} from "util";
const ChartTitle = ({prefixCls, title, unit}) => {
const cls = `${prefixCls}-grid-item-title`;
......@@ -20,11 +23,158 @@ const GridChart = memo((props) => {
contrastOption = 'day',
smooth = true,
curveCenter,
allPointAddress,
allSensorType,
dateRange
} = props;
const {prefixCls} = props;
const [gridData, setGridData] = useState([]);
const [pointAddressData, setPointAddressData] = useState(null);
const [pointAddressEntryData, setPointAddressEntryData] = useState(null);
const [sensorType, setSensorType] = useState(null);
// 新增逻辑:需要区分出哪些是统计值
const gridData = useMemo(() => {
const grids = dataSource.reduce((pre, item, index) => {
/**
* @param {array} dataSource
*/
const handleDataSource = async (dataSource) => {
props.setLoading(true);
// 1. 统计设备
let _deviceTypes = [];
let _deviceCodes = dataSource.reduce((final, cur) => {
if (!final.includes(cur.stationCode) && !_deviceTypes.includes(cur.deviceType)) {
final.push(cur.stationCode);
_deviceTypes.push(cur.deviceType);
}
return final;
}, []);
// 2. 获取对应的版本id
let _ids = [];
if (pointAddressData !== null) {
_ids = pointAddressData;
} else {
let _idRequest = await getPointAddress({code: _deviceCodes.join(',')});
_ids = _idRequest?.data ?? [];
setPointAddressData(_ids)
}
// 3. 获取对应的点表
let _map = {};
for await (let item of _ids) {
let _index = _deviceCodes.findIndex(code => code === item.code);
if (pointAddressEntryData && pointAddressEntryData[item.id]) {
_map[_deviceTypes[_index]] = pointAddressEntryData[item.id];
} else {
let _entry = await getPointAddressEntry({versionId: item.id});
_map[_deviceTypes[_index]] = _entry?.data ?? [];
setPointAddressEntryData({...pointAddressEntryData, [item.id]: _entry?.data})
}
}
// 4. 获取点类型
let _sensorType = []
if (sensorType) {
_sensorType = sensorType;
} else {
_sensorType = (await getSensorType())?.data ?? [];
}
//5. 找出统计值,合并
let _dataSource = cloneDeep(dataSource);
let _nameListMap = {};
let _indexArr = [];
let _tempValue = {};
let _finalData = {};
_dataSource.forEach((item, index) => {
let _sensorTypeId = _map[item.deviceType].find(sensor => sensor.name === item.sensorName)?.sensorTypeID || 0;
let _type = _sensorType.find(sensor => sensor.id === _sensorTypeId)?.type ?? '';
if (_type === '统计值') {
// 移除掉,并存储
_tempValue[`needToReplace_${item.stationCode}_${item.sensorName}`] = _dataSource.splice(index, 1, `needToReplace_${item.stationCode}_${item.sensorName}`)?.[0];
if (!_nameListMap[item.stationCode]) {
_nameListMap[item.stationCode] = {
code: item.stationCode,
deviceType: item.deviceType,
sensors: [item.sensorName]
}
} else {
_nameListMap[item.stationCode].sensors.push(item.sensorName)
}
}
})
//6. 请求数据并替换数据。grid模式下,请求的时间是一致的。
let baseParam = {
pageIndex: 1,
pageSize: 999,
dateFrom: dateRange[0].dateFrom,
dateTo: dateRange[0].dateTo,
}
let _arr = Object.values(_nameListMap)
for await (let item of _arr) {
let _params = {
...baseParam,
accountName: item.deviceType,
deviceCode: item.code,
nameTypeList: item.sensors.map(sensor => ({
name: sensor,
type: 'Sub'
})),
/* nameTypeList: ['今日用电量', '今日供水量'].map(sensor => ({
name: sensor,
type: 'Sub'
})),*/
dateType: returnDateType(dateRange[0])
};
// 虚拟点需要查出实际点后,进行查找
let _realSensors = {};
let _realSensorsMap = {};
// 统计类的如果是虚拟点,那么需要查出实际数据来源的点,查出映射关系
(await getSensorsRealName(_params))?.data?.forEach(sensor => {
// name 虚拟点 staticName实际的点
_realSensors[sensor.staticName] = sensor.name;
_realSensorsMap[sensor.name] = sensor.staticName;
});
// 请求统计数据时,需要使用实际点去获取
_params.nameTypeList.forEach(sensor => {
sensor.name = _realSensors[sensor.name]
});
// 获取数据后,将原始数据中的dataModel这部分替换掉
((await getStatisticsInfo(_params))?.data?.list?.[0].dNameDataList ?? [])?.forEach(obj => {
let _v = _tempValue[`needToReplace_${item.code}_${_realSensorsMap[obj.dName]}`];
_v.dataModel = obj.nameDate.map(d => {
return {
pt: moment(d.time),
pv: d.value,
maxPV: d.value, minPV: d.value, firstPV: d.value, lastPV: d.value,
}
});
_finalData[`needToReplace_${item.code}_${_realSensorsMap[obj.dName]}`] = _v;
});
// 替换数据
_dataSource.forEach((d, index) => {
if (_.isString(d) && d.includes('needToReplace') && _finalData[d]) {
_dataSource[index] = _finalData[d];
}
})
// 有不存在数据的,将原始数据替换回来
_dataSource.forEach((d, index) => {
if (_.isString(d) && d.includes('needToReplace')) {
_dataSource[index] = dataSource[index];
}
})
}
props.setLoading(false);
return _dataSource
};
const returnDateType = (date) => {
let {dateFrom, dateTo} = date;
let _duration = moment.duration(moment(dateTo) - moment(dateFrom), 'ms').days();
if (_duration >= 7) return 'month';
if (_duration >= 30) return 'year';
return 'day';
};
useEffect(() => {
async function handle() {
let _data = await handleDataSource(dataSource);
const grids = _data.reduce((pre, item, index) => {
const {sensorName, deviceType} = item;
const key = `${deviceType}_${sensorName}`; // 同设备类型同指标才在同一组
let grid = pre.find((g) => g.key === key);
......@@ -40,9 +190,11 @@ const GridChart = memo((props) => {
grid.list.push(item);
return pre;
}, []);
return grids;
}, [dataSource]);
setGridData(grids);
}
handle();
}, [dataSource])
const options = useMemo(() => {
let _options = gridData.map((item) => {
const {key, list, equipmentName, sensorName, stationCode, unit} = item;
......
import React, { memo, useEffect, useMemo, useRef } from 'react';
import { BasicChart } from '@wisdom-components/basicchart';
import React, {memo, useEffect, useMemo, useRef} from 'react';
import {BasicChart} from '@wisdom-components/basicchart';
import PandaEmpty from '@wisdom-components/empty';
import optionGenerator, {
alarmMarkLine,
......@@ -8,7 +8,7 @@ import optionGenerator, {
specialTypeChartOptionGenerator,
statusChartOptionGenerator
} from './utils';
import { isArray, cloneDeep } from 'lodash';
import {isArray, cloneDeep} from 'lodash';
const SingleChart = memo((props) => {
const {
......@@ -22,7 +22,8 @@ const SingleChart = memo((props) => {
chartType,
lineDataType,
showBoxOption,
special
special,
predicateData
} = props;
const chartRef = useRef();
const SpecialType = ['状态值', '开关值']; // 横向柱状条
......@@ -51,16 +52,16 @@ const SingleChart = memo((props) => {
if (dataSource.length === 1 && SpecialType.includes(_allPointAddress[dataSource[0].sensorName])) {
config.sensorType = _allPointAddress[dataSource[0].sensorName];
config.special.allValDesc = allValDesc;
return specialTypeChartOptionGenerator({ dataSource, config });
return specialTypeChartOptionGenerator({dataSource, config});
}
return optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType);
}, [dataSource, smooth, curveCenter, chartType]);
return optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType, predicateData);
}, [dataSource, smooth, curveCenter, chartType, predicateData]);
useEffect(() => {
chartRef.current?.resize?.();
const chart = chartRef.current?.getEchartsInstance?.();
function hander(params) {
const { selected } = params;
const {selected} = params;
const count = Object.values(selected || {}).filter((item) => item).length;
const option = cloneDeep(chart.getOption());
const needMarkLine = count === 1;
......@@ -126,7 +127,7 @@ const SingleChart = memo((props) => {
};
let yAxis = axisConfig;
if (isArray(option.yAxis)) {
yAxis = option.yAxis.map((item) => ({ ...axisConfig }));
yAxis = option.yAxis.map((item) => ({...axisConfig}));
}
let xAxis = axisConfig;
chart.setOption({
......@@ -145,9 +146,9 @@ const SingleChart = memo((props) => {
[dataSource],
);
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%'}}/>
);
});
......
......@@ -10,7 +10,7 @@ const monitorDeviceUrl = `${baseUrl}/PandaMonitor/Monitor/Device`;
// 获取单个设备的配置信息
export function getPointAddress(params) {
return request({
url: `/PandaMonitor/Monitor/PointAddress/GetPointAddress`,
url: `${baseUrl}/PandaMonitor/Monitor/PointAddress/GetPointAddress`,
method: REQUEST_METHOD_GET,
params
});
......@@ -19,7 +19,7 @@ export function getPointAddress(params) {
// 获取点表信息
export function getPointAddressEntry(params) {
return request({
url: `/PandaMonitor/Monitor/PointAddress/GetPointAddressEntry`,
url: `${baseUrl}/PandaMonitor/Monitor/PointAddress/GetPointAddressEntry`,
method: REQUEST_METHOD_GET,
params
});
......@@ -62,7 +62,32 @@ export function getDictionaryInfoAll(params) {
export function getSensorType() {
return request({
url: '/PandaMonitor/Monitor/Sensor/GetSensorType',
url: `${baseUrl}/PandaMonitor/Monitor/Sensor/GetSensorType`,
method: REQUEST_METHOD_GET,
})
}
export function getPredicateSensor(params) {
return request({
url: `${baseUrl}/PandaWater/CityWater/PiZhou/GetPredicateSensor`,
method: REQUEST_METHOD_GET,
params
})
}
// 获取统计数据
export function getStatisticsInfo(data) {
return request({
url: `${baseUrl}/PandaMonitor/Monitor/Device/EquipmentDataReport`,
method: REQUEST_METHOD_POST,
data,
});
}
export function getSensorsRealName (data) {
return request({
url:`${baseUrl}/PandaMonitor/Monitor/Device/GetStaticRealName`,
method: REQUEST_METHOD_POST,
data,
})
}
\ No newline at end of file
import React from 'react';
import HistoryView from '../index';
const deviceParams = [
/*const deviceParams = [
{
deviceCode: 'EGBF00000136',
sensors: '进水压力,出水瞬时流量,出水累计流量',
deviceType: '二供泵房',
pointAddressID: 4,
},
},*/
/* {
deviceCode: 'EGBF00000137',
sensors: '进水压力,出水瞬时流量,出水累计流量',
......@@ -21,7 +21,7 @@ const deviceParams = [
deviceType: '二供泵房',
pointAddressID: 4,
},*/
];
// ];
/*const deviceParams = [
{
"deviceCode": "LLJ00000055",
......@@ -58,9 +58,38 @@ const deviceParams = [
"deviceType": "二供泵房"
}
]*/
/*const deviceParams = [
{
"deviceCode": "EGBF00000244",
"sensors": "进水压力,出水瞬时流量,今日用电量",
"deviceType": "二供泵房"
},
{
"deviceCode": "EGBF00000081",
"sensors": "进水压力,出水瞬时流量,今日用电量",
"deviceType": "二供泵房"
}
]*/
const deviceParams = [
{
"deviceCode": "EGBF00000244",
"sensors": "进水压力,出水瞬时流量,今日用电量,今日供水量",
"deviceType": "二供泵房"
},
{
"deviceCode": "EGJZ00000317",
"sensors": "进水压力,出水瞬时流量",
"deviceType": "二供机组"
},
{
"deviceCode": "EGBF00000184",
"sensors": "进水压力,出水瞬时流量,今日用电量,今日供水量",
"deviceType": "二供泵房"
}
];
const Demo = () => {
return <div style={{ height: 700 }}>
<HistoryView deviceParams={deviceParams} grid />
return <div style={{height: 700}}>
<HistoryView deviceParams={deviceParams} grid/>
</div>;
};
......
......@@ -178,10 +178,16 @@ const deviceParams = [
"sensors": "PH,浑浊度,氨氮,总氮,总磷,溶解氧,水温,电导率,叶绿素a,藻密度,高锰酸盐指数"
}*/
/*邳州*/
{
/* {
"deviceCode": "TLC00000001",
"sensors": "1号碳滤池浊度",
"deviceType": "碳滤池"
}*/
/*邳州*/
{
"deviceCode": "SSBF00000001",
"sensors": "出水压力",
"deviceType": "送水泵房"
}
];
......
......@@ -35,7 +35,7 @@ import {
getExportDeviceHistoryUrl,
getDictionaryInfoAll,
getPointAddress,
getPointAddressEntry,
getPointAddressEntry, getPredicateSensor,
} from './apis';
import SingleChart from './SingleChart';
import GridChart from './GridChart';
......@@ -337,6 +337,8 @@ const HistoryView = (props) => {
//查询所有sensorType
const [allSensorType, setAllSensorType] = useState([]);
const [isSingleStatusSensor, setIsSingleStatusSensor] = useState(false);
const [predicateDevice, setPredicateDevice] = useState(null);
const [predicateData, setPredicateData] = useState(null);
// 历史数据相关的特征描述
const deviceConfig = useRef({
oneDevice: deviceParams.length === 1, //单设备
......@@ -1079,11 +1081,6 @@ const HistoryView = (props) => {
deviceParams
.map((item) => {
let _item = {...item};
// 历史曲线中,是否在线暂时去除,不显示 要显示是否在线解开这里即可 2023-09-15
/* _item.sensors =
item.sensors && !item.sensors.includes('是否在线')
? item.sensors + ',是否在线'
: item.sensors;*/
_item.sensors = item.sensors;
// special 业务
if (special1) {
......@@ -1092,7 +1089,7 @@ const HistoryView = (props) => {
return _item;
})
.forEach((i) => {
if (i.sensors && i.deviceCode && i.deviceCode)
if (i.sensors && i.deviceCode)
acrossTables.push(_.omit(i, ['pointAddressID']));
});
if (!acrossTables?.length || !dateRange.length) {
......@@ -1127,6 +1124,11 @@ const HistoryView = (props) => {
let _isNaN = isNaN(_num);
if (!_isNaN && _num >= 12) _finalParams.isInterpolation = false;
}
// 2024年1月23日 增加预测曲线,单设备单曲线
// 同期对比不允许、多设备的不允许
if (dateRange.length === 1 && predicateDevice) {
_finalParams.acrossTables.push(predicateDevice);
}
requestArr.push(getHistoryInfo(_finalParams));
});
setLoading(true);
......@@ -1135,6 +1137,7 @@ const HistoryView = (props) => {
setLoading(false);
if (results.length) {
let data = [];
let _predicateData = [];
results.forEach((res, index) => {
const {dateFrom, dateTo} = dateRange?.[index] ?? {};
if (res.code === 0 && res.data.length) {
......@@ -1165,7 +1168,8 @@ const HistoryView = (props) => {
};
});
});
deviceParams.forEach((p) => {
// 加入预测
(predicateDevice ? deviceParams.concat(predicateDevice) : deviceParams).forEach((p) => {
// 返回数据按查询指标顺序排序
const sensors = p.sensors?.split(',') ?? [];
if (sensors?.length) {
......@@ -1174,27 +1178,29 @@ const HistoryView = (props) => {
sensors.push(special1.name);
}
}
const list = sensors
.map((s) => {
const list = sensors.map((s) => {
const dataItem = res.data.find(
(d) => d.stationCode === p.deviceCode && d.sensorName === s,
);
if (dataItem) {
dataItem.dateFrom = dateFrom || '';
dataItem.dateTo = dateTo || '';
dataItem.deviceType = p.deviceType;
return dataItem;
} else {
return {};
}
})
.filter((item) => item.sensorName);
data = data.concat(list);
}).filter((item) => item.sensorName);
// 预测的
data = data.concat(list.filter(item => item.deviceType !== '预测'));
_predicateData = _predicateData.concat(list.filter(item => item.deviceType === '预测'));
});
}
});
setLoading(false);
handleTableData(data);
handleTableData(data)
setChartDataSource(data);
setPredicateData(_predicateData);
}
})
.catch((err) => {
......@@ -1322,6 +1328,11 @@ const HistoryView = (props) => {
contrast={timeValue === 'contrast'}
contrastOption={contrastOption}
deviceAlarmSchemes={deviceAlarmSchemes}
dateRange={dateRange}
allPointAddress={allPointAddress}
allSensorType={allSensorType}
loading={loading}
setLoading={setLoading}
/>
) : (
<SingleChart
......@@ -1331,6 +1342,7 @@ const HistoryView = (props) => {
showGridLine={chartGrid}
prefixCls={prefixCls}
dataSource={chartDataSource}
predicateData={predicateData}
chartType={isBoxPlots ? chartType : null}
contrast={timeValue === 'contrast'}
contrastOption={contrastOption}
......@@ -1374,11 +1386,13 @@ const HistoryView = (props) => {
// 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示
let _request1 = getPointAddressEntry(_params);
let _request2 = getSensorType();
await Promise.all([_request0, _request1, _request2]).then((result) => {
let _request3 = getPredicateSensor({deviceCode, sensors});
await Promise.all([_request0, _request1, _request2, _request3]).then((result) => {
if (result) {
let _res0 = result[0];
let _res1 = result[1];
let _res2 = result[2];
let _res3 = result[3];
// 查字典配置
if (_res0.code === 0) {
let _opt = _res0.data.reduce((final, cur) => {
......@@ -1421,6 +1435,10 @@ const HistoryView = (props) => {
let _isStatusSensor = ['状态值', '开关值'].includes(_sensor);
setIsSingleStatusSensor(_isStatusSensor);
}
// 单设备单曲线的设定加载
if (_res3.code === 0) {
setPredicateDevice({..._res3.data, deviceType: '预测'});
}
}
});
setCompleteInit(true);
......@@ -1497,11 +1515,6 @@ const HistoryView = (props) => {
<DownloadOutlined/>
下载
</Button>
{/* 保留此处代码,当项目需要表格定制时需要使用 */}
{/*<Button type="link" onClick={exportExcelBtn}>
<DownloadOutlined/>
原始数据
</Button> */}
</>
)}
</div>
......
......@@ -71,7 +71,7 @@ const currentOption = isMobile() ? MOBILE_OPTION : PC_OPTION;
*/
const nameFormatter = (data, contrast, contrastOption, nameWithSensor, isSingle) => {
const {equipmentName, sensorName, unit, dataModel, dateFrom, dateTo} = data;
let name = nameWithSensor ? (isSingle?`${sensorName}`:`${equipmentName}-${sensorName}`) : equipmentName;
let name = nameWithSensor ? (isSingle ? `${sensorName}` : `${equipmentName}-${sensorName}`) : equipmentName;
if (contrast) {
const time = dateFrom.slice(0, contrastOption === 'day' ? 10 : 7).replace(/-/g, '');
name = `${name}-${time}`;
......@@ -182,7 +182,20 @@ export const alarmMarkLine = (dataItem, index, dataSource, schemes) => {
data,
};
};
export const minMaxMarkPointForPredicateDevice = (dataItem, index, dateSource) => {
return {
symbol: 'circle',
animation: false,
label: {
show: false
},
symbolSize: 10,
data: [
{type: 'max', itemStyle: {color: '#dc5a5a'}},
{type: 'min', itemStyle: {color: '#62b659'}}
]
};
}
export const minMaxMarkPoint = (dataItem, index, dataSource) => {
const _isMobile = isMobile();
// 只有一个数据曲线时显示markline
......@@ -501,6 +514,8 @@ const returnXAxis = ({
smooth,
special,
yAxis,
predicateData,
chartType
}) => {
// 根据"指标名称"分类yAxis
const yAxisInterator = (() => {
......@@ -522,7 +537,8 @@ const returnXAxis = ({
if (!final.includes(cur.stationCode)) final.push(cur.stationCode);
return final
}, [])?.length;
let series = dataSource
// 线图 且 有预测数据情况下,才合并预测数据
let series = (predicateData && chartType === 'lineChart' ? dataSource.concat(predicateData) : dataSource)
.filter((item) => {
if (item.sensorName === '是否在线') {
_offlineData.push(item);
......@@ -537,20 +553,22 @@ const returnXAxis = ({
const areaStyle = areaStyleFormatter(item);
const _index = yAxis.findIndex((item) => item.name === unit);
const yAxisIndex = _index > -1 ? _index : 0;
const markLine = showMarkLine
let markLine = showMarkLine
? alarmMarkLine(item, index, dataSource, deviceAlarmSchemes)
: {};
const markPoint = showPoint ? minMaxMarkPoint(item, index, dataSource) : {};
// let markArea = null;
// 需求变更:设备离线改用“是否在线”的数据,离线的状态标记的数据用该部分的数据。 2023年4月25日09:36:55
// 暂时注释,离线逻辑需要再确认 2023-09-15
/* let _offlineAreasData = _offlineData
.find((offline) => offline.stationCode === item.stationCode);
let offlineAreas = offlineArea(_offlineAreasData);
if (offlineAreas.data?.length) {
restOption.markArea = null;
markArea = offlineAreas;
}*/
let markPoint = showPoint ? minMaxMarkPoint(item, index, dataSource) : {};
let _lineStyle = {};
if (item.deviceType === '预测' && chartType === 'lineChart') {
// markPoint = minMaxMarkPointForPredicateDevice(item, index, dataSource);
markPoint = null;
markLine = null;
_lineStyle = {
lineStyle: {
type: 'dashed',
color: '#07a49a'
}
}
}
// 需求新增:增加频率业务
return {
notMerge: true,
......@@ -564,6 +582,7 @@ const returnXAxis = ({
markLine,
markPoint,
markArea,
..._lineStyle,
};
});
// 由于series更新后,没有的数据曲线仍然停留在图表区上,导致图表可视区范围有问题
......@@ -967,6 +986,8 @@ const renderStatusItem = (params, api) => {
* @param {any} contrastOption 同期对比周期配置, day|month
* @param {any} smooth Ture/false, 曲线/折线
* @param {any} config 额外配置信息
* @param lineDataType
* @param predicateData
*/
const optionGenerator = (
......@@ -977,6 +998,7 @@ const optionGenerator = (
smooth,
config,
lineDataType = '',
predicateData
) => {
// 1. 处理配置,配置分配默认值;
const {
......@@ -1010,6 +1032,8 @@ const optionGenerator = (
restOption,
special,
yAxis,
predicateData,
chartType
});
// 3. 判断是否开启网格;
const grid = handleGrid(dataSource, needUnit, leftNum, rightNum, chartType);
......@@ -1110,6 +1134,7 @@ const optionGenerator = (
symbol: 'none',
});
});
// 加入预测逻辑
tooltip = {
trigger: 'axis',
formatter: (e) => {
......@@ -1156,6 +1181,62 @@ const optionGenerator = (
</div>`;
},
};
if (predicateData) {
tooltip = {
trigger: 'axis',
formatter: (e) => {
return `<div>
${headTemplate(e[0])}
<div>
<div style="display: flex; align-items: center;">
<span style="${
isMobile()
? 'width: ' +
handlePx(90, 'px') +
';overflow:hidden;text-overflow:ellipsis;white-space:nowrap'
: ''
}">${
e[0].seriesName
}</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.NORMAL};margin: 0 ${handlePx(
5,
'px',
)} 0 auto;">${e[0]?.value?.[1] ?? '-'}</span>
<span style="font-size: ${handlePx(12, 'px')};">${_unit ?? ''}</span>
</div>
<div style="display: ${predicateData && chartType === 'lineChart' && e.length >= 2 ? 'flex' : 'none'}">
<span>${e?.[1]?.seriesName}</span>
<span style="color: ${COLOR.NORMAL};margin: 0 ${handlePx(
5,
'px',
)} 0 auto;">${e[1]?.value?.[1] ?? '-'}</span>
<span style="font-size: ${handlePx(12, 'px')};">${_unit ?? ''}</span>
</div>
<div style="display: ${
lineDataType === '特征曲线' ? 'flex' : 'none'
}; align-items: center;">
<span>周期最小值</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.AVG};margin: 0 ${handlePx(
5,
'px',
)} 0 auto;">${e?.[2]?.value?.[1] ?? '-'}</span>
<span style="font-size: ${handlePx(12, 'px')};">${_unit ?? ''}</span>
</div>
<div style="display: ${
lineDataType === '特征曲线' ? 'flex' : 'none'
}; align-items: center;">
<span>周期最大值</span><span style="display:inline-block;">:</span>
<span style="color: ${COLOR.AVG};margin: 0 ${handlePx(
5,
'px',
)} 0 auto;">${_maxValues[e?.[3]?.dataIndex] ?? '-'}</span>
<span style="font-size: ${handlePx(12, 'px')};">${_unit ?? ''}</span>
</div>
</div>
</div>`;
},
};
}
}
// 单曲线需要标记最大值、最小值的情况下,需要增加自定义的series,将最大最小值显示在图表上
if (dataSource?.[0]?.dataModel?.length && chartType === 'lineChart') {
......
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