85 lines
3.5 KiB
Markdown
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` 事件 | 命令响应只表示服务器接受请求,不表示状态已生效 |
|