Files
ipad/src/components/exam/ExamDeliveryPanel.tsx
2025-12-25 10:55:24 +08:00

270 lines
9.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from 'react';
import type { ExamClient } from '../../data/mockData';
import { getReportSendQRcode, getReportSendInfo, saveReportSendAddress } from '../../api';
import { Button, Input } from '../ui';
export const ExamDeliveryPanel = ({ client }: { client: ExamClient }) => {
const [viewMode, setViewMode] = useState<'form' | 'image'>('form');
const [qrcodeUrl, setQrcodeUrl] = useState<string | null>(null);
const [qrcodeLoading, setQrcodeLoading] = useState(false);
// 表单字段
const [addressContact, setAddressContact] = useState('');
const [addressMobile, setAddressMobile] = useState('');
const [provinceName, setProvinceName] = useState('');
const [cityName, setCityName] = useState('');
const [countryName, setCountryName] = useState('');
const [addressContent, setAddressContent] = useState('');
const [saveLoading, setSaveLoading] = useState(false);
const [saveMessage, setSaveMessage] = useState<string | null>(null);
const [infoLoading, setInfoLoading] = useState(false);
// 获取报告寄送地址信息并自动填入表单
useEffect(() => {
if (!client.id) return;
setInfoLoading(true);
const appointmentId = Number(client.id);
if (!appointmentId) {
setInfoLoading(false);
return;
}
getReportSendInfo({ physical_exam_id: appointmentId })
.then((res) => {
if (res.Status === 200 && res.Data) {
const data = res.Data;
if (data.address_contact) {
setAddressContact(data.address_contact);
}
if (data.address_mobile) {
setAddressMobile(data.address_mobile);
}
if (data.address_content) {
setAddressContent(data.address_content);
}
}
})
.catch((err) => {
console.error('获取报告寄送地址失败', err);
})
.finally(() => {
setInfoLoading(false);
});
}, [client.id]);
useEffect(() => {
if (viewMode === 'image' && !qrcodeUrl && !qrcodeLoading) {
setQrcodeLoading(true);
// 使用 client.id 作为 appointment_id如果接口需要其他格式可以调整
getReportSendQRcode({ appointment_id: client.id })
.then((res) => {
if (res.Status === 200 && res.Data?.qrcode_url) {
setQrcodeUrl(res.Data.qrcode_url);
}
})
.catch((err) => {
console.error('获取报告寄送二维码失败', err);
})
.finally(() => {
setQrcodeLoading(false);
});
}
}, [viewMode, client.id, qrcodeUrl, qrcodeLoading]);
return (
<div className='flex justify-center'>
<div className='w-full rounded-2xl border shadow-sm px-6 py-4 text-xs text-gray-800'>
<div className='flex items-center justify-between mb-3'>
<div className='text-lg font-semibold text-gray-900'></div>
<div className='flex items-center gap-2'>
<button
onClick={() => setViewMode('form')}
className={`px-3 py-1.5 text-xs rounded-lg border transition-colors ${viewMode === 'form'
? 'bg-blue-600 text-white border-blue-600'
: 'bg-white text-gray-600 border-gray-200 hover:border-gray-300'
}`}
>
</button>
<button
onClick={() => setViewMode('image')}
className={`px-3 py-1.5 text-xs rounded-lg border transition-colors ${viewMode === 'image'
? 'bg-blue-600 text-white border-blue-600'
: 'bg-white text-gray-600 border-gray-200 hover:border-gray-300'
}`}
>
</button>
</div>
</div>
{viewMode === 'form' ? (
<>
<div className='grid grid-cols-2 gap-3 mb-3'>
<div>
<Input
placeholder='请输入收件人姓名'
className='mt-1'
value={addressContact}
onChange={(e) => setAddressContact(e.target.value)}
/>
</div>
<div>
<Input
placeholder='用于快递联系'
className='mt-1'
value={addressMobile}
onChange={(e) => setAddressMobile(e.target.value)}
/>
</div>
<div>
<Input
placeholder='例如:上海市'
className='mt-1'
value={provinceName}
onChange={(e) => setProvinceName(e.target.value)}
/>
</div>
<div>
<Input
placeholder='例如:上海市'
className='mt-1'
value={cityName}
onChange={(e) => setCityName(e.target.value)}
/>
</div>
<div>
<Input
placeholder='例如:浦东新区'
className='mt-1'
value={countryName}
onChange={(e) => setCountryName(e.target.value)}
/>
</div>
<div className='col-span-2'>
<Input
placeholder='请输入详细寄送地址'
className='mt-1'
value={addressContent}
onChange={(e) => setAddressContent(e.target.value)}
/>
</div>
</div>
<div className='space-y-2'>
<div></div>
<textarea
className='w-full rounded-2xl border px-3 py-2 text-xs outline-none focus:ring-2 focus:ring-gray-200 min-h-[80px]'
placeholder='如需多份报告、加急寄送等,请在此备注'
/>
</div>
{saveMessage && (
<div
className={`mt-3 text-xs px-3 py-2 rounded-lg ${saveMessage.includes('成功') ? 'bg-green-50 text-green-600' : 'bg-amber-50 text-amber-600'
}`}
>
{saveMessage}
</div>
)}
<div className='mt-4 flex items-center justify-between text-[11px] text-gray-500'>
<div>
<span className='font-medium text-gray-800'>{client.name}</span>{client.id}
</div>
<Button
className='px-4 py-1.5 text-xs'
onClick={async () => {
const physical_exam_id = Number(client.id);
if (!physical_exam_id) {
setSaveMessage('缺少体检ID');
return;
}
if (!addressContact.trim()) {
setSaveMessage('请输入收件人姓名');
return;
}
if (!addressMobile.trim()) {
setSaveMessage('请输入联系电话');
return;
}
if (!provinceName.trim()) {
setSaveMessage('请输入省份');
return;
}
if (!cityName.trim()) {
setSaveMessage('请输入城市');
return;
}
if (!countryName.trim()) {
setSaveMessage('请输入区县');
return;
}
if (!addressContent.trim()) {
setSaveMessage('请输入详细地址');
return;
}
setSaveLoading(true);
setSaveMessage(null);
try {
const res = await saveReportSendAddress({
physical_exam_id,
address_contact: addressContact.trim(),
address_mobile: addressMobile.trim(),
province_name: provinceName.trim(),
city_name: cityName.trim(),
country_name: countryName.trim(),
address_content: addressContent.trim(),
});
if (res.Status === 200 && res.Data?.is_success === 1) {
setSaveMessage('保存成功');
setTimeout(() => setSaveMessage(null), 2000);
} else {
setSaveMessage(res.Message || '保存失败');
}
} catch (err) {
console.error('保存报告寄送地址失败', err);
setSaveMessage('保存失败,请稍后重试');
} finally {
setSaveLoading(false);
}
}}
disabled={saveLoading}
>
{saveLoading ? '保存中...' : '保存寄送信息'}
</Button>
</div>
</>
) : (
<div className='flex flex-col items-center justify-center py-8'>
{qrcodeLoading ? (
<div className='text-gray-500'>...</div>
) : qrcodeUrl ? (
<div className='flex flex-col items-center gap-4'>
<img
src={qrcodeUrl.startsWith('data:') ? qrcodeUrl : `data:image/png;base64,${qrcodeUrl}`}
alt='报告寄送登记二维码'
className='max-w-full max-h-[400px] object-contain'
/>
<div className='text-xs text-gray-500'></div>
</div>
) : (
<div className='text-gray-500'></div>
)}
</div>
)}
</div>
</div>
);
};