feat: 添加双屏控制功能,支持在第二块屏幕上全屏展示内容;更新相关 UI 和逻辑以适应新功能
This commit is contained in:
@@ -480,10 +480,14 @@ export default function VoiceAssistant() {
|
||||
});
|
||||
|
||||
// 手势 → 对话控制:举手 toggle —— 无对话则开始,正在对话则结束
|
||||
// 【已按需求关闭】视觉手势识别误判会触发右上角弹窗/误开对话,故这里不再响应手势。
|
||||
const onGesture = useCallback(() => {
|
||||
// 视觉手势已关闭:识别到人脸/手势不再自动开始/结束对话
|
||||
}, []);
|
||||
const onGesture = useCallback((g) => {
|
||||
if (g !== 'raise') return;
|
||||
if (clientRef.current) {
|
||||
void stop();
|
||||
} else {
|
||||
void start();
|
||||
}
|
||||
}, [start, stop]);
|
||||
|
||||
useEffect(() => {
|
||||
gestureRef.current = onGesture;
|
||||
@@ -517,7 +521,7 @@ export default function VoiceAssistant() {
|
||||
loading: '摄像头启动中…',
|
||||
detecting: `识别中 · ${vision.faces} 人${vision.faces > 0 ? `(后端 ${vision.latency ?? '-'}ms)` : ' · 未检到人脸'} · 链路${vision.modelPhase === 'ok' ? 'OK' : vision.modelPhase === 'failed' ? `失败:${(vision.modelErr || '').slice(0, 40)}` : '连接中'} · 亮度${vision.frameLum ?? '-'}${vision.detectErr ? ` · 异常:${String(vision.detectErr).slice(0, 50)}` : ''}`,
|
||||
facing: `面向大屏 ${(vision.dwellMs / 1000).toFixed(1)}s / ${VISION_DWELL_MS / 1000}s`,
|
||||
triggered: '已触发 · 主动问候',
|
||||
triggered: '已识别到访客(主动问候已关闭)',
|
||||
silent: '静默中',
|
||||
error: '摄像头不可用',
|
||||
}[vision.status] ?? '';
|
||||
@@ -629,7 +633,7 @@ export default function VoiceAssistant() {
|
||||
</span>
|
||||
<span>
|
||||
{vision.gesture === 'raise' && (
|
||||
<b style={{ color: '#2f6bff' }}>您好呀 · {live ? '开始对话' : '结束对话'}</b>
|
||||
<b style={{ color: '#2f6bff' }}>{live ? '开始对话' : '结束对话'}</b>
|
||||
)}
|
||||
{visionStatusText}
|
||||
</span>
|
||||
|
||||
@@ -5,6 +5,13 @@ import { MQTT_TOPIC_HEARTBEAT } from '../config';
|
||||
import { Sfx } from './sounds';
|
||||
import { PAGE_ORDER } from './pageNav';
|
||||
import { aiStatus } from './statusBus';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
|
||||
// 当前窗口标识:主屏 'main' / 双屏副窗 'secondary'(浏览器开发环境回退 'main')
|
||||
const WINDOW_LABEL = (() => {
|
||||
try { return getCurrentWindow().label || 'main'; } catch { return 'main'; }
|
||||
})();
|
||||
|
||||
/* =========================================================
|
||||
MQTT 控制 —— 后端通过 opc/display/command 控制大屏
|
||||
@@ -69,6 +76,9 @@ export function useMqttControl() {
|
||||
connectMqtt();
|
||||
const off = onMqttMessage((topic, cmd) => {
|
||||
if (topic !== 'opc/display/command' || !cmd || !cmd.action) return;
|
||||
// 双屏独立控制:cmd.screen = main|secondary|both(缺省视为 both)
|
||||
const sc = cmd.screen;
|
||||
if (sc && sc !== 'both' && sc !== WINDOW_LABEL) return;
|
||||
|
||||
switch (cmd.action) {
|
||||
case 'navigate': {
|
||||
@@ -86,6 +96,12 @@ export function useMqttControl() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'dual_screen':
|
||||
// 双屏:admin 控制第二块屏全屏展示(Tauri 命令)——仅主窗口执行
|
||||
if (WINDOW_LABEL !== 'main') break;
|
||||
aiStatus(cmd.params?.on === false ? '正在关闭双屏' : '正在启动双屏', { icon: 'page' });
|
||||
invoke('set_dual_screen', { on: cmd.params?.on !== false }).catch(() => {});
|
||||
break;
|
||||
case 'alert':
|
||||
// 通知本身即展示,无需再弹「正在发送通知」状态提示
|
||||
window.dispatchEvent(new CustomEvent('dpm:alert', { detail: cmd.params || {} }));
|
||||
|
||||
Reference in New Issue
Block a user