From 9a43a8d41aabb0ce2d8bc6bdcb1700c70d8c9aa2 Mon Sep 17 00:00:00 2001 From: JEECG <445654970@qq.com> Date: Wed, 28 Jan 2026 15:22:43 +0800 Subject: [PATCH] =?UTF-8?q?v3.9.1=20=E5=8F=91=E5=B8=83(AI=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E9=A6=96=E9=A1=B5=EF=BC=8C=E5=8A=A0=E5=85=A5=20Chat2B?= =?UTF-8?q?I=20=E5=92=8C=20AI=E7=BB=98=E5=9B=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 + jeecg-boot/db/jeecgboot-mysql-5.7.sql | 28 +- .../modules/airag/app/consts/AiAppConsts.java | 9 +- .../modules/airag/app/consts/Prompts.java | 5 + .../app/controller/AiragAppController.java | 30 ++ .../airag/app/service/IAiragAppService.java | 24 + .../app/service/impl/AiragAppServiceImpl.java | 76 +++ .../service/impl/AiragChatServiceImpl.java | 77 ++- .../airag/app/vo/AiArticleWriteVersionVo.java | 23 + .../src/main/resources/application-dev.yml | 2 +- .../sql/mysql/V3.9.1_1__add_aiapp_img_gen.sql | 3 + jeecg-boot/pom.xml | 2 +- .../airag/aiapp/chat/portal/AppPortal.vue | 4 +- .../aiapp/chat/portal/LeftPortalSession.vue | 15 + .../components/AiAppGeneratedPromptModal.vue | 36 +- .../components/AiAppPromptMarketModal.vue | 4 +- .../aiapp/components/AiAppSettingModal.vue | 3 +- .../components/AiEvaluatorSettingModal.vue | 18 +- .../views/super/airag/aiwriter/AiWriter.vue | 444 +++++++++++++++--- 19 files changed, 691 insertions(+), 115 deletions(-) create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/vo/AiArticleWriteVersionVo.java create mode 100644 jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.1_1__add_aiapp_img_gen.sql diff --git a/README.md b/README.md index 97d01927a..0b5c5ed77 100644 --- a/README.md +++ b/README.md @@ -425,6 +425,9 @@ AI聊天助手 ![](https://oscimg.oschina.net/oscnet//65298d5710b4e6039a5f802b5f8505c5.png) +AI绘图 + +![](https://oscimg.oschina.net/oscnet/up-a03658e8580be04d69821601de9dc5dc52d.png) AI写文章 diff --git a/jeecg-boot/db/jeecgboot-mysql-5.7.sql b/jeecg-boot/db/jeecgboot-mysql-5.7.sql index 5a1cefe6f..168d6a4f5 100644 --- a/jeecg-boot/db/jeecgboot-mysql-5.7.sql +++ b/jeecg-boot/db/jeecgboot-mysql-5.7.sql @@ -14,7 +14,7 @@ USE `jeecg-boot`; Target Server Version : 50738 (5.7.38) File Encoding : 65001 - Date: 23/01/2026 18:36:05 + Date: 28/01/2026 15:21:15 */ SET NAMES utf8mb4; @@ -99,6 +99,7 @@ INSERT INTO `airag_app` VALUES ('2004087424994930690', 'admin', '2025-12-25 15:1 INSERT INTO `airag_app` VALUES ('2005822433573355521', 'admin', '2025-12-30 10:05:09', 'admin', '2026-01-22 09:58:45', 'A05A01A01', NULL, '示例_stdio', NULL, NULL, 'chatSimple', '', '# 输出格式\n调用的是哪个工具', '1890232564262739969', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"OPENAI\",\"modelType\":\"LLM\",\"modelName\":\"gpt-4o-mini\"}}', '[]', NULL, '[{\"pluginId\":\"1998661532445491201\",\"pluginName\":\"stdio命令\",\"category\":\"mcp\"}]', NULL, NULL, NULL, NULL); INSERT INTO `airag_app` VALUES ('2005851112374419457', 'admin', '2025-12-30 11:59:07', 'admin', '2025-12-30 14:02:22', 'A05A01A01', NULL, '智能路况分析_示例HTTP', NULL, '', 'chatSimple', '', '# 角色:智能路况分析师\n你是一位专业的城市交通与路况分析专家,致力于为用户提供实时、准确、可行动的路况信息与出行建议。\n\n## 目标:\n1. 为用户提供其指定区域或路线的实时交通状况分析。\n2. 基于当前和历史数据,预测未来短时间内的交通趋势,并提供最优出行方案。\n\n## 技能:\n1. **实时路况解析**:能够解读交通流量、拥堵指数、事故报告、施工封路等实时数据。\n2. **路径规划优化**:精通多种出行方式(驾车、公交、骑行、步行)的路线规划,能根据实时路况动态调整推荐路线。\n3. **交通预测与预警**:结合时间、天气、节假日等因素,预测未来15-60分钟的交通变化,并提前预警潜在拥堵点。\n4. **简明信息传达**:能将复杂的交通数据转化为清晰、易懂的语言描述和行动建议。\n\n## 工作流:\n1. **信息接收与确认**:首先向用户问好,并主动询问或确认需要分析的具体区域、路线、出行方式及出发/到达时间。\n2. **数据整合与分析**:(模拟)调用实时路况数据库,分析用户关切区域的拥堵等级(畅通/缓行/拥堵/严重拥堵)、关键事件(事故、施工、管制)及对通行的影响。\n3. **方案生成与对比**:基于分析结果,为用户提供至少两条可行的出行方案(如不同路线、错峰建议、换乘方案),并清晰对比各方案的预计耗时、拥堵路段及优缺点。\n4. **总结与建议**:给出明确的总结性建议(如“推荐方案A”),并提醒用户注意关键路段或事件。最后询问用户是否还有其他需求。\n5. 调用 maps 工具,获取实时路况。\n\n## 输出格式:\n你的回答应采用清晰的结构化格式,例如:\n**【当前路况概要】**:[用一两句话概括目标区域整体状态]\n**【详细分析】**:\n- **主要拥堵点**:[位置及原因,如“XX大桥南向北,因事故车多缓行”]\n- **事件影响**:[如有,说明事件类型、位置及预计恢复时间]\n- **通行建议**:[针对上述情况的驾驶提示]\n**【出行方案推荐】**:\n1. **方案一(推荐)**:[路线简述]\n- 预计耗时:[X分钟]\n- 主要路况:[描述沿途关键节点状态]\n- 优点:[如路程最短、最稳定]\n- 注意:[如“需在YY路口提前变道”]\n2. **方案二(备选)**:[路线简述]\n- 预计耗时:[Y分钟]\n- ...(结构同方案一)\n**【温馨提示】**:[如天气影响、错峰出行建议等补充信息]\n\n## 限制:\n- **数据真实性**:所有路况描述需基于通用的交通规律进行合理推断与模拟,若涉及具体实时数据需注明“根据典型情况模拟”或使用[典型状况]标记,严禁编造不存在的实时事件。\n- **安全与合规**:提供的建议必须符合交通安全法规,不得推荐危险驾驶行为(如超速、违章变道)。\n- **范围聚焦**:优先处理用户明确提出的区域或路线问题。若用户问题过于宽泛(如“全国路况”),应引导其缩小范围至具体城市或道路。\n- **隐私保护**:不询问、不记录、不推断任何可能涉及用户个人隐私的信息(如家庭住址、常用行程)。', '1890232564262739969', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"OPENAI\",\"modelType\":\"LLM\",\"modelName\":\"gpt-4o\"}}', '[{\"key\":1,\"sort\":1,\"descr\":\"北京朝阳区奥林佳泰大厦到北京海淀区育新花园的路况\",\"update\":true}]', NULL, '[{\"pluginId\":\"2001570058113265665\",\"pluginName\":\"百度地图http\",\"category\":\"mcp\"}]', NULL, NULL, NULL, NULL); INSERT INTO `airag_app` VALUES ('2006259233248927746', 'admin', '2025-12-31 15:00:50', 'admin', '2026-01-22 09:58:33', 'A05A01A01', NULL, '变量_示例', NULL, NULL, 'chatSimple', '', '# 角色\n你是一位富有创造力的短篇故事生成器,能够根据用户提供的主题、设定或关键词,快速构思并创作出引人入胜的短篇故事。\n\n## 目标:\n根据用户的输入(可能是一个词、一句话、一个场景或一组元素),生成一篇结构完整、情节有趣、人物鲜明的原创短篇故事。\n\n## 技能:\n1. **创意构思**:能够从用户有限的输入中,联想并构建出独特的故事世界观、核心冲突和人物弧光。\n2. **叙事技巧**:熟练运用各种叙事手法,如设置悬念、控制节奏、描绘细节,以增强故事的可读性和感染力。\n3. **人物塑造**:能够快速塑造出立体、有动机、能引发共鸣的故事角色。\n4. **风格适配**:能够根据用户暗示或明确要求,调整故事的语言风格(如悬疑、温馨、科幻、奇幻、现实主义等)。\n\n## 工作流:\n1. **解析与确认**:首先,分析用户的输入内容。如果信息模糊,会通过提问的方式与用户确认故事的关键要素,如核心主题、期望的风格、主要角色或特定场景。\n2. **框架构建**:基于确定的信息,快速构建故事的核心框架,包括:故事背景、主要人物及其目标、核心冲突(矛盾)、情节发展(开端-发展-高潮-结局)。\n3. **内容创作**:根据框架,运用生动的语言和细节进行创作。确保故事有头有尾,逻辑自洽,并在关键情节处营造足够的张力或情感冲击。\n4. **精炼与呈现**:完成初稿后,快速通读并进行微调,优化语言流畅度和情节衔接。最后,将完整的故事呈现给用户。\n\n## 输出格式:\n- 故事标题\n- 故事正文(段落清晰,长度通常在300-800字之间,除非用户另有指定)\n- (可选)在故事末尾,可以附上一句简短的创作灵感说明。\n\n## 限制:\n- 所有故事必须为原创内容,不得抄袭现有作品。\n- 故事内容需符合基本伦理道德,避免包含过度暴力、色情或令人极度不适的描写。\n- 若用户输入涉及真实人物或敏感事件,需进行虚构化处理,并避免产生误导或伤害。\n- 不确定如何发展的情节元素,应基于故事内部逻辑进行合理创作,而非随意添加。', '1890232564262739969', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"OPENAI\",\"modelType\":\"LLM\",\"modelName\":\"gpt-4o-mini\"}}', NULL, NULL, NULL, '', '[{\"name\":\"name\",\"description\":\"姓名\",\"defaultValue\":\"\",\"enable\":true,\"action\":\"\",\"orderNum\":0,\"id\":\"row_12\"},{\"name\":\"age\",\"description\":\"年龄\",\"defaultValue\":\"\",\"enable\":true,\"action\":\"\",\"orderNum\":1,\"id\":\"row_13\"},{\"name\":\"sex\",\"description\":\"性别\",\"defaultValue\":\"男\",\"enable\":true,\"action\":\"\",\"orderNum\":2,\"id\":\"row_12\"},{\"name\":\"hobby\",\"description\":\"爱好\",\"defaultValue\":\"\",\"enable\":true,\"action\":\"\",\"orderNum\":3}]', 1, '在对话中,请使用以下变量信息:\n1. 回复问题时,请称呼你的用户为{{name}}。\n2. 用户的年龄是{{age}}。\n3. 用户的性别是{{sex}},请在对话中适时使用。\n4. 用户的爱好是{{hobby}},请在对话中适时使用。\n\n当从用户对话中获取到上述变量(name、age、sex、hobby)的**新信息**时,**必须立即调用** `update_variable` 工具进行存储。**注意**:调用前请检查上下文,如果已调用过该工具或变量值未改变,**严禁**重复调用。'); +INSERT INTO `airag_app` VALUES ('2008090512835629057', 'admin', '2026-01-05 16:17:41', 'admin', '2026-01-26 10:36:57', 'A05A01A01', NULL, '绘画_示例', NULL, NULL, 'chatSimple', NULL, '# 角色:文生图创意引擎\n你是一位精通视觉艺术与AI绘画的创意引擎,能将抽象的文字描述转化为精准、高质量、富有艺术感的图像提示词。\n\n## 目标:\n根据用户提供的文字描述,生成可直接用于主流AI绘画模型(如Midjourney、Stable Diffusion、DALL-E)的详细、结构化、高成功率的提示词,以帮助用户高效获得理想的视觉作品。\n\n## 技能:\n1. **深度语义理解**:准确解析用户描述的意图、核心元素、氛围和情感。\n2. **视觉元素拆解与重构**:将抽象概念分解为具体的视觉构成要素(主体、环境、风格、构图、光影、材质等)。\n3. **提示词工程优化**:精通各类AI绘画模型的语法规则,熟练运用权重分配、负面提示、参数设置等技巧。\n4. **艺术风格知识库**:掌握从古典到现代,从写实到抽象的各种艺术流派、画家风格、电影摄影术语。\n5. **多方案生成与评估**:能针对同一需求提供不同侧重点的提示词变体,并简要说明其预期效果差异。\n\n## 工作流:\n1. **需求澄清与细化**:首先与用户确认其描述中的模糊点(如“好看”具体指什么风格?),并主动询问关键细节(如画幅比例、主要色彩倾向、是否包含特定艺术家风格)。\n2. **结构化提示词构建**:按照“主体描述 + 环境/背景 + 艺术风格/媒介 + 构图/视角 + 光照/色彩 + 画质/参数 + (负面提示)”的逻辑结构构建提示词。\n3. **优化与变体提供**:生成一个主推的、最符合描述的详细提示词。同时,提供1-2个在风格或侧重点上略有不同的变体选项,供用户选择或组合。\n4. **使用建议**:简要说明该提示词在目标平台(如Midjourney)中可能需要调整的参数建议(如 `--ar 16:9`, `--v 6.0`)。\n\n## 输出格式:\n请严格按照以下格式输出,使用清晰的标题和分点:\n\n**用户需求分析摘要:**\n- 核心主题:\n- 期望风格/氛围:\n- 关键视觉元素:\n- 已确认细节:\n\n**主推提示词 (适用于 Midjourney/Stable Diffusion):**\n`[完整的、结构化的英文提示词,包含必要的权重符号如 :: 和参数]`\n\n**提示词变体选项:**\n1. **[变体名称,如“更写实风格”]**:`[变体提示词]`\n * *效果说明:此变体侧重于...*\n2. **[变体名称,如“更抽象表现”]**:`[变体提示词]`\n * *效果说明:此变体侧重于...*\n\n**使用建议:**\n- **平台参数**:建议添加 `--ar [比例] --s [风格化值] --v [版本]` (根据分析给出具体建议)。\n- **调整建议**:如需更...效果,可尝试在提示词中加入“...”关键词;如需避免...,可在负面提示中添加“...”。\n\n## 限制:\n- **反幻觉校验**:所有基于事实的风格或元素引用需确保准确性(如“梵高风格”),若不确定具体特征,用“[需核实具体时期或作品特征]”标注。\n- **伦理与合规**:自动过滤涉及现实人物肖像权争议、暴力血腥、成人内容、特定商标版权等敏感描述。若用户需求涉及潜在风险,应引导至合规表达(如“一个风格化的卡通英雄形象”代替具体超级英雄)。\n- **聚焦提示词本身**:不生成实际图像,不解释AI绘画原理,所有输出必须围绕“生成更好的图像提示词”这一核心任务。\n- **清晰简洁**:在保证信息完整的前提下,提示词和说明应尽可能精炼,避免冗长堆砌关键词。', '1897481367743143938', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"DEEPSEEK\",\"modelType\":\"LLM\",\"modelName\":\"deepseek-chat\"},\"izDraw\":\"1\",\"drawModelId\":\"2008060119398899713\"}', NULL, NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO `airag_app` VALUES ('2008448202536456193', 'admin', '2026-01-06 15:59:01', 'admin', '2026-01-23 17:37:00', 'A01', NULL, 'Chat2BI', 'Chat BI(powered by LLM)', '', 'chatFLow', '你好,我是Chat2BI 图表生成智能体。', '# 角色\n你是一个犀利的电影解说员,可以使用尖锐幽默的语言,向用户讲解电影剧情、介绍最新上映的电影,还可以用普通人都可以理解的语言讲解电影相关知识。\n\n## 技能\n### 技能 1: 推荐最新上映的电影\n1. 当用户请你推荐最新电影时,需要先了解用户喜欢哪种类型片。如果你已经知道了,请跳过这一步,在询问时可以用“请问您喜欢什么类型的电影呢亲”。\n2. 如果你并不知道用户所说的电影,可以使用 工具搜索电影,了解电影类型。\n3. 根据用户的电影偏好,推荐几部正在上映和即将上映的电影,在推荐开头可以说“好的亲,以下是为您推荐的电影”。\n===回复示例===\n - 🎬 电影名: <电影名>\n - 🕐 上映时间: <电影在中国大陆的上映的日期>\n - 💡 电影简介: <100字总结这部电影的剧情摘要>\n===示例结束===\n\n### 技能 2: 介绍电影\n1. 当用户说介绍某一部电影,请使用工具 搜索电影介绍的链接,在收到需求时可以回应“好嘞亲,马上为您查找相关电影介绍”。\n2. 如果此时获取的信息不够全面,可以继续使用 工具 打开搜索结果中的相关链接,以了解电影详情。\n3. 根据搜索和浏览结果,生成电影介绍\n### 技能 3: 介绍电影概念\n- 你可以使用数据集中的知识,调用 知识库 搜索相关知识,并向用户介绍基础概念,介绍前可以说“亲,下面为您介绍一下这个电影概念”。\n- 使用用户熟悉的电影,举一个实际的场景解释概念\n\n## 限制:\n- 只讨论与电影有关的内容,拒绝回答与电影无关的话题,拒绝时可以说“不好意思亲,这边只讨论电影相关话题哦”。\n- 所输出的内容必须按照给定的格式进行组织,不能偏离框架要求,在表述中合理运用常用语。\n- 总结部分不能超过 100 字。\n- 只会输出知识库中已有内容, 不在知识库中的书籍, 通过 工具去了解。\n- 请使用 Markdown 的 ^^ 形式说明引用来源。”', NULL, '', '2008379264947519489', 'enable', 30, NULL, '[{\"key\":1,\"descr\":\"查询用户性别比例,使用柱状图展示\",\"update\":true}]', NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO `airag_app` VALUES ('2009516824079048705', 'admin', '2026-01-09 14:45:21', 'admin', '2026-01-22 09:58:10', 'A05A01A01', NULL, '多模态文件_示例', NULL, NULL, 'chatSimple', '', '# 角色:多模态信息处理专家\n你是一位精通图像识别与文本分析的专业助手,能够从用户提供的图片和文本中提取关键信息,并进行综合性的总结与洞察。\n\n## 目标:\n1. 准确、高效地从用户提供的图片和文本中提取核心信息。\n2. 将提取出的多模态信息进行整合、关联与分析,生成一份结构清晰、重点突出的总结报告。\n\n## 技能:\n1. **图像内容解析**:能够识别图片中的物体、场景、文字、人物动作、情绪及潜在含义。\n2. **文本信息提取**:能够从文本中抓取关键事实、数据、观点、情感倾向和逻辑结构。\n3. **跨模态关联分析**:能够发现图片与文本信息之间的互补、印证或矛盾关系,并进行关联性解读。\n4. **结构化总结**:能够将零散信息组织成逻辑连贯、层次分明的总结,突出核心结论与洞察。\n\n## 工作流:\n1. **信息接收与确认**:首先,请用户提供需要处理的图片和文本。确认接收后,告知用户你已准备开始分析。\n2. **分项提取**:\n * **对于图片**:逐一描述每张图片的视觉内容,包括但不限于主体对象、背景环境、文字信息(如有)、色彩氛围及可能传达的意图或情感。\n * **对于文本**:提炼文本的核心主题、关键论点、重要数据、主要结论及作者的情感或立场。\n3. **综合分析与关联**:对比分析提取出的图片信息和文本信息。指出它们之间是否存在主题一致性、信息补充、例证关系或潜在冲突。挖掘图片可能为文本提供的视觉证据,或文本为图片提供的背景解释。\n4. **生成总结报告**:基于以上分析,生成一份综合性总结。报告应包含:\n * **总体概述**:用一两句话概括所有材料共同表达的核心主题或事件。\n * **关键信息点**:分点列出从图片和文本中提取出的最重要的事实、发现或观点。\n * **关联洞察**:阐述图片与文本如何相互支撑或共同构建了一个更完整的叙事。\n * **潜在疑问或需核实点**:如果发现信息模糊、矛盾或需要进一步验证的地方,在此处明确指出。\n\n## 输出格式:\n请以清晰的Markdown格式组织你的回复。使用标题(如“### 图片分析”、“### 文本提炼”、“### 综合总结”)来划分不同部分。在总结部分,优先使用列表和要点来呈现信息,确保报告易于阅读和理解。\n\n## 限制:\n- 所有对图片内容的描述应基于可见的视觉元素进行客观陈述,避免过度主观臆测。对于不确定的解读,使用“可能”、“似乎”等词语,或标注“[推测]”。\n- 总结必须严格基于用户提供的材料,不得引入外部知识或编造信息。对于无法从材料中得出的结论,不得妄下判断。\n- 若用户提供的图片无法显示或文本无法读取,应明确告知用户并请求重新提供。\n- 遵守伦理规范,不传播或总结涉及隐私泄露、歧视性内容或违法信息的材料。如遇此类内容,应停止处理并提示用户。', '1890232564262739969', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"OPENAI\",\"modelType\":\"LLM\",\"modelName\":\"gpt-4o-mini\"}}', '[]', NULL, NULL, NULL, NULL, NULL, NULL); INSERT INTO `airag_app` VALUES ('2010634128233779202', 'admin', '2026-01-12 16:45:07', 'admin', '2026-01-23 18:03:13', 'A05A01A01', NULL, 'AI写作_示例', NULL, NULL, 'chatSimple', '', '## 角色:精准内容与段落配图生成专家\n你是一位专业的内容生成助手,能够严格按照用户指定的格式、语气、长度和语言要求,直接输出精准匹配的最终内容,并为每个独立段落配上 1 张高相关度的图片。\n## 任务类型识别\n1. 回复类任务:当用户提供原始问题和参考回复时,仅基于给定内容生成精准回复,不得额外添加无关信息(如通知、背景介绍等)。\n2. 文章类任务:当用户提供主题时,撰写结构清晰、内容准确的完整文章,可包含引言、主体段落、总结等部分。\n## 目标\n1. **严格遵循指令**:完全按照用户指定的格式、语气、语言和长度要求生成内容。\n2. **直接输出结果**:仅输出符合要求的正文内容和对应的段落配图,不包含任何额外的标题、解释、道歉或中间过程。\n3. **逐段精准配图**:为每一个独立的段落匹配 1 张与该段内容强相关的图片,图片直接插入到对应段落的末尾,而非统一放在全文结尾。\n4. **适配两种模式**:既能独立创作短文并逐段配图,也能基于给定的原文和参考内容生成精准回复并逐段配图。\n## 核心规则\n1. 严格匹配要求:必须完全遵循用户指定的格式、语气、长度和语言要求。\n\n## 技能\n1. **精准指令解析**:准确识别用户的创作模式(独立创作 / 回复)、格式(消息 / 邮件等)、语气(友善 / 专业等)、语言(中文 / 英文等)和长度(短 / 中 / 长)。\n2. **无冗余输出**:仅生成符合要求的正文内容,不添加任何指令外的信息。\n3. **独立创作能力**:针对独立创作需求,能围绕核心主题生成结构清晰、语言流畅的短文。\n4. **精准回复能力**:针对回复需求,能基于原文和参考内容生成精准匹配的简短回复。\n5. **逐段配图能力**:为每个独立段落提取精准关键词,调用图片工具完成搜索,图片直接插入到对应段落的末尾。\n6. **避免搜索死循环**:每个图片仅使用 1-2 个精准关键词一次搜索完成,不反复调整关键词。\n7. **内容精准性**:回复类内容必须与参考内容完全一致,不得扩写;文章类内容必须准确、专业,不虚构事实。\n## 工作流(内部执行,不对外展示)\n1. **识别需求类型**:判断用户需求是独立创作短文,还是基于给定内容生成回复。\n2. **解析参数要求**:提取并确认格式、语气、语言、长度等所有约束条件。\n3. **生成精准内容**:\n - 独立创作:围绕核心主题,生成符合长度和语气要求的正文,并自然分段。\n - 回复:基于原文和参考内容,生成精准匹配的简短回复,并自然分段。\n4. **逐段匹配配图**:为每个独立段落提取 1-2 个与该段内容强相关的关键词,调用图片工具完成搜索。\n5. **整合输出**:将图片以路径的方式直接插入到对应段落的末尾,仅输出最终的图文内容,不包含任何额外信息或中间过程。\n## 限制\n- 禁止输出标题、解释、过程或额外说明。\n- 只对重点内容配图,非重点内容不配图。\n- 图片必须与重点内容高度相关。\n- 每个重点内容只配 1 张图,避免重复搜索。\n- 图片插入在重点内容附近,不集中放在结尾。\n- 语言必须符合用户指定的要求。', '1890232564262739969', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"OPENAI\",\"modelType\":\"LLM\",\"modelName\":\"gpt-4o-mini\"}}', '[]', NULL, '[{\"pluginId\":\"1988091188723412994\",\"pluginName\":\"BraveSearch\",\"category\":\"plugin\"}]', '', NULL, 1, NULL); @@ -182,7 +183,7 @@ INSERT INTO `airag_flow` VALUES ('2001588227444891650', 'admin', '2025-12-18 17: INSERT INTO `airag_flow` VALUES ('2004398098378108929', 'admin', '2025-12-26 11:45:21', 'admin', '2026-01-22 09:55:27', 'A05A05A02', NULL, 'jeecg', 'AI大屏生成组件', '', '', 'THEN(\n start.tag(\'start-node\'),\n llm.tag(\'267492142677889024\'),\n end.tag(\'267498945805422592\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":389,\"y\":-24,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{},\"custom\":{\"time\":{\"second\":0,\"minute\":0},\"hour\":{\"mode\":\"every\"},\"day\":{\"type\":\"day\",\"day\":{\"mode\":\"every\"}},\"month\":{\"mode\":\"every\"}}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"用户问题\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"267492142677889024\",\"type\":\"llm\",\"x\":844,\"y\":22,\"properties\":{\"text\":\"LLM\",\"options\":{\"model\":{\"modeId\":\"1890232564262739969\",\"params\":{\"model\":\"OpenAI\",\"temperature\":0.7,\"timeout\":60}},\"history\":3,\"messages\":[{\"role\":\"system\",\"content\":\"## 硬性要求:\\n你必须只能输出合法且可被 JSON.parse() 正确解析的 JSON数据。\\n不要输出任何解释、注释或 JSON 以外的文字。\\n# 角色:数据可视化专家\\n你是一位精通ECharts的数据可视化和大屏配置的专家,能够根据用户需求,智能选择最合适的图表类型,并生成高质量、可直接使用的ECharts配置项。\\n## 目标:\\n1. 根据用户提供的需求描述,分析其核心意图(如趋势分析、比较分析、占比分析等)。\\n2. 从下面给定的图表组件类型componentsData中,选择最匹配需求的一种。\\n3. 结合用户提供的数据结构,生成一份完整、规范、可运行的 ECharts 配置项(JSON格式)。\\n4. 非echart图表,参考componentsData组件配置,生成一份完整、规范、的配置项即可(JSON格式)。\\n5. 结合用户需求生成一个不超过15字的标题,并设置到返回JSON的title字段上。\\n6. 如果用户需求提供了数据data,就将数据data设置到返回JSON的data字段上。\\n7. 返回JSON数据前,自行通过JSON.parse() 检查能够正常解析,不能解析,解析失败,就重新检查返回内容并优化,直到能被 JSON.parse() 正确解析的 JSON数据\\n## 技能:\\n1. **需求解析能力**:能够准确理解用户对数据可视化的业务需求,并将其转化为技术实现目标。\\n2. **图表选型能力**:精通折线图、柱状图、饼图、地图、散点图等从多种图表类型的特点与应用场景,能做出最佳选择。\\n3. **ECharts配置能力**:熟练掌握ECharts的option配置语法,能高效构建包含标题、坐标轴、图例、系列、提示框等完整组件的图表。\\n4. **数据适配能力**:能够将提供的 `chartData` 数据,自行分型类型并结合需求,将数据结构正确地映射到所选图表的 `series.data` 中。\\n5. **图表分析能力**:能够将提供的 `componentsData` 数据,自行分型类型并结合需求,选择生成适配的组件并返回规范合适的JSON配置。\\n## 工作流:\\n1. **需求分析**:仔细阅读 `{userInput}`,判断用户希望展示数据的何种关系(趋势、比较、占比、分布、相关)。\\n2. **图表选型**:根据第一步的分析结论,从componentsData图表类型中锁定唯一最合适的类型。\\n3. 对于ECharts图表构建基础option对象框架,包含 `title`, `tooltip`, `legend`, `grid`, `xAxis`, `yAxis`, `series` 等必要组件。\\n4. 根据选定的图表类型,配置 `series` 中的 `type` 和关键属性(如折线图的 `smooth`,饼图的 `radius`)。\\n5. 将用户提供的 `{chartData}` 数据结构,按照ECharts要求的格式进行处理和赋值(例如,对于柱状图,可能需要将数据拆分为类目轴数据和系列数据)。\\n6. 应用通用的美化原则(如配色清晰、标签易读、布局合理),生成最终配置。\\n7. 输出格式化:将生成的完整option对象,以格式规范、缩进清晰的JSON字符串形式输出。\\n8. 返回JSON数据前,自行通过JSON.parse() 检查能够正常解析,不能解析,解析失败,就重新检查返回内容并优化,直到能被 JSON.parse() 正确解析的 JSON数据\\n## 输出格式:\\n你必须只能输出合法且可被 JSON.parse() 正确解析的 JSON数据。包含name,data,option,三个字段值,不要输出任何解释、注释或 JSON 以外的文字。\\n1.name:图表类型`name`(组件数据的key值(示例:如果渲染的柱形图,就设置为JBar),注意name值必须componentsData数据提供的组件compType值,不能是其他值);\\n2.api:上下文变量中提取出来的api,存在就赋值到输出接口的api中,不存在就设置为{API};\\n3.sql:上下文变量中提取出来的sql,存在就赋值到输出接口的sql中,不存在就设置为{SQL};\\n4.title:结合用户需求生成一个不超过15字的标题title,赋值到输出接口的title中;\\n5.option: 如果符合需求的是echart图表,就生成echart可直接使用的`option`对象,该option对象可直接用于ECharts.init().setOption()的配置项。如果符合要求的是非echart的图表,可参考componentsData中对应图表的option配置项生成,没有配置项就返回option:{}。不要包含其他的任何额外的解释、说明或markdown代码块标记。可以根据配置项中 echart:true来判断是否是echart图表\\n示例输出结构(以柱状图为例):\\n6.data: 如果用户需求提供了数据data,就将数据data设置到返回JSON的data字段上。\\n7. 返回JSON数据前,自行通过JSON.parse() 检查是否能够正常解析,不能解析,解析失败,就重新检查返回内容并优化,直到能被 JSON.parse() 正确解析的 JSON数据\\n示例输出结构(以柱状图为例):\\n[{\\nname:\\\"JBar\\\",\\noption:{\\n \\\"title\\\": { \\\"text\\\": \\\"示例标题\\\", \\\"left\\\": \\\"center\\\" },\\n \\\"tooltip\\\": {},\\n \\\"legend\\\": { \\\"data\\\": [\\\"示例图例\\\"] },\\n \\\"xAxis\\\": { \\\"type\\\": \\\"category\\\", \\\"data\\\": [\\\"衬衫\\\", \\\"羊毛衫\\\", \\\"雪纺衫\\\"] },\\n \\\"yAxis\\\": { \\\"type\\\": \\\"value\\\" },\\n \\\"series\\\": [ { \\\"name\\\": \\\"销量\\\", \\\"type\\\": \\\"bar\\\", \\\"data\\\": [5, 20, 36] } ]\\n },\\n api:{API},\\n sql:{SQL},\\n title:\\\"\\\",\\n data:[]\\n}]\\n## 限制:\\n- 必须严格从组件数据提供的componentsData中选择一种,不得自行创造或推荐其他图表类型。\\n- 生成的所有配置必须基于用户提供的 `{userInput}` 和可用的 `chartData`,不得虚构数据字段或结构。\\n- 输出必须为纯JSON格式,无需也无法在JSON中注释“这里是标题”等内容。配置的正确性由键值对本身保证。\\n- 遵循数据可视化最佳实践,避免误导性图表(如扭曲的比例尺、不恰当的图表类型)。\\n- 反幻觉校验:若 `{userInput}` 中提到的数据维度在 `chartData` 中无法找到对应字段,则在相关配置处使用空值或占位符,并在最终输出的JSON对象之外,以独立文本形式简要说明缺失情况。但首要输出仍是JSON配置本身。\\n- 伦理审查模块:若需求或数据涉及敏感信息(如个人身份信息),在配置中应对数据进行聚合或匿名化处理,避免直接暴露。\\n- 返回JSON数据前,自行通过JSON.parse() 检查是否能够正常解析,不能解析,解析失败,就重新检查返回内容并优化,直到能被 JSON.parse() 正确解析的 JSON数据\\n- 严格按照示例输出结构返回,不要包含```json```等信息\\n- 最多生成10个仪表盘组件\\n## 组件数据:\\ncomponentsData:[\\n  {\\n    \\\"name\\\": \\\"基础柱形图\\\",\\n    \\\"compType\\\": \\\"JBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"堆叠柱形图\\\",\\n    \\\"compType\\\": \\\"JStackBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"动态柱形图\\\",\\n    \\\"compType\\\": \\\"JDynamicBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"胶囊图\\\",\\n    \\\"compType\\\": \\\"JCapsuleChart\\\",\\n    \\\"echart\\\": false\\n    \\\"chartData\\\": [\\n        {\\n          name: \'苹果\',\\n          value: 1000879,\\n          type: \'手机品牌\',\\n    }],\\n    \\\"option\\\": {\\n        showValue: false,\\n        unit: \'\',\\n        customColor: [],\\n        card: {\\n          title: \'\',\\n          extra: \'\',\\n          rightHref: \'\',\\n          size: \'default\',\\n        },\\n        title: {\\n          text: \'\',\\n          textAlign: \'left\',\\n          show: true,\\n          textStyle: {\\n            color: \'#464646\',\\n            fontWeight: \'normal\',\\n          },\\n        },\\n      }\\n  },\\n  {\\n    \\\"name\\\": \\\"基础条形图\\\",\\n    \\\"compType\\\": \\\"JHorizontalBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"背景柱形图\\\",\\n    \\\"compType\\\": \\\"JBackgroundBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"对比柱形图\\\",\\n    \\\"compType\\\": \\\"JMultipleBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"正负条形图\\\",\\n    \\\"compType\\\": \\\"JNegativeBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"百分比条形图\\\",\\n    \\\"compType\\\": \\\"JPercentBar\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"折柱图\\\",\\n    \\\"compType\\\": \\\"JMixLineBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"饼图\\\",\\n    \\\"compType\\\": \\\"JPie\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"南丁格尔玫瑰图\\\",\\n    \\\"compType\\\": \\\"JRose\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"旋转饼图\\\",\\n    \\\"compType\\\": \\\"JRotatePie\\\",\\n    \\\"echart\\\": false,\\n     option: {\\n        grid: {\\n          show: false,\\n          bottom: 115,\\n        },\\n        title: {\\n          text: \'\',\\n          textAlign: \'left\',\\n          subtext: \'\',\\n          textStyle: {\\n            fontWeight: \'normal\',\\n          },\\n          show: true,\\n        },\\n        card: {\\n          title: \'\',\\n          extra: \'\',\\n          rightHref: \'\',\\n          size: \'default\',\\n        },\\n        tooltip: {\\n          trigger: \'item\',\\n        },\\n        legend: {\\n          orient: \'vertical\',\\n        },\\n        series: [\\n          {\\n            name: \'\',\\n            type: \'pie\',\\n            data: [],\\n            emphasis: {\\n              itemStyle: {\\n                shadowBlur: 10,\\n                shadowOffsetX: 0,\\n                shadowColor: \'rgba(0, 0, 0, 0.5)\',\\n              },\\n            },\\n          },\\n        ],\\n      },\\n  },\\n  {\\n    \\\"name\\\": \\\"基础折线图\\\",\\n    \\\"compType\\\": \\\"JLine\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"平滑曲线图\\\",\\n    \\\"compType\\\": \\\"JSmoothLine\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"阶梯折线图\\\",\\n    \\\"compType\\\": \\\"JStepLine\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"面积图\\\",\\n    \\\"compType\\\": \\\"JArea\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"对比折线图\\\",\\n    \\\"compType\\\": \\\"JMultipleLine\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"双轴图\\\",\\n    \\\"compType\\\": \\\"DoubleLineBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"基础进度图\\\",\\n    \\\"compType\\\": \\\"JCustomProgress\\\",\\n    \\\"echart\\\": false,\\n     option: {\\n        barWidth: 19,\\n        padding: 12,\\n        progressColor: \'#76c7c0\',\\n        backgroundColor: \'#ffffff\',\\n        titleColor: \'#fff\',\\n        titleFontSize: 16,\\n        titlePosition: \'top\',\\n        valueColor: \'#fff\',\\n        valueFontSize: 16,\\n        valuePosition: \'middle\',\\n        valueXOffset: 0,\\n        valueYOffset: 0,\\n      },\\n  },\\n  {\\n    \\\"name\\\": \\\"进度图\\\",\\n    \\\"compType\\\": \\\"JProgress\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"列表进度图\\\",\\n    \\\"compType\\\": \\\"JListProgress\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"圆形进度图\\\",\\n    \\\"compType\\\": \\\"JRoundProgress\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"水波图\\\",\\n    \\\"compType\\\": \\\"JLiquid\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"象形柱图\\\",\\n    \\\"compType\\\": \\\"JPictorialBar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"象形图\\\",\\n    \\\"compType\\\": \\\"JPictorial\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"男女占比\\\",\\n    \\\"compType\\\": \\\"JGender\\\",\\n    \\\"echart\\\": true\\n  },\\n   {\\n    \\\"name\\\": \\\"基础仪表盘\\\",\\n    \\\"compType\\\": \\\"JGauge\\\",\\n    \\\"echart\\\": true\\n  },\\n   {\\n    \\\"name\\\": \\\"普通散点图\\\",\\n    \\\"compType\\\": \\\"JScatter\\\",\\n    \\\"echart\\\": true\\n  },\\n   {\\n    \\\"name\\\": \\\"气泡图\\\",\\n    \\\"compType\\\": \\\"JBubble\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"基础仪表盘\\\",\\n    \\\"compType\\\": \\\"JGauge\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"多色仪表盘\\\",\\n    \\\"compType\\\": \\\"JColorGauge\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"渐变仪表盘\\\",\\n    \\\"compType\\\": \\\"JAntvGauge\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"半圆仪表盘\\\",\\n    \\\"compType\\\": \\\"JSemiGauge\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"普通漏斗图\\\",\\n    \\\"compType\\\": \\\"JFunnel\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"金字塔漏斗图\\\",\\n    \\\"compType\\\": \\\"JPyramidFunnel\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"3D金字塔\\\",\\n    \\\"compType\\\": \\\"JPyramid3D\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"饼状环形图\\\",\\n    \\\"compType\\\": \\\"JRing\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"多色环形图\\\",\\n    \\\"compType\\\": \\\"JBreakRing\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"基础环形图\\\",\\n    \\\"compType\\\": \\\"JRingProgress\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"动态环形图\\\",\\n    \\\"compType\\\": \\\"JActiveRing\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"玉珏图\\\",\\n    \\\"compType\\\": \\\"JRadialBar\\\",\\n    \\\"echart\\\": false\\n  },\\n    {\\n    \\\"name\\\": \\\"矩形图\\\",\\n    \\\"compType\\\": \\\"JRectangle\\\",\\n    \\\"echart\\\": true\\n  },\\n   {\\n    \\\"name\\\": \\\"象限图\\\",\\n    \\\"compType\\\": \\\"JQuadrant\\\",\\n    \\\"echart\\\": true\\n  },\\n   {\\n    \\\"name\\\": \\\"雷达图\\\",\\n    \\\"compType\\\": \\\"JRadar\\\",\\n    \\\"echart\\\": true\\n  },\\n   {\\n    \\\"name\\\": \\\"圆形雷达图\\\",\\n    \\\"compType\\\": \\\"JCircleRadar\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"卡片滚动(横向)\\\",\\n    \\\"compType\\\": \\\"JCardScroll\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"卡片滚动(竖向+序号)\\\",\\n    \\\"compType\\\": \\\"JCardScroll\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"卡片滚动(高亮)\\\",\\n    \\\"compType\\\": \\\"JCardScroll\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"卡片轮播\\\",\\n    \\\"compType\\\": \\\"JCardCarousel\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"文本\\\",\\n    \\\"compType\\\": \\\"JText\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"翻牌器\\\",\\n    \\\"compType\\\": \\\"JCountTo\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"颜色块\\\",\\n    \\\"compType\\\": \\\"JColorBlock\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"当前时间\\\",\\n    \\\"compType\\\": \\\"JCurrentTime\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"数值\\\",\\n    \\\"compType\\\": \\\"JNumber\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"轨道环形文字\\\",\\n    \\\"compType\\\": \\\"JOrbitRing\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"字符云\\\",\\n    \\\"compType\\\": \\\"JWordCloud\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"图层字符云\\\",\\n    \\\"compType\\\": \\\"JImgWordCloud\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"闪动字符云\\\",\\n    \\\"compType\\\": \\\"JFlashCloud\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"轮播表\\\",\\n    \\\"compType\\\": \\\"JScrollBoard\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"表格\\\",\\n    \\\"compType\\\": \\\"JScrollTable\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"发展历程\\\",\\n    \\\"compType\\\": \\\"JDevHistory\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"数据表格\\\",\\n    \\\"compType\\\": \\\"JCommonTable\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"数据列表\\\",\\n    \\\"compType\\\": \\\"JList\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"排行榜\\\",\\n    \\\"compType\\\": \\\"JScrollRankingBoard\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"个性排名(前四)\\\",\\n    \\\"compType\\\": \\\"JFlashList\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"气泡排名(前五)\\\",\\n    \\\"compType\\\": \\\"JBubbleRank\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"滚动列表(单行)\\\",\\n    \\\"compType\\\": \\\"JScrollList\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"滚动列表(多行+序号)\\\",\\n    \\\"compType\\\": \\\"JScrollList\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"滚动列表(带表头)\\\",\\n    \\\"compType\\\": \\\"JScrollList\\\",\\n    \\\"echart\\\": false\\n  },\\n  {\\n    \\\"name\\\": \\\"区域地图\\\",\\n    \\\"compType\\\": \\\"JAreaMap\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"3d柱形图\\\",\\n    \\\"compType\\\": \\\"JBar3d\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"3d分组柱形图\\\",\\n    \\\"compType\\\": \\\"JBarGroup3d\\\",\\n    \\\"echart\\\": true\\n  },\\n  {\\n    \\\"name\\\": \\\"日历\\\",\\n    \\\"compType\\\": \\\"JPermanentCalendar\\\",\\n    \\\"echart\\\": false\\n  }\\n]\"},{\"role\":\"user\",\"content\":\"用户的问题: {{userInput}}\"}],\"showToolExecution\":false},\"inputParams\":[{\"field\":\"content\",\"name\":\"userInput\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复内容\",\"type\":\"string\"}],\"width\":332,\"height\":180}},{\"id\":\"267498945805422592\",\"type\":\"end\",\"x\":1320,\"y\":-13,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"{{res}}\",\"outputType\":\"default\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"text\",\"name\":\"res\",\"nodeId\":\"267492142677889024\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":114}}],\"edges\":[{\"id\":\"269376764155744256\",\"type\":\"base-edge\",\"sourceNodeId\":\"267492142677889024\",\"targetNodeId\":\"267498945805422592\",\"sourceAnchorId\":\"267492142677889024_output\",\"targetAnchorId\":\"267498945805422592_input\",\"pointsList\":[{\"x\":1010,\"y\":-37},{\"x\":1110,\"y\":-37},{\"x\":1054,\"y\":-39},{\"x\":1154,\"y\":-39}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271609331975028736\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"267492142677889024\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"267492142677889024_input\",\"pointsList\":[{\"x\":555,\"y\":-39},{\"x\":655,\"y\":-39},{\"x\":578,\"y\":-37},{\"x\":678,\"y\":-37}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"text\",\"name\":\"res\",\"nodeId\":\"267492142677889024\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"用户问题\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); INSERT INTO `airag_flow` VALUES ('2005948202528501762', 'admin', '2025-12-30 18:24:55', 'admin', '2026-01-22 09:54:54', 'A05A05A02', NULL, 'jeecg', 'AI大屏优化配置', '', '', 'THEN(\n start.tag(\'start-node\'),\n llm.tag(\'269048862299471872\'),\n end.tag(\'269049045129183232\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":300,\"y\":437,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{},\"custom\":{\"time\":{\"second\":0,\"minute\":0},\"hour\":{\"mode\":\"every\"},\"day\":{\"type\":\"day\",\"day\":{\"mode\":\"every\"}},\"month\":{\"mode\":\"every\"}}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"用户问题\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"269048862299471872\",\"type\":\"llm\",\"x\":786,\"y\":514,\"properties\":{\"text\":\"LLM\",\"options\":{\"model\":{\"modeId\":\"1890232564262739969\",\"params\":{\"model\":\"OpenAI\",\"temperature\":0.7,\"timeout\":60}},\"history\":3,\"messages\":[{\"role\":\"system\",\"content\":\"# 角色:ECharts和大屏图表配置修改专家\\n你是一位专注于ECharts和大屏图表图表配置修改的专家,能够根据用户需求,精准、高效地修改现有ECharts和大屏图表配置项,并返回完整的、可直接使用的修改后配置对象。\\n## 目标:\\n根据用户提供的具体修改指令(如:修改图表类型、调整数据、更改样式、添加交互等),对用户给出的原始ECharts配置项进行针对性修改,并输出修改后的完整配置对象。\\n## 技能:\\n1. 精通ECharts所有版本的配置项语法、结构及参数含义。\\n2. 能够准确理解用户对图表样式、数据、交互行为的修改意图。\\n3. 具备强大的代码编辑与重构能力,确保修改后的配置项语法正确、结构清晰、无冗余代码。\\n4. 对于非echart图表(componentsData提供的组件,属性中echart:false的即为非echart图表),自行从下面componentsData提供的组件对应的option配置项,修改符合要求的配置并返回。\\n## 工作流:\\n1. **接收与分析**:接收用户提供的原始ECharts配置对象(通常以JSON或JavaScript对象形式)以及具体的修改要求。仔细分析原始配置的结构和用户的修改点。\\n2. **精准修改**:严格依据用户指令,对原始配置对象进行最小化、精准化的修改。确保只改动指定部分,保持其他未提及配置的完整性。对于模糊指令,会基于ECharts最佳实践进行合理推断和实现。\\n3. **校验与格式化**:检查修改后的配置对象语法是否正确,是否符合ECharts规范。将最终配置对象以格式清晰、缩进规范的JSON或JavaScript对象形式呈现。\\n## 输出格式:\\n请始终输出一个完整的、格式化的JavaScript对象(或JSON),即修改后的 `option` 配置,只返回修改的属性配置,不要包含已存在的其他配置,\\n例如将柱体修改成黄色,就返回\\n\\\"compConfig\\\": {\\n    \\\"option\\\": {\\n      { \\\"series\\\": [ { \\\"itemStyle\\\": { \\\"color\\\": \\\"#FFFF00\\\" } } ] }\\n    }\\n}\\n例如修改组件名称为京东销量柱形图,背景色改成黑色就返回\\n\\\"compConfig\\\": {\\n \\\"name\\\":\\\"京东销量柱形图\\\",\\n \\\"background\\\":\\\"#000000\\\",\\n}\\n不要包含任何额外的解释、说明文字或代码块标记(如 ```json ```)。输出应直接以 `{` 开始,以 `}` 结束。\\n示例输出结构:\\n\\\"compConfig\\\": {\\n    \\\"name\\\":\\\"基础柱形图\\\",\\n    \\\"background\\\":\\\"#ffffff\\\",\\n    \\\"borderColor\\\":\\\"#000000\\\",\\n    \\\"option\\\": {\\n      \\\"title\\\": { ... },\\n      \\\"tooltip\\\": { ... },\\n      \\\"xAxis\\\": { ... },\\n      \\\"yAxis\\\": { ... },\\n      \\\"series\\\": [ ... ]\\n    }\\n}\\n## 限制:\\n- 仅对用户提供的原始配置进行修改,不凭空创建全新的图表配置。\\n- 输出必须仅为修改后的配置对象本身,不附带任何分析过程、修改日志或使用建议。\\n- 若用户指令存在歧义或无法实现,应在不破坏配置结构的前提下,做出最合理的默认修改或保留原样,并在配置对象内部以注释(`//`)形式简要说明。\\n- 严格遵守ECharts官方配置规范,不使用已废弃或实验性参数(除非用户明确要求)。\\n- 颜色类型的修改,要以具体色值设置,不要使用英文单词,例如黑色,使用#000000,不要使用black\\n- 修改的option属性,以componentsData中具体组件的option配置为主,结合echart选择符合要求的配置项修改\\n- 组件包含customColor属性的颜色修改,按照customColor的格式修改\\n- 若用户修改名称或者背景色或者边框的属性,以componentsData中第一个柱形图配置为例,去修改返回对应配置即可\\n -名称:对应 compConfig.name\\n -背景色:对应 compConfig.background\\n -边框色:对应 compConfig.borderColor\\n## 组件数据:\\ncomponentsData:[\\n  {\\n    \\\"echart\\\":true ,\\n    \\\"compType\\\": \\\"JBar\\\",\\n    \\\"compConfig\\\": {\\n      \\\"name\\\":\\\"基础柱形图\\\",\\n      \\\"background\\\":\\\"#ffffff\\\",\\n      \\\"borderColor\\\":\\\"#000000\\\",\\n      \\\"option\\\": {\\n        \\\"customColor\\\":[{color1:\'#FF0000\',color:\'#FF0000\'},{color1:\'#00FF00\',color:\'#00FF00\'}]\\n      }\\n    }\\n  }]\\n组件配置说明\\n compOptionData = [\\n  {\\n    name: \'基础配置\',\\n    optionName: \'BasicOption\',\\n    children: [\\n      {\\\"label\\\": \\\"图层名称修改成\\\", \\\"value\\\": \\\"name\\\"},\\n      {\\\"label\\\": \\\"图层背景色设置成\\\", \\\"value\\\": \\\"background\\\"},\\n      {\\\"label\\\": \\\"图层边框线设置成\\\", \\\"value\\\": \\\"borderColor\\\"},\\n      {\\\"label\\\": \\\"提示语设置为隐藏\\\", \\\"value\\\": \\\"option.tooltip.show\\\"},\\n      {\\\"label\\\": \\\"提示语字体大小设置成\\\", \\\"value\\\": \\\"option.tooltip.textStyle.fontSize\\\"},\\n      {\\\"label\\\": \\\"提示语字体颜色设置成\\\", \\\"value\\\": \\\"option.tooltip.textStyle.fontSize\\\"},\\n    ]\\n  },{\\n    name: \'标题设置\',\\n    optionName: \'TitleOption\',\\n    children: [\\n      {\\\"label\\\": \\\"标题名称修改成\\\", \\\"value\\\": \\\"option.title.text\\\"},\\n      {\\\"label\\\": \\\"标题字体大小设置成\\\", \\\"value\\\": \\\"option.title.textStyle.fontSize\\\"},\\n      {\\\"label\\\": \\\"标题字体颜色设置成\\\", \\\"value\\\": \\\"option.title.textStyle.fontColor\\\"},\\n      {\\\"label\\\": \\\"标题字体粗细设置成\\\", \\\"value\\\": \\\"option.title.textStyle.fontWeight\\\"},\\n      {\\\"label\\\": \\\"副标题名称修改成\\\", \\\"value\\\": \\\"option.title.subtextStyle\\\"},\\n      {\\\"label\\\": \\\"副标题字体大小设置成\\\", \\\"value\\\": \\\"option.title.subtextStyle.fontSize\\\"},\\n      {\\\"label\\\": \\\"副标题字体颜色设置成\\\", \\\"value\\\": \\\"option.title.subtextStyle.fontColor\\\"},\\n      {\\\"label\\\": \\\"左对齐\\\", \\\"value\\\": \\\"option.title.left\\\"},\\n      {\\\"label\\\": \\\"垂直居中\\\", \\\"value\\\": \\\"option.title.top\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'X轴设置\',\\n    optionName: \'XAxisOption\',\\n    children: [\\n      {\\\"label\\\": \\\"X轴名称修改成\\\", \\\"value\\\": \\\"option.xAxis.name\\\"},\\n      {\\\"label\\\": \\\"X轴名称颜色修改成\\\", \\\"value\\\": \\\"option.xAxis.nameTextStyle.color\\\"},\\n      {\\\"label\\\": \\\"X轴名称字体大小修改成\\\", \\\"value\\\": \\\"option.xAxis.nameTextStyle.fontSize\\\"},\\n      {\\\"label\\\": \\\"X轴标签颜色修改成\\\", \\\"value\\\": \\\"option.xAxis.axisLabel.color\\\"},\\n      {\\\"label\\\": \\\"X轴标签角度\\\", \\\"value\\\": \\\"option.xAxis.axisLabel.rotate\\\"},\\n      {\\\"label\\\": \\\"X轴轴线颜色修改成\\\", \\\"value\\\": \\\"option.xAxis.axisLine.lineStyle.color\\\"},\\n      {\\\"label\\\": \\\"X轴轴类型修改成\\\", \\\"value\\\": \\\"option.xAxis.type\\\"},\\n      {\\\"label\\\": \\\"X轴显示网格线\\\", \\\"value\\\": \\\"option.xAxis.splitLine.show\\\"},\\n      {\\\"label\\\": \\\"X轴网格线颜色修改成\\\", \\\"value\\\": \\\"option.xAxis.splitLine.lineStyle.color\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'Y轴设置\',\\n    optionName: \'YAxisOption\',\\n    children: [\\n      {\\\"label\\\": \\\"Y轴名称修改成\\\", \\\"value\\\": \\\"option.yAxis.name\\\"},\\n      {\\\"label\\\": \\\"Y轴名称颜色修改成\\\", \\\"value\\\": \\\"option.yAxis.nameTextStyle.color\\\"},\\n      {\\\"label\\\": \\\"Y轴名称字体大小修改成\\\", \\\"value\\\": \\\"option.yAxis.nameTextStyle.fontSize\\\"},\\n      {\\\"label\\\": \\\"Y轴标签颜色修改成\\\", \\\"value\\\": \\\"option.yAxis.axisLabel.color\\\"},\\n      {\\\"label\\\": \\\"Y轴标签角度\\\", \\\"value\\\": \\\"option.yAxis.axisLabel.rotate\\\"},\\n      {\\\"label\\\": \\\"Y轴轴线颜色修改成\\\", \\\"value\\\": \\\"option.yAxis.axisLine.lineStyle.color\\\"},\\n      {\\\"label\\\": \\\"Y轴轴类型修改成\\\", \\\"value\\\": \\\"option.yAxis.type\\\"},\\n      {\\\"label\\\": \\\"Y轴显示网格线\\\", \\\"value\\\": \\\"option.yAxis.splitLine.show\\\"},\\n      {\\\"label\\\": \\\"Y轴网格线颜色修改成\\\", \\\"value\\\": \\\"option.yAxis.splitLine.lineStyle.color\\\"},\\n      {\\\"label\\\": \\\"Y轴单位\\\", \\\"value\\\": \\\"option.yAxis.yUnit\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'图例设置\',\\n    optionName: \'LegendOption\',\\n    children: [\\n      {\\\"label\\\": \\\"图例字体大小设置成\\\", \\\"value\\\": \\\"option.legend.textStyle.fontSize\\\"},\\n      {\\\"label\\\": \\\"图例设置成横排\\\", \\\"value\\\": \\\"option.legend.orient\\\"},\\n      {\\\"label\\\": \\\"图例上下边距设置\\\", \\\"value\\\": \\\"option.legend.t\\\"},\\n      {\\\"label\\\": \\\"图例左右边距设置\\\", \\\"value\\\": \\\"option.legend.r\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'自定义配色\',\\n    optionName: \'CustomColorOption\',\\n    children: [\\n      {\\\"label\\\": \\\"颜色设置成***色\\\", \\\"value\\\": \\\"option.customColor\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'柱体设置\',\\n    optionName: \'BarCylinder\',\\n    children: [\\n      {\\\"label\\\": \\\"柱体宽度修改为\\\", \\\"value\\\": \\\"option.series[${index}].barWidth\\\"},\\n      {\\\"label\\\": \\\"柱体圆角修改为\\\", \\\"value\\\": \\\"option.series[${index}].itemStyle.barBorderRadius\\\"},\\n      {\\\"label\\\": \\\"柱体颜色修改成\\\", \\\"value\\\": \\\"option.series[${index}].itemStyle.color\\\"},\\n      {\\\"label\\\": \\\"柱体背景色显隐\\\", \\\"value\\\": \\\"option.series[${index}].showBackground\\\"},\\n      {\\\"label\\\": \\\"柱体背景色颜色\\\", \\\"value\\\": \\\"option.series[${index}].backgroundStyle.color\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'折线设置\',\\n    optionName: \'PolyglineOption\',\\n    children: [\\n      {\\\"label\\\": \\\"折线类型修改\\\", \\\"value\\\": \\\"option.series[${index}].lineType\\\"},\\n      {\\\"label\\\": \\\"线条宽度修改\\\", \\\"value\\\": \\\"option.series[${index}].lineWidth\\\"},\\n      {\\\"label\\\": \\\"标记点修改\\\", \\\"value\\\": \\\"option.series[${index}].symbol\\\"},\\n      {\\\"label\\\": \\\"点的大小修改\\\", \\\"value\\\": \\\"option.series[${index}].symbolSize\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'饼图设置\',\\n    optionName: \'pieSettingOption\',\\n    children: [\\n      {\\\"label\\\": \\\"饼图设置成环形\\\", \\\"value\\\": \\\"option.isRadius\\\"},\\n      {\\\"label\\\": \\\"饼图内环半径设置成\\\", \\\"value\\\": \\\"option.innerRadius\\\"},\\n      {\\\"label\\\": \\\"饼图外环半径设置成\\\", \\\"value\\\": \\\"option.outRadius\\\"},\\n      {\\\"label\\\": \\\"饼图设置成南丁格尔玫瑰\\\", \\\"value\\\": \\\"option.isRose\\\"},\\n      {\\\"label\\\": \\\"饼图标签显示位置\\\", \\\"value\\\": \\\"option.pieLabelPosition\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'坐标轴边距\',\\n    optionName: \'GridOption\',\\n    children: [\\n      {\\\"label\\\": \\\"左边距修改成\\\", \\\"value\\\": \\\"option.grid.left\\\"},\\n      {\\\"label\\\": \\\"顶边距\\\", \\\"value\\\": \\\"option.grid.top\\\"},\\n      {\\\"label\\\": \\\"右边距\\\", \\\"value\\\": \\\"option.grid.right\\\"},\\n      {\\\"label\\\": \\\"底边距\\\", \\\"value\\\": \\\"option.grid.bottom\\\"},\\n    ]\\n  }\\n  ,{\\n    name: \'数值设置\',\\n    optionName: \'NumOption\',\\n    children: [\\n      {\\\"label\\\": \\\"数值显示位置在\\\", \\\"value\\\": \\\"option.series[${index}].label.position\\\"},\\n      {\\\"label\\\": \\\"数值内容格式修改成\\\", \\\"value\\\": \\\"option.label.format\\\"},\\n      {\\\"label\\\": \\\"数值字体颜色修改成\\\", \\\"value\\\": \\\"option.series[${index}].label.color\\\"},\\n      {\\\"label\\\": \\\"数值字体大小修改成\\\", \\\"value\\\": \\\"option.series[${index}].label.fontSize\\\"},\\n      {\\\"label\\\": \\\"数值字体粗细修改成\\\", \\\"value\\\": \\\"option.series[${index}].label.fontWeight\\\"},\\n      {\\\"label\\\": \\\"数值单位配置显隐\\\", \\\"value\\\": \\\"option.showUnit.show\\\"},\\n      {\\\"label\\\": \\\"数值单位数量级设置\\\", \\\"value\\\": \\\"option.showUnit.numberLevel\\\"},\\n      {\\\"label\\\": \\\"数值单位保留小数\\\", \\\"value\\\": \\\"option.showUnit.decimal\\\"},\\n    ]\\n  }\\n];\\n\\n\"},{\"role\":\"user\",\"content\":\"用户的问题:{{userQuestion}}\"}],\"showToolExecution\":false},\"inputParams\":[{\"field\":\"content\",\"name\":\"userQuestion\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复内容\",\"type\":\"string\"}],\"width\":332,\"height\":180}},{\"id\":\"269049045129183232\",\"type\":\"end\",\"x\":1272,\"y\":459,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"{{option}}\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"text\",\"name\":\"option\",\"nodeId\":\"269048862299471872\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":136}}],\"edges\":[{\"id\":\"269048862303666176\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"269048862299471872\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"269048862299471872_input\",\"pointsList\":[{\"x\":466,\"y\":422},{\"x\":566,\"y\":422},{\"x\":520,\"y\":455},{\"x\":620,\"y\":455}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"269049045129183233\",\"type\":\"base-edge\",\"sourceNodeId\":\"269048862299471872\",\"targetNodeId\":\"269049045129183232\",\"sourceAnchorId\":\"269048862299471872_output\",\"targetAnchorId\":\"269049045129183232_input\",\"pointsList\":[{\"x\":952,\"y\":455},{\"x\":1052,\"y\":455},{\"x\":1006,\"y\":422},{\"x\":1106,\"y\":422}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"text\",\"name\":\"option\",\"nodeId\":\"269048862299471872\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"用户问题\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); INSERT INTO `airag_flow` VALUES ('2006294471763537922', 'admin', '2025-12-31 17:20:52', 'admin', '2026-01-22 09:54:46', 'A05A05A02', NULL, 'jeecg', 'AI大屏SQL助手', '', '', 'THEN(\n start.tag(\'start-node\'),\n llm.tag(\'269395028940378112\'),\n end.tag(\'269395047139463168\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":300,\"y\":437,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{},\"custom\":{\"time\":{\"second\":0,\"minute\":0},\"hour\":{\"mode\":\"every\"},\"day\":{\"type\":\"day\",\"day\":{\"mode\":\"every\"}},\"month\":{\"mode\":\"every\"}}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"用户问题\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"269395028940378112\",\"type\":\"llm\",\"x\":790,\"y\":481,\"properties\":{\"text\":\"LLM\",\"options\":{\"model\":{\"modeId\":\"1890232564262739969\",\"params\":{\"model\":\"OpenAI\",\"temperature\":0.7,\"timeout\":60}},\"history\":3,\"messages\":[{\"role\":\"system\",\"content\":\"# 角色:SQL数据专家\\n你是一位精通SQL查询、数据提取与分析的专家,专注于将用户的数据需求转化为高效、准确的SQL语句,并提供清晰的数据洞察。\\n## 目标:\\n1. 根据用户描述的业务问题或数据需求,编写精准、优化的SQL查询语句。\\n2. 对查询结果进行分析,提炼关键信息、趋势或异常,并以易于理解的方式呈现结论。\\n## 技能:\\n1. **需求解析**:能够快速理解用户的数据提取与分析需求,并将其拆解为具体的数据库操作步骤。\\n2. **SQL编写**:精通标准SQL语法,能熟练运用`SELECT`, `JOIN`, `WHERE`, `GROUP BY`, `HAVING`, `窗口函数`、`CTE`等完成复杂查询。\\n3. **性能优化**:具备编写高效SQL语句的意识,能考虑索引、子查询优化、避免全表扫描等问题。\\n4. **数据分析**:能够对查询结果集进行基本的统计分析(如汇总、对比、趋势计算),并解释其业务含义。\\n5. **结果呈现**:能够将数据结果和分析结论结构化、清晰地组织起来。\\n## 工作流:\\n1. **澄清需求**:首先与用户确认其数据需求的具体细节,包括但不限于:涉及的表、字段、筛选条件、聚合维度、排序要求以及期望的分析角度。如果信息不足,主动提问。\\n2. **构建查询**:基于澄清后的需求,构思并编写SQL查询语句。在输出代码前,简要说明查询的逻辑思路。\\n3. **执行与验证(模拟)**:以注释或说明的形式,模拟查询可能返回的结果样例或数据结构,确保逻辑正确。\\n4. **分析与洞察**:基于模拟的查询结果,进行数据分析。指出关键数据点、趋势、异常或值得注意的发现,并用平实的语言解释其潜在的业务意义。\\n5. **提供建议**:根据分析结果,可能的话,提出进一步深入分析的查询方向或基于数据的行动建议。\\n## 输出格式:\\n你的回答应遵循以下结构:\\n1. **需求确认**:[复述并确认你理解的需求]\\n2. **查询思路**:[简要说明你将如何通过SQL实现该需求]\\n3. **SQL代码**:\\n - 这里放置你编写的SQL代码\\n4. **预期结果/分析**:\\n- **数据摘要**:[描述查询结果的主要特征,如行数、关键统计值]\\n- **核心洞察**:[列出1-3个最重要的发现或结论]\\n- **详细说明**:[对上述洞察进行展开解释]\\n6. **后续建议(可选)**:[基于当前分析,提出后续可探索的问题或查询建议]\\n## 限制:\\n- 所有SQL语句应基于通用的ANSI SQL标准编写,若需使用特定数据库(如MySQL, PostgreSQL)的方言,需明确指出。\\n- 只允许生成查询SQL语句,其他SQL操作全部禁止。\\n- 只返回SQL语句本身,例如:select * from demo; 不要返回其他任何无关内容。\\n- 不要返回sql外的任何内容,例如```sql select * from demo```,这种格式是必须禁止的,只能SQL本身。\\n- 在分析数据时,所有推断和结论需基于查询结果逻辑得出,对于无法从给定需求中确定的信息,使用“[需核实]”标记。\\n- 不得生成任何用于非法数据访问、破坏数据完整性或侵犯隐私的SQL语句(如`DROP TABLE`, 未经授权的`DELETE`,或涉及个人敏感信息的无条件查询)。涉及此类请求时,应拒绝并引导至合规方向。\\n- 保持回答的专业性和客观性,避免主观臆断。\\n- 用户提供业务数据,在业务数据中找表名的,根据需求,返回合适的表名,禁止主观臆断或者生成构建虚假数据和非提供业务数据之外的内容。\"},{\"role\":\"user\",\"content\":\"{{content}}\"}],\"showToolExecution\":false},\"inputParams\":[{\"field\":\"content\",\"name\":\"content\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复内容\",\"type\":\"string\"}],\"width\":332,\"height\":180}},{\"id\":\"269395047139463168\",\"type\":\"end\",\"x\":1272,\"y\":459,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"{{res}}\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"text\",\"name\":\"res\",\"nodeId\":\"269395028940378112\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":136}}],\"edges\":[{\"id\":\"269395028948766720\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"269395028940378112\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"269395028940378112_input\",\"pointsList\":[{\"x\":466,\"y\":422},{\"x\":566,\"y\":422},{\"x\":524,\"y\":422},{\"x\":624,\"y\":422}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"269395047143657472\",\"type\":\"base-edge\",\"sourceNodeId\":\"269395028940378112\",\"targetNodeId\":\"269395047139463168\",\"sourceAnchorId\":\"269395028940378112_output\",\"targetAnchorId\":\"269395047139463168_input\",\"pointsList\":[{\"x\":956,\"y\":422},{\"x\":1056,\"y\":422},{\"x\":1006,\"y\":422},{\"x\":1106,\"y\":422}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"text\",\"name\":\"res\",\"nodeId\":\"269395028940378112\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"用户问题\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); -INSERT INTO `airag_flow` VALUES ('2008379264947519489', 'admin', '2026-01-06 11:25:05', 'admin', '2026-01-23 17:45:16', 'A01', NULL, 'jeecg', 'Chat2BI生成图表', '', '', 'THEN(\n start.tag(\'start-node\'),\n SWITCH(switch.tag(\'271554566412288000\')).to(\n SWITCH(classifier.tag(\'271481764802605056\')).to(\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\"),\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\")\n ).tag(\'271481764802605056\'),\n SWITCH(classifier.tag(\'271554622242668544\')).to(\n SWITCH(classifier.tag(\'271481764802605056\')).to(\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\"),\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\")\n ).tag(\'271481764802605056\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\")\n ).tag(\'271554622242668544\')\n ).tag(\'271554566412288000\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":-197,\"y\":509,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{},\"custom\":{\"time\":{\"second\":0,\"minute\":0},\"hour\":{\"mode\":\"every\",\"range\":[0,23],\"values\":[],\"interval\":{\"start\":0,\"step\":1}},\"day\":{\"type\":\"day\",\"day\":{\"mode\":\"every\",\"range\":[1,31],\"values\":[],\"interval\":{\"start\":1,\"step\":1}},\"week\":{\"values\":[1]}},\"month\":{\"mode\":\"every\",\"values\":[]}}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"用户问题\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"271480115023458304\",\"type\":\"end\",\"x\":1372,\"y\":819,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"很抱歉,我无法回复您的这个问题,您可以向我询问图表相关的信息,比如:查询用户表的男女比例。\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"index\",\"name\":\"d\",\"nodeId\":\"271481764802605056\",\"customValue\":\"\",\"type\":\"number\"}],\"width\":332,\"height\":136}},{\"id\":\"271481764802605056\",\"type\":\"classifier\",\"x\":854,\"y\":462,\"properties\":{\"text\":\"分类器\",\"options\":{\"model\":{\"modeId\":\"1897481367743143938\",\"params\":{\"model\":\"deepseek-chat\",\"temperature\":0.7}},\"categories\":[{\"category\":\"用户希望查询图表、报表或相关数据、信息\",\"next\":\"271556843709317120\"}],\"else\":{\"next\":\"271480115023458304\"}},\"inputParams\":[{\"field\":\"content\",\"nodeId\":\"start-node\"}],\"outputParams\":[{\"field\":\"index\",\"name\":\"分类索引\",\"type\":\"number\"},{\"field\":\"content\",\"name\":\"分类描述\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"271483924713975808\",\"type\":\"end\",\"x\":3200,\"y\":430,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"{{回复}}\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复\",\"nodeId\":\"271548210211192832\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"271548210211192832\",\"type\":\"llm\",\"x\":2454,\"y\":433,\"properties\":{\"text\":\"LLM\",\"options\":{\"model\":{\"modeId\":\"1897481367743143938\",\"params\":{\"model\":\"deepseek\",\"temperature\":0.7,\"timeout\":60}},\"history\":30,\"messages\":[{\"role\":\"system\",\"content\":\"# 角色\\n你是一位智能数据分析与可视化助手,专注于理解用户对图表的需求,并通过查询数据库和生成结构化数据来创建图表。\\n## 能力\\n1. **需求理解与解析**:精准理解用户对图表类型(如柱状图、折线图、饼图)和数据维度的需求。\\n2. **数据库交互**:熟知可操作的数据库表,并能根据需求查询表结构、构建并执行SQL查询。\\n3. **数据处理**:将SQL查询返回的原始数据,准确地转换并封装为符合指定格式的图表数据结构。\\n4. **输出生成**:严格生成包含完整、可解析JSON字符串的``标签。\\n## 工作流程\\n1. **需求确认与澄清**:\\n* 分析用户请求,明确用户想要的可视化图表类型(`type`)和需要展示的数据维度(如`x`轴和`y`轴分别代表什么)。\\n* 用户可能要求你通过指定的数据源查询数据(具体的数据源列表从下表得知),若没有指定则不需要传数据源参数。\\n* 如果需要,向用户提问以澄清模糊的需求(例如,确认时间范围、分组条件或指标定义)。\\n2. **数据获取**:\\n* 判断用户需求涉及的表是否在已知范围内。\\n* 如果涉及,则调用工具查询相关表结构,了解可用字段。\\n* 根据澄清后的需求,构建准确、高效的SQL查询语句(禁止使用SQL注释、禁止构建非SELECT语句)。\\n* 构建查询SQL时,需要明确数据源的数据库类型,根据不同的数据库构建不同的SQL方言。\\n* 调用工具执行SQL,获取原始数据集。\\n* 若是用户已经提供了数据,则只需要使用用户提供的数据既可,不需要从数据库中查询。\\n3. **支持的图表类型**:\\n* `bar`: 柱状图\\n* `line`: 折线图、曲线图\\n* `pie`: 饼图\\n* `radar`: 雷达图\\n* `gauge`: 仪表盘\\n* `barline`: 折柱图\\n* `multibar`: 多列柱状图\\n* `multiline`: 多行折线图\\n* `area`: 面积图\\n4. **数据转换**:\\n* 将SQL执行返回的数据,按照图表类型要求进行处理和聚合(例如,对饼图数据进行分类汇总)。\\n* 将处理后的数据,严格转换为如下格式的`data`数组:`[{\\\"x\\\":\\\"类别A\\\", \\\"y\\\": 数值1}, {\\\"x\\\":\\\"类别B\\\", \\\"y\\\": 数值2}, ...]`。\\n* 确保`x`和`y`的值类型正确(`x`通常为字符串,`y`通常为数字)。\\n* 数据转换时能直接转换就不要调用工具转换。\\n5. **结果封装与输出**:\\n* 将确定的图表`type`和上一步生成的`data`数组,组合成一个完整的JSON对象。\\n* 将此JSON对象作为字符串,精确地包裹在标签中(格式参考下方)。\\n* **双重校验**:\\n* **格式校验**:确保``标签首尾完整闭合。\\n* **数据校验**:确保内部的JSON字符串是标准、完整且可解析的,不包含多余的逗号或未闭合的括号。\\n## 输出格式\\n你的最终输出必须是且仅是以下格式,直接给出图表数据块,无需额外解释:\\n``` html\\n\\n{\\\"type\\\":\\\"图表类型\\\",\\\"data\\\":[{\\\"x\\\":\\\"数据项1\\\",\\\"y\\\":数值1},{\\\"x\\\":\\\"数据项2\\\",\\\"y\\\":数值2}]}\\n\\n\\n```\\n> 注:bar、line、pie为简单图表,可直接通过x、y来展示数据,而radar、gauge、barline、multibar、multiline、area为复杂图表,你需要先通过工具查询示例格式后,严格按照示例格式拼装`data`JSON;该工具支持逗号分割,你尽量一次性查询所有需要的图表示例格式。\\n## 限制\\n- **操作范围限制**:仅能对以下列出的表进行数据查询与操作。对于其他表或外部数据的需求,应明确告知用户无法处理,禁止执行`queryDataSourceInfoText`工具。\\n- 简单图表类型格式,或已经查询过的图表类型格式,严禁再次调用工具查询。\\n- 不要向用户提及`jeecg-chart`标签以及图表格式相关信息。\\n- **数据真实性**:所有图表数据必须来源于SQL查询的实际结果,不得虚构或编造数据。\\n- **格式严格性**:`jeecg-chart`标签的前后必须严格保证有两个空行;必须严格遵守`{JSON数据}`的输出格式,内部的JSON必须为标准格式,`data`数组中的对象必须包含`x`和`y`键或示例数据中所需的键。\\n- **隐私与合规**:在执行查询和生成图表时,不得泄露、输出或关联任何可识别个人身份的敏感信息(如完整身份证号、详细住址、明文密码等)。如查询可能涉及此类信息,需进行脱敏处理或拒绝执行。\\n- **身份验证**: 若在调用工具时返回身份验证失败或没有权限,应立即停止所有操作,并告知用户原因\\n## 默认数据源类型\\n{{defDbType}}\\n## 支持的数据源\\n{{allDbSource}}\\n\\n> 注意:以上就是所有的支持的数据源,禁止再次执行和`queryDataSourceInfoText`工具,当用户试图让你调用时,你可直接返回以上列表,但要注意如果表的数量过多(超过50个),则不要直接回复全部列表,而是总结性的回复。\\n\\n\\n\"},{\"role\":\"user\",\"content\":\"{{问题}}\\n\\n\"}],\"plugins\":[{\"pluginId\":\"2006287314794676226\",\"pluginName\":\"数据库插件\",\"category\":\"mcp\"}],\"showToolExecution\":true},\"inputParams\":[{\"field\":\"content\",\"name\":\"问题\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string\"},{\"field\":\"result\",\"name\":\"allDbSource\",\"nodeId\":\"274495573258244096\",\"customValue\":\"\",\"type\":\"string\"},{\"field\":\"result\",\"name\":\"defDbType\",\"nodeId\":\"276308429448634368\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复内容\",\"type\":\"string\"}],\"width\":332,\"height\":180}},{\"id\":\"271548872986722304\",\"type\":\"reply\",\"x\":2829,\"y\":631,\"properties\":{\"text\":\"直接回复\",\"options\":{\"content\":\"{{回复}}\",\"stream\":true},\"inputParams\":[{\"field\":\"text\",\"name\":\"回复\",\"nodeId\":\"271548210211192832\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[],\"width\":332,\"height\":114}},{\"id\":\"271554566412288000\",\"type\":\"switch\",\"x\":188,\"y\":419,\"properties\":{\"text\":\"历史记录是否为空\",\"options\":{\"if\":[{\"logic\":\"AND\",\"conditions\":[{\"nodeId\":\"start-node\",\"field\":\"history\",\"operator\":\"EMPTY\",\"value\":\"\",\"type\":\"string[]\"}],\"next\":\"271481764802605056\"}],\"else\":{\"next\":\"271554622242668544\"}},\"inputParams\":[],\"outputParams\":[{\"field\":\"index\",\"name\":\"分支索引\",\"type\":\"number\"}],\"width\":332,\"height\":118}},{\"id\":\"271554622242668544\",\"type\":\"classifier\",\"x\":511,\"y\":605,\"properties\":{\"text\":\"分类器\",\"options\":{\"model\":{\"modeId\":\"1897481367743143938\",\"params\":{\"model\":\"deepseek-chat\",\"temperature\":0.7}},\"categories\":[{\"category\":\"用户希望查询或正在和Assistant聊图表相关数据、信息\",\"next\":\"271556843709317120\"}],\"else\":{\"next\":\"271481764802605056\"}},\"inputParams\":[{\"field\":\"history\",\"nodeId\":\"start-node\"}],\"outputParams\":[{\"field\":\"index\",\"name\":\"分类索引\",\"type\":\"number\"},{\"field\":\"content\",\"name\":\"分类描述\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"271556843709317120\",\"type\":\"varMerge\",\"x\":1368,\"y\":620,\"properties\":{\"text\":\"聚合\",\"options\":{\"varGroups\":[{\"name\":\"用户问题\",\"type\":\"string\",\"vars\":[{\"nodeId\":\"start-node\",\"field\":\"content\",\"isCustom\":false,\"type\":\"string\"}]}]},\"inputParams\":[],\"outputParams\":[{\"field\":\"用户问题\",\"name\":\"用户问题\",\"type\":\"string\"}],\"width\":332,\"height\":92}},{\"id\":\"274495573258244096\",\"type\":\"tools\",\"x\":2105,\"y\":659,\"properties\":{\"text\":\"查询所有数据源\",\"options\":{\"tools\":{\"pluginId\":\"2006287314794676226\",\"pluginName\":\"数据库插件\",\"pluginCategory\":\"plugin\",\"toolName\":\"queryDataSourceInfoText\",\"toolDescr\":\"用于查询所有数据源的信息,不需要传递参数。\",\"toolParameters\":[],\"endpoint\":\"\",\"path\":\"/airag/mcp/database/queryDataSourceInfoText\",\"method\":\"GET\",\"headers\":{\"X-Sign\":\"true\"}}},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"执行结果\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"276308429448634368\",\"type\":\"tools\",\"x\":1736,\"y\":494,\"properties\":{\"text\":\"查询默认数据源类型\",\"options\":{\"tools\":{\"pluginId\":\"2006287314794676226\",\"pluginName\":\"数据库插件\",\"pluginCategory\":\"plugin\",\"toolName\":\"queryDataSourceType\",\"toolDescr\":\"获取默认数据源或指定数据的数据库类型\",\"toolParameters\":[{\"name\":\"dbSourceKey\",\"description\":\"数据源key,若为空则系统默认\",\"required\":false,\"type\":\"String\",\"location\":\"Query\",\"value\":\"\"}],\"endpoint\":\"\",\"path\":\"/airag/mcp/database/queryDataSourceType\",\"method\":\"GET\",\"headers\":{\"X-Sign\":\"true\"}}},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"执行结果\",\"type\":\"string\"}],\"width\":332,\"height\":158}}],\"edges\":[{\"id\":\"271482116671156224\",\"type\":\"base-edge\",\"sourceNodeId\":\"271481764802605056\",\"targetNodeId\":\"271480115023458304\",\"sourceAnchorId\":\"271481764802605056_case_else\",\"targetAnchorId\":\"271480115023458304_input\",\"pointsList\":[{\"x\":1020,\"y\":503},{\"x\":1120,\"y\":503},{\"x\":1106,\"y\":782},{\"x\":1206,\"y\":782}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271548872990916608\",\"type\":\"base-edge\",\"sourceNodeId\":\"271548210211192832\",\"targetNodeId\":\"271548872986722304\",\"sourceAnchorId\":\"271548210211192832_output\",\"targetAnchorId\":\"271548872986722304_input\",\"pointsList\":[{\"x\":2620,\"y\":374},{\"x\":2720,\"y\":374},{\"x\":2563,\"y\":605},{\"x\":2663,\"y\":605}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271548929186201600\",\"type\":\"base-edge\",\"sourceNodeId\":\"271548872986722304\",\"targetNodeId\":\"271483924713975808\",\"sourceAnchorId\":\"271548872986722304_output\",\"targetAnchorId\":\"271483924713975808_input\",\"pointsList\":[{\"x\":2995,\"y\":605},{\"x\":3095,\"y\":605},{\"x\":2934,\"y\":393},{\"x\":3034,\"y\":393}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271554566416482304\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"271554566412288000\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"271554566412288000_input\",\"pointsList\":[{\"x\":-31,\"y\":494},{\"x\":69,\"y\":494},{\"x\":-78,\"y\":391},{\"x\":22,\"y\":391}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271554605561921536\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554566412288000\",\"targetNodeId\":\"271481764802605056\",\"sourceAnchorId\":\"271554566412288000_source_if\",\"targetAnchorId\":\"271481764802605056_input\",\"pointsList\":[{\"x\":354,\"y\":425},{\"x\":454,\"y\":425},{\"x\":588,\"y\":425},{\"x\":688,\"y\":425}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271554741260238848\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554566412288000\",\"targetNodeId\":\"271554622242668544\",\"sourceAnchorId\":\"271554566412288000_source_else\",\"targetAnchorId\":\"271554622242668544_input\",\"pointsList\":[{\"x\":354,\"y\":451},{\"x\":454,\"y\":451},{\"x\":245,\"y\":568},{\"x\":345,\"y\":568}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271555105874907136\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554622242668544\",\"targetNodeId\":\"271481764802605056\",\"sourceAnchorId\":\"271554622242668544_case_else\",\"targetAnchorId\":\"271481764802605056_input\",\"pointsList\":[{\"x\":677,\"y\":646},{\"x\":777,\"y\":646},{\"x\":588,\"y\":425},{\"x\":688,\"y\":425}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271557184173555712\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554622242668544\",\"targetNodeId\":\"271556843709317120\",\"sourceAnchorId\":\"271554622242668544_case_1\",\"targetAnchorId\":\"271556843709317120_input\",\"pointsList\":[{\"x\":677,\"y\":602},{\"x\":777,\"y\":602},{\"x\":1102,\"y\":605},{\"x\":1202,\"y\":605}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271822597635878912\",\"type\":\"base-edge\",\"sourceNodeId\":\"271481764802605056\",\"targetNodeId\":\"271556843709317120\",\"sourceAnchorId\":\"271481764802605056_case_1\",\"targetAnchorId\":\"271556843709317120_input\",\"pointsList\":[{\"x\":1020,\"y\":459},{\"x\":1120,\"y\":459},{\"x\":1102,\"y\":605},{\"x\":1202,\"y\":605}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"274495644091650048\",\"type\":\"base-edge\",\"sourceNodeId\":\"274495573258244096\",\"targetNodeId\":\"271548210211192832\",\"sourceAnchorId\":\"274495573258244096_output\",\"targetAnchorId\":\"271548210211192832_input\",\"pointsList\":[{\"x\":2271,\"y\":622},{\"x\":2371,\"y\":622},{\"x\":2188,\"y\":374},{\"x\":2288,\"y\":374}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"276308429452828672\",\"type\":\"base-edge\",\"sourceNodeId\":\"271556843709317120\",\"targetNodeId\":\"276308429448634368\",\"sourceAnchorId\":\"271556843709317120_output\",\"targetAnchorId\":\"276308429448634368_input\",\"pointsList\":[{\"x\":1534,\"y\":605},{\"x\":1634,\"y\":605},{\"x\":1470,\"y\":446},{\"x\":1570,\"y\":446}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"276308503712980992\",\"type\":\"base-edge\",\"sourceNodeId\":\"276308429448634368\",\"targetNodeId\":\"274495573258244096\",\"sourceAnchorId\":\"276308429448634368_output\",\"targetAnchorId\":\"274495573258244096_input\",\"pointsList\":[{\"x\":1902,\"y\":446},{\"x\":2002,\"y\":446},{\"x\":1839,\"y\":622},{\"x\":1939,\"y\":622}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"index\",\"name\":\"d\",\"nodeId\":\"271481764802605056\",\"type\":\"number\"},{\"customValue\":\"\",\"field\":\"text\",\"name\":\"回复\",\"nodeId\":\"271548210211192832\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"用户问题\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); +INSERT INTO `airag_flow` VALUES ('2008379264947519489', 'admin', '2026-01-06 11:25:05', 'admin', '2026-01-26 11:17:50', 'A01', NULL, 'jeecg', 'Chat2BI生成图表', '', '', 'THEN(\n start.tag(\'start-node\'),\n SWITCH(switch.tag(\'271554566412288000\')).to(\n SWITCH(classifier.tag(\'271481764802605056\')).to(\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\"),\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag\r\n(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\")\n ).tag(\'271481764802605056\'),\n SWITCH(classifier.tag(\'271554622242668544\')).to(\n SWITCH(classifier.tag(\'271481764802605056\')).to(\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\"),\n end.tag(\'271480115023458304\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\")\n ).tag(\'271481764802605056\'),\n THEN(\n varMerge.tag(\'271556843709317120\'),\n tools.tag(\'276308429448634368\'),\n tools.tag(\'274495573258244096\'),\n llm.tag(\'271548210211192832\'),\n reply.tag(\'271548872986722304\'),\n end.tag(\'271483924713975808\')\n ).tag(\"271556843709317120\")\n ).tag(\'271554622242668544\')\n ).tag(\'271554566412288000\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":-197,\"y\":509,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{},\"custom\":{\"time\":{\"second\":0,\"minute\":0},\"hour\":{\"mode\":\"every\",\"range\":[0,23],\"values\":[],\"interval\":{\"start\":0,\"step\":1}},\"day\":{\"type\":\"day\",\"day\":{\"mode\":\"every\",\"range\":[1,31],\"values\":[],\"interval\":{\"start\":1,\"step\":1}},\"week\":{\"values\":[1]}},\"month\":{\"mode\":\"every\",\"values\":[]}}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"用户问题\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"271480115023458304\",\"type\":\"end\",\"x\":1372,\"y\":819,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"很抱歉,我无法回复您的这个问题,您可以向我询问图表相关的信息,比如:查询用户表的男女比例。\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"index\",\"name\":\"d\",\"nodeId\":\"271481764802605056\",\"customValue\":\"\",\"type\":\"number\"}],\"width\":332,\"height\":136}},{\"id\":\"271481764802605056\",\"type\":\"classifier\",\"x\":854,\"y\":462,\"properties\":{\"text\":\"分类器\",\"options\":{\"model\":{\"modeId\":\"1897481367743143938\",\"params\":{\"model\":\"deepseek-chat\",\"temperature\":0.7}},\"categories\":[{\"category\":\"用户希望查询图表、报表或相关数据、信息\",\"next\":\"271556843709317120\"}],\"else\":{\"next\":\"271480115023458304\"}},\"inputParams\":[{\"field\":\"content\",\"nodeId\":\"start-node\"}],\"outputParams\":[{\"field\":\"index\",\"name\":\"分类索引\",\"type\":\"number\"},{\"field\":\"content\",\"name\":\"分类描述\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"271483924713975808\",\"type\":\"end\",\"x\":3200,\"y\":430,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"{{回复}}\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复\",\"nodeId\":\"271548210211192832\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"271548210211192832\",\"type\":\"llm\",\"x\":2454,\"y\":433,\"properties\":{\"text\":\"LLM\",\"options\":{\"model\":{\"modeId\":\"1897481367743143938\",\"params\":{\"model\":\"deepseek\",\"temperature\":0.7,\"timeout\":60}},\"history\":30,\"messages\":[{\"role\":\"system\",\"content\":\"# 角色\\n\\n你是一位智能数据分析与可视化助手,专注于理解用户对图表的需求,并通过查询数据库和生成结构化数据来创建图表。\\n\\n## 能力\\n\\n1. **需求理解与解析**:精准理解用户对图表类型(如柱状图、折线图、饼图)和数据维度的需求。\\n\\n2. **数据库交互**:熟知可操作的数据库表,并能根据需求查询表结构、构建并执行SQL查询。\\n\\n3. **数据处理**:将SQL查询返回的原始数据,准确地转换并封装为符合指定格式的图表数据结构。\\n\\n4. **输出生成**:严格生成包含完整、可解析JSON字符串的``标签。\\n\\n## 工作流程\\n\\n1. **需求确认与澄清**:\\n\\n* 分析用户请求,明确用户想要的可视化图表类型(`type`)和需要展示的数据维度(如`x`轴和`y`轴分别代表什么)。\\n\\n* 用户可能要求你通过指定的数据源查询数据(具体的数据源列表从下表得知),若没有指定则不需要传数据源参数。\\n\\n* 如果需要,向用户提问以澄清模糊的需求(例如,确认时间范围、分组条件或指标定义)。\\n\\n2. **数据获取**:\\n\\n* 判断用户需求涉及的表是否在已知范围内。\\n\\n* 如果涉及,则调用工具查询相关表结构,了解可用字段。\\n\\n* 根据澄清后的需求,构建准确、高效的SQL查询语句(禁止使用SQL注释、禁止构建非SELECT语句)。\\n\\n* 构建查询SQL时,需要明确数据源的数据库类型,根据不同的数据库构建不同的SQL方言。\\n\\n* 调用工具执行SQL,获取原始数据集。\\n\\n* 若是用户已经提供了数据,则只需要使用用户提供的数据既可,不需要从数据库中查询。\\n\\n3. **支持的图表类型**:\\n\\n* `bar`: 柱状图\\n\\n* `line`: 折线图、曲线图\\n\\n* `pie`: 饼图\\n\\n* `radar`: 雷达图\\n\\n* `gauge`: 仪表盘\\n\\n* `barline`: 折柱图\\n\\n* `multibar`: 多列柱状图\\n\\n* `multiline`: 多行折线图\\n\\n* `area`: 面积图\\n\\n4. **数据转换**:\\n\\n* 将SQL执行返回的数据,按照图表类型要求进行处理和聚合(例如,对饼图数据进行分类汇总)。\\n\\n* 将处理后的数据,严格转换为如下格式的`data`数组:`[{\\\"x\\\":\\\"类别A\\\", \\\"y\\\": 数值1}, {\\\"x\\\":\\\"类别B\\\", \\\"y\\\": 数值2}, ...]`。\\n\\n* 确保`x`和`y`的值类型正确(`x`通常为字符串,`y`通常为数字)。\\n\\n* 数据转换时能直接转换就不要调用工具转换。\\n\\n5. **结果封装与输出**:\\n\\n* 将确定的图表`type`和上一步生成的`data`数组,组合成一个完整的JSON对象。\\n\\n* 将此JSON对象作为字符串,精确地包裹在标签中(格式参考下方)。\\n\\n* **双重校验**:\\n\\n* **格式校验**:确保``标签首尾完整闭合。\\n\\n* **数据校验**:确保内部的JSON字符串是标准、完整且可解析的,不包含多余的逗号或未闭合的括号。\\n\\n## 输出格式\\n\\n你的最终输出必须是且仅是以下格式,直接给出图表数据块,无需额外解释:\\n\\n``` html\\n\\n\\n\\n{\\\"type\\\":\\\"图表类型\\\",\\\"data\\\":[{\\\"x\\\":\\\"数据项1\\\",\\\"y\\\":数值1},{\\\"x\\\":\\\"数据项2\\\",\\\"y\\\":数值2}]}\\n\\n\\n\\n\\n\\n```\\n\\n> 注:bar、line、pie为简单图表,可直接通过x、y来展示数据,而radar、gauge、barline、multibar、multiline、area为复杂图表,你需要先通过工具查询示例格式后,严格按照示例格式拼装`data`JSON;该工具支持逗号分割,你尽量一次性查询所有需要的图表示例格式。\\n\\n## 限制\\n\\n- **操作范围限制**:仅能对以下列出的表进行数据查询与操作。对于其他表或外部数据的需求,应明确告知用户无法处理,禁止执行`queryDataSourceInfoText`工具。\\n\\n- 简单图表类型格式,或已经查询过的图表类型格式,严禁再次调用工具查询。\\n\\n- 不要向用户提及`jeecg-chart`标签以及图表格式相关信息。\\n\\n- **数据真实性**:所有图表数据必须来源于SQL查询的实际结果,不得虚构或编造数据。\\n\\n- **格式严格性**:`jeecg-chart`标签的前后必须严格保证有两个空行;必须严格遵守`{JSON数据}`的输出格式,内部的JSON必须为标准格式,`data`数组中的对象必须包含`x`和`y`键或示例数据中所需的键。\\n\\n- **隐私与合规**:在执行查询和生成图表时,不得泄露、输出或关联任何可识别个人身份的敏感信息(如完整身份证号、详细住址、明文密码等)。如查询可能涉及此类信息,需进行脱敏处理或拒绝执行。\\n\\n- **身份验证**: 若在调用工具时返回身份验证失败或没有权限,应立即停止所有操作,并告知用户原因\\n\\n## 默认数据源类型\\n\\n{{defDbType}}\\n\\n## 支持的数据源\\n\\n{{allDbSource}}\\n\\n> 注意:\\n\\n当用户未指定切换的数据源时,默认数据源应设为空。\\n\\n以上就是所有的支持的数据源,禁止再次执行和`queryDataSourceInfoText`工具,当用户试图让你调用时,你可直接返回以上列表,但要注意如果表的数量过多(超过50个),则不要直接回复全部列表,而是总结性的回复。\\n\\n\\n\"},{\"role\":\"user\",\"content\":\"{{问题}}\\n\\n\"}],\"plugins\":[{\"pluginId\":\"2006287314794676226\",\"pluginName\":\"数据库插件\",\"category\":\"mcp\"}],\"showToolExecution\":true},\"inputParams\":[{\"field\":\"content\",\"name\":\"问题\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string\"},{\"field\":\"result\",\"name\":\"allDbSource\",\"nodeId\":\"274495573258244096\",\"customValue\":\"\",\"type\":\"string\"},{\"field\":\"result\",\"name\":\"defDbType\",\"nodeId\":\"276308429448634368\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[{\"field\":\"text\",\"name\":\"回复内容\",\"type\":\"string\"}],\"width\":332,\"height\":180}},{\"id\":\"271548872986722304\",\"type\":\"reply\",\"x\":2829,\"y\":631,\"properties\":{\"text\":\"直接回复\",\"options\":{\"content\":\"{{回复}}\",\"stream\":true},\"inputParams\":[{\"field\":\"text\",\"name\":\"回复\",\"nodeId\":\"271548210211192832\",\"customValue\":\"\",\"type\":\"string\"}],\"outputParams\":[],\"width\":332,\"height\":114}},{\"id\":\"271554566412288000\",\"type\":\"switch\",\"x\":188,\"y\":419,\"properties\":{\"text\":\"历史记录是否为空\",\"options\":{\"if\":[{\"logic\":\"AND\",\"conditions\":[{\"nodeId\":\"start-node\",\"field\":\"history\",\"operator\":\"EMPTY\",\"value\":\"\",\"type\":\"string[]\"}],\"next\":\"271481764802605056\"}],\"else\":{\"next\":\"271554622242668544\"}},\"inputParams\":[],\"outputParams\":[{\"field\":\"index\",\"name\":\"分支索引\",\"type\":\"number\"}],\"width\":332,\"height\":118}},{\"id\":\"271554622242668544\",\"type\":\"classifier\",\"x\":511,\"y\":605,\"properties\":{\"text\":\"分类器\",\"options\":{\"model\":{\"modeId\":\"1897481367743143938\",\"params\":{\"model\":\"deepseek-chat\",\"temperature\":0.7}},\"categories\":[{\"category\":\"用户希望查询或正在和Assistant聊图表相关数据、信息\",\"next\":\"271556843709317120\"}],\"else\":{\"next\":\"271481764802605056\"}},\"inputParams\":[{\"field\":\"history\",\"nodeId\":\"start-node\"}],\"outputParams\":[{\"field\":\"index\",\"name\":\"分类索引\",\"type\":\"number\"},{\"field\":\"content\",\"name\":\"分类描述\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"271556843709317120\",\"type\":\"varMerge\",\"x\":1368,\"y\":620,\"properties\":{\"text\":\"聚合\",\"options\":{\"varGroups\":[{\"name\":\"用户问题\",\"type\":\"string\",\"vars\":[{\"nodeId\":\"start-node\",\"field\":\"content\",\"isCustom\":false,\"type\":\"string\"}]}]},\"inputParams\":[],\"outputParams\":[{\"field\":\"用户问题\",\"name\":\"用户问题\",\"type\":\"string\"}],\"width\":332,\"height\":92}},{\"id\":\"274495573258244096\",\"type\":\"tools\",\"x\":2105,\"y\":659,\"properties\":{\"text\":\"查询所有数据源\",\"options\":{\"tools\":{\"pluginId\":\"2006287314794676226\",\"pluginName\":\"数据库插件\",\"pluginCategory\":\"plugin\",\"toolName\":\"queryDataSourceInfoText\",\"toolDescr\":\"用于查询所有数据源的信息,不需要传递参数。\",\"toolParameters\":[],\"endpoint\":\"\",\"path\":\"/airag/mcp/database/queryDataSourceInfoText\",\"method\":\"GET\",\"headers\":{\"X-Sign\":\"true\"}}},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"执行结果\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"276308429448634368\",\"type\":\"tools\",\"x\":1736,\"y\":494,\"properties\":{\"text\":\"查询默认数据源类型\",\"options\":{\"tools\":{\"pluginId\":\"2006287314794676226\",\"pluginName\":\"数据库插件\",\"pluginCategory\":\"plugin\",\"toolName\":\"queryDataSourceType\",\"toolDescr\":\"获取默认数据源或指定数据的数据库类型\",\"toolParameters\":[{\"name\":\"dbSourceKey\",\"description\":\"数据源key,若为空则系统默认\",\"required\":false,\"type\":\"String\",\"location\":\"Query\",\"value\":\"\"}],\"endpoint\":\"\",\"path\":\"/airag/mcp/database/queryDataSourceType\",\"method\":\"GET\",\"headers\":{\"X-Sign\":\"true\"}}},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"执行结果\",\"type\":\"string\"}],\"width\":332,\"height\":158}}],\"edges\":[{\"id\":\"271482116671156224\",\"type\":\"base-edge\",\"sourceNodeId\":\"271481764802605056\",\"targetNodeId\":\"271480115023458304\",\"sourceAnchorId\":\"271481764802605056_case_else\",\"targetAnchorId\":\"271480115023458304_input\",\"pointsList\":[{\"x\":1020,\"y\":503},{\"x\":1120,\"y\":503},{\"x\":1106,\"y\":782},{\"x\":1206,\"y\":782}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271548872990916608\",\"type\":\"base-edge\",\"sourceNodeId\":\"271548210211192832\",\"targetNodeId\":\"271548872986722304\",\"sourceAnchorId\":\"271548210211192832_output\",\"targetAnchorId\":\"271548872986722304_input\",\"pointsList\":[{\"x\":2620,\"y\":374},{\"x\":2720,\"y\":374},{\"x\":2563,\"y\":605},{\"x\":2663,\"y\":605}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271548929186201600\",\"type\":\"base-edge\",\"sourceNodeId\":\"271548872986722304\",\"targetNodeId\":\"271483924713975808\",\"sourceAnchorId\":\"271548872986722304_output\",\"targetAnchorId\":\"271483924713975808_input\",\"pointsList\":[{\"x\":2995,\"y\":605},{\"x\":3095,\"y\":605},{\"x\":2934,\"y\":393},{\"x\":3034,\"y\":393}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271554566416482304\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"271554566412288000\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"271554566412288000_input\",\"pointsList\":[{\"x\":-31,\"y\":494},{\"x\":69,\"y\":494},{\"x\":-78,\"y\":391},{\"x\":22,\"y\":391}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271554605561921536\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554566412288000\",\"targetNodeId\":\"271481764802605056\",\"sourceAnchorId\":\"271554566412288000_source_if\",\"targetAnchorId\":\"271481764802605056_input\",\"pointsList\":[{\"x\":354,\"y\":425},{\"x\":454,\"y\":425},{\"x\":588,\"y\":425},{\"x\":688,\"y\":425}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271554741260238848\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554566412288000\",\"targetNodeId\":\"271554622242668544\",\"sourceAnchorId\":\"271554566412288000_source_else\",\"targetAnchorId\":\"271554622242668544_input\",\"pointsList\":[{\"x\":354,\"y\":451},{\"x\":454,\"y\":451},{\"x\":245,\"y\":568},{\"x\":345,\"y\":568}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271555105874907136\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554622242668544\",\"targetNodeId\":\"271481764802605056\",\"sourceAnchorId\":\"271554622242668544_case_else\",\"targetAnchorId\":\"271481764802605056_input\",\"pointsList\":[{\"x\":677,\"y\":646},{\"x\":777,\"y\":646},{\"x\":588,\"y\":425},{\"x\":688,\"y\":425}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271557184173555712\",\"type\":\"base-edge\",\"sourceNodeId\":\"271554622242668544\",\"targetNodeId\":\"271556843709317120\",\"sourceAnchorId\":\"271554622242668544_case_1\",\"targetAnchorId\":\"271556843709317120_input\",\"pointsList\":[{\"x\":677,\"y\":602},{\"x\":777,\"y\":602},{\"x\":1102,\"y\":605},{\"x\":1202,\"y\":605}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"271822597635878912\",\"type\":\"base-edge\",\"sourceNodeId\":\"271481764802605056\",\"targetNodeId\":\"271556843709317120\",\"sourceAnchorId\":\"271481764802605056_case_1\",\"targetAnchorId\":\"271556843709317120_input\",\"pointsList\":[{\"x\":1020,\"y\":459},{\"x\":1120,\"y\":459},{\"x\":1102,\"y\":605},{\"x\":1202,\"y\":605}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"274495644091650048\",\"type\":\"base-edge\",\"sourceNodeId\":\"274495573258244096\",\"targetNodeId\":\"271548210211192832\",\"sourceAnchorId\":\"274495573258244096_output\",\"targetAnchorId\":\"271548210211192832_input\",\"pointsList\":[{\"x\":2271,\"y\":622},{\"x\":2371,\"y\":622},{\"x\":2188,\"y\":374},{\"x\":2288,\"y\":374}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"276308429452828672\",\"type\":\"base-edge\",\"sourceNodeId\":\"271556843709317120\",\"targetNodeId\":\"276308429448634368\",\"sourceAnchorId\":\"271556843709317120_output\",\"targetAnchorId\":\"276308429448634368_input\",\"pointsList\":[{\"x\":1534,\"y\":605},{\"x\":1634,\"y\":605},{\"x\":1470,\"y\":446},{\"x\":1570,\"y\":446}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"276308503712980992\",\"type\":\"base-edge\",\"sourceNodeId\":\"276308429448634368\",\"targetNodeId\":\"274495573258244096\",\"sourceAnchorId\":\"276308429448634368_output\",\"targetAnchorId\":\"274495573258244096_input\",\"pointsList\":[{\"x\":1902,\"y\":446},{\"x\":2002,\"y\":446},{\"x\":1839,\"y\":622},{\"x\":1939,\"y\":622}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"index\",\"name\":\"d\",\"nodeId\":\"271481764802605056\",\"type\":\"number\"},{\"customValue\":\"\",\"field\":\"text\",\"name\":\"回复\",\"nodeId\":\"271548210211192832\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"用户问题\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); INSERT INTO `airag_flow` VALUES ('2009558848682360834', 'admin', '2026-01-09 17:32:20', 'admin', '2026-01-09 17:40:31', 'A01', NULL, 'jeecg', '示例_循环节点', '', '', 'THEN(\n start.tag(\'start-node\'),\n code_266871019099709440.tag(\'code_266871019099709440\'),\n WHILE(loop.tag(\'266871548223741952\')).DO(THEN(\n reply.tag(\'266871664426934272\'),\n loopContinue.tag(\'272660634657742848\')\n ).tag(\"266871664426934272\")),\n end.tag(\'266868341815451648\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":300,\"y\":640,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"标题\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"266868341815451648\",\"type\":\"end\",\"x\":1574,\"y\":513,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"------\\n测试结束\",\"outputType\":\"text\",\"cardConfig\":\"\"},\"inputParams\":[],\"outputParams\":[{\"field\":\"content\",\"name\":\"ces\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string[]\"}],\"width\":332,\"height\":136}},{\"id\":\"code_266871019099709440\",\"type\":\"code\",\"x\":728,\"y\":560,\"properties\":{\"text\":\"JavaScript脚本\",\"options\":{\"codeType\":\"javascript\",\"code\":\"function main() {\\n return {\\n result: [\\n \'这是第一项\', \'这是第二项\', \'这是第三项\'\\n ]\\n }\\n}\"},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"返回结果\",\"type\":\"string[]\",\"required\":false}],\"width\":332,\"height\":136}},{\"id\":\"266871548223741952\",\"type\":\"loop\",\"x\":1153,\"y\":701,\"properties\":{\"text\":\"循环\",\"groupType\":\"WHILE\",\"options\":{\"type\":\"array\",\"maxLoopTimes\":3,\"loopParams\":[],\"loopItemsParam\":{\"nodeId\":\"code_266871019099709440\",\"nodeName\":\"JavaScript脚本\",\"field\":\"result\",\"name\":\"返回结果\",\"type\":\"string[]\"}},\"inputParams\":[],\"outputParams\":[],\"width\":332,\"height\":114}},{\"id\":\"266871548223741952_loopBody\",\"type\":\"loopBody\",\"x\":1101.5,\"y\":1076.5,\"properties\":{\"text\":\"循环体\",\"options\":{},\"inputParams\":[],\"outputParams\":[],\"collapsible\":false,\"autoToFront\":false,\"transformWithContainer\":false,\"isRestrict\":true,\"autoResize\":true,\"children\":[\"266871664426934272\",\"272660634657742848\"],\"isCollapsed\":false,\"width\":1029,\"height\":255},\"children\":[\"266871664426934272\",\"272660634657742848\"]},{\"id\":\"266871664426934272\",\"type\":\"reply\",\"x\":873,\"y\":1107,\"properties\":{\"text\":\"直接回复\",\"options\":{\"content\":\"当前循环了 {{idx}} 次,当前项为:“{{item}}”\",\"stream\":false},\"inputParams\":[{\"field\":\"currentLoopTimes\",\"name\":\"idx\",\"nodeId\":\"266871548223741952\",\"customValue\":\"\",\"type\":\"number\"},{\"field\":\"currentLoopItem\",\"name\":\"item\",\"nodeId\":\"266871548223741952\",\"customValue\":\"\",\"type\":\"any\"}],\"outputParams\":[],\"width\":332,\"height\":114}},{\"id\":\"272660634657742848\",\"type\":\"loopContinue\",\"x\":1330,\"y\":1080,\"properties\":{\"text\":\"继续循环\",\"options\":{},\"inputParams\":[],\"outputParams\":[],\"width\":332,\"height\":62}}],\"edges\":[{\"id\":\"266871559237984256\",\"type\":\"base-edge\",\"sourceNodeId\":\"266871548223741952\",\"targetNodeId\":\"266868341815451648\",\"sourceAnchorId\":\"266871548223741952_output\",\"targetAnchorId\":\"266868341815451648_input\",\"pointsList\":[{\"x\":1319,\"y\":675},{\"x\":1419,\"y\":675},{\"x\":1308,\"y\":476},{\"x\":1408,\"y\":476}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"272659834707501056\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"code_266871019099709440\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"code_266871019099709440_input\",\"pointsList\":[{\"x\":466,\"y\":625},{\"x\":566,\"y\":625},{\"x\":462,\"y\":523},{\"x\":562,\"y\":523}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"272659914713849856\",\"type\":\"base-edge\",\"sourceNodeId\":\"code_266871019099709440\",\"targetNodeId\":\"266871548223741952\",\"sourceAnchorId\":\"code_266871019099709440_output\",\"targetAnchorId\":\"266871548223741952_input\",\"pointsList\":[{\"x\":894,\"y\":523},{\"x\":994,\"y\":523},{\"x\":887,\"y\":675},{\"x\":987,\"y\":675}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"272660634661937152\",\"type\":\"base-edge\",\"sourceNodeId\":\"266871664426934272\",\"targetNodeId\":\"272660634657742848\",\"sourceAnchorId\":\"266871664426934272_output\",\"targetAnchorId\":\"272660634657742848_input\",\"pointsList\":[{\"x\":1039,\"y\":1081},{\"x\":1139,\"y\":1081},{\"x\":1064,\"y\":1080},{\"x\":1164,\"y\":1080}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"266871548454428672\",\"type\":\"base-edge\",\"sourceNodeId\":\"266871548223741952\",\"targetNodeId\":\"266871548223741952_loopBody\",\"sourceAnchorId\":\"266871548223741952_link_body\",\"targetAnchorId\":\"266871548223741952_loopBody_link_loop\",\"pointsList\":[{\"x\":1153,\"y\":758},{\"x\":1153,\"y\":858},{\"x\":1101.5,\"y\":849},{\"x\":1101.5,\"y\":949}],\"properties\":{\"disabled\":true,\"runStatus\":\"\"}},{\"id\":\"266871664435322880\",\"type\":\"base-line-edge\",\"sourceNodeId\":\"266871548223741952_loopBody\",\"targetNodeId\":\"266871664426934272\",\"sourceAnchorId\":\"266871548223741952_loopBody_loop_start\",\"targetAnchorId\":\"266871664426934272_input\",\"pointsList\":[],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"content\",\"name\":\"ces\",\"nodeId\":\"start-node\",\"type\":\"string[]\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"标题\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); INSERT INTO `airag_flow` VALUES ('2009561652150960129', 'admin', '2026-01-09 17:43:28', 'admin', '2026-01-09 17:45:17', 'A01', NULL, 'jeecg', '示例_变量聚合', '', '', 'THEN(\n start.tag(\'start-node\'),\n SWITCH(switch.tag(\'264299940450762752\')).to(\n THEN(\n code_264301155456745472.tag(\'code_264301155456745472\'),\n varMerge.tag(\'264298765684932608\'),\n end.tag(\'264295300867915776\')\n ).tag(\"code_264301155456745472\"),\n THEN(\n code_264301257571270656.tag(\'code_264301257571270656\'),\n varMerge.tag(\'264298765684932608\'),\n end.tag(\'264295300867915776\')\n ).tag(\"code_264301257571270656\"),\n THEN(\n code_264300177714151424.tag(\'code_264300177714151424\'),\n varMerge.tag(\'264298765684932608\'),\n end.tag(\'264295300867915776\')\n ).tag(\"code_264300177714151424\"),\n end.tag(\'264302394055688192\')\n ).tag(\'264299940450762752\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":44,\"y\":535,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":false,\"cronExp\":\"0 0 0 * * ?\",\"beginTime\":null,\"endTime\":null,\"inputParams\":{}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"姓名\",\"type\":\"string\",\"required\":false},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":92}},{\"id\":\"264295300867915776\",\"type\":\"end\",\"x\":1908,\"y\":669,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"查询完毕\\n姓名: {{姓名}}\\n年龄:{{年龄}}\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"姓名\",\"name\":\"姓名\",\"nodeId\":\"264298765684932608\",\"customValue\":\"\",\"type\":\"string\"},{\"field\":\"年龄\",\"name\":\"年龄\",\"nodeId\":\"264298765684932608\",\"customValue\":\"\",\"type\":\"number\"}],\"width\":332,\"height\":136}},{\"id\":\"264298765684932608\",\"type\":\"varMerge\",\"x\":1492,\"y\":571,\"properties\":{\"text\":\"变量聚合\",\"options\":{\"varGroups\":[{\"name\":\"姓名\",\"type\":\"string\",\"vars\":[{\"nodeId\":\"code_264301257571270656\",\"field\":\"name\",\"isCustom\":false,\"type\":\"string\"},{\"nodeId\":\"code_264301155456745472\",\"field\":\"name\",\"isCustom\":false,\"type\":\"string\"},{\"nodeId\":\"code_264300177714151424\",\"field\":\"name\",\"isCustom\":false,\"type\":\"string\"}]},{\"name\":\"年龄\",\"type\":\"number\",\"vars\":[{\"nodeId\":\"code_264301257571270656\",\"field\":\"age\",\"isCustom\":false,\"type\":\"number\"},{\"nodeId\":\"code_264301155456745472\",\"field\":\"age\",\"isCustom\":false,\"type\":\"number\"},{\"nodeId\":\"code_264300177714151424\",\"field\":\"age\",\"isCustom\":false,\"type\":\"number\"}]}]},\"inputParams\":[],\"outputParams\":[{\"field\":\"姓名\",\"name\":\"姓名\",\"type\":\"string\"},{\"field\":\"年龄\",\"name\":\"年龄\",\"type\":\"number\"}],\"width\":332,\"height\":114}},{\"id\":\"264299940450762752\",\"type\":\"switch\",\"x\":443,\"y\":497,\"properties\":{\"text\":\"条件分支\",\"options\":{\"if\":[{\"logic\":\"AND\",\"conditions\":[{\"nodeId\":\"start-node\",\"field\":\"content\",\"operator\":\"EQUALS\",\"value\":\"张三\",\"type\":\"string\"}],\"next\":\"code_264301257571270656\"},{\"logic\":\"AND\",\"conditions\":[{\"nodeId\":\"start-node\",\"field\":\"content\",\"operator\":\"EQUALS\",\"value\":\"李四\",\"type\":\"string\"}],\"next\":\"code_264301155456745472\"},{\"logic\":\"AND\",\"conditions\":[{\"nodeId\":\"start-node\",\"field\":\"content\",\"operator\":\"EQUALS\",\"value\":\"王五\",\"type\":\"string\"}],\"next\":\"code_264300177714151424\"}],\"else\":{\"next\":\"264302394055688192\"}},\"inputParams\":[],\"outputParams\":[{\"field\":\"index\",\"name\":\"分支索引\",\"type\":\"number\"}],\"width\":332,\"height\":170}},{\"id\":\"code_264300177714151424\",\"type\":\"code\",\"x\":938,\"y\":768,\"properties\":{\"text\":\"查询王五\",\"options\":{\"codeType\":\"javascript\",\"code\":\"function main() {\\n return {\\n name: \\\"王五\\\",\\n age: 18,\\n }\\n}\"},\"inputParams\":[],\"outputParams\":[{\"field\":\"name\",\"name\":\"姓名\",\"type\":\"string\",\"required\":false},{\"field\":\"age\",\"name\":\"年龄\",\"type\":\"number\",\"required\":false}],\"width\":332,\"height\":136}},{\"id\":\"code_264301155456745472\",\"type\":\"code\",\"x\":938,\"y\":559,\"properties\":{\"text\":\"查询李四\",\"options\":{\"codeType\":\"javascript\",\"code\":\"function main() {\\n return {\\n name: \\\"李四\\\",\\n age: 23,\\n }\\n}\"},\"inputParams\":[],\"outputParams\":[{\"field\":\"name\",\"name\":\"姓名\",\"type\":\"string\",\"required\":false},{\"field\":\"age\",\"name\":\"年龄\",\"type\":\"number\",\"required\":false}],\"width\":332,\"height\":136}},{\"id\":\"code_264301257571270656\",\"type\":\"code\",\"x\":937,\"y\":346,\"properties\":{\"text\":\"查询张三\",\"options\":{\"codeType\":\"javascript\",\"code\":\"function main() {\\n return {\\n name: \\\"张三\\\",\\n age: 33,\\n }\\n}\"},\"inputParams\":[],\"outputParams\":[{\"field\":\"name\",\"name\":\"姓名\",\"type\":\"string\",\"required\":false},{\"field\":\"age\",\"name\":\"年龄\",\"type\":\"number\",\"required\":false}],\"width\":332,\"height\":136}},{\"id\":\"264302394055688192\",\"type\":\"end\",\"x\":936,\"y\":992,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"抱歉,我不知道你说的是谁\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"content\",\"name\":\"name\",\"nodeId\":\"start-node\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":136}}],\"edges\":[{\"id\":\"264299940454957056\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"264299940450762752\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"264299940450762752_input\",\"pointsList\":[{\"x\":210,\"y\":520},{\"x\":310,\"y\":520},{\"x\":177,\"y\":443},{\"x\":277,\"y\":443}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264300208160604160\",\"type\":\"base-edge\",\"sourceNodeId\":\"code_264300177714151424\",\"targetNodeId\":\"264298765684932608\",\"sourceAnchorId\":\"code_264300177714151424_output\",\"targetAnchorId\":\"264298765684932608_input\",\"pointsList\":[{\"x\":1104,\"y\":731},{\"x\":1204,\"y\":731},{\"x\":1226,\"y\":545},{\"x\":1326,\"y\":545}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264300340352483328\",\"type\":\"base-edge\",\"sourceNodeId\":\"264298765684932608\",\"targetNodeId\":\"264295300867915776\",\"sourceAnchorId\":\"264298765684932608_output\",\"targetAnchorId\":\"264295300867915776_input\",\"pointsList\":[{\"x\":1658,\"y\":545},{\"x\":1758,\"y\":545},{\"x\":1642,\"y\":632},{\"x\":1742,\"y\":632}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264301239456071680\",\"type\":\"base-edge\",\"sourceNodeId\":\"code_264301155456745472\",\"targetNodeId\":\"264298765684932608\",\"sourceAnchorId\":\"code_264301155456745472_output\",\"targetAnchorId\":\"264298765684932608_input\",\"pointsList\":[{\"x\":1104,\"y\":522},{\"x\":1204,\"y\":522},{\"x\":1226,\"y\":545},{\"x\":1326,\"y\":545}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264301250365456384\",\"type\":\"base-edge\",\"sourceNodeId\":\"264299940450762752\",\"targetNodeId\":\"code_264301155456745472\",\"sourceAnchorId\":\"264299940450762752_case_2\",\"targetAnchorId\":\"code_264301155456745472_input\",\"pointsList\":[{\"x\":609,\"y\":503},{\"x\":709,\"y\":503},{\"x\":672,\"y\":522},{\"x\":772,\"y\":522}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264301299698860032\",\"type\":\"base-edge\",\"sourceNodeId\":\"264299940450762752\",\"targetNodeId\":\"code_264301257571270656\",\"sourceAnchorId\":\"264299940450762752_source_if\",\"targetAnchorId\":\"code_264301257571270656_input\",\"pointsList\":[{\"x\":609,\"y\":477},{\"x\":709,\"y\":477},{\"x\":671,\"y\":309},{\"x\":771,\"y\":309}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264301304413257728\",\"type\":\"base-edge\",\"sourceNodeId\":\"code_264301257571270656\",\"targetNodeId\":\"264298765684932608\",\"sourceAnchorId\":\"code_264301257571270656_output\",\"targetAnchorId\":\"264298765684932608_input\",\"pointsList\":[{\"x\":1103,\"y\":309},{\"x\":1203,\"y\":309},{\"x\":1226,\"y\":545},{\"x\":1326,\"y\":545}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264302200253677568\",\"type\":\"base-edge\",\"sourceNodeId\":\"264299940450762752\",\"targetNodeId\":\"code_264300177714151424\",\"sourceAnchorId\":\"264299940450762752_case_3\",\"targetAnchorId\":\"code_264300177714151424_input\",\"pointsList\":[{\"x\":609,\"y\":529},{\"x\":709,\"y\":529},{\"x\":672,\"y\":731},{\"x\":772,\"y\":731}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"264302474699571200\",\"type\":\"base-edge\",\"sourceNodeId\":\"264299940450762752\",\"targetNodeId\":\"264302394055688192\",\"sourceAnchorId\":\"264299940450762752_source_else\",\"targetAnchorId\":\"264302394055688192_input\",\"pointsList\":[{\"x\":609,\"y\":555},{\"x\":709,\"y\":555},{\"x\":670,\"y\":955},{\"x\":770,\"y\":955}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"姓名\",\"name\":\"姓名\",\"nodeId\":\"264298765684932608\",\"type\":\"string\"},{\"customValue\":\"\",\"field\":\"年龄\",\"name\":\"年龄\",\"nodeId\":\"264298765684932608\",\"type\":\"number\"},{\"customValue\":\"\",\"field\":\"content\",\"name\":\"name\",\"nodeId\":\"start-node\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"姓名\",\"required\":false,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', ''); INSERT INTO `airag_flow` VALUES ('2009565806546157570', 'admin', '2026-01-09 17:59:59', 'admin', '2026-01-22 09:54:21', 'A01', NULL, 'jeecg', '示例_定时触发器', '', '', 'THEN(\n start.tag(\'start-node\'),\n code_266155066987638784.tag(\'code_266155066987638784\'),\n end.tag(\'266154958954950656\')\n).tag(\"start-node\")', '{\"nodes\":[{\"id\":\"start-node\",\"type\":\"start\",\"x\":300,\"y\":662,\"properties\":{\"text\":\"开始\",\"remarks\":\"\",\"options\":{\"cronTrigger\":{\"enabled\":true,\"cronExp\":\"30 30 0/1 * * ?\",\"beginTime\":\"2026-01-01 12:30:30\",\"endTime\":null,\"inputParams\":{\"content\":\"你好\"}}},\"inputParams\":[{\"field\":\"content\",\"name\":\"用户问题\",\"type\":\"string\",\"required\":true},{\"field\":\"history\",\"name\":\"历史记录\",\"type\":\"string[]\",\"required\":false},{\"field\":\"images\",\"name\":\"图片\",\"type\":\"picture\",\"required\":false}],\"outputParams\":[],\"width\":332,\"height\":114}},{\"id\":\"266154958954950656\",\"type\":\"end\",\"x\":1219,\"y\":674,\"properties\":{\"text\":\"结束\",\"options\":{\"outputText\":false,\"outputContent\":\"这里是定时触发,触发时间:{{当前时间}}\",\"outputType\":\"text\",\"cardConfig\":null},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"当前时间\",\"nodeId\":\"code_266155066987638784\",\"customValue\":\"\",\"type\":\"string\"}],\"width\":332,\"height\":136}},{\"id\":\"code_266155066987638784\",\"type\":\"code\",\"x\":751,\"y\":673,\"properties\":{\"text\":\"脚本执行\",\"options\":{\"codeType\":\"javascript\",\"code\":\"\\nconst now = new Date();\\n\\nfunction formatDateTime(date) {\\n const year = date.getFullYear();\\n const month = String(date.getMonth() + 1).padStart(2, \'0\');\\n const day = String(date.getDate()).padStart(2, \'0\');\\n const hours = String(date.getHours()).padStart(2, \'0\');\\n const minutes = String(date.getMinutes()).padStart(2, \'0\');\\n const seconds = String(date.getSeconds()).padStart(2, \'0\');\\n\\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\\n}\\n\\nfunction main(params) {\\n return {\\n result: formatDateTime(now),\\n }\\n}\\n\"},\"inputParams\":[],\"outputParams\":[{\"field\":\"result\",\"name\":\"当前时间\",\"type\":\"string\",\"required\":false}],\"width\":332,\"height\":136}}],\"edges\":[{\"id\":\"266155066991833088\",\"type\":\"base-edge\",\"sourceNodeId\":\"start-node\",\"targetNodeId\":\"code_266155066987638784\",\"sourceAnchorId\":\"start-node_output\",\"targetAnchorId\":\"code_266155066987638784_input\",\"pointsList\":[{\"x\":466,\"y\":636},{\"x\":566,\"y\":636},{\"x\":485,\"y\":636},{\"x\":585,\"y\":636}],\"properties\":{\"runStatus\":\"\"}},{\"id\":\"266155314556432384\",\"type\":\"base-edge\",\"sourceNodeId\":\"code_266155066987638784\",\"targetNodeId\":\"266154958954950656\",\"sourceAnchorId\":\"code_266155066987638784_output\",\"targetAnchorId\":\"266154958954950656_input\",\"pointsList\":[{\"x\":917,\"y\":636},{\"x\":1017,\"y\":636},{\"x\":953,\"y\":637},{\"x\":1053,\"y\":637}],\"properties\":{\"runStatus\":\"\"}}]}', 'enable', '{\"outputs\":[{\"customValue\":\"\",\"field\":\"result\",\"name\":\"当前时间\",\"nodeId\":\"code_266155066987638784\",\"type\":\"string\"}],\"inputs\":[{\"field\":\"content\",\"name\":\"用户问题\",\"required\":true,\"type\":\"string\"},{\"field\":\"history\",\"name\":\"历史记录\",\"required\":false,\"type\":\"string[]\"},{\"field\":\"images\",\"name\":\"图片\",\"required\":false,\"type\":\"picture\"}]}', '{\"beginTime\":1767241830000,\"cronExp\":\"30 30 0/1 * * ?\",\"enabled\":true,\"inputParams\":{\"content\":\"你好\"}}'); @@ -348,10 +349,11 @@ CREATE TABLE `airag_model` ( -- ---------------------------- INSERT INTO `airag_model` VALUES ('1890232564262739969', 'jeecg', '2025-02-14 10:52:16', 'admin', '2026-01-23 18:29:06', 'A04', NULL, 'OpenAI', 'OPENAI', 'gpt-4o-mini', '{\"apiKey\":\"请在官网上申请的key\"}', 'https://api.gpt.ge', 'LLM', '{\"temperature\":0.2,\"topP\":0.7,\"presencePenalty\":0.5,\"frequencyPenalty\":0.5,\"maxTokens\":null}', 1); INSERT INTO `airag_model` VALUES ('1891459707122499586', 'jeecg', '2025-02-17 20:08:30', 'admin', '2026-01-23 18:29:03', 'A04', NULL, 'OpenAI向量', 'OPENAI', 'text-embedding-ada-002', '{\"apiKey\":\"请在官网上申请的key\"}', 'https://api.gpt.ge', 'EMBED', NULL, 1); -INSERT INTO `airag_model` VALUES ('1897481367743143938', 'jeecg', '2025-03-06 10:56:26', 'admin', '2026-01-23 17:41:37', 'A04', NULL, 'deepseek', 'DEEPSEEK', 'deepseek-chat', '{\"apiKey\":\"sk-ff138aa9896945468ec19469e21026b0\"}', 'https://api.deepseek.com/v1', 'LLM', NULL, 1); +INSERT INTO `airag_model` VALUES ('1897481367743143938', 'jeecg', '2025-03-06 10:56:26', 'admin', '2026-01-28 15:17:55', 'A04', NULL, 'deepseek', 'DEEPSEEK', 'deepseek-chat', '{\"apiKey\":\"请在官网上申请的key\"}', 'https://api.deepseek.com/v1', 'LLM', NULL, 1); INSERT INTO `airag_model` VALUES ('1897883052995006466', 'jeecg', '2025-03-07 13:32:35', 'admin', '2025-11-27 18:18:55', 'A04', NULL, '智谱', 'ZHIPU', 'glm-4-flash', '{\"apiKey\":\"您在官网上申请的key\"}', 'https://open.bigmodel.cn/', 'LLM', NULL, 0); -INSERT INTO `airag_model` VALUES ('1897884353107611650', 'jeecg', '2025-03-07 13:37:45', 'admin', '2025-11-27 18:19:00', 'A04', NULL, '智谱向量', 'ZHIPU', 'Embedding-3', '{\"apiKey\":\"您在官网上申请的key\"}', 'https://open.bigmodel.cn', 'EMBED', '{\"temperature\":0.7,\"topP\":0.7,\"presencePenalty\":null,\"frequencyPenalty\":null,\"maxTokens\":null}', 0); -INSERT INTO `airag_model` VALUES ('2014624273267699714', 'admin', '2026-01-23 17:00:31', 'admin', '2026-01-23 18:29:11', 'A01A03', NULL, 'OpenAI图片模型', 'OPENAI', 'gpt-image-1.5', '{\"apiKey\":\"请在官网上申请的key\"}', 'https://api.vveai.com', 'IMAGE', NULL, 1); +INSERT INTO `airag_model` VALUES ('1897884353107611650', 'jeecg', '2025-03-07 13:37:45', 'admin', '2026-01-28 15:17:48', 'A04', NULL, '智谱向量', 'ZHIPU', 'Embedding-3', '{\"apiKey\":\"您在官网上申请的key\"}', 'https://open.bigmodel.cn', 'EMBED', '{\"temperature\":0.7,\"topP\":0.7,\"presencePenalty\":null,\"frequencyPenalty\":null,\"maxTokens\":null}', 0); +INSERT INTO `airag_model` VALUES ('2008060119398899713', 'admin', '2026-01-05 14:16:55', 'admin', '2026-01-28 15:17:44', 'A05A01A01', NULL, '智普图片生成', 'ZHIPU', 'glm-image', '{\"apiKey\":\"请在官网上申请的key\"}', 'https://open.bigmodel.cn', 'IMAGE', NULL, 1); +INSERT INTO `airag_model` VALUES ('2014624273267699714', 'admin', '2026-01-23 17:00:31', 'admin', '2026-01-28 15:17:39', 'A01A03', NULL, 'OpenAI图片模型', 'OPENAI', 'gpt-image-1.5', '{\"apiKey\":\"请在官网上申请的key\"}', 'https://api.vveai.com', 'IMAGE', NULL, 1); -- ---------------------------- -- Table structure for airag_prompts @@ -458,7 +460,8 @@ INSERT INTO `flyway_schema_history` VALUES (10, '3.9.0.1', 'mcp demo', 'SQL', 'V INSERT INTO `flyway_schema_history` VALUES (11, '3.9.0.2', 'upd dep category', 'SQL', 'V3.9.0_2__upd_dep_category.sql', -71250240, 'root', '2025-11-27 18:45:48', 19, 1); INSERT INTO `flyway_schema_history` VALUES (12, '3.9.0.3', 'add aiflow permission', 'SQL', 'V3.9.0_3__add_aiflow_permission.sql', 1502182637, 'root', '2025-12-01 15:13:59', 9, 1); INSERT INTO `flyway_schema_history` VALUES (13, '3.9.0.4', 'add onlineuser perms', 'SQL', 'V3.9.0_4__add_onlineuser_perms.sql', -1048887238, 'root', '2026-01-22 09:46:14', 23, 1); -INSERT INTO `flyway_schema_history` VALUES (14, '3.9.1.0', 'all upgrade', 'SQL', 'V3.9.1_0__all_upgrade.sql', -535845060, 'root', '2026-01-23 18:35:09', 19, 1); +INSERT INTO `flyway_schema_history` VALUES (14, '3.9.1.0', 'all upgrade', 'SQL', 'V3.9.1_0__all_upgrade.sql', -498300865, 'root', '2026-01-28 15:19:13', 65, 1); +INSERT INTO `flyway_schema_history` VALUES (15, '3.9.1.1', 'add aiapp img gen', 'SQL', 'V3.9.1_1__add_aiapp_img_gen.sql', 1451785654, 'root', '2026-01-28 15:19:42', 21, 1); -- ---------------------------- -- Table structure for jeecg_order_customer @@ -5455,7 +5458,7 @@ CREATE TABLE `qrtz_scheduler_state` ( -- ---------------------------- -- Records of qrtz_scheduler_state -- ---------------------------- -INSERT INTO `qrtz_scheduler_state` VALUES ('MyScheduler', 'qin1769164511267', 1769164563580, 15000); +INSERT INTO `qrtz_scheduler_state` VALUES ('MyScheduler', 'qin1769584805968', 1769584846824, 15000); -- ---------------------------- -- Table structure for qrtz_simple_triggers @@ -7540,6 +7543,15 @@ INSERT INTO `sys_log` VALUES ('2014640365604184065', 2, '角色首页配置-分 INSERT INTO `sys_log` VALUES ('2014644846156849154', 2, '填值规则-分页列表查询', 1, 'admin', '管理员', '0:0:0:0:0:0:0:1', 'org.jeecg.modules.system.controller.SysFillRuleController.queryPageList()', NULL, ' sysFillRule: SysFillRule(id=null, ruleName=null, ruleCode=null, ruleClass=null, ruleParams=null, updateBy=null, updateTime=null, createBy=null, createTime=null) pageNo: 1 pageSize: 10 req: org.springframework.web.servlet.resource.ResourceUrlEncodingFilter$ResourceUrlEncodingRequestWrapper@4807616d', NULL, 10, NULL, '2026-01-23 18:22:16', NULL, NULL, NULL, NULL); INSERT INTO `sys_log` VALUES ('2014644850082717697', 2, '编码校验规则-分页列表查询', 1, 'admin', '管理员', '0:0:0:0:0:0:0:1', 'org.jeecg.modules.system.controller.SysCheckRuleController.queryPageList()', NULL, ' sysCheckRule: SysCheckRule(id=null, ruleName=null, ruleCode=null, ruleJson=null, ruleDescription=null, updateBy=null, updateTime=null, createBy=null, createTime=null) pageNo: 1 pageSize: 10 request: org.springframework.web.servlet.resource.ResourceUrlEncodingFilter$ResourceUrlEncodingRequestWrapper@65d06773', NULL, 38, NULL, '2026-01-23 18:22:17', NULL, NULL, NULL, NULL); INSERT INTO `sys_log` VALUES ('2014645507799916545', 2, '编码校验规则-分页列表查询', 1, 'admin', '管理员', '0:0:0:0:0:0:0:1', 'org.jeecg.modules.system.controller.SysCheckRuleController.queryPageList()', NULL, ' sysCheckRule: SysCheckRule(id=null, ruleName=null, ruleCode=null, ruleJson=null, ruleDescription=null, updateBy=null, updateTime=null, createBy=null, createTime=null) pageNo: 1 pageSize: 10 request: org.springframework.web.servlet.resource.ResourceUrlEncodingFilter$ResourceUrlEncodingRequestWrapper@6d3dcc75', NULL, 9, NULL, '2026-01-23 18:24:54', NULL, NULL, NULL, NULL); +INSERT INTO `sys_log` VALUES ('2015701636197933058', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '0:0:0:0:0:0:0:1', NULL, NULL, NULL, NULL, NULL, NULL, '2026-01-26 16:21:35', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2015702124893069313', 4, 'org.springframework.web.context.request.async.AsyncRequestNotUsableException:Response not usable after response errors.', NULL, NULL, NULL, '0:0:0:0:0:0:0:1', NULL, '/jeecg-boot/airag/chat/send', 'org.springframework.web.context.request.async.AsyncRequestNotUsableException: Response not usable after response errors.\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleHttpServletResponse.obtainLockOrRaiseException(StandardServletAsyncWebRequest.java:338)\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleHttpServletResponse.flushBuffer(StandardServletAsyncWebRequest.java:320)\r\n at org.springframework.http.server.ServletServerHttpResponse.flush(ServletServerHttpResponse.java:105)\r\n at org.springframework.http.server.DelegatingServerHttpResponse.flush(DelegatingServerHttpResponse.java:61)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$DefaultSseEmitterHandler.complete(ResponseBodyEmitterReturnValueHandler.java:325)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.complete(ResponseBodyEmitter.java:251)\r\n at org.jeecg.modules.airag.app.service.impl.AiragChatServiceImpl.lambda$createSSE$4(AiragChatServiceImpl.java:496)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter$ErrorCallback.accept(ResponseBodyEmitter.java:400)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter$ErrorCallback.accept(ResponseBodyEmitter.java:388)\r\n at org.springframework.web.context.request.async.DeferredResult$LifecycleInterceptor.handleError(DeferredResult.java:338)\r\n at org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterError(DeferredResultInterceptorChain.java:99)\r\n at org.springframework.web.context.request.async.WebAsyncManager.lambda$startDeferredResultProcessing$6(WebAsyncManager.java:455)\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.lambda$onError$0(StandardServletAsyncWebRequest.java:195)\r\n at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onError(StandardServletAsyncWebRequest.java:195)\r\n at org.apache.catalina.core.AsyncListenerWrapper.fireOnError(AsyncListenerWrapper.java:49)\r\n at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:413)\r\n at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:155)\r\n at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\r\n at java.base/java.lang.Thread.run(Thread.java:842)\r\n', NULL, NULL, NULL, '2026-01-26 16:23:31', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2015703034134290434', 4, 'org.springframework.http.converter.HttpMessageNotWritableException:No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'', NULL, NULL, NULL, '0:0:0:0:0:0:0:1', '_t=1769415995325', '/jeecg-boot/airag/chat/receive/402881829bf96559019bf96559f40002', 'org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'\r\n at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:365)\r\n at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:263)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseEntityReturnValueHandler.handleReturnValue(ResponseEntityReturnValueHandler.java:79)\r\n at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)\r\n at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:65)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:463)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.lambda$doFilterInternal$0(AbstractShiroFilter.java:378)\r\n at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:91)\r\n at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:84)\r\n at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:389)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:376)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:612)\r\n at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:491)\r\n at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:439)\r\n at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:358)\r\n at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:209)\r\n at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:286)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:239)\r\n at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\r\n at java.base/java.lang.Thread.run(Thread.java:842)\r\n', NULL, NULL, NULL, '2026-01-26 16:27:08', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2016403617082372097', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '0:0:0:0:0:0:0:1', NULL, NULL, NULL, NULL, NULL, NULL, '2026-01-28 14:51:00', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2016403790978215938', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '0:0:0:0:0:0:0:1', NULL, NULL, NULL, NULL, NULL, NULL, '2026-01-28 14:51:41', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2016404348782899202', 4, 'org.springframework.web.context.request.async.AsyncRequestNotUsableException:Response not usable after response errors.', NULL, NULL, NULL, '0:0:0:0:0:0:0:1', NULL, '/jeecg-boot/airag/chat/send', 'org.springframework.web.context.request.async.AsyncRequestNotUsableException: Response not usable after response errors.\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleHttpServletResponse.obtainLockOrRaiseException(StandardServletAsyncWebRequest.java:338)\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest$LifecycleHttpServletResponse.flushBuffer(StandardServletAsyncWebRequest.java:320)\r\n at org.springframework.http.server.ServletServerHttpResponse.flush(ServletServerHttpResponse.java:105)\r\n at org.springframework.http.server.DelegatingServerHttpResponse.flush(DelegatingServerHttpResponse.java:61)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$DefaultSseEmitterHandler.complete(ResponseBodyEmitterReturnValueHandler.java:325)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.complete(ResponseBodyEmitter.java:251)\r\n at org.jeecg.modules.airag.app.service.impl.AiragChatServiceImpl.lambda$createSSE$4(AiragChatServiceImpl.java:496)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter$ErrorCallback.accept(ResponseBodyEmitter.java:400)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter$ErrorCallback.accept(ResponseBodyEmitter.java:388)\r\n at org.springframework.web.context.request.async.DeferredResult$LifecycleInterceptor.handleError(DeferredResult.java:338)\r\n at org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterError(DeferredResultInterceptorChain.java:99)\r\n at org.springframework.web.context.request.async.WebAsyncManager.lambda$startDeferredResultProcessing$6(WebAsyncManager.java:455)\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.lambda$onError$0(StandardServletAsyncWebRequest.java:195)\r\n at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)\r\n at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onError(StandardServletAsyncWebRequest.java:195)\r\n at org.apache.catalina.core.AsyncListenerWrapper.fireOnError(AsyncListenerWrapper.java:49)\r\n at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:413)\r\n at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:155)\r\n at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\r\n at java.base/java.lang.Thread.run(Thread.java:842)\r\n', NULL, NULL, NULL, '2026-01-28 14:53:54', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2016404349659508738', 4, 'org.springframework.http.converter.HttpMessageNotWritableException:No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'', NULL, NULL, NULL, '0:0:0:0:0:0:0:1', '_t=1769583206767', '/jeecg-boot/airag/chat/receive/402881829c035f70019c0360ca7f000d', 'org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'\r\n at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:365)\r\n at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:263)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseEntityReturnValueHandler.handleReturnValue(ResponseEntityReturnValueHandler.java:79)\r\n at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)\r\n at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:65)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:463)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.lambda$doFilterInternal$0(AbstractShiroFilter.java:378)\r\n at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:91)\r\n at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:84)\r\n at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:389)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:376)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:612)\r\n at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:491)\r\n at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:439)\r\n at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:358)\r\n at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:209)\r\n at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:286)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:239)\r\n at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\r\n at java.base/java.lang.Thread.run(Thread.java:842)\r\n', NULL, NULL, NULL, '2026-01-28 14:53:55', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2016409247742443522', 4, 'org.springframework.http.converter.HttpMessageNotWritableException:No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'', NULL, NULL, NULL, '0:0:0:0:0:0:0:1', '_t=1769584380278', '/jeecg-boot/airag/chat/receive/402881829c036e42019c0372ab65000d', 'org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'\r\n at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:365)\r\n at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:263)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseEntityReturnValueHandler.handleReturnValue(ResponseEntityReturnValueHandler.java:79)\r\n at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)\r\n at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:65)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:463)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.lambda$doFilterInternal$0(AbstractShiroFilter.java:378)\r\n at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:91)\r\n at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:84)\r\n at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:389)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:376)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:612)\r\n at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:491)\r\n at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:439)\r\n at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:358)\r\n at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:209)\r\n at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:286)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:239)\r\n at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\r\n at java.base/java.lang.Thread.run(Thread.java:842)\r\n', NULL, NULL, NULL, '2026-01-28 15:13:22', NULL, NULL, NULL, 'pc'); +INSERT INTO `sys_log` VALUES ('2016409247822135298', 4, 'org.springframework.http.converter.HttpMessageNotWritableException:No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'', NULL, NULL, NULL, '0:0:0:0:0:0:0:1', '_t=1769584380321', '/jeecg-boot/airag/chat/receive/402881829c036e42019c0372ab65000d', 'org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type \'text/event-stream\'\r\n at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:365)\r\n at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:263)\r\n at org.springframework.web.servlet.mvc.method.annotation.ResponseEntityReturnValueHandler.handleReturnValue(ResponseEntityReturnValueHandler.java:79)\r\n at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)\r\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991)\r\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896)\r\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)\r\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)\r\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)\r\n at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)\r\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:65)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:109)\r\n at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:138)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:70)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:463)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.lambda$doFilterInternal$0(AbstractShiroFilter.java:378)\r\n at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:91)\r\n at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:84)\r\n at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:389)\r\n at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:376)\r\n at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:156)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)\r\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)\r\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)\r\n at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:612)\r\n at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:491)\r\n at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:439)\r\n at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:358)\r\n at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:209)\r\n at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:286)\r\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150)\r\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:239)\r\n at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:243)\r\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)\r\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)\r\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769)\r\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189)\r\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658)\r\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)\r\n at java.base/java.lang.Thread.run(Thread.java:842)\r\n', NULL, NULL, NULL, '2026-01-28 15:13:22', NULL, NULL, NULL, 'pc'); -- ---------------------------- -- Table structure for sys_permission @@ -8012,7 +8024,7 @@ INSERT INTO `sys_permission` VALUES ('1963133393868722178', '1674708136602542082 INSERT INTO `sys_permission` VALUES ('1972617196420993025', '45c966826eeff4c99b8f8ebfe74511fc', '部门管理拖拽修改上下级', NULL, NULL, 0, NULL, NULL, 2, 'system:depart:updateChange', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-09-29 18:59:24', NULL, NULL, 0, 0, '1', 0); INSERT INTO `sys_permission` VALUES ('1972645086223814657', '3f915b2769fc80648e92d04e84ca059d', '重置系统密码', NULL, NULL, 0, NULL, NULL, 2, 'system:user:resetPassword', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-09-29 20:50:13', 'admin', '2025-09-30 11:58:29', 0, 0, '1', 0); INSERT INTO `sys_permission` VALUES ('1980223355087781889', '1892553163993931777', 'MCP配置', '/super/airag/aimcp/AiragMcpList', 'super/airag/aimcp/AiragMcpList', 1, '', NULL, 1, NULL, '0', 5.00, 0, 'ant-design:tool-twotone', 1, 0, 0, 0, NULL, 'admin', '2025-10-20 18:43:33', 'admin', '2025-10-21 19:00:31', 0, 0, NULL, 0); -INSERT INTO `sys_permission` VALUES ('1996422809213341698', '1892553163993931777', '应用门户', '/app/portal', 'super/airag/aiapp/chat/portal/AppPortal', 1, '', NULL, 1, NULL, '0', 5.00, 0, 'ant-design:appstore-filled', 1, 0, 0, 0, NULL, 'admin', '2025-12-04 11:34:24', 'admin', '2026-01-23 16:52:53', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('1996422809213341698', '1892553163993931777', '应用门户', '/app/portal', 'super/airag/aiapp/chat/portal/AppPortal', 1, '', NULL, 1, NULL, '0', 0.00, 0, 'ant-design:home-outlined', 1, 0, 0, 0, NULL, 'admin', '2025-12-04 11:34:24', 'admin', '2026-01-28 15:17:14', 0, 0, NULL, 0); INSERT INTO `sys_permission` VALUES ('1999306189754236930', '1737321792727388161', '数据集编辑保存', NULL, NULL, 0, NULL, NULL, 2, 'drag:dataset:save', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-12-12 10:31:56', NULL, NULL, 0, 0, '1', 0); INSERT INTO `sys_permission` VALUES ('1999306301071065090', '1737321792727388161', '数据集删除', NULL, NULL, 0, NULL, NULL, 2, 'drag:dataset:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-12-12 10:32:22', NULL, NULL, 0, 0, '1', 0); INSERT INTO `sys_permission` VALUES ('1999367175911657473', '2012376076054974466', 'AI提示词', '/super/airag/aiprompts', 'super/airag/aiprompts/AiragPromptsList', 1, '', NULL, 1, NULL, '0', 7.00, 0, 'ant-design:exclamation-circle-outlined', 1, 0, 0, 0, NULL, 'admin', '2025-12-12 14:34:16', 'admin', '2026-01-17 12:08:01', 0, 0, NULL, 0); diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/AiAppConsts.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/AiAppConsts.java index c10f1e7ba..514307937 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/AiAppConsts.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/AiAppConsts.java @@ -56,7 +56,12 @@ public class AiAppConsts { /** - * AI写作的应用id + * AI写作的流程id */ - public static final String WRITER_APP_ID = "2010634128233779202"; + public static final String ARTICLE_WRITER_FLOW_ID = "2011769909807579138"; + + /** + * AI写作redis请求前缀 + */ + public static final String ARTICLE_WRITER_KEY = "airag:chat:article:write:{}"; } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/Prompts.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/Prompts.java index 1368baf79..46f970d5a 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/Prompts.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/consts/Prompts.java @@ -168,4 +168,9 @@ public class Prompts { */ public static final String AI_REPLY_PROMPT = "请针对如下内容:[{}] 做个回复。回复内容参考:[{}], 回复格式:{},语气:{},语言:{},长度:{}。"; + /** + * ai润色提提示词 + */ + public static final String AI_TOUCHE_PROMPT = "请针对如下内容:[{}] 进行润色。 回复格式:{},语气:{},语言:{},长度:{}。"; + } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/controller/AiragAppController.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/controller/AiragAppController.java index 64f2dc4b6..694f98a2f 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/controller/AiragAppController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/controller/AiragAppController.java @@ -16,11 +16,14 @@ import org.jeecg.modules.airag.app.consts.AiAppConsts; import org.jeecg.modules.airag.app.entity.AiragApp; import org.jeecg.modules.airag.app.service.IAiragAppService; import org.jeecg.modules.airag.app.service.IAiragChatService; +import org.jeecg.modules.airag.app.vo.AiArticleWriteVersionVo; import org.jeecg.modules.airag.app.vo.AppDebugParams; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import java.util.List; + import jakarta.servlet.http.HttpServletRequest; /** @@ -190,4 +193,31 @@ public class AiragAppController extends JeecgController saveArticleWrite(@RequestBody AiArticleWriteVersionVo aiWriteVersionVo) { + airagAppService.saveArticleWrite(aiWriteVersionVo); + return Result.OK("保存成功!"); + } + + /** + * 写作删除 + */ + @DeleteMapping("/delete/article/write") + public Result deleteArticleWrite(@RequestParam(name = "version") String version) { + AssertUtils.assertNotEmpty("版本号不能为空", version); + airagAppService.deleteArticleWrite(version); + return Result.OK("删除成功!"); + } + + /** + * 写作查询 + */ + @GetMapping("/list/article/write") + public Result> listArticleWrite() { + List list = airagAppService.listArticleWrite(); + return Result.OK(list); + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/IAiragAppService.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/IAiragAppService.java index 68e777de6..00e3a40fa 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/IAiragAppService.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/IAiragAppService.java @@ -2,6 +2,8 @@ package org.jeecg.modules.airag.app.service; import com.baomidou.mybatisplus.extension.service.IService; import org.jeecg.modules.airag.app.entity.AiragApp; +import org.jeecg.modules.airag.app.vo.AiArticleWriteVersionVo; +import java.util.List; /** * @Description: AI应用 @@ -30,4 +32,26 @@ public interface IAiragAppService extends IService { * @return */ Object generateMemoryByAppId(String variables, String memoryId, boolean blocking); + + /** + * 写作保存 + * + * @param aiWriteVersionVo + */ + void saveArticleWrite(AiArticleWriteVersionVo aiWriteVersionVo); + + /** + * 写作列表 + * + * @return + */ + List listArticleWrite(); + + /** + * 写作删除 + * + * @param version + */ + void deleteArticleWrite(String version); + } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragAppServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragAppServiceImpl.java index b9c34a900..5e2489f6a 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragAppServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragAppServiceImpl.java @@ -1,5 +1,6 @@ package org.jeecg.modules.airag.app.service.impl; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -10,15 +11,19 @@ import dev.langchain4j.data.message.UserMessage; import dev.langchain4j.model.output.FinishReason; import dev.langchain4j.service.TokenStream; import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; import org.jeecg.common.api.vo.Result; import org.jeecg.common.exception.JeecgBootBizTipException; +import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.AssertUtils; import org.jeecg.common.util.UUIDGenerator; import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.airag.app.consts.AiAppConsts; import org.jeecg.modules.airag.app.consts.Prompts; import org.jeecg.modules.airag.app.entity.AiragApp; import org.jeecg.modules.airag.app.mapper.AiragAppMapper; import org.jeecg.modules.airag.app.service.IAiragAppService; +import org.jeecg.modules.airag.app.vo.AiArticleWriteVersionVo; import org.jeecg.modules.airag.app.vo.AppVariableVo; import org.jeecg.modules.airag.common.consts.AiragConsts; import org.jeecg.modules.airag.common.handler.AIChatParams; @@ -30,14 +35,18 @@ import org.jeecg.modules.airag.common.vo.event.EventMessageData; import org.jeecg.modules.airag.llm.entity.AiragKnowledge; import org.jeecg.modules.airag.llm.service.IAiragKnowledgeService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * @Description: AI应用 @@ -54,6 +63,9 @@ public class AiragAppServiceImpl extends ServiceImpl i @Autowired private IAiragKnowledgeService airagKnowledgeService; + + @Autowired + private RedisTemplate redisTemplate; @Override public Object generatePrompt(String prompt, boolean blocking) { @@ -247,4 +259,68 @@ public class AiragAppServiceImpl extends ServiceImpl i emitter.complete(); } } + + + /** + * 写作列表 + */ + @Override + public List listArticleWrite() { + LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String redisKey = StrUtil.format(AiAppConsts.ARTICLE_WRITER_KEY, loginUser.getUsername()); + Object data = redisTemplate.opsForValue().get(redisKey); + if (data == null) { + return new ArrayList<>(); + } + List aiWriteViewVoList = (List) data; + Collections.reverse(aiWriteViewVoList); + return aiWriteViewVoList; + } + + /** + * 写作报错 + */ + @Override + public void saveArticleWrite(AiArticleWriteVersionVo aiWriteVersionVo) { + LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String redisKey = StrUtil.format(AiAppConsts.ARTICLE_WRITER_KEY, loginUser.getUsername()); + //先查看redis中是否存在 + Object data = redisTemplate.opsForValue().get(redisKey); + if(null != data){ + List aiWriteVersionVos = (List) data; + aiWriteVersionVo.setVersion("V"+(aiWriteVersionVos.size() + 1)); + aiWriteVersionVos.add(aiWriteVersionVo); + redisTemplate.opsForValue().set(redisKey, aiWriteVersionVos); + }else{ + List aiWriteVersionVos = new ArrayList<>(); + aiWriteVersionVo.setVersion("V1"); + aiWriteVersionVos.add(aiWriteVersionVo); + redisTemplate.opsForValue().set(redisKey, aiWriteVersionVos); + } + } + + /** + * 写作删除 + */ + @Override + public void deleteArticleWrite(String version) { + LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String redisKey = StrUtil.format(AiAppConsts.ARTICLE_WRITER_KEY, loginUser.getUsername()); + Object data = redisTemplate.opsForValue().get(redisKey); + if (data == null) { + return; + } + List aiWriteVersionVos = (List) data; + if (aiWriteVersionVos.isEmpty()) { + return; + } + List newList = aiWriteVersionVos.stream() + .filter(vo -> !version.equals(vo.getVersion())) + .collect(Collectors.toList()); + if (newList.isEmpty()) { + redisTemplate.delete(redisKey); + } else { + redisTemplate.opsForValue().set(redisKey, newList); + } + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragChatServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragChatServiceImpl.java index eefea3e1f..e0395dbbe 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragChatServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/service/impl/AiragChatServiceImpl.java @@ -933,21 +933,32 @@ public class AiragChatServiceImpl implements IAiragChatService { private SseEmitter genImageChat(SseEmitter emitter, ChatSendParams sendParams, String requestId, List messages, ChatConversation chatConversation, String topicId) { AssertUtils.assertNotEmpty("请选择绘画模型", sendParams.getDrawModelId()); AIChatParams aiChatParams = new AIChatParams(); - try { - List images = sendParams.getImages(); - List> imageList = new ArrayList<>(); - if(CollectionUtils.isEmpty(images)) { - //生成图片 - imageList = aiChatHandler.imageGenerate(sendParams.getDrawModelId(), sendParams.getContent(), aiChatParams); - } else { - //图生图 - imageList = aiChatHandler.imageEdit(sendParams.getDrawModelId(), sendParams.getContent(), images, aiChatParams); - } - // 记录历史消息 - String imageMarkdown = imageList.stream().map(map -> { - String newUrl = this.uploadImage(map); - return "![](" + newUrl + ")"; - }).collect(Collectors.joining("\n")); + //update-begin---author:wangshuai---date:2026-01-26---for: 【QQYUN-14615】应用门户加入新工具:取绘画id--- + String drawModelId = sendParams.getDrawModelId(); + if(oConvertUtils.isEmpty(sendParams.getDrawModelId())){ + AiragApp app = chatConversation.getApp(); + String metadata = app.getMetadata(); + if(oConvertUtils.isNotEmpty(metadata) && metadata.contains("drawModelId")){ + drawModelId = JSONObject.parseObject(drawModelId).getString("drawModelId"); + } + } + + try { + List images = sendParams.getImages(); + List> imageList; + if(CollectionUtils.isEmpty(images)) { + //生成图片 + imageList = aiChatHandler.imageGenerate(drawModelId, sendParams.getContent(), aiChatParams); + } else { + //图生图 + imageList = aiChatHandler.imageEdit(drawModelId, sendParams.getContent(), images, aiChatParams); + } + // 记录历史消息 + String imageMarkdown = imageList.stream().map(map -> { + String newUrl = this.uploadImage(map); + return "![](" + newUrl + ")"; + }).collect(Collectors.joining("\n")); + //update-end---author:wangshuai---date:2026-01-26---for:【QQYUN-14615】应用门户加入新工具:取绘画id--- AiMessage aiMessage = new AiMessage(imageMarkdown); appendMessage(messages, aiMessage, chatConversation, topicId); // 处理绘画结果并通过SSE返回给客户端 @@ -1868,18 +1879,46 @@ public class AiragChatServiceImpl implements IAiragChatService { @Override public SseEmitter genAiWriter(AiWriteGenerateVo aiWriteGenerateVo) { String activeMode = "compose"; + String reply = "reply"; ChatSendParams sendParams = new ChatSendParams(); - sendParams.setAppId(AiAppConsts.WRITER_APP_ID); + sendParams.setAppId(AiAppConsts.ARTICLE_WRITER_FLOW_ID); String content = ""; //写作 if (activeMode.equals(aiWriteGenerateVo.getActiveMode())) { content = StrUtil.format(Prompts.AI_WRITER_PROMPT, aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength()); - } else { + } else if(reply.equals(aiWriteGenerateVo.getActiveMode())){ //回复 content = StrUtil.format(Prompts.AI_REPLY_PROMPT, aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getOriginalContent(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength()); + } else { + content = StrUtil.format(Prompts.AI_TOUCHE_PROMPT, aiWriteGenerateVo.getPrompt(), aiWriteGenerateVo.getFormat(), aiWriteGenerateVo.getTone(), aiWriteGenerateVo.getLanguage(), aiWriteGenerateVo.getLength()); } sendParams.setContent(content); - sendParams.setIzSaveSession(false); - return this.send(sendParams); + //组装会话 + String requestId = UUIDGenerator.generate(); + String topicId = UUIDGenerator.generate(); + String conversationId = UUIDGenerator.generate(); + ChatConversation chatConversation = new ChatConversation(); + chatConversation.setId(conversationId); + chatConversation.setMessages(new ArrayList<>()); + Map flowInputs = new HashMap<>(); + flowInputs.put("type", aiWriteGenerateVo.getActiveMode()); + flowInputs.put("version", "V1"); + chatConversation.setFlowInputs(flowInputs); + SseEmitter emitter = createSSE(requestId); + // 缓存emitter + AiragLocalCache.put(AiragConsts.CACHE_TYPE_SSE, requestId, emitter); + // 缓存开始发送时间 + log.info("[AI-CHAT]开始发送消息,requestId:{}", requestId); + AiragLocalCache.put(AiragConsts.CACHE_TYPE_SSE_SEND_TIME, requestId, System.currentTimeMillis()); + // 初始化历史消息缓存 + AiragLocalCache.put(AiragConsts.CACHE_TYPE_SSE_HISTORY_MSG, requestId, new CopyOnWriteArrayList<>()); + + // 发送就绪消息 + EventData eventRequestId = new EventData(requestId, null, EventData.EVENT_INIT_REQUEST_ID, chatConversation.getId(), topicId); + eventRequestId.setData(EventMessageData.builder().message("").build()); + sendMessage2Client(emitter, eventRequestId); + + sendWithFlow(requestId, AiAppConsts.ARTICLE_WRITER_FLOW_ID, chatConversation, topicId, new ArrayList<>(), sendParams); + return emitter; } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/vo/AiArticleWriteVersionVo.java b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/vo/AiArticleWriteVersionVo.java new file mode 100644 index 000000000..27308352e --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/vo/AiArticleWriteVersionVo.java @@ -0,0 +1,23 @@ +package org.jeecg.modules.airag.app.vo; + +import lombok.Data; + +/** +* @Description: AI写作版本号 +* +* @author: wangshuai +* @date: 2026/1/16 11:57 +*/ +@Data +public class AiArticleWriteVersionVo { + + /** + * 当前版本号 + */ + private String version; + + /** + * 写作内容 + */ + private String content; +} diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml index 8722baac6..8d00e4d25 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml @@ -25,7 +25,7 @@ spring: # lazy-initialization: true flyway: # 是否启用flyway - enabled: false + enabled: true # 迁移sql脚本存放路径 locations: classpath:flyway/sql/mysql # 是否关闭要清除已有库下的表功能,生产环境必须为true,否则会删库,非常重要!!! diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.1_1__add_aiapp_img_gen.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.1_1__add_aiapp_img_gen.sql new file mode 100644 index 000000000..bb469a7a7 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.1_1__add_aiapp_img_gen.sql @@ -0,0 +1,3 @@ +INSERT INTO `airag_app` (`id`, `create_by`, `create_time`, `update_by`, `update_time`, `sys_org_code`, `tenant_id`, `name`, `descr`, `icon`, `type`, `prologue`, `prompt`, `model_id`, `knowledge_ids`, `flow_id`, `status`, `msg_num`, `metadata`, `preset_question`, `quick_command`, `plugins`, `memory_id`, `variables`, `iz_open_memory`, `memory_prompt`) VALUES ('2008090512835629057', 'admin', '2026-01-05 16:17:41', 'admin', '2026-01-26 10:36:57', 'A05A01A01', NULL, '绘画_示例', NULL, NULL, 'chatSimple', NULL, '# 角色:文生图创意引擎\n你是一位精通视觉艺术与AI绘画的创意引擎,能将抽象的文字描述转化为精准、高质量、富有艺术感的图像提示词。\n\n## 目标:\n根据用户提供的文字描述,生成可直接用于主流AI绘画模型(如Midjourney、Stable Diffusion、DALL-E)的详细、结构化、高成功率的提示词,以帮助用户高效获得理想的视觉作品。\n\n## 技能:\n1. **深度语义理解**:准确解析用户描述的意图、核心元素、氛围和情感。\n2. **视觉元素拆解与重构**:将抽象概念分解为具体的视觉构成要素(主体、环境、风格、构图、光影、材质等)。\n3. **提示词工程优化**:精通各类AI绘画模型的语法规则,熟练运用权重分配、负面提示、参数设置等技巧。\n4. **艺术风格知识库**:掌握从古典到现代,从写实到抽象的各种艺术流派、画家风格、电影摄影术语。\n5. **多方案生成与评估**:能针对同一需求提供不同侧重点的提示词变体,并简要说明其预期效果差异。\n\n## 工作流:\n1. **需求澄清与细化**:首先与用户确认其描述中的模糊点(如“好看”具体指什么风格?),并主动询问关键细节(如画幅比例、主要色彩倾向、是否包含特定艺术家风格)。\n2. **结构化提示词构建**:按照“主体描述 + 环境/背景 + 艺术风格/媒介 + 构图/视角 + 光照/色彩 + 画质/参数 + (负面提示)”的逻辑结构构建提示词。\n3. **优化与变体提供**:生成一个主推的、最符合描述的详细提示词。同时,提供1-2个在风格或侧重点上略有不同的变体选项,供用户选择或组合。\n4. **使用建议**:简要说明该提示词在目标平台(如Midjourney)中可能需要调整的参数建议(如 `--ar 16:9`, `--v 6.0`)。\n\n## 输出格式:\n请严格按照以下格式输出,使用清晰的标题和分点:\n\n**用户需求分析摘要:**\n- 核心主题:\n- 期望风格/氛围:\n- 关键视觉元素:\n- 已确认细节:\n\n**主推提示词 (适用于 Midjourney/Stable Diffusion):**\n`[完整的、结构化的英文提示词,包含必要的权重符号如 :: 和参数]`\n\n**提示词变体选项:**\n1. **[变体名称,如“更写实风格”]**:`[变体提示词]`\n * *效果说明:此变体侧重于...*\n2. **[变体名称,如“更抽象表现”]**:`[变体提示词]`\n * *效果说明:此变体侧重于...*\n\n**使用建议:**\n- **平台参数**:建议添加 `--ar [比例] --s [风格化值] --v [版本]` (根据分析给出具体建议)。\n- **调整建议**:如需更...效果,可尝试在提示词中加入“...”关键词;如需避免...,可在负面提示中添加“...”。\n\n## 限制:\n- **反幻觉校验**:所有基于事实的风格或元素引用需确保准确性(如“梵高风格”),若不确定具体特征,用“[需核实具体时期或作品特征]”标注。\n- **伦理与合规**:自动过滤涉及现实人物肖像权争议、暴力血腥、成人内容、特定商标版权等敏感描述。若用户需求涉及潜在风险,应引导至合规表达(如“一个风格化的卡通英雄形象”代替具体超级英雄)。\n- **聚焦提示词本身**:不生成实际图像,不解释AI绘画原理,所有输出必须围绕“生成更好的图像提示词”这一核心任务。\n- **清晰简洁**:在保证信息完整的前提下,提示词和说明应尽可能精炼,避免冗长堆砌关键词。', '1897481367743143938', '', NULL, 'enable', 1, '{\"modelInfo\":{\"provider\":\"DEEPSEEK\",\"modelType\":\"LLM\",\"modelName\":\"deepseek-chat\"},\"izDraw\":\"1\",\"drawModelId\":\"2008060119398899713\"}', NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +INSERT INTO `airag_model` (`id`, `create_by`, `create_time`, `update_by`, `update_time`, `sys_org_code`, `tenant_id`, `name`, `provider`, `model_name`, `credential`, `base_url`, `model_type`, `model_params`, `activate_flag`) VALUES ('2008060119398899713', 'admin', '2026-01-05 14:16:55', 'admin', '2026-01-27 20:11:51', 'A05A01A01', NULL, '智普图片生成', 'ZHIPU', 'glm-image', '{\"apiKey\":\"76ca78587074479d8939a13\"}', 'https://open.bigmodel.cn', 'IMAGE', NULL, 1); \ No newline at end of file diff --git a/jeecg-boot/pom.xml b/jeecg-boot/pom.xml index ff01558ff..f820f6469 100644 --- a/jeecg-boot/pom.xml +++ b/jeecg-boot/pom.xml @@ -546,7 +546,7 @@ org.jeecgframework.boot3 jeecg-boot-starter-chatgpt - 3.9.1 + 3.9.1.1 diff --git a/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/AppPortal.vue b/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/AppPortal.vue index a29840e84..1caa2e1a2 100644 --- a/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/AppPortal.vue +++ b/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/AppPortal.vue @@ -25,8 +25,8 @@ :historyData="historyData" type="view" :formState="appData" - :prologue="appData.prologue" - :presetQuestion="appData.presetQuestion" + :prologue="appData?.prologue" + :presetQuestion="appData?.presetQuestion" @reload-message-title="reloadMessageTitle" :chatTitle="chatTitle" :conversationSettings="getCurrentSettings" diff --git a/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/LeftPortalSession.vue b/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/LeftPortalSession.vue index e04404e70..92b513999 100644 --- a/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/LeftPortalSession.vue +++ b/jeecgboot-vue3/src/views/super/airag/aiapp/chat/portal/LeftPortalSession.vue @@ -108,6 +108,21 @@ name: '看图说话', icon: 'https://jeecgdev.oss-cn-beijing.aliyuncs.com/temp/工具-图片解析_1743065064801.png', prologue: '上传一张图片,我来为你讲述图片中的故事', + }, + { + id: '2008448202536456193', + name: 'Chat2BI', + icon: 'https://minio.jeecg.com/otatest/chatShow_1769395642452.png', + prologue: '你好,我是图表生成智能体。', + flowId: '2008379264947519489', + type: 'chatFLow', + presetQuestion: '[{"key":1,"descr":"用户性别比例","update":true}]' + }, + { + id: '2008090512835629057', + name: 'AI绘画', + icon: 'https://minio.jeecg.com/otatest/AiWrite_1769395779558.png', + prologue: '请输入文本,并选择图像生成,我来为你生成图片', }, ]); diff --git a/jeecgboot-vue3/src/views/super/airag/aiapp/components/AiAppGeneratedPromptModal.vue b/jeecgboot-vue3/src/views/super/airag/aiapp/components/AiAppGeneratedPromptModal.vue index 7146ae6bd..09da4ca97 100644 --- a/jeecgboot-vue3/src/views/super/airag/aiapp/components/AiAppGeneratedPromptModal.vue +++ b/jeecgboot-vue3/src/views/super/airag/aiapp/components/AiAppGeneratedPromptModal.vue @@ -16,7 +16,14 @@
-
指令
+
+ 指令 + + + 词库选择 + + +
@@ -50,17 +57,21 @@ + +