From 8038acb8d14ea3308e5c2e8365b1225f2f35cfc0 Mon Sep 17 00:00:00 2001 From: wangdan-fit2cloud Date: Tue, 25 Aug 2026 12:39:16 +0800 Subject: [PATCH] feat: quota setting --- .../{ => application}/application.ts | 4 +- .../admin/workspace/knowledge/knowledge.ts | 27 ++++ ui/src/api/admin/workspace/shared.ts | 16 +- ui/src/api/enums/index.ts | 1 + ui/src/api/enums/knowledge.ts | 9 ++ ui/src/api/types/index.ts | 1 + ui/src/api/types/knowledge.ts | 27 ++++ ui/src/components.d.ts | 2 + ui/src/components/COMPONENT_README.md | 36 +++-- .../components/business/folder-tree/index.vue | 34 ++--- .../components/global/mk-list-item/index.vue | 4 +- ui/src/components/global/mk-table/index.vue | 2 +- .../mk-table/mk-table-more-dropdown.vue | 26 ++++ .../components/global/mk-tag-group/index.vue | 2 +- ui/src/components/mk-source-card/index.vue | 6 +- .../mk-source-card-action-dropdown.vue | 6 +- .../admin/workspace/modules/knowledge.ts | 2 +- ui/src/stores/theme.ts | 1 + ui/src/utils/number.ts | 17 +++ ui/src/views/VIEW_README.md | 3 +- ui/src/views/application/ApplicationView.vue | 2 +- .../components/ApplicationCard.vue | 10 +- ui/src/views/knowledge/KnowledgeView.vue | 139 ++++++++++++++++++ .../knowledge/components/KnowledgeCard.vue | 87 +++++++++++ ui/src/views/model/components/ModelCard.vue | 34 ++--- .../chat/user-groups/GroupsListView.vue | 18 +-- .../views/system/chat/users/UserListView.vue | 29 +++- .../chat/users/dialog/QuotaSettingsDialog.vue | 132 +++++++++++++++++ .../system/identity/groups/GroupsListView.vue | 26 ++-- .../system/identity/roles/RoleListView.vue | 14 +- .../identity/workspaces/WorkspaceListView.vue | 26 ++-- ui/src/views/tool/components/ToolCard.vue | 50 +++---- .../workflow/ApplicationWorkflowView.vue | 2 +- 33 files changed, 646 insertions(+), 149 deletions(-) rename ui/src/api/admin/workspace/{ => application}/application.ts (90%) create mode 100644 ui/src/api/admin/workspace/knowledge/knowledge.ts create mode 100644 ui/src/api/enums/knowledge.ts create mode 100644 ui/src/api/types/knowledge.ts create mode 100644 ui/src/components/global/mk-table/mk-table-more-dropdown.vue create mode 100644 ui/src/utils/number.ts create mode 100644 ui/src/views/knowledge/KnowledgeView.vue create mode 100644 ui/src/views/knowledge/components/KnowledgeCard.vue create mode 100644 ui/src/views/system/chat/users/dialog/QuotaSettingsDialog.vue diff --git a/ui/src/api/admin/workspace/application.ts b/ui/src/api/admin/workspace/application/application.ts similarity index 90% rename from ui/src/api/admin/workspace/application.ts rename to ui/src/api/admin/workspace/application/application.ts index 4dbedcb2dc1..287ce456b0d 100644 --- a/ui/src/api/admin/workspace/application.ts +++ b/ui/src/api/admin/workspace/application/application.ts @@ -1,5 +1,5 @@ -import { get, put } from '../core/request' -import type { ParamsPage, ResponsePage } from '../core/types' +import { get, put } from '../../core/request' +import type { ParamsPage, ResponsePage } from '../../core/types' import type { ApplicationDetail, ApplicationFormPayload, diff --git a/ui/src/api/admin/workspace/knowledge/knowledge.ts b/ui/src/api/admin/workspace/knowledge/knowledge.ts new file mode 100644 index 00000000000..f329b17e69e --- /dev/null +++ b/ui/src/api/admin/workspace/knowledge/knowledge.ts @@ -0,0 +1,27 @@ +import { del, get } from '../../core/request' +import type { ParamsPage, ResponsePage } from '../../core/types' +import type { KnowledgeItem, RequestParams } from '@/api/types' +import { getWorkspaceId } from '@/utils/workspace-context' + +const getPrefix = () => { + const workspaceId = getWorkspaceId() + return `/workspace/${workspaceId}/knowledge` +} + +/** 获取工作空间知识库分页列表。 */ +const getKnowledgePage = (page: ParamsPage, query?: RequestParams) => { + return get>( + `${getPrefix()}/${page.currentPage}/${page.pageSize}`, + query, + ) +} + +/** 删除工作空间知识库。 */ +const deleteKnowledge = (knowledgeId: string) => { + return del(`${getPrefix()}/${knowledgeId}`) +} + +export default { + deleteKnowledge, + getKnowledgePage, +} diff --git a/ui/src/api/admin/workspace/shared.ts b/ui/src/api/admin/workspace/shared.ts index 27dbc58a86a..54b6f9959f7 100644 --- a/ui/src/api/admin/workspace/shared.ts +++ b/ui/src/api/admin/workspace/shared.ts @@ -1,6 +1,6 @@ import { get } from '../core/request' import type { ParamsPage, ResponsePage } from '../core/types' -import type { RequestParams, ModelItem, ToolItem } from '@/api/types' +import type { KnowledgeItem, RequestParams, ModelItem, ToolItem } from '@/api/types' import { getWorkspaceId } from '@/utils/workspace-context' const getPrefix = () => { @@ -15,10 +15,22 @@ const getModelList = (query?: RequestParams) => { /** 获取工作空间共享的工具列表。 */ const getToolPage = (page: ParamsPage, query?: RequestParams) => { - return get>(`${getPrefix()}/tool/${page.currentPage}/${page.pageSize}`, query) + return get>( + `${getPrefix()}/tool/${page.currentPage}/${page.pageSize}`, + query, + ) +} + +/** 获取工作空间共享的知识库列表。 */ +const getKnowledgePage = (page: ParamsPage, query?: RequestParams) => { + return get>( + `${getPrefix()}/knowledge/${page.currentPage}/${page.pageSize}`, + query, + ) } export default { + getKnowledgePage, getModelList, getToolPage, } diff --git a/ui/src/api/enums/index.ts b/ui/src/api/enums/index.ts index f183e679d7e..0ab0454b646 100644 --- a/ui/src/api/enums/index.ts +++ b/ui/src/api/enums/index.ts @@ -5,3 +5,4 @@ export * from './system-role' export * from './model' export * from './resource-authorization' export * from './tool' +export * from './knowledge' diff --git a/ui/src/api/enums/knowledge.ts b/ui/src/api/enums/knowledge.ts new file mode 100644 index 00000000000..7040c16130d --- /dev/null +++ b/ui/src/api/enums/knowledge.ts @@ -0,0 +1,9 @@ +/** 后端知识库类型。 */ +// TODO v3不再用数字表示 待修改 +export const KNOWLEDGE_TYPE = { + BASE: 0, + WEB: 1, + LARK: 2, + YUQUE: 3, + WORKFLOW: 4, +} as const diff --git a/ui/src/api/types/index.ts b/ui/src/api/types/index.ts index db422a0189c..c964e41133a 100644 --- a/ui/src/api/types/index.ts +++ b/ui/src/api/types/index.ts @@ -15,3 +15,4 @@ export type * from './model' export type * from './resource-authorization' export type * from './folder' export type * from './tool' +export type * from './knowledge' diff --git a/ui/src/api/types/knowledge.ts b/ui/src/api/types/knowledge.ts new file mode 100644 index 00000000000..1f7d731f312 --- /dev/null +++ b/ui/src/api/types/knowledge.ts @@ -0,0 +1,27 @@ +/** Workspace 知识库列表和知识库卡片共用的业务类型。 */ + +import { KNOWLEDGE_TYPE } from '@/api/enums' + +export type KnowledgeType = (typeof KNOWLEDGE_TYPE)[keyof typeof KNOWLEDGE_TYPE] + +export interface KnowledgeItem { + application_mapping_count?: number + char_length?: number | null + create_time?: string + desc?: string | null + document_count?: number | null + embedding_model_id?: string | null + file_count_limit?: number + file_size_limit?: number + folder_id?: string + id: string + image_count?: number | null + meta?: Record + name: string + nick_name?: string | null + scope?: string + type: KnowledgeType + update_time?: string + user_id?: string | null + workspace_id: string +} diff --git a/ui/src/components.d.ts b/ui/src/components.d.ts index 554e9297c02..b99373c1ee4 100644 --- a/ui/src/components.d.ts +++ b/ui/src/components.d.ts @@ -28,6 +28,7 @@ declare module 'vue' { MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default'] MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default'] MkTable: typeof import('./components/global/mk-table/index.vue')['default'] + MkTableMoreDropdown: typeof import('./components/global/mk-table/mk-table-more-dropdown.vue')['default'] MkTagGroup: typeof import('./components/global/mk-tag-group/index.vue')['default'] MkViewLayout: typeof import('./components/global/mk-view-layout/index.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] @@ -54,6 +55,7 @@ declare global { const MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default'] const MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default'] const MkTable: typeof import('./components/global/mk-table/index.vue')['default'] + const MkTableMoreDropdown: typeof import('./components/global/mk-table/mk-table-more-dropdown.vue')['default'] const MkTagGroup: typeof import('./components/global/mk-tag-group/index.vue')['default'] const MkViewLayout: typeof import('./components/global/mk-view-layout/index.vue')['default'] const RouterLink: typeof import('vue-router')['RouterLink'] diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index 024d2288505..33b93a72145 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -77,7 +77,8 @@ src/components/ │ ├── mk-status-label/ │ │ └── index.vue # 布尔状态图标和文案 │ ├── mk-table/ -│ │ └── index.vue # 表格、分页、列宽拖拽和批量操作 +│ │ ├── index.vue # 表格、分页、列宽拖拽和批量操作 +│ │ └── mk-table-more-dropdown.vue # 表格操作列 More 下拉菜单 │ └── mk-tag-group/ │ └── index.vue # 标签折叠和剩余标签浮层 ├── mk-search-list/ @@ -409,7 +410,8 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载 数据驱动使用时传入 `row`。`label-field` 默认读取 `name`,`index` 默认为 `0`;未提供默认插槽时 组件显示对应字段文本。`action` 和 `action-dropdown` 插槽需要配合 `row` 使用,并接收 `row`、 -`index`。 +`index`。`action-dropdown` 由组件统一渲染 More 触发器、`MkDropdown` 和 `MkDropdownMenu`,插槽中 +直接放置 `MkDropdownItem`。 ```vue @@ -472,6 +474,17 @@ const paginationConfig = ref({ 重新计算 `max-height`。传入 `resizable` 后启用列宽拖拽,并隐藏为拖拽借用的原生边框视觉。 需要显示 Element Plus 原生边框时直接使用 `el-table`。 +表格操作列需要 More 菜单时使用 `MkTableMoreDropdown`。组件统一提供点击型、右下定位的 More +按钮以及 `MkDropdownMenu`,默认插槽中直接放置 `MkDropdownItem`。其他 Dropdown 属性和事件通过 +`$attrs` 传入,菜单容器样式通过 `menu-class` 设置。 + +```vue + + 配额设置 + 删除 + +``` + 包含 `type="selection"` 的选择列时,选择数据会显示页面底部操作栏。批量按钮放入 `footer-batch-actions` 插槽,当前选择通过 `selection-change` 返回。组件暴露 `tableRef` 和 `clearSelection()`。操作栏在 `MkViewLayout` 的主内容滚动区域内吸附于页面底部,不随表格内容 @@ -539,7 +552,8 @@ const config = defineModel({ required: true }) `footer` 插槽作为左侧常驻内容并始终贴在卡片底部;无论是否传入内容,底部都会保留固定位置。 `footer` 作用域提供 `Action` 和 `ActionDropdown`。左侧常驻内容与 `Action` 写在同一个插槽内; `Action` 是卡片悬浮或内部获得焦点时显示的右侧操作容器,可以只放开关或按钮。 -需要 More 菜单时,再将 `ActionDropdown` 放入 `Action`,下拉菜单内容写入其默认插槽。 +需要 More 菜单时,再将 `ActionDropdown` 放入 `Action`,组件会统一渲染 `MkDropdownMenu`,默认 +插槽中直接放置 `MkDropdownItem`。 需要自定义头部时可 通过 `icon`、`title`、`subtitle` 和 `tag` 插槽覆盖对应区域;`title` 插槽提供 `{ title }`, 便于在保留标题文案的同时追加状态图标等内容。 @@ -561,10 +575,8 @@ import MkSourceCard from '@/components/mk-source-card/index.vue' - - 编辑 - 删除 - + 编辑 + 删除 @@ -654,7 +666,7 @@ Props 和模型: - `data` 应传入全量数据;组件内的 50 条分批仅用于控制 DOM 渲染数量,不替代后端分页。 - 搜索词或数据源变化时,渲染范围和滚动位置会重置到第一批。 - 提供 `action-dropdown` 时,组件内部使用固定 More 按钮和点击型、非 Teleport 的 - `MkDropdown`。 + `MkDropdown`,并统一包裹 `MkDropdownMenu`;插槽中直接放置 `MkDropdownItem`。 - `action` 和 `action-dropdown` 二选一;同时提供时优先渲染 `action-dropdown`,不渲染 `action`。 #### 默认字段示例 @@ -711,11 +723,9 @@ function selectItem(item: SearchListItem, index: number) { {{ workspace.displayName }} ``` diff --git a/ui/src/components/business/folder-tree/index.vue b/ui/src/components/business/folder-tree/index.vue index 0b6c3e8e73d..a4920687a20 100644 --- a/ui/src/components/business/folder-tree/index.vue +++ b/ui/src/components/business/folder-tree/index.vue @@ -397,24 +397,22 @@ defineExpose({ refresh: loadFolders, openCreate: handleOpenCreateFolder }) diff --git a/ui/src/components/global/mk-list-item/index.vue b/ui/src/components/global/mk-list-item/index.vue index 32a74749fac..38d41c1782e 100644 --- a/ui/src/components/global/mk-list-item/index.vue +++ b/ui/src/components/global/mk-list-item/index.vue @@ -56,7 +56,9 @@ const slotRow = computed(() => row as T) diff --git a/ui/src/components/global/mk-table/index.vue b/ui/src/components/global/mk-table/index.vue index b28c0e5a975..94cd1c5327a 100644 --- a/ui/src/components/global/mk-table/index.vue +++ b/ui/src/components/global/mk-table/index.vue @@ -192,7 +192,7 @@ defineExpose({ clearSelection, tableRef })