- Task 15 UI:6 项原创特色(说话者流光 / 柔性网格 / 自视频浮窗 / 静音氛围色 / 入会滑入 / NetworkBadge 3 条波浪)+ 说话者双源探测(RTP audioLevel + WebAudio RMS)+ 主持人四件套(静音/开麦/转让/踢出) - 新增 SelfVideoFloat 浮窗组件 + 4 份 design-system 页面文档(home / preview / room / invite) - 媒体回归补丁(手工联调触发): * 后端 signal_service 在 OnRoomJoin 追加 pushExistingRoomState → 向新加入者补发历史 producers + 历史成员 audio/video 状态 * 新增 Redis Hash memberStateKey 持久化成员 audio/video enabled,OnMemberStateChanged 落盘、cleanupUserResources 清理 * 前端 _broadcastSelfState 在本地音视频开关末尾同步 state.changed;_afterJoined 先 getRoom 再 room.join 修复后入者成员状态时序;_onMemberStateChanged 占位兜底 * _cleanupRemoteProducer 改为按 producerId 精准清理(修复 "关音频误关视频") * _onRoomEnded + createAndEnter/joinAndEnter 强化 reset(修复重入会看不到自己画面) * mediasoup-client ensureSend/RecvTransport 引入 in-flight Promise 锁防并发重复建连 - 文档同步:CURRENT_STATUS.md / Task 15 plan / phase2e-2 implementation plan Made-with: Cursor
5.7 KiB
5.7 KiB
Meeting Room (会议室主页面) Page Overrides
PROJECT: EchoChat Generated: 2026-04-24 (via Task 15 UI 打磨) Page Type: Full Screen — Meeting Main View (Fixed Fullscreen Layer) Route:
/pages/meeting/room
⚠️ Rules in this file override
design-system/echochat/MASTER.md. ⚠️ 本页面是 EchoChat 会议模块原创视觉的集大成体现,包含 6 条原创特色: 流光轮廓 / 柔性网格 / 自视频浮窗吸附 / 静音氛围色 / 入会滑入 / 波浪网络徽标。
Page Layout
- 结构: 顶部信息条(Title + Code + State pill + NetworkBadge + Timer) + 主视频区 + 聊天侧栏(可隐藏)+ 底部工具栏
- Z-index 层级(严格遵守):
room root: 1000(高于 CustomTabBar)top-bar: 5video-grid: autoSelfVideoFloat: 120MemberPanel / InviteDialog 遮罩: 200MeetingToolbar: 210Leave Confirm Modal: 220
原创特色 1:说话者流光轮廓
规范:
.tile.speaking {
border: 2rpx solid transparent;
background:
linear-gradient(#0B1220, #0B1220) padding-box,
conic-gradient(from var(--flow-angle, 0deg),
#10B981, #2563EB, #6366F1, #10B981) border-box;
animation: flow 3s linear infinite;
box-shadow: 0 0 24rpx rgba(99, 102, 241, 0.45);
}
@property --flow-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
@keyframes flow { to { --flow-angle: 360deg; } }
- 触发:
audioLevel >= 0.05,1 in / 2 out 防抖(500ms polling) - Safari 17- fallback: 静态蓝环
border-color: #3B82F6 + box-shadow(既有实现)
原创特色 2:柔性网格(2/3 人非等分)
| 成员数(不含本地浮窗) | 布局 | 说明 |
|---|---|---|
| 0 | 居中文案 "等待其他人加入…" | 只有自己时本地浮窗承担唯一画面 |
| 1 | 单块铺满 | 远端唯一成员占满视频区 |
| 2 | 左右 65/35 | 首位(加入时间早)为主画面 |
| 3 | 大块左侧 60% + 右侧 2 块上下叠放各 50% | 三角视觉焦点 |
| 4-9 | repeat(3, 1fr) 等分 |
保守兜底 |
| 10+ | repeat(ceil(sqrt(n)), 1fr) |
同现有 |
- 间隙:
gap: 12rpx(保持现有) - 小屏(
max-width: 750px): 回退到纵向等分,不启用非等分
原创特色 3:自视频浮窗四角吸附
规范:
- 默认位置: 右下角,距视频区
24rpx - 尺寸:
- 桌面端:
280px × 180px - 移动端:
240rpx × 150rpx(16:10)
- 桌面端:
- 视觉:
border-radius: 16rpx; 阴影0 12rpx 32rpx rgba(0,0,0,0.45);1rpx solid rgba(255,255,255,0.1)微边 - 图钉按钮: 右上角
36rpx × 36rpx半透明圆形按钮,点击切换 float ↔ grid - 拖拽:
- PC:
mousedown/mousemove/mouseup - 移动:
touchstart/touchmove/touchend - 拖拽中禁用
user-select: none,cursor: grabbing
- PC:
- 吸附:
- 释放时计算距离 4 角最近者
transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1)
- Z-index: 120
原创特色 4:静音氛围色
规范:
- 工具栏背景
computed(allMuted):- 正常(默认或有人开麦):
rgba(17, 24, 39, 0.88) - 全员静音且 ≥ 2 人:
linear-gradient(to top, rgba(30, 58, 138, 0.88), rgba(30, 64, 175, 0.78))(冷蓝)
- 正常(默认或有人开麦):
- 过渡:
transition: background 0.4s ease - 触发条件:
tiles.length >= 2 && tiles.every(t => !t.audioEnabled)
原创特色 5:入会滑入动效
- 新成员
tile插入网格时使用@keyframes slideIn:
@keyframes slideIn {
from { transform: translateY(16rpx); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.grid-cell { animation: slideIn 0.28s cubic-bezier(0.2,0.8,0.2,1) both; }
- 注意: 避免所有 tile 在页面首次挂载时全部跑动画;用
v-forkey +<transition-group>或者标志位isFirstLoad = false后才启用。
原创特色 6:NetworkBadge 3 条波浪
规范:
- 3 条 SVG 曲线
<path d="M0 8 C 2 4, 4 12, 6 8 S 10 4, 12 8 S 16 12, 18 8" /> - 宽度
18px,高16px,stroke-width: 2,fill: none - level → 可见条数 & 颜色:
4优秀: 3 条#10B9813良好: 2 条#22C55E2一般: 1 条#F59E0B1很差: 1 条短版#EF44440已断: 静态水平红线 +!小图标
- 动效:
@keyframes wave { from { transform: translateX(0); } to { transform: translateX(-6px); } },1.2s linear infinite,3 条相位差0s / -0.3s / -0.6s
Color Palette (页面专属)
| 用途 | Hex |
|---|---|
| 房间背景 | #0F172A |
| 视频区背景 | #0B1220 |
| 视频块背景 | #0B1220 |
| 聊天侧栏 | #1F2937 |
| Toolbar 默认 | rgba(17,24,39,0.88) |
| Toolbar 全员静音 | linear-gradient(to top, rgba(30,58,138,0.88), rgba(30,64,175,0.78)) |
| 状态 pill 已连接 | rgba(16,185,129,0.2) + #86EFAC |
| 状态 pill 重连 | rgba(245,158,11,0.25) + #FBBF24 |
Motion Timeline
| 事件 | 动效 | 时长 |
|---|---|---|
| 页面挂载 | Top-bar fade-in | 200ms |
| 新成员加入 | tile slideIn |
280ms |
| 开始说话 | 边框流光启动 | 持续 |
| 全员静音 | Toolbar 背景渐变 | 400ms |
| 浮窗释放吸附 | transform 缓动 |
220ms |
Interactions
- 工具栏按钮: 所有交互事件见
MeetingToolbar.vue;二次点击成员/聊天/邀请均 toggle 关闭 - 浮窗图钉: 点击切换 float/grid 模式,
meetingStore.uiPrefs.selfFloat记忆 - 主持人:
- 成员面板右侧三点菜单展开"请他静音 / 请他开麦 / 转让主持人 / 踢出会议"
- 四件套全部收敛在 MemberPanel 内,不在主界面暴露
Accessibility
- 所有动效尊重
@media (prefers-reduced-motion: reduce),禁用流光旋转与入会滑入,改为渐变态