feat: folder

This commit is contained in:
wangdan-fit2cloud 2025-06-19 17:10:39 +08:00
parent e02d417af9
commit 2e15552853
14 changed files with 336 additions and 295 deletions

View File

@ -41,7 +41,7 @@
{{ $t('common.cancel') }} {{ $t('common.cancel') }}
</el-button> </el-button>
<el-button type="primary" @click="submitHandle" :loading="loading"> <el-button type="primary" @click="submitHandle" :loading="loading">
{{ $t('common.add') }} {{ isEdit ? $t('common.confirm') : $t('common.add') }}
</el-button> </el-button>
</span> </span>
</template> </template>
@ -67,6 +67,7 @@ const loading = ref(false)
const dialogVisible = ref<boolean>(false) const dialogVisible = ref<boolean>(false)
const sourceType = ref<any>('') const sourceType = ref<any>('')
const isEdit = ref<boolean>(false) const isEdit = ref<boolean>(false)
const editId = ref<string>('')
const folderForm = ref<any>({ const folderForm = ref<any>({
name: '', name: '',
@ -98,11 +99,16 @@ watch(dialogVisible, (bool) => {
const open = (source: string, id: string, data?: any) => { const open = (source: string, id: string, data?: any) => {
sourceType.value = source sourceType.value = source
folderForm.value.parent_id = id
if (data) { if (data) {
// id
editId.value = data.id
folderForm.value.name = data.name folderForm.value.name = data.name
folderForm.value.desc = data.desc folderForm.value.desc = data.desc
folderForm.value.parent_id = data.parent_id
isEdit.value = true isEdit.value = true
} else {
// idid
folderForm.value.parent_id = id
} }
dialogVisible.value = true dialogVisible.value = true
} }
@ -111,7 +117,9 @@ const submitHandle = async () => {
await FolderFormRef.value.validate((valid: any) => { await FolderFormRef.value.validate((valid: any) => {
if (valid) { if (valid) {
if (isEdit.value) { if (isEdit.value) {
folderApi.putFolder(sourceType.value, folderForm.value, loading).then((res) => { folderApi
.putFolder(editId.value, sourceType.value, folderForm.value, loading)
.then((res) => {
MsgSuccess(t('common.editSuccess')) MsgSuccess(t('common.editSuccess'))
emit('refresh') emit('refresh')
dialogVisible.value = false dialogVisible.value = false

View File

@ -27,6 +27,7 @@
highlight-current highlight-current
class="overflow-inherit_node__children" class="overflow-inherit_node__children"
node-key="id" node-key="id"
v-loading="loading"
> >
<template #default="{ node, data }"> <template #default="{ node, data }">
<div class="flex-between w-full" @mouseenter.stop="handleMouseEnter(data)"> <div class="flex-between w-full" @mouseenter.stop="handleMouseEnter(data)">
@ -36,6 +37,7 @@
</div> </div>
<div <div
v-if="canOperation"
@click.stop @click.stop
v-show="hoverNodeId === data.id" v-show="hoverNodeId === data.id"
@mouseenter.stop="handleMouseEnter(data)" @mouseenter.stop="handleMouseEnter(data)"
@ -103,6 +105,10 @@ const props = defineProps({
type: String, type: String,
default: 'views.system.share_knowledge', default: 'views.system.share_knowledge',
}, },
canOperation: {
type: Boolean,
default: true,
},
}) })
interface Tree { interface Tree {
name: string name: string
@ -122,11 +128,12 @@ const treeRef = ref<TreeInstance>()
const filterText = ref('') const filterText = ref('')
const hoverNodeId = ref<string | undefined>('') const hoverNodeId = ref<string | undefined>('')
const title = ref('') const title = ref('')
const loading = ref(false)
watch(filterText, (val) => { watch(filterText, (val) => {
treeRef.value!.filter(val) treeRef.value!.filter(val)
}) })
let time let time: any
function handleMouseEnter(data: Tree) { function handleMouseEnter(data: Tree) {
clearTimeout(time) clearTimeout(time)
@ -153,7 +160,7 @@ const handleSharedNodeClick = () => {
} }
function deleteFolder(row: Tree) { function deleteFolder(row: Tree) {
folderApi.delFolder(row.id as string, props.source).then(() => { folderApi.delFolder(row.id as string, props.source, loading).then(() => {
emit('refreshTree') emit('refreshTree')
}) })
} }

View File

@ -2,11 +2,11 @@
<div v-infinite-scroll="loadData" :infinite-scroll-disabled="disabledScroll"> <div v-infinite-scroll="loadData" :infinite-scroll-disabled="disabledScroll">
<slot /> <slot />
</div> </div>
<div style="padding: 16px 10px"> <div style="padding: 0 10px 16px">
<el-divider v-if="size > 0 && loading"> <el-divider v-if="size > 0 && loading" style="background: none">
<el-text type="info"> {{ $t('components.loading') }}...</el-text> <el-text type="info"> {{ $t('components.loading') }}...</el-text>
</el-divider> </el-divider>
<el-divider v-if="noMore"> <el-divider v-if="noMore" style="background: none !important">
<el-text type="info"> {{ $t('components.noMore') }}</el-text> <el-text type="info"> {{ $t('components.noMore') }}</el-text>
</el-divider> </el-divider>
</div> </div>
@ -21,27 +21,27 @@ const props = defineProps({
*/ */
size: { size: {
type: Number, type: Number,
default: 0 default: 0,
}, },
/** /**
* 总数 * 总数
*/ */
total: { total: {
type: Number, type: Number,
default: 0 default: 0,
}, },
/** /**
* 总数 * 总数
*/ */
page_size: { page_size: {
type: Number, type: Number,
default: 0 default: 0,
}, },
current_page: { current_page: {
type: Number, type: Number,
default: 0 default: 0,
}, },
loading: Boolean loading: Boolean,
}) })
const emit = defineEmits(['update:current_page', 'load']) const emit = defineEmits(['update:current_page', 'load'])
@ -53,12 +53,12 @@ watch(
if (val === 1) { if (val === 1) {
current.value = 1 current.value = 1
} }
} },
) )
const noMore = computed( const noMore = computed(
() => () =>
props.size > 0 && props.size === props.total && props.total > props.page_size && !props.loading props.size > 0 && props.size === props.total && props.total > props.page_size && !props.loading,
) )
const disabledScroll = computed(() => props.size > 0 && (props.loading || noMore.value)) const disabledScroll = computed(() => props.size > 0 && (props.loading || noMore.value))

View File

@ -11,10 +11,11 @@
<slot name="search"> </slot> <slot name="search"> </slot>
</div> </div>
</div> </div>
<el-scrollbar>
<div class="content-container__main p-16"> <div class="content-container__main p-16">
<slot></slot> <slot></slot>
</div> </div>
</el-scrollbar>
</div> </div>
</template> </template>

View File

@ -241,3 +241,7 @@
.el-form--label-top .el-form-item .el-form-item__label { .el-form--label-top .el-form-item .el-form-item__label {
padding-right: 0; padding-right: 0;
} }
.el-divider__text {
background: var(--app-layout-bg-color);
}

View File

@ -43,6 +43,7 @@
@handleNodeClick="folderClickHandel" @handleNodeClick="folderClickHandel"
class="p-8" class="p-8"
v-loading="folderLoading" v-loading="folderLoading"
:canOperation="false"
/> />
</template> </template>
<el-scrollbar> <el-scrollbar>

View File

@ -7,6 +7,7 @@
:data="folderList" :data="folderList"
:currentNodeKey="currentFolder?.id" :currentNodeKey="currentFolder?.id"
@handleNodeClick="folderClickHandel" @handleNodeClick="folderClickHandel"
@refreshTree="refreshFolder"
class="p-8" class="p-8"
/> />
</template> </template>
@ -129,7 +130,10 @@
</el-dropdown> </el-dropdown>
</div> </div>
</template> </template>
<div v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading"> <div
v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading"
style="max-height: calc(100vh - 140px)"
>
<InfiniteScroll <InfiniteScroll
:size="applicationList.length" :size="applicationList.length"
:total="paginationConfig.total" :total="paginationConfig.total"
@ -367,21 +371,6 @@ function getList() {
}) })
} }
function getFolder() {
const params = {}
folder.asyncGetFolder(FolderSource.APPLICATION, params, loading).then((res: any) => {
folderList.value = res.data
currentFolder.value = res.data?.[0] || {}
getList()
})
}
function folderClickHandel(row: any) {
currentFolder.value = row
applicationList.value = []
getList()
}
function clickFolder(item: any) { function clickFolder(item: any) {
currentFolder.value.id = item.id currentFolder.value.id = item.id
applicationList.value = [] applicationList.value = []
@ -482,15 +471,6 @@ const exportApplication = (application: any) => {
}) })
} }
const CreateFolderDialogRef = ref()
function openCreateFolder() {
CreateFolderDialogRef.value.open(FolderSource.APPLICATION, currentFolder.value.parent_id)
}
function refreshFolder() {
applicationList.value = []
getFolder()
getList()
}
const elUploadRef = ref() const elUploadRef = ref()
const importApplication = (file: any) => { const importApplication = (file: any) => {
const formData = new FormData() const formData = new FormData()
@ -515,8 +495,34 @@ const importApplication = (file: any) => {
}) })
} }
onMounted(() => { //
const CreateFolderDialogRef = ref()
function openCreateFolder() {
CreateFolderDialogRef.value.open(FolderSource.APPLICATION, currentFolder.value.id)
}
function getFolder(bool?: boolean) {
const params = {}
folder.asyncGetFolder(FolderSource.APPLICATION, params, loading).then((res: any) => {
folderList.value = res.data
if (bool) {
//
currentFolder.value = res.data?.[0] || {}
}
getList()
})
}
function folderClickHandel(row: any) {
currentFolder.value = row
applicationList.value = []
getList()
}
function refreshFolder() {
applicationList.value = []
getFolder() getFolder()
}
onMounted(() => {
getFolder(true)
}) })
</script> </script>

View File

@ -61,14 +61,14 @@ const props = withDefaults(
next_disable: boolean next_disable: boolean
}>(), }>(),
{} {},
) )
const emit = defineEmits(['update:chatId', 'update:currentAbstract', 'refresh']) const emit = defineEmits(['update:chatId', 'update:currentAbstract', 'refresh'])
const route = useRoute() const route = useRoute()
const { const {
params: { id } params: { id },
} = route } = route
const loading = ref(false) const loading = ref(false)
const visible = ref(false) const visible = ref(false)
@ -77,7 +77,7 @@ const recordList = ref<chatType[]>([])
const paginationConfig = reactive({ const paginationConfig = reactive({
current_page: 1, current_page: 1,
page_size: 20, page_size: 20,
total: 0 total: 0,
}) })
function closeHandle() { function closeHandle() {
@ -93,7 +93,7 @@ function getChatRecord() {
paginationConfig.total = res.data.total paginationConfig.total = res.data.total
const list = res.data.records const list = res.data.records
recordList.value = [...list, ...recordList.value].sort((a, b) => recordList.value = [...list, ...recordList.value].sort((a, b) =>
a.create_time.localeCompare(b.create_time) a.create_time.localeCompare(b.create_time),
) )
if (paginationConfig.current_page === 1) { if (paginationConfig.current_page === 1) {
nextTick(() => { nextTick(() => {
@ -113,7 +113,7 @@ watch(
if (props.chatId) { if (props.chatId) {
getChatRecord() getChatRecord()
} }
} },
) )
watch(visible, (bool) => { watch(visible, (bool) => {
@ -143,7 +143,7 @@ const open = () => {
} }
defineExpose({ defineExpose({
open open,
}) })
</script> </script>
<style lang="scss"> <style lang="scss">
@ -158,9 +158,5 @@ defineExpose({
background: var(--app-layout-bg-color); background: var(--app-layout-bg-color);
padding: 0; padding: 0;
} }
:deep(.el-divider__text) {
background: var(--app-layout-bg-color);
}
} }
</style> </style>

View File

@ -146,7 +146,11 @@
</el-dropdown> </el-dropdown>
</div> </div>
</template> </template>
<div v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading">
<div
v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading"
style="max-height: calc(100vh - 140px)"
>
<InfiniteScroll <InfiniteScroll
:size="knowledgeList.length" :size="knowledgeList.length"
:total="paginationConfig.total" :total="paginationConfig.total"
@ -456,34 +460,12 @@ function getList() {
}) })
} }
function getFolder() {
const params = {}
folder.asyncGetFolder(FolderSource.KNOWLEDGE, params, loading).then((res: any) => {
folderList.value = res.data
currentFolder.value = res.data?.[0] || {}
getList()
})
}
function folderClickHandel(row: any) {
currentFolder.value = row
knowledgeList.value = []
if (currentFolder.value.id === 'share') return
getList()
}
function clickFolder(item: any) { function clickFolder(item: any) {
currentFolder.value.id = item.id currentFolder.value.id = item.id
knowledgeList.value = [] knowledgeList.value = []
getList() getList()
} }
const CreateFolderDialogRef = ref()
function openCreateFolder() {
CreateFolderDialogRef.value.open(FolderSource.KNOWLEDGE, currentFolder.value.parent_id)
}
const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>() const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>()
function openGenerateDialog(row: any) { function openGenerateDialog(row: any) {
if (GenerateRelatedDialogRef.value) { if (GenerateRelatedDialogRef.value) {
@ -521,14 +503,36 @@ function deleteKnowledge(row: any) {
.catch(() => {}) .catch(() => {})
} }
//
const CreateFolderDialogRef = ref()
function openCreateFolder() {
CreateFolderDialogRef.value.open(FolderSource.KNOWLEDGE, currentFolder.value.id)
}
function getFolder(bool?: boolean) {
const params = {}
folder.asyncGetFolder(FolderSource.KNOWLEDGE, params, loading).then((res: any) => {
folderList.value = res.data
if (bool) {
//
currentFolder.value = res.data?.[0] || {}
}
getList()
})
}
function folderClickHandel(row: any) {
currentFolder.value = row
knowledgeList.value = []
if (currentFolder.value.id === 'share') return
getList()
}
function refreshFolder() { function refreshFolder() {
console.log(currentFolder.value)
knowledgeList.value = [] knowledgeList.value = []
getFolder() getFolder()
getList()
} }
onMounted(() => { onMounted(() => {
getFolder() getFolder(true)
}) })
</script> </script>

View File

@ -324,7 +324,7 @@ function clickFolder(item: any) {
const CreateFolderDialogRef = ref() const CreateFolderDialogRef = ref()
function openCreateFolder() { function openCreateFolder() {
CreateFolderDialogRef.value.open('KNOWLEDGE', currentFolder.value.parent_id) CreateFolderDialogRef.value.open('KNOWLEDGE', currentFolder.value.id)
} }
const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>() const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>()

View File

@ -426,7 +426,7 @@ function configInitParams(item: any) {
const CreateFolderDialogRef = ref() const CreateFolderDialogRef = ref()
function openCreateFolder() { function openCreateFolder() {
CreateFolderDialogRef.value.open('TOOL', currentFolder.value.parent_id) CreateFolderDialogRef.value.open('TOOL', currentFolder.value.id)
} }
const elUploadRef = ref() const elUploadRef = ref()

View File

@ -242,7 +242,7 @@ function folderClickHandel(row: any) {
const CreateFolderDialogRef = ref() const CreateFolderDialogRef = ref()
function openCreateFolder() { function openCreateFolder() {
CreateFolderDialogRef.value.open('KNOWLEDGE', currentFolder.value.parent_id) CreateFolderDialogRef.value.open('KNOWLEDGE', currentFolder.value.id)
} }
const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>() const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>()

View File

@ -386,7 +386,7 @@ function folderClickHandel(row: any) {
const CreateFolderDialogRef = ref() const CreateFolderDialogRef = ref()
function openCreateFolder() { function openCreateFolder() {
CreateFolderDialogRef.value.open('KNOWLEDGE', currentFolder.value.parent_id) CreateFolderDialogRef.value.open('KNOWLEDGE', currentFolder.value.id)
} }
const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>() const GenerateRelatedDialogRef = ref<InstanceType<typeof GenerateRelatedDialog>>()

View File

@ -7,6 +7,7 @@
:data="folderList" :data="folderList"
:currentNodeKey="currentFolder?.id" :currentNodeKey="currentFolder?.id"
@handleNodeClick="folderClickHandel" @handleNodeClick="folderClickHandel"
@refreshTree ="refreshFolder"
shareTitle="views.system.share_tool" shareTitle="views.system.share_tool"
isShared isShared
class="p-8" class="p-8"
@ -109,7 +110,18 @@
</div> </div>
</template> </template>
<div> <div
v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading"
style="max-height: calc(100vh - 140px)"
>
<InfiniteScroll
:size="toolList.length"
:total="paginationConfig.total"
:page_size="paginationConfig.page_size"
v-model:current_page="paginationConfig.current_page"
@load="getList"
:loading="loading"
>
<el-row v-if="toolList.length > 0" :gutter="15"> <el-row v-if="toolList.length > 0" :gutter="15">
<template v-for="(item, index) in toolList" :key="index"> <template v-for="(item, index) in toolList" :key="index">
<el-col <el-col
@ -286,6 +298,7 @@
</template> </template>
</el-row> </el-row>
<el-empty :description="$t('common.noData')" v-else /> <el-empty :description="$t('common.noData')" v-else />
</InfiniteScroll>
</div> </div>
</ContentContainer> </ContentContainer>
<InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" /> <InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" />
@ -373,15 +386,11 @@ function getList() {
}) })
} }
function getFolder() { function clickFolder(item: any) {
const params = {} currentFolder.value.id = item.id
folder.asyncGetFolder(FolderSource.TOOL, params, loading).then((res: any) => { toolList.value = []
folderList.value = res.data
currentFolder.value = res.data?.[0] || {}
getList() getList()
})
} }
async function changeState(row: any) { async function changeState(row: any) {
if (row.is_active) { if (row.is_active) {
MsgConfirm( MsgConfirm(
@ -444,24 +453,6 @@ function refresh(data: any) {
getList() getList()
} }
function refreshFolder() {
toolList.value = []
getFolder()
getList()
}
function folderClickHandel(row: any) {
currentFolder.value = row
toolList.value = []
getList()
}
function clickFolder(item: any) {
currentFolder.value.id = item.id
toolList.value = []
getList()
}
function copyTool(row: any) { function copyTool(row: any) {
ToolDrawertitle.value = t('views.tool.copyTool') ToolDrawertitle.value = t('views.tool.copyTool')
const obj = cloneDeep(row) const obj = cloneDeep(row)
@ -506,11 +497,6 @@ function configInitParams(item: any) {
}) })
} }
const CreateFolderDialogRef = ref()
function openCreateFolder() {
CreateFolderDialogRef.value.open(FolderSource.TOOL, currentFolder.value.parent_id)
}
const elUploadRef = ref() const elUploadRef = ref()
function importTool(file: any) { function importTool(file: any) {
const formData = new FormData() const formData = new FormData()
@ -535,8 +521,36 @@ function importTool(file: any) {
}) })
} }
onMounted(() => { //
const CreateFolderDialogRef = ref()
function openCreateFolder() {
CreateFolderDialogRef.value.open(FolderSource.TOOL, currentFolder.value.id)
}
function getFolder(bool?: boolean) {
const params = {}
folder.asyncGetFolder(FolderSource.TOOL, params, loading).then((res: any) => {
folderList.value = res.data
if (bool) {
//
currentFolder.value = res.data?.[0] || {}
}
getList()
})
}
function refreshFolder() {
toolList.value = []
getFolder() getFolder()
}
function folderClickHandel(row: any) {
currentFolder.value = row
toolList.value = []
getList()
}
onMounted(() => {
getFolder(true)
}) })
</script> </script>