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

3.5 KiB

切换频道

用户流程:选择目标频道 → (频道有密码时输入密码) → 发送切换请求 → 等待服务端确认 → 进入目标频道 对应程序流程:TsClient.clientMove(selfID, targetID, password) → 等待 onClientMoved 服务端事实 → 比对 clientID → 提交新频道


一、时序:当前用户切换频道

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 匹配目标频道和请求上下文 命令响应不能直接提交频道

命令响应与事件事实的区别

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