<template>
  <div class="coil-bind-page">
    <!-- 筛选 + 操作一体栏 -->
    <div class="filter-bar">
      <el-form :inline="true" :model="query" size="small" class="filter-form">
        <el-form-item label="出口卷号">
          <el-input
            v-model="query.coilId"
            placeholder="模糊搜索"
            clearable
            style="width:150px"
            @keyup.enter.native="handleSearch"
          />
        </el-form-item>
        <el-form-item label="入口卷号">
          <el-input
            v-model="query.enCoilId"
            placeholder="模糊搜索"
            clearable
            style="width:150px"
            @keyup.enter.native="handleSearch"
          />
        </el-form-item>
        <el-form-item label="异常">
          <el-select v-model="query.hasAnomaly" placeholder="全部" clearable style="width:88px">
            <el-option label="有异常" :value="1" />
            <el-option label="正常"   :value="0" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" :loading="loading" @click="handleSearch">查询</el-button>
          <el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>

      <!-- 右侧：始终可见的操作区 -->
      <div class="toolbar-action">
        <transition name="sel-fade">
          <span v-if="selected.length" class="sel-badge">
            已选 <b>{{ selected.length }}</b> 条
            <el-button type="text" size="mini" style="color:#909399;padding:0 4px" @click="$refs.recordTable.clearSelection()">清除</el-button>
          </span>
        </transition>
        <el-button
          type="primary"
          size="small"
          icon="el-icon-connection"
          :disabled="!selected.length"
          @click="openBindDialog"
        >重新绑定规程方案</el-button>
      </div>
    </div>

    <!-- 表格 -->
    <div class="table-wrap" v-loading="loading">
      <el-table
        ref="recordTable"
        :data="rows"
        size="small"
        border
        :height="tableHeight"
        @selection-change="onSelectionChange"
      >
        <el-table-column type="selection" width="44" fixed />
        <el-table-column type="index" width="44" label="序" align="center" fixed />
        <el-table-column prop="coilId"   label="出口卷号" width="160" fixed show-overflow-tooltip />
        <el-table-column prop="enCoilId" label="入口卷号" width="160" show-overflow-tooltip>
          <template slot-scope="{ row }">{{ row.enCoilId || '—' }}</template>
        </el-table-column>
        <el-table-column label="当前规程方案" min-width="220" show-overflow-tooltip>
          <template slot-scope="{ row }">
            <template v-if="row.specName || row.specCode">
              <span class="tag-spec">{{ row.specCode || '—' }}</span>
              <span class="tag-spec-name">{{ row.specName }}</span>
            </template>
            <span v-else class="dim">—</span>
          </template>
        </el-table-column>
        <el-table-column label="版本" width="110">
          <template slot-scope="{ row }">
            <template v-if="row.versionCode">
              <span class="tag-version">{{ row.versionCode }}</span>
              <el-tag
                v-if="row.isActive === 1"
                type="success"
                size="mini"
                effect="dark"
                style="border-radius:8px;margin-left:4px"
              >生效</el-tag>
            </template>
            <span v-else class="dim">—</span>
          </template>
        </el-table-column>
        <el-table-column label="异常" width="76" align="center">
          <template slot-scope="{ row }">
            <el-tag
              v-if="row.hasAnomaly === 1"
              type="danger"
              size="mini"
              effect="plain"
              disable-transitions
            >{{ row.anomalyCnt }} 项</el-tag>
            <el-tag v-else type="success" size="mini" effect="plain" disable-transitions>正常</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="检测时间" width="152">
          <template slot-scope="{ row }">{{ fmtTime(row.processTime) }}</template>
        </el-table-column>
        <el-table-column label="记录时间" width="152">
          <template slot-scope="{ row }">{{ fmtTime(row.createTime) }}</template>
        </el-table-column>
        <el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip>
          <template slot-scope="{ row }">{{ row.remark || '—' }}</template>
        </el-table-column>
        <el-table-column label="操作" width="72" align="center" fixed="right">
          <template slot-scope="{ row }">
            <el-button type="text" size="mini" @click.stop="openDetail(row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 底部分页栏 -->
    <div class="bottom-bar">
      <el-pagination
        small
        layout="total, sizes, prev, pager, next"
        :total="total"
        :page-size="query.pageSize"
        :page-sizes="[20, 50, 100]"
        :current-page="query.pageNum"
        @size-change="v => { query.pageSize = v; query.pageNum = 1; loadRows() }"
        @current-change="v => { query.pageNum = v; loadRows() }"
      />
    </div>

    <!-- ══════════════════════════════════════
         钢卷参数详情 抽屉
         ══════════════════════════════════════ -->
    <el-drawer
      :visible.sync="detailDrawerVisible"
      :title="detailRow ? ('钢卷参数详情 · ' + detailRow.coilId) : '钢卷参数详情'"
      direction="rtl"
      size="780px"
      append-to-body
      @close="onDetailClose"
    >
      <div class="detail-wrap" v-loading="detailLoading">
        <!-- 基本信息卡 -->
        <div class="detail-info-card" v-if="detailRow">
          <div class="dic-row">
            <span class="dic-label">出口卷号</span>
            <span class="dic-val">{{ detailRow.coilId || '—' }}</span>
            <span class="dic-label">入口卷号</span>
            <span class="dic-val">{{ detailRow.enCoilId || '—' }}</span>
          </div>
          <div class="dic-row">
            <span class="dic-label">规程方案</span>
            <span class="dic-val">
              <span v-if="detailRow.specCode" class="tag-spec">{{ detailRow.specCode }}</span>
              <span v-if="detailRow.specName" class="tag-spec-name">{{ detailRow.specName }}</span>
              <span v-if="!detailRow.specCode && !detailRow.specName" class="dim">—</span>
            </span>
            <span class="dic-label">版本</span>
            <span class="dic-val">
              <span v-if="detailRow.versionCode" class="tag-version">{{ detailRow.versionCode }}</span>
              <span v-else class="dim">—</span>
            </span>
          </div>
          <div class="dic-row">
            <span class="dic-label">检测时间</span>
            <span class="dic-val">{{ fmtTime(detailRow.processTime) }}</span>
            <span class="dic-label">异常状态</span>
            <span class="dic-val">
              <el-tag v-if="detailRow.hasAnomaly === 1" type="danger" size="mini" effect="plain">{{ detailRow.anomalyCnt }} 项异常</el-tag>
              <el-tag v-else type="success" size="mini" effect="plain">正常</el-tag>
            </span>
          </div>
        </div>

        <!-- 参数分段 Tab -->
        <div class="seg-tabs">
          <div class="seg-tab-bar">
            <button
              v-for="seg in detailSegmentTabs"
              :key="seg.segmentType"
              :class="['seg-tab-btn', { 'is-active': detailActiveTab === seg.segmentType }]"
              @click="detailActiveTab = seg.segmentType"
            >
              {{ seg.segmentLabel }}
              <span v-if="seg.anomalyCount > 0" class="seg-badge">{{ seg.anomalyCount }}</span>
            </button>
          </div>

          <template v-for="seg in detailSegmentTabs">
            <div v-show="detailActiveTab === seg.segmentType" :key="seg.segmentType" class="seg-tab-pane">
              <div v-if="!detailLoading && seg.groups.length === 0" class="detail-empty">暂无参数数据</div>
              <div v-for="group in seg.groups" :key="group.planId" class="param-group">
                <div class="param-group-hd">
                  <span class="pg-point">{{ group.pointName }}</span>
                  <span v-if="group.pointCode" class="pg-code">{{ group.pointCode }}</span>
                </div>
                <el-table :data="group.params" size="mini" border :row-class-name="paramRowClass">
                  <el-table-column label="参数名称" prop="paramName" min-width="120" show-overflow-tooltip />
                  <el-table-column label="编码" prop="paramCode" width="100" show-overflow-tooltip />
                  <el-table-column label="单位" prop="unit" width="68" align="center">
                    <template slot-scope="{ row }">{{ row.unit || '—' }}</template>
                  </el-table-column>
                  <el-table-column label="设定目标" width="84" align="right">
                    <template slot-scope="{ row }">
                      <span :class="row._hasAnomaly ? 'val-anomaly' : ''">{{ fmtNum(row.targetValue) }}</span>
                    </template>
                  </el-table-column>
                  <el-table-column label="下限" width="72" align="right">
                    <template slot-scope="{ row }">{{ fmtNum(row.lowerLimit) }}</template>
                  </el-table-column>
                  <el-table-column label="上限" width="72" align="right">
                    <template slot-scope="{ row }">{{ fmtNum(row.upperLimit) }}</template>
                  </el-table-column>
                  <el-table-column label="实际最大" width="84" align="right">
                    <template slot-scope="{ row }">
                      <span v-if="row._hasAnomaly" :class="row._anomalyType === 'UPPER' ? 'val-danger' : 'val-ok'">{{ fmtNum(row._actualMax) }}</span>
                      <span v-else class="dim">—</span>
                    </template>
                  </el-table-column>
                  <el-table-column label="实际最小" width="84" align="right">
                    <template slot-scope="{ row }">
                      <span v-if="row._hasAnomaly" :class="row._anomalyType === 'LOWER' ? 'val-danger' : 'val-ok'">{{ fmtNum(row._actualMin) }}</span>
                      <span v-else class="dim">—</span>
                    </template>
                  </el-table-column>
                  <el-table-column label="偏差" width="72" align="right">
                    <template slot-scope="{ row }">
                      <span v-if="row._hasAnomaly" class="val-danger">
                        {{ fmtNum(row._anomalyType === 'UPPER' ? row._deviationMax : row._deviationMin) }}
                      </span>
                      <span v-else class="dim">—</span>
                    </template>
                  </el-table-column>
                  <el-table-column label="状态" width="76" align="center">
                    <template slot-scope="{ row }">
                      <el-tag v-if="row._hasAnomaly" type="danger" size="mini" effect="plain">
                        {{ row._anomalyType === 'UPPER' ? '超上限' : row._anomalyType === 'LOWER' ? '低于下限' : '异常' }}
                      </el-tag>
                      <el-tag v-else type="success" size="mini" effect="plain">正常</el-tag>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </div>
          </template>
        </div>
      </div>
    </el-drawer>

    <!-- ══════════════════════════════════════
         重新绑定 对话框
         ══════════════════════════════════════ -->
    <el-dialog
      title="重新绑定规程方案"
      :visible.sync="bindDialogVisible"
      width="960px"
      append-to-body
      :close-on-click-modal="false"
      @close="resetBindDialog"
    >
      <!-- ① 摘要条 — 始终可见 -->
      <div :class="['summary-bar', selectedVersion ? 'summary-bar--ready' : 'summary-bar--idle']">
        <template v-if="selectedVersion">
          <i class="el-icon-success summary-icon" />
          <span>
            将把
            <b class="s-count">{{ selected.length }}</b>
            条记录重新绑定至规程
            <span class="s-spec">{{ selectedSpec.specName }}</span>
            <span class="s-sep">›</span>
            版本
            <span class="s-version">{{ selectedVersion.versionCode }}</span>
          </span>
          <div class="summary-remove-opt">
            <el-checkbox v-model="removeOldRecord" :disabled="!singleSourceVersion">
              同时从原版本移除
              <span v-if="!singleSourceVersion" class="dim" style="margin-left:4px">（选中记录来自多个版本时不可用）</span>
            </el-checkbox>
          </div>
        </template>
        <template v-else>
          <i class="el-icon-info summary-icon summary-icon--idle" />
          <span class="s-idle">请先在下方选择目标规程，再选择版本后点击「确认绑定」</span>
        </template>
      </div>

      <!-- ② 左右选择区 -->
      <div class="bind-body">
        <!-- 左：规程列表 -->
        <div class="spec-col">
          <div class="col-hd">规程列表</div>
          <div class="spec-filter">
            <el-input
              v-model="specKeyword"
              placeholder="搜索名称 / 编码"
              size="mini"
              clearable
              prefix-icon="el-icon-search"
              @input="filterSpecs"
            />
          </div>
          <div class="spec-list" v-loading="specLoading">
            <div
              v-for="spec in filteredSpecList"
              :key="spec.specId"
              :class="['spec-item', { 'spec-item--active': selectedSpec && selectedSpec.specId === spec.specId }]"
              @click="selectSpec(spec)"
            >
              <div class="spec-item__name">{{ spec.specName }}</div>
              <div class="spec-item__code">{{ spec.specCode }}</div>
            </div>
            <div v-if="!specLoading && !filteredSpecList.length" class="list-empty">暂无规程</div>
          </div>
        </div>

        <div class="col-divider" />

        <!-- 右：版本列表 -->
        <div class="version-col">
          <template v-if="!selectedSpec">
            <div class="version-placeholder">
              <i class="el-icon-back" style="font-size:18px;color:#c0c4cc;margin-right:6px" />
              请在左侧选择规程
            </div>
          </template>
          <template v-else>
            <div class="col-hd">
              <span class="spec-name-label">{{ selectedSpec.specName }}</span>
              <span class="spec-code-chip">{{ selectedSpec.specCode }}</span>
            </div>
            <div v-if="selectedSpec.remark" class="spec-remark">{{ selectedSpec.remark }}</div>
            <div class="version-list" v-loading="versionLoading">
              <div v-if="!versionLoading && !versionList.length" class="list-empty">
                该规程暂无版本，请先在规程管理中创建
              </div>
              <div
                v-for="ver in versionList"
                :key="ver.versionId"
                :class="['version-card', {
                  'version-card--selected': selectedVersion && selectedVersion.versionId === ver.versionId,
                  'version-card--obsolete': ver.status === 'OBSOLETE'
                }]"
                @click="ver.status !== 'OBSOLETE' && selectVersion(ver)"
              >
                <div class="vc-body">
                  <div class="vc-row1">
                    <span class="vc-code">{{ ver.versionCode }}</span>
                    <el-tag :type="versionStatusType(ver.status)" size="mini" effect="plain" style="border-radius:10px;margin-left:6px">
                      {{ versionStatusLabel(ver.status) }}
                    </el-tag>
                    <el-tag v-if="ver.isActive === 1" type="success" size="mini" effect="dark" style="border-radius:10px;margin-left:4px">
                      当前生效
                    </el-tag>
                    <span v-if="ver.status === 'OBSOLETE'" class="obsolete-note">（已作废，不可选）</span>
                  </div>
                  <div class="vc-row2">
                    创建于 {{ (ver.createTime || '').substring(0, 16) || '—' }}
                    <template v-if="ver.updateTime && ver.updateTime !== ver.createTime">
                      &nbsp;· 更新于 {{ (ver.updateTime || '').substring(0, 16) }}
                    </template>
                  </div>
                  <div v-if="ver.remark" class="vc-remark">{{ ver.remark }}</div>
                </div>
                <div class="vc-check">
                  <i v-if="selectedVersion && selectedVersion.versionId === ver.versionId" class="el-icon-circle-check" />
                </div>
              </div>
            </div>
          </template>
        </div>
      </div>

      <div slot="footer" class="bind-footer">
        <el-button size="small" @click="bindDialogVisible = false">取消</el-button>
        <el-button
          size="small"
          type="primary"
          :disabled="!selectedVersion"
          :loading="bindLoading"
          @click="confirmBind"
        >确认绑定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listProcessCoilRecord, batchRebindCoilRecord } from '@/api/wms/processCoilRecord'
import { listProcessSpec } from '@/api/wms/processSpec'
import { listProcessSpecVersion } from '@/api/wms/processSpecVersion'
import { listProcessPlan, addProcessPlan } from '@/api/wms/processPlan'
import { listProcessPlanParam, addProcessPlanParam } from '@/api/wms/processPlanParam'
import { listAllProcessAnomaly } from '@/api/wms/processAnomaly'
import { getPresetSetupByCoilId } from '@/api/l2/timing'

// 三段 L1 预设设定值的结构定义（对应 PLTCM_PRESET_SETUP 表）
const PRESET_PLANS = [
  {
    segmentType: 'INLET', segmentName: '入口段', pointName: '入口设定值', pointCode: 'PRESET_INLET', sortOrder: 10,
    params: [
      { paramCode: 'POR_TEN',    paramName: '开卷机单位张力',   unit: 'N/mm²' },
      { paramCode: 'CEL_TEN',    paramName: '入口活套单位张力', unit: 'N/mm²' },
      { paramCode: 'FLAT_MESH_1', paramName: '矫直机1#辊插入量', unit: 'mm' },
      { paramCode: 'FLAT_MESH_2', paramName: '矫直机2#辊插入量', unit: 'mm' }
    ]
  },
  {
    segmentType: 'PROCESS', segmentName: '工艺段', pointName: '工艺设定值', pointCode: 'PRESET_PROCESS', sortOrder: 20,
    params: [
      { paramCode: 'TLV_TEN',    paramName: '拉弯矫直机单位张力', unit: 'N/mm²' },
      { paramCode: 'TLV_ELONG',  paramName: '拉弯矫直机延伸率',   unit: '%' },
      { paramCode: 'TLV_MESH_1', paramName: '弯曲辊1#弯辊量',    unit: 'mm' },
      { paramCode: 'TLV_MESH_2', paramName: '弯曲辊2#弯辊量',    unit: 'mm' }
    ]
  },
  {
    segmentType: 'OUTLET', segmentName: '出口段', pointName: '出口设定值', pointCode: 'PRESET_OUTLET', sortOrder: 30,
    params: [
      { paramCode: 'TR_TEN',   paramName: '酸洗出口张力辊张力', unit: 'N/mm²' },
      { paramCode: 'TRIM_TEN', paramName: '切边段单位张力',     unit: 'N/mm²' },
      { paramCode: 'TEL_TEN',  paramName: '联机活套单位张力',   unit: 'N/mm²' },
      { paramCode: 'CXL_TEN',  paramName: '出口活套单位张力',   unit: 'N/mm²' }
    ]
  }
]

const VERSION_STATUS = [
  { value: 'DRAFT',     label: '草稿' },
  { value: 'PUBLISHED', label: '已发布' },
  { value: 'OBSOLETE',  label: '已作废' }
]

export default {
  name: 'CoilSpecBind',
  data() {
    return {
      loading: false,
      rows:    [],
      total:   0,
      selected: [],
      query: {
        pageNum:    1,
        pageSize:   20,
        coilId:     '',
        enCoilId:   '',
        hasAnomaly: null
      },
      tableHeight: 'calc(100vh - 218px)',

      detailDrawerVisible: false,
      detailLoading:      false,
      detailRow:          null,
      detailParams:       [],
      detailActiveTab:    'INLET',

      bindDialogVisible: false,
      removeOldRecord:   false,
      specLoading:       false,
      specList:          [],
      filteredSpecList:  [],
      specKeyword:       '',
      selectedSpec:      null,
      versionLoading:    false,
      versionList:       [],
      selectedVersion:   null,
      bindLoading:       false
    }
  },
  computed: {
    detailParamGroups() {
      const planMap = {}
      for (const p of this.detailParams) {
        const key = p._planId
        if (!planMap[key]) {
          planMap[key] = {
            planId:      p._planId,
            segmentType: p._segmentType,
            segmentName: p._segmentName,
            pointName:   p._pointName,
            pointCode:   p._pointCode,
            sortOrder:   p._sortOrder,
            params: []
          }
        }
        planMap[key].params.push(p)
      }
      return Object.values(planMap).sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
    },
    detailSegmentTabs() {
      const SEG_ORDER = ['INLET', 'PROCESS', 'OUTLET']
      const SEG_LABELS = { INLET: '入口段', PROCESS: '工艺段', OUTLET: '出口段' }
      const map = {}
      for (const g of this.detailParamGroups) {
        const seg = g.segmentType || 'OTHER'
        if (!map[seg]) {
          map[seg] = { segmentType: seg, segmentLabel: SEG_LABELS[seg] || seg, anomalyCount: 0, groups: [] }
        }
        map[seg].groups.push(g)
        map[seg].anomalyCount += g.params.filter(p => p._hasAnomaly).length
      }
      for (const seg of SEG_ORDER) {
        if (!map[seg]) map[seg] = { segmentType: seg, segmentLabel: SEG_LABELS[seg], anomalyCount: 0, groups: [] }
      }
      return SEG_ORDER.map(s => map[s])
    },
    // 选中行是否全来自同一个版本（决定是否可以"移除旧记录"）
    singleSourceVersion() {
      if (!this.selected.length) return false
      const vids = [...new Set(this.selected.map(r => r.versionId))]
      return vids.length === 1
    }
  },
  created() {
    this.loadRows()
  },
  methods: {
    async loadRows() {
      this.loading = true
      try {
        const params = { ...this.query }
        if (!params.coilId)              delete params.coilId
        if (!params.enCoilId)            delete params.enCoilId
        if (params.hasAnomaly === null)  delete params.hasAnomaly
        const res = await listProcessCoilRecord(params)
        this.rows  = res.rows  || []
        this.total = res.total || 0
      } finally {
        this.loading = false
      }
    },
    handleSearch() {
      this.query.pageNum = 1
      this.loadRows()
    },
    handleReset() {
      this.query = { pageNum: 1, pageSize: 20, coilId: '', enCoilId: '', hasAnomaly: null }
      this.loadRows()
    },
    onSelectionChange(val) {
      this.selected = val
      if (!this.singleSourceVersion) this.removeOldRecord = false
    },

    // ── 绑定对话框 ──────────────────────────────
    openBindDialog() {
      this.specKeyword     = ''
      this.selectedSpec    = null
      this.selectedVersion = null
      this.versionList     = []
      this.removeOldRecord = false
      this.bindDialogVisible = true
      this.loadSpecs()
    },
    resetBindDialog() {
      this.selectedSpec    = null
      this.selectedVersion = null
      this.versionList     = []
      this.specKeyword     = ''
      this.removeOldRecord = false
    },

    async loadSpecs() {
      this.specLoading = true
      try {
        const res = await listProcessSpec({ pageNum: 1, pageSize: 200 })
        this.specList         = res.rows || []
        this.filteredSpecList = this.specList
      } finally {
        this.specLoading = false
      }
    },
    filterSpecs() {
      const kw = (this.specKeyword || '').trim().toLowerCase()
      this.filteredSpecList = kw
        ? this.specList.filter(s =>
            (s.specName || '').toLowerCase().includes(kw) ||
            (s.specCode || '').toLowerCase().includes(kw)
          )
        : this.specList
    },
    selectSpec(spec) {
      this.selectedSpec    = spec
      this.selectedVersion = null
      this.versionList     = []
      this.loadVersions(spec.specId)
    },
    async loadVersions(specId) {
      this.versionLoading = true
      try {
        const res = await listProcessSpecVersion({ specId, pageNum: 1, pageSize: 200 })
        this.versionList = res.rows || []
      } finally {
        this.versionLoading = false
      }
    },
    selectVersion(ver) {
      this.selectedVersion = ver
    },

    async confirmBind() {
      if (!this.selectedVersion || !this.selected.length) return
      this.bindLoading = true
      try {
        const coilIds = this.selected.map(r => r.coilId)
        const oldVersionId = (this.removeOldRecord && this.singleSourceVersion)
          ? this.selected[0].versionId
          : null
        await batchRebindCoilRecord({
          coilIds,
          newVersionId: this.selectedVersion.versionId,
          oldVersionId
        })
        this.$modal.msgSuccess(
          `已成功将 ${this.selected.length} 条记录绑定至【${this.selectedSpec.specName} / ${this.selectedVersion.versionCode}】`
        )
        this.bindDialogVisible = false
        this.$refs.recordTable.clearSelection()
        this.loadRows()
      } catch (e) {
        console.error(e)
      } finally {
        this.bindLoading = false
      }
    },

    // ── 详情抽屉 ──────────────────────────────────
    openDetail(row) {
      this.detailRow = row
      this.detailParams = []
      this.detailActiveTab = 'INLET'
      this.detailDrawerVisible = true
      this.loadDetailData(row)
    },
    onDetailClose() {
      this.detailRow = null
      this.detailParams = []
    },
    // Returns true if any preset plan points were auto-created
    async autoInitPresetParams(row, existingPlans) {
      try {
        const existingCodes = new Set(existingPlans.map(p => p.pointCode))
        const missing = PRESET_PLANS.filter(p => !existingCodes.has(p.pointCode))
        if (!missing.length) return false
        const srcId = row.enCoilId || row.coilId
        if (!srcId) return false
        const presetRes = await getPresetSetupByCoilId(srcId)
        const preset = (presetRes && presetRes.data && presetRes.data.data) || {}
        for (const def of missing) {
          const planRes = await addProcessPlan({
            versionId:   row.versionId,
            segmentType: def.segmentType,
            segmentName: def.segmentName,
            pointName:   def.pointName,
            pointCode:   def.pointCode,
            sortOrder:   def.sortOrder
          })
          const planId = planRes.data
          for (const p of def.params) {
            const val = preset[p.paramCode.toLowerCase()] ?? preset[p.paramCode]
            await addProcessPlanParam({
              planId,
              paramCode:   p.paramCode,
              paramName:   p.paramName,
              unit:        p.unit,
              targetValue: (val !== null && val !== undefined && val !== '') ? Number(val) : null,
              presetSrcId: srcId
            })
          }
        }
        return true
      } catch (e) {
        console.error('[autoInitPresetParams] failed', e)
        return false
      }
    },

    async loadDetailData(row) {
      if (!row.versionId) return
      this.detailLoading = true
      try {
        const [plansRes, anomalyRes] = await Promise.all([
          listProcessPlan({ versionId: row.versionId, pageNum: 1, pageSize: 200 }),
          listAllProcessAnomaly({ coilId: row.coilId, versionId: row.versionId })
        ])
        let plans = plansRes.rows || []

        const added = await this.autoInitPresetParams(row, plans)
        if (added) {
          const refreshed = await listProcessPlan({ versionId: row.versionId, pageNum: 1, pageSize: 200 })
          plans = refreshed.rows || []
        }

        const anomalyList = anomalyRes.data || []
        const anomalyMap = {}
        for (const a of anomalyList) {
          anomalyMap[a.paramCode] = a
        }

        const allParams = []
        const paramPromises = plans.map(plan =>
          listProcessPlanParam({ planId: plan.planId, pageNum: 1, pageSize: 500 })
            .then(res => {
              const params = res.rows || []
              for (const p of params) {
                const anomaly = anomalyMap[p.paramCode] || null
                allParams.push({
                  ...p,
                  _planId:      plan.planId,
                  _segmentType: plan.segmentType,
                  _segmentName: plan.segmentName,
                  _pointName:   plan.pointName,
                  _pointCode:   plan.pointCode,
                  _sortOrder:   plan.sortOrder,
                  _hasAnomaly:  !!anomaly,
                  _anomalyType: anomaly ? anomaly.anomalyType : null,
                  _actualMax:   anomaly ? anomaly.actualMax   : null,
                  _actualMin:   anomaly ? anomaly.actualMin   : null,
                  _deviationMax: anomaly ? anomaly.deviationMax : null,
                  _deviationMin: anomaly ? anomaly.deviationMin : null
                })
              }
            })
        )
        await Promise.all(paramPromises)
        this.detailParams = allParams
      } finally {
        this.detailLoading = false
      }
    },
    paramRowClass({ row }) {
      return row._hasAnomaly ? 'row-anomaly' : ''
    },
    fmtNum(val) {
      if (val === null || val === undefined || val === '') return '—'
      const n = Number(val)
      return isNaN(n) ? val : n.toFixed(3).replace(/\.?0+$/, '')
    },

    // ── 工具 ──────────────────────────────────
    fmtTime(val) {
      if (!val) return '—'
      return String(val).substring(0, 16)
    },
    versionStatusType(status) {
      return { DRAFT: '', PUBLISHED: 'success', OBSOLETE: 'info' }[status] || ''
    },
    versionStatusLabel(status) {
      return (VERSION_STATUS.find(s => s.value === status) || {}).label || status || '—'
    }
  }
}
</script>

<style scoped>
/* ── 页面 ── */
.coil-bind-page {
  padding: 12px 16px;
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  background: #fff;
}

/* ── 筛选 + 操作一体栏 ── */
.filter-bar {
  flex-shrink: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
  padding-bottom: 8px;
  border-bottom: 1px solid #f0f2f5;
}
.filter-form { flex: 1; min-width: 0; }
.filter-bar .el-form-item { margin-bottom: 6px; }
.toolbar-action {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 2px;
}
.sel-badge {
  font-size: 13px;
  color: #606266;
  white-space: nowrap;
}
.sel-badge b { color: #5F7BA0; font-size: 15px; margin: 0 2px; }
.sel-fade-enter-active, .sel-fade-leave-active { transition: opacity .2s; }
.sel-fade-enter, .sel-fade-leave-to { opacity: 0; }

/* ── 表格 ── */
.table-wrap {
  flex: 1;
  min-height: 0;
  border: 1px solid #ebeef5;
  border-radius: 3px;
  overflow: hidden;
}
.tag-spec {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 3px 0 0 3px;
  background: #ecf5ff;
  color: #3a6ea8;
  font-size: 11px;
  border: 1px solid #b3d8ff;
}
.tag-spec-name {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 0 3px 3px 0;
  background: #f5f7fa;
  color: #606266;
  font-size: 11px;
  border: 1px solid #dcdfe6;
  border-left: none;
}
.tag-version {
  display: inline-block;
  padding: 1px 8px;
  background: #f0f9eb;
  color: #4a8a2a;
  font-size: 11px;
  border: 1px solid #c2e7b0;
  border-radius: 3px;
}
.dim { font-size: 12px; color: #c0c4cc; }

/* ── 底部分页 ── */
.bottom-bar {
  flex-shrink: 0;
  display: flex;
  justify-content: flex-end;
  padding: 8px 0 0;
}

/* ── 摘要条 ── */
.summary-bar {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 16px;
  border-radius: 4px;
  margin-bottom: 12px;
  font-size: 13px;
  line-height: 1.6;
  transition: background .2s, border-color .2s;
  flex-wrap: wrap;
}
.summary-bar--idle  { background: #f4f4f5; border: 1px solid #e9e9eb; color: #909399; }
.summary-bar--ready { background: #ecf5ff; border: 1px solid #b3d8ff; color: #303133; }
.summary-icon { font-size: 16px; flex-shrink: 0; color: #5F7BA0; margin-top: 2px; }
.summary-icon--idle { color: #c0c4cc; }
.s-count   { font-size: 15px; color: #5F7BA0; margin: 0 2px; }
.s-spec    { font-weight: 600; color: #303133; margin: 0 3px; }
.s-sep     { color: #c0c4cc; margin: 0 3px; }
.s-version { font-weight: 600; color: #5F7BA0; }
.s-idle    { color: #909399; }
.summary-remove-opt {
  margin-left: auto;
  flex-shrink: 0;
  font-size: 12px;
  color: #606266;
}

/* ── 对话框主体 ── */
.bind-body {
  display: flex;
  height: 460px;
  overflow: hidden;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}
.col-hd {
  padding: 10px 14px 8px;
  font-size: 13px;
  font-weight: 600;
  color: #303133;
  border-bottom: 1px solid #f0f2f5;
  background: #fafafa;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.col-divider { width: 1px; background: #ebeef5; flex-shrink: 0; }

/* 左：规程列 */
.spec-col {
  width: 256px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.spec-filter { padding: 8px 10px; border-bottom: 1px solid #f0f2f5; flex-shrink: 0; }
.spec-list   { flex: 1; overflow-y: auto; padding: 4px 0; }
.spec-item {
  padding: 9px 14px;
  cursor: pointer;
  border-left: 3px solid transparent;
  transition: background .12s;
}
.spec-item:hover { background: #f5f7fa; }
.spec-item--active { background: #ecf5ff !important; border-left-color: #5F7BA0; }
.spec-item__name { font-size: 13px; font-weight: 500; color: #303133; line-height: 1.4; }
.spec-item__code { font-size: 11px; color: #909399; margin-top: 2px; }

/* 右：版本列 */
.version-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.spec-name-label { font-size: 13px; font-weight: 600; color: #303133; }
.spec-code-chip {
  font-size: 11px; color: #909399;
  background: #f0f2f5; padding: 1px 8px; border-radius: 10px;
}
.spec-remark {
  font-size: 12px; color: #909399;
  padding: 5px 14px; background: #fafbfc;
  border-bottom: 1px solid #f0f2f5; flex-shrink: 0;
}
.version-placeholder {
  flex: 1; display: flex; align-items: center; justify-content: center;
  color: #c0c4cc; font-size: 13px;
}
.version-list {
  flex: 1; overflow-y: auto; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 8px;
}

/* 版本卡片 */
.version-card {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 12px 14px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s, background .15s;
  background: #fff;
}
.version-card:hover:not(.version-card--obsolete) {
  border-color: #5F7BA0;
  box-shadow: 0 2px 8px rgba(95,123,160,.12);
}
.version-card--selected {
  border-color: #5F7BA0 !important;
  background: #f0f7ff !important;
  box-shadow: 0 0 0 2px rgba(95,123,160,.18) !important;
}
.version-card--obsolete { opacity: .5; cursor: not-allowed; background: #fafafa; }
.vc-body { flex: 1; min-width: 0; }
.vc-row1 { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin-bottom: 5px; }
.vc-code { font-size: 14px; font-weight: 600; color: #303133; }
.obsolete-note { font-size: 11px; color: #c0c4cc; margin-left: 4px; }
.vc-row2 { font-size: 11px; color: #c0c4cc; margin-bottom: 3px; }
.vc-remark { font-size: 12px; color: #909399; margin-top: 4px; word-break: break-all; }
.vc-check { font-size: 18px; color: #5F7BA0; flex-shrink: 0; margin-left: 10px; align-self: center; }

/* 底部 */
.bind-footer { display: flex; justify-content: flex-end; gap: 8px; }
.list-empty { padding: 32px 0; text-align: center; font-size: 13px; color: #c0c4cc; }

/* ── 详情抽屉 ── */
.detail-wrap {
  padding: 16px 20px 32px;
  height: 100%;
  overflow-y: auto;
  box-sizing: border-box;
}
.detail-info-card {
  background: #f8f9fb;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 12px 16px;
  margin-bottom: 16px;
}
.dic-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.dic-row:last-child { margin-bottom: 0; }
.dic-label {
  font-size: 12px;
  color: #909399;
  flex-shrink: 0;
  width: 56px;
  text-align: right;
}
.dic-val {
  font-size: 13px;
  color: #303133;
  min-width: 0;
  flex: 1;
}
/* ── 分段 Tab ── */
.seg-tabs { margin-top: 0; }
.seg-tab-bar {
  display: inline-flex;
  background: #f0f2f5;
  border-radius: 8px;
  padding: 3px;
  margin-bottom: 14px;
  gap: 2px;
}
.seg-tab-btn {
  border: none;
  background: transparent;
  border-radius: 6px;
  padding: 6px 20px;
  font-size: 13px;
  color: #606266;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background .15s, color .15s, box-shadow .15s;
  white-space: nowrap;
  outline: none;
}
.seg-tab-btn:hover:not(.is-active) { background: #e4e7ed; color: #303133; }
.seg-tab-btn.is-active {
  background: #fff;
  color: #303133;
  font-weight: 600;
  box-shadow: 0 1px 5px rgba(0,0,0,.1);
}
.seg-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  background: #f56c6c;
  color: #fff;
  border-radius: 8px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
}
.seg-tab-pane {}

.param-group { margin-bottom: 20px; }
.param-group-hd {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  padding: 0 2px;
}
.pg-point { font-size: 13px; font-weight: 600; color: #303133; }
.pg-code  { font-size: 11px; color: #909399; }
.val-danger { color: #f56c6c; font-weight: 600; }
.val-ok     { color: #67c23a; }
.val-anomaly { color: #e6a23c; font-weight: 600; }
.detail-empty {
  padding: 48px 0;
  text-align: center;
  font-size: 13px;
  color: #c0c4cc;
}
.param-group :deep(.row-anomaly td) { background: #fff8f0 !important; }
::v-deep .row-anomaly td { background: #fff8f8 !important; }
::v-deep .el-drawer__header { padding: 16px 20px 12px; font-size: 15px; font-weight: 600; color: #303133; margin-bottom: 0; border-bottom: 1px solid #f0f2f5; }
::v-deep .el-drawer__body { overflow: hidden; }

/* 覆盖 */
::v-deep .el-button--primary {
  color: #fff !important; background: #5F7BA0 !important; border-color: #5F7BA0 !important;
}
::v-deep .el-button--primary:hover,
::v-deep .el-button--primary:focus {
  background: #4d6a8e !important; border-color: #4d6a8e !important;
}
::v-deep .el-button--primary.is-disabled { opacity: .5; }
::v-deep .el-table .el-table__row:hover td { background: #f5f9ff !important; }
</style>
