Files
my_git_project/CardioAI/module2_predictor/templates/index.html
zhenchuan199 b5b299a682 Add CardioAI project with usage instructions
- Add comprehensive README.md with setup and usage instructions
- Add .env.example template (sanitized, no real API keys)
- Add root-level .gitignore to exclude .env and generated files
- Add all project modules (dashboard, predictor)
- Add data file and requirements.txt
2026-04-02 20:11:24 +08:00

1061 lines
37 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-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CardioAI 心血管疾病风险预测</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--success-gradient: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
--warning-gradient: linear-gradient(135deg, #f39c12 0%, #e74c3c 100%);
--danger-gradient: linear-gradient(135deg, #ff416c 0%, #ff4b2b 100%);
--glass-bg: rgba(255, 255, 255, 0.95);
--glass-border: rgba(255, 255, 255, 0.3);
--shadow-soft: 0 10px 40px rgba(0, 0, 0, 0.1);
--shadow-hover: 0 20px 60px rgba(0, 0, 0, 0.15);
}
body {
font-family: 'Noto Sans SC', -apple-system, BlinkMacSystemFont, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
min-height: 100vh;
padding: 1rem;
background-attachment: fixed;
}
.container {
max-width: 1000px;
margin: 0 auto;
animation: fadeInUp 0.6s ease;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 2rem;
padding: 1rem 0;
}
.logo-container {
display: inline-flex;
align-items: center;
gap: 1rem;
margin-bottom: 0.5rem;
}
.logo-icon {
width: 60px;
height: 60px;
background: var(--glass-bg);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
box-shadow: var(--shadow-soft);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.header h1 {
color: white;
font-size: 2.5rem;
font-weight: 700;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
letter-spacing: -1px;
}
.header p {
color: rgba(255,255,255,0.9);
font-size: 1.1rem;
font-weight: 300;
}
/* 主卡片 - 玻璃拟态 */
.main-card {
background: var(--glass-bg);
backdrop-filter: blur(20px);
border-radius: 24px;
box-shadow: var(--shadow-soft);
overflow: hidden;
border: 1px solid var(--glass-border);
}
/* 结果区域 */
.result-section {
background: var(--success-gradient);
padding: 3rem 2rem;
text-align: center;
display: none;
animation: slideDown 0.5s ease;
}
.result-section.show {
display: block;
}
.result-section.risk-high {
background: var(--danger-gradient);
}
.result-section.risk-medium {
background: var(--warning-gradient);
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.result-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(255,255,255,0.2);
padding: 0.5rem 1rem;
border-radius: 50px;
color: white;
font-size: 0.9rem;
margin-bottom: 1rem;
backdrop-filter: blur(10px);
}
.result-icon {
width: 80px;
height: 80px;
background: rgba(255,255,255,0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
margin: 0 auto 1.5rem;
backdrop-filter: blur(10px);
border: 3px solid rgba(255,255,255,0.3);
animation: bounceIn 0.6s ease;
}
@keyframes bounceIn {
0% { transform: scale(0); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.result-title {
color: white;
font-size: 2rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.result-probability-container {
margin: 2rem 0;
}
.result-probability {
color: white;
font-size: 4rem;
font-weight: 700;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}
.result-label {
color: rgba(255,255,255,0.9);
font-size: 1rem;
margin-top: 0.5rem;
}
/* 风险进度条 */
.risk-bar-container {
max-width: 400px;
margin: 1.5rem auto;
background: rgba(255,255,255,0.2);
border-radius: 10px;
height: 12px;
overflow: hidden;
}
.risk-bar {
height: 100%;
background: rgba(255,255,255,0.9);
border-radius: 10px;
transition: width 1s ease;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.risk-levels {
display: flex;
justify-content: space-between;
max-width: 400px;
margin: 0.5rem auto;
color: rgba(255,255,255,0.7);
font-size: 0.75rem;
}
/* 推荐卡片 */
.recommendation {
background: rgba(255,255,255,0.15);
border-radius: 16px;
padding: 1.5rem;
margin-top: 2rem;
color: white;
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.2);
max-width: 500px;
margin-left: auto;
margin-right: auto;
}
.recommendation-title {
font-weight: 600;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.recommendation-text {
font-size: 1rem;
line-height: 1.6;
opacity: 0.95;
}
/* 详情网格 */
.result-details {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
max-width: 600px;
margin: 2rem auto;
}
.detail-card {
background: rgba(255,255,255,0.1);
border-radius: 12px;
padding: 1rem;
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.2);
}
.detail-label {
font-size: 0.8rem;
color: rgba(255,255,255,0.8);
margin-bottom: 0.3rem;
}
.detail-value {
font-size: 1.3rem;
font-weight: 600;
color: white;
}
/* 表单区域 */
.form-section {
padding: 2.5rem;
}
.section-header {
text-align: center;
margin-bottom: 2rem;
}
.section-title {
color: #333;
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.section-subtitle {
color: #888;
font-size: 0.95rem;
}
/* 表单卡片 */
.form-card {
background: #f8f9fa;
border-radius: 16px;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid #e9ecef;
transition: all 0.3s ease;
}
.form-card:hover {
box-shadow: var(--shadow-soft);
transform: translateY(-2px);
}
.card-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1.5rem;
padding-bottom: 0.75rem;
border-bottom: 2px solid #e9ecef;
}
.card-icon {
width: 36px;
height: 36px;
background: var(--primary-gradient);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1rem;
}
.card-title {
color: #333;
font-size: 1.1rem;
font-weight: 600;
}
/* 表单网格 */
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.25rem;
}
.form-group {
position: relative;
}
.form-group label {
display: flex;
align-items: center;
gap: 0.25rem;
color: #555;
font-size: 0.9rem;
font-weight: 500;
margin-bottom: 0.5rem;
}
.required {
color: #e74c3c;
}
.input-wrapper {
position: relative;
}
.input-icon {
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: #999;
font-size: 1rem;
}
.form-group input,
.form-group select {
width: 100%;
padding: 0.9rem 1rem 0.9rem 2.8rem;
border: 2px solid #e0e0e0;
border-radius: 12px;
font-size: 1rem;
font-family: inherit;
transition: all 0.3s ease;
background: white;
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
}
.form-hint {
font-size: 0.75rem;
color: #888;
margin-top: 0.4rem;
display: flex;
align-items: center;
gap: 0.3rem;
}
/* BMI 实时显示 */
.bmi-display {
background: var(--primary-gradient);
color: white;
padding: 1rem 1.5rem;
border-radius: 12px;
margin-top: 1rem;
display: flex;
align-items: center;
justify-content: space-between;
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s ease;
}
.bmi-display.show {
opacity: 1;
transform: translateY(0);
}
.bmi-label {
font-size: 0.9rem;
opacity: 0.9;
}
.bmi-value {
font-size: 1.5rem;
font-weight: 700;
}
/* 按钮 */
.btn-container {
display: flex;
gap: 1rem;
margin-top: 2rem;
}
.btn {
flex: 1;
padding: 1rem 2rem;
border: none;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
font-family: inherit;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.btn-primary {
background: var(--primary-gradient);
color: white;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
}
.btn-secondary {
background: #f0f0f0;
color: #666;
}
.btn-secondary:hover {
background: #e0e0e0;
}
.btn-outline {
background: transparent;
border: 2px solid rgba(255,255,255,0.5);
color: white;
}
.btn-outline:hover {
background: rgba(255,255,255,0.1);
border-color: white;
}
/* 加载状态 */
.loading {
display: none;
text-align: center;
padding: 4rem 2rem;
}
.loading.show {
display: block;
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.spinner-container {
position: relative;
width: 80px;
height: 80px;
margin: 0 auto 1.5rem;
}
.spinner {
width: 80px;
height: 80px;
border: 4px solid rgba(102, 126, 234, 0.1);
border-top-color: #667eea;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.spinner-inner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.5rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading-text {
color: #666;
font-size: 1.1rem;
}
.loading-dots::after {
content: '';
animation: dots 1.5s infinite;
}
@keyframes dots {
0%, 20% { content: '.'; }
40% { content: '..'; }
60%, 100% { content: '...'; }
}
/* 页脚 */
.footer {
text-align: center;
padding: 2rem 1rem;
color: rgba(255,255,255,0.8);
font-size: 0.9rem;
}
.footer-links {
margin-top: 0.5rem;
display: flex;
justify-content: center;
gap: 1.5rem;
}
.footer-links a {
color: rgba(255,255,255,0.8);
text-decoration: none;
transition: color 0.3s;
}
.footer-links a:hover {
color: white;
}
/* 错误提示 */
.error-message {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
color: white;
padding: 1rem 1.5rem;
border-radius: 12px;
margin-bottom: 1.5rem;
display: none;
animation: shake 0.5s ease;
}
.error-message.show {
display: flex;
align-items: center;
gap: 0.75rem;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10px); }
75% { transform: translateX(10px); }
}
/* 响应式 */
@media (max-width: 768px) {
body {
padding: 0.5rem;
}
.header h1 {
font-size: 1.8rem;
}
.form-section {
padding: 1.5rem;
}
.form-grid {
grid-template-columns: 1fr;
}
.btn-container {
flex-direction: column;
}
.result-probability {
font-size: 3rem;
}
.result-details {
grid-template-columns: repeat(2, 1fr);
}
}
</style>
</head>
<body>
<div class="container">
<!-- 头部 -->
<div class="header">
<div class="logo-container">
<div class="logo-icon">❤️</div>
<h1>CardioAI</h1>
</div>
<p>智能心血管疾病风险预测系统</p>
</div>
<!-- 主卡片 -->
<div class="main-card">
<!-- 结果展示区域 -->
<div id="resultSection" class="result-section">
<div class="result-badge" id="resultBadge">
<i class="fas fa-shield-alt"></i>
<span>AI 分析完成</span>
</div>
<div class="result-icon" id="resultIcon">
<i class="fas fa-check-circle"></i>
</div>
<div class="result-title" id="resultTitle">健康状态良好</div>
<div class="result-probability-container">
<div class="result-probability" id="resultProbability">0%</div>
<div class="result-label">心血管疾病风险概率</div>
</div>
<!-- 风险进度条 -->
<div class="risk-bar-container">
<div class="risk-bar" id="riskBar" style="width: 0%"></div>
</div>
<div class="risk-levels">
<span>低风险</span>
<span>中风险</span>
<span>高风险</span>
</div>
<!-- 详情卡片 -->
<div class="result-details">
<div class="detail-card">
<div class="detail-label">BMI 指数</div>
<div class="detail-value" id="detailBMI">--</div>
</div>
<div class="detail-card">
<div class="detail-label">血压状态</div>
<div class="detail-value" id="detailBP">--</div>
</div>
<div class="detail-card">
<div class="detail-label">健康评分</div>
<div class="detail-value" id="detailScore">--</div>
</div>
</div>
<!-- 推荐 -->
<div class="recommendation">
<div class="recommendation-title">
<i class="fas fa-lightbulb"></i>
<span>健康建议</span>
</div>
<div class="recommendation-text" id="recommendation">
继续保持健康的生活方式
</div>
</div>
<!-- 返回按钮 -->
<div class="btn-container" style="margin-top: 2rem; max-width: 300px; margin-left: auto; margin-right: auto;">
<button type="button" class="btn btn-outline" onclick="resetForm()">
<i class="fas fa-redo"></i>
再次预测
</button>
</div>
</div>
<!-- 加载状态 -->
<div id="loadingSection" class="loading">
<div class="spinner-container">
<div class="spinner"></div>
<div class="spinner-inner">🫀</div>
</div>
<div class="loading-text">
AI 正在分析您的健康数据<span class="loading-dots"></span>
</div>
<p style="color: #999; font-size: 0.9rem; margin-top: 0.5rem;">请稍候</p>
</div>
<!-- 表单区域 -->
<div id="formSection" class="form-section">
<div id="errorMessage" class="error-message">
<i class="fas fa-exclamation-circle"></i>
<span id="errorText"></span>
</div>
<div class="section-header">
<h2 class="section-title">
<i class="fas fa-clipboard-list"></i>
健康信息录入
</h2>
<p class="section-subtitle">请填写以下信息AI 将为您评估心血管疾病风险</p>
</div>
<form id="predictForm">
<!-- 基本信息 -->
<div class="form-card">
<div class="card-header">
<div class="card-icon"><i class="fas fa-user"></i></div>
<div class="card-title">基本信息</div>
</div>
<div class="form-grid">
<div class="form-group">
<label>年龄 <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-birthday-cake input-icon"></i>
<input type="number" id="age_years" min="18" max="120" required placeholder="例如45">
</div>
<div class="form-hint"><i class="fas fa-info-circle"></i> 年龄范围 18-120 岁</div>
</div>
<div class="form-group">
<label>性别 <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-venus-mars input-icon"></i>
<select id="gender" required>
<option value="">请选择</option>
<option value="1">👩 女性</option>
<option value="2">👨 男性</option>
</select>
</div>
</div>
<div class="form-group">
<label>身高 (cm) <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-ruler-vertical input-icon"></i>
<input type="number" id="height" min="100" max="250" required placeholder="例如170">
</div>
</div>
<div class="form-group">
<label>体重 (kg) <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-weight input-icon"></i>
<input type="number" id="weight" min="30" max="300" required placeholder="例如65">
</div>
</div>
</div>
<!-- BMI 实时显示 -->
<div class="bmi-display" id="bmiDisplay">
<span class="bmi-label">BMI 指数</span>
<span class="bmi-value" id="bmiValue">--</span>
</div>
</div>
<!-- 血压信息 -->
<div class="form-card">
<div class="card-header">
<div class="card-icon"><i class="fas fa-heartbeat"></i></div>
<div class="card-title">血压信息</div>
</div>
<div class="form-grid">
<div class="form-group">
<label>收缩压 / 高压 (mmHg) <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-arrow-up input-icon"></i>
<input type="number" id="ap_hi" min="90" max="250" required placeholder="例如120">
</div>
<div class="form-hint"><i class="fas fa-info-circle"></i> 正常范围90-140 mmHg</div>
</div>
<div class="form-group">
<label>舒张压 / 低压 (mmHg) <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-arrow-down input-icon"></i>
<input type="number" id="ap_lo" min="60" max="150" required placeholder="例如80">
</div>
<div class="form-hint"><i class="fas fa-info-circle"></i> 正常范围60-90 mmHg</div>
</div>
</div>
</div>
<!-- 生化指标 -->
<div class="form-card">
<div class="card-header">
<div class="card-icon"><i class="fas fa-flask"></i></div>
<div class="card-title">生化指标</div>
</div>
<div class="form-grid">
<div class="form-group">
<label>胆固醇水平 <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-vial input-icon"></i>
<select id="cholesterol" required>
<option value="">请选择</option>
<option value="1">🟢 正常</option>
<option value="2">🟡 偏高</option>
<option value="3">🔴 非常高</option>
</select>
</div>
</div>
<div class="form-group">
<label>血糖水平 <span class="required">*</span></label>
<div class="input-wrapper">
<i class="fas fa-tint input-icon"></i>
<select id="gluc" required>
<option value="">请选择</option>
<option value="1">🟢 正常</option>
<option value="2">🟡 偏高</option>
<option value="3">🔴 非常高</option>
</select>
</div>
</div>
</div>
</div>
<!-- 生活习惯 -->
<div class="form-card">
<div class="card-header">
<div class="card-icon"><i class="fas fa-running"></i></div>
<div class="card-title">生活习惯</div>
</div>
<div class="form-grid">
<div class="form-group">
<label>吸烟状况</label>
<div class="input-wrapper">
<i class="fas fa-smoking input-icon"></i>
<select id="smoke">
<option value="0">🚭 不吸烟</option>
<option value="1">🚬 吸烟</option>
</select>
</div>
</div>
<div class="form-group">
<label>饮酒状况</label>
<div class="input-wrapper">
<i class="fas fa-wine-glass input-icon"></i>
<select id="alco">
<option value="0">🍵 不饮酒</option>
<option value="1">🍷 饮酒</option>
</select>
</div>
</div>
<div class="form-group">
<label>运动习惯</label>
<div class="input-wrapper">
<i class="fas fa-dumbbell input-icon"></i>
<select id="active">
<option value="1">🏃 经常运动</option>
<option value="0">🛋️ 缺乏运动</option>
</select>
</div>
</div>
</div>
</div>
<!-- 按钮 -->
<div class="btn-container">
<button type="button" class="btn btn-secondary" onclick="resetForm()">
<i class="fas fa-undo"></i>
重置
</button>
<button type="submit" class="btn btn-primary">
<i class="fas fa-stethoscope"></i>
开始 AI 分析
</button>
</div>
</form>
</div>
</div>
<!-- 页脚 -->
<div class="footer">
<p>CardioAI © 2024 | 心血管疾病智能分析系统</p>
<div class="footer-links">
<a href="#"><i class="fas fa-shield-alt"></i> 隐私保护</a>
<a href="#"><i class="fas fa-info-circle"></i> 使用说明</a>
<a href="#"><i class="fas fa-envelope"></i> 联系我们</a>
</div>
</div>
</div>
<script>
// BMI 实时计算
function updateBMI() {
const height = parseFloat(document.getElementById('height').value);
const weight = parseFloat(document.getElementById('weight').value);
const bmiDisplay = document.getElementById('bmiDisplay');
const bmiValue = document.getElementById('bmiValue');
if (height > 0 && weight > 0) {
const bmi = (weight / Math.pow(height / 100, 2)).toFixed(1);
bmiValue.textContent = bmi;
bmiDisplay.classList.add('show');
} else {
bmiDisplay.classList.remove('show');
}
}
document.getElementById('height').addEventListener('input', updateBMI);
document.getElementById('weight').addEventListener('input', updateBMI);
// 表单提交
document.getElementById('predictForm').addEventListener('submit', async function(e) {
e.preventDefault();
// 收集表单数据
const formData = {
age_years: parseInt(document.getElementById('age_years').value),
gender: parseInt(document.getElementById('gender').value),
height: parseInt(document.getElementById('height').value),
weight: parseFloat(document.getElementById('weight').value),
ap_hi: parseInt(document.getElementById('ap_hi').value),
ap_lo: parseInt(document.getElementById('ap_lo').value),
cholesterol: parseInt(document.getElementById('cholesterol').value),
gluc: parseInt(document.getElementById('gluc').value),
smoke: parseInt(document.getElementById('smoke').value),
alco: parseInt(document.getElementById('alco').value),
active: parseInt(document.getElementById('active').value)
};
// 显示加载状态
document.getElementById('formSection').style.display = 'none';
document.getElementById('loadingSection').classList.add('show');
document.getElementById('errorMessage').classList.remove('show');
try {
const response = await fetch('/predict_cardio', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
const result = await response.json();
if (result.success) {
showResult(result, formData);
} else {
showError(result.error || '预测失败,请重试');
}
} catch (error) {
showError('网络错误,请检查服务器连接');
}
});
// 显示结果
function showResult(result, data) {
document.getElementById('loadingSection').classList.remove('show');
document.getElementById('resultSection').classList.add('show');
const probability = result.probability['有风险'];
const resultSection = document.getElementById('resultSection');
// 设置风险样式
resultSection.classList.remove('risk-high', 'risk-medium');
if (probability >= 70) {
resultSection.classList.add('risk-high');
document.getElementById('resultIcon').innerHTML = '<i class="fas fa-exclamation-triangle"></i>';
document.getElementById('resultTitle').textContent = '高风险警告';
document.getElementById('resultBadge').innerHTML = '<i class="fas fa-exclamation-circle"></i><span>需要关注</span>';
} else if (probability >= 50) {
resultSection.classList.add('risk-medium');
document.getElementById('resultIcon').innerHTML = '<i class="fas fa-exclamation"></i>';
document.getElementById('resultTitle').textContent = '中度风险';
document.getElementById('resultBadge').innerHTML = '<i class="fas fa-bell"></i><span>建议预防</span>';
} else if (probability >= 30) {
document.getElementById('resultIcon').innerHTML = '<i class="fas fa-info-circle"></i>';
document.getElementById('resultTitle').textContent = '轻度风险';
document.getElementById('resultBadge').innerHTML = '<i class="fas fa-info"></i><span>注意观察</span>';
} else {
document.getElementById('resultIcon').innerHTML = '<i class="fas fa-check-circle"></i>';
document.getElementById('resultTitle').textContent = '健康状态良好';
document.getElementById('resultBadge').innerHTML = '<i class="fas fa-shield-alt"></i><span>状态良好</span>';
}
// 设置概率
document.getElementById('resultProbability').textContent = probability + '%';
document.getElementById('recommendation').textContent = result.recommendation;
// 动画进度条
setTimeout(() => {
document.getElementById('riskBar').style.width = probability + '%';
}, 300);
// 计算并显示详情
const bmi = (data.weight / Math.pow(data.height / 100, 2)).toFixed(1);
document.getElementById('detailBMI').textContent = bmi;
// 血压状态
const ap_hi = data.ap_hi;
const ap_lo = data.ap_lo;
let bpStatus = '正常';
if (ap_hi > 140 || ap_lo > 90) bpStatus = '偏高';
else if (ap_hi < 90 || ap_lo < 60) bpStatus = '偏低';
document.getElementById('detailBP').textContent = bpStatus;
// 健康评分
const score = Math.max(0, 100 - Math.round(probability * 0.8));
document.getElementById('detailScore').textContent = score;
}
// 显示错误
function showError(message) {
document.getElementById('loadingSection').classList.remove('show');
document.getElementById('formSection').style.display = 'block';
document.getElementById('errorText').textContent = message;
document.getElementById('errorMessage').classList.add('show');
}
// 重置表单
function resetForm() {
document.getElementById('predictForm').reset();
document.getElementById('resultSection').classList.remove('show');
document.getElementById('resultSection').classList.remove('risk-high', 'risk-medium');
document.getElementById('formSection').style.display = 'block';
document.getElementById('errorMessage').classList.remove('show');
document.getElementById('bmiDisplay').classList.remove('show');
document.getElementById('riskBar').style.width = '0%';
}
</script>
</body>
</html>