From 30e3ac67d2c875635ad86d792320b8c102381f12 Mon Sep 17 00:00:00 2001 From: Frudrax Cheng Date: Tue, 2 Jun 2026 10:38:40 +0800 Subject: [PATCH] Require dual signatures for aftersales confirmation --- src/components/SignatureOverlay.tsx | 5 +- src/pages/AftersalesConfirm.tsx | 166 ++++++++++++++++++------- src/pages/AftersalesDetail.tsx | 40 +++--- src/pages/styles/AftersalesConfirm.css | 34 ++++- src/pages/styles/AftersalesDetail.css | 31 +++-- src/types/index.ts | 3 + 6 files changed, 205 insertions(+), 74 deletions(-) diff --git a/src/components/SignatureOverlay.tsx b/src/components/SignatureOverlay.tsx index ec53a14..c6a3b04 100644 --- a/src/components/SignatureOverlay.tsx +++ b/src/components/SignatureOverlay.tsx @@ -5,11 +5,12 @@ import './SignatureOverlay.css'; interface SignatureOverlayProps { open: boolean; + title?: string; onCancel: () => void; onConfirm: (dataUrl: string) => void; } -function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps) { +function SignatureOverlay({ open, title = '请在框内签名', onCancel, onConfirm }: SignatureOverlayProps) { const padRef = useRef(null); const [, setData] = useState(''); @@ -44,7 +45,7 @@ function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps) - 请在框内签名 + {title} diff --git a/src/pages/AftersalesConfirm.tsx b/src/pages/AftersalesConfirm.tsx index 744afc3..ead6fbf 100644 --- a/src/pages/AftersalesConfirm.tsx +++ b/src/pages/AftersalesConfirm.tsx @@ -29,8 +29,11 @@ function AftersalesConfirmPage() { const [submitting, setSubmitting] = useState(false); const [rejectReason, setRejectReason] = useState(''); const [showRejectDialog, setShowRejectDialog] = useState(false); - const [signatureData, setSignatureData] = useState(''); - const [showSignatureOverlay, setShowSignatureOverlay] = useState(false); + const [customerSignatureData, setCustomerSignatureData] = useState(''); + const [responsibleSignatureData, setResponsibleSignatureData] = useState(''); + const [activeSignatureRole, setActiveSignatureRole] = useState<'customer' | 'responsible' | null>( + null, + ); const loadOrder = async () => { setLoading(true); @@ -53,15 +56,20 @@ function AftersalesConfirmPage() { }, [serialNumber]); const handleAuthorize = async () => { - if (!signatureData) { - message.error('请先签名'); + if (!customerSignatureData) { + message.error('请先完成客户签名'); + return; + } + if (!responsibleSignatureData) { + message.error('请先完成负责人签名'); return; } setSubmitting(true); try { const updated = await aftersalesApi.customerConfirm(serialNumber, { action: 'authorize', - signature: signatureData, + signature: customerSignatureData, + responsibleSignature: responsibleSignatureData, }); setOrder(updated); message.success('感谢您的确认,工单已完成'); @@ -99,8 +107,16 @@ function AftersalesConfirmPage() { } }; - const handleClearSignature = () => { - setSignatureData(''); + const handleClearSignature = (role: 'customer' | 'responsible') => { + if (role === 'customer') { + setCustomerSignatureData(''); + return; + } + setResponsibleSignatureData(''); + }; + + const openSignatureOverlay = (role: 'customer' | 'responsible') => { + setActiveSignatureRole(role); }; if (loading) { @@ -220,48 +236,103 @@ function AftersalesConfirmPage() { - {isClosed && order.signature && ( + {isClosed && (order.signature || order.responsibleSignature) && (
-

客户确认签名

- 客户确认签名 +
+ {order.signature && ( +
+

客户签名

+ 客户签名 +
+ )} + {order.responsibleSignature && ( +
+

负责人签名

+ 负责人签名 +
+ )} +
)} {isPending && ( <>
-
-

请签名确认维修结果

- {signatureData && ( - - )} +

请签名确认维修结果

+
+
+
+

客户签名

+ {customerSignatureData && ( + + )} +
+ {customerSignatureData ? ( + + ) : ( + + )} +
+
+
+

负责人签名

+ {responsibleSignatureData && ( + + )} +
+ {responsibleSignatureData ? ( + + ) : ( + + )} +
- {signatureData ? ( - - ) : ( - - )}