支持获取pdf展示体检同意书

This commit is contained in:
xianyi
2025-11-24 11:17:10 +08:00
parent 88973906a4
commit 3c984f3b68
2 changed files with 117 additions and 56 deletions

1
src/assets/testPdfBase64 Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
import { pdfjs } from "react-pdf";
import "./UI7.css";
import "../../assets/css/basic.css";
import { useNavigate } from "react-router-dom";
@@ -7,7 +8,20 @@ import ConfirmButton from "../../components/ConfirmButton";
import DecorLine from "../../components/DecorLine";
import WaitButton from "../../components/WaitButton";
const UI6: React.FC = () => {
// @ts-ignore - Vite 会处理 ?raw 导入
import testPdfBase64Raw from "../../assets/testPdfBase64?raw";
const testPdfBase64 = testPdfBase64Raw.trim();
// 配置 PDF.js worker
const workerPath = new URL("pdf.worker.min.js", document.baseURI).href;
pdfjs.GlobalWorkerOptions.workerSrc = workerPath;
if (window.electronAPI) {
window.electronAPI.log("info", `[UI7] PDF Worker 路径: ${workerPath}`);
}
const UI7: React.FC = () => {
const navigate = useNavigate();
const [countdown, setCountdown] = useState(5);
const [showWaitButton, setShowWaitButton] = useState(true);
@@ -15,6 +29,95 @@ const UI6: React.FC = () => {
const [isDrawing, setIsDrawing] = useState(false);
const dprRef = useRef<number>(1);
const lastPointRef = useRef<{ x: number; y: number } | null>(null);
// PDF 文本提取相关状态
const [pdfText, setPdfText] = useState<string>("");
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string>("");
// 从 PDF 中提取文本
useEffect(() => {
const extractTextFromPdf = async () => {
try {
setLoading(true);
window.electronAPI?.log("info", "[UI7] 开始从 PDF 提取文本");
// 清理 base64 字符串(移除可能的换行和空格)
const cleanBase64 = testPdfBase64.replace(/\s/g, "");
window.electronAPI?.log("info", `[UI7] Base64 长度: ${cleanBase64.length}`);
// 将 base64 转换为 Uint8Array
const binaryString = atob(cleanBase64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
window.electronAPI?.log("info", `[UI7] 转换为 Uint8Array长度: ${bytes.length}`);
// 加载 PDF 文档(使用 Uint8Array
const loadingTask = pdfjs.getDocument({ data: bytes });
const pdf = await loadingTask.promise;
window.electronAPI?.log("info", `[UI7] PDF 加载成功,共 ${pdf.numPages}`);
// 提取所有页面的文本
let allText = "";
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
const page = await pdf.getPage(pageNum);
const textContent = await page.getTextContent();
// 将文本项合并为字符串,保留换行信息
let pageText = "";
let lastY = null;
for (let i = 0; i < textContent.items.length; i++) {
const item = textContent.items[i] as any;
const currentY = item.transform ? item.transform[5] : null; // Y 坐标
// 如果 Y 坐标变化较大(超过行高的一半),认为是新行
if (lastY !== null && currentY !== null && Math.abs(currentY - lastY) > 5) {
pageText += "\n";
}
pageText += item.str;
// 如果当前项后面有空格标记,添加空格
if (item.hasEOL) {
pageText += "\n";
} else if (i < textContent.items.length - 1) {
const nextItem = textContent.items[i + 1] as any;
const nextX = nextItem.transform ? nextItem.transform[4] : null;
const currentX = item.transform ? item.transform[4] : null;
const currentWidth = item.width || 0;
// 如果下一个文本项距离较远,添加空格
if (currentX !== null && nextX !== null && (nextX - (currentX + currentWidth)) > 2) {
pageText += " ";
}
}
lastY = currentY;
}
allText += pageText + "\n\n";
}
window.electronAPI?.log("info", `[UI7] PDF 文本提取完成,长度: ${allText.length}`);
setPdfText(allText.trim());
setLoading(false);
setError("");
} catch (err) {
const errorMsg = `PDF文本提取失败: ${err}`;
console.error(errorMsg);
window.electronAPI?.log("error", `[UI7] ${errorMsg}`);
setError("PDF 文本提取失败,请检查文件");
setLoading(false);
}
};
extractTextFromPdf();
}, []);
useEffect(() => {
if (countdown > 0) {
@@ -191,62 +294,19 @@ const UI6: React.FC = () => {
<div className="ui7-text-wrapper">
<div className="ui7-text-content">
<span className="paragraph_1">
<br />
<br />
<br />
<br />
<br />
<br />
1.
<br />
<br />
2.
<br />
<br />
3.
<br />
B超等项目需空腹8小时以上
<br />
4.
<br />
CT等
<br />
5.
<br />
<br />
<br />
<br />
<br />
<br />
1.
<br />
<br />
2.
<br />
<br />
3.
<br />
X射线CT
<br />
<br />
{loading && <div style={{ padding: "20px", textAlign: "center" }}>PDF文本提取中...</div>}
{error && <div style={{ padding: "20px", color: "red", textAlign: "center" }}>{error}</div>}
{!loading && !error && pdfText && (
<span className="paragraph_1">
{pdfText.split("\n").map((line, index) => (
<React.Fragment key={index}>
{line}
{index < pdfText.split("\n").length - 1 && <br />}
</React.Fragment>
))}
</span>
)}
</div>
</div>
<span className="ui7-text_4"></span>
@@ -282,4 +342,4 @@ const UI6: React.FC = () => {
);
};
export default UI6;
export default UI7;