shanghai_vue3/public/abpm-report-template.html
2025-07-16 16:53:38 +08:00

2405 lines
108 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>
<!-- 引入ECharts -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<script>
// 检查ECharts是否成功加载
window.addEventListener('load', function() {
if (typeof echarts !== 'undefined') {
console.log('ECharts已成功加载, 版本:', echarts.version);
} else {
console.error('ECharts加载失败');
// 尝试从备用CDN加载
var script = document.createElement('script');
script.src = 'https://unpkg.com/echarts@5.4.3/dist/echarts.min.js';
script.onload = function() {
console.log('从备用CDN加载ECharts成功');
};
script.onerror = function() {
console.error('备用CDN也无法加载ECharts');
};
document.head.appendChild(script);
}
});
</script>
<style>
body {
margin: 0;
padding: 0;
font-family: 'Microsoft YaHei', Arial, sans-serif;
background-color: #f5f5f5;
color: #000;
}
.report-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.report-page {
margin-bottom: 40px;
border: 1px solid #ccc;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 210mm;
height: 297mm;
margin: 0 auto 40px;
position: relative;
background: white;
padding: 20mm;
box-sizing: border-box;
}
.page-header {
text-align: center;
margin-bottom: 20px;
border-bottom: 2px solid #ccc;
padding-bottom: 15px;
}
.page-header h1 {
margin: 0;
font-size: 24px;
font-weight: bold;
color: #000;
}
.page-header .patient-info {
margin-top: 10px;
font-size: 14px;
color: #000;
}
.basic-info-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
margin-bottom: 20px;
font-size: 12px;
}
.info-item {
display: flex;
align-items: center;
}
.info-label {
font-weight: bold;
margin-right: 8px;
color: #000;
min-width: 60px;
}
.info-value {
color: #000;
}
.chart-container {
width: 100%;
height: 450px;
margin: 20px 0;
border: 1px solid #000;
}
.statistics-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
font-size: 11px;
}
.statistics-table th,
.statistics-table td {
border: 1px solid #ccc;
padding: 6px;
text-align: center;
}
.statistics-table th {
background-color: #f5f5f5;
font-weight: bold;
color: #000;
}
.analysis-content {
margin: 20px 0;
padding: 15px;
background-color: #fafafa;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 12px;
line-height: 1.6;
white-space: pre-line;
color: #000;
}
.detailed-stats-table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
font-size: 10px;
}
.detailed-stats-table th,
.detailed-stats-table td {
border: 1px solid #ccc;
padding: 4px;
text-align: center;
}
.detailed-stats-table th {
background-color: #f5f5f5;
font-weight: bold;
color: #000;
}
.chart-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
margin: 15px 0;
}
.chart-item {
text-align: center;
}
.chart-item .chart {
width: 100%;
height: 200px;
border: 1px solid #000;
}
.chart-item .chart-title {
font-size: 11px;
font-weight: bold;
margin: 5px 0;
color: #000;
}
.chart-item .chart-info {
font-size: 10px;
color: #000;
margin: 5px 0;
}
.scatter-chart-container {
display: grid;
grid-template-rows: 1fr 1fr;
gap: 15px;
margin: 20px 0;
height: calc(100% - 120px);
}
.scatter-chart-item {
text-align: center;
}
.scatter-chart-item .chart {
width: 100%;
height: 240px;
border: 1px solid #000;
}
.hourly-chart-container {
margin: 20px 0;
}
.hourly-chart-container .chart {
width: 100%;
height: 420px;
border: 1px solid #000;
}
.data-table-container {
max-height: calc(100vh - 200px);
overflow-y: auto;
margin: 20px 0;
height: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 11px;
}
.data-table th,
.data-table td {
border: 1px solid #000;
padding: 5px;
text-align: center;
}
.data-table th {
background-color: #f5f5f5;
font-weight: bold;
position: sticky;
top: 0;
color: #000;
}
.page-footer {
position: absolute;
bottom: 15mm;
left: 20mm;
right: 20mm;
text-align: center;
font-size: 10px;
color: #000;
border-top: 1px solid #ccc;
padding-top: 5px;
}
/* 打印样式 */
@media print {
body {
background-color: white;
}
.report-container {
padding: 0;
max-width: none;
}
.report-page {
page-break-after: always;
break-after: page;
margin: 0;
border: 1px solid #ccc;
border-radius: 0;
box-shadow: none;
width: 210mm;
height: 297mm;
padding: 20mm;
}
.report-page:last-child {
page-break-after: auto;
break-after: auto;
}
@page {
margin: 0;
size: A4 portrait;
}
}
/* 隐藏某些页面的样式 */
.page-hidden {
display: none;
}
/* 测量时间字体颜色为黑色 */
[id^="measurement-date"] {
color: #000 !important;
}
</style>
</head>
<body>
<div id="loading-mask" style="position: fixed; left: 0; top: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.85); z-index: 9999; display: flex; align-items: center; justify-content: center; font-size: 22px; color: #409eff; letter-spacing: 2px; transition: opacity 0.3s;">加载中...</div>
<div class="report-container">
<!-- 数据说明:系统可以处理只有白天数据的情况,夜间数据缺失时会显示"--"或相应提示 -->
<!-- 第1页基本信息和趋势图 -->
<div class="report-page" id="page-1">
<div class="page-header">
<h1>动态血压监测报告</h1>
</div>
<!-- 基本信息 -->
<div class="basic-info-grid">
<div class="info-item">
<span class="info-label">姓名:</span>
<span class="info-value" id="patient-name">--</span>
</div>
<div class="info-item">
<span class="info-label">性别:</span>
<span class="info-value" id="patient-gender">--</span>
</div>
<div class="info-item">
<span class="info-label">年龄:</span>
<span class="info-value" id="patient-age">--</span>
</div>
<div class="info-item">
<span class="info-label">机构:</span>
<span class="info-value" id="patient-org">--</span>
</div>
<div class="info-item">
<span class="info-label">设备:</span>
<span class="info-value" id="patient-device">--</span>
</div>
<div class="info-item">
<span class="info-label">开始时间:</span>
<span class="info-value" id="record-start-time">--</span>
</div>
<div class="info-item">
<span class="info-label">结束时间:</span>
<span class="info-value" id="record-end-time">--</span>
</div>
<div class="info-item">
<span class="info-label">监测时长:</span>
<span class="info-value" id="record-duration">--</span>
</div>
<div class="info-item">
<span class="info-label">成功次数:</span>
<span class="info-value" id="success-count">--</span>
</div>
<div class="info-item">
<span class="info-label">最高收缩压:</span>
<span class="info-value" id="max-systolic">--</span>
</div>
<div class="info-item">
<span class="info-label">最低收缩压:</span>
<span class="info-value" id="min-systolic">--</span>
</div>
<div class="info-item">
<span class="info-label">平均收缩压:</span>
<span class="info-value" id="avg-systolic">--</span>
</div>
<div class="info-item">
<span class="info-label">平均舒张压:</span>
<span class="info-value" id="avg-diastolic">--</span>
</div>
<div class="info-item">
<span class="info-label">血压变异:</span>
<span class="info-value" id="bp-variability">--</span>
</div>
<div class="info-item">
<span class="info-label">成功率:</span>
<span class="info-value" id="success-rate">--</span>
</div>
</div>
<!-- 血压趋势图 -->
<div class="chart-container">
<div id="trend-chart" style="width: 100%; height: 100%;"></div>
</div>
<!-- 统计表格 -->
<table class="statistics-table">
<thead>
<tr>
<th rowspan="2">时段</th>
<th colspan="2">平均血压 (mmHg)</th>
<th rowspan="2">平均心率</th>
<th colspan="2">血压负荷 (%)</th>
</tr>
<tr>
<th>收缩压</th>
<th>舒张压</th>
<th>收缩压</th>
<th>舒张压</th>
</tr>
</thead>
<tbody>
<tr>
<td>整天</td>
<td id="all-avg-systolic">--</td>
<td id="all-avg-diastolic">--</td>
<td id="all-avg-heartrate">--</td>
<td id="all-systolic-load">--</td>
<td id="all-diastolic-load">--</td>
</tr>
<tr>
<td>白天</td>
<td id="day-avg-systolic">--</td>
<td id="day-avg-diastolic">--</td>
<td id="day-avg-heartrate">--</td>
<td id="day-systolic-load">--</td>
<td id="day-diastolic-load">--</td>
</tr>
<tr>
<td>夜间</td>
<td id="night-avg-systolic">--</td>
<td id="night-avg-diastolic">--</td>
<td id="night-avg-heartrate">--</td>
<td id="night-systolic-load">--</td>
<td id="night-diastolic-load">--</td>
</tr>
</tbody>
</table>
<div class="page-footer">
第1页 | 动态血压监测报告
</div>
</div>
<!-- 第2页分析报告文字 -->
<div class="report-page" id="page-2">
<div class="page-header">
<h1>动态血压监测分析报告</h1>
</div>
<div class="analysis-content" id="analysis-text">
<!-- 分析内容将通过JavaScript填充 -->
暂无分析内容
</div>
<div style="margin-top: 40px;">
<div style="display: flex; justify-content: flex-end; align-items: center;">
<div style="text-align: right;">
<p><strong>报告医生:</strong>_________________</p>
<p><strong>报告日期:</strong><span id="report-date">--</span></p>
</div>
</div>
</div>
<div class="page-footer">
第2页 | 动态血压监测报告
</div>
</div>
<!-- 第3页统计图 -->
<div class="report-page" id="page-3">
<div class="page-header">
<h1>统计图</h1>
<div class="patient-info" style="display: flex; justify-content: space-between; align-items: center;">
<span style="text-align: left;">姓名:<span id="patient-name-3">患者姓名</span></span>
<span style="flex: 1;"></span>
<span style="text-align: right;">测量时间:<span id="measurement-date">--</span></span>
</div>
</div>
<!-- 全天统计 -->
<div style="margin-bottom: 10px; font-size: 12px; font-weight: bold;">
全天 时间:<span id="all-time-range">--</span> 共:<span id="all-duration">--</span> 有效数据:<span id="all-effective-count">--</span> 共:<span id="all-total-count">--</span>
</div>
<table class="detailed-stats-table">
<thead>
<tr>
<th style="width: 140px;">项目</th>
<th style="width: 80px;">平均</th>
<th style="width: 80px;">标准差</th>
<th style="width: 80px;">最大值</th>
<th style="width: 100px;">出现时间</th>
<th style="width: 80px;">最小值</th>
<th style="width: 100px;">出现时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>收缩压 (mmHg/kPa)</td>
<td id="stats-all-avg-systolic">--</td>
<td id="stats-all-std-systolic">--</td>
<td id="stats-all-max-systolic">--</td>
<td id="stats-all-max-systolic-time">--</td>
<td id="stats-all-min-systolic">--</td>
<td id="stats-all-min-systolic-time">--</td>
</tr>
<tr>
<td>舒张压 (mmHg/kPa)</td>
<td id="stats-all-avg-diastolic">--</td>
<td id="stats-all-std-diastolic">--</td>
<td id="stats-all-max-diastolic">--</td>
<td id="stats-all-max-diastolic-time">--</td>
<td id="stats-all-min-diastolic">--</td>
<td id="stats-all-min-diastolic-time">--</td>
</tr>
<tr>
<td>平均压 (mmHg/kPa)</td>
<td id="stats-all-avg-mean">--</td>
<td id="stats-all-std-mean">--</td>
<td id="stats-all-max-mean">--</td>
<td id="stats-all-max-mean-time">--</td>
<td id="stats-all-min-mean">--</td>
<td id="stats-all-min-mean-time">--</td>
</tr>
<tr>
<td>心率 (次/分)</td>
<td id="stats-all-avg-hr">--</td>
<td id="stats-all-std-hr">--</td>
<td id="stats-all-max-hr">--</td>
<td id="stats-all-max-hr-time">--</td>
<td id="stats-all-min-hr">--</td>
<td id="stats-all-min-hr-time">--</td>
</tr>
<tr>
<td>脉压 (mmHg/kPa)</td>
<td id="stats-all-avg-pulse">--</td>
<td id="stats-all-std-pulse">--</td>
<td id="stats-all-max-pulse">--</td>
<td id="stats-all-max-pulse-time">--</td>
<td id="stats-all-min-pulse">--</td>
<td id="stats-all-min-pulse-time">--</td>
</tr>
</tbody>
</table>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>夜间比白天下降率:</span>
<span>收缩压:<span id="all-night-drop-systolic"></span>
<span style="margin-left: 20px;">舒张压:<span id="all-night-drop-diastolic"></span>
</div>
</div>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>血压负荷:</span>
<span>收缩压:<span id="all-pressure-load-systolic"></span></span>
<span style="margin-left: 20px;">舒张压:<span id="all-pressure-load-diastolic"></span></span>
</div>
</div>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>血压变异系数:</span>
<span>收缩压:<span id="all-variability-systolic"></span></span>
<span style="margin-left: 20px;">舒张压:<span id="all-variability-diastolic"></span></span>
</div>
</div>
<div style="margin: 8px 0; font-size: 10px;">
<span>动脉硬化指数:--</span>
</div>
<!-- 白天统计 -->
<div style="margin: 15px 0 10px 0; font-size: 12px; font-weight: bold;">
白天 时间:<span id="day-time-range">--</span> 共:<span id="day-duration">--</span> 有效数据:<span id="day-effective-count">--</span> 共:<span id="day-total-count">--</span>
</div>
<table class="detailed-stats-table">
<thead>
<tr>
<th style="width: 140px;">项目</th>
<th style="width: 80px;">平均</th>
<th style="width: 80px;">标准差</th>
<th style="width: 80px;">最大值</th>
<th style="width: 100px;">出现时间</th>
<th style="width: 80px;">最小值</th>
<th style="width: 100px;">出现时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>收缩压 (mmHg/kPa)</td>
<td id="stats-day-avg-systolic">--</td>
<td id="stats-day-std-systolic">--</td>
<td id="stats-day-max-systolic">--</td>
<td id="stats-day-max-systolic-time">--</td>
<td id="stats-day-min-systolic">--</td>
<td id="stats-day-min-systolic-time">--</td>
</tr>
<tr>
<td>舒张压 (mmHg/kPa)</td>
<td id="stats-day-avg-diastolic">--</td>
<td id="stats-day-std-diastolic">--</td>
<td id="stats-day-max-diastolic">--</td>
<td id="stats-day-max-diastolic-time">--</td>
<td id="stats-day-min-diastolic">--</td>
<td id="stats-day-min-diastolic-time">--</td>
</tr>
<tr>
<td>平均压 (mmHg/kPa)</td>
<td id="stats-day-avg-mean">--</td>
<td id="stats-day-std-mean">--</td>
<td id="stats-day-max-mean">--</td>
<td id="stats-day-max-mean-time">--</td>
<td id="stats-day-min-mean">--</td>
<td id="stats-day-min-mean-time">--</td>
</tr>
<tr>
<td>心率 (次/分)</td>
<td id="stats-day-avg-hr">--</td>
<td id="stats-day-std-hr">--</td>
<td id="stats-day-max-hr">--</td>
<td id="stats-day-max-hr-time">--</td>
<td id="stats-day-min-hr">--</td>
<td id="stats-day-min-hr-time">--</td>
</tr>
<tr>
<td>脉压 (mmHg/kPa)</td>
<td id="stats-day-avg-pulse">--</td>
<td id="stats-day-std-pulse">--</td>
<td id="stats-day-max-pulse">--</td>
<td id="stats-day-max-pulse-time">--</td>
<td id="stats-day-min-pulse">--</td>
<td id="stats-day-min-pulse-time">--</td>
</tr>
</tbody>
</table>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>血压负荷:</span>
<span>收缩压:<span id="day-pressure-load-systolic">88.46%</span></span>
<span style="margin-left: 20px;">舒张压:<span id="day-pressure-load-diastolic">88.46%</span></span>
</div>
</div>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>血压变异系数:</span>
<span>收缩压:<span id="day-variability-systolic">9.99%</span></span>
<span style="margin-left: 20px;">舒张压:<span id="day-variability-diastolic">15.34%</span></span>
</div>
</div>
<!-- 夜间统计 -->
<div style="margin: 15px 0 10px 0; font-size: 12px; font-weight: bold;">
夜间 时间:<span id="night-time-range">--</span> 共:<span id="night-duration">--</span> 有效数据:<span id="night-effective-count">--</span> 共:<span id="night-total-count">--</span>
</div>
<table class="detailed-stats-table">
<thead>
<tr>
<th style="width: 140px;">项目</th>
<th style="width: 80px;">平均</th>
<th style="width: 80px;">标准差</th>
<th style="width: 80px;">最大值</th>
<th style="width: 100px;">出现时间</th>
<th style="width: 80px;">最小值</th>
<th style="width: 100px;">出现时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>收缩压 (mmHg/kPa)</td>
<td id="stats-night-avg-systolic">--</td>
<td id="stats-night-std-systolic">--</td>
<td id="stats-night-max-systolic">--</td>
<td id="stats-night-max-systolic-time">--</td>
<td id="stats-night-min-systolic">--</td>
<td id="stats-night-min-systolic-time">--</td>
</tr>
<tr>
<td>舒张压 (mmHg/kPa)</td>
<td id="stats-night-avg-diastolic">--</td>
<td id="stats-night-std-diastolic">--</td>
<td id="stats-night-max-diastolic">--</td>
<td id="stats-night-max-diastolic-time">--</td>
<td id="stats-night-min-diastolic">--</td>
<td id="stats-night-min-diastolic-time">--</td>
</tr>
<tr>
<td>平均压 (mmHg/kPa)</td>
<td id="stats-night-avg-mean">--</td>
<td id="stats-night-std-mean">--</td>
<td id="stats-night-max-mean">--</td>
<td id="stats-night-max-mean-time">--</td>
<td id="stats-night-min-mean">--</td>
<td id="stats-night-min-mean-time">--</td>
</tr>
<tr>
<td>心率 (次/分)</td>
<td id="stats-night-avg-hr">--</td>
<td id="stats-night-std-hr">--</td>
<td id="stats-night-max-hr">--</td>
<td id="stats-night-max-hr-time">--</td>
<td id="stats-night-min-hr">--</td>
<td id="stats-night-min-hr-time">--</td>
</tr>
<tr>
<td>脉压 (mmHg/kPa)</td>
<td id="stats-night-avg-pulse">--</td>
<td id="stats-night-std-pulse">--</td>
<td id="stats-night-max-pulse">--</td>
<td id="stats-night-max-pulse-time">--</td>
<td id="stats-night-min-pulse">--</td>
<td id="stats-night-min-pulse-time">--</td>
</tr>
</tbody>
</table>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>血压负荷:</span>
<span>收缩压:<span id="night-pressure-load-systolic">100%</span></span>
<span style="margin-left: 20px;">舒张压:<span id="night-pressure-load-diastolic">50.0%</span></span>
</div>
</div>
<div style="display: flex; justify-content: space-between; margin: 8px 0; font-size: 10px;">
<div>
<span>血压变异系数:</span>
<span>收缩压:<span id="night-variability-systolic">7.44%</span></span>
<span style="margin-left: 20px;">舒张压:<span id="night-variability-diastolic">8.67%</span></span>
</div>
</div>
<div class="page-footer">
第3页 | 动态血压监测报告
</div>
</div>
<!-- 第4页柱状图 -->
<div class="report-page" id="page-4">
<div class="page-header">
<h1>柱状图</h1>
<div class="patient-info" style="display: flex; justify-content: space-between; align-items: center;">
<span style="text-align: left;">姓名:<span id="patient-name-4">患者姓名</span></span>
<span style="flex: 1;"></span>
<span style="text-align: right;">测量时间:<span id="measurement-date-4">--</span></span>
</div>
</div>
<div class="chart-grid">
<div class="chart-item">
<div class="chart" id="histogram-systolic-all"></div>
<div class="chart-title">收缩压分布 - 全天</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-systolic-day"></div>
<div class="chart-title">收缩压分布 - 白天</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-systolic-night"></div>
<div class="chart-title">收缩压分布 - 夜间</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-diastolic-all"></div>
<div class="chart-title">舒张压分布 - 全天</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-diastolic-day"></div>
<div class="chart-title">舒张压分布 - 白天</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-diastolic-night"></div>
<div class="chart-title">舒张压分布 - 夜间</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-hr-all"></div>
<div class="chart-title">心率分布 - 全天</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-hr-day"></div>
<div class="chart-title">心率分布 - 白天</div>
</div>
<div class="chart-item">
<div class="chart" id="histogram-hr-night"></div>
<div class="chart-title">心率分布 - 夜间</div>
</div>
</div>
<div class="page-footer">
第4页 | 动态血压监测报告
</div>
</div>
<!-- 第5页饼图 -->
<div class="report-page" id="page-5">
<div class="page-header">
<h1>扇形图</h1>
<div class="patient-info" style="display: flex; justify-content: space-between; align-items: center;">
<span style="text-align: left;">姓名:<span id="patient-name-5">患者姓名</span></span>
<span style="flex: 1;"></span>
<span style="text-align: right;">测量时间:<span id="measurement-date-5">--</span></span>
</div>
</div>
<div class="chart-grid">
<div class="chart-item">
<div class="chart" id="pie-systolic-day"></div>
<div class="chart-title">收缩压 - 白天</div>
<div class="chart-info">
<div>最大值:<span id="pie-day-sys-max">--</span></div>
<div>最小值:<span id="pie-day-sys-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-systolic-night"></div>
<div class="chart-title">收缩压 - 夜间</div>
<div class="chart-info">
<div>最大值:<span id="pie-night-sys-max">--</span></div>
<div>最小值:<span id="pie-night-sys-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-systolic-all"></div>
<div class="chart-title">收缩压 - 全天</div>
<div class="chart-info">
<div>最大值:<span id="pie-all-sys-max">--</span></div>
<div>最小值:<span id="pie-all-sys-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-diastolic-day"></div>
<div class="chart-title">舒张压 - 白天</div>
<div class="chart-info">
<div>最大值:<span id="pie-day-dia-max">--</span></div>
<div>最小值:<span id="pie-day-dia-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-diastolic-night"></div>
<div class="chart-title">舒张压 - 夜间</div>
<div class="chart-info">
<div>最大值:<span id="pie-night-dia-max">--</span></div>
<div>最小值:<span id="pie-night-dia-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-diastolic-all"></div>
<div class="chart-title">舒张压 - 全天</div>
<div class="chart-info">
<div>最大值:<span id="pie-all-dia-max">--</span></div>
<div>最小值:<span id="pie-all-dia-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-hr-day"></div>
<div class="chart-title">心率 - 白天</div>
<div class="chart-info">
<div>最大值:<span id="pie-day-hr-max">--</span></div>
<div>最小值:<span id="pie-day-hr-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-hr-night"></div>
<div class="chart-title">心率 - 夜间</div>
<div class="chart-info">
<div>最大值:<span id="pie-night-hr-max">--</span></div>
<div>最小值:<span id="pie-night-hr-min">--</span></div>
</div>
</div>
<div class="chart-item">
<div class="chart" id="pie-hr-all"></div>
<div class="chart-title">心率 - 全天</div>
<div class="chart-info">
<div>最大值:<span id="pie-all-hr-max">--</span></div>
<div>最小值:<span id="pie-all-hr-min">--</span></div>
</div>
</div>
</div>
<div class="page-footer">
第5页 | 动态血压监测报告
</div>
</div>
<!-- 第6页拟合图 -->
<div class="report-page" id="page-6">
<div class="page-header">
<h1>拟合图</h1>
<div class="patient-info" style="display: flex; justify-content: space-between; align-items: center;">
<span style="text-align: left;">姓名:<span id="patient-name-6">患者姓名</span></span>
<span style="flex: 1;"></span>
<span style="text-align: right;">测量时间:<span id="measurement-date-6">--</span></span>
</div>
</div>
<div class="scatter-chart-container">
<div class="scatter-chart-item">
<div class="chart-title">收缩压与舒张压关系</div>
<div class="chart" id="scatter-bp-relation"></div>
</div>
<div class="scatter-chart-item">
<div class="chart-title">心率与收缩压关系</div>
<div class="chart" id="scatter-hr-relation"></div>
</div>
</div>
<div class="page-footer">
第6页 | 动态血压监测报告
</div>
</div>
<!-- 第7页小时平均图 -->
<div class="report-page" id="page-7">
<div class="page-header">
<h1>平均血压趋势</h1>
<div class="patient-info" style="display: flex; justify-content: space-between; align-items: center;">
<span style="text-align: left;">姓名:<span id="patient-name-7">患者姓名</span></span>
<span style="flex: 1;"></span>
<span style="text-align: right;">测量时间:<span id="measurement-date-7">--</span></span>
</div>
</div>
<div class="hourly-chart-container">
<div class="chart-title" style="text-align: center; margin-bottom: 10px;">血压和心率平均值趋势图</div>
<div class="chart" id="hourly-average-chart"></div>
</div>
<div class="page-footer">
第7页 | 动态血压监测报告
</div>
</div>
<!-- 第8页患者数据表 -->
<div class="report-page" id="page-8">
<div class="page-header">
<h1>详细测量数据表</h1>
<div class="patient-info" style="display: flex; justify-content: space-between; align-items: center;">
<span style="text-align: left;">姓名:<span id="patient-name-8">患者姓名</span></span>
<span style="flex: 1;"></span>
<span style="text-align: right;">测量时间:<span id="measurement-date-8">--</span></span>
</div>
</div>
<div class="data-table-container">
<table class="data-table" id="patient-data-table">
<thead>
<tr>
<th>序号</th>
<th>日期</th>
<th>时间</th>
<th>收缩压</th>
<th>舒张压</th>
<th>心率</th>
<th>平均压</th>
<th>血压等级</th>
</tr>
</thead>
<tbody id="patient-data-tbody">
<!-- 数据行将通过JavaScript生成 -->
</tbody>
</table>
</div>
<div class="page-footer">
第8页 | 动态血压监测报告
</div>
</div>
</div>
<script>
// 全局变量
let patientData = {};
let chartDataTable = [];
let analysisResult = '';
// 数据验证函数
function validateData(data) {
showDebugInfo('开始数据验证');
if (!data) {
showDebugInfo('验证失败:数据为空');
return false;
}
if (!data.patientData) {
showDebugInfo('验证失败:缺少患者数据');
return false;
}
if (!data.chartDataTable || !Array.isArray(data.chartDataTable)) {
showDebugInfo('验证失败:图表数据不是数组');
return false;
}
// 检查必要的患者信息字段
const requiredFields = ['name', 'gender', 'age'];
for (const field of requiredFields) {
if (!data.patientData[field]) {
showDebugInfo(`验证警告:缺少患者字段 ${field}`);
}
}
// 检查图表数据结构
if (data.chartDataTable.length > 0) {
const firstItem = data.chartDataTable[0];
const requiredChartFields = ['systolic', 'diastolic', 'heartRate'];
for (const field of requiredChartFields) {
if (typeof firstItem[field] === 'undefined') {
showDebugInfo(`验证警告:图表数据缺少字段 ${field}`);
}
}
}
showDebugInfo('数据验证通过');
return true;
}
// 初始化报告数据
function initializeReport(data) {
hideLoading(); // 数据渲染完成后隐藏loading
showDebugInfo('开始初始化报告数据');
console.log('开始初始化报告数据:', data);
if (!data) {
showDebugInfo('错误:未收到有效数据');
console.error('未收到有效数据');
return;
}
// 详细检查数据结构
// 数据验证
if (!validateData(data)) {
showDebugInfo('数据验证失败,停止初始化');
return;
}
showDebugInfo('数据类型检查 - data类型: ' + typeof data);
showDebugInfo('patientData存在: ' + (data.patientData ? '是' : '否'));
showDebugInfo('chartDataTable存在: ' + (data.chartDataTable ? '是' : '否'));
showDebugInfo('analysisResult存在: ' + (data.analysisResult ? '是' : '否'));
patientData = data.patientData || {};
chartDataTable = data.chartDataTable || [];
analysisResult = data.analysisResult || '';
showDebugInfo('患者姓名: ' + (patientData.name || '空'));
showDebugInfo('图表数据条数: ' + chartDataTable.length);
showDebugInfo('分析结果: ' + (analysisResult ? '有内容' : '空'));
console.log('解析后的数据:', {
patientData: patientData,
chartDataCount: chartDataTable.length,
analysisResult: analysisResult
});
// 检查ECharts是否加载
if (typeof echarts === 'undefined') {
console.error('ECharts库未加载');
return;
} else {
console.log('ECharts库已加载');
}
try {
// 填充基本信息
console.log('填充基本信息...');
fillBasicInfo();
// 填充分析内容
console.log('填充分析内容...');
fillAnalysisContent();
// 填充统计数据
console.log('填充统计数据...');
console.log('当前chartDataTable数据样本:', chartDataTable.slice(0, 3));
fillStatisticsData();
// 渲染图表
console.log('渲染图表...');
renderAllCharts();
// 填充数据表
console.log('填充数据表...');
fillDataTable();
console.log('所有数据初始化完成');
} catch (error) {
console.error('初始化过程中出错:', error);
}
}
// 填充基本信息
function fillBasicInfo() {
console.log('开始填充基本信息,患者数据:', patientData);
// 患者基本信息
const nameElements = document.querySelectorAll('[id^="patient-name"]');
console.log('找到姓名元素数量:', nameElements.length);
nameElements.forEach(el => {
el.textContent = patientData.name || '--';
console.log('设置姓名:', patientData.name);
});
// 安全获取元素并设置内容
const setElementText = (id, value) => {
const element = document.getElementById(id);
if (element) {
const safeValue = (value == null || value === undefined || value === 'undefined' ||
(typeof value === 'number' && isNaN(value)) ||
(typeof value === 'string' && (value.includes('undefined') || value.includes('NaN'))))
? '--' : value;
element.textContent = safeValue;
console.log(`设置 ${id}:`, safeValue);
} else {
console.warn(`未找到元素: ${id}`);
}
};
setElementText('patient-gender', patientData.gender);
setElementText('patient-age', patientData.age);
setElementText('patient-org', patientData.orgname);
setElementText('patient-device', patientData.device);
setElementText('record-start-time', patientData.recordStartTime);
setElementText('record-end-time', patientData.recordEndTime);
setElementText('record-duration', patientData.recordDuration);
setElementText('success-count', patientData.successReadCount);
setElementText('success-rate', patientData.successReadPercent);
// 血压统计
document.getElementById('max-systolic').textContent = patientData.maxSystolic ?
`${patientData.maxSystolic} mmHg (${patientData.maxSystolicTime})` : '--';
document.getElementById('min-systolic').textContent = patientData.minSystolic ?
`${patientData.minSystolic} mmHg (${patientData.minSystolicTime})` : '--';
document.getElementById('avg-systolic').textContent = patientData.avgSystolic ?
`${patientData.avgSystolic} mmHg` : '--';
document.getElementById('avg-diastolic').textContent = patientData.avgDiastolic ?
`${patientData.avgDiastolic} mmHg` : '--';
document.getElementById('bp-variability').textContent =
`收缩压: ${patientData.systolicVariability || '--'}, 舒张压: ${patientData.diastolicVariability || '--'}`;
// 设置测量日期
const measurementDate = patientData.wearTime ?
new Date(patientData.wearTime).toLocaleDateString('zh-CN') : '--';
const measurementDateElements = document.querySelectorAll('[id^="measurement-date"]');
measurementDateElements.forEach(el => {
el.textContent = measurementDate;
});
// 设置报告日期
document.getElementById('report-date').textContent = new Date().toLocaleDateString('zh-CN');
}
// 填充分析内容
function fillAnalysisContent() {
document.getElementById('analysis-text').textContent = analysisResult || '暂无分析内容';
}
// 填充统计数据
function fillStatisticsData() {
console.log('开始填充统计数据chartDataTable长度:', chartDataTable ? chartDataTable.length : 'null');
if (!chartDataTable || chartDataTable.length === 0) {
console.warn('没有图表数据,显示默认值');
// 显示默认值而不是直接返回
showDefaultStats();
return;
}
// 计算统计数据
const stats = calculateStatistics(chartDataTable);
console.log('计算得到的统计数据:', stats);
// 填充汇总表格
document.getElementById('all-avg-systolic').textContent = stats.all.avgSystolic || '--';
document.getElementById('all-avg-diastolic').textContent = stats.all.avgDiastolic || '--';
document.getElementById('all-avg-heartrate').textContent = stats.all.avgHeartRate || '--';
document.getElementById('all-systolic-load').textContent = stats.all.systolicLoad?.toFixed(1) || '--';
document.getElementById('all-diastolic-load').textContent = stats.all.diastolicLoad?.toFixed(1) || '--';
document.getElementById('day-avg-systolic').textContent = stats.day.avgSystolic || '--';
document.getElementById('day-avg-diastolic').textContent = stats.day.avgDiastolic || '--';
document.getElementById('day-avg-heartrate').textContent = stats.day.avgHeartRate || '--';
document.getElementById('day-systolic-load').textContent = stats.day.systolicLoad?.toFixed(1) || '--';
document.getElementById('day-diastolic-load').textContent = stats.day.diastolicLoad?.toFixed(1) || '--';
document.getElementById('night-avg-systolic').textContent = stats.night.avgSystolic || '--';
document.getElementById('night-avg-diastolic').textContent = stats.night.avgDiastolic || '--';
document.getElementById('night-avg-heartrate').textContent = stats.night.avgHeartRate || '--';
document.getElementById('night-systolic-load').textContent = stats.night.systolicLoad?.toFixed(1) || '--';
document.getElementById('night-diastolic-load').textContent = stats.night.diastolicLoad?.toFixed(1) || '--';
// 填充详细统计表格
fillDetailedStats(stats);
}
// 显示默认统计数据(当没有数据时)
function showDefaultStats() {
console.log('显示默认统计数据');
// 填充汇总表格的默认值
document.getElementById('all-avg-systolic').textContent = '--';
document.getElementById('all-avg-diastolic').textContent = '--';
document.getElementById('all-avg-heartrate').textContent = '--';
document.getElementById('all-systolic-load').textContent = '--';
document.getElementById('all-diastolic-load').textContent = '--';
document.getElementById('day-avg-systolic').textContent = '--';
document.getElementById('day-avg-diastolic').textContent = '--';
document.getElementById('day-avg-heartrate').textContent = '--';
document.getElementById('day-systolic-load').textContent = '--';
document.getElementById('day-diastolic-load').textContent = '--';
document.getElementById('night-avg-systolic').textContent = '--';
document.getElementById('night-avg-diastolic').textContent = '--';
document.getElementById('night-avg-heartrate').textContent = '--';
document.getElementById('night-systolic-load').textContent = '--';
document.getElementById('night-diastolic-load').textContent = '--';
// 填充详细统计表格的默认值
fillDefaultDetailedStats();
}
// 填充默认的详细统计数据
function fillDefaultDetailedStats() {
const periods = ['all', 'day', 'night'];
const fields = ['systolic', 'diastolic', 'hr', 'mean', 'pulse'];
const stats = ['avg', 'std', 'max', 'min'];
const times = ['max-systolic-time', 'min-systolic-time', 'max-diastolic-time', 'min-diastolic-time',
'max-hr-time', 'min-hr-time', 'max-mean-time', 'min-mean-time', 'max-pulse-time', 'min-pulse-time'];
periods.forEach(period => {
// 统计头部信息
const safeSetText = (id, value) => {
const element = document.getElementById(id);
if (element) element.textContent = value;
};
safeSetText(`${period}-time-range`, '--');
safeSetText(`${period}-duration`, '--');
safeSetText(`${period}-effective-count`, '0');
safeSetText(`${period}-total-count`, '0');
// 统计数据
fields.forEach(field => {
stats.forEach(stat => {
safeSetText(`stats-${period}-${stat}-${field}`, '--');
});
});
// 时间数据
times.forEach(timeField => {
safeSetText(`stats-${period}-${timeField}`, '--');
});
// 血压负荷和变异系数
safeSetText(`${period}-pressure-load-systolic`, '--');
safeSetText(`${period}-pressure-load-diastolic`, '--');
safeSetText(`${period}-variability-systolic`, '--');
safeSetText(`${period}-variability-diastolic`, '--');
});
// 夜间下降率
const safeSetText = (id, value) => {
const element = document.getElementById(id);
if (element) element.textContent = value;
};
safeSetText('all-night-drop-systolic', '--');
safeSetText('all-night-drop-diastolic', '--');
safeSetText('all-minimum-index', '--');
}
// 填充默认时段统计数据
function fillDefaultPeriodStats(prefix) {
const fields = ['systolic', 'diastolic', 'hr', 'mean', 'pulse'];
const stats = ['avg', 'std', 'max', 'min'];
const times = ['max-systolic-time', 'min-systolic-time', 'max-diastolic-time', 'min-diastolic-time',
'max-hr-time', 'min-hr-time', 'max-mean-time', 'min-mean-time', 'max-pulse-time', 'min-pulse-time'];
const safeSetText = (id, value) => {
const element = document.getElementById(id);
if (element) element.textContent = value;
};
// 统计数据
fields.forEach(field => {
stats.forEach(stat => {
safeSetText(`${prefix}-${stat}-${field}`, '--');
});
});
// 时间数据
times.forEach(timeField => {
safeSetText(`${prefix}-${timeField}`, '--');
});
}
// 计算统计数据
function calculateStatistics(data) {
const daytimeData = data.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour >= 6 && hour < 22;
});
const nighttimeData = data.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour < 6 || hour >= 22;
});
const calculatePeriodStats = (periodData, periodType) => {
console.log(`计算${periodType}时段统计,数据长度:`, periodData.length);
if (periodData.length === 0) {
console.warn(`${periodType}时段没有数据,将显示默认值`);
return {
avgSystolic: undefined,
avgDiastolic: undefined,
avgHeartRate: undefined,
maxSystolic: undefined,
minSystolic: undefined,
maxDiastolic: undefined,
minDiastolic: undefined,
maxHeartRate: undefined,
minHeartRate: undefined,
systolicLoad: undefined,
diastolicLoad: undefined,
hasData: false // 标记是否有数据
};
}
const systolicValues = periodData.map(d => d.systolic).filter(v => v != null && !isNaN(v));
const diastolicValues = periodData.map(d => d.diastolic).filter(v => v != null && !isNaN(v));
const heartRateValues = periodData.map(d => d.heartRate).filter(v => v != null && !isNaN(v));
const avg = (arr) => arr.length > 0 ? Math.round(arr.reduce((a, b) => a + b, 0) / arr.length) : undefined;
const max = (arr) => arr.length > 0 ? Math.max(...arr) : undefined;
const min = (arr) => arr.length > 0 ? Math.min(...arr) : undefined;
// 根据时段类型设置阈值
let systolicThreshold, diastolicThreshold;
if (periodType === 'day') {
systolicThreshold = 135;
diastolicThreshold = 85;
} else if (periodType === 'night') {
systolicThreshold = 120;
diastolicThreshold = 70;
} else { // all
systolicThreshold = 140;
diastolicThreshold = 90;
}
return {
avgSystolic: avg(systolicValues),
avgDiastolic: avg(diastolicValues),
avgHeartRate: avg(heartRateValues),
maxSystolic: max(systolicValues),
minSystolic: min(systolicValues),
maxDiastolic: max(diastolicValues),
minDiastolic: min(diastolicValues),
maxHeartRate: max(heartRateValues),
minHeartRate: min(heartRateValues),
systolicLoad: systolicValues.length > 0 ? (systolicValues.filter(v => v >= systolicThreshold).length / systolicValues.length) * 100 : undefined,
diastolicLoad: diastolicValues.length > 0 ? (diastolicValues.filter(v => v >= diastolicThreshold).length / diastolicValues.length) * 100 : undefined,
hasData: true // 标记有数据
};
};
return {
all: calculatePeriodStats(data, 'all'),
day: calculatePeriodStats(daytimeData, 'day'),
night: calculatePeriodStats(nighttimeData, 'night')
};
}
// 填充详细统计数据
function fillDetailedStats(stats) {
// 计算标准差的辅助函数
const calculateStd = (values, avg) => {
if (!values || values.length === 0 || !avg || isNaN(avg)) return '--';
const variance = values.reduce((sum, val) => sum + Math.pow(val - avg, 2), 0) / values.length;
const result = Math.sqrt(variance);
return isNaN(result) ? '--' : result.toFixed(1);
};
// 格式化时间的辅助函数
const formatTime = (data, field, isMax) => {
if (!data || data.length === 0) return '--';
const values = data.map(d => d[field]).filter(v => v != null && !isNaN(v));
if (values.length === 0) return '--';
const targetValue = isMax ? Math.max(...values) : Math.min(...values);
const item = data.find(d => d[field] === targetValue);
if (!item) return '--';
return new Date(item.originalTime).toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
};
// 格式化数值显示包含kPa单位
const formatWithKPa = (mmHgValue) => {
if (mmHgValue == null || isNaN(mmHgValue) || mmHgValue === undefined) return '--';
const kPaValue = (mmHgValue / 7.5).toFixed(1);
return `${mmHgValue}/${kPaValue}`;
};
// 填充各时段的统计数据
const fillPeriodStats = (periodData, stats, prefix) => {
console.log(`填充${prefix}统计数据,数据长度:`, periodData ? periodData.length : 'null', '统计对象:', stats);
// 改进数据检查逻辑,允许部分数据缺失
if (!periodData) {
console.warn(`${prefix}时段数据为空`);
fillDefaultPeriodStats(prefix);
return;
}
if (!stats || Object.values(stats).every(v => v === undefined)) {
console.warn(`${prefix}统计数据为空或全部undefined`);
fillDefaultPeriodStats(prefix);
return;
}
const systolicValues = periodData.map(d => d.systolic).filter(v => v != null && !isNaN(v));
const diastolicValues = periodData.map(d => d.diastolic).filter(v => v != null && !isNaN(v));
const heartRateValues = periodData.map(d => d.heartRate).filter(v => v != null && !isNaN(v));
const meanPressureValues = periodData.map(d => Math.round((d.systolic + 2 * d.diastolic) / 3)).filter(v => v != null && !isNaN(v));
const pulsePressureValues = periodData.map(d => d.systolic - d.diastolic).filter(v => v != null && !isNaN(v));
// 平均值
const setElementText = (id, value) => {
const element = document.getElementById(id);
if (element) {
const safeValue = (value == null || value === undefined || value === 'undefined' ||
(typeof value === 'number' && isNaN(value)) ||
(typeof value === 'string' && (value.includes('undefined') || value.includes('NaN'))))
? '--' : value;
element.textContent = safeValue;
}
};
setElementText(`${prefix}-avg-systolic`, formatWithKPa(stats.avgSystolic));
setElementText(`${prefix}-avg-diastolic`, formatWithKPa(stats.avgDiastolic));
setElementText(`${prefix}-avg-hr`, stats.avgHeartRate || '--');
setElementText(`${prefix}-avg-mean`, formatWithKPa(Math.round((stats.avgSystolic + 2 * stats.avgDiastolic) / 3)));
setElementText(`${prefix}-avg-pulse`, formatWithKPa(stats.avgSystolic - stats.avgDiastolic));
// 标准差
setElementText(`${prefix}-std-systolic`, calculateStd(systolicValues, stats.avgSystolic));
setElementText(`${prefix}-std-diastolic`, calculateStd(diastolicValues, stats.avgDiastolic));
setElementText(`${prefix}-std-hr`, calculateStd(heartRateValues, stats.avgHeartRate));
setElementText(`${prefix}-std-mean`, calculateStd(meanPressureValues, (stats.avgSystolic + 2 * stats.avgDiastolic) / 3));
setElementText(`${prefix}-std-pulse`, calculateStd(pulsePressureValues, stats.avgSystolic - stats.avgDiastolic));
// 最大值
setElementText(`${prefix}-max-systolic`, formatWithKPa(stats.maxSystolic));
setElementText(`${prefix}-max-diastolic`, formatWithKPa(stats.maxDiastolic));
setElementText(`${prefix}-max-hr`, stats.maxHeartRate || '--');
setElementText(`${prefix}-max-mean`, meanPressureValues.length > 0 ? formatWithKPa(Math.max(...meanPressureValues)) : '--');
setElementText(`${prefix}-max-pulse`, pulsePressureValues.length > 0 ? formatWithKPa(Math.max(...pulsePressureValues)) : '--');
// 最小值
setElementText(`${prefix}-min-systolic`, formatWithKPa(stats.minSystolic));
setElementText(`${prefix}-min-diastolic`, formatWithKPa(stats.minDiastolic));
setElementText(`${prefix}-min-hr`, stats.minHeartRate || '--');
setElementText(`${prefix}-min-mean`, meanPressureValues.length > 0 ? formatWithKPa(Math.min(...meanPressureValues)) : '--');
setElementText(`${prefix}-min-pulse`, pulsePressureValues.length > 0 ? formatWithKPa(Math.min(...pulsePressureValues)) : '--');
// 时间
setElementText(`${prefix}-max-systolic-time`, formatTime(periodData, 'systolic', true));
setElementText(`${prefix}-min-systolic-time`, formatTime(periodData, 'systolic', false));
setElementText(`${prefix}-max-diastolic-time`, formatTime(periodData, 'diastolic', true));
setElementText(`${prefix}-min-diastolic-time`, formatTime(periodData, 'diastolic', false));
setElementText(`${prefix}-max-hr-time`, formatTime(periodData, 'heartRate', true));
setElementText(`${prefix}-min-hr-time`, formatTime(periodData, 'heartRate', false));
setElementText(`${prefix}-max-mean-time`, formatTime(periodData, 'heartRate', true)); // 简化处理
setElementText(`${prefix}-min-mean-time`, formatTime(periodData, 'heartRate', false)); // 简化处理
setElementText(`${prefix}-max-pulse-time`, formatTime(periodData, 'systolic', true)); // 简化处理
setElementText(`${prefix}-min-pulse-time`, formatTime(periodData, 'systolic', false)); // 简化处理
};
// 获取各时段数据
const daytimeData = getDaytimeData();
const nighttimeData = getNighttimeData();
// 填充三个时段的数据
fillPeriodStats(chartDataTable, stats.all, 'stats-all');
fillPeriodStats(daytimeData, stats.day, 'stats-day');
fillPeriodStats(nighttimeData, stats.night, 'stats-night');
// ====== 新增:动态填充统计区间、时长、有效数、总数 ======
// 全天
fillStatsHeader(chartDataTable, 'all');
// 白天
fillStatsHeader(daytimeData, 'day');
// 夜间
fillStatsHeader(nighttimeData, 'night');
// ====== 新增:动态填充血压负荷和变异系数 ======
fillAdditionalStats(chartDataTable, stats.all, 'all');
fillAdditionalStats(daytimeData, stats.day, 'day');
fillAdditionalStats(nighttimeData, stats.night, 'night');
// ====== 新增:动态填充夜间比白天下降率 ======
fillNightDropRates(stats.day, stats.night);
}
// 新增:动态填充统计区间、时长、有效数、总数
function fillStatsHeader(data, prefix) {
const safeSetText = (id, value) => {
const element = document.getElementById(id);
if (element) {
const safeValue = (value == null || value === undefined || value === 'undefined' ||
(typeof value === 'number' && isNaN(value)) ||
(typeof value === 'string' && (value.includes('undefined') || value.includes('NaN'))))
? '--' : value;
element.textContent = safeValue;
}
};
if (!data || data.length === 0) {
safeSetText(prefix+'-time-range', '--');
safeSetText(prefix+'-duration', '--');
safeSetText(prefix+'-effective-count', '0');
safeSetText(prefix+'-total-count', '0');
return;
}
// 计算时间区间
const times = data.map(item => new Date(item.originalTime).getTime()).sort((a,b)=>a-b);
const minTime = times[0];
const maxTime = times[times.length-1];
const minStr = new Date(minTime).toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
const maxStr = new Date(maxTime).toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
safeSetText(prefix+'-time-range', minStr + ' - ' + maxStr);
// 计算时长
const durationMs = maxTime - minTime;
const hours = Math.floor(durationMs / (1000*60*60));
const minutes = Math.floor((durationMs % (1000*60*60)) / (1000*60));
safeSetText(prefix+'-duration', (hours > 0 ? hours+'小时' : '') + (minutes > 0 ? minutes+'分' : ''));
// 有效数
const effectiveCount = data.filter(item => item.systolic && item.diastolic && item.heartRate).length;
safeSetText(prefix+'-effective-count', effectiveCount);
// 总数
safeSetText(prefix+'-total-count', data.length);
}
// 新增:动态填充血压负荷和变异系数
function fillAdditionalStats(data, stats, prefix) {
const safeSetText = (id, value) => {
const element = document.getElementById(id);
if (element) {
const safeValue = (value == null || value === undefined || value === 'undefined' ||
(typeof value === 'number' && isNaN(value)) ||
(typeof value === 'string' && (value.includes('undefined') || value.includes('NaN'))))
? '--' : value;
element.textContent = safeValue;
}
};
if (!data || data.length === 0 || !stats) {
// 如果没有数据,显示 --
safeSetText(`${prefix}-pressure-load-systolic`, '--');
safeSetText(`${prefix}-pressure-load-diastolic`, '--');
safeSetText(`${prefix}-variability-systolic`, '--');
safeSetText(`${prefix}-variability-diastolic`, '--');
return;
}
// 血压负荷
const systolicLoad = stats.systolicLoad;
const diastolicLoad = stats.diastolicLoad;
safeSetText(`${prefix}-pressure-load-systolic`, systolicLoad !== undefined ? systolicLoad.toFixed(1) + '%' : '--');
safeSetText(`${prefix}-pressure-load-diastolic`, diastolicLoad !== undefined ? diastolicLoad.toFixed(1) + '%' : '--');
// 计算血压变异系数
const systolicValues = data.map(d => d.systolic).filter(v => v != null && !isNaN(v));
const diastolicValues = data.map(d => d.diastolic).filter(v => v != null && !isNaN(v));
const calculateCV = (values, avg) => {
if (!values || values.length === 0 || !avg || avg === 0) return undefined;
const variance = values.reduce((sum, val) => sum + Math.pow(val - avg, 2), 0) / values.length;
const std = Math.sqrt(variance);
return (std / avg) * 100;
};
const systolicCV = calculateCV(systolicValues, stats.avgSystolic);
const diastolicCV = calculateCV(diastolicValues, stats.avgDiastolic);
safeSetText(`${prefix}-variability-systolic`, systolicCV !== undefined ? systolicCV.toFixed(2) + '%' : '--');
safeSetText(`${prefix}-variability-diastolic`, diastolicCV !== undefined ? diastolicCV.toFixed(2) + '%' : '--');
}
// 新增:动态填充夜间比白天下降率
function fillNightDropRates(dayStats, nightStats) {
const safeSetText = (id, value) => {
const element = document.getElementById(id);
if (element) {
const safeValue = (value == null || value === undefined || value === 'undefined' ||
(typeof value === 'number' && isNaN(value)) ||
(typeof value === 'string' && (value.includes('undefined') || value.includes('NaN'))))
? '--' : value;
element.textContent = safeValue;
}
};
// 检查是否有足够的数据来计算下降率
const hasValidDayData = dayStats && dayStats.hasData && dayStats.avgSystolic && dayStats.avgDiastolic;
const hasValidNightData = nightStats && nightStats.hasData && nightStats.avgSystolic && nightStats.avgDiastolic;
if (!hasValidDayData || !hasValidNightData) {
safeSetText('all-night-drop-systolic', '--');
safeSetText('all-night-drop-diastolic', '--');
return;
}
// 计算夜间比白天下降率
const systolicDropRate = ((dayStats.avgSystolic - nightStats.avgSystolic) / dayStats.avgSystolic) * 100;
const diastolicDropRate = ((dayStats.avgDiastolic - nightStats.avgDiastolic) / dayStats.avgDiastolic) * 100;
// 判断杓型
const getSystolicDipType = (rate) => {
if (rate < 0) return '反杓型';
if (rate < 10) return '非杓型';
if (rate <= 20) return '杓型';
return '深杓型';
};
const getDiastolicDipType = (rate) => {
if (rate < 0) return '反杓型';
if (rate < 10) return '非杓型';
if (rate <= 20) return '杓型';
return '深杓型';
};
const systolicText = systolicDropRate.toFixed(2) + '% (' + getSystolicDipType(systolicDropRate) + ')';
const diastolicText = diastolicDropRate.toFixed(2) + '% (' + getDiastolicDipType(diastolicDropRate) + ')';
safeSetText('all-night-drop-systolic', systolicText);
safeSetText('all-night-drop-diastolic', diastolicText);
}
// 渲染所有图表
function renderAllCharts() {
console.log('开始渲染所有图表, 数据表长度:', chartDataTable ? chartDataTable.length : 0);
if (!chartDataTable || chartDataTable.length === 0) {
console.warn('没有数据可用于渲染图表, chartDataTable:', chartDataTable);
// 显示无数据提示
const chartContainers = document.querySelectorAll('[id$="chart"], .chart');
chartContainers.forEach(container => {
if (container) {
container.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100%;color:#999;">暂无数据</div>';
}
});
return;
}
console.log('图表数据样本:', chartDataTable.slice(0, 2));
try {
// 渲染趋势图
console.log('渲染趋势图...');
renderTrendChart();
// 渲染柱状图
console.log('渲染柱状图...');
renderHistograms();
// 渲染饼图
console.log('渲染饼图...');
renderPieCharts();
// 渲染散点图
console.log('渲染散点图...');
renderScatterCharts();
// 渲染小时平均图
console.log('渲染小时平均图...');
renderHourlyChart();
console.log('所有图表渲染完成');
} catch (error) {
console.error('渲染图表过程中出错:', error);
}
}
// 渲染趋势图
function renderTrendChart() {
const chart = echarts.init(document.getElementById('trend-chart'));
const timeLabels = chartDataTable.map(item =>
new Date(item.originalTime).toLocaleDateString('zh-CN', {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})
);
const option = {
tooltip: { trigger: 'axis' },
legend: { data: ['收缩压', '舒张压', '心率'], top: 10 },
xAxis: { type: 'category', data: timeLabels },
yAxis: [
{ type: 'value', name: 'mmHg', position: 'left', min: 0, max: 200 },
{ type: 'value', name: '次/分', position: 'right', min: 50, max: 120 }
],
series: [
{
name: '收缩压',
type: 'line',
symbol: 'none',
lineStyle: { width: 2 },
data: chartDataTable.map(item => item.systolic),
itemStyle: { color: '#409eff' }
},
{
name: '舒张压',
type: 'line',
symbol: 'none',
lineStyle: { width: 2 },
data: chartDataTable.map(item => item.diastolic),
itemStyle: { color: '#67c23a' }
},
{
name: '心率',
type: 'line',
symbol: 'none',
lineStyle: { width: 2 },
yAxisIndex: 1,
data: chartDataTable.map(item => item.heartRate),
itemStyle: { color: '#e6a23c' }
}
]
};
chart.setOption(option);
}
// 渲染柱状图
function renderHistograms() {
// 收缩压柱状图
renderHistogram('histogram-systolic-all', chartDataTable, 'systolic', '收缩压分布 - 全天');
renderHistogram('histogram-systolic-day', getDaytimeData(), 'systolic', '收缩压分布 - 白天');
renderHistogram('histogram-systolic-night', getNighttimeData(), 'systolic', '收缩压分布 - 夜间');
// 舒张压柱状图
renderHistogram('histogram-diastolic-all', chartDataTable, 'diastolic', '舒张压分布 - 全天');
renderHistogram('histogram-diastolic-day', getDaytimeData(), 'diastolic', '舒张压分布 - 白天');
renderHistogram('histogram-diastolic-night', getNighttimeData(), 'diastolic', '舒张压分布 - 夜间');
// 心率柱状图
renderHistogram('histogram-hr-all', chartDataTable, 'heartRate', '心率分布 - 全天');
renderHistogram('histogram-hr-day', getDaytimeData(), 'heartRate', '心率分布 - 白天');
renderHistogram('histogram-hr-night', getNighttimeData(), 'heartRate', '心率分布 - 夜间');
}
// 渲染单个柱状图
function renderHistogram(elementId, data, field, title) {
const chart = echarts.init(document.getElementById(elementId));
let mmHgRanges, labels, counts, colors;
if (field === 'systolic') {
mmHgRanges = [130, 140, 150, 160, 170, 180, 190];
const kPaRanges = mmHgRanges.map(v => (v / 7.5).toFixed(1));
labels = mmHgRanges.map((v, i) => `${v} (${kPaRanges[i]})`);
counts = Array(mmHgRanges.length).fill(0);
data.forEach(item => {
const value = item[field];
for (let i = 0; i < mmHgRanges.length; i++) {
if (i === mmHgRanges.length - 1) {
if (value >= mmHgRanges[i]) counts[i]++;
} else if (value >= mmHgRanges[i] && value < mmHgRanges[i + 1]) {
counts[i]++;
break;
}
}
});
colors = '#5bc0de';
} else if (field === 'diastolic') {
mmHgRanges = [70, 80, 90, 100, 110, 120, 130, 140, 150, 160];
const kPaRanges = mmHgRanges.map(v => (v / 7.5).toFixed(1));
labels = mmHgRanges.map((v, i) => `${v} (${kPaRanges[i]})`);
counts = Array(mmHgRanges.length).fill(0);
data.forEach(item => {
const value = item[field];
for (let i = 0; i < mmHgRanges.length; i++) {
if (i === mmHgRanges.length - 1) {
if (value >= mmHgRanges[i]) counts[i]++;
} else if (value >= mmHgRanges[i] && value < mmHgRanges[i + 1]) {
counts[i]++;
break;
}
}
});
colors = '#5bc0de';
} else {
// heartRate
mmHgRanges = [60, 70, 80, 90, 100, 110, 120];
labels = mmHgRanges.map(v => `${v}`);
counts = Array(mmHgRanges.length).fill(0);
data.forEach(item => {
const value = item[field];
for (let i = 0; i < mmHgRanges.length; i++) {
if (i === mmHgRanges.length - 1) {
if (value >= mmHgRanges[i]) counts[i]++;
} else if (value >= mmHgRanges[i] && value < mmHgRanges[i + 1]) {
counts[i]++;
break;
}
}
});
colors = '#5bc0de';
}
const total = data.length;
const percentages = counts.map(count => total > 0 ? (count / total * 100).toFixed(1) : '0.0');
const option = {
xAxis: {
type: 'category',
data: labels,
axisLabel: { fontSize: 12 }
},
yAxis: {
type: 'value',
name: '百分率',
axisLabel: {
formatter: '{value}%',
fontSize: 12
}
},
series: [{
type: 'bar',
data: percentages,
barWidth: '40%',
itemStyle: { color: colors }
}],
tooltip: {
trigger: 'axis',
formatter: params => {
const idx = params[0].dataIndex;
return `${labels[idx]}<br/>百分比: ${percentages[idx]}%<br/>数量: ${counts[idx]}`;
}
},
grid: { left: 50, right: 20, bottom: 40, top: 30 },
legend: { show: false }
};
chart.setOption(option);
}
// 渲染饼图
function renderPieCharts() {
// 收缩压饼图
renderPieChart('pie-systolic-day', getDaytimeData(), 'systolic', 135);
renderPieChart('pie-systolic-night', getNighttimeData(), 'systolic', 120);
renderPieChart('pie-systolic-all', chartDataTable, 'systolic', 140);
// 舒张压饼图
renderPieChart('pie-diastolic-day', getDaytimeData(), 'diastolic', 85);
renderPieChart('pie-diastolic-night', getNighttimeData(), 'diastolic', 70);
renderPieChart('pie-diastolic-all', chartDataTable, 'diastolic', 90);
// 心率饼图
renderPieChart('pie-hr-day', getDaytimeData(), 'heartRate', null);
renderPieChart('pie-hr-night', getNighttimeData(), 'heartRate', null);
renderPieChart('pie-hr-all', chartDataTable, 'heartRate', null);
// 填充饼图统计信息
fillPieChartStats();
}
// 渲染单个饼图
function renderPieChart(elementId, data, field, threshold) {
const chart = echarts.init(document.getElementById(elementId));
let normalCount, abnormalCount;
if (field === 'heartRate') {
normalCount = data.filter(item => item[field] >= 60 && item[field] <= 100).length;
abnormalCount = data.length - normalCount;
} else {
normalCount = data.filter(item => item[field] < threshold).length;
abnormalCount = data.length - normalCount;
}
const normalPercent = data.length > 0 ? Math.round((normalCount / data.length) * 100) : 0;
const abnormalPercent = 100 - normalPercent;
const option = {
tooltip: {
trigger: 'item',
formatter: '{b}: {c}次 ({d}%)'
},
series: [{
type: 'pie',
radius: '60%',
data: [
{ value: normalCount, itemStyle: { color: '#7fc7ff' } },
{ value: abnormalCount, itemStyle: { color: '#ff7f7f' } }
],
label: {
show: true,
formatter: '{b}\n{c}次\n{d}%',
fontSize: 10,
position: 'inside'
},
labelLine: {
show: false
}
}]
};
chart.setOption(option);
}
// 渲染散点图
function renderScatterCharts() {
// 线性回归计算函数
const calculateLinearRegression = (data) => {
const n = data.length;
const sumX = data.reduce((sum, point) => sum + point[0], 0);
const sumY = data.reduce((sum, point) => sum + point[1], 0);
const sumXY = data.reduce((sum, point) => sum + point[0] * point[1], 0);
const sumXX = data.reduce((sum, point) => sum + point[0] * point[0], 0);
const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
const intercept = (sumY - slope * sumX) / n;
return { slope, intercept };
};
// 收缩压与舒张压关系
const bpChart = echarts.init(document.getElementById('scatter-bp-relation'));
const bpData = chartDataTable.map(item => [item.diastolic, item.systolic]);
const bpRegression = calculateLinearRegression(bpData);
// 生成拟合线数据
const bpFitLineData = [];
for (let x = 50; x <= 120; x += 10) {
const y = bpRegression.slope * x + bpRegression.intercept;
bpFitLineData.push([x, y]);
}
const bpOption = {
tooltip: {
trigger: 'item',
formatter: function(params) {
if (params.seriesName === '散点数据') {
return `舒张压: ${params.data[0]}mmHg<br/>收缩压: ${params.data[1]}mmHg`;
}
return '';
}
},
grid: {
left: 60,
right: 30,
bottom: 60,
top: 30
},
xAxis: {
type: 'value',
name: '舒张压(mmHg)',
min: 50,
max: 120,
nameLocation: 'middle',
nameGap: 30,
axisLine: { show: true },
axisTick: { show: true },
splitLine: { show: true, lineStyle: { color: '#e0e0e0' } }
},
yAxis: {
type: 'value',
name: '收缩压(mmHg)',
min: 100,
max: 200,
nameLocation: 'middle',
nameGap: 40,
axisLine: { show: true },
axisTick: { show: true },
splitLine: { show: true, lineStyle: { color: '#e0e0e0' } }
},
series: [
{
name: '散点数据',
symbolSize: 8,
data: bpData,
type: 'scatter',
itemStyle: { color: '#409eff', opacity: 0.7 }
},
{
name: '拟合线',
type: 'line',
data: bpFitLineData,
lineStyle: {
color: '#e6a23c',
width: 2,
type: 'solid'
},
symbol: 'none',
smooth: false
}
]
};
bpChart.setOption(bpOption);
// 心率与收缩压关系
const hrChart = echarts.init(document.getElementById('scatter-hr-relation'));
const hrData = chartDataTable.map(item => [item.heartRate, item.systolic]);
const hrRegression = calculateLinearRegression(hrData);
// 生成拟合线数据
const hrFitLineData = [];
for (let x = 50; x <= 120; x += 10) {
const y = hrRegression.slope * x + hrRegression.intercept;
hrFitLineData.push([x, y]);
}
const hrOption = {
tooltip: {
trigger: 'item',
formatter: function(params) {
if (params.seriesName === '散点数据') {
return `心率: ${params.data[0]}次/分<br/>收缩压: ${params.data[1]}mmHg`;
}
return '';
}
},
grid: {
left: 60,
right: 30,
bottom: 60,
top: 30
},
xAxis: {
type: 'value',
name: '心率(次/分)',
min: 50,
max: 120,
nameLocation: 'middle',
nameGap: 30,
axisLine: { show: true },
axisTick: { show: true },
splitLine: { show: true, lineStyle: { color: '#e0e0e0' } }
},
yAxis: {
type: 'value',
name: '收缩压(mmHg)',
min: 100,
max: 200,
nameLocation: 'middle',
nameGap: 40,
axisLine: { show: true },
axisTick: { show: true },
splitLine: { show: true, lineStyle: { color: '#e0e0e0' } }
},
series: [
{
name: '散点数据',
symbolSize: 8,
data: hrData,
type: 'scatter',
itemStyle: { color: '#409eff', opacity: 0.7 }
},
{
name: '拟合线',
type: 'line',
data: hrFitLineData,
lineStyle: {
color: '#e6a23c',
width: 2,
type: 'solid'
},
symbol: 'none',
smooth: false
}
]
};
hrChart.setOption(hrOption);
}
// 渲染小时平均图
function renderHourlyChart() {
const chart = echarts.init(document.getElementById('hourly-average-chart'));
// 按小时分组计算平均值
const hourlyData = Array.from({ length: 24 }, (_, hour) => {
const hourData = chartDataTable.filter(item => new Date(item.originalTime).getHours() === hour);
if (hourData.length === 0) {
return { hour, systolic: null, diastolic: null, heartRate: null };
}
const avgSystolic = Math.round(hourData.reduce((sum, item) => sum + item.systolic, 0) / hourData.length);
const avgDiastolic = Math.round(hourData.reduce((sum, item) => sum + item.diastolic, 0) / hourData.length);
const avgHeartRate = Math.round(hourData.reduce((sum, item) => sum + item.heartRate, 0) / hourData.length);
return { hour, systolic: avgSystolic, diastolic: avgDiastolic, heartRate: avgHeartRate };
});
const option = {
tooltip: { trigger: 'axis' },
legend: { data: ['收缩压', '舒张压', '心率'], bottom: 0 },
xAxis: {
type: 'category',
data: Array.from({ length: 24 }, (_, i) => String(i).padStart(2, '0'))
},
yAxis: [
{ type: 'value', name: 'mmHg', position: 'left', min: 0, max: 200 },
{ type: 'value', name: '次/分', position: 'right', min: 50, max: 120 }
],
series: [
{
name: '收缩压',
type: 'line',
smooth: true,
data: hourlyData.map(d => d.systolic),
itemStyle: { color: '#409eff' }
},
{
name: '舒张压',
type: 'line',
smooth: true,
data: hourlyData.map(d => d.diastolic),
itemStyle: { color: '#67c23a' }
},
{
name: '心率',
type: 'line',
smooth: true,
yAxisIndex: 1,
data: hourlyData.map(d => d.heartRate),
itemStyle: { color: '#e6a23c' }
}
]
};
chart.setOption(option);
}
// 填充数据表
function fillDataTable() {
const tbody = document.getElementById('patient-data-tbody');
tbody.innerHTML = '';
chartDataTable.forEach((item, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${index + 1}</td>
<td>${new Date(item.originalTime).toLocaleDateString('zh-CN')}</td>
<td>${new Date(item.originalTime).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}</td>
<td>${item.systolic}</td>
<td>${item.diastolic}</td>
<td>${item.heartRate}</td>
<td>${item.avgBP}</td>
<td>${item.status}</td>
`;
tbody.appendChild(row);
});
}
// 填充饼图统计信息
function fillPieChartStats() {
const daytimeData = getDaytimeData();
const nighttimeData = getNighttimeData();
// 收缩压统计
fillPieStats(daytimeData, 'systolic', 'pie-day-sys');
fillPieStats(nighttimeData, 'systolic', 'pie-night-sys');
fillPieStats(chartDataTable, 'systolic', 'pie-all-sys');
// 舒张压统计
fillPieStats(daytimeData, 'diastolic', 'pie-day-dia');
fillPieStats(nighttimeData, 'diastolic', 'pie-night-dia');
fillPieStats(chartDataTable, 'diastolic', 'pie-all-dia');
// 心率统计
fillPieStats(daytimeData, 'heartRate', 'pie-day-hr');
fillPieStats(nighttimeData, 'heartRate', 'pie-night-hr');
fillPieStats(chartDataTable, 'heartRate', 'pie-all-hr');
}
// 填充单个饼图的统计信息
function fillPieStats(data, field, prefix) {
if (!data || data.length === 0) return;
const values = data.map(item => item[field]);
const maxValue = Math.max(...values);
const minValue = Math.min(...values);
// 找到最大值和最小值对应的时间
const maxItem = data.find(item => item[field] === maxValue);
const minItem = data.find(item => item[field] === minValue);
const formatTime = (item) => {
if (!item) return '--';
return new Date(item.originalTime).toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
};
const maxElement = document.getElementById(`${prefix}-max`);
const minElement = document.getElementById(`${prefix}-min`);
if (maxElement) {
maxElement.textContent = `${maxValue} (${formatTime(maxItem)})`;
}
if (minElement) {
minElement.textContent = `${minValue} (${formatTime(minItem)})`;
}
}
// 辅助函数
function getDaytimeData() {
return chartDataTable.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour >= 6 && hour < 22;
});
}
function getNighttimeData() {
return chartDataTable.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour < 6 || hour >= 22;
});
}
// 暴露全局函数供外部调用
window.initializeABPMReport = initializeReport;
// 页面打印函数
window.printReport = function() {
window.print();
};
// 页面导出PDF函数
window.exportToPDF = function() {
alert('PDF导出功能开发中...');
};
// 监听来自父窗口的消息
window.addEventListener('message', function(event) {
showLoading(); // 接收到数据前显示loading
showDebugInfo('收到消息: ' + JSON.stringify(event.data));
if (event.data && event.data.type === 'INIT_ABPM_REPORT') {
showDebugInfo('开始初始化ABPM报告数据');
// 详细调试信息
const receivedData = event.data.data;
showDebugInfo('接收到的数据结构: ' + JSON.stringify(receivedData, null, 2));
showDebugInfo('患者数据存在: ' + (receivedData && receivedData.patientData ? '是' : '否'));
showDebugInfo('图表数据存在: ' + (receivedData && receivedData.chartDataTable ? '是' : '否'));
showDebugInfo('图表数据条数: ' + (receivedData && receivedData.chartDataTable ? receivedData.chartDataTable.length : '0'));
showDebugInfo('分析结果存在: ' + (receivedData && receivedData.analysisResult ? '是' : '否'));
// 延迟一点时间确保页面完全加载
setTimeout(() => {
try {
initializeReport(receivedData);
showDebugInfo('报告数据初始化完成');
} catch (error) {
showDebugInfo('初始化报告数据失败: ' + error.message);
console.error('初始化报告数据失败:', error);
}
}, 500);
}
});
// 显示调试信息到页面
function showDebugInfo(message) {
const debugInfo = document.getElementById('debug-info');
const debugContent = document.getElementById('debug-content');
if (debugInfo && debugContent) {
debugInfo.style.display = 'block';
debugContent.innerHTML += '<div>' + new Date().toLocaleTimeString() + ': ' + message + '</div>';
}
console.log('调试:', message);
}
// 创建测试数据
function createTestData() {
showLoading(); // 加载测试数据前显示loading
// 检查URL参数来决定使用哪种测试数据
const urlParams = new URLSearchParams(window.location.search);
const testType = urlParams.get('test') || 'normal';
let testData;
if (testType === 'dayonly') {
// 只有白天数据的测试
testData = {
patientData: {
name: '测试患者(仅白天数据)',
gender: '男',
age: '45岁',
orgname: '测试医院',
device: '测试设备',
recordStartTime: '2024-01-01 08:00:00',
recordEndTime: '2024-01-01 20:00:00',
recordDuration: '12小时',
successReadCount: '7',
successReadPercent: '95%',
maxSystolic: '145',
maxSystolicTime: '12:00',
minSystolic: '130',
minSystolicTime: '08:00',
avgSystolic: '137',
avgDiastolic: '85',
systolicVariability: '12.5%',
diastolicVariability: '10.2%',
wearTime: '2024-01-01'
},
chartDataTable: [
// 只有白天数据 (6:00-22:00)
{ originalTime: '2024-01-01 08:00:00', systolic: 130, diastolic: 80, heartRate: 70, avgBP: 97, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-01 10:00:00', systolic: 140, diastolic: 90, heartRate: 75, avgBP: 107, status: '轻度高血压', suggestion: '注意饮食' },
{ originalTime: '2024-01-01 12:00:00', systolic: 145, diastolic: 95, heartRate: 80, avgBP: 112, status: '轻度高血压', suggestion: '适量运动' },
{ originalTime: '2024-01-01 14:00:00', systolic: 135, diastolic: 85, heartRate: 72, avgBP: 102, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-01 16:00:00', systolic: 142, diastolic: 88, heartRate: 78, avgBP: 106, status: '轻度高血压', suggestion: '注意监测' },
{ originalTime: '2024-01-01 18:00:00', systolic: 138, diastolic: 82, heartRate: 74, avgBP: 101, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-01 20:00:00', systolic: 132, diastolic: 78, heartRate: 69, avgBP: 96, status: '正常', suggestion: '继续保持' }
],
analysisResult: '测试分析结果:患者仅有白天血压数据,白天血压控制基本正常,但缺少夜间数据无法评估昼夜节律。'
};
} else {
// 正常的全天数据测试
testData = {
patientData: {
name: '测试患者',
gender: '男',
age: '45岁',
orgname: '测试医院',
device: '测试设备',
recordStartTime: '2024-01-01 08:00:00',
recordEndTime: '2024-01-02 08:00:00',
recordDuration: '24小时',
successReadCount: '11',
successReadPercent: '95%',
maxSystolic: '145',
maxSystolicTime: '12:00',
minSystolic: '118',
minSystolicTime: '03:00',
avgSystolic: '133',
avgDiastolic: '81',
systolicVariability: '12.5%',
diastolicVariability: '10.2%',
wearTime: '2024-01-01'
},
chartDataTable: [
// 白天数据 (6:00-22:00)
{ originalTime: '2024-01-01 08:00:00', systolic: 130, diastolic: 80, heartRate: 70, avgBP: 97, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-01 10:00:00', systolic: 140, diastolic: 90, heartRate: 75, avgBP: 107, status: '轻度高血压', suggestion: '注意饮食' },
{ originalTime: '2024-01-01 12:00:00', systolic: 145, diastolic: 95, heartRate: 80, avgBP: 112, status: '轻度高血压', suggestion: '适量运动' },
{ originalTime: '2024-01-01 14:00:00', systolic: 135, diastolic: 85, heartRate: 72, avgBP: 102, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-01 16:00:00', systolic: 142, diastolic: 88, heartRate: 78, avgBP: 106, status: '轻度高血压', suggestion: '注意监测' },
{ originalTime: '2024-01-01 18:00:00', systolic: 138, diastolic: 82, heartRate: 74, avgBP: 101, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-01 20:00:00', systolic: 132, diastolic: 78, heartRate: 69, avgBP: 96, status: '正常', suggestion: '继续保持' },
// 夜间数据 (22:00-6:00)
{ originalTime: '2024-01-01 23:00:00', systolic: 125, diastolic: 75, heartRate: 65, avgBP: 92, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-02 01:00:00', systolic: 120, diastolic: 70, heartRate: 62, avgBP: 87, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-02 03:00:00', systolic: 118, diastolic: 68, heartRate: 60, avgBP: 85, status: '正常', suggestion: '继续保持' },
{ originalTime: '2024-01-02 05:00:00', systolic: 122, diastolic: 72, heartRate: 63, avgBP: 89, status: '正常', suggestion: '继续保持' }
],
analysisResult: '测试分析结果:患者血压控制基本正常,建议继续监测。'
};
}
console.log(`使用测试数据初始化报告 (${testType})`);
console.log('测试数据内容:', testData);
console.log('测试数据chartDataTable长度:', testData.chartDataTable.length);
initializeReport(testData);
}
// 页面加载完成后的初始化
document.addEventListener('DOMContentLoaded', function() {
showLoading(); // 页面初始显示loading
showDebugInfo('页面DOM加载完成');
console.log('ABPM报告模板页面加载完成');
// 向父窗口发送加载完成消息
if (window.opener) {
showDebugInfo('检测到父窗口,发送加载完成消息');
window.opener.postMessage({
type: 'ABPM_TEMPLATE_LOADED'
}, '*');
} else {
// 如果不是从其他窗口打开的,使用测试数据
showDebugInfo('独立打开页面将在3秒后加载测试数据');
console.log('独立打开页面将在3秒后加载测试数据');
console.log('测试说明:');
console.log('- 正常测试(包含白天+夜间数据):直接打开页面');
console.log('- 仅白天数据测试在URL后添加 ?test=dayonly');
console.log('例如file:///path/to/abpm-report-template.html?test=dayonly');
setTimeout(() => {
createTestData();
}, 3000);
}
});
// loading 遮罩控制
function showLoading() {
const mask = document.getElementById('loading-mask');
if (mask) mask.style.display = 'flex';
}
function hideLoading() {
const mask = document.getElementById('loading-mask');
if (mask) mask.style.display = 'none';
}
</script>
</body>
</html>