<template>
  <div class="track-container">
    <el-row :gutter="20">
      <!-- 左侧：设备列表 -->
      <el-col :span="16">
        <!-- Loading Status / 加载状态 -->
        <div v-if="isLoading" class="loading-container">
          <el-icon class="is-loading"><i class="el-icon-loading"></i></el-icon>
          <span>Loading...</span>
          <!-- 加载中... -->
        </div>

        <!-- WebSocket Connection Status Indicator / WebSocket 连接状态指示 -->
        <div v-if="!isLoading" class="ws-status-bar">
          <el-tooltip content="Measurement Data" placement="top">
            <!-- 测量数据 -->
            <el-badge :is-dot="true" :type="socketStatus.measure ? 'success' : 'danger'">
              <i class="el-icon-data-analysis"></i>
            </el-badge>
          </el-tooltip>
          <el-tooltip content="Position Tracking" placement="top">
            <!-- 位置追踪 -->
            <el-badge :is-dot="true" :type="socketStatus.position ? 'success' : 'danger'">
              <i class="el-icon-location"></i>
            </el-badge>
          </el-tooltip>
          <el-tooltip content="Operation Signal" placement="top">
            <!-- 操作信号 -->
            <el-badge :is-dot="true" :type="socketStatus.signal ? 'success' : 'danger'">
              <i class="el-icon-bell"></i>
            </el-badge>
          </el-tooltip>
          <el-tooltip content="Material Mapping" placement="top">
            <!-- 物料映射 -->
            <el-badge :is-dot="true" :type="socketStatus.matmap ? 'success' : 'danger'">
              <i class="el-icon-map-location"></i>
            </el-badge>
          </el-tooltip>
          <el-tooltip content="Calculation Result" placement="top">
            <!-- 计算结果 -->
            <el-badge :is-dot="true" :type="socketStatus.calcSetup ? 'success' : 'danger'">
              <i class="el-icon-s-marketing"></i>
            </el-badge>
          </el-tooltip>
        </div>

        <div v-if="!isLoading" class="device-layout">
          <!-- Entry Section / 入口段区域 -->
          <div class="section-area entry-area">
            <div class="section-header">
              Entry Section
              <!-- 入口段 -->
              <span class="section-info" v-if="positionData.entrySpeed">Speed: {{ positionData.entrySpeed.toFixed(1) }} m/min</span>
              <!-- 速度 -->
            </div>
            <div class="section-summary" v-if="entrySectionMetrics.length">
              <div class="summary-item" v-for="item in entrySectionMetrics" :key="item.label">
                <span class="summary-label">{{ item.label }}：</span>
                <span class="summary-value">{{ item.value }}</span>
              </div>
            </div>
            <div class="device-grid">
              <div v-for="device in entryDevicesList" :key="device.positionNameEn" class="device-card" :class="{
                active: selectedCard && selectedCard.positionNameEn === device.positionNameEn,
                'has-data': hasMatId(device.positionNameEn)
              }" @click="selectDevice(device.positionNameEn)">
                <div class="device-name">{{ device.positionNameCn }}</div>
                <div class="device-code">{{ device.positionNameEn }}</div>
                <div class="device-status">
                  <span class="coil-id" :class="{ 'status-working': isDeviceWorking(device.positionNameEn), 'status-idle': !isDeviceWorking(device.positionNameEn) }">
                    {{ getDeviceStatus(device.positionNameEn) }}
                  </span>
                </div>
              </div>
            </div>
          </div>

          <!-- Furnace Section / 熔炉段区域 -->
          <div class="section-area furnace-area">
            <div class="section-header">
              Furnace Section
              <!-- 熔炉段 -->
              <span class="section-info" v-if="positionData.technologySpeed">Speed: {{ positionData.technologySpeed.toFixed(1) }} m/min</span>
              <!-- 速度 -->
            </div>
            <div class="section-summary" v-if="furnaceSectionMetrics.length">
              <div class="summary-item" v-for="item in furnaceSectionMetrics" :key="item.label">
                <span class="summary-label">{{ item.label }}：</span>
                <span class="summary-value">{{ item.value }}</span>
              </div>
            </div>
            <div class="device-grid">
              <div v-for="device in furnaceDevicesList" :key="device.positionNameEn" class="device-card" :class="{
                active: selectedCard && selectedCard.positionNameEn === device.positionNameEn,
                'has-data': hasMatId(device.positionNameEn)
              }" @click="selectDevice(device.positionNameEn)">
                <div class="device-name">{{ device.positionNameCn }}</div>
                <div class="device-code">{{ device.positionNameEn }}</div>
                <div class="device-status">
                  <span class="coil-id" :class="{ 'status-working': isDeviceWorking(device.positionNameEn), 'status-idle': !isDeviceWorking(device.positionNameEn) }">
                    {{ getDeviceStatus(device.positionNameEn) }}
                  </span>
                </div>
              </div>
            </div>
          </div>

          <!-- Coating Section / 涂层段区域 -->
          <div class="section-area coat-area">
            <div class="section-header">Coating Section</div>
            <!-- 涂层段 -->
            <div class="section-summary" v-if="coatSectionMetrics.length">
              <div class="summary-item" v-for="item in coatSectionMetrics" :key="item.label">
                <span class="summary-label">{{ item.label }}：</span>
                <span class="summary-value">{{ item.value }}</span>
              </div>
            </div>
            <div class="device-grid">
              <div v-for="device in coatDevicesList" :key="device.positionNameEn" class="device-card" :class="{
                active: selectedCard && selectedCard.positionNameEn === device.positionNameEn,
                'has-data': hasMatId(device.positionNameEn)
              }" @click="selectDevice(device.positionNameEn)">
                <div class="device-name">{{ device.positionNameCn }}</div>
                <div class="device-code">{{ device.positionNameEn }}</div>
                <div class="device-status">
                  <span class="coil-id" :class="{ 'status-working': isDeviceWorking(device.positionNameEn), 'status-idle': !isDeviceWorking(device.positionNameEn) }">
                    {{ getDeviceStatus(device.positionNameEn) }}
                  </span>
                </div>
              </div>
            </div>
          </div>

          <!-- Exit Section / 出口段区域 -->
          <div class="section-area exit-area">
            <div class="section-header">
              Exit Section
              <!-- 出口段 -->
              <span class="section-info" v-if="positionData.exitSpeed">Speed: {{ positionData.exitSpeed.toFixed(1) }} m/min</span>
              <!-- 速度 -->
            </div>
            <div class="section-summary" v-if="exitSectionMetrics.length">
              <div class="summary-item" v-for="item in exitSectionMetrics" :key="item.label">
                <span class="summary-label">{{ item.label }}：</span>
                <span class="summary-value">{{ item.value }}</span>
              </div>
            </div>
            <div class="device-grid">
              <div v-for="device in exitDevicesList" :key="device.positionNameEn" class="device-card" :class="{
                active: selectedCard && selectedCard.positionNameEn === device.positionNameEn,
                'has-data': hasMatId(device.positionNameEn)
              }" @click="selectDevice(device.positionNameEn)">
                <div class="device-name">{{ device.positionNameCn }}</div>
                <div class="device-code">{{ device.positionNameEn }}</div>
                <div class="device-status">
                  <span class="coil-id" :class="{ 'status-working': isDeviceWorking(device.positionNameEn), 'status-idle': !isDeviceWorking(device.positionNameEn) }">
                    {{ getDeviceStatus(device.positionNameEn) }}
                  </span>
                </div>
              </div>
            </div>
          </div>

          <!-- Other Section / 其他段区域 -->
          <div class="section-area" v-if="exitOtherDevicesList.length">
            <div class="section-header">Other Section</div>
            <!-- 其他段 -->
            <div class="device-grid other-exit-grid">
              <div v-for="device in exitOtherDevicesList" :key="device.positionNameEn" class="device-card" :class="{
                active: selectedCard && selectedCard.positionNameEn === device.positionNameEn,
                'has-data': hasMatId(device.positionNameEn)
              }" @click="selectDevice(device.positionNameEn)">
                <div class="device-name">{{ device.positionNameCn }}</div>
                <div class="device-code">{{ device.positionNameEn }}</div>
                <div class="device-status">
                  <span class="coil-id" :class="{ 'status-working': isDeviceWorking(device.positionNameEn), 'status-idle': !isDeviceWorking(device.positionNameEn) }">
                    {{ getDeviceStatus(device.positionNameEn) }}
                  </span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </el-col>

      <!-- 右侧：信息面板 -->
      <el-col :span="8">
        <div class="info-panels">
          <!-- Production Plan List / 生产计划列表 -->
          <div class="panel">
            <div class="panel-title">
              <i class="el-icon-s-order"></i> Production Plan
              <!-- 生产计划 -->
            </div>
            <div class="plan-list-vertical">
              <el-empty v-if="planQueue.length === 0" description="No production plan" :image-size="80" />
              <!-- 暂无生产计划 -->
              <div
                v-else
                v-for="(plan, index) in planQueue"
                :key="plan.id || plan.planid || index"
                class="plan-item-vertical"
                :class="getPlanItemClass(plan)"
                @click="selectPlan(plan)"
              >
                <div class="plan-item-top">
                  <div class="plan-order-dot" :class="getPlanOrderClass(plan.status)">{{ index + 1 }}</div>
                  <div class="plan-title-text">
                    <div class="plan-id">Plan ID: {{ plan.planid || '-' }}</div>
                    <!-- 计划ID -->
                    <div class="plan-coil">Coil ID: {{ plan.coilid || '-' }}</div>
                    <!-- 钢卷号 -->
                  </div>
                  <el-tag :type="getPlanStatusTagType(plan.status)" size="mini">{{ getPlanStatusText(plan.status) }}</el-tag>
                </div>
                <div class="plan-item-bottom">
                  <span>Steel Grade: {{ plan.steelGrade || '-' }}</span>
                  <!-- 钢种 -->
                  <span>Sequence: {{ plan.seqid || '-' }}</span>
                  <!-- 顺序 -->
                </div>
              </div>
            </div>
          </div>

          <!-- Production Plan Detail / 生产计划详情 -->
          <div class="panel" v-if="selectedPlan">
            <div class="panel-title">
              <i class="el-icon-document"></i> Plan Detail
              <!-- 生产计划详情 -->
              <el-button size="mini" type="text" icon="el-icon-close" @click="selectedPlan = null"></el-button>
            </div>
            <div class="plan-detail-content">
              <!-- Position Info (if on production line) / 位置信息（如果在产线上） -->
              <div v-if="selectedPlanPosition" class="position-alert">
                <div class="position-icon">
                  <i class="el-icon-location"></i>
                </div>
                <div class="position-info">
                  <div class="position-label">Current Position</div>
                  <!-- 当前位置 -->
                  <div class="position-name">{{ selectedPlanPosition.positionNameCn }}</div>
                  <div class="position-code">{{ selectedPlanPosition.positionNameEn }}</div>
                </div>
              </div>
              
              <el-descriptions :column="1" border size="small">
                <el-descriptions-item label="Plan ID">{{ selectedPlan.planid || '-' }}</el-descriptions-item>
                <!-- 计划ID -->
                <el-descriptions-item label="Coil ID">{{ selectedPlan.coilid || '-' }}</el-descriptions-item>
                <!-- 钢卷号 -->
                <el-descriptions-item label="Sequence">{{ selectedPlan.seqid || '-' }}</el-descriptions-item>
                <!-- 顺序号 -->
                <el-descriptions-item label="Status">
                  <!-- 状态 -->
                  <el-tag :type="getPlanStatusTagType(selectedPlan.status)" size="small" effect="dark">
                    {{ getPlanStatusText(selectedPlan.status) }}
                  </el-tag>
                </el-descriptions-item>
                <el-descriptions-item label="Steel Grade">{{ selectedPlan.steelGrade || '-' }}</el-descriptions-item>
                <!-- 钢种 -->
                <el-descriptions-item label="Entry Thickness">
                  <!-- 入口厚度 -->
                  {{ selectedPlan.entryThick ? selectedPlan.entryThick + ' mm' : '-' }}
                </el-descriptions-item>
                <el-descriptions-item label="Entry Width">
                  <!-- 入口宽度 -->
                  {{ selectedPlan.entryWidth ? selectedPlan.entryWidth + ' mm' : '-' }}
                </el-descriptions-item>
                <el-descriptions-item label="Entry Weight">
                  <!-- 入口重量 -->
                  {{ selectedPlan.entryWeight ? selectedPlan.entryWeight + ' t' : '-' }}
                </el-descriptions-item>
                <el-descriptions-item label="Entry Length">
                  <!-- 入口长度 -->
                  {{ selectedPlan.entryLength ? selectedPlan.entryLength + ' mm' : '-' }}
                </el-descriptions-item>
                <el-descriptions-item label="Order No">{{ selectedPlan.orderNo || '-' }}</el-descriptions-item>
                <!-- 订单号 -->
                <el-descriptions-item label="Unit Code">{{ selectedPlan.unitCode || '-' }}</el-descriptions-item>
                <!-- 机组号 -->
                <el-descriptions-item label="Plan Type">{{ selectedPlan.planType || '-' }}</el-descriptions-item>
                <!-- 计划类型 -->
              </el-descriptions>
              
              <!-- Time Information / 时间信息 -->
              <div class="plan-time-info" v-if="selectedPlan.onlineDate || selectedPlan.startDate || selectedPlan.endDate">
                <div class="info-subtitle">Time Information</div>
                <!-- 时间信息 -->
                <el-descriptions :column="1" border size="small">
                  <el-descriptions-item label="Online Time" v-if="selectedPlan.onlineDate">
                    <!-- 上线时间 -->
                    {{ formatDateTime(selectedPlan.onlineDate) }}
                  </el-descriptions-item>
                  <el-descriptions-item label="Start Time" v-if="selectedPlan.startDate">
                    <!-- 开始时间 -->
                    {{ formatDateTime(selectedPlan.startDate) }}
                  </el-descriptions-item>
                  <el-descriptions-item label="End Time" v-if="selectedPlan.endDate">
                    <!-- 结束时间 -->
                    {{ formatDateTime(selectedPlan.endDate) }}
                  </el-descriptions-item>
                </el-descriptions>
              </div>
            </div>
          </div>

          <!-- Recent Operation Signal / 最近操作信号 -->
          <div class="panel" v-if="signalData">
            <div class="panel-title">
              <i class="el-icon-bell"></i> Recent Operation
              <!-- 最近操作 -->
              <el-tag 
                :type="getOperationTagType(signalData.operation)" 
                size="mini" 
                effect="dark">
                {{ getOperationConfig(signalData.operation).icon }} {{ getOperationText(signalData.operation) }}
              </el-tag>
            </div>
            <div class="signal-info" :class="getSignalPanelClass(signalData.operation)">
              <el-tag :type="signalData.autoFlag === 1 ? 'warning' : 'info'" size="small">
                {{ signalData.autoFlag === 1 ? 'Manual' : 'Auto' }}
                <!-- {{ signalData.autoFlag === 1 ? '手动操作' : '自动操作' }} -->
              </el-tag>
              <div class="signal-detail">
                <div><strong>Operation Type:</strong> 
                  <!-- 操作类型 -->
                  <span :class="getOperationTextClass(signalData.operation)">
                    {{ getOperationText(signalData.operation) }}
                  </span>
                </div>
                <div><strong>Coil ID:</strong> {{ producingCoilId || signalData.entryMatId || '-' }}</div>
                <!-- 钢卷号 -->
                <div><strong>Plan ID:</strong> {{ signalData.planId || '-' }}</div>
                <!-- 计划ID -->
                <div v-if="signalData.porIdx !== null && signalData.porIdx !== undefined">
                  <strong>Pay-off Reel:</strong> {{ signalData.porIdx }}
                  <!-- 开卷机 -->
                </div>
                <div v-if="signalData.trIdx !== null && signalData.trIdx !== undefined">
                  <strong>Take-up Reel:</strong> {{ signalData.trIdx }}
                  <!-- 卷取机 -->
                </div>
                <div v-if="signalData.virtualPlanFlag">
                  <el-tag type="danger" size="mini">Virtual Coil</el-tag>
                  <!-- 虚拟卷 -->
                </div>
              </div>
            </div>
          </div>
          <!-- Operation Buttons / 操作按钮 -->
          <div class="panel">
            <div class="panel-title">Operations</div>
            <!-- 操作 -->
            <div class="btn-list">
              <el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'ONLINE')">Coil Online</el-button>
              <!-- 钢卷上线 -->
              <el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'UNLOAD')">Manual Unload</el-button>
              <!-- 手动卸卷 -->
              <el-button class="action-btn" size="small"
                @click="handleOperate(selectedCard, 'ALL_RETURN')">Full Return</el-button>
              <!-- 整卷回退 -->
              <el-button class="action-btn" size="small"
                @click="handleOperate(selectedCard, 'HALF_RETURN')">Half Return</el-button>
              <!-- 半卷回退 -->
              <el-button class="action-btn" size="small" @click="handleOperate(selectedCard, 'BLOCK')">Unload & Block</el-button>
              <!-- 卸卷并封闭 -->
            </div>
          </div>
          <!-- Device Basic Info / 设备基本信息 -->
          <div class="panel" v-if="selectedCard">
            <div class="panel-title">Basic Info</div>
            <!-- 基本信息 -->
            <table class="info-table">
              <tr>
                <td>Position Name</td>
                <!-- 位置名称 -->
                <td>{{ selectedCard.positionNameCn || '-' }}</td>
              </tr>
              <tr>
                <td>Position Code</td>
                <!-- 位置代号 -->
                <td>{{ selectedCard.positionNameEn || '-' }}</td>
              </tr>
              <tr>
                <td>Coil ID</td>
                <!-- 钢卷号 -->
                <td>{{ selectedCard.matId || '-' }}</td>
              </tr>
              <tr>
                <td>Plan ID</td>
                <!-- 计划ID -->
                <td>{{ selectedCard.planId || '-' }}</td>
              </tr>
              <tr>
                <td>Plan No</td>
                <!-- 计划号 -->
                <td>{{ selectedCard.planNo || '-' }}</td>
              </tr>
            </table>
          </div>

          <!-- 设备实时数据 -->

          <div class="panel">

            <!-- Adjustment Tool: Select two positions with two dropdowns / 调整工具，选择两个位置，两个下拉选，分别双向绑定 -->
            <el-form :model="adjustForm" ref="adjustForm" label-width="80px">
              <el-form-item label="Current Position" prop="current">
                <!-- 当前位置 -->
                <el-select v-model="adjustForm.current" placeholder="Please select current position">
                  <!-- 请选择当前位置 -->
                  <el-option v-for="item in matMapList" :key="item.positionNameEn" :label="item.positionNameCn"
                    :value="item.positionNameEn"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="Target Position" prop="target">
                <!-- 目标位置 -->
                <el-select v-model="adjustForm.target" placeholder="Please select target position">
                  <!-- 请选择目标位置 -->
                  <el-option v-for="item in matMapList" :key="item.positionNameEn" :label="item.positionNameCn"
                    :value="item.positionNameEn"></el-option>
                </el-select>
              </el-form-item>
            </el-form>
            <el-button type="primary" :disabled="!adjustForm.current || !adjustForm.target"
              @click="handleConfirmAdjust">Confirm Adjustment</el-button>
            <!-- 确认调整 -->
          </div>
        </div>

      </el-col>
    </el-row>

    <!-- Calculation Setup Result Dialog / 计算结果对话框 -->
    <el-dialog
      title="Calculation Setup Result"
      :visible.sync="showCalcResultDialog"
      width="80%"
      v-if="calcSetupResult"
    >
      <div class="calc-result-header">
        <el-tag :type="calcSetupResult.flag ? 'success' : 'danger'">
          {{ calcSetupResult.flag ? 'Calculation Success' : 'Calculation Failed' }}
          <!-- {{ calcSetupResult.flag ? '计算成功' : '计算失败' }} -->
        </el-tag>
        <span>Key: {{ calcSetupResult.key }}</span>
      </div>
      <el-table
        v-if="calcSetupResult.flag && calcSetupResult.lists && calcSetupResult.lists.length > 0"
        :data="calcSetupResult.lists"
        border
        stripe
        max-height="500"
      >
        <el-table-column prop="passno" label="Pass No" width="80" fixed></el-table-column>
        <!-- 道次号 -->
        <el-table-column prop="entryThick" label="Entry Thickness (mm)" width="120"></el-table-column>
        <!-- 入口厚度 -->
        <el-table-column prop="exitThick" label="Exit Thickness (mm)" width="120"></el-table-column>
        <!-- 出口厚度 -->
        <el-table-column prop="reduction" label="Reduction (%)" width="100"></el-table-column>
        <!-- 压下率 -->
        <el-table-column prop="rollSpeed" label="Roll Speed" width="120"></el-table-column>
        <!-- 轧制速度 -->
        <el-table-column prop="rollForce" label="Roll Force (kN)" width="120"></el-table-column>
        <!-- 轧制力 -->
        <el-table-column prop="entryTension" label="Entry Tension" width="120"></el-table-column>
        <!-- 入口张力 -->
        <el-table-column prop="exitTension" label="Exit Tension" width="120"></el-table-column>
        <!-- 出口张力 -->
      </el-table>
      <div v-else class="empty-msg">No calculation result data</div>
      <!-- 无计算结果数据 -->
    </el-dialog>

    <el-dialog :visible.sync="operateMatStatus" :title="getOperateTitle" width="50%">
      <el-form :model="operateMatForm" :rules="operateRules" ref="operateForm" label-width="120px">
        <el-form-item label="Pay-off Reel No" prop="porIdx">
          <!-- 开卷机编号 -->
          <el-input v-model="operateMatForm.porIdx"></el-input>
        </el-form-item>
        <el-form-item label="Take-up Reel No" prop="trIdx">
          <!-- 卷取机编号 -->
          <el-input v-model="operateMatForm.trIdx"></el-input>
        </el-form-item>
        <el-form-item label="Plan ID" prop="planId">
          <!-- 计划id -->
          <el-input v-model="operateMatForm.planId" placeholder="Please enter Plan ID"></el-input>
          <!-- 请输入计划ID -->
        </el-form-item>
        <el-form-item label="Coil ID" prop="entryMatId">
          <!-- 钢卷号 -->
          <el-input v-model="operateMatForm.entryMatId" placeholder="Please enter Coil ID"></el-input>
          <!-- 请输入钢卷号 -->
        </el-form-item>
        <el-form-item label="Operation Type" prop="operation">
          <!-- 操作类型 -->
          <el-select v-model="operateMatForm.operation" disabled>
            <el-option label="Coil Online" value="ONLINE"></el-option>
            <!-- 钢卷上线 -->
            <el-option label="Manual Unload" value="UNLOAD"></el-option>
            <!-- 手动卸卷 -->
            <el-option label="Full Return" value="ALL_RETURN"></el-option>
            <!-- 整卷回退 -->
            <el-option label="Half Return" value="HALF_RETURN"></el-option>
            <!-- 半卷回退 -->
            <el-option label="Unload & Block" value="BLOCK"></el-option>
            <!-- 卸卷并封闭 -->
          </el-select>
        </el-form-item>

        <!-- Return Related Fields / 回退相关字段 -->
        <template v-if="['ALL_RETURN', 'HALF_RETURN'].includes(operateMatForm.operation)">
          <el-form-item label="Return Coil ID" prop="returnMatId">
            <!-- 回退卷号 -->
            <el-input v-model="operateMatForm.returnMatId" placeholder="Please enter Return Coil ID"></el-input>
            <!-- 请输入回退卷号 -->
          </el-form-item>
          <el-form-item label="Return Weight" prop="returnWeight">
            <!-- 回退重量 -->
            <el-input v-model="operateMatForm.returnWeight" placeholder="Please enter Return Weight"></el-input>
            <!-- 请输入回退重量 -->
          </el-form-item>
          <el-form-item label="Return Remark" prop="returnRemark">
            <!-- 回退备注 -->
            <el-input v-model="operateMatForm.returnRemark" rows="3"></el-input>
          </el-form-item>
        </template>

        <!-- Output Length Fields / 产出长度字段 -->
        <template v-if="['PRODUCING', 'PRODUCT'].includes(operateMatForm.operation)">
          <el-form-item label="Output Coil Length" prop="coilLength">
            <!-- 产出钢卷长度 -->
            <el-input v-model="operateMatForm.coilLength" type="number" placeholder="Please enter Output Coil Length"></el-input>
            <!-- 请输入产出钢卷长度 -->
          </el-form-item>
        </template>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="operateMatStatus = false">Cancel</el-button>
        <!-- 取消 -->
        <el-button type="primary" @click="submitOperateForm">Confirm</el-button>
        <!-- 确定 -->
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { adjustPosition, getTrackMatPosition, operateMat, getBackData, getPlanQueue } from '@/api/l2/track'
import wsManager from '@/utils/websocketManager'

// Device metadata mapping based on backend DeviceEnum (section, source, parameter fields)
// 基于后端 DeviceEnum 的前端映射（区域、来源、参数字段）
const DEVICE_META = {
  POR1: { sectionType: 'ENTRY', sourceType: 'ENTRY', paramFields: ['tensionPorBr1', 'stripSpeed'] },
  POR2: { sectionType: 'ENTRY', sourceType: 'ENTRY', paramFields: ['tensionPorBr2', 'stripSpeed'] },
  WELDER: { sectionType: 'ENTRY', sourceType: 'ENTRY', paramFields: ['weldStatus'] },
  ENL1: { sectionType: 'PROCESS', sourceType: 'ENTRY', paramFields: ['celLength', 'celCapacity', 'tensionCel', 'celLengthMax', 'celLengthMin', 'bR4or5toBR6Tension'] },
  ENL2: { sectionType: 'PROCESS', sourceType: 'ENTRY', paramFields: ['celLength', 'celCapacity', 'tensionCel', 'celLengthMax', 'celLengthMin', 'bR4or5toBR6Tension'] },
  ENL3: { sectionType: 'PROCESS', sourceType: 'ENTRY', paramFields: ['celLength', 'celCapacity', 'tensionCel', 'celLengthMax', 'celLengthMin', 'bR4or5toBR6Tension'] },

  CLEAN: { sectionType: 'PROCESS', sourceType: 'FURNACE', paramFields: ['cleaningVoltage', 'cleaningCurrent', 'alkaliConcentration', 'alkaliTemperature'] },
  FUR1: { sectionType: 'PROCESS', sourceType: 'FURNACE', paramFields: ['phfExitStripTemp', 'potTemperature', 'gasConsumption'] },
  FUR2: { sectionType: 'PROCESS', sourceType: 'FURNACE', paramFields: ['rtfExitStripTemp', 'zincPotPower'] },
  FUR3: { sectionType: 'PROCESS', sourceType: 'FURNACE', paramFields: ['jcsExitStripTemp', 'coolingTowerStripTemp'] },
  FUR4: { sectionType: 'PROCESS', sourceType: 'FURNACE', paramFields: ['scsExitStripTemp'] },
  POT: { sectionType: 'PROCESS', sourceType: 'COAT', paramFields: ['scsExitStripTemp'] },
  TOWER: { sectionType: 'PROCESS', sourceType: 'COAT', paramFields: ['scsExitStripTemp'] },
  TM: { sectionType: 'PROCESS', sourceType: 'COAT', paramFields: ['tensionBr5Tm', 'stripSpeedTmExit'] },
  TL: { sectionType: 'PROCESS', sourceType: 'COAT', paramFields: ['tlElongation', 'tensionTlBr7'] },
  COAT: { sectionType: 'PROCESS', sourceType: 'COAT', paramFields: [
    'avrCoatingWeightTop','stdCoatingWeightTop','maxCoatingWeightTop','minCoatingWeightTop',
    'avrCoatingWeightBottom','stdCoatingWeightBottom','maxCoatingWeightBottom','minCoatingWeightBottom',
    'airKnifePressure','airKnifeFlow','airKnifeGap','stripSpeedTmExit','tensionBr8Tm',
    'tensionTmBr9','tensionBr8Br9','tmMask','tmElongation','rollForceOperator','rollForceDrive',
    'motorTorque','bendingForce','antiCrimpingRollMesh','billyRollMesh',
    'tensionTlBr10Br11','tensionBr9toBr10Br11','tlFlag','tlElongation','levelingUnit1Mesh','levelingUnit2Mesh',
    'antiCrossBowUnitMesh','tensionBr10Br11toBr12','stripSpeedAfp','stripTempAfp'
  ] },

  CXL1: { sectionType: 'EXIT', sourceType: 'EXIT', paramFields: ['cxlLength', 'cxlCapacity', 'tensionCxl'] },
  CXL2: { sectionType: 'EXIT', sourceType: 'EXIT', paramFields: ['cxlLength', 'cxlCapacity', 'tensionCxl'] },
  TR: { sectionType: 'EXIT', sourceType: 'EXIT', paramFields: ['coilLength', 'speedExitSection', 'tensionBr9Tr'] },
  EXC: { sectionType: 'EXIT', sourceType: 'EXIT', paramFields: [] },
  WEIGHT: { sectionType: 'EXIT', sourceType: 'EXIT', paramFields: [] }
}

// Parameter field labels (English with Chinese comments)
// 参数字段标签（英文显示，中文注释）
const PARAM_LABELS = {
  tensionPorBr1: 'Tension POR-BR1', // 开卷张力1#
  tensionPorBr2: 'Tension POR-BR2', // 开卷张力2#
  stripSpeed: 'Strip Speed', // 带钢速度
  weldStatus: 'Weld Status', // 焊机状态
  celLength: 'Entry Loop Length', // 入口活套位置
  celCapacity: 'Entry Loop Capacity', // 入口活套套量
  tensionCel: 'Entry Loop Tension', // 入口活套张力
  celLengthMax: 'Entry Loop Max Length', // 入口活套最大长度
  celLengthMin: 'Entry Loop Min Length', // 入口活套最小长度
  bR4or5toBR6Tension: 'Tension BR4/5-BR6', // BR4/5到BR6张力
  cleaningVoltage: 'Cleaning Voltage', // 清洗电压
  cleaningCurrent: 'Cleaning Current', // 清洗电流
  alkaliConcentration: 'Alkali Concentration', // 碱液浓度
  alkaliTemperature: 'Alkali Temperature', // 碱液温度
  phfExitStripTemp: 'PH Exit Strip Temp', // PH炉出口温度
  potTemperature: 'Pot Temperature', // 锌锅温度
  gasConsumption: 'Gas Consumption', // 燃气消耗
  rtfExitStripTemp: 'RTF Exit Strip Temp', // RTF炉出口温度
  zincPotPower: 'Zinc Pot Power', // 锌锅功率
  jcsExitStripTemp: 'JCS Exit Strip Temp', // 冷却段出口温度
  coolingTowerStripTemp: 'Cooling Tower Temp', // 冷却塔温度
  scsExitStripTemp: 'SCS Exit Strip Temp', // 均衡段出口温度
  tensionBr5Tm: 'Tension BR5-TM', // BR5-TM张力
  stripSpeedTmExit: 'TM Exit Speed', // TM出口速度
  tmElongation: 'TM Elongation', // 光整延伸率
  tensionTlBr7: 'Tension TL-BR7', // TL-BR7张力
  tensionTlBr10Br11: 'Tension TL-BR10/11', // TL-BR10/11张力
  tlElongation: 'TL Elongation', // 拉矫延伸率
  tlFlag: 'TL Flag', // 拉矫机投用标志
  cxlLength: 'Exit Loop Length', // 出口活套位置
  cxlCapacity: 'Exit Loop Capacity', // 出口活套套量
  tensionCxl: 'Exit Loop Tension', // 出口活套张力
  coilLength: 'Coil Length', // 钢卷长度
  speedExitSection: 'Exit Section Speed', // 出口段速度
  tensionBr9Tr: 'Tension BR9-TR', // BR9-TR张力
  tensionBr8Tm: 'Tension BR8-TM', // BR8-TM张力
  tensionTmBr9: 'Tension TM-BR9', // TM-BR9张力
  tensionBr8Br9: 'Tension BR8-BR9', // BR8-BR9张力
  tensionBr9toBr10Br11: 'Tension BR9-BR10/11', // BR9到BR10/11张力
  tensionBr10Br11toBr12: 'Tension BR10/11-BR12', // BR10/11到BR12张力
  avrCoatingWeightTop: 'Avg Coating Weight Top', // 顶部平均涂层重量
  stdCoatingWeightTop: 'Std Coating Weight Top', // 顶部标准涂层重量
  maxCoatingWeightTop: 'Max Coating Weight Top', // 顶部最大涂层重量
  minCoatingWeightTop: 'Min Coating Weight Top', // 顶部最小涂层重量
  avrCoatingWeightBottom: 'Avg Coating Weight Bottom', // 底部平均涂层重量
  stdCoatingWeightBottom: 'Std Coating Weight Bottom', // 底部标准涂层重量
  maxCoatingWeightBottom: 'Max Coating Weight Bottom', // 底部最大涂层重量
  minCoatingWeightBottom: 'Min Coating Weight Bottom', // 底部最小涂层重量
  airKnifePressure: 'Air Knife Pressure', // 气刀压力
  airKnifeFlow: 'Air Knife Flow', // 气刀流量
  airKnifeGap: 'Air Knife Gap', // 气刀间隙
  tmMask: 'TM Mask', // TM掩码
  rollForceOperator: 'Roll Force Operator', // 操作侧辊压力
  rollForceDrive: 'Roll Force Drive', // 驱动侧辊压力
  motorTorque: 'Motor Torque', // 电机扭矩
  bendingForce: 'Bending Force', // 总弯曲力
  antiCrimpingRollMesh: 'Anti-Crimping Roll Mesh', // 防卷翘辊网距
  billyRollMesh: 'Billy Roll Mesh', // Billy Roll网距
  levelingUnit1Mesh: 'Leveling Unit 1 Mesh', // 矫直单元1网距
  levelingUnit2Mesh: 'Leveling Unit 2 Mesh', // 矫直单元2网距
  antiCrossBowUnitMesh: 'Anti Cross-Bow Unit Mesh', // 防横弯单元网距
  stripSpeedAfp: 'AFP Strip Speed', // AFP段钢带速度
  stripTempAfp: 'AFP Strip Temp' // AFP段钢带温度
}

const FIELD_ALIASES = {
  phfExitStripTemp: ['phFurnaceTemperatureActual', 'phFurnaceTemperature'],
  rtfExitStripTemp: ['nof1FurnaceTemperatureActual', 'nof1FurnaceTemperatureSet'],
  jcsExitStripTemp: ['jcsExitStripTemp'],
  scsExitStripTemp: ['scsExitStripTemp'],
  potTemperature: ['potTemperature'],
  zincPotPower: ['zincPotPower'],
  gasConsumption: ['gasConsumption'],
  coolingTowerStripTemp: ['coolingTowerTemperature', 'coolingTowerStripTemp'],
  cleaningVoltage: ['cleaningVoltage'],
  cleaningCurrent: ['cleaningCurrent'],
  alkaliConcentration: ['alkaliConcentration'],
  alkaliTemperature: ['alkaliTemperature']
}

const CLEANING_FIELDS = new Set(['cleaningVoltage', 'cleaningCurrent', 'alkaliConcentration', 'alkaliTemperature'])

export default {
  data() {
    return {
      // WebSocket 连接状态
      socketStatus: {
        measure: false,
        position: false,
        signal: false,
        matmap: false,
        calcSetup: false
      },
      matMapList: [],
      selectedCard: null,
      
      // 实时测量数据（track_measure）
      realtimeData: {
        entry: null,
        furnace: null,
        coat: null,
        exit: null
      },
      
      // 位置追踪数据（track_position）
      positionData: {
        coilStripLocationList: [],
        entryLoopLen: 0,
        exitLoopLen: 0,
        entryLoopPer: 0,
        exitLoopLPer: 0,
        porId: null,
        trId: null,
        entrySpeed: 0,
        technologySpeed: 0,
        exitSpeed: 0,
        matMapList: [],
      },
      
      // 操作信号数据（track_signal）
      signalData: null,
      // 上一次收到的操作类型（用于检测连续生产中）
      lastSignalOperation: null,
      
      // 计算设定结果（calc_setup_result）
      calcSetupResult: null,
      showCalcResultDialog: false,
      
      // 加载状态
      isLoading: true,
      
      // 计划队列tab
      activeQueueTab: 'all',
      
      // 生产计划队列
      planQueue: [],
      
      // 选中的生产计划
      selectedPlan: null,
      
      adjustForm: {
        current: null,
        target: null
      },
      adjustMode: false,
      operateMatForm: {
        porIdx: null,
        trIdx: null,
        planId: '',
        entryMatId: '',
        // planNo: '',
        operation: '',
        returnMatId: '',
        returnWeight: null,
        returnRemark: '',
        coilLength: null
      },
      operateRules: {
        planId: [{ required: true, message: '请输入计划id', trigger: 'blur' }],
        entryMatId: [{ required: true, message: '请输入钢卷号', trigger: 'blur' }],
        operation: [{ required: true, message: '请选择操作类型', trigger: 'change' }],
        returnMatId: [
          {
            required: true,
            message: '请输入回退卷号',
            trigger: 'blur',
            validator: (rule, val, cb) => {
              if (['ALL_RETURN', 'HALF_RETURN'].includes(this.operateMatForm.operation) && !val) {
                cb(new Error('请输入回退卷号'))
              } else cb()
            }
          }
        ],
        returnWeight: [
          {
            required: true,
            message: '请输入回退重量',
            trigger: 'blur',
            validator: (rule, val, cb) => {
              if (['ALL_RETURN', 'HALF_RETURN'].includes(this.operateMatForm.operation) && (val === null || val === '')) {
                cb(new Error('请输入回退重量'))
              } else cb()
            }
          }
        ]
      },
      operateMatStatus: false, // 操作对话框显示状态
      returnInfo: {},
      isLoadingReturn: false,
      returnError: ''
    }
  },
  computed: {
    // 当前计划（ONLINE 或 PRODUCING状态）
    currentPlans() {
      return this.planQueue.filter(plan => 
        ['ONLINE', 'PRODUCING', 'PRODUCTING'].includes(plan.status)
      )
    },
    
    // 当前生产中的计划（取状态为生产中的首条）
    producingPlan() {
      return this.planQueue.find(plan => ['PRODUCING', 'PRODUCTING'].includes(plan.status))
    },

    // 当前生产中的钢卷号
    producingCoilId() {
      if (this.producingPlan) {
        return this.producingPlan.coilid || this.producingPlan.matId || ''
      }
      return ''
    },
    
    // 显示的计划列表（根据tab切换）
    displayedPlans() {
      if (this.activeQueueTab === 'current') {
        return this.currentPlans
      }
      return this.planQueue
    },
    
    // 选中计划的位置信息
    selectedPlanPosition() {
      if (!this.selectedPlan || !this.matMapList || this.matMapList.length === 0) {
        return null
      }
      
      // 从matMapList中查找匹配的位置
      // matMapList中的字段是驼峰命名：planId, matId
      // 计划对象中的字段可能是：planid, coilid
      const position = this.matMapList.find(item => 
        (item.planId && item.planId === this.selectedPlan.planid) ||
        (item.planId && item.planId === this.selectedPlan.planId) ||
        (item.matId && item.matId === this.selectedPlan.coilid) ||
        (item.matId && item.matId === this.selectedPlan.matId)
      )
      
      return position
    },
    
    // Get operation title (English with Chinese comments)
    // 获取操作标题（英文显示，中文注释）
    getOperateTitle() {
      const titleMap = {
        'ONLINE': 'Coil Online', // 钢卷上线
        'UNLOAD': 'Manual Unload', // 手动卸卷
        'ALL_RETURN': 'Full Return', // 整卷回退
        'HALF_RETURN': 'Half Return', // 半卷回退
        'BLOCK': 'Unload & Block', // 卸卷并封闭
        'THROW_TAIL': 'Throw Tail' // 甩尾
      }
      return titleMap[this.operateMatForm.operation] || 'Coil Operation' // 钢卷操作
    },
    // 分段汇总数据
    entrySectionMetrics() {
      return this.buildSectionMetrics('ENTRY', ['stripSpeed', 'tensionPorBr1', 'tensionPorBr2', 'celLength', 'celCapacity'])
    },
    furnaceSectionMetrics() {
      return this.buildSectionMetrics('FURNACE', [
        'cleaningVoltage', 'cleaningCurrent', 'alkaliConcentration', 'alkaliTemperature',
        'phfExitStripTemp', 'rtfExitStripTemp', 'jcsExitStripTemp', 'scsExitStripTemp',
        'potTemperature', 'zincPotPower', 'gasConsumption', 'coolingTowerStripTemp'
      ])
    },
    coatSectionMetrics() {
      return this.buildSectionMetrics('COAT', ['stripSpeedTmExit', 'avrCoatingWeightTop', 'avrCoatingWeightBottom', 'tmElongation', 'tlElongation'])
    },
    exitSectionMetrics() {
      return this.buildSectionMetrics('EXIT', ['speedExitSection', 'coilLength', 'cxlLength', 'cxlCapacity', 'tensionBr9Tr'])
    },
    // 入口段设备列表（依据 DeviceEnum.sectionType）
    entryDevicesList() {
      return this.getDevicesBySection('ENTRY')
    },
    // 熔炉段设备列表（PROCESS 且来源 FURNACE）
    furnaceDevicesList() {
      return this.getDevicesBySource('FURNACE')
    },
    // 涂层段设备列表（PROCESS 且来源 COAT）
    coatDevicesList() {
      return this.getDevicesBySource('COAT')
    },
    // 出口段设备列表（EXIT，常规设备）
    exitDevicesList() {
      const exitDevices = this.getDevicesBySection('EXIT')
      return exitDevices.filter(d => !['INS', 'EXC', 'WEIGHT'].includes(d.positionNameEn))
    },
    // 出口其他设备列表
    exitOtherDevicesList() {
      return this.getDevicesBySection('EXIT').filter(d => ['INS', 'EXC', 'WEIGHT'].includes(d.positionNameEn))
    },
    // 根据选中设备获取详细数据
    currentDeviceData() {
      if (!this.selectedCard) return []
      const deviceId = this.selectedCard.positionNameEn
      const meta = DEVICE_META[deviceId]
      if (!meta) return []

      // 针对开卷机/入口活套/出口活套，先校验卷号匹配
      if (!this.matchReel(deviceId)) return []

      const source = this.getRealtimeSourceData(deviceId)
      if (!source) return []

      const data = []
      // 通用字段：按 DeviceEnum.paramFields 取值
      meta.paramFields.forEach(field => {
        const value = this.getFieldValueWithAlias(source, field)
        if (value !== null && value !== undefined && value !== '') {
          data.push({
            label: PARAM_LABELS[field] || field,
            value: this.formatValue(value),
            unit: this.getFieldUnit(field)
          })
        }
      })

      return data
    }
  },

  methods: {
    // ============ 辅助：设备元数据 ============
    getDevicesBySection(sectionType) {
      return this.matMapList.filter(d => DEVICE_META[d.positionNameEn]?.sectionType === sectionType)
    },
    getDevicesBySource(sourceType) {
      return this.matMapList.filter(d => DEVICE_META[d.positionNameEn]?.sourceType === sourceType)
    },
    // 判断设备是否有物料（用于绿框）
    hasMatId(deviceId) {
      const info = this.getDeviceInfo(deviceId)
      return !!(info && info.matId)
    },
    getRealtimeSourceData(deviceId) {
      const sourceType = DEVICE_META[deviceId]?.sourceType
      if (!sourceType) return null
      if (sourceType === 'ENTRY') return this.realtimeData.entry
      if (sourceType === 'FURNACE') return this.realtimeData.furnace
      if (sourceType === 'COAT') return this.realtimeData.coat
      if (sourceType === 'EXIT') return this.realtimeData.exit
      return null
    },
    getFieldValueWithAlias(source, field) {
      // 兼容后端字段命名差异（如大小写、别名）
      if (!source) return null
      // 按别名映射
      if (FIELD_ALIASES[field]) {
        for (const alias of FIELD_ALIASES[field]) {
          if (alias in source) return source[alias]
        }
      }
      if (field in source) return source[field]
      const lower = field.charAt(0).toLowerCase() + field.slice(1)
      if (lower in source) return source[lower]
      return null
    },
    getFieldUnit(field) {
      const unitMap = {
        stripSpeed: 'm/min',
        stripSpeedTmExit: 'm/min',
        stripSpeedAfp: 'm/min',
        celLength: 'm',
        cxlLength: 'm',
        celCapacity: '%',
        cxlCapacity: '%',
        tensionPorBr1: 'daN',
        tensionPorBr2: 'daN',
        tensionBr5Tm: 'daN',
        tensionTlBr7: 'daN',
        tensionCxl: 'daN',
        coilLength: 'm',
        speedExitSection: 'm/min',
        tlElongation: '%',
        tmElongation: '%',
        cleaningVoltage: 'V',
        cleaningCurrent: 'A',
        alkaliConcentration: 'g/L',
        alkaliTemperature: '℃',
        phfExitStripTemp: '℃',
        rtfExitStripTemp: '℃',
        jcsExitStripTemp: '℃',
        scsExitStripTemp: '℃',
        potTemperature: '℃',
        zincPotPower: 'kW',
        gasConsumption: 'm³/h'
      }
      return unitMap[field] || ''
    },
    getSectionSource(sectionType) {
      if (sectionType === 'ENTRY') return this.realtimeData.entry
      if (sectionType === 'FURNACE') return this.realtimeData.furnace
      if (sectionType === 'COAT') return this.realtimeData.coat
      if (sectionType === 'EXIT') return this.realtimeData.exit
      return null
    },
    buildSectionMetrics(sectionType, fields) {
      const source = this.getSectionSource(sectionType)
      return fields.map(f => {
        const raw = source ? this.getFieldValueWithAlias(source, f) : null
        const unit = this.getFieldUnit(f)
        return {
          label: PARAM_LABELS[f] || f,
          value: `${this.formatValue(raw)}${unit ? ' ' + unit : ''}`
        }
      })
    },
    matchReel(deviceId) {
      if (!['POR1', 'POR2', 'ENL1', 'ENL2', 'CXL1', 'CXL2'].includes(deviceId)) return true
      if (!this.realtimeData.entry) return false
      const reel = this.realtimeData.entry.payOffReelNumber
      if ((deviceId === 'POR1' || deviceId === 'ENL1' || deviceId === 'CXL1') && reel === 1) return true
      if ((deviceId === 'POR2' || deviceId === 'ENL2' || deviceId === 'CXL2') && reel === 2) return true
      return false
    },
    // ============ WebSocket 连接管理 ============
    
    initWebSockets() {
      // 1. track_measure - 实时测量数据
      wsManager.connect('track_measure', {
        onMessage: this.processMeasureData,
        onOpen: () => {
          this.socketStatus.measure = true
          console.log('✅ 测量数据连接成功')
        },
        onError: () => { this.socketStatus.measure = false },
        onClose: () => { this.socketStatus.measure = false }
      })

      // 2. track_position - 钢卷位置追踪
      wsManager.connect('track_position', {
        onMessage: this.processPositionData,
        onOpen: () => {
          this.socketStatus.position = true
          console.log('✅ 位置追踪连接成功')
        },
        onError: () => { this.socketStatus.position = false },
        onClose: () => { this.socketStatus.position = false }
      })

      // 3. track_signal - 操作信号
      wsManager.connect('track_signal', {
        onMessage: this.processSignalData,
        onOpen: () => {
          this.socketStatus.signal = true
          console.log('✅ 操作信号连接成功')
        },
        onError: () => { this.socketStatus.signal = false },
        onClose: () => { this.socketStatus.signal = false }
      })

      // 4. track_matmap - 物料位置映射
      wsManager.connect('track_matmap', {
        onMessage: this.processMatmapData,
        onOpen: () => {
          this.socketStatus.matmap = true
          console.log('✅ 物料映射连接成功')
        },
        onError: () => { this.socketStatus.matmap = false },
        onClose: () => { this.socketStatus.matmap = false }
      })

      // 5. calc_setup_result - 计算设定结果
      wsManager.connect('calc_setup_result', {
        onMessage: this.processCalcSetupResult,
        onOpen: () => {
          this.socketStatus.calcSetup = true
          console.log('✅ 计算结果连接成功')
        },
        onError: () => { this.socketStatus.calcSetup = false },
        onClose: () => { this.socketStatus.calcSetup = false }
      })
    },

    disconnectWebSockets() {
      wsManager.disconnectAll()
      this.socketStatus = {
        measure: false,
        position: false,
        signal: false,
        matmap: false,
        calcSetup: false
      }
    },

    // ============ 数据处理方法 ============
    
    processMeasureData(data) {
      if (data.appMeasureEntryMessage) {
        this.$set(this.realtimeData, 'entry', data.appMeasureEntryMessage)
      }
      if (data.appMeasureFurnaceMessage) {
        this.$set(this.realtimeData, 'furnace', data.appMeasureFurnaceMessage)
      }
      if (data.appMeasureCoatMessage) {
        this.$set(this.realtimeData, 'coat', data.appMeasureCoatMessage)
      }
      if (data.appMeasureExitMessage) {
        this.$set(this.realtimeData, 'exit', data.appMeasureExitMessage)
      }
      this.$forceUpdate()
    },

    processPositionData(data) {
      this.positionData = {
        coilStripLocationList: data.coilStripLocationList || [],
        entryLoopLen: data.entryLoopLen || 0,
        exitLoopLen: data.exitLoopLen || 0,
        entryLoopPer: data.entryLoopPer || 0,
        exitLoopLPer: data.exitLoopLPer || 0,
        porId: data.porId,
        trId: data.trId,
        entrySpeed: data.entrySpeed || 0,
        technologySpeed: data.technologySpeed || 0,
        exitSpeed: data.exitSpeed || 0,
        matMapList: data.matMapList || []
      }
      this.$forceUpdate()
    },

    processSignalData(data) {
      // 先记录是否为连续生产中信号
      const repeatProducing =this.lastSignalOperation === 'PRODUCING' && data.operation === 'PRODUCING'

      this.signalData = data
      const operationText = this.getOperationText(data.operation)
      const autoFlagText = data.autoFlag === 1 ? '[手动]' : '[自动]'
      const config = this.getOperationConfig(data.operation)
      
      // 检测到上线、生产中、生产完成等关键操作时，刷新生产计划队列
      if (['ONLINE', 'PRODUCING', 'PRODUCT'].includes(data.operation) ) {
        console.log(`检测到${operationText}操作，刷新生产计划队列...`)
        this.refreshPlanQueue()
      }
      
      // 右上角通知（所有操作都显示）
      if(!repeatProducing){
        this.$notify({
          title: `${config.icon} ${config.title}`,
          message: `${autoFlagText} ${operationText}\n钢卷号: ${data.entryMatId}\n计划ID: ${data.planId || '-'}`,
          type: config.type,
          duration: config.duration,
          position: 'top-right',
          showClose: true
        })
      
      }

      // 如果需要弹窗确认（甩尾等重要操作）
      if (config.needAlert) {
        this.$alert(
          `钢卷号: ${data.entryMatId}\n计划ID: ${data.planId || '-'}\n操作类型: ${operationText}\n操作方式: ${autoFlagText}`,
          `${config.icon} ${config.title}`,
          {
            confirmButtonText: '知道了',
            type: config.type,
            center: true
          }
        )
      }
      
      // 如果物料映射 WebSocket 未连接，则刷新数据
      if (!this.socketStatus.matmap) {
        this.fetchData()
      }


      // 记录本次操作类型
      this.lastSignalOperation = data.operation
    },

    processMatmapData(data) {
      if (Array.isArray(data)) {
        this.matMapList = data
        this.$forceUpdate()
      }
    },

    processCalcSetupResult(data) {
      this.calcSetupResult = data
      
      if (data.flag) {
        this.$message.success(`计算完成 (Key: ${data.key})`)
        this.showCalcResultDialog = true
      } else {
        this.$message.error(`计算失败 (Key: ${data.key})`)
      }
    },

    // ============ 辅助方法 ============
    
    // Get operation text (English with Chinese comments)
    // 获取操作文本（英文显示，中文注释）
    getOperationText(operation) {
      const operationMap = {
        ONLINE: 'Coil Online', // 钢卷上线
        UNLOAD: 'Unload', // 卸卷
        PRODUCING: 'Producing', // 生产中
        PRODUCT: 'Completed', // 生产完成
        PAY_OVER: 'Pay Over', // 甩尾
        THROW_TAIL: 'Throw Tail', // 甩尾
        ALL_RETURN: 'Full Return', // 整卷回退
        HALF_RETURN: 'Half Return', // 半卷回退
        BLOCK: 'Unload & Block' // 卸卷并封闭
      }
      return operationMap[operation] || operation
    },

    // 获取操作类型配置
    getOperationConfig(operation) {
      const configs = {
        ONLINE: {
          icon: '🎬',
          title: '钢卷上线通知',
          type: 'success',
          duration: 4000,
          needAlert: false
        },
        UNLOAD: {
          icon: '📤',
          title: '卸卷操作通知',
          type: 'info',
          duration: 3000,
          needAlert: false
        },
        PRODUCING: {
          icon: '⚙️',
          title: '生产状态变更',
          type: 'success',
          duration: 3000,
          needAlert: false
        },
        PRODUCT: {
          icon: '✅',
          title: '生产完成通知',
          type: 'success',
          duration: 4000,
          needAlert: false
        },
        PAY_OVER: {
          icon: '⚠️',
          title: '甩尾操作提示',
          type: 'warning',
          duration: 5000,
          needAlert: true
        },
        THROW_TAIL: {
          icon: '⚠️',
          title: '甩尾操作提示',
          type: 'warning',
          duration: 5000,
          needAlert: true
        },
        ALL_RETURN: {
          icon: '↩️',
          title: '整卷回退通知',
          type: 'warning',
          duration: 4000,
          needAlert: false
        },
        HALF_RETURN: {
          icon: '↩️',
          title: '半卷回退通知',
          type: 'warning',
          duration: 4000,
          needAlert: false
        },
        BLOCK: {
          icon: '🚫',
          title: '封闭操作通知',
          type: 'warning',
          duration: 3000,
          needAlert: false
        }
      }
      return configs[operation] || {
        icon: '📢',
        title: '操作通知',
        type: 'info',
        duration: 3000,
        needAlert: false
      }
    },

    // ============ API 方法 ============
    
    // 刷新生产计划队列（独立方法，可被信号触发）
    async refreshPlanQueue() {
      try {
        // 只查询活动状态的计划，排除已完成和甩尾
        const statuses = ['ONLINE', 'PRODUCING', 'READY', 'NEW']
        const allPlans = []
        
        // 并行查询所有状态
        const requests = statuses.map(status => 
          getPlanQueue({ status }).catch(err => {
            console.warn(`查询${status}状态失败:`, err)
            return { code: 500, data: [] }
          })
        )
        
        const results = await Promise.all(requests)
        
        // 合并所有查询结果
        results.forEach((res, index) => {
          if (res.code === 200 && res.data) {
            allPlans.push(...res.data)
          }
        })
        
        // 去重（根据id）
        const uniquePlans = Array.from(
          new Map(allPlans.map(plan => [plan.id, plan])).values()
        )
        
        // 排除已完成和甩尾的计划
        const excludeStatuses = ['PRODUCT', 'PAY_OVER', 'COMPLETED', 'CANCELLED', 'UNLOAD']
        const activePlans = uniquePlans.filter(plan => 
          !excludeStatuses.includes(plan.status)
        )
        
        // 定义状态优先级
        const statusPriority = {
          'PRODUCING': 1,
          'ONLINE': 2,
          'READY': 3,
          'NEW': 4
        }
        
        // 排序
        const sortedPlans = activePlans.sort((a, b) => {
          const priorityA = statusPriority[a.status] || 500
          const priorityB = statusPriority[b.status] || 500
          if (priorityA !== priorityB) {
            return priorityA - priorityB
          }
          return (a.seqid || 0) - (b.seqid || 0)
        })
        
        // 最多显示 5 个计划
        this.planQueue = sortedPlans.slice(0, 5)
        
        console.log('查询到的总计划数：', uniquePlans.length, '条')
        console.log('活动计划数：', activePlans.length, '条')
        console.log('显示的计划：', this.planQueue.length, '条', this.planQueue)
        
      } catch (err) {
        console.error('获取生产计划队列失败：', err)
        this.planQueue = this.generateMockPlanQueue()
      }
    },
    
    async fetchData() {
      try {
        this.isLoading = true
        const res = await getTrackMatPosition()
        
        // 只在 WebSocket 未连接时使用 API 数据
        if (!this.socketStatus.matmap) {
          this.matMapList = res.data.matMapList || []
        }
        
        // 获取生产计划队列
        await this.refreshPlanQueue()
        
      } catch (err) {
        console.error('获取钢卷数据失败：', err)
        this.$message.error('获取数据失败，请重试')
      } finally {
        // 延迟关闭加载状态，确保界面渲染完成
        setTimeout(() => {
          this.isLoading = false
        }, 500)
      }
    },

    // 生成模拟计划队列数据（降级方案）
    generateMockPlanQueue() {
      // 从物料映射中提取有钢卷的数据作为计划队列
      const plansFromMap = this.matMapList
        .filter(item => item.matId)
        .map((item, index) => ({
          planid: item.planId || `PLAN_${index + 1}`,
          coilid: item.matId,
          steelGrade: `Q235-${index + 1}`,
          status: index === 0 ? 'PRODUCING' : (index === 1 ? 'READY' : 'NEW'),
          seqid: index + 1
        }))
      
      return plansFromMap.slice(0, 5) // 最多显示5个计划
    },

    // Get plan status text (English with Chinese comments)
    // 获取计划状态文本（英文显示，中文注释）
    getPlanStatusText(status) {
      const statusMap = {
        NEW: 'New', // 新建
        READY: 'Ready', // 就绪
        ONLINE: 'Online', // 上线
        PRODUCING: 'Producing', // 生产中
        PRODUCT: 'Completed', // 生产完成
        PAY_OVER: 'Pay Over', // 甩尾
        UNLOAD: 'Unload', // 卸卷
        COMPLETED: 'Completed', // 已完成
        CANCELLED: 'Cancelled' // 已取消
      }
      return statusMap[status] || status || 'Unknown' // 未知
    },

    // 获取计划状态标签类型
    getPlanStatusTagType(status) {
      const typeMap = {
        NEW: 'info',
        READY: 'primary',
        ONLINE: 'warning',
        PRODUCING: 'success',
        PRODUCTING: 'success',  // 兼容带T的写法
        PRODUCT: 'info',
        PAY_OVER: '',
        UNLOAD: 'danger',
        COMPLETED: 'info',
        CANCELLED: 'danger'
      }
      return typeMap[status] || 'info'
    },

    // 获取计划卡片样式类
    getPlanItemClass(plan) {
      const classes = []
      
      if (plan.status === 'PRODUCING' || plan.status === 'PRODUCTING') {
        classes.push('plan-producing')
      }
      if (plan.status === 'ONLINE') {
        classes.push('plan-online')
      }
      if (plan.status === 'READY') {
        classes.push('plan-ready')
      }
      if (this.selectedPlan && this.selectedPlan.id === plan.id) {
        classes.push('plan-selected')
      }
      
      return classes
    },

    // 获取计划序号样式类
    getPlanOrderClass(status) {
      if (status === 'PRODUCING' || status === 'PRODUCTING') return 'order-producing'
      if (status === 'ONLINE') return 'order-online'
      if (status === 'READY') return 'order-ready'
      if (status === 'NEW') return 'order-new'
      return ''
    },


    // 根据设备ID获取设备信息
    getDeviceInfo(deviceId) {
      return this.matMapList.find(item => item.positionNameEn === deviceId)
    },

    // 选择设备
    selectDevice(deviceId) {
      const deviceInfo = this.getDeviceInfo(deviceId)
      if (deviceInfo) {
        this.selectedCard = this.selectedCard === deviceInfo ? null : deviceInfo
        if (this.selectedCard) {
          this.adjustForm.current = this.selectedCard.positionNameEn
        } else {
          this.adjustForm.current = null
        }
        // 选择设备时清除选中的计划
        this.selectedPlan = null
      }
    },

    // 选择生产计划
    selectPlan(plan) {
      if (this.selectedPlan && this.selectedPlan.id === plan.id) {
        this.selectedPlan = null
      } else {
        this.selectedPlan = plan
        // 选择计划时清除选中的设备
        this.selectedCard = null
        
        // 调试：查找并显示位置信息
        const position = this.matMapList.find(item => 
          (item.planId && item.planId === plan.planid) ||
          (item.planId && item.planId === plan.planId) ||
          (item.matId && item.matId === plan.coilid) ||
          (item.matId && item.matId === plan.matId)
        )
        
        if (position) {
          console.log('✅ 找到计划位置：', position.positionNameCn, '(', position.positionNameEn, ')')
          console.log('匹配详情 - matId:', position.matId, 'planId:', position.planId)
        } else {
          console.log('⚠️ 未找到计划位置')
          console.log('matMapList有', this.matMapList.length, '个设备:', this.matMapList)
          console.log('计划信息 - planid:', plan.planid, 'planId:', plan.planId, 'coilid:', plan.coilid, 'matId:', plan.matId)
        }
      }
    },

    // 格式化日期时间
    formatDateTime(dateTime) {
      if (!dateTime) return '-'
      const date = new Date(dateTime)
      if (isNaN(date.getTime())) return '-'
      
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      const seconds = String(date.getSeconds()).padStart(2, '0')
      
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
    },

    // 获取操作标签类型
    getOperationTagType(operation) {
      const typeMap = {
        ONLINE: 'success',
        UNLOAD: 'info',
        PRODUCING: 'success',
        PRODUCT: 'success',
        PAY_OVER: 'warning',
        THROW_TAIL: 'warning',
        ALL_RETURN: 'warning',
        HALF_RETURN: 'warning',
        BLOCK: 'danger'
      }
      return typeMap[operation] || 'info'
    },

    // 获取信号面板样式类
    getSignalPanelClass(operation) {
      if (operation === 'PAY_OVER' || operation === 'THROW_TAIL') {
        return 'signal-warning'
      }
      if (operation === 'ONLINE') {
        return 'signal-success'
      }
      if (operation === 'PRODUCT') {
        return 'signal-complete'
      }
      return ''
    },

    // 获取操作文本样式类
    getOperationTextClass(operation) {
      if (operation === 'PAY_OVER' || operation === 'THROW_TAIL') {
        return 'text-warning'
      }
      if (operation === 'ONLINE' || operation === 'PRODUCING' || operation === 'PRODUCT') {
        return 'text-success'
      }
      return ''
    },

    // 判断设备是否有实时数据（基于 sourceType & 卷号匹配）
    hasRealtimeData(deviceId) {
      const source = this.getRealtimeSourceData(deviceId)
      if (!source) return false
      if (!this.matchReel(deviceId)) return false
      const meta = DEVICE_META[deviceId]
      if (!meta) return false
      return meta.paramFields.some(f => {
        const val = this.getFieldValueWithAlias(source, f)
        return val !== null && val !== undefined
      })
    },

    // 判断设备是否工作中（统一依据 paramFields 有效数值/状态）
    isDeviceWorking(deviceId) {
      const info = this.getDeviceInfo(deviceId)
      if (info?.matId) return true
      const source = this.getRealtimeSourceData(deviceId)
      const meta = DEVICE_META[deviceId]
      if (!source || !meta || !this.matchReel(deviceId)) return false
      return meta.paramFields.some(f => {
        const val = this.getFieldValueWithAlias(source, f)
        if (val === null || val === undefined) return false
        if (typeof val === 'number') return val > 0
        if (typeof val === 'string') return val !== '' && val !== '--'
        return true
      })
    },

    // Get device status text (English with Chinese comments)
    // 获取设备状态文本（英文显示，中文注释）
    getDeviceStatus(deviceId) {
      const deviceInfo = this.getDeviceInfo(deviceId)
      
      // If there is material mapping coil ID, display coil ID
      // 如果有物料映射的钢卷号，显示钢卷号
      if (deviceInfo?.matId) {
        return deviceInfo.matId
      }
      
      // Determine working status based on real-time data
      // 根据实时数据判断工作状态
      if (this.isDeviceWorking(deviceId)) {
        return 'Working' // 工作中
      }
      
      return 'Idle' // 空闲
    },

  
    /**
     * 获取回退信息
     * @param {Number} posIdx - 位置索引（接口必填query参数）
     */
    fetchReturnData(posIdx) {
      // 1. 校验posIdx
      if (!posIdx && posIdx !== 0) {
        this.returnInfo = {};
        this.returnError = '缺少位置索引（posIdx），无法获取回退信息';
        return;
      }

      // 2. 加载状态初始化
      this.isLoadingReturn = true;
      this.returnError = '';

      // 3. 调用回退接口（posIdx作为query参数传递）
      getBackData({ posIdx })
        .then(res => {
          this.isLoadingReturn = false;
          // 接口成功且有数据
          if (res.code === 200 && res.data) {
            this.returnInfo = res.data;
          } else {
            this.returnInfo = {};
            this.returnError = res.msg || '获取回退信息失败';
          }
        })
        .catch(err => {
          this.isLoadingReturn = false;
          this.returnInfo = {};
          this.returnError = '获取回退信息出错，请重试';
          console.error('回退信息接口异常：', err);
        });
    },

    // 格式化数值
    formatValue(value) {
      if (value === null || value === undefined) return '0.00'
      if (typeof value === 'number') return value.toFixed(2)
      return value
    },


    // 确认调整位置
    handleConfirmAdjust() {
      const { current, target } = this.adjustForm

      if (!current || !target) {
        this.$message.warning('Please select current and target positions') // 请选择当前位置和目标位置
        return
      }

      const params = {
        currentPos: current,
        targetPos: target,
      }

      this.$confirm(`Confirm to adjust coil from ${current} to ${target}?`, 'Confirm Adjustment', {
        // 确定将 ${current} 的钢卷调整到 ${target}？, 确认调整
        confirmButtonText: 'Confirm', // 确定
        cancelButtonText: 'Cancel', // 取消
        type: 'warning'
      }).then(() => {
        adjustPosition(params).then(() => {
          this.$message.success('Adjustment successful') // 调整成功
          this.fetchData()
        }).catch(err => {
          console.error('Adjustment failed:', err) // 调整失败
          this.$message.error('Adjustment failed, please retry') // 调整失败，请重试
        })
      }).catch(() => {
        this.$message.info('Adjustment cancelled') // 已取消调整
      })
    },

    // 打开操作对话框
    handleOperate(row, operation) {
      this.$refs.operateForm?.resetFields()
      console.log(this.selectCard, row.posIdx)
      this.operateMatForm = {
        porIdx: row.posIdx.toString() || '',
        trIdx: row.posIdx.toString() || '',
        planId: row.planId || '',
        entryMatId: row.matId || '',
        planNo: row.planNo || '',
        operation: operation,
        returnMatId: '',
        returnWeight: null,
        returnRemark: '',
        coilLength: null
      }
      this.operateMatStatus = true
    },

    // 提交操作表单
    submitOperateForm() {
      this.$refs.operateForm.validate(valid => {
        if (valid) {
          operateMat(this.operateMatForm).then(() => {
            this.$message.success('Operation successful') // 操作成功
            this.operateMatStatus = false
            this.fetchData()
          }).catch(err => {
            console.error('Operation failed:', err) // 操作失败
            this.$message.error('Operation failed, please retry') // 操作失败，请重试
          })
        } else {
          this.$message.warning('Please complete the form') // 请完善表单信息
        }
      })
    }
  },

  async mounted() {
    await this.fetchData()
    this.initWebSockets()
  },

  beforeDestroy() {
    this.disconnectWebSockets()
  }
}
</script>

<style scoped>
.device-layout {
  background: #f5f5f5;
  border-radius: 4px;
  padding: 15px;
  height: calc(100vh - 60px);
  overflow-y: auto;
}

/* 分区区域 */
.section-area {
  margin-bottom: 20px;
  background: #fafafa;
  border-radius: 6px;
  padding: 12px;
  border: 1px solid #e8e8e8;
}

.section-header {
  font-size: 15px;
  font-weight: 600;
  color: #333;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 2px solid #ddd;
}

/* 设备网格 */
.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
}

/* 设备卡片 */
.device-card {
  background: #fff;
  border: 2px solid #e0e0e0;
  border-radius: 6px;
  padding: 12px;
  cursor: pointer;
  transition: all 0.2s ease;
  min-height: 120px;
}

.device-card:hover {
  border-color: #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
  transform: translateY(-2px);
}

.device-card.active {
  border-color: #409eff;
  background: #ecf5ff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.device-card.has-data {
  border-color: #67c23a;
}

.device-card.has-data:hover {
  border-color: #67c23a;
  box-shadow: 0 2px 8px rgba(103, 194, 58, 0.3);
}

.device-card.has-data.active {
  border-color: #409eff;
  background: #ecf5ff;
}

.device-name {
  font-size: 14px;
  font-weight: 600;
  color: #333;
  margin-bottom: 4px;
}

.device-code {
  font-size: 11px;
  color: #999;
  margin-bottom: 6px;
}

.device-status {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #f0f0f0;
}

.coil-id {
  font-size: 12px;
  font-weight: 500;
}

.status-working {
  color: #67c23a;
}

.status-idle {
  color: #909399;
}

.realtime-indicator {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #f0f0f0;
}

.mini-data {
  font-size: 11px;
  color: #666;
  margin-bottom: 3px;
  display: flex;
  justify-content: space-between;
}

.mini-label {
  color: #999;
}

.mini-value {
  color: #67c23a;
  font-weight: 500;
}

.section-summary {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
  margin: 8px 0 14px;
}

.summary-item {
  background: linear-gradient(135deg, #f7f9fc 0%, #eef2f7 100%);
  border: 1px solid #e0e6ed;
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 13px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

.summary-label {
  color: #606266;
  font-weight: 600;
}

.summary-value {
  color: #1f2d3d;
  font-weight: 700;
}

/* 段落色系 */
.entry-area .section-header { border-bottom-color: #409eff; }
.entry-area .summary-value { color: #409eff; }
.furnace-area .section-header { border-bottom-color: #e6a23c; }
.furnace-area .summary-value { color: #e6a23c; }
.coat-area .section-header { border-bottom-color: #67c23a; }
.coat-area .summary-value { color: #67c23a; }
.exit-area .section-header { border-bottom-color: #909399; }
.exit-area .summary-value { color: #909399; }

.panel {
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 15px;
  margin-bottom: 15px;
  background: #fff;
}

.panel-title {
  font-size: 14px;
  font-weight: 600;
  color: #333;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #eee;
}

.info-table {
  width: 100%;
  font-size: 13px;
}

.info-table tr {
  border-bottom: 1px solid #f5f5f5;
}

.info-table tr:last-child {
  border-bottom: none;
}

.info-table td {
  padding: 8px 0;
  line-height: 1.6;
}

.info-table td:first-child {
  color: #666;
  width: 80px;
}

.info-table td:last-child {
  color: #333;
  font-weight: 500;
}

.empty-msg {
  text-align: center;
  padding: 30px;
  color: #999;
  font-size: 13px;
}

.realtime-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.data-item {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  padding: 12px;
  text-align: center;
  background: #fafafa;
}

.data-label {
  font-size: 12px;
  color: #666;
  margin-bottom: 8px;
}

.data-value {
  font-size: 24px;
  font-weight: 600;
  color: #333;
  margin-bottom: 4px;
  font-family: 'Arial', sans-serif;
}

.data-unit {
  font-size: 12px;
  color: #999;
}

.btn-list {
  display: flex;
  flex-wrap: wrap;
}

.action-btn {
  margin-bottom: 8px;
  width: 80px;
  height: 40px;
}

/* 加载状态 */
.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 100px 0;
  color: #409eff;
  font-size: 16px;
}

.loading-container .el-icon-loading {
  font-size: 40px;
  margin-bottom: 15px;
  animation: rotating 2s linear infinite;
}

@keyframes rotating {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 生产计划队列面板 */
.plan-queue-panel {
  background: #fff;
  border-radius: 8px;
  margin-bottom: 15px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}

/* 队列头部 */
.queue-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 15px;
  background: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
}

.queue-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
  display: flex;
  align-items: center;
  gap: 6px;
}

.queue-title i {
  font-size: 16px;
  color: #409eff;
}

/* Tab切换按钮组 */
.queue-tabs {
  display: flex;
  gap: 0;
}

.queue-tab {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  cursor: pointer;
  transition: all 0.2s;
  font-size: 13px;
  color: #606266;
  background: transparent;
  border-bottom: 2px solid transparent;
  user-select: none;
}

.queue-tab:hover {
  color: #409eff;
}

.queue-tab.active {
  color: #409eff;
  font-weight: 600;
  border-bottom-color: #409eff;
}

.queue-tab i {
  font-size: 13px;
}

.queue-tab .tab-badge {
  margin-left: 4px;
}

.plan-queue-panel .panel-title {
  font-size: 14px;
  font-weight: 600;
  color: #333;
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* 右侧纵向生产计划列表 */
.plan-list-vertical {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.plan-item-vertical {
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  padding: 12px;
  background: #f7f9fc;
  transition: all 0.2s ease;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.plan-item-vertical:hover {
  border-color: #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
  transform: translateY(-1px);
}

.plan-item-vertical.plan-producing {
  background: #f0f9ff;
  border-color: #67c23a;
  animation: pulse-green 1.5s infinite;
}

.plan-item-vertical.plan-online {
  background: #fdf6ec;
  border-color: #e6a23c;
}

.plan-item-vertical.plan-ready {
  background: #ecf5ff;
  border-color: #409eff;
}

.plan-item-vertical.plan-selected {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.plan-item-top {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: space-between;
}

.plan-order-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: #fff;
  background: #909399;
  flex-shrink: 0;
}

.plan-order-dot.order-producing { background: #67c23a; animation: blink-green-dot 1.2s infinite; }
.plan-order-dot.order-online { background: #e6a23c; }
.plan-order-dot.order-ready { background: #409eff; }
.plan-order-dot.order-new { background: #909399; }

.plan-title-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  color: #303133;
}

.plan-id { font-weight: 600; }
.plan-coil { color: #606266; }

.plan-item-bottom {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: #606266;
}

.plan-queue-panel .panel-title i {
  margin-right: 8px;
  color: #409eff;
}

.plan-queue-list {
  max-height: none;
  overflow-y: visible;
  padding: 15px 20px;
}

.plan-items {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  padding-bottom: 5px;
}

.plan-item {
  min-width: 220px;
  background: #f5f7fa;
  border: 2px solid #e4e7ed;
  border-radius: 6px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: all 0.3s;
  cursor: pointer;
}

.plan-item:hover {
  border-color: #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
  transform: translateY(-2px);
}

.plan-item.plan-producing {
  background: #f0f9ff;
  border-color: #67c23a;
  animation: pulse-green 1.5s infinite;
}

.plan-item.plan-online {
  background: #fdf6ec;
  border-color: #e6a23c;
}

.plan-item.plan-ready {
  background: #ecf5ff;
  border-color: #409eff;
}

.plan-item.plan-selected {
  background: #f0f9ff;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

/* 绿色闪烁动画 */
@keyframes pulse-green {
  0%, 100% {
    border-color: #67c23a;
    box-shadow: 0 0 0 0 rgba(103, 194, 58, 0.4);
  }
  50% {
    border-color: #85ce61;
    box-shadow: 0 0 0 4px rgba(103, 194, 58, 0.6), 0 0 15px rgba(103, 194, 58, 0.4);
  }
}

.plan-order {
  width: 28px;
  height: 28px;
  background: #909399;
  color: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 14px;
  flex-shrink: 0;
}

.plan-order.order-producing {
  background: #67c23a;
  animation: blink-green-dot 1.2s infinite;
}

.plan-order.order-online {
  background: #e6a23c;
}

.plan-order.order-ready {
  background: #409eff;
}

.plan-order.order-new {
  background: #909399;
}

/* 绿色点闪烁动画 */
@keyframes blink-green-dot {
  0%, 100% {
    background: #67c23a;
    box-shadow: 0 0 5px rgba(103, 194, 58, 0.5);
  }
  50% {
    background: #85ce61;
    box-shadow: 0 0 10px rgba(103, 194, 58, 0.8);
  }
}

.plan-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.plan-row {
  display: flex;
  align-items: center;
  font-size: 13px;
}

.plan-label {
  color: #909399;
  min-width: 60px;
  flex-shrink: 0;
}

.plan-value {
  color: #303133;
  font-weight: 500;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.plan-status {
  display: flex;
  justify-content: flex-end;
}

/* WebSocket 状态栏 */
.ws-status-bar {
  display: flex;
  gap: 15px;
  padding: 10px;
  background: #f5f7fa;
  border-radius: 4px;
  margin-bottom: 10px;
  align-items: center;
}

.ws-status-bar i {
  font-size: 18px;
  color: #606266;
  cursor: pointer;
}

/* 分区头部增强 */
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.section-info {
  font-size: 13px;
  color: #67c23a;
  font-weight: 500;
}

/* 信号信息面板 */
.signal-info {
  padding: 10px 0;
}

.signal-info.signal-warning {
  background: #fef0f0;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #fde2e2;
}

.signal-info.signal-success {
  background: #f0f9ff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #c6e2ff;
}

.signal-info.signal-complete {
  background: #f0f9ff;
  padding: 15px;
  border-radius: 4px;
  border: 1px solid #b3e19d;
}

.signal-detail {
  margin-top: 10px;
  font-size: 13px;
  line-height: 2;
}

.signal-detail div {
  padding: 4px 0;
}

.text-warning {
  color: #e6a23c;
  font-weight: 600;
  font-size: 14px;
}

.text-success {
  color: #67c23a;
  font-weight: 600;
  font-size: 14px;
}

/* 计算结果头部 */
.calc-result-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  padding-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
  font-size: 14px;
}

/* 生产计划详情 */
.plan-detail-content {
  overflow-y: auto;
}

/* 位置信息提示卡片 */
.position-alert {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 15px;
  margin-bottom: 15px;
  background: #f0f9ff;
  border: 1px solid #b3d8ff;
  border-left: 4px solid #409eff;
  border-radius: 4px;
}

.position-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: #409eff;
  border-radius: 50%;
  color: #fff;
  font-size: 20px;
  flex-shrink: 0;
}

.position-info {
  flex: 1;
}

.position-label {
  font-size: 12px;
  color: #909399;
  margin-bottom: 4px;
}

.position-name {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 2px;
}

.position-code {
  font-size: 12px;
  color: #606266;
  font-family: 'Courier New', monospace;
}

.plan-time-info {
  margin-top: 15px;
  padding-top: 15px;
  border-top: 1px solid #ebeef5;
}

.info-subtitle {
  font-size: 13px;
  font-weight: 600;
  color: #606266;
  margin-bottom: 10px;
}

.panel-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.panel-title i {
  margin-right: 5px;
}
</style>
