Merge branch 'dev' into poc/bpic
1
.env
@@ -4,3 +4,4 @@ NODE_ENV = 'dev' // 如果是生产环境,请记得切换为production
|
||||
# flag
|
||||
VUE_APP_FLAG='dev'
|
||||
VUE_APP_ADMIN='http://39.104.123.254:7195'
|
||||
VUE_APP_DOCS='http://39.104.123.254:7546/'
|
||||
|
||||
@@ -265,8 +265,9 @@ export function uploadFileByTemplate(data) {
|
||||
export function datasetQuerySegments(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/querySegments`),
|
||||
method: 'get',
|
||||
params: data
|
||||
method: 'post',
|
||||
data,
|
||||
noLoading: true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -421,6 +422,7 @@ export function uploadImage(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 分段编辑
|
||||
export function segmentUpdate(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/segment/update`),
|
||||
@@ -428,3 +430,63 @@ 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
|
||||
})
|
||||
}
|
||||
|
||||
// 分段模板
|
||||
export function segmentTemplate(model) {
|
||||
// model 分别时 qa general
|
||||
return getUrl(`/template/download/${model}`)
|
||||
}
|
||||
// 导入分段
|
||||
export function importSegment(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/segment/batchImport`),
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出分段
|
||||
|
||||
export function exportSegment(data) {
|
||||
return getUrl(
|
||||
`/datasetDocumentEx/segment/export?documentId=${data.documentId}`
|
||||
)
|
||||
}
|
||||
|
||||
// 分段启用禁用
|
||||
export function switchStatus(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetDocumentEx/segment/switchStatus`),
|
||||
method: 'post',
|
||||
data,
|
||||
noLoading: true
|
||||
})
|
||||
}
|
||||
// 知识库关联智能体
|
||||
export function relatedApps(data) {
|
||||
return request({
|
||||
url: getUrl(`/datasetsEx/relatedApps`),
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 下载知识原文件
|
||||
export function downloadOriginalFile(data) {
|
||||
return getUrl(`/datasetDocumentEx/download/original_file?documentId=` + data)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,8 @@ const agentEdit = data => {
|
||||
const getAccessToken = data => {
|
||||
return request({
|
||||
url: getUrl('/third/access_token'),
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
noLoading: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 906 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 915 B |
|
Before Width: | Height: | Size: 827 B |
|
Before Width: | Height: | Size: 727 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
22
src/assets/sass/renderSass/drop.scss
Normal file
@@ -0,0 +1,22 @@
|
||||
.el-dropdown-menu__item:focus,
|
||||
.el-dropdown-menu__item:not(.is-disabled):hover {
|
||||
background-color: $--color-primary;
|
||||
color: #fff;
|
||||
}
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: $--color-primary;
|
||||
}
|
||||
//
|
||||
//.el-button {
|
||||
// &.el-dropdown__caret-button {
|
||||
// padding-left: 5px;
|
||||
// padding-right: 5px;
|
||||
// }
|
||||
//}
|
||||
.el-dropdown {
|
||||
& .el-dropdown__caret-button {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
@@ -346,3 +346,19 @@
|
||||
color: $--color-primary;
|
||||
}
|
||||
}
|
||||
.el-input-group__append .el-button,
|
||||
.el-input-group__append .el-select,
|
||||
.el-input-group__prepend .el-button,
|
||||
.el-input-group__prepend .el-select {
|
||||
margin: -10px 0;
|
||||
}
|
||||
|
||||
.el-input-group__append,
|
||||
.el-input-group__prepend {
|
||||
background: #fff;
|
||||
border-color: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
|
||||
color: $--color-primary;
|
||||
}
|
||||
|
||||
@@ -72,3 +72,34 @@
|
||||
//
|
||||
//}
|
||||
//.el-pagination.is-background .el-pager li:not(.disabled):hover
|
||||
|
||||
.tableBtn {
|
||||
padding: 5px;
|
||||
&.is-plain {
|
||||
&:hover {
|
||||
background: $--color-primary;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
&.el-button--danger {
|
||||
&.is-plain:focus,
|
||||
&.is-plain:hover {
|
||||
color: #fff;
|
||||
background: #ff1a1a;
|
||||
border-color: #ff1a1a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-pagination__sizes {
|
||||
& .el-select {
|
||||
& .el-input {
|
||||
&.el-input--mini {
|
||||
& .el-input__inner {
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
@import 'renderSass/message';
|
||||
@import 'renderSass/upload';
|
||||
@import 'renderSass/slider';
|
||||
@import 'renderSass/drop';
|
||||
|
||||
html,
|
||||
body,
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
:closeOnClickModal="closeOnClickModal"
|
||||
:close-on-press-escape="closeOnPressEscape"
|
||||
>
|
||||
<div slot="title">
|
||||
<slot name="title">{{ title }}</slot>
|
||||
</div>
|
||||
<div class="render-dialog-body">
|
||||
<slot name="default"></slot>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<div style="height: 100%;">
|
||||
<div class="flex align-items-c justify-content-b mb10">
|
||||
<div class="fileName flex align-items-c">
|
||||
<div class="fileName flex align-items-c ">
|
||||
<svg-icon
|
||||
icon-class="pdf"
|
||||
style="width: 20px;height: 20px"
|
||||
class-name="mr10"
|
||||
v-if='showPdf'
|
||||
/>
|
||||
{{ fileName }}
|
||||
</div>
|
||||
@@ -52,7 +53,7 @@
|
||||
element-loading-text="读取文档中..."
|
||||
>
|
||||
<iframe
|
||||
v-if="isShowPdf"
|
||||
v-if="showPdf"
|
||||
id="iframe"
|
||||
ref="iframe"
|
||||
:src="
|
||||
@@ -69,11 +70,35 @@
|
||||
element-loading-text="正在识别中..."
|
||||
>
|
||||
<div class="el-card ebiz-pdf" style="height: 100%;overflow: hidden">
|
||||
<div style="height: 47px;width: 100%;text-align: center;">
|
||||
<div class="flex align-items-c justify-content-c miner-navbar fs14">
|
||||
<el-icon
|
||||
class="el-icon-caret-left cursor-pointer"
|
||||
@click.native="changePageDown('down')"
|
||||
>
|
||||
</el-icon>
|
||||
<input
|
||||
style="width: 50px;text-align: center"
|
||||
v-model="copyValue"
|
||||
:min="0"
|
||||
class="fs13 miner-input el-input"
|
||||
@blur="blursChange"
|
||||
></input>
|
||||
<span class="mh5">/ </span>
|
||||
<span>{{ mdJsons.length }}</span>
|
||||
<el-icon
|
||||
class="el-icon-caret-right cursor-pointer"
|
||||
@click.native="changePageUp('up')"
|
||||
>
|
||||
></el-icon
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="scrollView" v-show="tab === '0'">
|
||||
<div
|
||||
class="view-body"
|
||||
id="viewBody"
|
||||
style="height:calc(100vh - 180px);overflow-y: scroll;overflow-x:hidden"
|
||||
style="height:calc(100vh - 227px);overflow-y: scroll;overflow-x:hidden"
|
||||
v-html="markdownHtml"
|
||||
></div>
|
||||
</div>
|
||||
@@ -122,9 +147,11 @@ export default {
|
||||
name: 'index',
|
||||
data() {
|
||||
return {
|
||||
copyValue: 1,
|
||||
mdJsons: {},
|
||||
finishenEnd: false,
|
||||
fileName: '',
|
||||
showPdf:true,
|
||||
recordId: '', //pdf 记录的id
|
||||
endEmit: false,
|
||||
tab: '0',
|
||||
@@ -278,8 +305,6 @@ export default {
|
||||
page: {
|
||||
handler(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
// this.changePage(newVal, this.tab)
|
||||
|
||||
this.getPDFDetailMarkDown()
|
||||
}
|
||||
}
|
||||
@@ -314,19 +339,77 @@ export default {
|
||||
},
|
||||
//changePage
|
||||
// 分页发生改变时
|
||||
changePage(page) {
|
||||
let documentId = document.getElementById(`view-code-${page - 1}`)
|
||||
let viewBody = document.getElementById('viewBody')
|
||||
if (this.tab === '1') {
|
||||
documentId = document.getElementById(`ebiz-code-${page - 1}`)
|
||||
viewBody = document.getElementById('md-editor')
|
||||
changePage(type) {
|
||||
// if (this.page <= 0 || this.page >= this.mdJsons.length) {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// switch (type) {
|
||||
// case 'down':
|
||||
// this.page -= 1
|
||||
// break
|
||||
// case 'up':
|
||||
// this.page += 1
|
||||
// break
|
||||
// },
|
||||
//
|
||||
// let documentId = document.getElementById(`view-code-${page - 1}`)
|
||||
// let viewBody = document.getElementById('viewBody')
|
||||
// if (this.tab === '1') {
|
||||
// documentId = document.getElementById(`ebiz-code-${page - 1}`)
|
||||
// viewBody = document.getElementById('md-editor')
|
||||
// }
|
||||
// if (documentId) {
|
||||
// viewBody.scrollTo({
|
||||
// top: documentId.offsetTop - 130,
|
||||
// behavior: 'smooth'
|
||||
// })
|
||||
// }
|
||||
},
|
||||
changePageDown(type) {
|
||||
if (this.page <= 0) {
|
||||
return false
|
||||
}
|
||||
if (documentId) {
|
||||
viewBody.scrollTo({
|
||||
top: documentId.offsetTop - 130,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
|
||||
switch (type) {
|
||||
case 'down':
|
||||
this.page -= 1
|
||||
break
|
||||
case 'up':
|
||||
this.page += 1
|
||||
break
|
||||
}
|
||||
this.copyValue = this.page
|
||||
},
|
||||
|
||||
blursChange(e) {
|
||||
if (!e.target.value.trim()) {
|
||||
this.copyValue = this.page
|
||||
}
|
||||
if (e.target.value < 0) {
|
||||
this.copyValue = this.page
|
||||
}
|
||||
if (e.target.value > this.mdJsons.length) {
|
||||
this.copyValue = this.page
|
||||
}
|
||||
this.page = this.copyValue
|
||||
},
|
||||
|
||||
changePageUp(type) {
|
||||
if (this.page >= this.mdJsons.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'down':
|
||||
this.page -= 1
|
||||
break
|
||||
case 'up':
|
||||
this.page += 1
|
||||
break
|
||||
}
|
||||
|
||||
this.copyValue = this.page
|
||||
},
|
||||
//重新识别表格
|
||||
retryMinerImage(chooseItem, loading, tableElement) {
|
||||
@@ -580,7 +663,9 @@ export default {
|
||||
JSON.parse(JSON.stringify(res.content.content.pdf_info))
|
||||
)
|
||||
// this.$refs.iframe 重新刷新iframe
|
||||
this.$refs.iframe.contentWindow.location.reload()
|
||||
if( this.$refs.iframe){
|
||||
this.$refs.iframe.contentWindow.location.reload()
|
||||
}
|
||||
|
||||
this.getPDFDetailMarkDown()
|
||||
})
|
||||
@@ -727,6 +812,11 @@ export default {
|
||||
if (res) {
|
||||
this.mdPges = res.content.content.pages
|
||||
this.fileName = res.content.content.name
|
||||
|
||||
// 隐藏非pdf文件
|
||||
this.showPdf = this.fileName.indexOf('.pdf') > 0;
|
||||
|
||||
|
||||
this.recordId = res.content.content.recordId
|
||||
switch (res.content.content.status) {
|
||||
case 0:
|
||||
@@ -841,6 +931,21 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.miner-navbar {
|
||||
margin-top: 11px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
padding-bottom: 10px;
|
||||
gap: 5px;
|
||||
& .miner-input {
|
||||
height: 20px ;
|
||||
line-height: 20px;
|
||||
border: 1px solid #BBBBBC;
|
||||
outline:none;
|
||||
border-radius: 2px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.lineHeight25 {
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const RenderSlot = {
|
||||
'el-tooltip',
|
||||
{
|
||||
props: {
|
||||
placement: 'left',
|
||||
placement: 'bottom',
|
||||
content: first[0].data.props.title
|
||||
// effect: 'light'
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@
|
||||
class="normal-button"
|
||||
:disabled="disabled"
|
||||
icon="el-icon-delete"
|
||||
@click="del(scope.row, scope.$index)"
|
||||
@click.stop="del(scope.row, scope.$index)"
|
||||
></el-button>
|
||||
<el-button
|
||||
class="normal-button"
|
||||
icon="el-icon-edit-outline"
|
||||
:disabled="disabled"
|
||||
@click="edit(scope.row, scope.$index)"
|
||||
@click.stop="edit(scope.row, scope.$index)"
|
||||
></el-button>
|
||||
</div>
|
||||
<!--如果渲染的是selfBtn-->
|
||||
@@ -75,10 +75,11 @@
|
||||
:disabled="
|
||||
item.disabled !== undefined ? item.disabled : disabled
|
||||
"
|
||||
:class="item.class"
|
||||
:type="btn.type ? btn.type : 'primary'"
|
||||
:size="btn.size ? btn.size : 'mini'"
|
||||
:key="btnIndex"
|
||||
@click="handlerMethods(scope.row, scope.$index, btn)"
|
||||
@click.stop="handlerMethods(scope.row, scope.$index, btn)"
|
||||
:label="btn.name"
|
||||
>
|
||||
{{ btn.name }}
|
||||
@@ -133,7 +134,7 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="
|
||||
@click.stop="
|
||||
e => {
|
||||
addRow(scope.row, scope.$index)
|
||||
}
|
||||
@@ -147,7 +148,7 @@
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="
|
||||
@click.stop="
|
||||
e => {
|
||||
delRow(scope.row, scope.$index)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script>
|
||||
import { DIFY_URL } from '@/config/base-url'
|
||||
import { agentAdd, agentDetail, agentEdit } from '@/api/intelligent-agent/list'
|
||||
import {
|
||||
agentAdd,
|
||||
agentDetail,
|
||||
agentEdit,
|
||||
getAccessToken
|
||||
} from '@/api/intelligent-agent/list'
|
||||
export default {
|
||||
name: 'workflow',
|
||||
props: {
|
||||
@@ -11,6 +16,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
timer: null,
|
||||
agentDetail: {},
|
||||
|
||||
resetName: '',
|
||||
@@ -76,6 +82,15 @@ export default {
|
||||
this.worker.instance.postMessage('init-worker', [
|
||||
this.messageChannel.instance.port2
|
||||
])
|
||||
// 每 5 分钟执行一次
|
||||
// ✅ 先清理已有 timer,防止重复创建
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
this.timer = setInterval(() => {
|
||||
this.initTokenRefresh()
|
||||
}, 1000 * 60 * 5)
|
||||
},
|
||||
destroyed() {
|
||||
// 组件销毁时清除 web worker 和 messageChannel
|
||||
@@ -83,6 +98,10 @@ export default {
|
||||
this.worker.instance = void 0
|
||||
this.messageChannel.instance.port1.close()
|
||||
this.messageChannel.instance = void 0
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.query': {
|
||||
@@ -96,8 +115,6 @@ export default {
|
||||
|
||||
// 当路由参数 id 变化时,更新 dify 的 src
|
||||
if (thirdAppId) {
|
||||
console.log(`current params:`, this.agent.params)
|
||||
|
||||
this.agent.src = `${DIFY_URL}/app/${thirdAppId}/workflow?${
|
||||
this.params
|
||||
}`
|
||||
@@ -110,6 +127,21 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async initTokenRefresh() {
|
||||
try {
|
||||
const thirdContent = await getAccessToken()
|
||||
const { refreshToken, accessToken } = thirdContent.content.content
|
||||
|
||||
// if (localStorage.getItem('refresh_token') !== refreshToken) {
|
||||
localStorage.setItem('refresh_token', refreshToken)
|
||||
// }
|
||||
// if (localStorage.getItem('console_token') !== accessToken) {
|
||||
localStorage.setItem('console_token', accessToken)
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error('Token refresh failed:', error)
|
||||
}
|
||||
},
|
||||
handleAgentLoad() {
|
||||
// 把 messageChannel port1 的所有权传递给 iframe
|
||||
this.$refs.agent.contentWindow.postMessage('init-iframe', '*', [
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<span class="title">你好,{{ userInfo.realName }}</span>
|
||||
<div class="subtitle">欢迎使用{{ title }}</div>
|
||||
<div class="role-info">
|
||||
当前角色:{{ userInfo.roleNames[0] || '未指定' }}
|
||||
当前角色:{{
|
||||
userInfo.roleNames ? userInfo.roleNames[0] : '未指定'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-container">
|
||||
@@ -29,7 +31,7 @@
|
||||
<span class="card-title">智能体</span>
|
||||
<div class="card-content">智能体管理列表</div>
|
||||
</div>
|
||||
<div class="card-item">
|
||||
<div class="card-item" @click="openTag">
|
||||
<span class="card-title">操作手册</span>
|
||||
<div class="card-content">智能管理平台使用手册</div>
|
||||
</div>
|
||||
@@ -426,6 +428,9 @@ export default {
|
||||
this.$router.push({
|
||||
path: url
|
||||
})
|
||||
},
|
||||
openTag() {
|
||||
window.open(process.env.VUE_APP_DOCS)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||
<hamburger
|
||||
:is-active="sidebar.opened"
|
||||
class="hamburger-container"
|
||||
@toggleClick="toggleSideBar"
|
||||
/>
|
||||
|
||||
<breadcrumb class="breadcrumb-container" />
|
||||
|
||||
<div class="right-menu" v-if="$store.state.settings.sidebarLogo">
|
||||
<el-dropdown class="avatar-container" trigger="click">
|
||||
<el-dropdown class="avatar-container" trigger="click" size="medium">
|
||||
<div class="avatar-wrapper">
|
||||
<el-avatar :size="size" :src="circleUrl" class="user-avatar" />
|
||||
<i class="el-icon-caret-bottom" />
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<el-dropdown
|
||||
class="avatar-container"
|
||||
trigger="click"
|
||||
size="medium"
|
||||
placement="top-start"
|
||||
>
|
||||
<div class="avatar-wrapper">
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
v-for="item in options"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
:key="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<div
|
||||
|
||||
@@ -20,9 +20,24 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'dialog.agent': {
|
||||
handler(val) {
|
||||
this.image = val.image
|
||||
this.imageType = val.imageType
|
||||
this.background = val.backgroundColor
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
isImage: '0',
|
||||
image: '',
|
||||
imageType: '',
|
||||
popover: false,
|
||||
background: '',
|
||||
chooseBack: [
|
||||
@@ -79,8 +94,17 @@ export default {
|
||||
},
|
||||
|
||||
chooseGround(colors) {
|
||||
this.$set(this.dialog.agent, 'backgroundColor', colors)
|
||||
this.background = colors
|
||||
},
|
||||
|
||||
saveEmoji() {
|
||||
this.dialog.agent.image = this.image
|
||||
this.dialog.agent.imageType = this.imageType
|
||||
this.$set(this.dialog.agent, 'backgroundColor', this.background)
|
||||
|
||||
this.popover = false
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交表单
|
||||
*/
|
||||
@@ -104,8 +128,9 @@ export default {
|
||||
},
|
||||
// 选择emoji
|
||||
selectEmoji(e) {
|
||||
this.dialog.agent.image = e.data
|
||||
this.dialog.agent.imageType = 'emoji'
|
||||
this.image = e.data
|
||||
this.imageType = 'emoji'
|
||||
// this.dialog.agent.imageType = 'emoji'
|
||||
},
|
||||
// 选择是否是上传图片
|
||||
changeUploadImage(e) {
|
||||
@@ -129,11 +154,8 @@ export default {
|
||||
label-position="top"
|
||||
label-width="80px"
|
||||
>
|
||||
<div class="flex ">
|
||||
<el-form-item label="名称与图标" prop="appName" style="flex:1">
|
||||
<el-input v-model="dialog.agent.appName" size="medium" />
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="imageId" class="mt30 ml20">
|
||||
<div class="flex align-items-c ">
|
||||
<el-form-item label="名称与图标" prop="imageId" class="mt30">
|
||||
<el-popover trigger="click" v-model="popover">
|
||||
<div style="width: 28vw">
|
||||
<el-radio-group
|
||||
@@ -150,22 +172,34 @@ export default {
|
||||
<div class="mt10" v-if="isImage === '0'">
|
||||
<VEmojiPicker @select="selectEmoji" class="emoji " />
|
||||
<div
|
||||
v-if="dialog.agent.image"
|
||||
v-if="image"
|
||||
class="flex mt10 back-content justify-content-b"
|
||||
>
|
||||
<template
|
||||
v-for="item in chooseBack"
|
||||
v-if="dialog.agent.imageType === 'emoji'"
|
||||
v-if="imageType === 'emoji'"
|
||||
>
|
||||
<div
|
||||
class="emoji-background"
|
||||
:style="`background:${item}`"
|
||||
@click="chooseGround(item)"
|
||||
:class="item === background ? 'activeBack' : ''"
|
||||
>
|
||||
{{ dialog.agent.image }}
|
||||
{{ image }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="flex align-items-c justify-content-b">
|
||||
<!-- <el-button size="medium" style="flex:1">取消</el-button>-->
|
||||
<el-button
|
||||
@click="saveEmoji"
|
||||
size="medium"
|
||||
type="primary"
|
||||
style="flex:1"
|
||||
>确认
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图片切割-->
|
||||
@@ -201,12 +235,27 @@ export default {
|
||||
<div v-if="dialog.agent.imageType === 'emoji'">
|
||||
{{ dialog.agent.image }}
|
||||
</div>
|
||||
<div v-else style="width: 100%">
|
||||
<img :src="dialog.agent.image" alt="" style="width: 100%;" />
|
||||
<div
|
||||
v-else-if="dialog.agent.imageType === 'image'"
|
||||
style="width: 100%;height: 100%;overflow: hidden;border-radius: 8px"
|
||||
>
|
||||
<img
|
||||
v-if="dialog.agent.image"
|
||||
:src="dialog.agent.image"
|
||||
alt=""
|
||||
style="width: 100%;height: 100%"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-else style="font-size: 30px" class=" fw600 white">
|
||||
{{ dialog.agent.appName[0] }}
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="appName" style="flex:1" class="mt60">
|
||||
<el-input v-model="dialog.agent.appName" size="medium" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-form-item label="选择应用类型" required prop="appType">
|
||||
@@ -272,6 +321,28 @@ export default {
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.emoji {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
& #Categories {
|
||||
& .category {
|
||||
&.active {
|
||||
border-bottom: 3px solid var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
& #InputSearch {
|
||||
& .container-search {
|
||||
& input {
|
||||
outline: none;
|
||||
border: 1px solid var(--color-primary);
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/sass/renderSass/theme.scss';
|
||||
@@ -302,27 +373,12 @@ export default {
|
||||
text-align: center;
|
||||
//margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.emoji {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
& #Categories {
|
||||
& .category {
|
||||
&.active {
|
||||
border-bottom: 3px solid var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
& #InputSearch {
|
||||
& .container-search {
|
||||
& input {
|
||||
outline: none;
|
||||
border: 1px solid var(--color-primary);
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.activeBack {
|
||||
border: 1px dashed #676f83;
|
||||
}
|
||||
}
|
||||
|
||||
.card-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -16,6 +16,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
agentType,
|
||||
agentConfig: {
|
||||
title: '',
|
||||
component: 'agent',
|
||||
@@ -26,12 +27,17 @@ export default {
|
||||
visibleRange: 0
|
||||
}
|
||||
},
|
||||
searchAppType: '',
|
||||
searchOption: {
|
||||
nameLike: '',
|
||||
appType: '',
|
||||
handleSearch: async () => {
|
||||
this.page = 1
|
||||
this.list = []
|
||||
await this.fetchAgentList({ nameLike: this.searchOption.nameLike })
|
||||
await this.fetchAgentList({
|
||||
nameLike: this.searchOption.nameLike,
|
||||
appType: this.searchOption.appType
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -201,7 +207,30 @@ export default {
|
||||
@keydown.enter.native="searchOption.handleSearch"
|
||||
>
|
||||
<template slot="prepend">
|
||||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||||
<el-select
|
||||
style="width: 140px"
|
||||
v-model="searchOption.appType"
|
||||
placeholder="请选择"
|
||||
slot="prepend"
|
||||
clearable
|
||||
@change="searchOption.handleSearch"
|
||||
>
|
||||
<el-option label="全部分类" value=""></el-option>
|
||||
<el-option
|
||||
v-for="item in agentType"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
:key="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<template slot="append">
|
||||
<el-button
|
||||
slot="append"
|
||||
icon="el-icon-search"
|
||||
@click="searchOption.handleSearch"
|
||||
></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
@@ -247,7 +276,10 @@ export default {
|
||||
}`
|
||||
"
|
||||
>
|
||||
<div v-if="listItem.imageType === 'image'">
|
||||
<div
|
||||
v-if="listItem.imageType === 'image'"
|
||||
style="width: 100%;height: 100%"
|
||||
>
|
||||
<img
|
||||
:src="listItem.image"
|
||||
alt=""
|
||||
@@ -315,10 +347,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>
|
||||
@@ -528,10 +560,10 @@ export default {
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
height: 35px;
|
||||
height: 18px;
|
||||
margin: 0;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
@@ -263,6 +263,14 @@ export default {
|
||||
{{ index + keyword }}
|
||||
#{{ keyword }}
|
||||
</el-tag>
|
||||
|
||||
<p
|
||||
class="fs12 r mt5 theme-line-back fw600"
|
||||
style="background-clip:text;color:transparent"
|
||||
v-if="contentItem.knowledgeName"
|
||||
>
|
||||
命中文档:{{ contentItem.knowledgeName }}
|
||||
</p>
|
||||
</section>
|
||||
<!-- score -->
|
||||
<span class="score">
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<template slot="title">
|
||||
<div class="flex align-items-c">
|
||||
<img
|
||||
src="@/assets/images/konwledge/knowledge-5.png"
|
||||
:src="`${static}/loadImage/knowledge-5.png`"
|
||||
alt=""
|
||||
style="height: 20px"
|
||||
/>
|
||||
@@ -79,6 +79,7 @@ export default {
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
static: process.env.VUE_APP_STATIC,
|
||||
// 0-向量检索 1-全文检索 2-混合检索
|
||||
searchMethod: 0,
|
||||
embeddingItem: {},
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
@click="chooseFixSearch(item)"
|
||||
>
|
||||
<img
|
||||
src="@/assets/images/konwledge/knowledge-2.png"
|
||||
:src="`${static}/loadImage/knowledge-2.png`"
|
||||
alt=""
|
||||
style="height: 30px"
|
||||
/>
|
||||
@@ -162,6 +162,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
static: process.env.VUE_APP_STATIC,
|
||||
form: {
|
||||
// 是否启用rerank模型
|
||||
rerankingEnable: true,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<!-- src/views/knowledge/detail/components/DocumentDrawer.vue -->
|
||||
<template>
|
||||
<el-drawer
|
||||
:visible.sync="visible"
|
||||
:visible.sync="drawerVisible"
|
||||
size="80%"
|
||||
:wrapperClosable="false"
|
||||
@close="$emit('update:visible', false)"
|
||||
@close="drawerVisible = false"
|
||||
>
|
||||
<!-- drawer title -->
|
||||
<template #title>
|
||||
@@ -54,24 +54,22 @@
|
||||
|
||||
<script>
|
||||
import knowledgeInfo from '@/views/track/views/knowledge-info/Index.vue'
|
||||
import TextModel from './TextModel.vue'
|
||||
import QAModel from './QAModel.vue'
|
||||
import {
|
||||
documentSourceOptions,
|
||||
segmentedModeOptionsMap
|
||||
} from '@/assets/js/utils/utilOptions'
|
||||
import RenderFile from '@/components/RenderFile/Index.vue'
|
||||
import knowledgePng_2 from '@/assets/images/konwledge/knowledge-2.png'
|
||||
import MetadataOperator from '@/views/knowledge/detail/components/metaData/MetadataOperator.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MetadataOperator,
|
||||
TextModel,
|
||||
QAModel,
|
||||
RenderFile,
|
||||
knowledgeInfo
|
||||
},
|
||||
emit: ['update:visible'],
|
||||
props: {
|
||||
visible: Boolean,
|
||||
descriptions: {
|
||||
@@ -89,12 +87,21 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
knowledgePng_2,
|
||||
localActiveSegment: this.activeSegment,
|
||||
documentSourceOptions,
|
||||
metadataDialogVisible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
drawerVisible: {
|
||||
get() {
|
||||
return this.visible
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('update:visible', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeSegment(newVal) {
|
||||
this.localActiveSegment = newVal
|
||||
|
||||
@@ -19,35 +19,53 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="actions ml10 flex align-items-c mr10"
|
||||
style="gap: 10px"
|
||||
class="actions flex align-items-c mr10 "
|
||||
style="gap: 10px;margin-top: -2px"
|
||||
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-switch-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click.native.stop=""-->
|
||||
<!-- v-model="segment.enabled"-->
|
||||
<!-- ></el-switch>-->
|
||||
<el-icon
|
||||
class="el-icon-edit mr10"
|
||||
@click.native.stop="handleSegmentClick(index)"
|
||||
></el-icon>
|
||||
<el-icon
|
||||
class="el-icon-delete mr10"
|
||||
@click.native.stop="deleteSegment(segment, index)"
|
||||
></el-icon>
|
||||
<el-switch
|
||||
size="mini"
|
||||
@click.native.stop=""
|
||||
@change="$event => changeEnable($event, segment.id)"
|
||||
v-model="segment.enabled"
|
||||
></el-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- {{ descriptions.doc_form }}-->
|
||||
<!-- 普通分段-->
|
||||
<div v-if="descriptions.doc_form === 'text_model'">
|
||||
<div>
|
||||
<p class="context">{{ segment.content }}</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>
|
||||
</div>
|
||||
<!-- QA分段-->
|
||||
<div v-else>
|
||||
<div class="context">
|
||||
<p>Q {{ segment.content }}</p>
|
||||
<p>A {{ segment.answer }}</p>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
@@ -70,53 +88,58 @@
|
||||
"
|
||||
>
|
||||
<div class="segment-content">
|
||||
<!-- Q & A-->
|
||||
<div>
|
||||
<div>
|
||||
<p>QUESTION</p>
|
||||
<p contenteditable class="resetHtml" ref="content">
|
||||
<p class="" v-if="descriptions.doc_form !== 'text_model'">
|
||||
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">
|
||||
<div v-if="descriptions.doc_form !== 'text_model'">
|
||||
<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
|
||||
"
|
||||
style="flex-wrap: wrap"
|
||||
>
|
||||
<span>关键词 :</span>
|
||||
<span class="mb10">关键词 :</span>
|
||||
<el-tag
|
||||
v-for="(item, index) in descriptions.data[activeSegment].keywords"
|
||||
:key="index"
|
||||
class="mr10"
|
||||
class="mr10 mb10"
|
||||
size="medium"
|
||||
type="info"
|
||||
:closable="!noEdit"
|
||||
@close="tagClose(item)"
|
||||
:closable="
|
||||
descriptions.data[activeSegment].keywords.length > 1 && !noEdit
|
||||
"
|
||||
@close="tagClose(item, index)"
|
||||
>
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
<el-input
|
||||
class="input-new-tag"
|
||||
class="input-new-tag mb5"
|
||||
v-if="createdTag"
|
||||
v-model="inputValue"
|
||||
ref="saveTagInput"
|
||||
size="small"
|
||||
size="mini"
|
||||
@keyup.enter.native="handleInputConfirm"
|
||||
/>
|
||||
<el-button
|
||||
v-if="!noEdit && !createdTag"
|
||||
size="medium"
|
||||
@click="showInput"
|
||||
class="fs12"
|
||||
class="fs12 mb10"
|
||||
style="padding: 7px;border-radius: 4px;font-size: 12px"
|
||||
>添加标签</el-button
|
||||
>
|
||||
@@ -133,7 +156,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { segmentUpdate } from '@/api/generatedApi'
|
||||
import { segmentUpdate, segmentDelete } from '@/api/generatedApi'
|
||||
|
||||
export default {
|
||||
name: 'QAModel',
|
||||
@@ -152,6 +175,7 @@ export default {
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
data() {
|
||||
return {
|
||||
createdTag: false,
|
||||
@@ -160,10 +184,23 @@ export default {
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
inject: ['changeEnable'],
|
||||
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',
|
||||
'提示'
|
||||
@@ -173,7 +210,7 @@ export default {
|
||||
let params = {
|
||||
keywords: this.descriptions.data[this.activeSegment].keywords,
|
||||
content: this.$refs.content.innerHTML,
|
||||
answer: this.$refs.answer.innerHTML
|
||||
answer: this.$refs.answer ? this.$refs.answer.innerHTML : undefined
|
||||
}
|
||||
this.saveSegment(params, () => {
|
||||
this.$message.success('保存成功')
|
||||
@@ -183,20 +220,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
|
||||
answer: this.$refs.answer ? this.$refs.answer.innerHTML : undefined
|
||||
}
|
||||
this.saveSegment(params)
|
||||
// this.saveSegment(params)
|
||||
},
|
||||
|
||||
handleInputConfirm() {
|
||||
@@ -206,7 +238,7 @@ export default {
|
||||
this.inputValue
|
||||
],
|
||||
content: this.$refs.content.innerHTML,
|
||||
answer: this.$refs.answer.innerHTML
|
||||
answer: this.$refs.answer ? this.$refs.answer.innerHTML : undefined
|
||||
}
|
||||
this.saveSegment(params)
|
||||
},
|
||||
@@ -252,6 +284,7 @@ export default {
|
||||
width: 100%;
|
||||
//height: 400px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.context {
|
||||
color: #3a3f4f;
|
||||
@@ -265,6 +298,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;
|
||||
}
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
<template>
|
||||
<div class="segment-split-view">
|
||||
<div class="segment-list">
|
||||
<!-- <el-checkbox-group v-model="selectedSegments">-->
|
||||
<div
|
||||
class="segment-list-item"
|
||||
v-for="(segment, index) in descriptions.data"
|
||||
:key="index"
|
||||
:class="{ active: activeSegment === index }"
|
||||
@click="handleSegmentClick(index)"
|
||||
>
|
||||
<div class="flex align-items-c justify-content-b" style="gap: 8px">
|
||||
<div class="flex align-items-c " style="gap: 8px">
|
||||
<!-- <el-checkbox class="mr pt15" :label="index">-->
|
||||
<span class="el-icon-s-unfold"></span>
|
||||
<span class="segment-number"
|
||||
>分段 - {{ (index + 1).toString().padStart(2, '0') }}</span
|
||||
>
|
||||
<span v-if="segment.word_count > 0">
|
||||
· {{ segment.word_count }}个字符 ·</span
|
||||
>
|
||||
<span> {{ segment.hit_count }} 次召回次数</span>
|
||||
</div>
|
||||
<div
|
||||
class="actions ml10 flex align-items-c mr10"
|
||||
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-switch-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click.native.stop=""-->
|
||||
<!-- v-model="segment.enabled"-->
|
||||
<!-- ></el-switch>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- </el-checkbox>-->
|
||||
<div>
|
||||
<div>
|
||||
<p class="context">{{ segment.content }}</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>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </el-checkbox-group>-->
|
||||
</div>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<el-drawer
|
||||
title="分段详情"
|
||||
:wrapperClosable="false"
|
||||
:visible.sync="dialogVisible"
|
||||
:modal="false"
|
||||
append-to-body
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<div
|
||||
style="height:calc(100% - 32px);overflow-x: hidden;overflow-y: auto"
|
||||
v-if="
|
||||
activeSegment !== null &&
|
||||
descriptions.data &&
|
||||
descriptions.data.length > 0
|
||||
"
|
||||
>
|
||||
<div class="segment-content">
|
||||
<p contenteditable class="resetHtml" ref="content">
|
||||
{{ descriptions.data[activeSegment].content }}
|
||||
</p>
|
||||
<div
|
||||
class="flex align-items-c mt20"
|
||||
v-if="
|
||||
descriptions.data[activeSegment].keywords &&
|
||||
descriptions.data[activeSegment].keywords.length
|
||||
"
|
||||
style="flex-wrap: wrap"
|
||||
>
|
||||
<span>关键词 :</span>
|
||||
<el-tag
|
||||
v-for="(item, index) in descriptions.data[activeSegment].keywords"
|
||||
:key="index"
|
||||
class="mr10 ellipsis"
|
||||
size="medium"
|
||||
:closable="!noEdit"
|
||||
type="info"
|
||||
@close="tagClose(item)"
|
||||
>
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
<el-input
|
||||
class="input-new-tag"
|
||||
v-if="createdTag"
|
||||
v-model="inputValue"
|
||||
ref="saveTagInput"
|
||||
size="small"
|
||||
@keyup.enter.native="handleInputConfirm"
|
||||
/>
|
||||
<el-button
|
||||
v-if="!noEdit && !createdTag"
|
||||
size="medium"
|
||||
@click="showInput"
|
||||
class="fs12"
|
||||
style="padding: 7px;border-radius: 4px;font-size: 12px"
|
||||
>添加标签</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<el-button @click="dialogVisible = false" size="medium">关闭</el-button>
|
||||
<el-button @click="saveUS" size="medium" type="primary" v-if="!noEdit"
|
||||
>保存</el-button
|
||||
>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { segmentUpdate } from '@/api/generatedApi'
|
||||
|
||||
export default {
|
||||
name: 'TextModel',
|
||||
props: {
|
||||
noEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
visible: Boolean,
|
||||
descriptions: {
|
||||
type: Object,
|
||||
default: () => ({ data: [] })
|
||||
},
|
||||
parentForm: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createdTag: false,
|
||||
inputValue: '',
|
||||
activeSegment: null,
|
||||
dialogVisible: false,
|
||||
selectedSegments: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteSegment() {
|
||||
this.$messageBox(
|
||||
() => {},
|
||||
'是否删除当前分段,删除后不可恢复',
|
||||
'warning',
|
||||
'提示'
|
||||
)
|
||||
},
|
||||
|
||||
saveUS() {
|
||||
let params = {
|
||||
keywords: this.descriptions.data[this.activeSegment].keywords,
|
||||
content: this.$refs.content.innerHTML,
|
||||
answer: null
|
||||
}
|
||||
this.saveSegment(params, () => {
|
||||
this.$message.success('保存成功')
|
||||
})
|
||||
},
|
||||
|
||||
showInput() {
|
||||
this.createdTag = true
|
||||
},
|
||||
tagClose() {
|
||||
this.descriptions.data[this.activeSegment].keywords.splice(
|
||||
this.descriptions.data[this.activeSegment].keywords.indexOf(
|
||||
this.inputValue
|
||||
),
|
||||
1
|
||||
)
|
||||
|
||||
let params = {
|
||||
keywords: this.descriptions.data[this.activeSegment].keywords,
|
||||
content: this.$refs.content.innerHTML,
|
||||
answer: null
|
||||
}
|
||||
this.saveSegment(params)
|
||||
},
|
||||
|
||||
handleInputConfirm() {
|
||||
let params = {
|
||||
keywords: [
|
||||
...this.descriptions.data[this.activeSegment].keywords,
|
||||
this.inputValue
|
||||
],
|
||||
content: this.$refs.content.innerHTML,
|
||||
answer: null
|
||||
}
|
||||
this.saveSegment(params)
|
||||
},
|
||||
|
||||
saveSegment(params, fun) {
|
||||
params.documentId = this.parentForm.id
|
||||
params.segmentId = this.descriptions.data[this.activeSegment].id
|
||||
segmentUpdate(params).then(res => {
|
||||
if (res) {
|
||||
this.descriptions.data[this.activeSegment] = JSON.parse(
|
||||
JSON.stringify(res.content.content)
|
||||
)
|
||||
// res.content.content.keywords
|
||||
// this.descriptions.data[this.activeSegment].content =
|
||||
// res.content.content.content
|
||||
// this.descriptions.data[this.activeSegment].answer =
|
||||
// res.content.content.answer
|
||||
this.createdTag = false
|
||||
this.inputValue = ''
|
||||
if (fun) {
|
||||
fun()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
handleSegmentClick(index) {
|
||||
this.activeSegment = index
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.segment-split-view {
|
||||
display: block;
|
||||
}
|
||||
.context {
|
||||
width: auto;
|
||||
overflow: hidden;
|
||||
//省略号
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
color: #3a3f4f;
|
||||
font-size: 14px;
|
||||
}
|
||||
.segment-list {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.segment-list-item {
|
||||
color: #70778d;
|
||||
cursor: pointer;
|
||||
padding: 15px 0 20px 15px;
|
||||
border-radius: 2px;
|
||||
transition: background-color 0.3s;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #f3f5f7;
|
||||
//margin-bottom: 10px;
|
||||
|
||||
&:hover {
|
||||
background: #f3f5f7;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #f3f5f7;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.segment-number {
|
||||
//color: #0a84ff;
|
||||
}
|
||||
|
||||
.segment-keywords {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #70778d;
|
||||
flex-wrap: wrap;
|
||||
|
||||
p {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.segment-content {
|
||||
padding: 20px;
|
||||
background: #f9f9f9;
|
||||
border-radius: 15px;
|
||||
//white-space: pre-wrap;
|
||||
line-height: 35px;
|
||||
color: #666;
|
||||
}
|
||||
.input-new-tag {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,216 @@
|
||||
<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"
|
||||
:key="index"
|
||||
@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>
|
||||
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="container batchAdd-container">
|
||||
<!-- 文件上传区域 -->
|
||||
<div
|
||||
@click.stop="createFile"
|
||||
@dragover.prevent="handleDragOver"
|
||||
@dragleave.prevent="handleDragLeave"
|
||||
@drop.prevent="handleDrop"
|
||||
class="upload-container"
|
||||
:class="{ 'drag-over': isDragOver }"
|
||||
>
|
||||
<el-empty v-if="fileList.length === 0">
|
||||
<template #image>
|
||||
<img :src="uploadPng" alt="" style="width: 50px;height: 50px;" />
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="flex flex-direction-c">
|
||||
<span class="upload-tip">点击或将文件拖拽到这里上传</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-empty>
|
||||
<div v-else @click.stop="">
|
||||
<div
|
||||
class="file-preview-container align-items-c justify-content-b mh20"
|
||||
v-for="item in fileList"
|
||||
>
|
||||
<div class="flex align-items-c fs12">
|
||||
<img
|
||||
:src="uploadPng"
|
||||
alt="CSV Icon"
|
||||
style="width: 25px;height: 30px"
|
||||
/>
|
||||
<span class="file-name fs12 ml20 fw500">{{ item.name }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-button type="primary" size="medium" @click.stop="removeFile(0)"
|
||||
>移除</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uploadPng from '@/assets/images/konwledge/upload.png'
|
||||
|
||||
export default {
|
||||
name: 'batchAddSegment',
|
||||
data() {
|
||||
return {
|
||||
uploadPng,
|
||||
fileList: [], // 文件列表
|
||||
isDragOver: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
fileList: {
|
||||
handler(newValue, oldValue) {
|
||||
if (newValue.length > 0) {
|
||||
this.$emit('getFileList', newValue)
|
||||
} else {
|
||||
this.$emit('getFileList', [])
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 生成filed
|
||||
createFile() {
|
||||
let input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = '.xlsx,.doc,.docx,.pdf,.txt'
|
||||
|
||||
input.onchange = e => {
|
||||
const newFiles = Array.from(e.target.files)
|
||||
if (this.fileList.length + newFiles.length > 1) {
|
||||
this.$message.error('最多只能上传1个文件')
|
||||
return
|
||||
}
|
||||
|
||||
this.fileList = [...this.fileList, ...newFiles]
|
||||
}
|
||||
input.click()
|
||||
},
|
||||
|
||||
// 新增:移除文件
|
||||
removeFile(index) {
|
||||
this.fileList.splice(index, 1)
|
||||
},
|
||||
|
||||
handleDragOver() {
|
||||
this.isDragOver = true
|
||||
},
|
||||
|
||||
handleDragLeave() {
|
||||
this.isDragOver = false
|
||||
},
|
||||
|
||||
handleDrop(event) {
|
||||
this.isDragOver = false
|
||||
const files = event.dataTransfer.files
|
||||
if (this.fileList.length + files.length > 1) {
|
||||
this.$message.error('最多只能上传1个文件')
|
||||
return
|
||||
}
|
||||
this.fileList = [...this.fileList, ...Array.from(files)]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.file-preview-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
//background-color: #f5f5f5; // 灰色背景
|
||||
padding: 15px 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
margin-left: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.upload-container {
|
||||
border-radius: 6px;
|
||||
border-style: dashed;
|
||||
border-width: 1px;
|
||||
border-color: #d9d9d9;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&.drag-over {
|
||||
border-color: var(--color-primary);
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #5f5e68;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.upload-tip-field {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
color: #b1b5c7;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
@@ -54,10 +54,10 @@
|
||||
>
|
||||
<div class="metadata-form">
|
||||
<div class="form-item">
|
||||
<label class="form-label">元数据类型</label>
|
||||
<label class="form-label">元数据</label>
|
||||
<el-select
|
||||
v-model="dialog.metadataId"
|
||||
placeholder="请选择元数据类型"
|
||||
placeholder="请选择元数据"
|
||||
filterable
|
||||
class="full-width"
|
||||
size="medium"
|
||||
@@ -143,10 +143,10 @@
|
||||
>
|
||||
<div class="metadata-form">
|
||||
<div class="form-item">
|
||||
<label class="form-label">元数据类型</label>
|
||||
<label class="form-label">元数据</label>
|
||||
<el-input
|
||||
v-model="editDialog.metadataKey"
|
||||
placeholder="元数据类型"
|
||||
placeholder="元数据"
|
||||
class="full-width"
|
||||
size="medium"
|
||||
disabled
|
||||
@@ -210,8 +210,6 @@ import {
|
||||
updateMetaDataDoc
|
||||
} from '@/api/generatedApi'
|
||||
import MeteData from '@/views/knowledge/detail/components/metaData/Index.vue'
|
||||
import { data } from 'autoprefixer'
|
||||
|
||||
export default {
|
||||
name: 'MetadataOperator',
|
||||
components: { MeteData },
|
||||
@@ -239,7 +237,6 @@ export default {
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
data,
|
||||
init(id) {
|
||||
this.documentId = id
|
||||
this.getDocList()
|
||||
@@ -314,7 +311,7 @@ export default {
|
||||
// 这里可以添加保存逻辑
|
||||
this.dialog.visible = false
|
||||
} else {
|
||||
this.$message.warning('请选择元数据类型并输入值')
|
||||
this.$message.warning('请选择元数据并输入值')
|
||||
}
|
||||
},
|
||||
toMetaData() {
|
||||
|
||||
@@ -1,49 +1,102 @@
|
||||
<template>
|
||||
<div id="preprocessing-container " class="mt20">
|
||||
<el-form label-width="180px" :model="form" ref="processForm">
|
||||
<el-form-item label="数据来源:" required prop="radio" position="top" class="el-form--label-top">
|
||||
<el-radio-group v-model="form.radio" size="medium" @change="getFileType">
|
||||
<el-radio-button label="1" size="medium">使用本地文件</el-radio-button>
|
||||
<el-radio-button label="2" size="medium">使用通用知识文件模板</el-radio-button>
|
||||
<el-form-item
|
||||
label="数据来源:"
|
||||
required
|
||||
prop="radio"
|
||||
position="top"
|
||||
class="el-form--label-top"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.radio"
|
||||
size="medium"
|
||||
@change="getFileType"
|
||||
>
|
||||
<el-radio-button label="1" size="medium"
|
||||
>使用本地文件</el-radio-button
|
||||
>
|
||||
<el-radio-button label="2" size="medium"
|
||||
>使用通用知识文件模板</el-radio-button
|
||||
>
|
||||
</el-radio-group>
|
||||
|
||||
<div class="mt10" v-if="form.radio === '2'">
|
||||
<el-button type="primary" size="medium" class="fs14" @click="downloadTemplate">下载知识文件模板</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="fs14"
|
||||
@click="downloadTemplate"
|
||||
>下载知识文件模板</el-button
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- 文件上传-->
|
||||
<el-form-item label="" required prop="file" label-width="0" class="el-form--label-top">
|
||||
<el-form-item
|
||||
label=""
|
||||
required
|
||||
prop="file"
|
||||
label-width="0"
|
||||
class="el-form--label-top"
|
||||
>
|
||||
<div
|
||||
@click="createFiled"
|
||||
@click.stop="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="fileList.length === 0">
|
||||
<template #image>
|
||||
<img :src="uloadPng" alt="" style='width: 50px;height: 50px;'></img>
|
||||
<img :src="uloadPng" alt="" style="width: 50px;height: 50px;" />
|
||||
</template>
|
||||
<template #description>
|
||||
<div class='flex flex-direction-c'>
|
||||
<span class='upload-tip'>点击或将文件拖拽到这里上传</span>
|
||||
<span class='upload-tip-field'>支持扩展名:.xlsx.doc.pdf.txt.docx</span>
|
||||
<div class="flex flex-direction-c">
|
||||
<span class="upload-tip">点击或将文件拖拽到这里上传</span>
|
||||
<span class="upload-tip-field"
|
||||
>支持扩展名:.xlsx.doc.pdf.txt.docx</span
|
||||
>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</el-empty>
|
||||
<el-result
|
||||
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">
|
||||
<el-button type="primary" size="medium" @click.stop="createFiled">重新上传</el-button>
|
||||
</template>
|
||||
</el-result>
|
||||
<div v-else>
|
||||
<el-result
|
||||
v-if="fileList.length === 1"
|
||||
icon="success"
|
||||
title="文件上传成功"
|
||||
:sub-title="`已上传文件:${fileList[0].name}`"
|
||||
style="height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center;"
|
||||
>
|
||||
<template slot="extra">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="medium"
|
||||
@click.stop="removeFile(0)"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-result>
|
||||
|
||||
<el-result v-else class="more-files">
|
||||
<template slot="icon">
|
||||
<div class="text-left">
|
||||
<el-button class="line-button" size="medium">
|
||||
文件上传</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template slot="extra" style="width: 100%;">
|
||||
<r-table
|
||||
:data="fileList"
|
||||
:columns="columns"
|
||||
style="width: 100%;"
|
||||
@removeFiled="removeFiled"
|
||||
:deletion="false"
|
||||
></r-table>
|
||||
</template>
|
||||
</el-result>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@@ -52,21 +105,40 @@
|
||||
<el-form-item label="是否进行预处理:" required prop="beMinerU">
|
||||
<template slot="label">
|
||||
是否进行预处理
|
||||
<el-tooltip class="item" effect="dark" content="通过整合最先进的文档解析模型来提高内容提取质量" placement="top">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
content="通过整合最先进的文档解析模型来提高内容提取质量"
|
||||
placement="top"
|
||||
>
|
||||
<i class="el-icon-info ml5" style="color: #909399;"></i>
|
||||
</el-tooltip>
|
||||
:
|
||||
</template>
|
||||
<el-switch v-model="form.beMinerU" size="medium">
|
||||
<el-switch
|
||||
v-model="form.beMinerU"
|
||||
size="medium"
|
||||
:disabled="fileList.length > 1"
|
||||
>
|
||||
<!-- <el-radio :label="true" size="medium">是</el-radio>-->
|
||||
<!-- <el-radio :label="false" size="medium">否</el-radio>-->
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="是否ocr协助处理:" v-if="form.beMinerU" required prop="beOcr">
|
||||
<el-form-item
|
||||
label="是否ocr协助处理:"
|
||||
v-if="form.beMinerU"
|
||||
required
|
||||
prop="beOcr"
|
||||
>
|
||||
<template slot="label">
|
||||
是否ocr协助处理
|
||||
<el-tooltip class="item" effect="dark" content="能更好的协助处理图片、表格类数据" placement="top">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
content="能更好的协助处理图片、表格类数据"
|
||||
placement="top"
|
||||
>
|
||||
<i class="el-icon-info ml5" style="color: #909399;"></i>
|
||||
</el-tooltip>
|
||||
:
|
||||
@@ -87,16 +159,18 @@
|
||||
<!-- </el-drawer>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadFileByCustom, uploadFileByTemplate } from '@/api/generatedApi'
|
||||
import { downloadKnowledgeTemplate } from '@/api/knowledge/task-page'
|
||||
import uloadPng from '@/assets/images/konwledge/upload.png'
|
||||
|
||||
export default {
|
||||
name: 'preprocessing',
|
||||
data() {
|
||||
return {
|
||||
uloadPng,
|
||||
filed: null,
|
||||
fileList: [], // 文件列表
|
||||
uploadLoading: false,
|
||||
headers: {},
|
||||
fieldList: [],
|
||||
@@ -106,31 +180,84 @@ export default {
|
||||
beOcr: false,
|
||||
datasetId: this.$route.query.datasetId
|
||||
},
|
||||
previewDialogVisible: false, // 添加对话框显示控制变量
|
||||
previewDialogVisible: false,
|
||||
documentId: '',
|
||||
isDragOver: false
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
watch: {
|
||||
'form.beMinerU': {
|
||||
handler(value) {
|
||||
// 如果不进行预处理,不进行ocr
|
||||
if (!value) {
|
||||
this.form.beOcr = false
|
||||
fileList: {
|
||||
handler(val) {
|
||||
if (val.length > 1) {
|
||||
this.form.beMinerU = false
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
filters: {},
|
||||
computed: {
|
||||
columns: vm => {
|
||||
return [
|
||||
{
|
||||
type: 'index',
|
||||
title: '序号'
|
||||
},
|
||||
{
|
||||
title: '文件名称',
|
||||
prop: 'name'
|
||||
},
|
||||
{
|
||||
title: '文件大小',
|
||||
prop: 'size',
|
||||
render: (h, params) => {
|
||||
return h('span', vm.formatFileSize(params.row.size))
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '文件类型',
|
||||
prop: 'type',
|
||||
render: (h, params) => {
|
||||
// 根据文件类型展示 是什么类型文件
|
||||
switch (params.row.type) {
|
||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
||||
return h('span', 'Excel')
|
||||
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
||||
return h('span', 'Word')
|
||||
case 'application/pdf':
|
||||
return h('span', 'PDF')
|
||||
case 'text/plain':
|
||||
return h('span', 'TXT')
|
||||
}
|
||||
return h('span', params.row.type)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
selfBtn: [
|
||||
{
|
||||
name: '移除',
|
||||
size: 'mini',
|
||||
type: 'primary',
|
||||
method: 'removeFiled',
|
||||
class: 'tableBtn'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeFiled(item) {
|
||||
this.removeFile(item.index)
|
||||
},
|
||||
|
||||
formatFileSize(size) {
|
||||
return (size / 1024 / 1024).toFixed(2) + 'MB'
|
||||
},
|
||||
getFileType() {
|
||||
this.$emit('getFileType', this.form.radio)
|
||||
},
|
||||
downloadTemplate() {
|
||||
console.log(`下载模板的链接是:${downloadKnowledgeTemplate().url}`)
|
||||
window.open(downloadKnowledgeTemplate().url, '_blank')
|
||||
},
|
||||
|
||||
@@ -138,18 +265,40 @@ export default {
|
||||
createFiled() {
|
||||
let input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.multiple = true // 支持多文件选择
|
||||
|
||||
// 对文件的类型做出限制
|
||||
input.accept = '.xlsx,.doc,.docx,.pdf,.txt'
|
||||
|
||||
input.onchange = e => {
|
||||
this.filed = e.target.files[0]
|
||||
const newFiles = Array.from(e.target.files)
|
||||
if (this.fileList.length + newFiles.length > 10) {
|
||||
this.$message.error('最多只能上传10个文件')
|
||||
return
|
||||
}
|
||||
|
||||
// 校验 最新上传的文件是否之前上传过
|
||||
for (let i = 0; i < newFiles.length; i++) {
|
||||
for (let j = 0; j < this.fileList.length; j++) {
|
||||
if (newFiles[i].name === this.fileList[j].name) {
|
||||
this.$message.error('请勿重复上传文件,请检查文件')
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.fileList = [...this.fileList, ...newFiles] // 将新选择的文件添加到文件列表
|
||||
}
|
||||
input.click()
|
||||
},
|
||||
|
||||
// 新增:移除文件
|
||||
removeFile(index) {
|
||||
this.fileList.splice(index, 1)
|
||||
},
|
||||
|
||||
uploadFiled(back) {
|
||||
if (!this.filed) {
|
||||
if (this.fileList.length === 0) {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '请上传文件'
|
||||
@@ -159,17 +308,20 @@ export default {
|
||||
|
||||
// 0否 1是
|
||||
let formData = new FormData()
|
||||
formData.append('file', this.filed)
|
||||
this.fileList.forEach(file => {
|
||||
formData.append('file', file)
|
||||
})
|
||||
formData.append('datasetId', this.form.datasetId)
|
||||
let api = this.form.radio === '1' ? uploadFileByCustom : uploadFileByTemplate
|
||||
let api =
|
||||
this.form.radio === '1' ? uploadFileByCustom : uploadFileByTemplate
|
||||
if (this.form.radio === '1') {
|
||||
formData.append('useMinerU', this.form.beMinerU ? '1': '0')
|
||||
formData.append('useOcr', this.form.beOcr? '1': '0')
|
||||
formData.append('useMinerU', this.form.beMinerU ? '1' : '0')
|
||||
formData.append('useOcr', this.form.beOcr ? '1' : '0')
|
||||
}
|
||||
api(formData).then(response => {
|
||||
if(response){
|
||||
if (response) {
|
||||
this.documentId = response.content.content
|
||||
if(back){
|
||||
if (back) {
|
||||
back(this.documentId)
|
||||
} else {
|
||||
// 向上导入documentId
|
||||
@@ -183,10 +335,9 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
handleDragOver() {
|
||||
this.isDragOver = true
|
||||
},
|
||||
@@ -198,8 +349,13 @@ export default {
|
||||
handleDrop(event) {
|
||||
this.isDragOver = false
|
||||
const files = event.dataTransfer.files
|
||||
this.filed = files[0]
|
||||
if (this.fileList.length + files.length > 10) {
|
||||
this.$message.error('最多只能上传10个文件')
|
||||
return
|
||||
}
|
||||
this.fileList = [...this.fileList, ...Array.from(files)] // 将拖拽的文件添加到文件列表
|
||||
},
|
||||
|
||||
handleUploadSuccess(response, file) {
|
||||
this.fieldList = [file]
|
||||
this.uploadLoading = false
|
||||
@@ -236,30 +392,35 @@ export default {
|
||||
// 返回 true 继续上传,返回 false 停止上传
|
||||
return true
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
computed: {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.more-files > .el-result__extra,
|
||||
.more-files > .el-result__icon {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/assets/sass/renderSass/theme.scss';
|
||||
.flex-direction-c{
|
||||
.flex-direction-c {
|
||||
flex-direction: column;
|
||||
line-height: 20px;
|
||||
}
|
||||
.upload-tip{
|
||||
.upload-tip {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
color: #5F5E68;
|
||||
color: #5f5e68;
|
||||
font-style: normal;
|
||||
}
|
||||
.upload-tip-field{
|
||||
.upload-tip-field {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
color: #B1B5C7;
|
||||
color: #b1b5c7;
|
||||
font-style: normal;
|
||||
}
|
||||
.upload-demo {
|
||||
|
||||
@@ -283,7 +283,6 @@ export default {
|
||||
},
|
||||
async getRuleList() {
|
||||
let res = await getRulesList({ ruleType: 1 })
|
||||
console.log(res)
|
||||
this.ruleList = res.content.content
|
||||
},
|
||||
// 获取详情
|
||||
@@ -311,7 +310,6 @@ export default {
|
||||
})
|
||||
},
|
||||
queryExistingRules(val) {
|
||||
console.log(val)
|
||||
if (val) {
|
||||
this.getDetail(val)
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
<!-- 添加预览组件 -->
|
||||
<split-preview
|
||||
:documentList="documentList"
|
||||
:documentId="documentId"
|
||||
:visible.sync="previewVisible"
|
||||
:preview-data="previewData"
|
||||
@@ -71,6 +72,7 @@
|
||||
@confirm="handlePreviewConfirm"
|
||||
@handleReUpload="handleReUpload"
|
||||
@handleClose="handleClose"
|
||||
@changePage="changePage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -88,6 +90,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
splitIndex: 0,
|
||||
dialogVisible: false,
|
||||
activeIndex: 0,
|
||||
previewVisible: false, // 控制预览组件显示
|
||||
@@ -112,6 +115,10 @@ export default {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
documentList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
documentId: {
|
||||
type: String,
|
||||
default: ''
|
||||
@@ -120,6 +127,10 @@ export default {
|
||||
watch: {},
|
||||
filters: {},
|
||||
methods: {
|
||||
async changePage(index) {
|
||||
this.previewData = await this.getPreviewOperation(this.documentId, index)
|
||||
},
|
||||
|
||||
handleClick(index) {
|
||||
this.activeIndex = index
|
||||
if (index === 1) {
|
||||
@@ -131,10 +142,15 @@ export default {
|
||||
|
||||
// 构建API请求参数
|
||||
buildExecSplitParams(documentId) {
|
||||
const params = {
|
||||
let params = {
|
||||
documentId: documentId,
|
||||
beAuto: this.activeIndex === 0
|
||||
}
|
||||
let splitDocId = documentId.split(',')
|
||||
if (splitDocId.length > 1) {
|
||||
params.documentId = undefined
|
||||
params.documentIds = splitDocId
|
||||
}
|
||||
|
||||
if (!params.beAuto && this.$refs.customTable.ruleId) {
|
||||
params.rulesId = this.$refs.customTable.ruleId
|
||||
@@ -161,7 +177,11 @@ export default {
|
||||
},
|
||||
|
||||
// 获取拆分预览
|
||||
async getPreviewOperation(documentId) {
|
||||
async getPreviewOperation(documentId, index) {
|
||||
let splitDocId = documentId.split(',')
|
||||
if (splitDocId.length > 1) {
|
||||
documentId = splitDocId[index ? index : 0]
|
||||
}
|
||||
const res = await splitResultPreview({ documentId })
|
||||
if (res.content.result !== '0') {
|
||||
const errorMsg =
|
||||
|
||||
@@ -6,6 +6,26 @@
|
||||
width="60%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<template slot="title">
|
||||
<div class="flex align-items-c" style="gap:10px">
|
||||
<span>拆分结果预览</span>
|
||||
<el-dropdown @command="command" trigger="click" size="medium">
|
||||
<span class="el-dropdown-link">
|
||||
{{ documentList[activeIndex].name
|
||||
}}<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item
|
||||
v-for="(item, index) in documentList"
|
||||
:command="index"
|
||||
:key="item.id"
|
||||
>{{ item.name }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-loading="loading" class="preview-content">
|
||||
<template v-if="!loading && previewData">
|
||||
<el-tree
|
||||
@@ -23,7 +43,13 @@
|
||||
</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 size="medium" @click="upFiled">前一个</el-button>-->
|
||||
<!-- <el-button size="medium" @click="downFiled">后一个</el-button>-->
|
||||
<el-button
|
||||
v-if="documentList.length === 1"
|
||||
size="medium"
|
||||
type="primary"
|
||||
@click="handleConfirm"
|
||||
>下一步</el-button
|
||||
>
|
||||
<el-button
|
||||
@@ -44,6 +70,10 @@ import { embedding } from '@/api/generatedApi'
|
||||
export default {
|
||||
name: 'SplitPreview',
|
||||
props: {
|
||||
documentList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
documentId: {
|
||||
type: String,
|
||||
default: ''
|
||||
@@ -66,6 +96,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeIndex: 0,
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'paragraphTitle'
|
||||
@@ -73,6 +104,19 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
upFiled() {
|
||||
this.$emit('changePage', 'up')
|
||||
},
|
||||
downFiled() {
|
||||
this.$emit('changePage', 'down')
|
||||
},
|
||||
command(index) {
|
||||
if (index === this.activeIndex) {
|
||||
return false
|
||||
}
|
||||
this.activeIndex = index
|
||||
this.$emit('changePage', this.activeIndex)
|
||||
},
|
||||
emitKnowledgeDataset() {
|
||||
this.$router.push({
|
||||
path: '/knowledge/reviewKnowledge',
|
||||
@@ -105,7 +149,8 @@ export default {
|
||||
handleConfirm() {
|
||||
this.$emit('confirm')
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
:key="index"
|
||||
>
|
||||
<div class="section-title">
|
||||
拆分规则 {{ index + 1 }}
|
||||
题词规则 {{ index + 1 }}
|
||||
<div>
|
||||
<el-button
|
||||
v-if="!isPreview && form.ruleList.length > 1"
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
:extract-results="extractResults"
|
||||
:is-auto-extract="activeIndex === 0"
|
||||
:loading="previewLoading"
|
||||
:documentList="documentList"
|
||||
@confirm="handlePreviewConfirm"
|
||||
/>
|
||||
</div>
|
||||
@@ -113,7 +114,12 @@ export default {
|
||||
documentId: ''
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
props: {
|
||||
documentList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
filters: {},
|
||||
methods: {
|
||||
@@ -128,10 +134,15 @@ export default {
|
||||
|
||||
// 构建执行题词的参数
|
||||
buildExecExtractParams(documentId) {
|
||||
const params = {
|
||||
let params = {
|
||||
documentId: documentId,
|
||||
beAuto: this.activeIndex === 0
|
||||
}
|
||||
let splitDocIds = documentId.split(',')
|
||||
if (splitDocIds.length > 1) {
|
||||
params.documentId = undefined
|
||||
params.documentIds = splitDocIds
|
||||
}
|
||||
|
||||
if (!params.beAuto && this.$refs.customTable.ruleId) {
|
||||
params.rulesId = this.$refs.customTable.ruleId
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
class="mt10"
|
||||
v-else
|
||||
:documentId="documentId"
|
||||
:documentList="this.documentList"
|
||||
@saveMarkDown="saveMarkDown"
|
||||
></r-miner-u>
|
||||
</div>
|
||||
@@ -58,11 +59,16 @@
|
||||
<step-split-config
|
||||
ref="splitConfig"
|
||||
v-if="active === 1"
|
||||
:documentList="this.documentList"
|
||||
@previewConfirmed="handlePreviewConfirm"
|
||||
@handleReUpload="handleReUpload"
|
||||
:documentId="documentId"
|
||||
></step-split-config>
|
||||
<step-words ref="words" v-if="active === 2"></step-words>
|
||||
<step-words
|
||||
ref="words"
|
||||
v-if="active === 2"
|
||||
:documentList="this.documentList"
|
||||
></step-words>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
@@ -120,7 +126,7 @@ import StepPreprocessing from './components/preprocessing.vue'
|
||||
import SplitConfig from '@/views/knowledge/detail/components/split/Index.vue'
|
||||
import Words from '@/views/knowledge/detail/components/words/Index.vue'
|
||||
import magic from '@/assets/images/konwledge/magic.png'
|
||||
import { directEmbedding } from '@/api/generatedApi'
|
||||
import { datasetDocumentEx, directEmbedding } from '@/api/generatedApi'
|
||||
// import StepC
|
||||
export default {
|
||||
name: 'create',
|
||||
@@ -130,7 +136,8 @@ export default {
|
||||
visible: false,
|
||||
active: 0,
|
||||
documentId: '1365038001244180480',
|
||||
isMd: false
|
||||
isMd: false,
|
||||
documentList: []
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
@@ -185,9 +192,32 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
getDocumentId(id) {
|
||||
async getDocumentId(id) {
|
||||
this.documentId = id
|
||||
|
||||
let splitDocIds = this.documentId.split(',')
|
||||
|
||||
for (let i = 0; i < splitDocIds.length; i++) {
|
||||
let content = await this.getFileDetail(splitDocIds[i])
|
||||
this.documentList.push({
|
||||
name: content.knowledgeName,
|
||||
id: content.id
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 获取文件详情 主要是名字与ID
|
||||
async getFileDetail(documentId) {
|
||||
const res = await datasetDocumentEx({ documentId })
|
||||
if (res.content.result !== '0') {
|
||||
const errorMsg =
|
||||
'获取文件详情失败: ' + (res.content.resultMessage || '未知错误')
|
||||
this.$message.error(errorMsg)
|
||||
throw new Error(errorMsg)
|
||||
}
|
||||
return res.content.content
|
||||
},
|
||||
|
||||
async nextStep() {
|
||||
if (this.active === 0) {
|
||||
this.$refs.stepPreProcessing.uploadFiled()
|
||||
@@ -211,13 +241,17 @@ export default {
|
||||
} else {
|
||||
this.active = 0
|
||||
}
|
||||
|
||||
this.documentList = []
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
mounted() {
|
||||
async mounted() {
|
||||
let { documentId, datasetId, activeLevel, isMd } = this.$route.query
|
||||
if (documentId) {
|
||||
// 继续处理时 调用接口查询文件信息
|
||||
this.documentId = documentId
|
||||
await this.getDocumentId(documentId)
|
||||
}
|
||||
if (activeLevel !== undefined) {
|
||||
this.active = Number(activeLevel)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class=" render-container">
|
||||
<div class="clearfix flex align-items-c justify-content-b ">
|
||||
<div class=" flex align-items-c j">
|
||||
<div class=" flex align-items-c justify-content-b" style="flex:1">
|
||||
<div class="hover-back mr5">
|
||||
<el-icon
|
||||
class="el-icon-arrow-left"
|
||||
@@ -10,11 +10,8 @@
|
||||
></el-icon>
|
||||
</div>
|
||||
|
||||
<img
|
||||
:src="knowledgeImage ? knowledgeImage : knowledgePng_1"
|
||||
class="header-icon"
|
||||
/>
|
||||
<div class="ml20" style="flex:1">
|
||||
<img :src="knowledgeImage" class="header-icon" />
|
||||
<div class="ml10" style="flex:1">
|
||||
<div class="flex align-items-c">
|
||||
<div class="mr20 header" v-if="!editKnowledge">
|
||||
{{ knowledgeName ? knowledgeName : '' }}
|
||||
@@ -32,32 +29,48 @@
|
||||
v-if="!editKnowledge"
|
||||
/>
|
||||
<div v-else>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="medium"
|
||||
class="render-button"
|
||||
@click="saveKnowledgeName"
|
||||
<el-button type="primary" size="medium" @click="saveKnowledgeName"
|
||||
>保存</el-button
|
||||
>
|
||||
<el-button
|
||||
size="medium"
|
||||
class="render-button"
|
||||
@click="cancelKnowledgeName"
|
||||
<el-button size="medium" @click="cancelKnowledgeName"
|
||||
>取消</el-button
|
||||
>
|
||||
</div>
|
||||
<span class="segment-content">{{
|
||||
segmentedMode | filterSegmentedMode
|
||||
}}</span>
|
||||
|
||||
<el-dropdown
|
||||
size="medium"
|
||||
placement="right"
|
||||
v-if="relatedAppList.length > 0"
|
||||
@command="handleRelatedApp"
|
||||
>
|
||||
<span class="segment-content cursor-pointer"
|
||||
>{{ relatedAppList.length }} 个关联应用</span
|
||||
>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="item in relatedAppList"
|
||||
:command="item"
|
||||
:key="item.id"
|
||||
disabled
|
||||
>
|
||||
<span>{{ item.appName }}</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div class="flex align-items-c mt10 ">
|
||||
<p class="fs14 knowledgeDesc" style="line-height: 20px">
|
||||
描述:{{ knowledgeDesc }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="mt10 fs14" style="line-height: 20px">
|
||||
描述:{{ knowledgeDesc }}
|
||||
</p>
|
||||
<!-- <p class="mt10 fs14" style="line-height: 20px">分段模式:{{ segmentedMode | filterSegmentedMode }}</p>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="flex:1" class="text-right">
|
||||
<div style="margin-left: auto" class="text-right">
|
||||
<!-- <el-button type="primary" size="medium" class="normal-button" @click="jumpEditKnowledge">修改知识库</el-button>-->
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -252,7 +265,9 @@ import {
|
||||
datasetQuerySegments,
|
||||
datasetsExPages,
|
||||
datasetUpdate,
|
||||
getDatasetById
|
||||
downloadOriginalFile,
|
||||
getDatasetById,
|
||||
relatedApps
|
||||
} from '@/api/generatedApi'
|
||||
import { getUserList } from '@/api/generatedApi/system'
|
||||
import {
|
||||
@@ -261,7 +276,6 @@ import {
|
||||
} from '@/assets/js/utils/utilOptions'
|
||||
import DocumentDrawer from './components/documentDetail/DocumentDrawer.vue'
|
||||
import knowledgeForm from '@/views/knowledge/detail/components/knowledgeForm.vue'
|
||||
import knowledgePng_1 from '@/assets/images/konwledge/knowledge-1.png'
|
||||
import hitTest from '@/views/knowledge/detail/components/HitTest/Index.vue'
|
||||
import MetaData from '@/views/knowledge/detail/components/metaData/Index.vue'
|
||||
import MetadataOperator from '@/views/knowledge/detail/components/metaData/MetadataOperator.vue'
|
||||
@@ -269,8 +283,16 @@ import SearchSetting from '@/views/knowledge/detail/components/SearchSetting/Ind
|
||||
import { displayStatus } from '@/assets/js/utils/utilOptions'
|
||||
export default {
|
||||
name: 'index',
|
||||
// 父子组件共享
|
||||
provide() {
|
||||
return {
|
||||
viewDocumentDetail: row => this.viewDocumentDetail(row)
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
relatedAppList: [],
|
||||
displayStatus,
|
||||
hitTestConfig: {
|
||||
title: '命中测试',
|
||||
@@ -284,7 +306,6 @@ export default {
|
||||
title: '标注元数据',
|
||||
visible: false
|
||||
},
|
||||
knowledgePng_1,
|
||||
activeName: -1,
|
||||
drawer: false,
|
||||
drawerForm: false,
|
||||
@@ -377,13 +398,6 @@ export default {
|
||||
// 跳转到知识库编辑
|
||||
jumpEditKnowledge() {
|
||||
this.drawerForm = true
|
||||
// let { datasetId } = this.$route.query
|
||||
// this.$router.push({
|
||||
// path: '/knowledge/knowledge-create',
|
||||
// query: {
|
||||
// datasetId: datasetId
|
||||
// }
|
||||
// })
|
||||
},
|
||||
/**
|
||||
* 检索设置
|
||||
@@ -456,24 +470,16 @@ export default {
|
||||
},
|
||||
// 查看文档详情
|
||||
viewDocumentDetail(row) {
|
||||
// 调用查询分段信息接口
|
||||
datasetQuerySegments({ documentId: row.id }).then(res => {
|
||||
if (res) {
|
||||
this.descriptions = {
|
||||
dataset: {
|
||||
knowledgeName: this.knowledgeName,
|
||||
segmentedMode: this.segmentedMode,
|
||||
knowledgeImage: this.knowledgeImage
|
||||
},
|
||||
...row,
|
||||
...res.content.content
|
||||
}
|
||||
this.drawer = true
|
||||
|
||||
// 调用datasetDocumentEx接口获取分词规则和词频规则
|
||||
this.getDocumentExInfo(row.id)
|
||||
this.descriptions = {
|
||||
...row,
|
||||
dataset: {
|
||||
knowledgeName: this.knowledgeName,
|
||||
segmentedMode: this.segmentedMode,
|
||||
knowledgeImage: this.knowledgeImage
|
||||
}
|
||||
})
|
||||
}
|
||||
this.drawer = true
|
||||
this.getDocumentExInfo(row.id)
|
||||
},
|
||||
|
||||
jumpToUpload(params) {
|
||||
@@ -531,6 +537,11 @@ export default {
|
||||
console.error('获取文档详情失败', err)
|
||||
})
|
||||
},
|
||||
// 下载原文件
|
||||
handleDownload(row) {
|
||||
let documentId = row.id
|
||||
window.open(downloadOriginalFile(documentId))
|
||||
},
|
||||
|
||||
// 提取规则文本(处理可能是JSON字符串的情况)
|
||||
extractRuleText(rule) {
|
||||
@@ -584,6 +595,17 @@ export default {
|
||||
},
|
||||
close() {
|
||||
this.metadataOperatorDrawer.visible = false
|
||||
},
|
||||
|
||||
getRelatedApps() {
|
||||
relatedApps({ id: this.$route.query.datasetId }).then(res => {
|
||||
if (res) {
|
||||
this.relatedAppList = res.content.content.intelligentAppDTOS
|
||||
}
|
||||
})
|
||||
},
|
||||
handleRelatedApp(item) {
|
||||
// console.log(item)
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
@@ -611,14 +633,16 @@ export default {
|
||||
this.getKnowledgeFiledList()
|
||||
// 获取用户下拉列表
|
||||
this.getUserData()
|
||||
let documentId = sessionStorage.getItem('documentId')
|
||||
if (documentId) {
|
||||
setTimeout(() => {
|
||||
let row = this.list.filter(item => item.id === documentId)
|
||||
this.viewDocumentDetail(row[0])
|
||||
sessionStorage.removeItem('documentId')
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 获取关联智能体
|
||||
this.getRelatedApps()
|
||||
// let documentId = sessionStorage.getItem('documentId')
|
||||
// if (documentId) {
|
||||
// setTimeout(() => {
|
||||
// let row = this.list.filter(item => item.id === documentId)
|
||||
// this.viewDocumentDetail(row[0])
|
||||
// sessionStorage.removeItem('documentId')
|
||||
// }, 1000)
|
||||
},
|
||||
computed: {
|
||||
datasetId() {
|
||||
@@ -646,17 +670,28 @@ export default {
|
||||
class: 'flex align-items-c'
|
||||
},
|
||||
[
|
||||
h('svg-icon', {
|
||||
props: {
|
||||
iconClass: params.row.useMineru === 1 ? 'miner' : 'none'
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
props: {
|
||||
// iconClass: params.row.useMineru === 1 ? 'miner' : 'none'
|
||||
},
|
||||
class: 'mr5',
|
||||
style: {
|
||||
// display: params.row.useMineru === 1 ? '' : 'none',
|
||||
width: '19px',
|
||||
height: '19px',
|
||||
fontSize: '13px',
|
||||
borderRadius: '6px',
|
||||
textAlign: 'center',
|
||||
lineHeight: '19px',
|
||||
color: '#fff',
|
||||
background:
|
||||
params.row.useMineru === 1 ? '#4f47f5' : 'unset'
|
||||
}
|
||||
},
|
||||
class: 'mr5',
|
||||
style: {
|
||||
// display: params.row.useMineru === 1 ? '' : 'none',
|
||||
width: '15px',
|
||||
fontSize: '15px'
|
||||
}
|
||||
}),
|
||||
params.row.useMineru === 1 ? '预' : ''
|
||||
),
|
||||
h('span', {}, text)
|
||||
]
|
||||
)
|
||||
@@ -762,6 +797,22 @@ export default {
|
||||
}
|
||||
// '标注元数据'
|
||||
),
|
||||
h(
|
||||
'el-button',
|
||||
{
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-download',
|
||||
title: '下载原文件'
|
||||
},
|
||||
on: {
|
||||
click: () => this.handleDownload(params.row)
|
||||
}
|
||||
}
|
||||
// '标注元数据'
|
||||
),
|
||||
params.row.optStatus < 4
|
||||
? h(
|
||||
'el-button',
|
||||
@@ -1003,7 +1054,7 @@ export default {
|
||||
line-height: 17px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
margin-left: 20px;
|
||||
margin-left: 10px;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
@@ -1044,4 +1095,13 @@ export default {
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.knowledgeDesc {
|
||||
display: -webkit-box; // 支持多行省略
|
||||
-webkit-line-clamp: 1; // 限制为两行
|
||||
-webkit-box-orient: vertical; // 垂直方向排列
|
||||
overflow: hidden; // 隐藏超出部分
|
||||
text-overflow: ellipsis; // 显示省略号
|
||||
max-width: 80%; // 限制宽度
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
placement="top"
|
||||
width="400"
|
||||
trigger="hover"
|
||||
content="设置分段之间的重叠长度可以保留分段之间的语义关系,提升召回效果。建议设置为最大分段长度的1096-25%。"
|
||||
content="设置分段之间的重叠长度可以保留分段之间的语义关系,提升召回效果。建议设置为最大分段长度的10%-25%。"
|
||||
>
|
||||
<el-icon
|
||||
class="el-icon-question"
|
||||
@@ -141,9 +141,24 @@
|
||||
style="width: 49.5%;height: calc(100vh - 110px)"
|
||||
class="el-card review"
|
||||
>
|
||||
<div class="title">
|
||||
{{ documentDetail.knowledgeName }}
|
||||
|
||||
<div class="title flex align-items-c" style="gap: 10px">
|
||||
<el-dropdown @command="command" trigger="click" size="medium">
|
||||
<span class="el-dropdown-link">
|
||||
{{
|
||||
documentDetail.length > 0
|
||||
? documentDetail[activeIndex].name
|
||||
: ''
|
||||
}}<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item
|
||||
v-for="(item, index) in documentDetail"
|
||||
:command="index"
|
||||
:key="item.id"
|
||||
>{{ item.name }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<span class="block" v-if="viewsDetail.total_segments">
|
||||
预估块{{ viewsDetail.total_segments }}
|
||||
</span>
|
||||
@@ -256,7 +271,8 @@ export default {
|
||||
chunkOverlap: 400
|
||||
},
|
||||
datasetDetail: {},
|
||||
documentDetail: {},
|
||||
activeIndex: 0,
|
||||
documentDetail: [],
|
||||
viewsDetail: {}
|
||||
}
|
||||
},
|
||||
@@ -265,12 +281,24 @@ export default {
|
||||
components: {},
|
||||
filters: {},
|
||||
methods: {
|
||||
command(index) {
|
||||
if (index === this.activeIndex) {
|
||||
return
|
||||
}
|
||||
this.activeIndex = index
|
||||
|
||||
this.review_logs()
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.form = JSON.parse(JSON.stringify(this.reset))
|
||||
},
|
||||
|
||||
review_logs() {
|
||||
let { documentId, active } = this.$route.query
|
||||
|
||||
let splitDocIds = documentId.split(',')
|
||||
|
||||
let api = segmentEstimate
|
||||
switch (active) {
|
||||
case '0':
|
||||
@@ -287,7 +315,7 @@ export default {
|
||||
break
|
||||
}
|
||||
api({
|
||||
documentId,
|
||||
documentId: splitDocIds[this.activeIndex],
|
||||
segmentConfig: {
|
||||
...this.form,
|
||||
removeExtraSpaces: this.form.removeExtraSpaces ? 1 : 0,
|
||||
@@ -299,13 +327,18 @@ export default {
|
||||
},
|
||||
|
||||
// 获取文档详情
|
||||
getDocumentDetail() {
|
||||
async getDocumentDetail() {
|
||||
let { documentId } = this.$route.query
|
||||
datasetDocumentEx({ documentId }).then(res => {
|
||||
if (res) {
|
||||
this.documentDetail = res.content.content
|
||||
}
|
||||
})
|
||||
|
||||
let splitDocIds = documentId.split(',')
|
||||
|
||||
for (let i = 0; i < splitDocIds.length; i++) {
|
||||
let content = await datasetDocumentEx({ documentId: splitDocIds[i] })
|
||||
this.documentDetail.push({
|
||||
name: content.content.content.knowledgeName,
|
||||
id: content.content.content.id
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 获取知识库详情
|
||||
@@ -320,6 +353,8 @@ export default {
|
||||
// 保存 处理
|
||||
saveUs() {
|
||||
let { documentId, active } = this.$route.query
|
||||
|
||||
let splitDocIds = documentId.split(',')
|
||||
let api = directEmbedding
|
||||
switch (active) {
|
||||
case '0':
|
||||
@@ -336,14 +371,21 @@ export default {
|
||||
break
|
||||
}
|
||||
|
||||
api({
|
||||
let params = {
|
||||
documentId,
|
||||
segmentConfig: {
|
||||
...this.form,
|
||||
removeExtraSpaces: this.form.removeExtraSpaces ? 1 : 0,
|
||||
removeUrlsEmails: this.form.removeUrlsEmails ? 1 : 0
|
||||
}
|
||||
}).then(res => {
|
||||
}
|
||||
|
||||
if (splitDocIds.length > 1) {
|
||||
params.documentIds = splitDocIds
|
||||
params.documentId = undefined
|
||||
}
|
||||
|
||||
api(params).then(res => {
|
||||
if (res) {
|
||||
this.$router.push({
|
||||
path: '/knowledge/detail',
|
||||
@@ -403,7 +445,7 @@ export default {
|
||||
& .review {
|
||||
& .title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
//line-height: 40px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="ledge-list mt20">
|
||||
<div class="ledge-list mt10 ">
|
||||
<el-card
|
||||
v-for="(item, index) in datasetList"
|
||||
class="item datasetList"
|
||||
@@ -57,13 +57,9 @@
|
||||
:key="index"
|
||||
@click.native.stop="knowLedgeDetail(item)"
|
||||
>
|
||||
<div class="dataset-header">
|
||||
<div class="dataset-header mb10">
|
||||
<div class="folder-content">
|
||||
<img
|
||||
:src="item.image ? item.image : getKnowledgeImage(index)"
|
||||
alt=""
|
||||
class="folder"
|
||||
/>
|
||||
<img :src="item.image" alt="" class="folder" />
|
||||
</div>
|
||||
<div class="dataset-body" style="flex:1">
|
||||
<h4 class="dataset-title">{{ item.name }}</h4>
|
||||
@@ -71,10 +67,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex align-items-c justify-content-b mh20 mv10">
|
||||
<div class="flex align-items-c justify-content-b mh20 mv5">
|
||||
<div class="theme-primary-desc-text-drank fs12">
|
||||
{{ item.segmentedMode | filterSegmentedMode }}
|
||||
</div>
|
||||
|
||||
<div class="opacity-button">
|
||||
<el-button
|
||||
class="default "
|
||||
@@ -109,25 +106,11 @@
|
||||
<script>
|
||||
import { docManageDataset, datasetDelete } from '@/api/generatedApi/index.js'
|
||||
import knowledgeForm from '@/views/knowledge/detail/components/knowledgeForm.vue'
|
||||
import knowledgePng_1 from '@/assets/images/konwledge/knowledge-1.png'
|
||||
import knowledgePng_2 from '@/assets/images/konwledge/knowledge-2.png'
|
||||
import knowledgePng_3 from '@/assets/images/konwledge/knowledge-3.png'
|
||||
import knowledgePng_4 from '@/assets/images/konwledge/knowledge-4.png'
|
||||
import knowledgePng_5 from '@/assets/images/konwledge/knowledge-5.png'
|
||||
import knowledgePng_6 from '@/assets/images/konwledge/knowledge-6.png'
|
||||
import knowledgePng_7 from '@/assets/images/konwledge/knowledge-7.png'
|
||||
export default {
|
||||
name: 'index',
|
||||
data() {
|
||||
return {
|
||||
datasetId: '',
|
||||
knowledgePng_1,
|
||||
knowledgePng_2,
|
||||
knowledgePng_3,
|
||||
knowledgePng_4,
|
||||
knowledgePng_5,
|
||||
knowledgePng_6,
|
||||
knowledgePng_7,
|
||||
datasetList: [],
|
||||
nameLike: '',
|
||||
drawer: false,
|
||||
@@ -139,7 +122,8 @@ export default {
|
||||
knowledgeForm: {
|
||||
name: 'knowledgeForm',
|
||||
component: knowledgeForm
|
||||
}
|
||||
},
|
||||
relatedAppList: []
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
@@ -159,6 +143,7 @@ export default {
|
||||
this.datasetList = res.content.content
|
||||
})
|
||||
},
|
||||
|
||||
createdKnowLedge(item) {
|
||||
this.datasetId = item ? item.id : ''
|
||||
this.drawer = true
|
||||
@@ -202,18 +187,6 @@ export default {
|
||||
// }).then(() => {
|
||||
//
|
||||
// })
|
||||
},
|
||||
getKnowledgeImage(index) {
|
||||
const images = [
|
||||
knowledgePng_1,
|
||||
knowledgePng_2,
|
||||
knowledgePng_3,
|
||||
knowledgePng_4,
|
||||
knowledgePng_5,
|
||||
knowledgePng_6,
|
||||
knowledgePng_7
|
||||
]
|
||||
return images[index % images.length]
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
@@ -390,10 +363,10 @@ export default {
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
height: 35px;
|
||||
height: 18px;
|
||||
margin: 0;
|
||||
display: -webkit-box; // 支持多行省略
|
||||
-webkit-line-clamp: 2; // 限制为两行
|
||||
-webkit-line-clamp: 1; // 限制为两行
|
||||
-webkit-box-orient: vertical; // 垂直方向排列
|
||||
overflow: hidden; // 隐藏超出部分
|
||||
text-overflow: ellipsis; // 显示省略号
|
||||
|
||||
@@ -118,6 +118,10 @@ export default {
|
||||
type: String,
|
||||
default: '添加用户'
|
||||
},
|
||||
roleListData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@@ -145,14 +149,20 @@ export default {
|
||||
email: '',
|
||||
sysUserRoleDTOs: []
|
||||
},
|
||||
roleListData: [],
|
||||
selectedRoleIds: [], // 新增,用于绑定选中的角色ID数组
|
||||
rules: {
|
||||
realName: [
|
||||
{ required: true, message: '请输入真实姓名', trigger: 'blur' }
|
||||
realName: [{ required: true, message: '请输入真实姓名' }],
|
||||
userName: [{ required: true, message: '请输入用户名称' }],
|
||||
email: [
|
||||
{ required: true, message: '请输入邮箱' },
|
||||
// 邮箱格式校验 正则
|
||||
{
|
||||
type: 'email',
|
||||
message: '请输入正确的邮箱地址'
|
||||
}
|
||||
],
|
||||
userName: [
|
||||
{ required: true, message: '请输入用户名称', trigger: 'blur' }
|
||||
sysUserRoleDTOs: [
|
||||
{ required: true, message: '请选择用户角色', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
roleOptions: [
|
||||
@@ -167,31 +177,18 @@ export default {
|
||||
handler(val) {
|
||||
if (val && Object.keys(val).length > 0) {
|
||||
this.form = { ...val }
|
||||
this.selectedRoleIds = this.form.sysUserRoleDTOs
|
||||
this.selectedRoleIds = this.form.sysUserRoleDTOs.map(item => {
|
||||
return item.roleId
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getRoleListData()
|
||||
// this.getRoleListData()
|
||||
},
|
||||
methods: {
|
||||
// 获取角色列表
|
||||
getRoleListData() {
|
||||
this.loading = true
|
||||
|
||||
getRoleList({})
|
||||
.then(response => {
|
||||
this.roleListData = response.content.content || []
|
||||
})
|
||||
.catch(error => {
|
||||
this.$message.error('获取角色列表出错', error)
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
this.$refs.form.resetFields()
|
||||
this.$emit('update:visible', false)
|
||||
@@ -205,7 +202,7 @@ export default {
|
||||
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
// this.loading = true
|
||||
const submitData = { ...this.form }
|
||||
|
||||
// 根据是否是编辑模式调用不同的API
|
||||
@@ -213,24 +210,18 @@ export default {
|
||||
? updateUser(submitData)
|
||||
: addUser(submitData)
|
||||
|
||||
apiRequest
|
||||
.then(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '添加成功')
|
||||
this.$emit('submit', submitData)
|
||||
this.handleClose()
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error(this.isEdit ? '修改用户出错' : '添加用户出错')
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
apiRequest.then(() => {
|
||||
this.$message.success(this.isEdit ? '修改成功' : '添加成功')
|
||||
this.$emit('submit', submitData)
|
||||
this.handleClose()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 处理角色选择变化
|
||||
handleRolesChange(roleIds) {
|
||||
this.form.sysUserRoleDTOs = roleIds.map(id => ({ roleId: id }))
|
||||
this.$refs.form.validateField('sysUserRoleDTOs')
|
||||
},
|
||||
clearForm() {
|
||||
this.form = {}
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
:title="dialogTitle"
|
||||
:is-edit="isEdit"
|
||||
:is-view="isView"
|
||||
:roleListData="roleListData"
|
||||
:user-data="currentUserData"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
@@ -90,6 +91,7 @@ import {
|
||||
changeUserStatus,
|
||||
resetPassword
|
||||
} from '@/api/generatedApi/system'
|
||||
import { getRoleList } from '@/api/system/role'
|
||||
|
||||
export default {
|
||||
name: 'UserManage',
|
||||
@@ -99,6 +101,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
roleListData: [],
|
||||
loading: false,
|
||||
dialogVisible: false,
|
||||
resetPasswordVisible: false,
|
||||
@@ -127,7 +130,35 @@ export default {
|
||||
{ prop: 'realName', key: '真实姓名' },
|
||||
{ prop: 'mobile', key: '手机号' },
|
||||
{ prop: 'email', key: '邮箱' },
|
||||
{ prop: 'userRoles', key: '用户角色' },
|
||||
{
|
||||
prop: 'userRoles',
|
||||
key: '用户角色',
|
||||
render: (h, p) => {
|
||||
let text = []
|
||||
p.row.sysUserRoleDTOs.map(item => {
|
||||
this.roleListData.find(role => {
|
||||
console.log(role, item)
|
||||
if (role.id === item.roleId) {
|
||||
text.push(role.roleName)
|
||||
}
|
||||
})
|
||||
})
|
||||
return h('div', [
|
||||
text.map(item => {
|
||||
return h(
|
||||
'el-tag',
|
||||
{
|
||||
props: {
|
||||
size: 'mini'
|
||||
},
|
||||
class: 'mr5'
|
||||
},
|
||||
item
|
||||
)
|
||||
})
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
key: '状态',
|
||||
@@ -222,9 +253,20 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getRoleListData()
|
||||
this.getUserList()
|
||||
},
|
||||
methods: {
|
||||
// 获取角色列表
|
||||
getRoleListData() {
|
||||
this.loading = true
|
||||
getRoleList({}).then(response => {
|
||||
if (response) {
|
||||
this.roleListData = response.content.content || []
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取用户列表
|
||||
getUserList() {
|
||||
this.loading = true
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
} from '@/api/generatedApi'
|
||||
import KnowledgeInfo from '@/views/track/views/knowledge-info/Index.vue'
|
||||
import { getUserList } from '@/api/generatedApi/system'
|
||||
import knowledgePng_2 from '@/assets/images/konwledge/knowledge-2.png'
|
||||
import knowledgePng_2 from '../../../public/loadImage/knowledge-2.png'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
KnowledgeInfo
|
||||
|
||||
@@ -1,20 +1,52 @@
|
||||
<script>
|
||||
import { datasetQuerySegments, getPdfUrl, queryTask } from '@/api/generatedApi'
|
||||
import TextModel from '@/views/knowledge/detail/components/documentDetail/TextModel.vue'
|
||||
import {
|
||||
datasetQuerySegments,
|
||||
importSegment,
|
||||
queryTask,
|
||||
segmentTemplate,
|
||||
exportSegment,
|
||||
switchStatus
|
||||
} from '@/api/generatedApi'
|
||||
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'
|
||||
import BatchAddSegment from '@/views/knowledge/detail/components/documentDetail/batchAddSegment.vue'
|
||||
import { Form } from 'element-ui'
|
||||
|
||||
export default {
|
||||
name: 'index',
|
||||
components: { MetadataOperator, QAModel, TextModel, RenderFile },
|
||||
components: {
|
||||
MetadataOperator,
|
||||
QAModel,
|
||||
RenderFile,
|
||||
AddSegment,
|
||||
BatchAddSegment
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
segmentPage: 1,
|
||||
segmentLimit: 10,
|
||||
segmentTotal: 101,
|
||||
searchText: '',
|
||||
keyWords: '',
|
||||
batchAddSegmentDialog: false,
|
||||
iframeSrc: window.location.origin,
|
||||
newForm: {},
|
||||
descriptions: null
|
||||
descriptions: null,
|
||||
addSegmentDialog: false,
|
||||
batchSegmentList: []
|
||||
}
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
changeEnable: this.changeEnable
|
||||
}
|
||||
},
|
||||
|
||||
inject: ['viewDocumentDetail'],
|
||||
|
||||
props: {
|
||||
noEdit: {
|
||||
type: Boolean,
|
||||
@@ -75,18 +107,98 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toSplit() {
|
||||
this.$router.push({
|
||||
path: '/knowledge/detail/create',
|
||||
query: {
|
||||
documentId: this.form.id,
|
||||
datasetId: this.form.datasetId,
|
||||
activeLevel: 1
|
||||
changeEnable(state, id) {
|
||||
let params = {
|
||||
documentId: this.form.id,
|
||||
segmentIds: [id],
|
||||
status: state ? 0 : 1 //枚举值:0-启用 1-禁用
|
||||
}
|
||||
switchStatus(params)
|
||||
},
|
||||
|
||||
inputSegment() {
|
||||
if (!this.searchText.trim()) {
|
||||
this.keyWords = ''
|
||||
this.segmentPage = 1
|
||||
this._getSplitResultPreview()
|
||||
}
|
||||
},
|
||||
searchSegment() {
|
||||
this.keyWords = this.searchText
|
||||
this.segmentPage = 1
|
||||
this._getSplitResultPreview()
|
||||
},
|
||||
sizeChange(size) {
|
||||
this.segmentPage = 1
|
||||
this.segmentLimit = size
|
||||
this._getSplitResultPreview()
|
||||
},
|
||||
currentChange(page) {
|
||||
this.segmentPage = page
|
||||
this._getSplitResultPreview()
|
||||
},
|
||||
|
||||
importSegmentToKnowledge() {
|
||||
let form = new FormData()
|
||||
form.append('documentId', this.form.id)
|
||||
if (this.batchSegmentList.length === 0) {
|
||||
this.$message.error('请先选择文件')
|
||||
return
|
||||
}
|
||||
|
||||
this.batchSegmentList.map(item => {
|
||||
form.append('file', item)
|
||||
})
|
||||
importSegment(form).then(res => {
|
||||
if (res) {
|
||||
this.$message.success('导入成功')
|
||||
this.batchAddSegmentDialog = false
|
||||
this.batchSegmentList = []
|
||||
this._getSplitResultPreview()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getPdfUrl,
|
||||
getFileList(list) {
|
||||
this.batchSegmentList = list
|
||||
},
|
||||
|
||||
downLoadSegmentTemplate() {
|
||||
let model = null
|
||||
switch (this.newForm.segmentedMode) {
|
||||
case 0:
|
||||
model = 'general'
|
||||
break
|
||||
case 1:
|
||||
model = 'qa'
|
||||
break
|
||||
default:
|
||||
model = 'general'
|
||||
return ''
|
||||
}
|
||||
window.open(segmentTemplate(model))
|
||||
},
|
||||
command(type) {
|
||||
switch (type) {
|
||||
case 'newAdd':
|
||||
// 批量新增
|
||||
this.batchAddSegmentDialog = true
|
||||
break
|
||||
case 'exportSeg':
|
||||
// 导出分段
|
||||
window.open(exportSegment({ documentId: this.form.id }))
|
||||
break
|
||||
}
|
||||
},
|
||||
// 新增分段
|
||||
addSegment() {
|
||||
if (this.newForm.optStatus !== 4) {
|
||||
return false
|
||||
}
|
||||
// this._getSplitResultPreview()
|
||||
|
||||
this.addSegmentDialog = true
|
||||
},
|
||||
_getTaskDetail() {
|
||||
queryTask({ id: this.form.id }).then(res => {
|
||||
const { content } = res.content
|
||||
@@ -94,8 +206,19 @@ export default {
|
||||
})
|
||||
},
|
||||
_getSplitResultPreview() {
|
||||
datasetQuerySegments({ documentId: this.form.id }).then(res => {
|
||||
if (this.descriptions && this.descriptions.data) {
|
||||
this.descriptions.data = []
|
||||
}
|
||||
let params = {
|
||||
documentId: this.form.id,
|
||||
page: this.segmentPage,
|
||||
pageSize: this.segmentLimit,
|
||||
keyword: this.keyWords
|
||||
// keyword: this.searchText
|
||||
}
|
||||
datasetQuerySegments(params).then(res => {
|
||||
this.descriptions = res.content.content
|
||||
this.segmentTotal = res.content.content.total
|
||||
})
|
||||
},
|
||||
openMetaDrawer() {
|
||||
@@ -123,11 +246,11 @@ export default {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class=" upload-info-container"
|
||||
class="upload-info-container"
|
||||
:class="!fullscreen ? 'render-container' : ''"
|
||||
>
|
||||
<div class="form-container">
|
||||
<el-descriptions class="" :column="4">
|
||||
<div class="form-container ph10">
|
||||
<el-descriptions class="mt10" :column="4">
|
||||
<el-descriptions-item label="知识库">
|
||||
{{ newForm.datasetName }}
|
||||
</el-descriptions-item>
|
||||
@@ -163,24 +286,92 @@ export default {
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<el-row :gutter="20">
|
||||
<div class="flex align-items-c mt10" style="gap:20px">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
v-if="!noEdit"
|
||||
split-button
|
||||
size="medium"
|
||||
type="primary"
|
||||
@click="addSegment"
|
||||
class="line-button"
|
||||
:class="newForm.optStatus !== 4 ? 'is-disabled' : ''"
|
||||
@command="command"
|
||||
>
|
||||
新增分段
|
||||
<el-dropdown-menu slot="dropdown" :disabled="newForm.optStatus !== 4">
|
||||
<el-dropdown-item
|
||||
command="newAdd"
|
||||
:disabled="newForm.optStatus !== 4"
|
||||
>批量新增</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
command="exportSeg"
|
||||
:disabled="newForm.optStatus !== 4"
|
||||
>分段导出</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<el-input
|
||||
style="width: 50vh;"
|
||||
size="small"
|
||||
placeholder="按下回车搜索分段内容"
|
||||
clearable
|
||||
v-model="searchText"
|
||||
@input="inputSegment"
|
||||
@keydown.enter.native="searchSegment"
|
||||
></el-input>
|
||||
</div>
|
||||
<el-row :gutter="20" class="mt10">
|
||||
<!-- 左侧:表单内容和知识内容 -->
|
||||
<el-col :span="12">
|
||||
<el-col
|
||||
:span="
|
||||
newForm.knowledgeName && newForm.knowledgeName.indexOf('.pdf') >= 0
|
||||
? 12
|
||||
: 24
|
||||
"
|
||||
>
|
||||
<!-- 知识内容 -->
|
||||
<div class="content-card el-card mt20">
|
||||
<div class="knowledge-content" v-if="descriptions">
|
||||
<text-model
|
||||
:noEdit="noEdit"
|
||||
v-if="descriptions.doc_form === 'text_model'"
|
||||
:descriptions="descriptions"
|
||||
:parentForm="form"
|
||||
/>
|
||||
<div class="content-card el-card ">
|
||||
<div
|
||||
v-if="descriptions"
|
||||
class="knowledge-content"
|
||||
v-loading="!descriptions.data"
|
||||
>
|
||||
<q-a-model
|
||||
:class="segmentTotal > 0 ? '' : ''"
|
||||
:noEdit="noEdit"
|
||||
v-else-if="descriptions.doc_form === 'qa_model'"
|
||||
:descriptions="descriptions"
|
||||
:parentForm="form"
|
||||
:style="{
|
||||
height: 'calc(100% - 40px)',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto'
|
||||
}"
|
||||
/>
|
||||
|
||||
<div
|
||||
style="height: 40px;width:100%;position: sticky;bottom: -1px;color:Red;background: #fff;"
|
||||
class="flex align-items-c justify-content-b"
|
||||
>
|
||||
<div>
|
||||
<el-pagination
|
||||
background
|
||||
small
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
:total="segmentTotal"
|
||||
:currentPage="segmentPage"
|
||||
layout="prev,sizes, pager, next"
|
||||
:page-sizes="[10, 20, 30, 40, 50]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- <div v-for="item in getSegmentPages()">-->
|
||||
<!-- {{ item }}-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="p20 flex align-items-c">
|
||||
<div class="mr10 fs14">暂无知识内容</div>
|
||||
@@ -196,8 +387,13 @@ export default {
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:原文内容 -->
|
||||
<el-col :span="12">
|
||||
<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,10 +402,66 @@ 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>
|
||||
|
||||
<r-dialog
|
||||
title="批量新增"
|
||||
:visible.sync="batchAddSegmentDialog"
|
||||
append-to-body
|
||||
width="40%"
|
||||
destroy-on-close
|
||||
>
|
||||
<template slot="title">
|
||||
<div class="flex align-items-c">
|
||||
<div>批量新增</div>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
class="ml20"
|
||||
icon="el-icon-download"
|
||||
@click="downLoadSegmentTemplate"
|
||||
>下载模板</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<batch-add-segment
|
||||
:document-id="form.id"
|
||||
@close="batchAddSegmentDialog = false"
|
||||
@getFileList="getFileList"
|
||||
></batch-add-segment>
|
||||
<div slot="footer">
|
||||
<el-button @click="batchAddSegmentDialog = false" size="medium"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button
|
||||
size="medium"
|
||||
type="primary"
|
||||
:disabled="batchSegmentList.length < 1"
|
||||
@click="importSegmentToKnowledge"
|
||||
>导入</el-button
|
||||
>
|
||||
</div>
|
||||
</r-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/sass/renderSass/theme.scss';
|
||||
.form-container {
|
||||
background: #fff;
|
||||
padding: 5px;
|
||||
@@ -218,12 +470,13 @@ export default {
|
||||
}
|
||||
|
||||
.content-card {
|
||||
margin-bottom: 20px;
|
||||
//margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
.knowledge-content {
|
||||
height: calc(100vh - 240px);
|
||||
position: relative;
|
||||
height: calc(100vh - 290px);
|
||||
overflow-y: auto;
|
||||
//&::-webkit-scrollbar {
|
||||
// width: 4px;
|
||||
@@ -232,7 +485,7 @@ export default {
|
||||
}
|
||||
|
||||
.full-height {
|
||||
height: calc(100vh - 240px);
|
||||
height: calc(100vh - 290px);
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
@@ -249,4 +502,20 @@ export default {
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
::v-deep .line-button {
|
||||
background: $--color-primary-button-gradient;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
&.is-disabled {
|
||||
& .el-button {
|
||||
cursor: no-drop;
|
||||
}
|
||||
}
|
||||
& .el-button-group {
|
||||
& .el-button {
|
||||
background: unset;
|
||||
border: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||