diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/chart.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/chart.ts index ddccbab7f8..c6f0227b63 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/chart.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/chart.ts @@ -121,6 +121,7 @@ export class Chart implements ChartType { let xField: FieldOption; let yField: FieldOption; let seriesField: FieldOption; + let colorField: FieldOption; let yFields: FieldOption[]; const getField = (fields: FieldOption[], selected: { field: string | string[]; alias?: string }) => { if (selected.alias) { @@ -146,17 +147,19 @@ export class Chart implements ChartType { xIndex = i; } }); - if (xIndex) { - // If there is a time field, the other field is used as the series field by default. - const index = xIndex === 0 ? 1 : 0; - seriesField = getField(fields, dimensions[index]); - } else { - xField = getField(fields, dimensions[0]); - seriesField = getField(fields, dimensions[1]); + xIndex = xIndex || 0; + xField = xField || getField(fields, dimensions[xIndex]); + const restFields = dimensions.filter((_, i) => i !== xIndex).map((i) => getField(fields, i)); + if (restFields.length === 1) { + seriesField = restFields[0]; + colorField = restFields[0]; + } else if (restFields.length > 1) { + colorField = restFields[0]; + seriesField = restFields[1]; } } } - return { xField, yField, seriesField, yFields }; + return { xField, yField, seriesField, colorField, yFields }; } /** diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/configs.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/configs.ts index b943a91e54..f41f44fe1f 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/configs.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/configs.ts @@ -49,4 +49,5 @@ export default { xField: (props: FieldConfigProps) => selectField({ name: 'xField', title: 'xField', required: true, ...props }), yField: (props: FieldConfigProps) => selectField({ name: 'yField', title: 'yField', required: true, ...props }), seriesField: (props: FieldConfigProps) => selectField({ name: 'seriesField', title: 'seriesField', ...props }), + colorField: (props: FieldConfigProps) => selectField({ name: 'colorField', title: 'colorField', ...props }), }; diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/dualAxes.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/dualAxes.ts index 437c2d18c8..58e78f5fd9 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/dualAxes.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/dualAxes.ts @@ -2,6 +2,7 @@ import { G2PlotChart } from './g2plot'; import { ChartType, RenderProps } from '../chart'; import React from 'react'; import { DualAxes as G2DualAxes } from '@ant-design/plots'; +import lodash from 'lodash'; export class DualAxes extends G2PlotChart { constructor() { @@ -59,18 +60,38 @@ export class DualAxes extends G2PlotChart { return { general: { xField: xField?.value, - yField: yFields?.map((f) => f.value).slice(0, 2) || [], + yField: yFields?.map((f) => f.value) || [], }, }; }; - render({ data, general, advanced, fieldProps }: RenderProps) { - const props = this.getProps({ data, general, advanced, fieldProps }); - const { data: _data } = props; - return () => - React.createElement(this.component, { - ...props, - data: [_data, _data], - }); + getProps({ data, general, advanced, fieldProps }: RenderProps) { + const props = super.getProps({ data, general, advanced, fieldProps }); + return { + ...lodash.omit(props, ['legend', 'tooltip']), + children: + props.yField?.map((yField: string, index: number) => { + return { + type: 'line', + yField, + colorField: () => { + const props = fieldProps[yField]; + const transformer = props?.transformer; + return props?.label || (transformer ? transformer(yField) : yField); + }, + axis: { + y: { + title: fieldProps[yField]?.label || yField, + position: index === 0 ? 'left' : 'right', + labelFormatter: (datnum) => { + const props = fieldProps[yField]; + const transformer = props?.transformer; + return transformer ? transformer(datnum) : datnum; + }, + }, + }, + }; + }) || [], + }; } } diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/g2plot.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/g2plot.ts index 9277ee8362..fd73f177e5 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/g2plot.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/g2plot.ts @@ -1,6 +1,5 @@ +import { transform } from 'lodash'; import { Chart, ChartProps, ChartType, RenderProps } from '../chart'; -import { FieldOption } from '../../hooks'; -import { QueryProps } from '../../renderer'; import configs from './configs'; export class G2PlotChart extends Chart { @@ -29,15 +28,6 @@ export class G2PlotChart extends Chart { const meta = {}; // Some charts render wrong when the field name contains a dot in G2Plot const replace = (key: string) => key.replace(/\./g, '_'); - Object.entries(fieldProps).forEach(([key, props]) => { - if (key.includes('.')) { - key = replace(key); - } - meta[key] = { - formatter: props.transformer, - alias: props.label, - }; - }); general = Object.entries(general).reduce((obj, [key, value]) => { obj[key] = value; if (key.includes('Field')) { @@ -49,7 +39,40 @@ export class G2PlotChart extends Chart { } return obj; }, {}); - return { + const config = { + legend: { + color: { + itemLabelText: (datnum) => { + const props = fieldProps[datnum.label]; + const transformer = props?.transformer; + return props?.label || (transformer ? transformer(datnum.label) : datnum.label); + }, + }, + }, + tooltip: (d, index, data, column) => { + const field = column.y.field; + const props = fieldProps[field]; + const name = props?.label || field; + const transformer = props?.transformer; + const value = column.y.value[index]; + return { name, value: transformer ? transformer(value) : value }; + }, + axis: { + x: { + labelFormatter: (datnum) => { + const props = fieldProps[general.xField]; + const transformer = props?.transformer; + return transformer ? transformer(datnum) : datnum; + }, + }, + y: { + labelFormatter: (datnum) => { + const props = fieldProps[general.yField]; + const transformer = props?.transformer; + return transformer ? transformer(datnum) : datnum; + }, + }, + }, data: data.map((item) => { const obj = {}; Object.entries(item).forEach(([key, value]) => { @@ -60,11 +83,27 @@ export class G2PlotChart extends Chart { }); return obj; }), - meta, - animation: false, + theme: 'classic', + animate: { + enter: { + type: false, + }, + update: { + type: false, + }, + exit: { + type: false, + }, + }, + colorField: general.seriesField, + stack: general.isStack, + percent: general.isPercent ? true : undefined, + ...(general.smooth ? { shapeField: 'smooth' } : {}), ...general, + seriesField: general.isGroup ? general.seriesField : undefined, ...advanced, }; + return config; } getReference() { diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/index.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/index.ts index 112583bbde..d19deda508 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/index.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/client/chart/g2plot/index.ts @@ -1,5 +1,4 @@ -import { Area, Column, Line, Scatter } from '@ant-design/plots'; -import { Bar } from './bar'; +import { Area, Column, Line, Scatter, Bar } from '@ant-design/plots'; import { Pie } from './pie'; import { DualAxes } from './dualAxes'; import { G2PlotChart } from './g2plot'; @@ -30,7 +29,12 @@ export default [ component: Column, config: ['isGroup', 'isStack', 'isPercent'], }), - new Bar(), + new G2PlotChart({ + name: 'bar', + title: 'Bar Chart', + component: Bar, + config: ['isGroup', 'isStack', 'isPercent'], + }), new Pie(), new DualAxes(), new G2PlotChart({ name: 'scatter', title: 'Scatter Chart', component: Scatter }),