增加对echarts图表的支持 (#249)

* 增加对echarts图表的支持

* 增加对echarts的支持
This commit is contained in:
不做了睡大觉
2023-09-04 18:17:39 +08:00
committed by GitHub
parent 5d596bd3d5
commit 32f482b232
6 changed files with 71 additions and 2 deletions

View File

@@ -61,4 +61,4 @@
"maxToken": 16000,
"price": 0
}
}
}

View File

@@ -25,6 +25,7 @@
"date-fns": "^2.30.0",
"dayjs": "^1.11.7",
"echarts": "^5.4.1",
"echarts-gl": "^2.0.9",
"formidable": "^2.1.1",
"framer-motion": "^9.0.6",
"hyperdown": "^2.4.29",

View File

@@ -0,0 +1,26 @@
// EChartsCodeBlock.tsx
import React, { useMemo } from 'react';
import EChartsRenderer from './EChartsRenderer';
import * as echarts from 'echarts';
interface EChartsCodeBlockProps {
code: string;
}
const EChartsCodeBlock: React.FC<EChartsCodeBlockProps> = ({ code }) => {
const getOption = useMemo(() => {
try {
const optionFunction = new Function("echarts",'"use strict";' + code + '; return getChartOption;');
return optionFunction(echarts); // 添加 echarts 参数
} catch (error) {
console.error('Error parsing ECharts code:', '\n', error, '\n', 'Code:', code);
return null;
}
}, [code]);
return getOption ? <EChartsRenderer getOption={getOption} /> : null;
};
export default EChartsCodeBlock;

View File

@@ -0,0 +1,35 @@
import React, { useRef, useEffect } from 'react';
import { ECharts } from 'echarts';
interface EChartsRendererProps {
getOption: () => any;
}
const EChartsRenderer: React.FC<EChartsRendererProps> = ({ getOption }) => {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
let chartInstance: ECharts | null = null;
(async () => {
const echarts = await import('echarts');
await import('echarts-gl');
if (chartRef.current) {
chartInstance = echarts.init(chartRef.current, { renderer: 'svg', ssr: true });
const option = getOption();
chartInstance.setOption(option);
}
})();
return () => {
if (chartInstance) {
chartInstance.dispose();
}
};
}, [getOption]);
return <div style={{ width: '100%', height: '400px', minWidth: '600px' }} ref={chartRef} />;
};
export default EChartsRenderer;

View File

@@ -14,6 +14,7 @@ import CodeLight from './CodeLight';
const MermaidCodeBlock = dynamic(() => import('./img/MermaidCodeBlock'));
const MdImage = dynamic(() => import('./img/Image'));
const ChatGuide = dynamic(() => import('./chat/Guide'));
const EChartsCodeBlock = dynamic(() => import('./img/EChartsCodeBlock'));
function Code({ inline, className, children }: any) {
const match = /language-(\w+)/.exec(className || '');
@@ -26,7 +27,9 @@ function Code({ inline, className, children }: any) {
if (codeType === 'guide') {
return <ChatGuide text={String(children)} />;
}
if (codeType === 'echarts') {
return <EChartsCodeBlock code={String(children)} />;
}
return (
<CodeLight className={className} inline={inline} match={match}>
{children}

4
client/src/types/echarts-gl.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module 'echarts-gl' {
export default echarts-gl
}