Skip to content

Commit 72ed72e

Browse files
authored
fix: charts plugins (labring#3530)
1 parent e5735fd commit 72ed72e

File tree

8 files changed

+52
-170
lines changed

8 files changed

+52
-170
lines changed

docSite/content/zh-cn/docs/development/intro.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI
148148

149149
## 加入社区
150150

151-
遇到困难了吗?有任何问题吗? 加入微信群与开发者和用户保持沟通
151+
遇到困难了吗?有任何问题吗? 加入飞书群与开发者和用户保持沟通
152152

153153
<img width="400px" src="https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png" class="medium-zoom-image" />
154154

packages/global/common/string/tools.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,22 @@ export const simpleText = (text = '') => {
2525
return text;
2626
};
2727

28-
/*
29-
replace {{variable}} to value
30-
*/
28+
export const valToStr = (val: any) => {
29+
if (val === undefined) return 'undefined';
30+
if (val === null) return 'null';
31+
32+
if (typeof val === 'object') return JSON.stringify(val);
33+
return String(val);
34+
};
35+
36+
// replace {{variable}} to value
3137
export function replaceVariable(text: any, obj: Record<string, string | number>) {
3238
if (typeof text !== 'string') return text;
3339

3440
for (const key in obj) {
3541
const val = obj[key];
36-
const formatVal = typeof val === 'object' ? JSON.stringify(val) : String(val);
37-
38-
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), formatVal);
42+
const formatVal = valToStr(val);
43+
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), () => formatVal);
3944
}
4045
return text || '';
4146
}

packages/global/core/workflow/runtime/utils.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { isValidReferenceValueFormat } from '../utils';
99
import { FlowNodeOutputItemType, ReferenceValueType } from '../type/io';
1010
import { ChatItemType, NodeOutputItemType } from '../../../core/chat/type';
1111
import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants';
12-
import { replaceVariable } from '../../../common/string/tools';
12+
import { replaceVariable, valToStr } from '../../../common/string/tools';
1313

1414
export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number => {
1515
let limit = 10;
@@ -343,11 +343,7 @@ export function replaceEditorVariable({
343343
if (input) return getReferenceVariableValue({ value: input.value, nodes, variables });
344344
})();
345345

346-
const formatVal = (() => {
347-
if (variableVal === undefined) return 'undefined';
348-
if (variableVal === null) return 'null';
349-
return typeof variableVal === 'object' ? JSON.stringify(variableVal) : String(variableVal);
350-
})();
346+
const formatVal = valToStr(variableVal);
351347

352348
const regex = new RegExp(`\\{\\{\\$(${nodeId}\\.${id})\\$\\}\\}`, 'g');
353349
text = text.replace(regex, () => formatVal);

packages/global/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"next": "14.2.5",
1414
"openai": "4.61.0",
1515
"openapi-types": "^12.1.3",
16+
"json5": "^2.2.3",
1617
"timezones-list": "^3.0.2"
1718
},
1819
"devDependencies": {

packages/plugins/src/drawing/baseChart/index.ts

+14-19
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { SystemPluginSpecialResponse } from '../../../type.d';
44

55
type Props = {
66
title: string;
7-
xAxis: string;
8-
yAxis: string;
7+
xAxis: string[];
8+
yAxis: string[];
99
chartType: string;
1010
};
1111

@@ -27,7 +27,12 @@ type Option = {
2727
series: SeriesData[]; // 使用定义的类型
2828
};
2929

30-
const generateChart = async (title: string, xAxis: string, yAxis: string, chartType: string) => {
30+
const generateChart = async (
31+
title: string,
32+
xAxis: string[],
33+
yAxis: string[],
34+
chartType: string
35+
) => {
3136
// @ts-ignore 无法使用dom,如使用jsdom会出现生成图片无法正常展示,有高手可以帮忙解决
3237
const chart = echarts.init(undefined, undefined, {
3338
renderer: 'svg', // 必须使用 SVG 模式
@@ -36,40 +41,30 @@ const generateChart = async (title: string, xAxis: string, yAxis: string, chartT
3641
height: 300
3742
});
3843

39-
let parsedXAxis: string[] = [];
40-
let parsedYAxis: number[] = [];
41-
try {
42-
parsedXAxis = json5.parse(xAxis);
43-
parsedYAxis = json5.parse(yAxis);
44-
} catch (error: any) {
45-
console.error('解析数据时出错:', error);
46-
return Promise.reject('Data error');
47-
}
48-
4944
const option: Option = {
5045
backgroundColor: '#f5f5f5',
5146
title: { text: title },
5247
tooltip: {},
53-
xAxis: { data: parsedXAxis },
48+
xAxis: { data: xAxis },
5449
yAxis: {},
5550
series: [] // 初始化为空数组
5651
};
5752

5853
// 根据 chartType 生成不同的图表
5954
switch (chartType) {
6055
case '柱状图':
61-
option.series.push({ name: 'Sample', type: 'bar', data: parsedYAxis });
56+
option.series.push({ name: 'Sample', type: 'bar', data: yAxis.map(Number) });
6257
break;
6358
case '折线图':
64-
option.series.push({ name: 'Sample', type: 'line', data: parsedYAxis });
59+
option.series.push({ name: 'Sample', type: 'line', data: yAxis.map(Number) });
6560
break;
6661
case '饼图':
6762
option.series.push({
6863
name: 'Sample',
6964
type: 'pie',
70-
data: parsedYAxis.map((value, index) => ({
71-
value,
72-
name: parsedXAxis[index] // 使用 xAxis 作为饼图的名称
65+
data: yAxis.map((value, index) => ({
66+
value: Number(value),
67+
name: xAxis[index] // 使用 xAxis 作为饼图的名称
7368
}))
7469
});
7570
break;

packages/plugins/src/drawing/baseChart/template.json

+13-131
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"author": "silencezhang",
3-
"version": "4812",
3+
"version": "4817",
44
"name": "基础图表",
55
"avatar": "core/workflow/template/baseChart",
66
"intro": "根据数据生成图表,可根据chartType生成柱状图,折线图,饼图",
@@ -68,7 +68,7 @@
6868
"canEdit": true,
6969
"key": "yAxis",
7070
"label": "yAxis",
71-
"description": "y轴数据,例如:['1', '2', '3']",
71+
"description": "y轴数据,例如:[1,2,3]",
7272
"defaultValue": "",
7373
"list": [
7474
{
@@ -77,7 +77,7 @@
7777
}
7878
],
7979
"required": true,
80-
"toolDescription": "y轴数据,例如:['1', '2', '3']"
80+
"toolDescription": "y轴数据,例如:[1,2,3]"
8181
},
8282
{
8383
"renderTypeList": ["select", "reference"],
@@ -145,19 +145,21 @@
145145
"flowNodeType": "pluginOutput",
146146
"showStatus": false,
147147
"position": {
148-
"x": 2122.252754006148,
149-
"y": -63.5218674613718
148+
"x": 2128.8138851197145,
149+
"y": -63.52186746137181
150150
},
151151
"version": "481",
152152
"inputs": [
153153
{
154154
"renderTypeList": ["reference"],
155155
"valueType": "string",
156156
"canEdit": true,
157-
"key": "相对路径URL",
158-
"label": "相对路径URL",
157+
"key": "图表 url",
158+
"label": "图表 url",
159159
"description": "可用使用markdown格式展示图片,如:![图片](url)",
160-
"value": ["ws0DFKJnCPhk", "bzaYjKyQFOw2"]
160+
"value": ["ws0DFKJnCPhk", "bzaYjKyQFOw2"],
161+
"isToolOutput": true,
162+
"required": true
161163
}
162164
],
163165
"outputs": []
@@ -170,8 +172,8 @@
170172
"flowNodeType": "httpRequest468",
171173
"showStatus": true,
172174
"position": {
173-
"x": 1216.5166647574395,
174-
"y": -206.30162946606856
175+
"x": 1264.2009472531117,
176+
"y": -455.0773486762623
175177
},
176178
"version": "481",
177179
"inputs": [
@@ -275,7 +277,7 @@
275277
"key": "system_httpJsonBody",
276278
"renderTypeList": ["hidden"],
277279
"valueType": "any",
278-
"value": "{\r\n \"title\": \"{{title-plugin}}\",\r\n \"xAxis\": \"{{xAxis-plugin}}\",\r\n \"yAxis\": \"{{yAxis-plugin}}\",\r\n \"chartType\": \"{{chartType-plugin}}\"\r\n}",
280+
"value": "{\r\n \"title\": \"{{$pluginInput.title$}}\",\r\n \"xAxis\": {{$pluginInput.xAxis$}},\r\n \"yAxis\": {{$pluginInput.yAxis$}},\r\n \"chartType\": \"{{$pluginInput.chartType$}}\"\r\n}",
279281
"label": "",
280282
"required": false,
281283
"valueDesc": "",
@@ -306,126 +308,6 @@
306308
"description": "",
307309
"debugLabel": "",
308310
"toolDescription": ""
309-
},
310-
{
311-
"renderTypeList": ["reference"],
312-
"valueType": "string",
313-
"canEdit": true,
314-
"key": "title-plugin",
315-
"label": "title-plugin",
316-
"customInputConfig": {
317-
"selectValueTypeList": [
318-
"string",
319-
"number",
320-
"boolean",
321-
"object",
322-
"arrayString",
323-
"arrayNumber",
324-
"arrayBoolean",
325-
"arrayObject",
326-
"arrayAny",
327-
"any",
328-
"chatHistory",
329-
"datasetQuote",
330-
"dynamic",
331-
"selectApp",
332-
"selectDataset"
333-
],
334-
"showDescription": false,
335-
"showDefaultValue": true
336-
},
337-
"required": true,
338-
"value": ["pluginInput", "title"]
339-
},
340-
{
341-
"renderTypeList": ["reference"],
342-
"valueType": "string",
343-
"canEdit": true,
344-
"key": "xAxis-plugin",
345-
"label": "xAxis-plugin",
346-
"customInputConfig": {
347-
"selectValueTypeList": [
348-
"string",
349-
"number",
350-
"boolean",
351-
"object",
352-
"arrayString",
353-
"arrayNumber",
354-
"arrayBoolean",
355-
"arrayObject",
356-
"arrayAny",
357-
"any",
358-
"chatHistory",
359-
"datasetQuote",
360-
"dynamic",
361-
"selectApp",
362-
"selectDataset"
363-
],
364-
"showDescription": false,
365-
"showDefaultValue": true
366-
},
367-
"required": true,
368-
"value": ["pluginInput", "xAxis"]
369-
},
370-
{
371-
"renderTypeList": ["reference"],
372-
"valueType": "string",
373-
"canEdit": true,
374-
"key": "yAxis-plugin",
375-
"label": "yAxis-plugin",
376-
"customInputConfig": {
377-
"selectValueTypeList": [
378-
"string",
379-
"number",
380-
"boolean",
381-
"object",
382-
"arrayString",
383-
"arrayNumber",
384-
"arrayBoolean",
385-
"arrayObject",
386-
"arrayAny",
387-
"any",
388-
"chatHistory",
389-
"datasetQuote",
390-
"dynamic",
391-
"selectApp",
392-
"selectDataset"
393-
],
394-
"showDescription": false,
395-
"showDefaultValue": true
396-
},
397-
"required": true,
398-
"value": ["pluginInput", "yAxis"]
399-
},
400-
{
401-
"renderTypeList": ["reference"],
402-
"valueType": "string",
403-
"canEdit": true,
404-
"key": "chartType-plugin",
405-
"label": "chartType-plugin",
406-
"customInputConfig": {
407-
"selectValueTypeList": [
408-
"string",
409-
"number",
410-
"boolean",
411-
"object",
412-
"arrayString",
413-
"arrayNumber",
414-
"arrayBoolean",
415-
"arrayObject",
416-
"arrayAny",
417-
"any",
418-
"chatHistory",
419-
"datasetQuote",
420-
"dynamic",
421-
"selectApp",
422-
"selectDataset"
423-
],
424-
"showDescription": false,
425-
"showDefaultValue": true
426-
},
427-
"required": true,
428-
"value": ["pluginInput", "chartType"]
429311
}
430312
],
431313
"outputs": [

packages/service/core/workflow/dispatch/tools/http468.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,17 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
177177
if (!httpJsonBody) return {};
178178
if (httpContentType === ContentTypes.json) {
179179
httpJsonBody = replaceStringVariables(httpJsonBody);
180+
181+
const replaceJsonBody = httpJsonBody.replace(/(".*?")\s*:\s*undefined\b/g, '$1: null');
182+
180183
// Json body, parse and return
181-
const jsonParse = json5.parse(
182-
httpJsonBody.replace(/(".*?")\s*:\s*undefined\b/g, '$1: null')
183-
);
184+
const jsonParse = json5.parse(replaceJsonBody);
184185
const removeSignJson = removeUndefinedSign(jsonParse);
185186
return removeSignJson;
186187
}
187188
httpJsonBody = replaceStringVariables(httpJsonBody);
188189
return httpJsonBody.replaceAll(UNDEFINED_SIGN, 'null');
189190
} catch (error) {
190-
console.log(error);
191191
return Promise.reject(`Invalid JSON body: ${httpJsonBody}`);
192192
}
193193
})();

pnpm-lock.yaml

+6-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)