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
3 changes: 3 additions & 0 deletions ui/src/api/API_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,6 @@ Workspace 共享知识库详情由 `resourceScope: 'workspace-shared'` 选择上
清除策略通过 PUT `batch_clean_time` 提交当前智能体的单元素 `id_list`、`clean_time`、
`file_clean_time`,避免调用通用应用编辑流程;成功后页面刷新应用详情。
聊天记录、标注、添加知识库接口保留在同一 API 文件,尚未接入本次日志列表页面。

Web 知识库创建的 `WebKnowledgeCreatePayload.doc_strategy` 使用公共 `DocumentStrategy` 类型,
包含 `split`、`visual` 和 `index`,字段与后端文档处理策略协议一致。
8 changes: 8 additions & 0 deletions ui/src/api/types/knowledge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,18 @@ export interface KnowledgeCreatePayload {
type: KnowledgeType
}

/** Web 文档分段、视觉处理和索引策略。 */
export interface DocumentStrategy {
split: { mode: 'smart' | 'advanced'; patterns: string[] | null; min_length: number; max_length: number; child_length: number; auto_clean: boolean }
visual: { enabled: boolean; strategy: 'model' | 'tool'; model_id: string | null; tool_id: string | null }
index: { title_as_question: boolean }
}

/** 创建 Web 知识库的站点配置。 */
export interface WebKnowledgeCreatePayload extends KnowledgeCreatePayload {
source_url: string
selector: string
doc_strategy?: DocumentStrategy
}

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

`ButtonCreateKnowledge` 内聚四类创建弹窗 Ref 和打开动作,列表页传入目标 `folderId`,通过
`WebKnowledgeDrawer` 使用底部两步抽屉,基本信息校验后进入文档处理策略,支持返回修改。
`create-knowledge/components/DocumentStrategyForm.vue` 维护分段、视觉增强和标题问题索引,
通过 `doc_strategy` 提交;智能分段默认策略与后端一致,高级分段使用与触发器类型相同的卡片外壳,
在选中卡片内展开配置,默认选择一级至四级标题标识、500–4096 分段长度、256 子块长度并开启自动清洗。
分段标识支持自定义正则表达式,留空使用后端默认规则;启用视觉增强后必须选择模型或工具。

`ButtonCreateKnowledge` 内聚四类创建浮层 Ref 和打开动作,列表页传入目标 `folderId`,通过
`refresh` 刷新列表。入口支持 `trigger` 插槽替换默认创建按钮,下拉使用 `persistent`。
各弹窗接收 `folderId`,通过 `open()` 打开;工作流额外接受可选的商店模板。共用的
各创建浮层接收 `folderId`,通过 `open()` 打开;工作流额外接受可选的商店模板。共用的
`KnowledgeBaseForm` 负责名称、描述、Embedding 模型必填校验以及工作空间和共享模型查询,
根据 `isSystemSharedResource()` 选择 System 共享 Model API 或 Workspace Model API,
通过 `getModelListWithShared({ model_type: 'EMBEDDING' })` 一次加载模型选项,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ defineExpose({ open, close })
<template #label>
<span class="flex-align-center gap-1">
<span>召回处理</span>
<MkTooltip placement="right" content="用户提问时,命中文档下的分段时按照设置的方式进行处理。">
<MkTooltip placement="right" content="用户提问时,召回的分段按照设置进行处理。">
<MkIcon name="icon_info_outlined" class="text-N600!" />
</MkTooltip>
</span>
Expand Down
8 changes: 4 additions & 4 deletions ui/src/views/knowledge/components/ButtonCreateKnowledge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { KNOWLEDGE_TYPE } from '@/api/enums'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
import CreateBaseKnowledgeDialog from '../create-knowledge/BaseKnowledgeDialog.vue'
import CreateWebKnowledgeDialog from '../create-knowledge/WebKnowledgeDialog.vue'
import CreateWebKnowledgeDrawer from '../create-knowledge/WebKnowledgeDrawer.vue'
import CreateLarkKnowledgeDialog from '../create-knowledge/LarkKnowledgeDialog.vue'
import CreateWorkflowKnowledgeDialog from '../create-knowledge/WorkflowKnowledgeDialog.vue'

Expand Down Expand Up @@ -48,7 +48,7 @@ function handleVisibleChange(visible: boolean) {

/* 各类型知识库创建 */
const createBaseKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateBaseKnowledgeDialog>>('createBaseKnowledgeDialogRef')
const createWebKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateWebKnowledgeDialog>>('createWebKnowledgeDialogRef')
const createWebKnowledgeDrawerRef = useTemplateRef<InstanceType<typeof CreateWebKnowledgeDrawer>>('createWebKnowledgeDrawerRef')
const createLarkKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateLarkKnowledgeDialog>>('createLarkKnowledgeDialogRef')

const createWorkflowKnowledgeDialogRef = useTemplateRef<InstanceType<typeof CreateWorkflowKnowledgeDialog>>('createWorkflowKnowledgeDialogRef')
Expand All @@ -58,7 +58,7 @@ function handleCreateBaseKnowledge() {
}

function handleCreateWebKnowledge() {
createWebKnowledgeDialogRef.value?.open()
createWebKnowledgeDrawerRef.value?.open()
}

function handleCreateLarkKnowledge() {
Expand Down Expand Up @@ -165,7 +165,7 @@ function handleImportCreate(file: UploadFile) {
</MkDropdown>

<CreateBaseKnowledgeDialog ref="createBaseKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
<CreateWebKnowledgeDialog ref="createWebKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
<CreateWebKnowledgeDrawer ref="createWebKnowledgeDrawerRef" :folder-id="folderId" @refresh="emit('refresh')" />
<CreateLarkKnowledgeDialog ref="createLarkKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
<CreateWorkflowKnowledgeDialog ref="createWorkflowKnowledgeDialogRef" :folder-id="folderId" @refresh="emit('refresh')" />
</template>
110 changes: 0 additions & 110 deletions ui/src/views/knowledge/create-knowledge/WebKnowledgeDialog.vue

This file was deleted.

154 changes: 154 additions & 0 deletions ui/src/views/knowledge/create-knowledge/WebKnowledgeDrawer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<script setup lang="ts">
import { ref, useTemplateRef, reactive } from 'vue'
import { KNOWLEDGE_TYPE_MAP } from '@/constants/knowledge'
import { useRoute, useRouter } from 'vue-router'
import type { FormInstance, FormRules } from 'element-plus'
import KnowledgeApi from '@/api/admin/workspace/knowledge/knowledge'
import { KNOWLEDGE_TYPE } from '@/api/enums'
import { useStore } from '@/stores'
import { MsgSuccess } from '@/utils/message'
import DocumentStrategyForm from './components/DocumentStrategyForm.vue'
import KnowledgeBaseForm from './components/KnowledgeBaseForm.vue'

defineOptions({ name: 'CreateWebKnowledgeDrawer' })
const props = defineProps<{ folderId: string }>()
const emit = defineEmits<{ refresh: [] }>()
const { auth } = useStore()
const route = useRoute()
const router = useRouter()

/* 创建表单 */
const baseFormRef = useTemplateRef<InstanceType<typeof KnowledgeBaseForm>>('baseFormRef')
const drawerVisible = ref(false)
const loading = ref(false)
const activeStep = ref(0)
const strategyFormRef = useTemplateRef<InstanceType<typeof DocumentStrategyForm>>('strategyFormRef')
const knowledgeFormRef = ref<FormInstance>()
const knowledgeForm = reactive({ source_url: '', selector: '' })
const knowledgeFormRules: FormRules<typeof knowledgeForm> = {
source_url: [{ required: true, whitespace: true, message: '请输入 Web 根地址', trigger: 'blur' }],
}

function resetData() {
baseFormRef.value?.reset()
Object.assign(knowledgeForm, { source_url: '', selector: '' })
knowledgeFormRef.value?.clearValidate()
loading.value = false
activeStep.value = 0
}

function open() {
drawerVisible.value = true
}

function handleNext() {
if (loading.value) return
loading.value = true
return Promise.all([baseFormRef.value?.validate(), knowledgeFormRef.value?.validate().catch(() => false)])
.then((results) => {
if (results.every(Boolean)) activeStep.value = 1
})
.finally(() => {
loading.value = false
})
}

/* 校验并创建,成功后刷新资料并进入文档列表 */
function submit() {
if (loading.value) return
loading.value = true
return Promise.all([baseFormRef.value?.validate(), knowledgeFormRef.value?.validate().catch(() => false), strategyFormRef.value?.validate()])
.then((validationResults) => {
if (!validationResults.every(Boolean) || !baseFormRef.value) return
const baseForm = baseFormRef.value.form
return KnowledgeApi.postWebKnowledge({
name: baseForm.name.trim(),
desc: baseForm.desc.trim(),
embedding_model_id: baseForm.embedding_model_id,
folder_id: props.folderId,
type: KNOWLEDGE_TYPE.WEB,
source_url: knowledgeForm.source_url.trim(),
selector: knowledgeForm.selector.trim(),
doc_strategy: strategyFormRef.value?.getStrategy(),
}).then((knowledge) => {
return auth.loadAuthBaseProfile().then(() => {
MsgSuccess('创建成功')
drawerVisible.value = false
emit('refresh')
return router.push({
name: 'workspace-knowledge-document-list',
params: { knowledgeId: knowledge.id, type: KNOWLEDGE_TYPE_MAP[knowledge.type], workspaceId: route.params.workspaceId },
})
})
})
})
.finally(() => {
loading.value = false
})
}

defineExpose({ open })
</script>

<template>
<MkDrawer v-model="drawerVisible" direction="btt" content-class="h-full p-0!" @closed="resetData">
<template #header>
<div class="flex w-full">
<h4>创建 Web 知识库</h4>
<el-steps :active="activeStep" finish-status="success" class="absolute-center w-85!">
<el-step title="基本信息" />
<el-step title="文档处理策略" />
</el-steps>
</div>
</template>
<MkViewLayout title="">
<template #default="{ Footer }">
<div class="mx-auto w-full max-w-200 pt-6">
<section v-show="activeStep === 0">
<h4 class="mb-5 border-l-2 border-primary pl-2">基本信息</h4>
<KnowledgeBaseForm ref="baseFormRef" :disabled="loading" />
<el-form
class="mt-4"
ref="knowledgeFormRef"
:model="knowledgeForm"
:rules="knowledgeFormRules"
:disabled="loading"
label-position="top"
require-asterisk-position="right"
@submit.prevent
>
<el-form-item label="Web 根地址" prop="source_url">
<el-input
v-model="knowledgeForm.source_url"
placeholder="请输入 Web 根地址"
@blur="knowledgeForm.source_url = knowledgeForm.source_url.trim()"
/>
</el-form-item>
<el-form-item label="选择器" prop="selector">
<el-input
v-model="knowledgeForm.selector"
placeholder="默认为 body,可输入 .classname/#idname/tagname"
@blur="knowledgeForm.selector = knowledgeForm.selector.trim()"
/>
</el-form-item>
</el-form>
</section>
<section v-show="activeStep === 1">
<h4 class="mb-5 mk-title-decoration">文档处理策略</h4>
<DocumentStrategyForm ref="strategyFormRef" />
</section>
</div>
<component :is="Footer">
<!-- 取消创建 -->
<el-button plain :disabled="loading" @click="drawerVisible = false">取消</el-button>
<!-- 返回基本信息 -->
<el-button v-if="activeStep === 1" plain :disabled="loading" @click="activeStep = 0">上一步</el-button>
<!-- 校验基本信息并进入策略配置 -->
<el-button v-if="activeStep === 0" type="primary" :loading="loading" @click="handleNext">下一步</el-button>
<!-- 创建知识库 -->
<el-button v-else type="primary" :loading="loading" @click="submit">创建</el-button>
</component>
</template>
</MkViewLayout>
</MkDrawer>
</template>
Loading
Loading