|
@@ -1,5 +1,42 @@
|
|
|
<template>
|
|
<template>
|
|
|
|
|
+ <!-- 智能台灯 -->
|
|
|
|
|
+ <div v-if="showLampPreview" class="desk-lamp-container">
|
|
|
|
|
+ <!-- 标题框 -->
|
|
|
|
|
+ <div class="desk-lamp-title-box">
|
|
|
|
|
+ <div class="desk-lamp-box-icon" @click="goBackLab">
|
|
|
|
|
+ <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
|
|
|
|
|
+ 返回虚拟实验室
|
|
|
|
|
+ </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>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 右下角按钮组 -->
|
|
|
|
|
+ <div class="button-group">
|
|
|
|
|
+ <el-button class="control-button run-button" @click="toggleLight">运行</el-button>
|
|
|
|
|
+ <el-button class="control-button code-button" @click="handleViewCode">智能台灯</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 显示当前灯光信息 -->
|
|
|
|
|
+ <div v-if="state.lamp.isLightOn" class="lamp-info">
|
|
|
|
|
+ <p>颜色: {{ state.lamp.colorLog }}色</p>
|
|
|
|
|
+ <p>亮度: {{ state.lamp.brightness }}%</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Blockly编程界面 -->
|
|
|
<div class="container">
|
|
<div class="container">
|
|
|
|
|
+ <!-- 返回智能台灯 -->
|
|
|
|
|
+ <div class="title-box">
|
|
|
|
|
+ <div class="box-icon" @click="goBack">
|
|
|
|
|
+ <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
|
|
|
|
|
+ 返回智能台灯
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<div class="content">
|
|
<div class="content">
|
|
|
<div class="toolbox-section">
|
|
<div class="toolbox-section">
|
|
|
<h2>工具箱</h2>
|
|
<h2>工具箱</h2>
|
|
@@ -85,6 +122,8 @@
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, onMounted, onUnmounted, reactive } from 'vue';
|
|
import { ref, onMounted, onUnmounted, reactive } from 'vue';
|
|
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
|
|
+import { ArrowLeftBold } from '@element-plus/icons-vue';
|
|
|
import * as Blockly from "blockly";
|
|
import * as Blockly from "blockly";
|
|
|
import 'blockly/msg/zh-hans';
|
|
import 'blockly/msg/zh-hans';
|
|
|
import { javascriptGenerator } from "blockly/javascript";
|
|
import { javascriptGenerator } from "blockly/javascript";
|
|
@@ -106,6 +145,27 @@ import { globalState } from "@/utils/globalState.js";
|
|
|
//音乐
|
|
//音乐
|
|
|
import { playMusic, stopMusic, onMusicEnded } from "@/api/blockly/music.js";
|
|
import { playMusic, stopMusic, onMusicEnded } from "@/api/blockly/music.js";
|
|
|
|
|
|
|
|
|
|
+const router = useRouter();
|
|
|
|
|
+// 台灯预览显示状态
|
|
|
|
|
+const showLampPreview = ref(true);
|
|
|
|
|
+// 返回虚拟实验室
|
|
|
|
|
+const goBackLab = () => {
|
|
|
|
|
+ router.push("/virtual-laboratory");
|
|
|
|
|
+};
|
|
|
|
|
+const goBack = () => {
|
|
|
|
|
+ showLampPreview.value = true;
|
|
|
|
|
+};
|
|
|
|
|
+// 切换灯光状态
|
|
|
|
|
+const toggleLight = () => {
|
|
|
|
|
+ state.lamp.isLightOn = true;
|
|
|
|
|
+ generateCode('javascript');
|
|
|
|
|
+ runCode();
|
|
|
|
|
+};
|
|
|
|
|
+// 查看代码编程界面显示状态
|
|
|
|
|
+const handleViewCode = () => {
|
|
|
|
|
+ showLampPreview.value = false;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// 响应式变量
|
|
// 响应式变量
|
|
|
const jsonData = ref(`{
|
|
const jsonData = ref(`{
|
|
|
"blocks": {
|
|
"blocks": {
|
|
@@ -1284,7 +1344,13 @@ const showStatus = (message, type = 'success') => {
|
|
|
};
|
|
};
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-<style scoped>
|
|
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+@use "sass:math";
|
|
|
|
|
+
|
|
|
|
|
+@function rpx($px) {
|
|
|
|
|
+ @return math.div($px, 750) * 100vw;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
* {
|
|
* {
|
|
|
margin: 0;
|
|
margin: 0;
|
|
|
padding: 0;
|
|
padding: 0;
|
|
@@ -1555,4 +1621,160 @@ textarea {
|
|
|
color: #721c24;
|
|
color: #721c24;
|
|
|
border: 1px solid #f5c6cb;
|
|
border: 1px solid #f5c6cb;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 智能台灯 */
|
|
|
|
|
+.desk-lamp-container {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.full-screen-image {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ object-fit: cover;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 台灯灯光样式 - 使用动态颜色 */
|
|
|
|
|
+.lamp-light-mask {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ width: rpx(78);
|
|
|
|
|
+ height: rpx(250);
|
|
|
|
|
+ margin-top: rpx(49);
|
|
|
|
|
+ margin-left: rpx(192);
|
|
|
|
|
+ background: linear-gradient(to bottom, var(--lamp-color) 0%, var(--lamp-color) 10%, rgba(255, 255, 255, 0) 90%);
|
|
|
|
|
+ filter: blur(60px);
|
|
|
|
|
+ transform: rotate(9deg);
|
|
|
|
|
+ transform-origin: top center;
|
|
|
|
|
+ opacity: var(--lamp-opacity, 0.6);
|
|
|
|
|
+ /* 创建扇形效果 */
|
|
|
|
|
+ clip-path: polygon(0% 0%, 100% 0%, 250% 100%, -150% 100%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 灯光信息显示 */
|
|
|
|
|
+.lamp-info {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 100px;
|
|
|
|
|
+ right: 30px;
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
|
|
+ padding: 10px 20px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 标题框样式 */
|
|
|
|
|
+.desk-lamp-title-box {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 20px;
|
|
|
|
|
+ left: 20px;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.desk-lamp-box-icon {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+ padding: 10px 20px;
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
|
|
+ border-radius: 30px;
|
|
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.desk-lamp-box-icon:hover {
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.3);
|
|
|
|
|
+ transform: translateX(-3px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.left-icon {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 右下角按钮组样式 */
|
|
|
|
|
+.button-group {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 30px;
|
|
|
|
|
+ right: 30px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 15px;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.control-button {
|
|
|
|
|
+ padding: 12px 24px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
+ backdrop-filter: blur(5px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.run-button {
|
|
|
|
|
+ background-color: rgba(64, 169, 255, 0.8);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.run-button:hover {
|
|
|
|
|
+ background-color: rgba(64, 169, 255, 1);
|
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.code-button {
|
|
|
|
|
+ background-color: rgba(132, 94, 255, 0.8);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.code-button:hover {
|
|
|
|
|
+ background-color: rgba(132, 94, 255, 1);
|
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
|
+}
|
|
|
|
|
+/* 返回按钮样式 */
|
|
|
|
|
+.title-box {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ top: 10px;
|
|
|
|
|
+ left: 20px;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.box-icon {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+ padding: 10px 20px;
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
|
|
+ border-radius: 30px;
|
|
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ width: fit-content;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.box-icon:hover {
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.3);
|
|
|
|
|
+ transform: translateX(-3px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.left-icon {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|