270 lines
9.9 KiB
TypeScript
270 lines
9.9 KiB
TypeScript
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>
|
||
);
|
||
};
|
||
|
||
|