默认关闭语音播放功能
This commit is contained in:
1 parent
c43b5e5ac1
commit
1b8f833789
6 files changed
+176
-112
No files matched your search
+10
-1
@@ -26,7 +26,12 @@ export async function translateToCommand(userInput) {
|
||||
if (response.data.choices && response.data.choices.length > 0) {
|
||||
const content = response.data.choices[0].message.content.trim();
|
||||
console.log("📥 AI 原始响应:", content);
|
||||
resolve(content === "UNKNOWN" ? null : content);
|
||||
|
||||
// 返回包含内容和语音开关状态的对象
|
||||
resolve({
|
||||
content: content === "UNKNOWN" ? null : content,
|
||||
voiceEnabled: response.voiceEnabled // 从 background.js 透传回来的开关状态
|
||||
});
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
@@ -35,11 +40,15 @@ export async function translateToCommand(userInput) {
|
||||
resolve(null);
|
||||
}
|
||||
} else {
|
||||
console.error("AI 请求失败:", response?.error);
|
||||
resolve(null);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听来自 content.js 的结果反馈
|
||||
window.addEventListener("AI_RESULT", handler);
|
||||
|
||||
// 触发自定义事件,由 content.js 转发给 background.js
|
||||
window.dispatchEvent(new CustomEvent("DO_AI_REQUEST", {
|
||||
detail: { userInput, systemPrompt }
|
||||
}));
|
||||
|
||||
+62
-69
@@ -1,4 +1,6 @@
|
||||
// scripts/commands.js
|
||||
|
||||
// 标准指令路由映射表
|
||||
export const COMMANDS = [
|
||||
{ key: "首页", menu: "首页", route: "/首页" },
|
||||
{ key: "添加设备", menu: "添加设备", route: "/添加设备/添加设备" },
|
||||
@@ -14,87 +16,69 @@ export const COMMANDS = [
|
||||
{ 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: "/系统管理/区域管理" },
|
||||
{ key: "角色管理", menu: "角色管理", route: "/系统管理/角色管理" },
|
||||
{ key: "用户管理", menu: "用户管理", route: "/系统管理/用户管理" }
|
||||
];
|
||||
|
||||
function waitForElement(selector, callback, timeout = 5000) {
|
||||
const start = Date.now();
|
||||
const timer = setInterval(() => {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) {
|
||||
clearInterval(timer);
|
||||
callback(el);
|
||||
} else if (Date.now() - start > timeout) {
|
||||
clearInterval(timer);
|
||||
console.warn("等待元素超时:", selector);
|
||||
/**
|
||||
* 展开侧边栏父级菜单
|
||||
*/
|
||||
function expandParentMenu(span) {
|
||||
let parent = span.closest('li');
|
||||
while (parent) {
|
||||
if (parent.classList.contains('el-submenu')) {
|
||||
const title = parent.querySelector('.el-submenu__title');
|
||||
if (title && !parent.classList.contains('is-opened')) {
|
||||
title.click();
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function autoFillAndSubmit(value) {
|
||||
waitForElement('.el-input__inner', (input) => {
|
||||
input.value = value;
|
||||
input.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
input.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
|
||||
const submitBtn = document.querySelector('.el-button--primary');
|
||||
if (submitBtn) {
|
||||
setTimeout(() => {
|
||||
submitBtn.click();
|
||||
}, 600);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function expandParentMenu(span) {
|
||||
const subMenu = span.closest(".el-sub-menu");
|
||||
if (subMenu && !subMenu.classList.contains("is-opened")) {
|
||||
const title = subMenu.querySelector(".el-sub-menu__title");
|
||||
if (title) title.click();
|
||||
parent = parent.parentElement.closest('li');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 AI 返回的混合指令 (对话 + 操作)
|
||||
* 自动填充并提交搜索(模拟针对某些页面的操作)
|
||||
*/
|
||||
export function handleCommand(aiResult, uiRefs) {
|
||||
function autoFillAndSubmit(arg) {
|
||||
if (!arg) return;
|
||||
setTimeout(() => {
|
||||
const input = document.querySelector('input[placeholder*="名称"], input[placeholder*="编号"]');
|
||||
if (input) {
|
||||
input.value = arg;
|
||||
input.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
const searchBtn = document.querySelector('button.el-button--primary');
|
||||
if (searchBtn) searchBtn.click();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心处理器:根据 AI 结果执行动作
|
||||
* @param {string} aiResult AI 返回的 XML 字符串
|
||||
* @param {object} uiRefs UI 更新引用的对象
|
||||
* @param {boolean} voiceEnabled 是否允许播放语音 (由 ai.js 传入)
|
||||
*/
|
||||
export function handleCommand(aiResult, uiRefs, voiceEnabled = false) {
|
||||
if (!aiResult || aiResult === "UNKNOWN") return;
|
||||
|
||||
// 1. 解析对话内容并反馈
|
||||
const commMatch = aiResult.match(/<communication>([\s\S]*?)<\/communication>/);
|
||||
if (commMatch && commMatch[1]) {
|
||||
const speechText = commMatch[1].trim();
|
||||
// 更新 UI 状态
|
||||
|
||||
// 始终更新 UI 界面上的文字状态
|
||||
if (uiRefs && uiRefs.updateStatus) {
|
||||
uiRefs.updateStatus(speechText);
|
||||
}
|
||||
// 语音播报
|
||||
const utterance = new SpeechSynthesisUtterance(speechText);
|
||||
utterance.lang = "zh-CN";
|
||||
window.speechSynthesis.speak(utterance);
|
||||
|
||||
// 仅在语音开关开启时播报语音
|
||||
if (voiceEnabled) {
|
||||
const utterance = new SpeechSynthesisUtterance(speechText);
|
||||
utterance.lang = "zh-CN";
|
||||
window.speechSynthesis.speak(utterance);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 解析指令逻辑
|
||||
@@ -105,22 +89,31 @@ export function handleCommand(aiResult, uiRefs) {
|
||||
const arg = argMatch ? argMatch[1].trim() : null;
|
||||
|
||||
if (key) {
|
||||
// 模糊匹配指令
|
||||
const command = COMMANDS.find(c => c.key === key) ||
|
||||
COMMANDS.find(c => key.includes(c.key));
|
||||
|
||||
if (command) {
|
||||
console.log("🚀 执行指令:", command.key, "参数:", arg);
|
||||
|
||||
// 尝试点击侧边栏菜单(针对 Element UI 结构)
|
||||
const allSpans = Array.from(document.querySelectorAll("span"));
|
||||
let span = allSpans.find(el => el.innerText.trim() === command.menu);
|
||||
|
||||
if (span) {
|
||||
expandParentMenu(span);
|
||||
span.click();
|
||||
window.location.hash = command.route;
|
||||
if (arg) autoFillAndSubmit(arg);
|
||||
} else {
|
||||
window.location.hash = command.route;
|
||||
if (arg) autoFillAndSubmit(arg);
|
||||
}
|
||||
|
||||
// 路由跳转
|
||||
window.location.hash = command.route;
|
||||
|
||||
// 自动填充搜索参数
|
||||
if (arg) {
|
||||
autoFillAndSubmit(arg);
|
||||
}
|
||||
} else {
|
||||
console.warn("⚠️ 未找到匹配指令:", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user