hookehuyr

feat(message): 修复 TabBar 未读红点显示问题

- 添加 unreadMsgCount 状态单独存储未读消息数
- 修复从 res.data 读取 unread_msg_count 字段(该字段不在 user 对象中)
- 优化 TabBarBadges 计算逻辑,直接从 unreadMsgCount 读取
- 消息列表页面添加自动刷新已读状态功能

影响文件:
- src/stores/user.js
- src/pages/message/index.vue

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
61 <script setup> 61 <script setup>
62 import Taro from '@tarojs/taro' 62 import Taro from '@tarojs/taro'
63 import { ref } from 'vue' 63 import { ref } from 'vue'
64 -import { useLoad } from '@tarojs/taro' 64 +import { useLoad, useDidShow } from '@tarojs/taro'
65 import { useGo } from '@/hooks/useGo' 65 import { useGo } from '@/hooks/useGo'
66 import LoadMoreList from '@/components/list/LoadMoreList' 66 import LoadMoreList from '@/components/list/LoadMoreList'
67 import NavHeader from '@/components/navigation/NavHeader.vue' 67 import NavHeader from '@/components/navigation/NavHeader.vue'
...@@ -83,6 +83,9 @@ const hasMore = ref(true) ...@@ -83,6 +83,9 @@ const hasMore = ref(true)
83 const loading = ref(false) 83 const loading = ref(false)
84 const loadingMore = ref(false) 84 const loadingMore = ref(false)
85 85
86 +// 标记:是否首次加载(用于区分 useLoad 和 useDidShow)
87 +const isFirstLoad = ref(true)
88 +
86 /** 89 /**
87 * 提取消息标题(第一行或截取) 90 * 提取消息标题(第一行或截取)
88 * 91 *
...@@ -205,6 +208,43 @@ useLoad(async (options) => { ...@@ -205,6 +208,43 @@ useLoad(async (options) => {
205 208
206 // 获取消息列表 209 // 获取消息列表
207 await fetchMessageList({ page: 0, limit: pageSize }) 210 await fetchMessageList({ page: 0, limit: pageSize })
211 +
212 + // 首次加载完成
213 + isFirstLoad.value = false
214 +})
215 +
216 +/**
217 + * 页面显示时刷新列表(用于从详情页返回时更新已读状态)
218 + */
219 +useDidShow(async () => {
220 + // 跳过首次加载(useLoad 已经处理过)
221 + if (isFirstLoad.value) {
222 + return
223 + }
224 +
225 + console.log('[Message] 页面显示,更新已读状态')
226 +
227 + try {
228 + // 重新获取当前页数据(用于更新已读状态)
229 + const res = USE_MOCK_DATA
230 + ? await mockMessageListAPI({ page: currentPage.value, limit: pageSize })
231 + : await myListAPI({ page: currentPage.value, limit: pageSize })
232 +
233 + if (res.code === 1 && res.data?.list) {
234 + const newList = res.data.list
235 +
236 + // 只更新现有列表项的状态,不改变列表顺序
237 + currentList.value = currentList.value.map(oldItem => {
238 + const newItem = newList.find(item => item.id === oldItem.id)
239 + // 如果找到了对应的消息,更新其状态;否则保持原样
240 + return newItem ? { ...oldItem, status: newItem.status } : oldItem
241 + })
242 +
243 + console.log('[Message] 已读状态已更新')
244 + }
245 + } catch (error) {
246 + console.error('[Message] 更新已读状态失败:', error)
247 + }
208 }) 248 })
209 249
210 /** 250 /**
......
...@@ -17,6 +17,9 @@ export const useUserStore = defineStore('user', () => { ...@@ -17,6 +17,9 @@ export const useUserStore = defineStore('user', () => {
17 /** 用户信息 */ 17 /** 用户信息 */
18 const userInfo = ref(null) 18 const userInfo = ref(null)
19 19
20 + /** 未读消息数 */
21 + const unreadMsgCount = ref(0)
22 +
20 /** 是否已授权(openid) */ 23 /** 是否已授权(openid) */
21 const isOpenid = ref(false) 24 const isOpenid = ref(false)
22 25
...@@ -109,6 +112,14 @@ export const useUserStore = defineStore('user', () => { ...@@ -109,6 +112,14 @@ export const useUserStore = defineStore('user', () => {
109 112
110 if (res.code === 1) { 113 if (res.code === 1) {
111 userInfo.value = res.data.user 114 userInfo.value = res.data.user
115 +
116 + // 从 res.data 中读取 unread_msg_count(不在 user 对象里)
117 + unreadMsgCount.value = res.data?.unread_msg_count ?? 0
118 +
119 + console.log('[UserStore] 用户信息已更新:', {
120 + unreadMsgCount: unreadMsgCount.value
121 + })
122 +
112 // 更新最后请求时间 123 // 更新最后请求时间
113 lastFetchTime = Date.now() 124 lastFetchTime = Date.now()
114 } else { 125 } else {
...@@ -204,32 +215,16 @@ export const useUserStore = defineStore('user', () => { ...@@ -204,32 +215,16 @@ export const useUserStore = defineStore('user', () => {
204 return [] 215 return []
205 } 216 }
206 217
207 - // 2. 检查用户信息是否存在 218 + // 2. 获取阈值
208 - if (!userInfo.value) {
209 - return []
210 - }
211 -
212 - // 3. 获取配置的字段名和阈值
213 - const fieldName = getFeatureConfig('tabbarBadgeField') // 'unread_count'
214 const threshold = getFeatureConfig('tabbarBadgeThreshold') // 1 219 const threshold = getFeatureConfig('tabbarBadgeThreshold') // 1
215 220
216 - // 4. 读取字段值 221 + // 3. 从 unreadMsgCount 读取值(而不是从 userInfo 中)
217 - const fieldValue = userInfo.value[fieldName] 222 + const count = unreadMsgCount.value
218 223
219 - // 5. 判断是否显示红点 224 + // 4. 判断是否显示红点
220 const badges = [] 225 const badges = []
221 - 226 + if (count >= threshold) {
222 - // 处理数字类型(如 unread_count: 5) 227 + badges.push('me')
223 - if (typeof fieldValue === 'number') {
224 - if (fieldValue >= threshold) {
225 - badges.push('me')
226 - }
227 - }
228 - // 处理布尔类型(如 has_notification: true)
229 - else if (typeof fieldValue === 'boolean') {
230 - if (fieldValue) {
231 - badges.push('me')
232 - }
233 } 228 }
234 229
235 return badges 230 return badges
...@@ -239,6 +234,7 @@ export const useUserStore = defineStore('user', () => { ...@@ -239,6 +234,7 @@ export const useUserStore = defineStore('user', () => {
239 return { 234 return {
240 // 状态 235 // 状态
241 userInfo, 236 userInfo,
237 + unreadMsgCount,
242 isOpenid, 238 isOpenid,
243 isLoggedIn, 239 isLoggedIn,
244 loading, 240 loading,
......