mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-10 19:36:50 +08:00
refactor(knowledge): 重构知识库详情页面
- 将 DocumentDrawer 组件抽离为独立模块 - 新增 QAModel 和 TextModel 组件用于展示不同类型的分段内容 - 优化知识库详情页面的结构和样式- 提升代码的可维护性和可复用性
This commit is contained in:
@@ -0,0 +1,286 @@
|
|||||||
|
<!-- src/views/knowledge/detail/components/DocumentDrawer.vue -->
|
||||||
|
<template>
|
||||||
|
<el-drawer :visible.sync="visible" size="80%" :title="descriptions.knowledgeName" @close="$emit('update:visible', false)">
|
||||||
|
<!-- 原drawer内容整体拷贝至此 -->
|
||||||
|
<div class="drawer-content">
|
||||||
|
<div class="file-header">
|
||||||
|
<div class="file-icon">
|
||||||
|
<i class="el-icon-document"></i>
|
||||||
|
</div>
|
||||||
|
<div class="file-info">
|
||||||
|
<h3>{{ descriptions.fileName || descriptions.knowledgeName }}</h3>
|
||||||
|
<el-tag type="primary" class="mr10">{{ getDocumentSourceLabel(descriptions.documentSource) }}</el-tag>
|
||||||
|
<el-tag type="info">{{ descriptions.createdDate }}</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider></el-divider>
|
||||||
|
|
||||||
|
<div class="segment-info">
|
||||||
|
<div class="segment-header">
|
||||||
|
<h4>分段规则</h4>
|
||||||
|
</div>
|
||||||
|
<div class="rule-card">
|
||||||
|
<div class="rule-item">
|
||||||
|
<h5>是否使用预处理:</h5>
|
||||||
|
<span>{{ descriptions.usePreProcess | filterUseMineru }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="rule-item">
|
||||||
|
<h5>是否使用OCR协助处理:</h5>
|
||||||
|
<span>{{ descriptions.useOcr | filterUseMineru }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="rule-item">
|
||||||
|
<h5>知识拆分规则:</h5>
|
||||||
|
<span v-if="!documentDetail.splitRules">
|
||||||
|
-
|
||||||
|
</span>
|
||||||
|
<div v-else class="flex">
|
||||||
|
<div v-for="item in documentDetail.splitRules" :key="item.id" class="rule-detail-item">
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">样式:</span> <span class="rule-value">{{ item.titleLevel }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">关键词:</span> <span class="rule-value">{{ item.ruleRegex }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">备注:</span> <span class="rule-value">{{ item.description }}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="rule-item">
|
||||||
|
<h5>知识题词规则:</h5>
|
||||||
|
<span v-if="!documentDetail.extractRules">
|
||||||
|
-
|
||||||
|
</span>
|
||||||
|
<div v-else class="flex">
|
||||||
|
<div v-for="item in documentDetail.extractRules" :key="item.id" class="rule-detail-item">
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">属性:</span> <span class="rule-value">{{ item.attribute }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">属性描述:</span><span class="rule-value">{{ item.attributeDesc }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">关键词:</span> <span class="rule-value">{{ item.keyword }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">关键词示例:</span> <span class="rule-value">{{ item.example }}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span class="rule-label">提示词:</span> <span class="rule-value">{{ item.prompt }}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider></el-divider>
|
||||||
|
<div class="segment-content-container">
|
||||||
|
<div class="segment-header mb15">
|
||||||
|
<h4>分段内容</h4>
|
||||||
|
<div class="segment-summary">
|
||||||
|
<span>共{{ descriptions.data ? descriptions.data.length : 0 }}个分段</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<text-model
|
||||||
|
v-if="descriptions.doc_form === 'text_model'"
|
||||||
|
:descriptions="descriptions"
|
||||||
|
:documentDetail="documentDetail"
|
||||||
|
:activeSegment="activeSegment"
|
||||||
|
/>
|
||||||
|
<q-a-model
|
||||||
|
v-else-if="descriptions.doc_form === 'qa_model'"
|
||||||
|
:descriptions="descriptions"
|
||||||
|
:documentDetail="documentDetail"
|
||||||
|
:activeSegment="activeSegment"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TextModel from './TextModel.vue'
|
||||||
|
import QAModel from './QAModel.vue'
|
||||||
|
import { segmentedModeOptionsMap } from '@/assets/js/utils/utilOptions'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { TextModel, QAModel },
|
||||||
|
props: {
|
||||||
|
visible: Boolean,
|
||||||
|
descriptions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({ data: [] })
|
||||||
|
},
|
||||||
|
documentDetail: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
activeSegment: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
localActiveSegment: this.activeSegment
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
activeSegment(newVal) {
|
||||||
|
this.localActiveSegment = newVal
|
||||||
|
},
|
||||||
|
// 深度监听descriptions变化
|
||||||
|
descriptions: {
|
||||||
|
handler(newVal) {
|
||||||
|
// 触发重新渲染的逻辑
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.localActiveSegment = 0 // 重置激活分段
|
||||||
|
this.$forceUpdate() // 强制刷新(仅在必要情况使用)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deep: true, // 必须开启深度监听
|
||||||
|
immediate: true // 初始化立即执行
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
filterSegmentedMode(val) {
|
||||||
|
switch (val) {
|
||||||
|
case 0:
|
||||||
|
return '传统分段模式'
|
||||||
|
case 1:
|
||||||
|
return ' Q&A分段模式'
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filterUseMineru(val) {
|
||||||
|
let item = segmentedModeOptionsMap.find(item => item.value === String(val))
|
||||||
|
return item ? item.label : '否'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getDocumentSourceLabel(sourceValue) {
|
||||||
|
// 保持原方法实现
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.drawer-content {
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
font-size: 36px;
|
||||||
|
margin-right: 15px;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
h3 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-info {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.segment-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rule-card {
|
||||||
|
//background: #fff;
|
||||||
|
//border-radius: 4px;
|
||||||
|
//padding: 15px;
|
||||||
|
//box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.rule-item {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 8px 0 0;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rule-detail-item {
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 10px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rule-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rule-value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.segment-content-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-summary {
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
123
src/views/knowledge/detail/components/documentDetail/QAModel.vue
Normal file
123
src/views/knowledge/detail/components/documentDetail/QAModel.vue
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div class="segment-split-view">
|
||||||
|
<div class="segment-list">
|
||||||
|
<div
|
||||||
|
v-for="(segment, index) in descriptions.data"
|
||||||
|
:key="index"
|
||||||
|
class="segment-list-item"
|
||||||
|
:class="{ active: activeSegment === index }"
|
||||||
|
@click="activeSegment = index"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span class="segment-number">分段 - {{ index + 1 }}</span> · <span v-if="segment.word_count > 0">{{ segment.word_count }}个字符</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>Q {{ segment.content }}</p>
|
||||||
|
<p>A {{ segment.answer }}</p>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="segment-keywords flex" v-if="segment.keywords && segment.keywords.length">-->
|
||||||
|
<!-- <p v-for="(item, index) in segment.keywords" :key="index" class="mr10">#{{ item }}</p>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <span class="segment-chars">{{ segment.characters || 0 }} characters</span>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="segment-detail" v-if="descriptions.data && descriptions.data.length > 0">
|
||||||
|
<div class="segment-content" v-if="activeSegment !== null">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p>QUESTION</p>
|
||||||
|
<p>{{ descriptions.data[activeSegment].content }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p>ANSWER</p>
|
||||||
|
<p>{{ descriptions.data[activeSegment].answer }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-c mt20" v-if="descriptions.data[activeSegment].keywords && descriptions.data[activeSegment].keywords.length">
|
||||||
|
关键词 :
|
||||||
|
<el-tag v-for="(item, index) in descriptions.data[activeSegment].keywords" :key="index" class="mr10" size="mini" type="primary">
|
||||||
|
{{ item }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="activeSegment !== null"></div>
|
||||||
|
<div class="segment-empty" v-else>
|
||||||
|
<el-empty description="请选择左侧分段查看详情"></el-empty>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'QAModel',
|
||||||
|
props: {
|
||||||
|
visible: Boolean,
|
||||||
|
descriptions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({ data: [{}] })
|
||||||
|
},
|
||||||
|
documentDetail: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
activeSegment: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.segment-split-view {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-list {
|
||||||
|
//flex: 1;
|
||||||
|
width: 45%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 15px 0 10px 15px;
|
||||||
|
border-radius: 15px;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-size: 14px;
|
||||||
|
&:hover {
|
||||||
|
background: #f3f5f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #f3f5f7;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.segment-number {
|
||||||
|
color: #0a84ff;
|
||||||
|
}
|
||||||
|
.segment-keywords {
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-detail {
|
||||||
|
width: 55%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-content {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 15px;
|
||||||
|
//white-space: pre-wrap;
|
||||||
|
line-height: 35px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-empty {
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
<template>
|
||||||
|
<div class="segment-split-view">
|
||||||
|
<div class="segment-list">
|
||||||
|
<div
|
||||||
|
v-for="(segment, index) in descriptions.data"
|
||||||
|
:key="index"
|
||||||
|
class="segment-list-item"
|
||||||
|
:class="{ active: activeSegment === index }"
|
||||||
|
@click="activeSegment = index"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span class="segment-number">分段 - {{ index + 1 }}</span> · <span v-if="segment.word_count > 0">{{ segment.word_count }}个字符</span>
|
||||||
|
</div>
|
||||||
|
<p>{{ segment.content.slice(0, 20) + '.....' }}</p>
|
||||||
|
<div class="segment-keywords flex" v-if="segment.keywords && segment.keywords.length">
|
||||||
|
<p v-for="(item, index) in segment.keywords" :key="index" class="mr10">#{{ item }}</p>
|
||||||
|
</div>
|
||||||
|
<!-- <span class="segment-chars">{{ segment.characters || 0 }} characters</span>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="segment-detail" v-if="descriptions.data && descriptions.data.length > 0">
|
||||||
|
<div class="segment-content" v-if="activeSegment !== null">
|
||||||
|
{{ descriptions.data[activeSegment].content }}
|
||||||
|
<div class="flex align-items-c mt20" v-if="descriptions.data[activeSegment].keywords && descriptions.data[activeSegment].keywords.length">
|
||||||
|
关键词 :
|
||||||
|
<el-tag v-for="(item, index) in descriptions.data[activeSegment].keywords" :key="index" class="mr10" size="mini" type="primary">
|
||||||
|
{{ item }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="activeSegment !== null"></div>
|
||||||
|
<div class="segment-empty" v-else>
|
||||||
|
<el-empty description="请选择左侧分段查看详情"></el-empty>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'TextModel',
|
||||||
|
props: {
|
||||||
|
visible: Boolean,
|
||||||
|
descriptions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({ data: [] })
|
||||||
|
},
|
||||||
|
documentDetail: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
activeSegment: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.segment-split-view {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-list {
|
||||||
|
//flex: 1;
|
||||||
|
width: 45%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 15px 0 10px 15px;
|
||||||
|
border-radius: 15px;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-size: 14px;
|
||||||
|
&:hover {
|
||||||
|
background: #f3f5f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #f3f5f7;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.segment-number {
|
||||||
|
color: #0a84ff;
|
||||||
|
}
|
||||||
|
.segment-keywords {
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-detail {
|
||||||
|
width: 55%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-content {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 15px;
|
||||||
|
//white-space: pre-wrap;
|
||||||
|
line-height: 35px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-empty {
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -120,8 +120,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {},
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getDetail()
|
this.getDetail()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,16 +13,27 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 文件上传-->
|
<!-- 文件上传-->
|
||||||
<el-form-item label="" required prop="file">
|
<el-form-item label="" required prop="file">
|
||||||
<div @click="createFiled" @dragover.prevent="handleDragOver" @dragleave.prevent="handleDragLeave"
|
<div
|
||||||
@drop.prevent="handleDrop" class="upload-demo" :class="{ 'drag-over': isDragOver }">
|
@click="createFiled"
|
||||||
|
@dragover.prevent="handleDragOver"
|
||||||
|
@dragleave.prevent="handleDragLeave"
|
||||||
|
@drop.prevent="handleDrop"
|
||||||
|
class="upload-demo"
|
||||||
|
:class="{ 'drag-over': isDragOver }"
|
||||||
|
>
|
||||||
<el-empty v-if="!filed">
|
<el-empty v-if="!filed">
|
||||||
<template #description>
|
<template #description>
|
||||||
<p>点击或将文件拖拽到这里上传</p>
|
<p>点击或将文件拖拽到这里上传</p>
|
||||||
<p>支持扩展名:.xlsx .doc .docx .pdf .txt...</p>
|
<p>支持扩展名:.xlsx .doc .docx .pdf .txt...</p>
|
||||||
</template>
|
</template>
|
||||||
</el-empty>
|
</el-empty>
|
||||||
<el-result v-else icon="success" title="文件上传成功" :sub-title="`已上传文件:${filed.name}`"
|
<el-result
|
||||||
style="height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center;">
|
v-else
|
||||||
|
icon="success"
|
||||||
|
title="文件上传成功"
|
||||||
|
:sub-title="`已上传文件:${filed.name}`"
|
||||||
|
style="height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center;"
|
||||||
|
>
|
||||||
<template slot="extra">
|
<template slot="extra">
|
||||||
<el-button type="primary" size="medium" @click.stop="createFiled">重新上传</el-button>
|
<el-button type="primary" size="medium" @click.stop="createFiled">重新上传</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -35,8 +46,7 @@
|
|||||||
<el-form-item label="是否进行预处理:" required prop="beMinerU">
|
<el-form-item label="是否进行预处理:" required prop="beMinerU">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
是否进行预处理
|
是否进行预处理
|
||||||
<el-tooltip class="item" effect="dark" content="通过整合最先进的文档解析模型来提高内容提取质量"
|
<el-tooltip class="item" effect="dark" content="通过整合最先进的文档解析模型来提高内容提取质量" placement="top">
|
||||||
placement="top">
|
|
||||||
<i class="el-icon-info ml5" style="color: #909399;"></i>
|
<i class="el-icon-info ml5" style="color: #909399;"></i>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
:
|
:
|
||||||
@@ -210,10 +220,8 @@ export default {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {},
|
||||||
},
|
mounted() {},
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
computed: {}
|
computed: {}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -249,7 +257,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.preview-container {
|
.preview-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 500px;
|
height: 500px;
|
||||||
|
|||||||
@@ -85,135 +85,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
<document-drawer
|
||||||
<el-drawer :visible.sync="drawer" size="80%" :title="descriptions.knowledgeName">
|
:visible.sync="drawer"
|
||||||
<div class="drawer-content">
|
:descriptions="descriptions"
|
||||||
<div class="file-header">
|
:document-detail="documentDetail"
|
||||||
<div class="file-icon">
|
:active-segment="activeSegment"
|
||||||
<i class="el-icon-document"></i>
|
@update:visible="val => (drawer = val)"
|
||||||
</div>
|
/>
|
||||||
<div class="file-info">
|
|
||||||
<h3>{{ descriptions.fileName || descriptions.knowledgeName }}</h3>
|
|
||||||
<el-tag type="primary" class="mr10">{{ getDocumentSourceLabel(descriptions.documentSource) }}</el-tag>
|
|
||||||
<el-tag type="info">{{ descriptions.createdDate }}</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider></el-divider>
|
|
||||||
|
|
||||||
<div class="segment-info">
|
|
||||||
<div class="segment-header">
|
|
||||||
<h4>分段规则</h4>
|
|
||||||
</div>
|
|
||||||
<div class="rule-card">
|
|
||||||
<div class="rule-item">
|
|
||||||
<h5>是否使用预处理:</h5>
|
|
||||||
<span>{{ descriptions.usePreProcess | filterUseMineru }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="rule-item">
|
|
||||||
<h5>是否使用OCR协助处理:</h5>
|
|
||||||
<span>{{ descriptions.useOcr | filterUseMineru }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="rule-item">
|
|
||||||
<h5>知识拆分规则:</h5>
|
|
||||||
<span v-if="!documentDetail.splitRules">
|
|
||||||
-
|
|
||||||
</span>
|
|
||||||
<div v-else>
|
|
||||||
<div v-for="item in documentDetail.splitRules" :key="item.id" class="rule-detail-item">
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">样式:</span> <span class="rule-value">{{ item.titleLevel }}</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">关键词:</span> <span class="rule-value">{{ item.ruleRegex }}</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">备注:</span> <span class="rule-value">{{ item.description }}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="rule-item">
|
|
||||||
<h5>知识题词规则:</h5>
|
|
||||||
<span v-if="!documentDetail.extractRules">
|
|
||||||
-
|
|
||||||
</span>
|
|
||||||
<div v-else>
|
|
||||||
<div v-for="item in documentDetail.extractRules" :key="item.id" class="rule-detail-item">
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">属性:</span> <span class="rule-value">{{ item.attribute }}</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">属性描述:</span><span class="rule-value">{{ item.attributeDesc }}</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">关键词:</span> <span class="rule-value">{{ item.keyword }}</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">关键词示例:</span> <span class="rule-value">{{ item.example }}</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="rule-label">提示词:</span> <span class="rule-value">{{ item.prompt }}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider></el-divider>
|
|
||||||
|
|
||||||
<div class="segment-content-container">
|
|
||||||
<div class="segment-header mb15">
|
|
||||||
<h4>分段内容</h4>
|
|
||||||
<div class="segment-summary">
|
|
||||||
<span>共{{ descriptions.data ? descriptions.data.length : 0 }}个分段</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="segment-split-view">
|
|
||||||
<div class="segment-list">
|
|
||||||
<div
|
|
||||||
v-for="(segment, index) in descriptions.data"
|
|
||||||
:key="index"
|
|
||||||
class="segment-list-item"
|
|
||||||
:class="{ active: activeSegment === index }"
|
|
||||||
@click="activeSegment = index"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<span class="segment-number">分段 - {{ index + 1 }}</span> · <span v-if="segment.word_count > 0">{{ segment.word_count }}个字符</span>
|
|
||||||
</div>
|
|
||||||
<p>{{ segment.content.slice(0, 20) + '.....' }}</p>
|
|
||||||
<div class="segment-keywords flex" v-if="segment.keywords && segment.keywords.length">
|
|
||||||
<p v-for="(item, index) in segment.keywords" :key="index" class="mr10">#{{ item }}</p>
|
|
||||||
</div>
|
|
||||||
<!-- <span class="segment-chars">{{ segment.characters || 0 }} characters</span>-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="segment-detail" v-if="descriptions.data && descriptions.data.length > 0">
|
|
||||||
<div class="segment-content" v-if="activeSegment !== null">
|
|
||||||
{{ descriptions.data[activeSegment].content }}
|
|
||||||
<div class="flex align-items-c mt20" v-if="descriptions.data[activeSegment].keywords && descriptions.data[activeSegment].keywords.length">
|
|
||||||
关键词 :
|
|
||||||
<el-tag v-for="(item, index) in descriptions.data[activeSegment].keywords" :key="index" class="mr10" size="mini" type="primary">
|
|
||||||
{{ item }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="activeSegment !== null"></div>
|
|
||||||
<div class="segment-empty" v-else>
|
|
||||||
<el-empty description="请选择左侧分段查看详情"></el-empty>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-drawer>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { datasetDocumentEx, datasetQueryDelete, datasetQuerySegments, datasetsExPages, datasetUpdate, getDatasetById } from '@/api/generatedApi/index'
|
import { datasetDocumentEx, datasetQueryDelete, datasetQuerySegments, datasetsExPages, datasetUpdate, getDatasetById } from '@/api/generatedApi/index'
|
||||||
import { documentSourceOptions, segmentedModeOptionsMap } from '@/assets/js/utils/utilOptions'
|
import { documentSourceOptions, segmentedModeOptionsMap } from '@/assets/js/utils/utilOptions'
|
||||||
|
import DocumentDrawer from './components/documentDetail/DocumentDrawer.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'index',
|
name: 'index',
|
||||||
@@ -251,7 +135,9 @@ export default {
|
|||||||
},
|
},
|
||||||
props: {},
|
props: {},
|
||||||
watch: {},
|
watch: {},
|
||||||
components: {},
|
components: {
|
||||||
|
DocumentDrawer
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 开启编辑 知识库标题
|
// 开启编辑 知识库标题
|
||||||
editKnowledgeName() {
|
editKnowledgeName() {
|
||||||
@@ -629,8 +515,9 @@ export default {
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e0e0e0;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
|||||||
@@ -213,15 +213,25 @@ export default {
|
|||||||
<el-form-item label="上传状态">
|
<el-form-item label="上传状态">
|
||||||
<el-select v-model="form.documentStatus" placeholder="请选择上传状态">
|
<el-select v-model="form.documentStatus" placeholder="请选择上传状态">
|
||||||
<el-option label="全部上传状态" value="" />
|
<el-option label="全部上传状态" value="" />
|
||||||
<el-option v-for="item in Object.keys(this.tableConfig.uploadStatusType)" :key="item"
|
<el-option
|
||||||
:label="tableConfig.uploadStatusType[item]" :value="Number(item)" />
|
v-for="item in Object.keys(this.tableConfig.uploadStatusType)"
|
||||||
|
:key="item"
|
||||||
|
:label="tableConfig.uploadStatusType[item]"
|
||||||
|
:value="Number(item)"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="任务时间">
|
<el-form-item label="任务时间">
|
||||||
<el-date-picker v-model="form.taskTime" type="daterange" unlink-panels range-separator="至"
|
<el-date-picker
|
||||||
start-placeholder="开始日期" end-placeholder="结束日期" />
|
v-model="form.taskTime"
|
||||||
|
type="daterange"
|
||||||
|
unlink-panels
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="9" :offset="11" class="mb20">
|
<el-col :span="9" :offset="11" class="mb20">
|
||||||
@@ -235,14 +245,19 @@ export default {
|
|||||||
|
|
||||||
<!-- 任务列表 -->
|
<!-- 任务列表 -->
|
||||||
<div>
|
<div>
|
||||||
<r-table :columns="tableConfig.columns" :data="tableData" :deletion="false" :total="tableConfig.total"
|
<r-table
|
||||||
@currentChange="handleCurrentChange" @sizeChange="handleSizeChange"
|
:columns="tableConfig.columns"
|
||||||
:currentPage="tableConfig.currentPage"
|
:data="tableData"
|
||||||
:pageSize="tableConfig.pageSize" />
|
:deletion="false"
|
||||||
|
:total="tableConfig.total"
|
||||||
|
@currentChange="handleCurrentChange"
|
||||||
|
@sizeChange="handleSizeChange"
|
||||||
|
:currentPage="tableConfig.currentPage"
|
||||||
|
:pageSize="tableConfig.pageSize"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 弹出提示框, 里面是各种详情内容 -->
|
<!-- 弹出提示框, 里面是各种详情内容 -->
|
||||||
<el-drawer title="上传任务详情" :visible.sync="infoDialogVisible" size="60%"
|
<el-drawer title="上传任务详情" :visible.sync="infoDialogVisible" size="60%" :before-close="() => (infoDialogVisible = false)">
|
||||||
:before-close="() => (infoDialogVisible = false)">
|
|
||||||
<knowledge-info :form="activeForm" v-if="infoDialogVisible"></knowledge-info>
|
<knowledge-info :form="activeForm" v-if="infoDialogVisible"></knowledge-info>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user