<template>
  <div class="tray-binding-container">
    <!-- 头部区域 -->
    <div class="header">
      <div class="back-button" @click="goBack">
        <i class="el-icon-back"></i> 返回托盘列表看板
      </div>
    </div>

    <!-- 托盘ID绑定区域 -->
    <div class="tray-id-section">
      <div class="tray-info">
        <div class="tray-display">
          <div class="tray-label">当前托盘：</div>
          <div class="tray-id">{{ fTrayCode || 'TP-未绑定' }}</div>
        </div>

        <!-- 添加托盘状态 -->
        <div class="tray-status">
          <div class="status-label">托盘状态：</div>
          <el-tag :type="trayStatusTagType" size="medium">
            {{ trayStatusText }}
          </el-tag>
        </div>
      </div>

      <!-- 设备扫描区域 -->
      <div
        class="scan-section"
        style="align-items: center;"
        v-if="trayStatus !== '1'"
      >
        <input
          type="text"
          class="scan-input"
          :placeholder="scanPlaceholder"
          v-model="deviceInput"
          @keyup.enter="addDevice"
          ref="deviceInput"
          :disabled="trayStatus === '1'"
        >
        <div class="status-bar">
          <i class="fas fa-info-circle"></i>
          <span v-if="trayStatus === '0'">已绑定设备: <span class="filled-count">{{ filledCount }}</span>/72</span>
          <span v-if="trayStatus === '3'">待处理异常设备: <span class="filled-count">{{ abnormalCount }}</span>/{{ initialAbnormalCount }}</span>
        </div>
      </div>
    </div>

    <!-- 设备矩阵区域 -->
    <div class="devices-grid-container">
      <div class="devices-grid">
        <div
          v-for="(device, index) in devices"
          :key="index"
          class="device-cell"
          :class="{
                  'active': activeCell === index,
                  'empty': !device.deviceCode,
                  'error': device.deviceCode && (device.status === '0' || device.status === '5')
                }"
          @click="setActiveCell(index)"
        >
          <div class="device-id">
            {{ device.deviceCode || '+' }}
            <!-- 添加错误状态图标 -->
            <i v-if="device.deviceCode && device.status === '0'" class="error-icon fas fa-exclamation-circle"></i>
          </div>
          <div class="position-indicator">
            {{ getPositionLabel(index) }}
          </div>
        </div>
      </div>
    </div>

    <!-- 操作按钮区域 -->
    <div class="binding-controls">
      <button
        v-if="trayStatus === '0'"
        class="reset-btn"
        @click="resetAll"
      >
        <i class="fas fa-redo"></i> 重置所有
      </button>
      <button
        v-if="trayStatus === '0' || trayStatus === '4'"
        class="bind-btn"
        @click="bindTray"
        :disabled="bindButtonDisabled"
      >
        <i class="fas fa-paper-plane"></i>
        {{ '提交绑定' }}
      </button>
      <!-- 一键解绑按钮 - 仅status=3时显示 -->
      <button
        v-if="trayStatus === '3'"
        class="unbind-btn"
        @click="unbindAll"
      >
        <i class="fas fa-unlink"></i> 一键解绑
      </button>
    </div>

    <!-- 使用说明区域 -->
    <div class="instructions">
      <h3><i class="fas fa-lightbulb"></i> 使用说明</h3>
      <ul>
        <li v-if="trayStatus === '0'"> 点击矩阵中的单元格或按顺序扫描<span class="highlight">设备条码</span>（扫描枪自动识别）</li>
        <li v-if="trayStatus === '0'"> 设备条码会自动填充到当前激活的单元格中</li>
        <li v-if="trayStatus === '3'"> 请扫描设备条码进行解绑</li>
        <li v-if="trayStatus === '3'"> 每解绑一个异常设备，待处理数量将减少</li>
        <li> 可以手动点击任何单元格进行修改或重新扫描</li>
        <li><i class="fas fa-bolt scanner-icon"></i> 提示：使用扫描枪时，请确保输入框获得焦点</li>
      </ul>
    </div>
  </div>
</template>

<script>
import {
  batchAdd,
  unbindSingleDevice,
  getAllExcludeUnbindingTimeByTrayId, unbindAllDevice, batchUpdateDeviceCodeAndUnbindingTime
} from "@/api/palletDeviceBinding/binding"
import {resetAll} from "@/api/palletDeviceBinding/binding"
export default {
  name: "TrayBinding",
  props: {
    modbusDeviceData: {
      type: Object,
      default: () => ({})
    }
  },
  watch: {
    modbusDeviceData: {
      immediate: true,
      handler(newVal) {
        this.fTrayId = newVal.fTrayId;
        this.fTrayCode = newVal.fTrayCode;
        this.trayStatus = newVal.fStatus; // 从父组件获取托盘状态
        // 查询托盘是否有绑定的设备数据
        this.getAllBindingData(newVal.fTrayId);
      }
    },
    // 监听输入框内容变化，实现手动输入自动触发
    deviceInput(newVal) {
      // 清除上一次的计时器
      if (this.inputTimer) {
        clearTimeout(this.inputTimer);
      }
      // 输入为空时不触发
      if (!newVal.trim()) return;

      // 500ms内无输入变化，则视为输入完成，自动触发addDevice
      this.inputTimer = setTimeout(() => {
        this.addDevice();
      }, 500); // 可根据需求调整延迟时间（如300ms-1000ms）
    },
  },
  beforeDestroy() {
    // 组件销毁时清除计时器，避免内存泄漏
    if (this.inputTimer) {
      clearTimeout(this.inputTimer);
    }
  },
  data() {
    return {
      // 托盘ID
      fTrayId: '',
      fTrayCode: '',
      trayInput: '',

      // 托盘状态
      trayStatus: '0', // 0:空闲, 1:运行中, 2:老化完成，3:标定完成

      // 异常设备计数
      abnormalCount: 0,
      initialAbnormalCount: 0,

      // 设备矩阵数据 (8x9 = 72个设备)
      devices: Array(72).fill().map((_, i) => {
        const row = Math.floor(i / 9) + 1; // 1-8行
        const col = (i % 9) + 1; // 1-9列
        let number;

        // 计算当前行的起始数字
        const rowStart = (row - 1) * 9 + 1;
        const rowEnd = row * 9;

        if (row % 2 === 1) {
          // 奇数行：从左到右递增（1-9, 19-27, 37-45, 55-63）
          number = rowStart + (col - 1);
        } else {
          // 偶数行：从右到左递增（18-10, 36-28, 54-46, 72-64）
          number = rowEnd - (col - 1);
        }

        return {
          index: i + 1,
          number: number,
          deviceCode: '',
          row: row,
          col: col
        }
      }),

      // 当前激活的单元格
      activeCell: 0,

      // 设备输入
      deviceInput: '',

      inputTimer: null, // 用于记录输入计时器
    };
  },
  computed: {
    // 计算已填充的设备数量
    filledCount() {
      return this.devices.filter(d => d.deviceCode).length;
    },

    // 计算绑定按钮是否禁用
    bindButtonDisabled() {
      if (this.trayStatus === '0' || this.trayStatus === '4') {
        return this.filledCount === 0 || !this.fTrayCode;
      } else if (this.trayStatus === '3') {
        return this.abnormalCount > 0;
      }
      return true;
    },

    // 托盘状态标签类型
    trayStatusTagType() {
      const map = {
        '0': 'success', // 空闲 - 绿色
        '1': 'primary', // 运行中 - 黄色
        '2': 'danger',   // 老化完成 - 红色
        '3': 'warning', // 标定完成
        '4': 'info' // 标定完成
      };
      return map[this.trayStatus] || 'info';
    },

    // 托盘状态文本
    trayStatusText() {
      const map = {
        '0': '空闲',
        '1': '运行中',
        '2': '老化完成',
        '3': '标定完成',
        '4': '已绑定'
      };
      return map[this.trayStatus] || '未知状态';
    },

    // 扫描输入框提示语
    scanPlaceholder() {
      return this.trayStatus === '3'
        ? '解绑设备条码...'
        : '扫描设备条码...';
    }
  },
  methods: {
    getAllBindingData(trayId) {
      this.devices = [];
      getAllExcludeUnbindingTimeByTrayId(trayId).then(res => {
        if(res.code === 200 && res.data.length > 0) {
          this.devices = res.data;

          // 计算初始异常设备数量（标定完成状态）
          if (this.trayStatus === '3') {
            this.abnormalCount = this.devices.filter(
              d => d.deviceCode && d.status !== '1'
            ).length;
            this.initialAbnormalCount = this.abnormalCount;
          }

          const firstDeviceCodeEmptyItem = this.devices.find(item =>
            item.deviceCode === null ||
            item.deviceCode === undefined ||
            (typeof item.deviceCode === 'string' && item.deviceCode.trim() === '')
          );

          if(firstDeviceCodeEmptyItem !== undefined) {
            // 自动移动到下一个单元格
            if (firstDeviceCodeEmptyItem.index < 72) {
              this.activeCell = firstDeviceCodeEmptyItem.index - 1;
            }
          } else {
            // 如果已经是最后一个，则回到第一个
            this.activeCell = 0;
          }

        } else {
          // 初始化设备矩阵数据 (8x9 = 72个设备)
          this.devices = Array(72).fill().map((_, i) => {
            const row = Math.floor(i / 9) + 1; // 1-8行
            const col = (i % 9) + 1; // 1-9列
            let number;

            // 计算当前行的起始数字
            const rowStart = (row - 1) * 9 + 1;
            const rowEnd = row * 9;

            if (row % 2 === 1) {
              // 奇数行：从左到右递增（1-9, 19-27, 37-45, 55-63）
              number = rowStart + (col - 1);
            } else {
              // 偶数行：从右到左递增（18-10, 36-28, 54-46, 72-64）
              number = rowEnd - (col - 1);
            }

            return {
              trayId: this.fTrayId,
              index: i + 1,
              number: number,
              deviceCode: '',
              row: row,
              col: col
            }
          })
        }
      })
    },

    // 返回托盘列表看板
    goBack() {
      this.$emit('go-back',1);
    },

    // 设置当前激活的单元格
    setActiveCell(index) {
      this.activeCell = index;
      this.$nextTick(() => {
        this.$refs.deviceInput.focus();
      });
    },

    // 添加设备到当前激活单元格
    addDevice() {

      // 清除计时器（避免重复触发）
      if (this.inputTimer) {
        clearTimeout(this.inputTimer);
        this.inputTimer = null;
      }

      // 原有逻辑：如果输入为空则不处理
      if (!this.deviceInput.trim()) return;


      if (this.deviceInput) {
        // 标定完成状态下的特殊处理 - 改为解绑操作
        if (this.trayStatus === '3') {
          // 检查扫描的设备是否存在
          const deviceIndex = this.devices.findIndex(
            d => d.deviceCode === this.deviceInput
          );

          if (deviceIndex !== -1) {
            // 找到设备，确认解绑
            this.confirmUnbind(deviceIndex);
          } else {
            // 设备不存在提示
            this.$message.warning(`设备 ${this.deviceInput} 不存在或未绑定`);
          }
        } else {
          // 空闲状态下的正常处理
          this.devices[this.activeCell].deviceCode = this.deviceInput;

          // 自动移动到下一个单元格
          if (this.activeCell < 71) {
            this.activeCell++;
          } else {
            this.activeCell = 0;
          }
        }

        this.deviceInput = '';
      }
    },

    // 确认解绑设备
    confirmUnbind(deviceIndex) {
      const device = this.devices[deviceIndex];
      this.$confirm(`确认解绑设备 ${device.deviceCode} 吗？`, '解绑确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 用户确认解绑
        this.executeUnbind(deviceIndex);
      }).catch(() => {
        // 用户取消解绑
        this.$message.info('已取消解绑操作');
      });
    },

    // 执行解绑操作
    executeUnbind(deviceIndex) {
      const device = this.devices[deviceIndex];

      // 调用解绑方法，传递设备信息和palletDeviceBindingId
      this.unbindDevice(device.deviceCode, device.palletDeviceBindingId, deviceIndex);
    },

    // 解绑单个设备
    unbindDevice(deviceCode, palletDeviceBindingId, deviceIndex) {
      // 这里调用您的后台解绑逻辑
      // 示例：假设您有一个解绑接口
      let palletDeviceBinding = {
        deviceCode: deviceCode,
        palletDeviceBindingId: palletDeviceBindingId
      }
      unbindSingleDevice(palletDeviceBinding).then(res => {
        if (res.code === 200) {
          // 解绑成功后的处理
          this.devices[deviceIndex].deviceCode = '';

          // 如果是异常设备，减少异常计数
          if (this.devices[deviceIndex].status === '0' || this.devices[deviceIndex].status === '5') {
            this.abnormalCount--;
          }

          this.$message.success(`设备 ${deviceCode} 解绑成功`);
        } else {
          this.$message.error("解绑失败");
        }
      })
    },

    // 获取位置标签 (行-列)
    getPositionLabel(index) {
      const row = Math.floor(index / 9) + 1;
      const col = (index % 9) + 1;
      return `${row}-${col}`;
    },

    // 一键解绑所有设备
    unbindAll() {
      this.$confirm('确定要解绑当前托盘下所有设备吗?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'error'
      }).then(() => {
        // 调用解绑接口（假设后端有对应的解绑接口，若无则需根据实际逻辑调整）
        // 这里复用现有resetAll接口或替换为实际解绑接口

        unbindAllDevice(this.fTrayId).then(res => {
          if (res.code === 200) {
            // 解绑成功后重置设备矩阵
            this.devices = this.devices.map(d => ({ ...d, deviceCode: '', status: '1' }));
            this.abnormalCount = this.devices.length; // 重置异常计数为总设备数
            this.initialAbnormalCount = this.abnormalCount;
            this.deviceInput = '';
            this.activeCell = 0;
            this.trayStatus = '0';
            this.$message.success("一键解绑成功");
          } else {
            this.$message.error("解绑失败");
          }
        })
      }).catch(() => {});
    },

    // 绑定托盘
    bindTray: function () {
      if (this.trayStatus === '0' || this.trayStatus === '4') {
        // 空闲状态 - 绑定设备
        const palletDeviceBindingId = this.devices[0].palletDeviceBindingId;
        if (this.filledCount > 0) {
          if(palletDeviceBindingId == null) {
            batchAdd(this.devices).then(res => {
              if (res.code === 200) {
                this.devices = res.data;
                this.trayStatus = '4';
                this.msgSuccess("绑定成功");
              } else {
                this.msgError("绑定失败");
              }
            })
          } else {
            batchUpdateDeviceCodeAndUnbindingTime(this.devices).then(res => {
              if (res.code === 200) {
                this.msgSuccess("绑定成功");
                if(this.trayStatus === '0') {
                  this.trayStatus = '4';
                }
              } else {
                this.msgError("绑定失败");
              }
            })
          }
        }
      } else if (this.trayStatus === '3') {
        // 标定完成状态 - 不再需要提交修复，改为解绑操作
        // 这里可以保留或移除，根据实际需求
      }
    },

    // 重置所有数据
    resetAll() {
      this.$confirm('确定要重置所有数据吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        resetAll(this.fTrayId).then(res => {
          if (res.code === 200) {
            this.deviceInput = '';
            this.devices = this.devices.map(d => ({ ...d, deviceCode: '' }));
            this.activeCell = 0;
            this.$nextTick(() => {
              this.$refs.deviceInput.focus();
            });
            this.msgSuccess("已重置");
          } else {
            this.msgError(res.msg);
          }
        })
      }).catch(() => {
      });
    }
  },
  mounted() {
    // 初始化时聚焦到托盘输入框
    this.$nextTick(() => {
      this.$refs.deviceInput.focus();
    });
  },
};
</script>

<style scoped>
/* 添加托盘信息容器样式 */
.tray-info {
  display: flex;
  flex-direction: column;
  gap: 15px;
  min-width: 300px;
}

.tray-status {
  display: flex;
  align-items: center;
  gap: 10px;
}

.status-label {
  font-size: 1.1rem;
  color: #64c8ff;
  font-weight: bold;
}

/* 其他样式保持不变 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
  background: linear-gradient(135deg, #0a1929, #0c2a46);
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 20px;
  color: #fff;
}

.tray-binding-container {
  width: 100%;
  max-width: 1400px;
  background: rgba(10, 20, 40, 0.85);
  border-radius: 20px;
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  border: 1px solid rgba(100, 180, 255, 0.3);
  padding: 30px;
  position: relative;
}

.header {
  text-align: right;
  margin-bottom: 30px;
  position: relative;
}

.back-button {
  cursor: pointer;
  margin-bottom: 20px;
  width: 200px;
  color: #409EFF;
  display: inline-flex;
  align-items: center;
  transition: all 0.3s;
  padding: 8px 15px;
  background: rgba(0, 40, 80, 0.4);
  border-radius: 8px;
  font-size: 1.1rem;
}

.back-button:hover {
  color: #66b1ff;
  background: rgba(0, 60, 120, 0.6);
  transform: translateX(-5px);
}

.tray-id-section {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 40px;
  flex-wrap: wrap;
  gap: 30px;
  background: rgba(0, 40, 80, 0.3);
  border-radius: 15px;
  padding: 25px;
  border: 1px solid rgba(64, 158, 255, 0.4);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.tray-display {
  display: flex;
  align-items: center;
  gap: 20px;
  min-width: 300px;
}

.tray-label {
  font-size: 1.4rem;
  color: #64c8ff;
  font-weight: bold;
}

.tray-id {
  font-size: 2.2rem;
  font-weight: bold;
  letter-spacing: 3px;
  background: linear-gradient(to right, #64c8ff, #3a7bd5);
  -webkit-background-clip: text;
  color: transparent;
  min-width: 250px;
  text-align: center;
}

.scan-section {
  display: flex;
  flex-direction: column;
  gap: 15px;
  min-width: 400px;
}

.scan-input {
  background: rgba(0, 30, 60, 0.5);
  border: 2px solid #409EFF;
  border-radius: 50px;
  padding: 15px 25px;
  color: white;
  font-size: 1.2rem;
  width: 100%;
  transition: all 0.3s;
}

.scan-input:focus {
  outline: none;
  border-color: #64c8ff;
  box-shadow: 0 0 15px rgba(100, 200, 255, 0.5);
}

.status-bar {
  text-align: center;
  padding: 15px;
  background: rgba(0, 30, 60, 0.5);
  border-radius: 10px;
  font-size: 1.2rem;
  color: #64ffda;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 15px;
}

.filled-count {
  font-weight: bold;
  color: #64c8ff;
  font-size: 1.4rem;
}

.devices-grid-container {
  margin-bottom: 40px;
  background: rgba(0, 40, 80, 0.3);
  border-radius: 15px;
  padding: 25px;
  border: 1px solid rgba(64, 158, 255, 0.4);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.grid-title {
  text-align: center;
  font-size: 1.8rem;
  color: #64ffda;
  margin-bottom: 25px;
  text-shadow: 0 0 10px rgba(100, 255, 218, 0.3);
}

.devices-grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 15px;
  margin: 0 auto;
  max-width: 100%;
}

/* 长方形设备单元格样式 */
.device-cell {
  background: rgba(30, 60, 100, 0.4);
  border: 2px solid rgba(64, 158, 255, 0.5);
  border-radius: 8px;
  height: 80px; /* 高度固定 */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  transition: all 0.3s;
  position: relative;
  overflow: hidden;
  padding: 5px;
}

.device-cell:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 15px rgba(0, 0, 0, 0.3);
  border-color: #64c8ff;
  background: rgba(40, 80, 140, 0.5);
}

.device-cell.active {
  border-color: #64ffda;
  background: rgba(100, 255, 218, 0.15);
  box-shadow: 0 0 15px rgba(100, 255, 218, 0.4);
  transform: scale(1.05);
}

.device-id {
  font-size: 0.85rem;
  font-weight: bold;
  color: #fff;
  text-align: center;
  word-break: break-all;
  width: 100%;
  padding: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  max-height: 40px;
}

.device-cell.empty .device-id {
  color: #a0d2ff;
  font-size: 1.8rem;
  opacity: 0.7;
}

.position-indicator {
  position: absolute;
  bottom: 5px;
  right: 5px;
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.6);
}

.binding-controls {
  display: flex;
  justify-content: center;
  gap: 30px;
  margin-top: 40px;
}

.bind-btn {
  background: linear-gradient(to right, #11998e, #38ef7d);
  color: white;
  border: none;
  padding: 18px 45px;
  font-size: 1.4rem;
  font-weight: bold;
  border-radius: 50px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 15px;
  transition: all 0.3s;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.bind-btn:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 20px rgba(17, 153, 142, 0.5);
}

.bind-btn:disabled {
  background: linear-gradient(to right, #555, #777);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.reset-btn {
  background: linear-gradient(to right, #ff416c, #ff4b2b);
  color: white;
  border: none;
  padding: 18px 45px;
  font-size: 1.4rem;
  font-weight: bold;
  border-radius: 50px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 15px;
  transition: all 0.3s;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.reset-btn:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 20px rgba(255, 65, 108, 0.5);
}

.instructions {
  background: rgba(0, 30, 60, 0.4);
  border-radius: 15px;
  padding: 25px;
  margin-top: 40px;
  border: 1px solid rgba(100, 200, 255, 0.3);
}

.instructions h3 {
  color: #64ffda;
  margin-bottom: 15px;
  font-size: 1.5rem;
}

.instructions ul {
  padding-left: 25px;
}

.instructions li {
  margin-bottom: 10px;
  line-height: 1.6;
  color: #a0d2ff;
}

.scanner-icon {
  color: #64ffda;
  animation: pulse 2s infinite;
}

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

.highlight {
  background: rgba(100, 255, 218, 0.2);
  padding: 2px 5px;
  border-radius: 4px;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .devices-grid {
    grid-template-columns: repeat(6, 1fr);
  }
}

@media (max-width: 900px) {
  .devices-grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .tray-id-section {
    flex-direction: column;
    align-items: stretch;
  }

  .tray-display, .scan-section {
    min-width: 100%;
  }
}

@media (max-width: 600px) {
  .devices-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .tray-display {
    flex-direction: column;
    text-align: center;
  }

  .bind-btn, .reset-btn {
    padding: 15px 30px;
    font-size: 1.2rem;
  }
}

.matrix-info {
  text-align: center;
  margin-top: 15px;
  color: #64c8ff;
  font-size: 1.1rem;
}

/* 设备单元格错误状态样式 */
.device-cell.error {
  border-color: #ff4d4f !important;
  box-shadow: 0 0 8px rgba(255, 77, 79, 0.5);
  position: relative;
  overflow: visible;
}

.device-cell.error::after {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  right: -3px;
  bottom: -3px;
  border: 2px solid #ff4d4f;
  border-radius: 8px;
  animation: pulseError 1.5s infinite;
  z-index: 1;
}

@keyframes pulseError {
  0% { opacity: 0.8; }
  50% { opacity: 0.3; }
  100% { opacity: 0.8; }
}

.error-icon {
  position: absolute;
  top: -8px;
  right: -8px;
  color: #ff4d4f;
  font-size: 18px;
  background: rgba(10, 20, 40, 0.9);
  border-radius: 50%;
  z-index: 2;
  animation: pulseIcon 1.5s infinite;
}

@keyframes pulseIcon {
  0% { transform: scale(1); }
  50% { transform: scale(1.2); }
  100% { transform: scale(1); }
}

/* 调整设备ID显示区域，为错误图标留出空间 */
.device-id {
  position: relative;
  padding-top: 5px;
  padding-right: 15px;
}

/* 一键解绑按钮样式 */
.unbind-btn {
  background: linear-gradient(to right, #9d4edd, #7b2cbf);
  color: white;
  border: none;
  padding: 18px 45px;
  font-size: 1.4rem;
  font-weight: bold;
  border-radius: 50px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 15px;
  transition: all 0.3s;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.unbind-btn:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 20px rgba(157, 78, 221, 0.5);
}
</style>
