import { ref, watch } from 'vue'; function storageKey(pageKey: string) { return `oms.operation.voiceBroadcast.${pageKey}`; } function pickChineseVoice(): SpeechSynthesisVoice | undefined { const voices = window.speechSynthesis?.getVoices?.() ?? []; return ( voices.find((v) => v.lang === 'zh-CN') || voices.find((v) => v.lang.startsWith('zh')) || voices[0] ); } /** * 操作扫描页语音播报(Web Speech API)。 */ export function useOperationVoiceBroadcast(pageKey: string) { const voiceEnabled = ref(true); try { const stored = localStorage.getItem(storageKey(pageKey)); if (stored != null) voiceEnabled.value = stored === '1'; } catch { /* ignore */ } watch(voiceEnabled, (v) => { try { localStorage.setItem(storageKey(pageKey), v ? '1' : '0'); } catch { /* ignore */ } if (!v) { window.speechSynthesis?.cancel?.(); } }); if (typeof window !== 'undefined' && window.speechSynthesis) { window.speechSynthesis.onvoiceschanged = () => { pickChineseVoice(); }; } function speak(text: string) { const content = text?.trim(); if (!voiceEnabled.value || !content || typeof window === 'undefined') return; if (!('speechSynthesis' in window)) return; window.speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(content); utterance.lang = 'zh-CN'; utterance.rate = 1.05; utterance.pitch = 1; const voice = pickChineseVoice(); if (voice) utterance.voice = voice; window.speechSynthesis.speak(utterance); } function stopSpeak() { window.speechSynthesis?.cancel?.(); } return { voiceEnabled, speak, stopSpeak }; }