<template>
  <div class="creative-zone" :style="{ '--grid-size': `${gridSize}px` }">
    <!-- 顶部固定头部组件 -->
    <div class="header-wrapper">
      <HeaderComponent :projectName="projectInfo.title" @updateProjectInfo="projectInfo = {...projectInfo, ...$event}" @openGuideModal="showGuideModal = true" />
    </div>
    
    <!-- 导入的侧边栏组件 -->
    <div class="sidebar-container">
      <iPandCardLeft 
      :Info="projectInfo.details"
      @generate-requested="handleGenerateRequested" 
      @model-generated="handleModelGenerated"
      @import-character="openImportModal"
    />
    </div>
    <!-- 主内容区域 - 可拖动场景 -->
    <main 
      class="main-content scene-container"
      :style="{ cursor: contentCursor }"
      @mousedown="startSceneDrag"
      @mousemove="dragScene"
      @mouseup="stopSceneDrag"
      @mouseleave="stopSceneDrag"
      @touchstart="startSceneDrag"
      @touchmove="dragScene"
      @touchend="stopSceneDrag"
      @wheel="handleWheel"
      @selectstart.prevent
    >
      <!-- 场景内容容器 -->
      <div 
        class="scene-content"
        :style="sceneContainerStyle"
      >
        <!-- IP图片展示组件 - 每个组件独立可拖动 -->
          <!-- @touchstart="startElementDrag($event, index)" -->
        <div 
          v-for="(card, index) in cards" 
          :key="card.id"
          class="draggable-element"
          :style="getElementStyle(index)"
          @mousedown="startElementDrag($event, index)"
          @mouseenter="bringToFront(index)"
          @mouseleave="sendToBack(index)"
        >
          <!-- 删除按钮 -->
          <button 
            class="delete-button"
            @click.stop="handleDeleteCard(index)"
            @mousedown.stop
            title="删除卡片"
          >
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
          </button>
          
          <!-- 根据卡片类型显示不同组件 -->
          <IPCard 
          @generate-smooth-white-model="(imageUrl)=>handleGenerateSmoothWhiteModel(index,imageUrl)"
          @create-new-card="(data)=>handleCreateFourViewCard(index,data)"
          @delete="handleDeleteCard(index)"
          :projectId="projectId"
          @create-prompt-card="(data)=>handleCreatePromptCard(index,data)"
          @generate-model-requested="(data)=>handleGenerateModelRequested(index,data)"
          @save-project="(item)=>{handleSaveProject(index,item,'image')}"
            v-if="card.type === 'image'"
            :cardData="card"
          />
          <ModelCard 
            v-else-if="card.type === 'model'"
            :cardData="card"
            :clickDisabled="isElementDragging"
            :projectId="projectId"
            @save-project="(item)=>{handleSaveProject(index,item,'model')}"
            @clickModel="handleModelClick"
            @refineModel="handleRefineModel"
          />
        </div>
      </div>
    </main>
    <!-- 模型展示弹窗 -->
    <ModelModal 
      :show="showModelModal"
      :modelData="selectedModel"
      @close="closeModal()"
    />

    <!-- 角色导入弹窗（iframe） -->
    <CharacterImportModal
      :show="showImportModal"
      :url="importUrl"
      @close="closeImportModal"
    />
    
    <!-- 引导弹窗 -->
    <GuideModal
      :show="showGuideModal"
      @close="closeGuideModal"
      @complete="completeGuide"
    />
  </div>
</template>

<script setup>
// 创意空间组件逻辑
import { ref, computed, onMounted, onUnmounted,watch } from 'vue';
import iPandCardLeft from '../../components/iPandCardLeft/index.vue';
import IPCard from '../../components/IPCard/index.vue';
import ModelCard from '../../components/modelCard/index.vue';
import ModelModal from '../../components/ModelModal/index.vue';
import CharacterImportModal from '../../components/CharacterImportModal/index.vue';
import HeaderComponent from '../../components/HeaderComponent/HeaderComponent.vue';
import GuideModal from '../../components/GuideModal/index.vue';
import {useRoute,useRouter} from 'vue-router';
import {MeshyServer} from '@deotaland/utils';
import { ElMessage } from 'element-plus';
import {Project} from './index';
const router = useRouter();
const PluginProject = new Project();
// 弹窗相关状态
const showModelModal = ref(false);
const selectedModel = ref(null);
const showImportModal = ref(false);
const importUrl = ref('https://xiaozhi.me/console/agents');
const showGuideModal = ref(false);
// 事件监听器清理函数存储
const cleanupFunctions = ref({});
const projectId = ref(null);
//项目数据
const projectInfo = ref({});
// 多个可拖动元素的数据
const cards = ref([
 
]);
watch(()=>[projectInfo.value,cards.value], () => {
  let newProjectInfo = {...projectInfo.value};
  newProjectInfo.details.node_card = cards.value;
  updateProjectInfo(newProjectInfo)
}, {deep: true});

//保存卡片项目
const handleSaveProject = (index,item,type='image')=>{
  let cardItem = cards.value[index];
  
  switch(type){
    case 'image':
      cardItem.imageUrl = item.imageUrl;
      break;
    case 'model':
      cardItem.modelUrl = item.modelUrl;
      cardItem.taskId = item.taskId;
      break;
  }
  cardItem.status = item.status;
  console.log(cards.value,'保存项目');
}
const createProject = async ()=>{
  const {id} = await PluginProject.createProject();
  // 创建新项目后，将当前路由跳转到 project/项目id
  await router.replace(`/project/${id}`);
  projectId.value = id;
  getProjectInfo(id);
  // projectId.value = 8;
  // getProjectInfo(8)
}
//获取项目信息
const getProjectInfo = async (id)=>{
  const data = await PluginProject.getProject(id);
  projectInfo.value = {...data};
  // 为没有id的卡片添加唯一id
  cards.value = [...projectInfo.value.details.node_card].map(card => ({
    ...card,
    id: card.id || Date.now() + Math.random().toString(36).substr(2, 9)
  }));
  }
//更新项目信息
const updateProjectInfo = async (newProjectInfo)=>{
  PluginProject.updateProject(projectId.value,newProjectInfo);
}
// 处理模型卡片点击事件
const handleModelClick = (modelData) => {
  // 如果正在拖动元素，则不触发弹窗
  if (isElementDragging.value) {
    return;
  }
  console.log('点击了模型卡片', modelData);
  // 接收并使用新的modelData对象
  selectedModel.value = modelData;
  showModelModal.value = true;
};

// 关闭弹窗
const closeModal = () => {
  showModelModal.value = false;
  selectedModel.value = null;
};

// 打开角色导入弹窗
const openImportModal = () => {
  showImportModal.value = true;
};

// 关闭角色导入弹窗
const closeImportModal = () => {
  showImportModal.value = false;
};

// 关闭引导弹窗
const closeGuideModal = () => {
  showGuideModal.value = false;
};

// 完成引导
const completeGuide = () => {
  showGuideModal.value = false;
};

// ==================== 定位计算器 ====================
/**
 * 卡片定位计算系统
 * 负责计算新卡片相对于最高层级卡片的确切位置
 */
class CardPositionCalculator {
  constructor() {
    this.ANIMATION_DURATION = 400; // 动画持续时间(ms)
    this.OFFSET_MARGIN = 30; // 卡片间距
    this.SCREEN_PADDING = 50; // 屏幕边缘最小间距
  }

  /**
   * 计算新卡片相对于最高层级卡片右侧的位置
   * @param {Object} highestCard - 当前最高层级的卡片
   * @param {number} scale - 当前缩放比例
   * @returns {Object} 位置信息 { x, y }
   */
  calculateRightSidePosition(highestCard, scale) {
    if (!highestCard) {
      return { x: -100, y:-100 };
    }

    // 获取最高层级卡片的当前偏移位置
    const currentX = this.parseOffset(highestCard.offsetX);
    const currentY = this.parseOffset(highestCard.offsetY);
    
    // 获取卡片宽度（默认250px）
    const cardWidth = this.parseCardWidth(highestCard.cardWidth);
    
    // 计算右侧位置：当前X + 卡片宽度 + 间距 + 屏幕边距
    const rightOffsetX = currentX + cardWidth + this.OFFSET_MARGIN + this.SCREEN_PADDING;
    
    // 获取场景容器的尺寸（假设场景容器充满整个视口）
    const containerWidth = window.innerWidth;
    const maxSafeX = containerWidth - cardWidth - this.SCREEN_PADDING;
    
    // 如果计算出的位置超出边界，则换行到下一行
    const finalX = rightOffsetX > maxSafeX ? 
      this.SCREEN_PADDING : // 如果超界则从左侧开始
      rightOffsetX;
    
    // Y坐标：如果换行，则向下移动一行的高度
    const finalY = rightOffsetX > maxSafeX ? 
      currentY + cardWidth + this.OFFSET_MARGIN : // 换行到下一行
      currentY; // 保持在同一行
    
    return { x: finalX-90, y: finalY };
  }

  /**
   * 解析偏移值字符串为数值
   * @param {string} offset - 偏移值字符串
   * @returns {number} 数值
   */
  parseOffset(offset) {
    if (typeof offset === 'number') return offset;
    if (typeof offset === 'string') {
      const num = parseFloat(offset.replace('px', ''));
      return isNaN(num) ? 0 : num;
    }
    return 0;
  }

  /**
   * 解析卡片宽度
   * @param {string|number} cardWidth - 卡片宽度
   * @returns {number} 数值
   */
  parseCardWidth(cardWidth) {
    if (typeof cardWidth === 'number') return cardWidth;
    if (typeof cardWidth === 'string') {
      const num = parseFloat(cardWidth.replace('px', ''));
      return isNaN(num) ? 250 : num;
    }
    return 250;
  }

  /**
   * 生成动画配置
   * @returns {Object} CSS动画属性
   */
  getAnimationConfig() {
    return {
      transition: `transform ${this.ANIMATION_DURATION}ms cubic-bezier(0.25, 0.46, 0.45, 0.94)`,
      willChange: 'transform' // 性能优化：告知浏览器该元素将改变transform
    };
  }
}

const positionCalculator = new CardPositionCalculator();

// 删除卡片方法
const handleDeleteCard = (index) => {
    cards.value.splice(index, 1);
};
/**
 * 创建带智能定位和层级管理的新卡片
 * @param {Object} cardConfig - 卡片配置对象
 * @returns {Object} 配置完整的新卡片
 */
const createSmartCard = (cardConfig,index=null) => {
  // 首先生成唯一ID
  const uniqueId = Date.now() + Math.random().toString(36).substr(2, 9);
  // 获取当前最高层级的卡片
  // const highestCard;
  // 获取当前最高层级的卡片（按 zIndex 最大值）
   let highestCard;
  if(index){
    highestCard = cards.value[index]
  }else{
 highestCard = cards.value[cards.value.length-1]
  }
  // 计算位置在最高层级卡片右侧
  const position = highestCard ? 
    positionCalculator.calculateRightSidePosition(highestCard, scale.value) : 
    { x: -100, y: -100 };

  // 为新卡片分配最高层级（使用新生成的ID）
  const newCard = {
    ...cardConfig,
    id: uniqueId,
    offsetX: `${position.x}px`,
    offsetY: `${position.y}px`,
    project_id: projectId.value,
    // 分配最高层级
    zIndex: cards.value.length+1,
  };
  console.log(newCard);
  return newCard;
};

const handleRefineModel = (taskId)=>{
  console.log('点击了模型卡片', taskId);
  // 使用统一的智能定位和层级管理系统创建模型卡片
  const newModelCard = createSmartCard({
    cardWidth: "250", // 默认宽度
    type: 'model', // 标记为模型类型
    modelUrl: null, // 初始为空，将由modelCard组件自己生成
    refineModel: true,//标记为模型细化
    refineModelTaskId: taskId
  });
  
  // 将新模型卡片添加到cards数组中
  cards.value.push(newModelCard);
}
// 处理精确定位白膜卡片生成
const handleGenerateSmoothWhiteModel = (index,imageUrl) => {
  console.log(imageUrl, 'imageUrlimageUrlimageUrl');
  // 使用统一的智能定位和层级管理系统创建白膜卡片
  const newCard = createSmartCard({
    imageUrl: imageUrl, // 传入基础图片作为初始图片
    type: 'image', // 标记为图片类型
    generateSmoothWhiteModelStatus: true
  },index);
  
  // 添加到卡片数组
  cards.value.push(newCard);
  
  console.log('已创建精确定位白膜卡片:', newCard);
}
// 处理四视图生成
const handleCreateFourViewCard = (index,params) => {
  const { baseImage } = params;
  
  // 创建新的四视图卡片对象
  const newCard = createSmartCard({
    imageUrl: baseImage, // 传入基础图片作为初始图片
    style: 'realistic', // 四视图通常使用写实风格
    type: 'image', // 标记为图片类型
    inspirationImage: null,
    module: null,
    sketch: null,
    isGenerating: true, // 标记正在生成中
    generateFourView: true // 标记为四视图生成模式
  },index);
  
  // 添加到卡片数组
  cards.value.push(newCard);
  
  console.log('已创建精确定位四视图卡片:', newCard);
}
// 处理提示词卡片生成
const handleCreatePromptCard = (index,params) => {
  const { img, diyPromptText } = params;
  // 创建新的提示词卡片对象
   const newCard = createSmartCard({
      imageUrl: img,
      diyPromptText:diyPromptText,
      status:'loading',
      type:'image',
    },index);
  // 添加到卡片数组
  cards.value.push(newCard);
}
// 处理图片生成请求
const handleGenerateRequested = async (params) => {
  // 根据请求的数量动态生成对应数量的IPCard组件实例
  const {count,profile,inspirationImage,ipType,ipTypeImg} = params
  for (let i = 0; i < count; i++) {
    // 使用统一的智能定位和层级管理系统创建卡片
    const newCard = createSmartCard({
      imageUrl: null, // 初始为空，将由IPCard组件自己生成
      prompt:profile.appearance,
      inspirationImage: inspirationImage,
      ipType:ipType,
      ipTypeImg:ipTypeImg,
      status:'loading',
      type:'image',
    });
    // 添加到卡片数组
    cards.value.push(newCard);
  }
};

// 处理模型生成请求
const handleGenerateModelRequested = (index,params) => {
  // 接收IPCard组件传递的参数，创建新的modelCard组件实例
  const {imageUrl } = params;
  // 使用统一的智能定位和层级管理系统创建模型卡片
  const newModelCard = createSmartCard({
    imageUrl: imageUrl, // 从IPCard接收的图片URL
    cardWidth: "250", // 默认宽度
    type: 'model', // 标记为模型类型
    modelUrl: null, // 初始为空，将由modelCard组件自己生成
    generateFourView: params.generateFourView || false, // 标记为四视图生成模式
    status:'loading',
    taskId:'',
    project_id: projectId.value,
  },index);
  
  // 将新模型卡片添加到cards数组中
  cards.value.push(newModelCard);
  
  console.log('已创建新的modelCard实例:', newModelCard);
};

// 处理模型生成事件
const handleModelGenerated = (modelData) => {
  // 使用统一的智能定位和层级管理系统创建模型卡片
  const newCard = createSmartCard({
    imageUrl: modelData.imageUrl, // 保留原始图片URL
    altText: `生成的3D模型 - ${modelData.prompt || '未知提示词'}`,
    cardWidth: "250", // 默认宽度
    prompt: modelData.prompt || '',
    style: modelData.style || '',
    profile: modelData.profile || '',
    timestamp: modelData.timestamp || Date.now(),
    type: 'model', // 标记为模型类型
    modelUrl: modelData.modelUrl, // 3D模型URL
    taskId: modelData.taskId, // 任务ID
    status: modelData.status // 任务状态
  });
  
  // 将新卡片添加到cards数组中
  cards.value.push(newCard);
  
  // 显示成功消息
  console.log('新3D模型已添加到场景中:', newCard);
};
// 场景和元素拖拽相关状态
const isElementDragging = ref(false);
const isSceneDragging = ref(false);
const draggedElementIndex = ref(null);
const elementStartX = ref(0);
const elementStartY = ref(0);
const sceneStartX = ref(0);
const sceneStartY = ref(0);
const sceneOffsetX = ref(0); // 调整初始X位置，让场景向左移动
const sceneOffsetY = ref(0); // 调整初始Y位置，让场景向上移动
const scale = ref(1); // 缩放比例
const zIndexCounter = ref(100); // z-index计数器
const originalZIndexes = ref(new Map()); // 记录每个元素的原始z-index

// 添加惯性动画相关状态
const elementVelocityX = ref(0);
const elementVelocityY = ref(0);
const lastMouseX = ref(0);
const lastMouseY = ref(0);
const lastTimestamp = ref(0);
const animationFrameId = ref(null);

// 计算场景容器样式
const sceneContainerStyle = computed(() => ({
  transform: `translate(${sceneOffsetX.value}px, ${sceneOffsetY.value}px) scale(${scale.value})`,
  transformOrigin: 'center center', // 缩放中心为场景中心
  transition: isSceneDragging.value ? 'none' : 'transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)' // 添加平滑过渡效果
}));

// 计算网格大小，根据缩放比例动态调整
const gridSize = computed(() => {
  // 基础网格大小为20px，根据缩放比例调整
  // 当缩放比例为1时，网格大小为20px
  // 当缩放比例变大时，网格大小相应变小，保持视觉上的一致性
  // 当缩放比例变小时，网格大小相应变大，避免网格过于密集
  const baseSize = 20;
  // 使用正比例关系，缩放比例越大，网格尺寸越大
  // 限制最小和最大网格大小，避免极端情况
  const adjustedSize = baseSize * scale.value;
  return Math.max(5, Math.min(50, adjustedSize));
});

// 获取指定索引元素的样式
const getElementStyle = (index) => {
  const card = cards.value[index];
  // 确保offsetX和offsetY有默认值
  const offsetX = card.offsetX || '0px';
  const offsetY = card.offsetY || '0px';
  
  // 初始化元素的原始z-index（如果还没有记录）
  if (!originalZIndexes.value.has(index) && card.zIndex) {
    originalZIndexes.value.set(index, card.zIndex);
  }
  
  return {
    transform: `translate(${offsetX}, ${offsetY})`,
    cursor: isElementDragging.value && draggedElementIndex.value === index ? 'grabbing' : 'grab',
    transition: isElementDragging.value && draggedElementIndex.value === index ? 'none' : 'transform 0.2s ease',
    zIndex: card.zIndex || 'auto' // 应用z-index
  };
};

// 将元素提升到最前面（悬停时）
const bringToFront = (index) => {
    cards.value[index].zIndex =cards.value.length+1;
};

// 将元素恢复到原始层级（鼠标离开时）
const sendToBack = (index) => {
  cards.value[index].zIndex =1;
};

// 计算主内容区域的鼠标样式
const contentCursor = computed(() => {
  return isSceneDragging.value ? 'grabbing' : 'grab';
});

// 开始拖动元素
const startElementDrag = (e, index) => {
  e.stopPropagation(); // 阻止事件冒泡到场景
  e.preventDefault(); // 阻止默认行为，包括图片重影效果
  
  // 检查是否点击在控制按钮上，如果是则不启动拖动
  if (e.target.closest('.control-button')) {
    return;
  }
  
  isElementDragging.value = true;
  isSceneDragging.value = false;
  draggedElementIndex.value = index;
  cards.value[index].zIndex =cards.value.length+1;
  // 支持触摸和鼠标事件
  const clientX = e.touches ? e.touches[0].clientX : e.clientX;
  const clientY = e.touches ? e.touches[0].clientY : e.clientY;
  // 获取当前元素的偏移量（转换为数值）
  const currentOffsetX = parseFloat(cards.value[index].offsetX) || 0;
  const currentOffsetY = parseFloat(cards.value[index].offsetY) || 0;
  // 考虑场景缩放比例，调整元素起始位置计算
  elementStartX.value = clientX - (currentOffsetX * scale.value);
  elementStartY.value = clientY - (currentOffsetY * scale.value);
  cards.value[index].offsetX = `${currentOffsetX}px`;
  cards.value[index].offsetY = `${currentOffsetY}px`;
};

// 拖动元素
const dragElement = (e) => {
  if (isElementDragging.value && draggedElementIndex.value !== null) {
    e.preventDefault(); // 阻止默认行为
    
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches ? e.touches[0].clientY : e.clientY;
    const currentTime = performance.now();
    
    // 计算速度
    if (lastTimestamp.value > 0) {
      const deltaTime = currentTime - lastTimestamp.value;
      if (deltaTime > 0) {
        elementVelocityX.value = (clientX - lastMouseX.value) / deltaTime * 16.67; // 转换为每帧速度
        elementVelocityY.value = (clientY - lastMouseY.value) / deltaTime * 16.67;
      }
    }
    
    // 更新最后位置和时间
    lastMouseX.value = clientX;
    lastMouseY.value = clientY;
    lastTimestamp.value = currentTime;
    
    // 考虑场景缩放比例，调整元素移动速度
    const newOffsetX = (clientX - elementStartX.value) / scale.value;
    const newOffsetY = (clientY - elementStartY.value) / scale.value;
    
    // 更新元素位置，使用像素值
    cards.value[draggedElementIndex.value].offsetX = `${newOffsetX}px`;
    cards.value[draggedElementIndex.value].offsetY = `${newOffsetY}px`;
  }
};

// 停止拖动元素
const stopElementDrag = () => {
  if (isElementDragging.value && draggedElementIndex.value !== null) {
    // 启动惯性动画
    applyInertiaToElement();
  }
  
  isElementDragging.value = false;
  draggedElementIndex.value = null;
  lastTimestamp.value = 0;
};

// 应用元素惯性动画
const applyInertiaToElement = () => {
  if (Math.abs(elementVelocityX.value) < 0.1 && Math.abs(elementVelocityY.value) < 0.1) {
    elementVelocityX.value = 0;
    elementVelocityY.value = 0;
    return;
  }
  
  const index = draggedElementIndex.value;
  if (index === null) return;
  
  // 应用摩擦力减速
  const friction = 0.95;
  elementVelocityX.value *= friction;
  elementVelocityY.value *= friction;
  
  // 更新元素位置
  const currentOffsetX = parseFloat(cards.value[index].offsetX) || 0;
  const currentOffsetY = parseFloat(cards.value[index].offsetY) || 0;
  
  cards.value[index].offsetX = `${currentOffsetX + elementVelocityX.value / scale.value}px`;
  cards.value[index].offsetY = `${currentOffsetY + elementVelocityY.value / scale.value}px`;
  
  // 继续动画
  animationFrameId.value = requestAnimationFrame(applyInertiaToElement);
};

// 开始拖动场景
const startSceneDrag = (e) => {
  // 如果正在拖动元素，则不响应场景拖动
  if (isElementDragging.value) return;
  
  // 只有在主内容区域（不是侧边栏）才允许拖动场景
  if (e.target.closest('.main-content') && !e.target.closest('.floating-sidebar')) {
    e.preventDefault();
    isSceneDragging.value = true;
    
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches ? e.touches[0].clientY : e.clientY;
    
    sceneStartX.value = clientX - sceneOffsetX.value;
    sceneStartY.value = clientY - sceneOffsetY.value;
  }
};

// 拖动场景
const dragScene = (e) => {
  if (isSceneDragging.value) {
    e.preventDefault();
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches ? e.touches[0].clientY : e.clientY;
    
    sceneOffsetX.value = clientX - sceneStartX.value;
    sceneOffsetY.value = clientY - sceneStartY.value;
  } else if (isElementDragging.value) {
    // 如果正在拖动元素，则执行元素拖动
    dragElement(e);
  }
};

// 停止拖动场景
const stopSceneDrag = () => {
  isSceneDragging.value = false;
  isElementDragging.value = false;
  draggedElementIndex.value = null;
};
// 处理鼠标滚轮事件，实现缩放和移动功能
const handleWheel = (e) => {
  e.preventDefault(); // 阻止默认的滚轮行为（页面滚动）
  
  // 如果按下了Ctrl键（Windows/Linux）或Cmd键（Mac），执行缩放操作
  if (e.ctrlKey || e.metaKey) {
    // 计算缩放比例增量
    const scaleFactor = e.deltaY > 0 ? 0.9 : 1.1;
    
    // 限制缩放范围，防止缩放过大或过小
    const newScale = scale.value * scaleFactor;
    if (newScale >= 0.1 && newScale <= 5) {
      // 获取场景容器元素
      const container = e.currentTarget;
      // 计算鼠标在容器中的相对位置（像素值）
      const rect = container.getBoundingClientRect();
      const mouseX = e.clientX - rect.left;
      const mouseY = e.clientY - rect.top;
      
      // 补偿偏移量：向右偏移600像素，向上偏移400像素
      // 这意味着实际鼠标位置需要向左偏移600，向下偏移400
      const adjustedMouseX = mouseX - 900;
      const adjustedMouseY = mouseY - 400;
      
      // 计算当前场景中心点相对于调整后鼠标位置的偏移
      const currentOffsetFromMouseX = adjustedMouseX - sceneOffsetX.value;
      const currentOffsetFromMouseY = adjustedMouseY - sceneOffsetY.value;
      
      // 计算缩放后的新偏移量，使缩放围绕调整后的鼠标位置进行
      const newOffsetFromMouseX = currentOffsetFromMouseX * scaleFactor;
      const newOffsetFromMouseY = currentOffsetFromMouseY * scaleFactor;
      
      // 更新场景偏移量
      sceneOffsetX.value = adjustedMouseX - newOffsetFromMouseX;
      sceneOffsetY.value = adjustedMouseY - newOffsetFromMouseY;
      
      // 更新缩放比例
      scale.value = newScale;
    }
  } else {
    // 单纯滚轮滚动，实现场景上下移动
    const moveAmount = e.deltaY * 0.5; // 调整移动速度
    sceneOffsetY.value += (-moveAmount);
  }
};

// 修改阻止鼠标滚轮缩放的函数，仅在侧边栏区域阻止
const preventZoom = (e) => {
  // 检查事件是否来自侧边栏区域
  if ((e.ctrlKey || e.metaKey) && e.target.closest('.floating-sidebar')) {
    e.preventDefault();
  }
};

// 监听触摸事件以防止缩放手势
const preventPinchZoom = (e) => {
  // 检测多点触控（缩放手势通常使用两个手指）
  if (e.touches && e.touches.length > 1) {
    e.preventDefault();
  }
};

// 导入被动事件监听器工具
import { addPassiveEventListener } from '@/utils/passiveEventListeners'
const init = ()=>{
  const route = useRoute();
  projectId.value = route.params.id;
  if(projectId.value === 'new'){
    createProject();
    return
  }
  getProjectInfo(projectId.value);
}
// 组件挂载时添加事件监听器
onMounted(() => {
  MeshyServer.pollingEnabled = true;
  // 每次进入都显示引导弹窗
  // showGuideModal.value = true;
  init();
  // 使用优化的被动事件监听器
  const removeWheelListener = addPassiveEventListener(document, 'wheel', preventZoom);
  const removeTouchStartListener = addPassiveEventListener(document, 'touchstart', preventPinchZoom);
  const removeTouchMoveListener = addPassiveEventListener(document, 'touchmove', preventPinchZoom);
  // 存储清理函数以便组件卸载时使用
  cleanupFunctions.value = {
    wheel: removeWheelListener,
    touchstart: removeTouchStartListener,
    touchmove: removeTouchMoveListener
  };
});

// 组件卸载时移除事件监听器，避免内存泄漏
onUnmounted(() => {// 禁用轮询
  MeshyServer.pollingEnabled = false;
  if (cleanupFunctions.value) {
    Object.values(cleanupFunctions.value).forEach(cleanup => {
      if (typeof cleanup === 'function') {
        cleanup();
      }
    });
  }
});

</script>

<style scoped>
/* 头部组件容器样式 */
.header-wrapper {
  position: fixed;
  top:8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  width: 98.6%;
  background-color: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(229, 231, 235, 0.8);
  transition: all 0.3s ease;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.06);
}

/* 暗色主题下的头部组件容器 */
html.dark .header-wrapper {
  background-color: rgba(31, 41, 55, 0.95);
  border-bottom-color: rgba(75, 85, 99, 0.8);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.2);
}

.creative-zone {
  color: #1f2937; /* 默认亮色主题文字颜色 */
  height: 100vh; /* 固定高度为视口高度 */
  overflow: hidden; /* 禁止溢出滚动 */
  display: flex;
  gap: 20px;
  box-sizing: border-box; /* 确保内边距不增加总尺寸 */
  position: relative;
  transition: all 0.3s ease;
  /* 背景渐变，移除网格 */
  background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 50%, #e5e7eb 100%);
}

/* 暗色主题适配 */
html.dark .creative-zone {
  color: #ffffff; /* 暗色主题文字颜色 */
  background: linear-gradient(135deg, #1F2937 0%, #111827 50%, #030712 100%);
}
.sidebar-container{
  position: absolute;
  left: 12px;
  top: 70px;
  z-index: 30;
  /* background-color: rgba(255, 255, 255, 0.95); */
  border-radius: 12px;
  /* border: 1px solid rgba(229, 231, 235, 0.8); */
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.06);
  transition: all 0.3s ease;
}

/* 暗色主题下的侧边栏容器 */
html.dark .sidebar-container {
  background-color: rgba(31, 41, 55, 0.95);
  border-bottom-color: rgba(75, 85, 99, 0.8);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.2);
}
.creative-zone::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(45deg, rgba(107, 70, 193, 0.05) 0%, transparent 50%, rgba(167, 139, 250, 0.05) 100%);
  pointer-events: none;
  z-index: 0;
}

/* 暗色主题下的背景叠加层 */
html.dark .creative-zone::before {
  background: linear-gradient(45deg, rgba(167, 139, 250, 0.1) 0%, transparent 50%, rgba(107, 70, 193, 0.1) 100%);
}

/* 全局box-sizing设置，确保所有元素的尺寸计算一致 */
* {
  box-sizing: border-box;
  touch-action: manipulation;
}

/* 防止在移动设备上的缩放手势 */
html {
  touch-action: pan-x pan-y;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
}

/* 防止用户选择文本和右键菜单 */
body {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}



/* 主内容区域 */
.main-content {
  flex: 1;
  position: relative;
  overflow: hidden;
  user-select: none;
  touch-action: none; /* 阻止触摸设备上的默认行为 */
}

.scene-container {
    width: 100%;
    height: 100%;
    transition: transform 0.1s ease-out;
    position: relative;
    z-index: 1;
    background: 
      /* 网格背景 */
      linear-gradient(rgba(107, 70, 193, 0.2) 1px, transparent 1px),
      linear-gradient(90deg, rgba(107, 70, 193, 0.2) 1px, transparent 1px),
      radial-gradient(ellipse at center, rgba(255, 255, 255, 0.8) 0%, rgba(243, 244, 246, 0.8) 100%);
    background-size: var(--grid-size) var(--grid-size), var(--grid-size) var(--grid-size), auto;
    background-position: center center, center center, center;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 
      inset 0 2px 8px rgba(0, 0, 0, 0.05),
      0 2px 8px rgba(0, 0, 0, 0.05);
    transition: all 0.3s ease;
  }

/* 暗色主题下的场景容器 */
html.dark .scene-container {
    background: 
      /* 网格背景 */
      linear-gradient(rgba(255, 255, 255, 0.15) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255, 255, 255, 0.15) 1px, transparent 1px),
      radial-gradient(ellipse at center, rgba(31, 41, 55, 0.8) 0%, rgba(17, 24, 39, 0.8) 100%);
    background-size: var(--grid-size) var(--grid-size), var(--grid-size) var(--grid-size), auto;
    background-position: center center, center center, center;
    box-shadow: 
      inset 0 2px 8px rgba(0, 0, 0, 0.3),
      0 2px 8px rgba(0, 0, 0, 0.2);
}

.scene-content {
  position: absolute;
  top: 0%;
  left: 0%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  will-change: transform; /* 提示浏览器提前准备渲染变换 */
  contain: layout style;
}

/* 可拖拽元素样式 */
.draggable-element {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* 初始居中 */
    cursor: grab;
    user-select: none;
    -webkit-user-drag: none; /* 禁用图片拖拽的默认行为 */
    -khtml-user-drag: none;
    -moz-user-drag: none;
    -o-user-drag: none;
    user-drag: none;
    /* 禁用图片重影效果 */
    pointer-events: auto;
    will-change: transform; /* 提示浏览器优化渲染 */
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    border-radius: 8px;
    box-shadow: 
      0 4px 12px rgba(107, 70, 193, 0.15),
      0 2px 6px rgba(0, 0, 0, 0.08),
      inset 0 1px 0 rgba(255, 255, 255, 0.2);
  }

/* 暗色主题下的可拖拽元素 */
html.dark .draggable-element {
    background: rgba(31, 41, 55, 0.95);
    box-shadow: 
      0 4px 12px rgba(167, 139, 250, 0.15),
      0 2px 6px rgba(0, 0, 0, 0.3),
      inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

.draggable-element:hover {
    transform: translate(-50%, -50%) scale(1.02);
    box-shadow: 
      0 8px 25px rgba(107, 70, 193, 0.25),
      0 4px 12px rgba(107, 70, 193, 0.15),
      inset 0 1px 0 rgba(255, 255, 255, 0.3);
  }

/* 暗色主题下的悬停效果 */
html.dark .draggable-element:hover {
    box-shadow: 
      0 8px 25px rgba(167, 139, 250, 0.25),
      0 4px 12px rgba(167, 139, 250, 0.15),
      inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

/* 当鼠标悬停在可拖拽元素上时显示删除按钮 */
.draggable-element:hover .delete-button {
  opacity: 1;
  visibility: visible;
  transform: scale(1);
}

/* 删除按钮样式 */
.delete-button {
  position: absolute;
  top: -10px;
  right: -10px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: linear-gradient(135deg, #6B46C1 0%, #553C9A 50%, #44337A 100%);
  color: white;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 
    0 4px 12px rgba(107, 70, 193, 0.4),
    0 2px 4px rgba(0, 0, 0, 0.1),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
  opacity: 0;
  visibility: hidden;
  flex-shrink: 0;
  transform: scale(0.8);
  backdrop-filter: blur(10px);
  overflow: hidden;
}

.delete-button::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(circle at center, rgba(255, 255, 255, 0.2) 0%, transparent 70%);
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.delete-button:hover::before {
  opacity: 1;
}

.delete-button:hover {
  background: linear-gradient(135deg, #7C3AED 0%, #6B46C1 50%, #553C9A 100%);
  transform: scale(1.15);
  box-shadow: 
    0 8px 25px rgba(107, 70, 193, 0.6),
    0 4px 12px rgba(107, 70, 193, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.delete-button:active {
  transform: scale(1.05);
  transition: all 0.1s ease;
}

.delete-button:focus {
  outline: none;
  box-shadow: 
    0 4px 12px rgba(255, 71, 87, 0.4),
    0 2px 4px rgba(0, 0, 0, 0.1),
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    0 0 0 3px rgba(255, 71, 87, 0.3);
}

.delete-button svg {
  width: 16px !important;
  height: 16px !important;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  stroke: currentColor;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
}

.delete-button:hover svg {
  transform: scale(1.1);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
}

.draggable-element * {
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  -o-user-drag: none;
  user-drag: none;
}

/* 拖动时的鼠标效果 */
.draggable-element:active {
  cursor: grabbing;
}

.ip-display-section {
  margin-top: 30px;
  padding: 20px;
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  text-align: center;
  transition: all 0.3s ease;
}

.ip-display-section h2 {
  margin-bottom: 20px;
  color: #333;
  font-size: 20px;
  font-weight: 600;
}

/* 暗色主题下的IP展示区域 */
html.dark .ip-display-section {
  background-color: rgba(31, 41, 55, 0.9);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

html.dark .ip-display-section h2 {
  color: #E5E7EB;
}



h1 {
  font-size: 2.5rem;
  margin-bottom: 1rem;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}

p {
  font-size: 1.2rem;
  opacity: 0.9;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .creative-zone {
    flex-direction: column;
    gap: 10px;
    padding: 5px;
  }
  
  .floating-sidebar {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 15px;
    max-height: calc(100vh - 10px);
  }
  
  .main-content {
    flex: 1;
    min-height: 0; /* 允许主内容区域缩小 */
  }
  
  h1 {
    font-size: 2rem;
  }
  
  p {
    font-size: 1rem;
  }
}
</style>
