From fb6e16a425e9ade08dbcca96d6a2f1c9b2f25b1e Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期三, 14 一月 2026 17:51:56 +0800
Subject: [PATCH] fix: 合格率统计调整:铜、铝合并为【导体】统计数据。明细表格字段更改和导出按钮
---
src/views/statisticalCharts/qualificationRateStatistics/index.vue | 350 +++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 222 insertions(+), 128 deletions(-)
diff --git a/src/views/statisticalCharts/qualificationRateStatistics/index.vue b/src/views/statisticalCharts/qualificationRateStatistics/index.vue
index 2e4996f..3456973 100644
--- a/src/views/statisticalCharts/qualificationRateStatistics/index.vue
+++ b/src/views/statisticalCharts/qualificationRateStatistics/index.vue
@@ -30,28 +30,22 @@
</el-col>
</el-row>
<el-row :gutter="20">
- <el-col :span="6">
+ <el-col :span="8">
<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="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;">
+ <el-col :span="8">
+ <div class="pie-card" :class="{ active: currentMaterialProp === '01Cu,02Al' }" @click="updateTitle('瀵间綋')">
+ <div class="title"><span style="color: #005BAC;font-weight: bold;">瀵间綋</span>鍚堟牸鐜�</div>
+ <Echarts ref="chart" :legend="pieLegend" :series="conductorPieSeries" :tooltip="pieTooltip"
+ style="height: 36vh;">
</Echarts>
</div>
</el-col>
- <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">
+ <el-col :span="8">
<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;">
@@ -79,9 +73,16 @@
</el-col>
<el-col :span="12">
<div class="inspection-card">
- <div class="title"><span style="color: #005BAC;font-weight: bold;">{{ inspectionTitle }}</span>鏄庣粏鏁版嵁</div>
+ <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="downloadTable">
+ 涓嬭浇
+ </el-button>
+ </div>
<lims-table :tableData="tableData" :column="tableColumn" :tableLoading="tableLoading"
- :height="'calc(40vh - 40px)'"></lims-table>
+ :height="'calc(40vh - 40px)'" :show-summary="true" :summary-method="getSummaries"></lims-table>
</div>
</el-col>
</el-row>
@@ -96,7 +97,8 @@
getRawPassRateByBarChart,
getRawPassRateByCake,
getRawUpMonth,
- getMaterialPropTable
+ getMaterialPropTable,
+ exportSupplierExcel
} from "@/api/statisticalCharts/dataAnalysis";
export default {
@@ -243,40 +245,7 @@
]
}
],
- cuPieSeries: [
- {
- 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' } },
- ]
- }
- ],
- alPieSeries: [
+ conductorPieSeries: [
{
name: 'Access From',
type: 'pie',
@@ -420,34 +389,18 @@
tableData: [],
tableLoading: false,
tableColumn: [
- { label: '鎵瑰彿', prop: 'updateBatchNo', minWidth: '120px' },
- { label: '鎶佃揪鎴愬搧鏁伴噺', prop: 'qtyArrived', minWidth: '100px' },
- { label: '闆朵欢鎻忚堪', prop: 'partDesc', minWidth: '200px' },
+ { label: '渚涘簲鍟嗗悕绉�', prop: 'supplierName', minWidth: '200px' },
+ { label: '鍒拌揣鎵规', prop: 'totalBatch', minWidth: '100px' },
+ { label: '涓嶅悎鏍兼壒娆�', prop: 'unqualifiedBatch', minWidth: '100px' },
{
- dataType: 'tag',
- label: '妫�楠岀姸鎬�',
- prop: 'inspectStatus',
+ label: '鍚堟牸鐜�(%)',
+ prop: 'passRate',
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' }
+ formatData: (val) => (val != null ? val + '%' : '0%')
+ }
],
rawPassRate: '',
- cuPassRate: '',
- alPassRate: '',
+ conductorPassRate: '',
dlanPassRate: '',
sum: '',
}
@@ -471,27 +424,51 @@
},
getBar() {
- const params = {
- dateType: this.dateType,
- beginDate: this.beginDate,
- endDate: this.endDate,
- sampleName: this.sampleName,
- modelName: this.modelName,
- supplierName: this.supplierName,
- materialProp: this.currentMaterialProp,
- };
+ const types = this.currentMaterialProp.split(',');
+ const requests = types.map(t => {
+ const params = {
+ dateType: this.dateType,
+ beginDate: this.beginDate,
+ endDate: this.endDate,
+ sampleName: this.sampleName,
+ modelName: this.modelName,
+ supplierName: this.supplierName,
+ materialProp: t,
+ };
+ return getRawPassRateByBarChart(params);
+ });
- getRawPassRateByBarChart(params).then((res) => {
+ Promise.all(requests).then((responses) => {
+ let dateMap = {}; // { date: { qualified, unQualified } }
+
+ responses.forEach(res => {
+ if (res.data && Array.isArray(res.data)) {
+ res.data.forEach(item => {
+ const date = item.searchTime;
+ if (!dateMap[date]) {
+ dateMap[date] = { qualified: 0, unQualified: 0 };
+ }
+ dateMap[date].qualified += (item.qualified || 0);
+ dateMap[date].unQualified += (item.unQualified || 0);
+ });
+ }
+ });
+
+ const sortedDates = Object.keys(dateMap).sort();
let qualifiedData = [];
let unQualifiedData = [];
let lineData = [];
let xAxis = [];
- res.data.forEach(item => {
- qualifiedData.push(item.qualified || 0);
- unQualifiedData.push(item.unQualified || 0);
- lineData.push(item.passRate || 0);
- xAxis.push(item.searchTime);
+ sortedDates.forEach(date => {
+ const { qualified, unQualified } = dateMap[date];
+ const total = qualified + unQualified;
+ const passRate = total > 0 ? (qualified / total * 100).toFixed(2) : 0;
+
+ xAxis.push(date);
+ qualifiedData.push(qualified);
+ unQualifiedData.push(unQualified);
+ lineData.push(parseFloat(passRate));
});
this.echartsSeries[0].data = qualifiedData;
@@ -505,32 +482,46 @@
getRawPass() {
const materials = [
{ type: '00Raw', series: 'rawPieSeries', rate: 'rawPassRate' },
- { type: '01Cu', series: 'cuPieSeries', rate: 'cuPassRate' },
- { type: '02Al', series: 'alPieSeries', rate: 'alPassRate' },
+ { type: '01Cu,02Al', series: 'conductorPieSeries', rate: 'conductorPassRate' },
{ 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 + '%' : ''
+ const types = item.type.split(',');
+ const requests = types.map(t => {
+ const params = {
+ dateType: this.dateType,
+ beginDate: this.beginDate,
+ endDate: this.endDate,
+ sampleName: this.sampleName,
+ modelName: this.modelName,
+ supplierName: this.supplierName,
+ materialProp: t
+ };
+ return getRawPassRateByCake(params);
+ });
+
+ Promise.all(requests).then((responses) => {
+ let unQualified = 0;
+ let qualified = 0;
+ responses.forEach(res => {
+ if (res.data) {
+ unQualified += (res.data.unQualified || 0);
+ qualified += (res.data.qualified || 0);
+ }
+ });
+
+ if (qualified + unQualified > 0) {
+ this[item.series][0].data[0].value = unQualified;
+ this[item.series][0].data[1].value = qualified;
+ const passRate = (qualified / (qualified + unQualified) * 100).toFixed(2);
+ this[item.rate] = passRate + '%';
} else {
- this[item.series][0].data[0].value = 0
- this[item.series][0].data[1].value = 0
- this[item.rate] = ''
+ this[item.series][0].data[0].value = 0;
+ this[item.series][0].data[1].value = 0;
+ this[item.rate] = '';
}
- })
+ });
});
},
// 鑾峰彇鏈湀妫�楠岀被鍨嬫暟閲�
@@ -590,8 +581,7 @@
const typeMap = {
'鍘熸潗鏂�': '00Raw',
- '閾�': '01Cu',
- '閾�': '02Al',
+ '瀵间綋': '01Cu,02Al',
'鐢电紗': '04Dlan',
};
@@ -605,24 +595,49 @@
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,
- };
+ const types = this.currentMaterialProp.split(',');
+ const requests = types.map(t => {
+ const params = {
+ dateType: this.dateType,
+ beginDate: this.beginDate,
+ endDate: this.endDate,
+ sampleName: this.sampleName,
+ modelName: this.modelName,
+ supplierName: this.supplierName,
+ materialProp: t,
+ };
+ return getMaterialPropTable(params);
+ });
- 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 = [];
- }
+ Promise.all(requests).then((responses) => {
+ let supplierMap = {}; // { supplierName: { totalBatch, unqualifiedBatch } }
+
+ responses.forEach(res => {
+ const data = Array.isArray(res.data) ? res.data : (res.data && res.data.records ? res.data.records : []);
+ data.forEach(item => {
+ const name = item.supplierName || '鏈煡渚涘簲鍟�';
+ if (!supplierMap[name]) {
+ supplierMap[name] = { totalBatch: 0, unqualifiedBatch: 0 };
+ }
+ supplierMap[name].totalBatch += (item.totalBatch || 0);
+ supplierMap[name].unqualifiedBatch += (item.unqualifiedBatch || 0);
+ });
+ });
+
+ const tableData = Object.keys(supplierMap).map(name => {
+ const { totalBatch, unqualifiedBatch } = supplierMap[name];
+ const passRate = totalBatch > 0 ? ((totalBatch - unqualifiedBatch) / totalBatch * 100).toFixed(2) : 0;
+ return {
+ supplierName: name,
+ totalBatch,
+ unqualifiedBatch,
+ passRate
+ };
+ });
+
+ // Sort by totalBatch descending
+ tableData.sort((a, b) => b.totalBatch - a.totalBatch);
+ this.tableData = tableData;
this.tableLoading = false;
}).catch(() => {
this.tableLoading = false;
@@ -639,6 +654,85 @@
const title = `${this.inspectionTitle}_鍚堟牸鐜囪秼鍔縛;
this.$refs.barChart.downloadImage(title);
},
+
+ // 涓嬭浇琛ㄦ牸鏁版嵁
+ downloadTable() {
+ if (!this.tableData || this.tableData.length === 0) {
+ this.$message.warning("娌℃湁鍙鍑虹殑鏁版嵁");
+ return;
+ }
+
+ exportSupplierExcel(this.tableData)
+ .then(res => {
+ if (res.type && res.type.includes("application/json")) {
+ const fileReader = new FileReader();
+ fileReader.onload = () => {
+ const msg = JSON.parse(fileReader.result);
+ this.$message.error(msg.msg || "瀵煎嚭澶辫触");
+ };
+ fileReader.readAsText(res);
+ return;
+ }
+
+ const blob = new Blob([res], {
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+ });
+
+ const fileName = `${this.inspectionTitle}鍚堟牸鐜囩粺璁�.xlsx`;
+
+ if (window.navigator && window.navigator.msSaveOrOpenBlob) {
+ window.navigator.msSaveOrOpenBlob(blob, fileName);
+ } else {
+ const link = document.createElement("a");
+ link.href = window.URL.createObjectURL(blob);
+ link.download = fileName;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ window.URL.revokeObjectURL(link.href);
+ }
+ })
+ .catch(() => {
+ this.$message.error("瀵煎嚭澶辫触");
+ });
+ },
+
+ getSummaries(param) {
+ const { columns, data } = param;
+ const sums = [];
+ columns.forEach((column, index) => {
+ if (index === 0) {
+ sums[index] = '鍚堣';
+ return;
+ }
+
+ const property = column.property;
+ if (property === 'supplierName') {
+ sums[index] = '';
+ return;
+ }
+
+ if (property === 'totalBatch' || property === 'unqualifiedBatch') {
+ const values = data.map(item => Number(item[property]));
+ sums[index] = values.reduce((prev, curr) => {
+ const value = Number(curr);
+ if (!isNaN(value)) {
+ return prev + curr;
+ } else {
+ return prev;
+ }
+ }, 0);
+ } else if (property === 'passRate') {
+ const totalBatch = data.reduce((prev, curr) => prev + (Number(curr.totalBatch) || 0), 0);
+ const unqualifiedBatch = data.reduce((prev, curr) => prev + (Number(curr.unqualifiedBatch) || 0), 0);
+ sums[index] = totalBatch > 0 ? ((totalBatch - unqualifiedBatch) / totalBatch * 100).toFixed(2) + '%' : '0%';
+ } else {
+ sums[index] = '';
+ }
+ });
+
+ return sums;
+ },
},
}
</script>
--
Gitblit v1.9.3