From d259eda6b41532fb0be47d0b4ce2d4c04c899be3 Mon Sep 17 00:00:00 2001 From: silencezhang7 <765596994@qq.com> Date: Fri, 27 Sep 2024 13:50:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EBI=E5=9C=96=E6=A8=99=E5=8A=9F?= =?UTF-8?q?=E8=83=BD-=E6=9F=B1=E7=8B=80=E5=9C=96=20(#2779)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 新增BI圖標功能-柱狀圖 * 新增BI图表功能-柱狀圖,优化代码,删除无用代码 * 优化生成逻辑,支持插件手动选择图表类型:目前支持柱状图,折线图,饼图 * 修改包名称,完成基础图表 --- packages/plugins/package.json | 4 +- packages/plugins/register.ts | 4 +- .../plugins/src/drawing/baseChart/index.ts | 93 +++ .../src/drawing/baseChart/template.json | 551 ++++++++++++++++++ packages/plugins/src/drawing/template.json | 17 + .../web/components/common/Icon/constants.ts | 2 + .../Icon/icons/core/workflow/template/BI.svg | 1 + .../core/workflow/template/baseChart.svg | 1 + 8 files changed, 671 insertions(+), 2 deletions(-) create mode 100644 packages/plugins/src/drawing/baseChart/index.ts create mode 100644 packages/plugins/src/drawing/baseChart/template.json create mode 100644 packages/plugins/src/drawing/template.json create mode 100644 packages/web/components/common/Icon/icons/core/workflow/template/BI.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/template/baseChart.svg diff --git a/packages/plugins/package.json b/packages/plugins/package.json index 8611adefd..d9c824490 100644 --- a/packages/plugins/package.json +++ b/packages/plugins/package.json @@ -1,11 +1,13 @@ { "name": "@fastgpt/plugins", "version": "1.0.0", + "type": "module", "dependencies": { "duck-duck-scrape": "^2.2.5", "lodash": "^4.17.21", "axios": "^1.5.1", - "expr-eval": "^2.0.2" + "expr-eval": "^2.0.2", + "echarts": "5.4.1" }, "devDependencies": { "@fastgpt/global": "workspace:*", diff --git a/packages/plugins/register.ts b/packages/plugins/register.ts index 91ba768ea..91ba92f12 100644 --- a/packages/plugins/register.ts +++ b/packages/plugins/register.ts @@ -22,7 +22,9 @@ const packagePluginList = [ 'duckduckgo/search', 'duckduckgo/searchImg', 'duckduckgo/searchNews', - 'duckduckgo/searchVideo' + 'duckduckgo/searchVideo', + 'drawing', + 'drawing/baseChart' ]; export const list = [...staticPluginList, ...packagePluginList]; diff --git a/packages/plugins/src/drawing/baseChart/index.ts b/packages/plugins/src/drawing/baseChart/index.ts new file mode 100644 index 000000000..f5f71cc16 --- /dev/null +++ b/packages/plugins/src/drawing/baseChart/index.ts @@ -0,0 +1,93 @@ +import * as echarts from 'echarts'; + +type Props = { + title: string; + xAxis: string; + yAxis: string; + chartType: string; +}; + +type Response = Promise<{ + result: string; +}>; + +type SeriesData = { + name: string; + type: 'bar' | 'line' | 'pie'; // 只允许这三种类型 + data: number[] | { value: number; name: string }[]; // 根据图表类型的数据结构 +}; +type Option = { + backgroundColor: string; + title: { text: string }; + tooltip: {}; + xAxis: { data: string[] }; + yAxis: {}; + series: SeriesData[]; // 使用定义的类型 +}; + +const generateChart = (title: string, xAxis: string, yAxis: string, chartType: string) => { + // @ts-ignore 无法使用dom,如使用jsdom会出现生成图片无法正常展示,有高手可以帮忙解决 + const chart = echarts.init(undefined, undefined, { + renderer: 'svg', // 必须使用 SVG 模式 + ssr: true, // 开启 SSR + width: 400, // 需要指明高和宽 + height: 300 + }); + + let parsedXAxis: string[] = []; + let parsedYAxis: number[] = []; + try { + parsedXAxis = JSON.parse(xAxis); + parsedYAxis = JSON.parse(yAxis); + } catch (error: unknown) { + console.error('解析数据时出错:', error); + } + + const option: Option = { + backgroundColor: '#f5f5f5', + title: { text: title }, + tooltip: {}, + xAxis: { data: parsedXAxis }, + yAxis: {}, + series: [] // 初始化为空数组 + }; + + // 根据 chartType 生成不同的图表 + switch (chartType) { + case '柱状图': + option.series.push({ name: 'Sample', type: 'bar', data: parsedYAxis }); + break; + case '折线图': + option.series.push({ name: 'Sample', type: 'line', data: parsedYAxis }); + break; + case '饼图': + option.series.push({ + name: 'Sample', + type: 'pie', + data: parsedYAxis.map((value, index) => ({ + value, + name: parsedXAxis[index] // 使用 xAxis 作为饼图的名称 + })) + }); + break; + default: + console.error('不支持的图表类型:', chartType); + return ''; + } + + chart.setOption(option); + // 生成 Base64 图像 + const base64Image = chart.getDataURL({ type: 'png' }); + // 释放图表实例 + chart.dispose(); + + return base64Image; +}; + +const main = async ({ title, xAxis, yAxis, chartType }: Props): Response => { + return { + result: generateChart(title, xAxis, yAxis, chartType) + }; +}; + +export default main; diff --git a/packages/plugins/src/drawing/baseChart/template.json b/packages/plugins/src/drawing/baseChart/template.json new file mode 100644 index 000000000..8157a28ff --- /dev/null +++ b/packages/plugins/src/drawing/baseChart/template.json @@ -0,0 +1,551 @@ +{ + "author": "", + "version": "486", + "name": "基础图表", + "avatar": "core/workflow/template/baseChart", + "intro": "根据数据生成图表,可根据chartType生成柱状图,折线图,饼图", + "showStatus": true, + "weight": 10, + + "isTool": true, + "templateType": "search", + + "workflow": { + "nodes": [ + { + "nodeId": "pluginInput", + "name": "common:core.module.template.self_input", + "intro": "workflow:intro_plugin_input", + "avatar": "core/workflow/template/workflowStart", + "flowNodeType": "pluginInput", + "showStatus": false, + "position": { + "x": 613.7921798611637, + "y": -124.66724109717275 + }, + "version": "481", + "inputs": [ + { + "renderTypeList": [ + "reference" + ], + "selectedTypeIndex": 0, + "valueType": "string", + "canEdit": true, + "key": "title", + "label": "title", + "description": "BI图表的标题", + "defaultValue": "", + "list": [ + { + "label": "", + "value": "" + } + ], + "required": true, + "toolDescription": "BI图表的标题" + }, + { + "renderTypeList": [ + "reference" + ], + "selectedTypeIndex": 0, + "valueType": "string", + "canEdit": true, + "key": "xAxis", + "label": "xAxis", + "description": "x轴数据", + "defaultValue": "", + "required": true, + "toolDescription": "x轴数据", + "list": [ + { + "label": "", + "value": "" + } + ] + }, + { + "renderTypeList": [ + "reference" + ], + "selectedTypeIndex": 0, + "valueType": "string", + "canEdit": true, + "key": "yAxis", + "label": "yAxis", + "description": "y轴数据", + "defaultValue": "", + "list": [ + { + "label": "", + "value": "" + } + ], + "required": true, + "toolDescription": "y轴数据" + }, + { + "renderTypeList": [ + "select" + ], + "selectedTypeIndex": 0, + "valueType": "string", + "canEdit": true, + "key": "chartType", + "label": "chartType", + "description": "图表类型,如柱状图,折线图,饼图", + "defaultValue": "", + "required": true, + "list": [ + { + "label": "柱状图", + "value": "柱状图" + }, + { + "label": "折线图", + "value": "折线图" + }, + { + "label": "饼图", + "value": "饼图" + } + ], + "toolDescription": "图表类型,如柱状图,折线图,饼图" + } + ], + "outputs": [ + { + "id": "title", + "valueType": "string", + "key": "title", + "label": "title", + "type": "hidden" + }, + { + "id": "xAxis", + "valueType": "string", + "key": "xAxis", + "label": "xAxis", + "type": "hidden" + }, + { + "id": "yAxis", + "valueType": "string", + "key": "yAxis", + "label": "yAxis", + "type": "hidden" + }, + { + "id": "chartType", + "valueType": "string", + "key": "chartType", + "label": "chartType", + "type": "hidden" + } + ] + }, + { + "nodeId": "pluginOutput", + "name": "common:core.module.template.self_output", + "intro": "workflow:intro_custom_plugin_output", + "avatar": "core/workflow/template/pluginOutput", + "flowNodeType": "pluginOutput", + "showStatus": false, + "position": { + "x": 2122.252754006148, + "y": -63.5218674613718 + }, + "version": "481", + "inputs": [ + { + "renderTypeList": [ + "reference" + ], + "valueType": "string", + "canEdit": true, + "key": "图片base64数据", + "label": "图片base64数据", + "description": "可用使用markdown格式展示图片,如:![图片](base64)", + "value": [ + "ws0DFKJnCPhk", + "bzaYjKyQFOw2" + ] + } + ], + "outputs": [] + }, + { + "nodeId": "ws0DFKJnCPhk", + "name": "HTTP 请求", + "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", + "avatar": "core/workflow/template/httpRequest", + "flowNodeType": "httpRequest468", + "showStatus": true, + "position": { + "x": 1216.5166647574395, + "y": -206.30162946606856 + }, + "version": "481", + "inputs": [ + { + "key": "system_addInputParam", + "renderTypeList": [ + "addInputParam" + ], + "valueType": "dynamic", + "label": "", + "required": false, + "description": "接收前方节点的输出值作为变量,这些变量可以被 HTTP 请求参数使用。", + "customInputConfig": { + "selectValueTypeList": [ + "string", + "number", + "boolean", + "object", + "arrayString", + "arrayNumber", + "arrayBoolean", + "arrayObject", + "any", + "chatHistory", + "datasetQuote", + "dynamic", + "selectApp", + "selectDataset" + ], + "showDescription": false, + "showDefaultValue": true + }, + "valueDesc": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpMethod", + "renderTypeList": [ + "custom" + ], + "valueType": "string", + "label": "", + "value": "POST", + "required": true, + "valueDesc": "", + "description": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpTimeout", + "renderTypeList": [ + "custom" + ], + "valueType": "number", + "label": "", + "value": 30, + "min": 5, + "max": 600, + "required": true, + "valueDesc": "", + "description": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpReqUrl", + "renderTypeList": [ + "hidden" + ], + "valueType": "string", + "label": "", + "description": "新的 HTTP 请求地址。如果出现两个“请求地址”,可以删除该模块重新加入,会拉取最新的模块配置。", + "placeholder": "https://api.ai.com/getInventory", + "required": false, + "valueDesc": "", + "debugLabel": "", + "toolDescription": "", + "value": "drawing/baseChart" + }, + { + "key": "system_httpHeader", + "renderTypeList": [ + "custom" + ], + "valueType": "any", + "value": [], + "label": "", + "description": "自定义请求头,请严格填入 JSON 字符串。\n1. 确保最后一个属性没有逗号\n2. 确保 key 包含双引号\n例如:{\"Authorization\":\"Bearer xxx\"}", + "placeholder": "common:core.module.input.description.Http Request Header", + "required": false, + "valueDesc": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpParams", + "renderTypeList": [ + "hidden" + ], + "valueType": "any", + "value": [], + "label": "", + "required": false, + "valueDesc": "", + "description": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpJsonBody", + "renderTypeList": [ + "hidden" + ], + "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}", + "label": "", + "required": false, + "valueDesc": "", + "description": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpFormBody", + "renderTypeList": [ + "hidden" + ], + "valueType": "any", + "value": [], + "label": "", + "required": false, + "valueDesc": "", + "description": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "key": "system_httpContentType", + "renderTypeList": [ + "hidden" + ], + "valueType": "string", + "value": "json", + "label": "", + "required": false, + "valueDesc": "", + "description": "", + "debugLabel": "", + "toolDescription": "" + }, + { + "renderTypeList": [ + "reference" + ], + "valueType": "string", + "canEdit": true, + "key": "title-plugin", + "label": "title-plugin", + "customInputConfig": { + "selectValueTypeList": [ + "string", + "number", + "boolean", + "object", + "arrayString", + "arrayNumber", + "arrayBoolean", + "arrayObject", + "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", + "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", + "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", + "any", + "chatHistory", + "datasetQuote", + "dynamic", + "selectApp", + "selectDataset" + ], + "showDescription": false, + "showDefaultValue": true + }, + "required": true, + "value": [ + "pluginInput", + "chartType" + ] + } + ], + "outputs": [ + { + "id": "system_addOutputParam", + "key": "system_addOutputParam", + "type": "dynamic", + "valueType": "dynamic", + "label": "", + "customFieldConfig": { + "selectValueTypeList": [ + "string", + "number", + "boolean", + "object", + "arrayString", + "arrayNumber", + "arrayBoolean", + "arrayObject", + "any", + "chatHistory", + "datasetQuote", + "dynamic", + "selectApp", + "selectDataset" + ], + "showDescription": false, + "showDefaultValue": false + }, + "valueDesc": "", + "description": "" + }, + { + "id": "error", + "key": "error", + "label": "请求错误", + "description": "HTTP请求错误信息,成功时返回空", + "valueType": "object", + "type": "static", + "valueDesc": "" + }, + { + "id": "httpRawResponse", + "key": "httpRawResponse", + "required": true, + "label": "原始响应", + "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", + "valueType": "any", + "type": "static", + "valueDesc": "" + }, + { + "id": "bzaYjKyQFOw2", + "valueType": "string", + "type": "dynamic", + "key": "result", + "label": "result" + } + ] + } + ], + "edges": [ + { + "source": "pluginInput", + "target": "ws0DFKJnCPhk", + "sourceHandle": "pluginInput-source-right", + "targetHandle": "ws0DFKJnCPhk-target-left" + }, + { + "source": "ws0DFKJnCPhk", + "target": "pluginOutput", + "sourceHandle": "ws0DFKJnCPhk-source-right", + "targetHandle": "pluginOutput-target-left" + } + ] + } +} diff --git a/packages/plugins/src/drawing/template.json b/packages/plugins/src/drawing/template.json new file mode 100644 index 000000000..c1a36e98f --- /dev/null +++ b/packages/plugins/src/drawing/template.json @@ -0,0 +1,17 @@ +{ + "author": "", + "version": "486", + "name": "BI图表功能", + "avatar": "core/workflow/template/BI", + "intro": "BI图表功能,可以生成一些常用的图表,如饼图,柱状图,折线图等", + "showStatus": false, + "weight": 100, + + "isTool": true, + "templateType": "tools", + + "workflow": { + "nodes": [], + "edges": [] + } +} diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index bed30fa3c..44c8d0682 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -267,6 +267,8 @@ export const iconPaths = { 'core/workflow/undo': () => import('./icons/core/workflow/undo.svg'), 'core/workflow/upload': () => import('./icons/core/workflow/upload.svg'), 'core/workflow/versionHistories': () => import('./icons/core/workflow/versionHistories.svg'), + 'core/workflow/template/baseChart': () => import('./icons/core/workflow/template/baseChart.svg'), + 'core/workflow/template/BI': () => import('./icons/core/workflow/template/BI.svg'), date: () => import('./icons/date.svg'), delete: () => import('./icons/delete.svg'), edit: () => import('./icons/edit.svg'), diff --git a/packages/web/components/common/Icon/icons/core/workflow/template/BI.svg b/packages/web/components/common/Icon/icons/core/workflow/template/BI.svg new file mode 100644 index 000000000..10c52f0a1 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/template/BI.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/template/baseChart.svg b/packages/web/components/common/Icon/icons/core/workflow/template/baseChart.svg new file mode 100644 index 000000000..5ac3bea6c --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/template/baseChart.svg @@ -0,0 +1 @@ + \ No newline at end of file