Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion ui/src/api/API_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,18 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展

`workspace/knowledge/document.ts` 仅维护文档分页查询,路径为
`/workspace/<workspaceId>/knowledge/<knowledgeId>/document/<currentPage>/<pageSize>`。
分页使用 `ParamsPage` / `ResponsePage<DocumentItem>`,支持 `name`、`create_user`、`status`、`task_type` 筛选;
分页使用 `ParamsPage` / `ResponsePage<DocumentItem>`,支持 `name`、`create_user`、`status`、`task_type`、`is_active`、`hit_handling_method` 和 `tags` 筛选;
文件任务使用 `DOCUMENT_TASK_STATE` 的字符状态及 `DOCUMENT_TASK_TYPE` 的任务位置,
不使用通用 `STATE_TYPES`;选择全部时省略状态与任务类型,非任务专属状态省略任务类型。
文件状态响应还包含 `REVOKE: '4'`、`REVOKED: '5'`、`IGNORED: 'n'`。
`DocumentItem.status_meta` 使用可空的 `DocumentStatusMeta`:`aggs` 为 `{ status, count }[]`,
`state_time` 按任务编号、状态字符两级索引时间字符串;两项均可缺省。
`DocumentTaskState` 和 `DocumentTaskType` 从文档枚举派生,统一从 `@/api/types` 导入。
启用状态传布尔值,`false` 不省略;单选全部时省略该字段。`tags` 传数组,沿用 Axios 的
`tags[]` 序列化,内容为标签 ID 或特殊值 `NO_TAG`,不传标签名称或 JSON 字符串。
`workspace/knowledge/knowledge.ts` 和 `workspace/shared/knowledge/knowledge.ts` 的
`getKnowledgeTags(knowledgeId)` 分别请求对应资源前缀的 `/<knowledgeId>/tags`,返回
`KnowledgeTagGroup[]`;页面将分组转换为级联选项,MkTableFilter 内部展开父组并去重,页面直接用组件返回的叶子标签 ID 数组查询。
文档页传 `resource_type: 'document'`,创建者选项复用 Workspace `common.ts` 的 `getAllUsers`。
类型从 `@/api/types` 导入,命中处理枚举从 `@/api/enums` 导入。API 不接收 loading,不重复包装响应。

Expand Down
14 changes: 13 additions & 1 deletion ui/src/api/admin/workspace/knowledge/knowledge.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { del, get, getExportFile, post, put } from '../../core/request'
import type { ParamsPage, ResponsePage } from '../../core/types'
import type { Dict, KnowledgeDetail, KnowledgeItem, KnowledgeCreatePayload, WebKnowledgeCreatePayload, LarkKnowledgeCreatePayload } from '@/api/types'
import type {
Dict,
KnowledgeTagGroup,
KnowledgeDetail,
KnowledgeItem,
KnowledgeCreatePayload,
WebKnowledgeCreatePayload,
LarkKnowledgeCreatePayload,
} from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = () => {
Expand Down Expand Up @@ -99,7 +107,11 @@ const getKnowledgeMcpConfig = (knowledgeId: string): Promise<string> =>
/** 提交知识库分词索引任务。 */
const putKnowledgeKeywordIndex = (knowledgeId: string) => put<undefined, void>(`${getPrefix()}/${knowledgeId}/tokenize`)

/** 获取知识库按标签名称分组的标签选项。 */
const getKnowledgeTags = (knowledgeId: string) => get<KnowledgeTagGroup[]>(`${getPrefix()}/${knowledgeId}/tags`)

export default {
getKnowledgeTags,
getKnowledgeMcpConfig,
putKnowledgeKeywordIndex,
exportKnowledgeExcel,
Expand Down
7 changes: 5 additions & 2 deletions ui/src/api/admin/workspace/shared/knowledge/knowledge.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { get } from '../../../core/request'
import type { ParamsPage, ResponsePage } from '../../../core/types'
import type { Dict, KnowledgeDetail, KnowledgeItem } from '@/api/types'
import type { Dict, KnowledgeTagGroup, KnowledgeDetail, KnowledgeItem } from '@/api/types'
import { getWorkspaceId } from '@/utils/resource-context'

const getPrefix = () => `/system/shared/workspace/${getWorkspaceId()}/knowledge`
Expand All @@ -15,4 +15,7 @@ const getAllKnowledge = (query?: Dict<unknown>) => get<KnowledgeItem[]>(getPrefi
/** 获取工作空间共享的知识库详情。 */
const getKnowledgeDetail = (knowledgeId: string) => get<KnowledgeDetail>(`${getPrefix()}/${knowledgeId}`)

export default { getKnowledgePage, getAllKnowledge, getKnowledgeDetail }
/** 获取知识库按标签名称分组的标签选项。 */
const getKnowledgeTags = (knowledgeId: string) => get<KnowledgeTagGroup[]>(`${getPrefix()}/${knowledgeId}/tags`)

export default { getKnowledgeTags, getKnowledgePage, getAllKnowledge, getKnowledgeDetail }
2 changes: 1 addition & 1 deletion ui/src/api/enums/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
export const DOCUMENT_HIT_HANDLING = { OPTIMIZATION: 'optimization', DIRECTLY_RETURN: 'directly_return' } as const

/** 文档任务状态,使用文件状态协议中的字符值。 */
export const DOCUMENT_TASK_STATE = { PENDING: '0', STARTED: '1', SUCCESS: '2', FAILURE: '3' } as const
export const DOCUMENT_TASK_STATE = { PENDING: '0', STARTED: '1', SUCCESS: '2', FAILURE: '3', REVOKE: '4', REVOKED: '5', IGNORED: 'n' } as const

/** 文档状态字符串中各任务的位置。 */
export const DOCUMENT_TASK_TYPE = { EMBEDDING: 1, GENERATE_PROBLEM: 2, SYNC: 3, TOKENIZE: 4 } as const
4 changes: 4 additions & 0 deletions ui/src/api/enums/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
export const STATE_TYPES = {
PENDING: 'PENDING',
STARTED: 'STARTED',
EMBEDDING: 'EMBEDDING',
GENERATE: 'GENERATE',
SYNC: 'SYNC',
TOKENIZE: 'TOKENIZE',
SUCCESS: 'SUCCESS',
FAILURE: 'FAILURE',
REVOKE: 'REVOKE',
Expand Down
14 changes: 12 additions & 2 deletions ui/src/api/types/document.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import type { DOCUMENT_HIT_HANDLING } from '@/api/enums'
import type { DOCUMENT_HIT_HANDLING, DOCUMENT_TASK_STATE, DOCUMENT_TASK_TYPE } from '@/api/enums'
import type { KnowledgeType } from './knowledge'
export type DocumentHitHandling = (typeof DOCUMENT_HIT_HANDLING)[keyof typeof DOCUMENT_HIT_HANDLING]
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 DocumentStatusMeta {
aggs?: { status: string; count: number }[]
state_time?: Partial<Record<DocumentTaskType, Partial<Record<DocumentTaskState, string>>>>
}

/** 文档分页列表数据。 */
export interface DocumentItem {
id: string
Expand All @@ -9,13 +18,14 @@ export interface DocumentItem {
type: KnowledgeType
is_active: boolean
status: string
status_meta?: Record<string, unknown>
status_meta?: DocumentStatusMeta | null
paragraph_count: number
char_length: number
hit_num: number
hit_handling_method: DocumentHitHandling
directly_return_similarity: number
tags?: { id: string; key: string; value: string }[]
tag_count?: number | null
meta?: Record<string, unknown>
nick_name?: string | null
create_time: string
Expand Down
2 changes: 1 addition & 1 deletion ui/src/assets/iconfont.js

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions ui/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ declare module 'vue' {
MkSourceCardActionDropdown: typeof import('./components/global/mk-source-card/MkSourceCardActionDropdown.vue')['default']
MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default']
MkTable: typeof import('./components/global/mk-table/index.vue')['default']
MkTableFilter: typeof import('./components/global/mk-table/MkTableFilter.vue')['default']
MkTableFilter: typeof import('./components/global/mk-table/mk-table-filter/index.vue')['default']
MkTableMoreDropdown: typeof import('./components/global/mk-table/MkTableMoreDropdown.vue')['default']
MkTagGroup: typeof import('./components/global/mk-tag-group/index.vue')['default']
MkTooltip: typeof import('./components/global/mk-tooltip/index.vue')['default']
MkViewLayout: typeof import('./components/global/mk-view-layout/index.vue')['default']
PortalIcon: typeof import('./components/global/mk-icon/PortalIcon.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
TableFilterCascader: typeof import('./components/global/mk-table/mk-table-filter/TableFilterCascader.vue')['default']
TableFilterMultiple: typeof import('./components/global/mk-table/mk-table-filter/TableFilterMultiple.vue')['default']
TableFilterSingle: typeof import('./components/global/mk-table/mk-table-filter/TableFilterSingle.vue')['default']
ToolIcon: typeof import('./components/global/mk-icon/ToolIcon.vue')['default']
TriggerIcon: typeof import('./components/global/mk-icon/TriggerIcon.vue')['default']
}
Expand Down Expand Up @@ -83,14 +86,17 @@ declare global {
const MkSourceCardActionDropdown: typeof import('./components/global/mk-source-card/MkSourceCardActionDropdown.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 MkTableFilter: typeof import('./components/global/mk-table/MkTableFilter.vue')['default']
const MkTableFilter: typeof import('./components/global/mk-table/mk-table-filter/index.vue')['default']
const MkTableMoreDropdown: typeof import('./components/global/mk-table/MkTableMoreDropdown.vue')['default']
const MkTagGroup: typeof import('./components/global/mk-tag-group/index.vue')['default']
const MkTooltip: typeof import('./components/global/mk-tooltip/index.vue')['default']
const MkViewLayout: typeof import('./components/global/mk-view-layout/index.vue')['default']
const PortalIcon: typeof import('./components/global/mk-icon/PortalIcon.vue')['default']
const RouterLink: typeof import('vue-router')['RouterLink']
const RouterView: typeof import('vue-router')['RouterView']
const TableFilterCascader: typeof import('./components/global/mk-table/mk-table-filter/TableFilterCascader.vue')['default']
const TableFilterMultiple: typeof import('./components/global/mk-table/mk-table-filter/TableFilterMultiple.vue')['default']
const TableFilterSingle: typeof import('./components/global/mk-table/mk-table-filter/TableFilterSingle.vue')['default']
const ToolIcon: typeof import('./components/global/mk-icon/ToolIcon.vue')['default']
const TriggerIcon: typeof import('./components/global/mk-icon/TriggerIcon.vue')['default']
}
56 changes: 53 additions & 3 deletions ui/src/components/COMPONENT_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载
传入 `status` 时仅显示该状态配置的图标;未配置状态或没有图标时只显示文案,不回退到其他状态图标。
未传 `status` 时,`active` 为 true 显示成功图标,为 false 显示 `icon_ban_filled`。
组件直接使用公共枚举 `STATE_TYPES` 匹配图标;新增状态需补齐 `STATE_LABELS` 文案,图标可按需配置。
`STARTED`、`PENDING`、`REVOKE` 及 `EMBEDDING`、`GENERATE`、`SYNC`、`TOKENIZE`
统一显示内置加载图标,使用方直接传入 `status`,无需额外组合 `LoadingIcon`。
`status` 优先于 `active`,状态文案统一使用 `STATE_LABELS`,不提供 `text` 覆盖。

```vue
Expand Down Expand Up @@ -279,9 +281,57 @@ Dialog、Drawer、Popover、嵌套区域等其他大、小表格均禁止开启
虚拟表格、跨页和跨列表拖拽不属于该接口。排序工具不会深拷贝普通表格的行对象;工作流使用方应在
数据写回边界自行 `cloneDeep`,保持 LogicFlow 的可观察树约束。

表头需要多选筛选时使用 `MkTableFilter`。`label` 设置表头文案,`options` 接收
`OptionItem<string>[]`,必填 `v-model` 绑定已选字符串数组;打开时复制为草稿,确认或重置后
写回并触发 `change`。过长的选项文案会显示省略号,悬停时可查看完整文案。
`MkTableFilter` 放在 `global/mk-table/mk-table-filter/`,公共入口为 `index.vue`。
入口统一选择模式、渲染触发按钮、计算筛选高亮和回写模型;三个内部组件分别维护对应交互:
`TableFilterSingle.vue` 复用 `MkDropdown`、`MkDropdownMenu` 和 `MkDropdownItem`,
`TableFilterMultiple.vue` 管理多选草稿及确认,`TableFilterCascader.vue` 管理级联面板及即时提交。
内部组件通过默认插槽接收同一个触发按钮,只向入口发送 `select` 和 `open`;页面只使用
`MkTableFilter`,不直接引用模式组件。多选与级联继续使用 Popover,不强行统一其提交和关闭行为。

表头筛选使用 `MkTableFilter`,`label` 设置表头文案,必填 `v-model` 保存已生效的条件。
`mode` 支持以下模式,默认 `multiple`;调用时显式填写 `mode`,便于区分筛选方式:

| 模式 | options / v-model | 生效方式 |
| ---------- | --------------------------------------------------------- | ----------------------------------------------------------- |
| `multiple` | `TableFilterOption[]` / 字符串、数字或布尔值数组 | 打开时复制草稿,确定后提交;重置提交 `[]`;点击外部丢弃草稿 |
| `single` | `TableFilterOption[]` / 字符串、数字或布尔值,加 `null` | 点击立即提交并关闭;“全部”提交 `null` |
| `cascader` | Element Plus `CascaderOption[]` / 由 `cascaderProps` 决定 | 勾选立即提交;多选保持打开,单选提交后关闭 |

`TableFilterOption` 位于 `global/mk-table/mk-table-filter/types.ts`,包含 `label`、`value` 和可选
`disabled`;扁平选项不使用空字符串作为业务值。`false`、`0` 都是有效筛选条件,正确高亮筛选图标。
多选“全部”只操作可用选项,保留已选禁用项;无草稿选择时仍通过“重置”清空。
过长的扁平选项文案省略,悬停查看完整文案。

级联默认配置为 `{ multiple: true, checkStrictly: true, emitPath: false, showPrefix: false }`,与 v2 文档标签筛选一致:
父子节点独立选择,隐藏节点前的选择框。静态多选时,组件保留面板的原始勾选,
对外将选中的父组递归展开为可用叶子节点并去重;页面直接使用回写值,不再自行转换父组。
单选、父子联动和懒加载沿用原生返回值;`emitPath: true` 时返回对应叶子的完整路径。
外部模型变更同步面板;自身提交后的模型回写保留原始父组勾选,关闭再打开也保持。
通过 `cascaderProps` 覆盖字段映射、单多选、路径输出及懒加载等原生配置。
级联多选重置为 `[]`,单选重置为 `null`;单选模型需声明可空类型。
`width` 可覆盖弹层宽度,扁平模式默认 192px,级联默认自适应。

`change(value)` 在写回模型后触发,类型跟随模型;`open` 在每次打开时触发,供页面加载选项。
组件不请求业务接口、不转换查询参数。文档文件状态用唯一选项值映射为 `status` 和 `task_type`,
映射和分页重置由页面负责,切换条件时一起更新这两个参数,避免残留任务类型。

```vue
<!-- 多选:保留确定与重置 -->
<MkTableFilter mode="multiple" v-model="workspaceIds" label="工作空间" :options="workspaceOptions" @change="reload" />
<!-- 单选:enabled 声明为 boolean | null -->
<MkTableFilter
v-model="enabled"
mode="single"
label="启用状态"
:options="[
{ label: '已启用', value: true },
{ label: '已禁用', value: false },
]"
@change="reload"
/>
<!-- 级联:tagIds 为标签值数组,选项通过 children 组织 -->
<MkTableFilter v-model="tagIds" mode="cascader" label="标签" :options="tagOptions" @open="loadTagOptions" @change="reload" />
```

表格操作列需要 More 菜单时使用 `MkTableMoreDropdown`。组件统一提供点击型、右下定位的 More
按钮以及 `MkDropdownMenu`,默认插槽中直接放置 `MkDropdownItem`;插槽为空,或其中的条件菜单项
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,13 @@ defineExpose({ open, close })
<el-table-column v-if="showWorkspace" prop="workspace_name" label="工作空间" min-width="140" show-overflow-tooltip>
<template #header>
<!-- 筛选关联资源所属工作空间 -->
<MkTableFilter v-model="selectedWorkspaceIds" label="工作空间" :options="workspaceOptions" @change="handleWorkspaceFilterChange" />
<MkTableFilter
mode="multiple"
v-model="selectedWorkspaceIds"
label="工作空间"
:options="workspaceOptions"
@change="handleWorkspaceFilterChange"
/>
</template>
</el-table-column>
<el-table-column prop="username" label="创建者" min-width="100" show-overflow-tooltip />
Expand Down
4 changes: 4 additions & 0 deletions ui/src/components/global/mk-status-label/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const statusOptions: Partial<Record<State, { name?: string; loading?: boolean }>
[STATE_TYPES.SUCCESS]: { name: 'icon_succeed_colorful' },
[STATE_TYPES.FAILURE]: { name: 'icon_close_colorful' },
[STATE_TYPES.STARTED]: { loading: true },
[STATE_TYPES.EMBEDDING]: { loading: true },
[STATE_TYPES.GENERATE]: { loading: true },
[STATE_TYPES.SYNC]: { loading: true },
[STATE_TYPES.TOKENIZE]: { loading: true },
[STATE_TYPES.REVOKE]: { loading: true },
[STATE_TYPES.PENDING]: { loading: true },
[STATE_TYPES.REVOKED]: { name: 'icon_close_colorful' },
Expand Down
76 changes: 0 additions & 76 deletions ui/src/components/global/mk-table/MkTableFilter.vue

This file was deleted.

Loading
Loading