mirror of
https://github.com/mfish-qf/mfish-nocode.git
synced 2026-08-28 11:11:30 +08:00
feat: 增加前端操作
This commit is contained in:
@@ -50,8 +50,6 @@
|
||||
--chart-series-1: #3C2ECA;
|
||||
--chart-series-2: #A9AEFF;
|
||||
--chart-series-3: #6F6FFF;
|
||||
--chart-series-4: #22A5F7;
|
||||
--chart-other: #D3D4DA;
|
||||
--accent: #27D2BF;
|
||||
--accent-soft: #EAFBF8;
|
||||
--accent-text: #0F766E;
|
||||
@@ -65,7 +63,6 @@
|
||||
--spacer-20: 20px;
|
||||
--spacer-24: 24px;
|
||||
--font-sans: "SF Pro Text", "PingFang SC", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
--font-metric: "Inter", "SF Pro Text", "PingFang SC", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
--font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
||||
--weight-regular: 400;
|
||||
--weight-medium: 500;
|
||||
@@ -86,136 +83,135 @@
|
||||
--brand-soft: #1A1759;
|
||||
--brand-soft-strong: #3C2ECA;
|
||||
--brand-text: #CFD8FF;
|
||||
--chart-series-1: #4B3FE3;
|
||||
--accent-soft: #123F3C;
|
||||
--accent-text: #CCFBF1;
|
||||
}
|
||||
.widget {
|
||||
color: var(--text);
|
||||
background: transparent;
|
||||
font: var(--weight-regular) var(--text-body) var(--font-sans);
|
||||
}
|
||||
.arch-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-card);
|
||||
padding: var(--spacer-20);
|
||||
}
|
||||
.arch-title {
|
||||
font: var(--weight-medium) var(--text-title) var(--font-sans);
|
||||
color: var(--text);
|
||||
margin: 0 0 var(--spacer-4) 0;
|
||||
}
|
||||
.arch-sub {
|
||||
font: var(--weight-regular) var(--text-caption) var(--font-sans);
|
||||
color: var(--text-muted);
|
||||
margin: 0 0 var(--spacer-16) 0;
|
||||
}
|
||||
.widget { color: var(--text); background: white; font: var(--weight-regular) var(--text-body) var(--font-sans); }
|
||||
.t { fill: var(--text); font: var(--weight-regular) var(--text-body) var(--font-sans); }
|
||||
.th { fill: var(--text); font: var(--weight-medium) var(--text-body) var(--font-sans); }
|
||||
.ts { fill: var(--text-muted); font: var(--weight-regular) var(--text-caption) var(--font-sans); }
|
||||
.tc { fill: var(--text); font: var(--weight-medium) var(--text-code) var(--font-mono); }
|
||||
.tcode { fill: var(--text-muted); font: var(--weight-regular) var(--text-code) var(--font-mono); }
|
||||
.arr { stroke: var(--text-muted); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; fill: none; }
|
||||
.arr-brand { stroke: var(--brand); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; fill: none; }
|
||||
.boundary { fill: var(--surface-muted); stroke: var(--border); stroke-dasharray: 4 4; }
|
||||
.boundary-brand { fill: var(--brand-soft); stroke: var(--brand); stroke-dasharray: 4 4; }
|
||||
.node { fill: var(--surface); stroke: var(--border); }
|
||||
.node-brand { fill: var(--surface); stroke: var(--brand); }
|
||||
.legend-row { display: flex; align-items: center; gap: var(--spacer-8); font: var(--weight-regular) var(--text-caption) var(--font-sans); color: var(--text-muted); }
|
||||
.legend-swatch { width: 14px; height: 10px; border-radius: 3px; flex-shrink: 0; }
|
||||
.legend-line { width: 18px; height: 2px; flex-shrink: 0; }
|
||||
.arr-brand { stroke: var(--brand); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; fill: none; }
|
||||
.boundary { fill: none; stroke: var(--border); stroke-width: 1.2; stroke-dasharray: 5 4; rx: 12; }
|
||||
.boundary-brand { fill: none; stroke: var(--brand); stroke-width: 1.4; stroke-dasharray: 5 4; rx: 12; opacity: 0.7; }
|
||||
.chip { fill: var(--surface-muted); stroke: var(--border); stroke-width: 1; rx: 6; }
|
||||
.chip-brand { fill: var(--brand-soft); stroke: var(--brand); stroke-width: 1; rx: 6; }
|
||||
rect.c-neutral { fill: var(--surface); stroke: var(--border); stroke-width: 1.2; rx: 8; }
|
||||
rect.c-brand { fill: var(--brand-soft); stroke: var(--brand); stroke-width: 1.6; rx: 8; }
|
||||
rect.c-accent { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1.2; rx: 8; }
|
||||
.c-brand ~ .th, .c-brand ~ .t { fill: var(--brand-text); }
|
||||
</style>
|
||||
<div class="widget arch-card" data-dynamic-ui-widget data-template="node-flow">
|
||||
<h3 class="arch-title">mfish-nocode AI 能力架构</h3>
|
||||
<p class="arch-sub">三支柱编排:Planner 规划 · Capability Engine 能力聚合 · Memory+LLM 上下文路由</p>
|
||||
<svg viewBox="0 0 720 600" width="100%" height="auto" role="img" aria-label="AI能力架构图">
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto">
|
||||
<path d="M1 1 L7 4 L1 7 Z" fill="#52525B"/>
|
||||
</marker>
|
||||
<marker id="arrow-brand" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto">
|
||||
<path d="M1 1 L7 4 L1 7 Z" fill="#4B3FE3"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<!-- Tier 1: Entry Layer -->
|
||||
<rect class="boundary" x="80" y="24" width="560" height="86" rx="12"/>
|
||||
<text class="ts" x="360" y="44" text-anchor="middle">入口层 · Entry Points</text>
|
||||
<rect class="node" x="100" y="54" width="160" height="46" rx="8"/>
|
||||
<text class="tc" x="180" y="74" text-anchor="middle">/router</text>
|
||||
<text class="ts" x="180" y="90" text-anchor="middle">路由聊天</text>
|
||||
<rect class="node" x="280" y="54" width="160" height="46" rx="8"/>
|
||||
<text class="tc" x="360" y="74" text-anchor="middle">/assist/chat</text>
|
||||
<text class="ts" x="360" y="90" text-anchor="middle">垂直助手</text>
|
||||
<rect class="node" x="460" y="54" width="160" height="46" rx="8"/>
|
||||
<text class="tc" x="540" y="74" text-anchor="middle">/agent/chat</text>
|
||||
<text class="ts" x="540" y="90" text-anchor="middle">自主规划</text>
|
||||
<!-- Connector: Entry → AgentRuntime -->
|
||||
<path class="arr-brand" d="M 360 110 L 360 140" marker-end="url(#arrow-brand)"/>
|
||||
<!-- Tier 2: AgentRuntime (brand focal) -->
|
||||
<rect class="node-brand" x="230" y="140" width="260" height="54" rx="8" fill="var(--brand-soft)"/>
|
||||
<text class="th" x="360" y="163" text-anchor="middle" fill="var(--brand-text)">AgentRuntime 编排器</text>
|
||||
<text class="ts" x="360" y="181" text-anchor="middle" fill="var(--brand)">Plan → Execute → Emit</text>
|
||||
<!-- Connectors: AgentRuntime → 3 Pillars (junction at y=210) -->
|
||||
<path class="arr" d="M 360 194 L 360 210 L 140 210 L 140 220" marker-end="url(#arrow)"/>
|
||||
<path class="arr-brand" d="M 360 194 L 360 220" marker-end="url(#arrow-brand)"/>
|
||||
<path class="arr" d="M 360 194 L 360 210 L 580 210 L 580 220" marker-end="url(#arrow)"/>
|
||||
<!-- Pillar 1: Planner (neutral) -->
|
||||
<rect class="boundary" x="40" y="220" width="200" height="170" rx="12"/>
|
||||
<text class="ts" x="140" y="240" text-anchor="middle">Planner 柱 · 规划</text>
|
||||
<rect class="node" x="60" y="250" width="160" height="32" rx="8"/>
|
||||
<text class="t" x="140" y="270" text-anchor="middle">Planner 任务规划</text>
|
||||
<rect class="node" x="60" y="294" width="160" height="32" rx="8"/>
|
||||
<text class="t" x="140" y="314" text-anchor="middle">Executor 步骤执行</text>
|
||||
<rect class="node" x="60" y="338" width="160" height="32" rx="8"/>
|
||||
<text class="t" x="140" y="358" text-anchor="middle">EventBus 事件流</text>
|
||||
<path class="arr" d="M 140 282 L 140 294" marker-end="url(#arrow)"/>
|
||||
<path class="arr" d="M 140 326 L 140 338" marker-end="url(#arrow)"/>
|
||||
<!-- Pillar 2: CapabilityEngine (brand focal) -->
|
||||
<rect class="boundary-brand" x="260" y="220" width="200" height="170" rx="12"/>
|
||||
<text class="ts" x="360" y="240" text-anchor="middle" fill="var(--brand)">Capability Engine · 能力聚合</text>
|
||||
<rect class="node-brand" x="280" y="250" width="160" height="26" rx="8"/>
|
||||
<text class="tc" x="360" y="267" text-anchor="middle">ToolCapability</text>
|
||||
<rect class="node-brand" x="280" y="284" width="160" height="26" rx="8"/>
|
||||
<text class="tc" x="360" y="301" text-anchor="middle">McpCapability</text>
|
||||
<rect class="node-brand" x="280" y="318" width="160" height="26" rx="8"/>
|
||||
<text class="tc" x="360" y="335" text-anchor="middle">SkillCapability</text>
|
||||
<rect class="node-brand" x="280" y="352" width="160" height="26" rx="8"/>
|
||||
<text class="tc" x="360" y="369" text-anchor="middle">WorkflowCapability</text>
|
||||
<!-- Pillar 3: Memory + LLM (neutral) -->
|
||||
<rect class="boundary" x="480" y="220" width="200" height="170" rx="12"/>
|
||||
<text class="ts" x="580" y="240" text-anchor="middle">Memory + LLM 柱 · 上下文</text>
|
||||
<rect class="node" x="500" y="258" width="160" height="44" rx="8"/>
|
||||
<text class="t" x="580" y="278" text-anchor="middle">ChatMemory</text>
|
||||
<text class="ts" x="580" y="294" text-anchor="middle">会话窗口策略</text>
|
||||
<rect class="node" x="500" y="316" width="160" height="44" rx="8"/>
|
||||
<text class="t" x="580" y="336" text-anchor="middle">LlmModelRouter</text>
|
||||
<text class="ts" x="580" y="352" text-anchor="middle">多租户路由</text>
|
||||
<!-- Connector: CapabilityEngine → External -->
|
||||
<path class="arr-brand" d="M 360 390 L 360 424" marker-end="url(#arrow-brand)"/>
|
||||
<!-- Tier 4: External Systems -->
|
||||
<rect class="boundary" x="40" y="424" width="640" height="76" rx="12"/>
|
||||
<text class="ts" x="360" y="444" text-anchor="middle">外部系统 · External Systems</text>
|
||||
<rect class="node" x="60" y="456" width="140" height="34" rx="8"/>
|
||||
<text class="t" x="130" y="478" text-anchor="middle">微服务 Feign+HTTP</text>
|
||||
<rect class="node" x="220" y="456" width="140" height="34" rx="8"/>
|
||||
<text class="t" x="290" y="478" text-anchor="middle">MCP 服务器</text>
|
||||
<rect class="node" x="380" y="456" width="140" height="34" rx="8"/>
|
||||
<text class="t" x="450" y="478" text-anchor="middle">skills/*.md</text>
|
||||
<rect class="node" x="540" y="456" width="140" height="34" rx="8"/>
|
||||
<text class="t" x="610" y="478" text-anchor="middle">Flowable 工作流</text>
|
||||
<!-- Legend -->
|
||||
<g transform="translate(40, 528)">
|
||||
<rect class="boundary-brand" x="0" y="0" width="18" height="12" rx="3"/>
|
||||
<text class="ts" x="24" y="10">核心引擎</text>
|
||||
<rect class="boundary" x="100" y="0" width="18" height="12" rx="3"/>
|
||||
<text class="ts" x="124" y="10">支撑层</text>
|
||||
<line class="arr-brand" x1="200" y1="6" x2="224" y2="6"/>
|
||||
<text class="ts" x="230" y="10">主调用链</text>
|
||||
<line class="arr" x1="310" y1="6" x2="334" y2="6"/>
|
||||
<text class="ts" x="340" y="10">编排流向</text>
|
||||
</g>
|
||||
<text class="ts" x="680" y="538" text-anchor="end">mf-common-ai · mf-ai</text>
|
||||
</svg>
|
||||
|
||||
<div class="widget" data-dynamic-ui-widget data-template="node-flow" data-mounted="true" style="padding:4px">
|
||||
<svg viewBox="0 0 720 820" width="100%" height="auto" role="img" aria-label="AI 服务架构图">
|
||||
<defs>
|
||||
<marker id="ah" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto">
|
||||
<path d="M1 1 L7 4 L1 7 Z" fill="var(--text-muted)"/>
|
||||
</marker>
|
||||
<marker id="ahb" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="8" markerHeight="8" markerUnits="userSpaceOnUse" orient="auto">
|
||||
<path d="M1 1 L7 4 L1 7 Z" fill="var(--brand)"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<text x="360" y="28" text-anchor="middle" class="th" style="font-size:15px">AI 服务架构图(重构后)</text>
|
||||
|
||||
<!-- L1 Entry -->
|
||||
<rect class="boundary" x="40" y="50" width="640" height="100"/>
|
||||
<rect class="chip" x="52" y="42" width="120" height="20"/>
|
||||
<text x="112" y="56" text-anchor="middle" class="ts">入口层 Entry</text>
|
||||
<rect class="c-neutral" x="60" y="82" width="186" height="52"/>
|
||||
<text x="153" y="104" text-anchor="middle" class="th">Chat 入口</text>
|
||||
<text x="153" y="122" text-anchor="middle" class="tcode">AiController</text>
|
||||
<rect class="c-neutral" x="267" y="82" width="186" height="52"/>
|
||||
<text x="360" y="104" text-anchor="middle" class="th">Router 路由</text>
|
||||
<text x="360" y="122" text-anchor="middle" class="tcode">RouterController</text>
|
||||
<rect class="c-neutral" x="474" y="82" width="186" height="52"/>
|
||||
<text x="567" y="104" text-anchor="middle" class="th">Agent 智能体</text>
|
||||
<text x="567" y="122" text-anchor="middle" class="tcode">AgentController</text>
|
||||
|
||||
<!-- arrow L1->L2 -->
|
||||
<path class="arr" d="M360 150 L360 172" marker-end="url(#ah)"/>
|
||||
|
||||
<!-- L2 Assistant -->
|
||||
<rect class="boundary" x="40" y="175" width="640" height="92"/>
|
||||
<rect class="chip" x="52" y="167" width="150" height="20"/>
|
||||
<text x="127" y="181" text-anchor="middle" class="ts">Assistant 层(模板方法)</text>
|
||||
<rect class="c-neutral" x="60" y="205" width="600" height="50"/>
|
||||
<text x="360" y="227" text-anchor="middle" class="th">BaseAssistant · 按租户实时构建 ChatClient</text>
|
||||
<text x="360" y="245" text-anchor="middle" class="tcode">MfishAssistant / SysAssistant / AgentAssistant …</text>
|
||||
|
||||
<!-- arrow L2->L3 (brand) -->
|
||||
<path class="arr-brand" d="M360 267 L360 289" marker-end="url(#ahb)"/>
|
||||
|
||||
<!-- L3 Runtime (BRAND focal) -->
|
||||
<rect class="boundary-brand" x="40" y="292" width="640" height="110"/>
|
||||
<rect class="chip-brand" x="52" y="284" width="210" height="20"/>
|
||||
<text x="157" y="298" text-anchor="middle" class="ts" style="fill:var(--brand)">运行时边界 Runtime(新)</text>
|
||||
<rect class="c-brand" x="60" y="322" width="290" height="62"/>
|
||||
<text x="205" y="345" text-anchor="middle" class="th">ToolRuntime</text>
|
||||
<text x="205" y="363" text-anchor="middle" class="ts" style="fill:var(--brand)">工具聚合·上下文·提示词·前端通道</text>
|
||||
<text x="205" y="378" text-anchor="middle" class="tcode" style="fill:var(--brand)">resolveServiceIds / buildToolContext</text>
|
||||
<rect class="c-brand" x="370" y="322" width="290" height="62"/>
|
||||
<text x="515" y="345" text-anchor="middle" class="th">AgentOrchestrator</text>
|
||||
<text x="515" y="363" text-anchor="middle" class="ts" style="fill:var(--brand)">Agent 模式编排(规划+执行)</text>
|
||||
<text x="515" y="378" text-anchor="middle" class="tcode" style="fill:var(--brand)">Planner · Executor</text>
|
||||
|
||||
<!-- arrow L3->L4 -->
|
||||
<path class="arr-brand" d="M360 402 L360 424" marker-end="url(#ahb)"/>
|
||||
|
||||
<!-- L4 Tool Aggregation -->
|
||||
<rect class="boundary" x="40" y="427" width="640" height="110"/>
|
||||
<rect class="chip" x="52" y="419" width="150" height="20"/>
|
||||
<text x="127" y="433" text-anchor="middle" class="ts">工具聚合层</text>
|
||||
<rect class="c-neutral" x="60" y="457" width="290" height="62"/>
|
||||
<text x="205" y="480" text-anchor="middle" class="th">ApiToolEngine</text>
|
||||
<text x="205" y="498" text-anchor="middle" class="ts">按 serviceId 合并工具</text>
|
||||
<text x="205" y="513" text-anchor="middle" class="tcode">register / replace</text>
|
||||
<rect class="c-neutral" x="370" y="457" width="290" height="62"/>
|
||||
<text x="515" y="480" text-anchor="middle" class="th">CapabilityEngine</text>
|
||||
<text x="515" y="498" text-anchor="middle" class="ts">四子引擎异步注册</text>
|
||||
<text x="515" y="513" text-anchor="middle" class="tcode">Tool / MCP / Skill / Workflow</text>
|
||||
|
||||
<!-- arrow L4->L5 -->
|
||||
<path class="arr" d="M360 537 L360 559" marker-end="url(#ah)"/>
|
||||
|
||||
<!-- L5 Fault Tolerance -->
|
||||
<rect class="boundary" x="40" y="562" width="640" height="92"/>
|
||||
<rect class="chip" x="52" y="554" width="120" height="20"/>
|
||||
<text x="112" y="568" text-anchor="middle" class="ts">容错层</text>
|
||||
<rect class="c-accent" x="60" y="592" width="600" height="50"/>
|
||||
<text x="360" y="614" text-anchor="middle" class="th">FaultTolerantToolCallingManager</text>
|
||||
<text x="360" y="632" text-anchor="middle" class="ts" style="fill:var(--accent-text)">无效工具容错 + 按 Skill toolOrder 排序(setter 注入 ToolOrderProvider)</text>
|
||||
|
||||
<!-- arrow L5->L6 -->
|
||||
<path class="arr" d="M360 642 L360 664" marker-end="url(#ah)"/>
|
||||
|
||||
<!-- L6 Cross-cutting -->
|
||||
<rect class="boundary" x="40" y="667" width="640" height="100"/>
|
||||
<rect class="chip" x="52" y="659" width="120" height="20"/>
|
||||
<text x="112" y="673" text-anchor="middle" class="ts">横切层</text>
|
||||
<rect class="c-neutral" x="60" y="699" width="186" height="52"/>
|
||||
<text x="153" y="721" text-anchor="middle" class="th">模型路由</text>
|
||||
<text x="153" y="739" text-anchor="middle" class="tcode">LlmModelRouter</text>
|
||||
<rect class="c-neutral" x="267" y="699" width="186" height="52"/>
|
||||
<text x="360" y="721" text-anchor="middle" class="th">会话记忆</text>
|
||||
<text x="360" y="739" text-anchor="middle" class="tcode">ConversationMemoryStore</text>
|
||||
<rect class="c-neutral" x="474" y="699" width="186" height="52"/>
|
||||
<text x="567" y="721" text-anchor="middle" class="th">前端双通道</text>
|
||||
<text x="567" y="739" text-anchor="middle" class="tcode">FrontendActionHolder</text>
|
||||
|
||||
<!-- Legend -->
|
||||
<rect class="chip" x="40" y="785" width="640" height="24"/>
|
||||
<circle cx="58" cy="797" r="5" fill="var(--brand-soft)" stroke="var(--brand)" stroke-width="1.4"/>
|
||||
<text x="70" y="801" class="ts">新边界(ToolRuntime)</text>
|
||||
<circle cx="210" cy="797" r="5" fill="var(--surface)" stroke="var(--border)" stroke-width="1.2"/>
|
||||
<text x="222" y="801" class="ts">标准模块</text>
|
||||
<circle cx="300" cy="797" r="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2"/>
|
||||
<text x="312" y="801" class="ts">容错/排序</text>
|
||||
<line x1="380" y1="797" x2="408" y2="797" class="arr-brand"/>
|
||||
<text x="416" y="801" class="ts">主数据流</text>
|
||||
<line x1="480" y1="797" x2="508" y2="797" class="arr"/>
|
||||
<text x="516" y="801" class="ts">调用/依赖</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
### 智能网关路由
|
||||
|
||||
@@ -58,7 +58,7 @@ public class MfishAssistant extends BaseAssistant {
|
||||
"""
|
||||
## 工具使用与交互规则
|
||||
你可以使用系统提供的工具来帮助用户完成操作。工具分为四类:
|
||||
- skill 开头的工具:平台领域知识包(如 skill.code-gen-guide 代码生成指导、skill.leave-apply 请假申请指导),
|
||||
- skill 开头的工具:平台领域知识包(如 skill.code-build 代码生成指导、skill.leave-apply 请假申请指导),
|
||||
调用后会返回专业操作指南,指南中包含完整的多步操作流程(含前端操作步骤)。
|
||||
- frontend. 开头的工具:前端操作工具(如 frontend.navigate 路由跳转、frontend.refresh 刷新页面),
|
||||
用于触发前端 UI 交互。当 skill 指南中包含前端操作步骤时,必须实际调用这些工具。
|
||||
@@ -69,8 +69,9 @@ public class MfishAssistant extends BaseAssistant {
|
||||
1. 先分析需求:理解用户想做什么,判断属于哪个领域(代码生成?工作流?权限?请假?)
|
||||
2. 【强制】优先调用对应 skill 工具:
|
||||
- 用户要"请假/年假/事假/病假"→ 先调用 skill.leave-apply 获取请假流程指南
|
||||
- 用户要"创建代码/生成代码"→ 先调用 skill.code-gen-guide 获取代码生成流程指南
|
||||
- 用户要"创建代码/生成代码/为表XX生成代码"→ 先调用 skill.code-build 获取代码生成流程指南
|
||||
- 用户要"工作流/审批流"→ 先调用 skill.workflow-guide 获取工作流指南
|
||||
- 用户要"打开/跳转/进入XX页面"→ 先调用 skill.page-navigate 获取页面导航指南
|
||||
3. 【最关键】调用 skill 后必须继续执行指南步骤:
|
||||
- skill 工具返回的是操作指南,不是最终答案!你尚未完成任何操作!
|
||||
- 获取指南后,必须立即按指南中的步骤顺序,逐个调用对应的工具(包括 frontend.navigate、
|
||||
@@ -90,9 +91,12 @@ public class MfishAssistant extends BaseAssistant {
|
||||
调用 demoLeaveApply.submit → 等待返回 → 调用 frontend.refresh → 等待返回 → 汇总反馈。
|
||||
6. 【关键】前端操作不得跳过:当 skill 指南中包含 frontend.navigate 或 frontend.refresh 步骤时,
|
||||
必须实际调用对应的 frontend 工具。这些操作会触发前端页面跳转和数据刷新,是完整业务流程的一部分。
|
||||
7. 精确选择工具:仔细阅读工具名和描述,不要把"代码生成"工具和"自助API"工具混淆。
|
||||
7. 【强制】禁止编造路由地址:当需要前端跳转时,必须通过 menu.queryRoutePaths 工具查询真实路由地址,
|
||||
严禁根据常识、训练数据或 skill 示例猜测路由地址(如 /screen、/user、/demo 等)。
|
||||
frontend.navigate 的 target 参数必须来自 menu.queryRoutePaths 的返回结果。
|
||||
8. 精确选择工具:仔细阅读工具名和描述,不要把"代码生成"工具和"自助API"工具混淆。
|
||||
工具名前缀代表所属服务:sys=系统服务、oauth=认证服务、nocode=低代码服务、skill=技能包、frontend=前端操作
|
||||
8. 工具结果反馈:所有工具调用完成后,将最终结果用通俗易懂的方式告诉用户
|
||||
9. 工具结果反馈:所有工具调用完成后,将最终结果用通俗易懂的方式告诉用户
|
||||
""";
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
name: code-build
|
||||
type: guide
|
||||
requires: mf-sys,frontend
|
||||
toolOrder: dbConnect.query,frontend.navigate,codeBuild.add,frontend.refresh
|
||||
deferredTools: frontend.refresh
|
||||
description: 指导 AI 完成代码生成的完整流程:查询数据库连接、跳转代码生成页面、创建代码生成记录、刷新列表
|
||||
---
|
||||
|
||||
【执行指令 - 立即执行】这是操作指南,不是最终答案!你尚未执行任何操作!
|
||||
获取本指南后,必须立即按"执行步骤"中的顺序,逐个调用对应工具(dbConnect.query → frontend.navigate → codeBuild.add → frontend.refresh)。
|
||||
严禁仅返回指南内容而不执行!严禁出现"我无法调用"、"请您手动操作"等表述!
|
||||
工具已就绪,你必须实际调用它们完成代码生成记录的创建。
|
||||
|
||||
你是摸鱼低代码平台的代码生成助手。当用户表达"生成代码"、"代码生成"、"创建代码生成记录"、"为表XX生成代码"等意图时,按以下流程操作。
|
||||
|
||||
## 前置信息收集
|
||||
|
||||
在调用 codeBuild.add 前,需要确认以下信息。**能从用户输入合理推断的字段无需追问**,只有真正缺失且无法推断的字段才需要向用户追问:
|
||||
|
||||
| 信息 | 字段 | 说明 | 推断规则 |
|
||||
|------|------|------|----------|
|
||||
| 数据库表名 | tableName | 要生成代码的数据库表名 | 用户必须提供(如"sys_user"),无法推断 |
|
||||
| 实体类名 | entityName | Java 实体类名 | 不传则系统自动用表名驼峰化(如 sys_user → SysUser),用户未明确指定时不填 |
|
||||
| 接口路径前缀 | apiPrefix | REST API 路径前缀 | 不传则系统使用包名最底层(如 cn.com.mfish.sys → sys),用户未明确指定时不填 |
|
||||
| 项目包名 | packageName | 生成代码的项目包名 | 不传则使用默认包名 cn.com.mfish.sys,用户未明确指定时不填 |
|
||||
| 表描述 | tableComment | 表的中文描述 | 不传则系统自动从数据库表注释获取,用户未明确指定时不填 |
|
||||
| 数据库连接ID | connectId | 数据库连接的唯一ID | 通过步骤1查询获取,无需用户提供 |
|
||||
|
||||
**推断示例**:
|
||||
- 用户:"为表 sys_user 生成代码"
|
||||
- tableName=sys_user,其他字段不填(使用系统默认值),connectId 通过查询获取
|
||||
- 所有字段均可推断或使用默认值,无需追问,直接执行步骤1
|
||||
|
||||
- 用户:"为表 sys_user 生成代码,实体类叫 SysUser,接口前缀 sys"
|
||||
- tableName=sys_user,entityName=SysUser,apiPrefix=sys
|
||||
- connectId 通过查询获取,直接执行步骤1
|
||||
|
||||
**仅当以下信息缺失时才追问**:
|
||||
- 用户完全没说要为哪张表生成代码(tableName 是必填项)
|
||||
|
||||
## 执行步骤(严格按顺序,每次只调用一个工具,等待返回后再调用下一个)
|
||||
|
||||
### 步骤 1:查询数据库连接列表
|
||||
- 工具:`dbConnect.query`(GET /dbConnect)
|
||||
- 无需参数(查询当前租户下所有数据库连接)
|
||||
- 从返回结果中取第一条记录的 `id` 字段作为 connectId
|
||||
- 返回结果结构:`data.list[0].id` 或 `data[0].id`(视分页结构而定)
|
||||
- 如果返回为空,告知用户需要先配置数据库连接
|
||||
|
||||
### 步骤 2:路由到代码生成页面
|
||||
- 工具:`frontend.navigate`
|
||||
- target:`/tools/code-build`
|
||||
- description:`正在为您打开代码生成页面...`
|
||||
- 必须在创建记录前调用此工具,让用户看到代码生成页面
|
||||
|
||||
### 步骤 3:创建代码生成记录
|
||||
- 工具:`codeBuild.add`(POST /codeBuild)
|
||||
- body 包含:
|
||||
- `connectId`:步骤 1 获取的数据库连接 ID
|
||||
- `tableName`:用户指定的表名(必填)
|
||||
- `entityName`:用户指定的实体类名(可选,不填则系统自动驼峰化)
|
||||
- `apiPrefix`:用户指定的接口前缀(可选,不填则系统使用包名)
|
||||
- `packageName`:用户指定的项目包名(可选,不填则使用默认包名)
|
||||
- `tableComment`:用户指定的表描述(可选,不填则系统从数据库获取)
|
||||
- 从返回结果中取出 `data.id`,这是代码生成记录的 ID
|
||||
|
||||
### 步骤 4:刷新页面
|
||||
- 工具:`frontend.refresh`
|
||||
- description:`代码生成记录已创建,正在刷新列表...`
|
||||
- 创建成功后调用此工具刷新代码生成列表,让用户看到最新记录
|
||||
|
||||
### 步骤 5:反馈结果
|
||||
向用户告知:
|
||||
- 代码生成记录已创建成功
|
||||
- 记录 ID
|
||||
- 使用的数据库表名
|
||||
- 可选操作:查看代码(codeBuild.query)、下载代码(codeBuild.downloadCode)、保存到本地(codeBuild.saveLocal)、生成菜单(codeBuild.createMenu)
|
||||
|
||||
## 可选操作
|
||||
|
||||
### 查看生成的代码
|
||||
- 工具:`codeBuild.query`(GET /codeBuild/view/{id})
|
||||
- path 参数 id 为步骤 3 返回的记录 ID
|
||||
- 返回生成的代码文件列表
|
||||
|
||||
### 下载生成的代码
|
||||
- 工具:`codeBuild.downloadCode`(GET /codeBuild/download/{id})
|
||||
- 下载为 ZIP 压缩包
|
||||
|
||||
### 保存代码到本地 IDE
|
||||
- 工具:`codeBuild.saveLocal`(GET /codeBuild/saveLocal/{id})
|
||||
- 将生成的代码保存到本地项目目录
|
||||
|
||||
### 创建菜单
|
||||
- 工具:`codeBuild.createMenu`(POST /codeBuild/menu)
|
||||
- 为生成的代码创建对应的系统菜单
|
||||
|
||||
## 禁止行为
|
||||
|
||||
- ❌ 不得仅返回本指南内容而不执行任何工具调用
|
||||
- ❌ 不得跳过 dbConnect.query(步骤1)直接调用 codeBuild.add(需要真实的 connectId)
|
||||
- ❌ 不得跳过 frontend.navigate(步骤2)直接创建记录
|
||||
- ❌ 不得跳过 frontend.refresh(步骤4)不刷新页面
|
||||
- ❌ 不得在 codeBuild.add 完成前调用 frontend.refresh
|
||||
- ❌ 不得编造 connectId(必须从 dbConnect.query 返回结果中获取)
|
||||
- ❌ 不得编造 tableName(必须由用户提供)
|
||||
- ❌ 不得出现"我无法调用"、"请您手动操作"等虚假执行表述
|
||||
- ❌ 不得一次性发起多个工具调用(必须串行:查询连接 → 跳转页面 → 创建记录 → 刷新)
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
name: page-navigate
|
||||
type: guide
|
||||
requires: mf-oauth,frontend
|
||||
toolOrder: menu.queryRoutePaths,frontend.navigate
|
||||
description: 指导 AI 根据用户意图打开平台页面。分析用户输入生成多个同义词关键词查询路由,匹配后跳转
|
||||
---
|
||||
|
||||
【执行指令 - 立即执行】这是操作指南,不是最终答案!你尚未执行任何操作!
|
||||
获取本指南后,必须立即按"执行步骤"中的顺序,逐个调用对应工具(menu.queryRoutePaths → frontend.navigate)。
|
||||
严禁仅返回指南内容而不执行!
|
||||
|
||||
你是摸鱼低代码平台的页面导航助手。当用户表达"打开XX页面"、"跳转到XX"、"进入XX"等导航意图时,按以下流程操作。
|
||||
|
||||
## 执行步骤(严格按顺序,每次只调用一个工具,等待返回后再调用下一个)
|
||||
|
||||
### 步骤 1:分析用户意图,生成多个关键词查询路由
|
||||
- 工具:`menu.queryRoutePaths`(GET /menu/routePaths)
|
||||
- **关键**:不要只用一个关键词查询,要分析用户输入,生成多个可能匹配的关键词(含同义词、近义词、英文词),用英文逗号拼接传入 keyword 参数
|
||||
- 后端支持逗号分隔的多关键词 OR 匹配,任一关键词命中菜单名称即返回
|
||||
- 返回结果为匹配的路由列表,每项包含:
|
||||
- `menuName`:菜单名称(如"自助大屏")
|
||||
- `routePath`:完整路由地址(如 `/mf-screen`)
|
||||
|
||||
**关键词生成规则**:
|
||||
1. **原词提取**:从用户输入中直接提取关键词(如"打开自助大屏"→"大屏")
|
||||
2. **同义词扩展**:补充同义词(如"大屏"→补"可视化"、"看板")
|
||||
3. **英文扩展**:补充可能的英文词(如"大屏"→补"screen"、"dashboard")
|
||||
4. **相关词扩展**:补充相关业务词(如"调度"→补"任务"、"定时"、"job")
|
||||
5. **拼接**:用英文逗号拼接所有关键词,如 `大屏,可视化,看板,screen,dashboard`
|
||||
|
||||
### 步骤 2:匹配路由并跳转
|
||||
- 工具:`frontend.navigate`
|
||||
- 从步骤 1 返回的路由列表中找到 menuName 最匹配的项
|
||||
- 将匹配项的 `routePath` 作为 target 参数传入 frontend.navigate
|
||||
- description 参数填写操作说明(如"正在为您打开自助大屏页面...")
|
||||
|
||||
## 关键词生成示例
|
||||
|
||||
| 用户输入 | 生成关键词 | 说明 |
|
||||
|---------|-----------|------|
|
||||
| 打开自助大屏 | `大屏,可视化,看板,screen,dashboard` | 原词+同义词+英文 |
|
||||
| 跳转到请假申请 | `请假,假期,leave,申请` | 原词+同义词+英文 |
|
||||
| 进入用户管理 | `用户,user,管理,账号` | 原词+英文+相关词 |
|
||||
| 打开定时任务 | `定时,任务,调度,job,scheduler,task` | 原词+同义词+英文 |
|
||||
| 跳转到工作流 | `工作流,流程,审批,workflow,flow,process` | 原词+同义词+英文 |
|
||||
| 进入数据字典 | `字典,dictionary,dict,数据` | 原词+英文+相关词 |
|
||||
| 打开代码生成 | `代码,生成,code,build,gen` | 原词+同义词+英文 |
|
||||
| 打开菜单管理 | `菜单,menu,导航,navigation` | 原词+英文+相关词 |
|
||||
| 打开角色管理 | `角色,role,权限,permission` | 原词+英文+相关词 |
|
||||
| 打开数据库连接 | `数据库,连接,database,db,connect,数据源` | 原词+同义词+英文 |
|
||||
| 打开AI模型配置 | `AI,模型,大模型,配置,model,llm` | 原词+同义词+英文 |
|
||||
|
||||
## 匹配规则
|
||||
|
||||
1. **精确匹配**:用户说的页面名称与 menuName 完全一致
|
||||
2. **包含匹配**:用户说的关键词包含在 menuName 中
|
||||
3. **未匹配**:如果查询结果为空,用更宽泛的关键词重试一次;仍为空则告知用户未找到对应页面
|
||||
|
||||
## 推断示例
|
||||
|
||||
- 用户:"打开自助大屏"
|
||||
- 生成关键词:`大屏,可视化,看板,screen,dashboard`
|
||||
- 调用 menu.queryRoutePaths keyword="大屏,可视化,看板,screen,dashboard"
|
||||
- 返回 [{menuName:"自助大屏", routePath:"<查询返回的真实路由>"}]
|
||||
- 调用 frontend.navigate target="<查询返回的真实路由>" description="正在为您打开自助大屏页面..."
|
||||
|
||||
- 用户:"跳转到请假申请"
|
||||
- 生成关键词:`请假,假期,leave,申请`
|
||||
- 调用 menu.queryRoutePaths keyword="请假,假期,leave,申请"
|
||||
- 返回 [{menuName:"请假申请", routePath:"<查询返回的真实路由>"}]
|
||||
- 调用 frontend.navigate target="<查询返回的真实路由>" description="正在为您打开请假申请页面..."
|
||||
|
||||
- 用户:"进入用户管理"
|
||||
- 生成关键词:`用户,user,管理,账号`
|
||||
- 调用 menu.queryRoutePaths keyword="用户,user,管理,账号"
|
||||
- 返回 [{menuName:"用户管理", routePath:"<查询返回的真实路由>"}]
|
||||
- 调用 frontend.navigate target="<查询返回的真实路由>" description="正在为您打开用户管理页面..."
|
||||
|
||||
## 禁止行为
|
||||
|
||||
- ❌ 不得跳过步骤 1(查询路由)直接调用 frontend.navigate
|
||||
- ❌ 不得虚构路由路径,必须从 menu.queryRoutePaths 返回的结果中获取
|
||||
- ❌ 不得从本指南示例中复制路由地址(示例中的 `<查询返回的真实路由>` 是占位符,不是真实路由)
|
||||
- ❌ 不得根据常识或训练数据猜测路由地址(如 /screen、/user、/demo 等)
|
||||
- ❌ 不得仅返回指南内容而不执行任何工具调用
|
||||
- ❌ 不得一次性发起多个工具调用(必须串行:查询路由 → 等待返回 → 跳转页面)
|
||||
- ❌ 不得只生成一个关键词查询(必须生成多个同义词/英文词提高匹配率)
|
||||
- ❌ 不得出现"我无法调用"、"请您手动操作"等虚假执行表述
|
||||
+3
-2
@@ -28,9 +28,10 @@ public interface SsoMenuService extends IService<SsoMenu> {
|
||||
Result<Boolean> routeExist(String routePath, String parentId);
|
||||
|
||||
/**
|
||||
* 查询所有菜单的完整路由地址(子菜单路由拼接父菜单路由)
|
||||
* 查询菜单的完整路由地址(子菜单路由拼接父菜单路由)
|
||||
*
|
||||
* @param keyword 菜单名称关键词(可选,为空返回全部)
|
||||
* @return 路由地址列表(含菜单名称)
|
||||
*/
|
||||
Result<List<MenuRouteVo>> queryRoutePaths();
|
||||
Result<List<MenuRouteVo>> queryRoutePaths(String keyword);
|
||||
}
|
||||
|
||||
@@ -153,10 +153,11 @@ public class SsoMenuController {
|
||||
*
|
||||
* @return 路由地址列表
|
||||
*/
|
||||
@Operation(summary = "获取所有路由地址", description = "查询所有菜单的完整路由地址(含菜单名称),子菜单路由拼接父菜单路由")
|
||||
@Operation(summary = "获取路由地址", description = "查询菜单的完整路由地址(含菜单名称),子菜单路由拼接父菜单路由。支持多个关键词(逗号分隔,OR 匹配),keyword 为空返回全部。供 AI 导航工具查询可用路由使用")
|
||||
@GetMapping("/routePaths")
|
||||
@InnerUser
|
||||
public Result<List<MenuRouteVo>> queryRoutePaths() {
|
||||
return ssoMenuService.queryRoutePaths();
|
||||
public Result<List<MenuRouteVo>> queryRoutePaths(
|
||||
@Parameter(description = "菜单名称关键词(可选,支持逗号分隔的多关键词 OR 匹配,如 '大屏,可视化,screen',为空返回全部)", example = "大屏,可视化")
|
||||
@RequestParam(required = false) String keyword) {
|
||||
return ssoMenuService.queryRoutePaths(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -178,7 +179,7 @@ public class SsoMenuServiceImpl extends ServiceImpl<SsoMenuMapper, SsoMenu> impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<List<MenuRouteVo>> queryRoutePaths() {
|
||||
public Result<List<MenuRouteVo>> queryRoutePaths(String keyword) {
|
||||
// 查询所有目录和菜单(排除按钮 menuType=2),按钮无路由地址
|
||||
List<SsoMenu> menus = baseMapper.selectList(new LambdaQueryWrapper<SsoMenu>()
|
||||
.lt(SsoMenu::getMenuType, 2)
|
||||
@@ -197,6 +198,21 @@ public class SsoMenuServiceImpl extends ServiceImpl<SsoMenuMapper, SsoMenu> impl
|
||||
routePaths.add(new MenuRouteVo(menu.getMenuName(), fullPath));
|
||||
}
|
||||
}
|
||||
// 关键词过滤:支持逗号分隔的多个关键词(OR 匹配,忽略大小写)
|
||||
// 例如 keyword="大屏,可视化,screen" → 菜单名称包含任一关键词即匹配
|
||||
if (StringUtils.isNotEmpty(keyword)) {
|
||||
String[] keywords = keyword.split("[,,]");
|
||||
List<String> lowerKeywords = Arrays.stream(keywords)
|
||||
.map(String::trim)
|
||||
.filter(k -> !k.isEmpty())
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList());
|
||||
routePaths = routePaths.stream()
|
||||
.filter(vo -> vo.getMenuName() != null
|
||||
&& lowerKeywords.stream()
|
||||
.anyMatch(kw -> vo.getMenuName().toLowerCase().contains(kw)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return Result.ok(routePaths, "路由地址查询成功");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user