From 6b5e5bf417523be86bb4b076659b9db2f340c6b3 Mon Sep 17 00:00:00 2001 From: "xinxin.wu" Date: Sat, 10 Oct 2026 16:29:53 +0800 Subject: [PATCH] feat: database tags management --- ui/src/api/API_README.md | 23 ++ .../api/admin/workspace/knowledge/document.ts | 20 ++ ui/src/api/admin/workspace/knowledge/tags.ts | 35 ++- ui/src/api/types/knowledge.ts | 13 +- ui/src/views/VIEW_README.md | 43 ++- .../library/tags/TagDocumentDrawer.vue | 214 +++++++++++++++ .../tags/components/ButtonImportTags.vue | 144 ++++++++++ .../library/tags/components/TagFormDialog.vue | 172 ++++++++++++ .../knowledge-detail/library/tags/index.vue | 247 +++++++++++++++++- 9 files changed, 898 insertions(+), 13 deletions(-) create mode 100644 ui/src/views/knowledge-detail/library/tags/TagDocumentDrawer.vue create mode 100644 ui/src/views/knowledge-detail/library/tags/components/ButtonImportTags.vue create mode 100644 ui/src/views/knowledge-detail/library/tags/components/TagFormDialog.vue diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index 5585dd2fcc3..9ff16552642 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -619,6 +619,29 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展 文档页传 `resource_type: 'document'`,创建者选项复用 Workspace `common.ts` 的 `getAllUsers`。 类型从 `@/api/types` 导入,命中处理枚举从 `@/api/enums` 导入。API 不接收 loading,不重复包装响应。 +### 知识库标签与文档关联 + +`workspace/knowledge/tags.ts` 维护标签创建、编辑和删除,前缀为 +`/workspace//knowledge//tags`,工作空间由 `getWorkspaceId()` 读取。 +标签查询暂保留在 `workspace/knowledge/knowledge.ts`,`getKnowledgeTags(knowledgeId)` 返回非分页 `KnowledgeTagGroup[]`; +标签值中的可选 `doc_count` 表示关联文档数量。`postKnowledgeTags` 直接提交 +`KnowledgeTagPayload[]`(`key`、`value`),用于创建标签和新增标签值; +`putKnowledgeTag` 向 `/` 提交 `KnowledgeTagUpdatePayload`(`id`、`key`、`value`),仅用于已有的单项编辑。 +`deleteKnowledgeTag` 按路径末尾 `key` 删除整个标签、`one` 删除单个标签值; +`putBatchDeleteKnowledgeTags` 使用 PUT `batch_delete`,请求体直接为标签 ID 数组,不包装为 `id_list`。 +标签类型统一维护在 `types/knowledge.ts`。多行编辑等待 V3 新协议,不组合旧接口模拟整组保存, +也不声明推测的新接口;导入、模板下载尚未接入,三个待接请求入口的页面状态处理已预留。 + +文档与标签的关联由 `workspace/knowledge/document.ts` 维护,不使用标签删除接口代替取消关联。 +`getDocumentTags` 查询 `document//tags`,返回分组标签; +`postAddDocumentTags` POST 到 `document/batch_add_tag`,提交 `{ document_ids, tag_ids }`; +`putDeleteDocumentTags` PUT 到 `document//tags/batch_delete`,直接提交标签 ID 数组。 +`putUnlinkTagDocuments` PUT 到知识库下的 `tag//docs_delete`,提交 `{ id_list: documentIds }`, +用于取消同一标签与单个或多个文档的关联。 +关联文档列表复用 `getDocumentPage`,传 `resource_type: 'document'`、`tags: [tagId]`, +未关联列表另传 `tag_exclude: true`;标签数组沿用请求层的 `tags[]` 序列化。 +名称使用 `name`;关联文档抽屉不传 `order_by`,按接口默认顺序展示。 + ### 工作空间共享资源查询 `workspace/shared/` 按最终资源文件拆分:`model.ts` 提供 `getModelList`,`tool.ts` 提供 diff --git a/ui/src/api/admin/workspace/knowledge/document.ts b/ui/src/api/admin/workspace/knowledge/document.ts index 3a637e49633..1dd6d473a15 100644 --- a/ui/src/api/admin/workspace/knowledge/document.ts +++ b/ui/src/api/admin/workspace/knowledge/document.ts @@ -16,6 +16,7 @@ import type { WebDocumentImportPayload, LarkDocumentList, LarkDocumentImportPayload, + KnowledgeTagGroup, } from '@/api/types' import { getWorkspaceId } from '@/utils/resource-context' @@ -154,7 +155,26 @@ const postReplaceDocumentSource = (knowledgeId: string, documentId: string, file return post(`${getPrefix(knowledgeId)}/${documentId}/replace_source_file`, data) } +/** 查询文档当前标签。 */ +const getDocumentTags = (knowledgeId: string, documentId: string) => get(`${getPrefix(knowledgeId)}/${documentId}/tags`) + +/** 给指定文档批量添加已有标签。 */ +const postAddDocumentTags = (knowledgeId: string, documentIds: string[], tagIds: string[]) => + post(`${getPrefix(knowledgeId)}/batch_add_tag`, { document_ids: documentIds, tag_ids: tagIds }) + +/** 从单个文档移除指定标签,不删除标签本身。 */ +const putDeleteDocumentTags = (knowledgeId: string, documentId: string, tagIds: string[]) => + put(`${getPrefix(knowledgeId)}/${documentId}/tags/batch_delete`, tagIds) + +/** 取消指定标签与单个或多个文档的关联。 */ +const putUnlinkTagDocuments = (knowledgeId: string, tagId: string, documentIds: string[]) => + put(`/workspace/${getWorkspaceId()}/knowledge/${knowledgeId}/tag/${tagId}/docs_delete`, { id_list: documentIds }) + export default { + getDocumentTags, + postAddDocumentTags, + putDeleteDocumentTags, + putUnlinkTagDocuments, getDocumentPage, putBatchCreateDocuments, postSplitDocuments, diff --git a/ui/src/api/admin/workspace/knowledge/tags.ts b/ui/src/api/admin/workspace/knowledge/tags.ts index 3c159e0fa03..09f426878b4 100644 --- a/ui/src/api/admin/workspace/knowledge/tags.ts +++ b/ui/src/api/admin/workspace/knowledge/tags.ts @@ -1,10 +1,29 @@ -/** 查询文档当前标签。 */ -const getDocumentTags = (knowledgeId: string, documentId: string) => get(`${getPrefix(knowledgeId)}/${documentId}/tags`) +import { del, post, put } from '../../core/request' +import type { KnowledgeTagPayload, KnowledgeTagUpdatePayload } from '@/api/types' +import { getWorkspaceId } from '@/utils/resource-context' -/** 批量添加文档标签。 */ -const postAddDocumentTags = (knowledgeId: string, documentIds: string[], tagIds: string[]) => - post(`${getPrefix(knowledgeId)}/batch_add_tag`, { document_ids: documentIds, tag_ids: tagIds }) +const getPrefix = (knowledgeId: string) => `/workspace/${getWorkspaceId()}/knowledge/${knowledgeId}/tags` -/** 移除文档标签关联。 */ -const putDeleteDocumentTags = (knowledgeId: string, documentId: string, tagIds: string[]) => - put(`${getPrefix(knowledgeId)}/${documentId}/tags/batch_delete`, tagIds) +// TODO:接入标签导入、模板下载、整组/多行编辑接口。 +// 请求路径、参数和响应类型以 V3 接口协议为准。 + +/** 创建知识库标签或为已有标签新增值。 */ +const postKnowledgeTags = (knowledgeId: string, tags: KnowledgeTagPayload[]) => post(getPrefix(knowledgeId), tags) + +/** 编辑单个知识库标签,不支持多行编辑。 */ +const putKnowledgeTag = (knowledgeId: string, tagId: string, tag: KnowledgeTagUpdatePayload) => + put(`${getPrefix(knowledgeId)}/${tagId}`, tag) + +/** 删除整个标签分组或单个标签值。 */ +const deleteKnowledgeTag = (knowledgeId: string, tagId: string, type: 'key' | 'one') => + del(`${getPrefix(knowledgeId)}/${tagId}/${type}`) + +/** 批量删除所选标签,直接提交标签 ID 数组。 */ +const putBatchDeleteKnowledgeTags = (knowledgeId: string, tagIds: string[]) => put(`${getPrefix(knowledgeId)}/batch_delete`, tagIds) + +export default { + postKnowledgeTags, + putKnowledgeTag, + deleteKnowledgeTag, + putBatchDeleteKnowledgeTags, +} diff --git a/ui/src/api/types/knowledge.ts b/ui/src/api/types/knowledge.ts index 8e589ee6aa8..0aa4c3c0840 100644 --- a/ui/src/api/types/knowledge.ts +++ b/ui/src/api/types/knowledge.ts @@ -55,7 +55,18 @@ export interface KnowledgeDetail extends KnowledgeItem { /** 按标签名称分组的知识库标签。 */ export interface KnowledgeTagGroup { key: string - values: { id: string; value: string; create_time: string; update_time: string }[] + values: { id: string; value: string; doc_count?: number; create_time: string; update_time: string }[] +} + +/** 创建知识库标签的名称和值。 */ +export interface KnowledgeTagPayload { + key: string + value: string +} + +/** 编辑单个知识库标签,保留现有接口的 ID 字段。 */ +export interface KnowledgeTagUpdatePayload extends KnowledgeTagPayload { + id: string } /** 知识库工作流任务状态。 */ diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index be6d22638f2..3d721637125 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -474,6 +474,7 @@ Dialog。新增或重命名文件时,应同步更新所有导入和页面功 | `home/index.vue` | Workspace 首页 | | `knowledge/index.vue` | 工作空间知识库目录与知识库卡片页面 | | `knowledge-detail/index.vue` | 知识库详情页面 | +| `knowledge-detail/library/tags/index.vue` | 标签分组查询、创建、单值编辑、删除与关联文档管理 | | `knowledge-detail/setting/base/index.vue` | 知识库基本信息、来源配置与上传限制设置 | | `knowledge-detail/setting/document-strategy/index.vue` | Web 知识库文档处理策略回填、校验与保存 | | `knowledge-detail/setting/scheduled-sync/index.vue` | Web、飞书与工作流知识库定时同步设置与日志 | @@ -717,9 +718,9 @@ Workspace API 内部通过 `getWorkspaceId()` 读取当前路由工作空间。 `ResourceDetailLayout` 生成资料库、工作流、检索优化、授权与集成、设置目录,返回列表时恢复所属文件夹。 资料库包含文档、图片、标签管理;检索优化包含召回测试、问题、自定义分词;授权与集成包含 对话用户、外部检索服务。资料库页面统一放在 `knowledge-detail/library/` 下,包含 `document/`、 -`image/`、`tag/`;文档专属组件及 Action 随 `document/` 集中维护。其他页面继续放在 +`image/`、`tags/`;文档专属组件及 Action 随 `document/` 集中维护。其他页面继续放在 `knowledge-detail/` 下的 `recall-test/`、`question/`、`dictionary/`、`chat-user/`、`external-retrieval/`。 -图片、标签管理及这五个页面暂只展示占位内容。 +图片及这五个页面暂只展示占位内容。 容器通过 `knowledge-detail/context.ts` 提供只读详情与替换能力;设置页复用已加载详情,保存成功后 更新容器数据,同步名称等展示。基本信息复用创建流程的 `KnowledgeBaseForm`,类型配置和校验留在 `setting/base/index.vue` 中,通用知识库标题为“设置”,其他类型为“基础设置”。 @@ -843,6 +844,44 @@ Action 仍通过上层 `action-dropdown/index.ts` 导出,弹窗仅在目录内 文档详情路由暂未启用,System 知识库详情路由暂未注册。 +### 资料库标签管理 + +`knowledge-detail/library/tags/index.vue` 复用详情布局的 `customHeader` 与 Teleport, +维护搜索、导入入口、创建入口和标签表格,不嵌套页面布局或修改路由。 +通过 `workspace/knowledge/knowledge.ts` 查询全量分组,前端按标签名或值搜索并保留完整命中分组; +先按标签组分页,再展开各组标签值,分页总数为标签组数。 +`MkTable` 合并选择列和标签名,选择行为与工作空间成员表格一致,不额外联动同组记录; +批量底栏按实际选中记录数统计,删除确认明确影响所选记录所属标签及其全部值。 +标签名旁提供新增值、编辑标签、删除标签;行末提供编辑值和删除值, +数量链接打开同目录 `TagDocumentDrawer.vue`。 + +`library/tags/components/TagFormDialog.vue` 为标签管理和后续文档入口共用的创建、编辑弹窗, +接收知识库 ID 与完整 Tags API,参考添加成员流程复用 `MkDialog`、`el-form` 和 `MkFormList`。 +创建允许多行标签名与值;新增值锁定标签名;编辑值回填单项并锁定标签名。 +标签名最多 64 字、标签值最多 128 字,校验必填、纯空白和表单内重复组合。 +创建与单个已有标签值编辑使用已确认接口;整组编辑或编辑中增删行走独立请求入口, +保留编辑前快照、已有 ID 与清理首尾空格后的当前草稿,交由请求入口按 V3 协议映射参数。 +所有分支共用校验、loading、成功关闭和刷新;多行接口未接入时仅提示并保留草稿, +不即时删除、不拼接多次旧请求、不模拟成功。 +常驻弹窗在 `closed` 清理草稿和校验。 + +`library/tags/components/ButtonImportTags.vue` 在同一组件内维护导入按钮与弹窗, +复用 `MkDialog`、`el-form` 和 `MkDragUpload`,不再单独拆分导入 Dialog。 +支持单个 XLS、XLSX 文件的选择、拖拽、更换、删除及必填校验,关闭后清理文件和校验状态。 +接收知识库 ID 与完整 Tags API,页面监听 `refresh` 重新查询标签列表;已预接提交 loading、重复提交保护、 +成功提示和关闭弹窗,失败保留文件。模板下载有独立 loading 和重复点击保护,下载期间禁止提交与关闭, +结束后恢复状态,不关闭弹窗或刷新列表。导入、模板下载接口尚未确认,真实请求保留 TODO; +请求占位返回 `undefined` 时仅提示尚未接入,不发送请求、不模拟成功或刷新列表。 + +`TagDocumentDrawer.vue` 接收知识库 ID 与完整 Document API,通过 `open(tag)` 固定当前标签, +以“已关联文档/未关联文档”两页签共用表格,提供搜索、启用状态筛选、分页、单个与批量关联/取消关联;创建时间仅展示,不提供排序入口。 +启用状态复用 `MkTableFilter mode="single"`,支持全部、已启用、已禁用;查询传布尔 `is_active`,全部时省略。 +名称或状态筛选后回到第一页并清空选择,切换页签时重置筛选条件。 +文档图标和时间格式沿用文档列表,状态使用 `MkStatusLabel`;批量操作放在顶部,不再显示页面批量底栏。 +搜索、分页和页签切换清空选择,关联变更后重新查询并通知标签页刷新数量,末页为空时回退。 +抽屉在 `closed` 重置标签、筛选、分页和选择,不新增权限判断或共享范围接口。 +文档页原有标签查询继续使用 Knowledge API,共享标签查询保持原接口,不启用尚未接入的文档标签入口。 + `KnowledgeWorkflowView` 复用 `ButtonDefaultModelSetting`,从知识库详情读取默认模型配置, 随工作流保存提交并将配置传入画布;支持应用到所有节点,保存失败回滚至已保存配置。 diff --git a/ui/src/views/knowledge-detail/library/tags/TagDocumentDrawer.vue b/ui/src/views/knowledge-detail/library/tags/TagDocumentDrawer.vue new file mode 100644 index 00000000000..e91262e3d60 --- /dev/null +++ b/ui/src/views/knowledge-detail/library/tags/TagDocumentDrawer.vue @@ -0,0 +1,214 @@ + + + diff --git a/ui/src/views/knowledge-detail/library/tags/components/ButtonImportTags.vue b/ui/src/views/knowledge-detail/library/tags/components/ButtonImportTags.vue new file mode 100644 index 00000000000..97436f59c07 --- /dev/null +++ b/ui/src/views/knowledge-detail/library/tags/components/ButtonImportTags.vue @@ -0,0 +1,144 @@ + + + diff --git a/ui/src/views/knowledge-detail/library/tags/components/TagFormDialog.vue b/ui/src/views/knowledge-detail/library/tags/components/TagFormDialog.vue new file mode 100644 index 00000000000..ba5df0cbeb0 --- /dev/null +++ b/ui/src/views/knowledge-detail/library/tags/components/TagFormDialog.vue @@ -0,0 +1,172 @@ + + + diff --git a/ui/src/views/knowledge-detail/library/tags/index.vue b/ui/src/views/knowledge-detail/library/tags/index.vue index 1ae01041829..17c6503fb76 100644 --- a/ui/src/views/knowledge-detail/library/tags/index.vue +++ b/ui/src/views/knowledge-detail/library/tags/index.vue @@ -1,10 +1,253 @@