Explorar o código

1、blockly新页面——语音识别
2、生成代码功能

liyanbo hai 6 meses
pai
achega
81557d8344
Modificáronse 1 ficheiros con 167 adicións e 116 borrados
  1. 167 116
      src/components/blockly/BlocklyEditor.vue

+ 167 - 116
src/components/blockly/BlocklyEditor.vue

@@ -9,6 +9,21 @@
         </div>
       </div>
 
+    <!-- 收音状态显示区域 - 添加这段代码 -->
+    <div v-if="isRecording" class="recording-status-container">
+      <div class="recording-text">正在收音...</div>
+      <div class="equalizer">
+        <div class="bar bar-1"></div>
+        <div class="bar bar-2"></div>
+        <div class="bar bar-3"></div>
+        <div class="bar bar-4"></div>
+        <div class="bar bar-5"></div>
+        <div class="bar bar-6"></div>
+        <div class="bar bar-7"></div>
+      </div>
+      <div class="recording-countdown">{{ recordingCountdown }}秒</div>
+    </div>
+
     <img src="@/assets/images/desklamp.png" alt="智能台灯" class="full-screen-image" />
     <!-- 使用动态样式设置灯光遮罩 -->
      <div v-if="state.lamp.isLightOn"  :style="{ '--lamp-color': state.lamp.color,'--lamp-opacity': state.lamp.brightness / 100 }" class="lamp-light-mask"></div>
@@ -23,6 +38,14 @@
     <div v-if="state.lamp.isLightOn" class="lamp-info">
       <p>颜色: {{ state.lamp.colorLog }}色</p>
       <p>亮度: {{ state.lamp.brightness }}%</p>
+
+      <!-- 音乐播放状态显示和控制按钮 -->
+      <div v-if="state.isMusicPlaying" class="music-info">
+        <p>正在播放: {{ state.currentMusicName }}</p>
+        <button class="stop-music-btn" @click="handleStopMusic">
+          停止播放
+        </button>
+      </div>
     </div>
   </div>
 
@@ -130,7 +153,8 @@
         <h2>工作区</h2>
         <div id="blocklyDiv"></div>
         <div class="controls">
-          <button id="generateCode" @click="generateCode">生成代码</button>
+          <button id="generateCode" @click="generateCode('javascript')">生成JavaScript代码</button>
+          <button id="generateCode" @click="generateCode('python')">生成Python代码</button>
           <button id="runCode" @click="runCode">运行代码</button>
           <button @click="clearWorkspace">清空工作区</button>
         </div>
@@ -194,6 +218,11 @@ import {ElButton} from "element-plus";
 const router = useRouter();
 // 台灯预览显示状态
 const showLampPreview = ref(true);
+// 语音识别
+const isRecording = ref(false);
+const recordingCountdown = ref(10);
+let countdownInterval = null;
+
 // 返回虚拟实验室
 const goBackLab = () => {
   router.push("/virtual-laboratory");
@@ -205,124 +234,45 @@ const goBack = () => {
 const toggleLight = () => {
   state.lamp.isLightOn = true;
   generateCode('javascript');
+  // 在运行前设置为正在录音状态
+  startRecordingStatus();
   runCode();
 };
+// 添加开始录音状态函数
+function startRecordingStatus() {
+  isRecording.value = true;
+  recordingCountdown.value = 10;
+
+  // 清除之前的定时器
+  if (countdownInterval) {
+    clearInterval(countdownInterval);
+  }
+
+  // 设置新的倒计时
+  countdownInterval = setInterval(() => {
+    recordingCountdown.value--;
+    if (recordingCountdown.value <= 0) {
+      clearInterval(countdownInterval);
+      endRecordingStatus();
+    }
+  }, 1000);
+}
+
+// 添加结束录音状态函数
+function endRecordingStatus() {
+  isRecording.value = false;
+  if (countdownInterval) {
+    clearInterval(countdownInterval);
+    countdownInterval = null;
+  }
+}
 // 查看代码编程界面显示状态
 const handleViewCode = () => {
   showLampPreview.value = false;
 };
 
 // 响应式变量
-const jsonData = ref(`{
-  "blocks": {
-    "languageVersion": 0,
-    "blocks": [
-      {
-        "type": "variables_set",
-        "id": "kM:Fgf:wd4U3Z$j0x8oK",
-        "x": 90,
-        "y": 130,
-        "fields": {
-          "VAR": {
-            "id": "MHW(ZbOKhL!/An\`5N@6\`"
-          }
-        },
-        "inputs": {
-          "VALUE": {
-            "block": {
-              "type": "ai_voice_input",
-              "id": "l5E=g|1L+4hThQ8v})lQ",
-              "fields": {
-                "LANGUAGE": "zh-CN"
-              },
-              "inputs": {
-                "PROMPT": {
-                  "block": {
-                    "type": "text",
-                    "id": "Q*n.c_)@7j^E2=s5/X!n",
-                    "fields": {
-                      "TEXT": "请发言:"
-                    }
-                  }
-                }
-              }
-            }
-          }
-        },
-        "next": {
-          "block": {
-            "type": "variables_set",
-            "id": "]g.xbBe.i=a9B*Kfw@|\`",
-            "fields": {
-              "VAR": {
-                "id": "zn.7{ZqbUaH1?P,R05hF"
-              }
-            },
-            "inputs": {
-              "VALUE": {
-                "block": {
-                  "type": "ai_text_to_text",
-                  "id": "R$h+R!6#@+4=+WX1*nvh",
-                  "inputs": {
-                    "PROMPT": {
-                      "block": {
-                        "type": "variables_get",
-                        "id": "h$S$nt)3VU.=nX*W-mo~",
-                        "fields": {
-                          "VAR": {
-                            "id": "MHW(ZbOKhL!/An\`5N@6\`"
-                          }
-                        }
-                      }
-                    },
-                    "提示词": {
-                      "block": {
-                        "type": "text",
-                        "id": "7k%sgLP?i]e[,m^49P++",
-                        "fields": {
-                          "TEXT": "请只回复我指定格式:白,100,热闹"
-                        }
-                      }
-                    }
-                  }
-                }
-              }
-            },
-            "next": {
-              "block": {
-                "type": "ai_smart_lamp_single_param",
-                "id": "!.0;Ktwm+Z?o8_9FRa}G",
-                "inputs": {
-                  "PARAMS": {
-                    "block": {
-                      "type": "variables_get",
-                      "id": "d{cIJ-kEFFQcn~%A,g@g",
-                      "fields": {
-                        "VAR": {
-                          "id": "zn.7{ZqbUaH1?P,R05hF"
-                        }
-                      }
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    ]
-  },
-  "variables": [
-    {
-      "name": "inputText",
-      "id": "MHW(ZbOKhL!/An\`5N@6\`"
-    },
-    {
-      "name": "lampConfig",
-      "id": "zn.7{ZqbUaH1?P,R05hF"
-    }
-  ]
-}`);
+const jsonData = ref(``);
 
 const output = ref('// 生成的代码将显示在这里\n');
 const statusMessage = ref('');
@@ -356,8 +306,8 @@ const state = reactive({
 
   // 台灯状态
   lamp: {
-    isLightOn: false,// 台灯是否亮着
-    brightness: 0, // 默认亮度50%
+    isLightOn: true,// 台灯是否亮着
+    brightness: 50, // 默认亮度50%
     color: "#ffffff", // 默认颜色白色
     colorLog: "白", // 默认颜色白色
   },
@@ -1316,9 +1266,9 @@ const exportWorkspaceToJson = () => {
 const generateCode = (language = 'javascript') => {
   try {
     let generator;
-    if (language === "javascript") {
+    if (language == "javascript") {
       generator = javascriptGenerator;
-    } else if (language === "python") {
+    } else if (language == "python") {
       generator = pythonGenerator;
     } else {
       console.error("不支持的语言类型");
@@ -1327,7 +1277,19 @@ const generateCode = (language = 'javascript') => {
 
     const code = generator.workspaceToCode(workspace);
     output.value = code;
-    showStatus('代码生成成功!');
+
+    // 将生成的代码也输出到JSON框中
+    // 创建一个包含代码的JSON对象
+    const codeJson = {
+      "generated_code": {
+        "language": language,
+        "code": code
+      }
+    };
+    // 将JSON对象格式化为字符串并设置到JSON框
+    jsonData.value = JSON.stringify(codeJson, null, 2);
+
+    showStatus('代码生成成功!已同时输出到JSON框');
   } catch (error) {
     output.value = '// 代码生成错误: ' + error.message;
     showStatus('代码生成错误: ' + error.message, 'error');
@@ -1904,4 +1866,93 @@ textarea {
 .left-icon {
   font-size: 18px;
 }
+
+
+/* 语音识别-录音状态容器 */
+.recording-status-container {
+  position: absolute;
+  top: 20%;
+  left: 50%;
+  transform: translateX(-50%);
+  background: rgba(0, 0, 0, 0.7);
+  color: white;
+  padding: 20px 40px;
+  border-radius: 10px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
+  text-align: center;
+  z-index: 1000;
+  backdrop-filter: blur(5px);
+}
+
+.recording-text {
+  font-size: 18px;
+  margin-bottom: 15px;
+  font-weight: 500;
+}
+
+.recording-countdown {
+  font-size: 16px;
+  color: #4CAF50;
+  margin-top: 15px;
+  font-weight: bold;
+}
+
+.equalizer {
+  display: flex;
+  justify-content: center;
+  align-items: flex-end;
+  height: 60px;
+  gap: 4px;
+}
+
+.bar {
+  width: 8px;
+  background: linear-gradient(180deg, #4CAF50 0%, #8BC34A 100%);
+  border-radius: 4px;
+  animation: equalize 1s infinite ease-in-out;
+}
+
+.bar-1 { animation-delay: 0s; }
+.bar-2 { animation-delay: 0.1s; }
+.bar-3 { animation-delay: 0.2s; }
+.bar-4 { animation-delay: 0.3s; }
+.bar-5 { animation-delay: 0.4s; }
+.bar-6 { animation-delay: 0.5s; }
+.bar-7 { animation-delay: 0.6s; }
+
+@keyframes equalize {
+  0%, 100% { height: 10px; }
+  25% { height: 40px; }
+  50% { height: 60px; }
+  75% { height: 25px; }
+}
+
+//台灯播放音乐
+.music-info {
+  margin-top: 10px;
+  padding: 8px;
+  background-color: rgba(255, 255, 255, 0.1);
+  border-radius: 6px;
+}
+
+.music-info p {
+  margin: 0 0 8px 0;
+  color: #ffffff;
+  font-size: 14px;
+}
+
+.stop-music-btn {
+  background-color: #ff4d4f;
+  color: white;
+  border: none;
+  padding: 6px 12px;
+  border-radius: 4px;
+  cursor: pointer;
+  font-size: 12px;
+  transition: background-color 0.3s;
+}
+
+.stop-music-btn:hover {
+  background-color: #ff7875;
+}
 </style>