Files
2026-07-20 19:01:03 +08:00

85 lines
3.5 KiB
Markdown

# 切换频道
> 用户流程:选择目标频道 → (频道有密码时输入密码) → 发送切换请求 → 等待服务端确认 → 进入目标频道
> 对应程序流程:TsClient.clientMove(selfID, targetID, password) → 等待 onClientMoved 服务端事实 → 比对 clientID → 提交新频道
---
## 一、时序:当前用户切换频道
```mermaid
sequenceDiagram
participant UI as 频道选择 UI<br/>表达用户切换意图
participant FSM as 切换状态机<br/>管理确认、请求和等待事实
participant BRIDGE as TSBridge<br/>调用 TsClient API
participant SDK as Go SDK (gomobile)<br/>发送 ClientMove 命令
participant TS as TeamSpeak 服务器<br/>验证权限、密码并执行移动
participant EVT as EventBus<br/>处理 ClientMoved 服务端事实
participant STORE as 当前用户状态<br/>保存已确认频道
UI->>FSM: ChannelJoinRequested(targetID)
FSM->>STORE: 读取 confirmedChannelID
FSM-->>UI: 显示确认或密码输入
UI->>FSM: ChannelJoinConfirmed(password)
FSM->>FSM: 状态改为 requesting
FSM->>BRIDGE: clientMove(selfID, targetID, password)
BRIDGE->>SDK: gomobile ClientMove
SDK->>TS: clientmove
alt 命令被服务器拒绝
TS-->>SDK: error
SDK-->>BRIDGE: 命令失败
BRIDGE-->>FSM: 返回错误
FSM->>FSM: 状态改为 failed
FSM-->>UI: 显示失败原因
else 命令请求成功
TS-->>SDK: command ok
SDK-->>BRIDGE: 命令成功
BRIDGE-->>FSM: 返回成功(不代表状态已提交)
FSM->>FSM: 状态改为 waitingServerEvent
TS-->>SDK: notifyclientmoved
SDK->>EVT: onClientMoved(TsClientMoved)
EVT->>STORE: 比对 clientID == selfID
EVT->>STORE: 提交 channelID = targetID
STORE-->>FSM: SelfMoved(targetID)
FSM->>FSM: 状态恢复 idle
FSM-->>UI: 导航到目标房间
end
```
---
## 二、事件依赖
### 频道切换前置依赖矩阵
| 操作或事件 | 必须依赖 | 建议依赖 | 依赖失败时的处理 |
| --- | --- | --- | --- |
| `TsClient.clientMove` | 已连接、目标频道 ID、目标客户端 ID | 已同步频道和成员 | 命令失败保留原频道事实 |
| 提交自己新频道 | 自己的 `onClientMoved` | 匹配目标频道和请求上下文 | 命令响应不能直接提交频道 |
### 命令响应与事件事实的区别
```mermaid
flowchart LR
INTENT[用户意图<br/>例如发送消息或切换频道] --> COMMAND[客户端请求<br/>调用 SDK 命令方法]
COMMAND --> RESPONSE{命令响应<br/>判断服务器是否接受请求}
RESPONSE -- 失败 --> FAILED[请求失败<br/>保留原事实并展示原因]
RESPONSE -- 成功 --> WAITFACT[等待事实事件<br/>仅对存在对应推送的操作适用]
WAITFACT --> EVENT[服务端推送事件<br/>例如 OnClientMoved 或 OnTextMessage]
EVENT --> COMMIT[提交服务器事实<br/>更新频道位置或消息实体]
RESPONSE -- 无对应事实事件 --> LOCALDONE[完成本次调用<br/>仅记录调用结果而不猜测远端效果]
```
**关键区分:**
- `TsClient.clientMove` 返回成功:命令执行成功;当前用户频道应由自己的 `onClientMoved` 最终确认。
- 命令成功 ≠ 状态已提交。必须等待服务端推送的 `onClientMoved` 事件才能更新本地频道事实。
### 权威性划分
| 数据 | 推荐权威来源 | 原因 |
| --- | --- | --- |
| 当前用户频道 | 自己的 `onClientMoved` 事件 | 命令响应只表示服务器接受请求,不表示状态已生效 |