<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Box, MoreFilled, Plus, Search } from '@element-plus/icons-vue'
import ExcelImportDialog from '../components/ExcelImportDialog.vue'

const assets = ref([])
const metrics = ref([])
const products = ref([])
const viewMode = ref('card')
const loading = ref(false)
const assetDialogVisible = ref(false)
const isEditAsset = ref(false)
const bindDialogVisible = ref(false)
const productDialogVisible = ref(false)
const viewMetricsDialogVisible = ref(false)
const recordDialogVisible = ref(false)
const recordEditing = ref(false)
const recordSaving = ref(false)
const searchKeyword = ref('')
const selectedCategory = ref('整机')
const selectedMetricIds = ref([])
const selectedProductIds = ref([])
const metricLimits = ref({})
const metricLowerLimits = ref({})
const metricBaselines = ref({})
const metricFailures = ref({})
const metricIdeals = ref({})
const metricExtremes = ref({})
const metricCriterionWeights = ref({})
const metricIndicatorWeights = ref({})
const metricCycleHours = ref({})
const metricUnits = ref({})
const productTotalQuantity = ref({})
const productProcessNotes = ref({})
const currentAsset = ref(null)
const currentMetrics = ref([])
const detailAsset = ref(null)
const detailRecords = ref([])
const currentRecordSession = ref(null)
const editableSessionRows = ref([])

const assetForm = reactive({
  asset_category: '整机',
  asset_name: '',
  asset_type: '',
  asset_code: '',
})

const unitOptions = ['μm', 'mm', 'Hz', 'μm/min', 'mm/s']

const isAdmin = computed(() => {
  const role = localStorage.getItem('precision_user_role') || ''
  return ['admin', '管理员', '系统管理员'].includes(role)
})

const fetchJson = async (url, options) => {
  const res = await fetch(url, options)
  const data = await res.json()
  if (!res.ok || data.status === 'error') throw new Error(data.message || '请求失败')
  return data
}

const loadMetrics = async () => {
  const data = await fetchJson('/api/metrics')
  metrics.value = data.data || []
}

const loadProducts = async () => {
  const data = await fetchJson('/api/products')
  products.value = data.data || []
}

const loadAssets = async () => {
  loading.value = true
  try {
    const data = await fetchJson('/api/assets')
    assets.value = data.data || []
  } finally {
    loading.value = false
  }
}

const normalizedKeyword = computed(() => searchKeyword.value.trim().toLowerCase())

const filteredAssets = computed(() =>
  assets.value.filter((asset) => {
    const matchesCategory = !selectedCategory.value || asset.asset_category === selectedCategory.value
    const text = `${asset.asset_code || ''} ${asset.asset_name || ''} ${asset.asset_type || ''}`.toLowerCase()
    const matchesKeyword = !normalizedKeyword.value || text.includes(normalizedKeyword.value)
    return matchesCategory && matchesKeyword
  }),
)

const currentSectionMeta = computed(() =>
  selectedCategory.value === '部件'
    ? { title: '部件台账', kicker: 'COMPONENT', type: '部件', tag: 'success', empty: '暂无部件资产' }
    : { title: '整机台账', kicker: 'WHOLE MACHINE', type: '整机', tag: 'primary', empty: '暂无整机资产' }
)

const recordSessions = computed(() => {
  const groups = new Map()
  detailRecords.value.forEach((record) => {
    const key = record.created_at
    if (!groups.has(key)) {
      groups.set(key, {
        sessionKey: key,
        created_at: key,
        metrics: [],
      })
    }
    groups.get(key).metrics.push(record)
  })
  return Array.from(groups.values())
    .map((session) => ({
      ...session,
      metric_count: session.metrics.length,
      summary: session.metrics.map((item) => item.metric_name).join('、'),
    }))
    .sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
})

const recentRecordSessions = computed(() => recordSessions.value.slice(0, 6))

const resetAssetForm = () => {
  Object.assign(assetForm, {
    asset_category: selectedCategory.value || '整机',
    asset_name: '',
    asset_type: '',
    asset_code: '',
  })
}

const openCreateDialog = (category = '') => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可新增或修改设备资产')
    return
  }
  resetAssetForm()
  isEditAsset.value = false
  currentAsset.value = null
  if (category) assetForm.asset_category = category
  else assetForm.asset_category = selectedCategory.value || '整机'
  assetDialogVisible.value = true
}

const openEditDialog = (asset) => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可新增或修改设备资产')
    return
  }
  currentAsset.value = asset
  isEditAsset.value = true
  Object.assign(assetForm, {
    asset_category: asset.asset_category || '整机',
    asset_name: asset.asset_name || '',
    asset_type: asset.asset_type || '',
    asset_code: asset.asset_code || '',
  })
  assetDialogVisible.value = true
}

const saveAsset = async () => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可新增或修改设备资产')
    return
  }
  if (!assetForm.asset_code || !assetForm.asset_name) {
    ElMessage.warning('请填写编号和名称')
    return
  }
  await fetchJson(isEditAsset.value ? `/api/assets/${currentAsset.value.asset_id}` : '/api/assets', {
    method: isEditAsset.value ? 'PUT' : 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(assetForm),
  })
  ElMessage.success(isEditAsset.value ? '设备信息已更新' : '设备已加入台账')
  assetDialogVisible.value = false
  isEditAsset.value = false
  currentAsset.value = null
  loadAssets()
}

const deleteAsset = async (asset) => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可删除设备资产')
    return
  }
  await ElMessageBox.confirm(`确定删除“${asset.asset_code}”及其关联测试记录吗？`, '提示', { type: 'warning' })
  await fetchJson(`/api/assets/${asset.asset_id}`, { method: 'DELETE' })
  ElMessage.success('设备已删除')
  if (detailAsset.value?.asset_id === asset.asset_id) detailAsset.value = null
  loadAssets()
}

const openMetricsDialog = async (asset) => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可配置设备指标')
    return
  }
  currentAsset.value = asset
  selectedMetricIds.value = []
  metricLimits.value = {}
  metricLowerLimits.value = {}
  metricBaselines.value = {}
  metricFailures.value = {}
  metricIdeals.value = {}
  metricExtremes.value = {}
  metricCriterionWeights.value = {}
  metricIndicatorWeights.value = {}
  metricCycleHours.value = {}
  metricUnits.value = {}
  const data = await fetchJson(`/api/assets/${asset.asset_id}/metrics`)
  ;(data.data || []).forEach((item) => {
    selectedMetricIds.value.push(item.metric_id)
    metricLimits.value[item.metric_id] = item.upper_limit
    metricLowerLimits.value[item.metric_id] = item.lower_limit
    metricBaselines.value[item.metric_id] = item.baseline_value
    metricFailures.value[item.metric_id] = item.failure_value
    metricIdeals.value[item.metric_id] = item.ideal_value
    metricExtremes.value[item.metric_id] = item.extreme_value
    metricCriterionWeights.value[item.metric_id] = item.criterion_weight
    metricIndicatorWeights.value[item.metric_id] = item.indicator_weight
    metricCycleHours.value[item.metric_id] = item.cycle_hours
    metricUnits.value[item.metric_id] = item.unit || 'μm'
  })
  bindDialogVisible.value = true
}

const openProductsDialog = async (asset) => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可配置加工制品')
    return
  }
  currentAsset.value = asset
  selectedProductIds.value = []
  productTotalQuantity.value = {}
  productProcessNotes.value = {}
  const data = await fetchJson(`/api/assets/${asset.asset_id}/products`)
  ;(data.data || []).forEach((item) => {
    selectedProductIds.value.push(item.product_id)
    productTotalQuantity.value[item.product_id] = item.total_quantity
    productProcessNotes.value[item.product_id] = item.process_note || ''
  })
  productDialogVisible.value = true
}

const saveMetrics = async () => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可配置设备指标')
    return
  }
  const payload = {
    metrics: selectedMetricIds.value.map((id) => ({
      metric_id: id,
      upper_limit: metricLimits.value[id] !== '' && metricLimits.value[id] !== undefined ? Number(metricLimits.value[id]) : null,
      lower_limit: metricLowerLimits.value[id] !== '' && metricLowerLimits.value[id] !== undefined ? Number(metricLowerLimits.value[id]) : null,
      baseline_value: metricBaselines.value[id] !== '' && metricBaselines.value[id] !== undefined ? Number(metricBaselines.value[id]) : null,
      failure_value: metricFailures.value[id] !== '' && metricFailures.value[id] !== undefined ? Number(metricFailures.value[id]) : null,
      ideal_value: metricIdeals.value[id] !== '' && metricIdeals.value[id] !== undefined ? Number(metricIdeals.value[id]) : null,
      extreme_value: metricExtremes.value[id] !== '' && metricExtremes.value[id] !== undefined ? Number(metricExtremes.value[id]) : null,
      criterion_weight: metricCriterionWeights.value[id] !== '' && metricCriterionWeights.value[id] !== undefined ? Number(metricCriterionWeights.value[id]) : null,
      indicator_weight: metricIndicatorWeights.value[id] !== '' && metricIndicatorWeights.value[id] !== undefined ? Number(metricIndicatorWeights.value[id]) : null,
      cycle_hours: metricCycleHours.value[id] !== '' && metricCycleHours.value[id] !== undefined ? Number(metricCycleHours.value[id]) : null,
      unit: metricUnits.value[id] || 'μm',
    })),
  }
  await fetchJson(`/api/assets/${currentAsset.value.asset_id}/metrics`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  })
  ElMessage.success('指标配置已保存')
  bindDialogVisible.value = false
  if (detailAsset.value?.asset_id === currentAsset.value.asset_id) {
    openDetail(detailAsset.value.asset_id)
  }
}

const saveProducts = async () => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可配置加工制品')
    return
  }
  await fetchJson(`/api/assets/${currentAsset.value.asset_id}/products`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      bindings: selectedProductIds.value.map((id) => ({
        product_id: id,
        total_quantity: productTotalQuantity.value[id] !== '' && productTotalQuantity.value[id] !== undefined ? Number(productTotalQuantity.value[id]) : null,
        process_note: productProcessNotes.value[id] || '',
      })),
    }),
  })
  ElMessage.success('加工制品绑定已保存')
  productDialogVisible.value = false
  if (detailAsset.value?.asset_id === currentAsset.value.asset_id) {
    openDetail(detailAsset.value.asset_id)
  }
}

const openViewMetrics = async (asset) => {
  currentAsset.value = asset
  const data = await fetchJson(`/api/assets/${asset.asset_id}/metrics/detail`)
  currentMetrics.value = data.data || []
  viewMetricsDialogVisible.value = true
}

const openDetail = async (assetId) => {
  const [assetData, recordsData] = await Promise.all([
    fetchJson(`/api/assets/${assetId}`),
    fetchJson(`/api/records?asset_id=${assetId}`),
  ])
  detailAsset.value = assetData.data
  detailRecords.value = recordsData.data || []
}

const closeDetail = () => {
  detailAsset.value = null
  detailRecords.value = []
}

const filteredMetrics = computed(() =>
  metrics.value.filter(() => true),
)

const isProcessMetric = (metric) =>
  `${metric?.category_level_1 || ''}${metric?.category_level_2 || ''}${metric?.metric_name || ''}`.includes('加工')

const isPartAsset = computed(() => currentAsset.value?.asset_category === '部件')

const formatTime = (time) => {
  if (!time) return '-'
  const date = new Date(time)
  if (Number.isNaN(date.getTime())) return time
  return date.toLocaleString('zh-CN')
}

const formatRecordValue = (record) => {
  if (record?.raw_data?.val !== undefined) return record.raw_data.val
  if (Array.isArray(record?.raw_data?.samples)) return record.raw_data.samples.join(', ')
  return '-'
}

const openRecordDialog = (session) => {
  currentRecordSession.value = session
  editableSessionRows.value = session.metrics.map((item) => ({
    metric_id: item.metric_id,
    metric_name: item.metric_name,
    value_type: item.value_type,
    raw_data: JSON.parse(JSON.stringify(item.raw_data)),
    samplesText: Array.isArray(item.raw_data?.samples) ? item.raw_data.samples.join(', ') : '',
  }))
  recordEditing.value = false
  recordDialogVisible.value = true
}

const enableRecordEdit = () => {
  if (!isAdmin.value) {
    ElMessage.warning('仅管理员可修改测试记录')
    return
  }
  recordEditing.value = true
}

const saveRecordSession = async () => {
  recordSaving.value = true
  try {
    const records = editableSessionRows.value.map((item) => {
      if (item.value_type === '单值') {
        return { metric_id: item.metric_id, raw_data: { val: Number(item.raw_data.val) } }
      }
      const samples = item.samplesText
        .split(/[,，\s\n]+/)
        .filter((value) => value.trim() !== '')
        .map(Number)
      if (samples.some(Number.isNaN)) {
        throw new Error(`指标“${item.metric_name}”存在非法数字`)
      }
      return { metric_id: item.metric_id, raw_data: { samples } }
    })

    await fetchJson('/api/records/session', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        asset_id: detailAsset.value.asset_id,
        record_date: currentRecordSession.value.sessionKey,
        records,
      }),
    })

    ElMessage.success('该次记录已更新')
    recordDialogVisible.value = false
    await openDetail(detailAsset.value.asset_id)
  } catch (error) {
    ElMessage.error(error.message || '保存失败')
  } finally {
    recordSaving.value = false
    recordEditing.value = false
  }
}

onMounted(async () => {
  await Promise.all([loadAssets(), loadMetrics(), loadProducts()])
})

const reloadLedgerData = () => Promise.all([loadAssets(), loadMetrics(), loadProducts()])
</script>

<template>
  <div class="equipment-ledger" v-loading="loading">
    <template v-if="!detailAsset">
      <div class="ledger-toolbar">
        <div class="toolbar-left">
          <el-radio-group v-model="selectedCategory">
            <el-radio-button label="整机">整机台账</el-radio-button>
            <el-radio-button label="部件">部件台账</el-radio-button>
          </el-radio-group>
          <el-input v-model="searchKeyword" placeholder="搜索设备编号/名称" clearable style="width: 240px">
            <template #prefix><el-icon><Search /></el-icon></template>
          </el-input>
        </div>
        <div class="toolbar-right">
          <el-radio-group v-model="viewMode">
            <el-radio-button label="card">卡片视图</el-radio-button>
            <el-radio-button label="table">列表视图</el-radio-button>
          </el-radio-group>
          <el-button type="primary" @click="openCreateDialog()">
            <el-icon><Plus /></el-icon>
            新增设备
          </el-button>
          <ExcelImportDialog title="设备台账与绑定" scope-key="资产台账" @success="reloadLedgerData" />
        </div>
      </div>

      <div v-if="viewMode === 'card'" class="ledger-columns single">
        <section class="ledger-panel">
          <div class="panel-header">
            <div>
              <div class="panel-kicker">{{ currentSectionMeta.kicker }}</div>
              <h3>{{ currentSectionMeta.title }}</h3>
            </div>
            <el-button :type="currentSectionMeta.tag === 'primary' ? 'primary' : 'success'" plain @click="openCreateDialog(currentSectionMeta.type)">
              新增{{ currentSectionMeta.type }}
            </el-button>
          </div>
          <div class="panel-grid">
            <div v-for="asset in filteredAssets" :key="asset.asset_id" class="equipment-card" @click="openDetail(asset.asset_id)">
              <div class="card-top">
                <div class="asset-icon"><el-icon><Box /></el-icon></div>
                <el-tag :type="currentSectionMeta.tag">{{ currentSectionMeta.type }}</el-tag>
                <el-dropdown trigger="click">
                  <el-button text class="more-btn" @click.stop><el-icon><MoreFilled /></el-icon></el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item @click="openDetail(asset.asset_id)">查看详情</el-dropdown-item>
                      <el-dropdown-item @click="openViewMetrics(asset)">查看指标</el-dropdown-item>
                      <el-dropdown-item :disabled="!isAdmin" @click="openEditDialog(asset)">编辑设备</el-dropdown-item>
                      <el-dropdown-item :disabled="!isAdmin" @click="openMetricsDialog(asset)">配置指标</el-dropdown-item>
                      <el-dropdown-item :disabled="!isAdmin || asset.asset_category !== '整机'" @click="openProductsDialog(asset)">绑定制品</el-dropdown-item>
                      <el-dropdown-item divided :disabled="!isAdmin" @click="deleteAsset(asset)">删除设备</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
              <div class="asset-code">{{ asset.asset_code }}</div>
              <h3>{{ asset.asset_name }}</h3>
              <div class="asset-meta">
                <div><span>规格类型</span><strong>{{ asset.asset_type || '-' }}</strong></div>
                <div><span>已录记录</span><strong>{{ asset.record_count || '-' }}</strong></div>
              </div>
            </div>
            <el-empty v-if="!filteredAssets.length" :description="`${currentSectionMeta.empty}，请先新增${currentSectionMeta.type}`">
              <el-button :type="currentSectionMeta.tag === 'primary' ? 'primary' : 'success'" @click="openCreateDialog(currentSectionMeta.type)">
                新增{{ currentSectionMeta.type }}
              </el-button>
            </el-empty>
          </div>
        </section>
      </div>

      <el-table v-else :data="filteredAssets" stripe>
        <el-table-column prop="asset_code" label="设备编号" width="150" />
        <el-table-column prop="asset_name" label="设备名称" min-width="180" />
        <el-table-column prop="asset_category" label="类型" width="100" />
        <el-table-column prop="asset_type" label="规格类型" min-width="160" />
          <el-table-column label="操作" width="280">
            <template #default="{ row }">
              <el-button size="small" type="primary" plain @click="openDetail(row.asset_id)">详情</el-button>
            <el-button size="small" type="info" plain @click="openViewMetrics(row)">查看指标</el-button>
            <el-button size="small" type="primary" plain :disabled="!isAdmin" @click="openEditDialog(row)">编辑</el-button>
            <el-button size="small" type="warning" :disabled="!isAdmin" @click="openMetricsDialog(row)">配置指标</el-button>
            <el-button size="small" type="success" plain :disabled="!isAdmin || row.asset_category !== '整机'" @click="openProductsDialog(row)">绑定制品</el-button>
            <el-button size="small" type="danger" plain :disabled="!isAdmin" @click="deleteAsset(row)">删除</el-button>
            </template>
          </el-table-column>
      </el-table>
      <el-empty v-if="!filteredAssets.length" :description="`${currentSectionMeta.empty}，请先新增${currentSectionMeta.type}`">
        <el-button :type="currentSectionMeta.tag === 'primary' ? 'primary' : 'success'" @click="openCreateDialog(currentSectionMeta.type)">
          新增{{ currentSectionMeta.type }}
        </el-button>
      </el-empty>
    </template>

    <div v-else class="detail-view">
      <div class="detail-toolbar">
        <el-button plain @click="closeDetail">返回台账</el-button>
      </div>

      <section class="detail-hero">
        <div>
          <div class="panel-kicker">ASSET DETAIL</div>
          <h2>{{ detailAsset.asset_name }}</h2>
          <p>{{ detailAsset.asset_code }} · {{ detailAsset.asset_type || '未配置规格类型' }}</p>
        </div>
        <div class="detail-badges">
          <el-tag :type="detailAsset.asset_category === '整机' ? 'primary' : 'success'" size="large">
            {{ detailAsset.asset_category }}
          </el-tag>
          <el-tag type="info" size="large">指标 {{ detailAsset.metric_count }}</el-tag>
          <el-tag type="warning" size="large">记录 {{ recordSessions.length }}</el-tag>
          <el-tag v-if="detailAsset.asset_category === '整机'" type="success" size="large">制品 {{ detailAsset.product_count }}</el-tag>
        </div>
      </section>

      <div class="detail-grid">
        <section class="detail-card">
          <div class="detail-card-title">基础信息</div>
          <div class="detail-stats">
            <div><span>规格类型</span><strong>{{ detailAsset.asset_type || '-' }}</strong></div>
            <div><span>最近记录</span><strong>{{ formatTime(detailAsset.latest_record_at) }}</strong></div>
          </div>
          <div style="margin-top: 14px">
            <el-button type="primary" plain size="small" :disabled="!isAdmin" @click="openEditDialog(detailAsset)">编辑资产信息</el-button>
          </div>
        </section>

        <section class="detail-card">
          <div class="detail-card-header">
            <div class="detail-card-title">已配指标</div>
            <el-button type="primary" size="small" :disabled="!isAdmin" @click="openMetricsDialog(detailAsset)">配置指标</el-button>
          </div>
          <el-table :data="detailAsset.metrics || []" stripe max-height="320">
            <el-table-column prop="category_level_1" label="一级分类" width="120" />
            <el-table-column prop="category_level_2" label="二级类型" width="150" />
            <el-table-column prop="metric_name" label="指标名称" />
            <el-table-column prop="baseline_value" label="初始值" width="90" />
            <el-table-column prop="failure_value" label="失效值" width="90" />
            <el-table-column prop="upper_limit" label="上限" width="90" />
            <el-table-column prop="lower_limit" label="下限" width="90" />
            <el-table-column prop="unit" label="单位" width="80" />
          </el-table>
        </section>

        <section v-if="detailAsset.asset_category === '整机'" class="detail-card">
          <div class="detail-card-header">
            <div class="detail-card-title">加工制品配置</div>
            <el-button type="success" size="small" :disabled="!isAdmin" @click="openProductsDialog(detailAsset)">绑定制品</el-button>
          </div>
          <el-table :data="detailAsset.products || []" stripe max-height="320">
            <el-table-column prop="product_code" label="产品编号" width="120" />
            <el-table-column prop="product_name" label="产品名称" min-width="160" />
            <el-table-column prop="total_quantity" label="计划数量" width="100" />
            <el-table-column prop="process_note" label="工艺/批次说明" show-overflow-tooltip />
          </el-table>
        </section>
      </div>

      <div class="record-grid">
        <section class="detail-card">
          <div class="detail-card-title">近期测试记录</div>
          <el-table :data="recentRecordSessions" stripe>
            <el-table-column prop="created_at" label="记录时间" width="180">
              <template #default="{ row }">{{ formatTime(row.created_at) }}</template>
            </el-table-column>
            <el-table-column prop="metric_count" label="指标数" width="90" />
            <el-table-column prop="summary" label="指标摘要" show-overflow-tooltip />
            <el-table-column label="详情" width="90">
              <template #default="{ row }">
                <el-button type="primary" text @click="openRecordDialog(row)">详情</el-button>
              </template>
            </el-table-column>
          </el-table>
        </section>

        <section class="detail-card">
          <div class="detail-card-title">全部测试记录</div>
          <el-table :data="recordSessions" stripe max-height="420">
            <el-table-column prop="created_at" label="记录时间" width="180">
              <template #default="{ row }">{{ formatTime(row.created_at) }}</template>
            </el-table-column>
            <el-table-column prop="metric_count" label="指标数" width="90" />
            <el-table-column prop="summary" label="指标摘要" show-overflow-tooltip />
            <el-table-column label="详情" width="90">
              <template #default="{ row }">
                <el-button type="primary" text @click="openRecordDialog(row)">详情</el-button>
              </template>
            </el-table-column>
          </el-table>
        </section>
      </div>
    </div>

    <el-dialog v-model="assetDialogVisible" :title="isEditAsset ? '编辑设备资产' : '新增设备资产'" width="520px">
      <el-form :model="assetForm" label-width="92px">
        <el-form-item label="资产类型">
          <el-radio-group v-model="assetForm.asset_category">
            <el-radio label="整机">整机</el-radio>
            <el-radio label="部件">部件</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="设备编号"><el-input v-model="assetForm.asset_code" /></el-form-item>
        <el-form-item label="设备名称"><el-input v-model="assetForm.asset_name" /></el-form-item>
        <el-form-item label="规格类型"><el-input v-model="assetForm.asset_type" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="assetDialogVisible = false">取消</el-button>
        <el-button type="primary" :disabled="!isAdmin" @click="saveAsset">保存</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="bindDialogVisible"
      :title="`配置指标 - ${currentAsset?.asset_code || ''}`"
      width="min(1120px, calc(100vw - 32px))"
      top="4vh"
      append-to-body
      destroy-on-close
      class="metric-config-dialog"
    >
      <div class="metric-config-note">
        <strong>配置说明</strong>
        <span v-if="isPartAsset">部件指标需配置出厂标准值、失效阈值和单循环小时，用于保持度/保持时间分支判定。</span>
        <span v-else>几何、位置与加工精度均配置出厂精度、失效精度；权重用于指标层和准则层逐级汇总。</span>
      </div>
      <div class="metric-list metric-config-list">
        <el-checkbox-group v-model="selectedMetricIds">
          <div v-for="metric in filteredMetrics" :key="metric.metric_id" class="metric-row">
            <div class="metric-row-header">
              <el-checkbox :value="metric.metric_id" :label="metric.metric_id">
                <el-tag size="small" :type="isProcessMetric(metric) ? 'success' : 'info'">{{ metric.category_level_1 }}</el-tag>
                <span class="metric-name">{{ metric.metric_name }}</span>
              </el-checkbox>
              <span v-if="selectedMetricIds.includes(metric.metric_id)" class="metric-config-state">已纳入评估</span>
            </div>
            <div v-if="selectedMetricIds.includes(metric.metric_id)" class="metric-inputs">
              <label v-if="isPartAsset || !isProcessMetric(metric)" class="metric-field">
                <span>出厂/标准值 δ0</span>
                <el-input v-model="metricBaselines[metric.metric_id]" placeholder="例如 5" size="small" />
              </label>
              <label v-if="isPartAsset || !isProcessMetric(metric)" class="metric-field">
                <span>失效阈值 δth</span>
                <el-input v-model="metricFailures[metric.metric_id]" placeholder="例如 15" size="small" />
              </label>
              <label v-if="!isPartAsset && isProcessMetric(metric)" class="metric-field">
                <span>出厂精度</span>
                <el-input v-model="metricLowerLimits[metric.metric_id]" placeholder="例如 8" size="small" />
              </label>
              <label v-if="!isPartAsset && isProcessMetric(metric)" class="metric-field">
                <span>失效精度</span>
                <el-input v-model="metricLimits[metric.metric_id]" placeholder="例如 25" size="small" />
              </label>
              <label v-if="!isPartAsset" class="metric-field">
                <span>指标层权重</span>
                <el-input v-model="metricIndicatorWeights[metric.metric_id]" placeholder="例如 0.25" size="small" />
              </label>
              <label v-if="!isPartAsset" class="metric-field">
                <span>准则层权重</span>
                <el-input v-model="metricCriterionWeights[metric.metric_id]" placeholder="例如 0.25" size="small" />
              </label>
              <label v-if="!isPartAsset && !isProcessMetric(metric)" class="metric-field">
                <span>归一化理想值</span>
                <el-input v-model="metricIdeals[metric.metric_id]" placeholder="留空使用规范值" size="small" />
              </label>
              <label v-if="!isPartAsset && !isProcessMetric(metric)" class="metric-field">
                <span>归一化极限值</span>
                <el-input v-model="metricExtremes[metric.metric_id]" placeholder="留空使用规范值" size="small" />
              </label>
              <label v-if="isPartAsset" class="metric-field">
                <span>单循环小时</span>
                <el-input v-model="metricCycleHours[metric.metric_id]" placeholder="例如 8" size="small" />
              </label>
              <label class="metric-field">
                <span>数据单位</span>
                <el-select v-model="metricUnits[metric.metric_id]" placeholder="单位" size="small">
                  <el-option v-for="unit in unitOptions" :key="unit" :label="unit" :value="unit" />
                </el-select>
              </label>
            </div>
          </div>
        </el-checkbox-group>
      </div>
      <template #footer>
        <el-button @click="bindDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveMetrics">保存配置</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="viewMetricsDialogVisible" :title="`指标一览 - ${currentAsset?.asset_code || ''}`" width="720px">
      <el-table :data="currentMetrics" stripe max-height="420">
        <el-table-column prop="category_level_1" label="精度大类" width="120" />
        <el-table-column prop="category_level_2" label="精度类型" width="160" />
        <el-table-column prop="metric_name" label="指标名称" />
        <el-table-column prop="baseline_value" label="初始值" width="90" />
        <el-table-column prop="failure_value" label="失效值" width="90" />
        <el-table-column prop="unit" label="单位" width="80" />
      </el-table>
    </el-dialog>

    <el-dialog
      v-model="productDialogVisible"
      :title="`绑定加工制品 - ${currentAsset?.asset_code || ''}`"
      width="min(920px, calc(100vw - 32px))"
      top="4vh"
      append-to-body
      destroy-on-close
      class="metric-config-dialog"
    >
      <div class="metric-config-note">
        <strong>配置说明</strong>
        <span>选择该设备参与加工精度评价的制品，并填写计划/试制数量和生产说明。制品对应的加工精度指标在参数设置中维护。</span>
      </div>
      <div class="metric-list metric-config-list product-bind-list">
        <el-checkbox-group v-model="selectedProductIds">
          <div v-for="product in products" :key="product.product_id" class="metric-row">
            <div class="metric-row-header">
              <el-checkbox :value="product.product_id" :label="product.product_id">
                <el-tag size="small" type="success">{{ product.product_code }}</el-tag>
                <span class="metric-name">{{ product.product_name }}</span>
              </el-checkbox>
              <span v-if="selectedProductIds.includes(product.product_id)" class="metric-config-state">已绑定</span>
            </div>
            <div v-if="selectedProductIds.includes(product.product_id)" class="metric-inputs product-bind-inputs">
              <label class="metric-field">
                <span>计划/试制数量</span>
                <el-input v-model="productTotalQuantity[product.product_id]" placeholder="例如 50" size="small" />
              </label>
              <label class="metric-field product-note-field">
                <span>工艺或生产说明</span>
                <el-input v-model="productProcessNotes[product.product_id]" placeholder="例如 t1-t10 批次测试" size="small" />
              </label>
            </div>
          </div>
        </el-checkbox-group>
      </div>
      <template #footer>
        <el-button @click="productDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveProducts">保存配置</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="recordDialogVisible"
      title="测试记录详情"
      width="900px"
      align-center
      destroy-on-close
      append-to-body
      class="record-detail-dialog reliability-dialog"
    >
      <div v-if="currentRecordSession" class="record-dialog-shell">
        <div class="record-dialog-meta">
          <span class="record-meta-chip">记录时间：{{ formatTime(currentRecordSession.created_at) }}</span>
          <span class="record-meta-chip">指标数：{{ currentRecordSession.metric_count }}</span>
        </div>
        <el-table :data="editableSessionRows" stripe max-height="420">
          <el-table-column prop="metric_name" label="指标名称" min-width="240" />
          <el-table-column prop="value_type" label="录入方式" width="100" />
          <el-table-column label="记录值" min-width="260">
            <template #default="{ row }">
              <el-input-number
                v-if="recordEditing && row.value_type === '单值'"
                v-model="row.raw_data.val"
                :precision="4"
                :step="0.001"
                style="width: 100%"
              />
              <el-input
                v-else-if="recordEditing"
                v-model="row.samplesText"
                type="textarea"
                :rows="2"
                placeholder="多个数值用逗号或空格分隔"
              />
              <span class="record-value-text">{{ row.value_type === '单值' ? row.raw_data.val : row.samplesText }}</span>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <template #footer>
        <el-button v-if="!recordEditing" @click="recordDialogVisible = false">关闭</el-button>
        <el-button v-if="!recordEditing" type="primary" :disabled="!isAdmin" @click="enableRecordEdit">修改</el-button>
        <el-button v-if="recordEditing" @click="recordEditing = false">取消</el-button>
        <el-button v-if="recordEditing" type="primary" :loading="recordSaving" @click="saveRecordSession">确认</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.ledger-toolbar,
.panel-header,
.detail-toolbar,
.detail-stats,
.detail-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.toolbar-left,
.toolbar-right,
.detail-badges,
.record-dialog-meta {
  display: flex;
  align-items: center;
  gap: 12px;
}

.record-dialog-shell {
  display: grid;
  gap: 18px;
}

.record-meta-chip {
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(239, 244, 251, 0.95);
  color: #5c6f8f;
  font-size: 13px;
  line-height: 1;
  border: 1px solid rgba(216, 226, 240, 0.9);
}

.record-value-text {
  color: #33445d;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
}

.ledger-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
}

.ledger-panel,
.detail-card,
.detail-hero {
  border-radius: 30px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  background: linear-gradient(145deg, rgba(250, 252, 255, 0.96), rgba(234, 242, 251, 0.9));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    inset 0 0 0 6px rgba(255, 255, 255, 0.2),
    0 18px 38px rgba(111, 133, 166, 0.14);
}

.ledger-panel {
  padding: 18px;
}

.panel-kicker {
  margin-bottom: 6px;
  color: #6f86a5;
  font-size: 11px;
  letter-spacing: 0.24em;
}

.panel-header h3,
.detail-hero h2 {
  margin: 0;
  color: #203553;
}

.panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.equipment-card {
  min-height: 164px;
  padding: 15px 16px;
  border-radius: 24px;
  cursor: pointer;
  background: linear-gradient(150deg, rgba(255, 255, 255, 0.92), rgba(228, 238, 248, 0.84));
  border: 1px solid rgba(255, 255, 255, 0.94);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.88), 0 14px 28px rgba(111, 133, 166, 0.12);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.equipment-card:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 18px 34px rgba(99, 124, 160, 0.18);
}

.card-top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.asset-icon {
  width: 38px;
  height: 38px;
  border-radius: 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #6f88a6;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(234, 242, 250, 0.84));
}

.more-btn {
  margin-left: auto;
}

.asset-code {
  margin-top: 14px;
  color: #7c8aa0;
  font-size: 12px;
}

.equipment-card h3 {
  margin: 6px 0 14px;
  color: #203553;
  font-size: 17px;
}

.asset-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.asset-meta span,
.detail-stats span {
  display: block;
  margin-bottom: 4px;
  color: #7d8ca3;
  font-size: 12px;
}

.asset-meta strong,
.detail-stats strong {
  color: #203553;
}

.detail-view {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.detail-hero {
  padding: 26px 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
}

.detail-hero p {
  margin: 10px 0 0;
  color: #6c7e96;
}

.detail-grid,
.record-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
}

.detail-card {
  padding: 20px;
}

.detail-card-title {
  color: #203553;
  font-weight: 700;
}

.detail-card-header {
  margin-bottom: 16px;
}

.detail-stats {
  align-items: stretch;
}

.detail-stats > div {
  flex: 1;
  padding: 18px;
  border-radius: 20px;
  background: rgba(244, 248, 252, 0.8);
}

.metric-row {
  padding: 14px 16px;
  border-bottom: 1px solid rgba(222, 230, 240, 0.72);
  border-radius: 18px;
  transition: background 0.2s ease, box-shadow 0.2s ease;
}

.metric-row:has(.metric-inputs) {
  margin-bottom: 10px;
  background: linear-gradient(145deg, rgba(248, 251, 255, 0.96), rgba(237, 244, 251, 0.86));
  box-shadow: inset 0 0 0 1px rgba(218, 229, 242, 0.72);
}

.metric-row-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-width: 0;
}

.metric-row-header :deep(.el-checkbox) {
  min-width: 0;
  height: auto;
  white-space: normal;
}

.metric-row-header :deep(.el-checkbox__label) {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  white-space: normal;
}

.metric-name {
  color: #39506e;
  line-height: 1.45;
  word-break: break-word;
}

.metric-config-state {
  flex: none;
  color: #6d88aa;
  font-size: 12px;
}

.metric-inputs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px 14px;
  margin-top: 14px;
  padding: 14px;
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.68);
}

.metric-field {
  display: grid;
  gap: 7px;
  min-width: 0;
}

.metric-field > span {
  color: #6d7f98;
  font-size: 12px;
  line-height: 1;
}

.metric-field :deep(.el-select) {
  width: 100%;
}

.product-bind-inputs {
  grid-template-columns: minmax(160px, 0.6fr) minmax(260px, 1.4fr);
}

.metric-config-note {
  display: flex;
  gap: 12px;
  margin-bottom: 14px;
  padding: 12px 16px;
  border: 1px solid rgba(207, 222, 239, 0.88);
  border-radius: 16px;
  color: #627590;
  background: linear-gradient(135deg, rgba(238, 246, 255, 0.96), rgba(246, 251, 255, 0.9));
  font-size: 13px;
  line-height: 1.65;
}

.metric-config-note strong {
  flex: none;
  color: #304a6b;
}

.metric-config-list {
  max-height: calc(84vh - 170px);
  overflow-y: auto;
  overflow-x: hidden;
  padding-right: 6px;
}

:deep(.metric-config-dialog .el-dialog__body) {
  padding-top: 10px;
  overflow: hidden;
}

.record-dialog-meta {
  margin-bottom: 14px;
  color: #70839d;
  font-size: 13px;
}

@media (max-width: 1280px) {
  .ledger-columns,
  .detail-grid,
  .record-grid {
    grid-template-columns: 1fr;
  }

  .metric-inputs {
    grid-template-columns: repeat(2, minmax(120px, 1fr));
  }

  .product-bind-inputs {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 680px) {
  .metric-inputs {
    grid-template-columns: 1fr;
  }

  .metric-row {
    padding: 12px;
  }

  .metric-row-header {
    align-items: flex-start;
  }

  .metric-config-state {
    display: none;
  }

  .metric-config-note {
    display: grid;
    gap: 4px;
  }
}
</style>
