<template>
  <div class="mat-page">
    <!-- 顶部状态条 -->
    <div class="status-bar">
      <div class="status-item">
        <span class="kv-label">当前卷号</span>
        <span class="kv-value">{{ current.coil_no || '—' }}</span>
      </div>
      <div class="status-item">
        <span class="kv-label">工艺段速度</span>
        <span class="kv-value">{{ current.speed.toFixed(1) }} <span class="kv-unit">m/min</span></span>
      </div>
      <div class="status-item">
        <span class="kv-label">焊缝位置</span>
        <span class="kv-value">{{ (weld.position * 100).toFixed(1) }} <span class="kv-unit">%</span></span>
      </div>
      <div class="status-item">
        <span class="kv-label">当前设备</span>
        <span class="kv-value">{{ currentEquipment.label }}</span>
      </div>
      <div class="status-item">
        <span class="kv-label">开卷张力</span>
        <span class="kv-value">{{ uncoiler.tension.toFixed(1) }} <span class="kv-unit">kN</span></span>
      </div>
      <div class="status-item">
        <span class="kv-label">收卷张力</span>
        <span class="kv-value">{{ recoiler.tension.toFixed(1) }} <span class="kv-unit">kN</span></span>
      </div>
      <div class="status-item" style="margin-left:auto;">
        <span :class="['badge', l1Online ? 'badge-green' : 'badge-yellow']">{{ l1Online ? 'L1 在线' : '模拟数据' }}</span>
        <span class="kv-label" style="margin-left:8px;">{{ rtItems.length }} 测点</span>
      </div>
    </div>

    <!-- 在线计划队列 + 入口移动 -->
    <div class="card" style="margin-bottom:8px;">
      <div class="card-header">
        在线计划（入口队列）
        <span class="ch-badge">在线 {{ onlinePlans.length }} / 生产中 {{ producingPlan ? 1 : 0 }}</span>
      </div>
      <div style="padding:8px 14px;">
        <div v-if="producingPlan" class="producing-row">
          <span class="badge badge-yellow">生产中</span>
          <span class="kv-label">冷卷号</span><span class="kv-value">{{ producingPlan.cold_coil_no || producingPlan.plan_no }}</span>
          <span class="kv-label">钢种</span><span class="kv-value">{{ producingPlan.steel_grade || '—' }}</span>
          <span class="kv-label">规格</span><span class="kv-value">{{ fmt(producingPlan.product_thickness) }}×{{ fmt(producingPlan.product_width, 0) }}</span>
          <span class="kv-label">线速度</span><span class="kv-value">{{ fmt(producingPlan.run_speed, 0) }}<span class="kv-unit"> m/min</span></span>
          <span class="kv-label">带头</span><span class="kv-value">{{ fmt(prodLength, 0) }}<span class="kv-unit"> / 2000 m</span></span>
          <div class="prog-bar-wrap" style="flex:1;min-width:120px;height:8px;">
            <div class="prog-bar-fill" :style="{ width: prodPct + '%', background: prodPct >= 100 ? 'var(--accent-green)' : 'var(--sms-teal)' }"></div>
          </div>
          <span class="kv-value">{{ prodPct.toFixed(0) }}%</span>
        </div>
        <table class="data-table compact" v-if="onlinePlans.length">
          <thead><tr><th>冷卷号</th><th>钢种</th><th>厚度</th><th>宽度</th><th>分卷</th><th>下达时间</th><th>操作</th></tr></thead>
          <tbody>
            <tr v-for="p in onlinePlans" :key="p.id">
              <td class="td-num">{{ p.cold_coil_no || p.plan_no }}</td>
              <td>{{ p.steel_grade || '—' }}</td>
              <td class="td-num">{{ fmt(p.product_thickness) }}</td>
              <td class="td-num">{{ fmt(p.product_width, 0) }}</td>
              <td class="td-num">{{ p.split_count || 1 }}</td>
              <td class="td-muted">{{ fmtTime(p.plan_date) }}</td>
              <td>
                <button class="btn btn-primary btn-sm" :disabled="moving" @click="movePlan(p)">移动 →</button>
              </td>
            </tr>
          </tbody>
        </table>
        <div v-else-if="!producingPlan" class="td-muted" style="text-align:center;padding:10px;font-size:12px;">暂无在线计划</div>
      </div>
    </div>

    <!-- 产线总图 -->
    <div class="line-wrap card">
      <div class="card-header">推拉酸洗线 - 物料跟踪总图</div>
      <div class="line-body">
        <svg viewBox="0 0 1900 305" preserveAspectRatio="xMidYMid meet" class="line-svg">
          <rect x="0" y="0" width="1900" height="305" fill="#f2f5f9" />

          <!-- 段位标签带 -->
          <g v-for="s in sections" :key="'sec-'+s.name">
            <rect :x="s.bandX" y="2" :width="s.bandW" height="20" :fill="s.color" opacity="0.18" rx="3"/>
            <rect :x="s.bandX" y="2" :width="s.bandW" height="20" fill="none" :stroke="s.color" stroke-width="1" opacity="0.7" rx="3"/>
            <text :x="s.labelX" y="16" text-anchor="middle" font-size="11" font-weight="bold" :fill="s.color"
                  font-family="Arial,sans-serif">{{ s.name }}</text>
          </g>

          <!-- 顶部标签 -->
          <g v-for="eq in equipments" :key="'lab-'+eq.k" font-family="Arial,sans-serif">
            <text :x="eq.x" y="40" text-anchor="middle" font-size="10.5" fill="#303133">{{ eq.label }}</text>
          </g>

          <!-- 主带钢线 -->
          <path d="M 40 185 L 1860 185" stroke="#9aa4b0" stroke-width="3" fill="none"/>
          <path d="M 40 185 L 1860 185" stroke="#c03639" stroke-width="1.4" fill="none" stroke-dasharray="6 10">
            <animate attributeName="stroke-dashoffset" from="16" to="0" dur="0.7s" repeatCount="indefinite"/>
          </path>

          <!-- 各设备图形 -->
          <g v-for="eq in equipments" :key="eq.k" :transform="`translate(${eq.x}, 185)`">
            <!-- 开卷机 -->
            <template v-if="eq.type==='coiler'">
              <circle r="38" fill="#e9eef4" stroke="#aab4c2" stroke-width="2"/>
              <circle r="22" fill="#f2f5f9" stroke="#9aa4b0" stroke-width="1.5"/>
              <circle r="8" fill="#cdd6e0" stroke="#9aa4b0" stroke-width="1"/>
              <path d="M-38 0 a38 38 0 0 1 76 0" stroke="#c03639" stroke-width="1" fill="none" opacity="0.5">
                <animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="3s" repeatCount="indefinite"/>
              </path>
              <text y="58" text-anchor="middle" font-size="10" fill="#5b6470">DC-1</text>
            </template>

            <!-- 九辊矫直机：5上4下 -->
            <template v-else-if="eq.type==='rolls9'">
              <rect x="-44" y="-26" width="88" height="52" fill="#e9eef4" stroke="#aab4c2" stroke-width="1.5" rx="3"/>
              <g v-for="i in 5" :key="'t'+i">
                <circle :cx="-36 + (i-1)*18" cy="-10" r="6" fill="#dde4ec" stroke="#8b97a7" stroke-width="1"/>
              </g>
              <g v-for="i in 4" :key="'b'+i">
                <circle :cx="-27 + (i-1)*18" cy="10" r="6" fill="#dde4ec" stroke="#8b97a7" stroke-width="1"/>
              </g>
              <text y="44" text-anchor="middle" font-size="9" fill="#5b6470">STR-9</text>
            </template>

            <!-- 切头/切尾剪 -->
            <template v-else-if="eq.type==='shear'">
              <rect x="-30" y="-26" width="60" height="52" fill="#e9eef4" stroke="#aab4c2" stroke-width="1.5" rx="2"/>
              <line x1="-18" y1="-16" x2="18" y2="16" stroke="#da3633" stroke-width="2.2"/>
              <line x1="-18" y1="16" x2="18" y2="-16" stroke="#da3633" stroke-width="2.2"/>
              <circle cx="-18" cy="-16" r="3" fill="#da3633"/>
              <circle cx="18" cy="-16" r="3" fill="#da3633"/>
              <circle cx="0" cy="0" r="3" fill="#c03639"/>
              <text y="44" text-anchor="middle" font-size="9" fill="#5b6470">{{ eq.code }}</text>
            </template>

            <!-- 酸洗槽 -->
            <template v-else-if="eq.type==='acid'">
              <path d="M -32 -24 L 32 -24 L 28 26 L -28 26 Z" fill="#f0e3cf" stroke="#cf9a5a" stroke-width="2"/>
              <path d="M -30 -10 L 30 -10 L 27 24 L -27 24 Z" fill="#ffaa44" opacity="0.55">
                <animate attributeName="opacity" values="0.5;0.7;0.5" dur="2.5s" repeatCount="indefinite"/>
              </path>
              <path d="M -22 -10 q 4 -6 8 0 t 8 0 t 8 0 t 8 0" stroke="#ffd28a" stroke-width="1" fill="none" opacity="0.7"/>
              <!-- 蒸汽 -->
              <g opacity="0.6">
                <circle cx="-12" cy="-30" r="3" fill="#b8c0cc">
                  <animate attributeName="cy" values="-30;-46;-30" dur="2s" repeatCount="indefinite"/>
                  <animate attributeName="opacity" values="0.6;0;0.6" dur="2s" repeatCount="indefinite"/>
                </circle>
                <circle cx="6" cy="-32" r="2.5" fill="#b8c0cc">
                  <animate attributeName="cy" values="-32;-50;-32" dur="2.3s" repeatCount="indefinite"/>
                  <animate attributeName="opacity" values="0.5;0;0.5" dur="2.3s" repeatCount="indefinite"/>
                </circle>
              </g>
              <text x="0" y="44" text-anchor="middle" font-size="9" fill="#c97e2a">{{ acid[eq.idx].temp.toFixed(0) }}°C · {{ acid[eq.idx].conc.toFixed(0) }}g/L</text>
            </template>

            <!-- 漂洗段 -->
            <template v-else-if="eq.type==='rinse'">
              <path d="M -34 -24 L 34 -24 L 30 26 L -30 26 Z" fill="#e2eef4" stroke="#5a9ec0" stroke-width="2"/>
              <path d="M -32 -8 L 32 -8 L 29 24 L -29 24 Z" fill="#3aa0c8" opacity="0.55">
                <animate attributeName="opacity" values="0.5;0.7;0.5" dur="2.5s" repeatCount="indefinite"/>
              </path>
              <path d="M -22 -8 q 4 -5 8 0 t 8 0 t 8 0 t 8 0" stroke="#bce4f0" stroke-width="1" fill="none" opacity="0.7"/>
              <text y="44" text-anchor="middle" font-size="9" fill="#3aa0c8">5级逆流</text>
            </template>

            <!-- 热风烘干段 -->
            <template v-else-if="eq.type==='dryer'">
              <rect x="-36" y="-26" width="72" height="52" fill="#f4ead2" stroke="#a08030" stroke-width="2" rx="3"/>
              <g stroke="#e89426" stroke-width="1.6" fill="none">
                <path d="M -26 -12 q 4 -6 8 0 t 8 0 t 8 0 t 8 0 t 8 0">
                  <animate attributeName="opacity" values="0.4;1;0.4" dur="1.4s" repeatCount="indefinite"/>
                </path>
                <path d="M -26 4 q 4 -6 8 0 t 8 0 t 8 0 t 8 0 t 8 0">
                  <animate attributeName="opacity" values="0.7;0.3;0.7" dur="1.4s" repeatCount="indefinite"/>
                </path>
              </g>
              <text y="44" text-anchor="middle" font-size="9" fill="#e89426">{{ dryer.t1.toFixed(0) }}/{{ dryer.t2.toFixed(0) }}/{{ dryer.t3.toFixed(0) }}°C</text>
            </template>

            <!-- 夹送辊 / 挤干辊 (两辊上下) -->
            <template v-else-if="eq.type==='pinch'">
              <rect x="-30" y="-26" width="60" height="52" fill="#e9eef4" stroke="#aab4c2" stroke-width="1.5" rx="2"/>
              <ellipse cx="0" cy="-12" rx="22" ry="6" fill="#dde4ec" stroke="#8b97a7" stroke-width="1.2"/>
              <ellipse cx="0" cy="12" rx="22" ry="6" fill="#dde4ec" stroke="#8b97a7" stroke-width="1.2"/>
              <line x1="-22" y1="-12" x2="-22" y2="12" stroke="#9aa4b0" stroke-width="1"/>
              <line x1="22" y1="-12" x2="22" y2="12" stroke="#9aa4b0" stroke-width="1"/>
              <text y="44" text-anchor="middle" font-size="9" fill="#5b6470">{{ eq.code }}</text>
            </template>

            <!-- 活套坑 -->
            <template v-else-if="eq.type==='loop'">
              <rect x="-40" y="-26" width="80" height="58" fill="#e9eef4" stroke="#aab4c2" stroke-width="2" rx="3"/>
              <path d="M -32 -16 Q -20 32 -8 -16 Q 4 32 16 -16 Q 28 32 36 -16" stroke="#c03639" stroke-width="1.8" fill="none">
                <animate attributeName="opacity" values="0.6;1;0.6" dur="1.6s" repeatCount="indefinite"/>
              </path>
              <text y="48" text-anchor="middle" font-size="9" fill="#5b6470">LOOP</text>
            </template>

            <!-- 三辊张力装置 -->
            <template v-else-if="eq.type==='tension3'">
              <rect x="-32" y="-26" width="64" height="52" fill="#e9eef4" stroke="#aab4c2" stroke-width="1.5" rx="3"/>
              <circle cx="-16" cy="-8" r="8" fill="#dde4ec" stroke="#8b97a7" stroke-width="1.2"/>
              <circle cx="16" cy="-8" r="8" fill="#dde4ec" stroke="#8b97a7" stroke-width="1.2"/>
              <circle cx="0" cy="12" r="9" fill="#dde4ec" stroke="#8b97a7" stroke-width="1.2"/>
              <text y="44" text-anchor="middle" font-size="9" fill="#5b6470">TEN-3</text>
            </template>

            <!-- 平整机 -->
            <template v-else-if="eq.type==='leveler'">
              <rect x="-34" y="-26" width="68" height="52" fill="#e9eef4" stroke="#aab4c2" stroke-width="2" rx="2"/>
              <circle cx="0" cy="-14" r="11" fill="#aab4c2" stroke="#8b97a7" stroke-width="1.4"/>
              <circle cx="0" cy="14" r="11" fill="#aab4c2" stroke="#8b97a7" stroke-width="1.4"/>
              <line x1="-28" y1="0" x2="-12" y2="0" stroke="#8b97a7" stroke-width="1"/>
              <line x1="12" y1="0" x2="28" y2="0" stroke="#8b97a7" stroke-width="1"/>
              <text y="44" text-anchor="middle" font-size="9" fill="#5b6470">SPM</text>
            </template>

            <!-- 静电涂油机 -->
            <template v-else-if="eq.type==='oiler'">
              <rect x="-26" y="-26" width="52" height="52" fill="#e9eef4" stroke="#aab4c2" stroke-width="1.5" rx="2"/>
              <path d="M 0 -14 L -10 4 L 10 4 Z" fill="#aab4c2" stroke="#8b97a7" stroke-width="1"/>
              <g fill="#5a9bd4">
                <circle cx="-6" cy="10" r="1.6">
                  <animate attributeName="cy" values="6;22;6" dur="1.2s" repeatCount="indefinite"/>
                </circle>
                <circle cx="0" cy="14" r="1.4">
                  <animate attributeName="cy" values="8;22;8" dur="1.4s" repeatCount="indefinite"/>
                </circle>
                <circle cx="6" cy="10" r="1.6">
                  <animate attributeName="cy" values="6;22;6" dur="1.3s" repeatCount="indefinite"/>
                </circle>
              </g>
              <text y="44" text-anchor="middle" font-size="9" fill="#5b6470">EOL</text>
            </template>

            <!-- 卷取机 -->
            <template v-else-if="eq.type==='recoiler'">
              <circle r="38" fill="#e9eef4" stroke="#aab4c2" stroke-width="2"/>
              <circle r="22" fill="#f2f5f9" stroke="#9aa4b0" stroke-width="1.5"/>
              <circle r="8" fill="#cdd6e0" stroke="#9aa4b0" stroke-width="1"/>
              <path d="M-38 0 a38 38 0 0 1 76 0" stroke="#c03639" stroke-width="1" fill="none" opacity="0.5">
                <animateTransform attributeName="transform" type="rotate" from="360" to="0" dur="3s" repeatCount="indefinite"/>
              </path>
              <text y="58" text-anchor="middle" font-size="10" fill="#5b6470">REC-1</text>
            </template>

            <!-- 当前设备高亮光环 -->
            <circle v-if="eq.k === currentEquipment.k" r="48" fill="none" stroke="#c03639" stroke-width="2" stroke-dasharray="4 4" opacity="0.7">
              <animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="6s" repeatCount="indefinite"/>
            </circle>
          </g>

          <!-- 焊缝标记 -->
          <g :transform="`translate(${weldX}, 185)`">
            <circle r="11" fill="#ff8c1a" opacity="0.35">
              <animate attributeName="r" values="9;22;9" dur="1.0s" repeatCount="indefinite"/>
              <animate attributeName="opacity" values="0.7;0.05;0.7" dur="1.0s" repeatCount="indefinite"/>
            </circle>
            <circle r="6" fill="#ff8c1a">
              <animate attributeName="fill" values="#ff8c1a;#ff7700;#ff8c1a" dur="0.6s" repeatCount="indefinite"/>
            </circle>
            <text y="-18" text-anchor="middle" font-size="11" fill="#c03639" font-weight="bold">WELD</text>
          </g>

          <!-- 图例 -->
          <g transform="translate(20,290)" font-size="10" fill="#606266">
            <circle cx="6" cy="-3" r="5" fill="#ff8c1a"/>
            <text x="18" y="0">焊缝位置 {{ (weld.position * 100).toFixed(1) }}%</text>
            <rect x="160" y="-7" width="12" height="8" fill="#ffaa44" opacity="0.5"/>
            <text x="178" y="0">酸洗液</text>
            <rect x="230" y="-7" width="12" height="8" fill="#3aa0c8" opacity="0.5"/>
            <text x="248" y="0">漂洗水</text>
            <circle cx="310" cy="-3" r="5" fill="none" stroke="#c03639" stroke-width="1.5" stroke-dasharray="2 2"/>
            <text x="322" y="0">当前设备</text>
            <text x="420" y="0" fill="#909399">— — 带钢运行方向 →</text>
          </g>
        </svg>
      </div>
    </div>

    <!-- 下半: 左 跟踪表 | 右 实时数据 -->
    <div class="split-row">
      <div class="card split-left">
        <div class="card-header">物料跟踪表 <span class="hd-cnt">共 {{ equipments.length }} 台设备</span></div>
        <div class="card-body" style="padding:0;">
          <div class="track-scroll">
            <table class="data-table compact tracking-table">
              <thead>
                <tr>
                  <th style="width:32px;">#</th>
                  <th style="width:72px;">段</th>
                  <th>设备</th>
                  <th style="width:64px;">状态</th>
                  <th>当前钢卷</th>
                  <th style="width:80px;">辊缝 (mm)</th>
                  <th style="width:78px;">速度</th>
                  <th style="width:78px;">张力/温度</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(eq, i) in equipments" :key="eq.k"
                    :class="{ 'row-active': eq.k === currentEquipment.k, 'row-passed': i < currentEquipment.idx, 'row-pending': i > currentEquipment.idx }">
                  <td class="td-num">{{ i + 1 }}</td>
                  <td><span class="sec-tag" :style="{ color: sectionColor(eq.section), borderColor: sectionColor(eq.section) }">{{ eq.section }}</span></td>
                  <td>{{ eq.label }}</td>
                  <td>
                    <span v-if="eq.k === currentEquipment.k" class="badge badge-yellow">加工中</span>
                    <span v-else-if="i < currentEquipment.idx" class="badge badge-blue">已过</span>
                    <span v-else class="badge badge-gray">待入</span>
                  </td>
                  <td class="td-num">{{ rowOf(eq, i).coil }}</td>
                  <td class="td-num">{{ rowOf(eq, i).gap }}</td>
                  <td class="td-num">{{ rowOf(eq, i).speed }}</td>
                  <td class="td-num">{{ rowOf(eq, i).aux }}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>

      <div class="card split-right">
        <div class="card-header">实时数据 <span class="hd-cnt">{{ rtItems.length }} 项</span></div>
        <div class="card-body sec-body">
          <div class="dg">
            <div v-for="it in rtItems" :key="it.k" class="dg-item">
              <span class="lbl">{{ it.label }}</span>
              <span class="vbox">{{ it.val }}</span>
              <span v-if="it.unit" class="unit">{{ it.unit }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { getPlans, startProducing, saveRuntime } from '@/api'
function rnd(base, amp) { return base + (Math.random() - 0.5) * amp }
function fix(v, n = 1) { return Number(v).toFixed(n) }

const EQUIPMENTS = [
  { k:'uncoiler',     label:'开卷机',       type:'coiler',   code:'DC-1',  section:'入口段' },
  { k:'straightener', label:'九辊矫直机',   type:'rolls9',   code:'STR-9', section:'入口段' },
  { k:'crop_shear',   label:'切头剪',       type:'shear',    code:'CRP',   section:'入口段' },
  { k:'acid1',        label:'酸洗槽1',      type:'acid',     idx:0,        section:'酸洗段' },
  { k:'acid2',        label:'酸洗槽2',      type:'acid',     idx:1,        section:'酸洗段' },
  { k:'acid3',        label:'酸洗槽3',      type:'acid',     idx:2,        section:'酸洗段' },
  { k:'acid4',        label:'酸洗槽4',      type:'acid',     idx:3,        section:'酸洗段' },
  { k:'acid5',        label:'酸洗槽5',      type:'acid',     idx:4,        section:'酸洗段' },
  { k:'rinse',        label:'漂洗段',       type:'rinse',                  section:'清洗段' },
  { k:'dryer',        label:'热风烘干段',   type:'dryer',                  section:'烘干段' },
  { k:'br1',          label:'1号夹送辊',    type:'pinch',    code:'BR-1',  section:'出口段' },
  { k:'loop',         label:'活套坑',       type:'loop',                   section:'出口段' },
  { k:'br2',          label:'2号夹送辊',    type:'pinch',    code:'BR-2',  section:'出口段' },
  { k:'br3',          label:'3号夹送辊',    type:'pinch',    code:'BR-3',  section:'出口段' },
  { k:'tension',      label:'三辊张力装置', type:'tension3', code:'TEN-3', section:'出口段' },
  { k:'leveler',      label:'平整机',       type:'leveler',  code:'SPM',   section:'出口段' },
  { k:'tail_shear',   label:'切尾剪',       type:'shear',    code:'TLS',   section:'出口段' },
  { k:'oiler',        label:'静电涂油机',   type:'oiler',    code:'EOL',   section:'出口段' },
  { k:'recoiler',     label:'卷取机',       type:'recoiler', code:'REC-1', section:'出口段' },
]

const SECTION_COLORS = {
  '入口段': '#4a7fbe',
  '酸洗段': '#d98a2a',
  '清洗段': '#2f93b8',
  '烘干段': '#d96a2a',
  '出口段': '#5ba84e',
}

// 默认辊缝值 (mm)
const DEFAULT_GAP = {
  straightener: 4.20,
  br1: 3.80, br2: 3.80, br3: 3.80,
  tension: 4.00,
  leveler: 3.50,
}

export default {
  name: 'Material',
  data() {
    return {
      l1Online: false,
      now: Date.now(),
      prodBase: null,   // { id, len, at, speed } 用于客户端平滑外推生产进度
      current: { coil_no: '26053552', speed: 95.0 },
      prev_coil_no: '26053551',
      weld: { position: 0.08 },

      uncoiler:     { tension: 18.5, speed: 92.0, current: 240, torque: 1.8, diameter: 1450 },
      straightener: { speed: 92.0, current: 165, torque: 1.5, gap: 4.20 },
      br1:          { speed: 92.0, current: 145, torque: 1.3, gap: 3.80 },
      br2:          { speed: 92.0, current: 142, torque: 1.3, gap: 3.80 },
      br3:          { speed: 92.0, current: 140, torque: 1.3, gap: 3.80 },
      tension_vfd:  [
        { speed: 92.0, current: 158, torque: 1.6 },
        { speed: 92.0, current: 156, torque: 1.5 },
        { speed: 92.0, current: 154, torque: 1.5 },
      ],
      tension_gap:  4.00,
      leveler:      { gap: 3.50, force: 280, elongation: 0.45 },
      recoiler:     { tension: 22.4, diameter: 980, speed: 95 },

      acid: [
        { temp: 82, conc: 198, level: 0.97, cond: 215, tank_conc: 195, tank_cond: 210 },
        { temp: 81, conc: 188, level: 1.03, cond: 205, tank_conc: 185, tank_cond: 200 },
        { temp: 81, conc: 175, level: 0.94, cond: 192, tank_conc: 172, tank_cond: 188 },
        { temp: 80, conc: 162, level: 0.74, cond: 178, tank_conc: 158, tank_cond: 175 },
        { temp: 74, conc: 148, level: 0.71, cond: 162, tank_conc: 145, tank_cond: 160 },
      ],
      acid_mist:    { ph: 6.8, vfd_speed: 48.5, vfd_current: 32.6 },
      acid_cond:    { level: 1.85, temp: 42.5, cond: 12.5 },

      rinse_tank_temp: [65, 62, 58, 54, 48],
      rinse: [
        { conc: 0.5, cond: 18.5, level: 0.45, tank_conc: 0.4, tank_cond: 17.5 },
        { conc: 0.3, cond: 12.2, level: 0.54, tank_conc: 0.3, tank_cond: 11.8 },
        { conc: 0.2, cond:  6.8, level: 0.18, tank_conc: 0.2, tank_cond:  6.5 },
        { conc: 0.1, cond:  2.5, level: 0.77, tank_conc: 0.1, tank_cond:  2.4 },
        { conc: 0.0, cond:  0.8, level: 0.81, tank_conc: 0.0, tank_cond:  0.7 },
      ],
      rinse_mist:   { ph: 7.0, vfd_speed: 45.2, vfd_current: 28.4 },
      rinse_cond:   { level: 2.10, temp: 38.6, cond: 4.5 },

      dryer: { t1: 145, t2: 168, t3: 152 },

      _timer: null,
      _plansTimer: null,
      plans: [],
      moving: false,
    }
  },
  computed: {
    onlinePlans() { return this.plans.filter(p => p.status === 'online' && p.on_saddle !== 1) },
    producingPlan() { return this.plans.find(p => p.status === 'producing') || null },
    prodLength() {
      const p = this.producingPlan
      if (!p) return 0
      const b = this.prodBase
      if (b && b.id === p.id) {
        return Math.min(2000, b.len + b.speed / 60 * Math.max(0, (this.now - b.at) / 1000))
      }
      return p.run_length_m || 0
    },
    prodPct() { return this.producingPlan ? Math.max(0, Math.min(100, this.prodLength / 2000 * 100)) : 0 },
    equipments() {
      const n = EQUIPMENTS.length
      const xStart = 50, xEnd = 1850
      const step = (xEnd - xStart) / (n - 1)
      return EQUIPMENTS.map((e, i) => ({ ...e, x: xStart + step * i }))
    },
    sections() {
      const eqs = this.equipments
      if (!eqs.length) return []
      const groups = []
      let cur = null
      eqs.forEach((e, i) => {
        if (!cur || cur.name !== e.section) {
          if (cur) groups.push(cur)
          cur = { name: e.section, color: SECTION_COLORS[e.section] || '#9aa8b6',
                  x0: e.x, x1: e.x }
        } else { cur.x1 = e.x }
      })
      if (cur) groups.push(cur)
      const half = eqs.length > 1 ? (eqs[1].x - eqs[0].x) / 2 : 30
      return groups.map(g => ({
        ...g,
        bandX: g.x0 - half + 4,
        bandW: (g.x1 - g.x0) + half * 2 - 8,
        labelX: (g.x0 + g.x1) / 2,
      }))
    },
    weldX() {
      const p = Math.max(0, Math.min(1, this.weld.position))
      return 50 + (1850 - 50) * p
    },
    currentEquipment() {
      const n = this.equipments.length
      const idx = Math.max(0, Math.min(n - 1, Math.floor(this.weld.position * n)))
      return { ...this.equipments[idx], idx }
    },
    rtItems() {
      const items = []
      const push = (k, label, val, unit) => items.push({ k, label, val, unit })

      push('u_t',  '开卷机 开卷张力',    fix(this.uncoiler.tension, 1), 'kN')
      push('u_s',  '开卷机 速度反馈',    fix(this.uncoiler.speed, 1),   'm/min')
      push('u_c',  '开卷机 电流反馈',    fix(this.uncoiler.current, 0), 'A')
      push('u_q',  '开卷机 扭矩反馈',    fix(this.uncoiler.torque, 2),  'kN·m')

      push('st_s', '九辊矫直机 速度反馈',fix(this.straightener.speed, 1),   'm/min')
      push('st_c', '九辊矫直机 电流反馈',fix(this.straightener.current, 0), 'A')
      push('st_q', '九辊矫直机 扭矩反馈',fix(this.straightener.torque, 2),  'kN·m')

      for (const [k, name] of [['br1','1号夹送辊'], ['br2','2号夹送辊'], ['br3','3号夹送辊']]) {
        push(k+'_s', `${name} 速度反馈`, fix(this[k].speed, 1),   'm/min')
        push(k+'_c', `${name} 电流反馈`, fix(this[k].current, 0), 'A')
        push(k+'_q', `${name} 扭矩反馈`, fix(this[k].torque, 2),  'kN·m')
      }

      this.tension_vfd.forEach((v, i) => {
        push(`tv${i}s`, `三辊张力 变频器${i+1} 速度反馈`, fix(v.speed, 1),   'm/min')
        push(`tv${i}c`, `三辊张力 变频器${i+1} 电流反馈`, fix(v.current, 0), 'A')
        push(`tv${i}q`, `三辊张力 变频器${i+1} 扭矩反馈`, fix(v.torque, 2),  'kN·m')
      })

      push('r_t', '收卷机 收卷张力', fix(this.recoiler.tension, 1), 'kN')

      const avg = (arr, k) => arr.reduce((s, x) => s + x[k], 0) / arr.length
      push('at', '酸洗 槽温度均值',  fix(avg(this.acid, 'temp'), 1),       '°C')
      push('al', '酸洗 罐液位均值',  fix(avg(this.acid, 'level'), 2),      'm')
      push('ac', '酸洗 槽浓度均值',  fix(avg(this.acid, 'conc'), 1),       'g/L')
      push('ae', '酸洗 槽电导率均值',fix(avg(this.acid, 'cond'), 1),       'mS/cm')
      push('atc','酸洗 罐浓度均值',  fix(avg(this.acid, 'tank_conc'), 1),  'g/L')
      push('ate','酸洗 罐电导率均值',fix(avg(this.acid, 'tank_cond'), 1),  'mS/cm')
      push('amp', '酸雾塔 PH',           fix(this.acid_mist.ph, 2),        '')
      push('ams', '酸雾塔 变频器频率',   fix(this.acid_mist.vfd_speed, 1), 'Hz')
      push('amc', '酸雾塔 变频器电流',   fix(this.acid_mist.vfd_current,1),'A')
      push('acl', '酸侧冷凝水罐 液位',   fix(this.acid_cond.level, 2),     'm')
      push('act', '酸侧冷凝水罐 温度',   fix(this.acid_cond.temp, 1),      '°C')
      push('acc', '酸侧冷凝水罐 电导率', fix(this.acid_cond.cond, 1),      'μS/cm')

      const rtAvg = this.rinse_tank_temp.reduce((s, x) => s + x, 0) / this.rinse_tank_temp.length
      push('rt', '漂洗 槽温度均值',  fix(rtAvg, 1),                         '°C')
      push('rl', '漂洗 罐液位均值',  fix(avg(this.rinse, 'level'), 2),      'm')
      push('rc', '漂洗 槽浓度均值',  fix(avg(this.rinse, 'conc'), 2),       'g/L')
      push('re', '漂洗 槽电导率均值',fix(avg(this.rinse, 'cond'), 2),       'μS/cm')
      push('rtc','漂洗 罐浓度均值',  fix(avg(this.rinse, 'tank_conc'), 2),  'g/L')
      push('rte','漂洗 罐电导率均值',fix(avg(this.rinse, 'tank_cond'), 2),  'μS/cm')
      push('rmp', '漂洗酸雾塔 PH',         fix(this.rinse_mist.ph, 2),        '')
      push('rms', '漂洗酸雾塔 变频器频率', fix(this.rinse_mist.vfd_speed, 1), 'Hz')
      push('rmc', '漂洗酸雾塔 变频器电流', fix(this.rinse_mist.vfd_current,1),'A')
      push('rcl', '漂洗冷凝水罐 液位',     fix(this.rinse_cond.level, 2),     'm')
      push('rct', '漂洗冷凝水罐 温度',     fix(this.rinse_cond.temp, 1),      '°C')
      push('rcc', '漂洗冷凝水罐 电导率',   fix(this.rinse_cond.cond, 2),      'μS/cm')

      push('lvg', '平整机 辊缝',         fix(this.leveler.gap, 2),       'mm')
      push('lvf', '平整机 轧制力',       fix(this.leveler.force, 0),     'kN')
      push('lve', '平整机 延伸率',       fix(this.leveler.elongation,2), '%')

      push('dt1','烘干1段温度', fix(this.dryer.t1, 0), '°C')
      push('dt2','烘干2段温度', fix(this.dryer.t2, 0), '°C')
      push('dt3','烘干3段温度', fix(this.dryer.t3, 0), '°C')

      return items
    },
  },
  methods: {
    fmt(v, n = 2) { return v != null && v !== '' ? Number(v).toFixed(n) : '—' },
    sectionColor(s) { return SECTION_COLORS[s] || '#9aa8b6' },
    fmtTime(t) { return t ? t.slice(0, 16).replace('T', ' ') : '—' },
    async loadPlans() {
      try {
        const res = await getPlans({ page: 1, page_size: 50 })
        this.plans = res.data.items || []
        // 把生产中的卷号同步到产线显示 + 记录进度外推基准
        const pp = this.producingPlan
        if (pp && pp.cold_coil_no) this.current.coil_no = pp.cold_coil_no
        this.prodBase = pp ? { id: pp.id, len: pp.run_length_m || 0, at: Date.now(), speed: pp.run_speed || 0 } : null
        // 持久化实时数据快照到在产计划
        if (pp) this.persistRuntime(pp)
      } catch (e) { /* ignore */ }
    },
    async persistRuntime(pp) {
      try {
        const snapshot = {
          time: new Date().toISOString(),
          coil_no: pp.cold_coil_no || pp.plan_no,
          line_speed: Number(this.current.speed.toFixed(1)),
          weld_position: Number((this.weld.position * 100).toFixed(1)),
          items: this.rtItems.map(it => ({ label: it.label, value: it.val, unit: it.unit })),
        }
        await saveRuntime(pp.id, snapshot)
      } catch (e) { /* ignore */ }
    },
    async movePlan(p) {
      if (this.moving) return
      this.moving = true
      try {
        await startProducing(p.id)
        this.$message && this.$message.success(`已开始生产 ${p.cold_coil_no || p.plan_no}`)
        await this.loadPlans()
      } catch (e) {
        this.$message && this.$message.error('移动失败')
      } finally {
        this.moving = false
      }
    },
    // 一行的展示数据：根据设备状态决定卷号/速度/辊缝/辅助列
    rowOf(eq, i) {
      const curIdx = this.currentEquipment.idx
      const isHere = i === curIdx
      const passed = i < curIdx
      const cur = this.current.coil_no || '—'
      const prev = this.prev_coil_no || '—'

      let coil = '—'
      if (isHere) coil = cur
      else if (passed) coil = cur          // 已被本卷穿过
      else coil = prev                     // 还在上一卷尾部

      const speed = (isHere || passed) ? this.current.speed.toFixed(1) : prev !== '—' ? '0.0' : '—'

      let gap = '—'
      let aux = '—'
      switch (eq.type) {
        case 'coiler':
          gap = '—'
          aux = this.uncoiler.tension.toFixed(1) + ' kN'
          break
        case 'recoiler':
          gap = '—'
          aux = this.recoiler.tension.toFixed(1) + ' kN'
          break
        case 'rolls9':
          gap = this.straightener.gap.toFixed(2)
          aux = this.straightener.torque.toFixed(2) + ' kN·m'
          break
        case 'pinch':
          gap = this[eq.k].gap.toFixed(2)
          aux = this[eq.k].torque.toFixed(2) + ' kN·m'
          break
        case 'tension3':
          gap = this.tension_gap.toFixed(2)
          aux = this.tension_vfd[0].torque.toFixed(2) + ' kN·m'
          break
        case 'leveler':
          gap = this.leveler.gap.toFixed(2)
          aux = this.leveler.force.toFixed(0) + ' kN'
          break
        case 'acid':
          gap = '—'
          aux = this.acid[eq.idx].temp.toFixed(1) + ' °C'
          break
        case 'rinse':
          gap = '—'
          aux = this.rinse_tank_temp[0].toFixed(1) + ' °C'
          break
        case 'dryer':
          gap = '—'
          aux = this.dryer.t2.toFixed(0) + ' °C'
          break
        case 'shear':
        case 'oiler':
        case 'loop':
          gap = '—'
          aux = '—'
          break
      }
      return { coil, gap, speed, aux }
    },
    tick() {
      this.now = Date.now()
      // 焊缝(带头)位置与线速度跟随实际在产卷进度（带头 = run_length / 2000）
      const pp = this.producingPlan
      if (pp) {
        this.weld.position = Math.max(0, Math.min(1, this.prodLength / 2000))
        this.current.speed = pp.run_speed || 0
      } else {
        this.weld.position = 0
        this.current.speed = 0
      }

      const wig = (o, key, amp) => { o[key] = rnd(o[key], amp) }
      wig(this.uncoiler, 'tension', 0.4); wig(this.uncoiler, 'speed', 2)
      wig(this.uncoiler, 'current', 6);   wig(this.uncoiler, 'torque', 0.1)
      wig(this.straightener, 'speed', 2); wig(this.straightener, 'current', 5)
      wig(this.straightener, 'torque', 0.1); wig(this.straightener, 'gap', 0.01)
      ;['br1','br2','br3'].forEach(k => {
        wig(this[k], 'speed', 2); wig(this[k], 'current', 5)
        wig(this[k], 'torque', 0.1); wig(this[k], 'gap', 0.01)
      })
      this.tension_vfd.forEach(v => { wig(v, 'speed', 2); wig(v, 'current', 5); wig(v, 'torque', 0.1) })
      this.tension_gap = rnd(this.tension_gap, 0.01)
      wig(this.leveler, 'gap', 0.005); wig(this.leveler, 'force', 8); wig(this.leveler, 'elongation', 0.02)
      wig(this.recoiler, 'tension', 0.4)
      this.acid.forEach(a => {
        wig(a, 'temp', 0.3); wig(a, 'conc', 1); wig(a, 'cond', 0.8); wig(a, 'level', 0.02)
        wig(a, 'tank_conc', 1); wig(a, 'tank_cond', 0.8)
      })
      wig(this.acid_mist, 'ph', 0.05); wig(this.acid_mist, 'vfd_speed', 0.6); wig(this.acid_mist, 'vfd_current', 0.4)
      wig(this.acid_cond, 'level', 0.02); wig(this.acid_cond, 'temp', 0.3); wig(this.acid_cond, 'cond', 0.2)
      this.rinse.forEach(r => {
        wig(r, 'conc', 0.05); wig(r, 'cond', 0.3); wig(r, 'level', 0.02)
        wig(r, 'tank_conc', 0.05); wig(r, 'tank_cond', 0.3)
      })
      for (let i = 0; i < this.rinse_tank_temp.length; i++) this.rinse_tank_temp[i] = rnd(this.rinse_tank_temp[i], 0.4)
      wig(this.rinse_mist, 'ph', 0.05); wig(this.rinse_mist, 'vfd_speed', 0.6); wig(this.rinse_mist, 'vfd_current', 0.4)
      wig(this.rinse_cond, 'level', 0.02); wig(this.rinse_cond, 'temp', 0.3); wig(this.rinse_cond, 'cond', 0.1)
      wig(this.dryer, 't1', 2); wig(this.dryer, 't2', 2); wig(this.dryer, 't3', 2)
    },
  },
  created() {
    this.tick()
    this._timer = setInterval(this.tick, 2000)
    this.loadPlans()
    this._plansTimer = setInterval(this.loadPlans, 10000)
  },
  beforeDestroy() {
    if (this._timer) clearInterval(this._timer)
    if (this._plansTimer) clearInterval(this._plansTimer)
  },
}
</script>

<style lang="scss" scoped>
@import '@/assets/styles/variables';

.mat-page { display: flex; flex-direction: column; gap: 10px; }

.status-bar {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 8px 16px;
  background: $bg-card; border: 1px solid $border; border-radius: 6px;
}
.status-item { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.status-item .kv-label { color: $text-muted; font-size: 11px; }
.status-item .kv-value { color: $sms-highlight; font-weight: 600; }
.status-item .kv-unit { color: $text-muted; font-size: 10px; margin-left: 2px; }

.line-wrap { padding: 0; }
.line-body { padding: 6px 10px 10px; background: #f2f5f9; }
.line-svg { width: 100%; height: 305px; display: block; }

.split-row { display: grid; grid-template-columns: 1fr 3fr; gap: 10px; align-items: stretch; }
.split-left, .split-right { display: flex; flex-direction: column; min-height: 540px; }
.split-right .card-body { flex: 1; overflow-y: auto; }

.track-scroll { max-height: 640px; overflow: auto; }

.producing-row { display: flex; align-items: center; gap: 10px; padding: 6px 4px 10px; font-size: 12px; border-bottom: 1px dashed $border; margin-bottom: 6px;
  .kv-label { color: $text-muted; font-size: 11px; margin-left: 6px; }
  .kv-value { color: $sms-highlight; font-weight: 600; }
}
.btn-sm { padding: 2px 10px; font-size: 11px; }

.hd-cnt { font-size: 11px; color: $text-muted; margin-left: 8px; font-weight: 400; }

.sec-body { padding: 10px 14px; background: $bg-card; }

.dg { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 4px 18px; }
.dg-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: $text-primary; padding: 2px 0; }
.dg-item .lbl { color: $text-muted; flex: 1; min-width: 140px; }
.dg-item .vbox {
  background: $bg-panel; border: 1px solid $border; padding: 1px 8px;
  min-width: 70px; text-align: right; font-family: monospace;
  color: $sms-teal; border-radius: 2px;
}
.dg-item .unit { color: $text-muted; font-size: 11px; min-width: 44px; }

.data-table.compact th, .data-table.compact td { padding: 5px 8px; font-size: 11.5px; }
.tracking-table tr.row-active { background: rgba($sms-teal, 0.08); }
.tracking-table tr.row-active td { color: $sms-teal !important; font-weight: 600; }
.tracking-table tr.row-passed td { color: $text-muted; }
.tracking-table tr.row-pending td { color: $text-muted; }
.sec-tag { display: inline-block; font-size: 10.5px; padding: 1px 6px;
  border: 1px solid; border-radius: 3px; background: rgba(0,0,0,.02);
  font-weight: 600; letter-spacing: 0.5px; white-space: nowrap; }
.tracking-table th, .tracking-table td { white-space: nowrap; }
</style>
