mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-06 17:36:48 +08:00
2025-5-19: 新增分段, 分段删除
- 添加分段创建、更新和删除接口 - 实现新增分段对话框和相关逻辑 - 优化分段显示和操作界面 - 添加分段相关的样式和交互
This commit is contained in:
@@ -421,6 +421,7 @@ export function uploadImage(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 分段编辑
|
||||
export function segmentUpdate(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/segment/update`),
|
||||
@@ -428,3 +429,20 @@ export function segmentUpdate(data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 分段删除
|
||||
export function segmentDelete(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/segment/delete`),
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 新增分段
|
||||
export function segmentCreate(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/segment/create`),
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -315,10 +315,10 @@ export default {
|
||||
<el-button
|
||||
class="line-button"
|
||||
size="medium"
|
||||
icon="el-icon-odometer"
|
||||
icon="el-icon-more"
|
||||
@click.stop="jumpToLogs(listItem.id)"
|
||||
type="primary"
|
||||
>日志与监测
|
||||
>更多
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
@@ -24,11 +24,14 @@
|
||||
v-if="!noEdit"
|
||||
>
|
||||
<!-- 删除 编辑-->
|
||||
<!-- <el-icon class="el-icon-edit" @click.native.stop=""></el-icon>-->
|
||||
<!-- <el-icon-->
|
||||
<!-- class="el-icon-delete"-->
|
||||
<!-- @click.native.stop="deleteSegment"-->
|
||||
<!-- ></el-icon>-->
|
||||
<el-icon
|
||||
class="el-icon-edit mr10"
|
||||
@click.native.stop="handleSegmentClick(index)"
|
||||
></el-icon>
|
||||
<el-icon
|
||||
class="el-icon-delete"
|
||||
@click.native.stop="deleteSegment(segment, index)"
|
||||
></el-icon>
|
||||
<!-- <el-switch-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click.native.stop=""-->
|
||||
@@ -72,20 +75,20 @@
|
||||
<div class="segment-content">
|
||||
<div>
|
||||
<div>
|
||||
<p>QUESTION</p>
|
||||
<p contenteditable class="resetHtml" ref="content">
|
||||
<p class="">QUESTION:</p>
|
||||
<p contenteditable class="resetHtml fs13" ref="content">
|
||||
{{ descriptions.data[activeSegment].content }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>ANSWER</p>
|
||||
<p contenteditable class="resetHtml" ref="answer">
|
||||
<p class="">ANSWER:</p>
|
||||
<p contenteditable class="resetHtml fs13" ref="answer">
|
||||
{{ descriptions.data[activeSegment].answer }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex align-items-c mt20"
|
||||
class="flex align-items-c mt20 fs13"
|
||||
v-if="
|
||||
descriptions.data[activeSegment].keywords &&
|
||||
descriptions.data[activeSegment].keywords.length
|
||||
@@ -99,8 +102,10 @@
|
||||
class="mr10"
|
||||
size="medium"
|
||||
type="info"
|
||||
:closable="!noEdit"
|
||||
@close="tagClose(item)"
|
||||
:closable="
|
||||
descriptions.data[activeSegment].keywords.length > 1 && !noEdit
|
||||
"
|
||||
@close="tagClose(item, index)"
|
||||
>
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
@@ -133,7 +138,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { segmentUpdate } from '@/api/generatedApi'
|
||||
import { segmentUpdate, segmentDelete } from '@/api/generatedApi'
|
||||
|
||||
export default {
|
||||
name: 'QAModel',
|
||||
@@ -152,6 +157,7 @@ export default {
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
data() {
|
||||
return {
|
||||
createdTag: false,
|
||||
@@ -160,10 +166,22 @@ export default {
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
deleteSegment() {
|
||||
deleteSegment(segment, index) {
|
||||
this.$messageBox(
|
||||
() => {},
|
||||
() => {
|
||||
segmentDelete({
|
||||
documentId: this.parentForm.id,
|
||||
segmentId: segment.id
|
||||
}).then(res => {
|
||||
if (res) {
|
||||
this.$message.success('删除成功')
|
||||
|
||||
this.descriptions.data.splice(index, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
'是否删除当前分段,删除后不可恢复',
|
||||
'warning',
|
||||
'提示'
|
||||
@@ -183,20 +201,15 @@ export default {
|
||||
showInput() {
|
||||
this.createdTag = true
|
||||
},
|
||||
tagClose() {
|
||||
this.descriptions.data[this.activeSegment].keywords.splice(
|
||||
this.descriptions.data[this.activeSegment].keywords.indexOf(
|
||||
this.inputValue
|
||||
),
|
||||
1
|
||||
)
|
||||
|
||||
tagClose(item, index) {
|
||||
this.descriptions.data[this.activeSegment].keywords.splice(index, 1)
|
||||
// console.log(this.descriptions.data[this.activeSegment].keywords)
|
||||
let params = {
|
||||
keywords: this.descriptions.data[this.activeSegment].keywords,
|
||||
content: this.$refs.content.innerHTML,
|
||||
answer: this.$refs.answer.innerHTML
|
||||
}
|
||||
this.saveSegment(params)
|
||||
// this.saveSegment(params)
|
||||
},
|
||||
|
||||
handleInputConfirm() {
|
||||
@@ -265,6 +278,21 @@ export default {
|
||||
border-radius: 2px;
|
||||
transition: background-color 0.3s;
|
||||
border-bottom: 1px solid #f3f5f7;
|
||||
position: relative;
|
||||
.actions {
|
||||
position: absolute;
|
||||
display: none; /* 默认隐藏 */
|
||||
background: #fff;
|
||||
padding: 3px 5px;
|
||||
border-radius: 5px;
|
||||
right: 10px;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
&:hover .actions {
|
||||
display: flex; /* 悬停或激活时显示操作按钮 */
|
||||
gap: 10px;
|
||||
}
|
||||
&:hover {
|
||||
background: #f3f5f7;
|
||||
}
|
||||
|
||||
@@ -26,12 +26,15 @@
|
||||
style="gap: 10px"
|
||||
v-if="!noEdit"
|
||||
>
|
||||
<!-- 删除 编辑-->
|
||||
<!-- <el-icon class="el-icon-edit" @click.native.stop=""></el-icon>-->
|
||||
<!-- <el-icon-->
|
||||
<!-- class="el-icon-delete"-->
|
||||
<!-- @click.native.stop="deleteSegment"-->
|
||||
<!-- ></el-icon>-->
|
||||
<!-- 删除 编辑-->
|
||||
<el-icon
|
||||
class="el-icon-edit mr10"
|
||||
@click.native.stop="handleSegmentClick(index)"
|
||||
></el-icon>
|
||||
<el-icon
|
||||
class="el-icon-delete"
|
||||
@click.native.stop="deleteSegment(segment, index)"
|
||||
></el-icon>
|
||||
<!-- <el-switch-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click.native.stop=""-->
|
||||
@@ -81,7 +84,7 @@
|
||||
"
|
||||
>
|
||||
<div class="segment-content">
|
||||
<p contenteditable class="resetHtml" ref="content">
|
||||
<p contenteditable class="resetHtml fs13" ref="content">
|
||||
{{ descriptions.data[activeSegment].content }}
|
||||
</p>
|
||||
<div
|
||||
@@ -95,10 +98,12 @@
|
||||
<span>关键词 :</span>
|
||||
<el-tag
|
||||
v-for="(item, index) in descriptions.data[activeSegment].keywords"
|
||||
:key="index"
|
||||
:key="item"
|
||||
class="mr10 ellipsis"
|
||||
size="medium"
|
||||
:closable="!noEdit"
|
||||
:closable="
|
||||
descriptions.data[activeSegment].keywords.length > 1 && !noEdit
|
||||
"
|
||||
type="info"
|
||||
@close="tagClose(item)"
|
||||
>
|
||||
@@ -133,7 +138,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { segmentUpdate } from '@/api/generatedApi'
|
||||
import { segmentDelete, segmentUpdate } from '@/api/generatedApi'
|
||||
|
||||
export default {
|
||||
name: 'TextModel',
|
||||
@@ -161,10 +166,22 @@ export default {
|
||||
selectedSegments: []
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
deleteSegment() {
|
||||
deleteSegment(segment, index) {
|
||||
this.$messageBox(
|
||||
() => {},
|
||||
() => {
|
||||
segmentDelete({
|
||||
documentId: this.parentForm.id,
|
||||
segmentId: segment.id
|
||||
}).then(res => {
|
||||
if (res) {
|
||||
this.$message.success('删除成功')
|
||||
|
||||
this.descriptions.data.splice(index, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
'是否删除当前分段,删除后不可恢复',
|
||||
'warning',
|
||||
'提示'
|
||||
@@ -186,13 +203,7 @@ export default {
|
||||
this.createdTag = true
|
||||
},
|
||||
tagClose() {
|
||||
this.descriptions.data[this.activeSegment].keywords.splice(
|
||||
this.descriptions.data[this.activeSegment].keywords.indexOf(
|
||||
this.inputValue
|
||||
),
|
||||
1
|
||||
)
|
||||
|
||||
this.descriptions.data[this.activeSegment].keywords.splice(index, 1)
|
||||
let params = {
|
||||
keywords: this.descriptions.data[this.activeSegment].keywords,
|
||||
content: this.$refs.content.innerHTML,
|
||||
@@ -222,8 +233,9 @@ export default {
|
||||
JSON.stringify(res.content.content)
|
||||
)
|
||||
// res.content.content.keywords
|
||||
// this.descriptions.data[this.activeSegment].content =
|
||||
// res.content.content.content
|
||||
this.descriptions.data[this.activeSegment].keywords = JSON.parse(
|
||||
JSON.stringify(res.content.content.keywords)
|
||||
)
|
||||
// this.descriptions.data[this.activeSegment].answer =
|
||||
// res.content.content.answer
|
||||
this.createdTag = false
|
||||
@@ -273,8 +285,27 @@ export default {
|
||||
transition: background-color 0.3s;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #f3f5f7;
|
||||
position: relative;
|
||||
//margin-bottom: 10px;
|
||||
|
||||
&.active {
|
||||
background: #f3f5f7;
|
||||
}
|
||||
|
||||
.actions {
|
||||
position: absolute;
|
||||
display: none; /* 默认隐藏 */
|
||||
background: #fff;
|
||||
padding: 3px 5px;
|
||||
border-radius: 5px;
|
||||
right: 10px;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
&:hover .actions {
|
||||
display: flex; /* 悬停或激活时显示操作按钮 */
|
||||
gap: 10px;
|
||||
}
|
||||
&:hover {
|
||||
background: #f3f5f7;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<div class="add-segment-container">
|
||||
<div class="add-segment-content">
|
||||
<div class="add-segment-text fs13">
|
||||
<!-- Q&A-->
|
||||
<div v-if="descriptions.doc_form === 'qa_model'">
|
||||
<div class="mv10">Question</div>
|
||||
<el-input
|
||||
type="textarea"
|
||||
class="text-input-q-a"
|
||||
v-model="question"
|
||||
placeholder="请填写分段内容"
|
||||
></el-input>
|
||||
|
||||
<div class="mv10">Answer</div>
|
||||
|
||||
<el-input
|
||||
type="textarea"
|
||||
class="text-input-q-a"
|
||||
v-model="answer"
|
||||
placeholder="请填写分段内容"
|
||||
></el-input>
|
||||
</div>
|
||||
<!-- model-->
|
||||
<div v-else>
|
||||
<el-input
|
||||
type="textarea"
|
||||
class="text-input"
|
||||
v-model="question"
|
||||
placeholder="请填写分段内容"
|
||||
></el-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="add-segment-bottom ">
|
||||
<div class=" mt5 fs13 mb5" style="flex:none">关键词:</div>
|
||||
|
||||
<div
|
||||
class="add-segment-tags mb10 fs14 flex align-items-s justify-content-s "
|
||||
>
|
||||
<div
|
||||
class="flex align-items-s mb10"
|
||||
style="max-height: 80px;overflow: auto;gap: 10px;flex-wrap: wrap;align-items: self-start"
|
||||
>
|
||||
<el-tag
|
||||
v-for="(item, index) in keywords"
|
||||
size="medium"
|
||||
:closable="keywords.length > 1"
|
||||
type="info"
|
||||
@close="keywords.splice(index, 1)"
|
||||
>{{ item }}</el-tag
|
||||
>
|
||||
|
||||
<el-input
|
||||
class="input-new-tag"
|
||||
v-if="createdTag"
|
||||
v-model="inputValue"
|
||||
ref="saveTagInput"
|
||||
size="small"
|
||||
@keyup.enter.native="pushKeyWords"
|
||||
/>
|
||||
<el-button
|
||||
v-if="!createdTag"
|
||||
size="small"
|
||||
@click="showInput"
|
||||
class="fs12"
|
||||
style="padding: 7px;border-radius: 4px;font-size: 12px"
|
||||
>添加标签</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex align-items-c justify-content-b">
|
||||
<el-checkbox v-model="continueAdd">连续新增</el-checkbox>
|
||||
<div>
|
||||
<el-button size="medium" @click="close">取消</el-button>
|
||||
<el-button
|
||||
class="line-button"
|
||||
size="medium"
|
||||
@click="handleInputConfirm"
|
||||
>保存</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { segmentCreate } from '@/api/generatedApi'
|
||||
|
||||
export default {
|
||||
name: 'addSegment',
|
||||
data() {
|
||||
return {
|
||||
continueAdd: false,
|
||||
question: '',
|
||||
answer: '',
|
||||
createdTag: false,
|
||||
inputValue: '',
|
||||
keywords: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
descriptions: {
|
||||
type: Object,
|
||||
default: () => ({ data: [] })
|
||||
},
|
||||
documentId: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pushKeyWords() {
|
||||
this.keywords.push(this.inputValue)
|
||||
this.createdTag = false
|
||||
},
|
||||
showInput() {
|
||||
this.createdTag = true
|
||||
},
|
||||
handleInputConfirm() {
|
||||
let params = {
|
||||
documentId: this.documentId,
|
||||
segment: {
|
||||
keywords: this.keywords,
|
||||
content: this.question,
|
||||
answer: this.answer
|
||||
}
|
||||
}
|
||||
segmentCreate(params).then(res => {
|
||||
if (res) {
|
||||
this.$message.success('新增分段成功')
|
||||
this.descriptions.data.push({
|
||||
...res.content.content
|
||||
})
|
||||
|
||||
if (!this.continueAdd) {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
})
|
||||
// this.saveSegment(params)
|
||||
},
|
||||
|
||||
close() {
|
||||
this.$emit('close', true)
|
||||
},
|
||||
addSegment() {
|
||||
this.$emit('addSegment', this.text)
|
||||
this.text = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
::v-deep .text-input {
|
||||
height: 100%;
|
||||
.el-textarea__inner {
|
||||
padding: 5px 8px;
|
||||
height: calc(100vh - 310px);
|
||||
//border: unset;
|
||||
//resize: unset;
|
||||
//height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .text-input-q-a {
|
||||
height: 100%;
|
||||
.el-textarea__inner {
|
||||
padding: 5px 8px;
|
||||
height: calc(100vh - 700px);
|
||||
//border: unset;
|
||||
//resize: unset;
|
||||
//height: 100%;
|
||||
}
|
||||
}
|
||||
.add-segment-container {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
& .add-segment-content {
|
||||
//background: rebeccapurple;
|
||||
|
||||
//overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
& .add-segment-text {
|
||||
height: calc(100vh - 310px);
|
||||
//height: 100%;
|
||||
//height: 999px;
|
||||
//background: blue;
|
||||
}
|
||||
}
|
||||
|
||||
& .add-segment-bottom {
|
||||
width: 100%;
|
||||
padding: 10px 0 0 0;
|
||||
position: sticky;
|
||||
background: #fff;
|
||||
bottom: 0;
|
||||
& .add-segment-tags {
|
||||
height: 100px;
|
||||
//background: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
.input-new-tag {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -4,15 +4,16 @@ import TextModel from '@/views/knowledge/detail/components/documentDetail/TextMo
|
||||
import QAModel from '@/views/knowledge/detail/components/documentDetail/QAModel.vue'
|
||||
import RenderFile from '@/components/RenderFile/Index.vue'
|
||||
import MetadataOperator from '@/views/knowledge/detail/components/metaData/MetadataOperator.vue'
|
||||
|
||||
import AddSegment from '@/views/knowledge/detail/components/documentDetail/addSegment.vue'
|
||||
export default {
|
||||
name: 'index',
|
||||
components: { MetadataOperator, QAModel, TextModel, RenderFile },
|
||||
components: { MetadataOperator, QAModel, TextModel, RenderFile, AddSegment },
|
||||
data() {
|
||||
return {
|
||||
iframeSrc: window.location.origin,
|
||||
newForm: {},
|
||||
descriptions: null
|
||||
descriptions: null,
|
||||
addSegmentDialog: false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@@ -75,6 +76,11 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 新增分段
|
||||
addSegment() {
|
||||
this.addSegmentDialog = true
|
||||
},
|
||||
|
||||
toSplit() {
|
||||
this.$router.push({
|
||||
path: '/knowledge/detail/create',
|
||||
@@ -163,11 +169,26 @@ export default {
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<el-row :gutter="20">
|
||||
<div :class="!noEdit ? 'mt10' : 'mt40'">
|
||||
<el-button
|
||||
class="line-button"
|
||||
size="medium"
|
||||
v-if="!noEdit"
|
||||
@click="addSegment"
|
||||
>新增分段</el-button
|
||||
>
|
||||
</div>
|
||||
<el-row :gutter="20" class="mt10">
|
||||
<!-- 左侧:表单内容和知识内容 -->
|
||||
<el-col :span="newForm.knowledgeName.indexOf('.pdf') >= 0 ? 12 : 24">
|
||||
<el-col
|
||||
:span="
|
||||
newForm.knowledgeName && newForm.knowledgeName.indexOf('.pdf') >= 0
|
||||
? 12
|
||||
: 24
|
||||
"
|
||||
>
|
||||
<!-- 知识内容 -->
|
||||
<div class="content-card el-card mt20">
|
||||
<div class="content-card el-card ">
|
||||
<div class="knowledge-content" v-if="descriptions">
|
||||
<text-model
|
||||
:noEdit="noEdit"
|
||||
@@ -196,8 +217,13 @@ export default {
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:原文内容 -->
|
||||
<el-col :span="12" v-if="newForm.knowledgeName.indexOf('.pdf') >= 0">
|
||||
<div class="content-card el-card full-height mt20">
|
||||
<el-col
|
||||
:span="12"
|
||||
v-if="
|
||||
newForm.knowledgeName && newForm.knowledgeName.indexOf('.pdf') >= 0
|
||||
"
|
||||
>
|
||||
<div class="content-card el-card full-height ">
|
||||
<!-- <metadata-operator-->
|
||||
<!-- @openMetaDrawer="openMetaDrawer"-->
|
||||
<!-- ></metadata-operator>-->
|
||||
@@ -206,6 +232,21 @@ export default {
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<el-drawer
|
||||
title="新增分段"
|
||||
:visible.sync="addSegmentDialog"
|
||||
:wrapperClosable="false"
|
||||
width="50%"
|
||||
append-to-body
|
||||
:modal="false"
|
||||
>
|
||||
<add-segment
|
||||
:descriptions="descriptions"
|
||||
:document-id="form.id"
|
||||
@close="addSegmentDialog = false"
|
||||
></add-segment>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -218,12 +259,12 @@ export default {
|
||||
}
|
||||
|
||||
.content-card {
|
||||
margin-bottom: 20px;
|
||||
//margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
.knowledge-content {
|
||||
height: calc(100vh - 240px);
|
||||
height: calc(100vh - 250px);
|
||||
overflow-y: auto;
|
||||
//&::-webkit-scrollbar {
|
||||
// width: 4px;
|
||||
@@ -232,7 +273,7 @@ export default {
|
||||
}
|
||||
|
||||
.full-height {
|
||||
height: calc(100vh - 240px);
|
||||
height: calc(100vh - 250px);
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user