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

11 KiB
Raw Blame History

前端红点功能接口文档

一、功能概述

消息红点功能用于提示用户有未读的评论/回复和新增关注消息。

红点显示条件

  • 有别人回复给我的评论/回复未读
  • 有新用户关注我未读

二、接口列表

接口 用途
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

请求参数: 无

响应示例:

{
  "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

请求参数:

{
  "type": "comment",          // 消息类型: comment-评论, follow-关注, all-全部
  "ids": [123, 456, 789]      // 消息ID数组type为all时可不传
}

type 参数说明:

  • "comment": 标记指定评论/回复为已读,需传 ids评论ID数组
  • "follow": 标记指定关注为已读,需传 ids关注者用户ID数组
  • "all": 标记所有未读消息为已读,不需要传 ids

响应示例:

{
  "code": 200,
  "message": "获取成功",
  "data": {
    "updated_count": 8,         // 总更新数量
    "detail": {
      "comment_count": 5,       // 评论更新数量
      "follow_count": 3         // 关注更新数量
    },
    "message": "标记成功"
  }
}

使用示例:

  1. 标记指定评论为已读:
{
  "type": "comment",
  "ids": [123, 456]
}
  1. 标记指定关注为已读:
{
  "type": "follow",
  "ids": [789, 012]
}
  1. 标记全部消息为已读:
{
  "type": "all"
}

四、辅助接口

3. 获取评论/回复消息列表

接口: POST /api/comments/my_activities

请求参数:

{
  "page": 1,
  "pageSize": 20
}

响应示例:

{
  "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

请求参数:

{
  "page": 1,
  "page_size": 20
}

响应示例:

{
  "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 红点

// 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. 消息页面显示分类红点

// 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
    })
  }
})
<!-- 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. 评论消息列表(进入时自动标记已读)

// 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. 关注消息列表(进入时自动标记已读)

// 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. 一键清空所有未读

// 清空所有未读消息
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. 红点刷新时机

// 推荐刷新时机
const REFRESH_TIMING = {
  onLaunch: true,        // App启动时
  onShow: true,          // App从后台进入前台
  onTabSwitch: true,     // 切换到消息Tab
  afterMarkRead: true,   // 标记已读后
  onPullRefresh: true    // 下拉刷新
}

2. 防抖优化

// utils/debounce.js
let timer = null
export function debounceCheckReddot() {
  if (timer) clearTimeout(timer)
  timer = setTimeout(() => {
    getApp().checkReddot()
  }, 300)
}

3. 错误处理

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 参数: 必须是 commentfollowall

十、联系后端

相关文件:

  • 消息接口: api/controller_front/msg_message.js
  • 评论接口: api/controller_front/gme_comments.js
  • 关注接口: api/controller_front/user_follow.js