完善体检导检单打印面板

This commit is contained in:
xianyi
2025-12-16 09:46:46 +08:00
parent 626147efdf
commit 2eeb23075a

View File

@@ -1,44 +1,62 @@
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { getTongyishuPdf } from '../../api'; import { submitDaojiandanSign } from '../../api';
import type { ExamClient } from '../../data/mockData'; import type { ExamClient } from '../../data/mockData';
import { Button } from '../ui'; import type { SignaturePadHandle } from '../ui';
import { Button, SignaturePad } from '../ui';
export const ExamPrintPanel = ({ client }: { client: ExamClient }) => { export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
const [pdfUrl, setPdfUrl] = useState<string | null>(null); const [pdfUrl, setPdfUrl] = useState<string | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [pdfReady, setPdfReady] = useState(false); const [pdfReady, setPdfReady] = useState(false);
const [pdfBlobUrl, setPdfBlobUrl] = useState<string | null>(null); const [pdfBlobUrl, setPdfBlobUrl] = useState<string | null>(null);
const [signatureSubmitted, setSignatureSubmitted] = useState(false);
const [submitLoading, setSubmitLoading] = useState(false);
const [submitMessage, setSubmitMessage] = useState<string | null>(null);
const signaturePadRef = useRef<SignaturePadHandle | null>(null);
const printRef = useRef<HTMLDivElement>(null); const printRef = useRef<HTMLDivElement>(null);
const iframeRef = useRef<HTMLIFrameElement>(null); const iframeRef = useRef<HTMLIFrameElement>(null);
useEffect(() => { const handleSubmitSign = async () => {
const physical_exam_id = Number(client.id); const examId = Number(client.id);
if (!physical_exam_id) { if (!examId) {
setError('无效的体检ID'); setSubmitMessage('无效的体检ID');
setLoading(false);
return; return;
} }
setPdfReady(false); const dataUrl = signaturePadRef.current?.toDataURL('image/png');
getTongyishuPdf({ exam_id: physical_exam_id }) if (!dataUrl) {
.then((res) => { setSubmitMessage('请先完成签名');
if (res.Status === 200 && res.Data?.list_pdf_url && res.Data.list_pdf_url.length > 0) { return;
setPdfUrl(res.Data.list_pdf_url[0].pdf_url); }
setPdfReady(false);
} else { setSubmitLoading(true);
setError(res.Message || '未获取到PDF文件'); setSubmitMessage(null);
} try {
}) // 将 base64 转换为 Blob
.catch((err) => { const blob = await fetch(dataUrl).then(r => r.blob());
console.error('获取PDF失败', err);
setError('获取PDF失败请稍后重试'); // 提交签名生成导检单PDF
}) const res = await submitDaojiandanSign({
.finally(() => { exam_id: examId,
setLoading(false); sign_file: blob,
}); });
}, [client.id]);
if (res.Status === 200 && res.Data?.pdf_url) {
setSubmitMessage('签名提交成功,正在加载导检单...');
setSignatureSubmitted(true);
setPdfUrl(res.Data.pdf_url);
} else {
setSubmitMessage(res.Message || '签名提交失败');
}
} catch (err) {
console.error('提交签名失败', err);
setSubmitMessage('签名提交失败,请稍后重试');
} finally {
setSubmitLoading(false);
}
};
useEffect(() => { useEffect(() => {
if (!pdfUrl) return; if (!pdfUrl) return;
@@ -88,24 +106,67 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
<div className='flex items-center justify-between border-b pb-3 mb-3'> <div className='flex items-center justify-between border-b pb-3 mb-3'>
<div> <div>
<div className='text-sm font-semibold'> · </div> <div className='text-sm font-semibold'> · </div>
<div className='text-[11px] text-gray-500 mt-1'></div> <div className='text-[11px] text-gray-500 mt-1'>
{signatureSubmitted
? '此为预览页面,实际打印效果以院内打印机为准。'
: '请先完成签名签名后将生成导检单PDF'}
</div>
</div> </div>
<div className='flex items-center gap-3'> <div className='flex items-center gap-3'>
<div className='text-right text-[11px] text-gray-500'> <div className='text-right text-[11px] text-gray-500'>
<div>{client.id}</div> <div>{client.id}</div>
<div>{new Date().toLocaleDateString('zh-CN')}</div> <div>{new Date().toLocaleDateString('zh-CN')}</div>
</div> </div>
<Button {signatureSubmitted && (
className='px-4 py-1.5 text-xs bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 disabled:cursor-not-allowed' <Button
onClick={handlePrint} className='px-4 py-1.5 text-xs bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50 disabled:cursor-not-allowed'
disabled={loading || !pdfReady || !pdfUrl} onClick={handlePrint}
> disabled={loading || !pdfReady || !pdfUrl}
>
</Button>
</Button>
)}
</div> </div>
</div> </div>
{loading ? ( {!signatureSubmitted ? (
<div className='flex flex-col gap-4'>
<div className='text-sm font-medium text-gray-900'></div>
<div className='ui7-signature-wrapper border rounded-xl overflow-hidden bg-gray-50'>
<SignaturePad
ref={signaturePadRef}
className='ui7-signature-canvas w-full h-72 bg-white touch-none'
/>
<div className='flex items-center justify-between px-3 py-2 bg-gray-50 border-t'>
<div className='text-xs text-gray-500'></div>
<Button
className='ui7-clear-button py-1 px-3'
onClick={() => signaturePadRef.current?.clear()}
disabled={submitLoading}
>
</Button>
</div>
</div>
{submitMessage && (
<div
className={`text-sm text-center ${submitMessage.includes('成功') ? 'text-green-600' : 'text-amber-600'
}`}
>
{submitMessage}
</div>
)}
<div className='flex items-center justify-end gap-3'>
<Button
className='py-2 px-6 bg-blue-600 text-white hover:bg-blue-700'
onClick={handleSubmitSign}
disabled={submitLoading}
>
{submitLoading ? '提交中...' : '提交签名'}
</Button>
</div>
</div>
) : loading ? (
<div className='flex items-center justify-center py-12 text-gray-500'> <div className='flex items-center justify-center py-12 text-gray-500'>
<div>PDF...</div> <div>PDF...</div>
</div> </div>
@@ -115,29 +176,13 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
<Button <Button
className='px-4 py-1.5 text-xs' className='px-4 py-1.5 text-xs'
onClick={() => { onClick={() => {
setLoading(true);
setError(null); setError(null);
const physical_exam_id = Number(client.id); setPdfUrl(null);
if (physical_exam_id) { setSignatureSubmitted(false);
getTongyishuPdf({ exam_id: physical_exam_id }) signaturePadRef.current?.clear();
.then((res) => {
if (res.Status === 200 && res.Data?.list_pdf_url && res.Data.list_pdf_url.length > 0) {
setPdfUrl(res.Data.list_pdf_url[0].pdf_url);
} else {
setError(res.Message || '未获取到PDF文件');
}
})
.catch((err) => {
console.error('获取PDF失败', err);
setError('获取PDF失败请稍后重试');
})
.finally(() => {
setLoading(false);
});
}
}} }}
> >
</Button> </Button>
</div> </div>
) : pdfUrl ? ( ) : pdfUrl ? (