fix(knowledge base): knowledge base lark upload (#3255)

This commit is contained in:
dataeaseShu 2025-06-13 17:12:31 +08:00 committed by GitHub
parent 67ec3c15f8
commit ac6716b29b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 285 additions and 122 deletions

View File

@ -275,6 +275,13 @@ const importLarkDocument: (
return post(`${prefix}/lark/${knowledge_id}/import`, data, null, loading)
}
const postLarkKnowledge: (data: any, loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (
data,
loading,
) => {
return post(`${prefix}/knowledge/lark/save`, data, null, loading)
}
export default {
getKnowledgeByFolder,
getKnowledgeList,
@ -294,4 +301,5 @@ export default {
getLarkDocumentList,
importLarkDocument,
postLarkKnowledge,
}

View File

@ -333,6 +333,13 @@ const importLarkDocument: (
return post(`${prefix}/lark/${knowledge_id}/import`, data, null, loading)
}
const postLarkKnowledge: (data: any, loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (
data,
loading,
) => {
return post(`${prefix}/knowledge/lark/save`, data, null, loading)
}
export default {
getKnowledgeByFolder,
getKnowledgeList,
@ -349,9 +356,6 @@ export default {
postKnowledge,
getKnowledgeModel,
postWebKnowledge,
getLarkDocumentList,
importLarkDocument,
getSharedWorkspaceKnowledge,
getSharedWorkspaceKnowledgePage,
getSharedAuthorizationKnowledgeGet,
@ -360,4 +364,8 @@ export default {
getSharedAuthorizationToolPost,
getSharedAuthorizationModelGet,
getSharedAuthorizationModelPost,
getLarkDocumentList,
importLarkDocument,
postLarkKnowledge,
}

View File

@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.833496 3.33333C0.833496 2.8731 1.20659 2.5 1.66683 2.5H8.6518C8.96744 2.5 9.256 2.67834 9.39716 2.96066L10.0002 4.16667H18.3335C18.7937 4.16667 19.1668 4.53976 19.1668 5V16.6667C19.1668 17.1269 18.7937 17.5 18.3335 17.5H1.66683C1.20659 17.5 0.833496 17.1269 0.833496 16.6667V3.33333Z" fill="#FFA53D"/>
<path d="M0.833496 4.99999C0.833496 4.53975 1.20659 4.16666 1.66683 4.16666H18.3335C18.7937 4.16666 19.1668 4.53975 19.1668 4.99999V16.6667C19.1668 17.1269 18.7937 17.5 18.3335 17.5H1.66683C1.20659 17.5 0.833496 17.1269 0.833496 16.6667V4.99999Z" fill="#FFC60A"/>
</svg>

After

Width:  |  Height:  |  Size: 681 B

View File

@ -1,17 +1,17 @@
<template>
<el-avatar v-if="type === 1" class="avatar-purple" shape="square" :size="32">
<el-avatar v-if="type === 1" class="avatar-purple" shape="square" :size="size">
<img src="@/assets/knowledge/icon_web.svg" style="width: 58%" alt="" />
</el-avatar>
<el-avatar
v-else-if="type === 2"
class="avatar-purple"
shape="square"
:size="32"
:size="size"
style="background: none"
>
<img src="@/assets/knowledge/logo_lark.svg" style="width: 100%" alt="" />
</el-avatar>
<el-avatar v-else class="avatar-blue" shape="square" :size="32">
<el-avatar v-else class="avatar-blue" shape="square" :size="size">
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
</el-avatar>
</template>
@ -22,5 +22,9 @@ const props = defineProps({
type: [String, Number],
default: '',
},
size: {
type: [String, Number],
default: 32,
},
})
</script>

View File

@ -54,8 +54,8 @@
<script setup lang="ts">
import { ref, watch, reactive } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import BaseForm from '@/views/knowledge/component/BaseForm.vue'
import KnowledgeApi from '@/api/knowledge/knowledge'
import BaseForm from '@/views/knowledge-shared-system/component/BaseForm.vue'
import KnowledgeApi from '@/api/shared/knowledge'
import { MsgSuccess, MsgAlert } from '@/utils/message'
import { t } from '@/locales'
import { ComplexPermission } from '@/utils/permission/type'
@ -142,7 +142,7 @@ const submitHandle = async () => {
await DatasetFormRef.value.validate((valid: any) => {
if (valid) {
const obj = { ...BaseFormRef.value.form, ...datasetForm.value }
KnowledgeApi.postLarkKnowledge(obj, loading).then((res) => {
KnowledgeApi.postLarkKnowledge({...obj, embedding_model_id: obj.embedding }, loading).then((res) => {
MsgSuccess(t('common.createSuccess'))
router.push({ path: `/knowledge/${res.data.id}/document` })
emit('refresh')

View File

@ -165,6 +165,7 @@ function refreshMigrateParagraph() {}
border: 1px solid #ffffff;
box-shadow: none !important;
position: relative;
overflow: inherit;
&:hover {
background: rgba(31, 35, 41, 0.1);
border: 1px solid #dee0e3;
@ -173,7 +174,9 @@ function refreshMigrateParagraph() {}
position: absolute;
right: 0;
top: 0;
overflow: inherit;
border: 1px solid #dee0e3;
z-index: 10;
}
}
</style>

View File

@ -65,38 +65,39 @@
<div v-else>
<el-scrollbar class="paragraph-scollbar">
<div class="paragraph-detail">
<InfiniteScroll
:size="paragraphDetail.length"
:total="paginationConfig.total"
:page_size="paginationConfig.page_size"
v-model:current_page="paginationConfig.current_page"
@load="getParagraphList"
:loading="loading"
>
<VueDraggable
ref="el"
v-bind:modelValue="paragraphDetail"
:disabled="isBatch === true"
handle=".handle"
:animation="150"
ghostClass="ghost"
@end="onEnd"
<el-checkbox-group v-model="multipleSelection">
<InfiniteScroll
:size="paragraphDetail.length"
:total="paginationConfig.total"
:page_size="paginationConfig.page_size"
v-model:current_page="paginationConfig.current_page"
@load="getParagraphList"
:loading="loading"
>
<el-checkbox-group v-model="multipleSelection">
<VueDraggable
ref="el"
v-model="paragraphDetail"
:disabled="isBatch === true"
handle=".handle"
:animation="150"
ghostClass="ghost"
>
<template v-for="(item, index) in paragraphDetail" :key="item.id">
<!-- 批量操作 -->
<div class="paragraph-card flex" :id="item.id" v-if="isBatch === true">
<el-checkbox :value="item.id" />
<ParagraphCard :data="item" class="mb-8 w-full" />
</div>
<!-- 非批量操作 -->
<div class="handle paragraph-card flex" :id="item.id" v-else>
<img
src="@/assets/sort.svg"
alt=""
height="15"
class="handle-img mr-8 mt-24 cursor"
/>
<div style="display: flex; margin-bottom: 16px">
<!-- 批量操作 -->
<div class="paragraph-card flex" :id="item.id" v-if="isBatch === true">
<el-checkbox :value="item.id" />
<ParagraphCard :data="item" class="mb-8 w-full" />
</div>
<!-- 非批量操作 -->
<div class="handle paragraph-card flex" :id="item.id" v-else>
<img
src="@/assets/sort.svg"
alt=""
height="15"
class="handle-img mr-8 mt-24 cursor"
/>
</div>
<ParagraphCard
:data="item"
class="mb-8 w-full"
@ -105,9 +106,9 @@
/>
</div>
</template>
</el-checkbox-group>
</VueDraggable>
</InfiniteScroll>
</VueDraggable>
</InfiniteScroll>
</el-checkbox-group>
</div>
</el-scrollbar>
</div>
@ -341,6 +342,10 @@ onMounted(() => {
height: calc(100vh - 215px);
max-width: 1000px;
margin: 16px auto;
// .el-checkbox-group {
// display: flex;
// }
}
&__main {

View File

@ -3,12 +3,12 @@
v-model="filterText"
:placeholder="$t('common.search')"
prefix-icon="Search"
class="mb-16 mt-4"
class="mb-16 mt-4 1"
clearable
/>
<div class="pt-0">
<el-table :data="filterData" :max-height="tableHeight">
<el-table-column prop="name" :label="$t('common.name')">
<el-table row-key="id" :data="filterData" :max-height="tableHeight">
<el-table-column class-name="folder-flex" prop="name" :label="$t('common.name')">
<template #default="{ row }">
<div class="flex align-center">
<el-avatar
@ -16,7 +16,7 @@
style="background: none"
class="mr-12"
shape="square"
:size="24"
:size="20"
>
<img :src="row?.icon" alt="" />
</el-avatar>
@ -26,10 +26,23 @@
:name="row?.name"
pinyinColor
shape="square"
:size="24"
:size="20"
class="mr-12"
/>
<KnowledgeIcon v-if="isKnowledge" :type="row.icon" />
<el-avatar
v-if="row.isFolder"
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>
<KnowledgeIcon class="mr-12" :size="20" v-else-if="isKnowledge" :type="row.icon" />
<auto-tooltip :content="row?.name">
{{ row?.name }}
@ -43,16 +56,24 @@
width="100"
fixed="right"
>
<template #header>
<!-- <template #header>
<el-checkbox
:disabled="props.manage"
v-model="allChecked[AuthorizationEnum.MANAGE]"
:indeterminate="allIndeterminate[AuthorizationEnum.MANAGE]"
:label="$t('views.resourceAuthorization.setting.management')"
/>
</template>
</template> -->
<template #default="{ row }">
<el-checkbox
v-if="row.isFolder"
:disabled="props.manage"
v-model="row.permission[AuthorizationEnum.MANAGE]"
:indeterminate="row.permissionHalf[AuthorizationEnum.MANAGE]"
@change="(e: boolean) => checkedOperateChange(AuthorizationEnum.MANAGE, row, e)"
/>
<el-checkbox
v-else
:disabled="props.manage"
v-model="row.permission[AuthorizationEnum.MANAGE]"
@change="(e: boolean) => checkedOperateChange(AuthorizationEnum.MANAGE, row, e)"
@ -65,16 +86,24 @@
width="100"
fixed="right"
>
<template #header>
<!-- <template #header>
<el-checkbox
:disabled="props.manage"
v-model="allChecked[AuthorizationEnum.VIEW]"
:indeterminate="allIndeterminate[AuthorizationEnum.VIEW]"
:label="$t('views.resourceAuthorization.setting.check')"
/>
</template>
</template> -->
<template #default="{ row }">
<el-checkbox
v-if="row.isFolder"
:disabled="props.manage"
v-model="row.permission[AuthorizationEnum.VIEW]"
:indeterminate="row.permissionHalf[AuthorizationEnum.VIEW]"
@change="(e: boolean) => checkedOperateChange(AuthorizationEnum.VIEW, row, e)"
/>
<el-checkbox
v-else
:disabled="props.manage"
v-model="row.permission[AuthorizationEnum.VIEW]"
@change="(e: boolean) => checkedOperateChange(AuthorizationEnum.VIEW, row, e)"
@ -103,74 +132,9 @@ const props = defineProps({
const isKnowledge = computed(() => props.type === AuthorizationEnum.KNOWLEDGE)
const isApplication = computed(() => props.type === AuthorizationEnum.APPLICATION)
const emit = defineEmits(['update:data'])
const allChecked: any = ref({
[AuthorizationEnum.MANAGE]: computed({
get: () => {
return filterData.value.some((item: any) => item.permission[AuthorizationEnum.MANAGE])
},
set: (val: boolean) => {
if (val) {
filterData.value.map((item: any) => {
item.permission[AuthorizationEnum.MANAGE] = true
item.permission[AuthorizationEnum.VIEW] = true
})
} else {
filterData.value.map((item: any) => {
item.permission[AuthorizationEnum.MANAGE] = false
})
}
},
}),
[AuthorizationEnum.VIEW]: computed({
get: () => {
return filterData.value.some((item: any) => item.permission[AuthorizationEnum.VIEW])
},
set: (val: boolean) => {
if (val) {
filterData.value.map((item: any) => {
item.permission[AuthorizationEnum.VIEW] = true
})
} else {
filterData.value.map((item: any) => {
item.permission[AuthorizationEnum.VIEW] = false
item.permission[AuthorizationEnum.MANAGE] = false
})
}
},
}),
})
const filterText = ref('')
const filterData = computed(() =>
props.data.filter((v: any) => v.name.toLowerCase().includes(filterText.value.toLowerCase())),
)
const allIndeterminate: any = ref({
[AuthorizationEnum.MANAGE]: computed(() => {
const all_not_checked = filterData.value.every(
(item: any) => !item.permission[AuthorizationEnum.MANAGE],
)
if (all_not_checked) {
return false
}
return !filterData.value.every((item: any) => item.permission[AuthorizationEnum.MANAGE])
}),
[AuthorizationEnum.VIEW]: computed(() => {
const all_not_checked = filterData.value.every(
(item: any) => !item.permission[AuthorizationEnum.VIEW],
)
if (all_not_checked) {
return false
}
return !filterData.value.every((item: any) => item.permission[AuthorizationEnum.VIEW])
}),
})
function checkedOperateChange(Name: string | number, row: any, e: boolean) {
props.data.map((item: any) => {
if (item.id === row.id) {
const dfsPermission = (arr: any = [], Name: string | number, e: boolean, idArr: any[]) => {
arr.map((item: any) => {
if (idArr.includes(item.id)) {
item.permission[Name] = e
if (Name === AuthorizationEnum.MANAGE && e) {
item.permission[AuthorizationEnum.VIEW] = true
@ -178,7 +142,36 @@ function checkedOperateChange(Name: string | number, row: any, e: boolean) {
item.permission[AuthorizationEnum.MANAGE] = false
}
}
if (item.children?.length) {
dfsPermission(
item.children,
Name,
e,
idArr.includes(item.id) ? item.children.map((ele: any) => ele.id) : idArr,
)
}
})
}
const emit = defineEmits(['update:data', 'refreshData'])
const filterText = ref('')
const filterData = computed(() =>
props.data.filter((v: any) => v.name.toLowerCase().includes(filterText.value.toLowerCase())),
)
function checkedOperateChange(Name: string | number, row: any, e: boolean) {
dfsPermission(props.data, Name, e, [row.id])
emit('refreshData')
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
:deep(.folder-flex) {
.cell {
display: flex;
align-items: center;
}
}
</style>

View File

@ -52,6 +52,7 @@
:type="item.value"
:tableHeight="tableHeight"
:manage="isManage(currentType)"
@refreshData="refreshData"
></PermissionSetting>
</el-tab-pane>
</el-tabs>
@ -73,6 +74,8 @@ import PermissionSetting from './component/PermissionSetting.vue'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
import { AuthorizationEnum } from '@/enums/system'
import { t } from '@/locales'
import useStore from '@/stores'
import { cloneDeep } from 'lodash'
const loading = ref(false)
const rLoading = ref(false)
@ -84,6 +87,7 @@ const filterText = ref('')
const activeName = ref(AuthorizationEnum.KNOWLEDGE)
const tableHeight = ref(0)
const { folder } = useStore()
const settingTags = reactive([
{
@ -146,15 +150,149 @@ function getMember(id?: string) {
const user = (id && memberList.value.find((p: any) => p.user_id === id)) || null
currentUser.value = user ? user.id : memberList.value[0].id
currentType.value = user ? user.type : memberList.value[0].type
ResourcePermissions(currentUser.value)
getWholeTree(currentUser.value)
})
}
const dfsPermissionIndeterminateTrue = (arr: any = [], type: string) => {
return arr.every((item: any) => {
if (item.children?.length) {
item.permission[type] = dfsPermissionIndeterminateTrue(item.children, type)
}
return item.permission[type]
})
}
const dfsPermissionIndeterminate = (
arr: any = [],
type: string,
permissionHalf: any,
permissionHalfMap: any,
id: string,
) => {
arr.forEach((item: any) => {
if (item.isFolder) {
if (!permissionHalfMap[item.id]) {
permissionHalfMap[item.id] = cloneDeep(permissionHalf)
}
}
if (item.children?.length) {
dfsPermissionIndeterminate(item.children, type, permissionHalf, permissionHalfMap, item.id)
}
if (!item.isFolder) {
permissionHalfMap[id][type] = [...permissionHalfMap[id][type], item.permission[type]]
}
if (item.isFolder) {
item.permissionHalf[type] = permissionHalfMap[item.id][type].length
? new Set(permissionHalfMap[item.id][type]).size > 1
: false
if (item.children.some((ele: any) => ele.isFolder && ele.permissionHalf[type])) {
item.permissionHalf[type] = true
}
if (
item.children.some((ele: any) => ele.permission[type]) &&
item.children.some((ele: any) => !ele.permission[type])
) {
item.permissionHalf[type] = true
}
}
})
}
const dfsFolder = (arr: any[] = [], folderIdMap: any) => {
arr.forEach((ele) => {
if (ele.permission) return
if (ele.children?.length) {
if (folderIdMap[ele.id]) {
ele.children = [...ele.children, ...folderIdMap[ele.id]]
}
dfsFolder(ele.children, folderIdMap)
} else {
ele.children = folderIdMap[ele.id] || []
}
ele.isFolder = true
ele.permission = {
VIEW: false,
MANAGE: false,
ROLE: false,
}
ele.permissionHalf = {
VIEW: false,
MANAGE: false,
ROLE: false,
}
})
}
function getFolder() {
return folder.asyncGetFolder('KNOWLEDGE', {}, loading)
}
function getResourcePermissions(user_id: string) {
return AuthorizationApi.getResourceAuthorization(user_id, rLoading)
}
const getWholeTree = async (user_id: string) => {
const [parentRes, childrenRes] = await Promise.all([getFolder(), getResourcePermissions(user_id)])
if (!childrenRes.data || Object.keys(childrenRes.data).length > 0) {
settingTags.map((item: any) => {
let folderIdMap = []
const folderTree = cloneDeep((parentRes as unknown as any).data)
if (Object.keys(childrenRes.data).indexOf(item.value) !== -1) {
folderIdMap = getFolderIdMap(childrenRes.data[item.value])
dfsFolder(folderTree, folderIdMap)
const permissionHalf = {
VIEW: [],
MANAGE: [],
ROLE: [],
}
Object.keys(permissionHalf).forEach((ele) => {
dfsPermissionIndeterminateTrue(folderTree, ele)
dfsPermissionIndeterminate(folderTree, ele, cloneDeep(permissionHalf), {}, 'default')
})
item.data = folderTree
}
})
}
}
const refreshData = () => {
settingTags.map((item: any) => {
if (activeName.value === item.value) {
const permissionHalf = {
VIEW: [],
MANAGE: [],
ROLE: [],
}
Object.keys(permissionHalf).forEach((ele) => {
dfsPermissionIndeterminateTrue(item.data, ele)
dfsPermissionIndeterminate(item.data, ele, cloneDeep(permissionHalf), {}, 'default')
})
}
})
}
const getFolderIdMap = (arr: any = []) => {
return arr.reduce((pre: any, next: any) => {
if (pre[next.folder_id]) {
pre[next.folder_id].push(next)
} else {
pre[next.folder_id] = [next]
}
return pre
}, {})
}
function ResourcePermissions(user_id: string) {
AuthorizationApi.getResourceAuthorization(user_id, rLoading).then((res) => {
if (!res.data || Object.keys(res.data).length > 0) {
settingTags.map((item: any) => {
if (Object.keys(res.data).indexOf(item.value) !== -1) {
item.data = res.data[item.value]
getFolderIdMap(item.data)
}
})
}