Skip to content

Commit

Permalink
feat(web): add download image function&fix null data point (#1653)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenluli committed Jun 21, 2024
1 parent 889c345 commit c57ee02
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 30 deletions.
6 changes: 4 additions & 2 deletions web/app/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const en = {
Description: 'Description',
Storage: 'Storage',
Please_input_the_description: 'Please input the description',
Please_select_the_storage:'Please select the storage',
Please_select_the_storage: 'Please select the storage',
Next: 'Next',
the_name_can_only_contain: 'the name can only contain numbers, letters, Chinese characters, "-" and "_"',
Text: 'Text',
Expand Down Expand Up @@ -223,6 +223,7 @@ const en = {
Chinese: 'Chinese',
English: 'English',
refreshSuccess: 'Refresh Success',
Download: 'Download'
} as const;

export type I18nKeys = keyof typeof en;
Expand All @@ -249,7 +250,7 @@ const zh: Resources['translation'] = {
Description: '描述',
Storage: '存储类型',
Please_input_the_description: '请输入描述',
Please_select_the_storage:'请选择存储类型',
Please_select_the_storage: '请选择存储类型',
Next: '下一步',
the_name_can_only_contain: '名称只能包含数字、字母、中文字符、-或_',
Text: '文本',
Expand Down Expand Up @@ -452,6 +453,7 @@ const zh: Resources['translation'] = {
Chinese: '中文',
English: '英文',
refreshSuccess: '刷新成功',
Download: '下载',
} as const;

i18n.use(initReactI18next).init({
Expand Down
9 changes: 9 additions & 0 deletions web/components/chart/autoChart/charts/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,12 @@ export const sortData = ({ data, chartType, xField }: {
}
return sortedData
}

/** 数据空值处理:后端返回的空数据为 '-', 在展示为图表时会有问题,修改为 null */
export const processNilData = (data: Datum[], emptyValue = '-') => data.map((datum) => {
const processedDatum: Record<string, string | number | null> = {};
Object.keys(datum).forEach((key) => {
processedDatum[key] = datum[key] === emptyValue ? null : datum[key];
});
return processedDatum;
});
72 changes: 44 additions & 28 deletions web/components/chart/autoChart/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import { Empty, Row, Col, Select, Tooltip } from 'antd';
import { Advice, Advisor } from '@antv/ava';
import { Chart } from '@berryv/g2-react';
import { Empty, Row, Col, Select, Tooltip, Button, Space } from 'antd';
import { Advice, Advisor, Datum } from '@antv/ava';
import { Chart, ChartRef } from '@berryv/g2-react';
import i18n, { I18nKeys } from '@/app/i18n';
import { customizeAdvisor, getVisAdvices } from './advisor/pipeline';
import { useContext, useEffect, useMemo, useState } from 'react';
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
import { defaultAdvicesFilter } from './advisor/utils';
import { AutoChartProps, ChartType, CustomAdvisorConfig, CustomChart, Specification } from './types';
import { customCharts } from './charts';
import { ChatContext } from '@/app/chat-context';
import { compact, concat, uniq } from 'lodash';
import { sortData } from './charts/util';
import { processNilData, sortData } from './charts/util';
import { downloadImage } from '../helpers/downloadChartImage';;
import { DownloadOutlined } from '@ant-design/icons';

const { Option } = Select;

export const AutoChart = (props: AutoChartProps) => {
const { data, chartType, scopeOfCharts, ruleConfig } = props;
const { chartType, scopeOfCharts, ruleConfig, data: originalData } = props;

// 处理空值数据 (为'-'的数据)
const data = processNilData(originalData) as Datum[];
const { mode } = useContext(ChatContext);

const [advisor, setAdvisor] = useState<Advisor>();
const [advices, setAdvices] = useState<Advice[]>([]);
const [renderChartType, setRenderChartType] = useState<ChartType>();
const chartRef = useRef<ChartRef>()

useEffect(() => {
const input_charts: CustomChart[] = customCharts;
Expand Down Expand Up @@ -106,6 +111,7 @@ export const AutoChart = (props: AutoChartProps) => {
autoFit: true,
height: 300,
}}
ref={chartRef}
/>
);
}
Expand All @@ -115,28 +121,38 @@ export const AutoChart = (props: AutoChartProps) => {
if (renderChartType) {
return (
<div>
<Row justify="start" className="mb-2">
<Col>{i18n.t('Advices')}</Col>
<Col style={{ marginLeft: 24 }}>
<Select
className="w-52"
value={renderChartType}
placeholder={'Chart Switcher'}
onChange={(value) => setRenderChartType(value)}
size={'small'}
>
{advices?.map((item) => {
const name = i18n.t(item.type as I18nKeys);

return (
<Option key={item.type} value={item.type}>
<Tooltip title={name} placement={'right'}>
<div>{name}</div>
</Tooltip>
</Option>
);
})}
</Select>
<Row justify='space-between' className="mb-2">
<Col>
<Space>
<span>{i18n.t('Advices')}</span>
<Select
className="w-52"
value={renderChartType}
placeholder={'Chart Switcher'}
onChange={(value) => setRenderChartType(value)}
size={'small'}
>
{advices?.map((item) => {
const name = i18n.t(item.type as I18nKeys);
return (
<Option key={item.type} value={item.type}>
<Tooltip title={name} placement={'right'}>
<div>{name}</div>
</Tooltip>
</Option>
);
})}
</Select>
</Space>
</Col>
<Col>
<Tooltip title={i18n.t('Download')}>
<Button
onClick={() => downloadImage(chartRef.current, i18n.t(renderChartType as I18nKeys))}
icon={<DownloadOutlined />}
type='text'
/>
</Tooltip>
</Col>
</Row>
<div className="auto-chart-content">{visComponent}</div>
Expand Down
40 changes: 40 additions & 0 deletions web/components/chart/helpers/downloadChartImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ChartRef as G2Chart } from "@berryv/g2-react";

const getChartCanvas = (chart: G2Chart) => {
if (!chart) return;
const chartContainer = chart.getContainer();
const canvasNode = chartContainer.getElementsByTagName('canvas')[0];
return canvasNode
}

/** 获得 g2 Chart 实例的 dataURL */
function toDataURL(chart: G2Chart) {
const canvasDom = getChartCanvas(chart);
if (canvasDom) {
const dataURL = canvasDom.toDataURL('image/png');
return dataURL;
}
}

/**
* 图表图片导出
* @param chart chart 实例
* @param name 图片名称
*/
export function downloadImage(chart: G2Chart, name: string = 'Chart') {
const link = document.createElement('a');
const filename = `${name}.png`;

setTimeout(() => {
const dataURL = toDataURL(chart);
if (dataURL) {
link.addEventListener('click', () => {
link.download = filename;
link.href = dataURL;
});
const e = document.createEvent('MouseEvents');
e.initEvent('click', false, false);
link.dispatchEvent(e);
}
}, 16);
}

0 comments on commit c57ee02

Please sign in to comment.