feat(frontend): Task 6 - Chat Store + API + WS 事件 + TabBar badge

API (api/im.js):
- getConversations / getHistoryMessages / pinConversation
- deleteConversation / clearHistory / searchMessages / getTotalUnread

Chat Store (store/chat.js):
- 会话列表管理 + 排序(置顶优先)
- 消息缓存 + 三态确认(sending/sent/failed)
- 全局未读数管理(Redis 同步)
- WS 事件监听:im.message.new/recalled/send.ack/offline.sync/typing
- 工具方法:游标分页加载、typing 超时清除

CustomTabBar:
- 消息 Tab 显示全局未读 badge(>99 显示 99+)

Made-with: Cursor
This commit is contained in:
bujinyuan
2026-03-03 10:58:35 +08:00
parent 2c7be494f2
commit 780dea3c31
3 changed files with 459 additions and 3 deletions

View File

@@ -21,8 +21,10 @@
:class="{ 'tab-active': currentIndex === index }"
@tap="switchTo(index)"
>
<!-- 图标区域使用 Unicode 字符占位后续替换为 SVG -->
<text class="tab-icon">{{ item.icon }}</text>
<view class="tab-icon-wrap">
<text class="tab-icon">{{ item.icon }}</text>
<text v-if="getBadge(index) > 0" class="tab-badge">{{ getBadge(index) > 99 ? '99+' : getBadge(index) }}</text>
</view>
<text class="tab-label">{{ item.label }}</text>
</view>
</view>
@@ -35,8 +37,12 @@
* Props:
* - current: 当前选中的 Tab 索引
*
* 跳转使用 uni.switchTab确保与 pages.json tabBar 配置的页面一致
* 功能:
* - 跳转使用 uni.switchTab确保与 pages.json tabBar 配置的页面一致
* - 消息 Tabindex=0显示全局未读消息 badge
*/
import { useChatStore } from '@/store/chat'
export default {
name: 'CustomTabBar',
props: {
@@ -70,6 +76,18 @@ export default {
switchTo(index) {
if (index === this.currentIndex) return
uni.switchTab({ url: this.tabs[index].path })
},
/**
* 获取指定 Tab 的 badge 数
* @param {number} index - Tab 索引
* @returns {number} badge 数量0 表示不显示)
*/
getBadge(index) {
if (index === 0) {
const chatStore = useChatStore()
return chatStore.totalUnread
}
return 0
}
}
}
@@ -108,11 +126,33 @@ export default {
transition: color 200ms ease;
}
.tab-icon-wrap {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.tab-icon {
font-size: 40rpx;
margin-bottom: 4rpx;
}
.tab-badge {
position: absolute;
top: -8rpx;
right: -20rpx;
min-width: 32rpx;
height: 32rpx;
padding: 0 8rpx;
font-size: 20rpx;
line-height: 32rpx;
color: #FFFFFF;
background-color: #EF4444;
border-radius: 16rpx;
text-align: center;
}
.tab-label {
font-size: 22rpx;
color: #94A3B8;