规范代码并增加操作

This commit is contained in:
张梦南 2026-01-02 21:06:54 +08:00
parent d431076623
commit 52c931e7f5
6 changed files with 169 additions and 133 deletions

66
commands.js Normal file
View File

@ -0,0 +1,66 @@
export const COMMANDS = [
{ key: "首页", menu: "首页", route: "/首页" },
{ key: "添加设备", menu: "添加设备", route: "/添加设备/添加设备" },
{ key: "监控中心", menu: "监控中心", route: "/监控中心/监控中心" },
{ key: "摄像头管理", menu: "摄像头管理", route: "/云视频管理/摄像头管理" },
{ key: "云视频监控", menu: "云视频监控", route: "/云视频监控/云视频监控" },
{ key: "GIS监控", menu: "GIS监控", route: "/GIS管理/GIS监控" },
{ key: "我的流量", menu: "我的流量", route: "/资源管理/我的流量" },
{ key: "我的资源", menu: "我的资源", route: "/资源管理/我的资源" },
{ key: "我的订单", menu: "我的订单", route: "/资源管理/我的订单" },
{ key: "仪表积分", menu: "仪表积分", route: "/资源管理/仪表积分" },
{ key: "报警设置", menu: "报警设置", route: "/报警管理/报警设置" },
{ key: "报警通知", menu: "报警通知", route: "/报警管理/报警通知" },
{ key: "报警记录", menu: "报警记录", route: "/报警管理/报警记录" },
{ key: "基础报表", menu: "基础报表", route: "/报表管理/基础报表" },
{ key: "高级报表配置", menu: "高级报表配置", route: "/报表管理/高级报表配置" },
{ key: "高级报表", menu: "高级报表", route: "/报表管理/高级报表" },
{ key: "应用场景", menu: "应用场景", route: "/仪表管理/应用场景" },
{ key: "仪表管理", menu: "仪表管理", route: "/仪表管理/仪表管理" },
{ key: "虚拟仪表", menu: "虚拟仪表", route: "/仪表管理/虚拟仪表" },
{ key: "物位监测", menu: "物位监测", route: "/场景管理/物位监测/物位监测" },
{ key: "物位监测配置", menu: "物位监测配置", route: "/场景管理/物位监测/物位监测配置" },
{ key: "车间看板", menu: "车间看板", route: "/场景管理/车间看板/车间看板" },
{ key: "车间看板配置", menu: "车间看板配置", route: "/场景管理/车间看板/车间看板配置" },
{ key: "能源结算", menu: "能源结算", route: "/场景管理/能源抄表/能源结算" },
{ key: "能源结算配置", menu: "能源结算配置", route: "/场景管理/能源抄表/能源结算配置" },
{ key: "多租户能源结算", menu: "多租户能源结算", route: "/场景管理/多租户结算/多租户能源结算" },
{ key: "租户管理", menu: "租户管理", route: "/场景管理/多租户结算/租户管理" },
{ key: "计价方式管理", menu: "计价方式管理", route: "/场景管理/多租户结算/计价方式管理" },
{ key: "单染缸印染结算", menu: "单染缸印染结算", route: "/场景管理/印染结算/单染缸印染结算" },
{ key: "多染缸印染结算", menu: "多染缸印染结算", route: "/场景管理/印染结算/多染缸印染结算" },
{ key: "染缸能耗一览表", menu: "染缸能耗一览表", route: "/场景管理/印染结算/染缸能耗一览表" },
{ key: "印染结算配置", menu: "印染结算配置", route: "/场景管理/印染结算/印染结算配置" },
{ key: "消息管理", menu: "消息管理", route: "/系统管理/消息管理" },
{ key: "数据服务", menu: "数据服务", route: "/系统管理/数据服务" },
{ key: "数据下云", menu: "数据下云", route: "/系统管理/数据下云" },
];
export 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")) {
title.click();
console.log("📂 已展开父菜单");
}
}
}
export function goToRoute(route) {
window.location.hash = route;
console.log("✅ 已跳转到路由:", route);
}
export function handleCommand(text) {
console.log("📥 收到指令:", text);
const command = COMMANDS.find(c => text.includes(c.key));
if (!command) {
alert("未识别指令:" + text);
return;
}
const span = [...document.querySelectorAll("span")]
.find(el => el.innerText.trim() === command.menu);
span && expandParentMenu(span);
goToRoute(command.route);
}

View File

@ -1,131 +1,7 @@
console.log("✅ 语音 + 文字插件已运行");
// content.js 是 content script 的入口,不直接写全部逻辑
// 用 module 方式加载其他文件
// ========= 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")) {
title.click();
console.log("📂 已展开父菜单");
}
}
}
// ========= 4. 路由跳转函数 =========
function goToRoute(route) {
window.location.hash = route;
console.log("✅ 已跳转到路由:", route);
}
// ========= 5. 指令配置 =========
const COMMANDS = [
{ key: "首页", menu: "首页", route: "/首页" },
{ key: "添加设备", menu: "添加设备", route: "/添加设备/添加设备" },
{ key: "监控中心", menu: "监控中心", route: "/监控中心/监控中心" },
];
// ========= 6. 指令解析(文字 & 语音共用) =========
function handleCommand(text) {
console.log("📥 收到指令:", text);
const command = COMMANDS.find(c => text.includes(c.key));
if (!command) {
alert("未识别指令:" + text);
return;
}
// 找菜单 DOM 并展开父菜单
const span = [...document.querySelectorAll("span")]
.find(el => el.innerText.trim() === command.menu);
span && expandParentMenu(span);
// 路由跳转
goToRoute(command.route);
}
// ========= 7. 文字输入支持 =========
const input = panel.querySelector("#voiceTextInput");
input.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
const value = input.value.trim();
if (value) {
handleCommand(value);
input.value = "";
}
}
});
// ========= 8. 语音识别支持 =========
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 = "❌";
}
// ========= 9. 快捷键 Alt+V 支持语音 =========
document.addEventListener("keydown", (e) => {
if (e.altKey && e.key.toLowerCase() === "v") {
if (supportSpeech && recognition) recognition.start();
}
});
const script = document.createElement('script');
script.type = 'module';
script.src = chrome.runtime.getURL('main.js');
document.head.appendChild(script);

21
main.js Normal file
View File

@ -0,0 +1,21 @@
import { createPanel } from './panel.js';
import { handleCommand } from './commands.js';
import { initVoice } from './voice.js';
console.log("✅ 语音 + 文字插件已运行");
const panel = createPanel();
// 文字输入支持
const input = panel.querySelector("#voiceTextInput");
input.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
const value = input.value.trim();
if (value) {
handleCommand(value);
input.value = "";
}
}
});
initVoice(panel, handleCommand);

View File

@ -1,12 +1,19 @@
{
"manifest_version": 3,
"name": "语音界面跳转",
"version": "1.0",
"version": "0.0.1",
"content_scripts": [
{
"matches": ["*://1718cloud.com/*"],
"js": ["content.js"]
"js": ["content.js"],
"run_at": "document_idle"
}
],
"permissions": ["activeTab"]
"permissions": ["activeTab"],
"web_accessible_resources": [
{
"resources": ["*.js"],
"matches": ["*://1718cloud.com/*"]
}
]
}

30
panel.js Normal file
View File

@ -0,0 +1,30 @@
export function createPanel() {
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);
return panel;
}

36
voice.js Normal file
View File

@ -0,0 +1,36 @@
// 语音识别
export function initVoice(panel, handleCommand) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const supportSpeech = !!SpeechRecognition;
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 = "❌";
}
document.addEventListener("keydown", (e) => {
if (e.altKey && e.key.toLowerCase() === "v" && supportSpeech && recognition) {
recognition.start();
}
});
return supportSpeech;
}