<template>
  <div id="robot-interface" class="robot-container">
    <div class="tree-panel" :style="{ width: isTreeCollapsed ? '0px' : '240px' }">
      <el-tree
        v-if="!isTreeCollapsed"
        :data="treeData"
        :props="treeProps"
        default-expand-all
        @node-click="handleNodeClick"
        @node-contextmenu="handleNodeContextMenu"
      />
      <!-- 右键菜单组件 -->
      <ContextMenu
        :visible="contextMenu.visible"
        :position="contextMenu.position"
        :menu-items="contextMenu.items"
        @close="contextMenu.visible = false"
        @select="handleMenuItemSelect"
      />
    </div>
    <div class="robot-panel">
      <div id="robot-bg" ref="robotBg" :style="{ backgroundImage: `url(${robotImage})`, width: bgSize.width + 'px', height: bgSize.height + 'px' }">
        <TechButtonWithLine
          v-for="(area,index) in adjustedAreas"
          :key="area.id"
          :total-buttons="5"
          :button-index="area.index"
          :button-position="area.position"
          :end-x="area.x"
          :end-y="area.y"
          :button-name="area.label"
          :button-width="120"
          :button-height="50"
          @click="openPopup(area)"
        />
      </div>
      <div class="toggle-button" @click="isTreeCollapsed = !isTreeCollapsed">
        {{ isTreeCollapsed ? '>' : '<' }}
      </div>
      
    </div>
    <div
      v-for="(popup, index) in popups"
      :key="popup.id"
      class="popup"
      :style="{
        position: 'absolute',
        top: popup.top,
        left: popup.left,
        zIndex: popup.zIndex,
        width: popup.width + 'px',
        height: popup.height + 'px'
      }"
      :class="{ resizing: isResizing[index], dragging: isDragging && dragIndex === index }"
    >
      <div class="drag-handle" @mousedown="startDragging($event, index)">
        <span class="popup-title">{{ popup.id.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) }}</span>
        <div class="popup-controls">
          <span class="control-icon" @click="minimizePopup(index)">⧓</span>
          <span class="control-icon" @click="maximizePopup(index)">□</span>
          <span class="control-icon close-icon" @click="closePopup(index)">×</span>
        </div>
      </div>
      <component :is="popup.component" v-bind="popup.props" :initialDeviceId = "popup.deviceId" :initialTerminalId = "popup.configId" />
      <div class="resize-edge top" @mousedown="startResizing($event, index, 'top')"></div>
      <div class="resize-edge bottom" @mousedown="startResizing($event, index, 'bottom')"></div>
      <div class="resize-edge left" @mousedown="startResizing($event, index, 'left')"></div>
      <div class="resize-edge right" @mousedown="startResizing($event, index, 'right')"></div>
      <div class="resize-corner top-left" @mousedown="startResizing($event, index, 'top-left')"></div>
      <div class="resize-corner top-right" @mousedown="startResizing($event, index, 'top-right')"></div>
      <div class="resize-corner bottom-left" @mousedown="startResizing($event, index, 'bottom-left')"></div>
      <div class="resize-corner bottom-right" @mousedown="startResizing($event, index, 'bottom-right')"></div>
    </div>

    <!-- 添加你现有的配置编辑对话框 -->
    <el-dialog :title="dialogTitle" v-model="dialogFormVisible" width="500px" append-to-body>
      <el-form ref="robotConfigFormRef" :model="dialogForm" :rules="dialogRules" label-width="80px">
        <el-form-item label="配置类型" prop="configType">
          <el-select v-model="dialogForm.configType" placeholder="请选择配置类型，区分是设备还是终端">
            <el-option
              v-for="dict in de_robot_config_type"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="配置ID" prop="configId">
          <el-select v-model="dialogForm.configId" placeholder="请选择配置信息" v-if="dialogForm.configType == 1">
            <el-option
              v-for="dict in terminalConfigList"
              :key="dict.id"
              :label="dict.name"
              :value="dict.id"
            ></el-option>
          </el-select>
          <el-select v-model="dialogForm.configId" placeholder="请选择配置信息" v-else>
            <el-option
              v-for="dict in registerList"
              :key="dict.id"
              :label="dict.deviceName || dict.deviceCode"
              :value="dict.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="节点名称" prop="nodeName">
          <el-input v-model="dialogForm.nodeName" placeholder="请输入节点名称，名称可以随意取，不强制唯一" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitDialogForm">确 定</el-button>
          <el-button @click="cancelDialog">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, computed, onUnmounted, watch, nextTick } from 'vue';
import HandControl from '../register/components/DexHand/index.vue';
import CameraView from '../register/components/Camera/index.vue';
import MusicPlayer from '../register/components/Speaker/index.vue';
import MechanicalArm from '../register/components/MechanicalArm/index.vue';
import image from '@/assets/images/robot.png';
import {  listRobot, getRobot, updateRobot } from '@/api/device/robot';
import { listTerminal } from '@/api/device/terminal'
import { listRegister } from '@/api/device/register'
import ContextMenu from './ContextMenu.vue'; // 导入右键菜单组件
import TechButtonWithLine from './TechButtonWithLine.vue';


// --- Existing Code ---
// 组件映射
const componentsMap = {
  HandControl,
  CameraView,
  MusicPlayer,
  MechanicalArm,
  TechButtonWithLine
};

const { proxy } = getCurrentInstance()
const { de_robot_config_type } = proxy.useDict("de_robot_config_type")

const terminalConfigList = ref([])
const registerList = ref([])

const robotImage = image;
const robotBg = ref(null);
const isTreeCollapsed = ref(false);
const popups = ref([]);
const isDragging = ref(false);
const isResizing = ref([]);
const currentZIndex = ref(2000);
const dragIndex = ref(null);
const resizeStart = ref({ index: null, startX: 0, startY: 0, originalWidth: 0, originalHeight: 0, originalTop: 0, originalLeft: 0, edge: '' });
const imageDimensions = ref({ width: 0, height: 0 });
const containerSize = ref({ width: 0, height: 0 });
const bgSize = ref({ width: 0, height: 0 });

// 原始坐标和尺寸（基于图片原始大小）
const originalAreas = ref([
  { id: 'camera', index: 1, position: 'left', x: 250, y: 134, component: CameraView, label: '摄像头', deviceId: '', configId: '' },
  { id: 'mouth', index: 1, position: 'right', x: 299, y: 220, component: MusicPlayer, label: '扬声器', deviceId: '', configId: '' },
  { id: 'arm-left', index: 2, position: 'left', x: 100, y: 650, component: MechanicalArm, label: '左机械臂', deviceId: '', configId: '' },
  { id: 'arm-right', index: 2, position: 'right', x: 480, y: 650, component: MechanicalArm, label: '右机械臂', deviceId: '', configId: '' },
  { id: 'hand-left', index: 3, position: 'left', x: 75, y: 885, component: HandControl, label: '左手', deviceId: '', configId: '' },
  { id: 'hand-right', index: 3, position: 'right', x: 520, y: 885, component: HandControl, label: '右手', deviceId: '', configId: '' },
]);

// 树数据
const treeData = ref([
]);

/**
 * 将扁平化的节点数据转换为树形结构。
 * 假设 id === 'root' 的节点是顶级节点，并且保留所有原始数据。
 *
 * @param {Array<Object>} flatData - 扁平化的节点数据数组。
 * @returns {Array<Object>} 转换后的树形结构数据。
 */
function convertFlatDataToTree(flatData) {
  const nodeMap = new Map();
  const rootNodes = [];

  // 1. 将所有节点存入 Map，并初始化 children 数组
  flatData.forEach(item => {
    // 复制 item，避免直接修改原始数据，并添加 children 属性
    // 保留所有原始数据字段
    nodeMap.set(item.id, { ...item, children: [] });
  });

  // 2. 遍历 Map，根据 pid 构建树形结构
  nodeMap.forEach(node => {
    if (node.pid === 'root') {
      // 如果 pid 是 'root'，则该节点是顶级节点
      rootNodes.push(node);
    } else {
      // 查找父节点
      const parent = nodeMap.get(node.pid);
      if (parent) {
        // 将当前节点添加到父节点的 children 数组中
        parent.children.push(node);
      } else {
        // 如果找不到父节点，可以选择抛出错误或忽略该节点
        console.warn(`节点 ${node.id} 的父节点 ${node.pid} 不存在，该节点将被忽略。`);
      }
    }
  });

  // 3. 最终返回的就是识别出的顶级节点列表
  //    这些顶级节点已经通过上面的逻辑构建了各自的子树
  return rootNodes;
}

const treeProps = { children: 'children', label: 'nodeName' };

const getAll = () => { 
  listRobot().then(res => { 
    treeData.value = convertFlatDataToTree(res.data)
    const configId = treeData.value[0].configId;
    for (let item of treeData.value[0].children) {
      const areaInfo = originalAreas.value.filter(area => area.label == item.nodeName)[0];
      areaInfo.deviceId = item.configId;
      areaInfo.configId = configId;
    }
  });
};

const handleNodeClick = (data) => {
  console.log('点击节点', data.label);
};

// --- New Code for Right-Click Menu ---
const contextMenu = ref({
  visible: false,
  position: { x: 0, y: 0 },
  items: [],
  currentNode: null // 存储当前右键点击的节点
});

const handleNodeContextMenu = (event, data, node, component) => {
  // 阻止默认右键菜单
  event.preventDefault();
  // 阻止事件冒泡到父元素（比如 el-tree 本身）
  event.stopPropagation();

  contextMenu.value.position = { x: event.clientX, y: event.clientY };
  contextMenu.value.currentNode = data; // 存储当前节点
  contextMenu.value.items = [
    { key: 'edit', label: '编辑' },
    // 可以添加其他菜单项，例如 '添加子节点', '删除' 等
    // { key: 'add', label: '添加子节点' },
    // { key: 'delete', label: '删除' }
  ];
  contextMenu.value.visible = true;
};

const handleMenuItemSelect = (item) => {
  if (item.key === 'edit') {
    openDialogForEdit(contextMenu.value.currentNode);
  }
  // 根据item.key处理其他菜单项
  // else if (item.key === 'add') {
  //   console.log('添加子节点 to:', contextMenu.value.currentNode);
  //   // 实现添加子节点的逻辑
  // }
  // else if (item.key === 'delete') {
  //   console.log('删除节点:', contextMenu.value.currentNode);
  //   // 实现删除节点的逻辑
  // }
};

// --- Integration with Existing Dialog ---
const dialogFormVisible = ref(false);
const dialogTitle = ref('');
const robotConfigFormRef = ref(null);
const dialogForm = ref({
  configId: '',
  configType: '',
  pid: '',
  nodeName: ''
});

const robotOptions = ref([]); // 用于el-tree-select的数据

const openDialogForEdit = (nodeData) => {
  console.log('编辑节点:', nodeData.id);
  dialogTitle.value = '编辑机器人配置';
  getRobot(nodeData.id).then(res => {
    dialogForm.value = {
      ...res.data,
    };
    dialogFormVisible.value = true;
    // 确保 robotOptions 有数据，以便 tree-select 可以渲染
    // 这里假设 treeData 结构能直接作为 robotOptions
    robotOptions.value = treeData.value[0].children; // 假设第一个子节点是可选择的父节点，或根据实际情况调整
    nextTick(() => {
      robotConfigFormRef.value?.clearValidate(); // 清除之前的校验
    });
  })
  
};

// 提交对话框表单
const submitDialogForm = () => {
  robotConfigFormRef.value.validate(async (valid) => {
    if (valid) {
      // 假设你有一个方法来更新 treeData
      await updateRobot(dialogForm.value);
      dialogFormVisible.value = false;
      getAll();
      // Optionally show a success message
      ElMessage.success('配置更新成功');
    } else {
      console.log('表单校验失败');
    }
  });
};

// 取消对话框
const cancelDialog = () => {
  dialogFormVisible.value = false;
};

// --- Existing Code (adjusted for clarity and potential issues) ---

// 计算调整后的区域
const adjustedAreas = computed(() => {
  if (!imageDimensions.value.width || !imageDimensions.value.height || !robotBg.value) return [];
  const treePanelWidth = isTreeCollapsed.value ? 0 : 240;
  // 确保 robot-panel 内部的 content 区域是可用的
  const contentContainerWidth = containerSize.value.width - treePanelWidth;
  const containerHeight = containerSize.value.height;

  // 仅当机器人背景图存在时，才计算缩放比例
  if (!robotBg.value || !robotBg.value.parentElement) {
    return [];
  }

  // 获取 robot-panel 的实际可用尺寸
  const robotPanel = robotBg.value.parentElement;
  const robotPanelRect = robotPanel.getBoundingClientRect();
  const robotPanelContentWidth = robotPanelRect.width;
  const robotPanelContentHeight = robotPanelRect.height;

  const scaleX = robotPanelContentWidth / imageDimensions.value.width;
  const scaleY = robotPanelContentHeight / imageDimensions.value.height;
  const scale = Math.min(scaleX, scaleY, 1); // 防止放大，如果图片比容器小，就按100%显示

  const scaledWidth = imageDimensions.value.width * scale;
  const scaledHeight = imageDimensions.value.height * scale;

  // 更新背景图片尺寸
  bgSize.value = { width: scaledWidth, height: scaledHeight };

  // 计算中心对齐的偏移量
  const offsetX = (robotPanelContentWidth - scaledWidth) / 2;
  const offsetY = (robotPanelContentHeight - scaledHeight) / 2;


  return originalAreas.value.map(area => ({
    ...area,
    x: area.x * scale + offsetX, // 应用缩放和中心偏移
    y: area.y * scale + offsetY, // 应用缩放和中心偏移
    width: area.width * scale,
    height: area.height * scale
  }));
});

// 打开弹窗，考虑树宽度和padding偏移
const openPopup = (area) => {
  const existingPopup = popups.value.find(p => p.id === area.id);
  if (existingPopup) {
    console.log('已打开ID为', area.id, '的弹窗');
    // 如果弹窗已存在，可以考虑将其置顶
    existingPopup.zIndex = currentZIndex.value++;
    return;
  }
  const treeWidth = isTreeCollapsed.value ? 0 : 240;
  // 弹窗的 left 偏移需要考虑 tree-panel 的宽度，以及 robot-panel 的 padding
  const leftOffset = treeWidth + 20; // tree宽度 + robot-panel padding-left

  const popup = {
    id: area.id,
    component: area.component,
    top: `${area.y}px`, // area.y 已经是居中后的 Y 坐标
    left: `${area.x + leftOffset}px`, // area.x 已经是居中后的 X 坐标，再加上 treePanel宽度和robot-panel的padding
    zIndex: currentZIndex.value++,
    deviceId: area.deviceId,
    configId: area.configId,
    width: 640,
    height: 480,
    originalWidth: 640,
    originalHeight: 480,
    originalTop: `${area.y}px`,
    originalLeft: `${area.x + leftOffset}px`,
    isMaximized: false,
    props: { terminalId: 'your-terminal-id', cameraId: 'your-camera-id' } // 示例props
  };
  popups.value.push(popup);
  isResizing.value.push(false);
  console.log('打开弹窗ID', area.id, '初始尺寸:', popup.width, 'x', popup.height, '位置:', popup.top, popup.left);
};

// 关闭弹窗
const closePopup = (index) => {
  popups.value.splice(index, 1);
  isResizing.value.splice(index, 1);
  console.log('关闭弹窗索引', index);
};

// 最小化弹窗
const minimizePopup = (index) => {
  const popup = popups.value[index];
  if (popup.isMaximized) {
    popup.width = popup.originalWidth;
    popup.height = popup.originalHeight;
    popup.top = popup.originalTop;
    popup.left = popup.originalLeft;
    popup.isMaximized = false;
    console.log('最小化弹窗', popup.id, '到尺寸:', popup.width, 'x', popup.height, '位置:', popup.top, popup.left);
  }
};

// 最大化弹窗
const maximizePopup = (index) => {
  const popup = popups.value[index];
  if (!popup.isMaximized) {
    popup.originalWidth = popup.width;
    popup.originalHeight = popup.height;
    popup.originalTop = popup.top;
    popup.originalLeft = popup.left;
    // 最大化时，需要考虑右侧的区域，而不是整个窗口
    const treeWidth = isTreeCollapsed.value ? 0 : 240;
    const availableWidth = window.innerWidth - treeWidth - 240;
    const availableHeight = window.innerHeight - 120;
    popup.width = availableWidth;
    popup.height = availableHeight;
    popup.top = '0px';
    popup.left = `${treeWidth}px`; // 紧贴 tree panel
    popup.isMaximized = true;
    console.log('最大化弹窗', popup.id, '到尺寸:', popup.width, 'x', popup.height, '位置:', popup.top, popup.left);
  }
};

// 拖动相关逻辑
const startDragging = (e, index) => {
  e.stopPropagation(); // 阻止事件冒泡到其他可点击区域
  isDragging.value = true;
  dragIndex.value = index;
  const popup = popups.value[index];
  popup.startX = e.pageX - parseInt(popup.left);
  popup.startY = e.pageY - parseInt(popup.top);
  popup.zIndex = currentZIndex.value++;
  document.addEventListener('mousemove', dragHandler);
  document.addEventListener('mouseup', stopDragging);
};

const dragHandler = (e) => {
  if (isDragging.value && dragIndex.value !== null) {
    requestAnimationFrame(() => {
      const popup = popups.value[dragIndex.value];
      // 限制拖动范围，防止移出可视区域
      const treeWidth = isTreeCollapsed.value ? 0 : 240;
      const maxX = window.innerWidth - popup.width - treeWidth; // 考虑 tree panel
      const maxY = window.innerHeight - popup.height;

      let newTop = e.pageY - popup.startY;
      let newLeft = e.pageX - popup.startX;

      // 限制在可视窗口内
      newTop = Math.max(0, newTop);
      newLeft = Math.max(treeWidth, newLeft); // 限制左侧不能移入 tree panel 区域

      newTop = Math.min(maxY, newTop);
      newLeft = Math.min(maxX, newLeft);

      popup.top = `${newTop}px`;
      popup.left = `${newLeft}px`;
    });
  }
};

const stopDragging = () => {
  isDragging.value = false;
  dragIndex.value = null;
  document.removeEventListener('mousemove', dragHandler);
  document.removeEventListener('mouseup', stopDragging);
};

// 调整大小相关逻辑
const startResizing = (e, index, edge) => {
  e.stopPropagation(); // 阻止事件冒泡
  const popup = popups.value[index];
  resizeStart.value = {
    index,
    startX: e.pageX,
    startY: e.pageY,
    originalWidth: popup.width,
    originalHeight: popup.height,
    originalTop: parseInt(popup.top) || 0,
    originalLeft: parseInt(popup.left) || 0,
    edge
  };
  isResizing.value[index] = true;
  popup.zIndex = currentZIndex.value++; // 调整大小的时候也提高 z-index
  document.addEventListener('mousemove', handleResize);
  document.addEventListener('mouseup', stopResizingGlobal);
};

const handleResize = (e) => {
  if (resizeStart.value.index !== null) {
    const index = resizeStart.value.index;
    const popup = popups.value[index];
    const diffX = e.pageX - resizeStart.value.startX;
    const diffY = e.pageY - resizeStart.value.startY;
    const minWidth = 200;
    const minHeight = 150;

    const treeWidth = isTreeCollapsed.value ? 0 : 240;

    switch (resizeStart.value.edge) {
      case 'top':
        const newHeightT = Math.max(minHeight, resizeStart.value.originalHeight - diffY);
        popup.height = newHeightT;
        popup.top = `${Math.max(0, resizeStart.value.originalTop + (resizeStart.value.originalHeight - newHeightT))}px`;
        break;
      case 'bottom':
        popup.height = Math.max(minHeight, resizeStart.value.originalHeight + diffY);
        break;
      case 'left':
        const newWidthL = Math.max(minWidth, resizeStart.value.originalWidth - diffX);
        popup.width = newWidthL;
        popup.left = `${Math.max(treeWidth, resizeStart.value.originalLeft + (resizeStart.value.originalWidth - newWidthL))}px`;
        break;
      case 'right':
        popup.width = Math.max(minWidth, resizeStart.value.originalWidth + diffX);
        break;
      case 'top-left':
        const newWidthTL = Math.max(minWidth, resizeStart.value.originalWidth - diffX);
        const newHeightTL = Math.max(minHeight, resizeStart.value.originalHeight - diffY);
        popup.width = newWidthTL;
        popup.height = newHeightTL;
        popup.left = `${Math.max(treeWidth, resizeStart.value.originalLeft + (resizeStart.value.originalWidth - newWidthTL))}px`;
        popup.top = `${Math.max(0, resizeStart.value.originalTop + (resizeStart.value.originalHeight - newHeightTL))}px`;
        break;
      case 'top-right':
        const newWidthTR = Math.max(minWidth, resizeStart.value.originalWidth + diffX);
        const newHeightTR = Math.max(minHeight, resizeStart.value.originalHeight - diffY);
        popup.width = newWidthTR;
        popup.height = newHeightTR;
        popup.top = `${Math.max(0, resizeStart.value.originalTop + (resizeStart.value.originalHeight - newHeightTR))}px`;
        break;
      case 'bottom-left':
        const newWidthBL = Math.max(minWidth, resizeStart.value.originalWidth - diffX);
        const newHeightBL = Math.max(minHeight, resizeStart.value.originalHeight + diffY);
        popup.width = newWidthBL;
        popup.height = newHeightBL;
        popup.left = `${Math.max(treeWidth, resizeStart.value.originalLeft + (resizeStart.value.originalWidth - newWidthBL))}px`;
        break;
      case 'bottom-right':
        popup.width = Math.max(minWidth, resizeStart.value.originalWidth + diffX);
        popup.height = Math.max(minHeight, resizeStart.value.originalHeight + diffY);
        break;
    }
    // 限制弹窗不超出容器
    const treePanelWidth = isTreeCollapsed.value ? 0 : 240;
    const containerRect = robotBg.value.parentElement.getBoundingClientRect();
    const maxLeft = containerRect.width - popup.width - treePanelWidth; // 考虑 robot-panel padding
    const maxTop = containerRect.height - popup.height;

    popup.left = `${Math.max(treePanelWidth, parseInt(popup.left))}px`; // 限制左侧不进入 tree panel
    popup.top = `${Math.max(0, parseInt(popup.top))}px`; // 限制顶部
    popup.left = `${Math.min(maxLeft + treePanelWidth, parseInt(popup.left))}px`; // 限制右侧
    popup.top = `${Math.min(maxTop, parseInt(popup.top))}px`; // 限制底部
  }
};

const stopResizingGlobal = () => {
  if (resizeStart.value.index !== null) {
    isResizing.value[resizeStart.value.index] = false;
    resizeStart.value = { index: null, startX: 0, startY: 0, originalWidth: 0, originalHeight: 0, originalTop: 0, originalLeft: 0, edge: '' };
    document.removeEventListener('mousemove', handleResize);
    document.removeEventListener('mouseup', stopResizingGlobal);
  }
};

// 防抖函数
const debounce = (fn, delay) => {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
};

// 更新容器和图片尺寸
const updateDimensions = debounce(() => {
  if (robotBg.value && robotBg.value.parentElement) {
    containerSize.value = {
      width: robotBg.value.parentElement.offsetWidth - 40, // 左右padding 20*2
      height: robotBg.value.parentElement.offsetHeight // 无垂直padding
    };
    // console.log('更新容器尺寸:', containerSize.value.width, 'x', containerSize.value.height);
  }
}, 50);

onMounted(() => {
  const img = new Image();
  img.src = robotImage;
  img.onload = () => {
    imageDimensions.value = { width: img.width, height: img.height };
    console.log('图片尺寸:', imageDimensions.value.width, 'x', imageDimensions.value.height);
    if (robotBg.value) {
      // 监听 robot-panel 的父元素（通常是 #app 或 main-container）的尺寸变化
      const containerElement = robotBg.value.parentElement;
      if (containerElement) {
        const observer = new ResizeObserver(updateDimensions);
        observer.observe(containerElement);
        watch(() => isTreeCollapsed.value, updateDimensions, { immediate: true });
        updateDimensions(); // 初始更新
        // 在 unmounted 时断开观察
        onUnmounted(() => {
          observer.disconnect();
          document.removeEventListener('mousemove', handleResize);
          document.removeEventListener('mouseup', stopResizingGlobal);
          document.removeEventListener('mousemove', dragHandler); // 确保拖动监听也被移除
          document.removeEventListener('mouseup', stopDragging);
        });
      }
    }
  };
  getAll();
  listRegister().then((res) => {
    registerList.value = res.rows;
  });
  listTerminal().then((res) => {
    terminalConfigList.value = res.rows;
  });
  // 初始化 robotOptions
  // const rootNode = treeData.value.find(item => item.id === 'robot-node-config');
  // if (rootNode && rootNode.children) {
  //   robotOptions.value = rootNode.children.filter(node => node.pid === 'root'); // 假设 'root' 是顶级父节点的 pid
  // } else {
  //   robotOptions.value = [];
  // }
});

// onUnmounted 已经包含在 onMounted 的回调中
</script>

<style scoped>
.robot-container {
  width: 100%;
  position: relative;
  display: flex;
  overflow: hidden;
  padding: 0;
  background-color: #fff;
  border-radius: 10px;
  height: calc(100vh - 120px); /* 示例高度，请根据实际布局调整 */
  box-sizing: border-box;
}

.tree-panel {
  flex-shrink: 0;
  border-right: 1px solid #ddd;
  overflow-y: auto;
  height: 100%; /* 填充父容器高度 */
  transition: width 0.3s ease;
  background-color: #f8f8f8; /* 示例背景色 */
}

.tree-panel:deep(.el-tree) {
  padding: 10px !important;
  background: transparent; /* 确保 treePanel 的背景色生效 */
}

.robot-panel {
  flex-grow: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  padding: 0 20px; /* 左右内边距 */
  position: relative;
}

#robot-bg {
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  min-width: 0;
  min-height: 0;
  /* position: relative; 添加 relative 定位 */
  /* 初始设置一个尺寸，或者由 JS 动态计算 */
  width: 100%; 
  height: 100%;
  /* box-sizing: border-box; 包含 padding */
}

.toggle-button {
  position: absolute;
  left: 20px; /* 紧贴 robot-panel 的左边距 */
  top: 10px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 24px;
  background-color: #e0e0e0;
  border-radius: 4px;
  z-index: 2001;
  box-shadow: 0 2px 4px rgba(0,0,0,.1);
}

.toggle-button:hover {
  background-color: #d0d0d0;
}

.clickable-area {
  cursor: pointer;
  position: absolute;
  /* background: rgba(255, 0, 0, 0.2); */ /* 用于调试区域 */
  box-sizing: border-box;
}

.clickable-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  text-shadow: 0 0 5px #000;
  animation: blink 1.5s infinite;
  font-size: 14px;
  font-weight: bold;
  pointer-events: none; /* 防止文本本身捕获点击事件 */
}

@keyframes blink {
  0% { opacity: 1; }
  50% { opacity: 0; }
  100% { opacity: 1; }
}

.popup {
  display: flex;
  flex-direction: column;
  background: white;
  user-select: none;
  overflow: hidden; /* 整体 overflow hidden，内容由子组件处理 */
  box-sizing: border-box;
  transition: width 0.2s, height 0.2s, top 0.2s, left 0.2s;
  border: 1px solid #eee;
  position: absolute; /* 确保 popup 是绝对定位 */
}

.popup.dragging {
  transition: none;
  opacity: 0.8;
}

.drag-handle {
  height: 30px;
  background: #e0e0e0;
  cursor: move;
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid #eee; /* 增加分隔线 */
}

.popup-title {
  font-size: 16px;
  font-weight: bold;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: absolute;
  left: 10px;
  right: 60px; /* 为右侧按钮留出空间 */
  text-align: center;
  user-select: none; /* 标题不可选 */
}

.popup-controls {
  position: absolute;
  right: 5px;
  display: flex;
  gap: 5px;
}

.control-icon {
  cursor: pointer;
  font-size: 18px;
  padding: 4px 8px;
  background: #f0f0f0;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
}

.control-icon:hover {
  background: #d0d0d0;
}

.close-icon {
  color: #ff4444;
}

.close-icon:hover {
  background: #ff6666;
}

.resize-edge, .resize-corner {
  position: absolute;
  background: transparent;
  z-index: 2;
  box-sizing: border-box;
}

.top { top: 0; left: 0; right: 0; height: 10px; cursor: ns-resize; }
.bottom { bottom: 0; left: 0; right: 0; height: 5px; cursor: ns-resize; }
.left { top: 0; bottom: 0; left: 0; width: 5px; cursor: ew-resize; }
.right { top: 0; bottom: 0; right: 0; width: 5px; cursor: ew-resize; }

.resize-corner {
  width: 12px;
  height: 12px;
  background: rgba(0, 0, 0, 0.05); /* 增加一些可见性 */
  border-radius: 2px;
}

.top-left { top: 0; left: 0; cursor: nwse-resize; }
.top-right { top: 0; right: 0; cursor: nesw-resize; }
.bottom-left { bottom: 0; left: 0; cursor: nesw-resize; }
.bottom-right { bottom: 0; right: 0; cursor: nwse-resize; }

.popup.resizing {
  transition: none;
}

/* dialog 样式，与你原有的保持一致 */
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding-top: 10px;
  border-top: 1px solid #eee;
}
.el-dialog {
  display: flex;
  flex-direction: column;
  margin: 0 !important;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.el-dialog .el-dialog__body {
  flex: 1;
  overflow: auto;
}
</style>