feat: 语音气泡浅蓝 + 页眉图标展示全部视觉状态 + 简化自动问候

- /voice 页右下角气泡文本改浅蓝色(最新 #4cc2ff / 历史 #6fb5ea)
- GlobalVision 广播 dpm:vision-status(status/cameraOn/gesture/faces)
- 页眉图标四态:默认灰(探索) → 识别中浅蓝(摄像头开/检测/面向) → 手势绿(惊喜) → 异常红
- 自动调用语音助手问候语简化为「您好呀,需要我的帮助吗?」
This commit is contained in:
Pine
2026-08-18 06:24:26 +08:00
parent 75498027f3
commit fbf2eccad2
5 changed files with 49 additions and 7 deletions
+15 -3
View File
@@ -24,6 +24,7 @@ export default function PageHeader() {
const [now, setNow] = useState(new Date());
const [aboutOpen, setAboutOpen] = useState(false);
const [gestureHit, setGestureHit] = useState(false); // 识别到手势 → 惊喜图标 3s
const [vision, setVision] = useState({ status: 'off', cameraOn: false, gesture: null }); // 视觉识别状态
const pageIdx = usePageIndex();
const gestureTimer = useRef(null);
@@ -32,7 +33,7 @@ export default function PageHeader() {
return () => clearInterval(iv);
}, []);
// 全局手势事件 → 右上角状态图标(默认灰色探索 → 识别到手势变绿色惊喜)
// 全局手势事件 → 惊喜图标 3s
useEffect(() => {
const onGesture = (e) => {
if (!e.detail || !e.detail.type) return;
@@ -47,6 +48,17 @@ export default function PageHeader() {
};
}, []);
// 视觉识别状态(GlobalVision 广播):off/loading/detecting/facing/triggered/silent/error
useEffect(() => {
const onStatus = (e) => setVision(e.detail || {});
window.addEventListener('dpm:vision-status', onStatus);
return () => window.removeEventListener('dpm:vision-status', onStatus);
}, []);
// 图标状态:手势(绿) > 视觉识别中(浅蓝) > 默认(灰)
const visionActive = vision.cameraOn && vision.status !== 'error' && vision.status !== 'off';
const visionError = vision.status === 'error';
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
const week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
const timeStr = now.toLocaleTimeString('zh-CN', { hour12: false });
@@ -101,9 +113,9 @@ export default function PageHeader() {
{status}
</div>
<button
className={`bd-about-btn${gestureHit ? ' gesture-hit' : ''}`}
className={`bd-about-btn${gestureHit ? ' gesture-hit' : visionActive ? ' vision-active' : visionError ? ' vision-error' : ''}`}
type="button"
title={gestureHit ? '识别到手势' : '关于 PineSound'}
title={gestureHit ? '识别到手势' : visionActive ? `视觉识别中(${vision.status})` : visionError ? '视觉识别异常' : '关于 PineSound'}
aria-label="关于 PineSound"
onClick={() => setAboutOpen(true)}
>