11<script setup lang='ts'>
2- import { computed , nextTick , onMounted } from ' vue'
3- import { NInput , NPopconfirm , NScrollbar } from ' naive-ui'
2+ import { computed , onMounted , ref } from ' vue'
3+ import { NInput , NPopconfirm , NScrollbar , NSpin } from ' naive-ui'
44import { SvgIcon } from ' @/components/common'
55import { useAppStore , useChatStore } from ' @/store'
66import { useBasicLayout } from ' @/hooks/useBasicLayout'
@@ -13,6 +13,8 @@ const appStore = useAppStore()
1313const chatStore = useChatStore ()
1414const authStore = useAuthStoreWithout ()
1515
16+ const loadingRoom = ref (false )
17+
1618const dataSources = computed (() => chatStore .history )
1719
1820onMounted (async () => {
@@ -23,10 +25,9 @@ onMounted(async () => {
2325async function handleSyncChatRoom() {
2426 // if (chatStore.history.length == 1 && chatStore.history[0].title == 'New Chat'
2527 // && chatStore.chat[0].data.length <= 0)
28+ loadingRoom .value = true
2629 chatStore .syncHistory (() => {
27- const scrollRef = document .querySelector (' #scrollRef' )
28- if (scrollRef )
29- nextTick (() => scrollRef .scrollTop = scrollRef .scrollHeight )
30+ loadingRoom .value = false
3031 })
3132}
3233
@@ -37,11 +38,6 @@ async function handleSelect({ uuid }: Chat.History) {
3738 // 这里不需要 不然每次切换都rename
3839 // if (chatStore.active)
3940 // chatStore.updateHistory(chatStore.active, { isEdit: false })
40- chatStore .syncChat ({ uuid } as Chat .History , () => {
41- const scrollRef = document .querySelector (' #scrollRef' )
42- if (scrollRef )
43- nextTick (() => scrollRef .scrollTop = scrollRef .scrollHeight )
44- })
4541 await chatStore .setActive (uuid )
4642
4743 if (isMobile .value )
@@ -74,55 +70,57 @@ function isActive(uuid: number) {
7470 </script >
7571
7672<template >
77- <NScrollbar class =" px-4" >
78- <div class =" flex flex-col gap-2 text-sm" >
79- <template v-if =" ! dataSources .length " >
80- <div class =" flex flex-col items-center mt-4 text-center text-neutral-300" >
81- <SvgIcon icon =" ri:inbox-line" class =" mb-2 text-3xl" />
82- <span >{{ $t('common.noData') }}</span >
83- </div >
84- </template >
85- <template v-else >
86- <div v-for =" (item, index) of dataSources" :key =" index" >
87- <a
88- class =" relative flex items-center gap-3 px-3 py-3 break-all border rounded-md cursor-pointer hover:bg-neutral-100 group dark:border-neutral-800 dark:hover:bg-[#24272e]"
89- :class =" isActive(item.uuid) && ['border-[#4b9e5f]', 'bg-neutral-100', 'text-[#4b9e5f]', 'dark:bg-[#24272e]', 'dark:border-[#4b9e5f]', 'pr-14']"
90- @click =" handleSelect(item)"
91- >
92- <span >
93- <SvgIcon icon =" ri:message-3-line" />
94- </span >
95- <div class =" relative flex-1 overflow-hidden break-all text-ellipsis whitespace-nowrap" >
96- <NInput
97- v-if =" item.isEdit"
98- v-model:value =" item.title" size =" tiny"
99- @keypress =" handleEnter(item, false, $event)"
100- />
101- <span v-else >{{ item.title }}</span >
102- </div >
103- <div v-if =" isActive(item.uuid)" class =" absolute z-10 flex visible right-1" >
104- <template v-if =" item .isEdit " >
105- <button class =" p-1" @click =" handleEdit(item, false, $event)" >
106- <SvgIcon icon =" ri:save-line" />
107- </button >
108- </template >
109- <template v-else >
110- <button class =" p-1" >
111- <SvgIcon icon =" ri:edit-line" @click =" handleEdit(item, true, $event)" />
112- </button >
113- <NPopconfirm placement =" bottom" @positive-click =" handleDeleteDebounce(index, $event)" >
114- <template #trigger >
115- <button class =" p-1" >
116- <SvgIcon icon =" ri:delete-bin-line" />
117- </button >
118- </template >
119- {{ $t('chat.deleteHistoryConfirm') }}
120- </NPopconfirm >
121- </template >
122- </div >
123- </a >
124- </div >
125- </template >
126- </div >
127- </NScrollbar >
73+ <NSpin :show =" loadingRoom" >
74+ <NScrollbar class =" px-4" >
75+ <div class =" flex flex-col gap-2 text-sm" >
76+ <template v-if =" ! dataSources .length " >
77+ <div class =" flex flex-col items-center mt-4 text-center text-neutral-300" >
78+ <SvgIcon icon =" ri:inbox-line" class =" mb-2 text-3xl" />
79+ <span >{{ $t('common.noData') }}</span >
80+ </div >
81+ </template >
82+ <template v-else >
83+ <div v-for =" (item, index) of dataSources" :key =" index" >
84+ <a
85+ class =" relative flex items-center gap-3 px-3 py-3 break-all border rounded-md cursor-pointer hover:bg-neutral-100 group dark:border-neutral-800 dark:hover:bg-[#24272e]"
86+ :class =" isActive(item.uuid) && ['border-[#4b9e5f]', 'bg-neutral-100', 'text-[#4b9e5f]', 'dark:bg-[#24272e]', 'dark:border-[#4b9e5f]', 'pr-14']"
87+ @click =" handleSelect(item)"
88+ >
89+ <span >
90+ <SvgIcon icon =" ri:message-3-line" />
91+ </span >
92+ <div class =" relative flex-1 overflow-hidden break-all text-ellipsis whitespace-nowrap" >
93+ <NInput
94+ v-if =" item.isEdit"
95+ v-model:value =" item.title" size =" tiny"
96+ @keypress =" handleEnter(item, false, $event)"
97+ />
98+ <span v-else >{{ item.title }}</span >
99+ </div >
100+ <div v-if =" isActive(item.uuid)" class =" absolute z-10 flex visible right-1" >
101+ <template v-if =" item .isEdit " >
102+ <button class =" p-1" @click =" handleEdit(item, false, $event)" >
103+ <SvgIcon icon =" ri:save-line" />
104+ </button >
105+ </template >
106+ <template v-else >
107+ <button class =" p-1" >
108+ <SvgIcon icon =" ri:edit-line" @click =" handleEdit(item, true, $event)" />
109+ </button >
110+ <NPopconfirm placement =" bottom" @positive-click =" handleDeleteDebounce(index, $event)" >
111+ <template #trigger >
112+ <button class =" p-1" >
113+ <SvgIcon icon =" ri:delete-bin-line" />
114+ </button >
115+ </template >
116+ {{ $t('chat.deleteHistoryConfirm') }}
117+ </NPopconfirm >
118+ </template >
119+ </div >
120+ </a >
121+ </div >
122+ </template >
123+ </div >
124+ </NScrollbar >
125+ </NSpin >
128126</template >
0 commit comments