feat: Chinese chart labels + matching Ant Design icons

All 17 chart types now show Chinese names (柱状图, 折线图, 饼图, etc.)
and use specific Ant Design icons instead of generic BarChartOutlined.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hailin 2026-04-05 02:11:46 -07:00
parent fe6cf014dc
commit e8f2554aa8
2 changed files with 66 additions and 35 deletions

View File

@ -29,136 +29,136 @@ export interface ChartTypeMeta {
export const CHART_TYPE_META: Record<ChartType, ChartTypeMeta> = { export const CHART_TYPE_META: Record<ChartType, ChartTypeMeta> = {
kpi: { kpi: {
type: 'kpi', type: 'kpi',
label: 'KPI Card', label: '指标卡',
icon: 'kpi', icon: 'dashboard',
category: 'basic', category: 'basic',
requiredBindings: ['value'], requiredBindings: ['value'],
optionalBindings: ['label'], optionalBindings: ['label'],
}, },
bar: { bar: {
type: 'bar', type: 'bar',
label: 'Bar Chart', label: '柱状图',
icon: 'bar', icon: 'bar-chart',
category: 'basic', category: 'basic',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['color', 'label'], optionalBindings: ['color', 'label'],
}, },
'grouped-bar': { 'grouped-bar': {
type: 'grouped-bar', type: 'grouped-bar',
label: 'Grouped Bar Chart', label: '分组柱状图',
icon: 'grouped-bar', icon: 'bar-chart',
category: 'basic', category: 'basic',
requiredBindings: ['x', 'y', 'series'], requiredBindings: ['x', 'y', 'series'],
optionalBindings: ['color', 'label'], optionalBindings: ['color', 'label'],
}, },
'stacked-bar': { 'stacked-bar': {
type: 'stacked-bar', type: 'stacked-bar',
label: 'Stacked Bar Chart', label: '堆叠柱状图',
icon: 'stacked-bar', icon: 'bar-chart',
category: 'composition', category: 'composition',
requiredBindings: ['x', 'y', 'series'], requiredBindings: ['x', 'y', 'series'],
optionalBindings: ['color', 'label'], optionalBindings: ['color', 'label'],
}, },
'horizontal-bar': { 'horizontal-bar': {
type: 'horizontal-bar', type: 'horizontal-bar',
label: 'Horizontal Bar Chart', label: '条形图',
icon: 'horizontal-bar', icon: 'bar-chart',
category: 'basic', category: 'basic',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['color', 'label'], optionalBindings: ['color', 'label'],
}, },
line: { line: {
type: 'line', type: 'line',
label: 'Line Chart', label: '折线图',
icon: 'line', icon: 'line-chart',
category: 'basic', category: 'basic',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['series', 'color', 'label'], optionalBindings: ['series', 'color', 'label'],
}, },
area: { area: {
type: 'area', type: 'area',
label: 'Area Chart', label: '面积图',
icon: 'area', icon: 'area-chart',
category: 'basic', category: 'basic',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['series', 'color', 'label'], optionalBindings: ['series', 'color', 'label'],
}, },
pie: { pie: {
type: 'pie', type: 'pie',
label: 'Pie Chart', label: '饼图',
icon: 'pie', icon: 'pie-chart',
category: 'composition', category: 'composition',
requiredBindings: ['label', 'value'], requiredBindings: ['label', 'value'],
optionalBindings: ['color'], optionalBindings: ['color'],
}, },
donut: { donut: {
type: 'donut', type: 'donut',
label: 'Donut Chart', label: '环形图',
icon: 'donut', icon: 'pie-chart',
category: 'composition', category: 'composition',
requiredBindings: ['label', 'value'], requiredBindings: ['label', 'value'],
optionalBindings: ['color'], optionalBindings: ['color'],
}, },
scatter: { scatter: {
type: 'scatter', type: 'scatter',
label: 'Scatter Plot', label: '散点图',
icon: 'scatter', icon: 'dot-chart',
category: 'relationship', category: 'relationship',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['size', 'color', 'label'], optionalBindings: ['size', 'color', 'label'],
}, },
radar: { radar: {
type: 'radar', type: 'radar',
label: 'Radar Chart', label: '雷达图',
icon: 'radar', icon: 'radar-chart',
category: 'statistical', category: 'statistical',
requiredBindings: ['label', 'value'], requiredBindings: ['label', 'value'],
optionalBindings: ['series', 'color'], optionalBindings: ['series', 'color'],
}, },
wordcloud: { wordcloud: {
type: 'wordcloud', type: 'wordcloud',
label: 'Word Cloud', label: '词云图',
icon: 'wordcloud', icon: 'cloud',
category: 'other', category: 'other',
requiredBindings: ['label', 'value'], requiredBindings: ['label', 'value'],
optionalBindings: ['color'], optionalBindings: ['color'],
}, },
'boston-matrix': { 'boston-matrix': {
type: 'boston-matrix', type: 'boston-matrix',
label: 'Boston Matrix', label: '波士顿矩阵',
icon: 'boston-matrix', icon: 'block',
category: 'relationship', category: 'relationship',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['size', 'label', 'color'], optionalBindings: ['size', 'label', 'color'],
}, },
heatmap: { heatmap: {
type: 'heatmap', type: 'heatmap',
label: 'Heatmap', label: '热力图',
icon: 'heatmap', icon: 'heat-map',
category: 'statistical', category: 'statistical',
requiredBindings: ['x', 'y', 'value'], requiredBindings: ['x', 'y', 'value'],
optionalBindings: ['color'], optionalBindings: ['color'],
}, },
map: { map: {
type: 'map', type: 'map',
label: 'Map', label: '地图',
icon: 'map', icon: 'global',
category: 'geo', category: 'geo',
requiredBindings: ['geo', 'value'], requiredBindings: ['geo', 'value'],
optionalBindings: ['color', 'label'], optionalBindings: ['color', 'label'],
}, },
combo: { combo: {
type: 'combo', type: 'combo',
label: 'Combo Chart', label: '组合图',
icon: 'combo', icon: 'stock',
category: 'statistical', category: 'statistical',
requiredBindings: ['x', 'y'], requiredBindings: ['x', 'y'],
optionalBindings: ['series', 'color', 'label'], optionalBindings: ['series', 'color', 'label'],
}, },
'data-table': { 'data-table': {
type: 'data-table', type: 'data-table',
label: 'Data Table', label: '数据表格',
icon: 'data-table', icon: 'table',
category: 'other', category: 'other',
requiredBindings: [], requiredBindings: [],
optionalBindings: ['x', 'y', 'label', 'value'], optionalBindings: ['x', 'y', 'label', 'value'],

View File

@ -11,6 +11,17 @@ import {
GlobalOutlined, GlobalOutlined,
QuestionOutlined, QuestionOutlined,
BarChartOutlined, BarChartOutlined,
LineChartOutlined,
PieChartOutlined,
DotChartOutlined,
RadarChartOutlined,
AreaChartOutlined,
HeatMapOutlined,
StockOutlined,
TableOutlined,
DashboardOutlined,
CloudOutlined,
BlockOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { useUIStore } from '@/adapters/state/zustand/uiStore'; import { useUIStore } from '@/adapters/state/zustand/uiStore';
import { useAppSelector, useAppDispatch } from '@/adapters/state/redux/store'; import { useAppSelector, useAppDispatch } from '@/adapters/state/redux/store';
@ -164,6 +175,26 @@ function FieldsTab() {
); );
} }
const ICON_MAP: Record<string, React.ReactNode> = {
'dashboard': <DashboardOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'bar-chart': <BarChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'line-chart': <LineChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'area-chart': <AreaChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'pie-chart': <PieChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'dot-chart': <DotChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'radar-chart': <RadarChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'heat-map': <HeatMapOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'stock': <StockOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'table': <TableOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'cloud': <CloudOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'block': <BlockOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
'global': <GlobalOutlined style={{ fontSize: 20, marginBottom: 4 }} />,
};
function ChartIcon({ icon }: { icon: string }) {
return <>{ICON_MAP[icon] ?? <BarChartOutlined style={{ fontSize: 20, marginBottom: 4 }} />}</>;
}
/** ChartsTab: chart type gallery grouped by category */ /** ChartsTab: chart type gallery grouped by category */
function ChartsTab() { function ChartsTab() {
const { handleCreate, loading } = useCreateChart(); const { handleCreate, loading } = useCreateChart();
@ -207,7 +238,7 @@ function ChartsTab() {
bodyStyle={{ padding: '8px 4px' }} bodyStyle={{ padding: '8px 4px' }}
onClick={() => !loading && handleCreate(meta.type)} onClick={() => !loading && handleCreate(meta.type)}
> >
<BarChartOutlined style={{ fontSize: 20, marginBottom: 4 }} /> <ChartIcon icon={meta.icon} />
<div style={{ fontSize: 11, lineHeight: 1.3 }}>{meta.label}</div> <div style={{ fontSize: 11, lineHeight: 1.3 }}>{meta.label}</div>
</Card> </Card>
))} ))}