# 前端红点功能接口文档 ## 一、功能概述 消息红点功能用于提示用户有未读的评论/回复和新增关注消息。 **红点显示条件**: - 有别人回复给我的评论/回复未读 - 有新用户关注我未读 --- ## 二、接口列表 | 接口 | 用途 | |------|------| | `POST /api/message/reddot_info` | 获取红点信息(数量统计) | | `POST /api/message/mark_as_read` | 标记消息已读(统一接口) | | `POST /api/comments/my_activities` | 获取评论/回复消息列表 | | `POST /api/user_follow/new_fans_list` | 获取新增关注列表 | --- ## 三、核心接口详情 ### 1. 获取红点信息 ⭐ **接口**: `POST /api/message/reddot_info` **请求参数**: 无 **响应示例**: ```json { "code": 200, "message": "获取成功", "data": { "comment_unread_count": 5, // 评论/回复未读数量 "follow_unread_count": 3, // 新增关注未读数量 "total_unread_count": 8, // 总未读数量 "has_reddot": true // 是否显示红点 } } ``` **字段说明**: - `comment_unread_count`: Number,评论/回复未读数量 - `follow_unread_count`: Number,新增关注未读数量 - `total_unread_count`: Number,总未读数量 - `has_reddot`: Boolean,是否显示红点 - `true`: 有未读消息,显示红点 - `false`: 无未读消息,隐藏红点 **使用场景**: - TabBar 显示红点和未读数 - 消息页面显示各类消息的未读数 - 应用启动时检查红点状态 --- ### 2. 标记消息已读 ⭐ **接口**: `POST /api/message/mark_as_read` **请求参数**: ```json { "type": "comment", // 消息类型: comment-评论, follow-关注, all-全部 "ids": [123, 456, 789] // 消息ID数组(type为all时可不传) } ``` **type 参数说明**: - `"comment"`: 标记指定评论/回复为已读,需传 `ids`(评论ID数组) - `"follow"`: 标记指定关注为已读,需传 `ids`(关注者用户ID数组) - `"all"`: 标记所有未读消息为已读,不需要传 `ids` **响应示例**: ```json { "code": 200, "message": "获取成功", "data": { "updated_count": 8, // 总更新数量 "detail": { "comment_count": 5, // 评论更新数量 "follow_count": 3 // 关注更新数量 }, "message": "标记成功" } } ``` **使用示例**: 1. 标记指定评论为已读: ```json { "type": "comment", "ids": [123, 456] } ``` 2. 标记指定关注为已读: ```json { "type": "follow", "ids": [789, 012] } ``` 3. 标记全部消息为已读: ```json { "type": "all" } ``` --- ## 四、辅助接口 ### 3. 获取评论/回复消息列表 **接口**: `POST /api/comments/my_activities` **请求参数**: ```json { "page": 1, "pageSize": 20 } ``` **响应示例**: ```json { "code": 200, "message": "获取成功", "data": { "rows": [ { "id": 456, "type": "reply", "activity_type": "received_reply", "content": "回复内容", "create_time": "2025-11-20 10:00:00", "is_read": 0, // 👈 0-未读, 1-已读 "user": { "id": 789, "nickname": "回复者昵称", "avatar_url": "头像地址" }, "game": { "id": 101, "title": "球局标题" } } ], "count": 50 } } ``` **字段说明**: - `is_read`: 0-未读, 1-已读 - `activity_type`: - `"my_activity"` - 我发表的 - `"received_reply"` - 别人回复我的(需要处理的) --- ### 4. 获取新增关注列表 **接口**: `POST /api/user_follow/new_fans_list` **请求参数**: ```json { "page": 1, "page_size": 20 } ``` **响应示例**: ```json { "code": 200, "message": "获取成功", "data": { "list": [ { "id": 123, "nickname": "粉丝昵称", "avatar_url": "头像地址", "follow_time": "2025-11-20 09:00:00", "is_mutual": false, "is_read": 0 // 👈 0-未读, 1-已读 } ], "total": 30 } } ``` --- ## 五、前端使用示例 ### 1. 显示 TabBar 红点 ```javascript // app.js 或全局方法 async function checkAndShowReddot() { const res = await request({ url: '/api/message/reddot_info', method: 'POST' }) const { has_reddot, total_unread_count } = res.data if (has_reddot) { // 显示红点和数字 wx.setTabBarBadge({ index: 2, // 消息Tab的索引 text: total_unread_count > 99 ? '99+' : String(total_unread_count) }) } else { // 隐藏红点 wx.removeTabBarBadge({ index: 2 }) } } // App 启动时检查 App({ onLaunch() { this.checkReddot() }, checkReddot() { checkAndShowReddot() } }) ``` --- ### 2. 消息页面显示分类红点 ```javascript // pages/message/message.js Page({ data: { commentUnreadCount: 0, followUnreadCount: 0 }, onShow() { this.loadReddotInfo() }, async loadReddotInfo() { const res = await request({ url: '/api/message/reddot_info', method: 'POST' }) this.setData({ commentUnreadCount: res.data.comment_unread_count, followUnreadCount: res.data.follow_unread_count }) } }) ``` ```html 评论与回复 {{commentUnreadCount}} 新增关注 {{followUnreadCount}} ``` --- ### 3. 评论消息列表(进入时自动标记已读) ```javascript // pages/message/comment-list.js Page({ data: { commentList: [] }, async onLoad() { await this.loadComments() await this.markAllAsRead() }, // 加载评论列表 async loadComments() { const res = await request({ url: '/api/comments/my_activities', method: 'POST', data: { page: 1, pageSize: 20 } }) // 筛选出别人回复给我的 const receivedReplies = res.data.rows.filter( item => item.activity_type === 'received_reply' ) this.setData({ commentList: receivedReplies }) }, // 标记所有评论为已读 async markAllAsRead() { const unreadIds = this.data.commentList .filter(item => item.is_read === 0) .map(item => item.id) if (unreadIds.length > 0) { await request({ url: '/api/message/mark_as_read', method: 'POST', data: { type: 'comment', ids: unreadIds } }) } }, onUnload() { // 离开页面时刷新红点 getApp().checkReddot() } }) ``` --- ### 4. 关注消息列表(进入时自动标记已读) ```javascript // pages/message/follow-list.js Page({ data: { fansList: [] }, async onLoad() { await this.loadFans() await this.markAllAsRead() }, async loadFans() { const res = await request({ url: '/api/user_follow/new_fans_list', method: 'POST', data: { page: 1, page_size: 20 } }) this.setData({ fansList: res.data.list }) }, async markAllAsRead() { const unreadFanIds = this.data.fansList .filter(item => item.is_read === 0) .map(item => item.id) if (unreadFanIds.length > 0) { await request({ url: '/api/message/mark_as_read', method: 'POST', data: { type: 'follow', ids: unreadFanIds } }) } }, onUnload() { getApp().checkReddot() } }) ``` --- ### 5. 一键清空所有未读 ```javascript // 清空所有未读消息 async function markAllMessagesAsRead() { wx.showLoading({ title: '处理中...' }) try { await request({ url: '/api/message/mark_as_read', method: 'POST', data: { type: 'all' } }) wx.showToast({ title: '已全部标记为已读', icon: 'success' }) // 刷新红点 getApp().checkReddot() } catch (err) { wx.showToast({ title: '操作失败', icon: 'none' }) } finally { wx.hideLoading() } } ``` --- ## 六、最佳实践 ### 1. 红点刷新时机 ```javascript // 推荐刷新时机 const REFRESH_TIMING = { onLaunch: true, // App启动时 onShow: true, // App从后台进入前台 onTabSwitch: true, // 切换到消息Tab afterMarkRead: true, // 标记已读后 onPullRefresh: true // 下拉刷新 } ``` ### 2. 防抖优化 ```javascript // utils/debounce.js let timer = null export function debounceCheckReddot() { if (timer) clearTimeout(timer) timer = setTimeout(() => { getApp().checkReddot() }, 300) } ``` ### 3. 错误处理 ```javascript async function safeMarkAsRead(type, ids) { try { await request({ url: '/api/message/mark_as_read', method: 'POST', data: { type, ids } }) } catch (err) { // 标记已读失败不影响用户体验,静默处理 console.warn('标记已读失败:', err) } } ``` --- ## 七、完整流程图 ``` 用户打开App ↓ 调用 /message/reddot_info ↓ 获取红点数据 ↓ ┌─────────────────┐ │ has_reddot? │ └────┬────────┬───┘ │ │ true false ↓ ↓ 显示红点 隐藏红点 带数字 │ │ 用户点击 ↓ 进入消息页面 ↓ 显示各分类未读数 │ │ 点击某分类 ↓ 加载消息列表 ↓ 标记已读 ↓ ┌─────────────────┐ │ 选择标记方式 │ └─┬─────────┬─────┘ │ │ 按ID 全部 标记 标记 ↓ ↓ 调用 mark_as_read type=comment/follow ids=[...] │ │ └────┬────┘ ↓ 标记成功 ↓ 刷新红点 ``` --- ## 八、接口对比说明 ### 旧方案 vs 新方案 | 功能 | 旧方案 | 新方案 | |------|--------|--------| | 获取红点 | `/api/user/detail` | `/api/message/reddot_info` | | 标记评论已读 | `/api/comments/mark_as_read` | `/api/message/mark_as_read` (type=comment) | | 标记关注已读 | `/api/user_follow/mark_as_read` | `/api/message/mark_as_read` (type=follow) | | 标记全部已读 | ❌ 无 | `/api/message/mark_as_read` (type=all) | **新方案优势**: - ✅ 统一的接口设计 - ✅ 减少接口数量 - ✅ 支持一键清空所有未读 - ✅ 返回详细的未读数统计 - ✅ 更清晰的职责划分 --- ## 九、注意事项 1. **权限控制**: 只能标记属于自己的消息 2. **分页处理**: 翻页时注意标记已读 3. **实时性**: 标记后刷新红点状态 4. **错误处理**: 标记失败可静默处理 5. **type 参数**: 必须是 `comment`、`follow` 或 `all` --- ## 十、联系后端 **相关文件**: - 消息接口: `api/controller_front/msg_message.js` ⭐ - 评论接口: `api/controller_front/gme_comments.js` - 关注接口: `api/controller_front/user_follow.js`