<template>
  <div class="app-container" v-loading="loading">
    <el-row>
      <el-form inline>
        <el-form-item label="逻辑库位">
          <warehouse-select
            v-model="queryParams.warehouseIds"
            multiple
            collapse-tags
            placeholder="请选择仓库/库区/库位"
            style="width: 280px"
            clearable
          />
        </el-form-item>
        <el-form-item label="品质">
          <muti-select
            v-model="queryParams.qualityStatusCsv"
            :options="dict.type.coil_quality_status"
            placeholder="请选择品质"
            clearable
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getList">查询</el-button>
          <el-button @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </el-row>

    <!-- 操作提示 -->
    <el-alert
      v-if="!hintDismissed"
      title="💡 操作提示"
      type="info"
      :closable="true"
      @close="hintDismissed = true"
      show-icon
      style="margin-bottom: 16px"
    >
      <ul class="hint-list">
        <li>点击<strong>柱状图</strong>或<strong>饼图</strong>的库区，可钻取该库区的详情弹窗</li>
        <li>点击下方<strong>库区汇总表格</strong>的任意行，打开详情弹窗</li>
        <li>弹窗内可切换<strong>卷数/净重</strong>指标、配置<strong>品质合并分组</strong>（如 A类 / B类），透视<strong>班组 × 品质</strong>交叉分布</li>
        <li>品质合并配置会自动保存，下次打开无需重新设置</li>
      </ul>
    </el-alert>

    <!-- 汇总统计 -->
    <el-descriptions title="汇总统计" :column="4" border v-if="summary.totalCount > 0">
      <el-descriptions-item label="总钢卷数">{{ summary.totalCount }}</el-descriptions-item>
      <el-descriptions-item label="总净重(t)">{{ summary.totalNetWeight }}</el-descriptions-item>
      <el-descriptions-item label="均重(t)">{{ summary.avgWeight }}</el-descriptions-item>
      <el-descriptions-item label="非空库区数">{{ summary.warehouseCount }}</el-descriptions-item>
    </el-descriptions>

    <!-- ECharts 图表区域 -->
    <el-row :gutter="20" v-if="aggregatedList.length > 0" style="margin-top: 20px">
      <el-col :span="14">
        <div class="chart-card">
          <h3 class="chart-title">各库区总净重 / 均重</h3>
          <div ref="barChartRef" class="chart-box"></div>
        </div>
      </el-col>
      <el-col :span="10">
        <div class="chart-card">
          <h3 class="chart-title">各库区钢卷数量分布</h3>
          <div ref="pieChartRef" class="chart-box"></div>
        </div>
      </el-col>
    </el-row>

    <!-- 汇总明细表格：按库区汇总（点击行可钻取详情） -->
    <div v-if="aggregatedList.length > 0" style="margin-top: 20px">
      <h3>库区汇总明细（点击行查看详情）</h3>
      <el-table
        :data="aggregatedList"
        border
        stripe
        max-height="700"
        style="width: 100%"
        @row-click="handleRowClick"
        row-class-name="clickable-row"
      >
        <el-table-column prop="warehouseName" label="逻辑库位" align="center" min-width="200" show-overflow-tooltip />
        <el-table-column prop="coilCount" label="卷数" align="center" width="100" sortable />
        <el-table-column prop="totalNetWeight" label="总净重(t)" align="center" width="140" sortable />
        <el-table-column prop="avgNetWeight" label="均重(t)" align="center" width="120" />
      </el-table>
    </div>

    <el-empty v-if="!loading && aggregatedList.length === 0" description="暂无数据" />

    <!-- 库区详情弹窗 -->
    <el-dialog
      :title="`${dialogTitle}`"
      :visible.sync="dialogVisible"
      width="90%"
      top="5vh"
      :close-on-click-modal="false"
      @closed="handleDialogClosed"
    >
      <div v-loading="dialogLoading">
        <!-- 数据透视图：班组 × 品质 -->
        <div v-if="dialogPivotTeams.length > 0 && dialogPivotCols.length > 0">
          <div class="pivot-toolbar">
            <h4>班组 × 品质 数据透视图</h4>
            <div class="pivot-actions">
              <el-radio-group v-model="dialogPivotMeasure" size="small" @change="buildDialogPivot">
                <el-radio-button label="count">卷数</el-radio-button>
                <el-radio-button label="weight">净重(t)</el-radio-button>
              </el-radio-group>
              <el-button size="small" type="primary" plain @click="showMergeConfig">品质合并配置</el-button>
              <el-button size="small" @click="resetMergeConfig">重置合并</el-button>
            </div>
          </div>

          <el-table
            :data="dialogPivotRows"
            border
            stripe
            class="pivot-table"
            :header-cell-style="pivotHeaderStyle"
          >
            <el-table-column prop="team" label="班组" align="center" width="100" fixed="left" />
            <el-table-column
              v-for="col in dialogPivotCols"
              :key="col.key"
              :label="col.label"
              align="center"
              :min-width="100"
            >
              <template slot-scope="{ row }">
                <span :style="{ color: getDialogPivotCellColor(row[col.key]) }">
                  {{ formatDialogPivotValue(row[col.key]) }}
                </span>
              </template>
            </el-table-column>
            <el-table-column prop="_total" label="合计" align="center" width="110">
              <template slot-scope="{ row }">
                <strong>{{ formatDialogPivotValue(row._total) }}</strong>
              </template>
            </el-table-column>
          </el-table>

          <!-- 列合计行 -->
          <div class="pivot-footer" v-if="dialogPivotColTotals">
            <span class="footer-label">合计</span>
            <span v-for="col in dialogPivotCols" :key="col.key" class="footer-cell">
              {{ formatDialogPivotValue(dialogPivotColTotals[col.key]) }}
            </span>
            <span class="footer-cell footer-total">
              <strong>{{ formatDialogPivotValue(dialogPivotColTotals._total) }}</strong>
            </span>
          </div>
        </div>

        <!-- 弹窗汇总 -->
        <el-descriptions :column="4" border v-if="dialogSummary.totalCount > 0" style="margin-top: 16px">
          <el-descriptions-item label="钢卷数">{{ dialogSummary.totalCount }}</el-descriptions-item>
          <el-descriptions-item label="总净重(t)">{{ dialogSummary.totalNetWeight }}</el-descriptions-item>
          <el-descriptions-item label="均重(t)">{{ dialogSummary.avgWeight }}</el-descriptions-item>
          <el-descriptions-item label="品质种类">{{ dialogSummary.qualityKinds }}</el-descriptions-item>
        </el-descriptions>

        <!-- 钢卷明细表格 -->
        <div style="display: flex; align-items: center; justify-content: space-between; margin-top: 20px">
          <h4 style="margin: 0">钢卷明细</h4>
          <el-button type="primary" size="small" icon="el-icon-download" @click="handleExportDetail">导出</el-button>
        </div>
        <el-table :data="dialogList" border stripe max-height="500" style="width: 100%">
          <el-table-column prop="enterCoilNo" label="入场钢卷号" align="center" min-width="150" show-overflow-tooltip />
          <el-table-column prop="currentCoilNo" label="当前钢卷号" align="center" min-width="150" show-overflow-tooltip />
          <el-table-column prop="itemName" label="物料名称" align="center" min-width="140" show-overflow-tooltip />
          <el-table-column prop="specification" label="规格" align="center" width="120" />
          <el-table-column prop="netWeight" label="净重(t)" align="center" width="100" />
          <el-table-column prop="qualityStatus" label="品质" align="center" width="80">
            <template slot-scope="scope">
              <dict-tag v-if="scope.row.qualityStatus" :options="dict.type.coil_quality_status" :value="scope.row.qualityStatus" />
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column prop="team" label="班组" align="center" width="80" />
          <el-table-column label="距今" align="center" width="90">
            <template slot-scope="scope">
              {{ timeAgo(scope.row.createTime) }}
            </template>
          </el-table-column>
        </el-table>

        <pagination
          :total="dialogTotal"
          :page.sync="dialogPageNum"
          :limit.sync="dialogPageSize"
          @pagination="fetchDialogList"
        />
      </div>
    </el-dialog>

    <!-- 品质合并配置弹窗 -->
    <el-dialog
      title="品质合并配置"
      :visible.sync="mergeConfigVisible"
      width="700px"
      :close-on-click-modal="false"
    >
      <div class="merge-config-body">
        <div v-for="(group, gi) in mergeGroups" :key="gi" class="merge-group">
          <div class="merge-group-header">
            <el-input v-model="group.name" placeholder="分组名称" size="small" style="width: 120px" />
            <el-button type="text" icon="el-icon-delete" style="color: #F56C6C" @click="removeMergeGroup(gi)" :disabled="mergeGroups.length <= 1">删除</el-button>
          </div>
          <div class="merge-group-tags">
            <el-tag v-for="(qs, qi) in group.qualities" :key="qi" closable size="small" @close="removeQualityFromGroup(gi, qi)">{{ qs }}</el-tag>
            <el-button v-if="unassignedQualities.length > 0" size="mini" icon="el-icon-plus" @click="showAddQuality(gi)">添加品质</el-button>
          </div>
        </div>
        <el-button type="primary" size="small" icon="el-icon-plus" @click="addMergeGroup">新增分组</el-button>
        <div class="unassigned-section" v-if="unassignedQualities.length > 0">
          <h4>未分配品质（将单独成列）</h4>
          <el-tag v-for="qs in unassignedQualities" :key="qs" size="small" type="info">{{ qs }}</el-tag>
        </div>
      </div>
      <span slot="footer">
        <el-button @click="mergeConfigVisible = false">取消</el-button>
        <el-button type="primary" @click="applyMergeConfig">应用</el-button>
      </span>
    </el-dialog>

    <!-- 添加品质到分组的弹窗 -->
    <el-dialog title="选择品质" :visible.sync="addQualityVisible" width="400px" append-to-body>
      <el-checkbox-group v-model="selectedQualities">
        <el-checkbox v-for="qs in unassignedQualities" :key="qs" :label="qs">{{ qs }}</el-checkbox>
      </el-checkbox-group>
      <span slot="footer">
        <el-button @click="addQualityVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmAddQuality">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { listLightCoil, listMaterialCoil } from "@/api/wms/coil";
import { listWarehouse } from "@/api/wms/warehouse";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import MutiSelect from "@/components/MutiSelect";
import * as echarts from "echarts";

const DEFAULT_MERGE_GROUPS = [
  { name: 'A类', qualities: ['A+', 'A', 'A-'] },
  { name: 'B类', qualities: ['B+', 'B', 'B-'] },
  { name: 'C类', qualities: ['C+', 'C', 'C-'] },
  { name: 'D类', qualities: ['D+', 'D', 'D-'] },
  { name: 'O类', qualities: ['O'] },
];

const PIVOT_STORAGE_KEY = 'coil-stock-pivot-config';

export default {
  components: { WarehouseSelect, MutiSelect },
  dicts: ['coil_quality_status'],
  data() {
    return {
      loading: false,
      hintDismissed: false,
      queryParams: {
        warehouseIds: [],
        qualityStatusCsv: 'A+,A,A-,B+,B,B-',
      },
      allCoils: [],
      warehouseMap: {},
      aggregatedList: [],
      barChartInst: null,
      pieChartInst: null,

      // 品质合并配置（全局共享）
      mergeGroups: [],
      mergeConfigVisible: false,
      addQualityVisible: false,
      addQualityGroupIndex: -1,
      selectedQualities: [],

      // 弹窗
      dialogVisible: false,
      dialogLoading: false,
      dialogTitle: '',
      currentWarehouse: null,
      dialogList: [],
      dialogPageNum: 1,
      dialogPageSize: 20,
      dialogTotal: 0,
      dialogAllCoils: [],

      // 弹窗内数据透视图
      dialogPivotMeasure: 'count',
      dialogPivotCols: [],
      dialogPivotRows: [],
      dialogPivotTeams: [],
      dialogPivotColTotals: null,
    };
  },
  computed: {
    summary() {
      if (this.allCoils.length === 0) return { totalCount: 0, totalNetWeight: 0, avgWeight: 0, warehouseCount: 0 };
      const totalCount = this.allCoils.length;
      const totalNetWeight = this.allCoils.reduce((sum, c) => sum + (parseFloat(c.netWeight) || 0), 0);
      const warehouseIds = new Set(this.allCoils.map(c => c.warehouseId).filter(Boolean));
      return {
        totalCount,
        totalNetWeight: totalNetWeight.toFixed(2),
        avgWeight: totalCount > 0 ? (totalNetWeight / totalCount).toFixed(2) : '0.00',
        warehouseCount: warehouseIds.size,
      };
    },
    dialogSummary() {
      const list = this.dialogAllCoils;
      if (list.length === 0) return { totalCount: 0, totalNetWeight: 0, avgWeight: 0, qualityKinds: 0 };
      const totalCount = list.length;
      const totalNetWeight = list.reduce((s, c) => s + (parseFloat(c.netWeight) || 0), 0);
      const qualitySet = new Set(list.map(c => c.qualityStatus).filter(Boolean));
      return {
        totalCount,
        totalNetWeight: totalNetWeight.toFixed(2),
        avgWeight: totalCount > 0 ? (totalNetWeight / totalCount).toFixed(2) : '0.00',
        qualityKinds: qualitySet.size,
      };
    },
    unassignedQualities() {
      const assigned = new Set();
      this.mergeGroups.forEach(g => g.qualities.forEach(q => assigned.add(q)));
      const all = new Set();
      this.allCoils.forEach(c => { if (c.qualityStatus) all.add(c.qualityStatus); });
      this.dialogAllCoils.forEach(c => { if (c.qualityStatus) all.add(c.qualityStatus); });
      return [...all].filter(q => !assigned.has(q)).sort();
    },
  },
  mounted() {
    this.loadMergeConfig();
    this.fetchWarehouseMap().then(() => { this.getList(); });
  },
  beforeDestroy() {
    this.disposeChart(this.barChartInst);
    this.disposeChart(this.pieChartInst);
  },
  methods: {
    disposeChart(inst) { if (inst) inst.dispose(); },

    // ============ 品质合并配置持久化 ============
    loadMergeConfig() {
      try {
        const saved = localStorage.getItem(PIVOT_STORAGE_KEY);
        if (saved) { this.mergeGroups = JSON.parse(saved); return; }
      } catch (e) { /* ignore */ }
      this.mergeGroups = JSON.parse(JSON.stringify(DEFAULT_MERGE_GROUPS));
    },
    saveMergeConfig() {
      try { localStorage.setItem(PIVOT_STORAGE_KEY, JSON.stringify(this.mergeGroups)); } catch (e) { /* ignore */ }
    },
    showMergeConfig() { this.mergeConfigVisible = true; },
    addMergeGroup() { this.mergeGroups.push({ name: '新分组', qualities: [] }); },
    removeMergeGroup(gi) { if (this.mergeGroups.length <= 1) return; this.mergeGroups.splice(gi, 1); },
    showAddQuality(gi) { this.addQualityGroupIndex = gi; this.selectedQualities = []; this.addQualityVisible = true; },
    confirmAddQuality() {
      if (this.addQualityGroupIndex >= 0 && this.selectedQualities.length > 0) {
        const group = this.mergeGroups[this.addQualityGroupIndex];
        this.selectedQualities.forEach(q => { if (!group.qualities.includes(q)) group.qualities.push(q); });
      }
      this.addQualityVisible = false;
      this.addQualityGroupIndex = -1;
    },
    removeQualityFromGroup(gi, qi) { this.mergeGroups[gi].qualities.splice(qi, 1); },
    applyMergeConfig() {
      this.saveMergeConfig();
      this.mergeConfigVisible = false;
      this.buildDialogPivot();
    },
    resetMergeConfig() {
      this.mergeGroups = JSON.parse(JSON.stringify(DEFAULT_MERGE_GROUPS));
      this.saveMergeConfig();
      this.buildDialogPivot();
    },

    async fetchWarehouseMap() {
      try {
        const res = await listWarehouse({ pageNum: 1, pageSize: 9999 });
        const list = res.data || [];
        const map = {};
        const allIds = [];
        list.forEach(item => {
          map[item.warehouseId] = item.warehouseName;
          allIds.push(item.warehouseId);
        });
        this.warehouseMap = map;
        // 默认全选
        if (this.queryParams.warehouseIds.length === 0) {
          this.queryParams.warehouseIds = allIds;
        }
      } catch (e) { console.error('获取仓库列表失败:', e); }
    },

    getList() {
      this.loading = true;
      const params = { pageSize: 99999, pageNum: 1, dataType: 1, status: 0 };
      if (this.queryParams.warehouseIds && this.queryParams.warehouseIds.length > 0) {
        params.warehouseIds = this.queryParams.warehouseIds.join(',');
      }
      if (this.queryParams.qualityStatusCsv) params.qualityStatusCsv = this.queryParams.qualityStatusCsv;

      listLightCoil(params)
        .then(res => {
          this.allCoils = res || [];
          this.buildAggregation();
        })
        .catch(err => { console.error('查询钢卷列表失败:', err); this.$message.error('查询钢卷数据失败'); })
        .finally(() => { this.loading = false; });
    },

    buildAggregation() {
      const map = {};
      this.allCoils.forEach(coil => {
        const whId = coil.warehouseId || '__unknown__';
        if (!map[whId]) map[whId] = { warehouseId: coil.warehouseId, coilCount: 0, totalNetWeight: 0 };
        map[whId].coilCount += 1;
        map[whId].totalNetWeight += parseFloat(coil.netWeight) || 0;
      });
      this.aggregatedList = Object.values(map).map(item => ({
        ...item,
        warehouseName: item.warehouseId ? (this.warehouseMap[item.warehouseId] || `未知库区(${item.warehouseId})`) : '未知库区',
        totalNetWeight: parseFloat(item.totalNetWeight.toFixed(2)),
        avgNetWeight: item.coilCount > 0 ? parseFloat((item.totalNetWeight / item.coilCount).toFixed(2)) : 0,
      }));
      this.aggregatedList.sort((a, b) => a.warehouseName.localeCompare(b.warehouseName, 'zh'));
      this.$nextTick(() => { this.renderCharts(); });
    },

    // ============ 主页面图表 ============
    renderCharts() { this.renderBarChart(); this.renderPieChart(); },

    renderBarChart() {
      const dom = this.$refs.barChartRef;
      if (!dom) return;
      if (!this.barChartInst) this.barChartInst = echarts.init(dom);
      this.barChartInst.off('click');
      this.barChartInst.on('click', params => { this.handleChartClick(params.name); });
      this.barChartInst.setOption({
        tooltip: {
          trigger: 'axis', axisPointer: { type: 'cross', crossStyle: { color: '#999' } },
          formatter: params => `${params[0].name}<br/>${params[0].marker} 总净重: ${params[0].value} t<br/>${params[1].marker} 均重: ${params[1].value} t`
        },
        legend: { data: ['总净重', '均重'], bottom: 0 },
        grid: { left: '3%', right: '4%', bottom: '12%', containLabel: true },
        xAxis: { type: 'category', data: this.aggregatedList.map(i => i.warehouseName), axisLabel: { rotate: 30, color: '#666' }, axisLine: { lineStyle: { color: '#ddd' } } },
        yAxis: [
          { type: 'value', name: '总净重(t)', axisLabel: { color: '#666' }, splitLine: { lineStyle: { color: '#f0f0f0' } } },
          { type: 'value', name: '均重(t)', axisLabel: { color: '#666' }, splitLine: { show: false } },
        ],
        series: [
          { name: '总净重', type: 'bar', data: this.aggregatedList.map(i => i.totalNetWeight), itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#165DFF' }, { offset: 1, color: '#6AA1FF' }]) }, emphasis: { itemStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#0E42D2' }, { offset: 1, color: '#4080FF' }]) } } },
          { name: '均重', type: 'line', yAxisIndex: 1, data: this.aggregatedList.map(i => i.avgNetWeight), lineStyle: { color: '#F7BA1E', width: 2 }, itemStyle: { color: '#F7BA1E' }, symbol: 'circle', symbolSize: 6 },
        ]
      });
    },

    renderPieChart() {
      const dom = this.$refs.pieChartRef;
      if (!dom) return;
      if (!this.pieChartInst) this.pieChartInst = echarts.init(dom);
      this.pieChartInst.off('click');
      this.pieChartInst.on('click', params => { this.handleChartClick(params.name); });
      const colors = ['#165DFF','#14C9C9','#F7BA1E','#F77234','#722ED1','#00B42A','#F5319D','#0FC6C2','#FF7D00','#3491FA'];
      this.pieChartInst.setOption({
        tooltip: { trigger: 'item', formatter: '{b}: {c} 卷 ({d}%)' },
        series: [{ name: '钢卷数量', type: 'pie', radius: ['45%','72%'], center: ['50%','48%'], avoidLabelOverlap: false, itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 }, label: { show: true, formatter: '{b}\n{d}%' }, emphasis: { label: { show: true, fontSize: 14, fontWeight: 'bold' } }, data: this.aggregatedList.map((item, i) => ({ name: item.warehouseName, value: item.coilCount, itemStyle: { color: colors[i % colors.length] } })) }]
      });
    },

    // ============ 弹窗 ============
    handleChartClick(warehouseName) {
      const row = this.aggregatedList.find(item => item.warehouseName === warehouseName);
      if (row) this.handleRowClick(row);
    },

    handleRowClick(row) {
      this.currentWarehouse = { warehouseId: row.warehouseId, warehouseName: row.warehouseName };
      this.dialogTitle = `库区详情 - ${row.warehouseName}`;
      this.dialogVisible = true;
      this.dialogPageNum = 1;
      this.dialogList = [];
      this.dialogAllCoils = [];
      this.dialogPivotCols = [];
      this.dialogPivotRows = [];
      this.dialogPivotTeams = [];
      this.dialogPivotColTotals = null;
      this.$nextTick(() => { this.loadDialogData(); });
    },

    loadDialogData() {
      if (!this.currentWarehouse) return;
      this.dialogLoading = true;
      const baseParams = { 
        warehouseId: this.currentWarehouse.warehouseId, 
        qualityStatusCsv: this.queryParams.qualityStatusCsv || '',
        dataType: 1, status: 0,
      };
      Promise.all([
        listLightCoil({ ...baseParams, pageSize: 99999, pageNum: 1 }),
        listMaterialCoil({ ...baseParams, pageNum: this.dialogPageNum, pageSize: this.dialogPageSize }),
      ]).then(([lightRes, detailRes]) => {
        this.dialogAllCoils = lightRes || [];
        this.dialogList = (detailRes.rows || []).map(item => ({ ...item, netWeight: item.netWeight != null ? parseFloat(item.netWeight).toFixed(2) : '0.00' }));
        this.dialogTotal = detailRes.total || 0;
        this.$nextTick(() => { this.buildDialogPivot(); });
      }).catch(err => { console.error('加载库区详情失败:', err); this.$message.error('加载详情失败'); })
        .finally(() => { this.dialogLoading = false; });
    },

    fetchDialogList() {
      if (!this.currentWarehouse) return;
      this.dialogLoading = true;
      listMaterialCoil({ warehouseId: this.currentWarehouse.warehouseId, dataType: 1, status: 0, pageNum: this.dialogPageNum, pageSize: this.dialogPageSize })
        .then(res => {
          this.dialogList = (res.rows || []).map(item => ({ ...item, netWeight: item.netWeight != null ? parseFloat(item.netWeight).toFixed(2) : '0.00' }));
          this.dialogTotal = res.total || 0;
        }).catch(err => { console.error('加载钢卷明细失败:', err); })
        .finally(() => { this.dialogLoading = false; });
    },

    handleExportDetail() {
      if (!this.currentWarehouse) return;
      this.download('wms/materialCoil/export', {
        warehouseId: this.currentWarehouse.warehouseId,
        dataType: 1,
        status: 0,
      }, `钢卷明细_${this.currentWarehouse.warehouseName}_${new Date().getTime()}.xlsx`);
    },

    // ============ 弹窗数据透视图（班组 × 品质） ============
    getQualityGroup(qs) {
      if (!qs) return '未知';
      for (const g of this.mergeGroups) { if (g.qualities.includes(qs)) return g.name; }
      return qs;
    },

    buildDialogPivot() {
      if (this.dialogAllCoils.length === 0) {
        this.dialogPivotCols = []; this.dialogPivotRows = []; this.dialogPivotTeams = []; this.dialogPivotColTotals = null;
        return;
      }
      const colSet = new Set();
      this.dialogAllCoils.forEach(c => colSet.add(this.getQualityGroup(c.qualityStatus)));
      this.dialogPivotCols = [...colSet].sort().map(key => ({ key, label: key }));

      const teamSet = new Set();
      this.dialogAllCoils.forEach(c => teamSet.add(c.team || '未知'));
      this.dialogPivotTeams = [...teamSet].sort((a, b) => a.localeCompare(b, 'zh'));

      const cross = {};
      const useWeight = this.dialogPivotMeasure === 'weight';
      this.dialogAllCoils.forEach(c => {
        const team = c.team || '未知';
        const colKey = this.getQualityGroup(c.qualityStatus);
        if (!cross[team]) cross[team] = {};
        cross[team][colKey] = (cross[team][colKey] || 0) + (useWeight ? (parseFloat(c.netWeight) || 0) : 1);
      });

      this.dialogPivotColTotals = {};
      this.dialogPivotCols.forEach(col => { this.dialogPivotColTotals[col.key] = 0; });
      this.dialogPivotColTotals._total = 0;

      this.dialogPivotRows = this.dialogPivotTeams.map(team => {
        const row = { team };
        let rowTotal = 0;
        this.dialogPivotCols.forEach(col => {
          const v = cross[team]?.[col.key] || 0;
          row[col.key] = v;
          rowTotal += v;
          this.dialogPivotColTotals[col.key] += v;
        });
        row._total = rowTotal;
        this.dialogPivotColTotals._total += rowTotal;
        return row;
      });

      if (useWeight) {
        Object.keys(this.dialogPivotColTotals).forEach(k => { this.dialogPivotColTotals[k] = parseFloat(this.dialogPivotColTotals[k].toFixed(2)); });
      }
    },

    getDialogPivotCellColor(val) {
      if (!val || val === 0) return '#c0c4cc';
      const maxVal = this.dialogPivotColTotals?._total || 1;
      const ratio = Math.min(val / Math.max(maxVal / this.dialogPivotCols.length / 2, 1), 1);
      return `rgb(${Math.round(22 + (1 - ratio) * 200)},${Math.round(93 + (1 - ratio) * 100)},${Math.round(255 * (1 - ratio * 0.6))})`;
    },

    formatDialogPivotValue(val) {
      if (val == null || val === 0) return this.dialogPivotMeasure === 'weight' ? '0' : '0';
      return this.dialogPivotMeasure === 'weight' ? val.toFixed(2) : String(val);
    },

    pivotHeaderStyle() {
      return { background: '#f5f7fa', color: '#303133', fontWeight: '600' };
    },

    handleDialogClosed() {
      this.currentWarehouse = null;
    },

    // 计算距今时间
    timeAgo(createTime) {
      if (!createTime) return '-';
      const then = new Date(createTime).getTime();
      if (isNaN(then)) return '-';
      const diff = Date.now() - then;
      if (diff < 0) return '-';
      const seconds = Math.floor(diff / 1000);
      if (seconds < 60) return `${seconds}秒前`;
      const minutes = Math.floor(seconds / 60);
      if (minutes < 60) return `${minutes}分钟前`;
      const hours = Math.floor(minutes / 60);
      if (hours < 24) return `${hours}小时前`;
      const days = Math.floor(hours / 24);
      return `${days}天前`;
    },

    resetQuery() {
      this.queryParams = { warehouseIds: Object.keys(this.warehouseMap), qualityStatusCsv: 'A+,A,A-,B+,B,B-' };
      this.getList();
    },
  },
};
</script>

<style scoped>
.app-container { padding: 20px; }
h3 { margin: 16px 0 12px; font-size: 16px; color: #303133; }
h4 { margin: 8px 0; font-size: 15px; color: #303133; }

.chart-card { background: #fff; border-radius: 6px; padding: 16px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.chart-title { margin: 0 0 8px; font-size: 15px; font-weight: 500; color: #303133; }
.chart-box { width: 100%; height: 380px; }

/* 数据透视图 */
.pivot-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.pivot-toolbar h4 { margin: 0; }
.pivot-actions { display: flex; gap: 10px; align-items: center; }
.pivot-table { width: 100%; }
.pivot-footer { display: flex; align-items: center; background: #f5f7fa; border: 1px solid #ebeef5; border-top: 0; padding: 8px 0; font-size: 14px; }
.pivot-footer .footer-label { width: 100px; text-align: center; font-weight: 600; color: #303133; }
.pivot-footer .footer-cell { flex: 1; min-width: 100px; text-align: center; color: #606266; }
.pivot-footer .footer-total { width: 110px; flex: none; }

/* 合并配置 */
.merge-group { background: #f5f7fa; border-radius: 6px; padding: 12px; margin-bottom: 12px; }
.merge-group-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.merge-group-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.unassigned-section { margin-top: 16px; padding-top: 12px; border-top: 1px dashed #dcdfe6; }
.unassigned-section h4 { margin: 0 0 8px; font-size: 13px; color: #909399; }
.unassigned-section .el-tag { margin-right: 6px; margin-bottom: 6px; }

.clickable-row { cursor: pointer; }

.hint-list {
  margin: 4px 0 0;
  padding-left: 20px;
  line-height: 1.8;
}
</style>
