Skip to content

Commit ec2dd64

Browse files
feat: web knowledge
1 parent 85db0c9 commit ec2dd64

8 files changed

Lines changed: 443 additions & 118 deletions

File tree

‎ui/src/api/API_README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,3 +601,6 @@ Workspace 共享知识库详情由 `resourceScope: 'workspace-shared'` 选择上
601601
清除策略通过 PUT `batch_clean_time` 提交当前智能体的单元素 `id_list`、`clean_time`、
602602
`file_clean_time`,避免调用通用应用编辑流程;成功后页面刷新应用详情。
603603
聊天记录、标注、添加知识库接口保留在同一 API 文件,尚未接入本次日志列表页面。
604+
605+
Web 知识库创建的 `WebKnowledgeCreatePayload.doc_strategy` 使用公共 `DocumentStrategy` 类型,
606+
包含 `split`、`visual` 和 `index`,字段与后端文档处理策略协议一致。

‎ui/src/api/types/knowledge.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,18 @@ export interface KnowledgeCreatePayload {
101101
type: KnowledgeType
102102
}
103103

104+
/** Web 文档分段、视觉处理和索引策略。 */
105+
export interface DocumentStrategy {
106+
split: { mode: 'smart' | 'advanced'; patterns: string[] | null; min_length: number; max_length: number; child_length: number; auto_clean: boolean }
107+
visual: { enabled: boolean; strategy: 'model' | 'tool'; model_id: string | null; tool_id: string | null }
108+
index: { title_as_question: boolean }
109+
}
110+
104111
/** 创建 Web 知识库的站点配置。 */
105112
export interface WebKnowledgeCreatePayload extends KnowledgeCreatePayload {
106113
source_url: string
107114
selector: string
115+
doc_strategy?: DocumentStrategy
108116
}
109117

110118
/** 创建飞书知识库的应用配置。 */

‎ui/src/views/VIEW_README.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ src/views/knowledge/
200200
│ └── ButtonTemplateStore.vue # 知识库模板中心与模板创建入口
201201
├── create-knowledge/
202202
│ ├── CreateBaseKnowledgeDialog.vue # 通用知识库创建
203-
│ ├── CreateWebKnowledgeDialog.vue # Web 站点配置与创建
203+
│ ├── WebKnowledgeDrawer.vue # Web 站点配置与两步创建抽屉
204204
│ ├── CreateLarkKnowledgeDialog.vue # 飞书应用配置与创建
205205
│ ├── CreateWorkflowKnowledgeDialog.vue # 工作流知识库创建
206206
│ └── components/
@@ -240,9 +240,15 @@ MCP 配置沿用工具的只读文本与悬浮复制交互,专属弹窗按需
240240
回填模板名称与描述,仍需选择向量模型;提交沿用 `work_flow_template`。创建成功关闭模板中心、
241241
刷新列表并进入知识库工作流,取消创建保留模板中心;创建弹窗在 `closed` 后卸载。
242242

243-
`ButtonCreateKnowledge` 内聚四类创建弹窗 Ref 和打开动作,列表页传入目标 `folderId`,通过
243+
`WebKnowledgeDrawer` 使用底部两步抽屉,基本信息校验后进入文档处理策略,支持返回修改。
244+
`create-knowledge/components/DocumentStrategyForm.vue` 维护分段、视觉增强和标题问题索引,
245+
通过 `doc_strategy` 提交;智能分段默认策略与后端一致,高级分段使用与触发器类型相同的卡片外壳,
246+
在选中卡片内展开配置,默认选择一级至四级标题标识、500–4096 分段长度、256 子块长度并开启自动清洗。
247+
分段标识支持自定义正则表达式,留空使用后端默认规则;启用视觉增强后必须选择模型或工具。
248+
249+
`ButtonCreateKnowledge` 内聚四类创建浮层 Ref 和打开动作,列表页传入目标 `folderId`,通过
244250
`refresh` 刷新列表。入口支持 `trigger` 插槽替换默认创建按钮,下拉使用 `persistent`。
245-
各弹窗接收 `folderId`,通过 `open()` 打开;工作流额外接受可选的商店模板。共用的
251+
各创建浮层接收 `folderId`,通过 `open()` 打开;工作流额外接受可选的商店模板。共用的
246252
`KnowledgeBaseForm` 负责名称、描述、Embedding 模型必填校验以及工作空间和共享模型查询,
247253
根据 `isSystemSharedResource()` 选择 System 共享 Model API 或 Workspace Model API,
248254
通过 `getModelListWithShared({ model_type: 'EMBEDDING' })` 一次加载模型选项,

‎ui/src/views/knowledge-detail/library/document/action-dropdown/setting/DocumentSettingDialog.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ defineExpose({ open, close })
7575
<template #label>
7676
<span class="flex-align-center gap-1">
7777
<span>召回处理</span>
78-
<MkTooltip placement="right" content="用户提问时,命中文档下的分段时按照设置的方式进行处理。">
78+
<MkTooltip placement="right" content="用户提问时,召回的分段按照设置进行处理。">
7979
<MkIcon name="icon_info_outlined" class="text-N600!" />
8080
</MkTooltip>
8181
</span>

‎ui/src/views/knowledge/components/ButtonCreateKnowledge.vue‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { KNOWLEDGE_TYPE } from '@/api/enums'
66
import { useStore } from '@/stores'
77
import { MsgSuccess } from '@/utils/message'
88
import CreateBaseKnowledgeDialog from '../create-knowledge/BaseKnowledgeDialog.vue'
9-
import CreateWebKnowledgeDialog from '../create-knowledge/WebKnowledgeDialog.vue'
9+
import CreateWebKnowledgeDrawer from '../create-knowledge/WebKnowledgeDrawer.vue'
1010
import CreateLarkKnowledgeDialog from '../create-knowledge/LarkKnowledgeDialog.vue'
1111
import CreateWorkflowKnowledgeDialog from '../create-knowledge/WorkflowKnowledgeDialog.vue'
1212
@@ -48,7 +48,7 @@ function handleVisibleChange(visible: boolean) {
4848
4949
/* 各类型知识库创建 */
5050
const createBaseKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateBaseKnowledgeDialog>>('createBaseKnowledgeDialogRef')
51-
const createWebKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateWebKnowledgeDialog>>('createWebKnowledgeDialogRef')
51+
const createWebKnowledgeDrawerRef = useTemplateRef<InstanceType<typeof CreateWebKnowledgeDrawer>>('createWebKnowledgeDrawerRef')
5252
const createLarkKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateLarkKnowledgeDialog>>('createLarkKnowledgeDialogRef')
5353
5454
const createWorkflowKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateWorkflowKnowledgeDialog>>('createWorkflowKnowledgeDialogRef')
@@ -58,7 +58,7 @@ function handleCreateBaseKnowledge() {
5858
}
5959
6060
function handleCreateWebKnowledge() {
61-
createWebKnowledgeDialogRef.value?.open()
61+
createWebKnowledgeDrawerRef.value?.open()
6262
}
6363
6464
function handleCreateLarkKnowledge() {
@@ -165,7 +165,7 @@ function handleImportCreate(file: UploadFile) {
165165
</MkDropdown>
166166

167167
<CreateBaseKnowledgeDialog ref="createBaseKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
168-
<CreateWebKnowledgeDialog ref="createWebKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
168+
<CreateWebKnowledgeDrawer ref="createWebKnowledgeDrawerRef" :folder-id="folderId" @refresh="emit('refresh')" />
169169
<CreateLarkKnowledgeDialog ref="createLarkKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
170170
<CreateWorkflowKnowledgeDialog ref="createWorkflowKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
171171
</template>

‎ui/src/views/knowledge/create-knowledge/WebKnowledgeDialog.vue‎

Lines changed: 0 additions & 110 deletions
This file was deleted.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<script setup lang="ts">
2+
import { ref, useTemplateRef, reactive } from 'vue'
3+
import { KNOWLEDGE_TYPE_MAP } from '@/constants/knowledge'
4+
import { useRoute, useRouter } from 'vue-router'
5+
import type { FormInstance, FormRules } from 'element-plus'
6+
import KnowledgeApi from '@/api/admin/workspace/knowledge/knowledge'
7+
import { KNOWLEDGE_TYPE } from '@/api/enums'
8+
import { useStore } from '@/stores'
9+
import { MsgSuccess } from '@/utils/message'
10+
import DocumentStrategyForm from './components/DocumentStrategyForm.vue'
11+
import KnowledgeBaseForm from './components/KnowledgeBaseForm.vue'
12+
13+
defineOptions({ name: 'CreateWebKnowledgeDrawer' })
14+
const props = defineProps<{ folderId: string }>()
15+
const emit = defineEmits<{ refresh: [] }>()
16+
const { auth } = useStore()
17+
const route = useRoute()
18+
const router = useRouter()
19+
20+
/* 创建表单 */
21+
const baseFormRef = useTemplateRef<InstanceType<typeof KnowledgeBaseForm>>('baseFormRef')
22+
const drawerVisible = ref(false)
23+
const loading = ref(false)
24+
const activeStep = ref(0)
25+
const strategyFormRef = useTemplateRef<InstanceType<typeof DocumentStrategyForm>>('strategyFormRef')
26+
const knowledgeFormRef = ref<FormInstance>()
27+
const knowledgeForm = reactive({ source_url: '', selector: '' })
28+
const knowledgeFormRules: FormRules<typeof knowledgeForm> = {
29+
source_url: [{ required: true, whitespace: true, message: '请输入 Web 根地址', trigger: 'blur' }],
30+
}
31+
32+
function resetData() {
33+
baseFormRef.value?.reset()
34+
Object.assign(knowledgeForm, { source_url: '', selector: '' })
35+
knowledgeFormRef.value?.clearValidate()
36+
loading.value = false
37+
activeStep.value = 0
38+
}
39+
40+
function open() {
41+
drawerVisible.value = true
42+
}
43+
44+
function handleNext() {
45+
if (loading.value) return
46+
loading.value = true
47+
return Promise.all([baseFormRef.value?.validate(), knowledgeFormRef.value?.validate().catch(() => false)])
48+
.then((results) => {
49+
if (results.every(Boolean)) activeStep.value = 1
50+
})
51+
.finally(() => {
52+
loading.value = false
53+
})
54+
}
55+
56+
/* 校验并创建,成功后刷新资料并进入文档列表 */
57+
function submit() {
58+
if (loading.value) return
59+
loading.value = true
60+
return Promise.all([baseFormRef.value?.validate(), knowledgeFormRef.value?.validate().catch(() => false), strategyFormRef.value?.validate()])
61+
.then((validationResults) => {
62+
if (!validationResults.every(Boolean) || !baseFormRef.value) return
63+
const baseForm = baseFormRef.value.form
64+
return KnowledgeApi.postWebKnowledge({
65+
name: baseForm.name.trim(),
66+
desc: baseForm.desc.trim(),
67+
embedding_model_id: baseForm.embedding_model_id,
68+
folder_id: props.folderId,
69+
type: KNOWLEDGE_TYPE.WEB,
70+
source_url: knowledgeForm.source_url.trim(),
71+
selector: knowledgeForm.selector.trim(),
72+
doc_strategy: strategyFormRef.value?.getStrategy(),
73+
}).then((knowledge) => {
74+
return auth.loadAuthBaseProfile().then(() => {
75+
MsgSuccess('创建成功')
76+
drawerVisible.value = false
77+
emit('refresh')
78+
return router.push({
79+
name: 'workspace-knowledge-document-list',
80+
params: { knowledgeId: knowledge.id, type: KNOWLEDGE_TYPE_MAP[knowledge.type], workspaceId: route.params.workspaceId },
81+
})
82+
})
83+
})
84+
})
85+
.finally(() => {
86+
loading.value = false
87+
})
88+
}
89+
90+
defineExpose({ open })
91+
</script>
92+
93+
<template>
94+
<MkDrawer v-model="drawerVisible" direction="btt" content-class="h-full p-0!" @closed="resetData">
95+
<template #header>
96+
<div class="flex w-full">
97+
<h4>创建 Web 知识库</h4>
98+
<el-steps :active="activeStep" finish-status="success" class="absolute-center w-85!">
99+
<el-step title="基本信息" />
100+
<el-step title="文档处理策略" />
101+
</el-steps>
102+
</div>
103+
</template>
104+
<MkViewLayout title="">
105+
<template #default="{ Footer }">
106+
<div class="mx-auto w-full max-w-200 pt-6">
107+
<section v-show="activeStep === 0">
108+
<h4 class="mb-5 border-l-2 border-primary pl-2">基本信息</h4>
109+
<KnowledgeBaseForm ref="baseFormRef" :disabled="loading" />
110+
<el-form
111+
class="mt-4"
112+
ref="knowledgeFormRef"
113+
:model="knowledgeForm"
114+
:rules="knowledgeFormRules"
115+
:disabled="loading"
116+
label-position="top"
117+
require-asterisk-position="right"
118+
@submit.prevent
119+
>
120+
<el-form-item label="Web 根地址" prop="source_url">
121+
<el-input
122+
v-model="knowledgeForm.source_url"
123+
placeholder="请输入 Web 根地址"
124+
@blur="knowledgeForm.source_url = knowledgeForm.source_url.trim()"
125+
/>
126+
</el-form-item>
127+
<el-form-item label="选择器" prop="selector">
128+
<el-input
129+
v-model="knowledgeForm.selector"
130+
placeholder="默认为 body,可输入 .classname/#idname/tagname"
131+
@blur="knowledgeForm.selector = knowledgeForm.selector.trim()"
132+
/>
133+
</el-form-item>
134+
</el-form>
135+
</section>
136+
<section v-show="activeStep === 1">
137+
<h4 class="mb-5 mk-title-decoration">文档处理策略</h4>
138+
<DocumentStrategyForm ref="strategyFormRef" />
139+
</section>
140+
</div>
141+
<component :is="Footer">
142+
<!-- 取消创建 -->
143+
<el-button plain :disabled="loading" @click="drawerVisible = false">取消</el-button>
144+
<!-- 返回基本信息 -->
145+
<el-button v-if="activeStep === 1" plain :disabled="loading" @click="activeStep = 0">上一步</el-button>
146+
<!-- 校验基本信息并进入策略配置 -->
147+
<el-button v-if="activeStep === 0" type="primary" :loading="loading" @click="handleNext">下一步</el-button>
148+
<!-- 创建知识库 -->
149+
<el-button v-else type="primary" :loading="loading" @click="submit">创建</el-button>
150+
</component>
151+
</template>
152+
</MkViewLayout>
153+
</MkDrawer>
154+
</template>

0 commit comments

Comments
 (0)