11<script setup lang='ts'>
22import type { Ref } from ' vue'
3- import { computed , onMounted , onUnmounted , ref } from ' vue'
3+ import { computed , nextTick , onMounted , onUnmounted , ref } from ' vue'
44import { useRoute } from ' vue-router'
55import { storeToRefs } from ' pinia'
6+ import type { MessageReactive } from ' naive-ui'
67import { NAutoComplete , NButton , NInput , NSpin , useDialog , useMessage } from ' naive-ui'
78import html2canvas from ' html2canvas'
89import { Message } from ' ./components'
@@ -32,7 +33,7 @@ useCopyCode()
3233
3334const { isMobile } = useBasicLayout ()
3435const { addChat, updateChat, updateChatSome, getChatByUuidAndIndex } = useChat ()
35- const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom } = useScroll ()
36+ const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom, scrollTo } = useScroll ()
3637const { usingContext, toggleUsingContext } = useUsingContext ()
3738
3839const { uuid } = route .params as { uuid: string }
@@ -45,6 +46,10 @@ const firstLoading = ref<boolean>(false)
4546const loading = ref <boolean >(false )
4647const inputRef = ref <Ref | null >(null )
4748
49+ let loadingms: MessageReactive
50+ let allmsg: MessageReactive
51+ let prevScrollTop: number
52+
4853// 添加PromptStore
4954const promptStore = usePromptStore ()
5055
@@ -421,6 +426,40 @@ function handleStop() {
421426 }
422427}
423428
429+ async function loadMoreMessage(event : any ) {
430+ const chatIndex = chatStore .chat .findIndex (d => d .uuid === + uuid )
431+ if (chatIndex <= - 1 )
432+ return
433+
434+ const scrollPosition = event .target .scrollHeight - event .target .scrollTop
435+
436+ const lastId = chatStore .chat [chatIndex ].data [0 ].uuid
437+ await chatStore .syncChat ({ uuid: + uuid } as Chat .History , lastId , () => {
438+ loadingms && loadingms .destroy ()
439+ nextTick (() => scrollTo (event .target .scrollHeight - scrollPosition ))
440+ }, () => {
441+ loadingms = ms .loading (
442+ ' 加载中...' , {
443+ duration: 0 ,
444+ },
445+ )
446+ }, () => {
447+ allmsg && allmsg .destroy ()
448+ allmsg = ms .warning (' 没有更多了' , {
449+ duration: 1000 ,
450+ })
451+ })
452+ }
453+
454+ const handleLoadMoreMessage = debounce (loadMoreMessage , 300 )
455+
456+ async function handleScroll(event : any ) {
457+ const scrollTop = event .target .scrollTop
458+ if (scrollTop < 50 && (scrollTop < prevScrollTop || prevScrollTop === undefined ))
459+ handleLoadMoreMessage (event )
460+ prevScrollTop = scrollTop
461+ }
462+
424463// 可优化部分
425464// 搜索选项计算,这里使用value作为索引项,所以当出现重复value时渲染异常(多项同时出现选中效果)
426465// 理想状态下其实应该是key作为索引项,但官方的renderOption会出现问题,所以就需要value反renderLabel实现
@@ -468,7 +507,7 @@ onMounted(() => {
468507 firstLoading .value = true
469508 debounce (() => {
470509 // 直接刷 极小概率不请求
471- chatStore .syncChat ({ uuid: Number (uuid ) } as Chat .History , () => {
510+ chatStore .syncChat ({ uuid: Number (uuid ) } as Chat .History , undefined , () => {
472511 firstLoading .value = false
473512 scrollToBottom ()
474513 if (inputRef .value && ! isMobile .value )
@@ -492,7 +531,7 @@ onUnmounted(() => {
492531 @toggle-using-context =" toggleUsingContext"
493532 />
494533 <main class =" flex-1 overflow-hidden" >
495- <div id =" scrollRef" ref =" scrollRef" class =" h-full overflow-hidden overflow-y-auto" >
534+ <div id =" scrollRef" ref =" scrollRef" class =" h-full overflow-hidden overflow-y-auto" @scroll = " handleScroll " >
496535 <div
497536 id =" image-wrapper"
498537 class =" w-full max-w-screen-xl m-auto dark:bg-[#101014]"
0 commit comments