【功能新增】AI:知识库文档上传:60%,SplitStep 完成度更高

This commit is contained in:
YunaiV 2025-03-01 10:07:44 +08:00
parent da91896419
commit de41b6cdba
7 changed files with 130 additions and 97 deletions

View File

@ -24,11 +24,16 @@ export const KnowledgeDocumentApi = {
return await request.get({ url: `/ai/knowledge/document/get?id=` + id }) return await request.get({ url: `/ai/knowledge/document/get?id=` + id })
}, },
// 新增知识库文档 // 新增知识库文档(单个)
createKnowledgeDocument: async (data: KnowledgeDocumentVO) => { createKnowledgeDocument: async (data: KnowledgeDocumentVO) => {
return await request.post({ url: `/ai/knowledge/document/create`, data }) return await request.post({ url: `/ai/knowledge/document/create`, data })
}, },
// 新增知识库文档(批量)
createKnowledgeDocumentList: async (data: any) => {
return await request.post({ url: `/ai/knowledge/document/create-list`, data })
},
// // 修改AI 知识库文档 // // 修改AI 知识库文档
// updateKnowledgeDocument: async (data: KnowledgeDocumentVO) => { // updateKnowledgeDocument: async (data: KnowledgeDocumentVO) => {
// return await request.put({ url: `/ai/knowledge/document/update`, data }) // return await request.put({ url: `/ai/knowledge/document/update`, data })

View File

@ -633,7 +633,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
}, },
{ {
path: 'console/knowledge/document/create', path: 'console/knowledge/document/create',
component: () => import('@/views/ai/knowledge/document/create/index.vue'), component: () => import('@/views/ai/knowledge/document/form/index.vue'),
name: 'AiKnowledgeDocumentCreate', name: 'AiKnowledgeDocumentCreate',
meta: { meta: {
title: '创建文档', title: '创建文档',
@ -642,6 +642,18 @@ const remainingRouter: AppRouteRecordRaw[] = [
hidden: true, hidden: true,
activeMenu: '/ai/console/knowledge/document' activeMenu: '/ai/console/knowledge/document'
} }
},
{
path: 'console/knowledge/document/update',
component: () => import('@/views/ai/knowledge/document/form/index.vue'),
name: 'AiKnowledgeDocumentUpdate',
meta: {
title: '修改文档',
icon: 'ep:edit',
noCache: true,
hidden: true,
activeMenu: '/ai/console/knowledge/document'
}
} }
] ]
}, },

View File

@ -78,17 +78,24 @@
<!-- 添加底部按钮 --> <!-- 添加底部按钮 -->
<div class="mt-20px flex justify-between"> <div class="mt-20px flex justify-between">
<el-button @click="handlePrevStep">上一步</el-button> <div>
<el-button type="primary" @click="handleNextStep">保存并处理</el-button> <el-button v-if="!modelData.id" @click="handlePrevStep">上一步</el-button>
</div>
<div>
<el-button type="primary" :loading="submitLoading" @click="handleSave">
保存并处理
</el-button>
</div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { PropType, ref, computed, inject, onMounted, getCurrentInstance } from 'vue' import { computed, getCurrentInstance, inject, onMounted, PropType, ref } from 'vue'
import { Icon } from '@/components/Icon' import { Icon } from '@/components/Icon'
import { KnowledgeSegmentApi } from '@/api/ai/knowledge/segment' import { KnowledgeSegmentApi } from '@/api/ai/knowledge/segment'
import { useMessage } from '@/hooks/web/useMessage' import { useMessage } from '@/hooks/web/useMessage'
import { KnowledgeDocumentApi } from '@/api/ai/knowledge/document'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -108,6 +115,7 @@ const modelData = computed({
const splitLoading = ref(false) // const splitLoading = ref(false) //
const currentFile = ref<any>(null) // const currentFile = ref<any>(null) //
const submitLoading = ref(false) //
/** 选择文件 */ /** 选择文件 */
const selectFile = async (index: number) => { const selectFile = async (index: number) => {
@ -124,8 +132,11 @@ const splitContent = async (file: any) => {
splitLoading.value = true splitLoading.value = true
try { try {
const data = await KnowledgeSegmentApi.splitContent(file.url, modelData.value.segmentMaxTokens) // Token // Token
file.segments = data file.segments = await KnowledgeSegmentApi.splitContent(
file.url,
modelData.value.segmentMaxTokens
)
} catch (error) { } catch (error) {
console.error('获取分段内容失败:', file, error) console.error('获取分段内容失败:', file, error)
message.error('获取分段内容失败') message.error('获取分段内容失败')
@ -158,22 +169,46 @@ const handlePrevStep = () => {
} }
} }
/** 下一步按钮处理 */ /** 保存操作 */
const handleNextStep = () => { const handleSave = async () => {
const parentEl = parent || getCurrentInstance()?.parent //
if (parentEl && typeof parentEl.exposed?.goToNextStep === 'function') { if (!currentFile?.value?.segments || currentFile.value.segments.length === 0) {
parentEl.exposed.goToNextStep() message.warning('请先预览分段内容')
} return
}
/** 组件激活时自动调用分段接口 TODO 芋艿:需要看下 */
const activated = async () => {
if (!currentFile.value && modelData.value.list && modelData.value.list.length > 0) {
currentFile.value = modelData.value.list[0] //
} }
if (currentFile.value) { //
await splitContent(currentFile.value) // submitLoading.value = true
try {
if (modelData.value.id) {
//
modelData.value.ids = await KnowledgeDocumentApi.createKnowledgeDocumentList({
id: modelData.value.id,
segmentMaxTokens: modelData.value.segmentMaxTokens
})
} else {
//
modelData.value.ids = await KnowledgeDocumentApi.createKnowledgeDocumentList({
knowledgeId: modelData.value.knowledgeId,
segmentMaxTokens: modelData.value.segmentMaxTokens,
list: modelData.value.list.map((item: any) => ({
name: item.name,
url: item.url
}))
})
}
//
const parentEl = parent || getCurrentInstance()?.parent
if (parentEl && typeof parentEl.exposed?.goToNextStep === 'function') {
parentEl.exposed.goToNextStep()
}
} catch (error: any) {
console.error('保存失败:', modelData.value, error)
message.error(error.message)
} finally {
//
submitLoading.value = false
} }
} }

View File

@ -8,8 +8,8 @@
<!-- 左侧标题 --> <!-- 左侧标题 -->
<div class="w-200px flex items-center overflow-hidden"> <div class="w-200px flex items-center overflow-hidden">
<Icon icon="ep:arrow-left" class="cursor-pointer flex-shrink-0" @click="handleBack" /> <Icon icon="ep:arrow-left" class="cursor-pointer flex-shrink-0" @click="handleBack" />
<span class="ml-10px text-16px truncate" :title="formData.name || '创建知识库文档'"> <span class="ml-10px text-16px truncate">
{{ formData.name || '创建知识库文档' }} {{ formData.id ? '编辑知识库文档' : '创建知识库文档' }}
</span> </span>
</div> </div>
@ -68,29 +68,25 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useMessage } from '@/hooks/web/useMessage'
import { useTagsViewStore } from '@/store/modules/tagsView' import { useTagsViewStore } from '@/store/modules/tagsView'
import UploadStep from './UploadStep.vue' import UploadStep from './UploadStep.vue'
import SplitStep from './SplitStep.vue' import SplitStep from './SplitStep.vue'
import ProcessStep from './ProcessStep.vue' import ProcessStep from './ProcessStep.vue'
import { KnowledgeDocumentApi } from '@/api/ai/knowledge/document'
const router = useRouter()
const { delView } = useTagsViewStore() // const { delView } = useTagsViewStore() //
const route = useRoute() const route = useRoute() //
const message = useMessage() const router = useRouter() //
// //
const uploadDocumentRef = ref() const uploadDocumentRef = ref()
const documentSegmentRef = ref() const documentSegmentRef = ref()
const processCompleteRef = ref() const processCompleteRef = ref()
const currentStep = ref(0) // const currentStep = ref(0) //
const steps = [{ title: '上传文档' }, { title: '文档分段' }, { title: '处理并完成' }] const steps = [{ title: '上传文档' }, { title: '文档分段' }, { title: '处理并完成' }]
//
const formData = ref({ const formData = ref({
knowlegeId: undefined, // knowledgeId: undefined, //
id: undefined, // (documentId) id: undefined, // (documentId)
segmentMaxTokens: 500, // token segmentMaxTokens: 500, // token
list: [] as Array<{ list: [] as Array<{
name: string name: string
@ -101,17 +97,35 @@ const formData = ref({
tokens?: number tokens?: number
}> }>
}>, // }>, //
documentIds: [], // / ProcessStep
status: 0 // 0: 稿, 1: , 2: status: 0 // 0: 稿, 1: , 2:
}) }) //
provide('parent', getCurrentInstance()) // parent 使
/** 初始化数据 */ /** 初始化数据 */
const initData = async () => { const initData = async () => {
// TODO @knowlegeId // ID
const documentId = route.params.id as string if (route.query.knowledgeId) {
formData.value.knowledgeId = route.query.knowledgeId as any
}
// ID
const documentId = route.query.id
if (documentId) { if (documentId) {
// //
// API formData.value.id = documentId as any
// formData.value = await DocumentApi.getDocument(documentId) const document = await KnowledgeDocumentApi.getKnowledgeDocument(documentId as any)
formData.value.segmentMaxTokens = document.segmentMaxTokens
formData.value.list = [
{
name: document.name,
url: document.url,
segments: []
}
]
//
goToNextStep()
} }
// TODO @便 // TODO @便
@ -141,52 +155,12 @@ const goToPrevStep = () => {
} }
} }
/** 保存操作 */
const handleSave = async () => {
try {
//
const documentData = {
...formData.value
}
if (formData.value.id) {
//
// await DocumentApi.updateDocument(documentData)
message.success('修改成功')
} else {
//
// formData.value.id = await DocumentApi.createDocument(documentData)
message.success('新增成功')
try {
await message.confirm('创建文档成功,是否继续编辑?')
//
await nextTick()
//
delView(unref(router.currentRoute))
//
await router.push({
name: 'AiKnowledgeDocumentUpdate',
params: { id: formData.value.id }
})
} catch {
//
delView(unref(router.currentRoute))
//
await router.push({ name: 'AiKnowledgeDocument' })
}
}
} catch (error: any) {
console.error('保存失败:', error)
message.warning(error.message || '请完善所有步骤的必填信息')
}
}
/** 返回列表页 */ /** 返回列表页 */
const handleBack = () => { const handleBack = () => {
// //
delView(unref(router.currentRoute)) delView(unref(router.currentRoute))
// //
router.push({ name: 'AiKnowledgeDocument' }) router.push({ name: 'AiKnowledgeDocument', query: { knowledgeId: formData.value.knowledgeId } })
} }
/** 初始化 */ /** 初始化 */
@ -194,10 +168,7 @@ onMounted(async () => {
await initData() await initData()
}) })
// parent使 /** 添加组件卸载前的清理代码 */
provide('parent', getCurrentInstance())
//
onBeforeUnmount(() => { onBeforeUnmount(() => {
// //
uploadDocumentRef.value = null uploadDocumentRef.value = null
@ -205,11 +176,10 @@ onBeforeUnmount(() => {
processCompleteRef.value = null processCompleteRef.value = null
}) })
// 使 /** 暴露方法给子组件使用 */
defineExpose({ defineExpose({
goToNextStep, goToNextStep,
goToPrevStep, goToPrevStep
handleSave
}) })
</script> </script>

View File

@ -68,7 +68,7 @@
<el-button <el-button
link link
type="primary" type="primary"
@click="openForm('update', scope.row.id)" @click="handleUpdate(scope.row.id)"
v-hasPermi="['ai:knowledge:update']" v-hasPermi="['ai:knowledge:update']"
> >
编辑 编辑
@ -148,15 +148,20 @@ const resetQuery = () => {
handleQuery() handleQuery()
} }
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 跳转到创建文档页面 */ /** 跳转到创建文档页面 */
const handleCreate = () => { const handleCreate = () => {
router.push({ name: 'AiKnowledgeDocumentCreate' }) router.push({
name: 'AiKnowledgeDocumentCreate',
query: { knowledgeId: queryParams.knowledgeId }
})
}
/** 跳转到更新文档页面 */
const handleUpdate = (id: number) => {
router.push({
name: 'AiKnowledgeDocumentUpdate',
query: { id, knowledgeId: queryParams.knowledgeId }
})
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
@ -174,10 +179,16 @@ const handleDelete = async (id: number) => {
/** 初始化 **/ /** 初始化 **/
onMounted(() => { onMounted(() => {
// ID // ID
if (route.query.knowledgeId) { if (!route.query.knowledgeId) {
queryParams.knowledgeId = route.query.knowledgeId as any message.error('知识库 ID 不存在,无法查看文档列表')
//
router.push({ name: 'AiKnowledge' })
return
} }
// ID
queryParams.knowledgeId = route.query.knowledgeId as any
getList() getList()
}) })
</script> </script>