# 群聊参与者展开/缩略双模式 PRD > **版本**: v1.0 > **日期**: 2026-07-14 > **作者**: 许清楚(产品经理) > **状态**: 待评审 --- ## 1. 项目信息 | 字段 | 值 | |------|-----| | **项目名称** | participant_dual_mode | | **技术栈** | H5端: Vue3 + Vant4 + TypeScript / 坐席端: Vue3 + Element Plus + TypeScript / 后端: 无需改动 | | **语言** | 中文 | | **UI风格** | 企微浅色扁平风格,accent = #07C160 | ### 原始需求复述 IT智能服务台群聊功能中,同一会话最多有4种角色:原始员工(发起人)、主责坐席、协作坐席、被邀请人。当前参与者展示存在两个问题:H5端 `ParticipantList.vue` 平铺完整列表始终占用较大空间,挤压聊天区域;坐席端 `ParticipantBar.vue` 一行横条信息密度低,只能看到名字缩略。本次需求为群聊参与者展示实现**展开/缩略双模式**,让用户在"快速概览谁在群里"和"查看参与者详情"之间切换。 ### 已确认设计决策(用户已拍板) 1. H5端展开模式:方案B 底部弹出 — Vant4 `van-popup position="bottom"` 2. 坐席端展开模式:就地向下展开 — 点击 ParticipantBar 横条向下撑开详情面板(~150px) 3. 头像排列顺序:主责坐席第一位,其余按加入时间排列,不分组 4. 退出确认:H5端点击"退出会话"弹 `van-dialog` 二次确认(保留已有实现) 5. 缩略模式角色区分:头像边框色 — 坐席蓝框、发起人橙框、被邀请人无框 6. 缩略模式信息量:头像条显示数字徽标,如"5人在群" 7. 自己的标识:自己头像加高亮环 + 略放大 8. 默认模式:缩略模式为默认,点击展开 9. 超员处理:缩略头像条超过N个显示前几个 + "+剩余人数"文本;展开模式支持滚动 --- ## 2. 产品定义 ### 2.1 产品目标 **提升信息密度与空间利用率**:将H5端原本平铺占用大量纵向空间的参与者列表改为缩略头像条(一行),释放出的空间归还给聊天区域;将坐席端一行横条改为可展开的详情面板,在需要时才展示完整信息。两端默认均为缩略模式,用户按需展开,兼顾"快速概览"与"查看详情"两种场景。 **统一双端交互心智模型**:H5端和坐席端虽然技术栈不同(Vant4 vs Element Plus),但交互逻辑保持一致——缩略模式看"谁在群里",展开模式看"每个人是谁",降低用户跨端使用的学习成本。 **保持角色辨识度**:通过头像边框色(坐席蓝框、发起人橙框、被邀请人无框)和自己的高亮环,在缩略模式下也能快速辨识参与者的角色身份和自己的位置。 ### 2.2 用户故事 | # | 角色 | 用户故事 | |---|------|---------| | US-1 | 员工 | **As a** 报修员工, **I want** 在聊天页面看到一行紧凑的参与者头像条而不是占满半屏的列表, **so that** 聊天区域有更多空间显示消息记录,我能看清上下文 | | US-2 | 员工 | **As a** 被邀请参与会话的员工, **I want** 点击头像条从底部弹出参与者详情面板,看到每个人的姓名、部门和角色, **so that** 我能确认群里都有谁再决定是否发言 | | US-3 | 员工 | **As a** 被邀请员工, **I want** 在展开的详情面板中点击"退出会话"并经过二次确认后退出, **so that** 我可以安全退出不再相关的会话,且不会误触退出 | | US-4 | 坐席 | **As a** 主责坐席, **I want** 点击参与者横条就地展开详情面板,看到每个参与者的完整信息(姓名、角色、加入状态), **so that** 我在需要时快速了解协作人员情况,不展开时不占空间 | | US-5 | 坐席 | **As a** 主责坐席, **I want** 在展开的详情面板中直接操作"邀请"和"移除参与者", **so that** 管理参与者不需要额外跳转到其他页面 | | US-6 | 坐席/员工 | **As a** 任何参与者, **I want** 缩略模式中通过头像边框颜色快速区分坐席/发起人/被邀请人,并看到自己的头像有高亮标记, **so that** 我一眼就能知道群里的角色构成和自己的位置 | --- ## 3. 需求池(P0/P1/P2) ### P0 — 必须完成(核心体验) #### FE-H5-01 H5端缩略模式头像条 | 项目 | 说明 | |------|------| | **需求** | 将 `ParticipantList.vue` 改造为默认显示一行紧凑头像条 | | **布局** | 横向排列:`[5人在群] [头像1][头像2][头像3]+2` ,高度约 40px | | **头像排列** | 主责坐席第一位,其余按加入时间顺序排列,不分组 | | **角色边框** | 坐席蓝框 `#3b82f6`、发起人橙框 `#FF9800`、被邀请人无边框 | | **自己标识** | 自己头像加高亮环 `#07C160`(2px ring)+ scale(1.1) 放大 | | **超员处理** | 缩略头像条最多显示 N 个头像(N=4),超出显示 `+剩余人数` 文本 | | **数字徽标** | 头像条左侧显示"X人在群"文字徽标 | | **交互** | 点击头像条任意位置触发展开 | | **约束** | 缩略模式高度 ≤ 44px,不遮挡聊天消息区 | #### FE-H5-02 H5端展开模式(底部弹出) | 项目 | 说明 | |------|------| | **需求** | 点击缩略头像条,从底部弹出参与者详情面板 | | **组件** | Vant4 `van-popup` `position="bottom"` `round` | | **内容** | 完整参与者列表:头像(32px) + 姓名 + 部门 + 角色徽标(发起人/坐席/已加入/待加入) | | **排列** | 与缩略模式一致:主责坐席第一位,其余按加入时间排列 | | **当前用户** | 高亮背景色 + "(我)"文字标签(保留现有实现) | | **头像降级** | 有avatar URL用img,加载失败显示姓名首字(保留现有逻辑) | | **退出按钮** | 仅被邀请人可见,点击弹 `showConfirmDialog` 二次确认(保留现有实现) | | **关闭方式** | 下滑关闭 / 点击遮罩关闭 / 点击右上角关闭按钮 | | **约束** | 弹出面板高度不超过屏幕 60%,内容区支持纵向滚动;上方聊天记录仍可见 | #### FE-Agent-01 坐席端缩略模式横条改造 | 项目 | 说明 | |------|------| | **需求** | 改造 `ParticipantBar.vue` 缩略模式,增加数字徽标和角色边框 | | **布局** | 保持现有一行横条结构:`[N人参与:] [头像1][头像2]... + 邀请` | | **角色边框** | 主责坐席蓝框 `#3b82f6`、协作坐席绿框 `#07C160`、发起人橙框 `#FF9800`、被邀请人无框 | | **自己标识** | 自己头像加高亮环 + scale(1.1) 放大 | | **超员处理** | 超过 N 个头像(N=6)只显示前几个 + `+剩余人数` 文本,溢出部分不横向滚动 | | **数字徽标** | 保留现有"N人参与:"文字,增加总人数计算(主责+协作+被邀请) | | **交互** | 点击横条主体区域触发展开;"+ 邀请"按钮独立点击不触发展开 | | **约束** | 缩略模式高度 ≤ 36px | #### FE-Agent-02 坐席端展开模式(就地展开) | 项目 | 说明 | |------|------| | **需求** | 点击 ParticipantBar 横条,在其原位置向下撑开详情面板 | | **布局** | flex 垂直布局,展开面板高度 ~150px,消息区被 flex 自动压缩但依然可见可滚动 | | **内容** | 参与者详情:头像(28px) + 姓名 + 角色标签(主责/协作/发起人) + 加入状态(已加入/待加入) | | **排列** | 主责坐席第一位,其余按加入时间排列,不分组 | | **操作按钮** | 主责坐席可见"+ 邀请"按钮和每项的"移除"图标(保留现有功能) | | **收起** | 面板右上角"收起"按钮 / 再次点击横条折叠回去 | | **动画** | 展开/收起使用 CSS transition(max-height / opacity),时长 ≤ 200ms | | **约束** | 展开面板内容超出时支持纵向滚动;展开时消息区最小高度不低于 200px | ### P1 — 应该完成(体验增强) #### FE-Common-01 展开状态记忆 | 项目 | 说明 | |------|------| | **需求** | 用户在当前会话中展开参与者面板后,切换会话再切回时保持展开/收起状态 | | **实现** | 状态存储在组件本地 `ref`,按会话 ID 记忆(不持久化到 localStorage) | | **约束** | 页面刷新后恢复默认缩略模式 | #### FE-H5-03 缩略头像条角标提示 | 项目 | 说明 | |------|------| | **需求** | 当有新的待加入参与者时,缩略头像条显示小红点角标 | | **触发** | participants 列表中存在 `joined === false` 的项时显示 | | **样式** | 头像条右上角 8px 红点 | #### FE-Agent-03 展开面板头像悬停 tooltip | 项目 | 说明 | |------|------| | **需求** | 坐席端展开面板中,鼠标悬停头像显示完整姓名和部门 tooltip | | **组件** | Element Plus `el-tooltip` | | **约束** | 仅在姓名被截断时显示(内容溢出时) | ### P2 — 可以后续实现(锦上添花) #### FE-Common-02 参与者加入/退出动画 | 项目 | 说明 | |------|------| | **需求** | 参与者加入或退出时,头像条有平滑的增减动画 | | **实现** | Vue `` + CSS transition | | **约束** | 不影响功能,动画时长 ≤ 300ms | #### FE-Common-03 缩略头像条长按预览(H5端) | 项目 | 说明 | |------|------| | **需求** | H5端长按缩略头像条中某个头像,弹出该参与者的简要信息卡片 | | **组件** | Vant4 `van-popup` 小型弹窗 | | **约束** | 不与点击展开冲突,长按 ≥ 500ms 触发 | #### FE-Agent-04 展开面板键盘快捷键 | 项目 | 说明 | |------|------| | **需求** | 坐席端支持快捷键切换展开/收起 | | **快捷键** | `Ctrl+Shift+P`(Participant) | | **约束** | 仅在聊天区域聚焦时生效 | --- ## 4. UI 设计稿描述 ### 4.1 H5端 — 缩略模式(默认) ``` ┌─────────────────────────────────┐ │ [< 返回] IT智能服务台 │ ← 顶部导航栏 ├─────────────────────────────────┤ │ │ │ [聊天消息区域 — 释放空间] │ │ │ │ 消息1... │ │ 消息2... │ │ │ ├─────────────────────────────────┤ │ 5人在群 (🟦)(🟧)( )( )+1 ▼ │ ← 缩略头像条 (h≈40px) ├─────────────────────────────────┤ │ [输入框] [发送] │ ← 输入区 └─────────────────────────────────┘ 缩略头像条细节: ┌──────────────────────────────────┐ │ 5人在群 [A][B][C][D]+1 ▼ │ │ ↑ ↑ ↑ ↑ │ │ 蓝框 橙框 无框 高亮环 │ │ (坐席)(发起人)(被邀请)(自己)│ └──────────────────────────────────┘ - 头像尺寸: 28px 圆形 - 角色边框: 2px solid (蓝#3b82f6/橙#FF9800/无) - 自己: 额外高亮环 #07C160 + scale(1.1) - 超员: 最多4个头像 + "+N" 文本 - 箭头: ▼ 表示可展开 ``` ### 4.2 H5端 — 展开模式(底部弹出) ``` ┌─────────────────────────────────┐ │ [< 返回] IT智能服务台 │ ├─────────────────────────────────┤ │ │ │ [聊天消息区域 — 仍可见] │ ← 上方聊天记录可见 │ 消息1... │ │ │ ├─────────────────────────────────┤ │ 5人在群 [A][B][C][D]+1 ▼ │ ← 缩略条仍显示 ╞═════════════════════════════════╡ ← van-popup 分隔 │ 参与者 [×] │ ← 弹出面板头部 │─────────────────────────────────│ │ (🟦) 张三 IT坐席 坐席 │ ← 主责坐席(蓝框) │ (🟧) 李四 财务部 发起人 │ ← 发起人(橙框) │ ( ) 王五 市场部 已加入 │ ← 被邀请人 │ ( ) 赵六 人事部 待加入 │ ← 待加入(灰色) │─────────────────────────────────│ │ [ 退出会话 ] │ ← 仅被邀请人可见 └─────────────────────────────────┘ ↑ 下滑关闭 / 点击遮罩关闭 弹出面板细节: - van-popup position="bottom" round - 最大高度: 60vh,内容超出纵向滚动 - 头像: 32px 圆形 - 每行: 头像 + 姓名 + 部门 + 角色徽标 - 当前用户: 背景色高亮 + "(我)"标签 - 退出按钮: 红色描边按钮,点击弹 van-dialog 二次确认 ``` ### 4.3 坐席端 — 缩略模式(默认) ``` ┌──────────────────────────────────────────────────────┐ │ UserInfoBar (用户信息栏) │ ├──────────────────────────────────────────────────────┤ │ TroubleshootBar (排查步骤栏) │ ├──────────────────────────────────────────────────────┤ │ 5人参与: [A][B][C][D][E][F]+1 + 邀请 ▼ │ ← ParticipantBar 缩略 (h≈36px) ├──────────────────────────────────────────────────────┤ │ │ │ [聊天消息区域] │ │ │ │ 消息1... │ │ 消息2... │ │ │ ├──────────────────────────────────────────────────────┤ │ [回复输入框] [发送] │ └──────────────────────────────────────────────────────┘ 缩略横条细节: ┌──────────────────────────────────────────────────────┐ │ 5人参与: (🟦)(🟧)( )( )(🟩)( )+1 + 邀请 ▼ │ │ ↑ ↑ ↑ ↑ ↑ ↑ │ │ 主责 发起 被邀 被邀 协作 被邀 │ │ 蓝框 橙框 无框 无框 绿框 无框 │ └──────────────────────────────────────────────────────┘ - 头像尺寸: 20px 圆形 - 角色边框: 2px solid (蓝#3b82f6/绿#07C160/橙#FF9800/无) - 自己: 高亮环 #07C160 + scale(1.1) - 超员: 最多6个头像 + "+N" 文本 - "+ 邀请"按钮独立点击,不触发展开 - ▼ 箭头表示可展开 ``` ### 4.4 坐席端 — 展开模式(就地展开) ``` ┌──────────────────────────────────────────────────────┐ │ UserInfoBar (用户信息栏) │ ├──────────────────────────────────────────────────────┤ │ TroubleshootBar (排查步骤栏) │ ├──────────────────────────────────────────────────────┤ │ 5人参与: [A][B][C][D][E][F]+1 + 邀请 ▲ │ ← 横条(点击收起) │┌────────────────────────────────────────────────────┐│ ││ 参与者详情 [收起] ││ ← 展开面板 (~150px) ││────────────────────────────────────────────────────││ ││ (🟦) 张三(主责) IT坐席 ││ ← 主责坐席 ││ (🟧) 李四 财务部 发起人 ││ ← 发起人 ││ ( ) 王五 市场部 已加入 [×] ││ ← 被邀请人(可移除) ││ ( ) 赵六 人事部 待加入 [×] ││ ← 待加入(可移除) ││ (🟩) 钱七(协作) IT坐席 ││ ← 协作坐席 │└────────────────────────────────────────────────────┘│ ├──────────────────────────────────────────────────────┤ │ │ │ [聊天消息区域 — 被压缩但可见] │ ← flex 自动压缩 │ 消息1... │ │ │ ├──────────────────────────────────────────────────────┤ │ [回复输入框] [发送] │ └──────────────────────────────────────────────────────┘ 展开面板细节: - 面板高度: ~150px,内容超出纵向滚动 - 头像: 28px 圆形 - 每行: 头像 + 姓名 + 角色标签 + 部门 + 加入状态 + [移除图标] - 移除图标: 仅主责坐席可见,点击移除参与者 - "+ 邀请"按钮: 仅主责坐席可见 - 收起: 点击"收起"按钮或再次点击横条 - 动画: max-height + opacity transition ≤ 200ms - 消息区最小高度: 200px(保证可用性) ``` ### 4.5 角色边框色规范 | 角色 | 边框色 | 色值 | 说明 | |------|--------|------|------| | 主责坐席 | 蓝色 | `#3b82f6` | 2px solid border | | 协作坐席 | 绿色 | `#07C160` | 2px solid border | | 发起人(员工) | 橙色 | `#FF9800` | 2px solid border | | 被邀请人 | 无边框 | — | 默认样式 | | 自己(任意角色) | 高亮环 | `#07C160` | 额外 2px ring + scale(1.1) | --- ## 5. 待确认问题 | # | 问题 | 影响范围 | 建议 | |---|------|---------|------| | Q1 | 缩略头像条超员阈值 N 的取值:H5端取4、坐席端取6是否合理? | 两端缩略模式 | 建议根据实际手机屏幕宽度(375px基准)和桌面端横条宽度做原型验证后确定 | | Q2 | H5端坐席目前无头像接口,缩略模式中坐席头像使用首字母降级,蓝色边框 + 首字母的视觉效果是否需要设计稿确认? | H5端缩略+展开 | 建议出一张视觉稿确认首字母头像 + 边框的呈现效果 | | Q3 | 坐席端展开面板高度固定 ~150px,当参与者超过5人时需要滚动。是否考虑改为自适应高度(如 min(150px, 内容高度))? | 坐席端展开 | 建议固定150px + 滚动,避免面板过高挤压消息区 | | Q4 | 发起人(原始员工)在坐席端的角色边框目前使用橙色,但现有代码中坐席端未区分发起人边框(只有主责蓝边、协作绿边)。是否需要后端在 participants 数据中标记发起人角色? | 坐席端 | 当前 `participants` 不含发起人(发起人在 `currentConversation.employee_id`),需确认坐席端是否需要单独展示发起人头像条目 | | Q5 | H5端展开模式弹出面板与输入框的层级关系:弹出面板是否遮罩输入框?还是输入框下移? | H5端展开 | 建议遮罩输入框,弹出面板为独立浮层,关闭后恢复输入框 |