You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dashboard/src/components/LineWithKPI.jsx

104 lines
3.4 KiB
JavaScript

import { observer } from 'mobx-react';
import { Line } from '@ant-design/plots';
import { merge, isEmpty, groupBy, sortBy } from '../utils/commons';
import { dataFieldAlias } from '../libs/ht';
export default observer((props) => {
const { dataSource, showKPI, ...config } = props;
const kpiKey = dataFieldAlias[config.yField]?.nestkey?.v;
const seriesData = groupBy(dataSource, ele => ele[config.seriesField]);
const splitData = showKPI ? dataSource.reduce((r, v) => {
r.push(v);
if ( ! isEmpty(v[kpiKey])) { // 有设目标才多显示一条虚线, 颜色和数据线一致
r.push({...v, [config.yField]: v[kpiKey], [config.seriesField]: `${v[config.seriesField]} ${dataFieldAlias[kpiKey].label}`, extraLine: true,});
}
return r;
}, []).sort(sortBy(config.xField)) : (dataSource.slice()).sort(sortBy(config.xField));
const dataColors = [
"#5D7092","#F6BD16","#6F5EF9","#6DC8EC","#945FB9","#FF9845","#1E9493",
"#FF99C3","#FF6B3B","#626681","#FFC100","#9FB40F","#76523B","#DAD5B5",
"#0E8E89","#E19348","#F383A2","#247FEA","#5B8FF9","#5AD8A6",
];
const colorSets = Object.keys(seriesData)
.sort()
.filter((ele) => !ele.includes(' '))
.reduce((obj, k, i) => ({ ...obj, [k]: dataColors[i] || dataColors[i % 20] }), {});
// console.log('colorSets', colorSets);
const mergeLineConfig = merge(
{
color: (item) => {
const thisSeries = item[config.seriesField]?.split(' ')?.[0];
return colorSets[thisSeries];
},
lineStyle: (data) => {
if (data[config.seriesField].includes('目标')) {
return {
lineDash: [8, 20],
opacity: 0.5,
};
}
if (data[config.seriesField].includes('@')) {
return {
lineDash: [4, 8],
opacity: 0.6,
lineWidth: 1.5,
};
}
return {
opacity: 1,
};
},
legend: {
custom: true,
items: Object.keys(seriesData)
.map((ele) => ({
id: ele,
name: ele,
value: ele,
marker: {
symbol: ele.includes(' ') ? 'hyphen' : 'circle',
style: { fill: colorSets[ele], stroke: colorSets[ele?.split(' ')?.[0]] || '#5B8FF9', r: 3, lineWidth: 2, color: colorSets[ele] },
},
}))
.sort(sortBy('name')),
},
tooltip: {
// title: dataFieldAlias[config.yField]?.alias,
showTitle: true,
customItems: (items) => items.sort(sortBy('name')).map((ele) => ({ ...ele, title: `${ele.title} ${dataFieldAlias[config.yField]?.alias}` })),
},
// annotations: [
// // 低于 0 颜色变化
// {
// type: 'regionFilter',
// start: ['min', 0],
// end: ['max', 0],
// color: '#F4664A',
// },
// {
// type: 'text',
// position: ['min', 0],
// content: '0',
// offsetY: -4,
// style: {
// textBaseline: 'bottom',
// },
// },
// {
// type: 'line',
// start: ['min', 0],
// end: ['max', 0],
// style: {
// stroke: '#F4664A',
// lineDash: [2, 2],
// },
// },
// ],
},
config
);
return <Line {...mergeLineConfig} data={splitData} />;
});