diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index 4c2a35b43d3..81713e8cedc 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -170,6 +170,15 @@ v3 编辑表单提交 `{ name, description }`,标题上限 64、更新说明 共享工具 API 不提供工作空间文件夹移动或批量接口;复用卡片、Action 和表单接收完整 Workspace 与 System 共享 API 的联合类型,不补造接口以匹配 Workspace 方法集合。 +### System 共享知识库 + +`system/shared-resources/knowledge/knowledge.ts` 使用 `/system/shared/knowledge`,维护分页、详情、 +通用 / Web / 飞书 / 工作流创建、导入、删除、重新向量化、Web 同步、关联问题、分词索引、MCP +配置与三种导出。工作流创建在 Workspace 与 System 共享范围均由同一个 Knowledge API 的 +`postKnowledgeWorkflow` 提交;`workspace/knowledge/workflow.ts` 仅维护已创建知识库的工作流 +画布接口。System 共享范围没有工作空间文件夹、批量接口或独立的知识库工作流 API 文件。复用创建入口 +和卡片 Action 时使用完整 Workspace / System 资源管理 / System 共享知识库 API 的联合类型,由页面显式传入当前范围的 API。 + ### 工具代码生成 三个范围的 `tool/tool.ts` 均提供 `postToolGenerateCode(payload)`,沿用 v2 的 diff --git a/ui/src/api/admin/system/shared-resources/knowledge/knowledge.ts b/ui/src/api/admin/system/shared-resources/knowledge/knowledge.ts new file mode 100644 index 00000000000..4424f4ef4b1 --- /dev/null +++ b/ui/src/api/admin/system/shared-resources/knowledge/knowledge.ts @@ -0,0 +1,104 @@ +import { del, get, getExportFile, post, put } from '@/api/admin/core/request' +import type { ParamsPage, ResponsePage } from '@/api/admin/core/types' +import type { + Dict, + KnowledgeCreatePayload, + KnowledgeDetail, + KnowledgeGeneratePayload, + KnowledgeItem, + KnowledgeSyncType, + KnowledgeWorkflowCreatePayload, + LarkKnowledgeCreatePayload, + WebKnowledgeCreatePayload, +} from '@/api/types' + +const prefix = '/system/shared/knowledge' + +/** 获取 System 共享知识库分页列表。 */ +const getKnowledgePage = (page: ParamsPage, query?: Dict) => { + return get>(`${prefix}/${page.currentPage}/${page.pageSize}`, query) +} + +/** 获取 System 共享知识库详情。 */ +const getKnowledgeDetail = (knowledgeId: string) => get(`${prefix}/${knowledgeId}`) + +/** 创建 System 共享通用知识库。 */ +const postKnowledge = (payload: KnowledgeCreatePayload) => post(`${prefix}/base`, payload) + +/** 创建 System 共享 Web 知识库。 */ +const postWebKnowledge = (payload: WebKnowledgeCreatePayload) => post(`${prefix}/web`, payload) + +/** 创建 System 共享飞书知识库。 */ +const postLarkKnowledge = (payload: LarkKnowledgeCreatePayload) => post(`${prefix}/lark/save`, payload) + +/** 创建 System 共享工作流知识库。 */ +const postKnowledgeWorkflow = (payload: KnowledgeWorkflowCreatePayload) => + post(`${prefix}/workflow`, payload) + +/** 导入知识库压缩包并创建 System 共享知识库。 */ +const postKnowledgeImport = (file: File, folderId: string) => { + const payload = new FormData() + payload.append('file', file) + payload.append('folder_id', folderId) + return post(`${prefix}/import_knowledge`, payload) +} + +/** 更新 System 共享知识库信息。 */ +const putKnowledge = (knowledgeId: string, payload: Partial) => + put, KnowledgeItem>(`${prefix}/${knowledgeId}`, payload) + +/** 删除 System 共享知识库。 */ +const deleteKnowledge = (knowledgeId: string) => del(`${prefix}/${knowledgeId}`) + +/** 根据知识库中的分段生成关联问题。 */ +const putGenerateKnowledgeQuestions = (knowledgeId: string, payload: KnowledgeGeneratePayload) => { + return put(`${prefix}/${knowledgeId}/generate_related`, payload) +} + +/** 对知识库中的文档重新向量化。 */ +const putReEmbeddingKnowledge = (knowledgeId: string) => put(`${prefix}/${knowledgeId}/embedding`) + +/** 同步 System 共享 Web 知识库。 */ +const putSyncWebKnowledge = (knowledgeId: string, syncType: KnowledgeSyncType) => { + return put(`${prefix}/${knowledgeId}/sync`, undefined, { sync_type: syncType }) +} + +/** 将知识库文档导出为 Excel。 */ +const exportKnowledgeExcel = (knowledgeId: string, knowledgeName: string) => getExportFile(`${knowledgeName}.xlsx`, `${prefix}/${knowledgeId}/export`) + +/** 将知识库文档及图片导出为 ZIP。 */ +const exportKnowledgeZip = (knowledgeId: string, knowledgeName: string) => + getExportFile(`${knowledgeName}.zip`, `${prefix}/${knowledgeId}/export_zip`) + +/** 导出可用于导入创建的知识库压缩包。 */ +const exportKnowledge = (knowledgeId: string, knowledgeName: string) => + getExportFile(`${knowledgeName}.zip`, `${prefix}/${knowledgeId}/export_knowledge`) + +/** 获取知识库外部检索服务生成的 MCP 连接配置。 */ +const getKnowledgeMcpConfig = (knowledgeId: string): Promise => + get<{ mcp_config: Record }>(`${prefix}/${knowledgeId}/external_service`).then(({ mcp_config }) => + JSON.stringify(mcp_config, null, 2), + ) + +/** 提交知识库分词索引任务。 */ +const putKnowledgeKeywordIndex = (knowledgeId: string) => put(`${prefix}/${knowledgeId}/tokenize`) + +export default { + deleteKnowledge, + exportKnowledge, + exportKnowledgeExcel, + exportKnowledgeZip, + getKnowledgeDetail, + getKnowledgeMcpConfig, + getKnowledgePage, + postKnowledge, + postKnowledgeImport, + postKnowledgeWorkflow, + postLarkKnowledge, + postWebKnowledge, + putGenerateKnowledgeQuestions, + putKnowledge, + putKnowledgeKeywordIndex, + putReEmbeddingKnowledge, + putSyncWebKnowledge, +} diff --git a/ui/src/api/admin/workspace/knowledge/knowledge.ts b/ui/src/api/admin/workspace/knowledge/knowledge.ts index b75070b74dc..2f736c516c4 100644 --- a/ui/src/api/admin/workspace/knowledge/knowledge.ts +++ b/ui/src/api/admin/workspace/knowledge/knowledge.ts @@ -8,6 +8,7 @@ import type { KnowledgeGeneratePayload, KnowledgeSyncType, KnowledgeCreatePayload, + KnowledgeWorkflowCreatePayload, WebKnowledgeCreatePayload, LarkKnowledgeCreatePayload, } from '@/api/types' @@ -47,6 +48,11 @@ const postLarkKnowledge = (payload: LarkKnowledgeCreatePayload) => { return post(`${getPrefix()}/lark/save`, payload) } +/** 创建工作流知识库。 */ +const postKnowledgeWorkflow = (payload: KnowledgeWorkflowCreatePayload) => { + return post(`${getPrefix()}/workflow`, payload) +} + /** 删除工作空间知识库。 */ const deleteKnowledge = (knowledgeId: string) => { return del(`${getPrefix()}/${knowledgeId}`) @@ -132,6 +138,7 @@ export default { postKnowledge, postWebKnowledge, postLarkKnowledge, + postKnowledgeWorkflow, deleteKnowledge, getAllKnowledge, getKnowledgeDetail, diff --git a/ui/src/api/admin/workspace/knowledge/workflow.ts b/ui/src/api/admin/workspace/knowledge/workflow.ts index 2bce1a37366..50fac32d9f1 100644 --- a/ui/src/api/admin/workspace/knowledge/workflow.ts +++ b/ui/src/api/admin/workspace/knowledge/workflow.ts @@ -4,10 +4,7 @@ import { get, post, put, getExportFile } from '../../core/request' import type { DefaultModelSettingPayload, Dict, - KnowledgeItem, KnowledgeExecutionRecord, - KnowledgeCreatePayload, - KnowledgeWorkflowTemplate, KnowledgeWorkflowAction, KnowledgeWorkflowDebugPayload, KnowledgeWorkflowDetail, @@ -21,21 +18,11 @@ type KnowledgeWorkflowPayload = | { default_model_setting?: DefaultModelSettingPayload; work_flow: LogicFlow.GraphConfigData; work_flow_template?: never } | { work_flow_template: WorkflowStoreTemplate; work_flow?: never } -interface CreateKnowledgeWorkflowPayload extends KnowledgeCreatePayload { - work_flow: LogicFlow.GraphConfigData - work_flow_template?: KnowledgeWorkflowTemplate -} - const getPrefix = () => { const workspaceId = getWorkspaceId() return `/workspace/${workspaceId}/knowledge` } -/** 创建工作流知识库。 */ -const postKnowledgeWorkflow = (payload: CreateKnowledgeWorkflowPayload) => { - return post(`${getPrefix()}/workflow`, payload) -} - /** 保存知识库工作流。 */ const putKnowledgeWorkflow = (knowledgeId: string, payload: KnowledgeWorkflowPayload) => { return put(`${getPrefix()}/${knowledgeId}/workflow`, payload) @@ -85,7 +72,6 @@ export default { getWorkflowVersions, putWorkflowVersion, exportKnowledgeWorkflow, - postKnowledgeWorkflow, putKnowledgeWorkflow, putKnowledgeWorkflowPublish, getKnowledgeWorkflowFormList, diff --git a/ui/src/api/types/knowledge.ts b/ui/src/api/types/knowledge.ts index 08eeed2c1c1..8e589ee6aa8 100644 --- a/ui/src/api/types/knowledge.ts +++ b/ui/src/api/types/knowledge.ts @@ -104,6 +104,12 @@ export interface KnowledgeCreatePayload { type: KnowledgeType } +/** 创建工作流知识库的请求参数。 */ +export interface KnowledgeWorkflowCreatePayload extends KnowledgeCreatePayload { + work_flow: LogicFlow.GraphConfigData + work_flow_template?: KnowledgeWorkflowTemplate +} + /** Web 文档分段、视觉处理和索引策略。 */ export interface DocumentStrategy { split: { mode: 'smart' | 'advanced'; patterns: string[] | null; min_length: number; max_length: number; child_length: number; auto_clean: boolean } diff --git a/ui/src/router/ROUTE_README.md b/ui/src/router/ROUTE_README.md index 59d32581236..de4fc01b74b 100644 --- a/ui/src/router/ROUTE_README.md +++ b/ui/src/router/ROUTE_README.md @@ -255,7 +255,8 @@ System 共享资源页面: /admin/system/share/tools ``` -`system-shared-tools` 渲染 `views/system/shared-resources/tool/index.vue`,提供共享工具管理页面。 +`system-shared-knowledge` 渲染 `views/system/shared-resources/knowledge/index.vue`,提供共享知识库 +卡片管理页面;`system-shared-tools` 渲染 `views/system/shared-resources/tool/index.vue`,提供共享工具管理页面。 共享资源路由是 System 导航的一部分,继续在 `admin/system/index.ts` 的 `share` 子路由中维护。 已实现的共享资源页面放在 `views/system/shared-resources/`,由页面处理 System 范围的查询和操作, diff --git a/ui/src/router/admin/system/index.ts b/ui/src/router/admin/system/index.ts index 48cad59be56..03d75e11147 100644 --- a/ui/src/router/admin/system/index.ts +++ b/ui/src/router/admin/system/index.ts @@ -200,7 +200,7 @@ export const systemRoutes: RouteRecordRaw = { { path: 'knowledge', name: 'system-shared-knowledge', - component: () => import('@/views/system/index.vue'), + component: () => import('@/views/system/shared-resources/knowledge/index.vue'), meta: { title: '知识库', order: 10, permission: perm.knowledge.share.read, next: 'system-shared-tools' }, }, diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index 2b925514a2c..5a956a79707 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -214,7 +214,9 @@ src/views/knowledge/ ``` `KnowledgeCard` 只负责展示、选择状态和 `action-dropdown` 插槽;页面传入完整 Knowledge API, -组合单项转移、删除 Action,并管理批量选择、全选、批量转移与批量删除。共享知识库不展示这些操作。 +组合单项转移、删除 Action,并管理批量选择、全选、批量转移与批量删除。工作空间共享知识库保持只读, +不传操作插槽并传入 `disabled`;System 共享知识库页传入 `shared`、不传 `disabled`,保留共享标识, +并组合同步、向量化、生成问题、分词索引、MCP 配置、关联资源、导出及删除等菜单操作。 `GenerateQuestionsAction` 在非共享知识库菜单提供“生成问题”,复用公共 `GenerateQuestionsDialog`,打开时固定知识库 ID,提交知识库生成接口;共用页面 loading, 成功提示并关闭,失败保留表单。不新增权限判断。 @@ -257,7 +259,10 @@ MCP 配置沿用工具的只读文本与悬浮复制交互,专属弹窗按需 通过 `isSystemResource()`、`isSystemSharedResource()` 判断,供应商继续使用共用 Provider API。 `ButtonCreateKnowledge` 内聚四类创建浮层 Ref 和打开动作,列表页传入目标 `folderId`,通过 -`refresh` 刷新列表。入口支持 `trigger` 插槽替换默认创建按钮,下拉使用 `persistent`。 +`refresh` 刷新列表。入口支持 `trigger` 插槽替换默认创建按钮,下拉使用 `persistent`。默认使用 +Workspace 知识库 API;System 共享知识库页传入完整 System 共享知识库 API,创建、导入与工作流创建 +均不读取工作空间 ID。创建入口及模板中心只接收一个完整 Knowledge API,工作流创建也使用该对象的 +`postKnowledgeWorkflow`;已创建知识库的工作流画布接口仍由 `workspace/knowledge/workflow.ts` 维护。 各创建浮层接收 `folderId`,通过 `open()` 打开;工作流额外接受可选的商店模板。共用的 `KnowledgeBaseForm` 负责名称、描述、Embedding 模型必填校验以及工作空间和共享模型查询, 根据 `isSystemSharedResource()` 选择 System 共享 Model API 或 Workspace Model API, @@ -267,7 +272,8 @@ MCP 配置沿用工具的只读文本与悬浮复制交互,专属弹窗按需 刷新选项不覆盖用户选择或设置页回填的模型。 创建前校验表单,提交期间禁止重复提交和关闭;成功后刷新用户基础资料并通知列表刷新, 普通类型将接口返回的 `knowledge.type` 通过 `KNOWLEDGE_TYPE_MAP` 转为字符串后进入文档列表,工作流进入画布。常驻弹窗在关闭动画结束后清理表单,打开时只回填本次模板与显示,工作流模板使用 -`cloneDeep` 隔离;创建流程使用 Workspace API,不通过路由字符串推测 System 范围。 +`cloneDeep` 隔离;创建流程默认使用 Workspace API,不通过路由字符串推测 System 范围;System +共享页通过入口显式传入对应 API,创建成功后仅刷新共享列表,不进入工作空间详情或工作流路由。 飞书创建沿用扩展接口 `/lark/save`,部署环境需要提供该接口。 “导入创建”沿用智能体和工具的菜单文件选择交互,调用 `postKnowledgeImport` 上传文件及当前 `folderId`,导入成功后先刷新用户基础资料,再通知知识库列表刷新。上传期间禁止重复导入, @@ -382,6 +388,8 @@ Action 放入 `views/system/shared-resources//action-dropdown/`。Act ```text src/views/system/shared-resources/ +├── knowledge/ +│ └── index.vue ├── model/ │ └── index.vue └── tool/ @@ -395,6 +403,12 @@ src/views/system/shared-resources/ 共享页开启工作流创建,创建后进入 `system-shared-workflow-tool`。共享页支持普通工具、Skills、MCP、数据源及 导入创建,工作流卡片点击进入画布(支持 Ctrl / Command 新标签页),编辑菜单仍修改基础信息。共享页不组合工作空间专用的移动、授权和触发器入口。 +`KnowledgeSharedView` 使用 System 共享知识库 API,复用 `KnowledgeCard`、创建入口和模板中心。 +卡片点击绑定页面的 `handleOpenKnowledge`,详情路由暂未接入,方法内保留 `router.push` 的 TODO。 +创建、模板创建和导入均使用 System 共享接口;Web 同步、向量化、关联问题、分词索引、 +MCP 配置、关联资源、导出与删除通过复用 Action 组合,授权工作空间暂保留 TODO,不组合工作空间专用的设置、 +文件夹移动或批量操作。 + System 用户页面按业务流程归拢操作入口和专属 Dialog。入口组件管理弹窗 Ref、打开动作并转发 `refresh`;列表页负责查询、批量选择和刷新策略,创建与编辑共用的 `UserFromDrawer` 仍由页面管理。 diff --git a/ui/src/views/knowledge/components/ButtonCreateKnowledge.vue b/ui/src/views/knowledge/components/ButtonCreateKnowledge.vue index 20e533d3df2..cfc3c8464e9 100644 --- a/ui/src/views/knowledge/components/ButtonCreateKnowledge.vue +++ b/ui/src/views/knowledge/components/ButtonCreateKnowledge.vue @@ -2,6 +2,7 @@ import { computed, ref, useTemplateRef, type CSSProperties } from 'vue' import type { UploadFile, UploadInstance } from 'element-plus' import KnowledgeApi from '@/api/admin/workspace/knowledge/knowledge' +import type SystemSharedKnowledgeApi from '@/api/admin/system/shared-resources/knowledge/knowledge' import { KNOWLEDGE_TYPE } from '@/api/enums' import { useStore } from '@/stores' import { MsgSuccess } from '@/utils/message' @@ -14,13 +15,14 @@ defineOptions({ name: 'ButtonCreateKnowledge' }) const props = withDefaults( defineProps<{ + api?: typeof KnowledgeApi | typeof SystemSharedKnowledgeApi folderId: string trigger?: 'click' | 'hover' | 'contextmenu' popperStyle?: CSSProperties popperClass?: string fitTriggerWidth?: boolean }>(), - { trigger: 'click', fitTriggerWidth: false }, + { api: () => KnowledgeApi, trigger: 'click', fitTriggerWidth: false }, ) const { auth } = useStore() @@ -76,7 +78,7 @@ const importing = ref(false) function handleImportCreate(file: UploadFile) { if (!file.raw || importing.value) return importing.value = true - return KnowledgeApi.postKnowledgeImport(file.raw, props.folderId) + return props.api.postKnowledgeImport(file.raw, props.folderId) .then(() => { // 先刷新新资源权限,再通知列表加载导入的知识库。 return auth.loadAuthBaseProfile().then(() => { @@ -164,8 +166,8 @@ function handleImportCreate(file: UploadFile) { - - - - + + + + diff --git a/ui/src/views/knowledge/components/ButtonTemplateStore.vue b/ui/src/views/knowledge/components/ButtonTemplateStore.vue index 574351d359e..cea64bdef5f 100644 --- a/ui/src/views/knowledge/components/ButtonTemplateStore.vue +++ b/ui/src/views/knowledge/components/ButtonTemplateStore.vue @@ -1,13 +1,18 @@ + +