<template>
  <div class="assembly-dashboard"
    :style="{ width: `${style.width}px`, height: `${style.height}px`, transform: style.transform }">
    <div class="dashboard-shell">
      <header class="dashboard-header">
        <div class="brand"><img class="brand-logo" :src="clientLogoUrl" alt="RENLY" /></div>
        <h1>质检测试任务看板</h1>
        <div class="current-time">{{ currentTime }}</div>
      </header>
      <main class="dashboard-content">
        <section class="summary-row">
          <article v-for="item in summaryCards" :key="item.title" class="panel summary-card" :class="item.className">
            <div>
              <div class="summary-title">{{ item.title }}</div>
              <div v-if="item.metrics" class="summary-metrics">
                <div v-for="metric in item.metrics" :key="metric.label" class="summary-metric">
                  <span>{{ metric.label }}</span>
                  <b>{{ metric.value }}</b>
                  <small>{{ item.unit }}</small>
                </div>
              </div>
              <div v-else class="summary-body">
                <img class="summary-icon" :src="item.icon" :alt="item.title" />
                <div class="summary-value" :class="item.valueClass"><span>{{ item.value }}</span><small
                    v-if="item.unit">{{ item.unit }}</small></div>
              </div>
            </div>
            <div v-if="item.people" class="people-list">
              <div v-for="person in item.people" :key="person.name"><span>{{ person.name }}</span><b>{{ person.group
                  }}</b></div>
            </div>
          </article>
        </section>
        <section class="main-grid">
          <div class="left-column">
            <article class="panel table-panel test-summary-panel">
              <div class="panel-caption">测试任务汇总</div>
              <div class="summary-wrap">
                <table class="test-summary-table">
                  <thead>
                    <tr>
                      <th class="summary-group-th">项目</th>
                      <th class="summary-product-th">产品</th>
                      <th class="summary-metric-th">指标</th>
                      <th class="summary-count-th">数量</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="row in testSummaryRows" :key="`${row.groupKey}-${row.productKey}-${row.metricKey}`">
                      <td v-if="row.groupRowspan" :rowspan="row.groupRowspan" class="summary-group-cell">
                        <div class="summary-total">
                          <span>{{ row.group }}</span>
                          <strong>{{ row.groupTotal }}</strong>
                        </div>
                      </td>
                      <td v-if="row.productRowspan" :rowspan="row.productRowspan" class="summary-product-cell">
                        <div class="summary-product">
                          <img class="summary-product-image" :src="row.productImage" alt="" />
                          <div class="summary-product-text">
                            <span>{{ row.product }}</span>
                            <strong>{{ row.productTotal }}</strong>
                          </div>
                        </div>
                      </td>
                      <td class="summary-metric-cell" :class="`metric-${row.metricKey}`">{{ row.metric }}</td>
                      <td class="summary-count-cell" :class="`metric-${row.metricKey}`">{{ row.value }}</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </article>
            <article class="panel table-panel">
              <div class="panel-caption">已完工任务</div>
              <div class="scroll-wrap">
                <table>
                  <thead>
                    <tr>
                      <th class="idx-th">序号</th>
                      <th v-for="c in doneColumns" :key="c.key">{{ c.label }}</th>
                    </tr>
                  </thead>
                  <tbody :style="doneScrollStyle">
                    <tr v-for="(r, i) in doneDisplayRows" :key="i">
                      <td class="idx-td">{{ r._idx }}</td>
                      <td v-for="c in doneColumns" :key="c.key" :class="c.key === 'passRate' ? r.rateClass : ''">{{ r[c.key] }}</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </article>
          </div>
          <aside class="right-column">
            <article class="panel table-panel">
              <div class="panel-caption">发货任务列表</div>
              <div class="scroll-wrap">
                <table>
                  <thead>
                    <tr>
                      <th class="idx-th">序号</th>
                      <th v-for="c in taskColumns2" :key="c.key">{{ c.label }}</th>
                    </tr>
                  </thead>
                  <tbody :style="deliveryScrollStyle">
                    <tr v-for="(r, i) in deliveryDisplayRows" :key="i">
                      <td class="idx-td">{{ r._idx }}</td>
                      <td v-for="c in taskColumns2" :key="c.key">{{ r[c.key] }}</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </article>
            <article class="panel table-panel task-panel">
              <div class="panel-caption">测试装配任务列表</div>
              <div class="scroll-wrap">
                <table>
                  <thead>
                    <tr>
                      <th class="idx-th">序号</th>
                      <th v-for="c in taskColumns" :key="c.key" :style="{ width: c.width }">{{ c.label }}</th>
                    </tr>
                  </thead>
                  <tbody :style="taskScrollStyle">
                    <tr v-for="(r, i) in taskDisplayRows" :key="i" :class="{ warning: r.urgentQty > 0 }">
                      <td class="idx-td">{{ r._idx }}</td>
                      <td v-for="c in taskColumns" :key="c.key" :style="{ width: c.width }">{{ r[c.key] }}</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </article>
          </aside>
        </section>
      </main>
    </div>
  </div>
</template>

<script setup>
import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
import assemblyImage from '@/assets/dashboard/机械.png'
import electricImage from '@/assets/dashboard/电气.png'
import otherImage from '@/assets/dashboard/其他.png'
import valveImage from '@/assets/dashboard/阀.png'
const CreateData = inject('CreateData')
const ExecDatabase = inject('ExecDatabase')
defineOptions({ name: 'AssemblyCenterTaskDashboard' })

const now = ref(new Date())
let timer = null
let resizeHandler = null
let scrollTimers = []
const style = reactive({ width: 1920, height: 1080, transform: 'scaleY(1) scaleX(1) translate(-50%, -50%)' })
const setScale = () => { const s = getScale(); style.transform = `scaleY(${s.y}) scaleX(${s.x}) translate(-50%, -50%)` }
const getScale = () => ({ x: window.innerWidth / style.width, y: window.innerHeight / style.height })
const pad = v => String(v).padStart(2, '0')
const currentTime = computed(() => `${now.value.getFullYear()}-${pad(now.value.getMonth() + 1)}-${pad(now.value.getDate())} ${pad(now.value.getHours())}:${pad(now.value.getMinutes())}:${pad(now.value.getSeconds())}`)
const clientLogoUrl = './public/ClientLogo.png'
const icon = name => `./public/svg/${name}.svg`
const tableData = ref([])
const getFirstRow = rows => {
  if (Array.isArray(rows) && rows.length > 0) {
    return rows[0]
  }
  return {}
}
onMounted(() => {
  startClock();
  setScale();
  resizeHandler = setScale;
  window.addEventListener('resize', resizeHandler)
  searchDashboardData()
  startAllScroll()
  setInterval(function(){
    searchDashboardData()
  },600000)
  
})
onUnmounted(() => {
  if (timer) window.clearInterval(timer);
  if (resizeHandler) window.removeEventListener('resize', resizeHandler)
  stopAllScroll()
})

// ============ 滚动数据 ============
const deliveryRows = ref([])
const taskRows = ref([])
const doneRows = ref([])
const rawTestAssemblyRows = ref([])
const stagnationRows = ref([])

// 每个列表的滚动偏移
const deliveryOffset = ref(0)
const taskOffset = ref(0)
const doneOffset = ref(0)

// 可见行数
const VISIBLE_ROWS = {
  delivery: 8,
  task: 7,
  done: 7
}

const testSummaryGroups = [
  {
    key: 'valve',
    label: '部件类',
    products: [
      { key: 'valveMain', label: '阀', image: valveImage },
      { key: 'valveOther', label: '其他', image: otherImage }
    ]
  },
  {
    key: 'system',
    label: '系统类',
    products: [
      { key: 'systemElectric', label: '电气', image: electricImage },
      { key: 'systemAssembly', label: '机械', image: assemblyImage }
    ]
  }
]

const testSummaryMetrics = [
  { key: 'urgent', label: '加急' },
  { key: 'stagnation', label: '滞留' }
]

// 生成带序号和循环滚动的显示行
const makeDisplayRows = (rows, offset, visibleCount, loopFill = true) => {
  if (!rows || rows.length === 0) return []
  const len = rows.length
  const count = loopFill ? visibleCount : Math.min(visibleCount, len)
  const result = []
  for (let i = 0; i < count; i++) {
    const idx = (offset + i) % len
    result.push({ ...rows[idx], _idx: idx + 1 })
  }
  return result
}

const deliveryDisplayRows = computed(() => makeDisplayRows(deliveryRows.value, deliveryOffset.value, VISIBLE_ROWS.delivery, false))
const taskDisplayRows = computed(() => makeDisplayRows(taskRows.value, taskOffset.value, VISIBLE_ROWS.task, false))
const doneDisplayRows = computed(() => makeDisplayRows(doneRows.value, doneOffset.value, VISIBLE_ROWS.done))
const testSummaryRows = computed(() => {
  const rows = []

  testSummaryGroups.forEach(group => {
    const groupTotal = getTestGroupTotal(group)

    group.products.forEach(product => {
      const productTotal = getTestProductTotal(product.key)

      testSummaryMetrics.forEach(metric => {
        rows.push({
          group: group.label,
          groupKey: group.key,
          groupTotal,
          groupRowspan: rows.filter(item => item.groupKey === group.key).length === 0
            ? group.products.length * testSummaryMetrics.length
            : 0,
          product: product.label,
          productKey: product.key,
          productImage: product.image,
          productTotal,
          productRowspan: metric.key === testSummaryMetrics[0].key ? testSummaryMetrics.length : 0,
          metric: metric.label,
          metricKey: metric.key,
          value: countTestSummaryRows(product.key, metric.key)
        })
      })
    })
  })

  return rows
})

// 滚动样式（平滑过渡）
const deliveryScrollStyle = computed(() => ({ transition: 'none' }))
const taskScrollStyle = computed(() => ({ transition: 'none' }))
const doneScrollStyle = computed(() => ({ transition: 'none' }))

// 启动单个列表滚动
const startScroll = (rowsRef, offsetRef) => {
  const id = window.setInterval(() => {
    if (rowsRef.value.length > 0) {
      offsetRef.value = (offsetRef.value + 1) % rowsRef.value.length
    }
  }, 2000)
  scrollTimers.push(id)
  return id
}

const startScrollWhenOverflow = (rowsRef, offsetRef, visibleCount) => {
  const id = window.setInterval(() => {
    if (rowsRef.value.length > visibleCount) {
      offsetRef.value = (offsetRef.value + 1) % rowsRef.value.length
    } else if (offsetRef.value !== 0) {
      offsetRef.value = 0
    }
  }, 2000)
  scrollTimers.push(id)
  return id
}

const startAllScroll = () => {
  startScrollWhenOverflow(deliveryRows, deliveryOffset, VISIBLE_ROWS.delivery)
  startScrollWhenOverflow(taskRows, taskOffset, VISIBLE_ROWS.task)
  startScroll(doneRows, doneOffset)
}

const stopAllScroll = () => {
  scrollTimers.forEach(id => window.clearInterval(id))
  scrollTimers = []
}

// ============ 数据查询 ============
const searchDashboardData = () => {
  searchTestAssemblyTaskData()
  searchTestAssemblyTaskListData()
  searchQualityTimelinessData()
  searchStagnationData()
  searchDoneTaskData()
  searchDeliveryData()
}
const searchTestAssemblyTaskData = () => {
  const param = [
    ['任务类型', '全部'],
    ['生产订单', ''],
    ['销售订单', ''],
    ['物料名称', ''],
    ['物料编码', '']
  ]
  queryDashboardData('质检测试看板_测试装配任务_查询', applyTestAssemblyTaskData, param)
}
const searchTestAssemblyTaskListData = () => {
  queryDashboardData('质量管理_测试装配任务_查询2', applyTaskData)
}
const searchQualityTimelinessData = () => {
  const param = [
    ['任务类型', '全部'],
    ['生产订单', ''],
    ['销售订单', ''],
    ['物料名称', ''],
    ['物料编码', '']
  ]
  queryDashboardData('质量管理_测试装配任务_质检及时率', applyQualityTimelinessData, param)
}
const searchDoneTaskData = () => {
  const param = [
    ['任务类型', '全部'],
    ['生产订单', ''],
    ['销售订单', ''],
    ['物料名称', ''],
    ['物料编码', '']
  ]
  queryDashboardData('质量管理_测试装配任务_完成查询', applyDoneTaskData, param)
}
const searchStagnationData = () => {
  const param = [
    ['合同号', ''],
    ['订单号', ''],
    ['零件编号', ''],
    ['零件名称', ''],
    ['完工日期_Start', ''],
    ['完工日期_End', ''],
    ['检测日期_Start', ''],
    ['检测日期_End', ''],
    ['检测结果', ''],
    ['检测人', ''],
    ['检测类别', ''],
    ['属性', '2']
  ]
  queryDashboardData('质量管理_及时检验报表_查询', applyStagnationData, param)
}
const searchDeliveryData = () => {
  queryDashboardData('质检测试看板_质检发货状态查询', applyDeliveryData)
}
const applyTestAssemblyTaskData = rows => {
  const sortedRows = sortTestAssemblyTaskRows(rows)
  rawTestAssemblyRows.value = sortedRows
  const executableRows = sortedRows.filter(isInspectionUnfinished)

  summaryCards[0].value = executableRows.filter(isReworkTask).length
  summaryCards[1].value = sortedRows.filter(isUrgentTask).length
  summaryCards[4].value = sortedRows.reduce((sum, item) => sum + getNumber(item.异常未关闭数 || item.测试装配异常未关闭总数), 0)
}
const applyQualityTimelinessData = rows => {
  const row = getFirstRow(rows)
  summaryCards[3].value = `${getNumber(row.质检及时率).toFixed(2)}`
}
const applyStagnationData = rows => {
  stagnationRows.value = rows
  summaryCards[2].value = rows.length
}
const applyDeliveryData = rows => {
  deliveryRows.value = rows.map(item => {
    let requiredDate = ''
    if (item.要求发货日期) {
      // 如果是字符串
      if (typeof item.要求发货日期 === 'string') {
        requiredDate = item.要求发货日期.split(' ')[0]
      } 
      // 如果是 Date 对象
      else if (item.要求发货日期 instanceof Date) {
        requiredDate = item.要求发货日期.toISOString().split('T')[0]
      }
      // 如果是其他格式
      else {
        const dateStr = String(item.要求发货日期)
        requiredDate = dateStr.split(' ')[0]
      }
    }
  return {
    productionOrder: item.订单编号,
    salesOrder: item.合同号 || '',
    materialName: item.物料描述 || '',
    materialCode: item.物料编号 || '',
    assignQty: item.交货数量,
    taskdate: requiredDate,
    accumulatedHours: formatWorkMinutes(item.合同装配工时),
  }
  })
}
const applyDoneTaskData = rows => {
  doneRows.value = rows.map(item => ({
    productionOrder: item.生产订单?.toString() || item.计划号?.toString() || '',
    materialName: item.物料名称 || item.零件名称 || '',
    materialCode: item.物料编码 || item.零件编码 || '',
    passRate: `${getPassRate(item)}%`,
    rateClass: getPassRate(item) <= 70 ? 'orange-cell' : 'green-cell'
  }))
}

const applyTaskData = rows => {
  taskRows.value = rows.filter(item => getNumber(item.合格数) !== getNumber(item.完成数量)).map(item => ({
    productionOrder: item.生产订单?.toString() || item.订单号?.toString() || item.计划号?.toString() || '',
    salesOrder: item.销售订单 || item.合同号 || '',
    materialName: item.物料名称 || item.物料描述 || item.零件名称 || '',
    materialCode: item.物料编码 || item.物料编号 || item.零件编码 || '',
    taskType: item.任务类型 || (String(item.自制件属性 || item.物料名称 || item.零件名称 || '').includes('系统') ? '系统类' : '阀类'),
    urgentQty: getNumber(item.加急总数 || item.加急数量),
    assignQty: getNumber(item.计划数量 || item.计划生产数 || item.分配数),
    completeQty: getNumber(item.完成数量),
    inboundQty: getNumber(item.入库数量),
    passQty: getNumber(item.合格数),
    operator: item.操作人 || ''
  }))
}
const queryDashboardData = (procedureName, applyData, param = []) => {
  let data
  data = CreateData('11', procedureName, param)
  ExecDatabase(data).then(response => {
    const rows = getResponseRows(response)
    tableData.value = rows
    applyData(rows)
  })
}
const getResponseRows = response => {
  if (response && Array.isArray(response.data)) {
    return response.data
  }
  if (response && response.data && Array.isArray(response.data.result)) {
    return response.data.result
  }
  return []
}

const getNumber = value => {
  if (value === null || value === undefined || value === '') return 0
  const number = Number(String(value).replace(/,/g, ''))
  return Number.isNaN(number) ? 0 : number
}

const formatDate = value => {
  if (!value) return ''
  return String(value).split(' ')[0]
}

const formatWorkMinutes = value => {
  if (value === null || value === undefined || value === '') return ''
  const number = getNumber(value)
  if (number <= 0) return '0'
  const minutes = number / 60
  return Number.isInteger(minutes) ? String(minutes) : minutes.toFixed(2)
}

const getDateTime = value => {
  if (!value) return Infinity
  const time = new Date(String(value).replace(/-/g, '/')).getTime()
  return Number.isNaN(time) ? Infinity : time
}

const getField = (row, fields) => {
  for (const field of fields) {
    if (row[field] !== undefined && row[field] !== null) {
      return row[field]
    }
  }
  return ''
}

const normalizeText = value => {
  if (value === undefined || value === null) {
    return ''
  }
  return String(value).trim()
}

const getMaterialCodeText = item => normalizeText(getField(item, ['零件名称']))

const getAssignTargetText = item => normalizeText(getField(item, ['工位名称', '二次派工']))

const getTaskType = item => item.任务类型 || (String(item.自制件属性 || item.物料名称 || item.零件名称 || '').includes('系统') ? '系统类' : '阀类')

const isInspectionUnfinished = item => getNumber(item.完成数量) > getNumber(item.检验数量)

const isReworkTask = item => String(item.检测说明 || '').includes('返工')

const isUrgentTask = item => getNumber(item.加急总数 || item.加急数量) > 0

const getTaskGroupKey = item => {
  const materialCode = getMaterialCodeText(item)
  if (materialCode.includes('系统')) {
    return 'system'
  }
  if (materialCode.includes('阀')) {
    return 'valve'
  }

  const taskType = normalizeText(getTaskType(item))
  const fallbackText = normalizeText(getField(item, ['自制件属性', '物料名称', '零件名称', '物料描述']))
  return taskType.includes('系统') || fallbackText.includes('系统') ? 'system' : 'valve'
}

const getTaskProductKey = item => {
  const groupKey = getTaskGroupKey(item)

  if (groupKey === 'system') {
    const assignTarget = getAssignTargetText(item)
    return assignTarget.includes('电气装配') || assignTarget.includes('电气') ? 'systemElectric' : 'systemAssembly'
  }

  return getMaterialCodeText(item).includes('阀') ? 'valveMain' : 'valveOther'
}

const countTestProductTotal = productKey => {
  return rawTestAssemblyRows.value.filter(item => getTaskProductKey(item) === productKey).length
}

const countTestSummaryRows = (productKey, metricKey) => {
  const sourceRows = metricKey === 'stagnation' ? stagnationRows.value : rawTestAssemblyRows.value
  return sourceRows
    .filter(item => getTaskProductKey(item) === productKey)
    .filter(item => metricKey === 'urgent' ? isUrgentTask(item) : true)
    .length
}

const getTestProductTotal = productKey => {
  return countTestProductTotal(productKey)
}

const getTestGroupTotal = group => {
  return group.products.reduce((total, product) => total + getTestProductTotal(product.key), 0)
}

const sortTestAssemblyTaskRows = rows => rows.slice().sort((a, b) => {
  const unfinishedA = isInspectionUnfinished(a)
  const unfinishedB = isInspectionUnfinished(b)
  if (unfinishedA !== unfinishedB) return unfinishedA ? -1 : 1
  return getDateTime(a.预计送检日期) - getDateTime(b.预计送检日期)
})

const getPassRate = item => {
  const inspectQty = getNumber(item.检验数量)
  if (inspectQty <= 0) return 100
  return Number(((getNumber(item.检验合格数量) * 100) / inspectQty).toFixed(2))
}

const startClock = () => { now.value = new Date(); timer = window.setInterval(() => { now.value = new Date() }, 1000) }
const svgData = svg => 'data:image/svg+xml;utf8,' + encodeURIComponent(svg)
const svgIcon = (from, to, body) => svgData(
  `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" fill="none">
    <defs>
      <linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="${from}"/>
        <stop offset="1" stop-color="${to}"/>
      </linearGradient>
      <linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="#fff" stop-opacity=".35"/>
        <stop offset="1" stop-color="#fff" stop-opacity="0"/>
      </linearGradient>
      <filter id="glow" x="-55%" y="-55%" width="210%" height="210%"><feGaussianBlur stdDeviation="4" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
    </defs>
    <rect x="7" y="7" width="58" height="58" rx="11" fill="url(#bg)" filter="url(#glow)"/>
    <path d="M14 14h44v20c-10-4-29-4-44 1z" fill="url(#shine)"/>
    <g transform="translate(36 36) scale(1.12) translate(-36 -36)" stroke="#fff" stroke-width="4.1" stroke-linecap="round" stroke-linejoin="round" opacity=".96">${body}</g>
  </svg>`
)
const icons = {
  pending: svgIcon('#37a9ff', '#0862f3', '<rect x="23" y="20" width="26" height="36" rx="4"/><path d="M29 20h14l-3-6h-8l-3 6zM29 34h14M29 43h14"/>'),
  urgent: svgIcon('#ff7469', '#dc2524', '<path d="M21 55h30M25 50V34a11 11 0 0 1 22 0v16M36 13v8M18 21l6 6M54 21l-6 6M15 38h8M49 38h8"/>'),
  cart: svgIcon('#28a8ff', '#0a58ff', '<path d="M16 22h7l5 25h27l5-17H28"/><circle cx="32" cy="56" r="2.8"/><circle cx="52" cy="56" r="2.8"/>'),
  checklist: svgIcon('#49e89e', '#08a86e', '<rect x="21" y="17" width="32" height="42" rx="5"/><path d="M28 35l5 5 12-13M28 49h19"/>'),
  returnDown: svgIcon('#ffb23f', '#fb7418', '<rect x="21" y="23" width="31" height="32" rx="4"/><path d="M36 14v24M27 31l9 9 9-9"/>'),
  returnSales: svgIcon('#9867ff', '#6232e6', '<path d="M51 22H28a10 10 0 0 0 0 20h26M28 14l-11 9 11 9"/><rect x="35" y="37" width="18" height="18" rx="2"/>'),
  finalCheck: svgIcon('#3a95ff', '#0a61e8', '<path d="M36 14l16 7v13c0 11-7 18-16 24-9-6-16-13-16-24V21z"/><path d="M27 37l6 6 13-15"/>'),
  other: svgIcon('#4bd8ff', '#0a88cc', '<path d="M19 26l17-10 17 10-17 10zM19 26v19l17 10 17-10V26M36 36v19"/>'),
  shield: svgIcon('#3a9aff', '#0861e8', '<path d="M36 14l16 7v13c0 11-7 18-16 24-9-6-16-13-16-24V21z"/><path d="M28 37l6 6 12-14"/>'),
  done: svgIcon('#47eaa0', '#0da76b', '<rect x="19" y="19" width="34" height="34" rx="8"/><path d="M27 37l7 7 15-18"/>')
}
const summaryCards = reactive([
  { title: '待协助任务数', value: 0, unit: '条', icon: icons.pending, valueClass: 'red-text' },
  { title: '加急汇总', value: 0, unit: '条', icon: icons.urgent, valueClass: 'red-text' },
  { title: '滞留汇总', value: 0, unit: '条', icon: icons.returnDown, valueClass: 'orange-text' },
  { title: '质检及时率', value: '100.00', icon: icons.finalCheck, valueClass: 'green-text full-value' },
  { title: '异常未关闭消息数', value: 0, unit: '条', icon: icons.urgent, valueClass: 'red-text', className: 'exception-card' }
])
const taskColumns = [
  { label: '生产订单', key: 'productionOrder', width: '92px' },
  { label: '销售订单', key: 'salesOrder', width: '92px' },
  { label: '物料名称', key: 'materialName', width: '220px' },
  { label: '物料编码', key: 'materialCode', width: '260px' },
  { label: '任务类型', key: 'taskType', width: '92px' },
  { label: '加急数', key: 'urgentQty', width: '62px' },
  { label: '计划数', key: 'assignQty', width: '70px' },
  { label: '完成数', key: 'completeQty', width: '70px' },
  { label: '入库数', key: 'inboundQty', width: '70px' },
  { label: '合格数', key: 'passQty', width: '70px' },
  { label: '操作人', key: 'operator', width: '100px' },
  
]
const taskColumns2 = [
  { label: '生产订单', key: 'productionOrder', width: '72px' },
  { label: '销售订单', key: 'salesOrder', width: '92px' },
  { label: '物料名称', key: 'materialName', width: '190px' },
  { label: '物料编码', key: 'materialCode', width: '176px' },
  { label: '数量', key: 'assignQty', width: '176px' },
  { label: '要求发货日期', key: 'taskdate', width: '176px' },
  { label: '累计工时', key: 'accumulatedHours', width: '82px' },
]
const doneColumns = [
  { label: '生产订单', key: 'productionOrder', width: '88px' },
  { label: '物料名称', key: 'materialName', width: '150px' },
  { label: '物料编码', key: 'materialCode', width: '165px' },
  { label: '合格率', key: 'passRate', width: '86px' },
]
</script>

<style scoped lang="scss">
* {
  box-sizing: border-box;
}

.assembly-dashboard {
  position: fixed;
  left: 50%;
  top: 50%;
  width: 1920px;
  height: 1080px;
  transform-origin: 0 0;
  transition: .3s;
  overflow: hidden;
  color: #f3f9ff;
  font-family: 'Microsoft YaHei', Arial, sans-serif;
  background: #07001f;
}

.dashboard-shell {
  width: 100%;
  height: 100%;
  padding: 0 15px 15px;
}

.dashboard-header {
  display: grid;
  grid-template-columns: 336px 1fr 442px;
  align-items: center;
  height: 95px;
  border-bottom: 1px solid rgba(21, 162, 240, .7);
}

.brand {
  width: 300px;
  height: 72px;
  display: flex;
  align-items: center;
  overflow: visible;
  position: relative;
  z-index: 2;
}

.brand-logo {
  width: 224px;
  height: 58px;
  padding: 5px 10px;
  background: #ffffff;
  border-radius: 6px;
  object-fit: contain;
  object-position: left center;
  filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.28));
}
.dashboard-header h1 {
  margin: 0;
  color: #fff;
  font-size: 55px;
  font-weight: 900;
  letter-spacing: .08em;
  text-align: center;
}

.current-time {
  padding-right: 40px;
  color: #eef7ff;
  font-size: 27px;
  text-align: right;
}

.dashboard-content {
  display: grid;
  grid-template-rows: 126px 1fr;
  gap: 17px;
  height: calc(100% - 95px);
  padding-top: 10px;
}

.summary-row {
  display: grid;
  grid-template-columns: 1.28fr 1fr 1fr 1fr .82fr;
  gap: 17px;
}

.main-grid {
  display: grid;
  grid-template-columns: 610px 1fr;
  gap: 17px;
  min-height: 0;
}

.left-column {
  display: grid;
  grid-template-rows: 1fr .88fr;
  gap: 17px;
  min-height: 0;
}

.right-column {
  display: grid;
  grid-template-rows: .92fr 1.08fr;
  gap: 17px;
  min-width: 0;
  min-height: 0;
}

.panel {
  position: relative;
  border: 1px solid rgba(29, 153, 229, .78);
  background: rgba(3, 16, 48, .38);
  box-shadow: inset 0 0 18px rgba(27, 130, 214, .24), 0 0 10px rgba(1, 132, 220, .18);
}

.panel::before {
  position: absolute;
  inset: -1px;
  content: '';
  pointer-events: none;
  background: linear-gradient(90deg, #2bd8ff 0 14px, transparent 14px) left top/14px 2px no-repeat, linear-gradient(180deg, #2bd8ff 0 14px, transparent 14px) left top/2px 14px no-repeat, linear-gradient(270deg, #2bd8ff 0 14px, transparent 14px) right top/14px 2px no-repeat, linear-gradient(180deg, #2bd8ff 0 14px, transparent 14px) right top/2px 14px no-repeat, linear-gradient(90deg, #2bd8ff 0 14px, transparent 14px) left bottom/14px 2px no-repeat, linear-gradient(0deg, #2bd8ff 0 14px, transparent 14px) left bottom/2px 14px no-repeat, linear-gradient(270deg, #2bd8ff 0 14px, transparent 14px) right bottom/14px 2px no-repeat, linear-gradient(0deg, #2bd8ff 0 14px, transparent 14px) right bottom/2px 14px no-repeat;
}

.panel::after {
  position: absolute;
  inset: 0;
  content: '';
  pointer-events: none;
  box-shadow: inset 0 0 12px rgba(43, 216, 255, .12);
}

.summary-card {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  padding: 8px 18px;
}

.summary-card > div:first-child {
  width: 100%;
  min-width: 0;
}

.absence-card {
  justify-content: space-between;
}

.absence-card > div:first-child {
  width: auto;
  padding-right: 22px;
  border-right: 3px solid rgba(238, 247, 255, 0.92);
}

.absence-card .summary-title {
  text-align: left;
}

.absence-card .summary-body {
  display: flex;
  gap: 26px;
  width: auto;
}

.absence-card .summary-value {
  display: flex;
  gap: 8px;
}

.absence-card .summary-value span {
  text-align: left;
}

.executable-card {
  padding: 8px 16px;
}

.executable-card .summary-title {
  margin-bottom: 8px;
  font-size: 21px;
  text-align: left;
}

.summary-metrics {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  align-items: center;
  width: 100%;
}

.summary-metric {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: 22px 48px;
  align-items: baseline;
  min-width: 0;
  padding: 6px 10px 4px;
  color: #fff;
  font-weight: 800;
}

.summary-metric span {
  grid-column: 1 / -1;
  color: #89d4ff;
  font-size: 25px;
  line-height: 22px;
  white-space: nowrap;
}

.summary-metric b {
  color: #18c65b;
  font-size: 57px;
  line-height: 1;
  text-align: right;
  text-shadow: 0 0 10px rgba(24, 198, 91, .32);
}

.summary-metric small {
  color: #fff;
  font-size: 18px;
  font-weight: 700;
  text-align: left;
  white-space: nowrap;
}

.exception-card {
  padding: 8px 12px;
}

.exception-card .summary-title {
  font-size: 18px;
}

.exception-card .summary-body {
  grid-template-columns: 54px 150px;
  column-gap: 16px;
}

.exception-card .summary-icon {
  width: 54px;
  height: 54px;
}

.exception-card .summary-value {
  grid-template-columns: 105px 28px;
}

.exception-card .summary-value span {
  font-size: 48px;
}

.exception-card .summary-value small {
  font-size: 20px;
}

.summary-title {
  margin-bottom: 5px;
  color: #89d4ff;
  font-size: 20px;
  font-weight: 700;
  text-align: left;
}

.summary-body {
  display: grid;
  grid-template-columns: 66px 214px;
  align-items: center;
  justify-content: center;
  column-gap: 26px;
  width: 100%;
}

.summary-icon {
  width: 66px;
  height: 66px;
  object-fit: contain;
}

.summary-value {
  display: grid;
  grid-template-columns: 150px 32px;
  align-items: baseline;
  justify-content: center;
  color: #fff;
  font-weight: 900;
  line-height: 1;
}

.summary-value span {
  font-size: 57px;
  text-align: center;
}

.summary-value small {
  color: #fff;
  font-size: 22px;
  font-weight: 700;
  text-align: left;
}

.full-value span {
  grid-column: 1 / -1;
}

.red-text span {
  color: #ff1e2e;
}

.green-text span {
  color: #18c65b;
}

.orange-text span {
  color: #ff9c12;
}

.absence-card .summary-value::before {
  content: '总数：';
  color: #fff;
  font-size: 20px;
  font-weight: 700;
}

.people-list {
  min-width: 130px;
  color: #fff;
  font-size: 13px;
  line-height: 1.75;
}

.people-list div {
  display: flex;
  gap: 18px;
  justify-content: space-between;
}

.panel-caption {
  height: 38px;
  color: #8cd3ff;
  font-size: 28px;
  font-weight: 600;
  line-height: 38px;
  text-align: center;
}

.table-panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.summary-wrap,
.scroll-wrap {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: 0 9px 10px;
}

table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

th, td {
  height: 48px;
  border: 1px solid rgba(53, 149, 217, .54);
  color: #f1f8ff;
  font-size: 20px;
  line-height: 1.18;
  text-align: center;
  vertical-align: middle;
  white-space: pre-line;
  word-break: break-all;
  background: rgba(4, 24, 57, .44);
}

th {
  height: 44px;
  color: #bde9ff;
  font-weight: 500;
  background: rgba(12, 68, 119, .28);
}

.idx-th {
  width: 44px;
}

.idx-td {
  width: 44px;
  color: #89d4ff;
  font-size: 13px;
}

.task-panel td {
  height: 47px;
}

.test-summary-panel .panel-caption {
  height: 34px;
  font-size: 26px;
  line-height: 34px;
}

.test-summary-panel .summary-wrap {
  padding: 0 7px 7px;
}

.test-summary-table th {
  height: 38px;
  font-size: 18px;
}

.test-summary-table td {
  height: 40px;
  font-size: 18px;
}

.summary-group-th {
  width: 124px;
}

.summary-product-th {
  width: 244px;
}

.summary-metric-th {
  width: 98px;
}

.summary-count-th {
  width: 88px;
}

.summary-group-cell {
  color: #ffffff;
  font-weight: 800;
  background: rgba(7, 74, 112, 0.58);
}

.summary-total {
  display: grid;
  gap: 6px;
  justify-items: center;
  line-height: 1.05;
}

.summary-total span {
  color: #ffffff;
  font-size: 27px;
  font-weight: 900;
}

.summary-total strong {
  color: #ff3040;
  font-size: 34px;
  font-weight: 900;
}

.summary-product-cell {
  background: rgba(7, 45, 82, 0.58);
}

.summary-product {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr);
  align-items: center;
  gap: 6px;
  min-height: 78px;
  padding: 4px 8px;
}

.summary-product-image {
  width: 130px;
  height: 75px;
  object-fit: contain;
}

.summary-product-text {
  display: grid;
  gap: 4px;
  justify-items: center;
  line-height: 1.05;
}

.summary-product-text span {
  color: #ffffff;
  font-size: 24px;
  font-weight: 900;
}

.summary-product-text strong {
  color: #ff3040;
  font-size: 31px;
  font-weight: 900;
}

.summary-metric-cell {
  font-size: 24px;
  font-weight: 900;
}

.summary-count-cell {
  font-size: 31px;
  font-weight: 900;
}

.metric-urgent {
  color: #ff4451;
}

.metric-stagnation {
  color: #ffb13b;
}

.warning td {
  color: #ff4949;
}

.green-cell {
  color: #32ff32;
}

.orange-cell {
  color: #ff7a1a;
}
</style>
