Files
mini-programs/_doc/前端红点功能接口文档.md
2026-02-14 12:59:21 +08:00

569 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端红点功能接口文档
## 一、功能概述
消息红点功能用于提示用户有未读的评论/回复和新增关注消息。
**红点显示条件**
- 有别人回复给我的评论/回复未读
- 有新用户关注我未读
---
## 二、接口列表
| 接口 | 用途 |
|------|------|
| `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
<!-- pages/message/message.wxml -->
<view class="message-page">
<!-- 评论消息入口 -->
<view class="menu-item" bindtap="goToComments">
<text>评论与回复</text>
<view wx:if="{{commentUnreadCount > 0}}" class="badge">
{{commentUnreadCount}}
</view>
</view>
<!-- 关注消息入口 -->
<view class="menu-item" bindtap="goToFollows">
<text>新增关注</text>
<view wx:if="{{followUnreadCount > 0}}" class="badge">
{{followUnreadCount}}
</view>
</view>
</view>
```
---
### 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`