|
|
@@ -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>
|