# 切换频道 > 用户流程:选择目标频道 → (频道有密码时输入密码) → 发送切换请求 → 等待服务端确认 → 进入目标频道 > 对应程序流程:TsClient.clientMove(selfID, targetID, password) → 等待 onClientMoved 服务端事实 → 比对 clientID → 提交新频道 --- ## 一、时序:当前用户切换频道 ```mermaid sequenceDiagram participant UI as 频道选择 UI
表达用户切换意图 participant FSM as 切换状态机
管理确认、请求和等待事实 participant BRIDGE as TSBridge
调用 TsClient API participant SDK as Go SDK (gomobile)
发送 ClientMove 命令 participant TS as TeamSpeak 服务器
验证权限、密码并执行移动 participant EVT as EventBus
处理 ClientMoved 服务端事实 participant STORE as 当前用户状态
保存已确认频道 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[用户意图
例如发送消息或切换频道] --> COMMAND[客户端请求
调用 SDK 命令方法] COMMAND --> RESPONSE{命令响应
判断服务器是否接受请求} RESPONSE -- 失败 --> FAILED[请求失败
保留原事实并展示原因] RESPONSE -- 成功 --> WAITFACT[等待事实事件
仅对存在对应推送的操作适用] WAITFACT --> EVENT[服务端推送事件
例如 OnClientMoved 或 OnTextMessage] EVENT --> COMMIT[提交服务器事实
更新频道位置或消息实体] RESPONSE -- 无对应事实事件 --> LOCALDONE[完成本次调用
仅记录调用结果而不猜测远端效果] ``` **关键区分:** - `TsClient.clientMove` 返回成功:命令执行成功;当前用户频道应由自己的 `onClientMoved` 最终确认。 - 命令成功 ≠ 状态已提交。必须等待服务端推送的 `onClientMoved` 事件才能更新本地频道事实。 ### 权威性划分 | 数据 | 推荐权威来源 | 原因 | | --- | --- | --- | | 当前用户频道 | 自己的 `onClientMoved` 事件 | 命令响应只表示服务器接受请求,不表示状态已生效 |