mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
perf: 优化文档分段前端懒加载 (#406)
This commit is contained in:
parent
cf4ce7ee46
commit
b123f0fa2f
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<div>
|
||||
<InfiniteScroll
|
||||
:size="paragraph_list.length"
|
||||
:total="modelValue.length"
|
||||
:page_size="page_size"
|
||||
v-model:current_page="current_page"
|
||||
@load="next()"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-card
|
||||
v-for="(child, cIndex) in paragraph_list"
|
||||
:key="cIndex"
|
||||
shadow="never"
|
||||
class="card-never mb-16"
|
||||
>
|
||||
<div class="flex-between">
|
||||
<span>{{ child.title || '-' }}</span>
|
||||
<div>
|
||||
<!-- 编辑分段按钮 -->
|
||||
<el-button link @click="editHandle(child, cIndex)">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
</el-button>
|
||||
<!-- 删除分段按钮 -->
|
||||
<el-button link @click="deleteHandle(child, cIndex)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lighter mt-12">
|
||||
{{ child.content }}
|
||||
</div>
|
||||
<div class="lighter mt-12">
|
||||
<el-text type="info"> {{ child.content.length }} 个字符 </el-text>
|
||||
</div>
|
||||
</el-card>
|
||||
</InfiniteScroll>
|
||||
|
||||
<EditParagraphDialog
|
||||
ref="EditParagraphDialogRef"
|
||||
@updateContent="updateContent"
|
||||
:isConnect="isConnect"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { defineProps, ref, computed } from 'vue'
|
||||
import EditParagraphDialog from './EditParagraphDialog.vue'
|
||||
import { MsgConfirm } from '@/utils/message'
|
||||
const page_size = ref<number>(20)
|
||||
const current_page = ref<number>(1)
|
||||
const currentCIndex = ref<number>(0)
|
||||
const EditParagraphDialogRef = ref()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const loading = ref<boolean>(false)
|
||||
const editHandle = (item: any, cIndex: number) => {
|
||||
currentCIndex.value = cIndex
|
||||
EditParagraphDialogRef.value.open(item)
|
||||
}
|
||||
|
||||
const props = defineProps<{ modelValue: Array<any>; isConnect: boolean }>()
|
||||
|
||||
const paragraph_list = computed(() => {
|
||||
return props.modelValue.slice(0, page_size.value * (current_page.value - 1) + page_size.value)
|
||||
})
|
||||
|
||||
const next = () => {
|
||||
loading.value = true
|
||||
current_page.value += 1
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const updateContent = (data: any) => {
|
||||
const new_value = [...props.modelValue]
|
||||
new_value[currentCIndex.value] = cloneDeep(data)
|
||||
emit('update:modelValue', new_value)
|
||||
}
|
||||
|
||||
const deleteHandle = (item: any, cIndex: number) => {
|
||||
MsgConfirm(`是否删除分段:${item.title || '-'} ?`, `删除后将不会存入知识库,对本地文档无影响。`, {
|
||||
confirmButtonText: '删除',
|
||||
confirmButtonClass: 'danger'
|
||||
})
|
||||
.then(() => {
|
||||
const new_value = [...props.modelValue]
|
||||
new_value.splice(cIndex, 1)
|
||||
emit('update:modelValue', new_value)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<el-tabs v-model="activeName" class="paragraph-tabs" @tab-click="handleClick">
|
||||
<el-tabs v-model="activeName" class="paragraph-tabs">
|
||||
<template v-for="(item, index) in newData" :key="index">
|
||||
<el-tab-pane :label="item.name" :name="index">
|
||||
<template #label>
|
||||
|
|
@ -8,55 +8,22 @@
|
|||
<span class="ml-4">{{ item?.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar ref="scrollRef" :key="index">
|
||||
<div class="mb-16">
|
||||
<el-text type="info">{{ item.content.length }} 段落</el-text>
|
||||
</div>
|
||||
<div class="paragraph-list" v-infinite-scroll="loadScroll">
|
||||
<el-card
|
||||
v-for="(child, cIndex) in scrollData"
|
||||
:key="cIndex"
|
||||
shadow="never"
|
||||
class="card-never mb-16"
|
||||
>
|
||||
<div class="flex-between">
|
||||
<span>{{ child.title || '-' }}</span>
|
||||
<div>
|
||||
<!-- 编辑分段按钮 -->
|
||||
<el-button link @click="editHandle(child, index, cIndex)">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
</el-button>
|
||||
<!-- 删除分段按钮 -->
|
||||
<el-button link @click="deleteHandle(child, index, cIndex)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lighter mt-12">
|
||||
{{ child.content }}
|
||||
</div>
|
||||
<div class="lighter mt-12">
|
||||
<el-text type="info"> {{ child.content.length }} 个字符 </el-text>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="mb-16">
|
||||
<el-text type="info">{{ item.content.length }} 段落</el-text>
|
||||
</div>
|
||||
<div class="paragraph-list" v-if="activeName == index">
|
||||
<el-scrollbar>
|
||||
<ParagraphList v-model="item.content" :isConnect="isConnect"> </ParagraphList>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</template>
|
||||
</el-tabs>
|
||||
<EditParagraphDialog
|
||||
ref="EditParagraphDialogRef"
|
||||
@updateContent="updateContent"
|
||||
:isConnect="isConnect"
|
||||
/>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, watch, nextTick } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import type { TabsPaneContext } from 'element-plus'
|
||||
import EditParagraphDialog from './EditParagraphDialog.vue'
|
||||
import { filesize, getImgUrl } from '@/utils/utils'
|
||||
import { MsgConfirm } from '@/utils/message'
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import ParagraphList from './ParagraphList.vue'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
|
|
@ -68,80 +35,20 @@ const props = defineProps({
|
|||
|
||||
const emit = defineEmits(['update:data'])
|
||||
|
||||
const EditParagraphDialogRef = ref()
|
||||
const scrollRef = ref()
|
||||
|
||||
const activeName = ref(0)
|
||||
const currentPIndex = ref(null) as any
|
||||
const currentCIndex = ref(null) as any
|
||||
|
||||
const newData = ref<any[]>([])
|
||||
|
||||
// 滚动加载数据
|
||||
const paginationConfig = reactive({
|
||||
current_page: 1,
|
||||
page_size: 20
|
||||
})
|
||||
|
||||
const scrollData = ref<any[]>([])
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(value) => {
|
||||
newData.value = value
|
||||
paginationConfig.current_page = 1
|
||||
nextTick(() => {
|
||||
scrollRef.value?.[activeName.value]?.scrollTo(0, 0)
|
||||
})
|
||||
scrollData.value = newData.value[activeName.value]?.content.slice(0, paginationConfig.page_size)
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
function loadScroll() {
|
||||
if (newData.value[activeName.value]?.content.length > scrollData.value.length) {
|
||||
paginationConfig.current_page += 1
|
||||
scrollData.value.push(
|
||||
...newData.value[activeName.value].content.slice(
|
||||
(paginationConfig.current_page - 1) * paginationConfig.page_size,
|
||||
paginationConfig.current_page * paginationConfig.page_size
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function editHandle(item: any, index: number, cIndex: number) {
|
||||
currentPIndex.value = index
|
||||
currentCIndex.value = cIndex
|
||||
EditParagraphDialogRef.value.open(item)
|
||||
}
|
||||
|
||||
function deleteHandle(item: any, index: number, cIndex: number) {
|
||||
MsgConfirm(`是否删除分段:${item.title || '-'} ?`, `删除后将不会存入知识库,对本地文档无影响。`, {
|
||||
confirmButtonText: '删除',
|
||||
confirmButtonClass: 'danger'
|
||||
})
|
||||
.then(() => {
|
||||
newData.value[index].content.splice(cIndex, 1)
|
||||
scrollData.value.splice(cIndex, 1)
|
||||
emit('update:data', newData.value)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function updateContent(data: any) {
|
||||
newData.value[currentPIndex.value].content[currentCIndex.value] = cloneDeep(data)
|
||||
scrollData.value[currentCIndex.value] = cloneDeep(data)
|
||||
emit('update:data', newData.value)
|
||||
}
|
||||
|
||||
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
||||
paginationConfig.current_page = 1
|
||||
scrollData.value = newData.value[Number(tab.index)]?.content.slice(0, paginationConfig.page_size)
|
||||
}
|
||||
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
|
@ -172,6 +79,6 @@ onMounted(() => {})
|
|||
}
|
||||
}
|
||||
.paragraph-list {
|
||||
height: calc(var(--create-dataset-height) - 131px);
|
||||
height: calc(var(--create-dataset-height) - 101px);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue