Files
l2-g30/src/views/l2/pdo/components/QualityCertificate.vue

643 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="quality-certificate-container">
<div id="qualityCertificateContent" class="certificate-content">
<!-- Header / 头部 -->
<div class="certificate-header">
<div class="header-top">
<div class="company-logo">
<!-- Company logo placeholder / 公司Logo占位 -->
</div>
<div class="header-title">
<h1>Product Quality Certificate</h1>
<!-- 产品质量证明书 -->
<div class="document-number">Document No.: {{ certificateData.documentNo || '-' }}</div>
<!-- 文档编号 -->
</div>
<div class="qr-code-placeholder">
<!-- QR code placeholder / 二维码占位 -->
</div>
</div>
<div class="header-info">
<div class="info-row">
<div class="info-item">
<span class="info-label">Licence No.:</span>
<!-- 许可证号 -->
<span class="info-value">{{ certificateData.licenceNo || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">Purchaser:</span>
<!-- 订货单位 -->
<span class="info-value">{{ certificateData.purchaser || '-' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">Customer:</span>
<!-- 收货单位 -->
<span class="info-value">{{ certificateData.customer || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">Contract No.:</span>
<!-- 合同编号 -->
<span class="info-value">{{ certificateData.contractNo || '-' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">Trade Mark:</span>
<!-- 品种名称 -->
<span class="info-value">{{ certificateData.tradeMark || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">Technique Standard:</span>
<!-- 技术条件 -->
<span class="info-value">{{ certificateData.techniqueStandard || '-' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">Odd No.:</span>
<!-- 结齐单号 -->
<span class="info-value">{{ certificateData.oddNo || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">Delivery Condition:</span>
<!-- 交货状态 -->
<span class="info-value">{{ certificateData.deliveryCondition || '-' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">Certificate No.:</span>
<!-- 证明书号 -->
<span class="info-value">{{ certificateData.certificateNo || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">Destination:</span>
<!-- 到站 -->
<span class="info-value">{{ certificateData.destination || '-' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">Wagon No.:</span>
<!-- 车号 -->
<span class="info-value">{{ certificateData.wagonNo || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">Delivery Date:</span>
<!-- 发货日期 -->
<span class="info-value">{{ certificateData.deliveryDate || '-' }}</span>
</div>
</div>
</div>
</div>
<!-- Main data table / 主数据表格 -->
<div class="certificate-table">
<table class="data-table">
<thead>
<tr>
<th rowspan="2" style="width: 3%;">No.</th>
<!-- 序号 -->
<th rowspan="2" style="width: 8%;">Coil No.</th>
<!-- 钢卷号 -->
<th rowspan="2" style="width: 7%;">Heat No.</th>
<!-- 熔炼号 -->
<th colspan="3" style="width: 9%;">Size</th>
<!-- 规格 -->
<th rowspan="2" style="width: 5%;">Weight (t)</th>
<!-- 重量 -->
<th colspan="5" style="width: 12%;">Chemical Composition (%)</th>
<!-- 化学成分 -->
<th colspan="5" style="width: 15%;">Tension Test</th>
<!-- 拉伸试验 -->
<th colspan="2" style="width: 8%;">Zinc-coating & Cold Bend</th>
<!-- 锌层冷弯 -->
<th style="width: 6%;">Zinc Coating Thickness</th>
<!-- 锌层厚度 -->
<th colspan="2" style="width: 8%;">Hardness</th>
<!-- 硬度 -->
<th rowspan="2" style="width: 6%;">Coating Weight (g/)</th>
<!-- 镀层重量 -->
<th rowspan="2" style="width: 6%;">Surface Quality</th>
<!-- 表面组别 -->
<th rowspan="2" style="width: 6%;">Flatness</th>
<!-- 不平度 -->
</tr>
<tr>
<th style="width: 3%;">Thickness (mm)</th>
<!-- -->
<th style="width: 3%;">Width (mm)</th>
<!-- -->
<th style="width: 3%;">Length (m)</th>
<!-- -->
<th style="width: 2.4%;">C</th>
<th style="width: 2.4%;">Si</th>
<th style="width: 2.4%;">Mn</th>
<th style="width: 2.4%;">P</th>
<th style="width: 2.4%;">S</th>
<th style="width: 3%;">Yield (MPa)</th>
<!-- 屈服 -->
<th style="width: 3%;">Tensile (MPa)</th>
<!-- 抗拉 -->
<th style="width: 3%;">Elongation (%)</th>
<!-- 伸长 -->
<th style="width: 3%;">n Value</th>
<!-- n值 -->
<th style="width: 3%;">r Value</th>
<!-- r值 -->
<th style="width: 4%;">Types</th>
<!-- 类型 -->
<th style="width: 4%;">Value</th>
<!-- -->
<th style="width: 6%;">Thickness</th>
<!-- 厚度 -->
<th style="width: 4%;">Types</th>
<!-- 类型 -->
<th style="width: 4%;">Value</th>
<!-- -->
</tr>
</thead>
<tbody>
<tr v-for="(coil, index) in certificateData.coils" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ coil.coilNo || '-' }}</td>
<td>{{ coil.heatNo || '-' }}</td>
<td>{{ formatNumber(coil.thickness) }}</td>
<td>{{ formatNumber(coil.width) }}</td>
<td>{{ formatNumber(coil.length) }}</td>
<td>{{ formatNumber(coil.weight) }}</td>
<td>{{ formatNumber(coil.c) }}</td>
<td>{{ formatNumber(coil.si) }}</td>
<td>{{ formatNumber(coil.mn) }}</td>
<td>{{ formatNumber(coil.p) }}</td>
<td>{{ formatNumber(coil.s) }}</td>
<td>{{ formatNumber(coil.yield) }}</td>
<td>{{ formatNumber(coil.tensile) }}</td>
<td>{{ formatNumber(coil.elongation) }}</td>
<td>{{ formatNumber(coil.nValue) }}</td>
<td>{{ formatNumber(coil.rValue) }}</td>
<td>{{ coil.zincCoatingType || '-' }}</td>
<td>{{ coil.zincCoatingValue || '-' }}</td>
<td>{{ formatNumber(coil.zincCoatingThickness) }}</td>
<td>{{ coil.hardnessType || '-' }}</td>
<td>{{ coil.hardnessValue || '-' }}</td>
<td>{{ formatNumber(coil.coatingWeight) }}</td>
<td>{{ coil.surfaceQuality || '-' }}</td>
<td>{{ coil.flatness || '-' }}</td>
</tr>
</tbody>
</table>
</div>
<!-- Footer information / 底部信息 -->
<div class="certificate-footer">
<div class="footer-row">
<div class="footer-item">
<span class="footer-label">Steel Grade:</span>
<!-- 牌号 -->
<span class="footer-value">{{ certificateData.steelGrade || '-' }}</span>
</div>
<div class="footer-item">
<span class="footer-label">Surface Structure:</span>
<!-- 表面结构 -->
<span class="footer-value">{{ certificateData.surfaceStructure || '-' }}</span>
</div>
<div class="footer-item">
<span class="footer-label">Edge:</span>
<!-- 边缘状态 -->
<span class="footer-value">{{ certificateData.edge || '-' }}</span>
</div>
</div>
<div class="footer-row">
<div class="footer-item">
<span class="footer-label">Coat Type:</span>
<!-- 镀层种类 -->
<span class="footer-value">{{ certificateData.coatType || '-' }}</span>
</div>
<div class="footer-item">
<span class="footer-label">Size Precision:</span>
<!-- 尺寸精度 -->
<span class="footer-value">{{ certificateData.sizePrecision || '-' }}</span>
</div>
<div class="footer-item">
<span class="footer-label">Surface Treatment:</span>
<!-- 表面处理 -->
<span class="footer-value">{{ certificateData.surfaceTreatment || '-' }}</span>
</div>
</div>
<div class="footer-row">
<div class="footer-item">
<span class="footer-label">Total Number:</span>
<!-- 总卷() -->
<span class="footer-value">{{ certificateData.totalNumber || '-' }}</span>
</div>
<div class="footer-item">
<span class="footer-label">Note:</span>
<!-- 注释 -->
<span class="footer-value">{{ certificateData.note || '-' }}</span>
</div>
<div class="footer-item">
<span class="footer-label">Total Weight (t):</span>
<!-- 总重量 -->
<span class="footer-value">{{ certificateData.totalWeight || '-' }}</span>
</div>
</div>
</div>
<!-- Remarks / 备注 -->
<div class="certificate-remarks">
<div class="remarks-title">Remarks:</div>
<!-- 备注 -->
<div class="remarks-content">
<p>1. It is certified herein that the products have been produced and tested according to above standards and the products are all qualified.</p>
<!-- 本产品已按上述标准生产和检验,其结果符合要求,特此证明 -->
<p>2. The original quality certificate is the basis for acceptance, copies are for reference only and not to be used as acceptance vouchers.</p>
<!-- 质量证明书原件是验收依据,复印件仅供参考,不作为验收凭证 -->
</div>
</div>
</div>
<!-- Print button / 打印按钮 -->
<div class="print-btn-container">
<el-button type="primary" @click="handlePrint" icon="el-icon-printer">
Print Certificate
<!-- 打印质保书 -->
</el-button>
</div>
</div>
</template>
<script>
import printJS from 'print-js';
import dayjs from 'dayjs';
export default {
name: 'QualityCertificate',
props: {
// Single coil detail / 单卷详情
detail: {
type: Object,
required: true,
default: () => ({})
}
},
data() {
return {
certificateData: {}
};
},
watch: {
// Only watch single coil detail / 仅监听单卷详情
detail: {
handler(newVal) {
if (newVal) {
this.initCertificateData(newVal);
}
},
immediate: true,
deep: true
}
},
methods: {
// Initialize certificate data for single coil / 初始化单卷质保书数据
initCertificateData(detail) {
const coils = [detail]; // 单卷:永远只有一个卷
this.certificateData = {
documentNo: detail.documentNo || `QG/GFJL(Y) 164-2004`,
licenceNo: detail.licenceNo || '',
purchaser: detail.purchaser || '',
customer: detail.customer || '',
contractNo: detail.contractNo || detail.planNo || '',
tradeMark: detail.tradeMark || detail.prodCode || '',
techniqueStandard: detail.techniqueStandard || '',
oddNo: detail.oddNo || '',
deliveryCondition: detail.deliveryCondition || detail.prodCode || '',
certificateNo: detail.certificateNo || detail.exitMatId || '',
destination: detail.destination || '',
wagonNo: detail.wagonNo || '',
deliveryDate: detail.deliveryDate || dayjs().format('YYYY-MM-DD'),
steelGrade: detail.steelGrade || '',
surfaceStructure: detail.surfaceStructure || 'Smooth',
edge: detail.edge || 'Untrimmed',
coatType: detail.coatType || '',
sizePrecision: detail.sizePrecision || 'Normal',
surfaceTreatment: detail.surfaceTreatment || '',
totalNumber: 1, // 单卷固定为1
note: detail.note || '',
totalWeight: this.calculateTotalWeight(coils),
coils: this.formatCoilsData(coils)
};
},
// Format coils data / 格式化卷数据
formatCoilsData(coils) {
return coils.map(coil => ({
coilNo: coil.exitMatId || coil.coilid || '-',
heatNo: coil.heatNo || coil.heatNo || '-',
thickness: coil.exitThickness || coil.entryThick || '-',
width: coil.exitWidth || coil.entryWidth || '-',
length: coil.exitLength || coil.entryLength || '-',
weight: coil.exitNetWeight || coil.actualWeight || coil.entryWeight || '-',
c: coil.c || coil.chemicalC || '-',
si: coil.si || coil.chemicalSi || '-',
mn: coil.mn || coil.chemicalMn || '-',
p: coil.p || coil.chemicalP || '-',
s: coil.s || coil.chemicalS || '-',
yield: coil.yield || coil.yieldStrength || '-',
tensile: coil.tensile || coil.tensileStrength || '-',
elongation: coil.elongation || coil.elongationPercent || '-',
nValue: coil.nValue || '-',
rValue: coil.rValue || '-',
zincCoatingType: coil.zincCoatingType || '-',
zincCoatingValue: coil.zincCoatingValue || (coil.weightTop && coil.weightBottom ? 'Qualified' : '-'),
zincCoatingThickness: coil.zincCoatingThickness || coil.zincCoatingThickness || '-', // 添加锌层厚度字段
hardnessType: coil.hardnessType || '-',
hardnessValue: coil.hardnessValue || '-',
coatingWeight: coil.coatingWeight || coil.weightTop || '-',
surfaceQuality: coil.surfaceQuality || coil.surfaceGroup || 'Premium',
flatness: coil.flatness || 'Premium'
}));
},
// Calculate total weight / 计算总重量
calculateTotalWeight(coils) {
const total = coils.reduce((sum, coil) => {
const weight = parseFloat(coil.exitNetWeight || coil.actualWeight || coil.entryWeight || 0);
return sum + (isNaN(weight) ? 0 : weight);
}, 0);
return total > 0 ? total.toFixed(2) : '-';
},
// Format number / 格式化数字
formatNumber(value) {
if (value === null || value === undefined || value === '' || value === '-') {
return '-';
}
const num = parseFloat(value);
if (isNaN(num)) {
return value;
}
// Keep 2 decimal places for most numbers, but show more precision for small values / 大多数数字保留2位小数但小数值显示更多精度
if (Math.abs(num) < 1) {
return num.toFixed(3);
}
return num.toFixed(2);
},
// Handle print / 处理打印
handlePrint() {
const printStyle = `
@page {
size: A4 landscape;
margin: 10mm;
}
.certificate-content {
width: 100%;
font-family: Arial, sans-serif;
}
`;
printJS({
printable: 'qualityCertificateContent',
type: 'html',
header: null,
footer: null,
style: printStyle,
scanStyles: true,
targetStyles: ['*'],
documentTitle: 'Quality Certificate',
onPrintDialogClose: () => {
console.log('Print dialog closed');
}
});
}
}
};
</script>
<style scoped>
.quality-certificate-container {
padding: 20px;
background: #fff;
}
.certificate-content {
width: 100%;
font-family: Arial, sans-serif;
font-size: 12px;
color: #000;
}
/* Header styles / 头部样式 */
.certificate-header {
margin-bottom: 20px;
}
.header-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #000;
}
.company-logo {
width: 80px;
height: 80px;
border: 1px solid #ccc;
background: #f5f5f5;
}
.header-title {
flex: 1;
text-align: center;
}
.header-title h1 {
font-size: 20px;
font-weight: bold;
margin: 0 0 5px 0;
}
.document-number {
font-size: 11px;
color: #666;
}
.qr-code-placeholder {
width: 60px;
height: 60px;
border: 1px solid #ccc;
background: #f5f5f5;
}
.header-info {
display: flex;
flex-direction: column;
gap: 8px;
}
.info-row {
display: flex;
gap: 30px;
}
.info-item {
flex: 1;
display: flex;
align-items: center;
}
.info-label {
font-weight: bold;
min-width: 120px;
margin-right: 8px;
}
.info-value {
flex: 1;
}
/* Table styles / 表格样式 */
.certificate-table {
margin: 20px 0;
overflow-x: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 10px;
border: 2px solid #000;
table-layout: fixed;
}
.data-table th,
.data-table td {
border: 1px solid #000;
padding: 6px 4px;
text-align: center;
vertical-align: middle;
word-wrap: break-word;
font-size: 10px;
}
.data-table th {
background: #f0f0f0;
font-weight: bold;
font-size: 9px;
}
.data-table tbody tr:nth-child(even) {
background: #fafafa;
}
.data-table tbody tr:hover {
background: #f0f0f0;
}
/* Footer styles / 底部样式 */
.certificate-footer {
margin: 20px 0;
padding: 10px 0;
border-top: 1px solid #000;
}
.footer-row {
display: flex;
gap: 30px;
margin-bottom: 8px;
}
.footer-item {
flex: 1;
display: flex;
align-items: center;
}
.footer-label {
font-weight: bold;
min-width: 120px;
margin-right: 8px;
}
.footer-value {
flex: 1;
}
/* Remarks styles / 备注样式 */
.certificate-remarks {
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #000;
}
.remarks-title {
font-weight: bold;
margin-bottom: 8px;
}
.remarks-content p {
margin: 5px 0;
line-height: 1.6;
}
/* Print button / 打印按钮 */
.print-btn-container {
text-align: center;
margin-top: 20px;
}
/* Print styles / 打印样式 */
@media print {
.print-btn-container {
display: none;
}
.quality-certificate-container {
padding: 0;
background: #fff;
}
.certificate-content {
font-size: 10px;
page-break-inside: avoid;
}
.certificate-header {
page-break-after: avoid;
}
.certificate-table {
page-break-inside: auto;
}
.data-table {
font-size: 8px;
}
.data-table th,
.data-table td {
padding: 3px 2px;
}
.data-table tbody tr {
page-break-inside: avoid;
}
.certificate-footer {
page-break-before: avoid;
}
.certificate-remarks {
page-break-inside: avoid;
}
}
</style>