mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-09 19:06:49 +08:00
扩展目录
This commit is contained in:
58
src/api/directory/index.js
Normal file
58
src/api/directory/index.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import request from '@/assets/js/utils/request'
|
||||
import getUrl from '@/assets/js/utils/get-url'
|
||||
|
||||
//单一目录详情
|
||||
export function getDirectoryById(params) {
|
||||
return request({
|
||||
url: getUrl('/directoryEx/query'),
|
||||
method: 'get',
|
||||
params: params,
|
||||
noLoading: true
|
||||
})
|
||||
}
|
||||
|
||||
// 目录内容修改
|
||||
export function directoryUpdate(data) {
|
||||
return request({
|
||||
url: getUrl('/directoryEx/update'),
|
||||
method: 'post',
|
||||
data,
|
||||
noLoading: true
|
||||
})
|
||||
}
|
||||
|
||||
// 目录新增
|
||||
export function directoryCreate(data) {
|
||||
return request({
|
||||
url: getUrl('/directoryEx/create'),
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 目录删除
|
||||
export function directoryDelete(data) {
|
||||
return request({
|
||||
url: getUrl(`/directoryEx/delete`),
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取目录树
|
||||
export function getDirectoryTree(params) {
|
||||
return request({
|
||||
url: getUrl(`/directoryEx/getDirectoryTree`),
|
||||
method: 'post',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 同步目录元数据
|
||||
export function markedMetadata(params) {
|
||||
return request({
|
||||
url: getUrl(`/directoryMetadataEx/markedMetadata`),
|
||||
method: 'post',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
<el-radio-group v-model="model.segmentedMode">
|
||||
<el-radio :label="0">通用分段模式</el-radio>
|
||||
<el-radio :label="1">Q&A分段模式</el-radio>
|
||||
<el-radio :label="2">目录型知识库</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
@@ -123,7 +124,8 @@ export default {
|
||||
id: null,
|
||||
imageType: 'upload-img',
|
||||
image: null,
|
||||
visibleRange: 0
|
||||
visibleRange: 0,
|
||||
useDirectory: 0
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
@@ -162,7 +164,8 @@ export default {
|
||||
userIds: [],
|
||||
image: null,
|
||||
imageType: 'upload-img',
|
||||
id: null
|
||||
id: null,
|
||||
useDirectory: 0
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -253,7 +256,8 @@ export default {
|
||||
userIds: [],
|
||||
image: null,
|
||||
imageType: 'upload-img',
|
||||
id: null
|
||||
id: null,
|
||||
useDirectory: 0
|
||||
}
|
||||
},
|
||||
|
||||
@@ -262,6 +266,10 @@ export default {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
if (this.model.segmentedMode === 2) {
|
||||
this.model.segmentedMode = 0
|
||||
this.model.useDirectory = 1
|
||||
}
|
||||
|
||||
// this.model.visibleRange = 0/**/
|
||||
;(!this.datasetId ? datasetCreate : datasetUpdate)(this.model).then(
|
||||
|
||||
@@ -312,6 +312,9 @@ export default {
|
||||
formData.append('file', file)
|
||||
})
|
||||
formData.append('datasetId', this.form.datasetId)
|
||||
if (this.$route.query.directoryId) {
|
||||
formData.append('directoryId', this.$route.query.directoryId)
|
||||
}
|
||||
let api =
|
||||
this.form.radio === '1' ? uploadFileByCustom : uploadFileByTemplate
|
||||
if (this.form.radio === '1') {
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt20 card-body">
|
||||
<div class="mt20 card-body" v-if="useDirectory !== 1">
|
||||
<el-empty v-if="!hasList">
|
||||
<div class="mt20">
|
||||
<el-button
|
||||
@@ -205,6 +205,29 @@
|
||||
></r-table>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div style="margin-bottom: 12px; display: flex; gap: 8px;">
|
||||
<el-button type="primary" size="small" @click="openCreateDialog()"
|
||||
>新建根目录</el-button
|
||||
>
|
||||
<el-button type="primary" size="small" @click="syncDirMetadata()"
|
||||
>同步目录元数据</el-button
|
||||
>
|
||||
</div>
|
||||
<r-table
|
||||
:columns="dirColumns"
|
||||
:data="treeData"
|
||||
:deletion="false"
|
||||
:total="treeData.length"
|
||||
/>
|
||||
<directory-form
|
||||
:visible.sync="dialogVisible"
|
||||
:parentId="currentParentId"
|
||||
:datasetId="$route.query.datasetId"
|
||||
:directoryId="currentDirectoryId"
|
||||
@update:visible="onDialogClose"
|
||||
/>
|
||||
</div>
|
||||
<document-drawer
|
||||
:visible.sync="drawer"
|
||||
:descriptions="descriptions"
|
||||
@@ -281,6 +304,12 @@ import MetaData from '@/views/knowledge/detail/components/metaData/Index.vue'
|
||||
import MetadataOperator from '@/views/knowledge/detail/components/metaData/MetadataOperator.vue'
|
||||
import SearchSetting from '@/views/knowledge/detail/components/SearchSetting/Index.vue'
|
||||
import { displayStatus } from '@/assets/js/utils/utilOptions'
|
||||
import DirectoryForm from '@/views/knowledge/directory/directoryForm.vue'
|
||||
import {
|
||||
directoryDelete,
|
||||
getDirectoryTree,
|
||||
markedMetadata
|
||||
} from '@/api/directory'
|
||||
export default {
|
||||
name: 'index',
|
||||
// 父子组件共享
|
||||
@@ -336,12 +365,18 @@ export default {
|
||||
documentDetail: {
|
||||
splitRules: '',
|
||||
extractRules: ''
|
||||
}
|
||||
},
|
||||
useDirectory: 0,
|
||||
treeData: [],
|
||||
dialogVisible: false,
|
||||
currentParentId: '',
|
||||
currentDirectoryId: ''
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
watch: {},
|
||||
components: {
|
||||
DirectoryForm,
|
||||
SearchSetting,
|
||||
MetaData,
|
||||
hitTest,
|
||||
@@ -385,13 +420,14 @@ export default {
|
||||
},
|
||||
|
||||
// 跳转去上传文件
|
||||
jumpAddKnowledge() {
|
||||
jumpAddKnowledge(directory) {
|
||||
sessionStorage.removeItem('documentId')
|
||||
let { datasetId } = this.$route.query
|
||||
this.$router.push({
|
||||
path: '/knowledge/detail/create',
|
||||
query: {
|
||||
datasetId: datasetId
|
||||
datasetId: datasetId,
|
||||
directoryId: directory ? directory.id : ''
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -419,6 +455,7 @@ export default {
|
||||
this.knowledgeDesc = res.content.content.description
|
||||
this.segmentedMode = res.content.content.segmentedMode
|
||||
this.knowledgeImage = res.content.content.image
|
||||
this.useDirectory = res.content.content.useDirectory
|
||||
})
|
||||
},
|
||||
|
||||
@@ -606,7 +643,101 @@ export default {
|
||||
},
|
||||
handleRelatedApp(item) {
|
||||
// console.log(item)
|
||||
},
|
||||
// 合并文档到 children,并加 type 字段
|
||||
mergeDocumentsToChildren(node) {
|
||||
node.type = 'directory'
|
||||
if (Array.isArray(node.documents) && node.documents.length > 0) {
|
||||
const docChildren = node.documents.map(doc => ({
|
||||
...doc,
|
||||
id: doc.id,
|
||||
knowledgeName: doc.knowledgeName,
|
||||
type: 'document',
|
||||
children: []
|
||||
}))
|
||||
node.children = (node.children || []).concat(docChildren)
|
||||
}
|
||||
if (Array.isArray(node.children)) {
|
||||
node.children.forEach(child => {
|
||||
if (!child.type || child.type !== 'document') {
|
||||
this.mergeDocumentsToChildren(child)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
async loadTree() {
|
||||
getDirectoryTree({ datasetId: this.$route.query.datasetId }).then(
|
||||
response => {
|
||||
const data = response.content.content
|
||||
data.forEach(node => this.mergeDocumentsToChildren(node))
|
||||
this.treeData = data
|
||||
}
|
||||
)
|
||||
},
|
||||
openCreateDialog(parent = null) {
|
||||
this.currentDirectoryId = ''
|
||||
this.currentParentId = parent ? parent.id : ''
|
||||
this.dialogVisible = true
|
||||
},
|
||||
syncDirMetadata(parent = null) {
|
||||
markedMetadata({ datasetId: this.$route.query.datasetId }).then(res => {
|
||||
if (res) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '同步成功!'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
onDialogClose(val) {
|
||||
this.dialogVisible = val
|
||||
if (!val) {
|
||||
this.loadTree()
|
||||
}
|
||||
},
|
||||
openEditDialog(directory) {
|
||||
// 这里可以弹出编辑目录的表单,具体实现根据你的 DirectoryForm 组件而定
|
||||
// 示例:
|
||||
this.currentParentId = ''
|
||||
this.currentDirectoryId = directory.id
|
||||
this.dialogVisible = true
|
||||
// 你可以根据需要传递更多编辑相关的数据
|
||||
},
|
||||
deleteDirectory(row) {
|
||||
let ids = []
|
||||
ids.push(row.id)
|
||||
this.$messageBox(
|
||||
() => {
|
||||
directoryDelete(ids).then(res => {
|
||||
if (res) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.loadTree()
|
||||
}
|
||||
})
|
||||
},
|
||||
'是否确认删除' + row.name + '目录?',
|
||||
'warning'
|
||||
)
|
||||
}
|
||||
// /**
|
||||
// * 跳转到上传知识页面
|
||||
// * @param directory 目录节点对象,可选
|
||||
// */
|
||||
// jumpAddKnowledge(directory) {
|
||||
// sessionStorage.removeItem('documentId')
|
||||
// let { datasetId } = this.$route.query
|
||||
// // 可根据需要将目录id传递给上传页面
|
||||
// this.$router.push({
|
||||
// path: '/knowledge/detail/create',
|
||||
// query: {
|
||||
// datasetId: datasetId,
|
||||
// directoryId: directory ? directory.id : undefined
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
},
|
||||
filters: {
|
||||
filterSegmentedMode(val) {
|
||||
@@ -630,7 +761,11 @@ export default {
|
||||
async mounted() {
|
||||
this.getKnowledgeDetail()
|
||||
// 获取知识库文件列表
|
||||
this.getKnowledgeFiledList()
|
||||
if (this.useDirectory === 1) {
|
||||
this.loadTree()
|
||||
} else {
|
||||
this.getKnowledgeFiledList()
|
||||
}
|
||||
// 获取用户下拉列表
|
||||
this.getUserData()
|
||||
|
||||
@@ -835,6 +970,240 @@ export default {
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
dirColumns() {
|
||||
return [
|
||||
{
|
||||
prop: 'name',
|
||||
key: '名称'
|
||||
// render: (h, params) => params.row.type === 'directory' ? params.row.name : ''
|
||||
},
|
||||
{
|
||||
key: '知识文件名称',
|
||||
prop: 'knowledgeName'
|
||||
},
|
||||
{
|
||||
key: '知识文件来源',
|
||||
prop: 'documentSource',
|
||||
render: (h, params) => {
|
||||
if (params.row.type !== 'document') {
|
||||
return ''
|
||||
}
|
||||
let text = documentSourceOptions.find(
|
||||
item => item.value === String(params.row.documentSource)
|
||||
).label
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
class: 'flex align-items-c'
|
||||
},
|
||||
[
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
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'
|
||||
}
|
||||
},
|
||||
params.row.useMineru === 1 ? '预' : ''
|
||||
),
|
||||
h('span', {}, text)
|
||||
]
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '状态',
|
||||
prop: 'statusLabel'
|
||||
},
|
||||
{
|
||||
key: '召回次数',
|
||||
prop: 'hitCount',
|
||||
render: (h, params) => {
|
||||
return h('div', !params.row.hitCount ? '0' : params.row.hitCount)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '上传用户',
|
||||
prop: 'createdUser',
|
||||
width: '100',
|
||||
render: (h, params) => {
|
||||
return h(
|
||||
'div',
|
||||
!params.row.createdUser ? '-' : params.row.createdUser
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '上传时间',
|
||||
prop: 'createdDate',
|
||||
width: '100'
|
||||
},
|
||||
{
|
||||
key: '操作',
|
||||
prop: 'knowledgeDesc',
|
||||
isRedraw: true,
|
||||
render: (h, params) => {
|
||||
return h('div', [
|
||||
// 目录类型按钮
|
||||
params.row.type === 'directory'
|
||||
? h('el-button', {
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-folder-add',
|
||||
title: '创建子目录'
|
||||
},
|
||||
on: {
|
||||
click: () => this.openCreateDialog(params.row)
|
||||
}
|
||||
})
|
||||
: '',
|
||||
params.row.type === 'directory'
|
||||
? h('el-button', {
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-edit',
|
||||
title: '编辑'
|
||||
},
|
||||
on: {
|
||||
click: () => this.openEditDialog(params.row)
|
||||
}
|
||||
})
|
||||
: '',
|
||||
params.row.type === 'directory'
|
||||
? h('el-button', {
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-delete',
|
||||
title: '删除'
|
||||
},
|
||||
on: {
|
||||
click: () => this.deleteDirectory(params.row)
|
||||
}
|
||||
})
|
||||
: '',
|
||||
// 文档类型按钮
|
||||
params.row.type === 'document'
|
||||
? h('el-button', {
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-tickets',
|
||||
title: '查看详情'
|
||||
},
|
||||
on: {
|
||||
click: () => this.viewDocumentDetail(params.row)
|
||||
}
|
||||
})
|
||||
: '',
|
||||
params.row.type === 'document'
|
||||
? h(
|
||||
'el-button',
|
||||
{
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'danger',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-delete',
|
||||
title: '删除'
|
||||
},
|
||||
on: {
|
||||
click: () => this.deleteKnowledge(params.row)
|
||||
}
|
||||
}
|
||||
// '删除'
|
||||
)
|
||||
: '',
|
||||
params.row.type === 'document'
|
||||
? h(
|
||||
'el-button',
|
||||
{
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-help',
|
||||
title: '添加元数据',
|
||||
disabled: params.row.documentStatus !== 1
|
||||
},
|
||||
on: {
|
||||
click: () => this.handleAddMetadata(params.row)
|
||||
}
|
||||
}
|
||||
// '标注元数据'
|
||||
)
|
||||
: '',
|
||||
params.row.type === 'document'
|
||||
? 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 && params.row.type === 'document'
|
||||
? h(
|
||||
'el-button',
|
||||
{
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-video-play',
|
||||
title: '继续处理'
|
||||
},
|
||||
on: {
|
||||
click: () => this.jumpToUpload(params)
|
||||
}
|
||||
}
|
||||
// '文件拆分处理'
|
||||
)
|
||||
: '',
|
||||
params.row.type === 'directory'
|
||||
? h('el-button', {
|
||||
class: 'floatSpan',
|
||||
props: {
|
||||
type: 'primary',
|
||||
size: 'mini',
|
||||
icon: 'el-icon-plus',
|
||||
title: '上传知识'
|
||||
},
|
||||
on: {
|
||||
click: () => this.jumpAddKnowledge(params.row)
|
||||
}
|
||||
})
|
||||
: ''
|
||||
])
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
155
src/views/knowledge/directory/directoryForm.vue
Normal file
155
src/views/knowledge/directory/directoryForm.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<r-dialog
|
||||
:visible.sync="visible"
|
||||
:title="(directoryId ? `修改` : `新增`) + '目录'"
|
||||
destroy-on-close
|
||||
width="500px"
|
||||
>
|
||||
<div slot="header" class="clearfix">
|
||||
<h3>{{ directoryId ? '修改' : '新增' }}</h3>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-form
|
||||
:model="model"
|
||||
ref="model"
|
||||
label-width="120px"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item label="目录名称:" prop="name">
|
||||
<el-input v-model="model.name" size="medium"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 可见范围-->
|
||||
<el-form-item label="可见权限:" prop="visibleRange">
|
||||
<otherSelect :model="model"></otherSelect>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div slot="footer" :span="24">
|
||||
<el-button
|
||||
size="medium"
|
||||
@click="resetForm(), $emit('update:visible', false)"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button type="primary" size="medium" @click="save">
|
||||
{{ directoryId ? '保存' : '创建' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</r-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import otherSelect from '@/views/knowledge/detail/components/otherSelect/otherIndex.vue'
|
||||
import {
|
||||
directoryCreate,
|
||||
directoryUpdate,
|
||||
getDirectoryById
|
||||
} from '@/api/directory'
|
||||
export default {
|
||||
name: 'knowledgeForm',
|
||||
components: { otherSelect },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
directoryId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
parentId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
datasetId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible: {
|
||||
handler(val) {
|
||||
this.$nextTick(() => {
|
||||
this.$emit('update:visible', val)
|
||||
|
||||
if (this.directoryId) {
|
||||
this.getDetail()
|
||||
} else {
|
||||
this.model = {
|
||||
name: '',
|
||||
visibleRange: 0,
|
||||
userIds: [],
|
||||
id: null,
|
||||
parentId: this.parentId,
|
||||
datasetId: this.datasetId
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: {
|
||||
name: '',
|
||||
id: null,
|
||||
visibleRange: 0,
|
||||
userIds: [],
|
||||
parentId: '',
|
||||
datasetId: ''
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入目录名称', trigger: 'blur' }],
|
||||
visibleRange: [{ required: true, message: '请选择可见权限' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail() {
|
||||
if (!this.directoryId) return
|
||||
getDirectoryById({ directoryId: this.directoryId }).then(res => {
|
||||
this.model = {
|
||||
...res.content.content,
|
||||
visibleRange: res.content.content.visibleRange
|
||||
? res.content.content.visibleRange
|
||||
: 0
|
||||
}
|
||||
})
|
||||
},
|
||||
resetForm() {
|
||||
this.model = {
|
||||
name: '',
|
||||
visibleRange: '',
|
||||
userIds: [],
|
||||
id: null,
|
||||
parentId: '',
|
||||
datasetId: '',
|
||||
directoryId: ''
|
||||
}
|
||||
},
|
||||
save() {
|
||||
this.$refs.model.validate(valid => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
|
||||
// this.model.visibleRange = 0/**/
|
||||
;(!this.directoryId ? directoryCreate : directoryUpdate)(
|
||||
this.model
|
||||
).then(res => {
|
||||
if (res) {
|
||||
// 添加保存成功的提示
|
||||
this.$message.success('保存成功')
|
||||
this.$emit('update:visible', false)
|
||||
this.resetForm()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user