完善体检导检单打印面板
This commit is contained in:
@@ -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 ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user