2026-01-02 20:03:01 +08:00
|
|
|
console.log("✅ 语音 + 文字插件已运行");
|
|
|
|
|
|
|
|
|
|
// ========= 1. 浏览器能力检测 =========
|
|
|
|
|
const SpeechRecognition =
|
|
|
|
|
window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
|
|
|
|
|
|
|
|
const supportSpeech = !!SpeechRecognition;
|
|
|
|
|
|
|
|
|
|
// ========= 2. 创建控制面板 =========
|
|
|
|
|
const panel = document.createElement("div");
|
|
|
|
|
panel.style.cssText = `
|
|
|
|
|
position: fixed;
|
|
|
|
|
bottom: 24px;
|
|
|
|
|
right: 24px;
|
|
|
|
|
z-index: 999999;
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0,0,0,.15);
|
|
|
|
|
padding: 10px;
|
|
|
|
|
width: 220px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
panel.innerHTML = `
|
|
|
|
|
<div style="display:flex;gap:6px;">
|
|
|
|
|
<input
|
|
|
|
|
id="voiceTextInput"
|
|
|
|
|
placeholder="输入指令,如:添加设备"
|
|
|
|
|
style="flex:1;padding:6px;border:1px solid #dcdfe6;border-radius:4px;"
|
|
|
|
|
/>
|
|
|
|
|
<button
|
|
|
|
|
id="voiceBtn"
|
|
|
|
|
style="padding:6px 10px;border:none;border-radius:4px;background:#409eff;color:#fff;cursor:pointer;"
|
|
|
|
|
>🎤</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="margin-top:6px;color:#999;font-size:12px;">
|
|
|
|
|
支持语音 / 回车文字指令
|
|
|
|
|
</div>
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
document.body.appendChild(panel);
|
|
|
|
|
|
|
|
|
|
// ========= 3. 父菜单展开函数 =========
|
|
|
|
|
function expandParentMenu(span) {
|
|
|
|
|
const subMenu = span.closest(".el-sub-menu");
|
|
|
|
|
if (subMenu) {
|
|
|
|
|
const title = subMenu.querySelector(".el-sub-menu__title");
|
|
|
|
|
if (title && !subMenu.classList.contains("is-opened")) {
|
2026-01-02 20:28:11 +08:00
|
|
|
title.click();
|
2026-01-02 20:03:01 +08:00
|
|
|
console.log("📂 已展开父菜单");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ========= 4. 路由跳转函数 =========
|
|
|
|
|
function goToRoute(route) {
|
|
|
|
|
window.location.hash = route;
|
|
|
|
|
console.log("✅ 已跳转到路由:", route);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
// ========= 5. 指令配置 =========
|
|
|
|
|
const COMMANDS = [
|
|
|
|
|
{ key: "首页", menu: "首页", route: "/首页" },
|
|
|
|
|
{ key: "添加设备", menu: "添加设备", route: "/添加设备/添加设备" },
|
|
|
|
|
{ key: "监控中心", menu: "监控中心", route: "/监控中心/监控中心" },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// ========= 6. 指令解析(文字 & 语音共用) =========
|
2026-01-02 20:03:01 +08:00
|
|
|
function handleCommand(text) {
|
|
|
|
|
console.log("📥 收到指令:", text);
|
|
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
const command = COMMANDS.find(c => text.includes(c.key));
|
2026-01-02 20:03:01 +08:00
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
if (!command) {
|
|
|
|
|
alert("未识别指令:" + text);
|
2026-01-02 20:03:01 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
// 找菜单 DOM 并展开父菜单
|
|
|
|
|
const span = [...document.querySelectorAll("span")]
|
|
|
|
|
.find(el => el.innerText.trim() === command.menu);
|
|
|
|
|
|
|
|
|
|
span && expandParentMenu(span);
|
2026-01-02 20:03:01 +08:00
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
// 路由跳转
|
|
|
|
|
goToRoute(command.route);
|
2026-01-02 20:03:01 +08:00
|
|
|
}
|
|
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
// ========= 7. 文字输入支持 =========
|
2026-01-02 20:03:01 +08:00
|
|
|
const input = panel.querySelector("#voiceTextInput");
|
|
|
|
|
input.addEventListener("keydown", (e) => {
|
|
|
|
|
if (e.key === "Enter") {
|
|
|
|
|
const value = input.value.trim();
|
|
|
|
|
if (value) {
|
|
|
|
|
handleCommand(value);
|
|
|
|
|
input.value = "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
// ========= 8. 语音识别支持 =========
|
2026-01-02 20:03:01 +08:00
|
|
|
let recognition;
|
|
|
|
|
if (supportSpeech) {
|
|
|
|
|
recognition = new SpeechRecognition();
|
|
|
|
|
recognition.lang = "zh-CN";
|
|
|
|
|
recognition.continuous = false;
|
|
|
|
|
recognition.interimResults = false;
|
|
|
|
|
|
|
|
|
|
recognition.onresult = (event) => {
|
|
|
|
|
const text = event.results[0][0].transcript.trim();
|
|
|
|
|
handleCommand(text);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
recognition.onerror = (event) => {
|
|
|
|
|
console.error("语音识别错误", event.error);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
panel.querySelector("#voiceBtn").onclick = () => {
|
|
|
|
|
recognition.start();
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
panel.querySelector("#voiceBtn").disabled = true;
|
|
|
|
|
panel.querySelector("#voiceBtn").innerText = "❌";
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-02 20:28:11 +08:00
|
|
|
// ========= 9. 快捷键 Alt+V 支持语音 =========
|
2026-01-02 20:03:01 +08:00
|
|
|
document.addEventListener("keydown", (e) => {
|
|
|
|
|
if (e.altKey && e.key.toLowerCase() === "v") {
|
|
|
|
|
if (supportSpeech && recognition) recognition.start();
|
|
|
|
|
}
|
|
|
|
|
});
|