Commit 658f834f authored by 陈龙's avatar 陈龙

feat: 历史曲线增加开关类型的图表

parent 706724f6
......@@ -30,7 +30,7 @@ path: /
## 多图表
<code src="./demos/GridDemo.js"></code>
[//]: # (<code src="./demos/GridDemo.js"></code>)
## API
......
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, minMaxMarkPoint, offlineArea} from './utils';
import {isArray, cloneDeep} from 'lodash';
import optionGenerator, {
alarmMarkLine,
minMaxMarkPoint,
offlineArea,
specialTypeChartOptionGenerator,
statusChartOptionGenerator
} from './utils';
import { isArray, cloneDeep } from 'lodash';
const SingleChart = memo((props) => {
const {
......@@ -19,7 +25,7 @@ const SingleChart = memo((props) => {
special
} = props;
const chartRef = useRef();
const SpecialType = ['状态值', '开关值']; // 横向柱状条
const option = useMemo(() => {
const config = {
needUnit: true,
......@@ -32,6 +38,21 @@ const SingleChart = memo((props) => {
showBoxOption,
special
};
let allValDesc = {};
let _allSensorType = special?.allSensorType?.reduce((final, curr) => {
final[curr.id] = curr.type;
return final;
}, {});
let _allPointAddress = special?.allPointAddress?.reduce((final, curr) => {
final[curr.name] = _allSensorType[curr.sensorTypeID];
allValDesc[curr.name] = curr.valDesc;
return final;
}, {});
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 optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType);
}, [dataSource, smooth, curveCenter, chartType]);
useEffect(() => {
......@@ -39,7 +60,7 @@ const SingleChart = memo((props) => {
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;
......@@ -105,7 +126,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({
......@@ -124,9 +145,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%' }} />
);
});
......
......@@ -8,13 +8,14 @@ const baseUrl = typeof DUMI_TYPE !== 'undefined' && DUMI_TYPE === 'dumi' ? '/api
const monitorDeviceUrl = `${baseUrl}/PandaMonitor/Monitor/Device`;
// 获取单个设备的配置信息
export function getPointAddress (params) {
export function getPointAddress(params) {
return request({
url: `/PandaMonitor/Monitor/PointAddress/GetPointAddress`,
method: REQUEST_METHOD_GET,
params
});
}
// 获取点表信息
export function getPointAddressEntry(params) {
return request({
......@@ -58,3 +59,10 @@ export function getDictionaryInfoAll(params) {
params
})
}
export function getSensorType() {
return request({
url: '/PandaMonitor/Monitor/Sensor/GetSensorType',
method: REQUEST_METHOD_GET,
})
}
\ No newline at end of file
......@@ -4,6 +4,18 @@ import { MobileHistoryChart } from "../mobile";
const deviceParams = [
/*10.182*/
/* {
"deviceCode": "EGBF00000136",
"sensors": "进水压力,出水瞬时流量,今日供水量,1#水箱液位,视频报警",
// "sensors": "视频报警",
"deviceType": "二供泵房"
}, */
{
"deviceCode": "EGJZ00000158",
"sensors": "进水压力,出水压力,泵1状态",
// "sensors": "泵1状态",
"deviceType": "二供机组"
}
/* {
deviceCode: 'EGBF00000141',
// sensors: '进水压力,出水瞬时流量,出水累计流量',
......@@ -16,13 +28,13 @@ const deviceParams = [
"sensors": "瞬时流量",
"deviceType": "水源井"
},*/
{
/* {
deviceCode: 'EGJZ00000197',
sensors: '进水压力,出水压力,出水瞬时流量,出水累计流量',
// sensors: '1#变频器运行频率',
deviceType: '二供机组',
// pointAddressID: 208,
},
},*/
/* {
deviceCode: 'EGJZ00000198',
sensors: '进水压力,出水压力,出水瞬时流量,出水累计流量',
......
......@@ -35,6 +35,7 @@ import SingleChart from './SingleChart';
import GridChart from './GridChart';
import './index.less';
import { globalConfig } from 'antd/lib/config-provider';
import { getSensorType } from "@wisdom-components/ec_realtimeinfo/es/apis";
const { RangePicker } = DatePicker;
const { Option } = Select;
......@@ -311,6 +312,10 @@ const HistoryView = (props) => {
const [percent, setPercent] = useState(0);
// 频率指标特殊业务
const [special1, setSpecial1] = useState(null);
const [allPointAddress, setAllPointAddress] = useState([]);
//查询所有sensorType
const [allSensorType, setAllSensorType] = useState([]);
const [isSingleStatusSensor, setIsSingleStatusSensor] = useState(false);
// 历史数据相关的特征描述
const deviceConfig = useRef({
oneDevice: deviceParams.length === 1,//单设备
......@@ -689,14 +694,14 @@ const HistoryView = (props) => {
);
};
const renderCurveOption = (isChart, isSingle) => {
const renderCurveOption = (isChart, isSingle, isStatus) => {
return (
<div
className={classNames(`${prefixCls}-cover`)}
style={isChart && isSingle ? { width: '100%' } : {}}
>
{
isChart ? <>
isChart && !isStatus ? <>
<div className={classNames(`${prefixCls}-label`)}>曲线选择</div>
<div className={`${prefixCls}-cover-item`}>
<Radio.Group
......@@ -713,7 +718,7 @@ const HistoryView = (props) => {
</div>
</> : ''
}
{isChart && isSingle && showBoxOption ? (
{isChart && isSingle && showBoxOption && !isStatus ? (
<>
{
lineDataType !== '原始曲线' ? <>
......@@ -736,6 +741,9 @@ const HistoryView = (props) => {
) : (
''
)}
{
!isStatus ?
<>
<div className={classNames(`${prefixCls}-label`)}>
{activeTabKey !== 'table' ? '曲线设置' : '表格设置'}
</div>
......@@ -762,6 +770,8 @@ const HistoryView = (props) => {
))}
</Select>
)}
</> : ''
}
</div>
);
};
......@@ -825,7 +835,7 @@ const HistoryView = (props) => {
key: dataIndex,
ellipsis: true,
align: 'center',
width:200
width: 200
};
// 同期对比
if (timeValue === 'contrast' && dataModel[0]) {
......@@ -1082,14 +1092,14 @@ const HistoryView = (props) => {
{...tableProps}
pagination={false}
onChange={handleChange}
scroll={{x:'max-content',y:'calc(100% - 40px)'}}
scroll={{ x: 'max-content', y: 'calc(100% - 40px)' }}
/>
) : (
<PandaEmpty />
)}
</div>
</>
}, [timeOrder, chartDataSource, columns, tableProps, tableData])
}, [timeOrder, chartDataSource, columns, tableProps, tableData, isSingleStatusSensor])
const returnLongestPeriod = (data) => {
let _earliest = ''
let _latest = '';
......@@ -1119,6 +1129,7 @@ const HistoryView = (props) => {
{renderCurveOption(
true,
deviceParams?.length === 1 && deviceParams?.[0]?.sensors?.split(',').length === 1,
isSingleStatusSensor
)}
</div>
{
......@@ -1151,6 +1162,8 @@ const HistoryView = (props) => {
deviceAlarmSchemes={deviceAlarmSchemes}
special={{
special1, // 频率业务
allPointAddress,
allSensorType, // 后续新增的开关量的特殊业务,用来处理开关量业务
}}
/>
)}
......@@ -1172,18 +1185,21 @@ const HistoryView = (props) => {
code: deviceCode
}))?.data?.[0]?.id;
let _params = {
deviceType: deviceType
// deviceType: deviceType
};
if (_id) _params.versionId = _id;
// 多曲线的居中,容易导致曲线被截断,故多曲线时,不请求
let _request0 = getDictionaryInfoAll({
level: '组件_ec_historyview'
});
// 以下请求为处理状态值、开关值的图表,只允许单曲线单指标情况下展示
let _request1 = getPointAddressEntry(_params);
await Promise.all([_request0, _request1]).then(result => {
let _request2 = getSensorType();
await Promise.all([_request0, _request1, _request2]).then(result => {
if (result) {
let _res0 = result[0];
let _res1 = result[1];
let _res2 = result[2];
// 查字典配置
if (_res0.code === 0) {
let _opt = _res0.data.reduce((final, cur) => {
......@@ -1203,6 +1219,7 @@ const HistoryView = (props) => {
if (_res1.code === 0) {
let _sensorConfig = _res1.data.find(item => item?.name.trim() === sensors.trim());
let _statusName = _sensorConfig?.statusName;
setAllPointAddress(_res1.data);
if (_statusName) {
let _statusConfig = _res1.data.find(item => item?.name.trim() === _statusName.trim());
let _valDesc = _statusConfig?.valDesc || '';
......@@ -1216,6 +1233,15 @@ const HistoryView = (props) => {
});
}
}
// 标记sensor是什么类型的
if (_res2.code === 0) {
setAllSensorType(_res2.data);
let _sensorID = _res1.data?.find(item => item.name === sensors)?.sensorTypeID;
let _sensor = _res2.data?.find(item => item.id === _sensorID)?.type;
let _isStatusSensor = ['状态值', '开关值'].includes(_sensor);
setIsSingleStatusSensor(_isStatusSensor);
}
}
});
setCompleteInit(true);
......
import moment from 'moment';
import _, {isArray} from 'lodash';
import _, { isArray } from 'lodash';
import maxIcon from './assets/最大实心.svg';
import minIcon from './assets/最小实心.svg';
import minIconDownArrow from './assets/最小实心箭头朝下.svg';
import lineChart from '@wisdom-components/basicchart/es/LineChart';
import * as echarts from "echarts";
/** 轴宽度, 用于计算多轴显示时, 轴线偏移和绘图区域尺寸 */
const AXIS_WIDTH = 40;
......@@ -67,7 +68,7 @@ const currentOption = isMobile() ? MOBILE_OPTION : PC_OPTION;
* @returns
*/
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;
if (contrast) {
const time = dateFrom.slice(0, contrastOption === 'day' ? 10 : 7).replace(/-/g, '');
......@@ -102,7 +103,7 @@ const dataAccessor = (data, contrast, contrastOption) => {
* @returns Null/areaStyle, 为null显示曲线图, 为areaStyle对象显示为面积图.
*/
const areaStyleFormatter = (data) => {
const {sensorName} = data;
const { sensorName } = data;
return sensorName && sensorName.indexOf('流量') > -1 ? {} : null;
};
......@@ -113,7 +114,7 @@ const areaStyleFormatter = (data) => {
* @returns
*/
const minMax = (data) => {
const {dataModel} = data;
const { dataModel } = data;
let min = Number.MAX_SAFE_INTEGER;
let max = Number.MIN_SAFE_INTEGER;
dataModel.forEach((item) => {
......@@ -144,7 +145,7 @@ const markLineItem = (name, value, color) => {
export const alarmMarkLine = (dataItem, index, dataSource, schemes) => {
// 只有一个数据曲线时显示markline
if (!dataItem || !schemes || dataSource.length !== 1) return {};
const {deviceType, stationCode, sensorName, decimalPoint} = dataItem;
const { deviceType, stationCode, sensorName, decimalPoint } = dataItem;
const curSchemes = schemes.filter(
(item) =>
item.deviceCode === stationCode &&
......@@ -153,7 +154,7 @@ export const alarmMarkLine = (dataItem, index, dataSource, schemes) => {
);
const data = [];
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'));
hLimit !== null && hLimit !== void 0 && data.push(markLineItem('高限', hLimit, '#fa8c16'));
llLimit !== null && llLimit !== void 0 && data.push(markLineItem('低低限', llLimit, '#FF0000'));
......@@ -245,7 +246,7 @@ export const decorateAxisGridLine = (axis, showGrid) => {
*/
export const offlineArea = (dataItem) => {
if (!dataItem) return {};
const {dataModel} = dataItem;
const { dataModel } = dataItem;
let datas = new Array();
let offlineData = [];
let hasOffline = false;
......@@ -255,7 +256,7 @@ export const offlineArea = (dataItem) => {
{
name: '离线',
xAxis: new Date(item.pt),
label: {show: !datas?.length},
label: { show: !datas?.length },
},
];
hasOffline = true;
......@@ -279,7 +280,7 @@ export const offlineArea = (dataItem) => {
// tooltip 模板
const headTemplate = (param, opt) => {
if (!param) return '';
const {name, axisValueLabel, axisType, axisValue} = param;
const { name, axisValueLabel, axisType, axisValue } = param;
const timeFormat =
opt && opt.contrast
? opt.contrastOption === 'day'
......@@ -295,7 +296,7 @@ const headTemplate = (param, opt) => {
};
const seriesTemplate = (param, unit) => {
if (!param || param.seriesName === '自定义') return '';
const {value, encode} = param;
const { value, encode } = param;
// const val = value[encode.y[0]];
const _unit = unit || '';
const color = '#008CFF';
......@@ -444,7 +445,7 @@ const handleSpecial1 = (special, dataSource) => {
},
},
name: item.text,
label: {show: true},
label: { show: true },
},
{
xAxis: item.lte,
......@@ -490,17 +491,17 @@ const returnXAxis = ({
smooth,
special,
yAxis
}) => {
}) => {
// 根据"指标名称"分类yAxis
const yAxisInterator = (() => {
const map = new Map();
let current = -1;
const get = (name) => (map.has(name) ? map.get(name) : map.set(name, ++current).get(name));
return {get};
return { get };
})();
let _offlineData = [];
// 生成visualMap、markArea
let {visualMap, markArea} = handleSpecial1(special, dataSource);
let { visualMap, markArea } = handleSpecial1(special, dataSource);
let _filterArr = ['是否在线'];
if (special?.special1?.name) {
_filterArr.push(special.special1.name);
......@@ -514,14 +515,13 @@ const returnXAxis = ({
return !_filterArr.includes(item.sensorName);
})
.map((item, index) => {
const {sensorName, unit} = item;
const { sensorName, unit } = item;
const name = nameFormatter(item, contrast, contrastOption, nameWithSensor);
const data = dataAccessor(item, contrast, contrastOption);
const type = 'line';
const areaStyle = areaStyleFormatter(item);
const _index = yAxis.findIndex(item => item.name === unit);
const yAxisIndex = _index > -1 ? _index : 0;
// console.log('yAxisIndex: ',yAxisInterator);
const markLine = showMarkLine
? alarmMarkLine(item, index, dataSource, deviceAlarmSchemes)
: {};
......@@ -628,11 +628,11 @@ const reduceYAxis = (arr, dataSource) => {
}
return final;
}, {});
console.log('datasource: ', dataSource);
// 2. 合并相同单位的数据,找出最大值
let _maxValueArr = Object.values(dataSource.reduce((final, cur) => {
let _key = cur.name === null ? 'null' : cur.name;
let _key = cur.sensorName === null ? 'null' : cur.sensorName;
let _maxValue = cur.dataModel.reduce((final, cur) => {
// eslint-disable-next-line no-param-reassign
if (cur.pv > final) final = cur.pv;
return final
}, 0);
......@@ -646,9 +646,13 @@ const reduceYAxis = (arr, dataSource) => {
// 3. 合并,生成Y轴配置
return Object.values(_arr).map((item, index) => {
let _key = item.name === null ? 'null' : item.name;
let _offset = _maxValueArr[index - 2];
let _lastAxisNumber = _maxValueArr[index - 2];
let _baseOffset = _offsetValue[index - 2] ?? 0;
let _finalOffset = (_offset !== undefined ? (_offset === 0 ? 2 : _offset.toString().replaceAll('.', '').length) * 12 : 0) + _baseOffset;
let _finalOffset = (
_lastAxisNumber !== undefined ? // 没有相邻的轴
(_lastAxisNumber === 0 ? 20 : _lastAxisNumber.toFixed(2).replaceAll('.', '').length) * 12
: 0
) + _baseOffset;
_offsetValue.push(_finalOffset);
return ({
...item,
......@@ -660,15 +664,23 @@ const reduceYAxis = (arr, dataSource) => {
})
});
};
const handleYAxis = ({dataSource, needUnit, curveCenter, showGridLine}) => {
// 1. 新需求:合并相同的坐标轴
// 一种指标一个y轴 -------- 需求变更:相同类型的指标放到同一指标轴(单位相同) 2023年9月28日
/**
*
* 1. 生成常规的yAxis配置;
* 2. 处理sensorType为状态值的指标,生成yAxis配置
*
* @param {array} dataSource 数据源
* @param {boolean} needUnit 是否显示单位。
* @param {boolean} curveCenter 曲线是否居中。
* @param {boolean} showGridLine 是否显示网格线。
* @return {object} 返回左右轴的margin、yAxis的配置。
* */
const handleYAxis = ({ dataSource, needUnit, curveCenter, showGridLine }) => {
const yAxisMap = new Map();
// 1. 找出最大值; 2. 计算出y轴最大宽度动态计算偏移距离;
dataSource.forEach((item, index) => {
const {sensorName, unit} = item;
const { sensorName, unit } = item;
const key = sensorName;
if (!yAxisMap.has(key)) {
/* const i = yAxisMap.size;
......@@ -704,7 +716,6 @@ const handleYAxis = ({dataSource, needUnit, curveCenter, showGridLine}) => {
};
yAxisMap.set(key, axis);
}
// 曲线居中
if (curveCenter && item.dataModel && item.dataModel.length > 0) {
const [min, max] = minMax(item);
......@@ -712,16 +723,28 @@ const handleYAxis = ({dataSource, needUnit, curveCenter, showGridLine}) => {
axis.min = axis.min === void 0 ? min : Math.min(min, axis.min);
axis.max = axis.max === void 0 ? max : Math.max(max, axis.max);
}
// 网格显示
const axis = yAxisMap.get(key);
decorateAxisGridLine(axis, showGridLine);
});
const yAxis = yAxisMap.size > 0 ? reduceYAxis([...yAxisMap.values()], dataSource) : {type: 'value'};
const yAxis = yAxisMap.size > 0 ? reduceYAxis([...yAxisMap.values()], dataSource) : { type: 'value' };
const leftNum = Math.ceil(yAxisMap.size / 2);
const rightNum = Math.floor(yAxisMap.size / 2);
return {leftNum, rightNum, yAxis};
return { leftNum, rightNum, yAxis };
};
/**
* 1. 最后的配置处理、合并
* dataZoom 缩放
* xAxis.minInterval X轴的最小间隔
* legend legend配置
* @param {object} restOption 额外配置
* @param {object} xAxis x轴的配置
* @param {array} legendData legend数组
* @param {string} chartType 线型 lineChart|boxChart
* @param {boolean} contrast 是否为同期对比
* @param {string} contrastOption 同期对比周期配置, day|month
* @param {object} config 其他的配置
* */
const assignOptions = (restOption, xAxis, legendData, chartType, contrast, contrastOption, config) => {
restOption.dataZoom = [
{
......@@ -754,7 +777,7 @@ const assignOptions = (restOption, xAxis, legendData, chartType, contrast, contr
];
xAxis.minInterval = 3600 * (1 * 1000);
if (legendData) {
restOption.legend = {...restOption.legend, ...{data: legendData}};
restOption.legend = { ...restOption.legend, ...{ data: legendData } };
}
};
......@@ -802,7 +825,7 @@ const handleGrid = (dataSource, needUnit, leftNum, rightNum, chartType) => {
return {
top: _base + _topForUnit,
// left: leftNum === 1 ? 10 : leftNum * AXIS_WIDTH,
left: 20,
left: 30,
right: 10,
// right: rightNum === 0 ? 20 : rightNum * AXIS_WIDTH,
bottom: 60,
......@@ -879,6 +902,36 @@ const returnCustomSeries = (dataSource) => {
data: [_minNumber, _maxNumber],
};
};
const renderStatusItem = (params, api) => {
var categoryIndex = api.value(0);
var start = api.coord([api.value(1), categoryIndex]);
var end = api.coord([api.value(2), categoryIndex]);
var height = api.size([0, 1])[1] * 0.4;
var rectShape = echarts.graphic.clipRectByRect(
{
x: start[0],
y: start[1] - height / 2,
width: end[0] - start[0],
height: height
},
{
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height
}
);
return (
rectShape && {
type: 'rect',
transition: ['shape'],
shape: rectShape,
style: api.style()
}
);
}
/**
* 图表配置项生成
*
......@@ -899,6 +952,7 @@ const optionGenerator = (
config,
lineDataType = '',
) => {
// 1. 处理配置,配置分配默认值;
const {
needUnit,
curveCenter,
......@@ -912,17 +966,13 @@ const optionGenerator = (
restOption,
special,
} = handleDefault(config, cusOption);
const {leftNum, rightNum, yAxis} = handleYAxis({
const { leftNum, rightNum, yAxis } = handleYAxis({
dataSource,
needUnit,
curveCenter,
showGridLine,
});
console.log(yAxis);
const grid = handleGrid(dataSource, needUnit, leftNum, rightNum, chartType);
let {xAxis, series, visualMap} = returnXAxis({
let { xAxis, series, visualMap } = returnXAxis({
dataSource,
contrast,
contrastOption,
......@@ -935,6 +985,8 @@ const optionGenerator = (
special,
yAxis
});
// 3. 判断是否开启网格;
const grid = handleGrid(dataSource, needUnit, leftNum, rightNum, chartType);
decorateAxisGridLine(xAxis, showGridLine);
const tooltipTimeFormat = !contrast
? 'YYYY-MM-DD HH:mm:ss'
......@@ -947,16 +999,16 @@ const optionGenerator = (
if (chartType === 'boxChart' && lineDataType === '特征曲线') {
const otherData =
dataSource?.[0]?.dataModel.map((item) => {
const {firstPV, lastPV, maxPV, minPV, pt} = item;
const { firstPV, lastPV, maxPV, minPV, pt } = item;
return [moment(pt).valueOf(), firstPV, lastPV, minPV, maxPV];
}) || []; //当存在othersData的时候,只是单曲线
xAxis = {type: 'time'};
xAxis = { type: 'time' };
decorateAxisGridLine(xAxis, showGridLine);
let unit = [];
series = series.map((item) => {
if (item.unit) unit.push(item.unit);
item.areaStyle = null;
return {...item, showSymbol: false};
return { ...item, showSymbol: false };
});
series.push({
type: 'candlestick',
......@@ -987,7 +1039,7 @@ const optionGenerator = (
* 2. 当最大值小于零时(此时,最小值一定小于零);
*/
dataSource?.[0]?.dataModel.forEach((item) => {
const {firstPV, lastPV, maxPV, minPV, pt} = item;
const { firstPV, lastPV, maxPV, minPV, pt } = item;
_maxValues.push(maxPV);
let time = contrast ? moment(pt).format(formatStr) : pt;
_maxData.push([
......@@ -997,13 +1049,13 @@ const optionGenerator = (
_minData.push([moment(time).valueOf(), maxPV > 0 ? minPV : maxPV]);
}); //当存在othersData的时候,只是单曲线
// xAxis = {type: 'category', data: series[0].data.map(item => moment(item[0]).format('YYYY-MM-DD HH:mm:ss'))};
xAxis = {type: 'time'};
xAxis = { type: 'time' };
decorateAxisGridLine(xAxis, showGridLine);
let _unit = '';
series = series.map((item) => {
_unit = item.unit ?? '';
item.areaStyle = null;
return {...item, showSymbol: false};
return { ...item, showSymbol: false };
});
[[..._minData], [..._maxData]].forEach((item, index) => {
series.push({
......@@ -1076,7 +1128,7 @@ const optionGenerator = (
} else {
tooltip = tooltipAccessor(
series.map((item) => item.unit),
{contrastOption, contrast},
{ contrastOption, contrast },
);
}
tooltip.timeFormat = tooltipTimeFormat;
......@@ -1093,8 +1145,232 @@ const optionGenerator = (
visualMap,
...restOption,
};
console.log('_options: ', _options)
return _options;
};
export default optionGenerator;
const handleDataSource = (dataSource) => {
let _temp = null;
let _data = [];
let _dataLength = dataSource[0].dataModel.length;
// handleSpecial2()
dataSource[0].dataModel.forEach((item, index) => {
if (index === 0) {
_data.push(item)
} else if (index === _dataLength - 1) {
_data.push(item);
} else {
if (_temp.pv !== item.pv) {
_data.push(item);
}
}
_temp = item;
});
return _data
};
const returnLegend = (sensorType) => {
const _colorMap = {
变频: '#1685ff',
工频: '#00d0c7',
运行: '#1685ff',
故障: '#ff6b37',
停止: '#666666',
};
};
const handleSpecial2 = (special, sensorName, sensorType, data1, data2) => {
let color = '';
let name = '';
let value1 = '';
let value2 = '';
// 1. valDesc
if (sensorType === '状态值') {
const _colorMap = {
变频: '#1685ff',
工频: '#00d0c7',
运行: '#1685ff',
故障: '#ff6b37',
停止: '#666666',
};
let _valDescMap = special.allValDesc[sensorName]?.split(';').reduce((final, cur) => {
let _arr = cur.split(':');
final[_arr[0]] = _arr[1];
return final
}, {});
name = _valDescMap[data1.pv];
color = _colorMap[name];
}
//2. 开关量
if (sensorType === '开关值') {
const _switchColorMap = {
0: '#666666',
1: '#1685ff'
};
const _switchNameMap = {
0: '关',
1: '开'
}
name = _switchNameMap[data1.pv];
color = _switchColorMap[data1.pv];
};
value1 = moment(data1.pt).valueOf();
value2 = moment(data2.pt).valueOf();
return { color, value1, value2, name }
};
const handleDataToSeries = (special, sensorName, sensorType, data) => {
let _data = [];
let _legend = []
data.forEach((item, index) => {
if (index === data.length - 1) return;
let { color, value1, value2, name } = handleSpecial2(special, sensorName, sensorType, item, data[index + 1])
if (!_legend.includes(name)) _legend.push(name);
_data.push({
itemStyle: { normal: { color } },
name: name,
value: [0, value1, value2, `${item.pt}-${data[index + 1].pt}`]
});
});
return { data: _data, legend: _legend };
};
const specialTypeChartOptionGenerator = ({ dataSource, cusOption, contrast, contrastOption, smooth, config }) => {
const { special, sensorType } = config;
const { allSensorType, allPointAddress } = special;
// 处理原始数据,处理数据为后series数据
const sensorName = dataSource[0].sensorName;
let _data = handleDataSource(dataSource);
let { data, legend } = handleDataToSeries(special, sensorName, sensorType, _data);
// 1. x/y轴
let xAxis = {
type: 'time',
axisLabel: {
formatter: contrast ? (contrastOption === 'month' ? '{dd}日' : '{HH}:{mm}')
: {
year: '{yyyy}',
month: '{MMM}',
day: '{MMM}{d}日',
hour: '{HH}:{mm}',
minute: '{HH}:{mm}',
second: '{HH}:{mm}:{ss}',
none: '{yyyy}-{MM}-{dd} {hh}:{mm}:{ss}',
},
},
minorTick: {
lineStyle: {
color: "#e2e2e2"
},
show: true,
splitNumber: 2
},
minorSplitLine: {
lineStyle: {
color: "#e2e2e2",
type: "dashed"
},
show: true
},
splitLine: {
show: true
},
"minInterval": 3600000
};
let yAxis = {
data: [dataSource[0].sensorName],
axisLine: {
show: true
},
minorTick: {
lineStyle: {
color: "#e2e2e2"
},
show: true,
splitNumber: 2
},
minorSplitLine: {
lineStyle: {
color: "#e2e2e2",
type: "dashed"
},
show: true
},
splitLine: {
show: true
},
};
//2. series
let series = [
{
type: 'custom',
renderItem: renderStatusItem,
itemStyle: {
opacity: 0.8
},
encode: {
x: [1, 2],
y: 0
},
data
},
...legend.map(item => {
let _map = {
变频: '#1685ff',
工频: '#00d0c7',
运行: '#1685ff',
故障: '#ff6b37',
停止: '#666666',
: '#666666',
: '#1685ff'
}
return {
type:'custom',
name:item,
color:_map[item],
renderItem:()=>{}
}
})
];
let grid = {
top: 80,
left: 30,
right: 10,
bottom: 60,
containLabel: true
};
let legendConfig = {
show: true,
data: legend,
selectedMode: false,
left: 'center',
top: 30
}
let _option = {
xAxis,
yAxis,
grid,
series,
legend: legendConfig,
tooltip: {
trigger: 'item',
formatter: function (params) {
return params.marker + params.name + ': ' + params?.value?.[3];
}
},
dataZoom: [
{
type: 'slider',
filterMode: 'weakFilter',
showDataShadow: false,
labelFormatter: ''
},
{
type: 'inside',
filterMode: 'weakFilter'
}
],
}
return _option;
};
export {
specialTypeChartOptionGenerator
}
\ No newline at end of file
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