完善签到可选项
This commit is contained in:
@@ -2,8 +2,8 @@ import { useEffect, useRef, useState } from 'react';
|
||||
import * as pdfjsLib from 'pdfjs-dist';
|
||||
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
|
||||
|
||||
import type { OutputTongyishuFileInfo, OutputTijianPdfFileInfo } from '../../api';
|
||||
import { signInMedicalExamCenter, submitTongyishuSign, submitDaojiandanSign, editDaojiandanPrintStatus, submitAddItemBillSign, getTijianPdfFile, getTongyishuPdf, getDaojiandanPdf } from '../../api';
|
||||
import type { OutputTongyishuFileInfo, OutputTijianPdfFileInfo, OutputPhysicalExamItemInfo } from '../../api';
|
||||
import { signInMedicalExamCenter, submitTongyishuSign, submitDaojiandanSign, editDaojiandanPrintStatus, submitAddItemBillSign, getTijianPdfFile, getTongyishuPdf, getDaojiandanPdf, getExamOptionalItemList, removeOptionalPackage } from '../../api';
|
||||
import type { SignaturePadHandle } from '../ui';
|
||||
import { Button, SignaturePad } from '../ui';
|
||||
|
||||
@@ -81,8 +81,13 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
const [batchPrintLoading, setBatchPrintLoading] = useState(false);
|
||||
const addItemBillCanvasContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// 可选项目列表相关状态
|
||||
const [optionalItemList, setOptionalItemList] = useState<OutputPhysicalExamItemInfo[]>([]);
|
||||
const [optionalItemLoading, setOptionalItemLoading] = useState(false);
|
||||
const [selectedOptionalItem, setSelectedOptionalItem] = useState<number | null>(null);
|
||||
|
||||
const busy =
|
||||
signLoading || submitLoading || consentLoading || pdfLoading || daojiandanSubmitLoading || addItemBillSubmitLoading || batchPrintLoading;
|
||||
signLoading || submitLoading || consentLoading || pdfLoading || daojiandanSubmitLoading || addItemBillSubmitLoading || batchPrintLoading || optionalItemLoading;
|
||||
|
||||
useEffect(() => {
|
||||
onBusyChange?.(busy);
|
||||
@@ -194,8 +199,24 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 加载可选项目列表
|
||||
const loadOptionalItems = async () => {
|
||||
if (!examId) return;
|
||||
setOptionalItemLoading(true);
|
||||
try {
|
||||
const res = await getExamOptionalItemList({ physical_exam_id: examId });
|
||||
if (res.Status === 200 && res.Data?.listOptionalItem) {
|
||||
setOptionalItemList(res.Data.listOptionalItem);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取可选项目列表失败', err);
|
||||
} finally {
|
||||
setOptionalItemLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 先加载知情同意书和导检单,然后刷新所有PDF状态(包括签名状态)
|
||||
Promise.all([loadTongyishu(), loadDaojiandan()]).then(() => {
|
||||
Promise.all([loadTongyishu(), loadDaojiandan(), loadOptionalItems()]).then(() => {
|
||||
refreshTijianPdfs(examId);
|
||||
});
|
||||
}, [examId]);
|
||||
@@ -268,6 +289,36 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
setMessage('请先上传身份证照片');
|
||||
return;
|
||||
}
|
||||
if (!examId) {
|
||||
setMessage('缺少体检ID');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果有可选项目,先移除未选中的项目
|
||||
if (optionalItemList.length > 0 && selectedOptionalItem != null) {
|
||||
const unselectedCodes = optionalItemList
|
||||
.map((item) => item.combination_code)
|
||||
.filter((code): code is number => code != null && code !== selectedOptionalItem);
|
||||
|
||||
if (unselectedCodes.length > 0) {
|
||||
try {
|
||||
const combinationCodeIds = unselectedCodes.join(',');
|
||||
const removeRes = await removeOptionalPackage({
|
||||
physical_exam_id: examId,
|
||||
combination_code_ids: combinationCodeIds,
|
||||
});
|
||||
if (removeRes.Status !== 200 || removeRes.Data?.is_success !== 1) {
|
||||
setMessage('移除未选项目失败:' + (removeRes.Message || '未知错误'));
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('移除未选项目失败', err);
|
||||
setMessage('移除未选项目失败,请稍后重试');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setSignLoading(true);
|
||||
setMessage(null);
|
||||
try {
|
||||
@@ -1620,6 +1671,7 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className='grid grid-cols-2 gap-4 text-sm'>
|
||||
<div className='p-4 rounded-2xl border bg-gray-50/60 flex flex-col gap-3'>
|
||||
@@ -1652,6 +1704,42 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
{message && (
|
||||
<div className={`text-xs ${message.includes('成功') ? 'text-green-600' : 'text-amber-600'}`}>{message}</div>
|
||||
)}
|
||||
{/* 可选项目列表 */}
|
||||
{optionalItemLoading ? (
|
||||
<div className='text-xs text-gray-500'>加载可选项目...</div>
|
||||
) : optionalItemList.length > 0 ? (
|
||||
<div className='mt-2 space-y-2'>
|
||||
<div className='text-xs font-medium text-gray-700'>可选项目(必选其一):</div>
|
||||
<div className='max-h-32 overflow-y-auto custom-scroll space-y-1'>
|
||||
{optionalItemList.map((item) => {
|
||||
const combinationCode = item.combination_code;
|
||||
const isSelected = combinationCode != null && combinationCode === selectedOptionalItem;
|
||||
return (
|
||||
<label
|
||||
key={combinationCode ?? `item-${item.package_code}`}
|
||||
className='flex items-center gap-2 cursor-pointer text-xs'
|
||||
>
|
||||
<input
|
||||
type='radio'
|
||||
name='optional-item'
|
||||
checked={isSelected}
|
||||
onChange={() => {
|
||||
if (combinationCode != null) {
|
||||
setSelectedOptionalItem(combinationCode);
|
||||
}
|
||||
}}
|
||||
disabled={busy}
|
||||
className='w-3 h-3'
|
||||
/>
|
||||
<span className={isSelected ? 'text-blue-600 font-medium' : 'text-gray-700'}>
|
||||
{item.combination_name || '未命名项目'}
|
||||
</span>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{showImagePreview && previewImage && (
|
||||
<div className='fixed inset-0 z-[80] bg-black/90 flex items-center justify-center p-6' onClick={() => setShowImagePreview(false)}>
|
||||
|
||||
Reference in New Issue
Block a user