gaoluyang
昨天 b64a0deae5b5d33f9e20671a68936b27f0b9b00b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import type { ImManagerChannelApi } from '#/api/im/manager/channel'
 
import { acceptHMRUpdate, defineStore } from 'pinia'
 
import { getSimpleChannelList } from '#/api/im/manager/channel'
 
import { ImConversationType } from '../../utils/constants'
import { getDb } from '../../utils/db'
import { useConversationStore } from './conversationStore'
 
/**
 * IM 频道 Store
 *
 * 负责:缓存当前用户能看到的频道精简列表(含 id / code / name / avatar),
 * 供会话列表 / 卡片渲染时反查频道名称 + 头像,避免显示「频道 1」这种占位
 */
export const useChannelStore = defineStore('imChannelStore', {
  state: () => ({
    channels: [] as ImManagerChannelApi.Channel[],
    loaded: false
  }),
 
  getters: {
    getChannel(state): (id: number) => ImManagerChannelApi.Channel | undefined {
      return (id: number) => state.channels.find((c) => c.id === id)
    }
  },
 
  actions: {
    // ==================== 本地缓存 ====================
 
    /** 从 IndexedDB 恢复频道列表 */
    async loadChannelList(): Promise<boolean> {
      try {
        const cached = await getDb().getAll<ImManagerChannelApi.Channel>('channels')
        if (!cached || cached.length === 0) {
          return false
        }
        this.channels = cached
        return true
      } catch (error) {
        console.warn('[IM channelStore] 本地频道缓存读取失败', error)
        return false
      }
    },
 
    /** 保存频道列表 */
    saveChannelList(): void {
      void getDb()
        .transaction(['channels'], 'readwrite', async (tx) => {
          const db = getDb()
          await db.clearStore('channels', tx)
          for (const channel of this.channels) {
            await db.put('channels', channel, tx)
          }
        })
        .catch((error) => console.warn('[IM channelStore] 本地频道缓存写入失败', error))
    },
 
    // ==================== 远端拉取 ====================
 
    /** 拉取启用的频道精简列表;成功后回填会话列表已有的频道 name / avatar,覆盖 IDB 旧占位 */
    async fetchChannelList(force = false) {
      if (this.loaded && !force) {
        return
      }
      try {
        this.channels = (await getSimpleChannelList()) || []
        this.loaded = true
        this.syncChannelConversationMetadata()
        this.saveChannelList()
      } catch (error) {
        console.warn('[IM channelStore] fetchChannelList 失败', error)
      }
    },
 
    /** 用最新的频道信息覆盖已有 CHANNEL 会话的 name / avatar */
    syncChannelConversationMetadata() {
      const conversationStore = useConversationStore()
      const indexed = new Map(this.channels.map((c) => [c.id, c]))
      conversationStore.conversations.forEach((conversation) => {
        if (conversation.type !== ImConversationType.CHANNEL) {
          return
        }
        const channel = indexed.get(conversation.targetId)
        if (!channel) {
          return
        }
        conversationStore.updateConversation(ImConversationType.CHANNEL, conversation.targetId, {
          name: channel.name,
          avatar: channel.avatar
        })
      })
    },
 
    /** 清空频道内存 */
    clear() {
      this.channels = []
      this.loaded = false
    }
  }
})
 
if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useChannelStore, import.meta.hot))
}
 
export const useChannelStoreWithOut = () => useChannelStore()