From 9e5f8704e92bf6c4fec5d34984a012fd9e7a084c Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Tue, 8 Sep 2026 19:14:10 +0800 Subject: [PATCH 1/4] feat: loop --- .../component/LoopFieldDialog.vue | 98 +++++++++---------- .../component/LoopFieldTable.vue | 32 +++--- .../nodes/loop-start-node/index.vue | 8 +- .../component/input/InputFieldFormDialog.vue | 10 +- .../component/input/InputFieldTable.vue | 10 +- .../output/OutputFieldFormDialog.vue | 10 +- .../component/output/OutputFieldTable.vue | 10 +- 7 files changed, 88 insertions(+), 90 deletions(-) diff --git a/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldDialog.vue b/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldDialog.vue index b333aa96582..7bb9af38185 100644 --- a/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldDialog.vue +++ b/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldDialog.vue @@ -1,52 +1,25 @@ - + + diff --git a/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldTable.vue b/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldTable.vue index e90f0265668..3138c7ed9ef 100644 --- a/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldTable.vue +++ b/ui/src/workflow-canvas/nodes/loop-start-node/component/LoopFieldTable.vue @@ -1,35 +1,36 @@ diff --git a/ui/src/workflow-canvas/icons/loop-break-node-icon.vue b/ui/src/workflow-canvas/icons/loop-break-node-icon.vue index b73cf6b4daa..ee57bd50ae3 100644 --- a/ui/src/workflow-canvas/icons/loop-break-node-icon.vue +++ b/ui/src/workflow-canvas/icons/loop-break-node-icon.vue @@ -1,6 +1,6 @@ diff --git a/ui/src/workflow-canvas/icons/loop-continue-node-icon.vue b/ui/src/workflow-canvas/icons/loop-continue-node-icon.vue index b73cf6b4daa..cc0d39c5aff 100644 --- a/ui/src/workflow-canvas/icons/loop-continue-node-icon.vue +++ b/ui/src/workflow-canvas/icons/loop-continue-node-icon.vue @@ -1,6 +1,6 @@ diff --git a/ui/src/workflow-canvas/icons/loop-node-icon.vue b/ui/src/workflow-canvas/icons/loop-node-icon.vue index b73cf6b4daa..cc0d39c5aff 100644 --- a/ui/src/workflow-canvas/icons/loop-node-icon.vue +++ b/ui/src/workflow-canvas/icons/loop-node-icon.vue @@ -1,6 +1,6 @@ diff --git a/ui/src/workflow-canvas/icons/loop-start-node-icon.vue b/ui/src/workflow-canvas/icons/loop-start-node-icon.vue index b73cf6b4daa..797fe0d5198 100644 --- a/ui/src/workflow-canvas/icons/loop-start-node-icon.vue +++ b/ui/src/workflow-canvas/icons/loop-start-node-icon.vue @@ -1,6 +1,6 @@ diff --git a/ui/src/workflow-canvas/nodes/loop-break-node/index.vue b/ui/src/workflow-canvas/nodes/loop-break-node/index.vue index 32f08bd497d..d15bfe650bc 100644 --- a/ui/src/workflow-canvas/nodes/loop-break-node/index.vue +++ b/ui/src/workflow-canvas/nodes/loop-break-node/index.vue @@ -1,21 +1,120 @@ - + + diff --git a/ui/src/workflow-canvas/nodes/loop-continue-node/index.vue b/ui/src/workflow-canvas/nodes/loop-continue-node/index.vue index 1fbeac62b57..58ac7223d0b 100644 --- a/ui/src/workflow-canvas/nodes/loop-continue-node/index.vue +++ b/ui/src/workflow-canvas/nodes/loop-continue-node/index.vue @@ -1,21 +1,120 @@ - + + diff --git a/ui/src/workflow-canvas/nodes/loop-node/index.vue b/ui/src/workflow-canvas/nodes/loop-node/index.vue index 756d042dfaf..068cfb2693c 100644 --- a/ui/src/workflow-canvas/nodes/loop-node/index.vue +++ b/ui/src/workflow-canvas/nodes/loop-node/index.vue @@ -1,27 +1,3 @@ - + + From fcb4b3077d11b480dccd59bcbf9645d4de375162 Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Tue, 8 Sep 2026 20:50:53 +0800 Subject: [PATCH 3/4] feat: think --- ui/AGENTS.md | 35 ++++-- ui/README.md | 119 +++++++++++++----- ui/src/api/admin/core/request.ts | 38 ++---- ui/src/components/COMPONENT_README.md | 4 +- .../select-model/ModelParamsDialog.vue | 2 +- ui/src/workflow-canvas/WORKFLOW_README.md | 30 +++-- .../component/ThinkingSetting.vue | 64 ++++++++++ ui/src/workflow-canvas/index.vue | 2 +- .../component/PromptGenerateDialog.vue | 2 +- .../component/ReasoningSettingDialog.vue | 57 --------- .../resource-setting/McpSettingDialog.vue | 2 +- .../nodes/ai-chat-node/index.vue | 24 ++-- .../nodes/ai-chat-node/types.ts | 9 +- .../component/FileUploadSettingDialog.vue | 17 +-- .../component/LongTermSettingDialog.vue | 2 +- .../workflow-canvas/nodes/base-node/index.vue | 16 ++- .../nodes/document-extract-node/index.vue | 5 +- .../nodes/image-understand-node/index.vue | 16 +-- .../workflow-canvas/nodes/loop-node/index.vue | 13 +- .../nodes/search-document-node/index.vue | 6 +- .../component/SearchSetting.vue | 2 +- .../nodes/search-knowledge-node/index.vue | 7 +- .../nodes/tool-lib-node/index.vue | 7 +- .../nodes/video-understand-node/index.vue | 16 +-- ui/src/workflow-canvas/types.ts | 7 ++ 25 files changed, 279 insertions(+), 223 deletions(-) create mode 100644 ui/src/workflow-canvas/component/ThinkingSetting.vue delete mode 100644 ui/src/workflow-canvas/nodes/ai-chat-node/component/ReasoningSettingDialog.vue diff --git a/ui/AGENTS.md b/ui/AGENTS.md index c1a40bee3fe..dab2290ed2d 100644 --- a/ui/AGENTS.md +++ b/ui/AGENTS.md @@ -68,17 +68,20 @@ ui/ │ ├── constants/ # Cross-feature constants grouped by domain │ │ └── CONSTANT_README.md # Shared constant placement and naming rules │ ├── layout/ # Shared application shells, headers, sidebars, types, and helpers -│ ├── locales/ # Reserved for internationalization messages and locale setup +│ ├── permission/ # Permission policies, business permission methods, and Admin $perm plugin │ ├── workflow-canvas/ # LogicFlow canvas and workflow domain components │ │ ├── component/ # Reusable workflow canvas UI │ │ ├── config/ # Maintainable node data, menus, mappings, and constants │ │ ├── core/ # Stable canvas behavior and shared node infrastructure +│ │ ├── details/ # Node execution detail dispatch and shared presentation │ │ ├── icons/ # Workflow node icons +│ │ ├── node-menu/ # Basic, tool, and application node selection menus │ │ ├── nodes/ # Workflow node definitions and components │ │ ├── plugins/ # Canvas-local plugins +│ │ ├── store/ # Resource API adapters, query caching, and request deduplication │ │ ├── WORKFLOW_README.md # Canvas boundaries and maintenance rules │ │ ├── types.ts # Workflow canvas protocol types -│ │ └── index.vue # MkWorkflow canvas entry +│ │ └── index.vue # WorkflowCanvas canvas entry │ ├── router/ # Vue Router routes and router instance │ │ └── ROUTE_README.md # Routing conventions and rules │ ├── stores/ # Shared Pinia instance and state stores @@ -95,16 +98,27 @@ ui/ │ ├── views/ # Route-level page components grouped by feature │ │ ├── VIEW_README.md # Page responsibilities and feature-local code rules │ │ ├── home/ # Workspace home page +│ │ ├── application/ # Application list and creation +│ │ ├── application-detail/ # Application overview and settings +│ │ ├── knowledge/ # Knowledge base list and cards +│ │ ├── knowledge-detail/ # Knowledge base and document details +│ │ ├── model/ # Model list, creation, and settings +│ │ ├── tool/ # Tool list, forms, and tool store +│ │ ├── trigger/ # Workspace trigger list │ │ ├── system/ # System-management pages -│ │ ├── login/ # Reserved for admin login pages -│ │ ├── chat/ # Chat-side pages, including user login +│ │ ├── login/ # Admin login, account recovery, and login modes +│ │ ├── chat/ # Chat entry placeholder page +│ │ ├── error/ # Not-found page +│ │ ├── details-demo/ # Temporary execution-detail preview page │ │ └── workflow/ # Full-screen workflow route pages ├── vite.config.ts # Vite entries, plugins, aliases, proxy, and build output ├── tsconfig*.json # TypeScript configuration └── package.json # Dependencies and npm scripts ``` -Directories marked as reserved may be empty while their feature is being introduced. Add files to the matching feature directory instead of creating parallel top-level structures. +Internationalization is not yet integrated; `src/locales/` has not been created. Chat currently has a +placeholder route page and a reserved independent API directory. Add files to the matching feature +directory instead of creating parallel top-level structures. Structural responsibilities: @@ -113,7 +127,7 @@ Structural responsibilities: - Put reusable application chrome in `layout/`, not in individual route views. - Keep LogicFlow initialization, node registration, and canvas behavior inside `workflow-canvas/`. Every page rendering this canvas belongs in `views/workflow/`; those Views own the page header, - route and page-level actions around `MkWorkflow`. + route and page-level actions around `WorkflowCanvas`. - Put server communication in `api/`, isolate Admin and Chat request systems, and group business APIs by domain and resource according to `src/api/API_README.md`. - Put backend fixed-value enums in `api/enums/` and import them through `@/api/enums`; keep @@ -149,7 +163,8 @@ Important variables: - `VITE_APP_PORT`: local dev server port - `VITE_APP_TITLE`: HTML title - `VITE_ENTRY`: HTML entry file -- `VITE_API_TARGET`: optional backend proxy target, defaults to `http://127.0.0.1:8080` +- `VITE_API_TARGET`: optional backend proxy target; currently defaults to `http://47.120.55.164:38080` + through `defaultBackendTarget` in `vite.config.ts`. Override it locally for a different backend. Build output mirrors the v2 layout: @@ -169,10 +184,14 @@ npm run chat # chat dev server npm run build # default admin build with type-check npm run build-chat # chat build with type-check npm run type-check -npm run lint npm run format ``` +Node.js must satisfy `^22.18.0 || >=24.12.0` as declared in `package.json`. +Admin and Chat use ports 3000 and 3001 respectively, with `strictPort` enabled. +`npm run lint` currently delegates to `lint:*`, but no matching scripts are defined. Use +`npx eslint ` for targeted linting until those scripts are configured. + ## Vite Configuration Main config: `vite.config.ts`. diff --git a/ui/README.md b/ui/README.md index 80619bb296b..920cb8d572f 100644 --- a/ui/README.md +++ b/ui/README.md @@ -1,48 +1,99 @@ -# ui +# MaxKB v3 前端 -This template should help get you started developing with Vue 3 in Vite. +MaxKB 企业级 AI 智能体平台的前端工程,使用 Vue 3.5、TypeScript 6、Vite 8、Element Plus、 +Tailwind CSS 4、Pinia 3 和 Vue Router 5,工作流画布基于 LogicFlow。 -## Recommended IDE Setup +项目采用 Admin 和 Chat 双入口。Admin 包含登录、工作空间资源、系统管理和工作流编辑等功能; +Chat 已配置独立入口与路由,当前 `ChatView.vue` 仍为空白占位页,`src/api/chat/` 的独立请求体系尚未实现。 -[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). +## 本地开发 -## Recommended Browser Setup +Node.js 版本要求为 `^22.18.0 || >=24.12.0`,以 `package.json` 的 `engines` 为准。 +以下命令均在 `ui/` 目录执行: -- Chromium-based browsers (Chrome, Edge, Brave, etc.): - - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) - - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters) -- Firefox: - - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/) - - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/) - -## Type Support for `.vue` Imports in TS - -TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. - -## Customize configuration - -See [Vite Configuration Reference](https://vite.dev/config/). - -## Project Setup - -```sh +```bash npm install +npm run dev ``` -### Compile and Hot-Reload for Development +Admin 默认访问地址为 `http://localhost:3000/admin/`。在另一个终端运行 `npm run chat`, +可通过 `http://localhost:3001/chat/` 访问 Chat 入口。开发服务器启用 `strictPort`,端口被占用时不会自动换端口。 -```sh -npm run dev -``` +### 后端代理与环境变量 -### Type-Check, Compile and Minify for Production +公共及 Admin 默认配置在 `env/.env`,Chat 模式通过 `env/.env.chat` 覆盖入口、路径和端口。 +本地覆盖可放在 `env/.env.local`,Chat 专属覆盖可放在 `env/.env.chat.local`。 -```sh -npm run build -``` +| 变量 | Admin 默认值 | Chat 默认值 | 用途 | +| ----------------- | ------------ | ----------- | -------------------------- | +| `VITE_APP_NAME` | `admin` | `chat` | 应用名称 | +| `VITE_BASE_PATH` | `/admin/` | `/chat/` | 路由基础路径与构建输出目录 | +| `VITE_APP_PORT` | `3000` | `3001` | 开发服务端口 | +| `VITE_APP_TITLE` | `MaxKB` | `MaxKB` | HTML 标题 | +| `VITE_ENTRY` | `admin.html` | `chat.html` | HTML 入口 | +| `VITE_API_TARGET` | 未设置 | 未设置 | 覆盖开发代理的后端地址 | -### Lint with [ESLint](https://eslint.org/) +当前未设置 `VITE_API_TARGET` 时,使用 `vite.config.ts` 中的 `defaultBackendTarget`, +值为 `http://47.120.55.164:38080`。连接本地后端时,在 `env/.env.local` 中配置: -```sh -npm run lint +```dotenv +VITE_API_TARGET=http://127.0.0.1:8080 ``` + +开发代理覆盖 `/admin/api`、`/chat/api`、`/doc`、`/schema`、`/static` 和当前应用基础路径下的 +OSS 文件接口。前端业务接口需要可用的后端服务。 + +## 构建与检查 + +| 命令 | 作用 | +| -------------------------------- | ------------------------------- | +| `npm run dev` | 启动 Admin 开发服务 | +| `npm run chat` | 启动 Chat 开发服务 | +| `npm run build` | 类型检查并构建 Admin | +| `npm run build-chat` | 类型检查并构建 Chat | +| `npm run build-only` | 仅构建 Admin | +| `npm run build-only-chat` | 仅构建 Chat | +| `npm run type-check` | 使用 `vue-tsc --build` 检查类型 | +| `npm run preview` | 预览 Admin 构建产物 | +| `npm run preview -- --mode chat` | 预览 Chat 构建产物 | +| `npm run format` | 使用 Prettier 格式化 `src/` | + +`npm run lint` 当前仅配置了 `run-s "lint:*"`,但尚未定义任何 `lint:*` 子脚本,不能作为已执行 +ESLint 检查的依据。需要检查代码时,可运行 `npx eslint <待检查的文件或目录>`。 + +默认构建分别输出 `dist/admin/index.html` 和 `dist/chat/index.html`,HTML 由构建插件统一重命名。 +静态资源使用相对路径(`base: './'`);部署时仍需为 History 路由配置对应入口回退, +并由部署服务转发 API 和文件请求。Vite 的开发代理不会随静态构建产物部署。 + +## 代码目录 + +| 目录或文件 | 职责 | +| ------------------------------- | ---------------------------------------------------- | +| `src/main.ts` / `src/chat.ts` | Admin / Chat 启动入口 | +| `src/api/` | 请求基础设施、业务 API、后端枚举与共享类型 | +| `src/components/` | 全局 Mk 组件、跨页面业务组件及其他共享组件 | +| `src/layout/` | 应用头部、侧栏与资源详情布局 | +| `src/views/` | 登录、工作空间、系统管理、资源详情和工作流等路由页面 | +| `src/workflow-canvas/` | 画布内核、节点配置、节点实现、执行详情与资源查询缓存 | +| `src/router/` | Admin / Chat 独立路由 | +| `src/permission/` | 权限策略、分业务权限方法与 Admin `$perm` 插件 | +| `src/stores/` | 共享 Pinia 实例及认证、用户、主题状态 | +| `src/styles/` | 主题变量、Tailwind、Element Plus 集成与全局样式 | +| `src/constants/` / `src/utils/` | 跨功能常量与工具函数 | +| `src/assets/` / `public/` | 源码导入资源 / 保留原始路径的静态资源 | + +## 开发约定与文档 + +修改前先阅读 [AGENTS.md](AGENTS.md),再阅读涉及领域的规则文档: + +- [样式](src/styles/STYLE_README.md) +- [组件](src/components/COMPONENT_README.md) +- [路由](src/router/ROUTE_README.md) +- [API](src/api/API_README.md) +- [页面](src/views/VIEW_README.md) +- [工作流画布](src/workflow-canvas/WORKFLOW_README.md) +- [常量](src/constants/CONSTANT_README.md) +- [工具函数](src/utils/UTILS_README.md) + +详细规则由各领域 README 维护;目录、公共接口或使用约定变化时同步对应文档。 +`src/components.d.ts` 由组件自动注册插件生成,不手动编辑。 diff --git a/ui/src/api/admin/core/request.ts b/ui/src/api/admin/core/request.ts index 683a0497233..5fbcfbb6f54 100644 --- a/ui/src/api/admin/core/request.ts +++ b/ui/src/api/admin/core/request.ts @@ -256,36 +256,20 @@ export function post(url: string, data?: TData, pa } /** 发送 POST 请求并返回可逐块读取的原始响应。 */ -export async function postStream(url: string, data?: TData, config: StreamRequestConfig = {}) { +export function postStream(base: string, path: string, data?: unknown) { const { auth, user } = useStore() - const headers = new Headers({ 'Content-Type': 'application/json' }) - if (auth.token) headers.set('Authorization', `Bearer ${auth.token}`) - if (user.language) headers.set('Accept-Language', user.language) - - const baseUrl = String(request.defaults.baseURL ?? '').replace(/\/+$/, '') - const response = await fetch(`${baseUrl}/${url.replace(/^\/+/, '')}`, { - body: JSON.stringify(data ?? {}), - headers, + const headers: Record = { 'Content-Type': 'application/json' } + if (auth.token) { + headers['Authorization'] = `Bearer ${auth.token}` + } + if (user.language) { + headers['Accept-Language'] = user.language + } + return fetch(`${base}${path.startsWith('/') ? path : `/${path}`}`, { method: 'POST', - signal: config.signal, + headers, + body: data === undefined ? undefined : JSON.stringify(data), }) - - if (response.ok) return response - - const errorMessage = (await getFetchErrorMessage(response)) || response.statusText - if (response.status === 401) { - auth.clearToken() - void router.push({ name: 'login' }) - } else if (response.status === 403) { - MsgError(errorMessage || 'No permission to access') - } else if (response.status === 404) { - void router.replace({ name: 'not-found', params: { pathMatch: ['404'] } }) - } else { - MsgError(errorMessage) - } - const error = new Error(errorMessage) - error.name = 'StreamRequestError' - throw error } /** 发送 PUT 请求。 */ diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index af3afa8f426..a75a9ee2c7f 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -294,7 +294,7 @@ Dialog 外壳仅在首次打开时挂载;默认在关闭动画结束、触发 ... @@ -313,7 +313,7 @@ Escape 关闭;这些默认行为可以通过同名 Props 覆盖。Element Plus ... diff --git a/ui/src/components/business/select-model/ModelParamsDialog.vue b/ui/src/components/business/select-model/ModelParamsDialog.vue index 0cca6e26718..c0ed0d98273 100644 --- a/ui/src/components/business/select-model/ModelParamsDialog.vue +++ b/ui/src/components/business/select-model/ModelParamsDialog.vue @@ -71,7 +71,7 @@ defineExpose({ open, resetDefault }) diff --git a/ui/src/workflow-canvas/WORKFLOW_README.md b/ui/src/workflow-canvas/WORKFLOW_README.md index 90bb60d142e..2c6e3ee472a 100644 --- a/ui/src/workflow-canvas/WORKFLOW_README.md +++ b/ui/src/workflow-canvas/WORKFLOW_README.md @@ -20,7 +20,7 @@ ```text src/workflow-canvas/ -├── component/ # 画布内可复用的控制和搜索组件 +├── component/ # 画布内可复用的控制、搜索和节点设置组件 ├── config/ # 节点数据、映射、常量及预留的本地化配置 ├── details/ # 执行详情:顶层分发入口与公共卡壳,节点内容由 nodes/*/details/ 提供 ├── core/ # 稳定的画布内核与所有节点共用的基础能力 @@ -30,6 +30,7 @@ src/workflow-canvas/ ├── node-menu/ # 基础组件、工具和智能体节点菜单及其菜单配置 ├── nodes/ # 已迁入节点的注册文件和 Vue 实现 ├── plugins/ # 仅供画布使用的 LogicFlow 插件 +├── store/ # 按资源范围适配查询接口,提供缓存及在途请求去重 ├── index.vue # 画布入口组件 WorkflowCanvas ├── style.scss # 画布内 LogicFlow 全局样式覆盖 ├── types.ts # 画布协议类型和枚举 @@ -172,6 +173,11 @@ AI 对话、意图识别、问题优化、参数提取、图片理解、视频 节点入口深拷贝写回列表并发送原有字段刷新事件,保留显隐条件引用校验。用户输入与接口传参继续 交叉检查参数重名;`UserInputSettingDialog` 独立维护直接展示参数设置,删除字段时由表格清理对应设置。 +基本信息节点的 `component/FileUploadSettingDialog.vue` 同时封装文件上传设置按钮与弹窗, +通过 `v-model` 接收 `FileUploadSetting`。节点入口根据上传开关挂载组件,并在配置写回后发送 +`refreshFileUploadConfig` 刷新开始节点文件变量;弹窗打开时重置并深拷贝草稿,确认时保留上传方式 +校验,取消不修改节点,关闭动画结束后统一清理草稿。 + 表单收集节点的 `component/form-setting/FormSettingTable` 通过 `v-model` 编辑动态表单的 `FormField[]`,负责增删改、排序和重名检查;`FormFieldDialog` 复用 `MkDynamicsFormConstructor`, 通过 `submit(data, index?)` 提交,由表格写回后调用 `close()`,关闭动画结束时重置编辑状态。 @@ -191,7 +197,11 @@ ID 数组及 `tool_list`、`skill_tool_list`、`application_list` 回显快照 已关联但缺少详情的资源保留 ID 回退展示。 AI 对话节点的提示词、历史记录、视觉理解和输出思考表单直接在节点入口维护,统一使用全局 -`MdEditorMagnify` 和节点表单样式;AI 提示词生成与思考过程配置仍使用独立弹窗。 +`MdEditorMagnify` 和节点表单样式;AI 提示词生成使用独立弹窗。AI 对话、图片理解和视频理解节点的 +输出思考设置统一复用 `component/ThinkingSetting.vue`,后续同类入口也应引用该组件。组件通过 +`v-model` 接收 `types.ts` 中的共享配置类型 `ReasoningSettingData`;节点入口维护输出思考开关, +并根据开关用 `v-if` 挂载设置组件。弹窗打开时重置并深拷贝草稿,仅在校验通过并保存后回写, +取消不修改节点,关闭动画结束后重置草稿及校验状态。当前开始、结束标签未配置必填规则。 问题优化、图片理解和视频理解节点的系统提示词与用户提示词,以及图片、文生视频和图生视频 节点的正向与负向提示词同样使用 `MdEditorMagnify`,必填字段由所在节点表单统一校验。 @@ -279,16 +289,16 @@ MkFormList 的排序、增删均以 `cloneDeep` 回写;MkTable 保留普通行 - 所有画布路由页面均放在 `src/views/workflow/`,并以 `XxxWorkflowView.vue` 命名,例如 `ApplicationWorkflowView.vue`。未来的智能体画布、知识库画布等都遵守此规则。 -- View 在 `MkWorkflow` 外部组织页面头部的保存、发布、调试等页面级操作;添加组件属于画布操作, - 由 `MkWorkflow` 内的 `AddNode` 统一提供。 +- View 在 `WorkflowCanvas` 外部组织页面头部的保存、发布、调试等页面级操作;添加组件属于画布操作, + 由 `WorkflowCanvas` 内的 `AddNode` 统一提供。 - 画布页面需要独立全屏展示时,由 `src/router/admin/workflow/` 配置不挂载业务 Layout 的路由; 画布模块不处理路由。 - View 通过 Props 传入图数据,通过组件实例暴露的方法操作画布。接口接入后,加载、保存及错误 处理仍由 View 或其所属业务层编排,不在节点和画布核心中直接发请求。 -- View 向 `MkWorkflow` 传入 `workflowMode`;`MkWorkflow` 将它用于右上角添加组件菜单,并桥接给 +- View 向 `WorkflowCanvas` 传入 `workflowMode`;`WorkflowCanvas` 将它用于右上角添加组件菜单,并桥接给 LogicFlow 节点内部的锚点菜单。 -`MkWorkflow` 当前对外暴露的方法包括: +`WorkflowCanvas` 当前对外暴露的方法包括: | 方法 | 用途 | | ----------------- | --------------------------- | @@ -321,7 +331,8 @@ MkFormList 的排序、增删均以 `cloneDeep` 回写;MkTable 保留普通行 - 已实现并注册:基本信息、开始、AI 对话、意图识别、问题优化、语音转文本、文本转语音、图片生成、 图片理解、文生视频、图生视频、视频理解、知识库检索、判断器、指定回复、智能体、自定义工具和 - 工具库工具、文档内容提取、多路召回和文档标签检索。 + 工具库工具、工具工作流、MCP、文档内容提取、多路召回和文档标签检索,以及参数提取、表单收集、 + 变量赋值、变量聚合、变量拆分、循环、循环体、循环开始、Break、Continue、工具基本信息和工具开始节点。 - 知识库检索节点在入口维护检索范围、参数摘要和问题表单,参数设置按钮与弹窗统一封装在 `component/SearchSetting.vue`,通过 `v-model` 接收检索参数,仅在校验通过并保存后深拷贝回写; 节点入口统一维护关联数据,范围引用加入节点表单校验,问题引用保留独立有效性检查。知识库选择复用 @@ -339,9 +350,12 @@ MkFormList 的排序、增删均以 `cloneDeep` 回写;MkTable 保留普通行 ```bash npm run type-check -npm run lint +npx eslint <本次修改的Vue或TypeScript文件> git diff --check ``` +当前 `npm run lint` 尚未配置对应的 `lint:*` 子脚本,不能替代实际 ESLint 检查。 +仅修改 Markdown 文档时,检查修改文件的 Prettier 格式、路径引用及 `git diff --check` 即可。 + 若当前迁移中的预留文件仍存在已知类型错误,应在交付说明中明确区分,不要通过改变现有画布业务 逻辑来绕过。 diff --git a/ui/src/workflow-canvas/component/ThinkingSetting.vue b/ui/src/workflow-canvas/component/ThinkingSetting.vue new file mode 100644 index 00000000000..3bca6a8bb4a --- /dev/null +++ b/ui/src/workflow-canvas/component/ThinkingSetting.vue @@ -0,0 +1,64 @@ + + + diff --git a/ui/src/workflow-canvas/index.vue b/ui/src/workflow-canvas/index.vue index 01bd6170106..5dceda02ff6 100644 --- a/ui/src/workflow-canvas/index.vue +++ b/ui/src/workflow-canvas/index.vue @@ -13,7 +13,7 @@ import { WorkflowMode, WorkflowNodeType, type ShapeItem } from '@/workflow-canva import type { DefaultModelSettingPayload } from '@/api/types' import NodeAdd from './component/NodeAdd.vue' import NodeSearch from './component/NodeSearch.vue' -defineOptions({ name: 'MkWorkflow' }) +defineOptions({ name: 'WorkflowCanvas' }) type CanvasWorkflowNodeModel = WorkflowNodeModel & { set_loop_body?: () => void } const apiType = inject('resourceScope', 'workspace') diff --git a/ui/src/workflow-canvas/nodes/ai-chat-node/component/PromptGenerateDialog.vue b/ui/src/workflow-canvas/nodes/ai-chat-node/component/PromptGenerateDialog.vue index 9019f981de3..a1279fbbb26 100644 --- a/ui/src/workflow-canvas/nodes/ai-chat-node/component/PromptGenerateDialog.vue +++ b/ui/src/workflow-canvas/nodes/ai-chat-node/component/PromptGenerateDialog.vue @@ -162,7 +162,7 @@ defineExpose({ open }) diff --git a/ui/src/workflow-canvas/nodes/ai-chat-node/component/ReasoningSettingDialog.vue b/ui/src/workflow-canvas/nodes/ai-chat-node/component/ReasoningSettingDialog.vue deleted file mode 100644 index 01798e1d6e8..00000000000 --- a/ui/src/workflow-canvas/nodes/ai-chat-node/component/ReasoningSettingDialog.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/ui/src/workflow-canvas/nodes/ai-chat-node/component/resource-setting/McpSettingDialog.vue b/ui/src/workflow-canvas/nodes/ai-chat-node/component/resource-setting/McpSettingDialog.vue index 04f4e7d1fc0..2d0a694218a 100644 --- a/ui/src/workflow-canvas/nodes/ai-chat-node/component/resource-setting/McpSettingDialog.vue +++ b/ui/src/workflow-canvas/nodes/ai-chat-node/component/resource-setting/McpSettingDialog.vue @@ -114,7 +114,7 @@ defineExpose({ open }) diff --git a/ui/src/workflow-canvas/nodes/ai-chat-node/index.vue b/ui/src/workflow-canvas/nodes/ai-chat-node/index.vue index 09c15738f7f..09eec35c0c0 100644 --- a/ui/src/workflow-canvas/nodes/ai-chat-node/index.vue +++ b/ui/src/workflow-canvas/nodes/ai-chat-node/index.vue @@ -11,9 +11,10 @@ import type { WorkflowNodeModel } from '@/workflow-canvas/core/workflow-node' import { useWorkflowStore } from '@/workflow-canvas/store' import { WorkflowMode } from '@/workflow-canvas/types' import PromptGenerateDialog from './component/PromptGenerateDialog.vue' -import ReasoningSettingDialog from './component/ReasoningSettingDialog.vue' +import ThinkingSetting from '@/workflow-canvas/component/ThinkingSetting.vue' import ResourceSetting from './component/resource-setting/index.vue' -import type { AiChatNodeForm, ReasoningSetting } from './types' +import type { AiChatNodeForm } from './types' +import type { ReasoningSettingData } from '@/workflow-canvas/types' import { fileTooltip } from '@/workflow-canvas/config/constants' defineOptions({ name: 'WorkflowAiChatNode' }) @@ -26,12 +27,11 @@ const store = useWorkflowStore(apiType) const formRef = useTemplateRef('formRef') const promptGenerateDialogRef = useTemplateRef>('promptGenerateDialogRef') -const reasoningSettingDialogRef = useTemplateRef>('reasoningSettingDialogRef') const modelOptions = ref([]) const providerOptions = ref([]) -const defaultReasoningSetting: ReasoningSetting = { +const defaultThinkingSetting: ReasoningSettingData = { reasoning_content_enable: false, reasoning_content_end: '', reasoning_content_start: '', @@ -51,7 +51,7 @@ const defaultForm: AiChatNodeForm = { model_id_reference: [], model_id_type: 'default', model_params_setting: {}, - model_setting: cloneDeep(defaultReasoningSetting), + model_setting: cloneDeep(defaultThinkingSetting), prompt: '{{开始.question}}', skill_tool_ids: [], system: '', @@ -83,9 +83,9 @@ const normalizedForm = { model_id_type: savedForm ? (savedForm.model_id_type ?? 'custom') : defaultForm.model_id_type, model_params_setting: savedForm?.model_params_setting ?? {}, model_setting: { - reasoning_content_enable: savedForm?.model_setting?.reasoning_content_enable ?? defaultReasoningSetting.reasoning_content_enable, - reasoning_content_end: savedForm?.model_setting?.reasoning_content_end ?? defaultReasoningSetting.reasoning_content_end, - reasoning_content_start: savedForm?.model_setting?.reasoning_content_start ?? defaultReasoningSetting.reasoning_content_start, + reasoning_content_enable: savedForm?.model_setting?.reasoning_content_enable ?? defaultThinkingSetting.reasoning_content_enable, + reasoning_content_end: savedForm?.model_setting?.reasoning_content_end ?? defaultThinkingSetting.reasoning_content_end, + reasoning_content_start: savedForm?.model_setting?.reasoning_content_start ?? defaultThinkingSetting.reasoning_content_start, }, prompt: savedForm?.prompt ?? defaultForm.prompt, skill_tool_ids: Array.isArray(savedForm?.skill_tool_ids) ? savedForm.skill_tool_ids : [], @@ -246,13 +246,10 @@ onMounted(() => { -
+
输出思考
- - - - +
@@ -273,6 +270,5 @@ onMounted(() => {
- diff --git a/ui/src/workflow-canvas/nodes/ai-chat-node/types.ts b/ui/src/workflow-canvas/nodes/ai-chat-node/types.ts index 107485d0519..d1890ae9372 100644 --- a/ui/src/workflow-canvas/nodes/ai-chat-node/types.ts +++ b/ui/src/workflow-canvas/nodes/ai-chat-node/types.ts @@ -1,4 +1,5 @@ import type { ApplicationDetail, ToolItem } from '@/api/types' +import type { ReasoningSettingData } from '@/workflow-canvas/types' export type AiModelSource = 'custom' | 'default' | 'reference' export type DialogueSource = 'NODE' | 'WORKFLOW' @@ -27,12 +28,6 @@ export interface VisionSetting { vision: boolean } -export interface ReasoningSetting { - reasoning_content_enable: boolean - reasoning_content_end: string - reasoning_content_start: string -} - export interface McpSetting { mcp_servers: string mcp_source: McpSource @@ -51,7 +46,7 @@ export interface ResourceSetting extends McpSetting { export interface AiChatNodeForm extends AiModelSetting, HistorySetting, PromptSetting, ResourceSetting, VisionSetting { is_result: boolean - model_setting: ReasoningSetting + model_setting: ReasoningSettingData } export type ToolResourceOption = Pick diff --git a/ui/src/workflow-canvas/nodes/base-node/component/FileUploadSettingDialog.vue b/ui/src/workflow-canvas/nodes/base-node/component/FileUploadSettingDialog.vue index 9231147d38d..f4c02a2a519 100644 --- a/ui/src/workflow-canvas/nodes/base-node/component/FileUploadSettingDialog.vue +++ b/ui/src/workflow-canvas/nodes/base-node/component/FileUploadSettingDialog.vue @@ -8,8 +8,9 @@ import type { FileUploadSetting } from '../types' defineOptions({ name: 'BaseNodeFileUploadSettingDialog' }) -const emit = defineEmits<{ submit: [setting: FileUploadSetting] }>() +const setting = defineModel({ required: true }) +// 文件上传设置:打开时创建草稿,确认后回写配置。 const visible = ref(false) const extensionInputVisible = ref(false) const extensionInput = ref('') @@ -52,12 +53,13 @@ function submit() { MsgWarning('请至少选择一种上传方式') return } - emit('submit', cloneDeep(formData.value)) + setting.value = cloneDeep(formData.value) visible.value = false } -function open(setting: FileUploadSetting) { - formData.value = cloneDeep(setting) +function open() { + resetData() + formData.value = cloneDeep(setting.value) visible.value = true } @@ -66,11 +68,12 @@ function resetData() { extensionInput.value = '' extensionInputVisible.value = false } - -defineExpose({ open })