mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-30 17:52:48 +00:00
feat: document
This commit is contained in:
parent
34448a2623
commit
516c88a510
|
|
@ -6,7 +6,6 @@ const ModelRouter = {
|
|||
redirect: '/knowledge',
|
||||
component: () => import('@/layout/layout-template/SimpleLayout.vue'),
|
||||
children: [
|
||||
|
||||
{
|
||||
path: '/knowledge/system/document/upload/shared',
|
||||
name: 'UploadDocumentSharedSystem',
|
||||
|
|
@ -14,6 +13,13 @@ const ModelRouter = {
|
|||
component: () => import('@/views/shared/document-shared/UploadDocument.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/knowledge/system/import/shared',
|
||||
name: 'ImportLarkDocumentShared',
|
||||
meta: { activeMenu: '/knowledge' },
|
||||
component: () => import('@/views/shared/document-shared/ImportLarkDocument.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ const ModelRouter = {
|
|||
component: () => import('@/views/document/UploadDocument.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/knowledge/import',
|
||||
name: 'ImportLarkDocument',
|
||||
meta: { activeMenu: '/knowledge' },
|
||||
component: () => import('@/views/document/ImportLarkDocument.vue'),
|
||||
hidden: true
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ const systemRouter = {
|
|||
},
|
||||
{
|
||||
path: '/system/authentication',
|
||||
name: 'authentication',
|
||||
name: 'SystemAuthentication',
|
||||
meta: {
|
||||
title: 'views.system.authentication.title',
|
||||
activeMenu: '/system',
|
||||
|
|
|
|||
|
|
@ -58,18 +58,6 @@ const useKnowledgeStore = defineStore('knowledg', {
|
|||
})
|
||||
})
|
||||
},
|
||||
async asyncSyncKnowledge(id: string, sync_type: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
knowledgeApi
|
||||
.putSyncWebKnowledge(id, sync_type, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type { knowledgeData } from '@/api/type/knowledge'
|
|||
import type { UploadUserFile } from 'element-plus'
|
||||
import knowledgeApi from '@/api/knowledge/knowledge'
|
||||
import { type Ref } from 'vue'
|
||||
import useFolderStore from './folder'
|
||||
|
||||
export interface knowledgeStateTypes {
|
||||
baseInfo: knowledgeData | null
|
||||
|
|
@ -46,6 +47,46 @@ const useKnowledgeStore = defineStore('knowledge', {
|
|||
})
|
||||
})
|
||||
},
|
||||
async asyncGetTreeRootKnowledge(loading?: Ref<boolean>) {
|
||||
const folder = useFolderStore()
|
||||
return Promise.all([
|
||||
folder.asyncGetFolder('KNOWLEDGE', {}, loading),
|
||||
this.asyncGetRootKnowledge(loading),
|
||||
])
|
||||
.then((res: any) => {
|
||||
const folderList = res[0].data
|
||||
const knowledgeList = res[1].data
|
||||
const arrMap: any = {}
|
||||
function buildIdMap(arr: any) {
|
||||
arr.forEach((item: any) => {
|
||||
arrMap[item.id] = item
|
||||
// 递归处理子节点
|
||||
if (item.children && item.children.length > 0) {
|
||||
buildIdMap(item.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
buildIdMap(folderList)
|
||||
knowledgeList
|
||||
.filter((v: any) => v.resource_type !== 'folder')
|
||||
.forEach((item: any) => {
|
||||
const targetFolder = arrMap[item.folder_id]
|
||||
if (targetFolder) {
|
||||
// 检查是否已有相同ID的子节点(避免重复插入)
|
||||
const existingChild = targetFolder.children.find(
|
||||
(child: any) => child.id === item.id,
|
||||
)
|
||||
if (!existingChild) {
|
||||
targetFolder.children.push(item)
|
||||
}
|
||||
}
|
||||
})
|
||||
return Promise.resolve(folderList)
|
||||
})
|
||||
.catch((error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
},
|
||||
async asyncGetKnowledgeDetail(knowledge_id: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
knowledgeApi
|
||||
|
|
@ -58,18 +99,6 @@ const useKnowledgeStore = defineStore('knowledge', {
|
|||
})
|
||||
})
|
||||
},
|
||||
async asyncSyncKnowledge(id: string, sync_type: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
knowledgeApi
|
||||
.putSyncWebKnowledge(id, sync_type, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ defineExpose({ open })
|
|||
}
|
||||
.max-height {
|
||||
max-height: calc(100vh - 260px);
|
||||
min-height: 300px;
|
||||
min-height: 500px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,293 @@
|
|||
<template>
|
||||
<div class="create-knowledge p-12-24">
|
||||
<div class="flex align-center mb-16">
|
||||
<back-button to="-1" style="margin-left: -4px"></back-button>
|
||||
<h3 style="display: inline-block">{{ $t('views.document.importDocument') }}</h3>
|
||||
</div>
|
||||
<el-card style="--el-card-padding: 0">
|
||||
<div class="create-knowledge__main flex" v-loading="loading">
|
||||
<div class="create-knowledge__component main-calc-height">
|
||||
<div class="upload-document p-24" style="min-width: 850px">
|
||||
<h4 class="title-decoration-1 mb-8">
|
||||
{{ $t('views.document.feishu.selectDocument') }}
|
||||
</h4>
|
||||
<el-form
|
||||
ref="FormRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<div class="mt-16 mb-16">
|
||||
<el-radio-group v-model="form.fileType" class="app-radio-button-group">
|
||||
<el-radio-button value="txt"
|
||||
>{{ $t('views.document.fileType.txt.label') }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="update-info flex p-8-12 border-r-4 mb-16">
|
||||
<div class="mt-4">
|
||||
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
|
||||
</div>
|
||||
<div class="ml-16 lighter">
|
||||
<p>{{ $t('views.document.feishu.tip1') }}</p>
|
||||
<p>{{ $t('views.document.feishu.tip2') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-4 mb-16">
|
||||
<el-checkbox
|
||||
v-model="allCheck"
|
||||
:label="$t('views.document.feishu.allCheck')"
|
||||
size="large"
|
||||
class="ml-24"
|
||||
@change="handleAllCheckChange"
|
||||
/>
|
||||
</div>
|
||||
<div style="height: calc(100vh - 450px)">
|
||||
<el-scrollbar>
|
||||
<el-tree
|
||||
:props="props"
|
||||
:load="loadNode"
|
||||
lazy
|
||||
show-checkbox
|
||||
node-key="token"
|
||||
ref="treeRef"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="flex align-center lighter">
|
||||
<img
|
||||
src="@/assets/fileType/file-icon.svg"
|
||||
alt=""
|
||||
height="20"
|
||||
v-if="data.type === 'folder'"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/docx-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.type === 'docx' || data.name.endsWith('.docx')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/xlsx-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.type === 'sheet' || data.name.endsWith('.xlsx')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/xls-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('xls')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/csv-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('csv')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/pdf-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.pdf')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/html-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.html')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/txt-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.txt')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/zip-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.zip')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/md-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.md')"
|
||||
/>
|
||||
|
||||
<span class="ml-4">{{ node.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<div class="create-knowledge__footer text-right border-t">
|
||||
<el-button @click="router.go(-1)">{{ $t('common.cancel') }}</el-button>
|
||||
|
||||
<el-button @click="submit" type="primary" :disabled="disabled">
|
||||
{{ $t('views.document.buttons.import') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { MsgConfirm, MsgSuccess, MsgWarning } from '@/utils/message'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import { t } from '@/locales'
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node'
|
||||
import documentApi from '@/api/knowledge/document'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const {
|
||||
query: { id, folder_token }, // id为knowledgeID,有id的是上传文档 folder_token为飞书文件夹token
|
||||
} = route
|
||||
const knowledgeId = id as string
|
||||
const folderToken = folder_token as string
|
||||
|
||||
const loading = ref(false)
|
||||
const disabled = ref(false)
|
||||
const allCheck = ref(false)
|
||||
const treeRef = ref<any>(null)
|
||||
|
||||
interface Tree {
|
||||
name: string
|
||||
leaf?: boolean
|
||||
type: string
|
||||
token: string
|
||||
is_exist: boolean
|
||||
}
|
||||
|
||||
const form = ref({
|
||||
fileType: 'txt',
|
||||
fileList: [] as any,
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
fileList: [
|
||||
{ required: true, message: t('views.document.upload.requiredMessage'), trigger: 'change' },
|
||||
],
|
||||
})
|
||||
|
||||
const props = {
|
||||
label: 'name',
|
||||
children: 'zones',
|
||||
isLeaf: (data: any) => data.type !== 'folder',
|
||||
disabled: (data: any) => data.is_exist,
|
||||
}
|
||||
|
||||
const loadNode = (node: Node, resolve: (nodeData: Tree[]) => void) => {
|
||||
const token = node.level === 0 ? folderToken : node.data.token // 根节点使用 folder_token,其他节点使用 node.data.token
|
||||
documentApi
|
||||
.getLarkDocumentList(knowledgeId, token, {}, loading)
|
||||
.then((res: any) => {
|
||||
const nodes = res.data.files as Tree[]
|
||||
resolve(nodes)
|
||||
nodes.forEach((childNode) => {
|
||||
if (childNode.is_exist) {
|
||||
treeRef.value?.setChecked(childNode.token, true, false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
.catch((err) => {
|
||||
console.error('Failed to load tree nodes:', err)
|
||||
})
|
||||
}
|
||||
|
||||
const handleAllCheckChange = (checked: boolean) => {
|
||||
if (checked) {
|
||||
// 获取所有已加载的节点
|
||||
const nodes = Object.values(treeRef.value?.store.nodesMap || {}) as any[]
|
||||
nodes.forEach((node) => {
|
||||
// 只选择未禁用且是文件的节点
|
||||
if (!node.disabled) {
|
||||
treeRef.value?.setChecked(node.data, true, false)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
treeRef.value?.setCheckedKeys([])
|
||||
}
|
||||
}
|
||||
|
||||
function submit() {
|
||||
loading.value = true
|
||||
disabled.value = true
|
||||
// 选中的节点的token
|
||||
const checkedNodes = treeRef.value?.getCheckedNodes() || []
|
||||
const filteredNodes = checkedNodes.filter((node: any) => !node.is_exist)
|
||||
const newList = filteredNodes.map((node: any) => {
|
||||
return {
|
||||
name: node.name,
|
||||
token: node.token,
|
||||
type: node.type,
|
||||
}
|
||||
})
|
||||
if (newList.length === 0) {
|
||||
disabled.value = false
|
||||
MsgWarning(t('views.document.feishu.errorMessage1'))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
documentApi
|
||||
.importLarkDocument(knowledgeId, newList, loading)
|
||||
.then((res) => {
|
||||
MsgSuccess(t('views.document.tip.importMessage'))
|
||||
disabled.value = false
|
||||
router.go(-1)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to load tree nodes:', err)
|
||||
})
|
||||
.finally(() => {
|
||||
disabled.value = false
|
||||
})
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
function back() {
|
||||
router.go(-1)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.create-knowledge {
|
||||
&__component {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
padding: 16px 24px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.upload-document {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.xlsx-icon {
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: #000000 !important;
|
||||
fill: #ffffff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -8,18 +8,49 @@
|
|||
:close-on-press-escape="false"
|
||||
>
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<h4 :id="titleId" :class="titleClass">{{ $t('views.chatLog.selectKnowledge') }}</h4>
|
||||
<h4 :id="titleId" :class="titleClass">{{ '文档迁移到' }}</h4>
|
||||
</template>
|
||||
<el-form
|
||||
class="p-24"
|
||||
ref="FormRef"
|
||||
:model="form"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-form-item :label="$t('views.chatLog.selectKnowledge')" required>
|
||||
<el-tree-select
|
||||
v-model="form.selectKnowledge"
|
||||
:data="knowledgeList"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<div class="flex align-center">
|
||||
<KnowledgeIcon class="mr-12" :size="20" v-if="data.resource_type" :type="data.type" />
|
||||
<el-avatar v-else class="mr-12" shape="square" :size="20" style="background: none">
|
||||
<img
|
||||
src="@/assets/knowledge/icon_file-folder_colorful.svg"
|
||||
style="width: 100%"
|
||||
alt=""
|
||||
/>
|
||||
</el-avatar>
|
||||
|
||||
{{ data.name }}
|
||||
</div>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-tree-select v-model="selectKnowledge" :data="knowledgeList" style="width: 240px">
|
||||
<template #default="{ data: { label } }">
|
||||
{{ label }}<span style="color: gray">(suffix)</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="submitHandle" :disabled="!selectKnowledge || loading">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submitHandle"
|
||||
:disabled="!form.selectKnowledge || loading"
|
||||
>
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
|
|
@ -43,13 +74,25 @@ const emit = defineEmits(['refresh'])
|
|||
const loading = ref<boolean>(false)
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
const selectKnowledge = ref('')
|
||||
const knowledgeList = ref<any>([])
|
||||
const documentList = ref<any>([])
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
disabled: (data: any, node: any) => {
|
||||
console.log(data, node)
|
||||
return data.id === id || (node?.isLeaf && !data.resource_type)
|
||||
},
|
||||
}
|
||||
|
||||
const form = ref<any>({
|
||||
selectKnowledge: '',
|
||||
})
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
selectKnowledge.value = ''
|
||||
form.value.selectKnowledge = ''
|
||||
knowledgeList.value = []
|
||||
documentList.value = []
|
||||
}
|
||||
|
|
@ -62,7 +105,7 @@ const open = (list: any) => {
|
|||
}
|
||||
const submitHandle = () => {
|
||||
documentApi
|
||||
.putMigrateMulDocument(id, selectKnowledge.value, documentList.value, loading)
|
||||
.putMigrateMulDocument(id, form.value.selectKnowledge, documentList.value, loading)
|
||||
.then((res) => {
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
|
|
@ -70,15 +113,12 @@ const submitHandle = () => {
|
|||
}
|
||||
|
||||
function getKnowledge() {
|
||||
knowledge.asyncGetRootKnowledge(loading).then((res: any) => {
|
||||
knowledgeList.value = res.data?.filter((v: any) => v.id !== id)
|
||||
knowledge.asyncGetTreeRootKnowledge(loading).then((res: any) => {
|
||||
knowledgeList.value = res || []
|
||||
console.log(knowledgeList.value)
|
||||
})
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
getKnowledge()
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
|
|
|||
|
|
@ -9,30 +9,70 @@
|
|||
<el-button
|
||||
v-if="knowledgeDetail.type === 0"
|
||||
type="primary"
|
||||
@click="router.push({ path: `/knowledge/document/upload/${folderId}`, query: { id: id } })"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_CREATE.getWorkspacePermission]"
|
||||
@click="
|
||||
router.push({ path: `/knowledge/document/upload/${folderId}`, query: { id: id } })
|
||||
"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_CREATE.getWorkspacePermission,
|
||||
]"
|
||||
>{{ $t('views.document.uploadDocument') }}
|
||||
</el-button>
|
||||
<el-button v-if="knowledgeDetail.type === 1" type="primary" @click="importDoc"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_CREATE.getWorkspacePermission]"
|
||||
>{{ $t('views.document.importDocument') }}
|
||||
<el-button
|
||||
v-if="knowledgeDetail.type === 1"
|
||||
type="primary"
|
||||
@click="importDoc"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_CREATE.getWorkspacePermission,
|
||||
]"
|
||||
>{{ $t('views.document.importDocument') }}
|
||||
</el-button>
|
||||
|
||||
<el-button @click="batchRefresh" :disabled="multipleSelection.length === 0"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission]"
|
||||
>{{ $t('views.knowledge.setting.vectorization') }}
|
||||
<el-button
|
||||
v-if="knowledgeDetail.type === 2"
|
||||
type="primary"
|
||||
@click="
|
||||
router.push({
|
||||
path: `/knowledge/import`,
|
||||
query: { id: id, folder_token: knowledgeDetail.meta.folder_token },
|
||||
})
|
||||
"
|
||||
>{{ $t('views.document.importDocument') }}
|
||||
</el-button>
|
||||
<el-button @click="openGenerateDialog()" :disabled="multipleSelection.length === 0"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_GENERATE.getWorkspacePermission]"
|
||||
>{{ $t('views.document.generateQuestion.title') }}
|
||||
<el-button
|
||||
@click="batchRefresh"
|
||||
:disabled="multipleSelection.length === 0"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission,
|
||||
]"
|
||||
>{{ $t('views.knowledge.setting.vectorization') }}
|
||||
</el-button>
|
||||
<el-button @click="openknowledgeDialog()" :disabled="multipleSelection.length === 0"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_MIGRATE.getWorkspacePermission]"
|
||||
>{{ $t('views.document.setting.migration') }}
|
||||
<el-button
|
||||
@click="openGenerateDialog()"
|
||||
:disabled="multipleSelection.length === 0"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_GENERATE.getWorkspacePermission,
|
||||
]"
|
||||
>{{ $t('views.document.generateQuestion.title') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="openknowledgeDialog()"
|
||||
:disabled="multipleSelection.length === 0"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_MIGRATE.getWorkspacePermission,
|
||||
]"
|
||||
>{{ $t('views.document.setting.migration') }}
|
||||
</el-button>
|
||||
<el-dropdown>
|
||||
<el-button class="ml-12 mr-12"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission]"
|
||||
<el-button
|
||||
class="ml-12 mr-12"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<el-icon><MoreFilled /></el-icon>
|
||||
</el-button>
|
||||
|
|
@ -51,18 +91,6 @@
|
|||
v-if="knowledgeDetail.type === 1"
|
||||
>{{ $t('views.document.syncDocument') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
divided
|
||||
v-if="knowledgeDetail.type === 2"
|
||||
type="primary"
|
||||
@click="
|
||||
router.push({
|
||||
path: '/knowledge/import',
|
||||
query: { id: id, folder_token: knowledgeDetail.meta.folder_token },
|
||||
})
|
||||
"
|
||||
>{{ $t('views.document.importDocument') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
divided
|
||||
@click="syncLarkMulDocument"
|
||||
|
|
@ -357,7 +385,10 @@
|
|||
text
|
||||
@click.stop="cancelTask(row, TaskType.EMBEDDING)"
|
||||
:title="$t('views.document.setting.cancelVectorization')"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission]"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<AppIcon iconName="app-close" style="font-size: 16px"></AppIcon>
|
||||
</el-button>
|
||||
|
|
@ -368,7 +399,10 @@
|
|||
text
|
||||
@click.stop="refreshDocument(row)"
|
||||
:title="$t('views.knowledge.setting.vectorization')"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission]"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<AppIcon iconName="app-document-refresh" style="font-size: 16px"></AppIcon>
|
||||
</el-button>
|
||||
|
|
@ -379,15 +413,23 @@
|
|||
text
|
||||
@click.stop="settingDoc(row)"
|
||||
:title="$t('common.setting')"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission]"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<el-icon><Setting /></el-icon>
|
||||
</el-button>
|
||||
</span>
|
||||
<span @click.stop>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button text type="primary"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission]"
|
||||
<el-button
|
||||
text
|
||||
type="primary"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<el-icon><MoreFilled /></el-icon>
|
||||
</el-button>
|
||||
|
|
@ -399,7 +441,8 @@
|
|||
getTaskState(row.status, TaskType.GENERATE_PROBLEM),
|
||||
)
|
||||
"
|
||||
@click="cancelTask(row, TaskType.GENERATE_PROBLEM)">
|
||||
@click="cancelTask(row, TaskType.GENERATE_PROBLEM)"
|
||||
>
|
||||
<el-icon><Connection /></el-icon>
|
||||
{{ $t('views.document.setting.cancelGenerateQuestion') }}
|
||||
</el-dropdown-item>
|
||||
|
|
@ -420,7 +463,8 @@
|
|||
{{ $t('views.document.setting.export') }} Zip
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="Delete" @click.stop="deleteDocument(row)">
|
||||
{{$t('common.delete')}}</el-dropdown-item>
|
||||
{{ $t('common.delete') }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
|
@ -433,7 +477,10 @@
|
|||
text
|
||||
@click.stop="syncDocument(row)"
|
||||
:title="$t('views.knowledge.setting.sync')"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_SYNC.getWorkspacePermission]"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_SYNC.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<el-icon><Refresh /></el-icon>
|
||||
</el-button>
|
||||
|
|
@ -449,8 +496,11 @@
|
|||
text
|
||||
@click.stop="cancelTask(row, TaskType.EMBEDDING)"
|
||||
:title="$t('views.document.setting.cancelVectorization')"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission]"
|
||||
>
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<AppIcon iconName="app-close" style="font-size: 16px"></AppIcon>
|
||||
</el-button>
|
||||
|
||||
|
|
@ -460,23 +510,30 @@
|
|||
text
|
||||
@click.stop="refreshDocument(row)"
|
||||
:title="$t('views.knowledge.setting.vectorization')"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission]"
|
||||
>
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<AppIcon iconName="app-document-refresh" style="font-size: 16px"></AppIcon>
|
||||
</el-button>
|
||||
</span>
|
||||
|
||||
<span @click.stop>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button text type="primary"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission]"
|
||||
<el-button
|
||||
text
|
||||
type="primary"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_EDIT.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
<el-icon><MoreFilled /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item icon="Setting" @click="settingDoc(row)"
|
||||
>{{
|
||||
<el-dropdown-item icon="Setting" @click="settingDoc(row)">{{
|
||||
$t('common.setting')
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
|
|
@ -490,29 +547,24 @@
|
|||
<el-icon><Connection /></el-icon>
|
||||
{{ $t('views.document.setting.cancelGenerateQuestion') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-else @click="openGenerateDialog(row)"
|
||||
>
|
||||
<el-dropdown-item v-else @click="openGenerateDialog(row)">
|
||||
<el-icon><Connection /></el-icon>
|
||||
{{ $t('views.document.generateQuestion.title') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="openknowledgeDialog(row)"
|
||||
>
|
||||
<el-dropdown-item @click="openknowledgeDialog(row)">
|
||||
<AppIcon iconName="app-migrate"></AppIcon>
|
||||
{{ $t('views.document.setting.migration') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="exportDocument(row)"
|
||||
>
|
||||
<el-dropdown-item @click="exportDocument(row)">
|
||||
<AppIcon iconName="app-export"></AppIcon>
|
||||
{{ $t('views.document.setting.export') }} Excel
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="exportDocumentZip(row)"
|
||||
>
|
||||
<el-dropdown-item @click="exportDocumentZip(row)">
|
||||
<AppIcon iconName="app-export"></AppIcon>
|
||||
{{ $t('views.document.setting.export') }} Zip
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="Delete" @click.stop="deleteDocument(row)"
|
||||
>
|
||||
{{$t('common.delete')}}
|
||||
<el-dropdown-item icon="Delete" @click.stop="deleteDocument(row)">
|
||||
{{ $t('common.delete') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
|
|
@ -526,14 +578,24 @@
|
|||
</div>
|
||||
</el-card>
|
||||
<div class="mul-operation w-full flex" v-if="multipleSelection.length !== 0">
|
||||
<el-button :disabled="multipleSelection.length === 0" @click="cancelTaskHandle(1, row)"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission]">
|
||||
<el-button
|
||||
:disabled="multipleSelection.length === 0"
|
||||
@click="cancelTaskHandle(1, row)"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_VECTOR.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
{{ $t('views.document.setting.cancelVectorization') }}
|
||||
</el-button>
|
||||
<el-button :disabled="multipleSelection.length === 0" @click="cancelTaskHandle(2, row)"
|
||||
v-hasPermission="[RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,PermissionConst.KNOWLEDGE_DOCUMENT_GENERATE.getWorkspacePermission]"
|
||||
<el-button
|
||||
:disabled="multipleSelection.length === 0"
|
||||
@click="cancelTaskHandle(2, row)"
|
||||
v-hasPermission="[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_GENERATE.getWorkspacePermission,
|
||||
]"
|
||||
>
|
||||
|
||||
{{ $t('views.document.setting.cancelGenerate') }}
|
||||
</el-button>
|
||||
<el-text type="info" class="secondary ml-24">
|
||||
|
|
|
|||
|
|
@ -1,290 +0,0 @@
|
|||
<template>
|
||||
<LayoutContainer :header="$t('views.document.importDocument')" class="create-knowledge">
|
||||
<template #backButton>
|
||||
<back-button @click="back"></back-button>
|
||||
</template>
|
||||
<div class="create-knowledge__main flex" v-loading="loading">
|
||||
<div class="create-knowledge__component main-calc-height">
|
||||
<div class="upload-document p-24" style="min-width: 850px">
|
||||
<h4 class="title-decoration-1 mb-8">
|
||||
{{ $t('views.document.feishu.selectDocument') }}
|
||||
</h4>
|
||||
<el-form
|
||||
ref="FormRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<div class="mt-16 mb-16">
|
||||
<el-radio-group v-model="form.fileType" class="app-radio-button-group">
|
||||
<el-radio-button value="txt"
|
||||
>{{ $t('views.document.fileType.txt.label') }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="update-info flex p-8-12 border-r-4 mb-16">
|
||||
<div class="mt-4">
|
||||
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
|
||||
</div>
|
||||
<div class="ml-16 lighter">
|
||||
<p>{{ $t('views.document.feishu.tip1') }}</p>
|
||||
<p>{{ $t('views.document.feishu.tip2') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-4 mb-16">
|
||||
<el-checkbox
|
||||
v-model="allCheck"
|
||||
:label="$t('views.document.feishu.allCheck')"
|
||||
size="large"
|
||||
class="ml-24"
|
||||
@change="handleAllCheckChange"
|
||||
/>
|
||||
</div>
|
||||
<div style="height: calc(100vh - 450px)">
|
||||
<el-scrollbar>
|
||||
<el-tree
|
||||
:props="props"
|
||||
:load="loadNode"
|
||||
lazy
|
||||
show-checkbox
|
||||
node-key="token"
|
||||
ref="treeRef"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="flex align-center lighter">
|
||||
<img
|
||||
src="@/assets/fileType/file-icon.svg"
|
||||
alt=""
|
||||
height="20"
|
||||
v-if="data.type === 'folder'"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/docx-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.type === 'docx' || data.name.endsWith('.docx')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/xlsx-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.type === 'sheet' || data.name.endsWith('.xlsx')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/xls-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('xls')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/csv-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('csv')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/pdf-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.pdf')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/html-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.html')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/txt-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.txt')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/zip-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.zip')"
|
||||
/>
|
||||
<img
|
||||
src="@/assets/fileType/md-icon.svg"
|
||||
alt=""
|
||||
height="22"
|
||||
v-else-if="data.name.endsWith('.md')"
|
||||
/>
|
||||
|
||||
<span class="ml-4">{{ node.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="create-knowledge__footer text-right border-t">
|
||||
<el-button @click="router.go(-1)">{{ $t('common.cancel') }}</el-button>
|
||||
|
||||
<el-button @click="submit" type="primary" :disabled="disabled">
|
||||
{{ $t('views.document.buttons.import') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</LayoutContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onUnmounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { MsgConfirm, MsgSuccess, MsgWarning } from '@/utils/message'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import { t } from '@/locales'
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node'
|
||||
import documentApi from '@/api/knowledge/document'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const {
|
||||
query: { id, folder_token }, // id为knowledgeID,有id的是上传文档 folder_token为飞书文件夹token
|
||||
} = route
|
||||
const knowledgeId = id as string
|
||||
const folderToken = folder_token as string
|
||||
|
||||
const loading = ref(false)
|
||||
const disabled = ref(false)
|
||||
const allCheck = ref(false)
|
||||
const treeRef = ref<any>(null)
|
||||
|
||||
interface Tree {
|
||||
name: string
|
||||
leaf?: boolean
|
||||
type: string
|
||||
token: string
|
||||
is_exist: boolean
|
||||
}
|
||||
|
||||
const form = ref({
|
||||
fileType: 'txt',
|
||||
fileList: [] as any,
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
fileList: [
|
||||
{ required: true, message: t('views.document.upload.requiredMessage'), trigger: 'change' },
|
||||
],
|
||||
})
|
||||
|
||||
const props = {
|
||||
label: 'name',
|
||||
children: 'zones',
|
||||
isLeaf: (data: any) => data.type !== 'folder',
|
||||
disabled: (data: any) => data.is_exist,
|
||||
}
|
||||
|
||||
const loadNode = (node: Node, resolve: (nodeData: Tree[]) => void) => {
|
||||
const token = node.level === 0 ? folderToken : node.data.token // 根节点使用 folder_token,其他节点使用 node.data.token
|
||||
documentApi
|
||||
.getLarkDocumentList(knowledgeId, token, {}, loading)
|
||||
.then((res: any) => {
|
||||
const nodes = res.data.files as Tree[]
|
||||
resolve(nodes)
|
||||
nodes.forEach((childNode) => {
|
||||
if (childNode.is_exist) {
|
||||
treeRef.value?.setChecked(childNode.token, true, false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
.catch((err) => {
|
||||
console.error('Failed to load tree nodes:', err)
|
||||
})
|
||||
}
|
||||
|
||||
const handleAllCheckChange = (checked: boolean) => {
|
||||
if (checked) {
|
||||
// 获取所有已加载的节点
|
||||
const nodes = Object.values(treeRef.value?.store.nodesMap || {}) as any[]
|
||||
nodes.forEach((node) => {
|
||||
// 只选择未禁用且是文件的节点
|
||||
if (!node.disabled) {
|
||||
treeRef.value?.setChecked(node.data, true, false)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
treeRef.value?.setCheckedKeys([])
|
||||
}
|
||||
}
|
||||
|
||||
function submit() {
|
||||
loading.value = true
|
||||
disabled.value = true
|
||||
// 选中的节点的token
|
||||
const checkedNodes = treeRef.value?.getCheckedNodes() || []
|
||||
const filteredNodes = checkedNodes.filter((node: any) => !node.is_exist)
|
||||
const newList = filteredNodes.map((node: any) => {
|
||||
return {
|
||||
name: node.name,
|
||||
token: node.token,
|
||||
type: node.type,
|
||||
}
|
||||
})
|
||||
if (newList.length === 0) {
|
||||
disabled.value = false
|
||||
MsgWarning(t('views.document.feishu.errorMessage1'))
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
documentApi
|
||||
.importLarkDocument(knowledgeId, newList, loading)
|
||||
.then((res) => {
|
||||
MsgSuccess(t('views.document.tip.importMessage'))
|
||||
disabled.value = false
|
||||
router.go(-1)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to load tree nodes:', err)
|
||||
})
|
||||
.finally(() => {
|
||||
disabled.value = false
|
||||
})
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
function back() {
|
||||
router.go(-1)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.create-knowledge {
|
||||
&__component {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
padding: 16px 24px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.upload-document {
|
||||
width: 70%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.xlsx-icon {
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: #000000 !important;
|
||||
fill: #ffffff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -36,9 +36,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import useStore from '@/stores'
|
||||
const { knowledge } = useStore()
|
||||
import knowledgeApi from '@/api/knowledge/knowledge'
|
||||
|
||||
const emit = defineEmits(['refresh'])
|
||||
const loading = ref<boolean>(false)
|
||||
|
|
@ -59,7 +57,7 @@ const open = (id: string) => {
|
|||
}
|
||||
|
||||
const submit = () => {
|
||||
knowledge.asyncSyncKnowledge(knowledgeId.value, method.value, loading).then((res: any) => {
|
||||
knowledgeApi.putSyncWebKnowledge(knowledgeId.value, method.value, loading).then((res: any) => {
|
||||
emit('refresh', res.data)
|
||||
dialogVisible.value = false
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,70 +1,56 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:title="$t('views.log.selectDataset')"
|
||||
:title="$t('views.chatLog.selectKnowledge')"
|
||||
v-model="dialogVisible"
|
||||
width="600"
|
||||
class="select-dataset-dialog"
|
||||
class="select-knowledge-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
>
|
||||
<template #header="{ titleId, titleClass }">
|
||||
<div class="my-header flex">
|
||||
<h4 :id="titleId" :class="titleClass">{{ $t('views.log.selectDataset') }}</h4>
|
||||
<el-button link class="ml-16" @click="refresh">
|
||||
<el-icon class="mr-4"><Refresh /></el-icon>{{ $t('common.refresh') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<h4 :id="titleId" :class="titleClass">{{ '文档迁移到' }}</h4>
|
||||
</template>
|
||||
<div class="content-height">
|
||||
<el-radio-group v-model="selectDataset" class="card__radio">
|
||||
<el-scrollbar height="500">
|
||||
<div class="p-16">
|
||||
<el-row :gutter="12" v-loading="loading">
|
||||
<el-col :span="12" v-for="(item, index) in datasetList" :key="index" class="mb-16">
|
||||
<el-card shadow="never" :class="item.id === selectDataset ? 'active' : ''">
|
||||
<el-radio :value="item.id" size="large">
|
||||
<div class="flex align-center">
|
||||
<el-avatar
|
||||
v-if="item?.type === '0'"
|
||||
class="mr-8 avatar-blue"
|
||||
shape="square"
|
||||
:size="32"
|
||||
>
|
||||
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<el-avatar
|
||||
v-if="item?.type === '1'"
|
||||
class="mr-8 avatar-purple"
|
||||
shape="square"
|
||||
:size="32"
|
||||
>
|
||||
<img src="@/assets/knowledge/icon_web.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<el-avatar
|
||||
v-if="item?.type === '2'"
|
||||
class="mr-8 avatar-purple"
|
||||
shape="square"
|
||||
:size="32"
|
||||
style="background: none"
|
||||
>
|
||||
<img src="@/assets/knowledge/logo_lark.svg" style="width: 100%" alt="" />
|
||||
</el-avatar>
|
||||
<span class="ellipsis" :title="item.name">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</div>
|
||||
</el-radio>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<el-form
|
||||
class="p-24"
|
||||
ref="FormRef"
|
||||
:model="form"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-form-item :label="$t('views.chatLog.selectKnowledge')" required>
|
||||
<el-tree-select
|
||||
v-model="form.selectKnowledge"
|
||||
:data="knowledgeList"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<div class="flex align-center">
|
||||
<KnowledgeIcon class="mr-12" :size="20" v-if="data.resource_type" :type="data.type" />
|
||||
<el-avatar v-else class="mr-12" shape="square" :size="20" style="background: none">
|
||||
<img
|
||||
src="@/assets/knowledge/icon_file-folder_colorful.svg"
|
||||
style="width: 100%"
|
||||
alt=""
|
||||
/>
|
||||
</el-avatar>
|
||||
|
||||
{{ data.name }}
|
||||
</div>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="submitHandle" :disabled="!selectDataset || loading">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submitHandle"
|
||||
:disabled="!form.selectKnowledge || loading"
|
||||
>
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
|
|
@ -80,7 +66,7 @@ import useStore from '@/stores/modules-shared-system'
|
|||
const { knowledge } = useStore()
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { id } // id为datasetID
|
||||
params: { id }, // id为knowledgeID
|
||||
} = route as any
|
||||
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
|
@ -88,46 +74,55 @@ const emit = defineEmits(['refresh'])
|
|||
const loading = ref<boolean>(false)
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
const selectDataset = ref('')
|
||||
const datasetList = ref<any>([])
|
||||
const knowledgeList = ref<any>([])
|
||||
const documentList = ref<any>([])
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
disabled: (data: any, node: any) => {
|
||||
console.log(data, node)
|
||||
return data.id === id || (node?.isLeaf && !data.resource_type)
|
||||
},
|
||||
}
|
||||
|
||||
const form = ref<any>({
|
||||
selectKnowledge: '',
|
||||
})
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
selectDataset.value = ''
|
||||
datasetList.value = []
|
||||
form.value.selectKnowledge = ''
|
||||
knowledgeList.value = []
|
||||
documentList.value = []
|
||||
}
|
||||
})
|
||||
|
||||
const open = (list: any) => {
|
||||
documentList.value = list
|
||||
getDataset()
|
||||
getKnowledge()
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const submitHandle = () => {
|
||||
documentApi
|
||||
.putMigrateMulDocument(id, selectDataset.value, documentList.value, loading)
|
||||
.putMigrateMulDocument(id, form.value.selectKnowledge, documentList.value, loading)
|
||||
.then((res) => {
|
||||
emit('refresh')
|
||||
dialogVisible.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function getDataset() {
|
||||
knowledge.asyncGetRootKnowledge(loading).then((res: any) => {
|
||||
datasetList.value = res.data?.filter((v: any) => v.id !== id)
|
||||
function getKnowledge() {
|
||||
knowledge.asyncGetTreeRootKnowledge(loading).then((res: any) => {
|
||||
knowledgeList.value = res || []
|
||||
console.log(knowledgeList.value)
|
||||
})
|
||||
}
|
||||
|
||||
const refresh = () => {
|
||||
getDataset()
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.select-dataset-dialog {
|
||||
.select-knowledge-dialog {
|
||||
padding: 0;
|
||||
.el-dialog__header {
|
||||
padding: 24px 24px 0 24px;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,18 @@
|
|||
>{{ $t('views.document.importDocument') }}
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-if="knowledgeDetail.type === 2"
|
||||
type="primary"
|
||||
@click="
|
||||
router.push({
|
||||
path: `/knowledge/import`,
|
||||
query: { id: id, folder_token: knowledgeDetail.meta.folder_token },
|
||||
})
|
||||
"
|
||||
>{{ $t('views.document.importDocument') }}
|
||||
</el-button>
|
||||
|
||||
<el-button @click="batchRefresh" :disabled="multipleSelection.length === 0">
|
||||
{{ $t('views.knowledge.setting.vectorization') }}
|
||||
</el-button>
|
||||
|
|
@ -49,18 +61,7 @@
|
|||
v-if="knowledgeDetail.type === 1"
|
||||
>{{ $t('views.document.syncDocument') }}</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
divided
|
||||
v-if="knowledgeDetail.type === 2"
|
||||
type="primary"
|
||||
@click="
|
||||
router.push({
|
||||
path: '/knowledge/import',
|
||||
query: { id: id, folder_token: knowledgeDetail.meta.folder_token },
|
||||
})
|
||||
"
|
||||
>{{ $t('views.document.importDocument') }}</el-dropdown-item
|
||||
>
|
||||
|
||||
<el-dropdown-item
|
||||
divided
|
||||
@click="syncLarkMulDocument"
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import useStore from '@/stores/modules-shared-system'
|
||||
const { knowledge } = useStore()
|
||||
import knowledgeApi from '@/api/shared/knowledge'
|
||||
|
||||
const emit = defineEmits(['refresh'])
|
||||
const loading = ref<boolean>(false)
|
||||
|
|
@ -57,9 +55,8 @@ const open = (id: string) => {
|
|||
knowledgeId.value = id
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const submit = () => {
|
||||
knowledge.asyncSyncKnowledge(knowledgeId.value, method.value, loading).then((res: any) => {
|
||||
knowledgeApi.putSyncWebKnowledge(knowledgeId.value, method.value, loading).then((res: any) => {
|
||||
emit('refresh', res.data)
|
||||
dialogVisible.value = false
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue