shanghai_vue3/public/CGM_report.html
2025-07-24 14:54:37 +08:00

1501 lines
68 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加载失败');
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: 400px;
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: 1000px;
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: 3px;
text-align: center;
line-height: 1.2;
}
.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;
}
/* 强制显示图例颜色 */
div[style*="background-color: #ff7f7f"] {
background-color: #ff7f7f !important;
-webkit-print-color-adjust: exact !important;
color-adjust: exact !important;
}
div[style*="background-color: #7fc7ff"] {
background-color: #7fc7ff !important;
-webkit-print-color-adjust: exact !important;
color-adjust: exact !important;
}
div[style*="background-color: #e6a23c"] {
background-color: #e6a23c !important;
-webkit-print-color-adjust: exact !important;
color-adjust: exact !important;
}
}
/* 隐藏某些页面的样式 */
.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="avg-glucose">--</span>
</div>
<div class="info-item">
<span class="info-label">最高血糖:</span>
<span class="info-value" id="max-glucose">--</span>
</div>
<div class="info-item">
<span class="info-label">最低血糖:</span>
<span class="info-value" id="min-glucose">--</span>
</div>
<div class="info-item">
<span class="info-label">血糖变异系数(CV%)</span>
<span class="info-value" id="glucose-cv">--</span>
</div>
<div class="info-item">
<span class="info-label">葡萄糖管理指标(GMI)</span>
<span class="info-value" id="glucose-gmi">--</span>
</div>
<div class="info-item">
<span class="info-label">目标范围内时间(TIR%)</span>
<span class="info-value" id="tir-percent">--</span>
</div>
<div class="info-item">
<span class="info-label">低血糖时间(TAR%)</span>
<span class="info-value" id="tar-percent">--</span>
</div>
<div class="info-item">
<span class="info-label">高血糖时间(THR%)</span>
<span class="info-value" id="thr-percent">--</span>
</div>
</div>
<!-- 血糖趋势图 -->
<div style="margin: 20px 0;">
<div class="chart-container" id="glucose-trend-chart" style="height: 350px; width: 100%; border: 1px solid #ddd; border-radius: 4px;"></div>
</div>
<!-- 血糖统计数据表格 -->
<div style="margin: 20px 0;">
<h3 style="text-align: center; margin-bottom: 20px; color: #333; font-size: 16px;">血糖统计数据</h3>
<!-- 时段统计表格 -->
<table class="statistics-table" style="margin-bottom: 25px;">
<thead>
<tr>
<th rowspan="2" style="background-color: #e8f4fd;">时段</th>
<th rowspan="2" style="background-color: #e8f4fd;">平均血糖<br>(mmol/L)</th>
<th rowspan="2" style="background-color: #e8f4fd;">血糖标准差</th>
<th colspan="3" style="background-color: #e8f4fd;">血糖分层统计 (%)</th>
</tr>
<tr>
<th style="background-color: #f0f9ff;">正常血糖<br>(3.9-10.0)</th>
<th style="background-color: #f0f9ff;">低血糖<br>(&lt;3.9)</th>
<th style="background-color: #f0f9ff;">高血糖<br>(≥10.0)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-weight: bold; background-color: #fafafa;">全天 (00:00-24:00)</td>
<td id="all-avg-glucose-main">--</td>
<td id="all-std-glucose-main">--</td>
<td id="all-tir-percent-main">--</td>
<td id="all-tar-percent-main">--</td>
<td id="all-thr-percent-main">--</td>
</tr>
<tr>
<td style="font-weight: bold; background-color: #fafafa;">白天 (08:00-22:00)</td>
<td id="day-avg-glucose-main">--</td>
<td id="day-std-glucose-main">--</td>
<td id="day-tir-percent-main">--</td>
<td id="day-tar-percent-main">--</td>
<td id="day-thr-percent-main">--</td>
</tr>
<tr>
<td style="font-weight: bold; background-color: #fafafa;">夜间 (22:00-08:00)</td>
<td id="night-avg-glucose-main">--</td>
<td id="night-std-glucose-main">--</td>
<td id="night-tir-percent-main">--</td>
<td id="night-tar-percent-main">--</td>
<td id="night-thr-percent-main">--</td>
</tr>
</tbody>
</table>
<!-- 极值统计表格 -->
<table class="statistics-table">
<thead>
<tr>
<th style="background-color: #e8f4fd;">血糖极值</th>
<th style="background-color: #e8f4fd;">数值 (mmol/L)</th>
<th style="background-color: #e8f4fd;">发生时间</th>
<th style="background-color: #e8f4fd;">时段分类</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-weight: bold; background-color: #fff2f0; color: #d32f2f;">最高血糖</td>
<td id="max-glucose-value-main" style="color: #d32f2f; font-weight: bold;">--</td>
<td id="max-glucose-time-main">--</td>
<td id="max-glucose-period-main">--</td>
</tr>
<tr>
<td style="font-weight: bold; background-color: #f3e5f5; color: #7b1fa2;">最低血糖</td>
<td id="min-glucose-value-main" style="color: #7b1fa2; font-weight: bold;">--</td>
<td id="min-glucose-time-main">--</td>
<td id="min-glucose-period-main">--</td>
</tr>
</tbody>
</table>
</div>
<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="display: flex; flex-direction: column; gap: 30px; margin: 20px 0;">
<div style="text-align: center;">
<div style="font-size: 18px; font-weight: bold; margin-bottom: 20px; color: #333;">白天血糖统计 (08:00-22:00)</div>
<div style="display: flex; justify-content: center; align-items: center; gap: 20px;">
<div id="pie-glucose-day" style="width: 220px; height: 220px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);"></div>
<div style="font-size: 13px; min-width: 180px;">
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #ff7f7f; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">低血糖 (&lt;3.9 mmol/L)</span>
</div>
<span id="day-low-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #7fc7ff; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">正常 (3.9-10.0 mmol/L)</span>
</div>
<span id="day-normal-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #e6a23c; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">高血糖 (≥10.0 mmol/L)</span>
</div>
<span id="day-high-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
</div>
</div>
</div>
<div style="text-align: center;">
<div style="font-size: 18px; font-weight: bold; margin-bottom: 20px; color: #333;">夜间血糖统计 (22:00-08:00)</div>
<div style="display: flex; justify-content: center; align-items: center; gap: 20px;">
<div id="pie-glucose-night" style="width: 220px; height: 220px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);"></div>
<div style="font-size: 13px; min-width: 180px;">
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #ff7f7f; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">低血糖 (&lt;3.9 mmol/L)</span>
</div>
<span id="night-low-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #7fc7ff; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">正常 (3.9-10.0 mmol/L)</span>
</div>
<span id="night-normal-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #e6a23c; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">高血糖 (≥10.0 mmol/L)</span>
</div>
<span id="night-high-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
</div>
</div>
</div>
<div style="text-align: center;">
<div style="font-size: 18px; font-weight: bold; margin-bottom: 20px; color: #333;">全天血糖统计 (00:00-24:00)</div>
<div style="display: flex; justify-content: center; align-items: center; gap: 20px;">
<div id="pie-glucose-all" style="width: 220px; height: 220px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);"></div>
<div style="font-size: 13px; min-width: 180px;">
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #ff7f7f; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">低血糖 (&lt;3.9 mmol/L)</span>
</div>
<span id="all-low-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #7fc7ff; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">正常 (3.9-10.0 mmol/L)</span>
</div>
<span id="all-normal-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; margin: 15px 0; padding: 8px; border-radius: 4px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f5f5f5'" onmouseout="this.style.backgroundColor='transparent'">
<div style="display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: #e6a23c; margin-right: 12px; border-radius: 3px; border: 1px solid #ddd;"></div>
<span style="font-weight: 500; color: #333;">高血糖 (≥10.0 mmol/L)</span>
</div>
<span id="all-high-percent" style="font-weight: 600; color: #666; font-size: 12px;">--</span>
</div>
</div>
</div>
</div>
</div>
<div class="page-footer">
第3页 | 动态血糖监测报告
</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 = ['glucose'];
for (const field of requiredChartFields) {
if (typeof firstItem[field] === 'undefined') {
showDebugInfo(`验证警告:图表数据缺少字段 ${field}`);
}
}
}
showDebugInfo('数据验证通过');
return true;
}
// 初始化报告数据
function initializeReport(data) {
hideLoading();
showDebugInfo('开始初始化报告数据');
if (!data) {
showDebugInfo('错误:未收到有效数据');
console.error('未收到有效数据');
return;
}
if (!validateData(data)) {
showDebugInfo('数据验证失败,停止初始化');
return;
}
patientData = data.patientData || {};
chartDataTable = data.chartDataTable || [];
analysisResult = data.analysisResult || '';
if (typeof echarts === 'undefined') {
console.error('ECharts库未加载');
return;
}
try {
fillBasicInfo();
fillAnalysisContent();
fillStatisticsData();
renderAllCharts();
} catch (error) {
console.error('初始化过程中出错:', error);
}
}
// 计算CGM特有指标
function calculateCGMMetrics(data) {
if (!data || data.length === 0) {
return {
avgGlucose: null,
maxGlucose: null,
maxGlucoseTime: null,
minGlucose: null,
minGlucoseTime: null,
glucoseCV: null,
glucoseGMI: null,
tirPercent: null,
tarPercent: null,
thrPercent: null
};
}
const glucoseValues = data.map(item => item.glucose).filter(v => v != null && !isNaN(v));
if (glucoseValues.length === 0) {
return {
avgGlucose: null,
maxGlucose: null,
maxGlucoseTime: null,
minGlucose: null,
minGlucoseTime: null,
glucoseCV: null,
glucoseGMI: null,
tirPercent: null,
tarPercent: null,
thrPercent: null
};
}
// 计算平均血糖
const avgGlucose = glucoseValues.reduce((sum, val) => sum + val, 0) / glucoseValues.length;
// 计算标准差
const variance = glucoseValues.reduce((sum, val) => sum + Math.pow(val - avgGlucose, 2), 0) / glucoseValues.length;
const stdDev = Math.sqrt(variance);
// 计算变异系数 (CV%)
const glucoseCV = avgGlucose > 0 ? (stdDev / avgGlucose) * 100 : null;
// 计算葡萄糖管理指标 (GMI) - 基于平均血糖的估算HbA1c
// GMI (%) = 3.31 + 0.02392 × 平均血糖(mg/dL)
// 将mmol/L转换为mg/dL: mmol/L × 18.018
const avgGlucoseMgDl = avgGlucose * 18.018;
const glucoseGMI = 3.31 + 0.02392 * avgGlucoseMgDl;
// 找到最高和最低血糖及其时间
const validData = data.filter(item => item.glucose != null && !isNaN(item.glucose) && item.originalTime);
const maxItem = validData.reduce((max, current) => current.glucose > max.glucose ? current : max, validData[0]);
const minItem = validData.reduce((min, current) => current.glucose < min.glucose ? current : min, validData[0]);
// 格式化时间
const formatTime = (timeStr) => {
const date = new Date(timeStr);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${month}/${day} ${hours}:${minutes}`;
};
// 血糖分层阈值 (mmol/L)
const LOW_GLUCOSE_THRESHOLD = 3.9;
const HIGH_GLUCOSE_THRESHOLD = 10.0;
const tirCount = glucoseValues.filter(v => v >= LOW_GLUCOSE_THRESHOLD && v < HIGH_GLUCOSE_THRESHOLD).length;
const tarCount = glucoseValues.filter(v => v < LOW_GLUCOSE_THRESHOLD).length;
const thrCount = glucoseValues.filter(v => v >= HIGH_GLUCOSE_THRESHOLD).length;
const totalCount = glucoseValues.length;
return {
avgGlucose: avgGlucose,
maxGlucose: maxItem ? maxItem.glucose : null,
maxGlucoseTime: maxItem ? formatTime(maxItem.originalTime) : null,
minGlucose: minItem ? minItem.glucose : null,
minGlucoseTime: minItem ? formatTime(minItem.originalTime) : null,
glucoseCV: glucoseCV,
glucoseGMI: glucoseGMI,
tirPercent: totalCount > 0 ? (tirCount / totalCount) * 100 : null,
tarPercent: totalCount > 0 ? (tarCount / totalCount) * 100 : null,
thrPercent: totalCount > 0 ? (thrCount / totalCount) * 100 : null
};
}
// 填充基本信息
function fillBasicInfo() {
const nameElements = document.querySelectorAll('[id^="patient-name"]');
nameElements.forEach(el => {
el.textContent = 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;
} 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);
// 计算CGM特有指标
const cgmMetrics = calculateCGMMetrics(chartDataTable);
// 优先使用计算出的值如果没有则使用patientData中的值
setElementText('avg-glucose', cgmMetrics.avgGlucose ? `${cgmMetrics.avgGlucose.toFixed(1)} mmol/L` :
(patientData.avgGlucose ? `${patientData.avgGlucose} mmol/L` : '--'));
setElementText('max-glucose', cgmMetrics.maxGlucose ? `${cgmMetrics.maxGlucose.toFixed(1)} mmol/L (${cgmMetrics.maxGlucoseTime})` :
(patientData.maxGlucose ? `${patientData.maxGlucose} mmol/L (${patientData.maxGlucoseTime})` : '--'));
setElementText('min-glucose', cgmMetrics.minGlucose ? `${cgmMetrics.minGlucose.toFixed(1)} mmol/L (${cgmMetrics.minGlucoseTime})` :
(patientData.minGlucose ? `${patientData.minGlucose} mmol/L (${patientData.minGlucoseTime})` : '--'));
setElementText('glucose-cv', cgmMetrics.glucoseCV ? `${cgmMetrics.glucoseCV.toFixed(1)}%` :
(patientData.glucoseCV ? `${patientData.glucoseCV}%` : '--'));
setElementText('glucose-gmi', cgmMetrics.glucoseGMI ? `${cgmMetrics.glucoseGMI.toFixed(1)}%` :
(patientData.glucoseGMI ? `${patientData.glucoseGMI}%` : '--'));
setElementText('tir-percent', cgmMetrics.tirPercent ? `${cgmMetrics.tirPercent.toFixed(1)}%` :
(patientData.tirPercent ? `${patientData.tirPercent}%` : '--'));
setElementText('tar-percent', cgmMetrics.tarPercent ? `${cgmMetrics.tarPercent.toFixed(1)}%` :
(patientData.tarPercent ? `${patientData.tarPercent}%` : '--'));
setElementText('thr-percent', cgmMetrics.thrPercent ? `${cgmMetrics.thrPercent.toFixed(1)}%` :
(patientData.thrPercent ? `${patientData.thrPercent}%` : '--'));
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() {
if (!chartDataTable || chartDataTable.length === 0) {
console.warn('没有图表数据,显示默认值');
showDefaultStats();
return;
}
const stats = calculateStatistics(chartDataTable);
const extremeValues = calculateExtremeValues(chartDataTable);
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;
} else {
console.warn(`未找到元素: ${id}`);
}
};
// 填充时段统计表格
setElementText('all-avg-glucose-main', stats.all.avgGlucose ? `${stats.all.avgGlucose.toFixed(1)}` : '--');
setElementText('all-std-glucose-main', stats.all.stdGlucose ? `${stats.all.stdGlucose.toFixed(2)}` : '--');
setElementText('all-tir-percent-main', stats.all.tirPercent ? `${stats.all.tirPercent.toFixed(1)}%` : '--');
setElementText('all-tar-percent-main', stats.all.tarPercent ? `${stats.all.tarPercent.toFixed(1)}%` : '--');
setElementText('all-thr-percent-main', stats.all.thrPercent ? `${stats.all.thrPercent.toFixed(1)}%` : '--');
setElementText('day-avg-glucose-main', stats.day.avgGlucose ? `${stats.day.avgGlucose.toFixed(1)}` : '--');
setElementText('day-std-glucose-main', stats.day.stdGlucose ? `${stats.day.stdGlucose.toFixed(2)}` : '--');
setElementText('day-tir-percent-main', stats.day.tirPercent ? `${stats.day.tirPercent.toFixed(1)}%` : '--');
setElementText('day-tar-percent-main', stats.day.tarPercent ? `${stats.day.tarPercent.toFixed(1)}%` : '--');
setElementText('day-thr-percent-main', stats.day.thrPercent ? `${stats.day.thrPercent.toFixed(1)}%` : '--');
setElementText('night-avg-glucose-main', stats.night.avgGlucose ? `${stats.night.avgGlucose.toFixed(1)}` : '--');
setElementText('night-std-glucose-main', stats.night.stdGlucose ? `${stats.night.stdGlucose.toFixed(2)}` : '--');
setElementText('night-tir-percent-main', stats.night.tirPercent ? `${stats.night.tirPercent.toFixed(1)}%` : '--');
setElementText('night-tar-percent-main', stats.night.tarPercent ? `${stats.night.tarPercent.toFixed(1)}%` : '--');
setElementText('night-thr-percent-main', stats.night.thrPercent ? `${stats.night.thrPercent.toFixed(1)}%` : '--');
// 填充极值统计表格
setElementText('max-glucose-value-main', extremeValues.maxValue ? `${extremeValues.maxValue.toFixed(1)}` : '--');
setElementText('max-glucose-time-main', extremeValues.maxTime || '--');
setElementText('max-glucose-period-main', extremeValues.maxPeriod || '--');
setElementText('min-glucose-value-main', extremeValues.minValue ? `${extremeValues.minValue.toFixed(1)}` : '--');
setElementText('min-glucose-time-main', extremeValues.minTime || '--');
setElementText('min-glucose-period-main', extremeValues.minPeriod || '--');
// 保持原有的统计表格填充(第二页)
setElementText('all-avg-glucose', stats.all.avgGlucose ? `${stats.all.avgGlucose.toFixed(1)}` : '--');
setElementText('all-std-glucose', stats.all.stdGlucose ? `${stats.all.stdGlucose.toFixed(2)}` : '--');
setElementText('all-tir-percent', stats.all.tirPercent ? `${stats.all.tirPercent.toFixed(1)}%` : '--');
setElementText('all-tar-percent', stats.all.tarPercent ? `${stats.all.tarPercent.toFixed(1)}%` : '--');
setElementText('all-thr-percent', stats.all.thrPercent ? `${stats.all.thrPercent.toFixed(1)}%` : '--');
setElementText('day-avg-glucose', stats.day.avgGlucose ? `${stats.day.avgGlucose.toFixed(1)}` : '--');
setElementText('day-std-glucose', stats.day.stdGlucose ? `${stats.day.stdGlucose.toFixed(2)}` : '--');
setElementText('day-tir-percent', stats.day.tirPercent ? `${stats.day.tirPercent.toFixed(1)}%` : '--');
setElementText('day-tar-percent', stats.day.tarPercent ? `${stats.day.tarPercent.toFixed(1)}%` : '--');
setElementText('day-thr-percent', stats.day.thrPercent ? `${stats.day.thrPercent.toFixed(1)}%` : '--');
setElementText('night-avg-glucose', stats.night.avgGlucose ? `${stats.night.avgGlucose.toFixed(1)}` : '--');
setElementText('night-std-glucose', stats.night.stdGlucose ? `${stats.night.stdGlucose.toFixed(2)}` : '--');
setElementText('night-tir-percent', stats.night.tirPercent ? `${stats.night.tirPercent.toFixed(1)}%` : '--');
setElementText('night-tar-percent', stats.night.tarPercent ? `${stats.night.tarPercent.toFixed(1)}%` : '--');
setElementText('night-thr-percent', stats.night.thrPercent ? `${stats.night.thrPercent.toFixed(1)}%` : '--');
}
// 显示默认统计数据(当没有数据时)
function showDefaultStats() {
const setElementText = (id, value) => {
const element = document.getElementById(id);
if (element) element.textContent = value;
};
const ids = [
'all-avg-glucose', 'all-std-glucose', 'all-tir-percent', 'all-tar-percent', 'all-thr-percent',
'day-avg-glucose', 'day-std-glucose', 'day-tir-percent', 'day-tar-percent', 'day-thr-percent',
'night-avg-glucose', 'night-std-glucose', 'night-tir-percent', 'night-tar-percent', 'night-thr-percent',
'all-avg-glucose-main', 'all-std-glucose-main', 'all-tir-percent-main', 'all-tar-percent-main', 'all-thr-percent-main',
'day-avg-glucose-main', 'day-std-glucose-main', 'day-tir-percent-main', 'day-tar-percent-main', 'day-thr-percent-main',
'night-avg-glucose-main', 'night-std-glucose-main', 'night-tir-percent-main', 'night-tar-percent-main', 'night-thr-percent-main',
'max-glucose-value-main', 'max-glucose-time-main', 'max-glucose-period-main',
'min-glucose-value-main', 'min-glucose-time-main', 'min-glucose-period-main'
];
ids.forEach(id => setElementText(id, '--'));
}
// 计算血糖极值和时间点
function calculateExtremeValues(data) {
if (!data || data.length === 0) {
return {
maxValue: null,
maxTime: null,
maxPeriod: null,
minValue: null,
minTime: null,
minPeriod: null
};
}
const validData = data.filter(item => item.glucose != null && !isNaN(item.glucose) && item.originalTime);
if (validData.length === 0) {
return {
maxValue: null,
maxTime: null,
maxPeriod: null,
minValue: null,
minTime: null,
minPeriod: null
};
}
// 找到最高血糖
const maxItem = validData.reduce((max, current) =>
current.glucose > max.glucose ? current : max
);
// 找到最低血糖
const minItem = validData.reduce((min, current) =>
current.glucose < min.glucose ? current : min
);
// 判断时段分类的函数
const getPeriodName = (timeStr) => {
const hour = new Date(timeStr).getHours();
if (hour >= 8 && hour < 22) {
return '白天';
} else {
return '夜间';
}
};
// 格式化时间显示
const formatTime = (timeStr) => {
const date = new Date(timeStr);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${month}/${day} ${hours}:${minutes}`;
};
return {
maxValue: maxItem.glucose,
maxTime: formatTime(maxItem.originalTime),
maxPeriod: getPeriodName(maxItem.originalTime),
minValue: minItem.glucose,
minTime: formatTime(minItem.originalTime),
minPeriod: getPeriodName(minItem.originalTime)
};
}
// 计算统计数据
function calculateStatistics(data) {
const daytimeData = data.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour >= 8 && hour < 22; // 白天定义为8点到22点
});
const nighttimeData = data.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour < 8 || hour >= 22; // 夜间定义为22点到次日8点
});
const calculatePeriodStats = (periodData) => {
if (periodData.length === 0) {
return {
avgGlucose: undefined,
stdGlucose: undefined,
tirPercent: undefined,
tarPercent: undefined,
thrPercent: undefined,
};
}
const glucoseValues = periodData.map(d => d.glucose).filter(v => v != null && !isNaN(v));
const avg = (arr) => arr.length > 0 ? arr.reduce((a, b) => a + b, 0) / arr.length : undefined;
const std = (arr, avgVal) => {
if (arr.length === 0 || avgVal === undefined) return undefined;
const variance = arr.reduce((sum, val) => sum + Math.pow(val - avgVal, 2), 0) / arr.length;
return Math.sqrt(variance);
};
const avgGlc = avg(glucoseValues);
const stdGlc = std(glucoseValues, avgGlc);
// 血糖分层阈值 (mmol/L)
const LOW_GLUCOSE_THRESHOLD = 3.9;
const HIGH_GLUCOSE_THRESHOLD = 10.0;
const tirCount = glucoseValues.filter(v => v >= LOW_GLUCOSE_THRESHOLD && v < HIGH_GLUCOSE_THRESHOLD).length;
const tarCount = glucoseValues.filter(v => v < LOW_GLUCOSE_THRESHOLD).length;
const thrCount = glucoseValues.filter(v => v >= HIGH_GLUCOSE_THRESHOLD).length;
const totalCount = glucoseValues.length;
return {
avgGlucose: avgGlc,
stdGlucose: stdGlc,
tirPercent: totalCount > 0 ? (tirCount / totalCount) * 100 : 0,
tarPercent: totalCount > 0 ? (tarCount / totalCount) * 100 : 0,
thrPercent: totalCount > 0 ? (thrCount / totalCount) * 100 : 0,
};
};
return {
all: calculatePeriodStats(data),
day: calculatePeriodStats(daytimeData),
night: calculatePeriodStats(nighttimeData)
};
}
// 渲染所有图表
function renderAllCharts() {
if (!chartDataTable || chartDataTable.length === 0) {
const chartContainers = document.querySelectorAll('[id$="chart"], .chart, [id^="pie-glucose"]');
chartContainers.forEach(container => {
if (container) {
container.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100%;color:#999;">暂无数据</div>';
}
});
return;
}
try {
// 渲染第一页的血糖趋势图
renderGlucoseTrendChart();
// 第一页现在使用统计表格,不需要渲染饼图
renderDetailPagePieCharts();
} catch (error) {
console.error('渲染图表过程中出错:', error);
}
}
// 渲染血糖趋势图
function renderGlucoseTrendChart() {
const chartContainer = document.getElementById('glucose-trend-chart');
if (!chartContainer) {
console.warn('未找到血糖趋势图容器');
return;
}
const chart = echarts.init(chartContainer);
if (!chartDataTable || chartDataTable.length === 0) {
const option = {
title: { text: '暂无数据', left: 'center', top: 'middle' },
grid: { left: 50, right: 20, bottom: 40, top: 30 }
};
chart.setOption(option);
return;
}
// 按时间排序数据
const sortedData = [...chartDataTable].sort((a, b) => {
return new Date(a.originalTime).getTime() - new Date(b.originalTime).getTime();
});
// 提取时间和血糖值
const timeData = sortedData.map(item => {
const date = new Date(item.originalTime);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${month}-${day} ${hours}:${minutes}`;
});
const glucoseData = sortedData.map(item => item.glucose);
// 血糖分类函数
const getGlucoseStatus = (glucoseValue) => {
if (glucoseValue < 3.9) return '低血糖';
if (glucoseValue > 10.0) return '高血糖';
return '正常血糖';
};
const option = {
title: {
text: '血糖趋势统计图',
left: 'center',
textStyle: {
fontSize: 18,
fontWeight: 'bold'
}
},
tooltip: {
trigger: 'axis',
position: function (pt) {
return [pt[0], '10%'];
},
formatter: function (params) {
const dataIndex = params[0].dataIndex;
const time = timeData[dataIndex];
const value = params[0].value;
const status = getGlucoseStatus(value);
return `时间: ${time}<br/>血糖值: ${value} mmol/L<br/>状态: ${status}`;
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: timeData
},
yAxis: {
type: 'value',
boundaryGap: [0, '100%'],
name: '血糖值 (mmol/L)'
},
series: [
{
name: '血糖值',
type: 'line',
symbol: 'circle',
symbolSize: 4,
sampling: 'lttb',
itemStyle: {
color: 'rgb(255, 70, 131)'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(255, 158, 68, 0.8)'
},
{
offset: 1,
color: 'rgba(255, 70, 131, 0.1)'
}
]
}
},
data: glucoseData
}
]
};
chart.setOption(option);
}
// 渲染第三页的饼图
function renderDetailPagePieCharts() {
renderPieChart('pie-glucose-day', getDaytimeData());
renderPieChart('pie-glucose-night', getNighttimeData());
renderPieChart('pie-glucose-all', chartDataTable);
}
// 渲染单个饼图
function renderPieChart(elementId, data) {
const chart = echarts.init(document.getElementById(elementId));
const glucoseValues = data.map(item => item.glucose).filter(v => v != null && !isNaN(v));
// 确定图例前缀
let legendPrefix = '';
if (elementId === 'pie-glucose-day') {
legendPrefix = 'day';
} else if (elementId === 'pie-glucose-night') {
legendPrefix = 'night';
} else if (elementId === 'pie-glucose-all') {
legendPrefix = 'all';
}
if (glucoseValues.length === 0) {
const option = {
title: { text: '暂无数据', left: 'center', top: 'middle' },
grid: { left: 50, right: 20, bottom: 40, top: 30 }
};
chart.setOption(option);
// 更新图例显示为无数据
if (legendPrefix) {
document.getElementById(`${legendPrefix}-low-percent`).textContent = '占0%';
document.getElementById(`${legendPrefix}-normal-percent`).textContent = '占0%';
document.getElementById(`${legendPrefix}-high-percent`).textContent = '占0%';
}
return;
}
const LOW_GLUCOSE_THRESHOLD = 3.9;
const HIGH_GLUCOSE_THRESHOLD = 10.0;
const lowCount = glucoseValues.filter(v => v < LOW_GLUCOSE_THRESHOLD).length;
const targetCount = glucoseValues.filter(v => v >= LOW_GLUCOSE_THRESHOLD && v < HIGH_GLUCOSE_THRESHOLD).length;
const highCount = glucoseValues.filter(v => v >= HIGH_GLUCOSE_THRESHOLD).length;
const totalCount = glucoseValues.length;
// 计算百分比
const lowPercentage = ((lowCount / totalCount) * 100).toFixed(1);
const normalPercentage = ((targetCount / totalCount) * 100).toFixed(1);
const highPercentage = ((highCount / totalCount) * 100).toFixed(1);
// 更新图例百分比显示
if (legendPrefix) {
document.getElementById(`${legendPrefix}-low-percent`).textContent = `${lowPercentage}%`;
document.getElementById(`${legendPrefix}-normal-percent`).textContent = `${normalPercentage}%`;
document.getElementById(`${legendPrefix}-high-percent`).textContent = `${highPercentage}%`;
}
const pieData = [];
if (lowCount > 0) {
pieData.push({
value: lowCount,
name: '低血糖',
itemStyle: { color: '#ff7f7f' },
label: {
formatter: `低血糖: ${lowCount} (${lowPercentage}%)`
}
});
}
if (targetCount > 0) {
pieData.push({
value: targetCount,
name: '正常血糖',
itemStyle: { color: '#7fc7ff' },
label: {
formatter: `正常血糖: ${targetCount} (${normalPercentage}%)`
}
});
}
if (highCount > 0) {
pieData.push({
value: highCount,
name: '高血糖',
itemStyle: { color: '#e6a23c' },
label: {
formatter: `高血糖: ${highCount} (${highPercentage}%)`
}
});
}
if (pieData.length === 0) pieData.push({ value: 1, name: '暂无数据', itemStyle: { color: '#f0f0f0' } });
const option = {
tooltip: {
trigger: 'item',
formatter: function(params) {
if (params.name === '暂无数据') {
return '暂无数据';
}
const percentage = ((params.value / totalCount) * 100).toFixed(1);
return `${params.name}: ${params.value} (${percentage}%)`;
}
},
legend: {
show: false // 隐藏图例,使用右侧的自定义图例
},
series: [{
type: 'pie',
radius: ['40%', '70%'], // 调整环形饼图大小
center: ['50%', '50%'], // 居中显示
data: pieData,
label: {
show: false // 隐藏饼图内部的百分比显示
},
labelLine: {
show: false
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.3)'
},
scale: true,
scaleSize: 5
},
animationType: 'scale',
animationEasing: 'elasticOut',
animationDelay: function (idx) {
return Math.random() * 200;
}
}]
};
chart.setOption(option);
}
// 辅助函数
function getDaytimeData() {
return chartDataTable.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour >= 8 && hour < 22;
});
}
function getNighttimeData() {
return chartDataTable.filter(item => {
const hour = new Date(item.originalTime).getHours();
return hour < 8 || hour >= 22;
});
}
// 暴露全局函数供外部调用
window.initializeCGMReport = initializeReport;
// 页面打印函数
window.printReport = function() {
window.print();
};
// 页面导出PDF函数
window.exportToPDF = function() {
alert('PDF导出功能开发中...');
};
// 监听来自父窗口的消息
window.addEventListener('message', function(event) {
showLoading();
if (event.data && event.data.type === 'INIT_CGM_REPORT') {
const receivedData = event.data.data;
setTimeout(() => {
try {
initializeReport(receivedData);
} catch (error) {
console.error('初始化报告数据失败:', error);
}
}, 500);
}
});
// 创建测试数据
function createTestData() {
showLoading();
const testData = {
patientData: {
name: '张三',
gender: '男',
age: '50岁',
orgname: '健康中心',
device: 'CGM设备',
recordStartTime: '2025-07-20 00:00:00',
recordEndTime: '2025-07-21 23:59:59',
recordDuration: '48小时',
avgGlucose: 7.5,
maxGlucose: 15.2,
maxGlucoseTime: '10:30',
minGlucose: 2.8,
minGlucoseTime: '03:15',
glucoseCV: 30.5,
glucoseGMI: 7.2,
tirPercent: 70.0,
tarPercent: 5.0,
thrPercent: 25.0,
wearTime: '2025-07-20'
},
chartDataTable: [
{ originalTime: '2025-07-20 00:00:00', glucose: 6.5 },
{ originalTime: '2025-07-20 01:00:00', glucose: 5.8 },
{ originalTime: '2025-07-20 02:00:00', glucose: 4.2 },
{ originalTime: '2025-07-20 03:00:00', glucose: 3.5 },
{ originalTime: '2025-07-20 03:15:00', glucose: 2.8 }, // 最低血糖
{ originalTime: '2025-07-20 04:00:00', glucose: 3.0 },
{ originalTime: '2025-07-20 05:00:00', glucose: 3.8 },
{ originalTime: '2025-07-20 06:00:00', glucose: 4.5 },
{ originalTime: '2025-07-20 07:00:00', glucose: 5.2 },
{ originalTime: '2025-07-20 08:00:00', glucose: 6.0 },
{ originalTime: '2025-07-20 09:00:00', glucose: 8.5 },
{ originalTime: '2025-07-20 10:00:00', glucose: 12.0 },
{ originalTime: '2025-07-20 10:30:00', glucose: 15.2 }, // 最高血糖
{ originalTime: '2025-07-20 11:00:00', glucose: 13.0 },
{ originalTime: '2025-07-20 12:00:00', glucose: 9.5 },
{ originalTime: '2025-07-20 13:00:00', glucose: 7.0 },
{ originalTime: '2025-07-20 14:00:00', glucose: 6.8 },
{ originalTime: '2025-07-20 15:00:00', glucose: 7.2 },
{ originalTime: '2025-07-20 16:00:00', glucose: 8.0 },
{ originalTime: '2025-07-20 17:00:00', glucose: 9.0 },
{ originalTime: '2025-07-20 18:00:00', glucose: 11.0 },
{ originalTime: '2025-07-20 19:00:00', glucose: 10.5 },
{ originalTime: '2025-07-20 20:00:00', glucose: 9.8 },
{ originalTime: '2025-07-20 21:00:00', glucose: 8.2 },
{ originalTime: '2025-07-20 22:00:00', glucose: 7.0 },
{ originalTime: '2025-07-20 23:00:00', glucose: 6.0 },
{ originalTime: '2025-07-21 00:00:00', glucose: 5.5 },
{ originalTime: '2025-07-21 01:00:00', glucose: 5.0 },
{ originalTime: '2025-07-21 02:00:00', glucose: 4.0 },
{ originalTime: '2025-07-21 03:00:00', glucose: 3.2 },
{ originalTime: '2025-07-21 04:00:00', glucose: 3.5 },
{ originalTime: '2025-07-21 05:00:00', glucose: 4.0 },
{ originalTime: '2025-07-21 06:00:00', glucose: 5.0 },
{ originalTime: '2025-07-21 07:00:00', glucose: 6.0 },
{ originalTime: '2025-07-21 08:00:00', glucose: 7.0 },
{ originalTime: '2025-07-21 09:00:00', glucose: 9.0 },
{ originalTime: '2025-07-21 10:00:00', glucose: 11.0 },
{ originalTime: '2025-07-21 11:00:00', glucose: 10.0 },
{ originalTime: '2025-07-21 12:00:00', glucose: 8.0 },
{ originalTime: '2025-07-21 13:00:00', glucose: 7.5 },
{ originalTime: '2025-07-21 14:00:00', glucose: 7.0 },
{ originalTime: '2025-07-21 15:00:00', glucose: 7.8 },
{ originalTime: '2025-07-21 16:00:00', glucose: 8.5 },
{ originalTime: '2025-07-21 17:00:00', glucose: 9.2 },
{ originalTime: '2025-07-21 18:00:00', glucose: 10.0 },
{ originalTime: '2025-07-21 19:00:00', glucose: 9.5 },
{ originalTime: '2025-07-21 20:00:00', glucose: 8.8 },
{ originalTime: '2025-07-21 21:00:00', glucose: 7.5 },
{ originalTime: '2025-07-21 22:00:00', glucose: 6.5 },
{ originalTime: '2025-07-21 23:00:00', glucose: 5.8 },
{ originalTime: '2025-07-21 23:59:59', glucose: 5.2 }
],
analysisResult: '该患者动态血糖监测报告显示,血糖波动较大,存在高血糖和低血糖风险。建议进一步调整饮食和运动,并密切监测血糖。'
};
initializeReport(testData);
}
document.addEventListener('DOMContentLoaded', function() {
showLoading();
if (window.opener) {
window.opener.postMessage({
type: 'CGM_TEMPLATE_LOADED'
}, '*');
} else {
setTimeout(() => {
createTestData();
}, 3000);
}
});
function showLoading() {
const mask = document.getElementById('loading-mask');
if (mask) mask.style.display = 'flex';
document.body.style.overflow = 'hidden';
}
function hideLoading() {
const mask = document.getElementById('loading-mask');
if (mask) mask.style.display = 'none';
document.body.style.overflow = '';
}
function showDebugInfo(message) {
// For debugging purposes, can be removed in final version
// console.log(message);
}
</script>
</body>
</html>