Files
EchoChat/docs/plans/2026-03-04-phase2c-design.md
bujinyuan 86f371cc5c docs: Phase 2c 设计文档 + 实施计划 + 项目进度更新
- 新增 Phase 2c 设计文档(群聊与已读回执)
- 新增 Phase 2c 实施计划(14 个 Task)
- 更新 CURRENT_STATUS.md 反映 Phase 2c 规划
- 更新 project-context.mdc 新增 Phase 2c 进度和模块信息

Made-with: Cursor
2026-03-04 10:34:35 +08:00

24 KiB
Raw Blame History

Phase 2c 设计文档:群聊与已读回执

状态: 📋 设计完成,待实施 分支: feature/phase2c-group-read-receipt 前置依赖: Phase 2b 全部完成(单聊即时通讯) 最后更新: 2026-03-04


一、设计目标

基于 Phase 2b 的单聊 IM 基础设施,实现群聊核心功能和已读回执系统,同时引入 MinIO 文件存储服务作为基础设施扩展。

核心交付物:

  • 群聊管理(创建/加入/退出/解散/搜索/角色管理/禁言/公告)
  • 群消息收发(复用 im.message.* 事件 + @提醒 + 管理员撤回)
  • 已读回执(单聊会话级 + 群聊消息级 + 实时推送 + 详情查看)
  • MinIO 文件存储Docker 容器 + Go SDK + 通用上传 API
  • 管理端群聊管理(群列表/详情/解散/移除成员)
  • 前端 9 个新页面 + 群聊 Store + API 封装

不包含(留待后续阶段):

  • 图片/语音/文件消息
  • 管理端消息管理
  • 消息类型扩展

二、需求决策记录

2.1 群聊功能决策

决策项 选定方案 说明
创建方式 选好友 + 搜索用户 ID 拉人 非好友也可拉入群
成员上限 200 人(默认) im_groups.max_members 可配置
角色体系 三级:群主(2) + 管理员(1) + 普通成员(0) 微信模式
管理操作 全功能 改群名/头像/公告、拉人/踢人、禁言/全体禁言、转让群主、解散、设管理员
入群方式 被拉入(无需审批)+ 主动申请(需审批) 群主/管理员审批
退出机制 主动退出 + 显示系统消息 "XX 退出/加入/被移出了群聊"
历史消息 钉钉模式 新成员可查看所有历史消息
群搜索 全局搜索公开群 + 自己的群 默认可搜索,群主可设为不可搜索
群头像 默认图标 + 群主手动上传 使用 MinIO 存储
群昵称 成员可设置群内昵称 仅在该群内显示
免打扰 微信模式 仍计未读(灰色数字),不推送通知
@提醒 @某人 + @所有人 所有成员可 @所有人,输入 @ 弹出成员选择
@通知 会话列表标记 显示 "[N条] @了我"
正在输入 群聊不显示 仅单聊保留
消息撤回 成员 2 分钟,管理员无时限 群主/管理员可撤回任何人消息
撤回展示 区分操作者 "管理员 XX 撤回了 YY 的一条消息"
群公告 需要 群主/管理员发布,发布时推送系统消息通知全员

2.2 已读回执决策

决策项 选定方案 说明
单聊粒度 会话级别 复用 last_read_msg_id消息 ID ≤ 该值即已读
群聊粒度 消息级别 im_message_reads 表记录每人每条消息的已读
展示方式 钉钉模式 单聊 "已读/未读",群聊 "X人已读" 可点击查看列表
存储方案 纯 PostgreSQL im_message_reads 表(联合主键 message_id + user_id
推送策略 差异化 单聊实时推送已读变化,群聊仅推送已读计数变化
详情查看 REST 按需拉取 点击 "X人已读" 时 GET /api/v1/im/messages/:id/reads

2.3 基础设施决策

决策项 选定方案 说明
文件存储 MinIODocker 镜像) 通用上传 API后续消息类型扩展可复用
前端架构 群聊独立页面体系 不复用单聊页面,完全独立
会话列表 分 Tab 单聊 Tab + 群聊 Tab
WS 事件 消息复用 + 管理独立 im.message.* 复用group.* 新增
消息搜索 统一全局搜索 单聊 + 群聊消息在同一搜索结果中
分支策略 从 phase2b 拉新分支 feature/phase2c-group-read-receipt
管理端 群列表 + 详情 + 解散 + 移除 4 个管理 API + 2 个前端页面

三、架构设计

3.1 新增模块

模块 位置 职责
group app/group/ 群聊管理(创建/加入/退出/角色/禁言/搜索/审批)
file app/file/ 文件上传MinIO SDK 封装 + 通用上传 API
storage pkg/storage/ MinIO 客户端初始化 + 配置

3.2 模块目录结构

backend/go-service/
├── app/
│   ├── group/                        # [新增] 群聊管理模块
│   │   ├── controller/
│   │   │   └── group_controller.go   # REST API 控制器(~15 个接口)
│   │   ├── service/
│   │   │   └── group_service.go      # 群创建/管理/审批/搜索业务逻辑
│   │   ├── dao/
│   │   │   └── group_dao.go          # im_groups + 成员角色 + 入群申请 CRUD
│   │   ├── handler/
│   │   │   └── group_handler.go      # WS 群管理事件处理
│   │   ├── model/
│   │   │   ├── group.go              # im_groups 模型
│   │   │   └── join_request.go       # im_group_join_requests 模型
│   │   ├── router.go
│   │   └── provider.go
│   ├── file/                         # [新增] 文件上传模块
│   │   ├── controller/
│   │   │   └── file_controller.go    # POST /api/v1/upload
│   │   ├── service/
│   │   │   └── file_service.go       # MinIO 上传/删除封装
│   │   ├── router.go
│   │   └── provider.go
│   ├── im/                           # [扩展]
│   │   ├── dao/
│   │   │   └── read_dao.go           # [新增] im_message_reads 操作
│   │   ├── model/
│   │   │   └── message_read.go       # [新增] im_message_reads 模型
│   │   └── service/
│   │       └── im_service.go         # [扩展] 群消息/已读回执/管理员撤回
│   └── constants/
│       └── group.go                  # [新增] 群聊相关常量
├── pkg/
│   └── storage/
│       └── minio.go                  # [新增] MinIO 客户端初始化

frontend/src/
├── pages/
│   ├── group/                        # [新增] 群聊页面(独立体系)
│   │   ├── index.vue                 # 群聊会话列表
│   │   ├── conversation.vue          # 群聊对话页
│   │   ├── create.vue                # 创建群聊
│   │   ├── settings.vue              # 群聊设置
│   │   ├── members.vue               # 群成员列表
│   │   ├── invite.vue                # 邀请入群
│   │   ├── join-requests.vue         # 入群申请审批
│   │   └── search.vue                # 搜索公开群
│   └── chat/
│       └── read-detail.vue           # [新增] 已读回执详情页
├── store/
│   └── group.js                      # [新增] 群聊 Pinia Store
├── api/
│   ├── group.js                      # [新增] 群聊 API
│   └── file.js                       # [新增] 文件上传 API

admin/src/
├── views/
│   └── group/                        # [新增] 管理端群聊管理
│       ├── list.vue                  # 群列表
│       └── detail.vue                # 群详情(含成员管理)
├── api/
│   └── group.js                      # [新增] 管理端群聊 API

3.3 跨模块接口注入

延续 Phase 2a/2b 的接口注入模式,通过 Wire Bind 在 app/provider/wire.go 中统一绑定。

接口 定义模块 实现方 用途
GroupMemberChecker im/service group/dao.GroupDAO 检查用户是否为群成员
GroupInfoGetter im/service group/dao.GroupDAO 获取群信息(名称/头像/成员数)
GroupRoleChecker im/service group/dao.GroupDAO 检查用户群角色(管理员撤回权限)
已有接口 - - FriendChecker / UserInfoGetter / FriendIDsGetter 等继续复用

四、数据库设计

4.1 新增表

im_groups群聊信息表

CREATE TABLE im_groups (
    id              BIGSERIAL PRIMARY KEY,
    conversation_id BIGINT NOT NULL UNIQUE REFERENCES im_conversations(id),
    name            VARCHAR(100) NOT NULL DEFAULT '',
    avatar          VARCHAR(500) DEFAULT '',
    owner_id        BIGINT NOT NULL,
    notice          TEXT DEFAULT '',
    max_members     INT NOT NULL DEFAULT 200,
    is_searchable   BOOLEAN NOT NULL DEFAULT TRUE,
    is_all_muted    BOOLEAN NOT NULL DEFAULT FALSE,
    status          SMALLINT NOT NULL DEFAULT 1,
    created_at      TIMESTAMP(0) NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP(0) NOT NULL DEFAULT NOW()
);

COMMENT ON TABLE  im_groups                IS '群聊信息表';
COMMENT ON COLUMN im_groups.id             IS '群唯一标识';
COMMENT ON COLUMN im_groups.conversation_id IS '关联 im_conversations.id';
COMMENT ON COLUMN im_groups.name           IS '群名称';
COMMENT ON COLUMN im_groups.avatar         IS '群头像 URLMinIO';
COMMENT ON COLUMN im_groups.owner_id       IS '群主用户 ID';
COMMENT ON COLUMN im_groups.notice         IS '群公告内容';
COMMENT ON COLUMN im_groups.max_members    IS '最大成员数,默认 200';
COMMENT ON COLUMN im_groups.is_searchable  IS '是否可被搜索发现';
COMMENT ON COLUMN im_groups.is_all_muted   IS '是否全体禁言';
COMMENT ON COLUMN im_groups.status         IS '群状态1=正常2=已解散';

CREATE INDEX idx_im_groups_owner ON im_groups(owner_id);
CREATE INDEX idx_im_groups_name ON im_groups USING gin(to_tsvector('simple', name));

im_group_join_requests入群申请表

CREATE TABLE im_group_join_requests (
    id          BIGSERIAL PRIMARY KEY,
    group_id    BIGINT NOT NULL REFERENCES im_groups(id),
    user_id     BIGINT NOT NULL,
    message     TEXT DEFAULT '',
    reviewer_id BIGINT DEFAULT NULL,
    status      SMALLINT NOT NULL DEFAULT 0,
    created_at  TIMESTAMP(0) NOT NULL DEFAULT NOW(),
    updated_at  TIMESTAMP(0) NOT NULL DEFAULT NOW()
);

COMMENT ON TABLE  im_group_join_requests              IS '入群申请表';
COMMENT ON COLUMN im_group_join_requests.id            IS '申请唯一标识';
COMMENT ON COLUMN im_group_join_requests.group_id      IS '目标群 ID';
COMMENT ON COLUMN im_group_join_requests.user_id       IS '申请人用户 ID';
COMMENT ON COLUMN im_group_join_requests.message       IS '申请附言';
COMMENT ON COLUMN im_group_join_requests.reviewer_id   IS '审批人用户 ID';
COMMENT ON COLUMN im_group_join_requests.status        IS '状态0=待审批1=通过2=拒绝';

CREATE INDEX idx_group_join_req_group ON im_group_join_requests(group_id, status);
CREATE INDEX idx_group_join_req_user ON im_group_join_requests(user_id);

im_message_reads消息已读记录表

CREATE TABLE im_message_reads (
    message_id BIGINT NOT NULL,
    user_id    BIGINT NOT NULL,
    read_at    TIMESTAMP(0) NOT NULL DEFAULT NOW(),
    PRIMARY KEY (message_id, user_id)
);

COMMENT ON TABLE  im_message_reads            IS '群聊消息已读记录表(消息级别)';
COMMENT ON COLUMN im_message_reads.message_id IS '消息 ID';
COMMENT ON COLUMN im_message_reads.user_id    IS '已读用户 ID';
COMMENT ON COLUMN im_message_reads.read_at    IS '已读时间';

CREATE INDEX idx_msg_reads_user ON im_message_reads(user_id, read_at);

4.2 扩展现有表

im_conversation_members — 新增 5 个字段

ALTER TABLE im_conversation_members
    ADD COLUMN role              SMALLINT NOT NULL DEFAULT 0,
    ADD COLUMN nickname          VARCHAR(50) DEFAULT '',
    ADD COLUMN is_muted          BOOLEAN NOT NULL DEFAULT FALSE,
    ADD COLUMN is_do_not_disturb BOOLEAN NOT NULL DEFAULT FALSE,
    ADD COLUMN joined_at         TIMESTAMP(0) DEFAULT NULL;

COMMENT ON COLUMN im_conversation_members.role              IS '成员角色0=普通成员1=管理员2=群主';
COMMENT ON COLUMN im_conversation_members.nickname          IS '群内昵称(仅群聊有效)';
COMMENT ON COLUMN im_conversation_members.is_muted          IS '是否被禁言';
COMMENT ON COLUMN im_conversation_members.is_do_not_disturb IS '是否消息免打扰(微信模式:仍计未读但灰色显示)';
COMMENT ON COLUMN im_conversation_members.joined_at         IS '加入群聊时间';

im_messages — 新增 1 个字段

ALTER TABLE im_messages
    ADD COLUMN at_user_ids BIGINT[] DEFAULT NULL;

COMMENT ON COLUMN im_messages.at_user_ids IS '@提醒用户 ID 列表NULL=无@,包含 0 表示 @所有人';

4.3 数据库表关系图

im_conversations (type=2 群聊)
    │ 1:1
    ├── im_groups (群信息:名称/头像/公告/群主)
    │       │ 1:N
    │       └── im_group_join_requests (入群申请)
    │ 1:N
    ├── im_conversation_members (成员:+role/nickname/is_muted/is_do_not_disturb)
    │ 1:N
    └── im_messages (消息:+at_user_ids)
            │ 1:N
            └── im_message_reads (群聊消息已读记录)

五、API 设计

5.1 群聊 REST API16 个)

# 方法 路径 描述 权限
1 POST /api/v1/groups 创建群聊 登录用户
2 GET /api/v1/groups/:id 群详情 群成员
3 PUT /api/v1/groups/:id 更新群信息 群主/管理员
4 DELETE /api/v1/groups/:id 解散群聊 群主
5 GET /api/v1/groups/:id/members 成员列表 群成员
6 POST /api/v1/groups/:id/members 邀请/拉人入群 群主/管理员
7 DELETE /api/v1/groups/:id/members/:uid 踢人 群主/管理员
8 PUT /api/v1/groups/:id/members/:uid/role 设置/取消管理员 群主
9 PUT /api/v1/groups/:id/members/:uid/mute 禁言/解除禁言 群主/管理员
10 POST /api/v1/groups/:id/leave 退出群聊 群成员
11 PUT /api/v1/groups/:id/transfer 转让群主 群主
12 PUT /api/v1/groups/:id/members/me/nickname 修改群昵称 群成员
13 POST /api/v1/groups/:id/join-requests 申请入群 登录用户
14 GET /api/v1/groups/:id/join-requests 入群申请列表 群主/管理员
15 PUT /api/v1/groups/:id/join-requests/:rid 审批入群申请 群主/管理员
16 GET /api/v1/groups/search 搜索公开群 登录用户

5.2 已读回执 REST API2 个)

# 方法 路径 描述
1 GET /api/v1/im/messages/:id/reads 消息已读详情(谁读了,分页)
2 GET /api/v1/im/messages/:id/read-count 消息已读/未读计数

5.3 文件上传 REST API1 个)

# 方法 路径 描述
1 POST /api/v1/upload 通用文件上传(返回 MinIO URL

5.4 管理端 REST API4 个)

# 方法 路径 描述
1 GET /api/v1/admin/groups 群列表(分页 + 筛选)
2 GET /api/v1/admin/groups/:id 群详情(含成员列表)
3 DELETE /api/v1/admin/groups/:id 管理员解散群
4 DELETE /api/v1/admin/groups/:id/members/:uid 管理员移除成员

5.5 WebSocket 事件

消息事件(复用 im.message.*,扩展群聊支持)

事件 方向 变更说明
im.message.send C→S data 新增 at_user_ids 字段
im.message.send.ack S→C 无变化
im.message.new S→C data 新增 conv_type、at_user_ids 字段
im.message.recall C→S 群聊时管理员可撤回他人消息(无时限)
im.message.recalled S→C 群聊时区分 "管理员 XX 撤回了 YY 的消息"

已读回执事件(新增)

事件 方向 说明
im.message.read C→S 上报已读:单聊走 last_read_msg_id群聊写 im_message_reads
im.message.read.ack S→C 单聊:实时推送已读状态给消息发送者
im.message.read.count S→C 群聊:推送已读计数变化 {msg_id, read_count}

群管理事件(新增 group.* 系列)

事件 方向 说明
group.member.join S→C 成员加入通知(含系统消息 "XX 加入了群聊"
group.member.leave S→C 成员退出通知(含系统消息 "XX 退出了群聊"
group.member.kicked S→C 成员被踢通知(含系统消息 "XX 被移出了群聊"
group.info.update S→C 群信息变更通知(名称/头像)
group.notice.update S→C 群公告变更通知(含系统消息)
group.dissolved S→C 群解散通知
group.mute.update S→C 禁言状态变更通知(个人/全体)
group.join.request S→C 新入群申请(推送给群主/管理员)
group.join.approved S→C 入群申请通过(推送给申请人)

六、核心业务流程

6.1 创建群聊

1. 用户选择好友 + 搜索用户 ID → 确定初始成员列表
2. POST /api/v1/groups {name, member_ids[]}
3. GroupService:
   a. 创建 im_conversations (type=2)
   b. 创建 im_groups (关联 conversation_id)
   c. 批量创建 im_conversation_members (创建者 role=2 群主, 其余 role=0)
   d. 插入系统消息 "XX 创建了群聊,邀请了 A、B、C 加入"
   e. PubSub 推送 group.member.join 给所有初始成员
4. 返回群信息 + 会话 ID

6.2 群消息发送

1. 发送者 WS: im.message.send {conversation_id, content, at_user_ids}
2. IMService.SendMessage:
   a. 查询 im_conversations.type → 群聊分支
   b. 校验群成员身份 + 禁言检查is_muted / is_all_muted管理员豁免全体禁言
   c. 写入 im_messages (含 at_user_ids)
   d. 更新 im_conversations.last_msg_*
   e. 遍历群成员:
      - 排除发送者
      - 非免打扰成员:递增 unread_count + Redis 全局未读
      - 免打扰成员:递增 unread_count不递增 Redis 全局未读
      - 被 @的成员:记录 @计数(可存 im_conversation_members 或 Redis
   f. PubSub.PublishToUsers → 推送 im.message.new 给所有在线成员
3. 发送者收到 im.message.send.ack

6.3 已读回执(单聊)

1. 用户打开单聊会话
2. 前端 WS: im.message.read {conversation_id}
3. IMService:
   a. 获取会话最新消息 ID → 更新 last_read_msg_id
   b. 清零 unread_count + Redis 全局未读
   c. PubSub 推送 im.message.read.ack 给对方
      {conversation_id, reader_id, last_read_msg_id}
4. 对方前端收到后,对 ID ≤ last_read_msg_id 的自己发送的消息标记为 "已读"

6.4 已读回执(群聊)

1. 用户打开群聊会话,前端获取可视区域消息 ID 列表
2. 前端 WS: im.message.read {conversation_id, message_ids[]}
3. IMService:
   a. 批量写入 im_message_reads (ON CONFLICT DO NOTHING)
   b. 更新 last_read_msg_id + 清零 unread_count
   c. 查询受影响消息的 sender_id去重
   d. 对每个 sender_id 推送 im.message.read.count
      {msg_id, read_count, total_members}
4. 发送者前端更新 "X人已读" 显示
5. 用户点击 "X人已读" → GET /api/v1/im/messages/:id/reads → 显示详情列表

6.5 @提醒流程

1. 发送者在输入框键入 @ → 弹出成员选择列表
2. 选择成员(或 @所有人)→ 消息中插入 @昵称 标记
3. 发送消息时 at_user_ids 包含被 @用户的 ID0 表示 @所有人)
4. 接收方前端:
   a. 收到 im.message.new 检查 at_user_ids
   b. 如果包含自己的 ID 或 0 → 标记该会话 "被@"
   c. 会话列表显示 "[N条] @了我"

七、前端页面规划

7.1 新增页面9 个)

页面 路径 功能描述
群聊会话列表 pages/group/index.vue 群聊 Tab 页,显示群会话列表
群聊对话页 pages/group/conversation.vue 群消息展示 + 发送 + @选择器
创建群聊 pages/group/create.vue 选好友 + 搜索用户 + 填群名
群设置 pages/group/settings.vue 群信息/公告/成员概览/免打扰/退群/解散
群成员列表 pages/group/members.vue 完整成员列表 + 角色标识 + 管理操作
邀请入群 pages/group/invite.vue 搜索用户 ID 拉人入群
入群审批 pages/group/join-requests.vue 群主/管理员审批入群申请
搜索群聊 pages/group/search.vue 搜索公开群 + 申请加入
已读详情 pages/chat/read-detail.vue 已读/未读人员列表(单聊+群聊共用)

7.2 修改现有页面

页面 修改内容
pages/chat/index.vue 改为 Tab 切换:单聊 Tab + 群聊 Tab
pages/chat/conversation.vue 添加单聊已读状态展示("已读"/"未读"
pages/chat/search.vue 全局搜索扩展支持群聊消息结果
components/CustomTabBar.vue TabBar 适配群聊入口

7.3 管理端新增页面2 个)

页面 路径 功能描述
群列表 admin/src/views/group/list.vue 群列表(搜索/分页/状态筛选)
群详情 admin/src/views/group/detail.vue 群信息 + 成员列表 + 解散/移除操作

八、Docker Compose 变更

deploy/docker/docker-compose.dev.yml 中新增 MinIO 服务:

minio:
  image: minio/minio:latest
  command: server /data --console-address ":9001"
  ports:
    - "9000:9000"
    - "9001:9001"
  environment:
    MINIO_ROOT_USER: echochat
    MINIO_ROOT_PASSWORD: echochat123456
  volumes:
    - minio_data:/data
  restart: unless-stopped

Go 后端 config.yaml 新增:

minio:
  endpoint: "localhost:9000"
  access_key: "echochat"
  secret_key: "echochat123456"
  bucket: "echochat"
  use_ssl: false

九、常量定义规划

// app/constants/group.go

// 群成员角色
const (
    GroupRoleMember = 0  // 普通成员
    GroupRoleAdmin  = 1  // 管理员
    GroupRoleOwner  = 2  // 群主
)

// 群状态
const (
    GroupStatusActive    = 1  // 正常
    GroupStatusDissolved = 2  // 已解散
)

// 入群申请状态
const (
    JoinRequestPending  = 0  // 待审批
    JoinRequestApproved = 1  // 已通过
    JoinRequestRejected = 2  // 已拒绝
)

// 系统消息类型im_messages.type 扩展)
const (
    MessageTypeSystem = 10  // 系统通知消息
)

十、DTO 扩展规划

10.1 群聊 DTO

// CreateGroupRequest 创建群聊请求
type CreateGroupRequest struct {
    Name      string  `json:"name" binding:"required"`
    MemberIDs []int64 `json:"member_ids" binding:"required,min=1"`
}

// GroupDTO 群详情
type GroupDTO struct {
    ID             int64  `json:"id"`
    ConversationID int64  `json:"conversation_id"`
    Name           string `json:"name"`
    Avatar         string `json:"avatar"`
    OwnerID        int64  `json:"owner_id"`
    OwnerNickname  string `json:"owner_nickname"`
    Notice         string `json:"notice"`
    MemberCount    int    `json:"member_count"`
    MaxMembers     int    `json:"max_members"`
    IsSearchable   bool   `json:"is_searchable"`
    IsAllMuted     bool   `json:"is_all_muted"`
    Status         int    `json:"status"`
    CreatedAt      string `json:"created_at"`
}

// GroupMemberDTO 群成员信息
type GroupMemberDTO struct {
    UserID       int64  `json:"user_id"`
    Username     string `json:"username"`
    Nickname     string `json:"nickname"`      // 群昵称(优先)或全局昵称
    Avatar       string `json:"avatar"`
    Role         int    `json:"role"`
    IsMuted      bool   `json:"is_muted"`
    IsOnline     bool   `json:"is_online"`
    JoinedAt     string `json:"joined_at"`
}

10.2 已读回执 DTO

// ReadDetailDTO 消息已读详情
type ReadDetailDTO struct {
    UserID   int64  `json:"user_id"`
    Nickname string `json:"nickname"`
    Avatar   string `json:"avatar"`
    ReadAt   string `json:"read_at"`
}

// ReadCountDTO 消息已读计数
type ReadCountDTO struct {
    MessageID    int64 `json:"message_id"`
    ReadCount    int   `json:"read_count"`
    UnreadCount  int   `json:"unread_count"`
    TotalMembers int   `json:"total_members"`
}

10.3 ConversationDTO 扩展

// ConversationDTO 扩展:增加群聊字段
type ConversationDTO struct {
    // 原有字段...
    GroupID        *int64  `json:"group_id,omitempty"`        // 群聊时的群 ID
    GroupName      string  `json:"group_name,omitempty"`      // 群名称
    GroupAvatar    string  `json:"group_avatar,omitempty"`    // 群头像
    MemberCount    int     `json:"member_count,omitempty"`    // 群成员数
    IsDoNotDisturb bool    `json:"is_do_not_disturb"`         // 是否免打扰
    AtMeCount      int     `json:"at_me_count,omitempty"`     // 被@计数
}