643 lines
19 KiB
Vue
643 lines
19 KiB
Vue
<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/m²)</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>
|
||
|