fix: charts plugins (#3530)

This commit is contained in:
Archer
2025-01-05 14:41:34 +08:00
committed by GitHub
parent e5735fddd1
commit 72ed72e595
8 changed files with 52 additions and 170 deletions

View File

@@ -148,7 +148,7 @@ FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI
## 加入社区 ## 加入社区
遇到困难了吗?有任何问题吗? 加入微信群与开发者和用户保持沟通。 遇到困难了吗?有任何问题吗? 加入飞书群与开发者和用户保持沟通。
<img width="400px" src="https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png" class="medium-zoom-image" /> <img width="400px" src="https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png" class="medium-zoom-image" />

View File

@@ -25,17 +25,22 @@ export const simpleText = (text = '') => {
return text; return text;
}; };
/* export const valToStr = (val: any) => {
replace {{variable}} to value if (val === undefined) return 'undefined';
*/ if (val === null) return 'null';
if (typeof val === 'object') return JSON.stringify(val);
return String(val);
};
// replace {{variable}} to value
export function replaceVariable(text: any, obj: Record<string, string | number>) { export function replaceVariable(text: any, obj: Record<string, string | number>) {
if (typeof text !== 'string') return text; if (typeof text !== 'string') return text;
for (const key in obj) { for (const key in obj) {
const val = obj[key]; const val = obj[key];
const formatVal = typeof val === 'object' ? JSON.stringify(val) : String(val); const formatVal = valToStr(val);
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), () => formatVal);
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), formatVal);
} }
return text || ''; return text || '';
} }

View File

@@ -9,7 +9,7 @@ import { isValidReferenceValueFormat } from '../utils';
import { FlowNodeOutputItemType, ReferenceValueType } from '../type/io'; import { FlowNodeOutputItemType, ReferenceValueType } from '../type/io';
import { ChatItemType, NodeOutputItemType } from '../../../core/chat/type'; import { ChatItemType, NodeOutputItemType } from '../../../core/chat/type';
import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants'; import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants';
import { replaceVariable } from '../../../common/string/tools'; import { replaceVariable, valToStr } from '../../../common/string/tools';
export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number => { export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number => {
let limit = 10; let limit = 10;
@@ -343,11 +343,7 @@ export function replaceEditorVariable({
if (input) return getReferenceVariableValue({ value: input.value, nodes, variables }); if (input) return getReferenceVariableValue({ value: input.value, nodes, variables });
})(); })();
const formatVal = (() => { const formatVal = valToStr(variableVal);
if (variableVal === undefined) return 'undefined';
if (variableVal === null) return 'null';
return typeof variableVal === 'object' ? JSON.stringify(variableVal) : String(variableVal);
})();
const regex = new RegExp(`\\{\\{\\$(${nodeId}\\.${id})\\$\\}\\}`, 'g'); const regex = new RegExp(`\\{\\{\\$(${nodeId}\\.${id})\\$\\}\\}`, 'g');
text = text.replace(regex, () => formatVal); text = text.replace(regex, () => formatVal);

View File

@@ -13,6 +13,7 @@
"next": "14.2.5", "next": "14.2.5",
"openai": "4.61.0", "openai": "4.61.0",
"openapi-types": "^12.1.3", "openapi-types": "^12.1.3",
"json5": "^2.2.3",
"timezones-list": "^3.0.2" "timezones-list": "^3.0.2"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -4,8 +4,8 @@ import { SystemPluginSpecialResponse } from '../../../type.d';
type Props = { type Props = {
title: string; title: string;
xAxis: string; xAxis: string[];
yAxis: string; yAxis: string[];
chartType: string; chartType: string;
}; };
@@ -27,7 +27,12 @@ type Option = {
series: SeriesData[]; // 使用定义的类型 series: SeriesData[]; // 使用定义的类型
}; };
const generateChart = async (title: string, xAxis: string, yAxis: string, chartType: string) => { const generateChart = async (
title: string,
xAxis: string[],
yAxis: string[],
chartType: string
) => {
// @ts-ignore 无法使用dom如使用jsdom会出现生成图片无法正常展示有高手可以帮忙解决 // @ts-ignore 无法使用dom如使用jsdom会出现生成图片无法正常展示有高手可以帮忙解决
const chart = echarts.init(undefined, undefined, { const chart = echarts.init(undefined, undefined, {
renderer: 'svg', // 必须使用 SVG 模式 renderer: 'svg', // 必须使用 SVG 模式
@@ -36,21 +41,11 @@ const generateChart = async (title: string, xAxis: string, yAxis: string, chartT
height: 300 height: 300
}); });
let parsedXAxis: string[] = [];
let parsedYAxis: number[] = [];
try {
parsedXAxis = json5.parse(xAxis);
parsedYAxis = json5.parse(yAxis);
} catch (error: any) {
console.error('解析数据时出错:', error);
return Promise.reject('Data error');
}
const option: Option = { const option: Option = {
backgroundColor: '#f5f5f5', backgroundColor: '#f5f5f5',
title: { text: title }, title: { text: title },
tooltip: {}, tooltip: {},
xAxis: { data: parsedXAxis }, xAxis: { data: xAxis },
yAxis: {}, yAxis: {},
series: [] // 初始化为空数组 series: [] // 初始化为空数组
}; };
@@ -58,18 +53,18 @@ const generateChart = async (title: string, xAxis: string, yAxis: string, chartT
// 根据 chartType 生成不同的图表 // 根据 chartType 生成不同的图表
switch (chartType) { switch (chartType) {
case '柱状图': case '柱状图':
option.series.push({ name: 'Sample', type: 'bar', data: parsedYAxis }); option.series.push({ name: 'Sample', type: 'bar', data: yAxis.map(Number) });
break; break;
case '折线图': case '折线图':
option.series.push({ name: 'Sample', type: 'line', data: parsedYAxis }); option.series.push({ name: 'Sample', type: 'line', data: yAxis.map(Number) });
break; break;
case '饼图': case '饼图':
option.series.push({ option.series.push({
name: 'Sample', name: 'Sample',
type: 'pie', type: 'pie',
data: parsedYAxis.map((value, index) => ({ data: yAxis.map((value, index) => ({
value, value: Number(value),
name: parsedXAxis[index] // 使用 xAxis 作为饼图的名称 name: xAxis[index] // 使用 xAxis 作为饼图的名称
})) }))
}); });
break; break;

View File

@@ -1,6 +1,6 @@
{ {
"author": "silencezhang", "author": "silencezhang",
"version": "4812", "version": "4817",
"name": "基础图表", "name": "基础图表",
"avatar": "core/workflow/template/baseChart", "avatar": "core/workflow/template/baseChart",
"intro": "根据数据生成图表可根据chartType生成柱状图折线图饼图", "intro": "根据数据生成图表可根据chartType生成柱状图折线图饼图",
@@ -68,7 +68,7 @@
"canEdit": true, "canEdit": true,
"key": "yAxis", "key": "yAxis",
"label": "yAxis", "label": "yAxis",
"description": "y轴数据例如['1', '2', '3']", "description": "y轴数据例如[1,2,3]",
"defaultValue": "", "defaultValue": "",
"list": [ "list": [
{ {
@@ -77,7 +77,7 @@
} }
], ],
"required": true, "required": true,
"toolDescription": "y轴数据例如['1', '2', '3']" "toolDescription": "y轴数据例如[1,2,3]"
}, },
{ {
"renderTypeList": ["select", "reference"], "renderTypeList": ["select", "reference"],
@@ -145,8 +145,8 @@
"flowNodeType": "pluginOutput", "flowNodeType": "pluginOutput",
"showStatus": false, "showStatus": false,
"position": { "position": {
"x": 2122.252754006148, "x": 2128.8138851197145,
"y": -63.5218674613718 "y": -63.52186746137181
}, },
"version": "481", "version": "481",
"inputs": [ "inputs": [
@@ -154,10 +154,12 @@
"renderTypeList": ["reference"], "renderTypeList": ["reference"],
"valueType": "string", "valueType": "string",
"canEdit": true, "canEdit": true,
"key": "相对路径URL", "key": "图表 url",
"label": "相对路径URL", "label": "图表 url",
"description": "可用使用markdown格式展示图片![图片](url)", "description": "可用使用markdown格式展示图片![图片](url)",
"value": ["ws0DFKJnCPhk", "bzaYjKyQFOw2"] "value": ["ws0DFKJnCPhk", "bzaYjKyQFOw2"],
"isToolOutput": true,
"required": true
} }
], ],
"outputs": [] "outputs": []
@@ -170,8 +172,8 @@
"flowNodeType": "httpRequest468", "flowNodeType": "httpRequest468",
"showStatus": true, "showStatus": true,
"position": { "position": {
"x": 1216.5166647574395, "x": 1264.2009472531117,
"y": -206.30162946606856 "y": -455.0773486762623
}, },
"version": "481", "version": "481",
"inputs": [ "inputs": [
@@ -275,7 +277,7 @@
"key": "system_httpJsonBody", "key": "system_httpJsonBody",
"renderTypeList": ["hidden"], "renderTypeList": ["hidden"],
"valueType": "any", "valueType": "any",
"value": "{\r\n \"title\": \"{{title-plugin}}\",\r\n \"xAxis\": \"{{xAxis-plugin}}\",\r\n \"yAxis\": \"{{yAxis-plugin}}\",\r\n \"chartType\": \"{{chartType-plugin}}\"\r\n}", "value": "{\r\n \"title\": \"{{$pluginInput.title$}}\",\r\n \"xAxis\": {{$pluginInput.xAxis$}},\r\n \"yAxis\": {{$pluginInput.yAxis$}},\r\n \"chartType\": \"{{$pluginInput.chartType$}}\"\r\n}",
"label": "", "label": "",
"required": false, "required": false,
"valueDesc": "", "valueDesc": "",
@@ -306,126 +308,6 @@
"description": "", "description": "",
"debugLabel": "", "debugLabel": "",
"toolDescription": "" "toolDescription": ""
},
{
"renderTypeList": ["reference"],
"valueType": "string",
"canEdit": true,
"key": "title-plugin",
"label": "title-plugin",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
},
"required": true,
"value": ["pluginInput", "title"]
},
{
"renderTypeList": ["reference"],
"valueType": "string",
"canEdit": true,
"key": "xAxis-plugin",
"label": "xAxis-plugin",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
},
"required": true,
"value": ["pluginInput", "xAxis"]
},
{
"renderTypeList": ["reference"],
"valueType": "string",
"canEdit": true,
"key": "yAxis-plugin",
"label": "yAxis-plugin",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
},
"required": true,
"value": ["pluginInput", "yAxis"]
},
{
"renderTypeList": ["reference"],
"valueType": "string",
"canEdit": true,
"key": "chartType-plugin",
"label": "chartType-plugin",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
},
"required": true,
"value": ["pluginInput", "chartType"]
} }
], ],
"outputs": [ "outputs": [

View File

@@ -177,17 +177,17 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
if (!httpJsonBody) return {}; if (!httpJsonBody) return {};
if (httpContentType === ContentTypes.json) { if (httpContentType === ContentTypes.json) {
httpJsonBody = replaceStringVariables(httpJsonBody); httpJsonBody = replaceStringVariables(httpJsonBody);
const replaceJsonBody = httpJsonBody.replace(/(".*?")\s*:\s*undefined\b/g, '$1: null');
// Json body, parse and return // Json body, parse and return
const jsonParse = json5.parse( const jsonParse = json5.parse(replaceJsonBody);
httpJsonBody.replace(/(".*?")\s*:\s*undefined\b/g, '$1: null')
);
const removeSignJson = removeUndefinedSign(jsonParse); const removeSignJson = removeUndefinedSign(jsonParse);
return removeSignJson; return removeSignJson;
} }
httpJsonBody = replaceStringVariables(httpJsonBody); httpJsonBody = replaceStringVariables(httpJsonBody);
return httpJsonBody.replaceAll(UNDEFINED_SIGN, 'null'); return httpJsonBody.replaceAll(UNDEFINED_SIGN, 'null');
} catch (error) { } catch (error) {
console.log(error);
return Promise.reject(`Invalid JSON body: ${httpJsonBody}`); return Promise.reject(`Invalid JSON body: ${httpJsonBody}`);
} }
})(); })();

9
pnpm-lock.yaml generated
View File

@@ -56,6 +56,9 @@ importers:
jschardet: jschardet:
specifier: 3.1.1 specifier: 3.1.1
version: 3.1.1 version: 3.1.1
json5:
specifier: ^2.2.3
version: 2.2.3
nanoid: nanoid:
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.2 version: 4.0.2
@@ -14519,7 +14522,7 @@ snapshots:
eslint: 8.56.0 eslint: 8.56.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0) eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
eslint-plugin-jsx-a11y: 6.9.0(eslint@8.56.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.56.0)
eslint-plugin-react: 7.34.4(eslint@8.56.0) eslint-plugin-react: 7.34.4(eslint@8.56.0)
eslint-plugin-react-hooks: 4.6.2(eslint@8.56.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.56.0)
@@ -14543,7 +14546,7 @@ snapshots:
enhanced-resolve: 5.17.0 enhanced-resolve: 5.17.0
eslint: 8.56.0 eslint: 8.56.0
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0) eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0)
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
fast-glob: 3.3.2 fast-glob: 3.3.2
get-tsconfig: 4.7.5 get-tsconfig: 4.7.5
is-core-module: 2.14.0 is-core-module: 2.14.0
@@ -14565,7 +14568,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint@8.56.0))(eslint@8.56.0): eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0):
dependencies: dependencies:
array-includes: 3.1.8 array-includes: 3.1.8
array.prototype.findlastindex: 1.2.5 array.prototype.findlastindex: 1.2.5