Skip to content

Commit e910bb0

Browse files
feat: application resource managemen
1 parent d3b67ff commit e910bb0

11 files changed

Lines changed: 146 additions & 79 deletions

File tree

‎ui/src/views/VIEW_README.md‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,11 +697,14 @@ Workspace API 内部通过 `getWorkspaceId()` 读取当前路由工作空间。
697697
选中后通过 `footer-batch-actions` 展示批量操作。右侧固定操作列提供启停、向量化、分词索引和更多菜单,
698698
运行或排队中的任务切换为取消入口。Web、飞书提供同步,普通与工作流文档提供原文下载和替换。
699699
单项与批量操作共用页面请求状态,删除和同步先确认,成功后清空选择并刷新,导出和下载保留选择。
700+
文档页及其 Action 的知识库类型统一读取响应式路由参数 `route.params.type`,使用
701+
`KNOWLEDGE_TYPE_KEY` 判断,不从详情或文档数据读取类型,也不通过 `knowledgeType` Prop 传递。
702+
Web 来源地址与选择器仅在单项设置中编辑,批量设置不展示这两个字段。
700703
文档操作统一放在 `document/action-dropdown/`,通过该目录 `index.ts` 导出,页面显式组合各 Action。
701704
文档状态展示、筛选配置和任务运行状态判断统一维护在 `document/status.ts`。
702705
文档任务是否排队或执行中通过其中的 `isDocumentTaskRunning(document, taskType)` 判断,
703706
页面及 Action 不重复解析状态字符串;文档或任务状态缺失时返回 `false`。
704-
`EmbeddingDocumentAction` 负责单项向量化与取消向量化,`BatchEmbeddingAction` 负责批量向量化按钮,`GenerateDocumentQuestionsAction` 负责文档生成问题入口和提交,`SettingDocumentAction` 负责召回及来源设置,
707+
`EmbeddingDocumentAction` 负责单项向量化与取消向量化,`BatchEmbeddingAction` 负责批量向量化按钮,`GenerateQuestionsAction` 负责单项生成问题与取消生成,`BatchGenerateQuestionsAction` 负责批量生成问题,`SettingDocumentAction` 负责召回及来源设置,
705708
`MigrateDocumentAction` 选择目标知识库,`DocumentTagsAction` 添加已有标签和移除文档标签关联;
706709
生成问题复用公共配置弹窗,其余 Action 按下文维护各自专属弹窗。组件接收完整 Document API、知识库 ID、文档 ID 或文档数组及禁用状态,
707710
点击时快照本次操作对象,内部管理弹窗和请求,成功后通过 `refresh` 通知页面刷新,失败保留输入。
@@ -711,7 +714,9 @@ Workspace API 内部通过 `getWorkspaceId()` 读取当前路由工作空间。
711714
向量化相关文件集中在 `document/action-dropdown/embedding/`,包含两个 Action 和共用的 `DocumentEmbeddingDialog.vue`;
712715
Action 仍通过上层 `action-dropdown/index.ts` 导出,弹窗仅在目录内部使用,管理分段范围与确认事件,
713716
请求和成功关闭由各自 Action 负责;打开时快照文档目标,失败保留范围选择。
714-
生成问题通过 `batch` 切换批量按钮,通过 `display` 区分行内菜单与图标按钮。
717+
生成问题相关 Action 集中在 `document/action-dropdown/generate-questions/`,通过上层 `index.ts` 导出。
718+
`GenerateQuestionsAction` 接收单个 `document`,内部判断任务状态并处理生成与单项取消,通过 `display` 区分菜单与图标按钮。
719+
`BatchGenerateQuestionsAction` 接收 `documentIds`,使用独立的批量生成按钮;批量取消继续使用 `BatchCancelTaskAction`。
715720
单项与批量复用公共 `GenerateQuestionsDialog`,Action 打开时保存知识库、文档 ID 快照,
716721
提交同一文档批量接口并通过 `refresh` 刷新状态;通过 `v-model:loading` 复用页面操作状态。
717722
公共弹窗按需挂载、关闭后卸载,不负责选择提交接口。当前尚无段落页,后续段落入口复用公共

‎ui/src/views/knowledge-detail/document/action-dropdown/SettingDocumentAction.vue‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
<script setup lang="ts">
2-
import { ref } from 'vue'
2+
import { computed, ref } from 'vue'
3+
import { useRoute } from 'vue-router'
34
import type { FormInstance } from 'element-plus'
4-
import { DOCUMENT_HIT_HANDLING, KNOWLEDGE_TYPE } from '@/api/enums'
5+
import { DOCUMENT_HIT_HANDLING } from '@/api/enums'
56
import type { DocumentItem, DocumentSettingPayload } from '@/api/types'
67
import type DocumentApi from '@/api/admin/workspace/knowledge/document'
8+
import { KNOWLEDGE_TYPE_KEY } from '@/constants/knowledge'
79
import { DOCUMENT_HIT_HANDLING_LABELS } from '@/constants/document'
810
import { MsgSuccess } from '@/utils/message'
911
1012
defineOptions({ name: 'SettingDocumentAction' })
1113
const props = defineProps<{ api: typeof DocumentApi; knowledgeId: string; documents: DocumentItem[]; batch?: boolean; disabled?: boolean }>()
1214
const emit = defineEmits<{ refresh: [] }>()
15+
const route = useRoute()
16+
const knowledgeType = computed(() => route.params.type)
1317
const visible = ref(false)
1418
const loading = ref(false)
1519
const formRef = ref<FormInstance>()
@@ -50,7 +54,7 @@ async function handleSubmit() {
5054
let request: Promise<unknown>
5155
if (document.value) {
5256
data.meta = { ...document.value.meta, allow_download: form.value.allow_download }
53-
if (document.value.type === KNOWLEDGE_TYPE.WEB) {
57+
if (knowledgeType.value === KNOWLEDGE_TYPE_KEY.WEB) {
5458
data.meta.source_url = form.value.source_url.trim()
5559
data.meta.selector = form.value.selector
5660
}
@@ -84,7 +88,7 @@ function handleClosed() {
8488
<MkAction label="设置" icon="icon_setting" :disabled="disabled || loading || !documents.length" @click="handleOpenDialog" />
8589
<MkDialog v-model="visible" title="文档设置" :show-close="!loading" @closed="handleClosed">
8690
<el-form ref="formRef" :model="form" label-position="top" :disabled="loading" @submit.prevent>
87-
<template v-if="document?.type === KNOWLEDGE_TYPE.WEB">
91+
<template v-if="document && knowledgeType === KNOWLEDGE_TYPE_KEY.WEB">
8892
<el-form-item label="文档地址" prop="source_url" :rules="[{ required: true, whitespace: true, message: '请输入文档地址', trigger: 'blur' }]">
8993
<el-input v-model="form.source_url" />
9094
</el-form-item>
@@ -109,7 +113,7 @@ function handleClosed() {
109113
align="left"
110114
/>
111115
</el-form-item>
112-
<el-checkbox v-model="form.allow_download">{{ document?.type === KNOWLEDGE_TYPE.WEB ? '允许预览' : '允许下载' }}</el-checkbox>
116+
<el-checkbox v-model="form.allow_download">{{ knowledgeType === KNOWLEDGE_TYPE_KEY.WEB ? '允许预览' : '允许下载' }}</el-checkbox>
113117
</el-form>
114118
<template #footer>
115119
<!-- 取消文档设置 -->
Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
<script setup lang="ts">
2+
import { computed } from 'vue'
3+
import { useRoute } from 'vue-router'
24
import type DocumentApi from '@/api/admin/workspace/knowledge/document'
3-
import { KNOWLEDGE_TYPE } from '@/api/enums'
4-
import type { DocumentItem, KnowledgeType } from '@/api/types'
5+
import { KNOWLEDGE_TYPE_KEY } from '@/constants/knowledge'
6+
import type { DocumentItem } from '@/api/types'
57
import { MsgConfirm, MsgInfo, MsgSuccess } from '@/utils/message'
68
79
defineOptions({ name: 'SyncDocumentAction' })
810
const props = defineProps<{
911
api: typeof DocumentApi
1012
knowledgeId: string
1113
documents: DocumentItem[]
12-
knowledgeType?: KnowledgeType
1314
batch?: boolean
1415
}>()
16+
const route = useRoute()
17+
const knowledgeType = computed(() => route.params.type)
1518
const loading = defineModel<boolean>('loading', { default: false })
1619
const emit = defineEmits<{ refresh: [] }>()
1720
1821
// 单项 Web 同步校验来源地址,确认覆盖后按知识库类型调用同步接口。
1922
function handleSync() {
2023
if (!props.documents.length || loading.value) return
2124
const document = props.batch ? undefined : props.documents[0]
22-
if (document?.type === KNOWLEDGE_TYPE.WEB && !document.meta?.source_url) {
25+
if (document && knowledgeType.value === KNOWLEDGE_TYPE_KEY.WEB && !document.meta?.source_url) {
2326
MsgInfo('文档没有来源地址,请先在设置中填写文档地址')
2427
return
2528
}
@@ -29,7 +32,7 @@ function handleSync() {
2932
if (loading.value) return
3033
loading.value = true
3134
const request =
32-
props.knowledgeType === KNOWLEDGE_TYPE.LARK
35+
knowledgeType.value === KNOWLEDGE_TYPE_KEY.LARK
3336
? props.api.putSyncLarkDocuments(props.knowledgeId, ids)
3437
: props.api.putSyncDocuments(props.knowledgeId, ids)
3538
return request
@@ -47,11 +50,5 @@ function handleSync() {
4750

4851
<template>
4952
<!-- 同步单个或选中文档 -->
50-
<MkAction
51-
v-if="knowledgeType === KNOWLEDGE_TYPE.WEB || knowledgeType === KNOWLEDGE_TYPE.LARK"
52-
:label="batch ? '同步文档' : '同步'"
53-
icon="icon_refresh_outlined"
54-
:disabled="loading || !documents.length"
55-
@click="handleSync"
56-
/>
53+
<MkAction :label="batch ? '同步文档' : '同步'" icon="icon_refresh_outlined" @click="handleSync" />
5754
</template>

ui/src/views/knowledge-detail/document/action-dropdown/GenerateDocumentQuestionsAction.vue renamed to ui/src/views/knowledge-detail/document/action-dropdown/generate-questions/BatchGenerateQuestionsAction.vue

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,17 @@ import type DocumentApi from '@/api/admin/workspace/knowledge/document'
55
import GenerateQuestionsDialog from '@/components/business/generate-questions/GenerateQuestionsDialog.vue'
66
import { MsgSuccess } from '@/utils/message'
77
8-
defineOptions({ name: 'GenerateDocumentQuestionsAction' })
8+
defineOptions({ name: 'BatchGenerateQuestionsAction' })
99
const props = defineProps<{
1010
api: typeof DocumentApi
1111
knowledgeId: string
1212
documentIds: string[]
13-
batch?: boolean
14-
display?: 'menu' | 'button'
1513
disabled?: boolean
1614
}>()
1715
const emit = defineEmits<{ refresh: [] }>()
1816
const loading = defineModel<boolean>('loading', { default: false })
1917
20-
/* 打开时固定目标文档,单项与批量共用文档生成接口。 */
18+
/* 打开时固定本次批量生成的目标文档。 */
2119
const dialogMounted = ref(false)
2220
const dialogRef = useTemplateRef<InstanceType<typeof GenerateQuestionsDialog>>('dialogRef')
2321
const targetDocumentIds = ref<string[]>([])
@@ -61,15 +59,6 @@ function handleClosed() {
6159

6260
<template>
6361
<!-- 批量生成问题 -->
64-
<el-button v-if="batch" :disabled="disabled || loading || !documentIds.length" @click="handleOpenDialog">生成问题</el-button>
65-
<!-- 单个文档生成问题 -->
66-
<MkAction
67-
v-else
68-
:display="display ?? 'menu'"
69-
label="生成问题"
70-
icon="icon_new-chat_outlined"
71-
:disabled="disabled || loading || !documentIds.length"
72-
@click="handleOpenDialog"
73-
/>
62+
<el-button :disabled="disabled || loading || !documentIds.length" @click="handleOpenDialog">生成问题</el-button>
7463
<GenerateQuestionsDialog v-if="dialogMounted" ref="dialogRef" :loading="loading" @submit="handleSubmit" @closed="handleClosed" />
7564
</template>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<script setup lang="ts">
2+
import { computed, nextTick, ref, useTemplateRef } from 'vue'
3+
import { DOCUMENT_TASK_TYPE } from '@/api/enums'
4+
import type { DocumentItem, DocumentTaskState, RelatedQuestionsConfig } from '@/api/types'
5+
import type DocumentApi from '@/api/admin/workspace/knowledge/document'
6+
import GenerateQuestionsDialog from '@/components/business/generate-questions/GenerateQuestionsDialog.vue'
7+
import { MsgSuccess } from '@/utils/message'
8+
import { isDocumentTaskRunning } from '../../status'
9+
10+
defineOptions({ name: 'GenerateQuestionsAction' })
11+
const props = defineProps<{
12+
api: typeof DocumentApi
13+
knowledgeId: string
14+
document: DocumentItem
15+
display?: 'menu' | 'button'
16+
disabled?: boolean
17+
}>()
18+
const emit = defineEmits<{ refresh: [] }>()
19+
const loading = defineModel<boolean>('loading', { default: false })
20+
21+
// 单个文档在排队或执行时展示取消入口,其余状态打开生成配置。
22+
const running = computed(() => isDocumentTaskRunning(props.document, DOCUMENT_TASK_TYPE.GENERATE_PROBLEM))
23+
24+
/* 打开时固定本次生成的目标文档。 */
25+
const dialogMounted = ref(false)
26+
const dialogRef = useTemplateRef<InstanceType<typeof GenerateQuestionsDialog>>('dialogRef')
27+
const targetDocumentId = ref('')
28+
const targetKnowledgeId = ref('')
29+
30+
function handleOpenDialog() {
31+
if (props.disabled || loading.value || dialogMounted.value || !props.document.id) return
32+
targetDocumentId.value = props.document.id
33+
targetKnowledgeId.value = props.knowledgeId
34+
dialogMounted.value = true
35+
return nextTick(() => dialogRef.value?.open())
36+
}
37+
38+
// 取消当前文档的生成问题任务。
39+
function handleCancelQuestions() {
40+
if (props.disabled || loading.value) return
41+
loading.value = true
42+
return props.api
43+
.putCancelTask(props.knowledgeId, props.document.id, DOCUMENT_TASK_TYPE.GENERATE_PROBLEM)
44+
.then(() => {
45+
MsgSuccess('操作成功')
46+
emit('refresh')
47+
})
48+
.catch(() => {})
49+
.finally(() => {
50+
loading.value = false
51+
})
52+
}
53+
54+
/* Action 负责提交和成功后的页面刷新,失败保留配置。 */
55+
function handleSubmit(config: RelatedQuestionsConfig, stateList: DocumentTaskState[]) {
56+
if (props.disabled || loading.value) return
57+
loading.value = true
58+
return props.api
59+
.putGenerateDocumentQuestions(targetKnowledgeId.value, {
60+
...config,
61+
document_id_list: [targetDocumentId.value],
62+
state_list: stateList,
63+
})
64+
.then(() => {
65+
MsgSuccess('任务已提交')
66+
dialogRef.value?.close()
67+
emit('refresh')
68+
})
69+
.catch(() => {})
70+
.finally(() => {
71+
loading.value = false
72+
})
73+
}
74+
75+
function handleClosed() {
76+
dialogMounted.value = false
77+
targetDocumentId.value = ''
78+
targetKnowledgeId.value = ''
79+
}
80+
</script>
81+
82+
<template>
83+
<!-- 单个文档生成或取消生成问题 -->
84+
<MkAction
85+
:display="display ?? 'menu'"
86+
:label="running ? '取消生成问题' : '生成问题'"
87+
:icon="running ? undefined : 'icon_new-chat_outlined'"
88+
:disabled="disabled || loading || !document.id"
89+
@click="running ? handleCancelQuestions() : handleOpenDialog()"
90+
/>
91+
<GenerateQuestionsDialog v-if="dialogMounted" ref="dialogRef" :loading="loading" @submit="handleSubmit" @closed="handleClosed" />
92+
</template>

‎ui/src/views/knowledge-detail/document/action-dropdown/index.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ export { default as BatchCancelTaskAction } from './BatchCancelTaskAction.vue'
33
export { default as DeleteDocumentAction } from './DeleteDocumentAction.vue'
44
export { default as DocumentTagsAction } from './DocumentTagsAction.vue'
55
export { default as EmbeddingDocumentAction } from './embedding/EmbeddingDocumentAction.vue'
6-
export { default as GenerateDocumentQuestionsAction } from './GenerateDocumentQuestionsAction.vue'
6+
export { default as GenerateQuestionsAction } from './generate-questions/GenerateQuestionsAction.vue'
7+
export { default as BatchGenerateQuestionsAction } from './generate-questions/BatchGenerateQuestionsAction.vue'
78
export { default as DownloadDocumentAction } from './DownloadDocumentAction.vue'
89
export { default as ExportDocumentAction } from './ExportDocumentAction.vue'
910
export { default as MigrateDocumentAction } from './MigrateDocumentAction.vue'

‎ui/src/views/knowledge-detail/document/index.vue‎

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import KnowledgeApi from '@/api/admin/workspace/knowledge/knowledge'
1010
import SharedKnowledgeApi from '@/api/admin/workspace/shared/knowledge/knowledge'
1111
import CommonApi from '@/api/admin/workspace/common'
1212
import CommonSystemApi from '@/api/admin/system/common'
13-
import { DOCUMENT_TASK_TYPE, KNOWLEDGE_TYPE } from '@/api/enums'
13+
import { DOCUMENT_TASK_TYPE } from '@/api/enums'
14+
import { KNOWLEDGE_TYPE_KEY } from '@/constants/knowledge'
1415
import { DOCUMENT_HIT_HANDLING_LABELS } from '@/constants/document'
15-
import { DOCUMENT_STATUS_FILTER_OPTIONS, isDocumentTaskRunning } from './status'
16+
import { DOCUMENT_STATUS_FILTER_OPTIONS } from './status'
1617
import type { Dict, DocumentHitHandling, DocumentItem, OptionItem } from '@/api/types'
1718
import { datetimeFormat } from '@/utils/time'
1819
import { isWorkspaceSharedResource } from '@/utils/resource-context'
@@ -26,7 +27,8 @@ import {
2627
DeleteDocumentAction,
2728
DocumentTagsAction,
2829
EmbeddingDocumentAction,
29-
GenerateDocumentQuestionsAction,
30+
GenerateQuestionsAction,
31+
BatchGenerateQuestionsAction,
3032
DownloadDocumentAction,
3133
ExportDocumentAction,
3234
MigrateDocumentAction,
@@ -36,18 +38,17 @@ import {
3638
TokenizeDocumentAction,
3739
BatchTokenizeAction,
3840
} from './action-dropdown'
39-
import { useKnowledgeDetailContext } from '../context'
4041
4142
defineOptions({ name: 'DocumentListView' })
4243
defineProps<ResourceDetailPageProps>()
4344
defineExpose({ customHeader: true })
4445
4546
const route = useRoute()
4647
const knowledgeId = computed(() => String(route.params.knowledgeId ?? ''))
47-
const { knowledge } = useKnowledgeDetailContext()
48+
const knowledgeType = computed(() => route.params.type)
4849
4950
/* 快速创建 */
50-
const showQuickCreate = computed(() => knowledge.value?.type === KNOWLEDGE_TYPE.BASE && !isWorkspaceSharedResource())
51+
const showQuickCreate = computed(() => knowledgeType.value === KNOWLEDGE_TYPE_KEY.BASE && !isWorkspaceSharedResource())
5152
const quickCreateRef = ref<InstanceType<typeof MkQuickCreate>>()
5253
5354
function handleCreateDocument(name: string) {
@@ -382,42 +383,29 @@ onBeforeUnmount(() => {
382383
@refresh="refreshAfterOperation"
383384
/>
384385
<!-- 更多文档操作 -->
385-
<MkTableMoreDropdown persistent>
386-
<!-- 文档设置 -->
387-
<SettingDocumentAction
388-
:api="DocumentApi"
389-
:knowledge-id="knowledgeId"
390-
:documents="[row]"
391-
:disabled="operationLoading"
392-
@refresh="refreshAfterOperation"
393-
/>
386+
<MkTableMoreDropdown>
394387
<!-- 同步文档 -->
395388
<SyncDocumentAction
389+
v-if="knowledgeType === KNOWLEDGE_TYPE_KEY.WEB || knowledgeType === KNOWLEDGE_TYPE_KEY.LARK"
396390
:api="DocumentApi"
397391
:knowledge-id="knowledgeId"
398392
v-model:loading="operationLoading"
399393
:documents="[row]"
400-
:knowledge-type="knowledge?.type"
401394
@refresh="refreshAfterOperation"
402395
/>
403-
<!-- 取消生成问题 -->
404-
<BatchCancelTaskAction
396+
<!-- 生成或取消生成问题 -->
397+
<GenerateQuestionsAction
405398
:api="DocumentApi"
406-
:knowledge-id="knowledgeId"
407399
v-model:loading="operationLoading"
408-
:document-ids="[row.id]"
409-
:task-type="DOCUMENT_TASK_TYPE.GENERATE_PROBLEM"
410-
label="取消生成问题"
411-
v-if="isDocumentTaskRunning(row, DOCUMENT_TASK_TYPE.GENERATE_PROBLEM)"
400+
:knowledge-id="knowledgeId"
401+
:document="row"
412402
@refresh="refreshAfterOperation"
413403
/>
414-
<!-- 生成问题 -->
415-
<GenerateDocumentQuestionsAction
404+
<!-- 文档设置 -->
405+
<SettingDocumentAction
416406
:api="DocumentApi"
417-
v-model:loading="operationLoading"
418-
v-else
419407
:knowledge-id="knowledgeId"
420-
:document-ids="[row.id]"
408+
:documents="[row]"
421409
:disabled="operationLoading"
422410
@refresh="refreshAfterOperation"
423411
/>
@@ -454,7 +442,7 @@ onBeforeUnmount(() => {
454442
:document-ids="[row.id]"
455443
format="zip"
456444
/>
457-
<template v-if="knowledge?.type === KNOWLEDGE_TYPE.BASE || knowledge?.type === KNOWLEDGE_TYPE.WORKFLOW">
445+
<template v-if="knowledgeType === KNOWLEDGE_TYPE_KEY.BASE || knowledgeType === KNOWLEDGE_TYPE_KEY.WORKFLOW">
458446
<!-- 下载原文档 -->
459447
<DownloadDocumentAction :api="DocumentApi" :knowledge-id="knowledgeId" v-model:loading="operationLoading" :document="row" />
460448
<!-- 替换原文档 -->
@@ -499,10 +487,9 @@ onBeforeUnmount(() => {
499487
@refresh="refreshAfterOperation"
500488
/>
501489
<!-- 批量生成问题 -->
502-
<GenerateDocumentQuestionsAction
490+
<BatchGenerateQuestionsAction
503491
:api="DocumentApi"
504492
v-model:loading="operationLoading"
505-
batch
506493
:knowledge-id="knowledgeId"
507494
:document-ids="selectedDocumentIds"
508495
:disabled="operationLoading"
@@ -537,7 +524,6 @@ onBeforeUnmount(() => {
537524
:knowledge-id="knowledgeId"
538525
v-model:loading="operationLoading"
539526
:documents="selectedDocuments"
540-
:knowledge-type="knowledge?.type"
541527
batch
542528
@refresh="refreshAfterOperation"
543529
/>

0 commit comments

Comments
 (0)