From a826469adfa61a5b75b3e6c5f3d657a9b244428d Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Thu, 8 Oct 2026 17:15:23 +0800 Subject: [PATCH] feat: document edit --- ui/src/api/API_README.md | 16 ++- ui/src/api/admin/model-provider.ts | 13 +-- .../resource-management/tool/tool-workflow.ts | 5 - .../shared-resources/tool/tool-workflow.ts | 5 - .../admin/workspace/application/chat-log.ts | 5 - .../api/admin/workspace/knowledge/document.ts | 14 +-- .../api/admin/workspace/knowledge/workflow.ts | 10 -- ui/src/api/admin/workspace/tool/workflow.ts | 5 - ui/src/api/types/document.ts | 3 + ui/src/api/types/tool.ts | 17 +-- ui/src/assets/file-type/csv-icon.svg | 8 +- ui/src/assets/file-type/doc-icon.svg | 6 +- ui/src/assets/file-type/docx-icon.svg | 6 +- .../assets/file-type/file-document-icon.svg | 6 +- ui/src/assets/file-type/html-icon.svg | 4 +- ui/src/assets/file-type/md-icon.svg | 8 +- ui/src/assets/file-type/pdf-icon.svg | 6 +- ui/src/assets/file-type/txt-icon.svg | 13 ++- ui/src/assets/file-type/unknown-icon.svg | 6 +- ui/src/assets/file-type/web-link-icon.svg | 2 +- ui/src/assets/file-type/xls-icon.svg | 6 +- ui/src/assets/file-type/xlsx-icon.svg | 6 +- ui/src/assets/file-type/zip-icon.svg | 7 +- ui/src/components/COMPONENT_README.md | 14 ++- .../GenerateQuestionsDialog.vue | 2 +- ui/src/components/mk-edit-name/index.vue | 110 ++++++++---------- ui/src/utils/UTILS_README.md | 5 +- ui/src/utils/message.ts | 2 +- ui/src/views/VIEW_README.md | 4 + .../setting/SettingDocumentAction.vue | 2 +- .../library/document/index.vue | 42 ++++++- .../components/DocumentStrategyForm.vue | 15 ++- .../components/KnowledgeBaseForm.vue | 5 +- .../create-model/SelectProviderDrawer.vue | 2 +- .../resource-management/application/index.vue | 2 +- .../resource-management/model/index.vue | 4 +- .../system/resource-management/tool/index.vue | 2 +- .../component/python-code/CodeGenerate.vue | 2 +- .../workflow/knowledge/debug/DebugDrawer.vue | 4 +- .../workflow/tool/debug/ResultDrawer.vue | 10 +- 40 files changed, 187 insertions(+), 217 deletions(-) diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index d856e3c916a..a30ea20f1f3 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -143,6 +143,9 @@ v3 编辑表单提交 `{ name, description }`,标题上限 64、更新说明 ### 模型选项查询 +`model-provider.ts` 的 `getProviderList(query?)` 统一查询 `GET /provider`;不传参数获取全部供应商, +传入 `{ model_type }` 筛选支持指定模型类型的供应商,不再单独封装按类型查询方法。 + `workspace/model.ts` 的 `getModelListWithShared(query)` 请求 `/workspace//model_list`,支持 `name`、`model_type`、`model_name` 筛选。 将 `shared_model` 与 `model` 按共享在前的顺序合并为 `ModelItem[]`,分别标记 @@ -422,8 +425,10 @@ API 对象和工作空间上下文,作为该抽屉的范围选择例外;用 `workspace/tool/workflow.ts` 的 `postToolWorkflowDebug(toolId, parameters)` 使用 Admin `postStream` 请求 `//debug`,返回原始 SSE Response;输入参数来自工具基础节点,`chat_record_id` 用于识别 -执行记录,表单续跑沿用该 ID 并传入 `position`。`getToolWorkflowRecord(toolId, recordId)` 查询 -`//tool_record/`,返回 `ToolWorkflowRecord` 的运行状态、输出及节点详情。 +执行记录,表单续跑沿用该 ID 并传入 `position`。调试结果与执行详情统一通过 +`getToolExecutionRecordDetail(toolId, recordId)` 查询 `//tool_record/`, +返回 `ToolExecutionRecordDetail` 的运行状态、输出及节点详情。Workspace、System 资源管理和 +System 共享资源分别保留各自路径下的同名接口,不再重复封装调试专用查询。 工具调试读取服务端已保存工作流,画布页面在调试前保存未提交改动。 ### 工具工作流模板中心 @@ -485,6 +490,8 @@ Admin 上传尚未创建的资源文件时,`sourceId` 可传 `undefined`,省 资源类型使用 `@/api/enums` 的 `FILE_SOURCE_TYPE` 与 `@/api/types` 的 `FileSourceType`, 包括知识库、智能体、工具、文档、对话及三种临时文件有效期。对话 Store 使用 `FILE_SOURCE_TYPE.CHAT` 调用对应 File API,对话 API 不再维护上传接口。 +知识库工作流调试上传复用 Admin `FileApi.postUploadFile`,传知识库 ID 与 `FILE_SOURCE_TYPE.KNOWLEDGE`, +通过返回的 `request` 获取文件地址,再适配动态表单的 `{ data: url }` 返回协议;工作流 API 不重复封装上传。 ### System 资源管理模型与工具 @@ -517,6 +524,11 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展 ### 知识库文档 +`putDocument(knowledgeId, documentId, data)` 统一通过 PUT `/` 更新名称、启用状态和单项设置, +不按更新字段重复封装同一接口。载荷 `DocumentUpdatePayload` 仅包含可更新字段,按需传入 +`name`、`is_active`、`hit_handling_method`、`directly_return_similarity`、`meta`,返回更新后的 +`DocumentItem`。名称上限 128 字符;共享文档仍只提供查询。 + `workspace/knowledge/document.ts` 同时维护文档启停、删除、召回设置、向量化、分词索引、 任务取消、生成问题、迁移、同步、导出、原文件下载/替换及标签关联。 批量任务沿用 v2 的 `id_list` / `state_list`;生成问题使用 `document_id_list`, diff --git a/ui/src/api/admin/model-provider.ts b/ui/src/api/admin/model-provider.ts index f53230b04cf..1dd3b460074 100644 --- a/ui/src/api/admin/model-provider.ts +++ b/ui/src/api/admin/model-provider.ts @@ -3,14 +3,9 @@ import type { BaseModelOption, DynamicFormField, ModelProviderItem, ModelTypeOpt const prefix = '/provider' -/** 获取全部模型供应商。 */ -const getProviderList = () => { - return get(prefix) -} - -/** 获取支持指定模型类型的供应商。 */ -const getProviderListByModelType = (modelType: string) => { - return get(prefix, { model_type: modelType }) +/** 获取模型供应商,可按模型类型筛选。 */ +const getProviderList = (query?: { model_type?: string }) => { + return get(prefix, query) } /** 获取创建模型所需的动态表单。 */ @@ -33,4 +28,4 @@ const getBaseModelList = (provider: string, modelType: string) => { return get(`${prefix}/model_list`, { model_type: modelType, provider }) } -export default { getBaseModelList, getBaseModelParamsForm, getModelCreateForm, getModelTypeList, getProviderList, getProviderListByModelType } +export default { getBaseModelList, getBaseModelParamsForm, getModelCreateForm, getModelTypeList, getProviderList } diff --git a/ui/src/api/admin/system/resource-management/tool/tool-workflow.ts b/ui/src/api/admin/system/resource-management/tool/tool-workflow.ts index fcf5cc89635..b496561f3ce 100644 --- a/ui/src/api/admin/system/resource-management/tool/tool-workflow.ts +++ b/ui/src/api/admin/system/resource-management/tool/tool-workflow.ts @@ -7,7 +7,6 @@ import type { ToolExecutionRecord, ToolExecutionRecordDetail, ToolWorkflowDetail, - ToolWorkflowRecord, WorkflowStoreTemplate, WorkflowVersion, WorkflowVersionPayload, @@ -39,9 +38,6 @@ const putToolWorkflowPublish = (toolId: string) => { const postToolWorkflowDebug = (toolId: string, parameters: Record) => postStream(ADMIN_API_BASE_PATH, `${prefix}/${toolId}/debug`, parameters) -/** 查询工具工作流调试的输出和节点执行记录。 */ -const getToolWorkflowRecord = (toolId: string, recordId: string) => get(`${prefix}/${toolId}/tool_record/${recordId}`) - /** 获取工具发布历史,按发布时间倒序返回完整版本快照。 */ const getWorkflowVersions = (toolId: string) => get(`${prefix}/${toolId}/tool_version`) @@ -68,5 +64,4 @@ export default { putToolWorkflow, putToolWorkflowPublish, postToolWorkflowDebug, - getToolWorkflowRecord, } diff --git a/ui/src/api/admin/system/shared-resources/tool/tool-workflow.ts b/ui/src/api/admin/system/shared-resources/tool/tool-workflow.ts index 6772991ac68..1bebb652f41 100644 --- a/ui/src/api/admin/system/shared-resources/tool/tool-workflow.ts +++ b/ui/src/api/admin/system/shared-resources/tool/tool-workflow.ts @@ -7,7 +7,6 @@ import type { ToolExecutionRecord, ToolExecutionRecordDetail, ToolWorkflowDetail, - ToolWorkflowRecord, WorkflowStoreTemplate, WorkflowVersion, WorkflowVersionPayload, @@ -39,9 +38,6 @@ const putToolWorkflowPublish = (toolId: string) => { const postToolWorkflowDebug = (toolId: string, parameters: Record) => postStream(ADMIN_API_BASE_PATH, `${prefix}/${toolId}/debug`, parameters) -/** 查询工具工作流调试的输出和节点执行记录。 */ -const getToolWorkflowRecord = (toolId: string, recordId: string) => get(`${prefix}/${toolId}/tool_record/${recordId}`) - /** 获取工具发布历史,按发布时间倒序返回完整版本快照。 */ const getWorkflowVersions = (toolId: string) => get(`${prefix}/${toolId}/tool_version`) @@ -68,5 +64,4 @@ export default { putToolWorkflow, putToolWorkflowPublish, postToolWorkflowDebug, - getToolWorkflowRecord, } diff --git a/ui/src/api/admin/workspace/application/chat-log.ts b/ui/src/api/admin/workspace/application/chat-log.ts index 8d2c45dcf40..4f10ce11eac 100644 --- a/ui/src/api/admin/workspace/application/chat-log.ts +++ b/ui/src/api/admin/workspace/application/chat-log.ts @@ -30,10 +30,6 @@ const getChatRecordLog = (applicationId: string, chatId: string, page: ParamsPag order_asc: orderAsc, }) -/** 获取聊天记录详情。 */ -const getChatRecordDetails = (applicationId: string, chatId: string, chatRecordId: string) => - get>(`${getPrefix()}/${applicationId}/chat/${chatId}/chat_record/${chatRecordId}`) - /** 获取聊天记录的标注段落。 */ const getMarkChatRecord = (applicationId: string, chatId: string, chatRecordId: string) => get[]>(`${getPrefix()}/${applicationId}/chat/${chatId}/chat_record/${chatRecordId}/improve`) @@ -67,7 +63,6 @@ export default { putChatLogCleanTime, postChatLogAddKnowledge, getChatRecordLog, - getChatRecordDetails, getMarkChatRecord, putChatRecordLog, deleteMarkChatRecord, diff --git a/ui/src/api/admin/workspace/knowledge/document.ts b/ui/src/api/admin/workspace/knowledge/document.ts index ae7b263784d..6e6cc82c8fc 100644 --- a/ui/src/api/admin/workspace/knowledge/document.ts +++ b/ui/src/api/admin/workspace/knowledge/document.ts @@ -8,6 +8,7 @@ import type { DocumentSettingPayload, DocumentTaskState, DocumentTaskType, + DocumentUpdatePayload, } from '@/api/types' import { getWorkspaceId } from '@/utils/resource-context' @@ -21,9 +22,9 @@ const getDocumentPage = (knowledgeId: string, page: ParamsPage, query?: Dict put(`${getPrefix(knowledgeId)}/batch_create`, documents) -/** 更新文档启用状态。 */ -const putDocumentActive = (knowledgeId: string, documentId: string, isActive: boolean) => - put(`${getPrefix(knowledgeId)}/${documentId}`, { is_active: isActive }) +/** 更新文档名称、启用状态或设置,返回保存后的文档。 */ +const putDocument = (knowledgeId: string, documentId: string, data: DocumentUpdatePayload) => + put(`${getPrefix(knowledgeId)}/${documentId}`, data) /** 删除单个文档。 */ const deleteDocument = (knowledgeId: string, documentId: string) => del(`${getPrefix(knowledgeId)}/${documentId}`) @@ -75,10 +76,6 @@ const putLarkDocumentSync = (knowledgeId: string, documentId: string) => const putMulLarkSyncDocument = (knowledgeId: string, documentIds: string[]) => put<{ id_list: string[] }, boolean>(`/workspace/${getWorkspaceId()}/knowledge/lark/${knowledgeId}/_batch`, { id_list: documentIds }) -/** 单个文档设置。 */ -const putDocumentSetting = (knowledgeId: string, documentId: string, data: DocumentSettingPayload) => - put(`${getPrefix(knowledgeId)}/${documentId}`, data) - /** 批量文档设置。 */ const putBatchDocumentSetting = (knowledgeId: string, documentIds: string[], data: DocumentSettingPayload) => put(`${getPrefix(knowledgeId)}/batch_hit_handling`, { ...data, id_list: documentIds }) @@ -117,7 +114,7 @@ const postReplaceDocumentSource = (knowledgeId: string, documentId: string, file export default { getDocumentPage, putQuickCreateDocuments, - putDocumentActive, + putDocument, deleteDocument, putBatchDeleteDocuments, putDocumentRefresh, @@ -126,7 +123,6 @@ export default { putBatchTokenizeDocuments, putCancelTask, putBatchCancelDocumentTask, - putDocumentSetting, putBatchDocumentSetting, putGenerateDocumentQuestions, putMigrateDocuments, diff --git a/ui/src/api/admin/workspace/knowledge/workflow.ts b/ui/src/api/admin/workspace/knowledge/workflow.ts index c17ff77ef16..2bce1a37366 100644 --- a/ui/src/api/admin/workspace/knowledge/workflow.ts +++ b/ui/src/api/admin/workspace/knowledge/workflow.ts @@ -46,15 +46,6 @@ const putKnowledgeWorkflowPublish = (knowledgeId: string) => { return put(`${getPrefix()}/${knowledgeId}/publish`) } -/** 上传知识库调试文件,返回文件访问地址(末段为 file_id)。 */ -const postKnowledgeUploadFile = (knowledgeId: string, file: File) => { - const payload = new FormData() - payload.append('file', file) - payload.append('source_id', knowledgeId) - payload.append('source_type', 'KNOWLEDGE') - return post('/oss/file', payload) -} - /** 获取数据源节点的动态表单配置。 */ const getKnowledgeWorkflowFormList = (knowledgeId: string, type: 'local' | 'tool', id: string, node: Dict) => { return post<{ node: Dict }, Dict[]>(`${getPrefix()}/${knowledgeId}/datasource/${type}/${id}/form_list`, { node }) @@ -97,7 +88,6 @@ export default { postKnowledgeWorkflow, putKnowledgeWorkflow, putKnowledgeWorkflowPublish, - postKnowledgeUploadFile, getKnowledgeWorkflowFormList, postKnowledgeWorkflowDebug, getKnowledgeWorkflowAction, diff --git a/ui/src/api/admin/workspace/tool/workflow.ts b/ui/src/api/admin/workspace/tool/workflow.ts index 81eab1ac79d..182e721089e 100644 --- a/ui/src/api/admin/workspace/tool/workflow.ts +++ b/ui/src/api/admin/workspace/tool/workflow.ts @@ -7,7 +7,6 @@ import type { ToolExecutionRecord, ToolExecutionRecordDetail, ToolWorkflowDetail, - ToolWorkflowRecord, WorkflowStoreTemplate, WorkflowVersion, WorkflowVersionPayload, @@ -43,9 +42,6 @@ const putToolWorkflowPublish = (toolId: string) => { const postToolWorkflowDebug = (toolId: string, parameters: Record) => postStream(ADMIN_API_BASE_PATH, `${getPrefix()}/${toolId}/debug`, parameters) -/** 查询工具工作流调试的输出和节点执行记录。 */ -const getToolWorkflowRecord = (toolId: string, recordId: string) => get(`${getPrefix()}/${toolId}/tool_record/${recordId}`) - /** 获取工具发布历史,按发布时间倒序返回完整版本快照。 */ const getWorkflowVersions = (toolId: string) => get(`${getPrefix()}/${toolId}/tool_version`) @@ -72,5 +68,4 @@ export default { putToolWorkflow, putToolWorkflowPublish, postToolWorkflowDebug, - getToolWorkflowRecord, } diff --git a/ui/src/api/types/document.ts b/ui/src/api/types/document.ts index 318f429c552..62ac0709509 100644 --- a/ui/src/api/types/document.ts +++ b/ui/src/api/types/document.ts @@ -49,3 +49,6 @@ export interface DocumentItem { create_time: string update_time: string } + +/** 单个文档的局部更新字段。 */ +export type DocumentUpdatePayload = Partial> diff --git a/ui/src/api/types/tool.ts b/ui/src/api/types/tool.ts index c44e0a6edcc..226e377b50a 100644 --- a/ui/src/api/types/tool.ts +++ b/ui/src/api/types/tool.ts @@ -172,19 +172,6 @@ export interface UpdateStoreToolPayload { versions: ToolStoreVersion[] } -/** 工具工作流调试完成后的执行记录。 */ -export interface ToolWorkflowRecord { - id: string - state: string - run_time?: number - meta: { - output?: unknown - details?: - | import('@/workflow-canvas/execution-details/types').ExecutionNodeDetail[] - | Record - } -} - /** 工作流工具模板商店的查询响应。 */ export interface ToolWorkflowStoreResponse { additionalProperties: { tags: ToolStoreTag[] } @@ -200,7 +187,9 @@ export interface ToolExecutionRecordDetail { input?: unknown output?: unknown err_message?: string - details?: ToolWorkflowRecord['meta']['details'] + details?: + | import('@/workflow-canvas/execution-details/types').ExecutionNodeDetail[] + | Record } } diff --git a/ui/src/assets/file-type/csv-icon.svg b/ui/src/assets/file-type/csv-icon.svg index 85147ccb46c..fda7cb4ea6f 100644 --- a/ui/src/assets/file-type/csv-icon.svg +++ b/ui/src/assets/file-type/csv-icon.svg @@ -1,7 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/doc-icon.svg b/ui/src/assets/file-type/doc-icon.svg index 899a0086195..6bee0d14ecd 100644 --- a/ui/src/assets/file-type/doc-icon.svg +++ b/ui/src/assets/file-type/doc-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/docx-icon.svg b/ui/src/assets/file-type/docx-icon.svg index 899a0086195..6bee0d14ecd 100644 --- a/ui/src/assets/file-type/docx-icon.svg +++ b/ui/src/assets/file-type/docx-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/file-document-icon.svg b/ui/src/assets/file-type/file-document-icon.svg index 86ac2d3f174..84742536158 100644 --- a/ui/src/assets/file-type/file-document-icon.svg +++ b/ui/src/assets/file-type/file-document-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/html-icon.svg b/ui/src/assets/file-type/html-icon.svg index b59a48826e4..5a4c480147f 100644 --- a/ui/src/assets/file-type/html-icon.svg +++ b/ui/src/assets/file-type/html-icon.svg @@ -1,6 +1,6 @@ - - + + diff --git a/ui/src/assets/file-type/md-icon.svg b/ui/src/assets/file-type/md-icon.svg index 7b35a9242c8..0aba62cc990 100644 --- a/ui/src/assets/file-type/md-icon.svg +++ b/ui/src/assets/file-type/md-icon.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/ui/src/assets/file-type/pdf-icon.svg b/ui/src/assets/file-type/pdf-icon.svg index 17a4be00440..541d8901402 100644 --- a/ui/src/assets/file-type/pdf-icon.svg +++ b/ui/src/assets/file-type/pdf-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/txt-icon.svg b/ui/src/assets/file-type/txt-icon.svg index 051ea2bdaa0..33448e820a9 100644 --- a/ui/src/assets/file-type/txt-icon.svg +++ b/ui/src/assets/file-type/txt-icon.svg @@ -1,7 +1,8 @@ - - - - - - + + + + + + + diff --git a/ui/src/assets/file-type/unknown-icon.svg b/ui/src/assets/file-type/unknown-icon.svg index 20270ac52c5..bbf75088afb 100644 --- a/ui/src/assets/file-type/unknown-icon.svg +++ b/ui/src/assets/file-type/unknown-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/web-link-icon.svg b/ui/src/assets/file-type/web-link-icon.svg index f09fab5ade6..70abcf1e703 100644 --- a/ui/src/assets/file-type/web-link-icon.svg +++ b/ui/src/assets/file-type/web-link-icon.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/ui/src/assets/file-type/xls-icon.svg b/ui/src/assets/file-type/xls-icon.svg index 22cb869537f..bfc2684b705 100644 --- a/ui/src/assets/file-type/xls-icon.svg +++ b/ui/src/assets/file-type/xls-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/xlsx-icon.svg b/ui/src/assets/file-type/xlsx-icon.svg index 22cb869537f..bfc2684b705 100644 --- a/ui/src/assets/file-type/xlsx-icon.svg +++ b/ui/src/assets/file-type/xlsx-icon.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/ui/src/assets/file-type/zip-icon.svg b/ui/src/assets/file-type/zip-icon.svg index ad5d625fb63..7af78f2bf90 100644 --- a/ui/src/assets/file-type/zip-icon.svg +++ b/ui/src/assets/file-type/zip-icon.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index c6978f19653..6fa65f7182f 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -532,11 +532,15 @@ Dialog、Drawer、Popover、嵌套区域等其他大、小表格均禁止开启 必填 `save(name): Promise` 由调用方执行业务请求并返回最终保存的名称;失败必须 reject, 不可吞掉错误后当作成功返回。组件不调用业务 API,仅在保存成功后回写模型。 -默认展示名称,`prefix` 插槽放文档等业务图标;长名称省略并提供原生 title。悬停或内部获得焦点时 -显示编辑按钮,点击后进入输入态并选中名称。Enter 或失焦保存,Esc 取消;输入法选词不提交。 -保存前清理首尾空格,拒绝空名称和纯空白;`maxlength` 可限制长度,`validate(name)` 可返回 -业务错误文案,返回 `undefined` 表示通过。名称未变化直接退出,不请求。 -保存期间只读并显示 loading,失败保留草稿及错误提示,允许重新聚焦后修改、重试或取消。 +`disabled` 默认为 `false`,为 `true` 时保留名称与前缀展示,隐藏编辑按钮且不触发新保存。 +编辑中切换为禁用时退出编辑、丢弃未提交草稿;已经发出的保存请求继续完成。 + +默认展示名称,`prefix` 插槽放文档等业务图标;长名称省略。悬停或内部获得焦点时 +显示编辑按钮,点击后进入输入态并聚焦,光标放在名称末尾。Enter 或失焦保存,Esc 取消;输入法选词不提交。 +编辑态仅使用 `el-input`,不包装 Form、FormItem 或错误 Tooltip。保存前清理首尾空格, +空名称或纯空白时阻止保存并通过 `MsgWarning` 提示“请输入名称”;`maxlength` 可限制长度,`validate(name)` 可返回 +业务错误文案并通过消息提示,返回 `undefined` 表示通过。名称未变化直接退出,不请求。 +保存期间输入框只读,失败保留草稿,接口错误由请求层提示,允许重新聚焦后修改、重试或取消。 名称展示区域保留父级点击行为,编辑按钮和输入区域阻止点击冒泡。 ```vue diff --git a/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue b/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue index c18a8ce06b4..9746b3fcbf6 100644 --- a/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue +++ b/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue @@ -49,7 +49,7 @@ const modelAvailable = computed(() => modelOptions.value.some(({ id, status }) = function loadModels() { modelLoading.value = true - return Promise.all([requestModelApi.value.getModelListWithShared({ model_type: 'LLM' }), ModelProviderApi.getProviderListByModelType('LLM')]) + return Promise.all([requestModelApi.value.getModelListWithShared({ model_type: 'LLM' }), ModelProviderApi.getProviderList({ model_type: 'LLM' })]) .then(([models, providers]) => { modelOptions.value = models providerOptions.value = providers diff --git a/ui/src/components/mk-edit-name/index.vue b/ui/src/components/mk-edit-name/index.vue index 104c6093844..5414835403e 100644 --- a/ui/src/components/mk-edit-name/index.vue +++ b/ui/src/components/mk-edit-name/index.vue @@ -1,12 +1,13 @@
+
- - - - - - - - - + @blur="handleBlur" + @compositionstart="composing = true" + @compositionend="handleCompositionEnd" + />
diff --git a/ui/src/utils/UTILS_README.md b/ui/src/utils/UTILS_README.md index 3bad9694f50..e95305d5d4b 100644 --- a/ui/src/utils/UTILS_README.md +++ b/ui/src/utils/UTILS_README.md @@ -102,8 +102,9 @@ MkTable、MkFormList 的排序优先使用其公开属性;普通列表再直 轻量反馈按需从 `utils/message.ts` 导入 `MsgSuccess`、`MsgInfo`、`MsgWarning` 或 `MsgError`, 不要在业务代码和请求层直接调用 `ElMessage`。 -消息默认显示关闭按钮并在 `3000ms` 后关闭;特殊场景通过第二个参数覆盖 Element Plus 消息 -选项。确认操作统一按需导入 `MsgConfirm(title, message, options?)`,默认提供确认、取消按钮和 +消息默认显示关闭按钮、在 `3000ms` 后关闭,并通过 `grouping: true` 合并相同内容的消息; +调用方无需重复传入。特殊场景通过第二个参数覆盖 Element Plus 消息选项,包括 `grouping: false`。 +确认操作统一按需导入 `MsgConfirm(title, message, options?)`,默认提供确认、取消按钮和 warning 类型;输入和普通警告弹窗继续直接使用 `ElMessageBox`。 ```ts diff --git a/ui/src/utils/message.ts b/ui/src/utils/message.ts index 91702ec9613..9a434c020a9 100644 --- a/ui/src/utils/message.ts +++ b/ui/src/utils/message.ts @@ -7,7 +7,7 @@ type MessageOverrides = Omit, 'message' | 'type'> type ConfirmContent = NonNullable type ConfirmOverrides = Omit -const DEFAULT_MESSAGE_OPTIONS: MessageOverrides = { duration: 3_000, showClose: true } +const DEFAULT_MESSAGE_OPTIONS: MessageOverrides = { duration: 3_000, showClose: true, grouping: true } function MKMessage(type: MessageType, message: MessageContent, options?: MessageOverrides) { return ElMessage({ ...DEFAULT_MESSAGE_OPTIONS, ...options, message, type }) diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index 6a800995c08..0bbd7e98c91 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -701,6 +701,10 @@ Workspace API 内部通过 `getWorkspaceId()` 读取当前路由工作空间。 搜索只提供名称 `name` 和创建者 `create_user`;创建者通过 Workspace `CommonApi.getAllUsers` 加载,支持按 `nick_name` 远程搜索。列表使用 `documentData`、`paginationConfig`、`documentQuery`, 查询方法为 `loadDocuments`,搜索处理为 `handleSearchChange`,搜索变化后回到第一页。 +文档名称列显式导入非全局 `MkEditName`,名称上限 128 字符,保存成功后按文档 ID 更新当前行的 +名称与更新时间;失败交由组件保留草稿。共享文档只读展示名称,列不叠加表格溢出提示。 +名称校验通过 `validate` 回调拒绝 `: \ / ? * [ ]`,命中任一字符时弹出提示并阻止保存。 + 文档页通过 `onMounted` 加载文档列表,创建者选项在展开下拉或输入关键词时通过 `remoteMethod` 按需加载,不在进入页面时预加载;其他列表页的同类创建者筛选遵循相同方式。不额外监听路由重置状态。切换工作空间 整页加载并返回知识库列表;当前知识库与共享资源入口均从其他页面进入,挂载时初始化筛选和分页。 diff --git a/ui/src/views/knowledge-detail/library/document/action-dropdown/setting/SettingDocumentAction.vue b/ui/src/views/knowledge-detail/library/document/action-dropdown/setting/SettingDocumentAction.vue index 6b83c55ea4f..11ce61cf640 100644 --- a/ui/src/views/knowledge-detail/library/document/action-dropdown/setting/SettingDocumentAction.vue +++ b/ui/src/views/knowledge-detail/library/document/action-dropdown/setting/SettingDocumentAction.vue @@ -37,7 +37,7 @@ function handleSubmit(data: DocumentSettingPayload) { if (loading.value) return loading.value = true return props.api - .putDocumentSetting(targetKnowledgeId.value, targetDocumentId.value, data) + .putDocument(targetKnowledgeId.value, targetDocumentId.value, data) .then(() => { MsgSuccess('设置成功') settingDialogRef.value?.close() diff --git a/ui/src/views/knowledge-detail/library/document/index.vue b/ui/src/views/knowledge-detail/library/document/index.vue index 6446dde5b89..26357dee88e 100644 --- a/ui/src/views/knowledge-detail/library/document/index.vue +++ b/ui/src/views/knowledge-detail/library/document/index.vue @@ -3,6 +3,7 @@ import { computed, onBeforeUnmount, onMounted, ref } from 'vue' import { useRoute } from 'vue-router' import type { CascaderOption } from 'element-plus' import type MkQuickCreate from '@/components/global/mk-table/MkQuickCreate.vue' +import MkEditName from '@/components/mk-edit-name/index.vue' import type { ResourceDetailPageProps } from '@/layout/ResourceDetailLayout.vue' import DocumentApi from '@/api/admin/workspace/knowledge/document' import SharedDocumentApi from '@/api/admin/workspace/shared/knowledge/document' @@ -19,6 +20,7 @@ import { datetimeFormat } from '@/utils/time' import { isWorkspaceSharedResource } from '@/utils/resource-context' import { numberFormat } from '@/utils/number' import { MsgSuccess } from '@/utils/message' +import { getFileIconUrl } from '@/utils/icon' import DocumentStatus from './components/DocumentStatus.vue' import DocumentTags from './components/DocumentTags.vue' import { @@ -72,6 +74,25 @@ function handleCreateDocument(name: string) { }) } +/* 文档名称编辑 */ +function validateDocumentName(name: string): string | undefined { + if (/[:\\/?*\[\]]/.test(name)) { + return '文件名称不能包含以下特殊字符:: \\ / ? * [ ]' + } +} + +function saveDocumentName(documentId: string, name: string): Promise { + return DocumentApi.putDocument(knowledgeId.value, documentId, { name }).then((document) => { + // 轮询可能已替换行对象,按 ID 更新当前列表中的名称与更新时间。 + const currentDocument = documentData.value.find(({ id }) => id === documentId) + if (currentDocument) { + currentDocument.name = document.name + currentDocument.update_time = document.update_time + } + return document.name + }) +} + /* 文档筛选与分页查询 */ const loading = ref(false) const documentData = ref([]) @@ -221,7 +242,7 @@ const operationLoading = ref(false) function handleChangeActive(document: DocumentItem) { if (operationLoading.value) return false operationLoading.value = true - return DocumentApi.putDocumentActive(knowledgeId.value, document.id, !document.is_active) + return DocumentApi.putDocument(knowledgeId.value, document.id, { is_active: !document.is_active }) .then(() => { MsgSuccess('操作成功') return refreshAfterOperation().then(() => false) @@ -276,7 +297,24 @@ onBeforeUnmount(() => { - + + + ([]) function loadModelOptions() { loading.value = true const requestModelApi = isSystemSharedResource() ? SystemSharedModelApi : ModelApi - return Promise.all([requestModelApi.getModelListWithShared({ model_type: 'EMBEDDING' }), ModelProviderApi.getProviderListByModelType('EMBEDDING')]) + return Promise.all([ + requestModelApi.getModelListWithShared({ model_type: 'EMBEDDING' }), + ModelProviderApi.getProviderList({ model_type: 'EMBEDDING' }), + ]) .then(([models, providers]) => { modelOptions.value = models providerOptions.value = providers diff --git a/ui/src/views/model/create-model/SelectProviderDrawer.vue b/ui/src/views/model/create-model/SelectProviderDrawer.vue index 1a1b8e4142e..f28f9edb23c 100644 --- a/ui/src/views/model/create-model/SelectProviderDrawer.vue +++ b/ui/src/views/model/create-model/SelectProviderDrawer.vue @@ -47,7 +47,7 @@ function handleModelTypeChange(value: string) { return } loading.value = true - ProviderApi.getProviderListByModelType(value) + ProviderApi.getProviderList({ model_type: value }) .then((providers) => { providerOptions.value = providers }) diff --git a/ui/src/views/system/resource-management/application/index.vue b/ui/src/views/system/resource-management/application/index.vue index 09f5eebe9a1..d801436130f 100644 --- a/ui/src/views/system/resource-management/application/index.vue +++ b/ui/src/views/system/resource-management/application/index.vue @@ -107,7 +107,7 @@ onMounted(() => { diff --git a/ui/src/views/system/resource-management/model/index.vue b/ui/src/views/system/resource-management/model/index.vue index 7bc76d66c34..7abaefd61b9 100644 --- a/ui/src/views/system/resource-management/model/index.vue +++ b/ui/src/views/system/resource-management/model/index.vue @@ -120,7 +120,7 @@ onMounted(() => { @@ -128,7 +128,7 @@ onMounted(() => { diff --git a/ui/src/views/system/resource-management/tool/index.vue b/ui/src/views/system/resource-management/tool/index.vue index bd1a25a6096..a419990caf6 100644 --- a/ui/src/views/system/resource-management/tool/index.vue +++ b/ui/src/views/system/resource-management/tool/index.vue @@ -148,7 +148,7 @@ onMounted(() => { diff --git a/ui/src/views/tool/tool-form/component/python-code/CodeGenerate.vue b/ui/src/views/tool/tool-form/component/python-code/CodeGenerate.vue index 8dd5cc91d7c..5d73de569a2 100644 --- a/ui/src/views/tool/tool-form/component/python-code/CodeGenerate.vue +++ b/ui/src/views/tool/tool-form/component/python-code/CodeGenerate.vue @@ -87,7 +87,7 @@ function loadModels() { model_type: 'LLM', ...(!isSystemSharedResource() && workspaceId ? { workspace_id: workspaceId } : {}), }) - return Promise.all([modelRequest, ModelProviderApi.getProviderListByModelType('LLM')]) + return Promise.all([modelRequest, ModelProviderApi.getProviderList({ model_type: 'LLM' })]) .then(([models, providers]) => { modelOptions.value = models providerOptions.value = providers diff --git a/ui/src/views/workflow/knowledge/debug/DebugDrawer.vue b/ui/src/views/workflow/knowledge/debug/DebugDrawer.vue index acf48931d88..feb2a32b8e5 100644 --- a/ui/src/views/workflow/knowledge/debug/DebugDrawer.vue +++ b/ui/src/views/workflow/knowledge/debug/DebugDrawer.vue @@ -2,6 +2,8 @@ import { computed, nextTick, provide, ref, useTemplateRef, type Component } from 'vue' import type LogicFlow from '@logicflow/core' import KnowledgeWorkflowApi from '@/api/admin/workspace/knowledge/workflow' +import FileApi from '@/api/admin/file' +import { FILE_SOURCE_TYPE } from '@/api/enums' import type { Dict } from '@/api/types' import { WorkflowNodeType } from '@/workflow-canvas/types' import type { FormField } from '@/components/mk-dynamics-form' @@ -18,7 +20,7 @@ type ActionStep = 'data_source' | 'knowledge_base' | 'result' const actionComponents: Record = { data_source: DataSource, knowledge_base: KnowledgeBase, result: Result } // mk-dynamics-form 的上传项通过 inject('upload') 获取上传函数;返回值的 data 为文件地址(末段即 file_id)。 -provide('upload', (file: File) => KnowledgeWorkflowApi.postKnowledgeUploadFile(props.knowledgeId, file).then((url) => ({ data: url }))) +provide('upload', (file: File) => FileApi.postUploadFile(file, props.knowledgeId, FILE_SOURCE_TYPE.KNOWLEDGE).request.then((url) => ({ data: url }))) const visible = ref(false) const loading = ref(false) diff --git a/ui/src/views/workflow/tool/debug/ResultDrawer.vue b/ui/src/views/workflow/tool/debug/ResultDrawer.vue index 7981875aecb..90edf598e17 100644 --- a/ui/src/views/workflow/tool/debug/ResultDrawer.vue +++ b/ui/src/views/workflow/tool/debug/ResultDrawer.vue @@ -2,7 +2,7 @@ import { computed, onBeforeUnmount, provide, ref } from 'vue' import { cloneDeep } from 'lodash' import WorkflowApi from '@/api/admin/workspace/tool/workflow' -import type { ToolWorkflowRecord } from '@/api/types' +import type { ToolExecutionRecordDetail } from '@/api/types' import { MsgError } from '@/utils/message' import { ConversationStream } from '@/conversation-panel/core/stream' import { aggregators } from '@/conversation-panel/core/aggregators' @@ -32,13 +32,13 @@ const running = defineModel('running', { default: false }) const visible = ref(false) const activeTab = ref('output') const blocks = ref([]) -const record = ref() +const record = ref() const errorMessage = ref('') let inputParameters: Record = {} let recordId = '' let stream: ConversationStream | undefined -const executionDetails = computed(() => Object.values(record.value?.meta.details ?? {})) -const output = computed(() => JSON.stringify(record.value?.meta.output ?? {}, null, 2)) +const executionDetails = computed(() => Object.values(record.value?.meta?.details ?? {})) +const output = computed(() => JSON.stringify(record.value?.meta?.output ?? {}, null, 2)) function receiveChunk(chunk: DebugChunk) { if (chunk.chat_record_id) recordId = chunk.chat_record_id @@ -77,7 +77,7 @@ async function execute(extra: Record = {}) { await stream.start() if (!visible.value) return if (streamError) throw streamError - const result = await (props.api ?? WorkflowApi).getToolWorkflowRecord(props.toolId, recordId) + const result = await (props.api ?? WorkflowApi).getToolExecutionRecordDetail(props.toolId, recordId) if (visible.value) record.value = result } catch (error) { if (visible.value) {