yuan
2026-06-02 308e2cc3b78e6f8351e4f3fb0ad1ca191ae0db48
src/views/reportAnalysis/reportManagement/index.vue
@@ -1,341 +1,379 @@
<template>
  <div class="report-management">
    <!-- 图表区域 -->
    <div class="charts-container">
      <el-row :gutter="20">
        <!-- 各类型完成数量 -->
        <el-col :span="9">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
                <span>各类型完成数量</span>
              </div>
            </template>
            <div class="top-container">
              <div class="typeNum">
                <div class="typeNum-left">
                  <img src="~@/assets/images/chartCard.svg"
                       alt="图表"
                       style="width: 40px; height: 40px; object-fit: contain;">
                  <div class="typeNum-left-text">原材料</div>
                </div>
                <div class="typeNum-center">
                  <div class="typeNum-leftLine">-</div>
                  <div class="typeNum-rightLine"></div>
                </div>
                <div class="typeNum-right">
                  <div class="typeNum-right-top">
                    <div class="typeNum-right-top-name">总数量</div>
                    <div class="typeNum-right-top-text">2099 <span class="unit">个</span></div>
  <div class="scale-container">
    <div class="report-management-container"
         :style="{ transform: `scale(${scaleRatio})` }">
      <div class="report-management">
        <!-- 图表区域 -->
        <div class="charts-container">
          <el-row :gutter="20">
            <!-- 各类型完成数量 -->
            <el-col :span="9">
              <el-card class="chart-card"
                       shadow="hover">
                <template #header>
                  <div class="card-header">
                    <div class="chart-title-line"></div>
                    <span>各类型完成数量</span>
                  </div>
                  <div class="typeNum-right-bottom">
                    <div class="typeNum-right-top-name">已完成数</div>
                    <div class="typeNum-right-top-text">2099 <span class="unit">个</span></div>
                  </div>
                </div>
              </div>
              <div class="typeNum">
                <div class="typeNum-left">
                  <img src="~@/assets/images/chartCard2.svg"
                       alt="图表"
                       style="width: 40px; height: 40px; object-fit: contain;">
                  <div class="typeNum-left-text"
                       style="color: #5EB334;">半成品</div>
                </div>
                <div class="typeNum-center">
                  <div class="typeNum-leftLine2">-</div>
                  <div class="typeNum-rightLine2"></div>
                </div>
                <div class="typeNum-right">
                  <div class="typeNum-right-top">
                    <div class="typeNum-right-top-name">总数量</div>
                    <div class="typeNum-right-top-text">2099 <span class="unit">个</span></div>
                  </div>
                  <div class="typeNum-right-bottom">
                    <div class="typeNum-right-top-name">已完成数</div>
                    <div class="typeNum-right-top-text">2099 <span class="unit">个</span></div>
                  </div>
                </div>
              </div>
              <div class="typeNum">
                <div class="typeNum-left">
                  <img src="~@/assets/images/chartCard3.svg"
                       alt="图表"
                       style="width: 40px; height: 40px; object-fit: contain;">
                  <div class="typeNum-left-text"
                       style="color: #8000FF;">成品</div>
                </div>
                <div class="typeNum-center">
                  <div class="typeNum-leftLine3">-</div>
                  <div class="typeNum-rightLine3"></div>
                </div>
                <div class="typeNum-right">
                  <div class="typeNum-right-top">
                    <div class="typeNum-right-top-name">总数量</div>
                    <div class="typeNum-right-top-text">2099 <span class="unit">个</span></div>
                  </div>
                  <div class="typeNum-right-bottom">
                    <div class="typeNum-right-top-name">已完成数</div>
                    <div class="typeNum-right-top-text">2099 <span class="unit">个</span></div>
                  </div>
                </div>
              </div>
            </div>
          </el-card>
        </el-col>
        <!-- 质检合格率 -->
        <el-col :span="15">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
                <span>质检合格率</span>
              </div>
            </template>
            <div class="top-container flex-center">
              <div class="quality-card blue-card">
                <div class="quality-card-title">
                  <img src="~@/assets/images/chartCard.svg"
                       alt="原材料"
                       style="width: 24px; height: 24px; margin-right: 8px;">
                  原材料合格率
                </div>
                <div class="quality-card-content">
                  <div class="quality-item">
                    <div>
                      <div class="quality-item-label blue-label">完成率</div>
                      <div class="quality-item-tip">占比</div>
                      <div class="quality-item-value">80%</div>
                </template>
                <div class="top-container">
                  <div class="typeNum">
                    <div class="typeNum-left">
                      <img src="~@/assets/images/chartCard.svg"
                           alt="图表"
                           style="width: 40px; height: 40px; object-fit: contain;">
                      <div class="typeNum-left-text">原材料</div>
                    </div>
                    <div class="quality-item-chart"
                         ref="materialCompletionChart"></div>
                  </div>
                  <div class="quality-item">
                    <div>
                      <div class="quality-item-label green-label">合格率</div>
                      <div class="quality-item-tip">占比</div>
                      <div class="quality-item-value">80%</div>
                    <div class="typeNum-center">
                      <div class="typeNum-leftLine">-</div>
                      <div class="typeNum-rightLine"></div>
                    </div>
                    <div class="quality-item-chart"
                         ref="materialQualityChart"></div>
                  </div>
                </div>
              </div>
              <div class="quality-card green-card">
                <div class="quality-card-title">
                  <img src="~@/assets/images/chartCard2.svg"
                       alt="半成品"
                       style="width: 24px; height: 24px; margin-right: 8px;">
                  半成品合格率
                </div>
                <div class="quality-card-content">
                  <div class="quality-item">
                    <div>
                      <div class="quality-item-label blue-label">完成率</div>
                      <div class="quality-item-tip">占比</div>
                      <div class="quality-item-value">80%</div>
                    <div class="typeNum-right">
                      <div class="typeNum-right-top">
                        <div class="typeNum-right-top-name">总数量</div>
                        <div class="typeNum-right-top-text">{{ getInspectStatValue(0, 'totalCount') }} <span class="unit">个</span></div>
                      </div>
                      <div class="typeNum-right-bottom">
                        <div class="typeNum-right-top-name">已完成数</div>
                        <div class="typeNum-right-top-text">{{ getInspectStatValue(0, 'completedCount') }} <span class="unit">个</span>
                        </div>
                      </div>
                    </div>
                    <div class="quality-item-chart"
                         ref="semiCompletionChart"></div>
                  </div>
                  <div class="quality-item">
                    <div>
                      <div class="quality-item-label green-label">合格率</div>
                      <div class="quality-item-tip">占比</div>
                      <div class="quality-item-value">80%</div>
                  <div class="typeNum">
                    <div class="typeNum-left">
                      <img src="~@/assets/images/chartCard2.svg"
                           alt="图表"
                           style="width: 40px; height: 40px; object-fit: contain;">
                      <div class="typeNum-left-text"
                           style="color: #5EB334;">半成品</div>
                    </div>
                    <div class="quality-item-chart"
                         ref="semiQualityChart"></div>
                  </div>
                </div>
              </div>
              <div class="quality-card purple-card">
                <div class="quality-card-title">
                  <img src="~@/assets/images/chartCard3.svg"
                       alt="成品"
                       style="width: 24px; height: 24px; margin-right: 8px;">
                  成品合格率
                </div>
                <div class="quality-card-content">
                  <div class="quality-item">
                    <div>
                      <div class="quality-item-label blue-label">完成率</div>
                      <div class="quality-item-tip">占比</div>
                      <div class="quality-item-value">80%</div>
                    <div class="typeNum-center">
                      <div class="typeNum-leftLine2">-</div>
                      <div class="typeNum-rightLine2"></div>
                    </div>
                    <div class="quality-item-chart"
                         ref="finalCompletionChart"></div>
                  </div>
                  <div class="quality-item">
                    <div>
                      <div class="quality-item-label green-label">合格率</div>
                      <div class="quality-item-tip">占比</div>
                      <div class="quality-item-value">80%</div>
                    <div class="typeNum-right">
                      <div class="typeNum-right-top">
                        <div class="typeNum-right-top-name">总数量</div>
                        <div class="typeNum-right-top-text">{{ getInspectStatValue(1, 'totalCount') }} <span class="unit">个</span></div>
                      </div>
                      <div class="typeNum-right-bottom">
                        <div class="typeNum-right-top-name">已完成数</div>
                        <div class="typeNum-right-top-text">{{ getInspectStatValue(1, 'completedCount') }} <span class="unit">个</span>
                        </div>
                      </div>
                    </div>
                    <div class="quality-item-chart"
                         ref="finalQualityChart"></div>
                  </div>
                  <div class="typeNum">
                    <div class="typeNum-left">
                      <img src="~@/assets/images/chartCard3.svg"
                           alt="图表"
                           style="width: 40px; height: 40px; object-fit: contain;">
                      <div class="typeNum-left-text"
                           style="color: #8000FF;">成品</div>
                    </div>
                    <div class="typeNum-center">
                      <div class="typeNum-leftLine3">-</div>
                      <div class="typeNum-rightLine3"></div>
                    </div>
                    <div class="typeNum-right">
                      <div class="typeNum-right-top">
                        <div class="typeNum-right-top-name">总数量</div>
                        <div class="typeNum-right-top-text">{{ getInspectStatValue(2, 'totalCount') }} <span class="unit">个</span></div>
                      </div>
                      <div class="typeNum-right-bottom">
                        <div class="typeNum-right-top-name">已完成数</div>
                        <div class="typeNum-right-top-text">{{ getInspectStatValue(2, 'completedCount') }} <span class="unit">个</span>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <div class="charts-container">
      <el-row :gutter="20">
        <!-- 质检合格率 -->
        <el-col :span="24">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
                <span>质检合格率</span>
              </div>
            </template>
            <div class="chart-container-line">
              <div class="container-line-left">
                <div style="height: 100%; width: 100%;"
                     ref="usageChartRef">
                </div>
              </div>
              <div class="container-line-right">
                <div style="height: 80%; width: 100%;"
                     ref="inspectionChartRef">
                </div>
                <div class="container-line-right-bottom">
                  <div class="inspection-chart-box">
                    <div class="chart-box-title">原材料抽检数</div>
                    <div class="chart-box-num">600</div>
              </el-card>
            </el-col>
            <!-- 质检合格率 -->
            <el-col :span="15">
              <el-card class="chart-card"
                       shadow="hover">
                <template #header>
                  <div class="card-header">
                    <div class="chart-title-line"></div>
                    <span>质检合格率</span>
                  </div>
                  <div class="inspection-chart-box">
                    <div class="chart-box-title">半成品抽检数</div>
                    <div class="chart-box-num">200</div>
                </template>
                <div class="top-container flex-center">
                  <div class="quality-card blue-card">
                    <div class="quality-card-title">
                      <img src="~@/assets/images/chartCard.svg"
                           alt="原材料"
                           style="width: 24px; height: 24px; margin-right: 8px;">
                      原材料合格率
                    </div>
                    <div class="quality-card-content">
                      <div class="quality-item">
                        <div>
                          <div class="quality-item-label blue-label">完成率</div>
                          <div class="quality-item-tip">占比</div>
                          <div class="quality-item-value">{{ getPassRateStatValue(0, 'completionRate') }}</div>
                        </div>
                        <div class="quality-item-chart"
                             ref="materialCompletionChart"></div>
                      </div>
                      <div class="quality-item">
                        <div>
                          <div class="quality-item-label green-label">合格率</div>
                          <div class="quality-item-tip">占比</div>
                          <div class="quality-item-value">{{ getPassRateStatValue(0, 'passRate') }}</div>
                        </div>
                        <div class="quality-item-chart"
                             ref="materialQualityChart"></div>
                      </div>
                    </div>
                  </div>
                  <div class="inspection-chart-box">
                    <div class="chart-box-title">成品抽检数</div>
                    <div class="chart-box-num">200</div>
                  <div class="quality-card green-card">
                    <div class="quality-card-title">
                      <img src="~@/assets/images/chartCard2.svg"
                           alt="半成品"
                           style="width: 24px; height: 24px; margin-right: 8px;">
                      半成品合格率
                    </div>
                    <div class="quality-card-content">
                      <div class="quality-item">
                        <div>
                          <div class="quality-item-label blue-label">完成率</div>
                          <div class="quality-item-tip">占比</div>
                          <div class="quality-item-value">{{ getPassRateStatValue(1, 'completionRate') }}</div>
                        </div>
                        <div class="quality-item-chart"
                             ref="semiCompletionChart"></div>
                      </div>
                      <div class="quality-item">
                        <div>
                          <div class="quality-item-label green-label">合格率</div>
                          <div class="quality-item-tip">占比</div>
                          <div class="quality-item-value">{{ getPassRateStatValue(1, 'passRate') }}</div>
                        </div>
                        <div class="quality-item-chart"
                             ref="semiQualityChart"></div>
                      </div>
                    </div>
                  </div>
                  <div class="quality-card purple-card">
                    <div class="quality-card-title">
                      <img src="~@/assets/images/chartCard3.svg"
                           alt="成品"
                           style="width: 24px; height: 24px; margin-right: 8px;">
                      成品合格率
                    </div>
                    <div class="quality-card-content">
                      <div class="quality-item">
                        <div>
                          <div class="quality-item-label blue-label">完成率</div>
                          <div class="quality-item-tip">占比</div>
                          <div class="quality-item-value">{{ getPassRateStatValue(2, 'completionRate') }}</div>
                        </div>
                        <div class="quality-item-chart"
                             ref="finalCompletionChart"></div>
                      </div>
                      <div class="quality-item">
                        <div>
                          <div class="quality-item-label green-label">合格率</div>
                          <div class="quality-item-tip">占比</div>
                          <div class="quality-item-value">{{ getPassRateStatValue(2, 'passRate') }}</div>
                        </div>
                        <div class="quality-item-chart"
                             ref="finalQualityChart"></div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <!-- </div> -->
            <!-- <div ref="sampleChartRef"
              </el-card>
            </el-col>
          </el-row>
        </div>
        <div class="charts-container">
          <el-row :gutter="20">
            <!-- 质检合格率 -->
            <el-col :span="24">
              <el-card class="chart-card"
                       shadow="hover">
                <template #header>
                  <div class="card-header">
                    <div class="chart-title-line"></div>
                    <span>质检合格率</span>
                  </div>
                </template>
                <div class="chart-container-line">
                  <div class="container-line-left">
                    <div style="height: 100%; width: 100%;"
                         ref="usageChartRef">
                    </div>
                  </div>
                  <div class="container-line-right">
                    <div style="height: 80%; width: 100%;"
                         ref="inspectionChartRef">
                    </div>
                    <div class="container-line-right-bottom">
                      <div class="inspection-chart-box">
                        <div class="chart-box-title">原材料总数</div>
                        <div class="chart-box-num">{{ getYearlyStatValue(0, 'totalCount') }}</div>
                      </div>
                      <div class="inspection-chart-box">
                        <div class="chart-box-title">半成品总数</div>
                        <div class="chart-box-num">{{ getYearlyStatValue(1, 'totalCount') }}</div>
                      </div>
                      <div class="inspection-chart-box">
                        <div class="chart-box-title">成品总数</div>
                        <div class="chart-box-num">{{ getYearlyStatValue(2, 'totalCount') }}</div>
                      </div>
                    </div>
                  </div>
                </div>
                <!-- </div> -->
                <!-- <div ref="sampleChartRef"
                 class="chart-container"></div> -->
            <div class="yearchange">
              <div style="margin-right: 8px;font-size: 14px;">年份:</div>
              <el-date-picker v-model="value3"
                              size="mini"
                              :clearable="false"
                              style="width: 60px;"
                              type="year"
                              :disabled-date="disabledDate"
                              placeholder="">
              </el-date-picker>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
    <div class="charts-container">
      <el-row :gutter="20">
        <!-- 样品进度图表 -->
        <el-col :span="12">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
                <span>质量完成明细</span>
              </div>
            </template>
            <div ref="equipmentChartRef"
                 class="chart-container"></div>
          </el-card>
        </el-col>
        <!-- 设备使用图表 -->
        <el-col :span="12">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
                <span>检测项目分类</span>
              </div>
            </template>
            <div class="chart-container-line">
              <div class="container-line2-left">
                <div class="info-box">
                  <div class="info-box-header">项目分布</div>
                  <div class="info-line">
                    <div class="info-icon"
                         style="background-color: #165DFF"></div>
                    <div class="info-line-title">物理性能</div>
                    <div class="info-line-value1">30%</div>
                    <div class="info-line-value2">300</div>
                  </div>
                  <div class="info-line">
                    <div class="info-icon"
                         style="background-color: #14C9C9;"></div>
                    <div class="info-line-title">物理性能</div>
                    <div class="info-line-value1">30%</div>
                    <div class="info-line-value2">300</div>
                  </div>
                  <div class="info-line">
                    <div class="info-icon"
                         style="background-color: #F7BA1E;"></div>
                    <div class="info-line-title">物理性能</div>
                    <div class="info-line-value1">30%</div>
                    <div class="info-line-value2">300</div>
                  </div>
                  <div class="info-line">
                    <div class="info-icon"
                         style="background-color: #722ED1;"></div>
                    <div class="info-line-title">物理性能</div>
                    <div class="info-line-value1">30%</div>
                    <div class="info-line-value2">300</div>
                  </div>
                  <div class="info-line">
                    <div class="info-icon"
                         style="background-color: #3491FA;"></div>
                    <div class="info-line-title">物理性能</div>
                    <div class="info-line-value1">30%</div>
                    <div class="info-line-value2">300</div>
                  </div>
                <div class="yearchange">
                  <div style="margin-right: 8px;font-size: 14px;">年份:</div>
                  <el-date-picker v-model="value3"
                                  size="mini"
                                  :clearable="false"
                                  style="width: 60px;"
                                  type="year"
                                  :disabled-date="disabledDate"
                                  placeholder="">
                  </el-date-picker>
                </div>
              </div>
              <div ref="sampleChartRef"
                   style="height: 100%; width: 50%;"
                   class="chart-container"></div>
            </div>
            <!-- Tab 选择器 -->
            <div class="tab-selector">
              <div class="tab-item"
                   :class="{ active: activeTab === 'raw' }"
                   @click="activeTab = 'raw'">原材料</div>
              <div class="tab-item"
                   :class="{ active: activeTab === 'semi' }"
                   @click="activeTab = 'semi'">半成品</div>
              <div class="tab-item"
                   :class="{ active: activeTab === 'final' }"
                   @click="activeTab = 'final'">成品</div>
            </div>
          </el-card>
        </el-col>
      </el-row>
              </el-card>
            </el-col>
          </el-row>
        </div>
        <div class="charts-container">
          <el-row :gutter="20">
            <!-- 样品进度图表 -->
            <el-col :span="12">
              <el-card class="chart-card"
                       shadow="hover">
                <template #header>
                  <div class="card-header">
                    <div class="chart-title-line"></div>
                    <span>质量完成明细</span>
                  </div>
                </template>
                <div ref="equipmentChartRef"
                     class="chart-container"></div>
              </el-card>
            </el-col>
            <!-- 设备使用图表 -->
            <el-col :span="12">
              <el-card class="chart-card"
                       shadow="hover">
                <template #header>
                  <div class="card-header">
                    <div class="chart-title-line"></div>
                    <span>检测项目分类</span>
                  </div>
                </template>
                <div class="chart-container-line">
                  <div class="container-line2-left">
                    <div class="info-box">
                      <div class="info-box-header">项目分布</div>
                      <div class="info-line"
                           v-for="(item, index) in topParametersData.list"
                           :key="index">
                        <div class="info-icon"
                             :style="{ backgroundColor: getParameterColor(index) }"></div>
                        <div class="info-line-title">{{ item.name }}</div>
                        <div class="info-line-value1">{{ item.percentage }}%</div>
                        <div class="info-line-value2">{{ item.count }}</div>
                      </div>
                    </div>
                  </div>
                  <div ref="sampleChartRef"
                       style="height: 100%; width: 50%;"
                       class="chart-container"></div>
                </div>
                <!-- Tab 选择器 -->
                <div class="tab-selector">
                  <div class="tab-item"
                       :class="{ active: activeTab === 'raw' }"
                       @click="activeTab = 'raw'">原材料</div>
                  <div class="tab-item"
                       :class="{ active: activeTab === 'semi' }"
                       @click="activeTab = 'semi'">半成品</div>
                  <div class="tab-item"
                       :class="{ active: activeTab === 'final' }"
                       @click="activeTab = 'final'">成品</div>
                </div>
              </el-card>
            </el-col>
          </el-row>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
  import { ref, reactive, onMounted, nextTick } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    ref,
    reactive,
    onMounted,
    nextTick,
    onBeforeUnmount,
    watch,
  } from "vue";
  import { ElMessage } from "element-plus";
  import * as echarts from "echarts";
  import { Box, Tools, Document, ShoppingCart } from "@element-plus/icons-vue";
  import {
    getInspectStatistics,
    getPassRateStatistics,
    getMonthlyPassRateStatistics,
    getYearlyPassRateStatistics,
    getMonthlyCompletionDetails,
    getTopParameters,
  } from "@/api/reportAnalysis/qualityReport";
  // 缩放比例
  const scaleRatio = ref(1);
  // 设计尺寸(基准尺寸)
  const designWidth = 1920;
  const designHeight = 1080;
  // 计算缩放比例
  const calculateScale = () => {
    const container = document.querySelector(".scale-container");
    if (!container) return;
    // 获取容器的实际尺寸
    const containerWidth = container.clientWidth;
    const containerHeight = container.clientHeight;
    if (containerWidth === 0) {
      // 如果还没渲染出来,延迟一下再计算
      setTimeout(calculateScale, 100);
      return;
    }
    // 计算宽度缩放比例,使其始终占满宽度
    const scaleX = containerWidth / designWidth;
    scaleRatio.value = scaleX;
  };
  // 窗口大小变化处理
  const handleResize = () => {
    calculateScale();
    // 同时调整图表
    sampleChart?.resize();
    equipmentChart?.resize();
    inspectionChart?.resize();
    usageChart?.resize();
    materialCompletionChartInstance?.resize();
    materialQualityChartInstance?.resize();
    semiCompletionChartInstance?.resize();
    semiQualityChartInstance?.resize();
    finalCompletionChartInstance?.resize();
    finalQualityChartInstance?.resize();
  };
  // 响应式数据
  const filterForm = reactive({
@@ -343,12 +381,127 @@
    reportType: "sample",
  });
  const statistics = reactive({
    totalSamples: 1250,
    activeEquipment: 45,
    completedInspections: 890,
    totalUsage: 2340,
  });
  const inspectStatisticsData = ref([]);
  const passRateStatisticsData = ref([]);
  const monthlyPassRateData = ref([]);
  const yearlyPassRateData = ref([]);
  const monthlyCompletionDetailsData = ref([]);
  const topParametersData = ref({ totalCount: 0, list: [] });
  const activeTab = ref("raw");
  const getParameterColor = index => {
    const colors = [
      "#165DFF",
      "#14C9C9",
      "#F7BA1E",
      "#722ED1",
      "#3491FA",
      "#FF7D00",
      "#F53F3F",
    ];
    return colors[index % colors.length];
  };
  const getYearlyStatValue = (type, field) => {
    const stat = yearlyPassRateData.value.find(item => item.modelType === type);
    return stat ? stat[field] : 0;
  };
  const getInspectStatValue = (type, field) => {
    const stat = inspectStatisticsData.value.find(
      item => item.modelType === type
    );
    return stat ? stat[field] : 0;
  };
  const getPassRateStatValue = (type, field) => {
    const stat = passRateStatisticsData.value.find(
      item => item.modelType === type
    );
    if (stat) {
      if (field === "completionRate" || field === "passRate") {
        return stat[field] ? parseFloat(stat[field]) + "%" : "0%";
      }
      return stat[field];
    }
    return field === "completionRate" || field === "passRate" ? "0%" : 0;
  };
  const fetchInspectStatisticsData = async () => {
    try {
      const res = await getInspectStatistics();
      if (res.code === 200) {
        inspectStatisticsData.value = res.data;
      }
    } catch (error) {
      console.error("Failed to fetch inspect statistics:", error);
    }
  };
  const fetchPassRateStatisticsData = async () => {
    try {
      const res = await getPassRateStatistics();
      if (res.code === 200) {
        passRateStatisticsData.value = res.data;
        // 数据获取后重新初始化图表
        initAllQualityCharts();
      }
    } catch (error) {
      console.error("Failed to fetch pass rate statistics:", error);
    }
  };
  const fetchMonthlyPassRateData = async () => {
    try {
      const year = value3.value.getFullYear().toString();
      const res = await getMonthlyPassRateStatistics(year);
      if (res.code === 200) {
        monthlyPassRateData.value = res.data;
        initUsageChart();
      }
    } catch (error) {
      console.error("Failed to fetch monthly pass rate statistics:", error);
    }
  };
  const fetchYearlyPassRateData = async () => {
    try {
      const year = value3.value.getFullYear().toString();
      const res = await getYearlyPassRateStatistics(year);
      if (res.code === 200) {
        yearlyPassRateData.value = res.data;
        initInspectionChart();
      }
    } catch (error) {
      console.error("Failed to fetch yearly pass rate statistics:", error);
    }
  };
  const fetchMonthlyCompletionDetailsData = async () => {
    try {
      const year = value3.value.getFullYear().toString();
      const res = await getMonthlyCompletionDetails(year);
      if (res.code === 200) {
        monthlyCompletionDetailsData.value = res.data;
        initEquipmentChart();
      }
    } catch (error) {
      console.error("Failed to fetch monthly completion details:", error);
    }
  };
  const fetchTopParametersData = async () => {
    try {
      const typeMap = { raw: 1, semi: 2, final: 3 };
      const res = await getTopParameters(typeMap[activeTab.value]);
      if (res.code === 200) {
        topParametersData.value = res.data;
        initSampleChart();
      }
    } catch (error) {
      console.error("Failed to fetch top parameters:", error);
    }
  };
  const tableData = ref([]);
  const tableLoading = ref(false);
@@ -368,8 +521,16 @@
    return time.getFullYear() > currentYear;
  };
  // Tab 选择器当前激活项
  const activeTab = ref("raw");
  // 监听年份变化
  watch(value3, () => {
    fetchMonthlyPassRateData();
    fetchYearlyPassRateData();
    fetchMonthlyCompletionDetailsData();
  });
  watch(activeTab, () => {
    fetchTopParametersData();
  });
  // 图表引用
  const sampleChartRef = ref(null);
@@ -399,60 +560,6 @@
  let finalCompletionChartInstance = null;
  let finalQualityChartInstance = null;
  // 初始化数据
  const initData = () => {
    // 模拟表格数据
    tableData.value = [
      {
        id: "SP001",
        name: "样品A-001",
        type: "金属材料",
        status: "检测中",
        progress: 75,
        createTime: "2025-01-15 09:30:00",
        updateTime: "2025-01-20 14:20:00",
      },
      {
        id: "SP002",
        name: "样品B-002",
        type: "塑料制品",
        status: "已完成",
        progress: 100,
        createTime: "2025-01-10 10:15:00",
        updateTime: "2025-01-18 16:45:00",
      },
      {
        id: "SP003",
        name: "样品C-003",
        type: "电子元件",
        status: "待检测",
        progress: 0,
        createTime: "2025-01-22 08:45:00",
        updateTime: "2025-01-22 08:45:00",
      },
      {
        id: "EQ001",
        name: "检测设备A",
        type: "原材料",
        status: "使用中",
        progress: 60,
        createTime: "2025-01-05 14:20:00",
        updateTime: "2025-01-20 11:30:00",
      },
      {
        id: "EQ002",
        name: "检测设备B",
        type: "半成品",
        status: "空闲",
        progress: 0,
        createTime: "2025-01-08 16:10:00",
        updateTime: "2025-01-19 09:15:00",
      },
    ];
    pagination.total = tableData.value.length;
  };
  // 初始化样品进度图表
  const initSampleChart = () => {
    if (sampleChartRef.value) {
@@ -471,7 +578,7 @@
        // },
        series: [
          {
            name: "样品状态",
            name: "检测项目",
            type: "pie",
            radius: ["40%", "80%"],
            avoidLabelOverlap: false,
@@ -489,12 +596,11 @@
            labelLine: {
              show: false,
            },
            data: [
              { value: 450, name: "已完成" },
              { value: 320, name: "检测中" },
              { value: 280, name: "待检测" },
              { value: 200, name: "已暂停" },
            ],
            data: topParametersData.value.list.map((item, index) => ({
              value: item.count,
              name: item.name,
              itemStyle: { color: getParameterColor(index) },
            })),
          },
        ],
      };
@@ -556,7 +662,9 @@
            name: "原材料",
            type: "bar",
            barWidth: "15%",
            data: [85, 75, 80, 85, 90, 88, 92, 87, 89, 91, 93, 95],
            data: monthlyCompletionDetailsData.value.map(
              item => item.rawMaterialCount
            ),
            itemStyle: {
              color: "#409EFF",
            },
@@ -566,7 +674,9 @@
            type: "bar",
            barWidth: "15%",
            data: [60, 65, 70, 68, 72, 75, 78, 80, 79, 82, 84, 85],
            data: monthlyCompletionDetailsData.value.map(
              item => item.processCount
            ),
            itemStyle: {
              color: "#67C23A",
            },
@@ -576,7 +686,9 @@
            type: "bar",
            barWidth: "15%",
            data: [75, 78, 80, 82, 85, 83, 86, 88, 87, 89, 90, 92],
            data: monthlyCompletionDetailsData.value.map(
              item => item.outgoingCount
            ),
            itemStyle: {
              color: "#E6A23C",
            },
@@ -601,12 +713,28 @@
        series: [
          {
            type: "pie",
            radius: "80%",
            radius: "70%",
            data: [
              { value: 335, name: "原材料", itemStyle: { color: "#1890FF" } },
              { value: 310, name: "半成品", itemStyle: { color: "#F7BA1E" } },
              { value: 234, name: "成品", itemStyle: { color: "#14C9C9" } },
              {
                value: getYearlyStatValue(0, "totalCount"),
                name: "原材料",
                itemStyle: { color: "#1890FF" },
              },
              {
                value: getYearlyStatValue(1, "totalCount"),
                name: "半成品",
                itemStyle: { color: "#F7BA1E" },
              },
              {
                value: getYearlyStatValue(2, "totalCount"),
                name: "成品",
                itemStyle: { color: "#14C9C9" },
              },
            ],
            label: {
              show: true,
              formatter: "{b}: {c}",
            },
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
@@ -683,32 +811,34 @@
          {
            name: "原材料", // 系列名称
            type: "line", // 图表类型为折线图
            stack: "Total", // 堆叠名称
            symbol: "none",
            // stack: "Total", // 堆叠名称
            symbol: "circle",
            itemStyle: {
              color: "#1890FF", // 设置这条线的颜色
            },
            data: [120, 132, 101, 134, 90, 230, 210, 182, 191, 234, 290, 330], // 领用次数数据
            data: monthlyPassRateData.value.map(
              item => item.rawMaterial.passRate
            ),
          },
          {
            name: "半成品", // 系列名称
            type: "line", // 图表类型为折线图
            stack: "Total", // 堆叠名称
            symbol: "none",
            // stack: "Total", // 堆叠名称
            symbol: "circle",
            itemStyle: {
              color: "#F7BA1E", // 设置这条线的颜色
            },
            data: [110, 125, 95, 128, 85, 220, 200, 175, 185, 225, 280, 320], // 归还次数数据
            data: monthlyPassRateData.value.map(item => item.process.passRate),
          },
          {
            name: "成品", // 系列名称
            type: "line", // 图表类型为折线图
            stack: "Total", // 堆叠名称
            symbol: "none",
            // stack: "Total", // 堆叠名称
            symbol: "circle",
            itemStyle: {
              color: "#14C9C9", // 设置这条线的颜色
            },
            data: [110, 125, 95, 128, 85, 220, 200, 175, 185, 225, 280, 320], // 归还次数数据
            data: monthlyPassRateData.value.map(item => item.outgoing.passRate),
          },
        ],
      };
@@ -718,9 +848,14 @@
  };
  // 初始化质检合格率图表
  const initQualityChart = (chartRef, color) => {
  const initQualityChart = (chartRef, color, value = 0.8) => {
    if (chartRef.value) {
      const chart = echarts.init(chartRef.value);
      let chart = echarts.getInstanceByDom(chartRef.value);
      if (!chart) {
        chart = echarts.init(chartRef.value);
      }
      const numericValue =
        typeof value === "string" ? parseFloat(value) / 100 : value / 100;
      const option = {
        series: [
          {
@@ -734,8 +869,8 @@
              show: false,
            },
            data: [
              { value: 0.8, itemStyle: { color: color } },
              { value: 0.2, itemStyle: { color: "#f5f5f5" } },
              { value: numericValue, itemStyle: { color: color } },
              { value: 1 - numericValue, itemStyle: { color: "#f5f5f5" } },
            ],
          },
        ],
@@ -750,22 +885,34 @@
  const initAllQualityCharts = () => {
    materialCompletionChartInstance = initQualityChart(
      materialCompletionChart,
      "#1890ff"
      "#1890ff",
      getPassRateStatValue(0, "completionRate")
    );
    materialQualityChartInstance = initQualityChart(
      materialQualityChart,
      "#52c41a"
      "#52c41a",
      getPassRateStatValue(0, "passRate")
    );
    semiCompletionChartInstance = initQualityChart(
      semiCompletionChart,
      "#1890ff"
      "#1890ff",
      getPassRateStatValue(1, "completionRate")
    );
    semiQualityChartInstance = initQualityChart(semiQualityChart, "#52c41a");
    semiQualityChartInstance = initQualityChart(
      semiQualityChart,
      "#52c41a",
      getPassRateStatValue(1, "passRate")
    );
    finalCompletionChartInstance = initQualityChart(
      finalCompletionChart,
      "#1890ff"
      "#1890ff",
      getPassRateStatValue(2, "completionRate")
    );
    finalQualityChartInstance = initQualityChart(finalQualityChart, "#722ed1");
    finalQualityChartInstance = initQualityChart(
      finalQualityChart,
      "#722ed1",
      getPassRateStatValue(2, "passRate")
    );
  };
  // 事件处理函数
@@ -854,8 +1001,19 @@
  };
  // 生命周期
  let resizeObserver = null;
  onMounted(() => {
    initData();
    // 计算初始缩放比例
    nextTick(() => {
      calculateScale();
    });
    fetchInspectStatisticsData();
    fetchPassRateStatisticsData();
    fetchMonthlyPassRateData();
    fetchYearlyPassRateData();
    fetchMonthlyCompletionDetailsData();
    fetchTopParametersData();
    nextTick(() => {
      initSampleChart();
      initEquipmentChart();
@@ -864,30 +1022,48 @@
      initAllQualityCharts();
    });
    // 监听窗口大小变化,重新调整图表大小
    window.addEventListener("resize", () => {
      sampleChart?.resize();
      equipmentChart?.resize();
      inspectionChart?.resize();
      usageChart?.resize();
    window.addEventListener("resize", handleResize);
      // 调整质检合格率图表大小
      materialCompletionChartInstance?.resize();
      materialQualityChartInstance?.resize();
      semiCompletionChartInstance?.resize();
      semiQualityChartInstance?.resize();
      finalCompletionChartInstance?.resize();
      finalQualityChartInstance?.resize();
    });
    // 使用 ResizeObserver 监听容器尺寸变化(解决侧边栏切换问题)
    const container = document.querySelector(".scale-container");
    if (container && window.ResizeObserver) {
      resizeObserver = new ResizeObserver(() => {
        handleResize();
      });
      resizeObserver.observe(container);
    }
  });
  onBeforeUnmount(() => {
    window.removeEventListener("resize", handleResize);
    if (resizeObserver) {
      resizeObserver.disconnect();
    }
  });
</script>
<style scoped>
  .scale-container {
    position: relative;
    width: 100%;
    height: calc(100vh - 84px);
    background-color: #f0f2f5;
    overflow-x: hidden;
    overflow-y: auto;
  }
  .report-management-container {
    position: relative;
    width: 1920px;
    height: 1080px;
    transform-origin: left top;
    background-color: #f0f2f5;
    transition: transform 0.3s;
  }
  .report-management {
    padding: 20px;
    background-color: #f5f5f5;
    min-height: 100vh;
    /* height: 87vh;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              overflow: hidden; */
    height: 100%;
  }
  .page-header {
@@ -978,6 +1154,7 @@
  .chart-card {
    margin-bottom: 20px;
  }
  .container-line-right-bottom {
    height: 20%;
    width: 100%;
@@ -986,6 +1163,7 @@
    align-items: center;
    /* background-color: #5b3f3f; */
  }
  .card-header {
    display: flex;
    justify-content: flex-start;
@@ -999,6 +1177,7 @@
    font-style: normal;
    text-transform: none;
  }
  .chart-title-line {
    width: 6px;
    height: 22px;
@@ -1011,6 +1190,7 @@
    height: 250px;
    width: 100%;
  }
  .chart-container-line {
    height: 250px;
    width: 100%;
@@ -1051,18 +1231,22 @@
    color: #fff;
    background-color: #409eff;
  }
  .container-line-left {
    height: 100%;
    width: 66%;
  }
  .container-line-right {
    height: 100%;
    width: 34%;
  }
  .container-line2-left {
    height: 100%;
    width: 50%;
  }
  .info-box {
    width: 92%;
    margin-left: 4%;
@@ -1073,6 +1257,7 @@
    align-items: center;
    justify-content: space-around;
  }
  .info-box-header {
    width: 100%;
    margin-left: 20px;
@@ -1087,17 +1272,20 @@
    padding-left: 20px;
    align-items: center;
  }
  .info-icon {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-right: 8px;
  }
  .info-line-title {
    font-size: 12px;
    color: #4e5969;
    flex: 1;
  }
  .info-line-value1 {
    font-size: 12px;
    color: #3d3d3d;
@@ -1105,6 +1293,7 @@
    font-weight: 500;
    margin-right: 15%;
  }
  .info-line-value2 {
    font-size: 12px;
    color: #3d3d3d;
@@ -1112,11 +1301,13 @@
    font-weight: 500;
    margin-right: 10%;
  }
  .top-container {
    height: 130px;
    width: 100%;
    display: flex;
  }
  .typeNum {
    height: 100%;
    width: 33.33%;
@@ -1124,6 +1315,7 @@
    align-items: center;
    justify-content: center;
  }
  .typeNum-left {
    font-size: 12px;
    color: #909399;
@@ -1132,25 +1324,30 @@
    align-items: center;
    justify-content: center;
  }
  .typeNum-left-text {
    font-size: 12px;
    color: #3491fa;
    font-weight: 500;
    margin-top: 5px;
  }
  .table-card {
    margin-bottom: 20px;
  }
  .typeNum-center {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-left: 10px;
  }
  .typeNum-leftLine {
    color: #3491fa;
    font-size: 12px;
  }
  .typeNum-rightLine {
    border-top: 1px solid #3491fa;
    border-left: 1px solid #3491fa;
@@ -1158,10 +1355,12 @@
    height: 80px;
    width: 8px;
  }
  .typeNum-leftLine2 {
    color: #5eb334;
    font-size: 12px;
  }
  .typeNum-rightLine2 {
    border-top: 1px solid #3491fa;
    border-left: 1px solid #5eb334;
@@ -1169,10 +1368,12 @@
    height: 80px;
    width: 8px;
  }
  .typeNum-leftLine3 {
    color: #8000ff;
    font-size: 12px;
  }
  .typeNum-rightLine3 {
    border-top: 1px solid #8000ff;
    border-left: 1px solid #8000ff;
@@ -1180,6 +1381,7 @@
    height: 80px;
    width: 8px;
  }
  .typeNum-right {
    margin-left: 10px;
    display: flex;
@@ -1187,21 +1389,25 @@
    height: 90%;
    justify-content: space-between;
  }
  .typeNum-right-top-name {
    font-weight: 400;
    font-size: 12px;
    color: #3d3d3d;
  }
  .typeNum-right-top-text {
    font-weight: 400;
    font-size: 16px;
    color: rgba(0, 0, 0, 0.85);
    margin-top: 5px;
  }
  .unit {
    font-size: 12px;
    color: #3d3d3d;
  }
  .inspection-chart-box {
    height: 50px;
    width: 30%;
@@ -1209,21 +1415,25 @@
    border-radius: 8px;
    padding-left: 15px;
  }
  .chart-box-title {
    font-size: 12px;
    color: #4e5969;
    margin-top: 5px;
  }
  .unit {
    font-size: 12px;
    color: #3d3d3d;
  }
  .chart-box-num {
    font-size: 18px;
    color: #000;
    margin-top: 5px;
    font-weight: 500;
  }
  /* 质检合格率卡片样式 */
  .top-container合格率 {
    height: 130px;
@@ -1233,9 +1443,11 @@
    align-items: center;
    justify-content: space-between;
  }
  .flex-center {
    justify-content: space-evenly;
  }
  .quality-card {
    /* flex: 1; */
    width: 32%;
@@ -1272,9 +1484,11 @@
    color: #666666;
    margin-bottom: 3px;
  }
  .blue-label {
    color: #1890ff;
  }
  .green-label {
    color: #52c41a;
  }
@@ -1317,9 +1531,10 @@
    height: 60px;
    margin-left: 10px;
  }
  /* .flex-center {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            justify-content: space-evenly;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          } */
                        justify-content: space-evenly;
                        } */
  .blue-chart {
    /* background-color: rgba(24, 144, 255, 0.1); */
@@ -1366,6 +1581,7 @@
    margin-top: 20px;
    text-align: right;
  }
  .yearchange {
    position: absolute;
    right: 40px;
@@ -1396,6 +1612,7 @@
  :deep(.el-tag) {
    margin: 0;
  }
  :deep(.el-input__prefix) {
    display: none !important;
  }