Add QR code to aftersales electronic form

This commit is contained in:
Frudrax Cheng
2026-05-29 10:01:22 +08:00
parent 6067e8621a
commit aaf5fc6911
2 changed files with 84 additions and 12 deletions
+44 -5
View File
@@ -1,4 +1,5 @@
import { useEffect, useState } from 'react';
import QRCode from 'qrcode';
import { useParams, useNavigate } from 'react-router-dom';
import {
Card,
@@ -79,6 +80,10 @@ function formatDateTime(value?: string) {
return new Date(value).toLocaleString('zh-CN');
}
function getAftersalesPublicUrl(serialNumber: string) {
return `${window.location.origin}/aftersales/${serialNumber}`;
}
function AftersalesDetailPage() {
const { serialNumber = '' } = useParams<{ serialNumber: string }>();
const navigate = useNavigate();
@@ -95,6 +100,7 @@ function AftersalesDetailPage() {
const [qrCodeDataUrl, setQrCodeDataUrl] = useState('');
const [qrUrl, setQrUrl] = useState('');
const [electronicFormVisible, setElectronicFormVisible] = useState(false);
const [electronicFormQrCodeDataUrl, setElectronicFormQrCodeDataUrl] = useState('');
const [reassignModalVisible, setReassignModalVisible] = useState(false);
const [reassignTechnicianId, setReassignTechnicianId] = useState<number | undefined>();
@@ -201,6 +207,20 @@ function AftersalesDetailPage() {
link.click();
};
const openElectronicForm = async () => {
if (!order) return;
try {
const qrCode = await QRCode.toDataURL(getAftersalesPublicUrl(order.serialNumber), {
width: 132,
margin: 1,
});
setElectronicFormQrCodeDataUrl(qrCode);
setElectronicFormVisible(true);
} catch (err: any) {
message.error(err?.message || '生成电子表单二维码失败');
}
};
const handlePrintElectronicForm = () => {
const formNode = document.querySelector('.aftersales-electronic-form');
if (!formNode) return;
@@ -219,10 +239,15 @@ function AftersalesDetailPage() {
<style>
body { margin: 24px; color: #111827; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
.aftersales-electronic-form { max-width: 1080px; margin: 0 auto; }
.electronic-form-header { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 16px; }
.electronic-form-header { display: grid; grid-template-columns: minmax(180px, 1fr) auto minmax(180px, 1fr); align-items: center; gap: 20px; margin-bottom: 16px; }
.electronic-form-brand { justify-self: start; }
.electronic-form-logo { height: 34px; object-fit: contain; }
.electronic-form-title { flex: 1; text-align: center; font-size: 20px; font-weight: 700; }
.electronic-form-serial { border: 2px solid #111827; padding: 8px 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 16px; font-weight: 700; }
.electronic-form-title { justify-self: center; text-align: center; font-size: 20px; font-weight: 700; }
.electronic-form-meta { justify-self: end; display: flex; align-items: center; gap: 12px; }
.electronic-form-qr { width: 82px; height: 82px; object-fit: contain; }
.electronic-form-serial { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.electronic-form-serial-label { font-size: 12px; color: #4b5563; }
.electronic-form-serial-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 16px; font-weight: 700; white-space: nowrap; }
.electronic-form-table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 13px; }
.electronic-form-table th, .electronic-form-table td { border: 1px solid #1f2937; padding: 9px 10px; vertical-align: top; word-break: break-word; }
.electronic-form-table th { width: 120px; background: #f3f4f6; text-align: left; font-weight: 600; }
@@ -323,7 +348,7 @@ function AftersalesDetailPage() {
}
extra={
<Space>
<Button icon={<FileTextOutlined />} onClick={() => setElectronicFormVisible(true)}>
<Button icon={<FileTextOutlined />} onClick={openElectronicForm}>
</Button>
<Button icon={<QrcodeOutlined />} onClick={handleGenerateQrCode}>
@@ -535,9 +560,23 @@ function AftersalesDetailPage() {
>
<div className="aftersales-electronic-form">
<div className="electronic-form-header">
<div className="electronic-form-brand">
<img src={logo} alt="浙江贝凡" className="electronic-form-logo" />
</div>
<div className="electronic-form-title"></div>
<div className="electronic-form-serial">{order.serialNumber}</div>
<div className="electronic-form-meta">
{electronicFormQrCodeDataUrl && (
<img
src={electronicFormQrCodeDataUrl}
alt="售后码二维码"
className="electronic-form-qr"
/>
)}
<div className="electronic-form-serial">
<span className="electronic-form-serial-label"></span>
<strong className="electronic-form-serial-code">{order.serialNumber}</strong>
</div>
</div>
</div>
<table className="electronic-form-table">
<tbody>
+39 -6
View File
@@ -3,28 +3,55 @@
}
.electronic-form-header {
display: flex;
display: grid;
grid-template-columns: minmax(180px, 1fr) auto minmax(180px, 1fr);
align-items: center;
justify-content: space-between;
gap: 20px;
margin-bottom: 16px;
}
.electronic-form-brand {
justify-self: start;
}
.electronic-form-logo {
height: 34px;
object-fit: contain;
}
.electronic-form-title {
flex: 1;
justify-self: center;
text-align: center;
font-size: 20px;
font-weight: 700;
}
.electronic-form-meta {
justify-self: end;
display: flex;
align-items: center;
gap: 12px;
}
.electronic-form-qr {
width: 82px;
height: 82px;
object-fit: contain;
}
.electronic-form-serial {
border: 2px solid #111827;
padding: 8px 12px;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 3px;
}
.electronic-form-serial-label {
font-size: 12px;
color: #4b5563;
}
.electronic-form-serial-code {
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 16px;
font-weight: 700;
@@ -68,10 +95,16 @@
@media (max-width: 720px) {
.electronic-form-header {
align-items: flex-start;
flex-direction: column;
grid-template-columns: 1fr;
gap: 10px;
}
.electronic-form-brand,
.electronic-form-title,
.electronic-form-meta {
justify-self: start;
}
.electronic-form-title {
text-align: left;
font-size: 18px;