From a3d59211f2d1f8edb7226268c449a13bcad554f4 Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Mon, 28 Sep 2026 13:24:37 +0800 Subject: [PATCH] feat: quick create --- ui/src/api/API_README.md | 5 +- ui/src/api/admin/core/request.ts | 2 +- .../api/admin/workspace/knowledge/document.ts | 10 +- ui/src/api/types/document.ts | 5 + ui/src/components.d.ts | 2 + ui/src/components/COMPONENT_README.md | 58 +++++++ .../global/mk-table/MkQuickCreate.vue | 71 ++++++++ ui/src/components/global/mk-table/index.vue | 48 +++++- ui/src/components/mk-edit-name/index.vue | 155 ++++++++++++++++++ ui/src/views/VIEW_README.md | 7 + .../application-detail/chat-log/index.vue | 2 +- .../views/knowledge-detail/document/index.vue | 33 +++- 12 files changed, 388 insertions(+), 10 deletions(-) create mode 100644 ui/src/components/global/mk-table/MkQuickCreate.vue create mode 100644 ui/src/components/mk-edit-name/index.vue diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index 1163c07ddd5..8987a149ed8 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -496,8 +496,11 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展 ### 知识库文档 -`workspace/knowledge/document.ts` 仅维护文档分页查询,路径为 +`workspace/knowledge/document.ts` 维护文档分页查询,路径为 `/workspace//knowledge//document//`。 +`putQuickCreateDocuments(knowledgeId, documents)` 通过 PUT `document/batch_create` 创建空白文档, +载荷为 `DocumentQuickCreatePayload[]`(仅含 `name`),返回 `DocumentItem[]`;名称上限 128 字符。 +共享文档 API 不增加创建接口;文档页监听公共 MkQuickCreate 的 `create` 事件,管理创建请求和提交状态。 分页使用 `ParamsPage` / `ResponsePage`,支持 `name`、`create_user`、`status`、`task_type`、`is_active`、`hit_handling_method` 和 `tags` 筛选; 文件任务使用 `DOCUMENT_TASK_STATE` 的字符状态及 `DOCUMENT_TASK_TYPE` 的任务位置, 不使用通用 `STATE_TYPES`;选择全部时省略状态与任务类型,非任务专属状态省略任务类型。 diff --git a/ui/src/api/admin/core/request.ts b/ui/src/api/admin/core/request.ts index 96c8ff6b44a..8f03404c21a 100644 --- a/ui/src/api/admin/core/request.ts +++ b/ui/src/api/admin/core/request.ts @@ -8,7 +8,7 @@ import type { Dict } from '@/api/types' import { MsgError } from '@/utils/message' import { ADMIN_API_BASE_PATH } from '@/api/constants' -const DEFAULT_TIMEOUT = 30 * 60 * 1_000 // 30 minutes +const DEFAULT_TIMEOUT = 30 * 60 * 1000 // 30 minutes interface ExportRequestConfig extends AxiosRequestConfig { skipGlobalErrorMessage?: boolean diff --git a/ui/src/api/admin/workspace/knowledge/document.ts b/ui/src/api/admin/workspace/knowledge/document.ts index 6429627572c..496b3339baf 100644 --- a/ui/src/api/admin/workspace/knowledge/document.ts +++ b/ui/src/api/admin/workspace/knowledge/document.ts @@ -1,6 +1,6 @@ -import { get } from '../../core/request' +import { get, put } from '../../core/request' import type { ParamsPage, ResponsePage } from '../../core/types' -import type { Dict, DocumentItem } from '@/api/types' +import type { Dict, DocumentItem, DocumentQuickCreatePayload } from '@/api/types' import { getWorkspaceId } from '@/utils/resource-context' const getPrefix = (knowledgeId: string) => `/workspace/${getWorkspaceId()}/knowledge/${knowledgeId}/document` @@ -9,4 +9,8 @@ const getPrefix = (knowledgeId: string) => `/workspace/${getWorkspaceId()}/knowl const getDocumentPage = (knowledgeId: string, page: ParamsPage, query?: Dict) => get>(`${getPrefix(knowledgeId)}/${page.currentPage}/${page.pageSize}`, query) -export default { getDocumentPage } +/** 批量创建仅包含名称的空白文档。 */ +const putQuickCreateDocuments = (knowledgeId: string, documents: DocumentQuickCreatePayload[]) => + put(`${getPrefix(knowledgeId)}/batch_create`, documents) + +export default { getDocumentPage, putQuickCreateDocuments } diff --git a/ui/src/api/types/document.ts b/ui/src/api/types/document.ts index 8b0fad4298d..81fc4308c57 100644 --- a/ui/src/api/types/document.ts +++ b/ui/src/api/types/document.ts @@ -4,6 +4,11 @@ export type DocumentHitHandling = (typeof DOCUMENT_HIT_HANDLING)[keyof typeof DO export type DocumentTaskState = (typeof DOCUMENT_TASK_STATE)[keyof typeof DOCUMENT_TASK_STATE] export type DocumentTaskType = (typeof DOCUMENT_TASK_TYPE)[keyof typeof DOCUMENT_TASK_TYPE] +/** 快速创建空白文档的请求数据。 */ +export interface DocumentQuickCreatePayload { + name: string +} + /** 文件各任务的分段计数及状态发生时间。 */ export interface DocumentStatusMeta { aggs?: { status: string | null; count: number }[] diff --git a/ui/src/components.d.ts b/ui/src/components.d.ts index 7d426d008ef..eb45cccdcb9 100644 --- a/ui/src/components.d.ts +++ b/ui/src/components.d.ts @@ -33,6 +33,7 @@ declare module 'vue' { MkIcon: typeof import('./components/global/mk-icon/index.vue')['default'] MkInfiniteScroll: typeof import('./components/global/mk-infinite-scroll/index.vue')['default'] MkListItem: typeof import('./components/global/mk-list-item/index.vue')['default'] + MkQuickCreate: typeof import('./components/global/mk-table/MkQuickCreate.vue')['default'] MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default'] MkSlider: typeof import('./components/global/mk-slider/index.vue')['default'] MkSourceCard: typeof import('./components/global/mk-source-card/index.vue')['default'] @@ -80,6 +81,7 @@ declare global { const MkIcon: typeof import('./components/global/mk-icon/index.vue')['default'] const MkInfiniteScroll: typeof import('./components/global/mk-infinite-scroll/index.vue')['default'] const MkListItem: typeof import('./components/global/mk-list-item/index.vue')['default'] + const MkQuickCreate: typeof import('./components/global/mk-table/MkQuickCreate.vue')['default'] const MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default'] const MkSlider: typeof import('./components/global/mk-slider/index.vue')['default'] const MkSourceCard: typeof import('./components/global/mk-source-card/index.vue')['default'] diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index 85052a23889..16ef8065d62 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -256,6 +256,31 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载 `paginationConfig` 由组件接收,其余 Table 属性和事件通过 `$attrs` 传入,列继续使用 `el-table-column`。 +`body-prepend` 插槽用于在表头下、数据行之前插入独立操作区,例如快速创建。内部借用 +Element Plus `append`,仅在传入该插槽时将直属表体滚动容器设为纵向 Flex,并将插槽排到前面; +内容自然占位,不写固定高度,不向 `data` 插入占位记录,不影响选择、排序、分页总数和空状态。 +该插槽用于默认的 `table-layout="fixed"` 表格;不与 `table-layout="auto"` 混用。 +操作区通过 sticky 固定在表头下方,纵向、横向滚动均保持原位,背景遮挡经过的普通列和固定列。 +表体使用 inline-size 容器,操作区宽度通过 `100cqw` 跟随表体可视宽度,滚动内容保留完整列宽; +表单展开和错误提示仍自然占位。表单状态、请求与成功后的刷新由调用方维护,MkTable 不内置业务创建逻辑。 + +`MkQuickCreate` 位于 `global/mk-table/MkQuickCreate.vue`,自动注册,供 `body-prepend` 插槽组合。 +组件只提供行内快速创建交互,不依赖文档 API 或业务 ID。点击创建只发出 `create(name)` 事件, +由页面管理请求、`loading`、成功提示及列表刷新;成功后通过组件 ref 调用 `close()` 清空并收起,失败保留输入。 +`text` 默认为“快速创建”,`placeholder` 默认为“请输入名称”,`maxlength` 默认为 256。 +组件不使用 Form 或表单校验;空名称、纯空白及提交期间禁用创建按钮,提交前 trim。 +Esc 或取消清理草稿;`loading` 默认为 false,为 true 时禁止创建和取消。组件不等待 Promise,不自动收起。 + +```vue + + + + +``` + `paginationConfig` 包含 `currentPage`、`pageSize`、`total` 和可选 `pageSizes`;不传则隐藏分页器, `pageSizes` 默认 `[10, 20, 50, 100]`。 @@ -438,6 +463,39 @@ Dialog、Drawer、Popover、嵌套区域等其他大、小表格均禁止开启 ## 手动导入的共享 UI +### MkEditName(行内编辑名称) + +手动导入 `@/components/mk-edit-name/index.vue`,不全局注册。必填 `v-model` 保存已生效名称, +必填 `save(name): Promise` 由调用方执行业务请求并返回最终保存的名称;失败必须 reject, +不可吞掉错误后当作成功返回。组件不调用业务 API,仅在保存成功后回写模型。 + +默认展示名称,`prefix` 插槽放文档等业务图标;长名称省略并提供原生 title。悬停或内部获得焦点时 +显示编辑按钮,点击后进入输入态并选中名称。Enter 或失焦保存,Esc 取消;输入法选词不提交。 +保存前清理首尾空格,拒绝空名称和纯空白;`maxlength` 可限制长度,`validate(name)` 可返回 +业务错误文案,返回 `undefined` 表示通过。名称未变化直接退出,不请求。 +保存期间只读并显示 loading,失败保留草稿及错误提示,允许重新聚焦后修改、重试或取消。 +名称展示区域保留父级点击行为,编辑按钮和输入区域阻止点击冒泡。 + +```vue + + + +``` + +表格通过列默认插槽使用,列表以资源 ID 为 key;该列不再启用 `show-overflow-tooltip`,避免编辑时 +叠加表格提示。单元格可用宽度控制组件宽度,业务图标在编辑态隐藏。 + ### MkEditAvatar(修改头像) 手动导入 `@/components/mk-edit-avatar/index.vue`,不参与全局注册。字符串 `v-model` 为当前 diff --git a/ui/src/components/global/mk-table/MkQuickCreate.vue b/ui/src/components/global/mk-table/MkQuickCreate.vue new file mode 100644 index 00000000000..54b27a6f53c --- /dev/null +++ b/ui/src/components/global/mk-table/MkQuickCreate.vue @@ -0,0 +1,71 @@ + + + diff --git a/ui/src/components/global/mk-table/index.vue b/ui/src/components/global/mk-table/index.vue index 84b8913a0cc..94774cf429d 100644 --- a/ui/src/components/global/mk-table/index.vue +++ b/ui/src/components/global/mk-table/index.vue @@ -1,5 +1,5 @@ + + diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index da7eaee3599..b1b98e89f64 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -873,6 +873,13 @@ Layout 保留标题栏固定位置和外层间距,页面负责内部布局。 资源入口只负责详情数据和侧栏 `resource-header`,无需转发标题栏属性。 文档页将标题与搜索放入标题栏,表格在正文中独立显示 loading。 +普通资料库(`KNOWLEDGE_TYPE.BASE`)的非共享文档页通过 MkTable 的 `body-prepend` 插槽展示 +公共 `MkQuickCreate`,类型读取已有知识库详情上下文,不重复请求详情。 +页面通过 `@create="handleCreateDocument"` 接收名称,管理创建请求及 `creatingDocument`,通过 `loading` 传给组件。 +创建成功后调用组件 `close()`、显示成功提示、保留筛选条件并回到第一页刷新,刷新失败不恢复已提交草稿。 +组件只维护输入及空名称禁用,创建失败时页面不关闭组件,保留草稿供重试。 +入口独立于文档数组,在空列表中同样显示,不计入分页或批量选择;不新增前端权限判断。 + 文档页的筛选选项、状态和事件集中在 `// 过滤项` 下:文件状态、启用状态、召回处理显式使用 `MkTableFilter mode="single"`,标签使用 `mode="cascader"`。文件状态按 v2 提供成功、失败、 索引中、分词索引中、排队中、生成中,同时映射 `status` 与可选 `task_type`;切换到非任务状态 diff --git a/ui/src/views/application-detail/chat-log/index.vue b/ui/src/views/application-detail/chat-log/index.vue index fb5c3c84d62..4890adaced9 100644 --- a/ui/src/views/application-detail/chat-log/index.vue +++ b/ui/src/views/application-detail/chat-log/index.vue @@ -181,7 +181,7 @@ onMounted(() => loadChatLogs()) > - +