222222</template >
223223
224224<script setup>
225- import { computed , nextTick , onBeforeUnmount , onMounted , reactive , ref , watch } from ' vue'
225+ import { computed , nextTick , onActivated , onBeforeUnmount , onDeactivated , onMounted , reactive , ref , watch } from ' vue'
226226import GroupListPanel from ' ../components/workspace/GroupListPanel.vue'
227227import ChatPanel from ' ../components/workspace/ChatPanel.vue'
228228import MemberPanel from ' ../components/workspace/MemberPanel.vue'
@@ -234,7 +234,11 @@ import { apiRequest, extractErrorMessage } from '../lib/api'
234234import { isPlaceholderGroupRecord , initials , parseMessageContent } from ' ../lib/format'
235235
236236const POLL_INTERVAL = 5000
237+ const MEMBER_SEARCH_DELAY = 300
237238let pollTimer = null
239+ let memberSearchTimer = null
240+ let workspaceRequestKey = 0
241+ let polling = false
238242
239243const props = defineProps ({
240244 apiBase: { type: String , required: true },
@@ -352,6 +356,10 @@ function resetWorkspace() {
352356 workspace .files = { files: [], folders: [] }
353357}
354358
359+ function isCurrentWorkspace (groupId , requestKey ) {
360+ return String (selectedGroupId .value ) === String (groupId) && workspaceRequestKey === requestKey
361+ }
362+
355363function messageKey (item ) {
356364 return String (item? .id ?? item? .message_id ?? item? .real_id ?? item? .real_seq ?? Math .random ())
357365}
@@ -367,7 +375,7 @@ function dedupeMessages(items) {
367375async function loadGroups (autoSelect = false ) {
368376 groupLoading .value = true
369377 try {
370- const payload = await apiRequest (props .apiBase , props .token , ' /groups' )
378+ const payload = await apiRequest (props .apiBase , props .token , ' /groups' , { params : { compact : true } } )
371379 allGroups .value = Array .isArray (payload? .items ) ? payload .items : []
372380 emit (' connection' , ' 已连接' )
373381
@@ -392,13 +400,23 @@ async function loadGroups(autoSelect = false) {
392400
393401async function handleSelectGroup (groupId ) {
394402 if (! groupId) return
403+ clearTimeout (memberSearchTimer)
395404 selectedGroupId .value = String (groupId)
396405 memberSearch .value = ' '
406+ tabLoaded .announcements = false
407+ tabLoaded .files = false
408+ tabLoaded .essence = false
409+ tabLoaded .honors = false
410+ tabLoading .announcements = false
411+ tabLoading .files = false
412+ tabLoading .essence = false
413+ tabLoading .honors = false
397414 closeMemberMenu ()
398415 await loadWorkspace (groupId)
399416}
400417
401418async function loadWorkspace (groupId ) {
419+ const requestKey = ++ workspaceRequestKey
402420 workspaceLoading .value = true
403421 try {
404422 const [profilePayload , messagesPayload , membersPayload , detailPayload ] = await Promise .all ([
@@ -407,15 +425,18 @@ async function loadWorkspace(groupId) {
407425 apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /members` , { params: { page: 1 , page_size: 30 }, timeout: 30000 }).catch (() => ({ items: [], pagination: {} })),
408426 apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /feature-switches` , { timeout: 30000 }).catch (() => [])
409427 ])
428+ if (! isCurrentWorkspace (groupId, requestKey)) return
410429 workspace .group_profile = profilePayload || {}
411430 workspace .messages = messagesPayload || { items: [], pagination: {} }
412431 workspace .members = membersPayload || { items: [], pagination: {} }
413432 workspace .detail .feature_switches = Array .isArray (detailPayload) ? detailPayload : (detailPayload? .switches || [])
414433 workspace .bot_profile = { capabilities: {} }
415434 try {
416435 const botProfile = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /bot-profile` , { timeout: 15000 })
436+ if (! isCurrentWorkspace (groupId, requestKey)) return
417437 workspace .bot_profile = botProfile || { capabilities: {} }
418438 } catch {}
439+ if (! isCurrentWorkspace (groupId, requestKey)) return
419440 workspace .announcements = { items: [] }
420441 workspace .files = { files: [], folders: [] }
421442 workspace .essence = { items: [] }
@@ -433,31 +454,37 @@ async function loadWorkspace(groupId) {
433454 const errorMsg = error? .isTimeout ? ' 加载超时,该群数据量较大,请稍后重试' : extractErrorMessage (error)
434455 emit (' notify' , { message: ` 群工作台加载失败:${ errorMsg} ` , type: ' error' })
435456 } finally {
436- workspaceLoading .value = false
457+ if ( isCurrentWorkspace (groupId, requestKey)) workspaceLoading .value = false
437458 }
438459}
439460
440461async function loadTabData (tabKey ) {
441462 if (! selectedGroupId .value || tabLoaded[tabKey] || tabLoading[tabKey]) return
463+ const groupId = selectedGroupId .value
464+ const requestKey = workspaceRequestKey
442465 tabLoading[tabKey] = true
443466 await nextTick ()
444467 window .mdui ? .mutation ? .()
445468 const startTime = Date .now ()
446469 try {
447470 if (tabKey === ' announcements' ) {
448- const data = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId .value } /announcements` , { timeout: 30000 })
471+ const data = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /announcements` , { timeout: 30000 })
472+ if (! isCurrentWorkspace (groupId, requestKey)) return
449473 workspace .announcements = data || { items: [] }
450474 tabLoaded .announcements = true
451475 } else if (tabKey === ' files' ) {
452- const data = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId .value } /files` , { timeout: 30000 })
476+ const data = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /files` , { timeout: 30000 })
477+ if (! isCurrentWorkspace (groupId, requestKey)) return
453478 workspace .files = data || { files: [], folders: [] }
454479 tabLoaded .files = true
455480 } else if (tabKey === ' essence' ) {
456- const data = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId .value } /essence` , { timeout: 30000 })
481+ const data = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /essence` , { timeout: 30000 })
482+ if (! isCurrentWorkspace (groupId, requestKey)) return
457483 workspace .essence = data || { items: [] }
458484 tabLoaded .essence = true
459485 } else if (tabKey === ' honors' ) {
460- const data = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId .value } /honors` , { timeout: 30000 })
486+ const data = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId} /honors` , { timeout: 30000 })
487+ if (! isCurrentWorkspace (groupId, requestKey)) return
461488 workspace .honors = data || { sections: [] }
462489 tabLoaded .honors = true
463490 }
@@ -478,51 +505,62 @@ function handleTabChange(tabKey) {
478505 startPolling ()
479506 } else {
480507 stopPolling ()
481- console .log (' Tab change to:' , tabKey, ' tabLoaded:' , tabLoaded[tabKey], ' tabLoading:' , tabLoading[tabKey])
482508 loadTabData (tabKey)
483509 }
484510}
485511
486512async function loadMembers (page = 1 ) {
487513 if (! selectedGroupId .value ) return
514+ const groupId = selectedGroupId .value
515+ const requestKey = workspaceRequestKey
488516 memberLoading .value = true
489517 try {
490- workspace . members = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId . value } /members` , {
518+ const members = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId } /members` , {
491519 params: {
492520 page,
493521 page_size: 30 ,
494522 keyword: memberSearch .value
495523 }
496524 })
525+ if (! isCurrentWorkspace (groupId, requestKey)) return
526+ workspace .members = members
497527 } catch (error) {
498528 emit (' notify' , { message: ` 成员加载失败:${ extractErrorMessage (error)} ` , type: ' error' })
499529 } finally {
500- memberLoading .value = false
530+ if ( isCurrentWorkspace (groupId, requestKey)) memberLoading .value = false
501531 }
502532}
503533
504534async function loadLatestMessages () {
505535 if (! selectedGroupId .value ) return
536+ const groupId = selectedGroupId .value
537+ const requestKey = workspaceRequestKey
506538 messagesLoading .value = true
507539 try {
508- workspace . messages = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId . value } /messages` , {
540+ const messages = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId } /messages` , {
509541 params: { limit: 60 }
510542 })
543+ if (! isCurrentWorkspace (groupId, requestKey)) return
544+ workspace .messages = messages
511545 } catch (error) {
512546 emit (' notify' , { message: ` 消息刷新失败:${ extractErrorMessage (error)} ` , type: ' error' })
513547 } finally {
514- messagesLoading .value = false
548+ if ( isCurrentWorkspace (groupId, requestKey)) messagesLoading .value = false
515549 }
516550}
517551
518552async function pollNewMessages () {
519- if (! selectedGroupId .value || centerActiveTab .value !== ' chat' ) return
553+ if (polling || ! selectedGroupId .value || centerActiveTab .value !== ' chat' ) return
554+ const groupId = selectedGroupId .value
555+ const requestKey = workspaceRequestKey
520556 const latestId = workspace .messages .pagination ? .latest_id
521557 if (! latestId) return
558+ polling = true
522559 try {
523- const result = await apiRequest (props .apiBase , props .token , ` /groups/${ selectedGroupId . value } /messages` , {
560+ const result = await apiRequest (props .apiBase , props .token , ` /groups/${ groupId } /messages` , {
524561 params: { limit: 60 , after_id: latestId }
525562 })
563+ if (! isCurrentWorkspace (groupId, requestKey)) return
526564 const newItems = result? .items || []
527565 if (newItems .length > 0 ) {
528566 workspace .messages = {
@@ -531,7 +569,9 @@ async function pollNewMessages() {
531569 pagination: result .pagination || workspace .messages .pagination
532570 }
533571 }
534- } catch {}
572+ } catch {} finally {
573+ polling = false
574+ }
535575}
536576
537577function startPolling () {
@@ -757,7 +797,8 @@ function handleGroupSearch(value) {
757797
758798function handleMemberSearch (value ) {
759799 memberSearch .value = value
760- loadMembers (1 )
800+ clearTimeout (memberSearchTimer)
801+ memberSearchTimer = setTimeout (() => loadMembers (1 ), MEMBER_SEARCH_DELAY )
761802}
762803
763804function changeGroupPage (offset ) {
@@ -783,8 +824,17 @@ onMounted(() => {
783824 window .addEventListener (' scroll' , onGlobalPointer, true )
784825})
785826
827+ onActivated (() => {
828+ if (selectedGroupId .value && centerActiveTab .value === ' chat' ) startPolling ()
829+ })
830+
831+ onDeactivated (() => {
832+ stopPolling ()
833+ })
834+
786835onBeforeUnmount (() => {
787836 stopPolling ()
837+ clearTimeout (memberSearchTimer)
788838 window .removeEventListener (' click' , onGlobalPointer)
789839 window .removeEventListener (' resize' , onGlobalPointer)
790840 window .removeEventListener (' scroll' , onGlobalPointer, true )
0 commit comments