外观
移动端与大屏交互
本节说明移动端如何与大屏配对、建立长连接,以及提问/回答的完整链路。
一、移动端配对(ScanPair.vue)
- 扫码自动配对:
onMounted时同时兼容 history 模式(?code=在search)与 hash 模式(#/mobile?code=在hash); - 手动输入:12 位上限,回车提交;
- 错误分型:
invalid(码错误/无效/不存在)、expired(过期)、network(网络/连接)、validation(未输入),各自配不同图标、配色与处理建议;invalid/expired提供"重新配对"按钮; - 自动配对失败会
replaceState清掉 URL 上的 code,避免刷新后反复用失效码触发连接而一直转圈; - 配对超时保护 5 分钟(
usePairing)。
大屏侧的配对码生成与设备管理见 配对码功能。
二、WebSocket 通道
{ws|wss}://{VITE_AI_APP_HOST}/ws/digital-human
?clientType=screen|mobile&clientId=xxx[&pairingCode=xxx]- 协议随页面协议自动切换(https → wss);
- 心跳 30 秒 一次
HEARTBEAT_REQ; - 大屏端断线指数退避自动重连:最多 5 次,延迟
min(1000 × 2^n, 30000)ms。
消息类型:
| type | 方向 | 说明 |
|---|---|---|
SCREEN_REGISTER | 后端 → 大屏 | 下发屏幕端 clientId |
PAIRING_SUCCESS | 后端 → 双端 | 携带 { deviceIp, deviceName, userAgent, pairedAt } |
PAIRING_FAIL | 后端 → 手机 | 断开并提示原因 |
COMMAND | 手机 → 大屏 | { text, type: 'text'|'voice', mode, knowledgeCategory? } |
RESPONSE | 大屏 → 手机 | 字符串 / { text } / { error } / { text, subtype:'search', searchResult } |
DISCONNECT | 后端 → 双端 | 携带原因 |
KICKED | 后端 → 手机 | 被大屏踢出,弹提示后 store.reset() 回到扫码页 |
HEARTBEAT_REQ / HEARTBEAT_RESP | 双向 | 保活 |
模式同步采用 piggyback:移动端不发送独立的 MODE_CHANGE 消息,而是把 mode 挂在 COMMAND 载荷里,大屏收到后先 setMode 再处理。
三、移动端遥控面板(RemotePanel.vue)
仿微信对话布局,MobileEntry.vue 在 isPaired && isConnected 时切换到面板,否则显示扫码页。
- 顶部:连接状态灯 + 模式切换下拉(智能交互 / 专家问答 / 系统导览)+ 断开连接(二次确认);
- 消息区:AI Markdown 气泡 / 用户气泡 / 系统提示 + "大屏回复中…"等待气泡,消息与等待态变化均自动滚底;
- 底部
ChatInputBar:文本输入(500 字上限,回车发送)/ 按住说话,错误以 toast 层展示; - 右下角 Fab + 左侧抽屉,两种形态:
- 系统导览 → "演示问题"抽屉(复用大屏端
demoList,点击即发送); - 智能交互 / 专家问答 → "猜你想问"(支持换一批)/ "选择知识库"抽屉;
- 系统导览 → "演示问题"抽屉(复用大屏端
- 三种模式均显示输入栏(系统导览支持自由输入,与大屏端行为对齐);
- 切出系统导览自动关闭演示抽屉,切到系统导览自动关闭猜你想问抽屉;
- 高度使用
100dvh兼容移动端地址栏伸缩,顶部/底部预留env(safe-area-inset-*)安全区。
四、移动端问答链路
手机 COMMAND → 大屏 handleMobileCommand → 按当前模式走 interactive / expert / demo 分支 → 大屏渲染回答并 TTS 播报 → RESPONSE 回推手机渲染。系统导览的自定义问题不重复走内置问答,回复由 NLU 回调通过 resolveMobileDemoAnswer 回传。
实现位置:移动端指令处理、
RESPONSE回推与配对相关逻辑都在core/connection.js(拆分前位于useAssistantCore.js)。