更新新签到
This commit is contained in:
@@ -4,7 +4,6 @@ import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
|
||||
|
||||
import { getDaojiandanPdf as getDaojiandanPdfApi, submitDaojiandanSign, editDaojiandanPrintStatus } from '../../api';
|
||||
import type { ExamClient } from '../../data/mockData';
|
||||
import { setExamActionRecord, setDaojiandanPdf, getDaojiandanPdf } from '../../utils/examActions';
|
||||
import type { SignaturePadHandle } from '../ui';
|
||||
import { Button, SignaturePad } from '../ui';
|
||||
|
||||
@@ -69,17 +68,7 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
||||
setSubmitMessage('签名提交成功,正在加载导检单...');
|
||||
setSignatureSubmitted(true);
|
||||
const pdfUrlValue = res.Data.pdf_url;
|
||||
const pdfNameValue = res.Data.pdf_name || '导检单';
|
||||
setPdfUrl(pdfUrlValue);
|
||||
// 保存导检单PDF信息到localStorage
|
||||
setDaojiandanPdf(examId, {
|
||||
pdf_name: pdfNameValue,
|
||||
pdf_url: pdfUrlValue,
|
||||
is_signed: true,
|
||||
});
|
||||
// 记录打印导检单是否签名操作
|
||||
setExamActionRecord(examId, 'printSign', true);
|
||||
|
||||
// 更新导检单打印状态
|
||||
try {
|
||||
await editDaojiandanPrintStatus({ exam_id: examId });
|
||||
@@ -102,12 +91,6 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
||||
useEffect(() => {
|
||||
const examId = Number(client.id);
|
||||
if (!examId) return;
|
||||
|
||||
const storedPdf = getDaojiandanPdf(examId);
|
||||
if (storedPdf && storedPdf.pdf_url) {
|
||||
setPdfUrl(storedPdf.pdf_url);
|
||||
setShowPreview(true);
|
||||
}
|
||||
}, [client.id]);
|
||||
|
||||
// 获取导检单PDF(优先使用localStorage,没有则调用接口)
|
||||
@@ -122,16 +105,6 @@ export const ExamPrintPanel = ({ client }: { client: ExamClient }) => {
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
// 先尝试从localStorage获取
|
||||
const storedPdf = getDaojiandanPdf(examId);
|
||||
if (storedPdf && storedPdf.pdf_url) {
|
||||
setPdfUrl(storedPdf.pdf_url);
|
||||
setShowPreview(true);
|
||||
setFetchLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果没有存储的,则调用接口获取
|
||||
const res = await getDaojiandanPdfApi({ exam_id: examId });
|
||||
if (res.Status === 200 && res.Data?.pdf_url) {
|
||||
const pdfUrlValue = res.Data.pdf_url;
|
||||
|
||||
@@ -2,19 +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 } from '../../api';
|
||||
import { getTongyishuPdf, signInMedicalExamCenter, submitTongyishuSign, submitDaojiandanSign, editDaojiandanPrintStatus, getDaojiandanPdf as getDaojiandanPdfApi, submitAddItemBillSign } from '../../api';
|
||||
import {
|
||||
setExamActionRecord,
|
||||
setTongyishuPdfList,
|
||||
getTongyishuPdfList,
|
||||
setDaojiandanPdf,
|
||||
getDaojiandanPdf as getDaojiandanPdfFromStorage,
|
||||
setAddItemBillPdf,
|
||||
getAddItemBillPdf as getAddItemBillPdfFromStorage,
|
||||
type TongyishuPdfInfo,
|
||||
type AddItemBillPdfInfo,
|
||||
} from '../../utils/examActions';
|
||||
import type { OutputTongyishuFileInfo, OutputTijianPdfFileInfo } from '../../api';
|
||||
import { signInMedicalExamCenter, submitTongyishuSign, submitDaojiandanSign, editDaojiandanPrintStatus, submitAddItemBillSign, getTijianPdfFile } from '../../api';
|
||||
import type { SignaturePadHandle } from '../ui';
|
||||
import { Button, SignaturePad } from '../ui';
|
||||
|
||||
@@ -74,14 +63,22 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
const [daojiandanPdfReady, setDaojiandanPdfReady] = useState(false);
|
||||
const [daojiandanPdfBlobUrl, setDaojiandanPdfBlobUrl] = useState<string | null>(null);
|
||||
const daojiandanCanvasContainerRef = useRef<HTMLDivElement>(null);
|
||||
// 加项单相关状态(支持多个加项单)
|
||||
const [addItemBillList, setAddItemBillList] = useState<AddItemBillPdfInfo[]>([]);
|
||||
const [currentAddItemBill, setCurrentAddItemBill] = useState<AddItemBillPdfInfo | null>(null);
|
||||
const [showAddItemBillPreview, setShowAddItemBillPreview] = useState(false);
|
||||
const [showAddItemBillSignature, setShowAddItemBillSignature] = useState(false);
|
||||
const addItemBillSignaturePadRef = useRef<SignaturePadHandle | null>(null);
|
||||
const [addItemBillSubmitLoading, setAddItemBillSubmitLoading] = useState(false);
|
||||
const [addItemBillSubmitMessage, setAddItemBillSubmitMessage] = useState<string | null>(null);
|
||||
type AddItemBillItem = {
|
||||
pdf_sort: number;
|
||||
combinationCode: string;
|
||||
payment_status?: string | null;
|
||||
payment_status_name?: string | null;
|
||||
pdf_name: string;
|
||||
pdf_url: string;
|
||||
is_signed: boolean;
|
||||
};
|
||||
const [addItemBillList, setAddItemBillList] = useState<AddItemBillItem[]>([]);
|
||||
const [currentAddItemBill, setCurrentAddItemBill] = useState<AddItemBillItem | null>(null);
|
||||
const [addItemBillPdfData, setAddItemBillPdfData] = useState<ArrayBuffer | null>(null);
|
||||
const [addItemBillPdfLoading, setAddItemBillPdfLoading] = useState(false);
|
||||
const [addItemBillPdfReady, setAddItemBillPdfReady] = useState(false);
|
||||
@@ -95,6 +92,86 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
return () => onBusyChange?.(false);
|
||||
}, [busy, onBusyChange]);
|
||||
|
||||
const refreshTijianPdfs = async (examIdValue: number) => {
|
||||
setConsentLoading(true);
|
||||
setConsentMessage(null);
|
||||
|
||||
try {
|
||||
const res = await getTijianPdfFile({ exam_id: examIdValue });
|
||||
const list: OutputTijianPdfFileInfo[] = res.Data || [];
|
||||
|
||||
// 知情同意书列表(pdf_type = 2)
|
||||
const consentItems = list.filter((item) => item.pdf_type === 2);
|
||||
const mappedConsent: OutputTongyishuFileInfo[] = consentItems.map((item) => ({
|
||||
pdf_name: item.pdf_name || '',
|
||||
pdf_url: item.sign_pdf_url || item.pdf_url || '',
|
||||
combination_code: item.combination_code ?? null,
|
||||
is_signed: item.is_sign === 1,
|
||||
}));
|
||||
setConsentList(mappedConsent);
|
||||
|
||||
// 已签名的组合码,用于一键打印等逻辑
|
||||
const signedCodes =
|
||||
consentItems
|
||||
.filter((item) => item.is_sign === 1 && item.combination_code !== null && item.combination_code !== undefined)
|
||||
.map((item) => Number(item.combination_code))
|
||||
.filter((n) => Number.isFinite(n)) || [];
|
||||
setSignedCombinationCodes(signedCodes);
|
||||
|
||||
if (!mappedConsent.length) {
|
||||
setConsentMessage(res.Message || '暂无知情同意书');
|
||||
}
|
||||
|
||||
// 导检单(pdf_type = 1,取第一条)
|
||||
const daojiandan = list.find((item) => item.pdf_type === 1);
|
||||
if (daojiandan) {
|
||||
const url = daojiandan.sign_pdf_url || daojiandan.pdf_url || null;
|
||||
setDaojiandanUrl(url);
|
||||
setIsDaojiandanSigned(daojiandan.is_sign === 1);
|
||||
} else {
|
||||
setDaojiandanUrl(null);
|
||||
setIsDaojiandanSigned(false);
|
||||
}
|
||||
|
||||
// 加项单(pdf_type = 3):完全由新接口提供列表和签名状态
|
||||
const addItemFromApi = list.filter((item) => item.pdf_type === 3);
|
||||
if (addItemFromApi.length > 0) {
|
||||
const addItemList: AddItemBillItem[] = addItemFromApi.map((item) => ({
|
||||
pdf_sort: item.combination_code ?? 0,
|
||||
combinationCode: String(item.combination_code ?? ''),
|
||||
payment_status: item.is_pay != null ? String(item.is_pay) : null,
|
||||
payment_status_name: item.is_pay_name ?? null,
|
||||
pdf_name: item.pdf_name || '加项单',
|
||||
pdf_url: item.sign_pdf_url || item.pdf_url || '',
|
||||
is_signed: item.is_sign === 1,
|
||||
}));
|
||||
setAddItemBillList(addItemList);
|
||||
const unsigned = addItemList.find((bill) => bill.is_signed !== true);
|
||||
setCurrentAddItemBill(unsigned || addItemList[0] || null);
|
||||
} else {
|
||||
setAddItemBillList([]);
|
||||
setCurrentAddItemBill(null);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取体检PDF列表失败', err);
|
||||
setConsentMessage('知情同意书加载失败,请稍后重试');
|
||||
} finally {
|
||||
setConsentLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化加载体检 PDF 列表(导检单、知情同意书、加项单)
|
||||
useEffect(() => {
|
||||
if (!examId) {
|
||||
setConsentList([]);
|
||||
setConsentMessage('缺少体检ID,无法获取知情同意书');
|
||||
setDaojiandanUrl(null);
|
||||
setIsDaojiandanSigned(false);
|
||||
return;
|
||||
}
|
||||
refreshTijianPdfs(examId);
|
||||
}, [examId]);
|
||||
|
||||
const handlePickFile = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
@@ -170,10 +247,6 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
const ok = res.Status === 200 && res.Data?.is_success === 0;
|
||||
if (ok) {
|
||||
setMessage('签到成功');
|
||||
// 记录身份证拍照与签到操作
|
||||
if (examId) {
|
||||
setExamActionRecord(examId, 'idCardSignIn', true);
|
||||
}
|
||||
} else {
|
||||
setMessage(res.Message || '签到失败');
|
||||
}
|
||||
@@ -210,20 +283,7 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
|
||||
if (res.Status === 200) {
|
||||
setSubmitMessage('签名提交成功');
|
||||
// 记录体检知情同意书的签字操作
|
||||
if (examId) {
|
||||
setExamActionRecord(examId, 'consentSign', true);
|
||||
}
|
||||
// 存储返回的PDF列表(标记为已签名)
|
||||
if (res.Data?.list_pdf_url && Array.isArray(res.Data.list_pdf_url) && examId) {
|
||||
const pdfList: TongyishuPdfInfo[] = res.Data.list_pdf_url.map((item) => ({
|
||||
pdf_name: item.pdf_name || '',
|
||||
pdf_url: item.pdf_url || '',
|
||||
combination_code: item.combination_code ?? null,
|
||||
is_signed: true,
|
||||
}));
|
||||
setTongyishuPdfList(examId, pdfList);
|
||||
}
|
||||
// 更新本地已签名组合码(立刻刷新按钮状态)
|
||||
setSignedCombinationCodes((prev) => {
|
||||
const code = Number(previewPdf.combination_code);
|
||||
if (!Number.isFinite(code)) return prev || [];
|
||||
@@ -234,6 +294,11 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
setPreviewPdf(null);
|
||||
setSubmitMessage(null);
|
||||
signaturePadRef.current?.clear();
|
||||
|
||||
// 更新签名状态(刷新统一 PDF 列表)
|
||||
if (examId) {
|
||||
refreshTijianPdfs(examId);
|
||||
}
|
||||
}, 2000);
|
||||
} else {
|
||||
setSubmitMessage(res.Message || '签名提交失败');
|
||||
@@ -246,121 +311,6 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!examId) {
|
||||
setConsentList([]);
|
||||
setConsentMessage('缺少体检ID,无法获取知情同意书');
|
||||
return;
|
||||
}
|
||||
setConsentLoading(true);
|
||||
setConsentMessage(null);
|
||||
|
||||
// 先检查 localStorage 中是否有已签名的知情同意书
|
||||
const storedList = getTongyishuPdfList(examId);
|
||||
const signedFromStored =
|
||||
storedList
|
||||
?.filter((pdf) => pdf.is_signed === true && pdf.combination_code !== null && pdf.combination_code !== undefined)
|
||||
.map((pdf) => Number(pdf.combination_code))
|
||||
.filter((n) => Number.isFinite(n)) || [];
|
||||
setSignedCombinationCodes(signedFromStored);
|
||||
const allSigned = storedList && storedList.length > 0 && storedList.every((pdf) => pdf.is_signed === true);
|
||||
|
||||
// 如果所有知情同意书都已签名,直接使用 localStorage 中的数据,不请求接口
|
||||
if (allSigned && storedList) {
|
||||
const mergedList = storedList.map((pdf) => ({
|
||||
pdf_name: pdf.pdf_name,
|
||||
pdf_url: pdf.pdf_url,
|
||||
combination_code: pdf.combination_code ?? null,
|
||||
}));
|
||||
setConsentList(mergedList);
|
||||
setConsentLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果有未签名的,请求接口获取最新列表
|
||||
getTongyishuPdf({ exam_id: examId })
|
||||
.then((res) => {
|
||||
const list = res.Data?.list_pdf_url || [];
|
||||
|
||||
// 合并接口返回的数据和本地已保存的已签名 PDF
|
||||
let mergedList = list;
|
||||
if (storedList && storedList.length > 0) {
|
||||
mergedList = list.map((item) => {
|
||||
if (item.combination_code === undefined || item.combination_code === null) return item;
|
||||
const code = Number(item.combination_code);
|
||||
if (!Number.isFinite(code)) return item;
|
||||
|
||||
const matched = storedList.find(
|
||||
(pdf) => pdf.combination_code !== null && Number(pdf.combination_code) === code && pdf.is_signed === true,
|
||||
);
|
||||
|
||||
// 如果本地有已签名的版本,优先使用
|
||||
if (matched && matched.pdf_url && matched.is_signed === true) {
|
||||
return {
|
||||
...item,
|
||||
pdf_url: matched.pdf_url,
|
||||
pdf_name: matched.pdf_name || item.pdf_name,
|
||||
};
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
setConsentList(mergedList);
|
||||
if (!list.length) {
|
||||
setConsentMessage(res.Data?.message || '暂无知情同意书');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('获取知情同意书失败', err);
|
||||
setConsentMessage('知情同意书加载失败,请稍后重试');
|
||||
})
|
||||
.finally(() => setConsentLoading(false));
|
||||
}, [examId]);
|
||||
|
||||
// 组件加载时检查导检单localStorage,如果没有则调用接口获取未签名的导检单
|
||||
useEffect(() => {
|
||||
if (!examId) return;
|
||||
|
||||
// 先检查 localStorage 中的导检单
|
||||
const storedPdf = getDaojiandanPdfFromStorage(examId);
|
||||
if (storedPdf && storedPdf.pdf_url) {
|
||||
setDaojiandanUrl(storedPdf.pdf_url);
|
||||
// 使用 localStorage 中保存的 is_signed 字段判断是否已签名
|
||||
setIsDaojiandanSigned(storedPdf.is_signed === true);
|
||||
} else {
|
||||
// 如果 localStorage 中没有导检单,调用接口获取未签名的导检单用于查看和签名
|
||||
const fetchDaojiandan = async () => {
|
||||
try {
|
||||
const res = await getDaojiandanPdfApi({ exam_id: examId });
|
||||
if (res.Status === 200 && res.Data?.pdf_url) {
|
||||
const pdfUrlValue = res.Data.pdf_url;
|
||||
// 不保存到 localStorage,只用于显示和签名
|
||||
setDaojiandanUrl(pdfUrlValue);
|
||||
setIsDaojiandanSigned(false); // 接口获取的是未签名的
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取导检单失败', err);
|
||||
}
|
||||
};
|
||||
fetchDaojiandan();
|
||||
}
|
||||
|
||||
// 检查加项单PDF(可能有多个)
|
||||
const storedAddItemBillList = getAddItemBillPdfFromStorage(examId);
|
||||
if (storedAddItemBillList && storedAddItemBillList.length > 0) {
|
||||
setAddItemBillList(storedAddItemBillList);
|
||||
// 默认选中第一个未签名的加项单,如果都已签名则选中第一个
|
||||
const unsigned = storedAddItemBillList.find((item) => item.is_signed !== true);
|
||||
setCurrentAddItemBill(unsigned || storedAddItemBillList[0]);
|
||||
} else {
|
||||
// 没有加项单:不再主动调用接口获取,因为新接口需要 CombinationCode(仅支付时知道)
|
||||
setAddItemBillList([]);
|
||||
setCurrentAddItemBill(null);
|
||||
}
|
||||
}, [examId]);
|
||||
|
||||
// 加载 PDF 数据
|
||||
useEffect(() => {
|
||||
if (!previewPdf?.pdf_url) {
|
||||
@@ -1026,16 +976,6 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
setDaojiandanUrl(pdfUrlValue);
|
||||
setIsDaojiandanSigned(true); // 签名成功后标记为已签名
|
||||
|
||||
// 保存导检单PDF信息到localStorage(标记为已签名)
|
||||
setDaojiandanPdf(examId, {
|
||||
pdf_name: pdfNameValue,
|
||||
pdf_url: pdfUrlValue,
|
||||
is_signed: true,
|
||||
});
|
||||
|
||||
// 记录打印导检单是否签名操作
|
||||
setExamActionRecord(examId, 'printSign', true);
|
||||
|
||||
// 更新导检单打印状态
|
||||
try {
|
||||
await editDaojiandanPrintStatus({ exam_id: examId });
|
||||
@@ -1090,43 +1030,36 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
sign_file: blob,
|
||||
});
|
||||
|
||||
if (res.Status === 200 && res.Data?.pdf_url) {
|
||||
if (res.Status === 200) {
|
||||
setAddItemBillSubmitMessage('签名提交成功');
|
||||
const pdfUrlValue = res.Data.pdf_url;
|
||||
const pdfNameValue = res.Data.pdf_name || '加项单';
|
||||
// 更新当前加项单为已签名,并更新本地列表与 localStorage
|
||||
setAddItemBillList((prev) => {
|
||||
const next = prev.map((item) => {
|
||||
if (item.pdf_sort === currentAddItemBill.pdf_sort) {
|
||||
const updated: AddItemBillPdfInfo = {
|
||||
...item,
|
||||
pdf_name: pdfNameValue,
|
||||
pdf_url: pdfUrlValue,
|
||||
payment_status: res.Data?.payment_status ?? item.payment_status ?? null,
|
||||
payment_status_name: res.Data?.payment_status_name ?? item.payment_status_name ?? null,
|
||||
is_signed: true,
|
||||
};
|
||||
// 同步写入 localStorage
|
||||
setAddItemBillPdf(examId, updated);
|
||||
return updated;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return next;
|
||||
});
|
||||
|
||||
setCurrentAddItemBill((prev) =>
|
||||
prev && prev.pdf_sort === currentAddItemBill.pdf_sort
|
||||
? {
|
||||
...prev,
|
||||
pdf_name: pdfNameValue,
|
||||
pdf_url: pdfUrlValue,
|
||||
payment_status: res.Data?.payment_status ?? prev.payment_status ?? null,
|
||||
payment_status_name: res.Data?.payment_status_name ?? prev.payment_status_name ?? null,
|
||||
is_signed: true,
|
||||
// 签名成功后刷新统一 PDF 列表,获取最新的加项单签名状态和地址
|
||||
if (examId) {
|
||||
try {
|
||||
const refreshRes = await getTijianPdfFile({ exam_id: examId as number });
|
||||
const list: OutputTijianPdfFileInfo[] = refreshRes.Data || [];
|
||||
const addItemFromApi = list.filter((item) => item.pdf_type === 3);
|
||||
if (addItemFromApi.length > 0) {
|
||||
const addItemList: AddItemBillItem[] = addItemFromApi.map((item) => ({
|
||||
pdf_sort: item.combination_code ?? 0,
|
||||
combinationCode: String(item.combination_code ?? ''),
|
||||
payment_status: item.is_pay != null ? String(item.is_pay) : null,
|
||||
payment_status_name: item.is_pay_name ?? null,
|
||||
pdf_name: item.pdf_name || '加项单',
|
||||
pdf_url: item.sign_pdf_url || item.pdf_url || '',
|
||||
is_signed: item.is_sign === 1,
|
||||
}));
|
||||
setAddItemBillList(addItemList);
|
||||
const unsigned = addItemList.find((bill) => bill.is_signed !== true);
|
||||
setCurrentAddItemBill(unsigned || addItemList[0] || null);
|
||||
} else {
|
||||
setAddItemBillList([]);
|
||||
setCurrentAddItemBill(null);
|
||||
}
|
||||
: prev
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('刷新加项单列表失败', e);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
setShowAddItemBillSignature(false);
|
||||
@@ -1146,7 +1079,7 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
};
|
||||
|
||||
// 加项单直接打印
|
||||
const handleAddItemBillDirectPrint = async (target: AddItemBillPdfInfo | null) => {
|
||||
const handleAddItemBillDirectPrint = async (target: AddItemBillItem | null) => {
|
||||
if (!target?.pdf_url) return;
|
||||
|
||||
try {
|
||||
@@ -1443,23 +1376,7 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
for (const item of consentList) {
|
||||
if (item.combination_code === undefined || item.combination_code === null) continue;
|
||||
if (!signedCombinationCodes.includes(Number(item.combination_code))) continue;
|
||||
|
||||
let targetUrl = item.pdf_url;
|
||||
|
||||
// 如果本地已保存签名后的PDF列表,则优先使用签名后的PDF地址
|
||||
if (examId) {
|
||||
const storedList = getTongyishuPdfList(examId);
|
||||
if (storedList && item.combination_code !== undefined && item.combination_code !== null) {
|
||||
const code = Number(item.combination_code);
|
||||
const matched = storedList.find(
|
||||
(pdf) => pdf.combination_code !== null && Number(pdf.combination_code) === code,
|
||||
);
|
||||
if (matched && matched.pdf_url) {
|
||||
targetUrl = matched.pdf_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const targetUrl = item.pdf_url;
|
||||
if (!targetUrl) continue;
|
||||
|
||||
try {
|
||||
@@ -1769,24 +1686,7 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
className='py-1.5 px-3 bg-blue-600 hover:bg-blue-700 text-white'
|
||||
onClick={() => {
|
||||
if (busy) return;
|
||||
let target = item;
|
||||
// 如果本地已保存签名后的PDF列表,则优先使用签名后的PDF地址
|
||||
if (examId) {
|
||||
const storedList = getTongyishuPdfList(examId);
|
||||
if (storedList && item.combination_code !== undefined && item.combination_code !== null) {
|
||||
const code = Number(item.combination_code);
|
||||
const matched = storedList.find(
|
||||
(pdf) => pdf.combination_code !== null && Number(pdf.combination_code) === code,
|
||||
);
|
||||
if (matched && matched.pdf_url) {
|
||||
target = {
|
||||
...item,
|
||||
pdf_url: matched.pdf_url,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
handleDirectPrint(target);
|
||||
handleDirectPrint(item);
|
||||
}}
|
||||
disabled={busy}
|
||||
>
|
||||
@@ -1798,26 +1698,7 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
onClick={() => {
|
||||
if (busy) return;
|
||||
|
||||
let target = item;
|
||||
|
||||
// 如果本地已保存签名后的PDF列表,则优先使用签名后的PDF地址
|
||||
if (examId) {
|
||||
const storedList = getTongyishuPdfList(examId);
|
||||
if (storedList && item.combination_code !== undefined && item.combination_code !== null) {
|
||||
const code = Number(item.combination_code);
|
||||
const matched = storedList.find(
|
||||
(pdf) => pdf.combination_code !== null && Number(pdf.combination_code) === code,
|
||||
);
|
||||
if (matched && matched.pdf_url) {
|
||||
target = {
|
||||
...item,
|
||||
pdf_url: matched.pdf_url,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setPreviewPdf(target);
|
||||
setPreviewPdf(item);
|
||||
}}
|
||||
disabled={busy}
|
||||
>
|
||||
@@ -2128,6 +2009,17 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
>
|
||||
打印
|
||||
</Button>
|
||||
<Button
|
||||
className='py-1 px-3 hover:bg-blue-700 text-white'
|
||||
onClick={() => {
|
||||
if (busy) return;
|
||||
setShowDaojiandanPreview(false);
|
||||
setShowDaojiandanSignature(true);
|
||||
}}
|
||||
disabled={busy}
|
||||
>
|
||||
签名
|
||||
</Button>
|
||||
<Button className='py-1 px-3' onClick={() => !busy && setShowDaojiandanPreview(false)} disabled={busy}>
|
||||
关闭
|
||||
</Button>
|
||||
@@ -2217,19 +2109,17 @@ export const ExamSignPanel = ({ examId, onBusyChange }: ExamSignPanelProps) => {
|
||||
打印
|
||||
</Button>
|
||||
)}
|
||||
{!currentAddItemBill.is_signed && (
|
||||
<Button
|
||||
className='py-1 px-3 bg-blue-600 hover:bg-blue-700 text-white'
|
||||
onClick={() => {
|
||||
if (busy) return;
|
||||
setShowAddItemBillPreview(false);
|
||||
setShowAddItemBillSignature(true);
|
||||
}}
|
||||
disabled={busy}
|
||||
>
|
||||
签名
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
className='py-1 px-3 hover:bg-blue-700 text-white'
|
||||
onClick={() => {
|
||||
if (busy) return;
|
||||
setShowAddItemBillPreview(false);
|
||||
setShowAddItemBillSignature(true);
|
||||
}}
|
||||
disabled={busy}
|
||||
>
|
||||
签名
|
||||
</Button>
|
||||
<Button className='py-1 px-3' onClick={() => !busy && setShowAddItemBillPreview(false)} disabled={busy}>
|
||||
关闭
|
||||
</Button>
|
||||
|
||||
@@ -40,20 +40,9 @@ export interface ExamActionRecord {
|
||||
/**
|
||||
* 获取操作记录
|
||||
*/
|
||||
export const getExamActionRecord = (examId: string | number): ExamActionRecord | null => {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const key = getExamActionKey(examId);
|
||||
const raw = localStorage.getItem(key);
|
||||
if (!raw) return null;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return parsed as ExamActionRecord;
|
||||
} catch (err) {
|
||||
console.warn('操作记录解析失败', err);
|
||||
return null;
|
||||
}
|
||||
export const getExamActionRecord = (_examId: string | number): ExamActionRecord | null => {
|
||||
// 已废弃,不再从本地存储读取
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -64,223 +53,13 @@ export const setExamActionRecord = (
|
||||
action: keyof ExamActionRecord,
|
||||
value: boolean = true
|
||||
): void => {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const key = getExamActionKey(examId);
|
||||
const existing = getExamActionRecord(examId) || {};
|
||||
|
||||
const updated: ExamActionRecord = {
|
||||
...existing,
|
||||
[action]: value,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
localStorage.setItem(key, JSON.stringify(updated));
|
||||
// 已废弃,不再写入本地存储
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查操作是否已完成
|
||||
*/
|
||||
export const isExamActionDone = (examId: string | number, action: keyof ExamActionRecord): boolean => {
|
||||
const record = getExamActionRecord(examId);
|
||||
return record?.[action] === true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 知情同意书PDF信息
|
||||
*/
|
||||
export interface TongyishuPdfInfo {
|
||||
/** PDF文件名称 */
|
||||
pdf_name: string;
|
||||
/** PDF文件地址 */
|
||||
pdf_url: string;
|
||||
/** 组合代码 */
|
||||
combination_code?: number | null;
|
||||
/** 是否已签名 */
|
||||
is_signed?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取知情同意书PDF列表的存储 key
|
||||
*/
|
||||
export const getTongyishuPdfListKey = (examId: string | number): string => {
|
||||
const today = getTodayString();
|
||||
return `yh_tongyishu_pdf_list_${today}_${examId}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 存储知情同意书PDF列表
|
||||
*/
|
||||
export const setTongyishuPdfList = (
|
||||
examId: string | number,
|
||||
pdfList: TongyishuPdfInfo[]
|
||||
): void => {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const key = getTongyishuPdfListKey(examId);
|
||||
localStorage.setItem(key, JSON.stringify(pdfList));
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取知情同意书PDF列表
|
||||
*/
|
||||
export const getTongyishuPdfList = (examId: string | number): TongyishuPdfInfo[] | null => {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const key = getTongyishuPdfListKey(examId);
|
||||
const raw = localStorage.getItem(key);
|
||||
if (!raw) return null;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return Array.isArray(parsed) ? parsed as TongyishuPdfInfo[] : null;
|
||||
} catch (err) {
|
||||
console.warn('知情同意书PDF列表解析失败', err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 导检单PDF信息
|
||||
*/
|
||||
export interface DaojiandanPdfInfo {
|
||||
/** PDF文件名称 */
|
||||
pdf_name: string;
|
||||
/** PDF文件地址 */
|
||||
pdf_url: string;
|
||||
/** 是否已签名 */
|
||||
is_signed?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导检单PDF的存储 key
|
||||
*/
|
||||
export const getDaojiandanPdfKey = (examId: string | number): string => {
|
||||
const today = getTodayString();
|
||||
return `yh_daojiandan_pdf_${today}_${examId}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 存储导检单PDF信息
|
||||
*/
|
||||
export const setDaojiandanPdf = (
|
||||
examId: string | number,
|
||||
pdfInfo: DaojiandanPdfInfo
|
||||
): void => {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const key = getDaojiandanPdfKey(examId);
|
||||
localStorage.setItem(key, JSON.stringify(pdfInfo));
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取导检单PDF信息
|
||||
*/
|
||||
export const getDaojiandanPdf = (examId: string | number): DaojiandanPdfInfo | null => {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const key = getDaojiandanPdfKey(examId);
|
||||
const raw = localStorage.getItem(key);
|
||||
if (!raw) return null;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
return parsed as DaojiandanPdfInfo;
|
||||
} catch (err) {
|
||||
console.warn('导检单PDF信息解析失败', err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 加项单PDF信息
|
||||
*/
|
||||
export interface AddItemBillPdfInfo {
|
||||
/** 加项单编号(接口返回的 pdf_sort) */
|
||||
pdf_sort: number;
|
||||
/** 加项组合代码(多个加项项目,用逗号拼接,例如:123,456) */
|
||||
combinationCode: string;
|
||||
/** 支付状态 (1-未支付 2-已支付) */
|
||||
payment_status?: string | null;
|
||||
/** 支付状态名称 (1-未支付 2-已支付) */
|
||||
payment_status_name?: string | null;
|
||||
/** PDF文件名称 */
|
||||
pdf_name: string;
|
||||
/** PDF文件地址 */
|
||||
pdf_url: string;
|
||||
/** 是否已签名 */
|
||||
is_signed?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取加项单PDF的存储 key
|
||||
*/
|
||||
export const getAddItemBillPdfKey = (examId: string | number): string => {
|
||||
const today = getTodayString();
|
||||
return `yh_add_item_bill_pdf_${today}_${examId}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 存储加项单PDF信息
|
||||
*/
|
||||
export const setAddItemBillPdf = (
|
||||
examId: string | number,
|
||||
pdfInfo: AddItemBillPdfInfo
|
||||
): void => {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const key = getAddItemBillPdfKey(examId);
|
||||
const raw = localStorage.getItem(key);
|
||||
let list: AddItemBillPdfInfo[] = [];
|
||||
|
||||
if (raw) {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (Array.isArray(parsed)) {
|
||||
list = parsed as AddItemBillPdfInfo[];
|
||||
} else if (parsed && typeof parsed === 'object') {
|
||||
// 兼容旧版本(单个对象)
|
||||
list = [parsed as AddItemBillPdfInfo];
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('加项单PDF信息解析失败,将重置为新列表', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 根据 pdf_sort 去重:同一个 pdf_sort 覆盖旧数据
|
||||
const index = list.findIndex((item) => item.pdf_sort === pdfInfo.pdf_sort);
|
||||
if (index >= 0) {
|
||||
list[index] = pdfInfo;
|
||||
} else {
|
||||
list.push(pdfInfo);
|
||||
}
|
||||
|
||||
localStorage.setItem(key, JSON.stringify(list));
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取加项单PDF信息
|
||||
*/
|
||||
export const getAddItemBillPdf = (examId: string | number): AddItemBillPdfInfo[] | null => {
|
||||
if (typeof window === 'undefined') return null;
|
||||
|
||||
const key = getAddItemBillPdfKey(examId);
|
||||
const raw = localStorage.getItem(key);
|
||||
if (!raw) return null;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (Array.isArray(parsed)) {
|
||||
return parsed as AddItemBillPdfInfo[];
|
||||
}
|
||||
if (parsed && typeof parsed === 'object') {
|
||||
// 兼容旧版本(单个对象)
|
||||
return [parsed as AddItemBillPdfInfo];
|
||||
}
|
||||
return null;
|
||||
} catch (err) {
|
||||
console.warn('加项单PDF信息解析失败', err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// 已废弃,统一由实时数据决定
|
||||
return false;
|
||||
};
|
||||
Reference in New Issue
Block a user