# 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 状态同步 | 所有页面 | — | 首次同步加载、增量更新、补偿同步、重连全量同步 |