feat(knowledge): 添加知识拆分预览功能

- 新增 SplitPreview 组件用于展示拆分预览结果
- 在 split 配置中集成预览功能,实现拆分和预览一体化
- 优化知识创建流程,支持预览确认后继续上传
-重构 API 调用,增加拆分结果预览接口
This commit is contained in:
du.meimei
2025-04-15 14:31:00 +08:00
parent 13205a1d84
commit 9e940180de
9 changed files with 306 additions and 58 deletions

View File

@@ -128,7 +128,14 @@ export function execSplit(data) {
data
})
}
// 拆分结果预览
export function splitResultPreview(params) {
return request({
url: getUrl(`/datasetDocumentEx/split/preview`),
method: 'get',
params: params
})
}
// 题词-新增
export function addRuleExtract(data) {
return request({

View File

@@ -117,6 +117,13 @@ export default {
},
uploadFiled() {
if (!this.filed) {
this.$message({
type: 'error',
message: '请上传文件'
})
return
}
let formData = new FormData()
formData.append('file', this.filed)
formData.append('datasetId', this.form.datasetId)

View File

@@ -1,23 +1,25 @@
<template>
<div>
<!-- 添加预处理结果预览对话框 -->
<el-drawer :title="currentId ? (isPreview? '预览' : '编辑')+'知识拆分规则' : '新增知识拆分规则'"
:visible.sync="dialogVisible" size="40%" :before-close="handleClose">
<el-drawer
:title="currentId ? (isPreview ? '预览' : '编辑') + '知识拆分规则' : '新增知识拆分规则'"
:visible.sync="dialogVisible"
size="40%"
:before-close="handleClose"
>
<div class="content">
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="100px">
<div class="form-section">
<div class="section-title">基本信息</div>
<el-row :gutter="20">
<el-col :span="isPreview? 24 : 12">
<el-col :span="isPreview ? 24 : 12">
<el-form-item label="规则名称" prop="ruleName">
<el-input :disabled="isPreview" v-model="form.ruleName" placeholder="请输入规则名称" />
</el-form-item>
</el-col>
<el-col v-if="!isPreview" :span="12">
<el-select v-model="searchValue" @change="queryExistingRules" filterable clearable
placeholder="查询并导入现有规则">
<el-option v-for="item in ruleList" :key="item.id" :label="item.ruleName"
:value="item.id" />
<el-select v-model="searchValue" @change="queryExistingRules" filterable clearable placeholder="查询并导入现有规则">
<el-option v-for="item in ruleList" :key="item.id" :label="item.ruleName" :value="item.id" />
</el-select>
</el-col>
</el-row>
@@ -27,24 +29,20 @@
<div class="form-section" v-for="(rule, index) in form.ruleList" :key="index">
<div class="section-title">
拆分规则 {{ index + 1 }}
<el-button v-if="!isPreview && form.ruleList.length > 1" type="text" class="delete-btn"
@click="removeRule(index)">
<el-button v-if="!isPreview && form.ruleList.length > 1" type="text" class="delete-btn" @click="removeRule(index)">
<i class="el-icon-delete"></i> 删除
</el-button>
</div>
<el-form-item label="样式" :prop="'ruleList.' + index + '.titleLevel'">
<el-select :disabled="isPreview" v-model="rule.titleLevel" placeholder="请选择标题级别">
<el-option v-for="item in options" :key="item.value" :label="item.label"
:value="item.value"></el-option>
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="关键词" :prop="'ruleList.' + index + '.ruleRegex'">
<el-input :disabled="isPreview" type="textarea" v-model="rule.ruleRegex"
placeholder="请输入规则表达式"></el-input>
<el-input :disabled="isPreview" type="textarea" v-model="rule.ruleRegex" placeholder="请输入规则表达式"></el-input>
</el-form-item>
<el-form-item label="备注" :prop="'ruleList.' + index + '.description'">
<el-input :disabled="isPreview" type="textarea" v-model="rule.description"
placeholder="请输入规则备注"></el-input>
<el-input :disabled="isPreview" type="textarea" v-model="rule.description" placeholder="请输入规则备注"></el-input>
</el-form-item>
<div class="text-right mb20">
<el-button v-if="!isPreview" type="primary" size="medium" @click="copyRule(index)">

View File

@@ -14,8 +14,7 @@
</el-row>
<!-- 其他表单项 -->
</el-form>
<r-table :columns="columns" :data="tableData" :isSelectOnly="true" :deletion="false"
@selection-change="getCheckData"></r-table>
<r-table :columns="columns" :data="tableData" :isSelectOnly="true" :deletion="false" @selection-change="getCheckData"></r-table>
<!-- 添加 AddRule 组件 -->
<add-rule ref="addRule" :ruleList="tableData" @getDataList="getDataList"></add-rule>
@@ -102,8 +101,7 @@ export default {
.then(_ => {
done()
})
.catch(_ => {
})
.catch(_ => {})
}
},
computed: {

View File

@@ -56,22 +56,38 @@
</ul>
<!-- 弹窗组件 -->
<custom-split-dialog class="active" ref="customTable"> </custom-split-dialog>
<!-- 添加预览组件 -->
<split-preview
:visible.sync="previewVisible"
:preview-data="previewData"
:is-auto-split="activeIndex === 0"
:loading="previewLoading"
@confirm="handlePreviewConfirm"
@handleReUpload="handleReUpload"
@handleClose="handleClose"
/>
</div>
</template>
<script>
import CustomSplitDialog from './CustomSplitDialog.vue'
import { execSplit } from '@/api/generatedApi'
import SplitPreview from './SplitPreview.vue' // 引入预览组件
import { execSplit, splitResultPreview } from '@/api/generatedApi'
export default {
name: 'splitConfig',
components: {
CustomSplitDialog
CustomSplitDialog,
SplitPreview // 注册预览组件
},
data() {
return {
dialogVisible: false,
activeIndex: 0,
previewVisible: false, // 控制预览组件显示
previewData: null, // 预览数据
previewLoading: false, // 预览加载状态
splitOptions: [
{
icon: 'el-icon-setting',
@@ -100,21 +116,119 @@ export default {
this.$refs.customTable.close()
}
},
// 构建API请求参数
buildExecSplitParams(documentId) {
const params = {
documentId: documentId,
beAuto: this.activeIndex === 0
}
if (!params.beAuto && this.$refs.customTable.ruleId) {
params.rulesId = this.$refs.customTable.ruleId
}
return params
},
// 执行拆分
async execSplitOperation(params) {
const res = await execSplit(params)
console.log('execSplit result:', res.content)
if (res.content.result !== '0') {
const errorMsg = '执行拆分失败: ' + (res.content.resultMessage || '未知错误')
this.$message.error(errorMsg)
throw new Error(errorMsg)
}
return res.content.content
},
// 获取拆分预览
async getPreviewOperation(documentId) {
const res = await splitResultPreview({ documentId })
console.log('splitResultPreview result:', res.content)
if (res.content.result !== '0') {
const errorMsg = '获取拆分预览失败: ' + (res.content.resultMessage || '未知错误')
this.$message.error(errorMsg)
throw new Error(errorMsg)
}
return res.content.content
},
// 处理成功响应
handleSuccessResponse(execSplitData, previewData) {
this.$message.success('拆分和预览获取成功!')
return {
success: true,
data: {
execSplitData,
previewData
}
}
},
// 处理错误
handleOperationError(error) {
const errorMsg = '操作失败: ' + (error.message || '未知网络错误')
this.$message.error(errorMsg)
return {
success: false,
message: errorMsg
}
},
// 显示预览
showPreview(previewData) {
this.previewData = previewData
console.log(previewData)
this.previewVisible = true
},
// 处理预览确认
handlePreviewConfirm() {
this.previewVisible = false
// 预览确认后的操作,例如进入下一步
this.$emit('previewConfirmed')
},
handleReUpload() {
this.previewVisible = false
// 预览确认后的操作,例如进入下一步
this.$emit('handleReUpload')
},
handleClose() {
this.previewVisible = false
},
// 修改主方法,添加预览功能
nextStep(documentId) {
return new Promise(async (resolve, reject) => {
let params = {
documentId: documentId,
beAuto: this.activeIndex === 0
try {
this.previewLoading = true
// 1. 构建参数
const params = this.buildExecSplitParams(documentId)
// 2. 执行拆分
const execSplitData = await this.execSplitOperation(params)
// 3. 获取预览
const previewData = await this.getPreviewOperation(documentId)
// 4. 显示预览组件
this.showPreview(previewData)
// 5. 处理成功响应
// const result = this.handleSuccessResponse(execSplitData, previewData)
// resolve(result)
} catch (error) {
// 6. 处理错误
const errorResult = this.handleOperationError(error)
reject(errorResult)
} finally {
this.previewLoading = false
}
if (params.beAuto === false) {
params.rulesId = this.$refs.customTable.ruleId
}
let res = await execSplit(params)
console.log(res.content)
resolve({
result: res.content.result,
data: res.content
})
})
}
},

View File

@@ -0,0 +1,103 @@
<template>
<div class="split-preview">
<el-dialog title="拆分结果预览" :visible.sync="visible" width="60%" :before-close="handleClose">
<div v-loading="loading" class="preview-content">
<template v-if="!loading && previewData">
<el-tree class="tree" :data="previewData" :props="defaultProps" default-expand-all @node-click="handleNodeClick"></el-tree>
</template>
<el-empty v-else-if="!loading && !previewData" description="暂无预览数据"></el-empty>
</div>
<span slot="footer" class="dialog-footer">
<el-button size="medium" @click="handleReUpload">重新上传</el-button>
<el-button size="medium" type="primary" @click="handleConfirm">完成</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'SplitPreview',
props: {
visible: {
type: Boolean,
default: false
},
previewData: {
type: Array
},
isAutoSplit: {
type: Boolean,
default: true
},
loading: {
type: Boolean,
default: false
}
},
data() {
return {
defaultProps: {
children: 'children',
label: 'paragraphTitle'
}
}
},
methods: {
handleNodeClick() {},
handleClose() {
this.$emit('update:visible', false)
},
handleReUpload() {
this.$emit('handleReUpload')
},
handleConfirm() {
this.$emit('confirm')
}
}
}
</script>
<style lang="scss" scoped>
.split-preview {
.preview-content {
min-height: 200px;
overflow-y: auto;
}
.preview-list {
.preview-item {
margin-bottom: 16px;
border: 1px solid #ebeef5;
border-radius: 4px;
.item-header {
padding: 8px 16px;
background-color: #f5f7fa;
border-bottom: 1px solid #ebeef5;
display: flex;
justify-content: space-between;
.item-title {
font-weight: bold;
}
.item-info {
color: #909399;
}
}
.item-content {
padding: 16px;
white-space: pre-wrap;
max-height: 200px;
overflow-y: auto;
}
}
}
.stat-info {
padding: 16px;
}
}
</style>

View File

@@ -13,7 +13,12 @@
<div class="components">
<step-preprocessing ref="stepPreProcessing" v-show="active === 0" @getForm="getForm" @getDocumentId="getDocumentId"></step-preprocessing>
<step-split-config ref="splitConfig" v-show="active === 1"></step-split-config>
<step-split-config
ref="splitConfig"
v-show="active === 1"
@previewConfirmed="handlePreviewConfirm"
@handleReUpload="handleReUpload"
></step-split-config>
<step-words ref="words" v-show="active === 2"></step-words>
</div>
</div>
@@ -81,7 +86,6 @@ export default {
},
async nextStep() {
if (this.active === 0) {
// this.active++
this.$refs.stepPreProcessing.uploadFiled()
} else if (this.active === 1) {
const res = await this.$refs.splitConfig.nextStep(this.documentId)
@@ -98,6 +102,14 @@ export default {
this.$message.success('创建成功')
}
}
},
// 预览完成
handlePreviewConfirm() {
this.active = 2
},
// 重新上传
handleReUpload() {
this.active = 0
}
},
created() {},

View File

@@ -141,8 +141,7 @@ export default {
},
watch: {
form: {
handler() {
},
handler() {},
deep: true
}
},
@@ -223,7 +222,6 @@ export default {
this.dialogOptions.currentComponent = 'AddRules'
}
}
}
</script>
@@ -284,8 +282,14 @@ export default {
<!-- 下方规则列表 -->
<div class="p20">
<r-table :columns="tableConfig.columns" :data="getCurrentTableData" :deletion="false" :total="tableConfig.total"
@currentChange="handleCurrentChange" @sizeChange="handleSizeChange" />
<r-table
:columns="tableConfig.columns"
:data="getCurrentTableData"
:deletion="false"
:total="tableConfig.total"
@currentChange="handleCurrentChange"
@sizeChange="handleSizeChange"
/>
</div>
</el-card>
<!-- 规则详情弹窗 -->

View File

@@ -58,29 +58,29 @@ export default {
// 按照顺序进行筛选,先按照知识库进行筛选
filteredList = this.form.knowledge
? filteredList.filter(item => {
return item.docTypeName === this.form.knowledge
})
return item.docTypeName === this.form.knowledge
})
: filteredList
// 按照知识文件名称进行筛选
filteredList = this.form.knowledgeName
? filteredList.filter(item => {
return item.fileName === this.form.knowledgeName
})
return item.fileName === this.form.knowledgeName
})
: filteredList
// 按照上传用户进行筛选
filteredList = this.form.uploadUser
? filteredList.filter(item => {
return item.createdUser === this.form.uploadUser
})
return item.createdUser === this.form.uploadUser
})
: filteredList
// 按照任务状态进行筛选
filteredList = this.form.taskStatus
? filteredList.filter(item => {
return item.processStatus === this.form.taskStatus
})
return item.processStatus === this.form.taskStatus
})
: filteredList
// 处理的状态格式化
@@ -94,11 +94,11 @@ export default {
filteredList =
this.form.taskTime.length > 0
? filteredList.filter(item => {
return (
new Date(item.uploadDate).getTime() >= new Date(this.form.taskTime[0]).getTime() &&
new Date(item.uploadDate).getTime() <= new Date(this.form.taskTime[1]).getTime()
)
})
return (
new Date(item.uploadDate).getTime() >= new Date(this.form.taskTime[0]).getTime() &&
new Date(item.uploadDate).getTime() <= new Date(this.form.taskTime[1]).getTime()
)
})
: filteredList
// 默认返回所有列表
@@ -242,12 +242,17 @@ export default {
<!-- 任务列表 -->
<div>
<r-table :columns="tableConfig.columns" :data="getFilterTableData" :deletion="false" :total="tableConfig.total"
@currentChange="handleCurrentChange" @sizeChange="handleSizeChange" />
<r-table
:columns="tableConfig.columns"
:data="getFilterTableData"
:deletion="false"
:total="tableConfig.total"
@currentChange="handleCurrentChange"
@sizeChange="handleSizeChange"
/>
<!-- 弹出提示框 里面是各种详情内容 -->
<el-drawer title="上传任务详情" :visible.sync="infoDialogVisible" size="80%"
:before-close="() => (infoDialogVisible = false)">
<el-drawer title="上传任务详情" :visible.sync="infoDialogVisible" size="80%" :before-close="() => (infoDialogVisible = false)">
<knowledge-info :form="activeForm" v-if="infoDialogVisible"></knowledge-info>
</el-drawer>
</div>