diff --git a/docs/FEATURES.md b/docs/FEATURES.md index f425475..988ef40 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -193,6 +193,7 @@ ### 2026-08-16 +- 工作流画布顶栏修正:名称输入框改为随内容自适应宽度(不再占大块空白),名称长度限制为英文 ≤150 字符 / 中文 ≤50 字符(混排按中文字符权重折算);顶栏改为可收缩布局,保证「保存 / 运行」按钮始终靠右可见不被挤出。 - 工作流画布增强:节点支持从左侧面板拖入;画布滚轮缩放(25%–250%)与空白处拖动平移;节点右键菜单(修改名称/说明/收藏/复制/删除)、连线右键删除(单击不再误删);右侧边栏只显示选中节点的选项并移除“各节点输出”总列表;新增画布导入/导出 JSON;顶栏「返回工作流」单行显示、名称框固定宽度、保存/运行右对齐。 - 新增「工作流」选项卡:画布式节点编辑器(开始/大模型/文本/输出,节点连线传参、拖动布局),内置 4 个预制工作流(翻译助手、内容总结、两步润色、写作助手)并支持自定义与恢复;新增 `workflows` 表与 `run_workflow` 命令,后端 `apps/desktop/src/workflow.rs` 执行引擎支持拓扑排序、模板变量(`{{input}}`/`{{节点id}}`)、循环检测,LLM 节点支持本地/在线大模型(节点 → 工作流 → 运行参数 → 自动回退);`workflow://node-status` 事件实时推送节点状态;5 个引擎单元测试 + 1 个真实模型端到端测试全部跑通。 - 新增「智能体」选项卡:内置 6 个预制智能体 + 支持自定义智能体(名称/图标/描述/系统提示词/默认模型/启用开关);每个智能体拥有独立会话区(`conversations.agent_id` 隔离),新建会话自动继承智能体系统提示词与默认模型;系统提示词统一注入 `chat_send` / `regenerate_message` / `edit_message` 链路;删除智能体时级联删除其会话;支持「恢复预制智能体」。 diff --git a/ui/src/pages/WorkflowCanvasPage.tsx b/ui/src/pages/WorkflowCanvasPage.tsx index 14cb743..2718c13 100644 --- a/ui/src/pages/WorkflowCanvasPage.tsx +++ b/ui/src/pages/WorkflowCanvasPage.tsx @@ -56,6 +56,30 @@ function newId(prefix: string) { return `${prefix}_${Date.now().toString(36)}${Math.floor(Math.random() * 1000)}`; } +/** 中文字符(CJK)按 3 个权重计,其余按 1:英文最多 150 字、中文最多 50 字,混排按权重折算。 */ +const NAME_MAX_WEIGHT = 150; + +function isCjkChar(ch: string) { + const code = ch.codePointAt(0) ?? 0; + return ( + (code >= 0x4e00 && code <= 0x9fff) || + (code >= 0x3400 && code <= 0x4dbf) || + (code >= 0xf900 && code <= 0xfaff) + ); +} + +function clampWorkflowName(value: string) { + let weight = 0; + let out = ""; + for (const ch of value) { + const w = isCjkChar(ch) ? 3 : 1; + if (weight + w > NAME_MAX_WEIGHT) break; + weight += w; + out += ch; + } + return out; +} + export default function WorkflowCanvasPage() { const { workflowId } = useParams<{ workflowId: string }>(); const workflows = useStore((s) => s.workflows); @@ -528,7 +552,7 @@ export default function WorkflowCanvasPage() { return (
{/* 顶部工具栏 */} -
+
setName(e.target.value)} + onChange={(e) => setName(clampWorkflowName(e.target.value))} placeholder="工作流名称" + title="英文不超过 150 个字符,中文不超过 50 个(混排按中文字符权重折算)" + style={{ width: `${Math.min(44, Math.max(6, [...name].length + 2))}ch` }} /> {workflow.kind === "preset" ? "预制" : "自定义"} - + {nodes.length} 节点 · {edges.length} 连线 - {msg ? {msg} : null} + {msg ? ( + + {msg} + + ) : null}