Files
ts-mobile-go/docs/UI架构设计.md
T

630 lines
29 KiB
Markdown
Raw Permalink Normal View History

2026-07-20 19:01:03 +08:00
# UI 架构设计
> 依据:`docs/流程/00_总览.md` 及 `docs/流程/01~08` 各流程文件
> 范围:页面布局、卡片设计、全局交互、状态处理、流程映射
---
## 一、架构总览
### 1.1 整体结构:3 页 3 卡
```
页面(Page) 卡片(Card
┌─────────────────────┐ ┌─────────────────────┐
│ 服务器配置页 │ │ 服务器详情卡 │
│ ServerConfigPage │ │ ServerDetailCard │
├─────────────────────┤ │ (底部弹出) │
│ 频道列表页 │ ├─────────────────────┤
│ ChannelListPage │ │ 频道详情卡 │
├─────────────────────┤ │ ChannelDetailCard │
│ 聊天页 │ │ (底部弹出) │
│ ChatPage │ ├─────────────────────┤
└─────────────────────┘ │ 语音卡 │
│ VoiceCard │
│ (底部弹出) │
└─────────────────────┘
```
### 1.2 页面导航关系
```
┌──────────────────────┐
│ 服务器配置页 │
│ (应用启动首屏) │
└──────────┬───────────┘
│ 连接成功
┌──────────────────────┐
┌────→│ 频道列表页 │──────┐
│ │ (主页面) │ │
│ └──────────────────────┘ │
│ │ │
│ │ 点击"中部-底部"当前频道 │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ 聊天页 │ │
│ │ (当前频道消息) │ │
│ └──────────┬───────────┘ │
│ │ 返回按钮 │
└────────────────┘ │
┌───────────────────────────────────┘
│ 头部左侧按钮
服务器详情卡(弹出)
频道列表页 / 聊天页
│ 头部右侧按钮
频道详情卡(弹出)
任意页面(服务器配置页除外)
│ 底部语音控制区 "展开" 按钮
语音卡(弹出)
```
### 1.3 卡片弹出规则
| 卡片 | 可弹出页面 | 弹出方式 | 关闭方式 |
| --- | --- | --- | --- |
| 服务器详情卡 | 频道列表页 | 底部弹出(BottomSheet) | 点击外部 / 下滑 / 断开后自动关闭 |
| 频道详情卡 | 频道列表页、聊天页 | 底部弹出(BottomSheet | 点击外部 / 下滑 |
| 语音卡 | 频道列表页、聊天页 | 底部弹出(BottomSheet),可拖拽为半屏 | 点击外部 / 下滑 / 点击展开按钮 |
---
## 二、页面详细设计
### 2.1 服务器配置页
> 对应流程:01 连接服务器
#### 布局
```
┌──────────────────────────────┐
│ 上:品牌区 │
│ [Logo] │
│ TeamSpeak Mobile │
│ 连接到你的 TeamSpeak 服务器 │
│ [🌙 主题] │ ← 右上角主题切换图标
├──────────────────────────────┤
│ 中:输入区 │
│ │
│ 服务器地址 │
│ ┌──────────────────────────┐│
│ │ ts.example.com ││
│ └──────────────────────────┘│
│ │
│ 昵称 │
│ ┌──────────────────────────┐│
│ │ 我的昵称 ││
│ └──────────────────────────┘│
│ │
│ 密码(可选) │
│ ┌──────────────────────────┐│
│ │ •••••• ││
│ └──────────────────────────┘│
│ │
│ ┌──────────────────────────┐│
│ │ 连接服务器 ││ ← 按钮状态见 5.1
│ └──────────────────────────┘│
├──────────────────────────────┤
│ 下:最近连接 │
│ │
│ 最近连接 │
│ ┌──────────────────────────┐│
│ │ 🟢 ts.myserver.com ││ ← 点击快速连接
│ │ 上次连接:2小时前 ││
│ ├──────────────────────────┤│
│ │ 🔴 ts.other.com ││
│ │ 上次连接:昨天 ││
│ └──────────────────────────┘│
│ │
│ [清空最近记录] │ ← 长按或编辑模式删除单条
└──────────────────────────────┘
```
#### 三段式结构说明
| 段落 | 内容 | 说明 |
| --- | --- | --- |
| 上(品牌区) | Logo + 描述文本 + 主题切换 | 仅展示,不可交互(主题图标除外) |
| 中(输入区) | 地址/昵称/密码输入 + 连接按钮 | 核心交互区,连接成功跳转频道列表页 |
| 下(最近连接) | 历史服务器列表 | 点击直接快速连接(复用已保存的昵称和密码) |
#### 输入验证规则
| 字段 | 必填 | 验证规则 | 错误提示 |
| --- | --- | --- | --- |
| 服务器地址 | 是 | 非空,格式合法(域名/IP/TSDNS) | "请输入有效的服务器地址" |
| 昵称 | 是 | 非空,满足服务器命名规则 | "请输入昵称" |
| 密码 | 否 | 仅当服务器需要密码时必填 | "该服务器需要密码" |
#### 最近连接列表
- 点击列表项 → 自动填充地址/昵称/密码 → 触发连接
- 最多保存 10 条历史记录
- 按最近连接时间倒序排列
- 连接成功的服务器标记为绿色,失败的标记为红色(短暂)
- 长按可删除单条记录
---
### 2.2 频道列表页
> 对应流程:02 浏览频道 + 03 切换频道 + 08 状态同步
#### 布局
```
┌──────────────────────────────────────┐
│ 头部(三段) │
│ ┌────┐ ┌──────────────────┐ ┌─────┐ │
│ │ ☰ │ │ MyServer │ │ 🟢 │ │
│ │服务│ │ 192.168.1.1:9987 │ │连接 │ │ ← 连接状态指示
│ │器卡│ │ 42人在线 │ │状态 │ │
│ └────┘ └──────────────────┘ └─────┘ │
├──────────────────────────────────────┤
│ 中部:频道树 + 成员 │
│ │
│ ▼ 📁 默认频道 │ ← 展开/折叠
│ ▼ 📁 大厅 │
│ 👤 Alice │ ← 点击弹出成员操作菜单
│ 👤 Bob 🔇 │ ← 🔇 = 正在发言
│ 👤 Charlie 🎤 │ ← 🎤 = 正在发言
│ ▶ 📁 游戏区 🔒 │ ← 🔒 = 有密码
│ (3人) │ ← 折叠时显示人数
│ ▶ 📁 音乐区 │
│ (1人) │
│ ▼ 📁 VIP 频道 🔒 │
│ 👤 Admin │
│ │
│ (频道列表支持滚动) │
├──────────────────────────────────────┤
│ 中部-底部:当前频道栏 │
│ ┌──────────────────────────────────┐ │
│ │ 💬 大厅 (5人) Alice🎤 Bob │ │ ← 点击跳转到聊天页
│ └──────────────────────────────────┘ │
├──────────────────────────────────────┤
│ 底部:语音控制 │
│ ┌──────┐ ┌────────────────┐ ┌─────┐ │
│ │ 🎤 │ │ PTT 按住发言 │ │ ⬆ │ │
│ │静音 │ │ │ │语音 │ │ ← 展开语音卡
│ └──────┘ └────────────────┘ └─────┘ │
└──────────────────────────────────────┘
```
#### 频道树交互
| 操作 | 行为 |
| --- | --- |
| 点击频道名 | 无密码 → 直接切换(发送 ClientMove |
| 点击有密码频道 🔒 | 弹出频道密码对话框(见 4.2) |
| 点击折叠频道 ▶ | 展开显示子频道 |
| 点击展开频道 ▼ | 折叠子频道 |
| 长按频道 | 弹出频道操作菜单(频道信息) |
| 点击成员 👤 | 弹出成员操作菜单(见 4.3) |
| 点击当前频道栏 | 跳转到聊天页 |
#### 未读消息指示
| 状态 | 显示 | 说明 |
| --- | --- | --- |
| 无未读 | 正常显示 | — |
| 有未读消息 | 频道名右侧显示红点 ● | 弱未读提示 |
| 有未读 @提及 | 频道名右侧显示数字 badge | 强未读提示 |
| 当前所在频道 | 不显示未读标记 | 已在该频道 |
#### 初始同步加载态
连接成功进入频道列表页时,如果首次同步尚未完成:
```
┌──────────────────────────────┐
│ 头部(正常) │
├──────────────────────────────┤
│ │
│ ⟳ 正在同步服务器数据... │ ← 居中加载指示器
│ │
├──────────────────────────────┤
│ 底部(正常) │
└──────────────────────────────┘
```
同步完成后自动切换为正常频道树视图。
---
### 2.3 聊天页
> 对应流程:04 文本消息
#### 布局
```
┌──────────────────────────────────────┐
│ 头部 │
│ ┌────┐ ┌──────────────────┐ ┌─────┐ │
│ │ ← │ │ 大厅 │ │ ⋮ │ │
│ │返回│ │ 5人 │ │频道 │ │ ← 右侧弹出频道详情卡
│ │ │ │ │ │详情 │ │
│ └────┘ └──────────────────┘ └─────┘ │
├──────────────────────────────────────┤
│ 中部:消息列表 │
│ │
│ ┌──────────────────────────────────┐ │
│ │ Alice 14:30 │ │
│ │ 大家好! │ │
│ ├──────────────────────────────────┤ │
│ │ Bob 14:31 │ │
│ │ 你好 Alice! │ │
│ ├──────────────────────────────────┤ │
│ │ Charlie 14:32 │ │
│ │ 有人一起打游戏吗? │ │
│ ├──────────────────────────────────┤ │
│ │ 我 14:33 │ │
│ │ 我来! │ │ ← 自己的消息靠右 / 不同颜色
│ └──────────────────────────────────┘ │
│ │
│ (消息列表支持滚动,新消息自动滚到底) │
├──────────────────────────────────────┤
│ 中部-底部:消息输入区 │
│ ┌──────────────────────────┐ ┌────┐ │
│ │ 输入消息... │ │ 发送│ │ ← 随输入法上抬
│ └──────────────────────────┘ └────┘ │
├──────────────────────────────────────┤
│ 底部:语音控制 │
│ ┌──────┐ ┌────────────────┐ ┌─────┐ │
│ │ 🎤 │ │ PTT 按住发言 │ │ ⬆ │ │
│ │静音 │ │ │ │语音 │ │
│ └──────┘ └────────────────┘ └─────┘ │
└──────────────────────────────────────┘
```
#### 消息显示格式
```
发送者名称 发送时间
消息内容
```
- 自己的消息靠右对齐或使用不同背景色区分
- 支持长按消息弹出操作菜单(复制 / Poke 发送者)
- 新消息到达时自动滚动到底部
- 如果用户正在查看历史消息,新消息到达时显示 "↓ 新消息" 提示条
#### 消息输入区与键盘联动
- 点击输入框 → 唤起输入法 → 输入区 + 发送按钮随键盘上抬
- 语音控制栏保持固定在底部,不受键盘影响
- 发送消息后输入框清空,保持键盘打开状态
- 输入框为空时发送按钮置灰不可点击
---
## 三、卡片详细设计
### 3.1 服务器详情卡
> 弹出方式:频道列表页头部左侧按钮触发,底部弹出 BottomSheet
```
┌──────────────────────────────┐
│ 服务器详情 ✕ │
├──────────────────────────────┤
│ │
│ 服务器名 │
│ My TeamSpeak Server │
│ │
│ 服务器地址 │
│ 192.168.1.1:9987 │
│ │
│ 在线人数 │
│ 42 / 100 │
│ │
│ ┌──────────────────────────┐│
│ │ 断开服务器 ││ ← 确认弹窗后执行 Disconnect
│ └──────────────────────────┘│
│ │
└──────────────────────────────┘
```
#### 行为
- 断开服务器 → 弹出确认对话框 "确定要断开连接吗?" → 确认后执行断开 → 关闭卡片 → 返回服务器配置页
- 卡片数据来自首次同步结果和实时事件更新
---
### 3.2 频道详情卡
> 弹出方式:聊天页头部右侧按钮触发,底部弹出 BottomSheet
```
┌──────────────────────────────┐
│ 频道详情 ✕ │
├──────────────────────────────┤
│ │
│ 频道名 │
│ 大厅 │
│ │
│ 频道描述 │
│ 欢迎来到大厅频道,请遵守规则 │
│ │
│ 频道人数 │
│ 5人 │
│ │
└──────────────────────────────┘
```
#### 行为
- 如果频道无描述,显示 "暂无描述"
- 有密码频道在频道名旁显示 🔒 图标
---
### 3.3 语音卡
> 弹出方式:频道列表页 / 聊天页底部语音控制区 "展开" 按钮
> 激活时机:进入频道后即激活,除服务器配置页外任意页面可弹出
```
┌──────────────────────────────┐
│ 语音控制 ✕ │
├──────────────────────────────┤
│ │
│ 正在发言 │
│ ┌──────────────────────────┐│
│ │ 🎤 Charlie ▓▓▓▓░░ -12dB││ ← 音量波形指示
│ │ 🎤 Alice ▓▓░░░░ -24dB││
│ └──────────────────────────┘│
│ (无人在发言时显示 "暂无发言")│
│ │
├──────────────────────────────┤
│ │
│ 频道内人员 (5) │
│ ┌──────────────────────────┐│
│ │ 👤 Alice ││ ← 长按弹出操作菜单(Poke)
│ │ 👤 Bob ││
│ │ 👤 Charlie 🎤 发言中 ││ ← 发言中高亮
│ │ 👤 David ││
│ │ 👤 Eve ││
│ └──────────────────────────┘│
│ (人员超出时可滚动) │
│ │
├──────────────────────────────┤
│ 控制 │
│ ┌──────────┐ ┌──────────────┐│
│ │ 🔊 扬声器 │ │ 🎙️ 降噪 ││
│ │ 开 / 关 │ │ 开 / 关 ││
│ └──────────┘ └──────────────┘│
│ │
└──────────────────────────────┘
```
#### 行为
- 发言人栏实时显示正在发送语音帧的成员,附带音量波形指示
- 频道内人员列表支持滚动
- 长按成员 → 弹出操作菜单(Poke)
- 扬声器控制:切换本地音频输出开/关
- 降噪控制:切换本地降噪算法开/关
---
## 四、全局交互
### 4.1 Poke 交互
> 对应流程:02 浏览频道中的 "poke 服务器内成员" 和 "被 poke"
#### 发送 Poke
| 入口 | 操作 |
| --- | --- |
| 频道列表页成员列表 | 长按成员 → 弹出菜单 → Poke |
| 语音卡成员列表 | 长按成员 → 弹出菜单 → Poke |
| 聊天页消息列表 | 长按消息 → 弹出菜单 → Poke 发送者 |
发送后调用 SDK 的 Poke 方法,无需等待服务端确认。
#### 接收 Poke 通知
收到 `OnPoked` 事件时:
```
┌──────────────────────────────┐
│ ┌──────────────────────────┐ │
│ │ 🫴 Alice poke 了你 │ │ ← 顶部 Toast,3秒自动消失
│ │ "起床啦!" │ │
│ └──────────────────────────┘ │
└──────────────────────────────┘
```
- Toast 从顶部滑入,3 秒后自动消失
- 如果在聊天页收到 Poke,同样显示 Toast(不自动跳转)
---
### 4.2 频道密码弹窗
> 对应流程:03 切换频道中的密码检查分支
点击有密码频道 🔒 时弹出:
```
┌──────────────────────────────┐
│ │
│ 该频道需要密码 │
│ │
│ ┌────────────────────────┐ │
│ │ 输入频道密码 │ │
│ └────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 取消 │ │ 进入 │ │
│ └──────────┘ └──────────┘ │
│ │
└──────────────────────────────┘
```
- 密码错误 → 按钮变为 "密码错误,重试" → 清空输入框 → 允许重新输入
- 点击取消 → 关闭弹窗,不发送 ClientMove
- 点击进入 → 发送 `ClientMove(selfID, targetID, password)`
---
### 4.3 成员点击行为
在频道列表页和语音卡中,点击/长按成员时弹出操作菜单:
```
┌──────────────────────────────┐
│ 👤 Alice │
│ 频道:大厅 │
├──────────────────────────────┤
│ 🫴 Poke │ → 发送 Poke
│ 📋 复制昵称 │ → 复制到剪贴板
└──────────────────────────────┘
```
---
### 4.4 主题切换
- 入口位置:服务器配置页右上角 🌙 图标
- 切换方式:点击在亮色/暗色主题间切换
- 持久化:选择保存到本地配置,下次启动自动应用
- 影响范围:全局所有页面和卡片
---
## 五、状态处理
### 5.1 连接状态
> 对应流程:01 连接服务器
#### 服务器配置页按钮状态
| 状态 | 按钮外观 | 说明 |
| --- | --- | --- |
| 空闲 | "连接服务器"(正常样式) | 等待用户输入并点击 |
| 连接中 | ⟳ "连接中..."(加载动画 + 禁用) | Connect + WaitConnected 进行中 |
| 连接失败 | "连接失败,点击重试"(红色 + 错误信息) | 显示具体失败原因(密码错误/超时/网络不可达) |
| 超时 | "连接超时,点击重试"(橙色) | WaitConnected 超时 |
#### 错误信息分类
| 错误类型 | 提示信息 | 建议操作 |
| --- | --- | --- |
| 密码错误 | "服务器密码错误" | 重新输入密码 |
| 昵称冲突 | "昵称已被使用,请更换" | 修改昵称 |
| 网络不可达 | "无法连接到服务器,请检查网络" | 检查网络后重试 |
| 地址无效 | "服务器地址无法解析" | 检查地址格式 |
| 超时 | "连接超时" | 检查网络后重试 |
| 服务器满 | "服务器已满" | 稍后重试 |
---
### 5.2 初始同步加载态
> 对应流程:08 状态同步 ① 首次同步
连接成功后进入频道列表页,首次同步期间:
- 频道树区域显示居中加载指示器 + "正在同步服务器数据..."
- 头部正常显示(但在线人数可能显示为 "--"
- 底部语音控制区正常显示
- 同步完成后自动切换到正常频道树视图
- 同步失败 → 显示 "同步失败" + 重试按钮
---
### 5.3 被踢处理
> 对应流程:07 断开连接
被服务器踢出时(`OnKicked` 触发):
```
┌──────────────────────────────┐
│ │
│ 你已被踢出 │
│ │
│ 原因:违反服务器规则 │ ← 显示踢出原因
│ │
│ ┌────────────────────┐ │
│ │ 重新连接 │ │
│ └────────────────────┘ │
│ │
│ ┌────────────────────┐ │
│ │ 返回主页 │ │
│ └────────────────────┘ │
│ │
└──────────────────────────────┘
```
- 全屏覆盖提示,不可通过点击外部关闭
- "重新连接" → 使用相同参数重新连接
- "返回主页" → 回到服务器配置页
- 清理当前会话状态(频道、成员、消息)
---
### 5.4 断线重连
> 对应流程:07 断开连接
网络异常断开时(`OnDisconnected(error)` 触发):
```
┌──────────────────────────────────────┐
│ ┌──────────────────────────────────┐ │
│ │ ⚠️ 连接已断开 │ │ ← 顶部横幅
│ │ 正在尝试重连... (3/5) │ │ ← 自动重连尝试计数
│ │ [手动重连] [放弃] │ │
│ └──────────────────────────────────┘ │
└──────────────────────────────────────┘
```
- 顶部横幅提示,不阻塞底层页面(页面数据冻结)
- 自动重连:最多尝试 5 次,间隔递增(2s → 4s → 8s → 16s → 30s
- 手动重连:用户主动触发立即重连
- 放弃:停止重连 → 显示完整断线提示(类似被踢处理) → 返回主页
- 重连成功 → 执行全量同步(08 状态同步 ⑥)→ 横幅消失 → 恢复正常
---
### 5.5 未读消息指示
> 对应流程:04 文本消息
#### 频道列表页
| 场景 | 显示 | 说明 |
| --- | --- | --- |
| 频道有新消息 | 频道名右侧显示红点 ● | 弱未读(用户不在该频道时) |
| 频道有 @提及 | 频道名右侧显示数字(如 3) | 强未读 |
| 当前所在频道 | 不显示 | 已在该频道,消息直接可见 |
| 用户进入频道后 | 清除该频道的未读标记 | 已读即清 |
---
## 六、页面与流程的对应关系
| 流程文件 | 主要承载页面 | 承载卡片 | 关键交互 |
| --- | --- | --- | --- |
| 01 连接服务器 | 服务器配置页 | — | 输入验证、连接按钮状态、最近连接快速连接 |
| 02 浏览频道 | 频道列表页 | 语音卡 | 频道树展开/折叠、成员列表、Poke、未读指示 |
| 03 切换频道 | 频道列表页 | — | 点击频道切换、密码弹窗、ClientMove 等待确认 |
| 04 文本消息 | 聊天页 | — | 消息列表、发送消息、未读归档 |
| 05 语音通信 | 频道列表页 + 聊天页 | 语音卡 | PTT 按钮、静音控制、发言人指示 |
| 06 文件传输 | — | — | 本应用不实现 |
| 07 断开连接 | 全屏覆盖 | 服务器详情卡 | 断开确认、被踢提示、断线重连横幅 |
| 08 状态同步 | 所有页面 | — | 首次同步加载、增量更新、补偿同步、重连全量同步 |