fix(web): fix inconsistency between model recommendation charts and display charts (#1615)

Co-authored-by: hzh97 <2976151305@qq.com>
Co-authored-by: aries_ckt <916701291@qq.com>
This commit is contained in:
chenluli
2024-06-13 19:33:36 +08:00
committed by GitHub
parent 57f7b6d64c
commit 28c67efbea
256 changed files with 144 additions and 62117 deletions

View File

@@ -1,17 +1,17 @@
import { hasSubset, intersects } from '../advisor/utils';
import { processDateEncode } from './util';
import { findOrdinalField, processDateEncode, findNominalField, isUniqueXValue, getLineSize } from './util';
import type { ChartKnowledge, CustomChart, GetChartConfigProps, Specification } from '../types';
import type { Datum } from '@antv/ava';
const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => {
const field4X = dataProps.find((field) =>
// @ts-ignore
intersects(field.levelOfMeasurements, ['Time', 'Ordinal']),
);
// @ts-ignore
const field4Y = dataProps.filter((field) => hasSubset(field.levelOfMeasurements, ['Interval']));
const field4Nominal = dataProps.find((field) =>
// @ts-ignore
hasSubset(field.levelOfMeasurements, ['Nominal']),
const ordinalField = findOrdinalField(dataProps);
const nominalField = findNominalField(dataProps);
// 放宽折线图的 x 轴条件,优先选择 time ordinal 类型,没有的话使用 nominal 类型
const field4X = ordinalField ?? nominalField;
const field4Y = dataProps.filter((field) => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Interval']));
const field4Nominal = dataProps.find(
(field) => field.name !== field4X?.name && field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal']),
);
if (!field4X || !field4Y) return null;
@@ -28,6 +28,10 @@ const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConf
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) {

View File

@@ -1,16 +1,16 @@
import { hasSubset } from '../advisor/utils';
import type { ChartKnowledge, CustomChart, GetChartConfigProps, Specification } from '../types';
import { findNominalField, findOrdinalField } from './util';
const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => {
try {
// @ts-ignore
const field4Y = dataProps?.filter((field) => hasSubset(field.levelOfMeasurements, ['Interval']));
const field4Nominal = dataProps?.find((field) =>
// @ts-ignore
hasSubset(field.levelOfMeasurements, ['Nominal']),
);
if (!field4Nominal || !field4Y) return null;
const nominalField = findNominalField(dataProps);
const ordinalField = findOrdinalField(dataProps);
const field4X = nominalField ?? ordinalField;
if (!field4X || !field4Y) return null;
const spec: Specification = {
type: 'view',
@@ -22,7 +22,7 @@ const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConf
const singleLine: Specification = {
type: 'interval',
encode: {
x: field4Nominal.name,
x: field4X.name,
y: field.name,
color: () => field.name,
series: () => field.name,

View File

@@ -1,15 +1,13 @@
import { hasSubset, intersects } from '../advisor/utils';
import { processDateEncode } from './util';
import { hasSubset } from '../advisor/utils';
import { findNominalField, findOrdinalField, getLineSize, processDateEncode } from './util';
import type { ChartKnowledge, CustomChart, GetChartConfigProps, Specification } from '../types';
import { Datum } from '@antv/ava';
const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => {
try {
// @ts-ignore
const field4Y = dataProps?.filter((field) => hasSubset(field.levelOfMeasurements, ['Interval']));
const field4Nominal = dataProps?.find((field) =>
// @ts-ignore
hasSubset(field.levelOfMeasurements, ['Nominal']),
);
const field4Nominal = findNominalField(dataProps) ?? findOrdinalField(dataProps);
if (!field4Nominal || !field4Y) return null;
const spec: Specification = {
@@ -26,6 +24,10 @@ const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConf
y: field.name,
color: () => field.name,
series: () => field.name,
size: (datum: Datum) => getLineSize(datum, data, { field4X: field4Nominal }),
},
legend: {
size: false,
},
};
spec.children.push(singleLine);

View File

@@ -1,3 +1,7 @@
import { Datum, FieldInfo } from '@antv/ava';
import { hasSubset, intersects } from '../advisor/utils';
import { uniq } from 'lodash';
type BasicDataPropertyForAdvice = any;
/**
@@ -14,3 +18,35 @@ export function processDateEncode(field: string, dataProps: BasicDataPropertyFor
}
return field;
}
export function findOrdinalField(fields: FieldInfo[]) {
return fields.find((field) => field.levelOfMeasurements && intersects(field.levelOfMeasurements, ['Time', 'Ordinal']));
}
export function findNominalField(fields: FieldInfo[]) {
return fields.find((field) => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal']));
}
// 识别 x 轴是否只有一条数据(绘制的折线图是否只有一个点)
export const isUniqueXValue = ({ data, xField }: { xField: string; data: Datum[] }): boolean => {
const uniqXValues = uniq(data.map((datum) => datum[xField]));
return uniqXValues.length <= 1;
};
/** 获取线宽:当只有一条数据时,折线图需要特殊设置线宽,否则仅绘制 1px看不见 */
export const getLineSize = (
datum: Datum,
allData: Datum[],
fields: {
field4Split?: FieldInfo;
field4X?: FieldInfo;
},
) => {
const { field4Split, field4X } = fields;
if (field4Split?.name && field4X?.name) {
const seriesValue = datum[field4Split.name];
const splitData = allData.filter((item) => field4Split.name && item[field4Split.name] === seriesValue);
return isUniqueXValue({ data: splitData, xField: field4X.name }) ? 5 : undefined;
}
return field4X?.name && isUniqueXValue({ data: allData, xField: field4X.name }) ? 5 : undefined;
};