<template>
  <div>
    <!-- ─── 标签页 ─── -->
    <div class="tab-bar">
      <span :class="['tab-item', { active: activeTab === 'tasks' }]" @click="activeTab = 'tasks'">检验任务</span>
      <span :class="['tab-item', { active: activeTab === 'abnormal' }]" @click="switchToAbnormal">异常管理</span>
    </div>

    <!-- ═══════════════════════════════════════ 检验任务 Tab ═══════════════════════════════════════ -->
    <template v-if="activeTab === 'tasks'">
      <!-- 过滤栏 -->
      <div class="card">
        <div class="card-body" style="padding:10px 14px;">
          <div class="flex-row" style="flex-wrap:wrap;gap:12px;">
            <div class="flex-row">
              <span class="kv-label">任务编号</span>
              <input v-model="taskQuery.task_code" class="kv-input" style="width:130px;" @keyup.enter="fetchTasks" />
            </div>
            <div class="flex-row">
              <span class="kv-label">卷号</span>
              <input v-model="taskQuery.coil_no" class="kv-input" style="width:120px;" @keyup.enter="fetchTasks" />
            </div>
            <div class="flex-row">
              <span class="kv-label">状态</span>
              <select v-model="taskQuery.status" class="kv-input" style="width:100px;">
                <option value="">全部</option>
                <option value="0">待检验</option>
                <option value="1">检验中</option>
                <option value="2">待审核</option>
                <option value="3">完成</option>
              </select>
            </div>
            <div class="flex-row">
              <span class="kv-label">结果</span>
              <select v-model="taskQuery.result" class="kv-input" style="width:100px;">
                <option value="">全部</option>
                <option value="qualified">合格</option>
                <option value="unqualified">不合格</option>
              </select>
            </div>
            <div class="flex-row">
              <button class="btn btn-primary" @click="fetchTasks">查询</button>
              <button class="btn btn-outline" @click="openTaskDialog()">＋ 新增任务</button>
            </div>
          </div>
        </div>
      </div>

      <div class="card">
        <div class="card-header">
          检验任务列表
          <span class="ch-badge">共 {{ taskTotal }} 条</span>
        </div>
        <div class="table-scroll">
          <table class="data-table">
            <thead>
              <tr>
                <th>任务编号</th><th>卷号</th><th>方案名称</th><th>检验人员</th>
                <th>检验时间</th><th>状态</th><th>结果</th><th>创建时间</th><th>操作</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="row in taskData" :key="row.id">
                <td class="td-num">{{ row.task_code }}</td>
                <td class="td-num">{{ row.coil_no || '—' }}</td>
                <td>{{ row.scheme_name || '—' }}</td>
                <td class="td-muted">{{ row.inspect_user || '—' }}</td>
                <td class="td-muted">{{ fmtTime(row.inspect_time) }}</td>
                <td><span :class="['badge', taskStatusBadge(row.status)]">{{ taskStatusLabel(row.status) }}</span></td>
                <td>
                  <span v-if="row.result" :class="['badge', row.result === 'qualified' ? 'badge-green' : 'badge-red']">
                    {{ row.result === 'qualified' ? '合格' : '不合格' }}
                  </span>
                  <span v-else class="td-muted">—</span>
                </td>
                <td class="td-muted">{{ fmtTime(row.created_at) }}</td>
                <td>
                  <span class="action-link" @click="openTaskDialog(row)">编辑</span>
                  <span class="action-link" style="color:#da3633;" @click="deleteTask(row)">删除</span>
                </td>
              </tr>
              <tr v-if="!taskData.length">
                <td colspan="9" class="td-muted" style="text-align:center;padding:24px;">暂无数据</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </template>

    <!-- ═══════════════════════════════════════ 异常管理 Tab ═══════════════════════════════════════ -->
    <template v-if="activeTab === 'abnormal'">
      <div class="abn-layout">
        <!-- 左侧：钢卷列表 -->
        <div class="abn-sidebar">
          <div class="sidebar-header">
            钢卷列表
            <span class="add-btn" title="刷新" @click="fetchCoils">⟳</span>
          </div>
          <div class="sidebar-search">
            <input v-model="coilQuery.coil_no" class="kv-input" placeholder="搜索卷号..." style="width:100%;" @keyup.enter="fetchCoils" />
          </div>
          <div class="cl-list">
            <div
              v-for="c in coils"
              :key="c.id"
              :class="['cl-item', { active: selectedCoil && selectedCoil.id === c.id }]"
              @click="selectCoil(c)"
            >
              <div class="cl-name">{{ c.coil_no }}</div>
              <div class="cl-meta">
                <span class="td-muted" style="font-size:10px;">{{ c.steel_grade || '—' }}</span>
                <span class="td-muted" style="font-size:10px;">{{ c.spec_thickness ? c.spec_thickness + '×' + (c.spec_width || '?') : '' }}</span>
              </div>
            </div>
            <div v-if="!coils.length" class="cl-empty">暂无钢卷</div>
          </div>
        </div>

        <!-- 右侧：异常管理面板 -->
        <div class="abn-main">
          <div v-if="!selectedCoil" class="empty-tip">请从左侧选择钢卷</div>

          <template v-else>
            <!-- 钢卷信息 -->
            <div class="card">
              <div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
                <span>钢卷信息</span>
                <button class="btn btn-outline" style="padding:2px 10px;font-size:11px;" @click="reloadCoil">⟳ 刷新</button>
              </div>
              <div class="card-body">
                <div class="kv-grid">
                  <div class="kv-cell"><span class="kv-label">入场卷号</span><span class="kv-value">{{ selectedCoil.coil_no || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">当前卷号</span><span class="kv-value">{{ selectedCoil.coil_no || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">厂家原料号</span><span class="kv-value">{{ selectedCoil.order_no || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">逻辑库位</span><span class="kv-value">酸连轧原料库</span></div>
                  <div class="kv-cell"><span class="kv-label">实际库区</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">班组</span><span class="kv-value">{{ selectedCoil.shift || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">材料类型</span><span class="kv-value">原料</span></div>
                  <div class="kv-cell"><span class="kv-label">物料名</span><span class="kv-value">热轧卷板</span></div>
                  <div class="kv-cell"><span class="kv-label">规格</span><span class="kv-value">{{ specStr }}</span></div>
                  <div class="kv-cell"><span class="kv-label">材质</span><span class="kv-value">{{ selectedCoil.steel_grade || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">厂家</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">镀层质量</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">表面处理</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">质量状态</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">切边要求</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">原料材质</span><span class="kv-value">{{ selectedCoil.steel_grade || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">包装要求</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">实测厚度[mm]</span><span class="kv-value">{{ selectedCoil.target_thickness || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">实测宽度[mm]</span><span class="kv-value">{{ selectedCoil.target_width || '—' }}</span></div>
                  <div class="kv-cell"><span class="kv-label">长度[m]</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">毛重[t]</span><span class="kv-value">{{ weightT(selectedCoil.gross_weight) }}</span></div>
                  <div class="kv-cell"><span class="kv-label">净重[t]</span><span class="kv-value">{{ weightT(selectedCoil.net_weight) }}</span></div>
                  <div class="kv-cell"><span class="kv-label">生产开始</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">生产结束</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">调制度</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">镀层种类</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">钢卷表面处理</span><span class="kv-value">—</span></div>
                  <div class="kv-cell"><span class="kv-label">备注</span><span class="kv-value">{{ selectedCoil.remark || '—' }}</span></div>
                </div>
              </div>
            </div>

            <!-- 异常记录 -->
            <div class="card">
              <div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
                <span>异常记录 <span class="ch-badge">{{ defects.length }} 行</span></span>
                <div class="flex-row" style="gap:8px;">
                  <button class="btn btn-outline" style="padding:2px 10px;font-size:11px;" @click="addDefectRow">＋ 新增行</button>
                  <button class="btn btn-outline" style="padding:2px 10px;font-size:11px;" @click="loadDefects">⟳ 刷新</button>
                  <button class="btn btn-primary" style="padding:2px 14px;font-size:11px;" :disabled="saving" @click="saveDefects">{{ saving ? '保存中...' : '保存' }}</button>
                </div>
              </div>
              <div class="table-scroll">
                <table class="data-table abn-table">
                  <thead>
                    <tr>
                      <th style="width:48px;">序号</th>
                      <th style="min-width:140px;">缺陷描述</th>
                      <th style="width:90px;">开始位置</th>
                      <th style="width:90px;">结束位置</th>
                      <th style="width:70px;">长度</th>
                      <th style="width:140px;">上下版面</th>
                      <th style="width:180px;">断面位置</th>
                      <th style="width:160px;">缺陷代码</th>
                      <th style="width:110px;">程度</th>
                      <th style="width:60px;">主缺陷</th>
                      <th style="min-width:120px;">缺陷图片</th>
                      <th style="width:60px;">操作</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="(d, idx) in defects" :key="idx">
                      <td class="td-num">{{ idx + 1 }}</td>
                      <td><input v-model="d.defect_desc" class="kv-input" style="width:100%;" placeholder="请输入缺陷描述" /></td>
                      <td><input v-model.number="d.start_position" type="number" class="kv-input" style="width:100%;" /></td>
                      <td><input v-model.number="d.end_position" type="number" class="kv-input" style="width:100%;" /></td>
                      <td class="td-num">{{ computeLen(d) }}</td>
                      <td>
                        <label class="ck"><input type="checkbox" v-model="d.upper_surface" />上板面</label>
                        <label class="ck"><input type="checkbox" v-model="d.lower_surface" />下板面</label>
                        <a class="all-link" @click="setAll(d, ['upper_surface','lower_surface'])">全选</a>
                      </td>
                      <td>
                        <label class="ck"><input type="checkbox" v-model="d.side_op" />操作侧</label>
                        <label class="ck"><input type="checkbox" v-model="d.side_middle" />中间</label>
                        <label class="ck"><input type="checkbox" v-model="d.side_drive" />驱动侧</label>
                        <a class="all-link" @click="setAll(d, ['side_op','side_middle','side_drive'])">全选</a>
                      </td>
                      <td>
                        <label v-for="opt in defectCodeOptions" :key="opt.value" class="rd">
                          <input type="radio" :value="opt.value" v-model="d.defect_code" />{{ opt.label }}
                        </label>
                      </td>
                      <td>
                        <label v-for="opt in degreeOptions" :key="opt.value" class="rd">
                          <input type="radio" :value="opt.value" v-model="d.degree" />{{ opt.label }}
                        </label>
                      </td>
                      <td style="text-align:center;"><input type="checkbox" v-model="d.is_main" /></td>
                      <td><input v-model="d.image_url" class="kv-input" style="width:100%;" placeholder="图片URL" /></td>
                      <td>
                        <span class="action-link" @click="clearRow(d)">清空</span>
                        <span class="action-link" style="color:#da3633;" @click="removeRow(idx)">删除</span>
                      </td>
                    </tr>
                    <tr v-if="!defects.length">
                      <td colspan="12" class="td-muted" style="text-align:center;padding:18px;">暂无异常，点击「＋ 新增行」开始录入</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </template>
        </div>
      </div>
    </template>

    <!-- ─── 新增/编辑任务弹窗 ─── -->
    <div v-if="taskDialogVisible" class="modal-mask" @click.self="taskDialogVisible = false">
      <div class="modal-box" style="width:560px;">
        <div class="modal-header">
          {{ editTask ? '编辑任务 #' + editTask.id : '新增检验任务' }}
          <span class="modal-close" @click="taskDialogVisible = false">✕</span>
        </div>
        <div class="modal-body">
          <div class="grid-2" style="gap:12px;">
            <div class="form-field">
              <div class="kv-label">任务编号 *</div>
              <input v-model="taskForm.task_code" class="kv-input" :disabled="!!editTask" />
            </div>
            <div class="form-field">
              <div class="kv-label">卷号</div>
              <input v-model="taskForm.coil_no" class="kv-input" />
            </div>
            <div class="form-field">
              <div class="kv-label">任务类型</div>
              <select v-model="taskForm.task_type" class="kv-input">
                <option value="">请选择</option>
                <option value="incoming">来料检验</option>
                <option value="process">过程检验</option>
                <option value="final">成品检验</option>
              </select>
            </div>
            <div class="form-field">
              <div class="kv-label">方案名称</div>
              <input v-model="taskForm.scheme_name" class="kv-input" />
            </div>
            <div class="form-field">
              <div class="kv-label">检验人员</div>
              <input v-model="taskForm.inspect_user" class="kv-input" />
            </div>
            <div v-if="editTask" class="form-field">
              <div class="kv-label">状态</div>
              <select v-model="taskForm.status" class="kv-input">
                <option :value="0">待检验</option>
                <option :value="1">检验中</option>
                <option :value="2">待审核</option>
                <option :value="3">完成</option>
              </select>
            </div>
            <div v-if="editTask" class="form-field">
              <div class="kv-label">检验结果</div>
              <select v-model="taskForm.result" class="kv-input">
                <option value="">待定</option>
                <option value="qualified">合格</option>
                <option value="unqualified">不合格</option>
              </select>
            </div>
            <div class="form-field" style="grid-column:1/-1;">
              <div class="kv-label">备注</div>
              <textarea v-model="taskForm.remark" class="kv-input" rows="2"></textarea>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <button class="btn btn-outline" @click="taskDialogVisible = false">取消</button>
          <button class="btn btn-primary" :disabled="saving" @click="saveTask">{{ saving ? '保存中...' : '保存' }}</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import {
  getQcTasks, createQcTask, updateQcTask, deleteQcTask,
  getCoils, getCoil,
  getQcDefectsByCoil, bulkSaveQcDefects,
} from '@/api'

const TASK_STATUS = {
  0: { label: '待检验', badge: 'badge-gray' },
  1: { label: '检验中', badge: 'badge-yellow' },
  2: { label: '待审核', badge: 'badge' },
  3: { label: '完成',   badge: 'badge-green' },
}

const DEFECT_CODES = [
  { value: 'S', label: '表面缺陷（S）' },
  { value: 'E', label: '边部问题（E）' },
  { value: 'M', label: '尺寸问题（M）' },
  { value: 'G', label: '收卷问题（G）' },
  { value: 'F', label: '版型问题（F）' },
]

const DEGREES = [
  { value: 'light',   label: '轻微' },
  { value: 'medium',  label: '中度' },
  { value: 'serious', label: '严重' },
]

function blankDefect() {
  return {
    defect_desc: '',
    start_position: 0,
    end_position: 0,
    upper_surface: false,
    lower_surface: false,
    side_op: false,
    side_middle: false,
    side_drive: false,
    defect_code: '',
    degree: '',
    is_main: false,
    image_url: '',
  }
}

export default {
  name: 'Quality',
  data() {
    return {
      activeTab: 'tasks',
      saving: false,

      // 任务
      taskData: [], taskTotal: 0,
      taskQuery: { page: 1, page_size: 20, task_code: '', coil_no: '', status: '', result: '' },
      taskDialogVisible: false, editTask: null, taskForm: {},

      // 异常管理
      coils: [],
      coilQuery: { coil_no: '', page: 1, page_size: 50 },
      selectedCoil: null,
      defects: [],

      defectCodeOptions: DEFECT_CODES,
      degreeOptions: DEGREES,
    }
  },
  computed: {
    specStr() {
      const c = this.selectedCoil || {}
      if (c.spec_thickness && c.spec_width) return `${c.spec_thickness}*${c.spec_width}`
      return '—'
    },
  },
  created() { this.fetchTasks() },
  methods: {
    // ── 任务 ──────────────────────────────────────
    async fetchTasks() {
      const params = { page: this.taskQuery.page, page_size: this.taskQuery.page_size }
      if (this.taskQuery.task_code) params.task_code = this.taskQuery.task_code
      if (this.taskQuery.coil_no) params.coil_no = this.taskQuery.coil_no
      if (this.taskQuery.status !== '') params.status = this.taskQuery.status
      if (this.taskQuery.result) params.result = this.taskQuery.result
      try {
        const res = await getQcTasks(params)
        this.taskData = res.data.items
        this.taskTotal = res.data.total
      } catch (e) { /* ignore */ }
    },
    openTaskDialog(row = null) {
      this.editTask = row
      this.taskForm = row ? { ...row } : { task_code: '', status: 0 }
      this.taskDialogVisible = true
    },
    async saveTask() {
      if (!this.taskForm.task_code) { this.$message.error('任务编号不能为空'); return }
      this.saving = true
      try {
        if (this.editTask) {
          await updateQcTask(this.editTask.id, this.taskForm)
        } else {
          await createQcTask(this.taskForm)
        }
        this.$message.success('保存成功')
        this.taskDialogVisible = false
        this.fetchTasks()
      } finally { this.saving = false }
    },
    async deleteTask(row) {
      if (!confirm(`确认删除任务 ${row.task_code}？`)) return
      try {
        await deleteQcTask(row.id)
        this.$message.success('已删除')
        this.fetchTasks()
      } catch (e) { this.$message.error('删除失败') }
    },

    // ── 异常管理 ──────────────────────────────────
    async switchToAbnormal() {
      this.activeTab = 'abnormal'
      if (!this.coils.length) await this.fetchCoils()
    },
    async fetchCoils() {
      try {
        const params = { page: 1, page_size: 50 }
        if (this.coilQuery.coil_no) params.coil_no = this.coilQuery.coil_no
        const res = await getCoils(params)
        this.coils = res.data.items || []
      } catch (e) { this.coils = [] }
    },
    async selectCoil(c) {
      this.selectedCoil = c
      await this.loadDefects()
    },
    async reloadCoil() {
      if (!this.selectedCoil) return
      try {
        const res = await getCoil(this.selectedCoil.coil_no)
        this.selectedCoil = res.data
      } catch (e) { /* ignore */ }
    },
    async loadDefects() {
      if (!this.selectedCoil) return
      try {
        const res = await getQcDefectsByCoil(this.selectedCoil.coil_no)
        this.defects = (res.data || []).map(d => ({
          defect_desc: d.defect_desc || '',
          start_position: d.start_position || 0,
          end_position: d.end_position || 0,
          upper_surface: !!d.upper_surface,
          lower_surface: !!d.lower_surface,
          side_op: !!d.side_op,
          side_middle: !!d.side_middle,
          side_drive: !!d.side_drive,
          defect_code: d.defect_code || '',
          degree: d.degree || '',
          is_main: !!d.is_main,
          image_url: d.image_url || '',
        }))
        if (!this.defects.length) this.addDefectRow()
      } catch (e) { this.defects = [blankDefect()] }
    },
    addDefectRow() { this.defects.push(blankDefect()) },
    removeRow(i) { this.defects.splice(i, 1) },
    clearRow(d) { Object.assign(d, blankDefect()) },
    setAll(d, keys) {
      const allOn = keys.every(k => d[k])
      keys.forEach(k => { d[k] = !allOn })
    },
    computeLen(d) {
      const s = parseFloat(d.start_position); const e = parseFloat(d.end_position)
      if (isNaN(s) || isNaN(e)) return 0
      const v = +(e - s).toFixed(3)
      return v
    },
    async saveDefects() {
      if (!this.selectedCoil) return
      this.saving = true
      try {
        const list = this.defects.map((d, i) => ({
          seq_no: i + 1,
          defect_desc: d.defect_desc || null,
          start_position: d.start_position != null ? Number(d.start_position) : null,
          end_position: d.end_position != null ? Number(d.end_position) : null,
          length_val: this.computeLen(d),
          upper_surface: !!d.upper_surface,
          lower_surface: !!d.lower_surface,
          side_op: !!d.side_op,
          side_middle: !!d.side_middle,
          side_drive: !!d.side_drive,
          defect_code: d.defect_code || null,
          degree: d.degree || null,
          is_main: !!d.is_main,
          image_url: d.image_url || null,
        }))
        await bulkSaveQcDefects({ coil_no: this.selectedCoil.coil_no, defects: list })
        this.$message.success('保存成功')
        await this.loadDefects()
      } catch (e) {
        this.$message.error('保存失败')
      } finally { this.saving = false }
    },

    // ── 工具 ─────────────────────────────────────
    fmtTime(t) { return t ? t.slice(0, 16).replace('T', ' ') : '—' },
    taskStatusLabel(s) { return TASK_STATUS[s]?.label || s },
    taskStatusBadge(s) { return TASK_STATUS[s]?.badge || 'badge-gray' },
    weightT(kg) { return kg ? (kg / 1000).toFixed(3) : '—' },
  },
}
</script>

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

.tab-bar {
  display: flex;
  margin-bottom: 14px;
  border-bottom: 2px solid $border;
}
.tab-item {
  padding: 8px 20px;
  font-size: 13px;
  cursor: pointer;
  color: $text-muted;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: all .15s;
  &:hover { color: $text-primary; }
  &.active { color: $sms-highlight; border-bottom-color: $sms-highlight; font-weight: 600; }
}

/* ─── 异常管理布局 ─── */
.abn-layout { display: flex; gap: 14px; align-items: flex-start; }
.abn-sidebar {
  width: 220px; flex-shrink: 0;
  background: $bg-card; border: 1px solid $border; border-radius: 6px;
  display: flex; flex-direction: column; max-height: calc(100vh - 180px);
}
.sidebar-header {
  padding: 10px 12px; font-size: 12px; font-weight: 600; color: $sms-highlight;
  border-bottom: 1px solid $border; background: $bg-panel;
  display: flex; align-items: center; justify-content: space-between;
}
.sidebar-search { padding: 8px 10px; border-bottom: 1px solid $border; }
.add-btn { cursor: pointer; color: $sms-highlight; font-size: 14px; &:hover { opacity: .7; } }
.cl-list { flex: 1; overflow-y: auto; }
.cl-item { padding: 8px 12px; cursor: pointer; border-bottom: 1px solid rgba($border, .5);
  &:hover { background: rgba(255,255,255,.03); }
  &.active { background: rgba(0,200,255,.08); border-left: 3px solid $sms-highlight; }
}
.cl-name { font-size: 12px; color: $text-primary; margin-bottom: 3px; }
.cl-meta { display: flex; gap: 6px; }
.cl-empty { padding: 20px; text-align: center; font-size: 12px; color: $text-muted; }

.abn-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.empty-tip { padding: 60px; text-align: center; color: $text-muted; font-size: 13px;
  background: $bg-card; border: 1px solid $border; border-radius: 6px; }

/* 钢卷信息网格：5列 */
.kv-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px 14px;
}
.kv-cell { display: flex; align-items: center; gap: 6px; font-size: 12px; min-width: 0; }
.kv-cell .kv-label { color: $text-muted; flex-shrink: 0; }
.kv-cell .kv-value { color: $text-primary; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 异常表格 */
.abn-table { table-layout: auto; font-size: 12px; }
.abn-table th, .abn-table td { padding: 6px 6px; vertical-align: middle; }
.abn-table .kv-input { font-size: 12px; padding: 3px 6px; }
.abn-table .ck { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; margin-right: 6px; cursor: pointer; }
.abn-table .rd { display: block; font-size: 11px; line-height: 1.6; cursor: pointer; }
.abn-table .all-link { display: block; font-size: 10px; color: $sms-highlight; cursor: pointer; margin-top: 2px;
  &:hover { text-decoration: underline; } }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; }
.form-field { display: flex; flex-direction: column; gap: 5px; }
.action-link { color: $sms-highlight; cursor: pointer; font-size: 11px; margin-right: 8px; &:hover { text-decoration: underline; } }
.modal-mask { position: fixed; inset: 0; background: rgba(0,0,0,.6); display: flex; align-items: center; justify-content: center; z-index: 9999; }
.modal-box { background: $bg-card; border: 1px solid $border; border-radius: 6px; max-width: 96vw; max-height: 92vh; display: flex; flex-direction: column; }
.modal-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: $bg-panel; border-bottom: 1px solid $border; font-size: 13px; font-weight: 600; color: $sms-highlight; .modal-close { cursor: pointer; color: $text-muted; &:hover { color: $text-primary; } } }
.modal-body { padding: 16px; overflow-y: auto; }
.modal-footer { padding: 10px 16px; background: $bg-panel; border-top: 1px solid $border; display: flex; justify-content: flex-end; gap: 10px; }
</style>
