inspect-front/public/templates/report-template.html
2025-03-17 14:54:53 +08:00

677 lines
21 KiB
HTML
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.

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>体检检查报告</title>
<!-- 添加PDF.js库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script>
<style>
.report-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.report-item {
margin-bottom: 40px;
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.report-title {
background-color: #4a90e2;
color: white;
padding: 15px;
font-size: 18px;
font-weight: bold;
border-bottom: 1px solid #e0e0e0;
}
.report-content {
padding: 20px;
text-align: center;
background-color: white;
}
.report-content img {
max-width: 100%;
height: auto;
}
.report-content iframe {
width: 100%;
height: 800px;
border: none;
}
.report-summary {
padding: 15px;
background-color: #f9f9f9;
border-top: 1px solid #e0e0e0;
}
/* 新增表格样式 */
.exam-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.exam-table th, .exam-table td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
.exam-table th {
background-color: #f5f5f5;
font-weight: bold;
}
.exam-table tr:nth-child(even) {
background-color: #fafafa;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
/* 默认隐藏打印占位符和打印专用内容 */
.print-placeholder {
display: none;
}
.print-only {
display: none;
}
.pdf-loading {
text-align: center;
padding: 20px;
font-style: italic;
color: #666;
}
.pdf-error {
color: red;
text-align: center;
padding: 20px;
border: 1px solid #ffcccc;
background-color: #fff8f8;
}
.pdf-page-info {
text-align: center;
font-size: 12px;
color: #666;
margin-top: 10px;
}
/* 加载动画 */
.loading-spinner {
width: 30px;
height: 30px;
border: 3px solid #f3f3f3;
border-top: 3px solid #3498db;
border-radius: 50%;
margin: 0 auto 10px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.pdf-image-container img {
max-width: 100%;
height: auto;
border: 1px solid #ddd;
margin: 10px 0;
}
/* 打印专用样式 - 完全重写 */
@media print {
body {
margin: 0;
padding: 0;
}
.report-container {
padding: 0;
max-width: none;
}
/* 一般检查特殊处理 */
.general-exam {
page-break-inside: avoid !important;
break-inside: avoid !important;
page-break-after: always !important;
break-after: page !important;
height: auto !important;
min-height: auto !important;
max-height: none !important;
margin: 0 !important;
padding: 0 !important;
border: none !important;
border-radius: 0 !important;
box-shadow: none !important;
display: block !important;
overflow: visible !important;
}
/* 一般检查的内容区域 */
.general-exam .report-content {
padding: 5px !important;
margin: 0 !important;
display: block !important;
overflow: visible !important;
height: auto !important;
}
/* 一般检查的表格 */
.general-exam .exam-table {
margin: 5px 0 !important;
font-size: 9px !important;
}
.general-exam .exam-table th,
.general-exam .exam-table td {
padding: 2px !important;
font-size: 9px !important;
}
/* 一般检查的小结 */
.general-exam .report-summary {
padding: 5px !important;
margin: 0 !important;
font-size: 9px !important;
}
.general-exam .report-summary h4 {
margin: 2px 0 !important;
font-size: 9px !important;
}
.general-exam .report-summary p {
margin: 2px 0 !important;
font-size: 9px !important;
}
/* 其他报告项目的样式 */
.report-item:not(.general-exam) {
page-break-after: always;
break-after: page;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
box-shadow: none;
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 最后一个报告不需要分页 */
.report-item:last-child {
page-break-after: auto;
break-after: auto;
}
/* 标题样式 */
h1 {
font-size: 18px;
margin: 10px 0;
}
.report-title {
padding: 8px 10px;
font-size: 16px;
background-color: #4a90e2 !important;
color: white !important;
}
/* 内容区域 */
.report-item:not(.general-exam) .report-content {
padding: 10px;
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
}
/* 表格样式 */
.report-item:not(.general-exam) .exam-table {
margin: 10px 0;
}
.report-item:not(.general-exam) .exam-table th,
.report-item:not(.general-exam) .exam-table td {
padding: 5px;
font-size: 11px;
}
/* 小结部分 */
.report-item:not(.general-exam) .report-summary {
padding: 8px;
font-size: 11px;
background-color: #f9f9f9 !important;
}
.report-item:not(.general-exam) .report-summary h4 {
margin: 3px 0;
}
.report-item:not(.general-exam) .report-summary p {
margin: 3px 0;
}
/* PDF图片容器 */
.pdf-image-container {
max-height: 500px;
overflow: hidden;
width: 100%;
text-align: center;
}
.pdf-image-container img {
max-width: 100%;
max-height: 480px;
object-fit: contain;
margin: 0 auto;
border: none;
}
.pdf-page-info {
font-size: 9px;
margin-top: 3px;
}
/* 隐藏屏幕元素 */
.screen-only {
display: none !important;
}
/* 显示打印元素 */
.print-only {
display: block !important;
}
/* 确保背景色和边框在打印时可见 */
.report-title,
.exam-table th,
.exam-table td,
.report-summary {
-webkit-print-color-adjust: exact !important;
color-adjust: exact !important;
print-color-adjust: exact !important;
}
/* 页面设置 */
@page {
margin: 0.5cm;
size: A4 portrait;
}
/* 超声检查报告的特殊样式 */
.ultrasound-exam .pdf-image-container {
max-height: 800px !important; /* 增加高度 */
}
.ultrasound-exam .pdf-image-container img {
max-width: 100% !important;
max-height: 880px !important; /* 增加高度 */
object-fit: contain !important;
}
/* 调整超声检查报告的内容区域 */
.ultrasound-exam .report-content {
padding: 5px !important;
}
/* 调整超声检查报告的小结部分 */
.ultrasound-exam .report-summary {
padding: 5px !important;
font-size: 10px !important;
}
.ultrasound-exam .report-summary p {
margin: 3px 0 !important;
font-size: 10px !important;
}
}
</style>
</head>
<body>
<div class="report-container">
<h1>体检报告 - </h1>
<!-- 一般检查部分 -->
<div class="report-item general-exam">
<div class="report-title">一般检查</div>
<div class="report-content">
<table class="exam-table">
<thead>
<tr>
<th>检查项目</th>
<th>检查结果</th>
</tr>
</thead>
<tbody>
<tr><td>体温</td><td>--</td></tr>
<tr><td>脉率</td><td>--</td></tr>
<tr><td>呼吸频率</td><td>--</td></tr>
<tr><td>血压</td><td>--</td></tr>
<tr><td>腰围</td><td>--</td></tr>
<tr><td>身高</td><td>--</td></tr>
<tr><td>体重</td><td>--</td></tr>
<tr><td>体质指数(BMI)</td><td>--</td></tr>
</tbody>
</table>
</div>
<div class="report-summary">
<h4>体检科小结:</h4>
<p>--</p>
</div>
</div>
<!-- 超声检查报告 -->
<div class="report-item ultrasound-exam">
<div class="report-title">超声检查报告</div>
<div class="report-content">
<!-- 屏幕查看时显示PDF -->
<div class="screen-only">
<iframe src=""></iframe>
</div>
<!-- 打印时显示渲染的PDF -->
<div class="print-only pdf-container" data-pdf-url="">
<div class="pdf-loading">正在准备PDF预览...</div>
<!-- 添加图片容器,用于存放渲染后的图片 -->
<div class="pdf-image-container" style="display:none;"></div>
</div>
</div>
<div class="report-summary">
<p><strong>【所见】</strong><br>--</p>
<p><strong>【所得】</strong><br>--</p>
</div>
</div>
<!-- 尿常规检查报告 -->
<div class="report-item">
<div class="report-title">尿常规检查报告</div>
<div class="report-content">
<!-- 屏幕查看时显示PDF -->
<div class="screen-only">
<iframe src=""></iframe>
</div>
<!-- 打印时显示渲染的PDF -->
<div class="print-only pdf-container" data-pdf-url="">
<div class="pdf-loading">正在准备PDF预览...</div>
<!-- 添加图片容器 -->
<div class="pdf-image-container" style="display:none;"></div>
</div>
</div>
<div class="report-summary">
<h4>检验科小结:</h4>
<p>--</p>
</div>
</div>
<!-- 生化检查报告 -->
<div class="report-item">
<div class="report-title">生化检查报告</div>
<div class="report-content">
<!-- 屏幕查看时显示PDF -->
<div class="screen-only">
<iframe src=""+#toolbar=0&navpanes=0&view=Fit></iframe>
</div>
<!-- 打印时显示渲染的PDF -->
<div class="print-only pdf-container" data-pdf-url="">
<div class="pdf-loading">正在准备PDF预览...</div>
<!-- 添加图片容器 -->
<div class="pdf-image-container" style="display:none;"></div>
</div>
</div>
<div class="report-summary">
<h4>检验科小结:</h4>
<p>--</p>
</div>
</div>
<!-- 血常规检查报告 -->
<div class="report-item">
<div class="report-title">血常规检查报告</div>
<div class="report-content">
<!-- 屏幕查看时显示PDF -->
<div class="screen-only">
<iframe src=""></iframe>
</div>
<!-- 打印时显示渲染的PDF -->
<div class="print-only pdf-container" data-pdf-url="">
<div class="pdf-loading">正在准备PDF预览...</div>
<!-- 添加图片容器 -->
<div class="pdf-image-container" style="display:none;"></div>
</div>
</div>
<div class="report-summary">
<h4>检验科小结:</h4>
<p>--</p>
</div>
</div>
<!-- 心电图检查报告 -->
<div class="report-item">
<div class="report-title">心电图检查报告</div>
<div class="report-content">
<img src="" alt="心电图检查">
</div>
<div class="report-summary">
<p><strong>【所见】</strong>
<br>--
</p>
<p><strong>【所得】</strong>
<br>--</p>
</div>
</div>
</div>
<!-- 添加PDF渲染脚本 -->
<script>
// 设置PDF.js worker
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js';
// 页面加载完成后立即开始预渲染所有PDF为图片
document.addEventListener('DOMContentLoaded', () => {
console.log('页面加载完成开始预渲染PDF为图片');
setTimeout(() => {
preRenderAllPDFs();
}, 1000);
});
// 预渲染所有PDF为图片
async function preRenderAllPDFs() {
const containers = document.querySelectorAll('.pdf-container');
for (const container of containers) {
const pdfUrl = container.getAttribute('data-pdf-url');
if (pdfUrl) {
try {
await renderPDFAsImage(pdfUrl, container);
} catch (error) {
console.error('预渲染PDF失败:', error);
showPDFError(container, pdfUrl);
}
}
}
console.log('所有PDF预渲染完成');
}
// 将PDF渲染为图片 - 完全重写
async function renderPDFAsImage(url, container) {
try {
console.log('开始渲染PDF为图片:', url);
const loadingElem = container.querySelector('.pdf-loading');
const imageContainer = container.querySelector('.pdf-image-container');
// 加载PDF
const loadingTask = pdfjsLib.getDocument({
url: url,
withCredentials: false,
cMapUrl: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/cmaps/',
cMapPacked: true
});
const pdf = await loadingTask.promise;
console.log('PDF加载成功, 页数:', pdf.numPages);
// 只渲染第一页
const page = await pdf.getPage(1);
// 检查是否为超声检查报告
let scale = 1.5;
// 查找最近的report-item父元素检查是否有ultrasound-exam类
const reportItem = container.closest('.report-item');
if (reportItem && reportItem.classList.contains('ultrasound-exam')) {
// 超声检查报告使用更大的缩放比例
scale = 3.0;
console.log('检测到超声检查报告,使用更大缩放比例:', scale);
}
const viewport = page.getViewport({ scale: scale });
// 创建canvas
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// 渲染PDF页面到canvas
const renderContext = {
canvasContext: context,
viewport: viewport
};
await page.render(renderContext).promise;
// 裁剪canvas - 移除底部多余空白
// 这里我们尝试自动检测内容区域,避免显示多余的空白
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// 从底部向上扫描,找到最后一行非空白像素
let bottomContentLine = canvas.height - 1;
let foundContent = false;
// 向上扫描最多200像素寻找内容
for (let y = canvas.height - 1; y > canvas.height - 200 && !foundContent; y--) {
for (let x = 0; x < canvas.width; x++) {
const idx = (y * canvas.width + x) * 4;
// 检查像素是否不是白色(简单判断)
if (data[idx] < 240 || data[idx + 1] < 240 || data[idx + 2] < 240) {
bottomContentLine = y + 20; // 添加一些边距
foundContent = true;
break;
}
}
}
// 创建新的canvas只包含内容部分
const newCanvas = document.createElement('canvas');
newCanvas.width = canvas.width;
newCanvas.height = Math.min(bottomContentLine + 1, canvas.height);
const newContext = newCanvas.getContext('2d');
// 将原canvas的内容复制到新canvas
newContext.drawImage(
canvas,
0, 0, canvas.width, newCanvas.height,
0, 0, newCanvas.width, newCanvas.height
);
// 将新canvas转换为图片
const imgData = newCanvas.toDataURL('image/png');
const img = document.createElement('img');
img.src = imgData;
img.alt = 'PDF预览';
// 添加页码信息
const pageInfo = document.createElement('p');
// pageInfo.textContent = `第1页共${pdf.numPages}页`;
// pageInfo.className = 'pdf-page-info';
// 清空并添加图片
imageContainer.innerHTML = '';
imageContainer.appendChild(img);
imageContainer.appendChild(pageInfo);
// 隐藏加载提示,显示图片
if (loadingElem) loadingElem.style.display = 'none';
imageContainer.style.display = 'block';
console.log('PDF渲染为图片完成');
return true;
} catch (error) {
console.error('渲染PDF为图片失败:', error);
throw error;
}
}
// 显示PDF错误信息
function showPDFError(container, url) {
const loadingElem = container.querySelector('.pdf-loading');
if (loadingElem) loadingElem.style.display = 'none';
const imageContainer = container.querySelector('.pdf-image-container');
imageContainer.innerHTML = `
<div class="pdf-error">
<p>无法加载PDF预览</p>
<p>请访问以下链接查看完整报告:</p>
<p>${url}</p>
</div>
`;
imageContainer.style.display = 'block';
}
// 打印前事件处理
window.addEventListener('beforeprint', () => {
console.log('打印前事件触发');
// 显示所有打印容器
document.querySelectorAll('.print-only').forEach(el => {
el.style.display = 'block';
});
// 检查是否所有PDF都已渲染为图片
const containers = document.querySelectorAll('.pdf-container');
let allRendered = true;
containers.forEach(container => {
const imageContainer = container.querySelector('.pdf-image-container');
if (imageContainer.style.display !== 'block') {
allRendered = false;
}
});
if (!allRendered) {
console.log('有PDF尚未渲染完成尝试再次渲染');
// 如果有未渲染完成的,尝试再次渲染
preRenderAllPDFs().catch(error => {
console.error('打印前渲染失败:', error);
});
} else {
console.log('所有PDF已渲染为图片可以直接打印');
}
});
</script>
</body>
</html>