ソースを参照

Merge branch 'master' of http://59.110.91.129:3000/zhangmengying/AIClass into wanzi

丸子 3 週間 前
コミット
d9fc0b4ab1

+ 107 - 3
README.md

@@ -1,5 +1,109 @@
-# Vue 3 + Vite
+# 人工智能通识课平台前端
 
-This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
+## 项目介绍
 
-Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
+人工智能通识课平台前端
+
+## 页面路由结构
+
+### 1. 基础页面
+
+- **登录页**
+  - `/` - 主登录页
+  - `/login` - 登录页
+  - `/quick-login` - 免登录(广电)
+  - `/promotion-login` - 免登录(营销号)
+  - `/register-login` - 注册登录
+  - `/blockly-register` - 编程课注册
+
+### 2. 管理界面
+
+- **管理后台**
+  - `/management-interface` - 管理界面
+
+### 3. 通识课模块
+
+- **首页**
+  - `/home` - 通识课首页
+
+- **智能课**
+  - `/ai-general-course` - 智能课页面
+
+- **AI实验室**
+  - `/ai-laboratory` - AI实验室页面
+
+- **英文数字人老师**
+  - `/ai-ennumerals` - 英文数字人老师页面
+
+- **能力测评**
+  - `/evaluation` - 问卷列表
+  - `/testTopic` - 在线测试
+  - `/testSubmit` - 测试提交
+
+- **个性化学习**
+  - `/personalized` - 个性化学习页面
+
+- **智能绘画**
+  - `/ai-painting` - 智能绘画页面
+
+- **图生图**
+  - `/ai-image` - 图生图页面
+
+- **AI头像**
+  - `/ai-avatar` - AI头像页面
+
+- **图生视频**
+  - `/ai-video` - 图生视频页面
+
+- **大运河**
+  - `/ai-grandcanal` - 大运河页面
+
+- **植物专家**
+  - `/ai-plantexperts` - 植物专家页面
+
+- **智能问答**
+  - `/ai-questions` - 智能问答页面
+
+- **发展历程**
+  - `/ai-develop` - 发展历程页面
+
+- **虚拟实验室**
+  - `/virtual-laboratory` - 虚拟实验室页面
+  - `/smartHome` - 智能家居页面
+  - `/smartDeskLamp` - 智能台灯页面
+
+- **AI古诗**
+  - `/ai-poetry` - AI古诗页面
+
+### 4. 编程课模块
+
+- **编程课首页**
+  - `/blocklyHome` - 编程课首页
+
+
+- **编程课列表**
+  - `/programmingList` - 编程课列表
+  - `/programmingCourset` - 编程课详情
+  - `/interface` - 编程课视频
+
+### 5. AI实验课模块
+
+- **实验课首页**
+  - `/aiCourseHome` - 实验课首页
+
+- **实验列表**
+  - `/experiment-type` - 实验类型页面
+  - `/experimental-course` - 实验课程页面
+  - `/experimental-interface` - 实验界面
+
+
+## 项目结构
+
+项目采用模块化设计,主要包含以下目录:
+
+- `src/views/` - 页面组件
+- `src/components/` - 可复用组件
+- `src/api/` - API接口和工具函数
+- `src/router/` - 路由配置
+- `src/utils/` - 工具函数
+- `src/assets/` - 静态资源

+ 74 - 0
src/api/blockly/blockly.js

@@ -360,6 +360,48 @@ const availableBlocks = {
     },
     isGeneral: true // 标记为通用积木
   },
+  // 循环积木 - while循环
+  controls_whileUntil: {
+    jsonConfig: {
+      "type": "controls_whileUntil",
+      "message0": "%1 %2 %3",
+      "args0": [
+        {
+          "type": "field_image",
+          "src": repeatImage,
+          "width": 25,
+          "height": 25,
+          "alt": "循环"
+        },
+        {
+          "type": "field_dropdown",
+          "name": "MODE",
+          "options": [
+            ["当", "WHILE"],
+            ["直到", "UNTIL"]
+          ]
+        },
+        {
+          "type": "input_value",
+          "name": "CONDITION",
+          "check": "Boolean"
+        }
+      ],
+      "message1": "执行 %1",
+      "args1": [
+        {
+          "type": "input_statement",
+          "name": "DO"
+        }
+      ],
+      "previousStatement": null,
+      "nextStatement": null,
+      "colour": "#5BA55B",
+      "tooltip": "当条件为真时重复执行内部代码",
+      "helpUrl": ""
+    },
+    isGeneral: true // 标记为通用积木
+  },
   // 当经过某个形状的积木(可作为参数使用的value类型)
   when_passed: {
     jsonConfig: {
@@ -387,6 +429,18 @@ const availableBlocks = {
     },
     isGeneral: true
   },
+  // 是否到达终点积木
+  is_at_end: {
+    jsonConfig: {
+      "type": "is_at_end",
+      "message0": "到达终点",
+      "output": "Boolean",
+      "colour": 10,
+      "tooltip": "检查角色是否到达终点位置",
+      "helpUrl": ""
+    },
+    isGeneral: true
+  },
   // 特殊积木 - 可根据配置动态加载
   pause: {
     jsonConfig: {
@@ -541,6 +595,9 @@ const availableGenerators = {
     const shape = block.getFieldValue('SHAPE');
     return [`whenPassed('${shape}')`, javascriptGenerator.ORDER_FUNCTION_CALL];
   },
+  is_at_end: function(block) {
+    return [`isAtEnd()`, javascriptGenerator.ORDER_FUNCTION_CALL];
+  },
   // 条件判断生成器 - 使用Blockly默认实现方式确保兼容性
   controls_if: function(block) {
     let code = '';
@@ -582,6 +639,13 @@ ${javascriptGenerator.prefixLines(elseCode, javascriptGenerator.INDENT)}}
     const code = `for (let i = 0; i < ${repeats}; i++) {\n${javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT)}}\n`;
     return code;
   },
+  controls_whileUntil: function(block) {
+    const until = block.getFieldValue('MODE') === 'UNTIL';
+    const condition = javascriptGenerator.valueToCode(block, 'CONDITION', javascriptGenerator.ORDER_NONE) || 'false';
+    const branch = javascriptGenerator.statementToCode(block, 'DO');
+    const code = until ? `while (!((${condition})) && loopCount < 100) {\n${javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT)}loopCount++;\n}` : `while ((${condition}) && loopCount < 100) {\n${javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT)}loopCount++;\n}`;
+    return code;
+  },
   // 特殊生成器 - 可根据配置动态加载
   pause: function(block) {
     const seconds = block.getFieldValue('SECONDS');
@@ -640,6 +704,9 @@ const availablePythonGenerators = {
     const shape = block.getFieldValue('SHAPE');
     return [`when_passed('${shape}')`, pythonGenerator.ORDER_FUNCTION_CALL];
   },
+  is_at_end: function(block) {
+    return [`is_at_end()`, pythonGenerator.ORDER_FUNCTION_CALL];
+  },
   // 条件判断生成器
   controls_if: function(block) {
     const n = block.elseifCount_;
@@ -679,6 +746,13 @@ ${pythonGenerator.prefixLines(elseCode, pythonGenerator.INDENT)}
     const code = `for i in range(${repeats}):\n${pythonGenerator.prefixLines(branch, pythonGenerator.INDENT)}\n`;
     return code;
   },
+  controls_whileUntil: function(block) {
+    const until = block.getFieldValue('MODE') === 'UNTIL';
+    const condition = pythonGenerator.valueToCode(block, 'CONDITION', pythonGenerator.ORDER_NONE) || 'False';
+    const branch = pythonGenerator.statementToCode(block, 'DO');
+    const code = until ? `while not (${condition}) and loop_count < 100:\n${pythonGenerator.prefixLines(branch, pythonGenerator.INDENT)}loop_count += 1\n` : `while (${condition}) and loop_count < 100:\n${pythonGenerator.prefixLines(branch, pythonGenerator.INDENT)}loop_count += 1\n`;
+    return code;
+  },
   // 特殊生成器 - 可根据配置动态加载
   pause: function(block) {
     const seconds = block.getFieldValue('SECONDS');

+ 12 - 1
src/components/blockly/MapGame.vue

@@ -592,6 +592,7 @@ function generateToolboxXml() {
       <block type="pickup_item"></block>
       <block type="use_item"></block>
       <block type="when_passed"></block>
+      <block type="is_at_end"></block>
   `;
 
   // 确保blocklySpecialBlocks是数组
@@ -615,6 +616,7 @@ function generateToolboxXml() {
     </category>
     <category name="循环" colour="160">
       <block type="controls_repeat_ext"></block>
+      <block type="controls_whileUntil"></block>
     </category>
     <category name="数学" colour="60">
       <block type="math_number"></block>
@@ -865,7 +867,7 @@ const runCode = async () => {
             reject(new Error('执行已取消'));
           });
 
-          const wrappedCode = `(async () => { ${code} })()`;
+          const wrappedCode = `(async () => { let loopCount = 0; ${code} })()`;
           await new Function(wrappedCode)();
           resolve();
         } catch (error) {
@@ -1233,6 +1235,15 @@ window.turnAround = async function() {
   await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
 };
 
+// 检查是否到达终点
+window.isAtEnd = function() {
+  const playerX = Math.round(playerPosition.value.x);
+  const playerY = Math.round(playerPosition.value.y);
+  const endX = endPoint.value.x;
+  const endY = endPoint.value.y;
+  return playerX === endX && playerY === endY;
+};
+
 // 拾取物品函数
 window.pickupItem = async function()  {
   if (shouldStopExecution || isColliding.value || isSliding.value) {

+ 8 - 2
src/components/study/SelfDirectedLearning.vue

@@ -855,7 +855,7 @@ const generateVoiceover = async (lessonIndex, sectionIndex, dialogueIndex) => {
 
   const dialogue = section.dialogues[dialogueIndex]
 
-  // 只处理数字人对话和提问
+  // 只处理数字人对话和提问、诗词
   if (dialogue.type === 'user') {
     return
   }
@@ -869,10 +869,16 @@ const generateVoiceover = async (lessonIndex, sectionIndex, dialogueIndex) => {
     return
   }
   try {
+    // 根据对话类型设置不同的command
+    const command = dialogue.type === 'poem'
+        ? "要有感情的朗读诗词语句,要符合诗词的节奏和韵律。"
+        : null
+
     // 调用后端API将文本转成语音
     const response = await textToSpeech({
       roleId: role.id,
-      content: dialogue.content
+      content: dialogue.content,
+      command: command
     })
 
     // 将返回的URL赋值给对话

+ 7 - 12
src/router/index.js

@@ -115,6 +115,10 @@ const routes = [
     path: '/virtual-laboratory',
     component: () => import('../views/virtuallaboratory/index.vue')
   },
+  // 智能台灯
+  { path: '/smartDeskLamp', component: () => import('../views/virtuallaboratory/blockly/SmartDeskLamp.vue') },
+  // 智能家居
+  { path: '/smartHome', component: () => import('../views/virtuallaboratory/blockly/SmartHome.vue') },
   // AI 古诗
   {
     path: '/ai-poetry',
@@ -126,13 +130,6 @@ const routes = [
     path: '/blocklyHome',
     component: () => import('../views/programming/ProgrammingGame.vue')
   },
-  // Blockly
-  { path: '/blockly', component: () => import('../views/blockly/Blockly.vue') },
-  // Blockly2
-  { path: '/blockly2', component: () => import('../views/blockly/Blockly2.vue') },
-  { path: '/mapGame', component: () => import('../views/blockly/MapGame.vue') },
-  // 编程游戏列表
-  { path: '/programming02', component: () => import('../views/gamepage/GameIndex.vue') },
   // 编程课列表
   {
     path: '/programmingList',
@@ -194,7 +191,9 @@ const homeRoutes = {
     '/ai-grandcanal',
     '/ai-plantexperts',
     '/virtual-laboratory',
-    '/ai-poetry'
+    '/smartHome',
+    '/smartDeskLamp',
+    '/ai-poetry',
   ]
 }
 
@@ -203,10 +202,6 @@ const blocklyRoutes = {
   login: '/blockly-login',
   role: 'blockly',
   children: [
-    '/blockly',
-    '/blockly2',
-    '/mapGame',
-    '/programming02',
     '/programmingList',
     '/programmingCourset',
     '/interface'

+ 0 - 2050
src/views/blockly/MapGame.vue

@@ -1,2050 +0,0 @@
-<template>
-  <div class="map-game-container">
-    <!-- 标题栏 -->
-    <div class="title-box">
-      <div class="box-icon" @click="navigateBack">
-        <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
-        {{ gameTitle }}
-      </div>
-      <!-- 游戏编号 -->
-      <div class="game-badge">{{ gameSort }}</div>
-    </div>
-
-    <div class="content">
-      <!-- 地图显示区域 -->
-      <div class="map-section">
-        <!-- 内容简介提示 -->
-        <div v-if="currentGameData?.info" class="info-message-container">
-          <div class="message-item">
-            <div class="avatar">
-              <img src="@/assets/images/xiaozhi2.png" alt="头像" class="avatar-image" />
-            </div>
-            <p v-if="currentGameData?.info" v-html="currentGameData?.info"></p>
-          </div>
-        </div>
-
-        <div class="map-container">
-          <!-- 地图背景 -->
-          <div class="map-background">
-            <img :src="mapBackground" alt="地图背景" class="map-image" @load="onMapImageLoad" />
-
-            <!-- 可行走区域标记 -->
-            <div
-                v-for="(point, index) in walkablePoints"
-                :key="index"
-                class="walkable-point"
-                :style="getPointStyle(point)"
-            >
-            </div>
-
-            <!-- 玩家角色 -->
-            <div
-                class="player"
-                :style="playerStyle"
-                :class="{ 'collision': isColliding, 'success': hasReachedEnd }"
-            >
-            </div>
-            <!-- 携带物品容器 -->
-            <div class="carried-items-container" v-show="gameState.player.carriedItems.length > 0">
-              <div
-                  v-for="(item, index) in gameState.player.carriedItems"
-                  :key="index"
-                  class="carried-item"
-                  :style="getCarriedItemStyle(index, item)"
-              ></div>
-            </div>
-          </div>
-
-          <!-- 游戏状态提示 -->
-          <div v-if="gameMessage" :class="['game-message', messageType]">
-            {{ gameMessage }}
-          </div>
-        </div>
-      </div>
-
-      <!-- Blockly工作区 -->
-      <div class="blockly-section">
-        <div class="toolbox-section" style="display: none;">
-          <h2>工具箱</h2>
-          <div id="toolbox">
-            <!-- 移动控制积木 -->
-            <category name="移动控制" colour="%{BKY_MOTION_HUE}">
-              <block type="move_forward"></block>
-              <block type="turn_left"></block>
-              <block type="turn_right"></block>
-              <block type="turn_around"></block>
-              <block type="pickup_item"></block>
-              <block type="use_item"></block>
-            </category>
-
-            <!-- 逻辑控制积木 -->
-            <category name="逻辑" colour="%{BKY_LOGIC_HUE}">
-              <block type="controls_if"></block>
-              <block type="logic_compare"></block>
-              <block type="logic_operation"></block>
-              <block type="logic_boolean"></block>
-            </category>
-
-            <!-- 循环控制积木 -->
-            <category name="循环" colour="%{BKY_LOOPS_HUE}">
-              <block type="controls_repeat_ext"></block>
-              <!--              <block type="controls_whileUntil"></block>-->
-            </category>
-
-            <!-- 数学运算积木 -->
-            <category name="数学" colour="%{BKY_MATH_HUE}">
-              <block type="math_number"></block>
-              <block type="math_arithmetic"></block>
-            </category>
-          </div>
-        </div>
-
-        <div class="workspace-section">
-          <div class="controls">
-            <button id="runCode" @click="runCode">运行代码</button>
-            <button @click="clearWorkspace">清空工作区</button>
-            <button @click="resetPlayer">重置玩家</button>
-          </div>
-
-          <div id="blocklyDiv"></div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import {ref, onMounted, onUnmounted, reactive, computed, nextTick} from 'vue';
-import { useRouter, useRoute } from 'vue-router';
-import { ArrowLeftBold } from '@element-plus/icons-vue';
-import * as Blockly from "blockly";
-import 'blockly/msg/zh-hans';
-import { javascriptGenerator } from "blockly/javascript";
-import playerImage from '@/assets/images/blockly/user.png';
-
-// 游戏接口数据
-import { getMapGameById } from '@/api/blockly/game.js';
-import { BLOCKLY_MAP_TYPE_DICT } from '@/api/blockly/blockly.js';
-
-// 配置常量
-const CONFIG = {
-  // 动画时长配置(毫秒)
-  ANIMATION: {
-    MOVE_DURATION: 500,      // 移动动画持续时间
-    ROTATE_DURATION: 500,    // 旋转动画持续时间(左转/右转)
-    TURN_AROUND_DURATION: 750, // 向后转动画持续时间
-  },
-  // 延迟配置(毫秒)
-  DELAY: {
-    ACTION_DELAY: 200,       // 每次动作后的延迟时间
-    COLLISION_DELAY: 300,    // 碰撞后的延迟时间
-    RESET_DELAY: 300,        // 重置后的延迟时间
-    MESSAGE_DISPLAY: 2000,   // 消息显示时间
-    COLLISION_RESET: 1000,   // 碰撞状态重置时间
-    LOOP_PREVENTION: 10,     // 循环防止UI阻塞的延迟
-    ITEMS_APPEAR: 300,      // 物品出现延迟时间
-    ITEMS_FLIGHT_ANIMATION_DELAY: 800, // 飞行动画延迟时间
-  },
-  // 游戏配置
-  GAME: {
-    MAX_LOOP_COUNT: 100,     // 最大循环次数
-    DIRECTIONS: {
-      UP: 0,
-      RIGHT: 1,
-      DOWN: 2,
-      LEFT: 3
-    }
-  },
-  // 样式配置
-  STYLES: {
-    DEFAULT_TILE_SIZE: 143,  // 默认瓦片大小
-    PLAYER_SIZE_RATIO: 0.8,   // 玩家大小占瓦片的比例
-    PLAYER_SIZE_MARGIN: 0.1   // 玩家大小占瓦片的比例
-  },
-  //提示语
-  TIPS: {
-    NO_ENTRY: '当前位置无通路,无法移动',
-    UNFINISHED: '任务未完成!',
-    FINISH: '恭喜你到达终点!',
-    PICKUP_ITEM: '拾取物品成功!',
-    NULL_PICKUP_ITEM: '当前位置没有可拾取的物品',
-    USE_ITEM_SUCCESS: '使用物品成功',
-    USE_SPECIAL_ITEM: '需要特殊物品才能使用',
-    NO_USE_ITEM: '当前位置不需要使用物品',
-  }
-};
-
-// 路由和游戏状态
-const router = useRouter();
-const route = useRoute();
-const gameTitle = ref('地图游戏编程'); // 默认标题
-const currentGameData = ref(null);
-const playerInitialDirection = ref(0); // 人物初始朝向
-const gameSort = ref('Game1'); // 默认排序
-
-// 运行控制标志
-let shouldStopExecution = false;
-let currentExecutionPromise = null;
-let executionAbortController = null;
-// 添加响应式的容器尺寸
-const mapContainerDimensions = ref({ width: 0, height: 0 });
-
-// Blockly相关状态
-let workspace = null;
-
-// 使用 Map 存储可行走点及其类型,提高查询效率
-let walkablePointsMap = new Map();
-
-// 创建游戏状态的响应式对象
-const gameState = reactive({
-  // 地图配置信息
-  mapConfig: {
-    // 地图背景图片路径
-    background: '',
-    // 每个瓦片的尺寸(像素)
-    tileSize: CONFIG.STYLES.DEFAULT_TILE_SIZE,
-  },
-
-  // 玩家相关状态
-  player: {
-    // 玩家当前位置坐标
-    position: {},
-    // 玩家当前朝向:0=上, 1=右, 2=下, 3=左
-    direction: 1,
-    // 是否正在发生碰撞
-    isColliding: false,
-    // 是否已到达终点
-    hasReachedEnd: false,
-    // 是否正在冰块上滑行
-    isSliding: false,
-    // 携带的物品数组
-    carriedItems: [],
-  },
-
-  // 游戏状态信息
-  status: {
-    // 当前显示的游戏消息
-    message: '',
-    // 消息类型(如success、error、info等)
-    messageType: ''
-  },
-
-  // 地图数据信息
-  mapData: {
-    // 游戏起点位置
-    startPoint: {},
-    // 游戏终点位置
-    endPoint: {},
-    // 地图上所有可行走的点坐标集合,添加type属性区分普通点和冰块
-    walkablePoints: [],
-    // 保存原始的可行走点数据,用于重置
-    originalWalkablePoints: [],
-  }
-});
-// BLOCKLY_MAP_TYPE_DICT和BLOCKLY_CUSTOMIZE_DICT已从blockly.js导入
-
-// 计算属性 - 提高性能和可读性
-const mapBackground = computed(() => gameState.mapConfig.background);
-// const tileSize = computed(() => gameState.mapConfig.tileSize);
-const walkablePoints = computed(() => gameState.mapData.walkablePoints);
-const startPoint = computed(() => gameState.mapData.startPoint);
-const endPoint = computed(() => gameState.mapData.endPoint);
-const playerPosition = computed(() => gameState.player.position);
-const playerDirection = computed(() => gameState.player.direction);
-const isColliding = computed(() => gameState.player.isColliding);
-const hasReachedEnd = computed(() => gameState.player.hasReachedEnd);
-const gameMessage = computed(() => gameState.status.message);
-const messageType = computed(() => gameState.status.messageType);
-const isSliding = computed(() => gameState.player.isSliding);
-
-// 计算玩家图片路径,优先使用接口数据
-const playerImageSrc = computed(() => {
-  if (currentGameData.value && currentGameData.value.userImage) {
-    return currentGameData.value.userImage.trim();
-  }
-  return playerImage;
-});
-
-// 地图图片加载完成后更新容器尺寸
-const onMapImageLoad = () => {
-  updateMapContainerDimensions();
-};
-
-// 计算实际瓦片大小(基于容器尺寸和地图数据)
-const tileSize = computed(() => {
-  if (mapContainerDimensions.value.width === 0 || mapContainerDimensions.value.height === 0) {
-    return gameState.mapConfig.tileSize;
-  }
-
-  // 获取地图数据中的最大坐标
-  let size = JSON.parse(gameState.mapConfig.tileSize);
-  // 计算基于容器的瓦片大小,确保地图完全可见
-  const tileWidth = mapContainerDimensions.value.width / size.x;
-  const tileHeight = mapContainerDimensions.value.height / size.y;
-
-  // 返回较小的值以确保地图完全可见
-  return Math.min(tileWidth, tileHeight);
-});
-
-// 生命周期钩子
-onMounted(async () => {
-  // 获取游戏数据
-  await fetchGameData();
-  // 初始化可行走点集合
-  initWalkablePointsSet();
-
-  // 注册自定义积木
-  registerCustomBlocks();
-  // 注册JavaScript生成器
-  registerJavaScriptGenerators();
-  // 初始化Blockly工作区
-  initBlockly();
-  // 重置玩家位置
-  resetPlayer();
-
-  await nextTick();
-  // 添加对窗口大小变化的监听
-  updateMapContainerDimensions();
-  window.addEventListener('resize', updateMapContainerDimensions);
-});
-
-// 获取游戏数据
-const fetchGameData = async () => {
-  try {
-    const gameId = route.query.gameId;
-    const nameFromRoute = route.query.gameName;
-    const sortFromRoute = route.query.gameSort;
-
-    if (nameFromRoute) {
-      gameTitle.value = nameFromRoute;
-    }
-    if (sortFromRoute) {
-      gameSort.value = sortFromRoute;
-    }
-
-    let mapGameData = await getMapGameById(gameId);
-    if (mapGameData.code === 0) {
-      currentGameData.value = mapGameData?.data;
-
-      // 使用接口数据
-      if (currentGameData.value && currentGameData.value.sort) {
-        let sortNum = currentGameData.value.sort;
-        gameSort.value = sortNum > 9 ? `Game${sortNum}` : `Game${sortNum}`;
-      }
-
-      await updateGameStateFromData(currentGameData.value);
-
-      // 数据更新后强制刷新容器尺寸(等待DOM更新)
-      await nextTick();
-      updateMapContainerDimensions();
-    }
-  } catch (error) {
-    console.error('获取游戏数据失败:', error);
-  }
-};
-
-// 根据获取到的数据更新游戏状态
-const updateGameStateFromData = (gameData) => {
-  try {
-    // 更新地图配置
-    gameState.mapConfig.background = gameData.mapBackground ? gameData.mapBackground.trim() : '';
-    gameState.mapConfig.tileSize = gameData.mapTileSize || CONFIG.STYLES.DEFAULT_TILE_SIZE;
-
-    // 更新玩家方向
-    if (gameData.userDirection) {
-      playerInitialDirection.value = gameData.userDirection;
-    }
-
-    // 更新地图数据
-    // 地图起点
-    if (gameData.mapStartPoint) {
-      const startPoint = JSON.parse(gameData.mapStartPoint);
-      gameState.mapData.startPoint = { x: startPoint.x, y: startPoint.y };
-      gameState.player.position = { x: startPoint.x, y: startPoint.y };
-    }
-    // 地图终点
-    if (gameData.mapEndPoint) {
-      const endPoint = JSON.parse(gameData.mapEndPoint);
-      gameState.mapData.endPoint = { x: endPoint.x, y: endPoint.y };
-    }
-    if (gameData.mapWalkablePoints) {
-      gameState.mapData.walkablePoints = JSON.parse(gameData.mapWalkablePoints);
-    }
-    // 重新初始化可行走点集合
-    initWalkablePointsSet();
-  } catch (error) {
-    console.error('更新游戏状态失败:', error);
-  }
-};
-
-// 初始化可行走点映射
-function initWalkablePointsSet() {
-  walkablePointsMap.clear();
-  gameState.mapData.walkablePoints.forEach(point => {
-    walkablePointsMap.set(`${point.x},${point.y}`, point);
-  });
-  // 保存原始的可行走点数据,用于重置
-  gameState.mapData.originalWalkablePoints = JSON.parse(JSON.stringify(gameState.mapData.walkablePoints));
-}
-
-// 可行走检查函数
-function isWalkable(x, y) {
-  return walkablePointsMap.has(`${x},${y}`);
-}
-
-// 计算点的样式
-function getPointStyle(point) {
-  const style = {
-    left: point.x * tileSize.value - tileSize.value + 'px',
-    top: point.y * tileSize.value - tileSize.value + 'px',
-    width: tileSize.value + 'px',
-    height: tileSize.value + 'px',
-  };
-
-  // 如果point有img属性,则添加图标
-  if (point.img) {
-    const iconSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO;
-    const marginSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN;
-
-    // 重置可能影响背景图显示的样式
-    style.backgroundColor = 'transparent';
-    style.backgroundImage = `url(${point.img})`;
-    style.backgroundSize = 'contain';
-    style.backgroundPosition = 'center';
-    style.backgroundRepeat = 'no-repeat';
-
-    // 设置与玩家相同的宽高和边距
-    style.width = iconSize + 'px';
-    style.height = iconSize + 'px';
-    style.margin = marginSize + 'px';
-  }
-
-  return style;
-}
-
-// 计算玩家样式
-const playerStyle = computed(() => ({
-  left: playerPosition.value.x * tileSize.value - tileSize.value + 'px',
-  top: playerPosition.value.y * tileSize.value - tileSize.value + 'px',
-  transform: `rotate(${playerDirection.value * 90}deg)`,
-  '--player-rotation': `${playerDirection.value * 90}deg`,
-  '--player-image': `url(${playerImageSrc.value})`,
-  width: (tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO) + 'px',
-  height: (tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO) + 'px',
-  margin: (tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN) + 'px',
-}));
-
-// 计算携带物品样式
-function getCarriedItemStyle(index, item) {
-  const baseSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO * 0.3;
-
-  return {
-    position: 'relative',
-    width: baseSize + 'px',
-    height: baseSize + 'px',
-    backgroundSize: 'contain',
-    backgroundPosition: 'center',
-    backgroundRepeat: 'no-repeat',
-    backgroundImage: `url(${item.img})`,
-    animationDelay: index * 0.1 + 's'
-  };
-}
-
-// 导航返回
-function navigateBack() {
-  router.back();
-}
-
-// 注册自定义积木
-function registerCustomBlocks() {
-  // 向前移动积木
-  Blockly.Blocks['move_forward'] = {
-    init: function() {
-      this.jsonInit({
-        "type": "move_forward",
-        "message0": "向前移动",
-        "previousStatement": null,
-        "nextStatement": null,
-        "colour": 230,
-        "tooltip": "控制角色向前移动一格",
-        "helpUrl": ""
-      });
-    }
-  };
-
-  // 向左转积木
-  Blockly.Blocks['turn_left'] = {
-    init: function() {
-      this.jsonInit({
-        "type": "turn_left",
-        "message0": "向左转",
-        "previousStatement": null,
-        "nextStatement": null,
-        "colour": 230,
-        "tooltip": "控制角色向左转",
-        "helpUrl": ""
-      });
-    }
-  };
-
-  // 向右转积木
-  Blockly.Blocks['turn_right'] = {
-    init: function() {
-      this.jsonInit({
-        "type": "turn_right",
-        "message0": "向右转",
-        "previousStatement": null,
-        "nextStatement": null,
-        "colour": 230,
-        "tooltip": "控制角色向右转",
-        "helpUrl": ""
-      });
-    }
-  };
-
-  // 向后转积木
-  Blockly.Blocks['turn_around'] = {
-    init: function() {
-      this.jsonInit({
-        "type": "turn_around",
-        "message0": "向后转",
-        "previousStatement": null,
-        "nextStatement": null,
-        "colour": 230,
-        "tooltip": "控制角色向后转",
-        "helpUrl": ""
-      });
-    }
-  };
-
-  // 拾取物品积木
-  Blockly.Blocks['pickup_item'] = {
-    init: function() {
-      this.jsonInit({
-        "type": "pickup_item",
-        "message0": "拾取物品",
-        "previousStatement": null,
-        "nextStatement": null,
-        "colour": 30,
-        "tooltip": "尝试拾取当前位置的物品",
-        "helpUrl": ""
-      });
-    }
-  };
-
-  // 使用物品积木
-  Blockly.Blocks['use_item'] = {
-    init: function() {
-      this.jsonInit({
-        "type": "use_item",
-        "message0": "使用物品",
-        "previousStatement": null,
-        "nextStatement": null,
-        "colour": 30,
-        "tooltip": "在当前位置使用物品",
-        "helpUrl": ""
-      });
-    }
-  };
-}
-
-// 注册JavaScript生成器
-function registerJavaScriptGenerators() {
-  // 向前移动生成器
-  javascriptGenerator.forBlock['move_forward'] = function(block) {
-    return 'await moveForward();\n';
-  };
-
-  // 向左转生成器
-  javascriptGenerator.forBlock['turn_left'] = function(block) {
-    return 'await turnLeft();\n';
-  };
-
-  // 向右转生成器
-  javascriptGenerator.forBlock['turn_right'] = function(block) {
-    return 'await turnRight();\n';
-  };
-
-  // 向后转生成器
-  javascriptGenerator.forBlock['turn_around'] = function(block) {
-    return 'await turnAround();\n';
-  };
-
-  // 拾取物品生成器
-  javascriptGenerator.forBlock['pickup_item'] = function(block) {
-    return 'await pickupItem();\n';
-  };
-
-  // 使用物品生成器
-  javascriptGenerator.forBlock['use_item'] = function(block) {
-    return 'await useItem();\n';
-  };
-
-  // 为重复循环块注册自定义生成器,确保支持异步操作
-  javascriptGenerator.forBlock['controls_repeat_ext'] = function(block) {
-    const repeats = javascriptGenerator.valueToCode(block, 'TIMES', javascriptGenerator.ORDER_ATOMIC) || '0';
-
-    // 确保获取到的是数字类型,如果是字符串需要转换
-    const safeRepeats = `(function() {
-      const num = Number(${repeats});
-      return isNaN(num) ? 0 : Math.max(0, Math.floor(num));
-    })()`;
-
-    // 获取循环体代码
-    const branch = javascriptGenerator.statementToCode(block, 'DO');
-
-    // 生成支持异步的循环代码
-    let code = `for (let i = 0; i < ${safeRepeats}; i++) {\n`;
-    code += javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT);
-    code += '}\n';
-
-    return code;
-  };
-
-  // 为while/until循环块注册自定义生成器
-  javascriptGenerator.forBlock['controls_whileUntil'] = function(block) {
-    const until = block.getFieldValue('MODE') === 'UNTIL';
-    const condition = javascriptGenerator.valueToCode(block, 'CONDITION',
-        javascriptGenerator.ORDER_NONE) || 'false';
-    const branch = javascriptGenerator.statementToCode(block, 'DO');
-
-    // 修复变量作用域问题,使用IIFE包装循环
-    let code = '(async function() {\n';
-    code += '  let loopCount = 0;\n';
-    code += until ? '  while (!((' + condition + ')) && loopCount < ' + CONFIG.GAME.MAX_LOOP_COUNT + ') {\n' :
-        '  while (((' + condition + ')) && loopCount < ' + CONFIG.GAME.MAX_LOOP_COUNT + ') {\n';
-    code += javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT + '  ');
-    code += '    loopCount++';
-    code += '    await new Promise(resolve => setTimeout(resolve, ' + CONFIG.DELAY.LOOP_PREVENTION + '));\n'; // 防止UI阻塞
-    code += '  }\n';
-    code += '})();\n';
-
-    return code;
-  };
-
-  // 为text_print块添加生成器,用于调试
-  javascriptGenerator.forBlock['text_print'] = function(block) {
-    const msg = javascriptGenerator.valueToCode(block, 'TEXT', javascriptGenerator.ORDER_NONE) || '';
-    return msg;
-  };
-}
-
-const setupBlocklyChineseLocale = () => {
-  // 使用扩展方式覆盖默认的英文文本为中文
-  const locale = {
-    // 逻辑积木中文配置
-    CONTROLS_IF_MSG_IF: "如果",
-    CONTROLS_IF_MSG_ELSEIF: "否则如果",
-    CONTROLS_IF_MSG_ELSE: "否则",
-    CONTROLS_IF_MSG_THEN: "执行",
-    CONTROLS_IF_MSG_DO: "执行",
-    CONTROLS_IF_TOOLTIP_1: "如果条件为真,则执行相应的代码。",
-    CONTROLS_IF_TOOLTIP_2: "如果条件为真,则执行相应的代码;否则执行其他代码。",
-    CONTROLS_IF_TOOLTIP_3: "如果条件为真,则执行相应的代码;否则检查其他条件。",
-    CONTROLS_IF_TOOLTIP_4: "如果条件为真,则执行相应的代码;否则检查其他条件,如果都不满足则执行最后代码。",
-
-    // 控制块的弹出菜单文本
-    CONTROLS_IF_IF: "如果",
-    CONTROLS_IF_ELSEIF: "否则如果",
-    CONTROLS_IF_ELSE: "否则",
-    CONTROLS_IF_IF_TITLE: "如果",
-    CONTROLS_IF_IF_TITLE_IF: "如果",
-    CONTROLS_IF_ELSEIF_TITLE_ELSEIF: "否则如果",
-    CONTROLS_IF_ELSE_TITLE: "否则",
-    CONTROLS_IF_ELSE_TITLE_ELSE: "否则",
-
-    // 条件块的提示文本和帮助URL
-    CONTROLS_IF_HELPURL: "条件语句帮助",
-    CONTROLS_IF_TOOLTIP_IF: "添加或删除条件。",
-    CONTROLS_IF_TOOLTIP_ELSE: "添加或删除否则块。",
-
-    // 添加设置按钮相关的中文配置
-    CONTROLS_IF_ELSEIF_TOOLTIP: "否则如果条件为真,则执行相应的代码。",
-    CONTROLS_IF_ELSE_TOOLTIP: "否则执行相应的代码。",
-
-    // 比较运算符中文配置
-    LOGIC_COMPARE_EQ: "等于",
-    LOGIC_COMPARE_NEQ: "不等于",
-    LOGIC_COMPARE_LT: "小于",
-    LOGIC_COMPARE_LTE: "小于等于",
-    LOGIC_COMPARE_GT: "大于",
-    LOGIC_COMPARE_GTE: "大于等于",
-    LOGIC_COMPARE_TOOLTIP_EQ: "比较两个值是否相等。",
-    LOGIC_COMPARE_TOOLTIP_NEQ: "比较两个值是否不相等。",
-    LOGIC_COMPARE_TOOLTIP_LT: "比较第一个值是否小于第二个值。",
-    LOGIC_COMPARE_TOOLTIP_LTE: "比较第一个值是否小于或等于第二个值。",
-    LOGIC_COMPARE_TOOLTIP_GT: "比较第一个值是否大于第二个值。",
-    LOGIC_COMPARE_TOOLTIP_GTE: "比较第一个值是否大于或等于第二个值。",
-
-    // 逻辑运算中文配置
-    LOGIC_OPERATION_AND: "且",
-    LOGIC_OPERATION_OR: "或",
-    LOGIC_OPERATION_TOOLTIP_AND: "如果两个条件都为真,则结果为真。",
-    LOGIC_OPERATION_TOOLTIP_OR: "如果任一条件为真,则结果为真。",
-
-    // 布尔值配置
-    LOGIC_BOOLEAN_TRUE: "真",
-    LOGIC_BOOLEAN_FALSE: "假",
-    LOGIC_BOOLEAN_TOOLTIP: "返回一个布尔值:真或假。",
-
-    // 循环积木中文配置
-    CONTROLS_REPEAT_TITLE: "重复%1次",
-    CONTROLS_REPEAT_TOOLTIP: "重复执行内部代码指定次数。",
-    CONTROLS_REPEAT_MSG_DO: "执行",
-    CONTROLS_REPEAT_INPUT_DO: "执行",
-    CONTROLS_WHILEUNTIL_MSG_DO: "执行",
-    CONTROLS_WHILEUNTIL_INPUT_DO: "执行",
-    CONTROLS_FOR_MSG_DO: "执行",
-    CONTROLS_FOR_INPUT_DO: "执行",
-    CONTROLS_FOR_EACH_MSG_DO: "执行",
-    CONTROLS_FOR_EACH_INPUT_DO: "执行",
-
-    // 数学积木中文配置
-    MATH_NUMBER_TOOLTIP: "一个数字。在编辑器中双击以更改。",
-    MATH_ADDITION_SYMBOL: "加",
-    MATH_SUBTRACTION_SYMBOL: "减",
-    MATH_MULTIPLICATION_SYMBOL: "乘",
-    MATH_DIVISION_SYMBOL: "除",
-    MATH_ARITHMETIC_TOOLTIP_ADD: "返回两个数的和。",
-    MATH_ARITHMETIC_TOOLTIP_SUBTRACT: "返回第一个数减去第二个数的差。",
-    MATH_ARITHMETIC_TOOLTIP_MULTIPLY: "返回两个数的积。",
-    MATH_ARITHMETIC_TOOLTIP_DIVIDE: "返回第一个数除以第二个数的商。"
-  };
-
-  // 使用Object.assign来合并配置,避免直接修改导入对象
-  Object.assign(Blockly.Msg, locale);
-}
-
-
-// 初始化Blockly工作区
-function initBlockly() {
-  // 应用中文配置
-  setupBlocklyChineseLocale();
-
-  const toolbox = document.getElementById('toolbox');
-  workspace = Blockly.inject('blocklyDiv', {
-    toolbox: toolbox,
-    collapse: false,
-    comments: true,
-    disable: false, // 设为false以允许编辑
-    maxBlocks: Infinity,
-    trashcan: true,
-    horizontalLayout: false,
-    toolboxPosition: 'start',
-    toolboxCollapse: false, // 设置工具箱默认展开
-    toolboxAlwaysExpanded: true, // 确保点击类别后保持展开状态
-    css: true,
-    media: 'https://unpkg.com/blockly/media/',
-    rtl: false,
-    scrollbars: true,
-    sounds: false, // 禁用声音以提高性能
-    oneBasedIndex: true,
-    grid: {
-      spacing: 20,
-      length: 3,
-      colour: "#ccc",
-      snap: true
-    },
-    zoom: {
-      controls: true,
-      wheel: true,
-      startScale: 1.0,
-      maxScale: 3,
-      minScale: 0.3,
-      scaleSpeed: 1.2
-    }
-  });
-}
-
-// 平滑移动函数
-async function smoothMoveTo(targetX, targetY) {
-  const startX = playerPosition.value.x;
-  const startY = playerPosition.value.y;
-
-  const startTime = performance.now();
-
-  // 使用Promise包装动画过程,使其可以await
-  return new Promise(resolve => {
-    function animate(currentTime) {
-      // 检查是否应该停止执行
-      if (shouldStopExecution) {
-        resolve();
-        return;
-      }
-
-      const elapsed = currentTime - startTime;
-      const progress = Math.min(elapsed / CONFIG.ANIMATION.MOVE_DURATION, 1); // 计算进度,最大为1
-
-      // 线性插值计算当前位置
-      const currentX = startX + (targetX - startX) * progress;
-      const currentY = startY + (targetY - startY) * progress;
-
-      gameState.player = {
-        ...gameState.player,
-        position: { x: currentX, y: currentY },
-      };
-
-      // 检查是否到达终点
-      if (progress < 1) {
-        // 继续动画
-        requestAnimationFrame(animate);
-      } else {
-        resolve(); // 动画完成
-      }
-    }
-
-    // 启动动画
-    requestAnimationFrame(animate);
-  });
-}
-
-// 处理地图类型逻辑
-async function switchMapType(type, isMapType = null) {
-  //取人物当前位置
-  let x = playerPosition.value.x;
-  let y = playerPosition.value.y;
-  let tileMap = walkablePointsMap.get(`${x},${y}`);
-
-  //判断是否是指定地图类型
-  if (isMapType) {
-    return isMapType === tileMap.type;
-  }
-
-  //移动前置
-  if (type === 0) {
-    //判断方块类型并处理逻辑
-    switch (tileMap.type) {
-      case BLOCKLY_MAP_TYPE_DICT.TASK:
-        await taskLogic(tileMap);
-        break;
-    }
-
-  }else {//移动后置
-
-    //判断方块类型并处理逻辑
-    switch (tileMap.type) {
-      case BLOCKLY_MAP_TYPE_DICT.ICE:
-        do {
-
-          showGameMessage(tileMap.tip, 'warning',300)
-
-
-          // 处理方块类型逻辑
-          await switchMapType(0);
-
-          console.log("滑行前位置:" + playerPosition.value.x + "," + playerPosition.value.y);
-          await slidingLogic();
-
-          tileMap = walkablePointsMap.get(`${playerPosition.value.x},${playerPosition.value.y}`);
-        }while (tileMap.type === BLOCKLY_MAP_TYPE_DICT.ICE && !isColliding.value)
-        break;
-      case BLOCKLY_MAP_TYPE_DICT.TRAP:
-        showGameMessage(tileMap.tip, 'error')
-        await handleWallCollision(tileMap.tip);
-        break;
-    }
-  }
-}
-
-// 处理冰块滑行逻辑
-async function slidingLogic() {
-  if (shouldStopExecution || isColliding.value) {
-    return;
-  }
-  gameState.player.isSliding = true;
-
-  try {
-    // 计算下一个位置
-    let nextX = playerPosition.value.x;
-    let nextY = playerPosition.value.y;
-
-    // 根据当前方向计算下一个位置
-    switch(playerDirection.value) {
-      case CONFIG.GAME.DIRECTIONS.UP: nextY--; break;
-      case CONFIG.GAME.DIRECTIONS.RIGHT: nextX++; break;
-      case CONFIG.GAME.DIRECTIONS.DOWN: nextY++; break;
-      case CONFIG.GAME.DIRECTIONS.LEFT: nextX--; break;
-    }
-
-    // 检查下一个位置是否可行走
-    if (isWalkable(nextX, nextY)) {
-
-      // 执行平滑移动到下一个位置
-      await smoothMoveTo(nextX, nextY);
-
-    } else {
-      // 使用统一的碰撞处理方法,但不等待延迟(因为slidingLogic不需要这个延迟)
-      await handleWallCollision();
-    }
-  } catch (error) {
-    console.error('滑行过程中发生错误:', error);
-  } finally {
-    // 无论如何都要确保滑行状态被重置
-    gameState.player.isSliding = false;
-  }
-}
-
-// 处理任务逻辑
-async function taskLogic(tileMap) {
-  if (shouldStopExecution || isColliding.value) {
-    return;
-  }
-
-  try {
-    // 判断当前位置是否有特殊需求
-    if (tileMap && tileMap.type === BLOCKLY_MAP_TYPE_DICT.TASK && tileMap.must === true && tileMap.status !== true) {
-      await handleWallCollision(tileMap.unfinishedTip);
-      return;
-    }
-  } catch (error) {
-    console.error('处理任务逻辑发生错误:', error);
-  }
-}
-
-// 物品拾取动画函数
-async function animateItemPickup(item, itemX, itemY) {
-  // 创建临时动画元素
-  const tempItem = document.createElement('div');
-  const iconSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO;
-  const marginSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN;
-
-  // 计算物品在地图上的实际位置
-  const itemLeft = itemX * tileSize.value - tileSize.value + marginSize;
-  const itemTop = itemY * tileSize.value - tileSize.value + marginSize;
-
-  // 平行移动到容器位置,同时调整大小
-  const finalSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO * 0.3;
-
-  // 获取携带物品容器的位置(左上角)
-  // 注意:这里不需要考虑当前已携带物品数量,因为物品还没被添加
-  let containerLeft = 30;
-  let containerTop = 30;
-
-  // 如果已经有物品,计算新物品应该出现的位置
-  if (gameState.player.carriedItems.length > 0) {
-    let containerSize = finalSize + 10;
-    containerLeft = 30 + gameState.player.carriedItems.length * containerSize;
-  }
-
-  // 设置临时元素样式
-  Object.assign(tempItem.style, {
-    position: 'absolute',
-    left: itemLeft + 'px',
-    top: itemTop + 'px',
-    width: iconSize + 'px',
-    height: iconSize + 'px',
-    backgroundImage: `url(${item.img})`,
-    backgroundSize: 'contain',
-    backgroundPosition: 'center',
-    backgroundRepeat: 'no-repeat',
-    zIndex: '100', // 确保在最上层
-    opacity: '0', // 初始完全透明
-    transform: 'scale(1)',
-  });
-
-  // 将临时元素添加到地图容器
-  const mapBackground = document.querySelector('.map-background');
-  if (!mapBackground) {
-    console.error('地图容器未找到');
-    return;
-  }
-  mapBackground.appendChild(tempItem);
-
-  // 触发淡入动画
-  tempItem.offsetHeight;
-  tempItem.style.transition = 'opacity ' + CONFIG.DELAY.ITEMS_APPEAR + 'ms ease-out';
-  tempItem.style.opacity = '1'; // 完全显示
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_APPEAR));
-
-  // 移动动画
-  tempItem.style.transition = 'all ' + CONFIG.DELAY.ITEMS_FLIGHT_ANIMATION_DELAY + 'ms ease-out'; // 减慢动画速度
-  Object.assign(tempItem.style, {
-    left: containerLeft + 'px',
-    top: containerTop + 'px',
-    width: finalSize + 'px',
-    height: finalSize + 'px',
-    opacity: '0.8',
-    transform: 'scale(1)',
-  });
-
-  // 等待动画完成
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_FLIGHT_ANIMATION_DELAY));
-
-  // 移除临时元素
-  if (mapBackground.contains(tempItem)) {
-    mapBackground.removeChild(tempItem);
-  }
-}
-
-// 物品使用动画函数
-async function animateItemUse(item, itemIndex) {
-  // 创建临时动画元素
-  const tempItem = document.createElement('div');
-  const finalSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO * 0.3;
-  const iconSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_RATIO;
-  const marginSize = tileSize.value * CONFIG.STYLES.PLAYER_SIZE_MARGIN;
-
-  // 计算物品在物品栏中的初始位置
-  let startLeft = 30;
-  let startTop = 30;
-  let containerSize = finalSize + 10;
-
-  // 根据物品索引计算在物品栏中的位置
-  if (itemIndex > 0) {
-    startLeft = 30 + itemIndex * containerSize;
-  }
-
-  // 计算玩家当前位置(物品目标位置)
-  const playerLeft = playerPosition.value.x * tileSize.value - tileSize.value + marginSize;
-  const playerTop = playerPosition.value.y * tileSize.value - tileSize.value + marginSize;
-
-  // 获取玩家元素
-  const playerElement = document.querySelector('.player');
-  const originalPlayerZIndex = playerElement ? playerElement.style.zIndex : '';
-
-  // 获取当前位置的任务点元素
-  let taskPointElement = null;
-  const walkablePointsElements = document.querySelectorAll('.walkable-point');
-  walkablePointsElements.forEach(el => {
-    const rect = el.getBoundingClientRect();
-    const targetRect = {
-      left: playerLeft,
-      top: playerTop,
-      width: iconSize,
-      height: iconSize
-    };
-    // 简单判断元素是否在玩家位置附近
-    if (Math.abs(rect.left - targetRect.left) < iconSize &&
-        Math.abs(rect.top - targetRect.top) < iconSize) {
-      taskPointElement = el;
-    }
-  });
-
-  // 先将任务图标置顶盖住人物
-  if (taskPointElement) {
-    taskPointElement.style.zIndex = '150';
-  }
-
-  // 设置临时元素初始样式
-  Object.assign(tempItem.style, {
-    position: 'absolute',
-    left: startLeft + 'px',
-    top: startTop + 'px',
-    width: finalSize + 'px',
-    height: finalSize + 'px',
-    backgroundImage: `url(${item.img})`,
-    backgroundSize: 'contain',
-    backgroundPosition: 'center',
-    backgroundRepeat: 'no-repeat',
-    zIndex: '120',
-    transition: 'transform ' + CONFIG.DELAY.ITEMS_APPEAR + 'ms ease-out',
-    transform: 'scale(1)',
-  });
-
-  // 将临时元素添加到地图容器
-  const mapBackground = document.querySelector('.map-background');
-  if (!mapBackground) {
-    console.error('地图容器未找到');
-    return;
-  }
-  mapBackground.appendChild(tempItem);
-
-  // 准备漂移动画
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_APPEAR));
-
-  // 设置漂移动画样式
-  tempItem.style.transition = 'all 1s ease-out';
-  Object.assign(tempItem.style, {
-    left: playerLeft + 'px',
-    top: playerTop + 'px',
-    width: iconSize + 'px',
-    height: iconSize + 'px',
-  });
-
-  // 等待漂移到玩家位置
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_FLIGHT_ANIMATION_DELAY));
-
-  // 物品使用效果动画
-  tempItem.style.transition = 'transform 0.3s ease-in-out';
-  tempItem.style.transform = 'scale(1.2)';
-
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_APPEAR));
-
-  // 移除临时元素
-  if (mapBackground.contains(tempItem)) {
-    mapBackground.removeChild(tempItem);
-  }
-
-  // 延迟一段时间后将人物图标置顶,露出完整的人物图标
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ITEMS_APPEAR));
-
-  // 恢复层级关系
-  if (taskPointElement) {
-    taskPointElement.style.zIndex = '';
-  }
-
-  if (playerElement) {
-    playerElement.style.zIndex = originalPlayerZIndex || '';
-  }
-}
-
-// 拾取物品函数
-window.pickupItem = async function()  {
-  if (shouldStopExecution || isColliding.value || isSliding.value) {
-    return;
-  }
-
-  //取人物当前位置
-  let x = playerPosition.value.x;
-  let y = playerPosition.value.y;
-  let tileMap = walkablePointsMap.get(`${x},${y}`);
-
-  // 判断是否是要拾取的方块类型
-  if (tileMap && tileMap.type === BLOCKLY_MAP_TYPE_DICT.ITEM) {
-    showGameMessage(tileMap.tip || CONFIG.TIPS.PICKUP_ITEM, 'warning')
-
-    // 处理携带物品逻辑
-    if (tileMap && tileMap.img) {
-
-      // 从地图上移除图标(但保留点的可通行性)
-      const pointIndex = gameState.mapData.walkablePoints.findIndex(
-          p => p.x === x && p.y === y
-      );
-      if (pointIndex !== -1) {
-
-        // 保留点但移除img属性
-        const updatedPoint = { ...gameState.mapData.walkablePoints[pointIndex] };
-        delete updatedPoint.img;
-        gameState.mapData.walkablePoints.splice(pointIndex, 1, updatedPoint);
-        // 更新映射
-        walkablePointsMap.set(`${x},${y}`, updatedPoint);
-
-        // 执行物品拾取动画:放大晃动两下然后移动到左上角物品容器
-        await animateItemPickup(tileMap, x, y);
-
-        // 将物品添加到玩家携带物品中
-        gameState.player.carriedItems.push({
-          ...tileMap,
-          originalX: x,
-          originalY: y
-        });
-      }
-    }
-  } else {
-    showGameMessage(CONFIG.TIPS.NULL_PICKUP_ITEM, 'info')
-  }
-
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
-}
-
-// 使用物品函数
-window.useItem = async function() {
-  if (shouldStopExecution || isColliding.value || isSliding.value) {
-    return;
-  }
-
-  //取人物当前位置
-  let x = playerPosition.value.x;
-  let y = playerPosition.value.y;
-  let tileMap = walkablePointsMap.get(`${x},${y}`);
-
-  // 判断当前位置是否有特殊需求
-  if (tileMap && tileMap.type === BLOCKLY_MAP_TYPE_DICT.TASK) {
-    // 检查玩家是否携带了需要的物品
-    const requiredItems = tileMap.type;
-
-    let hasRequiredItem = false;
-    let itemIndex = -1;
-
-    if (gameState.player.carriedItems.length > 0) {
-      hasRequiredItem = true;
-      itemIndex = 0;
-    }
-
-    if (hasRequiredItem) {
-
-      // 获取要使用的物品
-      const itemToUse = gameState.player.carriedItems[itemIndex];
-      // 执行物品使用动画
-      await animateItemUse(itemToUse, itemIndex);
-      // 从携带物品中移除已使用的物品
-      gameState.player.carriedItems.splice(itemIndex, 1);
-
-      // 从地图上移除图标(但保留点的可通行性)
-      const pointIndex = gameState.mapData.walkablePoints.findIndex(
-          p => p.x === x && p.y === y
-      );
-      if (pointIndex !== -1) {
-
-        // 保留点但移除img属性并设置完成状态图标
-        const updatedPoint = { ...gameState.mapData.walkablePoints[pointIndex] };
-        updatedPoint.img = updatedPoint.endImg; // 设置完成状态图标
-        updatedPoint.status = true;
-        gameState.mapData.walkablePoints.splice(pointIndex, 1, updatedPoint);
-
-        // 更新映射
-        walkablePointsMap.set(`${x},${y}`, updatedPoint);
-      }
-
-      // 使用物品成功
-      showGameMessage(tileMap.finishedTip || CONFIG.TIPS.USE_ITEM_SUCCESS, 'success');
-
-    } else {
-      // 提示缺少所需物品
-      showGameMessage(tileMap.unfinishedTip || CONFIG.TIPS.USE_SPECIAL_ITEM, 'warning');
-    }
-  } else {
-    showGameMessage(CONFIG.TIPS.NO_USE_ITEM, 'info');
-  }
-
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
-}
-
-// 向前移动
-window.moveForward = async function() {
-  if (shouldStopExecution || isColliding.value || isSliding.value) {
-    return;
-  }
-
-  let newX = playerPosition.value.x;
-  let newY = playerPosition.value.y;
-
-  // 向前移动
-  switch(playerDirection.value) {
-    case CONFIG.GAME.DIRECTIONS.UP: newY--; break;
-    case CONFIG.GAME.DIRECTIONS.RIGHT: newX++; break;
-    case CONFIG.GAME.DIRECTIONS.DOWN: newY++; break;
-    case CONFIG.GAME.DIRECTIONS.LEFT: newX--; break;
-  }
-
-  // 检查是否可以移动
-  if (isWalkable(newX, newY)) {
-
-    // 处理方块类型逻辑
-    await switchMapType(0);
-
-    // 使用平滑移动动画
-    await smoothMoveTo(newX, newY);
-
-    // 处理方块类型逻辑
-    await switchMapType(1);
-
-    await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
-  } else {
-    // 发生碰撞 使用统一的碰撞处理方法
-    await handleWallCollision();
-  }
-};
-
-//向左转(逆时针旋转90度)
-window.turnLeft = async function() {
-  // 如果已经发生过碰撞,不再执行任何旋转
-  if (shouldStopExecution || isColliding.value) {
-    return;
-  }
-
-  // 记录起始方向和目标方向
-  const startDirection = playerDirection.value;
-  const targetDirection = (playerDirection.value - 1 + 4) % 4;
-
-  // 实现平滑旋转
-  const startTime = performance.now();
-
-  // 使用 requestAnimationFrame 实现平滑动画
-  await new Promise(resolve => {
-    function animate(currentTime) {
-      // 检查是否应该停止执行
-      if (shouldStopExecution) {
-        resolve();
-        return;
-      }
-
-      const elapsedTime = currentTime - startTime;
-      const progress = Math.min(elapsedTime / CONFIG.ANIMATION.ROTATE_DURATION, 1);
-
-      // 在动画过程中更新方向
-      gameState.player.direction = startDirection - progress;
-
-      // 如果动画未完成,继续下一帧
-      if (progress < 1) {
-        requestAnimationFrame(animate);
-      } else {
-        // 动画完成后设置最终方向
-        gameState.player.direction = targetDirection;
-        resolve();
-      }
-    }
-    // 开始动画
-    requestAnimationFrame(animate);
-  });
-
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
-};
-
-//向右转(顺时针旋转90度)
-window.turnRight = async function() {
-  // 如果已经发生过碰撞,不再执行任何旋转
-  if (shouldStopExecution || isColliding.value) {
-    return;
-  }
-
-  // 记录起始方向和目标方向
-  const startDirection = playerDirection.value;
-  const targetDirection = (playerDirection.value + 1) % 4;
-
-  // 实现平滑旋转
-  const startTime = performance.now();
-
-  // 使用 requestAnimationFrame 实现平滑动画
-  await new Promise(resolve => {
-    function animate(currentTime) {
-      // 检查是否应该停止执行
-      if (shouldStopExecution) {
-        resolve();
-        return;
-      }
-
-      const elapsedTime = currentTime - startTime;
-      const progress = Math.min(elapsedTime / CONFIG.ANIMATION.ROTATE_DURATION, 1);
-
-      // 处理从3到0的边界情况,确保顺时针旋转
-      let currentDirection;
-      if (startDirection === 3 && targetDirection === 0) {
-        // 对于从3到0的顺时针旋转,我们需要模拟+1的效果而不是-3
-        currentDirection = startDirection + progress;
-        // 当超过3.99时,设置为0(避免显示4)
-        if (currentDirection > 3.99) {
-          currentDirection = 0;
-        }
-      } else {
-        // 正常情况下的线性插值
-        currentDirection = startDirection + (targetDirection - startDirection) * progress;
-      }
-
-      // 在动画过程中更新方向
-      gameState.player.direction = currentDirection;
-
-      // 如果动画未完成,继续下一帧
-      if (progress < 1) {
-        requestAnimationFrame(animate);
-      } else {
-        // 动画完成后设置最终方向
-        gameState.player.direction = targetDirection;
-        resolve();
-      }
-    }
-
-    // 开始动画
-    requestAnimationFrame(animate);
-  });
-
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
-};
-
-// 向后转(旋转180度)
-window.turnAround = async function() {
-  // 如果已经发生过碰撞,不再执行任何旋转
-  if (shouldStopExecution || isColliding.value) {
-    return;
-  }
-
-  // 记录起始方向和目标方向
-  const startDirection = playerDirection.value;
-  const targetDirection = (playerDirection.value + 2) % 4;
-
-  // 实现平滑旋转
-  const startTime = performance.now();
-
-  // 使用 requestAnimationFrame 实现平滑动画
-  await new Promise(resolve => {
-    function animate(currentTime) {
-      // 检查是否应该停止执行
-      if (shouldStopExecution) {
-        resolve();
-        return;
-      }
-
-      const elapsedTime = currentTime - startTime;
-      const progress = Math.min(elapsedTime / CONFIG.ANIMATION.TURN_AROUND_DURATION, 1);
-
-      // 在动画过程中更新方向
-      gameState.player.direction = startDirection + 2 * progress;
-
-      // 如果动画未完成,继续下一帧
-      if (progress < 1) {
-        requestAnimationFrame(animate);
-      } else {
-        // 动画完成后设置最终方向
-        gameState.player.direction = targetDirection;
-        resolve();
-      }
-    }
-    // 开始动画
-    requestAnimationFrame(animate);
-  });
-
-  await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
-};
-
-//校验是否到达终点
-window.isFinish = async function() {
-  // 如果已经发生过碰撞,不再执行任何检查
-  if (isColliding.value) {
-    return;
-  }
-
-  if (gameState.player.position.x === endPoint.value.x && gameState.player.position.y === endPoint.value.y) {
-
-    //检查是否有未完成的任务点
-    const pointIndex = gameState.mapData.walkablePoints.findIndex(
-        p => p.type === BLOCKLY_MAP_TYPE_DICT.TASK && p.status !== true
-    );
-    if (pointIndex !== -1) {
-      showGameMessage(CONFIG.TIPS.UNFINISHED, 'error');
-      return;
-    }
-
-    gameState.player.hasReachedEnd = true;
-    showGameMessage(CONFIG.TIPS.FINISH, 'success' );
-  }
-};
-
-// 运行代码
-const runCode = async () => {
-  try {
-    await resetPlayer();
-    await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.RESET_DELAY));
-    // 重置执行标志,允许新的执行
-    shouldStopExecution = false;
-
-    // 创建新的AbortController用于取消执行
-    executionAbortController = new AbortController();
-    const signal = executionAbortController.signal;
-
-    // 确保生成器和工作区都存在
-    if (!javascriptGenerator || !workspace) {
-      throw new Error('生成器或工作区未正确初始化');
-    }
-
-    // 生成JavaScript代码
-    const code = javascriptGenerator.workspaceToCode(workspace) + "await isFinish();";
-
-    try {
-      // 增强的安全检查
-      const unsafePatterns = [
-        'eval(', 'Function(', 'document.write', 'window.location',
-        'document.createElement', 'XMLHttpRequest', 'fetch',
-        'setInterval', 'setTimeout', 'window.',
-        'alert(', 'confirm(', 'prompt(',
-        'document.cookie', 'localStorage', 'sessionStorage'
-      ];
-
-      const hasUnsafeCode = unsafePatterns.some(pattern => code.includes(pattern));
-
-      if (hasUnsafeCode) {
-        throw new Error('代码包含不安全的操作');
-      }
-
-      // 包装代码为异步函数执行,并设置超时保护
-      currentExecutionPromise = new Promise(async (resolve, reject) => {
-        try {
-          // 检查信号是否已中止
-          if (signal.aborted) {
-            throw new Error('执行已取消');
-          }
-
-          // 添加信号监听
-          signal.addEventListener('abort', () => {
-            reject(new Error('执行已取消'));
-          });
-
-          const wrappedCode = `(async () => { ${code} })()`;
-          await new Function(wrappedCode)();
-          resolve();
-        } catch (error) {
-          reject(error);
-        }
-      });
-
-    } catch (error) {
-      // 捕获并显示执行错误
-      if (error.message !== '执行已取消') {
-        const errorMsg = error.message || '未知错误';
-        showGameMessage(`代码执行错误: ${errorMsg}`, 'error');
-        console.error('代码执行错误:', error);
-      }
-    } finally {
-      // 清除当前执行的Promise引用
-      currentExecutionPromise = null;
-    }
-  } catch (error) {
-    showGameMessage(`运行时错误: ${error.message || '未知错误'}`, 'error');
-    console.error('运行时错误:', error);
-  }
-};
-
-// 清空工作区
-const clearWorkspace = () => {
-  workspace.clear();
-  showGameMessage('工作区已清空', 'info');
-};
-
-// 重置玩家位置和状态
-const resetPlayer = () => {
-  // 设置标志强制停止所有执行
-  shouldStopExecution = true;
-
-  // 取消任何正在执行的代码
-  if (executionAbortController) {
-    executionAbortController.abort();
-    executionAbortController = null;
-  }
-
-  if (currentExecutionPromise) {
-    currentExecutionPromise = null;
-  }
-
-  // 重置携带的物品回地图
-  if (gameState.mapData.originalWalkablePoints.length > 0) {
-    gameState.mapData.walkablePoints = JSON.parse(JSON.stringify(gameState.mapData.originalWalkablePoints));
-  }
-  // 清空携带物品
-  gameState.player.carriedItems = [];
-  // 重新初始化可行走点集合
-  initWalkablePointsSet();
-
-  gameState.player.position = { ...startPoint.value };
-  gameState.player.direction = playerInitialDirection.value; // 重置为初始方向
-  gameState.player.isColliding = false; //碰撞标志
-  gameState.player.hasReachedEnd = false;
-  gameState.player.isSliding = false; // 重置滑行状态
-};
-
-// 更新地图容器尺寸的函数
-function updateMapContainerDimensions() {
-  const mapContainer = document.querySelector('.map-container');
-  if (mapContainer) {
-    const rect = mapContainer.getBoundingClientRect();
-    // 确保获取到有效的尺寸值
-    if (rect.width > 0 && rect.height > 0) {
-      mapContainerDimensions.value = {
-        width: rect.width,
-        height: rect.height
-      };
-    } else {
-      // 若尺寸无效,使用默认容器尺寸(可根据实际情况调整)
-      mapContainerDimensions.value = {
-        width: 800,
-        height: 600
-      };
-    }
-  }
-};
-
-// 显示游戏消息
-function showGameMessage(message, type = 'info', duration = CONFIG.DELAY.MESSAGE_DISPLAY) {
-  gameState.status.message = message;
-  gameState.status.messageType = type;
-
-  // 消息显示时间后自动清除消息
-  setTimeout(() => {
-    gameState.status.message = '';
-  }, duration);
-}
-
-// 统一处理撞到墙时的停止逻辑
-async function handleWallCollision(endMsg = CONFIG.TIPS.NO_ENTRY) {
-  // 设置碰撞状态
-  gameState.player.isColliding = true;
-  // 显示错误消息
-  showGameMessage(endMsg, 'error');
-
-  // 立即中止整个代码执行
-  if (executionAbortController) {
-    executionAbortController.abort();
-  }
-
-  // 所有动画和移动操作立即停止
-  shouldStopExecution = true;
-
-  // 碰撞状态重置时间后取消碰撞状态
-  setTimeout(() => {
-    gameState.player.isColliding = false;
-  }, CONFIG.DELAY.COLLISION_RESET);
-
-  // 返回一个Promise,允许调用者等待碰撞延迟
-  return new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.COLLISION_DELAY));
-}
-
-// 组件卸载时清理
-onUnmounted(() => {
-  if (workspace) {
-    workspace.dispose();
-  }
-  window.removeEventListener('resize', updateMapContainerDimensions);
-});
-
-</script>
-
-<style scoped lang="scss">
-@use "sass:math";
-
-@function rpx($px) {
-  @return math.div($px, 750) * 100vw;
-}
-
-//将tileSize属性绑定到CSS变量上
-:root {
-  --tile-size: v-bind('tileSize + "px"');
-}
-
-.map-game-container {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: transparent;
-  overflow-y: auto;
-}
-
-/* 自定义滚动条样式 */
-.map-game-container::-webkit-scrollbar {
-  width: rpx(2); /* 滚动条宽度 */
-}
-
-.map-game-container::-webkit-scrollbar-track {
-  background: #f1effd; /* 滚动条轨道背景色 */
-  border-radius: rpx(4);
-}
-
-.map-game-container::-webkit-scrollbar-thumb {
-  background: #e2ddfc; /* 滚动条滑块颜色 */
-  border-radius: rpx(4);
-}
-
-.map-game-container::-webkit-scrollbar-thumb:hover {
-  background: #e2ddfc; /* 滚动条滑块 hover 状态颜色 */
-}
-
-/* 游戏简介样式 */
-.info-message-container {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-}
-.message-item {
-  display: flex;
-  align-items: flex-start;
-  width: 100%;
-  margin-bottom: rpx(5);
-}
-/* 头像样式 */
-.avatar {
-  margin-right: rpx(4);
-  flex-shrink: 0;
-}
-.avatar-image {
-  width: rpx(30);
-  height: rpx(30);
-  object-fit: cover;
-}
-/* 消息内容样式 */
-.message-item {
-  flex: 1;
-}
-.message-item p {
-  margin: rpx(4) 0;
-  line-height: 1.6;
-  font-size: rpx(7);
-  text-align: left;
-  color: black;
-  background-color: #e6faff;
-  opacity: 0.8;
-  border-radius: rpx(4);
-  padding: rpx(6);
-  max-width: 100%;
-}
-.message-item p:first-child {
-  margin-top: 0;
-  font-weight: 500;
-}
-.message-item p:last-child {
-  margin-bottom: 0;
-}
-
-.title-box {
-  position: relative;
-  top: rpx(5);
-  padding-left: 15px;
-  z-index: 10;
-  display: flex;
-  flex-direction: column;
-}
-
-/* 右侧两个角为圆角的长方形格子样式 */
-.game-badge {
-  width: rpx(80);
-  height: rpx(20);
-  margin-left: rpx(10);
-  background-color: #5fb5dc;
-  color: #fff;
-  border-radius: 0 rpx(20) rpx(20) 0;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: rpx(15);
-  font-weight: bold;
-}
-
-.box-icon {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  padding: 10px 20px;
-  background-color: rgba(255, 255, 255, 0.8);
-  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.9);
-  transform: translate(-3px);
-}
-
-.left-icon {
-  font-size: 18px;
-}
-
-.content {
-  display: flex;
-  flex-wrap: nowrap;
-  gap: 20px;
-  padding: 20px;
-  min-width: 1160px;
-}
-
-/* 地图区域样式 */
-.map-section {
-  flex: 1;
-  min-width: 500px;
-  background: rgba(248, 249, 250, 0.82);
-  padding: 15px;
-  border-radius: 15px;
-}
-
-.map-container {
-  position: relative;
-  width: 100%;
-  height: 100%;
-  overflow: hidden; // 防止内容溢出
-}
-
-.map-background {
-  position: relative;
-  width: 100%;
-  height: 100%;
-  background-size: cover;
-  background-position: center;
-  background-repeat: no-repeat;
-}
-
-.map-image {
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-}
-
-/* 可行走区域样式 */
-.walkable-point {
-  position: absolute;
-  //background-color: rgba(52, 152, 219, 0.2);
-  //border: 1px solid rgba(52, 152, 219, 0.5);
-  //box-sizing: border-box;
-  //是否显示可行路线
-  opacity: 1;
-}
-
-/* 玩家样式 */
-.player {
-  position: absolute;
-  background-image: var(--player-image);
-  background-size: contain;
-  background-repeat: no-repeat;
-  background-position: center;
-  border-radius: 5px;
-  z-index: 10;
-}
-
-/* 碰撞动画 */
-.player.collision {
-  animation: collision 0.5s ease-in-out;
-}
-
-@keyframes collision {
-  0% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0) scale(1); }
-  25% { transform: rotate(var(--player-rotation)) translateX(-3px) translateY(-2px) scale(1.2); }
-  50% { transform: rotate(var(--player-rotation)) translateX(3px) translateY(2px) scale(1.2); }
-  75% { transform: rotate(var(--player-rotation)) translateX(-3px) translateY(-2px) scale(1.2); }
-  100% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0) scale(1); }
-}
-
-/* 滑行动画 */
-@keyframes sliding {
-  0% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0); }
-  25% { transform: rotate(var(--player-rotation)) translateX(2px) translateY(0); }
-  75% { transform: rotate(var(--player-rotation)) translateX(-2px) translateY(0); }
-  100% { transform: rotate(var(--player-rotation)) translateX(0) translateY(0); }
-}
-
-/* 携带物品容器 */
-.carried-items-container {
-  position: absolute;
-  top: 20px;
-  left: 20px;
-  background: rgba(255, 255, 255, 0.8);
-  border: 2px solid #3498db;
-  border-radius: 10px;
-  padding: 10px;
-  display: flex;
-  gap: 10px;
-  z-index: 15;
-  backdrop-filter: blur(10px);
-  animation: fadeInScale 0.5s ease-out;
-}
-
-/* 淡入缩放动画 */
-@keyframes fadeInScale {
-  0% {
-    opacity: 0;
-    transform: scale(0.5) translateY(-10px);
-  }
-  100% {
-    opacity: 1;
-    transform: scale(1) translateY(0);
-  }
-}
-
-/* 携带物品样式 */
-.carried-item {
-  animation: bounceIn 0.3s ease-out forwards;
-  opacity: 0;
-}
-
-/* 弹入动画 */
-@keyframes bounceIn {
-  0% {
-    opacity: 0;
-    transform: scale(0.3) translateY(-20px);
-  }
-  50% {
-    opacity: 0.7;
-    transform: scale(1.1) translateY(5px);
-  }
-  80% {
-    opacity: 0.9;
-    transform: scale(0.95) translateY(-2px);
-  }
-  100% {
-    opacity: 1;
-    transform: scale(1) translateY(0);
-  }
-}
-
-/* 成功到达终点动画 */
-.player.success {
-  animation: success 1s ease-in-out;
-}
-
-@keyframes success {
-  0% { transform: rotate(var(--player-rotation)) scale(1); }
-  10% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(-5px) translateY(-5px); }
-  20% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(5px) translateY(5px); }
-  30% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(-5px) translateY(-5px); }
-  40% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(5px) translateY(5px); }
-  50% { transform: rotate(var(--player-rotation)) scale(1.4) translateX(0) translateY(0); }
-  60% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(-3px) translateY(-3px); }
-  70% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(3px) translateY(3px); }
-  80% { transform: rotate(var(--player-rotation)) scale(1.3) translateX(-3px) translateY(-3px); }
-  90% { transform: rotate(var(--player-rotation)) scale(1.2) translateX(3px) translateY(3px); }
-  100% { transform: rotate(var(--player-rotation)) scale(1); }
-}
-
-/* 游戏消息样式 */
-.game-message {
-  position: absolute;
-  top: 20px;
-  left: 50%;
-  transform: translateX(-50%);
-  padding: 10px 20px;
-  border-radius: 5px;
-  font-weight: bold;
-  z-index: 20;
-  min-width: 200px;
-  text-align: center;
-}
-
-.game-message.success {
-  background-color: #d4edda;
-  color: #155724;
-  border: 1px solid #c3e6cb;
-}
-
-.game-message.error {
-  background-color: #f8d7da;
-  color: #721c24;
-  border: 1px solid #f5c6cb;
-}
-
-.game-message.info {
-  background-color: #d1ecf1;
-  color: #0c5460;
-  border: 1px solid #bee5eb;
-}
-
-.game-message.warning {
-  background-color: #baeff8;
-  color: #035767;
-  border: 1px solid #9be9f6;
-}
-
-/* Blockly区域样式 */
-.blockly-section {
-  flex: 1;
-  min-width: 600px;
-  display: flex;
-  flex-direction: column;
-  gap: 20px;
-}
-
-// 合并重复的区块样式
-.map-section, .toolbox-section, .workspace-section {
-  background: rgba(248, 249, 250, 0.82);
-  padding: 15px;
-  border-radius: 15px;
-  height: 100%;
-}
-
-.map-section h2, .toolbox-section h2, .workspace-section h2 {
-  margin-bottom: 15px;
-  color: #2c3e50;
-  border-bottom: 2px solid #3498db;
-  padding-bottom: 8px;
-}
-
-// 合并重复的区块背景样式
-.map-section,
-.toolbox-section,
-.workspace-section {
-  background: rgba(248, 249, 250, 0.82);
-  padding: 15px;
-  border-radius: 15px;
-}
-
-#blocklyDiv {
-  height: rpx(300);
-  // min-height: 500px;
-  width: 100%;
-  background: #fff;
-  border: 1px solid #ddd;
-  border-radius: 8px;
-}
-
-/* 优化Blockly积木样式 */
-/* 增加积木高度 */
-.blocklyBlockCanvas .blocklyBlock {
-  height: 45px; /* 增加默认高度 */
-  min-height: 45px;
-}
-
-/* 增加积木内部元素的行高和间距 */
-.blocklyText {
-  font-size: 16px;
-  line-height: 20px;
-  font-weight: 500;
-}
-
-/* 增加输入字段的高度 */
-.blocklyHtmlInput {
-  height: 30px;
-  font-size: 14px;
-  padding: 5px;
-}
-
-/* 增加下拉菜单的高度 */
-.blocklyDropdownMenu {
-  line-height: 28px;
-  font-size: 14px;
-}
-
-/* 优化积木圆角和阴影效果 */
-.blocklyBlock {
-  border-radius: 8px;
-  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
-}
-
-/* 增加积木之间的连接点间距 */
-.blocklyConnection {
-  height: 20px;
-  width: 20px;
-}
-
-/* 增加工具箱中积木的高度 */
-.blocklyTreeRow {
-  height: 40px;
-  line-height: 40px;
-}
-
-
-.controls {
-  display: flex;
-  gap: 10px;
-  margin: 15px 0px;
-  flex-wrap: wrap;
-}
-
-button {
-  padding: 10px 20px;
-  border: none;
-  border-radius: 5px;
-  background: #3498db;
-  color: #fff;
-  font-weight: 700;
-  cursor: pointer;
-  transition: all 0.3s ease;
-}
-
-button:hover {
-  background: #2980b9;
-  transform: translateY(-2px);
-  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
-}
-
-#runCode {
-  background: #e74c3c;
-}
-
-#runCode:hover {
-  background: #c0392b;
-}
-
-/* 响应式布局 */
-@media (max-width: 1200px) {
-  .map-section,
-  .blockly-section {
-    flex: 1;
-    min-width: 45%;
-  }
-
-  .map-background {
-    width: 100%;
-    height: 400px;
-  }
-}
-</style>

+ 0 - 564
src/views/gamepage/GameIndex.vue

@@ -1,564 +0,0 @@
-<template>
-  <!-- 游戏页面 -->
-  <div class="home-container">
-    <!-- 展开收起侧边栏 -->
-    <div
-      class="icon-expand"
-      :style="{
-        backgroundColor: drawerVisible ? '#44449c' : '#7F70C840',
-        left: drawerVisible ? '18%' : '0'
-      }"
-      @click="toggleDrawer"
-    >
-      <span
-        class="vertical-lines"
-        :style="{
-          color: drawerVisible ? '#8a78d0' : 'white'
-        }"
-        >||</span
-      >
-    </div>
-
-    <!-- 侧边栏组件 -->
-    <ProgrammingSidebar ref="leftPanelRef" v-show="drawerVisible" />
-
-    <div class="content-box">
-      <div class="box-1">
-        <div class="inner-box left-box">
-          <div class="box-icon" @click="goBack">
-            <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
-            {{ pageTitle }}
-          </div>
-          <!-- 下拉菜单已移除 -->
-        </div>
-        <div class="inner-box right-box">
-          <div class="top-right-box">
-            <el-autocomplete
-              v-model="SearchInput"
-              :fetch-suggestions="querySearch"
-              placeholder="搜索游戏"
-              @select="handleSearchSelect"
-              class="search-input"
-              value-key="typeName"
-              :trigger-on-focus="false"
-              :key="searchKey"
-            >
-              <template #prefix>
-                <el-icon class="el-input__icon"><search /></el-icon>
-              </template>
-              <!-- 下拉项模板 -->
-              <template #default="{ item }">
-                <div class="scrollbar">
-                  <!-- 序号和标题 -->
-                  {{ item.gameSort }} {{ item.typeName }}
-                </div>
-              </template>
-            </el-autocomplete>
-          </div>
-        </div>
-      </div>
-
-      <div class="box-2">
-        <div
-          class="small-box"
-          v-for="(game, index) in gameData"
-          :key="index"
-          @click="goToGame(game)"
-        >
-          <div
-            class="nested-box"
-            :style="{
-              backgroundImage: `url(${game.gameImage})`,
-              backgroundSize: 'cover'
-            }"
-          ></div>
-          <div class="additional-text">
-            {{ game.gameSort }} {{ game.typeName }}
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ref, onMounted, computed } from 'vue'
-// Element Plus 组件引入
-import { ArrowDown, Search, ArrowLeftBold } from '@element-plus/icons-vue'
-import { useRouter, useRoute } from 'vue-router'
-import teachingImg from '@/assets/icon/teaching.png'
-// 引入游戏列表接口
-import { GameList } from '@/api/blockly/game.js'
-import ProgrammingSidebar from '@/components/sidebar/ProgrammingSidebar.vue'
-import {homeRoutes} from "@/router/index.js";
-const leftPanelRef = ref(null)
-const route = useRoute()
-
-// 获取当前路由对象
-const router = useRouter() 
-// 页面标题
-const pageTitle = ref('返回首页')
-// 抽屉显示状态
-const drawerVisible = ref(true)
-// 游戏数据
-const gameData = ref([])
-
-// 获取游戏列表
-onMounted(() => {
-  GameList().then(res => {
-    // 根据接口返回的数据结构
-    if (res && res.data) {
-      // 处理返回的数据
-      gameData.value = res.data.list.map(item => {
-        let sortNum = item.sort || 0;
-        sortNum = sortNum > 9 ? sortNum : "0" + sortNum;
-        return {
-          id: item.id,
-          typeName: item.name,
-          gameImage: item.mapBackground,
-          gameSort: sortNum
-        };
-      })
-      // 重新渲染搜索组件
-      searchKey.value = Date.now()
-    }
-  }).catch(error => {
-    console.error('获取游戏列表失败:', error)
-  })
-})
-// 切换抽屉显示状态的函数
-const toggleDrawer = () => {
-  drawerVisible.value = !drawerVisible.value
-}
-// 游戏标题数组
-const gameTitles = computed(() => {
-  return gameData.value.map(item => {
-    return `${item.gameSort} ${item.typeName}`;
-  });
-})
-// 搜索框
-const SearchInput = ref('')
-// 用于强制重新渲染搜索组件的key
-const searchKey = ref(Date.now())
-// 搜索建议查询方法
-const querySearch = (queryString, cb) => {
-  const results = queryString
-    ? gameData.value.filter(item => {
-        // 游戏标题和序号查询
-        return item.typeName.toLowerCase().includes(queryString.toLowerCase()) ||
-               item.gameSort.includes(queryString)
-      })
-    : gameData.value
-  cb(results)
-}
-// 搜索选择处理方法
-const handleSearchSelect = item => {
-  goToGame(item)
-  // 清空输入框
-  SearchInput.value = ''
-}
-// 返回上一页
-const goBack = () => {
-   router.push(homeRoutes.home)
-}
-// 跳转到游戏页面
-const goToGame = game => {
-  router.push({
-    path: '/mapGame',
-    query: { gameId: game.id, gameName: game.typeName, gameSort: game.gameSort }
-  })
-}
-
-</script>
-
-<style scoped lang="scss">
-@use 'sass:math';
-// 定义rpx转换函数
-@function rpx($px) {
-  @return math.div($px, 750) * 100vw;
-}
-
-/* 过渡样式 */
-.drawer-slide-enter-active,
-.drawer-slide-leave-active {
-  transition: all 0.3s ease;
-}
-.drawer-slide-enter-from,
-.drawer-slide-leave-to {
-  transform: translateX(-100%);
-  opacity: 0;
-  transition: all 0.3s ease;
-}
-.home-container {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  display: flex;
-  flex-direction: row;
-  background: linear-gradient(
-    to bottom,
-    #e2ddfc,
-    #f1effd
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
-  gap: rpx(0);
-}
-.sidebar-layout {
-  display: flex;
-  flex-direction: row;
-  align-items: flex-start;
-}
-.icon-wrapper {
-  width: 40px; /* 根据实际需要调整宽度 */
-  flex-shrink: 0;
-  background-color: saddlebrown;
-}
-.main-content {
-  width: rpx(135);
-  height: 100%;
-  flex-grow: 1;
-  background: linear-gradient(to bottom, hsl(230, 100%, 21%), #8a78d0);  position: relative;
-  overflow-y: auto; /* 添加垂直滚动条 */
-  max-height: 100%; /* 设置最大高度 */
-  transition: all 0.3s ease;
-  // 自定义滚动条样式
-  &::-webkit-scrollbar {
-    width: rpx(0); // 滚动条宽度
-  }
-  &::-webkit-scrollbar-track {
-    background-color: rgba(255, 255, 255, 0.1); // 滚动条轨道背景色
-    border-radius: rpx(2); // 滚动条轨道圆角
-  }
-  &::-webkit-scrollbar-thumb {
-    background-color: rgba(255, 255, 255, 0.3); // 滚动条滑块颜色
-    border-radius: rpx(2); // 滚动条滑块圆角
-    transition: background-color 0.3s ease; // 滑块颜色过渡效果
-  }
-  &::-webkit-scrollbar-thumb:hover {
-    background-color: rgba(255, 255, 255, 0.5); // 鼠标悬停时的滑块颜色
-  }
-}
-.icon-expand {
-  width: rpx(8);
-  height: rpx(35);
-  border-top-right-radius: rpx(5);
-  border-bottom-right-radius: rpx(5);
-  z-index: 9999;
-  position: absolute;
-  top: 50%;
-  transform: translateY(-50%);
-  cursor: pointer; // 鼠标指针样式
-  // 修改裁剪路径使右侧边缘垂直无缝贴合
-  clip-path: polygon(0 0, 100% 15%, 100% 90%, 0 100%);
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  // 统一过渡时间与菜单保持同步
-  transition: all 0.3s ease;
-}
-.icon-expand .vertical-lines {
-  color: #8a78d0;
-  font-size: rpx(10);
-}
-.content-box {
-  flex: 1;
-  height: 100%;
-  display: flex;
-  flex-direction: column; /* 子元素上下排列 */
-  background: linear-gradient(
-    to bottom,
-    #e2ddfc,
-    #f1effd
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
-}
-.tac .el-menu {
-  background-color: transparent;
-  border: none;
-  width: 100%;
-  margin-left: rpx(10);
-  margin-top: rpx(10);
-}
-
-.mb-2 {
-  color: white;
-  font-size: rpx(9);
-  margin-left: rpx(10);
-  white-space: nowrap; /* 防止文字换行 */
-}
-.mb-2 img {
-  width: rpx(15);
-  height: rpx(15);
-  vertical-align: middle;
-  margin-top: rpx(-2);
-  margin-left: 0;
-}
-.el-menu-item {
-  width: rpx(115);
-  // height: rpx(20);
-  margin-bottom: rpx(5);
-  border-radius: rpx(6);
-  color: white;
-  font-size: rpx(8);
-}
-
-.el-menu ::v-deep(.el-menu-item:hover),
-.el-menu ::v-deep(.el-menu-item:focus),
-.el-menu ::v-deep(.el-menu-item:active) {
-  background: linear-gradient(
-    to bottom,
-    #ffefb0,
-    #ffcc00
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
-  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
-  color: black;
-}
-
-.drawer-box {
-  position: absolute;
-  display: flex;
-  // align-items: center;
-  margin-top: rpx(30);
-  height: 100%;
-  width: 100%;
-}
-
-.box-1 {
-  width: 100%;
-  height: rpx(50);
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  box-sizing: border-box;
-  font-size: rpx(16); // 默认字体大小
-}
-.inner-box {
-  height: 100%;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  font-size: rpx(16); // 默认字体大小
-}
-.left-box {
-  position: relative;
-  justify-content: left;
-  flex: 1;
-  display: flex;
-  align-items: center;
-  gap: rpx(5); // 间距控制
-}
-.box-icon {
-  height: 100%;
-  display: flex;
-  align-items: center; // 垂直居中
-  color: black; // 设置图标颜色为白色
-  padding-left: rpx(15);
-  font-size: rpx(10); // 设置图标大小,可按需调整
-  cursor: pointer; // 鼠标指针样式
-  z-index: 999;
-}
-.box-icon .left-icon {
-  margin-left: rpx(10);
-  margin-right: rpx(5); // 设置图标和文字之间的间距 ;
-}
-
-.dropdown-box {
-  height: 100%;
-  display: flex; // flex 布局;
-  align-items: center; // 垂直居中;
-}
-.dropdown-box .el-button {
-  width: rpx(60); // 设置按钮宽度;
-  height: rpx(15); // 设置按钮高度;
-  background-color: rgb(255, 255, 255, 0.7);
-  border: 1px white solid;
-  box-shadow: 0 4px 8px rgb(0, 0, 0, 0.3);
-  color: black;
-  border: none;
-  margin-left: rpx(10);
-  border-radius: rpx(12);
-  font-size: rpx(8); // 设置字体大小;
-}
-.dropdown-box .el-button:hover,
-.dropdown-box .el-button:focus,
-.dropdown-box .el-button:active {
-  border: none; /* 移除悬停、聚焦、点击状态下的边框 */
-  outline: none; /* 移除悬停、聚焦、点击状态下的轮廓线 el-scrollbar__view el-dropdown__list */
-}
-.dropdown-menu {
-  width: rpx(100);
-  border-radius: rpx(5);
-  border: 1px white solid;
-  background-color: rgb(255, 255, 255, 0.5);
-  backdrop-filter: blur(rpx(5));
-  box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
-  margin-left: rpx(40);
-}
-.dropdown-menu ::v-deep(.el-dropdown-menu__item) {
-  font-size: rpx(8);
-  color: black;
-  border-radius: rpx(5);
-  width: rpx(78);
-  height: rpx(20);
-  margin-left: rpx(4);
-  margin-bottom: rpx(8);
-}
-.dropdown-menu ::v-deep(.el-dropdown-menu__item:hover),
-.dropdown-menu ::v-deep(.el-dropdown-menu__item:focus),
-.dropdown-menu ::v-deep(.el-dropdown-menu__item:active) {
-  background: linear-gradient(
-    to bottom,
-    #fee78a,
-    #ffce1b
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
-}
-.right-box {
-  flex: 1;
-  position: relative; // 添加相对定位;
-  // background-color: #fff;
-  display: flex;
-  justify-content: right;
-  align-items: center;
-}
-.top-right-box {
-   width: rpx(130);
-  display: flex;
-  justify-content: flex;
-}
-.top-right-box {
-  ::v-deep(.el-input__wrapper) {
-    height: rpx(15);
-    font-size: rpx(6);
-    background-color: rgb(255, 255, 255, 0.5);
-    border-radius: rpx(12);
-    border: white 1px solid;
-    color: #aaa5c5;
-  }
-  ::v-deep(.el-input__icon) {
-    color: #aaa5c5; // 设置输入框图标颜色为白色
-  }
-  // 添加占位符样式
-  ::v-deep(.el-input__inner::placeholder) {
-    color: #aaa5c5;
-  }
-  // 添加输入框文字颜色样式
-  ::v-deep(.el-input__inner) {
-    color: black;
-  }
-  ::v-deep(.el-input--prefix){
-    width: rpx(100);
-    text-align: right;
-  }
-}
-// 搜索
-.search-input {
-  width: rpx(200); // 增加搜索框宽度
-  height: rpx(30); // 增加搜索框高度
-  font-size: rpx(9);
-  border-radius: rpx(8); // 添加圆角
-  border: 1px solid #dcdfe6; // 添加边框
-}
-::v-deep(.el-input__inner) {
-  color: #333; // 调整文字颜色
-}
-
-
-.box-2 {
-  width: 100%;
-  // flex: 1;
-  box-sizing: border-box;
-  display: flex; // 确保子元素水平排列
-  flex-wrap: wrap; // 允许子元素换行;
-  cursor: pointer; // 添加鼠标指针样式
-  // margin: rpx(10) 0; 
-  overflow-y: auto;
-}
-// Chrome、Edge等浏览器的滚动条样式
-.box-2::-webkit-scrollbar {
-  width: rpx(2);
-}
-.box-2::-webkit-scrollbar-track {
-  background: transparent; // 设置滚动条轨道背景
-  border-radius: rpx(3); // 设置滚动条轨道圆角
-}
-.box-2::-webkit-scrollbar-thumb {
-  background: linear-gradient(to bottom, hsl(230, 100%, 21%), #8a78d0);
-  border-radius: rpx(3); // 设置滚动条滑块圆角
-}
-.box-2::-webkit-scrollbar-thumb:hover {
-  background: linear-gradient(to bottom, hsl(230, 100%, 21%), #8a78d0);
-}
-.small-box {
-  flex: 0 0 calc(33.333% - rpx(10)); // 每个小盒子占三分之一宽度,减去间距
-  margin-left: rpx(10); // 设置小盒子间距
-  margin-top: rpx(3); // 设置小盒子间距
-  display: flex;
-  flex-direction: column;
-  justify-content: flex-start;
-  align-items: center;
-  color: black;
-  font-size: rpx(8);
-}
-.nested-box {
-  width: rpx(150);
-  height: rpx(80);
-  border-radius: rpx(10);
-  margin-top: rpx(5);
-  display: flex;
-  border: 1px solid white; // 添加边框;
-  justify-content: center;
-  align-items: center;
-}
-.nested-box:hover,
-.nested-box:active {
-  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
-}
-.additional-text {
-  margin-bottom: rpx(4);
-  font-size: rpx(8);
-}
-</style>
-
-<style lang="scss">
-/* 消除小三角 */
-.el-popper__arrow {
-  display: none;
-}
-.el-popper.is-light,
-.el-dropdown__popper.el-popper {
-  background: transparent;
-  border: none;
-  box-shadow: none;
-}
-.el-dropdown__popper {
-  --el-dropdown-menuItem-hover-color: none;
-}
-</style>
-
-<style lang='scss'>
-// 搜索下拉框样式
-@use 'sass:math';
-// 定义rpx转换函数
-@function rpx($px) {
-  @return math.div($px, 750) * 100vw;
-}
- .el-autocomplete-suggestion .el-scrollbar__wrap{
-  margin: 0 auto;
-  background-color: rgba(255, 255, 255, 0.7);
-  border: 2px solid white;
-  border-radius: rpx(5);
-  backdrop-filter: blur(rpx(5));
-}
- .el-autocomplete-suggestion li{
-  color: black;
-  font-size: rpx(7);
-  padding: rpx(5) rpx(8); // 调整下拉项内边距
-}
- .el-autocomplete-suggestion li:hover{
-  background: linear-gradient(
-    to bottom,
-    #ffefb0,
-    #ffcc00
-  );
-}
-</style>

+ 2 - 2
src/views/blockly/Blockly.vue → src/views/virtuallaboratory/blockly/SmartDeskLamp.vue

@@ -216,8 +216,8 @@ import { globalState } from "@/utils/globalState.js";
 //音乐
 import { playMusic, stopMusic, onMusicEnded } from "@/api/blockly/music.js";
 import {ElButton} from "element-plus";
-import LiveWaveform from '../../components/ai/voice/LiveWaveform.vue';
-import VoiceInputApi from '../../components/ai/voice/VoiceInput_Api.vue';
+import LiveWaveform from '../../../components/ai/voice/LiveWaveform.vue';
+import VoiceInputApi from '../../../components/ai/voice/VoiceInput_Api.vue';
 
 
 const router = useRouter();

+ 1 - 1
src/views/blockly/Blockly2.vue → src/views/virtuallaboratory/blockly/SmartHome.vue

@@ -234,7 +234,7 @@ import lightClose from '@/assets/images/smart-home/light-close.png' // 灯光关
 import television from '@/assets/images/smart-home/television.png' // 电视画面
 import curtainFront from '@/assets/images/smart-home/curtain-front.png' // 前面窗帘遮挡
 
-import LiveWaveform from '../../components/ai/voice/LiveWaveform.vue';
+import LiveWaveform from '../../../components/ai/voice/LiveWaveform.vue';
 import VoiceInputApi from "@/components/ai/voice/VoiceInput_Api.vue";
 
 const router = useRouter();