7bcc922ed2924583eecf3df378e5f70130d41368..ae30037d1e78add57b8aceb4f100019c097dfb2c
2026-06-17
设备保养增加保养内容字段
ae3003 对比 | 目录
2026-06-17 zhangwencui
质检合格率半成品隐藏掉
676c53 对比 | 目录
已添加1个文件
已修改5个文件
2400 ■■■■■ 文件已修改
.gitignore 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/maintenance_content.md 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/formDia.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/reportManagement/index.vue 2289 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -21,3 +21,6 @@
package-lock.json
yarn.lock
# Claude
.claude/
doc/maintenance_content.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
# è®¾å¤‡ä¿å…»å†…容字段
## æ¶‰åŠé¡µé¢
- ä¿å…»å®šæ—¶ä»»åŠ¡ç®¡ç†é¡µé¢ï¼ˆæ–°å¢ž/编辑弹窗、列表)
- è®¾å¤‡ä¿å…»è®°å½•管理页面(列表、详情弹窗、确认保养弹窗)
## API
### ä¿å…»å®šæ—¶ä»»åŠ¡
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /deviceMaintenanceTask/add | æ–°å¢žå®šæ—¶ä»»åŠ¡ï¼ˆæ–°å¢ž maintenanceContent å­—段) |
| POST | /deviceMaintenanceTask/update | ä¿®æ”¹å®šæ—¶ä»»åŠ¡ï¼ˆæ–°å¢ž maintenanceContent å­—段) |
| GET | /deviceMaintenanceTask/listPage | åˆ—表查询(返回新增字段) |
**新增请求/响应参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| maintenanceContent | String | å¦ | ä¿å…»å†…容,最长2000字 |
### è®¾å¤‡ä¿å…»è®°å½•
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | /device/maintenance | æ–°å¢žä¿å…»è®°å½•(新增 maintenanceContent å­—段) |
| PUT | /device/maintenance | ä¿®æ”¹ä¿å…»è®°å½•(新增 maintenanceContent å­—段) |
| POST | /device/maintenance/maintenance | ç¡®è®¤ä¿å…»ï¼ˆæ–°å¢ž maintenanceContent å­—段) |
| GET | /device/maintenance/page | åˆ—表查询(返回新增字段) |
| GET | /device/maintenance/{id} | è¯¦æƒ…查询(返回新增字段) |
| POST | /device/maintenance/export | å¯¼å‡ºExcel(新增"保养内容"列) |
**新增请求/响应参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| maintenanceContent | String | å¦ | ä¿å…»å†…容,最长2000字 |
**说明:** å®šæ—¶ä»»åŠ¡è§¦å‘ç”Ÿæˆä¿å…»è®°å½•æ—¶ï¼Œä¼šè‡ªåŠ¨å°†å®šæ—¶ä»»åŠ¡çš„ `maintenanceContent` å¤åˆ¶åˆ°ä¿å…»è®°å½•中。
## å‰ç«¯ä¿®æ”¹ç‚¹
### 1. ä¿å…»å®šæ—¶ä»»åŠ¡ - æ–°å¢ž/编辑弹窗
```html
<el-form-item label="保养内容" prop="maintenanceContent">
  <el-input v-model="form.maintenanceContent" type="textarea" :rows="3" placeholder="请输入保养内容" maxlength="2000" show-word-limit />
</el-form-item>
```
### 2. ä¿å…»å®šæ—¶ä»»åŠ¡ - åˆ—表
```html
<el-table-column label="保养内容" prop="maintenanceContent" min-width="150" show-overflow-tooltip />
```
### 3. è®¾å¤‡ä¿å…»è®°å½• - åˆ—表
```html
<el-table-column label="保养内容" prop="maintenanceContent" min-width="150" show-overflow-tooltip />
```
### 4. è®¾å¤‡ä¿å…»è®°å½• - è¯¦æƒ…弹窗
```html
<el-form-item label="保养内容">
  <span>{{ detail.maintenanceContent }}</span>
</el-form-item>
```
### 5. è®¾å¤‡ä¿å…»è®°å½• - ç¡®è®¤ä¿å…»å¼¹çª—(可选填写/修改)
```html
<el-form-item label="保养内容" prop="maintenanceContent">
  <el-input v-model="confirmForm.maintenanceContent" type="textarea" :rows="3" placeholder="请输入保养内容" maxlength="2000" show-word-limit />
</el-form-item>
```
### 6. å¯¼å‡º
导出Excel自动新增"保养内容"列,无需前端额外处理。
## æ³¨æ„äº‹é¡¹
- æ‰§è¡Œæ•°æ®åº“迁移脚本 `doc/20260617_device_maintenance_content.sql` åŽå†éƒ¨ç½²
- å®šæ—¶ä»»åŠ¡ç”Ÿæˆçš„ä¿å…»è®°å½•ä¼šè‡ªåŠ¨æºå¸¦å®šæ—¶ä»»åŠ¡çš„ä¿å…»å†…å®¹ï¼Œæ— éœ€æ‰‹åŠ¨å¡«å†™
- ä¿å…»è®°å½•的保养内容可在确认保养时修改
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
@@ -66,6 +66,9 @@
          </div>
        </div>
      </el-form-item>
      <el-form-item label="保养内容" prop="maintenanceContent">
        <el-input v-model="form.maintenanceContent" type="textarea" :rows="3" placeholder="请输入保养内容" maxlength="2000" show-word-limit />
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
@@ -98,6 +101,7 @@
  maintenanceActuallyTime: undefined,
  maintenanceResult: undefined,
  sparePartsIds: [],
  maintenanceContent: undefined,
});
const sparePartOptions = ref([])
@@ -118,6 +122,7 @@
      ? dayjs(data.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss")
      : dayjs().format("YYYY-MM-DD HH:mm:ss");
  form.maintenanceResult = data.maintenanceResult;
  form.maintenanceContent = data.maintenanceContent || "";
  if (Array.isArray(data?.sparePartsIds)) {
    form.sparePartsIds = data.sparePartsIds.map((v) => Number(v)).filter((v) => Number.isFinite(v));
  } else if (typeof data?.sparePartsIds === "string") {
@@ -158,6 +163,7 @@
    }
    const data = {
      id: planId.value,
      maintenanceContent: form.maintenanceContent,
      ...form,
      sparePartsIds: form.sparePartsIds ? form.sparePartsIds.join(",") : "",
      sparePartsQty: form.sparePartsIds
src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -189,6 +189,13 @@
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="保养内容" prop="maintenanceContent">
            <el-input v-model="form.maintenanceContent" type="textarea" :rows="3" placeholder="请输入保养内容" maxlength="2000" show-word-limit />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </FormDialog>
</template>
@@ -233,6 +240,7 @@
    isEnabled: 1,
    inspector: undefined,
    remarks: "",
    maintenanceContent: "",
    frequencyType: "",
    frequencyDetail: "",
    week: "",
@@ -383,6 +391,7 @@
    isEnabled: 1,
    inspector: undefined,
    remarks: "",
    maintenanceContent: "",
    frequencyType: "",
    frequencyDetail: "",
    week: "",
src/views/equipmentManagement/upkeep/index.vue
@@ -168,7 +168,7 @@
        @pagination="changePage"
      >
        <template #maintenanceResultRef="{ row }">
          <div>{{ row.maintenanceResult || '-' }}</div>
          <div>{{ { "0": "ç»´ä¿®", "1": "完好" }[row.maintenanceResult] || row.maintenanceResult || "-" }}</div>
        </template>
        <template #statusRef="{ row }">
          <el-tag v-if="row.status === 2" type="danger">失败</el-tag>
@@ -356,6 +356,7 @@
    },
    { prop: "registrant", label: "登记人", minWidth: 100 },
    { prop: "registrationDate", label: "登记日期", minWidth: 100 },
    { prop: "maintenanceContent", label: "保养内容", minWidth: 150, showOverflowTooltip: true },
    {
        label: "是否启用",
        prop: "isEnabled",
@@ -427,6 +428,7 @@
        dataType: "slot",
        slot: "maintenanceResultRef",
    },
    { prop: "maintenanceContent", label: "保养内容", minWidth: 150, showOverflowTooltip: true },
    {
        label: "状态",
        align: "center",
src/views/reportAnalysis/reportManagement/index.vue
@@ -5,18 +5,21 @@
      <el-row :gutter="20">
        <!-- å„类型完成数量 -->
        <el-col :span="9">
          <el-card class="chart-card" shadow="hover">
          <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="top-container"
                 :class="{ 'two-cols': !ENABLE_SEMI_FINISHED }">
              <div class="typeNum">
                <div class="typeNum-left">
                  <img src="~@/assets/images/chartCard.svg" alt="图表"
                    style="width: 40px; height: 40px; object-fit: contain;">
                  <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">
@@ -26,22 +29,23 @@
                <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 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 class="typeNum-right-top-text">{{ getInspectStatValue(0, 'completedCount') }} <span class="unit">个</span>
                    </div>
                  </div>
                </div>
              </div>
              <div class="typeNum">
              <div class="typeNum"
                   v-if="ENABLE_SEMI_FINISHED">
                <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>
                  <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>
@@ -50,22 +54,22 @@
                <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 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 class="typeNum-right-top-text">{{ getInspectStatValue(1, 'completedCount') }} <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>
                  <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>
@@ -74,13 +78,11 @@
                <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 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 class="typeNum-right-top-text">{{ getInspectStatValue(2, 'completedCount') }} <span class="unit">个</span>
                    </div>
                  </div>
                </div>
@@ -90,18 +92,21 @@
        </el-col>
        <!-- è´¨æ£€åˆæ ¼çއ -->
        <el-col :span="15">
          <el-card class="chart-card" shadow="hover">
          <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="top-container flex-center"
                 :class="{ 'quality-two-cols': !ENABLE_SEMI_FINISHED }">
              <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;">
                  <img src="~@/assets/images/chartCard.svg"
                       alt="原材料"
                       style="width: 24px; height: 24px; margin-right: 8px;">
                  åŽŸææ–™åˆæ ¼çŽ‡
                </div>
                <div class="quality-card-content">
@@ -111,7 +116,8 @@
                      <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 class="quality-item-chart"
                         ref="materialCompletionChart"></div>
                  </div>
                  <div class="quality-item">
                    <div>
@@ -119,14 +125,17 @@
                      <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 class="quality-item-chart"
                         ref="materialQualityChart"></div>
                  </div>
                </div>
              </div>
              <div class="quality-card green-card">
              <div class="quality-card green-card"
                   v-if="ENABLE_SEMI_FINISHED">
                <div class="quality-card-title">
                  <img src="~@/assets/images/chartCard2.svg" alt="半成品"
                    style="width: 24px; height: 24px; margin-right: 8px;">
                  <img src="~@/assets/images/chartCard2.svg"
                       alt="半成品"
                       style="width: 24px; height: 24px; margin-right: 8px;">
                  åŠæˆå“åˆæ ¼çއ
                </div>
                <div class="quality-card-content">
@@ -136,7 +145,8 @@
                      <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 class="quality-item-chart"
                         ref="semiCompletionChart"></div>
                  </div>
                  <div class="quality-item">
                    <div>
@@ -144,14 +154,16 @@
                      <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 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;">
                  <img src="~@/assets/images/chartCard3.svg"
                       alt="成品"
                       style="width: 24px; height: 24px; margin-right: 8px;">
                  æˆå“åˆæ ¼çއ
                </div>
                <div class="quality-card-content">
@@ -161,7 +173,8 @@
                      <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 class="quality-item-chart"
                         ref="finalCompletionChart"></div>
                  </div>
                  <div class="quality-item">
                    <div>
@@ -169,7 +182,8 @@
                      <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 class="quality-item-chart"
                         ref="finalQualityChart"></div>
                  </div>
                </div>
              </div>
@@ -182,7 +196,8 @@
      <el-row :gutter="20">
        <!-- è´¨æ£€åˆæ ¼çއ -->
        <el-col :span="24">
          <el-card class="chart-card" shadow="hover">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
@@ -191,18 +206,22 @@
            </template>
            <div class="chart-container-line">
              <div class="container-line-left">
                <div style="height: 100%; width: 100%;" ref="usageChartRef">
                <div style="height: 100%; width: 100%;"
                     ref="usageChartRef">
                </div>
              </div>
              <div class="container-line-right">
                <div style="height: 80%; width: 100%;" ref="inspectionChartRef">
                <div style="height: 80%; width: 100%;"
                     ref="inspectionChartRef">
                </div>
                <div class="container-line-right-bottom">
                <div class="container-line-right-bottom"
                     :class="{ 'two-boxes': !ENABLE_SEMI_FINISHED }">
                  <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="inspection-chart-box"
                       v-if="ENABLE_SEMI_FINISHED">
                    <div class="chart-box-title">半成品总数</div>
                    <div class="chart-box-num">{{ getYearlyStatValue(1, 'totalCount') }}</div>
                  </div>
@@ -218,8 +237,13 @@
                 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 v-model="value3"
                              size="mini"
                              :clearable="false"
                              style="width: 60px;"
                              type="year"
                              :disabled-date="disabledDate"
                              placeholder="">
              </el-date-picker>
            </div>
          </el-card>
@@ -230,19 +254,22 @@
      <el-row :gutter="20">
        <!-- æ ·å“è¿›åº¦å›¾è¡¨ -->
        <el-col :span="12">
          <el-card class="chart-card" shadow="hover">
          <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>
            <div ref="equipmentChartRef"
                 class="chart-container"></div>
          </el-card>
        </el-col>
        <!-- è®¾å¤‡ä½¿ç”¨å›¾è¡¨ -->
        <el-col :span="12">
          <el-card class="chart-card" shadow="hover">
          <el-card class="chart-card"
                   shadow="hover">
            <template #header>
              <div class="card-header">
                <div class="chart-title-line"></div>
@@ -253,21 +280,33 @@
              <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"
                       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 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 class="tab-item"
                   :class="{ active: activeTab === 'raw' }"
                   @click="activeTab = 'raw'">原材料</div>
              <div class="tab-item"
                   v-if="ENABLE_SEMI_FINISHED"
                   :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>
@@ -277,1194 +316,1286 @@
</template>
<script setup>
import { ref, reactive, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import * as echarts from "echarts";
import { getInspectStatistics, getPassRateStatistics, getMonthlyPassRateStatistics, getYearlyPassRateStatistics, getMonthlyCompletionDetails, getTopParameters } from "@/api/reportAnalysis/qualityReport";
  import { ref, reactive, onMounted, nextTick, watch } from "vue";
  import { ElMessage } from "element-plus";
  import * as echarts from "echarts";
  import {
    getInspectStatistics,
    getPassRateStatistics,
    getMonthlyPassRateStatistics,
    getYearlyPassRateStatistics,
    getMonthlyCompletionDetails,
    getTopParameters,
  } from "@/api/reportAnalysis/qualityReport";
// å“åº”式数据
const filterForm = reactive({
  dateRange: [],
  reportType: "sample",
});
  const ENABLE_SEMI_FINISHED = false;
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 filterForm = reactive({
    dateRange: [],
    reportType: "sample",
  });
const getParameterColor = (index) => {
  const colors = ['#165DFF', '#14C9C9', '#F7BA1E', '#722ED1', '#3491FA', '#FF7D00', '#F53F3F'];
  return colors[index % colors.length];
};
  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 getYearlyStatValue = (type, field) => {
  const stat = yearlyPassRateData.value.find(item => item.modelType === type);
  return stat ? stat[field] : 0;
};
  const getParameterColor = index => {
    const colors = [
      "#165DFF",
      "#14C9C9",
      "#F7BA1E",
      "#722ED1",
      "#3491FA",
      "#FF7D00",
      "#F53F3F",
    ];
    return colors[index % colors.length];
  };
const getInspectStatValue = (type, field) => {
  const stat = inspectStatisticsData.value.find(item => item.modelType === type);
  return stat ? stat[field] : 0;
};
  const getYearlyStatValue = (type, field) => {
    const stat = yearlyPassRateData.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] ? Number(stat[field]).toFixed(0) + '%' : '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] ? Number(stat[field]).toFixed(0) + "%" : "0%";
      }
      return stat[field];
    }
    return stat[field];
  }
  return field === 'completionRate' || field === 'passRate' ? '0%' : 0;
};
    return field === "completionRate" || field === "passRate" ? "0%" : 0;
  };
const fetchInspectStatisticsData = async () => {
  try {
    const res = await getInspectStatistics();
    if (res.code === 200) {
      inspectStatisticsData.value = res.data;
  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);
    }
  } 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();
  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);
    }
  } 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();
  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);
    }
  } 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();
  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);
    }
  } 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();
  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);
    }
  } 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();
  const fetchTopParametersData = async () => {
    try {
      const typeMap = {
        raw: 1,
        final: 3,
        ...(ENABLE_SEMI_FINISHED ? { semi: 2 } : {}),
      };
      const tabKey = ENABLE_SEMI_FINISHED
        ? activeTab.value
        : activeTab.value === "semi"
        ? "raw"
        : activeTab.value;
      const res = await getTopParameters(typeMap[tabKey] ?? 1);
      if (res.code === 200) {
        topParametersData.value = res.data;
        initSampleChart();
      }
    } catch (error) {
      console.error("Failed to fetch top parameters:", error);
    }
  } catch (error) {
    console.error("Failed to fetch top parameters:", error);
  }
};
  };
const tableData = ref([]);
const tableLoading = ref(false);
const pagination = reactive({
  currentPage: 1,
  pageSize: 20,
  total: 0,
});
  const tableData = ref([]);
  const tableLoading = ref(false);
  const pagination = reactive({
    currentPage: 1,
    pageSize: 20,
    total: 0,
  });
// åˆå§‹åŒ–年份为当前年份(使用Date对象)
const currentYear = new Date().getFullYear();
const value3 = ref(new Date(currentYear, 0, 1));
// é™åˆ¶æ—¥æœŸé€‰æ‹©ï¼Œä¸å…è®¸é€‰æ‹©ä»Šå¹´ä¹‹åŽçš„年份
const disabledDate = time => {
  // åˆå§‹åŒ–年份为当前年份(使用Date对象)
  const currentYear = new Date().getFullYear();
  return time.getFullYear() > currentYear;
};
  const value3 = ref(new Date(currentYear, 0, 1));
// ç›‘听年份变化
import { watch } from "vue";
watch(value3, () => {
  fetchMonthlyPassRateData();
  fetchYearlyPassRateData();
  fetchMonthlyCompletionDetailsData();
});
  // é™åˆ¶æ—¥æœŸé€‰æ‹©ï¼Œä¸å…è®¸é€‰æ‹©ä»Šå¹´ä¹‹åŽçš„年份
  const disabledDate = time => {
    const currentYear = new Date().getFullYear();
    return time.getFullYear() > currentYear;
  };
watch(activeTab, () => {
  fetchTopParametersData();
});
  // ç›‘听年份变化
  watch(value3, () => {
    fetchMonthlyPassRateData();
    fetchYearlyPassRateData();
    fetchMonthlyCompletionDetailsData();
  });
  watch(activeTab, val => {
    if (!ENABLE_SEMI_FINISHED && val === "semi") {
      activeTab.value = "raw";
      return;
    }
    fetchTopParametersData();
  });
// å›¾è¡¨å¼•用
const sampleChartRef = ref(null);
const equipmentChartRef = ref(null);
const inspectionChartRef = ref(null);
const usageChartRef = ref(null);
  // å›¾è¡¨å¼•用
  const sampleChartRef = ref(null);
  const equipmentChartRef = ref(null);
  const inspectionChartRef = ref(null);
  const usageChartRef = ref(null);
// è´¨æ£€åˆæ ¼çŽ‡å›¾è¡¨å¼•ç”¨
const materialCompletionChart = ref(null);
const materialQualityChart = ref(null);
const semiCompletionChart = ref(null);
const semiQualityChart = ref(null);
const finalCompletionChart = ref(null);
const finalQualityChart = ref(null);
  // è´¨æ£€åˆæ ¼çŽ‡å›¾è¡¨å¼•ç”¨
  const materialCompletionChart = ref(null);
  const materialQualityChart = ref(null);
  const semiCompletionChart = ref(null);
  const semiQualityChart = ref(null);
  const finalCompletionChart = ref(null);
  const finalQualityChart = ref(null);
// å›¾è¡¨å®žä¾‹
let sampleChart = null;
let equipmentChart = null;
let inspectionChart = null;
let usageChart = null;
  // å›¾è¡¨å®žä¾‹
  let sampleChart = null;
  let equipmentChart = null;
  let inspectionChart = null;
  let usageChart = null;
// è´¨æ£€åˆæ ¼çŽ‡å›¾è¡¨å®žä¾‹
let materialCompletionChartInstance = null;
let materialQualityChartInstance = null;
let semiCompletionChartInstance = null;
let semiQualityChartInstance = null;
let finalCompletionChartInstance = null;
let finalQualityChartInstance = null;
  // è´¨æ£€åˆæ ¼çŽ‡å›¾è¡¨å®žä¾‹
  let materialCompletionChartInstance = null;
  let materialQualityChartInstance = null;
  let semiCompletionChartInstance = null;
  let semiQualityChartInstance = null;
  let finalCompletionChartInstance = null;
  let finalQualityChartInstance = null;
// åˆå§‹åŒ–样品进度图表
const initSampleChart = () => {
  if (sampleChartRef.value) {
    sampleChart = echarts.init(sampleChartRef.value);
    const option = {
      title: {
        show: false,
      },
      tooltip: {
        trigger: "item",
        formatter: "{a} <br/>{b}: {c} ({d}%)",
      },
      // legend: {
      //   orient: "vertical",
      //   left: "left",
      // },
      series: [
        {
          name: "检测项目",
          type: "pie",
          radius: ["40%", "80%"],
          avoidLabelOverlap: false,
          label: {
            show: false,
            position: "center",
          },
          emphasis: {
  // åˆå§‹åŒ–样品进度图表
  const initSampleChart = () => {
    if (sampleChartRef.value) {
      sampleChart = echarts.init(sampleChartRef.value);
      const option = {
        title: {
          show: false,
        },
        tooltip: {
          trigger: "item",
          formatter: "{a} <br/>{b}: {c} ({d}%)",
        },
        // legend: {
        //   orient: "vertical",
        //   left: "left",
        // },
        series: [
          {
            name: "检测项目",
            type: "pie",
            radius: ["40%", "80%"],
            avoidLabelOverlap: false,
            label: {
              show: true,
              fontSize: "18",
              fontWeight: "bold",
              show: false,
              position: "center",
            },
            emphasis: {
              label: {
                show: true,
                fontSize: "18",
                fontWeight: "bold",
              },
            },
            labelLine: {
              show: false,
            },
            data: topParametersData.value.list.map((item, index) => ({
              value: item.count,
              name: item.name,
              itemStyle: { color: getParameterColor(index) },
            })),
          },
          labelLine: {
            show: false,
          },
          data: topParametersData.value.list.map((item, index) => ({
            value: item.count,
            name: item.name,
            itemStyle: { color: getParameterColor(index) }
          })),
        },
      ],
    };
    sampleChart.setOption(option);
  }
};
        ],
      };
      sampleChart.setOption(option);
    }
  };
// åˆå§‹åŒ–设备使用图表
const initEquipmentChart = () => {
  if (equipmentChartRef.value) {
    equipmentChart = echarts.init(equipmentChartRef.value);
    const option = {
      title: {
        show: false,
      },
      tooltip: {
        trigger: "axis",
        axisPointer: {
          type: "shadow",
        },
      },
      grid: {
        left: "1%",
        right: "1%",
        bottom: "1%",
        containLabel: true,
      },
      legend: {
        data: ["原材料", "半成品", "成品"], // å›¾ä¾‹æ•°æ®
        icon: ["circle", "circle", "circle"],
        itemWidth: 10, // è®¾ç½®å›¾æ ‡å®½åº¦
        itemHeight: 10,
        itemGap: 30,
        right: 10,
      },
      xAxis: {
        type: "category",
        data: [
          value3.value.getFullYear() + "-1",
          value3.value.getFullYear() + "-2",
          value3.value.getFullYear() + "-3",
          value3.value.getFullYear() + "-4",
          value3.value.getFullYear() + "-5",
          value3.value.getFullYear() + "-6",
          value3.value.getFullYear() + "-7",
          value3.value.getFullYear() + "-8",
          value3.value.getFullYear() + "-9",
          value3.value.getFullYear() + "-10",
          value3.value.getFullYear() + "-11",
          value3.value.getFullYear() + "-12",
        ], // æ”¹ä¸ºåäºŒä¸ªæœˆ
      },
      yAxis: {
        type: "value",
        name: "数(个)",
      },
      series: [
  // åˆå§‹åŒ–设备使用图表
  const initEquipmentChart = () => {
    if (equipmentChartRef.value) {
      equipmentChart = echarts.init(equipmentChartRef.value);
      const legendData = ENABLE_SEMI_FINISHED
        ? ["原材料", "半成品", "成品"]
        : ["原材料", "成品"];
      const barWidth = ENABLE_SEMI_FINISHED ? "15%" : "20%";
      const series = [
        {
          name: "原材料",
          type: "bar",
          barWidth: "15%",
          data: monthlyCompletionDetailsData.value.map(item => item.rawMaterialCount),
          barWidth,
          data: monthlyCompletionDetailsData.value.map(
            item => item.rawMaterialCount
          ),
          itemStyle: {
            color: "#409EFF",
          },
        },
        {
          name: "半成品",
          type: "bar",
          barWidth: "15%",
          data: monthlyCompletionDetailsData.value.map(item => item.processCount),
          itemStyle: {
            color: "#67C23A",
          },
        },
        ...(ENABLE_SEMI_FINISHED
          ? [
              {
                name: "半成品",
                type: "bar",
                barWidth,
                data: monthlyCompletionDetailsData.value.map(
                  item => item.processCount
                ),
                itemStyle: {
                  color: "#67C23A",
                },
              },
            ]
          : []),
        {
          name: "成品",
          type: "bar",
          barWidth: "15%",
          data: monthlyCompletionDetailsData.value.map(item => item.outgoingCount),
          barWidth,
          data: monthlyCompletionDetailsData.value.map(
            item => item.outgoingCount
          ),
          itemStyle: {
            color: "#E6A23C",
          },
        },
      ],
    };
    equipmentChart.setOption(option);
  }
};
// åˆå§‹åŒ–检测项目图表
const initInspectionChart = () => {
  if (inspectionChartRef.value) {
    inspectionChart = echarts.init(inspectionChartRef.value);
    const option = {
      title: {
        show: false,
      },
      tooltip: {
        trigger: "item",
      },
      series: [
        {
          type: "pie",
          radius: "70%",
          data: [
            { 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,
              shadowOffsetX: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
      ];
      const option = {
        title: {
          show: false,
        },
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
        },
      ],
    };
    inspectionChart.setOption(option);
  }
};
        grid: {
          left: "1%",
          right: "1%",
          bottom: "1%",
          containLabel: true,
        },
        legend: {
          data: legendData, // å›¾ä¾‹æ•°æ®
          icon: legendData.map(() => "circle"),
          itemWidth: 10, // è®¾ç½®å›¾æ ‡å®½åº¦
          itemHeight: 10,
          itemGap: 30,
          right: 10,
        },
        xAxis: {
          type: "category",
          data: [
            value3.value.getFullYear() + "-1",
            value3.value.getFullYear() + "-2",
            value3.value.getFullYear() + "-3",
            value3.value.getFullYear() + "-4",
            value3.value.getFullYear() + "-5",
            value3.value.getFullYear() + "-6",
            value3.value.getFullYear() + "-7",
            value3.value.getFullYear() + "-8",
            value3.value.getFullYear() + "-9",
            value3.value.getFullYear() + "-10",
            value3.value.getFullYear() + "-11",
            value3.value.getFullYear() + "-12",
          ], // æ”¹ä¸ºåäºŒä¸ªæœˆ
        },
        yAxis: {
          type: "value",
          name: "数(个)",
        },
        series,
      };
      equipmentChart.setOption(option);
    }
  };
// åˆå§‹åŒ–领用记录图表
const initUsageChart = () => {
  // æ£€æŸ¥å›¾è¡¨å®¹å™¨æ˜¯å¦å­˜åœ¨
  if (usageChartRef.value) {
    // åˆå§‹åŒ– ECharts å®žä¾‹
    usageChart = echarts.init(usageChartRef.value);
    // é…ç½®å›¾è¡¨é€‰é¡¹
    const option = {
      // æ ‡é¢˜é…ç½®ï¼ˆéšè—ï¼‰
      title: {
        show: false,
      },
      // ç½‘格配置(调整边距)
      grid: {
        left: "1%",
        right: "4%",
        bottom: "3%",
        top: "14%",
        containLabel: true,
      },
      // æç¤ºæ¡†é…ç½®
      tooltip: {
        trigger: "axis", // è§¦å‘类型为坐标轴触发
      },
      // å›¾ä¾‹é…ç½®
      legend: {
        data: ["原材料", "半成品", "成品"], // å›¾ä¾‹æ•°æ®
        icon: ["circle", "circle", "circle"],
        itemWidth: 10, // è®¾ç½®å›¾æ ‡å®½åº¦
        itemHeight: 10,
        itemGap: 30,
      },
      // X轴配置
      xAxis: {
        type: "category", // ç±»åˆ«è½´
        boundaryGap: false, // åæ ‡è½´ä¸¤è¾¹ç•™ç™½ç­–ç•¥
        data: [
          value3.value.getFullYear() + "-1",
          value3.value.getFullYear() + "-2",
          value3.value.getFullYear() + "-3",
          value3.value.getFullYear() + "-4",
          value3.value.getFullYear() + "-5",
          value3.value.getFullYear() + "-6",
          value3.value.getFullYear() + "-7",
          value3.value.getFullYear() + "-8",
          value3.value.getFullYear() + "-9",
          value3.value.getFullYear() + "-10",
          value3.value.getFullYear() + "-11",
          value3.value.getFullYear() + "-12",
        ], // X轴数据
      },
      // Y轴配置
      yAxis: {
        type: "value", // æ•°å€¼è½´
        name: "单位:%",
      },
      // ç³»åˆ—数据
      series: [
  // åˆå§‹åŒ–检测项目图表
  const initInspectionChart = () => {
    if (inspectionChartRef.value) {
      inspectionChart = echarts.init(inspectionChartRef.value);
      const data = [
        {
          name: "原材料", // ç³»åˆ—名称
          type: "line", // å›¾è¡¨ç±»åž‹ä¸ºæŠ˜çº¿å›¾
          // stack: "Total", // å †å åç§°
          value: getYearlyStatValue(0, "totalCount"),
          name: "原材料",
          itemStyle: { color: "#1890FF" },
        },
        ...(ENABLE_SEMI_FINISHED
          ? [
              {
                value: getYearlyStatValue(1, "totalCount"),
                name: "半成品",
                itemStyle: { color: "#F7BA1E" },
              },
            ]
          : []),
        {
          value: getYearlyStatValue(2, "totalCount"),
          name: "成品",
          itemStyle: { color: "#14C9C9" },
        },
      ];
      const option = {
        title: {
          show: false,
        },
        tooltip: {
          trigger: "item",
        },
        series: [
          {
            type: "pie",
            radius: "70%",
            data,
            label: {
              show: true,
              formatter: "{b}: {c}",
            },
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)",
              },
            },
          },
        ],
      };
      inspectionChart.setOption(option);
    }
  };
  // åˆå§‹åŒ–领用记录图表
  const initUsageChart = () => {
    // æ£€æŸ¥å›¾è¡¨å®¹å™¨æ˜¯å¦å­˜åœ¨
    if (usageChartRef.value) {
      // åˆå§‹åŒ– ECharts å®žä¾‹
      usageChart = echarts.init(usageChartRef.value);
      const legendData = ENABLE_SEMI_FINISHED
        ? ["原材料", "半成品", "成品"]
        : ["原材料", "成品"];
      const series = [
        {
          name: "原材料",
          type: "line",
          symbol: "circle",
          itemStyle: {
            color: "#1890FF", // è®¾ç½®è¿™æ¡çº¿çš„颜色
            color: "#1890FF",
          },
          data: monthlyPassRateData.value.map(item => item.rawMaterial.passRate),
        },
        ...(ENABLE_SEMI_FINISHED
          ? [
              {
                name: "半成品",
                type: "line",
                symbol: "circle",
                itemStyle: {
                  color: "#F7BA1E",
                },
                data: monthlyPassRateData.value.map(
                  item => item.process.passRate
                ),
              },
            ]
          : []),
        {
          name: "半成品", // ç³»åˆ—名称
          type: "line", // å›¾è¡¨ç±»åž‹ä¸ºæŠ˜çº¿å›¾
          // stack: "Total", // å †å åç§°
          name: "成品",
          type: "line",
          symbol: "circle",
          itemStyle: {
            color: "#F7BA1E", // è®¾ç½®è¿™æ¡çº¿çš„颜色
          },
          data: monthlyPassRateData.value.map(item => item.process.passRate),
        },
        {
          name: "成品", // ç³»åˆ—名称
          type: "line", // å›¾è¡¨ç±»åž‹ä¸ºæŠ˜çº¿å›¾
          // stack: "Total", // å †å åç§°
          symbol: "circle",
          itemStyle: {
            color: "#14C9C9", // è®¾ç½®è¿™æ¡çº¿çš„颜色
            color: "#14C9C9",
          },
          data: monthlyPassRateData.value.map(item => item.outgoing.passRate),
        },
      ],
    };
    // å°†é…ç½®åº”用到图表
    usageChart.setOption(option);
  }
};
// åˆå§‹åŒ–质检合格率图表
const initQualityChart = (chartRef, color, value = 0.8) => {
  if (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: [
        {
          type: "pie",
          radius: ["45%", "90%"],
          itemStyle: {
            borderColor: "#f5f5f5",
            // borderWidth: 2,
          },
          labelLine: {
            show: false,
          },
          data: [
            { value: numericValue, itemStyle: { color: color } },
            { value: 1 - numericValue, itemStyle: { color: "#f5f5f5" } },
          ],
      ];
      // é…ç½®å›¾è¡¨é€‰é¡¹
      const option = {
        // æ ‡é¢˜é…ç½®ï¼ˆéšè—ï¼‰
        title: {
          show: false,
        },
      ],
    };
    chart.setOption(option);
    return chart;
  }
  return null;
};
// åˆå§‹åŒ–所有质检合格率图表
const initAllQualityCharts = () => {
  materialCompletionChartInstance = initQualityChart(
    materialCompletionChart,
    "#1890ff",
    getPassRateStatValue(0, 'completionRate')
  );
  materialQualityChartInstance = initQualityChart(
    materialQualityChart,
    "#52c41a",
    getPassRateStatValue(0, 'passRate')
  );
  semiCompletionChartInstance = initQualityChart(
    semiCompletionChart,
    "#1890ff",
    getPassRateStatValue(1, 'completionRate')
  );
  semiQualityChartInstance = initQualityChart(
    semiQualityChart,
    "#52c41a",
    getPassRateStatValue(1, 'passRate')
  );
  finalCompletionChartInstance = initQualityChart(
    finalCompletionChart,
    "#1890ff",
    getPassRateStatValue(2, 'completionRate')
  );
  finalQualityChartInstance = initQualityChart(
    finalQualityChart,
    "#722ed1",
    getPassRateStatValue(2, 'passRate')
  );
};
// äº‹ä»¶å¤„理函数
const handleFilterChange = () => {
  ElMessage.success("筛选条件已更新");
  // è¿™é‡Œå¯ä»¥æ ¹æ®ç­›é€‰æ¡ä»¶é‡æ–°åŠ è½½æ•°æ®
};
const resetFilter = () => {
  filterForm.dateRange = [];
  filterForm.reportType = "sample";
  ElMessage.info("筛选条件已重置");
};
const exportReport = () => {
  ElMessage.success("报表导出功能开发中...");
};
const refreshSampleChart = () => {
  initSampleChart();
  ElMessage.success("样品进度图表已刷新");
};
const refreshEquipmentChart = () => {
  initEquipmentChart();
  ElMessage.success("设备使用图表已刷新");
};
const refreshInspectionChart = () => {
  initInspectionChart();
  ElMessage.success("检测项目图表已刷新");
};
const refreshUsageChart = () => {
  initUsageChart();
  ElMessage.success("领用记录图表已刷新");
};
const refreshTable = () => {
  tableLoading.value = true;
  setTimeout(() => {
    tableLoading.value = false;
    ElMessage.success("表格数据已刷新");
  }, 1000);
};
const exportTable = () => {
  ElMessage.success("表格导出功能开发中...");
};
const handleSizeChange = val => {
  pagination.pageSize = val;
  // é‡æ–°åŠ è½½æ•°æ®
};
const handleCurrentChange = val => {
  pagination.currentPage = val;
  // é‡æ–°åŠ è½½æ•°æ®
};
const getStatusType = status => {
  const statusMap = {
    å·²å®Œæˆ: "success",
    æ£€æµ‹ä¸­: "warning",
    å¾…检测: "info",
    å·²æš‚停: "danger",
    ä½¿ç”¨ä¸­: "primary",
    ç©ºé—²: "info",
        // ç½‘格配置(调整边距)
        grid: {
          left: "1%",
          right: "4%",
          bottom: "3%",
          top: "14%",
          containLabel: true,
        },
        // æç¤ºæ¡†é…ç½®
        tooltip: {
          trigger: "axis", // è§¦å‘类型为坐标轴触发
        },
        // å›¾ä¾‹é…ç½®
        legend: {
          data: legendData, // å›¾ä¾‹æ•°æ®
          icon: legendData.map(() => "circle"),
          itemWidth: 10, // è®¾ç½®å›¾æ ‡å®½åº¦
          itemHeight: 10,
          itemGap: 30,
        },
        // X轴配置
        xAxis: {
          type: "category", // ç±»åˆ«è½´
          boundaryGap: false, // åæ ‡è½´ä¸¤è¾¹ç•™ç™½ç­–ç•¥
          data: [
            value3.value.getFullYear() + "-1",
            value3.value.getFullYear() + "-2",
            value3.value.getFullYear() + "-3",
            value3.value.getFullYear() + "-4",
            value3.value.getFullYear() + "-5",
            value3.value.getFullYear() + "-6",
            value3.value.getFullYear() + "-7",
            value3.value.getFullYear() + "-8",
            value3.value.getFullYear() + "-9",
            value3.value.getFullYear() + "-10",
            value3.value.getFullYear() + "-11",
            value3.value.getFullYear() + "-12",
          ], // X轴数据
        },
        // Y轴配置
        yAxis: {
          type: "value", // æ•°å€¼è½´
          name: "单位:%",
        },
        // ç³»åˆ—数据
        series,
      };
      // å°†é…ç½®åº”用到图表
      usageChart.setOption(option);
    }
  };
  return statusMap[status] || "info";
};
const getProgressStatus = progress => {
  if (progress === 100) return "success";
  if (progress >= 80) return "warning";
  if (progress >= 50) return "";
  return "exception";
};
  // åˆå§‹åŒ–质检合格率图表
  const initQualityChart = (chartRef, color, value = 0.8) => {
    if (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: [
          {
            type: "pie",
            radius: ["45%", "90%"],
            itemStyle: {
              borderColor: "#f5f5f5",
              // borderWidth: 2,
            },
            labelLine: {
              show: false,
            },
            data: [
              { value: numericValue, itemStyle: { color: color } },
              { value: 1 - numericValue, itemStyle: { color: "#f5f5f5" } },
            ],
          },
        ],
      };
      chart.setOption(option);
      return chart;
    }
    return null;
  };
const viewDetail = row => {
  ElMessage.info(`查看详情: ${row.name}`);
};
  // åˆå§‹åŒ–所有质检合格率图表
  const initAllQualityCharts = () => {
    materialCompletionChartInstance = initQualityChart(
      materialCompletionChart,
      "#1890ff",
      getPassRateStatValue(0, "completionRate")
    );
    materialQualityChartInstance = initQualityChart(
      materialQualityChart,
      "#52c41a",
      getPassRateStatValue(0, "passRate")
    );
    if (ENABLE_SEMI_FINISHED) {
      semiCompletionChartInstance = initQualityChart(
        semiCompletionChart,
        "#1890ff",
        getPassRateStatValue(1, "completionRate")
      );
      semiQualityChartInstance = initQualityChart(
        semiQualityChart,
        "#52c41a",
        getPassRateStatValue(1, "passRate")
      );
    } else {
      semiCompletionChartInstance = null;
      semiQualityChartInstance = null;
    }
    finalCompletionChartInstance = initQualityChart(
      finalCompletionChart,
      "#1890ff",
      getPassRateStatValue(2, "completionRate")
    );
    finalQualityChartInstance = initQualityChart(
      finalQualityChart,
      "#722ed1",
      getPassRateStatValue(2, "passRate")
    );
  };
const editItem = row => {
  ElMessage.info(`编辑项目: ${row.name}`);
};
  // äº‹ä»¶å¤„理函数
  const handleFilterChange = () => {
    ElMessage.success("筛选条件已更新");
    // è¿™é‡Œå¯ä»¥æ ¹æ®ç­›é€‰æ¡ä»¶é‡æ–°åŠ è½½æ•°æ®
  };
// ç”Ÿå‘½å‘¨æœŸ
onMounted(() => {
  fetchInspectStatisticsData();
  fetchPassRateStatisticsData();
  fetchMonthlyPassRateData();
  fetchYearlyPassRateData();
  fetchMonthlyCompletionDetailsData();
  fetchTopParametersData();
  nextTick(() => {
  const resetFilter = () => {
    filterForm.dateRange = [];
    filterForm.reportType = "sample";
    ElMessage.info("筛选条件已重置");
  };
  const exportReport = () => {
    ElMessage.success("报表导出功能开发中...");
  };
  const refreshSampleChart = () => {
    initSampleChart();
    initEquipmentChart();
    initInspectionChart();
    initUsageChart();
    initAllQualityCharts();
  });
  // ç›‘听窗口大小变化,重新调整图表大小
  window.addEventListener("resize", () => {
    sampleChart?.resize();
    equipmentChart?.resize();
    inspectionChart?.resize();
    usageChart?.resize();
    ElMessage.success("样品进度图表已刷新");
  };
    // è°ƒæ•´è´¨æ£€åˆæ ¼çŽ‡å›¾è¡¨å¤§å°
    materialCompletionChartInstance?.resize();
    materialQualityChartInstance?.resize();
    semiCompletionChartInstance?.resize();
    semiQualityChartInstance?.resize();
    finalCompletionChartInstance?.resize();
    finalQualityChartInstance?.resize();
  const refreshEquipmentChart = () => {
    initEquipmentChart();
    ElMessage.success("设备使用图表已刷新");
  };
  const refreshInspectionChart = () => {
    initInspectionChart();
    ElMessage.success("检测项目图表已刷新");
  };
  const refreshUsageChart = () => {
    initUsageChart();
    ElMessage.success("领用记录图表已刷新");
  };
  const refreshTable = () => {
    tableLoading.value = true;
    setTimeout(() => {
      tableLoading.value = false;
      ElMessage.success("表格数据已刷新");
    }, 1000);
  };
  const exportTable = () => {
    ElMessage.success("表格导出功能开发中...");
  };
  const handleSizeChange = val => {
    pagination.pageSize = val;
    // é‡æ–°åŠ è½½æ•°æ®
  };
  const handleCurrentChange = val => {
    pagination.currentPage = val;
    // é‡æ–°åŠ è½½æ•°æ®
  };
  const getStatusType = status => {
    const statusMap = {
      å·²å®Œæˆ: "success",
      æ£€æµ‹ä¸­: "warning",
      å¾…检测: "info",
      å·²æš‚停: "danger",
      ä½¿ç”¨ä¸­: "primary",
      ç©ºé—²: "info",
    };
    return statusMap[status] || "info";
  };
  const getProgressStatus = progress => {
    if (progress === 100) return "success";
    if (progress >= 80) return "warning";
    if (progress >= 50) return "";
    return "exception";
  };
  const viewDetail = row => {
    ElMessage.info(`查看详情: ${row.name}`);
  };
  const editItem = row => {
    ElMessage.info(`编辑项目: ${row.name}`);
  };
  // ç”Ÿå‘½å‘¨æœŸ
  onMounted(() => {
    if (!ENABLE_SEMI_FINISHED && activeTab.value === "semi") {
      activeTab.value = "raw";
    }
    fetchInspectStatisticsData();
    fetchPassRateStatisticsData();
    fetchMonthlyPassRateData();
    fetchYearlyPassRateData();
    fetchMonthlyCompletionDetailsData();
    fetchTopParametersData();
    nextTick(() => {
      initSampleChart();
      initEquipmentChart();
      initInspectionChart();
      initUsageChart();
      initAllQualityCharts();
    });
    // ç›‘听窗口大小变化,重新调整图表大小
    window.addEventListener("resize", () => {
      sampleChart?.resize();
      equipmentChart?.resize();
      inspectionChart?.resize();
      usageChart?.resize();
      // è°ƒæ•´è´¨æ£€åˆæ ¼çŽ‡å›¾è¡¨å¤§å°
      materialCompletionChartInstance?.resize();
      materialQualityChartInstance?.resize();
      if (ENABLE_SEMI_FINISHED) {
        semiCompletionChartInstance?.resize();
        semiQualityChartInstance?.resize();
      }
      finalCompletionChartInstance?.resize();
      finalQualityChartInstance?.resize();
    });
  });
});
</script>
<style scoped>
.report-management {
  padding: 20px;
  min-height: 100vh;
  /* height: 87vh;
  overflow: hidden; */
}
  .report-management {
    padding: 20px;
    min-height: 100vh;
    /* height: 87vh;
      overflow: hidden; */
  }
.page-header {
  margin-bottom: 20px;
  text-align: center;
}
  .page-header {
    margin-bottom: 20px;
    text-align: center;
  }
.page-header h2 {
  color: #303133;
  margin-bottom: 8px;
  font-size: 24px;
  font-weight: 600;
}
  .page-header h2 {
    color: #303133;
    margin-bottom: 8px;
    font-size: 24px;
    font-weight: 600;
  }
.page-header p {
  color: #909399;
  font-size: 14px;
  margin: 0;
}
  .page-header p {
    color: #909399;
    font-size: 14px;
    margin: 0;
  }
.filter-card {
  margin-bottom: 20px;
}
  .filter-card {
    margin-bottom: 20px;
  }
.statistics-cards {
  margin-bottom: 20px;
}
  .statistics-cards {
    margin-bottom: 20px;
  }
.stat-card {
  height: 120px;
}
  .stat-card {
    height: 120px;
  }
.stat-content {
  display: flex;
  align-items: center;
  height: 100%;
}
  .stat-content {
    display: flex;
    align-items: center;
    height: 100%;
  }
.stat-icon {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 20px;
  font-size: 24px;
  color: white;
}
  .stat-icon {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 20px;
    font-size: 24px;
    color: white;
  }
.stat-card:nth-child(1) .stat-icon {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
  .stat-card:nth-child(1) .stat-icon {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  }
.stat-card:nth-child(2) .stat-icon {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
  .stat-card:nth-child(2) .stat-icon {
    background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  }
.stat-card:nth-child(3) .stat-icon {
  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
  .stat-card:nth-child(3) .stat-icon {
    background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
  }
.stat-card:nth-child(4) .stat-icon {
  background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
  .stat-card:nth-child(4) .stat-icon {
    background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
  }
.stat-info {
  flex: 1;
}
  .stat-info {
    flex: 1;
  }
.stat-number {
  font-size: 28px;
  font-weight: bold;
  color: #303133;
  margin-bottom: 8px;
}
  .stat-number {
    font-size: 28px;
    font-weight: bold;
    color: #303133;
    margin-bottom: 8px;
  }
.stat-label {
  font-size: 14px;
  color: #909399;
}
  .stat-label {
    font-size: 14px;
    color: #909399;
  }
.charts-container {
  /* margin-bottom: 20px; */
  position: relative;
}
  .charts-container {
    /* margin-bottom: 20px; */
    position: relative;
  }
.chart-card {
  margin-bottom: 20px;
}
  .chart-card {
    margin-bottom: 20px;
  }
.container-line-right-bottom {
  height: 20%;
  width: 100%;
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  /* background-color: #5b3f3f; */
}
  .container-line-right-bottom {
    height: 20%;
    width: 100%;
    display: flex;
    justify-content: space-evenly;
    align-items: center;
    /* background-color: #5b3f3f; */
  }
.card-header {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  font-family: Source Han Sans, Source Han Sans;
  font-weight: 700;
  font-size: 18px;
  color: #000000;
  /* line-height: 27px; */
  text-align: left;
  font-style: normal;
  text-transform: none;
}
  .card-header {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    font-family: Source Han Sans, Source Han Sans;
    font-weight: 700;
    font-size: 18px;
    color: #000000;
    /* line-height: 27px; */
    text-align: left;
    font-style: normal;
    text-transform: none;
  }
.chart-title-line {
  width: 6px;
  height: 22px;
  background-color: #161a9a;
  margin-right: 16px;
  border-radius: 3px;
}
  .chart-title-line {
    width: 6px;
    height: 22px;
    background-color: #161a9a;
    margin-right: 16px;
    border-radius: 3px;
  }
.chart-container {
  height: 250px;
  width: 100%;
}
  .chart-container {
    height: 250px;
    width: 100%;
  }
.chart-container-line {
  height: 250px;
  width: 100%;
  display: flex;
  position: relative;
}
  .chart-container-line {
    height: 250px;
    width: 100%;
    display: flex;
    position: relative;
  }
/* Tab é€‰æ‹©å™¨æ ·å¼ */
.tab-selector {
  position: absolute;
  top: 20px;
  right: 40px;
  display: flex;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
}
  /* Tab é€‰æ‹©å™¨æ ·å¼ */
  .tab-selector {
    position: absolute;
    top: 20px;
    right: 40px;
    display: flex;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    overflow: hidden;
  }
.tab-item {
  padding: 4px 12px;
  cursor: pointer;
  font-size: 14px;
  color: #606266;
  background-color: #fff;
  border-right: 1px solid #dcdfe6;
  transition: all 0.3s;
}
  .tab-item {
    padding: 4px 12px;
    cursor: pointer;
    font-size: 14px;
    color: #606266;
    background-color: #fff;
    border-right: 1px solid #dcdfe6;
    transition: all 0.3s;
  }
.tab-item:last-child {
  border-right: none;
}
  .tab-item:last-child {
    border-right: none;
  }
.tab-item:hover {
  color: #409eff;
}
  .tab-item:hover {
    color: #409eff;
  }
.tab-item.active {
  color: #fff;
  background-color: #409eff;
}
  .tab-item.active {
    color: #fff;
    background-color: #409eff;
  }
.container-line-left {
  height: 100%;
  width: 66%;
}
  .container-line-left {
    height: 100%;
    width: 66%;
  }
.container-line-right {
  height: 100%;
  width: 34%;
}
  .container-line-right {
    height: 100%;
    width: 34%;
  }
.container-line2-left {
  height: 100%;
  width: 50%;
}
  .container-line2-left {
    height: 100%;
    width: 50%;
  }
.info-box {
  width: 92%;
  margin-left: 4%;
  height: 100%;
  background-color: #f7f8fa;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-around;
}
  .info-box {
    width: 92%;
    margin-left: 4%;
    height: 100%;
    background-color: #f7f8fa;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-around;
  }
.info-box-header {
  width: 100%;
  margin-left: 20px;
  color: #1d2129;
  font-size: 16px;
  font-weight: 500;
}
  .info-box-header {
    width: 100%;
    margin-left: 20px;
    color: #1d2129;
    font-size: 16px;
    font-weight: 500;
  }
.info-line {
  width: 100%;
  display: flex;
  padding-left: 20px;
  align-items: center;
}
  .info-line {
    width: 100%;
    display: flex;
    padding-left: 20px;
    align-items: center;
  }
.info-icon {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 8px;
}
  .info-icon {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-right: 8px;
  }
.info-line-title {
  font-size: 12px;
  color: #4e5969;
  flex: 1;
}
  .info-line-title {
    font-size: 12px;
    color: #4e5969;
    flex: 1;
  }
.info-line-value1 {
  font-size: 12px;
  color: #3d3d3d;
  color: #1d2129;
  font-weight: 500;
  margin-right: 15%;
}
  .info-line-value1 {
    font-size: 12px;
    color: #3d3d3d;
    color: #1d2129;
    font-weight: 500;
    margin-right: 15%;
  }
.info-line-value2 {
  font-size: 12px;
  color: #3d3d3d;
  color: #1d2129;
  font-weight: 500;
  margin-right: 10%;
}
  .info-line-value2 {
    font-size: 12px;
    color: #3d3d3d;
    color: #1d2129;
    font-weight: 500;
    margin-right: 10%;
  }
.top-container {
  height: 130px;
  width: 100%;
  display: flex;
}
  .top-container {
    height: 130px;
    width: 100%;
    display: flex;
  }
.typeNum {
  height: 100%;
  width: 33.33%;
  display: flex;
  align-items: center;
  justify-content: center;
}
  .top-container.two-cols .typeNum {
    width: 50%;
  }
.typeNum-left {
  font-size: 12px;
  color: #909399;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
  .typeNum {
    height: 100%;
    width: 33.33%;
    display: flex;
    align-items: center;
    justify-content: center;
  }
.typeNum-left-text {
  font-size: 12px;
  color: #3491fa;
  font-weight: 500;
  margin-top: 5px;
}
  .typeNum-left {
    font-size: 12px;
    color: #909399;
    display: flex;
    flex-direction: column;
    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;
  }
.table-card {
  margin-bottom: 20px;
}
  .typeNum-leftLine {
    color: #3491fa;
    font-size: 12px;
  }
.typeNum-center {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 10px;
}
  .typeNum-rightLine {
    border-top: 1px solid #3491fa;
    border-left: 1px solid #3491fa;
    border-bottom: 1px solid #3491fa;
    height: 80px;
    width: 8px;
  }
.typeNum-leftLine {
  color: #3491fa;
  font-size: 12px;
}
  .typeNum-leftLine2 {
    color: #5eb334;
    font-size: 12px;
  }
.typeNum-rightLine {
  border-top: 1px solid #3491fa;
  border-left: 1px solid #3491fa;
  border-bottom: 1px solid #3491fa;
  height: 80px;
  width: 8px;
}
  .typeNum-rightLine2 {
    border-top: 1px solid #3491fa;
    border-left: 1px solid #5eb334;
    border-bottom: 1px solid #5eb334;
    height: 80px;
    width: 8px;
  }
.typeNum-leftLine2 {
  color: #5eb334;
  font-size: 12px;
}
  .typeNum-leftLine3 {
    color: #8000ff;
    font-size: 12px;
  }
.typeNum-rightLine2 {
  border-top: 1px solid #3491fa;
  border-left: 1px solid #5eb334;
  border-bottom: 1px solid #5eb334;
  height: 80px;
  width: 8px;
}
  .typeNum-rightLine3 {
    border-top: 1px solid #8000ff;
    border-left: 1px solid #8000ff;
    border-bottom: 1px solid #8000ff;
    height: 80px;
    width: 8px;
  }
.typeNum-leftLine3 {
  color: #8000ff;
  font-size: 12px;
}
  .typeNum-right {
    margin-left: 10px;
    display: flex;
    flex-direction: column;
    height: 90%;
    justify-content: space-between;
  }
.typeNum-rightLine3 {
  border-top: 1px solid #8000ff;
  border-left: 1px solid #8000ff;
  border-bottom: 1px solid #8000ff;
  height: 80px;
  width: 8px;
}
  .typeNum-right-top-name {
    font-weight: 400;
    font-size: 12px;
    color: #3d3d3d;
  }
.typeNum-right {
  margin-left: 10px;
  display: flex;
  flex-direction: column;
  height: 90%;
  justify-content: space-between;
}
  .typeNum-right-top-text {
    font-weight: 400;
    font-size: 16px;
    color: rgba(0, 0, 0, 0.85);
    margin-top: 5px;
  }
.typeNum-right-top-name {
  font-weight: 400;
  font-size: 12px;
  color: #3d3d3d;
}
  .unit {
    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;
}
  .inspection-chart-box {
    height: 50px;
    width: 30%;
    background-color: #f7f8fa;
    border-radius: 8px;
    padding-left: 15px;
  }
.unit {
  font-size: 12px;
  color: #3d3d3d;
}
  .chart-box-title {
    font-size: 12px;
    color: #4e5969;
    margin-top: 5px;
  }
.inspection-chart-box {
  height: 50px;
  width: 30%;
  background-color: #f7f8fa;
  border-radius: 8px;
  padding-left: 15px;
}
  .unit {
    font-size: 12px;
    color: #3d3d3d;
  }
.chart-box-title {
  font-size: 12px;
  color: #4e5969;
  margin-top: 5px;
}
  .chart-box-num {
    font-size: 18px;
    color: #000;
    margin-top: 5px;
    font-weight: 500;
  }
.unit {
  font-size: 12px;
  color: #3d3d3d;
}
  /* è´¨æ£€åˆæ ¼çŽ‡å¡ç‰‡æ ·å¼ */
  .top-container合格率 {
    height: 130px;
    width: 100%;
    display: flex;
    gap: 15px;
    align-items: center;
    justify-content: space-between;
  }
.chart-box-num {
  font-size: 18px;
  color: #000;
  margin-top: 5px;
  font-weight: 500;
}
  .flex-center {
    justify-content: space-evenly;
  }
/* è´¨æ£€åˆæ ¼çŽ‡å¡ç‰‡æ ·å¼ */
.top-container合格率 {
  height: 130px;
  width: 100%;
  display: flex;
  gap: 15px;
  align-items: center;
  justify-content: space-between;
}
  .quality-card {
    /* flex: 1; */
    width: 32%;
    /* height: 100px; */
    border-radius: 8px;
    padding: 12px;
    display: flex;
    flex-direction: column;
  }
.flex-center {
  justify-content: space-evenly;
}
  .top-container.quality-two-cols .quality-card {
    width: 48%;
  }
.quality-card {
  /* flex: 1; */
  width: 32%;
  /* height: 100px; */
  border-radius: 8px;
  padding: 12px;
  display: flex;
  flex-direction: column;
}
  .container-line-right-bottom.two-boxes .inspection-chart-box {
    width: 45%;
  }
.blue-card {
  background-color: #e6f7ff;
}
  .blue-card {
    background-color: #e6f7ff;
  }
.green-card {
  background-color: #f6ffed;
  color: #000000;
}
  .green-card {
    background-color: #f6ffed;
    color: #000000;
  }
.purple-card {
  background-color: #f9f0ff;
}
  .purple-card {
    background-color: #f9f0ff;
  }
.quality-card-title {
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
}
  .quality-card-title {
    font-size: 14px;
    font-weight: 500;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
  }
.quality-item-tip {
  font-size: 12px;
  color: #666666;
  margin-bottom: 3px;
}
  .quality-item-tip {
    font-size: 12px;
    color: #666666;
    margin-bottom: 3px;
  }
.blue-label {
  color: #1890ff;
}
  .blue-label {
    color: #1890ff;
  }
.green-label {
  color: #52c41a;
}
  .green-label {
    color: #52c41a;
  }
.quality-card-title {
  color: #000;
  font-weight: bold;
}
  .quality-card-title {
    color: #000;
    font-weight: bold;
  }
.quality-card-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex: 1;
}
  .quality-card-content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex: 1;
  }
.quality-item {
  display: flex;
  /* flex-direction: column; */
  align-items: center;
  justify-content: center;
  margin-top: 5px;
  flex: 1;
}
  .quality-item {
    display: flex;
    /* flex-direction: column; */
    align-items: center;
    justify-content: center;
    margin-top: 5px;
    flex: 1;
  }
.quality-item-label {
  font-size: 12px;
  /* color: #666; */
  margin-bottom: 4px;
}
  .quality-item-label {
    font-size: 12px;
    /* color: #666; */
    margin-bottom: 4px;
  }
.quality-item-value {
  font-size: 20px;
  font-weight: 500;
  margin-bottom: 4px;
}
  .quality-item-value {
    font-size: 20px;
    font-weight: 500;
    margin-bottom: 4px;
  }
.quality-item-chart {
  width: 60px;
  height: 60px;
  margin-left: 10px;
}
  .quality-item-chart {
    width: 60px;
    height: 60px;
    margin-left: 10px;
  }
/* .flex-center {
justify-content: space-evenly;
} */
  /* .flex-center {
    justify-content: space-evenly;
    } */
.blue-chart {
  /* background-color: rgba(24, 144, 255, 0.1); */
}
  .blue-chart {
    /* background-color: rgba(24, 144, 255, 0.1); */
  }
.green-chart {
  /* background-color: rgba(82, 196, 26, 0.1); */
}
  .green-chart {
    /* background-color: rgba(82, 196, 26, 0.1); */
  }
.purple-chart {
  /* background-color: rgba(114, 46, 209, 0.1); */
}
  .purple-chart {
    /* background-color: rgba(114, 46, 209, 0.1); */
  }
.chart-ring {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  border: 15px solid transparent;
  position: relative;
}
  .chart-ring {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    border: 15px solid transparent;
    position: relative;
  }
.blue-chart .chart-ring {
  border-top-color: #1890ff;
  border-right-color: #1890ff;
  border-bottom-color: #1890ff;
  transform: rotate(45deg);
}
  .blue-chart .chart-ring {
    border-top-color: #1890ff;
    border-right-color: #1890ff;
    border-bottom-color: #1890ff;
    transform: rotate(45deg);
  }
.green-chart .chart-ring {
  border-top-color: #52c41a;
  border-right-color: #52c41a;
  border-bottom-color: #52c41a;
  transform: rotate(45deg);
}
  .green-chart .chart-ring {
    border-top-color: #52c41a;
    border-right-color: #52c41a;
    border-bottom-color: #52c41a;
    transform: rotate(45deg);
  }
.purple-chart .chart-ring {
  border-top-color: #722ed1;
  border-right-color: #722ed1;
  border-bottom-color: #722ed1;
  transform: rotate(45deg);
}
  .purple-chart .chart-ring {
    border-top-color: #722ed1;
    border-right-color: #722ed1;
    border-bottom-color: #722ed1;
    transform: rotate(45deg);
  }
.pagination-container {
  margin-top: 20px;
  text-align: right;
}
  .pagination-container {
    margin-top: 20px;
    text-align: right;
  }
.yearchange {
  position: absolute;
  right: 40px;
  top: 20px;
  display: flex;
  align-items: center;
  /* width: 60px; */
}
  .yearchange {
    position: absolute;
    right: 40px;
    top: 20px;
    display: flex;
    align-items: center;
    /* width: 60px; */
  }
:deep(.el-card__header) {
  padding: 15px 20px;
  border-bottom: 1px solid #ffffff;
  background-color: #ffffff;
}
  :deep(.el-card__header) {
    padding: 15px 20px;
    border-bottom: 1px solid #ffffff;
    background-color: #ffffff;
  }
:deep(.el-card__body) {
  padding: 20px;
}
  :deep(.el-card__body) {
    padding: 20px;
  }
:deep(.el-table) {
  margin-bottom: 20px;
}
  :deep(.el-table) {
    margin-bottom: 20px;
  }
:deep(.el-progress) {
  margin: 0;
}
  :deep(.el-progress) {
    margin: 0;
  }
:deep(.el-tag) {
  margin: 0;
}
  :deep(.el-tag) {
    margin: 0;
  }
:deep(.el-input__prefix) {
  display: none !important;
}
  :deep(.el-input__prefix) {
    display: none !important;
  }
</style>