完善输入逻辑
This commit is contained in:
1 parent
d1f8b403c4
commit
9e486fa390
4 files changed
+127
-91
No files matched your search
+36
-21
@@ -1,6 +1,6 @@
|
||||
// scripts/panel.js
|
||||
export function createPanel() {
|
||||
const panelId = "automation-ai-panel";
|
||||
// 防止重复创建
|
||||
let panel = document.getElementById(panelId);
|
||||
if (panel) return getUIRefs(panel);
|
||||
|
||||
@@ -10,21 +10,30 @@ export function createPanel() {
|
||||
position: fixed; bottom: 24px; right: 24px; z-index: 2147483647;
|
||||
background: white; border-radius: 10px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,.2); padding: 12px; width: 260px;
|
||||
font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
font-size: 14px; font-family: sans-serif;
|
||||
`;
|
||||
|
||||
panel.innerHTML = `
|
||||
<style>
|
||||
@keyframes breathe {
|
||||
0% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 0.5; transform: scale(1.1); }
|
||||
100% { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
.recording-dot {
|
||||
width: 8px; height: 8px; background: #ff4d4f; border-radius: 50%;
|
||||
display: none; margin-right: 6px; animation: breathe 1.2s infinite;
|
||||
}
|
||||
</style>
|
||||
<div style="display:flex;gap:8px;align-items:center;">
|
||||
<input id="voiceTextInput" type="text" placeholder="输入指令或自然语言..."
|
||||
<input id="voiceTextInput" type="text" placeholder="输入指令或长按空格..."
|
||||
style="flex:1;padding:8px;border:1px solid #dcdfe6;border-radius:4px;outline:none;font-size:13px;" />
|
||||
<button id="voiceBtn" title="按 Alt+V 快捷开启"
|
||||
style="padding:8px 12px;border:none;border-radius:4px;background:#409eff;color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;">
|
||||
🎤
|
||||
</button>
|
||||
<button id="voiceBtn" style="padding:8px 12px;border:none;border-radius:4px;background:#409eff;color:#fff;cursor:pointer;">🎤</button>
|
||||
</div>
|
||||
<div id="panelStatus" style="margin-top:8px;color:#999;font-size:12px;display:flex;justify-content:space-between;align-items:center;">
|
||||
<div id="panelStatus" style="margin-top:10px;color:#999;font-size:12px;display:flex;align-items:center;">
|
||||
<div id="recordingIndicator" class="recording-dot"></div>
|
||||
<span id="statusText">准备就绪</span>
|
||||
<span id="aiLoading" style="display:none;color:#409eff;font-weight:bold;">🤖 思考中...</span>
|
||||
<span id="aiLoading" style="display:none;color:#409eff;margin-left:auto;font-weight:bold;">🤖 思考中...</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -33,19 +42,25 @@ export function createPanel() {
|
||||
}
|
||||
|
||||
function getUIRefs(panel) {
|
||||
const input = panel.querySelector("#voiceTextInput");
|
||||
const btn = panel.querySelector("#voiceBtn");
|
||||
const loading = panel.querySelector("#aiLoading");
|
||||
const statusText = panel.querySelector("#statusText");
|
||||
|
||||
return {
|
||||
input,
|
||||
btn,
|
||||
setLoading: (isLoading) => {
|
||||
loading.style.display = isLoading ? "inline" : "none";
|
||||
statusText.style.display = isLoading ? "none" : "inline";
|
||||
input.disabled = isLoading;
|
||||
if (!isLoading) input.focus();
|
||||
btn: panel.querySelector("#voiceBtn"),
|
||||
input: panel.querySelector("#voiceTextInput"),
|
||||
setLoading: (loading) => {
|
||||
panel.querySelector("#aiLoading").style.display = loading ? "inline" : "none";
|
||||
panel.querySelector("#statusText").style.visibility = loading ? "hidden" : "visible";
|
||||
},
|
||||
setRecording: (isRecording) => {
|
||||
const dot = panel.querySelector("#recordingIndicator");
|
||||
const text = panel.querySelector("#statusText");
|
||||
if (isRecording) {
|
||||
dot.style.display = "inline-block";
|
||||
text.innerText = "正在聆听...";
|
||||
text.style.color = "#ff4d4f";
|
||||
} else {
|
||||
dot.style.display = "none";
|
||||
text.innerText = "准备就绪";
|
||||
text.style.color = "#999";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
+22
-30
@@ -1,36 +1,28 @@
|
||||
// 语音识别
|
||||
|
||||
export function initVoice(panel, handleCommand) {
|
||||
// scripts/voice.js
|
||||
export function initVoice(panel, onResultCallback) {
|
||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||
const supportSpeech = !!SpeechRecognition;
|
||||
let recognition;
|
||||
if (!SpeechRecognition) return { supportSpeech: false };
|
||||
|
||||
if (supportSpeech) {
|
||||
recognition = new SpeechRecognition();
|
||||
recognition.lang = "zh-CN";
|
||||
recognition.continuous = false;
|
||||
recognition.interimResults = false;
|
||||
const recognition = new SpeechRecognition();
|
||||
recognition.lang = "zh-CN";
|
||||
recognition.continuous = false; // 改为 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();
|
||||
recognition.onresult = (event) => {
|
||||
const text = event.results[0][0].transcript.trim();
|
||||
if (text) {
|
||||
console.log("🎤 识别结果:", text);
|
||||
onResultCallback(text);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return supportSpeech;
|
||||
recognition.onerror = (event) => {
|
||||
if (event.error !== 'aborted') console.error("语音错误:", event.error);
|
||||
};
|
||||
|
||||
return {
|
||||
supportSpeech: true,
|
||||
start: () => { try { recognition.start(); } catch(e){} },
|
||||
stop: () => { try { recognition.stop(); } catch(e){} }
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user