mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-08-03 09:34:04 +00:00
Co-authored-by: Fangyin Cheng <staneyffer@gmail.com> Co-authored-by: 谨欣 <echo.cmy@antgroup.com> Co-authored-by: 严志勇 <yanzhiyong@tiansuixiansheng.com> Co-authored-by: yanzhiyong <932374019@qq.com>
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import type { Datum } from '@antv/ava';
|
||
import { hasSubset } from '../advisor/utils';
|
||
import type { ChartKnowledge, CustomChart, GetChartConfigProps, Specification } from '../types';
|
||
import { findNominalField, findOrdinalField, getLineSize, processDateEncode, sortData } from './util';
|
||
|
||
const MULTI_LINE_CHART = 'multi_line_chart';
|
||
const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => {
|
||
const ordinalField = findOrdinalField(dataProps);
|
||
const nominalField = findNominalField(dataProps);
|
||
// 放宽折线图的 x 轴条件,优先选择 time, ordinal, nominal 类型,没有的话使用第一个字段作兜底
|
||
const field4X = ordinalField ?? nominalField ?? dataProps[0];
|
||
const remainFields = dataProps.filter(field => field.name !== field4X?.name);
|
||
|
||
const field4Y = remainFields.filter(
|
||
field => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Interval']),
|
||
) ?? [remainFields[0]];
|
||
const field4Nominal = remainFields
|
||
.filter(field => !field4Y.find(y => y.name === field.name))
|
||
.find(field => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal']));
|
||
if (!field4X || !field4Y) return null;
|
||
|
||
const spec: Specification = {
|
||
type: 'view',
|
||
autoFit: true,
|
||
data: sortData({ data, chartType: MULTI_LINE_CHART, xField: field4X }),
|
||
children: [],
|
||
};
|
||
|
||
field4Y.forEach(field => {
|
||
const singleLine: Specification = {
|
||
type: 'line',
|
||
encode: {
|
||
x: processDateEncode(field4X.name as string, dataProps),
|
||
y: field.name,
|
||
size: (datum: Datum) => getLineSize(datum, data, { field4Split: field4Nominal, field4X }),
|
||
},
|
||
legend: {
|
||
size: false,
|
||
},
|
||
};
|
||
if (field4Nominal) {
|
||
singleLine.encode.color = field4Nominal.name;
|
||
}
|
||
spec.children.push(singleLine);
|
||
});
|
||
return spec;
|
||
};
|
||
|
||
const ckb: ChartKnowledge = {
|
||
id: MULTI_LINE_CHART,
|
||
name: 'multi_line_chart',
|
||
alias: ['multi_line_chart'],
|
||
family: ['LineCharts'],
|
||
def: 'multi_line_chart uses lines with segments to show changes in data in a ordinal dimension',
|
||
purpose: ['Comparison', 'Trend'],
|
||
coord: ['Cartesian2D'],
|
||
category: ['Statistic'],
|
||
shape: ['Lines'],
|
||
dataPres: [
|
||
{ minQty: 1, maxQty: 1, fieldConditions: ['Time', 'Ordinal'] },
|
||
{ minQty: 1, maxQty: '*', fieldConditions: ['Interval'] },
|
||
{ minQty: 0, maxQty: 1, fieldConditions: ['Nominal'] },
|
||
],
|
||
channel: ['Color', 'Direction', 'Position'],
|
||
recRate: 'Recommended',
|
||
toSpec: getChartSpec,
|
||
};
|
||
|
||
/* 订制一个图表需要的所有参数 */
|
||
export const multi_line_chart: CustomChart = {
|
||
/* 图表唯一 Id */
|
||
chartType: 'multi_line_chart',
|
||
/* 图表知识 */
|
||
chartKnowledge: ckb as ChartKnowledge,
|
||
/** 图表中文名 */
|
||
chineseName: '折线图',
|
||
};
|
||
|
||
export default multi_line_chart;
|