feat(meeting): Task 15 UI 打磨 + 主持人四件套 + 媒体层稳定性回归修复
- 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
This commit is contained in:
68
design-system/echochat/pages/meeting-home.md
Normal file
68
design-system/echochat/pages/meeting-home.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Meeting Home (会议 Hub 首页) Page Overrides
|
||||
|
||||
> **PROJECT:** EchoChat
|
||||
> **Generated:** 2026-04-24 (via Task 15 UI 打磨)
|
||||
> **Page Type:** Tab Page — Meeting Entrance + Quick Actions
|
||||
> **Route:** `/pages/meeting/home` / `/pages/meeting/join`
|
||||
|
||||
> ⚠️ Rules in this file **override** `design-system/echochat/MASTER.md`.
|
||||
> ⚠️ 会议相关页面整体采用**深色主题**(`#0F172A` 背景),与聊天模块浅色主题形成品牌视觉分层。
|
||||
|
||||
---
|
||||
|
||||
## Page Layout
|
||||
|
||||
- **结构:** 顶部品牌区 + 主操作卡片(创建 / 加入二选一)+ 底部"最近会议"列表
|
||||
- **背景:** `#0F172A` 纯色 + 顶部柔和蓝紫径向光晕(参考系统主色 `#2563EB`)
|
||||
- **状态栏:** 透明穿透,内容顶部留 `env(safe-area-inset-top)` 间距
|
||||
|
||||
### 主操作卡片(2 卡片横向)
|
||||
|
||||
| 卡片 | 主图标 | 背景 | 文案 |
|
||||
|------|-------|------|------|
|
||||
| 创建会议 | `video` svg 28px white | `linear-gradient(135deg, #2563EB, #6366F1)` | 主标题 "发起会议" + 副标题 "创建一个即时会议" |
|
||||
| 加入会议 | `log-in` svg 28px white | `rgba(255,255,255,0.06)` + `1rpx solid rgba(255,255,255,0.12)` | 主标题 "加入会议" + 副标题 "输入会议号或粘贴链接" |
|
||||
|
||||
- **尺寸:** 卡片高 `240rpx`,圆角 `24rpx`,阴影 `0 8rpx 24rpx rgba(37, 99, 235, 0.25)`(仅创建卡)
|
||||
- **悬停:** `transform: translateY(-4rpx)` + 阴影加深
|
||||
- **点击反馈:** `transform: scale(0.98)` `.12s`
|
||||
|
||||
### 最近会议列表
|
||||
|
||||
- **背景:** `rgba(255, 255, 255, 0.04)` + `1rpx solid rgba(255,255,255,0.08)` 边框
|
||||
- **列表项:** 时间(左对齐 `#94A3B8 22rpx`)+ 标题(`#F3F4F6 28rpx`)+ 时长徽标(右侧 `#10B981` 小标签)
|
||||
- **空状态:** 居中 icon `clock` + 灰字 "暂无最近会议"
|
||||
|
||||
## Color Palette (页面专属)
|
||||
|
||||
| 用途 | Hex | 说明 |
|
||||
|------|-----|------|
|
||||
| 主背景 | `#0F172A` | Slate 900 |
|
||||
| 卡片面 | `rgba(255,255,255,0.06)` | Glass 效果 |
|
||||
| 主 CTA 渐变 | `#2563EB → #6366F1` | 创建会议主按钮 |
|
||||
| 辅 CTA | `rgba(255,255,255,0.12)` | 加入会议按钮边框 |
|
||||
| 正文 | `#F3F4F6` | Gray 100 |
|
||||
| 辅助文字 | `#94A3B8` | Slate 400 |
|
||||
| 成功点缀 | `#10B981` | 在线 / 时长 |
|
||||
|
||||
## Typography
|
||||
|
||||
| 层级 | Size | Weight | Color |
|
||||
|------|------|--------|-------|
|
||||
| 品牌标题 | `44rpx` | 700 | `#F8FAFC` |
|
||||
| 卡片主标题 | `32rpx` | 600 | `#FFFFFF` |
|
||||
| 卡片副标题 | `24rpx` | 400 | `rgba(255,255,255,0.75)` |
|
||||
| 列表时间戳 | `22rpx` | 400 | `#94A3B8` |
|
||||
|
||||
## Motion
|
||||
|
||||
- **入场:** 两张主卡片依次淡入 + 向上 `16rpx` 位移,`stagger: 80ms`
|
||||
- **CTA 呼吸:** 创建卡在空闲 3s 后阴影脉动(`opacity 0.25 → 0.4 → 0.25`,`2.4s ease-in-out infinite`)
|
||||
- **点击触达:** 任何 CTA 点击后转场用 `slide-up` `.28s cubic-bezier(0.2,0.8,0.2,1)`
|
||||
|
||||
## Interactions
|
||||
|
||||
- **创建会议:** `navigateTo('/pages/meeting/preview?mode=create')`
|
||||
- **加入会议:** `navigateTo('/pages/meeting/join')`
|
||||
- **最近会议项点击:** 直接 `navigateTo('/pages/meeting/preview?code=xxx&mode=join')`
|
||||
- **长按列表项(暂不做):** Task 16 拓展
|
||||
86
design-system/echochat/pages/meeting-invite.md
Normal file
86
design-system/echochat/pages/meeting-invite.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Meeting Invite (邀请弹窗) Page Overrides
|
||||
|
||||
> **PROJECT:** EchoChat
|
||||
> **Generated:** 2026-04-24 (via Task 15 UI 打磨)
|
||||
> **Page Type:** Bottom Sheet / Center Modal — Share Meeting
|
||||
> **Component:** `frontend/src/components/meeting/InviteDialog.vue`
|
||||
|
||||
> ⚠️ Rules in this file **override** `design-system/echochat/MASTER.md`.
|
||||
|
||||
---
|
||||
|
||||
## Page Layout
|
||||
|
||||
- **容器类型:** 居中 Modal(桌面端)/ 底部 BottomSheet(移动端 `<= 750px`)
|
||||
- **遮罩:** `rgba(0, 0, 0, 0.55)` + backdrop blur `8px`
|
||||
- **容器:**
|
||||
- 桌面: `520rpx × auto`,`#FFFFFF`,圆角 `24rpx`,阴影 `0 24rpx 48rpx rgba(0,0,0,0.35)`
|
||||
- 移动: `100vw`,顶部圆角 `24rpx 24rpx 0 0`
|
||||
- **Z-index:** 200(同 MemberPanel 同级,因是互斥显示)
|
||||
|
||||
## 内容分区
|
||||
|
||||
### 1. 头部
|
||||
|
||||
- 关闭按钮(右上角 `56rpx` 圆形按钮)+ 标题 "邀请成员加入"
|
||||
- 副标题:会议标题 + 会议号格式化 `xxx-xxx-xxx`
|
||||
|
||||
### 2. 分享方式 3 选项(并列)
|
||||
|
||||
| 选项 | 图标 | 说明 | 操作 |
|
||||
|------|-----|------|-----|
|
||||
| 复制链接 | `link` 24px | 带 Token 链接,含密码(若有) | 复制到剪贴板 + toast |
|
||||
| 复制会议号 | `hash` 24px | 纯会议号(需对方手动输入密码) | 复制 + toast |
|
||||
| 邀请联系人 | `user-plus` 24px | 打开联系人选择器(复用 Phase 2a 组件) | 打开抽屉 |
|
||||
|
||||
- **布局:** 水平排列,每项尺寸 `144rpx × 144rpx`;图标上方居中,文案下方居中
|
||||
- **Hover / Active:** 卡片背景 `#F3F4F6` → `#E5E7EB`;`scale(0.98)` on active
|
||||
|
||||
### 3. 信息展示
|
||||
|
||||
- **邀请链接区:** 单行滚动 input(readonly)+ 右侧 "复制" 按钮
|
||||
- 背景 `#F8FAFC`,圆角 `12rpx`,高 `72rpx`
|
||||
- **密码提示:** 若会议有密码,额外展示 `Password:` 标签 + 密码 pill(可点击复制)
|
||||
- **过期时间:** 小字提示 "链接 24 小时内有效"(若后端返回过期时间)
|
||||
|
||||
## Color Palette
|
||||
|
||||
| 用途 | Hex |
|
||||
|------|-----|
|
||||
| 背景 | `#FFFFFF` |
|
||||
| 选项卡片 | `#F8FAFC` |
|
||||
| 选项悬停 | `#F3F4F6` |
|
||||
| 主 CTA | `#2563EB` |
|
||||
| 文本主 | `#1E293B` |
|
||||
| 辅助文本 | `#64748B` |
|
||||
| Toast 成功 | `#10B981` |
|
||||
|
||||
## Typography
|
||||
|
||||
| 层级 | Size | Weight |
|
||||
|------|------|--------|
|
||||
| 标题 | `32rpx` | 600 |
|
||||
| 副标题 | `24rpx` | 400 |
|
||||
| 选项名 | `26rpx` | 500 |
|
||||
| 输入框 | `26rpx` | 400,`monospace` for code |
|
||||
|
||||
## Motion
|
||||
|
||||
- **打开:**
|
||||
- 桌面: 遮罩 fade-in `180ms` + 容器 `scale(0.96) → 1 + opacity 0 → 1`,`220ms cubic-bezier(0.2,0.8,0.2,1)`
|
||||
- 移动: 底部滑入 `translateY(100%) → 0`,`260ms`
|
||||
- **关闭:** 反向播放,时长 `160ms`
|
||||
- **复制成功 toast:** 顶部滑入 `translateY(-20px) → 0` 停留 `1.2s` 再滑出
|
||||
|
||||
## Interactions
|
||||
|
||||
- **复制链接:**
|
||||
- `clipboard.writeText(joinLink)` → 成功显示 toast "链接已复制";失败显示 `Modal` 文本兜底
|
||||
- 含密码的链接形如 `https://echochat.app/#/pages/meeting/join?code=123456789&token=xxx`
|
||||
- **复制会议号:**
|
||||
- 复制无密码纯 9 位数(不含分隔符)
|
||||
- **联系人选择器:**
|
||||
- 打开 `ContactPicker` 组件(复用 Phase 2a)
|
||||
- 选中后 `POST /api/v1/meeting/rooms/:code/invite` 发送邀请
|
||||
- 成功后局部 toast,选择器不关闭方便批量邀请
|
||||
- **ESC / 点击遮罩:** 关闭
|
||||
63
design-system/echochat/pages/meeting-preview.md
Normal file
63
design-system/echochat/pages/meeting-preview.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Meeting Preview (设备预览页) Page Overrides
|
||||
|
||||
> **PROJECT:** EchoChat
|
||||
> **Generated:** 2026-04-24 (via Task 15 UI 打磨)
|
||||
> **Page Type:** Full Screen — Pre-join Device Check
|
||||
> **Route:** `/pages/meeting/preview`
|
||||
|
||||
> ⚠️ Rules in this file **override** `design-system/echochat/MASTER.md`.
|
||||
|
||||
---
|
||||
|
||||
## Page Layout
|
||||
|
||||
- **结构:** 左侧大预览区(≥ 60% 宽) + 右侧设备列表 + 底部入会操作条
|
||||
- **背景:** `#0F172A`(主区)+ `#111827`(右侧设备面板)
|
||||
- **顶部导航:** 透明,仅左侧返回图标 `#F3F4F6` 24px
|
||||
|
||||
### 左侧视频预览
|
||||
|
||||
- **比例:** 16:9,最大宽度 `960px`,圆角 `16rpx`,阴影 `0 12rpx 48rpx rgba(0,0,0,0.5)`
|
||||
- **视频关闭态:** 深灰占位 `#1F2937` + 用户头像(`140rpx` 圆形) + 昵称下方
|
||||
- **音量条覆盖层(创新点):**
|
||||
- **不是分段格子**,而是**渐变波浪条**横向贯穿预览底部
|
||||
- CSS: `height: 6rpx`,`linear-gradient(90deg, #10B981 0%, #F59E0B 100%)`
|
||||
- 音量 0-1 映射为宽度 `0-100%`,`transition: width 0.05s linear`
|
||||
- 实时刷新(约 16fps 节流)
|
||||
|
||||
### 右侧设备面板(宽 `420rpx`)
|
||||
|
||||
- **分组:** 摄像头 / 麦克风 / 扬声器 三段
|
||||
- **标题:** `24rpx` 600 `#94A3B8` uppercase
|
||||
- **下拉框:** 高 `72rpx`,`#1F2937` 背景,`12rpx` 圆角,右侧箭头 `chevron-down`
|
||||
- **入会设置(折叠):** "麦克风静音入会" + "摄像头关闭入会" 两个 toggle
|
||||
|
||||
### 底部操作条
|
||||
|
||||
- **高度:** `120rpx` + safe area
|
||||
- **左侧:** 麦克风 toggle + 摄像头 toggle(圆形 `80rpx`,开=蓝 `#2563EB` 关=灰 `#374151`)
|
||||
- **右侧:** 主 CTA "进入会议" `160rpx × 72rpx`,`#2563EB → #6366F1` 渐变
|
||||
|
||||
## Color Palette (页面专属)
|
||||
|
||||
| 用途 | Hex |
|
||||
|------|-----|
|
||||
| 预览区背景 | `#0F172A` |
|
||||
| 设备面板背景 | `#111827` |
|
||||
| 下拉框面 | `#1F2937` |
|
||||
| 音量条渐变 | `#10B981 → #F59E0B` |
|
||||
| 主 CTA | `#2563EB → #6366F1` |
|
||||
| 禁用态 | `#374151` |
|
||||
|
||||
## Motion
|
||||
|
||||
- **入场:** 视频预览先于右侧面板 `80ms` 出现
|
||||
- **设备切换:** 下拉选中后预览区视频有 `200ms` 淡出 + `200ms` 淡入的 crossfade
|
||||
- **音量波浪:** 超过 0.7(大声说话)时条形底部再叠一层 `0 0 16rpx #F59E0B` glow,脱离后 `300ms` 退场
|
||||
|
||||
## Interactions
|
||||
|
||||
- **下拉切换设备:** 立即释放旧 track,重新 `getUserMedia`(带 Loading 50ms 超时后再渲染)
|
||||
- **麦/摄 toggle:** 仅切换本地 preview track 启用态,不持久化设备选择
|
||||
- **入会设置 toggle:** 保存到 `meetingStore.devicePreview.enterMuted` / `enterCamOff`
|
||||
- **点击进入会议:** 禁用状态 = 设备权限未授予时灰显
|
||||
156
design-system/echochat/pages/meeting-room.md
Normal file
156
design-system/echochat/pages/meeting-room.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# 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`: 5
|
||||
- `video-grid`: auto
|
||||
- `SelfVideoFloat`: 120
|
||||
- `MemberPanel / InviteDialog 遮罩`: 200
|
||||
- `MeetingToolbar`: 210
|
||||
- `Leave Confirm Modal`: 220
|
||||
|
||||
## 原创特色 1:说话者流光轮廓
|
||||
|
||||
**规范:**
|
||||
|
||||
```css
|
||||
.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`
|
||||
- **吸附:**
|
||||
- 释放时计算距离 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`:
|
||||
|
||||
```css
|
||||
@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-for` key + `<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 条 `#10B981`
|
||||
- `3` 良好: 2 条 `#22C55E`
|
||||
- `2` 一般: 1 条 `#F59E0B`
|
||||
- `1` 很差: 1 条短版 `#EF4444`
|
||||
- `0` 已断: 静态水平红线 + `!` 小图标
|
||||
- **动效:** `@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)`,禁用流光旋转与入会滑入,改为渐变态
|
||||
Reference in New Issue
Block a user