增加AI通过上云码添加仪表的功能

This commit is contained in:
张梦南 2026-01-14 22:21:02 +08:00
parent e806d61ede
commit 53994476c4
2 changed files with 98 additions and 48 deletions

View File

@ -1,28 +1,47 @@
// ai.js // scripts/ai.js
import { COMMANDS } from './commands.js'; import { COMMANDS } from './commands.js';
export async function translateToCommand(userInput) { export async function translateToCommand(userInput) {
const availableKeys = COMMANDS.map(c => c.key).join(', '); const availableKeys = COMMANDS.map(c => c.key).join(', ');
const systemPrompt = `你是一个助手。将输入映射到以下关键词之一:${availableKeys}。只输出关键词,不要其他字。无法匹配则输出 UNKNOWN。`;
// 优化提示词:增加参数提取规则和别名映射
const systemPrompt = `你是一个工业自动化系统助手。
标准指令列表[${availableKeys}]
任务规则
1. 如果用户指令包含设备编号序列号或验证码20260114请按格式输出标准指令 参数
例如帮我添加一台编号为20260114的设备 -> 输出 添加设备 20260114
2. 如果只是单纯跳转只输出标准指令
3. 主界面主页映射为首页
4. 只输出结果不要输出任何解释说明或标点
5. 无法匹配请输出 UNKNOWN`;
return new Promise((resolve) => { return new Promise((resolve) => {
// 1. 监听结果
const handler = (event) => { const handler = (event) => {
const response = event.detail; const response = event.detail;
window.removeEventListener("AI_RESULT", handler); window.removeEventListener("AI_RESULT", handler);
if (response.success) { if (response && response.success && response.data) {
const content = response.data.choices[0].message.content.trim(); try {
console.log("📥 AI 识别结果:", content); if (response.data.choices && response.data.choices.length > 0) {
resolve(content === "UNKNOWN" ? null : content); const content = response.data.choices[0].message.content.trim();
console.log("📥 AI 映射结果:", content);
resolve(content === "UNKNOWN" ? null : content);
} else if (response.data.error || response.data.errors) {
console.error("AI服务报错:", response.data.error || response.data.errors);
resolve(null);
}
} catch (e) {
console.error("解析响应失败:", e);
resolve(null);
}
} else { } else {
console.error("AI 失败:", response.error);
resolve(null); resolve(null);
} }
}; };
window.addEventListener("AI_RESULT", handler); window.addEventListener("AI_RESULT", handler);
// 2. 触发请求
window.dispatchEvent(new CustomEvent("DO_AI_REQUEST", { window.dispatchEvent(new CustomEvent("DO_AI_REQUEST", {
detail: { userInput, systemPrompt } detail: { userInput, systemPrompt }
})); }));

View File

@ -39,51 +39,82 @@ export const COMMANDS = [
{ 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);
}
}, 200);
}
/**
* 自动化填写和点击逻辑
*/
function autoFillAndSubmit(value) {
// 1. 等待输入框出现 (针对 Element Plus 使用 .el-input__inner)
// 提示:如果有多个框,可改用 'input[placeholder*="上云码"]' 增加精度
waitForElement('.el-input__inner', (input) => {
console.log("🔍 已定位输入框,开始填充:", value);
// 填写内容
input.value = value;
// 关键:手动触发事件以同步 Vue 的双向绑定 (v-model)
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
// 2. 自动点击“确认”按钮 (通常类名为 el-button--primary)
const submitBtn = document.querySelector('.el-button--primary');
if (submitBtn) {
setTimeout(() => {
submitBtn.click();
console.log("✅ 自动化流程已触发提交");
}, 600);
}
});
}
export function expandParentMenu(span) { export function expandParentMenu(span) {
const subMenu = span.closest(".el-sub-menu"); const subMenu = span.closest(".el-sub-menu");
if (subMenu) { if (subMenu && !subMenu.classList.contains("is-opened")) {
const title = subMenu.querySelector(".el-sub-menu__title"); const title = subMenu.querySelector(".el-sub-menu__title");
if (title && !subMenu.classList.contains("is-opened")) { if (title) title.click();
title.click();
console.log("📂 已展开父菜单");
} }
}
} }
export function goToRoute(route) { export function handleCommand(aiResult) {
// 兼容 Hash 路由和普通路由,根据实际项目情况 if (!aiResult) return;
window.location.hash = route; console.log("🚀 处理自动化指令:", aiResult);
console.log("✅ 已跳转到路由:", route);
} // 解析格式:"指令 参数" (例如 "添加设备 20260114")
const [key, arg] = aiResult.split(" ");
export function handleCommand(keyOrText) {
console.log("🚀 执行指令逻辑:", keyOrText); const command = COMMANDS.find(c => c.key === key) ||
COMMANDS.find(c => key.includes(c.key));
// 尝试精确匹配 (AI返回的Key) 或 模糊匹配 (用户输入的Text)
const command = COMMANDS.find(c => c.key === keyOrText) || if (command) {
COMMANDS.find(c => keyOrText.includes(c.key)); // 第一步:查找菜单并跳转
const allSpans = Array.from(document.querySelectorAll("span"));
if (!command) { let span = allSpans.find(el => el.innerText.trim() === command.menu);
console.warn("无法执行,未找到对应菜单动作:", keyOrText);
return; if (span) {
} expandParentMenu(span);
span.click();
// 查找菜单 DOM 元素 (根据你原有的逻辑) window.location.hash = command.route;
const allSpans = Array.from(document.querySelectorAll("span"));
// 第二步:如果有编号参数,启动后续填充流程
// 优先全匹配,防止"报表"匹配到"高级报表" if (arg) {
let span = allSpans.find(el => el.innerText.trim() === command.menu); console.log(`⏳ 页面跳转中,准备填充参数: ${arg}`);
autoFillAndSubmit(arg);
if (span) { }
expandParentMenu(span); }
// 模拟点击触发 Vue/React 的路由跳转,或者直接改 Hash } else {
// 如果页面需要点击才能触发加载,建议 span.click() console.warn("未匹配到标准指令:", key);
// 如果只是纯 hash 跳转goToRoute 即可 }
// 建议先点击,确保侧边栏高亮
span.click();
goToRoute(command.route);
} else {
console.error(`❌ 未找到菜单元素: ${command.menu}`);
}
} }