From 47519ea9fd53705418a6c83ea40ae1cfecb26ae3 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期二, 13 一月 2026 17:54:15 +0800
Subject: [PATCH] 合格率统计重构:物料属性分类查询各自的合格率饼图及对应的柱状图以和详情表格

---
 src/views/statisticalCharts/qualificationRateStatistics/index.vue |  505 +++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 373 insertions(+), 132 deletions(-)

diff --git a/src/views/statisticalCharts/qualificationRateStatistics/index.vue b/src/views/statisticalCharts/qualificationRateStatistics/index.vue
index 17fd9a9..2e4996f 100644
--- a/src/views/statisticalCharts/qualificationRateStatistics/index.vue
+++ b/src/views/statisticalCharts/qualificationRateStatistics/index.vue
@@ -2,7 +2,7 @@
   <div class="app-container">
     <el-row>
       <el-col :span="4">
-        <el-radio-group v-model="dateType" @change="changeDate">
+        <el-radio-group v-model="dateType" @change="changeDateType">
           <el-radio-button label="1">鏈懆</el-radio-button>
           <el-radio-button label="2">鏈湀</el-radio-button>
           <el-radio-button label="3">浠婂勾</el-radio-button>
@@ -11,18 +11,9 @@
       <el-col :span="20">
         <el-form ref="entity" size="small" :inline="true">
           <el-form-item style="width: 20%;">
-            <el-date-picker
-              v-model="datePicker"
-              end-placeholder="缁撴潫鏃ユ湡"
-              format="yyyy-MM-dd"
-              placeholder="閫夋嫨鏃ユ湡"
-              range-separator="鑷�"
-              size="small"
-              start-placeholder="寮�濮嬫棩鏈�"
-              type="daterange"
-              style="width: 100%;"
-              value-format="yyyy-MM-dd"
-              @change="changeDatePicker">
+            <el-date-picker v-model="datePicker" end-placeholder="缁撴潫鏃ユ湡" format="yyyy-MM-dd" placeholder="閫夋嫨鏃ユ湡"
+              range-separator="鑷�" size="small" start-placeholder="寮�濮嬫棩鏈�" type="daterange" style="width: 100%;"
+              value-format="yyyy-MM-dd" @change="changeDatePicker">
             </el-date-picker>
           </el-form-item>
           <el-form-item label="鏍峰搧鍚嶇О" prop="sampleName">
@@ -32,65 +23,65 @@
             <el-input v-model="modelName" clearable placeholder="璇疯緭鍏ュ瀷鍙�" size="small" @change="changeDate"></el-input>
           </el-form-item>
           <el-form-item label="渚涘簲鍟嗗悕绉�" prop="supplierName">
-            <el-input v-model="supplierName" clearable placeholder="璇疯緭鍏ヤ緵搴斿晢鍚嶇О" size="small" @change="changeDate"></el-input>
+            <el-input v-model="supplierName" clearable placeholder="璇疯緭鍏ヤ緵搴斿晢鍚嶇О" size="small"
+              @change="changeDate"></el-input>
           </el-form-item>
         </el-form>
       </el-col>
     </el-row>
     <el-row :gutter="20">
-      <el-col :span="8">
-        <div class="pie-card">
-          <div class="title">鍘熸潗鏂欏悎鏍肩巼</div>
-          <span class="data">{{passRate}}</span>
-          <Echarts ref="chart"
-                   :legend="pieLegend"
-                   :series="materialPieSeries"
-                   :tooltip="pieTooltip"
-                   style="height: 36vh;"></Echarts>
+      <el-col :span="6">
+        <div class="pie-card" :class="{ active: currentMaterialProp === '00Raw' }" @click="updateTitle('鍘熸潗鏂�')">
+          <div class="title"><span style="color: #005BAC;font-weight: bold;">鍘熸潗鏂�</span>鍚堟牸鐜�</div>
+          <Echarts ref="chart" :legend="pieLegend" :series="rawPieSeries" :tooltip="pieTooltip" style="height: 36vh;">
+          </Echarts>
         </div>
       </el-col>
-      <el-col :span="8">
-        <div class="pie-card">
-          <div class="title"><span style="color: #F56C6C">鏈湀</span>妫�楠岀被鍨嬫暟閲�</div>
-          <Echarts ref="chart"
-                   :chartStyle="chartStyle2"
-                   :legend="pieLegend"
-                   :series="materialPieSeries1"
-                   :tooltip="pieTooltip"
-                   style="height: 36vh;"></Echarts>
+      <el-col :span="6">
+        <div class="pie-card" :class="{ active: currentMaterialProp === '01Cu' }" @click="updateTitle('閾�')">
+          <div class="title"><span style="color: #005BAC;font-weight: bold;">閾�</span>鍚堟牸鐜�</div>
+          <Echarts ref="chart" :legend="pieLegend" :series="cuPieSeries" :tooltip="pieTooltip" style="height: 36vh;">
+          </Echarts>
         </div>
       </el-col>
-      <el-col :span="8">
-        <div class="pie-card">
-          <div class="title">鍘熸潗鏂�<span style="color: #F56C6C">鏈湀</span>涓�<span style="color: #F56C6C">涓婃湀</span>鍚堟牸鐜囧姣�</div>
-          <Echarts ref="chart"
-                   :barColors="barColors2"
-                   :chartStyle="chartStyle"
-                   :grid="grid"
-                   :legend="barLegend"
-                   :series="barSeries"
-                   :tooltip="tooltip"
-                   :xAxis="xAxis1"
-                   :yAxis="yAxis1"
-                   style="height: 36vh;"></Echarts>
+      <el-col :span="6">
+        <div class="pie-card" :class="{ active: currentMaterialProp === '02Al' }" @click="updateTitle('閾�')">
+          <div class="title"><span style="color: #005BAC;font-weight: bold;">閾�</span>鍚堟牸鐜�</div>
+          <Echarts ref="chart" :legend="pieLegend" :series="alPieSeries" :tooltip="pieTooltip" style="height: 36vh;">
+          </Echarts>
+        </div>
+      </el-col>
+      <el-col :span="6">
+        <div class="pie-card" :class="{ active: currentMaterialProp === '04Dlan' }" @click="updateTitle('鐢电紗')">
+          <div class="title"><span style="color: #005BAC;font-weight: bold;">鐢电紗</span>鍚堟牸鐜�</div>
+          <Echarts ref="chart" :legend="pieLegend" :series="dlanPieSeries" :tooltip="pieTooltip" style="height: 36vh;">
+          </Echarts>
         </div>
       </el-col>
     </el-row>
-    <el-row>
-      <el-col :span="24">
+    <el-row :gutter="20">
+      <el-col :span="12">
         <div class="inspection-card">
-          <div class="title">鍚堟牸鐜�</div>
-          <Echarts ref="chart"
-                   :barColors="barColors"
-                   :grid="grid"
-                   :legend="legend"
-                   :lineColors="lineColors"
-                   :options="echartsOptions"
-                   :series="echartsSeries"
-                   :tooltip="tooltip"
-                   :xAxis="xAxis"
-                   :yAxis="yAxis"
-                   style="height: 40vh;"></Echarts>
+          <div class="title" style="display:flex;align-items:center;justify-content:space-between;">
+            <div>
+              <span style="color: #005BAC;font-weight: bold;">{{ inspectionTitle }}</span>鍚堟牸鐜囪秼鍔�
+            </div>
+            <el-button type="text" icon="el-icon-download" @click="downloadBarChart">
+              涓嬭浇
+            </el-button>
+          </div>
+          <Echarts ref="barChart" :barColors="barColors" :grid="grid" :legend="legend" :lineColors="lineColors"
+            :options="echartsOptions" :series="echartsSeries" :tooltip="tooltip" :xAxis="xAxis" :yAxis="yAxis"
+            style="height: 40vh;">
+          </Echarts>
+
+        </div>
+      </el-col>
+      <el-col :span="12">
+        <div class="inspection-card">
+          <div class="title"><span style="color: #005BAC;font-weight: bold;">{{ inspectionTitle }}</span>鏄庣粏鏁版嵁</div>
+          <lims-table :tableData="tableData" :column="tableColumn" :tableLoading="tableLoading"
+            :height="'calc(40vh - 40px)'"></lims-table>
         </div>
       </el-col>
     </el-row>
@@ -99,17 +90,19 @@
 
 <script>
 import Echarts from "@/components/echarts/echarts.vue";
+import limsTable from "@/components/Table/lims-table.vue";
 import {
   getOrderTypeCookie,
   getRawPassRateByBarChart,
   getRawPassRateByCake,
-  getRawUpMonth
+  getRawUpMonth,
+  getMaterialPropTable
 } from "@/api/statisticalCharts/dataAnalysis";
 
 export default {
   name: "QualificationRateStatistics",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: {Echarts},
+  components: { Echarts, limsTable },
   data() {
     // 杩欓噷瀛樻斁鏁版嵁
     return {
@@ -120,10 +113,17 @@
       sampleName: '',
       modelName: '',
       supplierName: '',
+      inspectionTitle: '鍘熸潗鏂�',
+      currentMaterialProp: '00Raw',
       echartsOptions: {
         title: {
-          text: '绀轰緥鍥捐〃',
-          left: 'center'
+          text: '',
+          left: 'center',
+          top: 10,
+          textStyle: {
+            fontSize: 14,
+            fontWeight: 'bold'
+          }
         }
       },
       xAxis: [
@@ -153,43 +153,46 @@
       ],
       echartsSeries: [
         {
-          name: '鎬绘暟',
+          name: '鍚堟牸',
           type: 'bar',
           data: [],
           label: {
             show: true,
-            position: 'top'
-          },
+            position: 'inside'
+          }
+        },
+        {
+          name: '涓嶅悎鏍�',
+          type: 'bar',
+          data: [],
+          label: {
+            show: true,
+            position: 'inside'
+          }
         },
         {
           name: '鍚堟牸鐜�',
           type: 'line',
           smooth: true,
-          tooltip: {
-            valueFormatter: function (value) {
-              return value + ' %';
-            }
-          },
+          yAxisIndex: 1,
+          data: [],
           label: {
             show: true,
-            position: 'top',
-            formatter: function (value) {
-              return value.value + ' %';
-            },
-            distance: 14
-          },
-          yAxisIndex: 1,
-          data: []
-        },
+            formatter: (v) => v.value + '%'
+          }
+        }
       ],
       grid: {
         left: '3%',
         right: '4%',
-        bottom: '3%',
+        bottom: '15%',
         containLabel: true
       },
       legend: {
-        data: ['鎬绘暟','鍚堟牸鐜�']
+        data: ['鍚堟牸', '涓嶅悎鏍�', '鍚堟牸鐜�'],
+        orient: 'horizontal',
+        bottom: 0,
+        itemGap: 20
       },
       tooltip: {
         trigger: 'axis',
@@ -198,22 +201,54 @@
         }
       },
       lineColors: ['#91A0FC'],
-      barColors: ['#86C1F4'],
+      barColors: ['#13ce66', '#F56C6C'], // 鍚堟牸缁� / 涓嶅悎鏍肩孩
       barColors2: ['#A4EEDA'],
       pieTooltip: {
         trigger: 'item'
       },
       pieLegend: {
-        orient: 'vertical',
-        right: 20,
-        top: 'middle',
+        orient: 'horizontal',
+        bottom: 0,
       },
-      materialPieSeries: [
+      rawPieSeries: [
         {
           name: 'Access From',
           type: 'pie',
-          radius: ['40%', '70%'],
-          right: '22%',
+          radius: '70%',
+          center: ['50%', '50%'],
+          avoidLabelOverlap: false,
+          itemStyle: {
+            borderColor: '#fff',
+            borderWidth: 2
+          },
+          label: {
+            alignTo: 'edge',
+            formatter: '{name|{b}}\n{time|{c}}',
+            edgeDistance: 10,
+            lineHeight: 15,
+            rich: {
+              time: {
+                fontSize: 10,
+                color: '#999'
+              }
+            }
+          },
+          labelLine: {
+            length: 20,
+            length2: 40
+          },
+          data: [
+            { value: 0, name: '涓嶅悎鏍兼暟閲�', itemStyle: { color: '#F56C6C' } },
+            { value: 0, name: '鍚堟牸鏁伴噺', itemStyle: { color: '#67C23A' } }
+          ]
+        }
+      ],
+      cuPieSeries: [
+        {
+          name: 'Access From',
+          type: 'pie',
+          radius: '70%',
+          center: ['50%', '50%'],
           avoidLabelOverlap: false,
           itemStyle: {
             borderColor: '#fff',
@@ -236,8 +271,74 @@
             length2: 40,
           },
           data: [
-            { value: 0, name: '涓嶅悎鏍兼暟閲�' },
-            { value: 0, name: '鍚堟牸鏁伴噺' },
+            { value: 0, name: '涓嶅悎鏍兼暟閲�', itemStyle: { color: '#F56C6C' } },
+            { value: 0, name: '鍚堟牸鏁伴噺', itemStyle: { color: '#67C23A' } },
+          ]
+        }
+      ],
+      alPieSeries: [
+        {
+          name: 'Access From',
+          type: 'pie',
+          radius: '70%',
+          center: ['50%', '50%'],
+          avoidLabelOverlap: false,
+          itemStyle: {
+            borderColor: '#fff',
+            borderWidth: 2
+          },
+          label: {
+            alignTo: 'edge',
+            formatter: '{name|{b}}\n{time|{c}}',
+            edgeDistance: 10,
+            lineHeight: 15,
+            rich: {
+              time: {
+                fontSize: 10,
+                color: '#999'
+              }
+            },
+          },
+          labelLine: {
+            length: 20,
+            length2: 40,
+          },
+          data: [
+            { value: 0, name: '涓嶅悎鏍兼暟閲�', itemStyle: { color: '#F56C6C' } },
+            { value: 0, name: '鍚堟牸鏁伴噺', itemStyle: { color: '#67C23A' } },
+          ]
+        }
+      ],
+      dlanPieSeries: [
+        {
+          name: 'Access From',
+          type: 'pie',
+          radius: '70%',
+          center: ['50%', '50%'],
+          avoidLabelOverlap: false,
+          itemStyle: {
+            borderColor: '#fff',
+            borderWidth: 2
+          },
+          label: {
+            alignTo: 'edge',
+            formatter: '{name|{b}}\n{time|{c}}',
+            edgeDistance: 10,
+            lineHeight: 15,
+            rich: {
+              time: {
+                fontSize: 10,
+                color: '#999'
+              }
+            },
+          },
+          labelLine: {
+            length: 20,
+            length2: 40,
+          },
+          data: [
+            { value: 0, name: '涓嶅悎鏍兼暟閲�', itemStyle: { color: '#F56C6C' } },
+            { value: 0, name: '鍚堟牸鏁伴噺', itemStyle: { color: '#67C23A' } },
           ]
         }
       ],
@@ -317,19 +418,58 @@
         },
       ],
       tableData: [],
-      passRate: '',
+      tableLoading: false,
+      tableColumn: [
+        { label: '鎵瑰彿', prop: 'updateBatchNo', minWidth: '120px' },
+        { label: '鎶佃揪鎴愬搧鏁伴噺', prop: 'qtyArrived', minWidth: '100px' },
+        { label: '闆朵欢鎻忚堪', prop: 'partDesc', minWidth: '200px' },
+        {
+          dataType: 'tag',
+          label: '妫�楠岀姸鎬�',
+          prop: 'inspectStatus',
+          minWidth: '100px',
+          formatData: (params) => {
+            if (params == 0) return '妫�楠屼腑'
+            if (params == 1) return '鍚堟牸'
+            if (params == 2) return '涓嶅悎鏍�'
+            if (params == 3) return '鏈笅鍗�'
+            if (params == 4) return '璁╂鏀捐'
+            return null
+          },
+          formatType: (params) => {
+            if (params == 1 || params == 4) return 'success'
+            if (params == 0 || params == 2) return 'danger'
+            if (params == 3) return 'warning'
+            return null
+          }
+        },
+        { label: '涓嬪彂鏃堕棿', prop: 'sendTime', minWidth: '150px' }
+      ],
+      rawPassRate: '',
+      cuPassRate: '',
+      alPassRate: '',
+      dlanPassRate: '',
       sum: '',
     }
   },
+
   mounted() {
-    this.getBar()
-    this.getRawPass()
-    this.getOrderType()
-    this.getPassRateCom()
+    this.setBarChartTitle();
+    this.getBar();
+    this.getRawPass();
+    this.getOrderType();
+    this.getPassRateCom();
+    this.getTableData();
   },
+
   // 鏂规硶闆嗗悎
   methods: {
     // 鑾峰彇鍚堟牸鐜囧浘琛ㄦ暟鎹�
+
+    setBarChartTitle() {
+      this.echartsOptions.title.text = `${this.inspectionTitle}鍚堟牸鐜囪秼鍔縛;
+    },
+
     getBar() {
       const params = {
         dateType: this.dateType,
@@ -338,38 +478,60 @@
         sampleName: this.sampleName,
         modelName: this.modelName,
         supplierName: this.supplierName,
-      }
+        materialProp: this.currentMaterialProp,
+      };
+
       getRawPassRateByBarChart(params).then((res) => {
-        let lineData = []
-        let barData = []
-        let xAxis = []
+        let qualifiedData = [];
+        let unQualifiedData = [];
+        let lineData = [];
+        let xAxis = [];
+
         res.data.forEach(item => {
-          barData.push(item.sum)
-          lineData.push(item.passRate)
-          xAxis.push(item.searchTime)
-        })
-        this.echartsSeries[0].data = barData
-        this.echartsSeries[1].data = lineData
-        this.yAxis[0].max = Math.ceil(Math.max.apply(null, barData) / 50) * 50
-        this.yAxis[0].interval = this.yAxis[0].max / 5
-        this.xAxis[0].data = xAxis
-      })
+          qualifiedData.push(item.qualified || 0);
+          unQualifiedData.push(item.unQualified || 0);
+          lineData.push(item.passRate || 0);
+          xAxis.push(item.searchTime);
+        });
+
+        this.echartsSeries[0].data = qualifiedData;
+        this.echartsSeries[1].data = unQualifiedData;
+        this.echartsSeries[2].data = lineData;
+        this.xAxis[0].data = xAxis;
+      });
     },
-    // 鑾峰彇鍘熸潗鏂欏悎鏍肩巼鍥捐〃鏁版嵁
+
+    // 鑾峰彇鐗╂枡灞炴�у悎鏍肩巼鍥捐〃鏁版嵁
     getRawPass() {
-      const params = {
-        dateType: this.dateType,
-        beginDate: this.beginDate,
-        endDate: this.endDate,
-        sampleName: this.sampleName,
-        modelName: this.modelName,
-        supplierName: this.supplierName,
-      }
-      getRawPassRateByCake(params).then((res) => {
-        this.materialPieSeries[0].data[0].value = res.data.unQualified
-        this.materialPieSeries[0].data[1].value = res.data.qualified
-        this.passRate = res.data.passRate + '%'
-      })
+      const materials = [
+        { type: '00Raw', series: 'rawPieSeries', rate: 'rawPassRate' },
+        { type: '01Cu', series: 'cuPieSeries', rate: 'cuPassRate' },
+        { type: '02Al', series: 'alPieSeries', rate: 'alPassRate' },
+        { type: '04Dlan', series: 'dlanPieSeries', rate: 'dlanPassRate' }
+      ];
+
+      materials.forEach(item => {
+        const params = {
+          dateType: this.dateType,
+          beginDate: this.beginDate,
+          endDate: this.endDate,
+          sampleName: this.sampleName,
+          modelName: this.modelName,
+          supplierName: this.supplierName,
+          materialProp: item.type
+        }
+        getRawPassRateByCake(params).then((res) => {
+          if (res.data) {
+            this[item.series][0].data[0].value = res.data.unQualified || 0
+            this[item.series][0].data[1].value = res.data.qualified || 0
+            this[item.rate] = res.data.passRate != null ? res.data.passRate + '%' : ''
+          } else {
+            this[item.series][0].data[0].value = 0
+            this[item.series][0].data[1].value = 0
+            this[item.rate] = ''
+          }
+        })
+      });
     },
     // 鑾峰彇鏈湀妫�楠岀被鍨嬫暟閲�
     getOrderType() {
@@ -393,13 +555,24 @@
         this.barSeries[0].data = barData
       })
     },
-    changeDate () {
+    changeDate() {
       this.getBar()
       this.getRawPass()
+      this.getTableData()
       // this.getOrderType()
       // this.getPassRateCom()
     },
-    changeDatePicker (val) {
+
+    changeDateType() {
+      this.datePicker = []
+      this.beginDate = ''
+      this.endDate = ''
+      this.getBar()
+      this.getRawPass()
+      this.getTableData()
+    },
+
+    changeDatePicker(val) {
       if (val) {
         this.beginDate = val[0] + ' 00:00:00'
         this.endDate = val[1] + ' 23:59:59'
@@ -409,8 +582,62 @@
       }
       this.getBar()
       this.getRawPass()
-      // this.getOrderType()
-      // this.getPassRateCom()
+      this.getTableData()
+    },
+
+    updateTitle(title) {
+      this.inspectionTitle = title;
+
+      const typeMap = {
+        '鍘熸潗鏂�': '00Raw',
+        '閾�': '01Cu',
+        '閾�': '02Al',
+        '鐢电紗': '04Dlan',
+      };
+
+      this.currentMaterialProp = typeMap[title] || '00Raw';
+
+      this.setBarChartTitle();
+      this.getBar();
+      this.getTableData();
+    },
+
+
+    getTableData() {
+      this.tableLoading = true;
+      const params = {
+        dateType: this.dateType,
+        beginDate: this.beginDate,
+        endDate: this.endDate,
+        sampleName: this.sampleName,
+        modelName: this.modelName,
+        supplierName: this.supplierName,
+        materialProp: this.currentMaterialProp,
+      };
+
+      getMaterialPropTable(params).then((res) => {
+        if (Array.isArray(res.data)) {
+          this.tableData = res.data;
+        } else if (res.data && res.data.records) {
+          this.tableData = res.data.records;
+        } else {
+          this.tableData = [];
+        }
+        this.tableLoading = false;
+      }).catch(() => {
+        this.tableLoading = false;
+      });
+    },
+
+    //  涓嬭浇鏌辩姸鍥惧浘鐗�
+    downloadBarChart() {
+      if (!this.$refs.barChart) {
+        this.$message.warning('鍥捐〃灏氭湭鍔犺浇瀹屾垚');
+        return;
+      }
+
+      const title = `${this.inspectionTitle}_鍚堟牸鐜囪秼鍔縛;
+      this.$refs.barChart.downloadImage(title);
     },
   },
 }
@@ -420,24 +647,38 @@
 .title {
   padding: 10px 0 0 20px;
 }
+
 .table {
   padding: 0 10px 10px;
 }
+
 .pie-card {
   width: 100%;
   background: #FFFFFF;
   margin-top: 10px;
   position: relative;
+  cursor: pointer;
+  border-radius: 8px;
+  transition:
+    transform 0.25s ease,
+    box-shadow 0.25s ease;
 }
+
+.pie-card.active {
+  transform: translateY(-3px) scale(1.03);
+  box-shadow: 0 5px 10px rgba(0, 91, 172, 0.25);
+}
+
 .data {
   position: absolute;
   font-size: 20px;
-  transform: translate(-50%);
-  left: 40%;
-  top: 42%;
+  transform: translate(-50%, -50%);
+  left: 50%;
+  top: 50%;
   z-index: 1;
 }
-.inspection-card{
+
+.inspection-card {
   width: 100%;
   background: #FFFFFF;
   margin-top: 10px;

--
Gitblit v1.9.3