Skip to content

Commit 1c2105e

Browse files
feat: document status
1 parent 7fb7361 commit 1c2105e

35 files changed

Lines changed: 500 additions & 340 deletions

File tree

‎ui/src/api/API_README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,9 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展
506506
批量任务沿用 v2 的 `id_list` / `state_list`;生成问题使用 `document_id_list`,
507507
添加标签使用 `document_ids` / `tag_ids`,迁移和批量导出直接提交文档 ID 数组。
508508
向量化、生成问题默认排除成功分段,也可选择全部分段。任务类型使用 `DOCUMENT_TASK_TYPE`。
509+
单项向量化使用 `putDocumentRefresh(knowledgeId, documentId, stateList)` 请求 `/<documentId>/refresh`;
510+
单项取消使用 `putCancelTask(knowledgeId, documentId, taskType)` 请求 `/<documentId>/cancel_task`,提交 `{ type }`。
511+
批量向量化与取消分别沿用 `batch_refresh` 和 `batch_cancel_task`,不以单元素批量请求代替单项接口。
509512
文档设置的共享载荷为 `DocumentSettingPayload`,生成问题使用 `DocumentGeneratePayload`;
510513
单项设置通过 `meta` 保留来源数据,批量设置将 `allow_download` 放在顶层。
511514
飞书同步沿用 v2 扩展接口 `/knowledge/lark/<knowledgeId>/_batch`,需部署环境支持。

‎ui/src/api/admin/workspace/knowledge/document.ts‎

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,43 @@ const putQuickCreateDocuments = (knowledgeId: string, documents: DocumentQuickCr
2626
const putDocumentActive = (knowledgeId: string, documentId: string, isActive: boolean) =>
2727
put(`${getPrefix(knowledgeId)}/${documentId}`, { is_active: isActive })
2828

29-
30-
3129
/** 删除单个文档。 */
3230
const deleteDocument = (knowledgeId: string, documentId: string) => del(`${getPrefix(knowledgeId)}/${documentId}`)
3331

3432
/** 批量删除文档。 */
3533
const putBatchDeleteDocuments = (knowledgeId: string, documentIds: string[]) =>
3634
put(`${getPrefix(knowledgeId)}/batch_delete`, { id_list: documentIds })
3735

36+
/** 单个文档向量化。 */
37+
const putDocumentRefresh = (knowledgeId: string, documentId: string, stateList: DocumentTaskState[]) =>
38+
put(`${getPrefix(knowledgeId)}/${documentId}/refresh`, { state_list: stateList })
3839

39-
/** 批量提交文档向量化。 */
40+
/** 批量文档向量化。 */
4041
const putBatchRefreshDocuments = (knowledgeId: string, documentIds: string[], stateList: DocumentTaskState[]) =>
4142
put(`${getPrefix(knowledgeId)}/batch_refresh`, { id_list: documentIds, state_list: stateList })
4243

43-
/** 批量提交文档分词索引。 */
44+
/** 单个文档分词索引。 */
45+
const putDocumentTokenize: (knowledge_id: string, document_id: string, state_list: Array<string>, loading?: Ref<boolean>) => Promise<Result<any>> = (
46+
knowledge_id,
47+
document_id,
48+
state_list,
49+
loading,
50+
) => {
51+
return put(`${getPrefix(knowledge_id)}/${document_id}/tokenize`, { state_list }, undefined, loading)
52+
}
53+
/** 批量文档分词索引。 */
4454
const putBatchTokenizeDocuments = (knowledgeId: string, documentIds: string[], stateList: DocumentTaskState[]) =>
4555
put(`${getPrefix(knowledgeId)}/batch_tokenize`, { id_list: documentIds, state_list: stateList })
4656

57+
/** 单个取消文档任务。 */
58+
const putCancelTask = (knowledgeId: string, documentId: string, taskType: DocumentTaskType) =>
59+
put(`${getPrefix(knowledgeId)}/${documentId}/cancel_task`, { type: taskType })
60+
4761
/** 批量取消指定文档任务。 */
4862
const putBatchCancelDocumentTask = (knowledgeId: string, documentIds: string[], taskType: DocumentTaskType) =>
4963
put(`${getPrefix(knowledgeId)}/batch_cancel_task`, { id_list: documentIds, type: taskType })
5064

65+
5166
/** 保存单个文档的召回及来源设置。 */
5267
const putDocumentSetting = (knowledgeId: string, documentId: string, data: DocumentSettingPayload) =>
5368
put(`${getPrefix(knowledgeId)}/${documentId}`, data)
@@ -103,8 +118,10 @@ export default {
103118
putDocumentActive,
104119
deleteDocument,
105120
putBatchDeleteDocuments,
121+
putDocumentRefresh,
106122
putBatchRefreshDocuments,
107123
putBatchTokenizeDocuments,
124+
putCancelTask,
108125
putBatchCancelDocumentTask,
109126
putDocumentSetting,
110127
putBatchDocumentSetting,

‎ui/src/api/enums/state.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
/** 跨业务复用的任务状态,按需扩展。 */
1+
/** 执行记录接口状态;文档任务阶段在所属 View 中维护。 */
22
export const STATE_TYPES = {
33
PENDING: 'PENDING',
44
STARTED: 'STARTED',
5-
EMBEDDING: 'EMBEDDING',
6-
GENERATE: 'GENERATE',
7-
SYNC: 'SYNC',
8-
TOKENIZE: 'TOKENIZE',
95
SUCCESS: 'SUCCESS',
106
FAILURE: 'FAILURE',
117
REVOKE: 'REVOKE',

‎ui/src/assets/iconfont.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ui/src/components/COMPONENT_README.md‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ Drawer 没有 `MkDialog` 的外壳挂载控制;需要按需挂载时,由业
193193
菜单项通过 `icon` Prop 传 Element Plus 图标,或使用 `icon` 插槽;`selectable` 预留勾选位,
194194
`selected` 控制选中。触发器遵循单根节点规则。
195195

196+
`hide-when-empty` 默认关闭。开启后检查 `dropdown` 插槽,展开标准 `MkDropdownMenu` 的默认插槽
197+
和 Fragment,忽略注释、空白文本;没有有效 VNode 时不渲染下拉入口,不改变 `persistent`。
198+
业务 Action 的组件 VNode 视为有效内容,不检查其内部的 `v-if`。此能力用于文档批量 More,
199+
表格和卡片 More 保持原有的默认插槽判断。
200+
196201
### MkViewLayout
197202

198203
满高页面布局,`loading` 覆盖整个根节点。`title` 默认读取路由标题,传空字符串隐藏;
@@ -276,19 +281,21 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载
276281

277282
### MkStatusLabel
278283

279-
`active` 控制布尔状态,默认“已启用 / 已禁用”;用 `activeText`、`inactiveText` 修改文案。
280-
多状态通过 `status` 直接传入 `STATE_LABELS` 的状态键,文案统一读取 `constants/state.ts`。
281-
传入 `status` 时仅显示该状态配置的图标;未配置状态或没有图标时只显示文案,不回退到其他状态图标。
282-
未传 `status` 时,`active` 为 true 显示成功图标,为 false 显示 `icon_ban_filled`。
283-
组件直接使用公共枚举 `STATE_TYPES` 匹配图标;新增状态需补齐 `STATE_LABELS` 文案,图标可按需配置。
284-
`STARTED`、`PENDING`、`REVOKE` 及 `EMBEDDING`、`GENERATE`、`SYNC`、`TOKENIZE`
285-
统一显示内置加载图标,使用方直接传入 `status`,无需额外组合 `LoadingIcon`。
286-
`status` 优先于 `active`,状态文案统一使用 `STATE_LABELS`,不提供 `text` 覆盖。
284+
提供 `success`、`failure`、`loading`、`disabled` 四种图标类型,通过 `type + label` 展示业务状态。
285+
组件不依赖 API 状态枚举或业务文案;业务方维护状态与 `{ type, label }` 的映射。
286+
`StatusLabelType`、`StatusLabelOptions` 从 `global/mk-status-label/types.ts` 导入。
287+
传入 `type` 时使用该类型和外部 `label`,优先于布尔模式,不回退到启用/禁用文案。
288+
289+
未传 `type` 时保留 `active` 便捷模式,默认“已启用 / 已禁用”;
290+
`activeText`、`inactiveText` 可修改文案,`inactiveIcon` 可覆盖未激活图标(默认 `icon_ban_filled`)。
291+
成功图标固定为 `icon_succeed_colorful`,失败图标为 `icon_close_colorful`,加载类型使用 `LoadingIcon`,
292+
禁用图标使用灰色样式。`inactiveIcon` 仅影响布尔模式。
293+
不再接收 `status`;未知业务状态由调用方显示原始文案,不伪装成成功或禁用状态。
287294

288295
```vue
289296
<MkStatusLabel :active="enabled" />
290-
<MkStatusLabel :status="row.state" />
291-
<MkStatusLabel status="TRIGGER_ERROR" />
297+
<MkStatusLabel type="loading" label="索引中" />
298+
<MkStatusLabel v-bind="executionStatus" />
292299
```
293300

294301
### MkTable

‎ui/src/components/business/resource-authorization-drawer/PermissionConfigDialog.vue‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ defineExpose({ open, close })
4444

4545
<template>
4646
<MkDialog v-model="visible" :title="scopeOnly ? '生效资源' : '配置权限'" :show-close="!loading" @closed="resetData">
47-
<el-radio-group v-if="!scopeOnly" v-model="permission" class="vertical-radio-group" :disabled="loading">
47+
<el-radio-group v-if="!scopeOnly" v-model="permission" class="mk-radio-group-vertical" :disabled="loading">
4848
<el-radio v-for="option in options" :key="option.value" :value="option.value">
4949
<p>{{ option.label }}</p>
5050
<p v-if="option.description" class="mt-1 text-N500">{{ option.description }}</p>
@@ -55,7 +55,7 @@ defineExpose({ open, close })
5555
<el-divider class="my-4!" />
5656
<h6 class="mb-2">生效资源</h6>
5757
</template>
58-
<el-radio-group v-model="includeChildren" class="vertical-radio-group" :disabled="loading">
58+
<el-radio-group v-model="includeChildren" class="mk-radio-group-vertical" :disabled="loading">
5959
<el-radio :value="false">仅当前资源</el-radio>
6060
<el-radio :value="true" :disabled="!canIncludeChildren">包含所有子文件夹</el-radio>
6161
</el-radio-group>

‎ui/src/components/global/mk-dropdown/index.vue‎

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,43 @@
11
<script setup lang="ts">
2-
import { ref } from 'vue'
2+
import { Fragment, isVNode, ref } from 'vue'
33
import type { DropdownInstance } from 'element-plus'
44
import type { Options } from '@popperjs/core'
5+
import { hasRenderableSlotContent } from '@/utils/vnode'
6+
import MkDropdownMenu from './MkDropdownMenu.vue'
57
68
defineOptions({ name: 'MkDropdown', inheritAttrs: false })
79
8-
withDefaults(defineProps<{ popperOptions?: Partial<Options>; persistent?: boolean }>(), {
10+
withDefaults(defineProps<{ popperOptions?: Partial<Options>; persistent?: boolean; hideWhenEmpty?: boolean }>(), {
911
popperOptions: () => ({}),
1012
persistent: false,
1113
/* 非必要不开启,调试时可临时开启 */
14+
hideWhenEmpty: false,
1215
})
1316
1417
const dropdownRef = ref<DropdownInstance>()
1518
16-
defineSlots<{
19+
const slots = defineSlots<{
1720
/** 下拉触发器,必须只渲染一个有效根节点 */
1821
default(): unknown
1922
dropdown(): unknown
2023
}>()
2124
25+
// 只展开标准菜单和 Fragment;业务 Action 仍按组件 VNode 判断。
26+
function hasDropdownContent(children: unknown): boolean {
27+
const childNodes = Array.isArray(children) ? children : [children]
28+
return childNodes.some((child) => {
29+
if (isVNode(child)) {
30+
if (child.type === Fragment) return hasDropdownContent(child.children)
31+
if (child.type === MkDropdownMenu) {
32+
const menuSlots = child.children
33+
const menuSlot = menuSlots && typeof menuSlots === 'object' && 'default' in menuSlots ? menuSlots.default : undefined
34+
return hasDropdownContent(typeof menuSlot === 'function' ? menuSlot() : menuSlots)
35+
}
36+
}
37+
return hasRenderableSlotContent(child)
38+
})
39+
}
40+
2241
function handleOpen() {
2342
dropdownRef.value?.handleOpen()
2443
}
@@ -31,7 +50,13 @@ defineExpose({ handleOpen, handleClose })
3150
</script>
3251

3352
<template>
34-
<el-dropdown class="mk-dropdown" ref="dropdownRef" :persistent="persistent" v-bind="$attrs">
53+
<el-dropdown
54+
v-if="!hideWhenEmpty || hasDropdownContent(slots.dropdown?.())"
55+
class="mk-dropdown"
56+
ref="dropdownRef"
57+
:persistent="persistent"
58+
v-bind="$attrs"
59+
>
3560
<slot />
3661
<template #dropdown>
3762
<slot name="dropdown" />
Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,34 @@
11
<script setup lang="ts">
22
import { computed } from 'vue'
3-
import { STATE_LABELS } from '@/constants/state'
4-
import { STATE_TYPES } from '@/api/enums'
5-
import type { State } from '@/api/types'
3+
import type { StatusLabelType } from './types'
64
75
defineOptions({ name: 'MkStatusLabel' })
86
97
const props = withDefaults(
108
defineProps<{
11-
active?: boolean // 启用状态
9+
type?: StatusLabelType
10+
label?: string
11+
active?: boolean
1212
activeText?: string
1313
inactiveText?: string
14-
status?: State // 多种状态
14+
inactiveIcon?: string
1515
}>(),
16-
{ activeText: '已启用', inactiveText: '已禁用' },
16+
{ activeText: '已启用', inactiveText: '已禁用', inactiveIcon: 'icon_ban_filled' },
1717
)
1818
19-
/* 状态文案与 STATE_LABELS 共用状态键,兼容原有启用/禁用展示。 */
20-
const statusOptions: Partial<Record<State, { name?: string; loading?: boolean }>> = {
21-
[STATE_TYPES.SUCCESS]: { name: 'icon_succeed_colorful' },
22-
[STATE_TYPES.FAILURE]: { name: 'icon_close_colorful' },
23-
[STATE_TYPES.STARTED]: { loading: true },
24-
[STATE_TYPES.EMBEDDING]: { loading: true },
25-
[STATE_TYPES.GENERATE]: { loading: true },
26-
[STATE_TYPES.SYNC]: { loading: true },
27-
[STATE_TYPES.TOKENIZE]: { loading: true },
28-
[STATE_TYPES.REVOKE]: { loading: true },
29-
[STATE_TYPES.PENDING]: { loading: true },
30-
[STATE_TYPES.REVOKED]: { name: 'icon_close_colorful' },
31-
}
32-
const presentation = computed(() => {
33-
if (props.status !== undefined) return statusOptions[props.status]
34-
return props.active ? statusOptions[STATE_TYPES.SUCCESS] : undefined
19+
const displayType = computed(() => props.type ?? (props.active ? 'success' : 'disabled'))
20+
const displayLabel = computed(() => (props.type !== undefined ? props.label : props.active ? props.activeText : props.inactiveText))
21+
const iconName = computed(() => {
22+
if (displayType.value === 'success') return 'icon_succeed_colorful'
23+
if (displayType.value === 'failure') return 'icon_close_colorful'
24+
return props.type === undefined ? props.inactiveIcon : 'icon_ban_filled'
3525
})
36-
const label = computed(() =>
37-
props.status !== undefined ? (STATE_LABELS[props.status] ?? props.status) : props.active ? props.activeText : props.inactiveText,
38-
)
3926
</script>
4027

4128
<template>
4229
<span class="flex-align-center gap-2">
43-
<LoadingIcon v-if="presentation?.loading" :size="16" />
44-
<MkIcon v-else-if="presentation?.name" :name="presentation.name" />
45-
<MkIcon v-else-if="status === undefined && !active" name="icon_ban_filled" class="text-N500!" />
46-
<span>{{ label }}</span>
30+
<LoadingIcon v-if="displayType === 'loading'" :size="16" />
31+
<MkIcon v-else :name="iconName" :class="{ 'text-N500!': displayType === 'disabled' }" />
32+
<span>{{ displayLabel }}</span>
4733
</span>
4834
</template>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export type StatusLabelType = 'success' | 'failure' | 'loading' | 'disabled'
2+
3+
export interface StatusLabelOptions {
4+
type: StatusLabelType
5+
label: string
6+
}

‎ui/src/constants/CONSTANT_README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ const knowledgeTypeLabel = KNOWLEDGE_TYPE_LABELS[knowledgeType]
3737
`trigger.ts` 的 `TRIGGER_SCHEDULE_OPTIONS` 统一提供触发器与长期记忆的周期级联选项,
3838
包含周期文案、执行时间和间隔数值;使用方只读,配置回填与校验仍由各自组件维护。
3939

40-
`state.ts` 的 `STATE_LABELS` 统一维护公共枚举 `STATE_TYPES` 的展示文案。触发器等使用通用状态协议的业务
41-
按需复用 `api/enums/state.ts` 中的状态值;新增状态时同步补齐文案和 `MkStatusLabel` 的图标映射。
42-
`STATE_LABELS` 还提供 `EMBEDDING`(索引中)、`GENERATE`(生成中)、`SYNC`(同步中)、
43-
`TOKENIZE`(分词索引中)的任务阶段文案,文档筛选直接复用对应文案。接口值继续使用
44-
`DOCUMENT_TASK_STATE` 和 `DOCUMENT_TASK_TYPE` 映射,不将展示状态键直接提交为文档任务状态。
40+
`state.ts` 的 `EXECUTION_STATUS_OPTIONS` 维护触发器、工具和知识库工作流执行记录共用的
41+
中文文案与图标类型,仅包含 `PENDING`、`STARTED`、`SUCCESS`、`FAILURE`、`REVOKE`、
42+
`REVOKED`、`TRIGGER_ERROR` 七种接口状态,列表筛选及执行详情复用该配置。新增状态只需在业务配置中补齐展示,
43+
不修改 `MkStatusLabel`。文档任务使用 `views/knowledge-detail/document/status.ts` 的独立配置,
44+
筛选查询仍映射 `DOCUMENT_TASK_STATE` 与 `DOCUMENT_TASK_TYPE`,不提交展示状态键。
4545

4646
`document.ts` 的 `DOCUMENT_HIT_HANDLING_LABELS` 维护文档命中处理方式的展示文案,
4747
映射键引用 API 枚举 `DOCUMENT_HIT_HANDLING`。

0 commit comments

Comments
 (0)