feat: 健康体检三端与医疗点PAD、体重管理多模块更新(员工端冠脉CTA体检接入:首页Banner新增第四张CTA暖红渐变卡片与圆点随张变色、reports页新增CTA报告条目共12份、新增cta-date/cta-hospital/report-cta四个CTA页面;医疗点PAD端:随访抽屉改为携带员工信息跳转goFollow带参回显、下次随访/随访效果/签字方式(手写+签字图片)/新增用药/巡诊任务(频次/单次/申请随诊)重构、单位名称规范化为采油一厂-信息部等、登录去掉校验直接进入系统、删除五类人群登记页;管理端健康体检:档案单位报表表头重做单层23列新增体检年份列与过程漏斗/疾病专项/费用三块口径、人数列点击弹窗人员名单+导出CSV、个人体检数据新增操作列查看报告弹窗、员工大表与个人档案新增异常员工下拉筛选、检前组合模板/例外配置/必检项目防癌筛查TAB融合、医院体检项目费用更名医院体检项目、检前侧边栏统一重建与CTA分组;管理端体重管理:结果异常页表格错位修复+异常判定收敛为五类指标+异常等级移除、PRD结果异常节同步;各模块CHANGELOG记录)
This commit is contained in:
@@ -172,9 +172,24 @@
|
||||
.project-card__meta {
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
}
|
||||
/* AI 推荐标签分三档,字号阶梯放大 + 深色实底强化等级对比:
|
||||
强烈推荐 12px 红橙实底 > 建议加做 11px 紫蓝实底 > 可选参考 10px 浅蓝描边 */
|
||||
.project-card__badge--ai {
|
||||
background: linear-gradient(135deg, #7c5cfc 0%, #4f8ef7 100%);
|
||||
color: #fff; cursor: pointer; box-shadow: 0 2px 6px rgba(124, 92, 252, 0.3);
|
||||
color: #fff; cursor: pointer; font-weight: 700;
|
||||
}
|
||||
.project-card__badge--ai-high {
|
||||
height: 26px; padding: 0 12px; border-radius: 13px; font-size: 12px;
|
||||
background: linear-gradient(135deg, #cf1322 0%, #f5222d 55%, #ff7a45 100%);
|
||||
box-shadow: 0 3px 8px rgba(207, 19, 34, 0.35);
|
||||
}
|
||||
.project-card__badge--ai-mid {
|
||||
height: 24px; padding: 0 11px; border-radius: 12px; font-size: 11px;
|
||||
background: linear-gradient(135deg, #531dab 0%, #722ed1 50%, #1677ff 100%);
|
||||
box-shadow: 0 2px 6px rgba(83, 29, 171, 0.35);
|
||||
}
|
||||
.project-card__badge--ai-low {
|
||||
height: 20px; padding: 0 8px; border-radius: 10px; font-size: 10px; font-weight: 600;
|
||||
background: #f0f5ff; color: #597ef7; border: 1px solid #d6e4ff;
|
||||
}
|
||||
.project-card__arrow {
|
||||
flex-shrink: 0; color: #d0d0d0; font-size: 16px; cursor: pointer;
|
||||
@@ -235,7 +250,15 @@
|
||||
/* AI 推荐理由弹窗 */
|
||||
.ai-modal { padding: 24px 20px 18px; }
|
||||
.ai-modal__project {
|
||||
font-size: 15px; font-weight: 700; color: #7c5cfc; text-align: center; margin-bottom: 12px;
|
||||
font-size: 15px; font-weight: 700; color: #7c5cfc; text-align: center; margin-bottom: 10px;
|
||||
}
|
||||
.ai-modal__level {
|
||||
display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 12px;
|
||||
}
|
||||
.ai-modal__level-cap { font-size: 12px; color: var(--text-muted); }
|
||||
.ai-modal__level-desc {
|
||||
font-size: 12px; line-height: 1.6; color: var(--text-secondary); text-align: center;
|
||||
margin: -4px 0 12px;
|
||||
}
|
||||
.ai-modal__reason {
|
||||
background: #f7f9fb; border-radius: 14px; padding: 14px 16px; margin-bottom: 18px;
|
||||
@@ -351,6 +374,11 @@
|
||||
<div class="confirm-modal ai-modal">
|
||||
<div class="confirm-modal__title">✨ 智能推荐</div>
|
||||
<div class="ai-modal__project" id="aiModalProject"></div>
|
||||
<div class="ai-modal__level">
|
||||
<span class="ai-modal__level-cap">推荐等级</span>
|
||||
<span class="project-card__badge" id="aiModalLevel"></span>
|
||||
</div>
|
||||
<div class="ai-modal__level-desc" id="aiModalLevelDesc"></div>
|
||||
<div class="ai-modal__reason" id="aiModalReason"></div>
|
||||
<button class="confirm-modal__btn confirm-modal__btn--primary ai-modal__close" onclick="closeAiReason()">知道了</button>
|
||||
</div>
|
||||
@@ -359,6 +387,12 @@
|
||||
<script>
|
||||
// 年度体检总额度(可用额度 = 总额度 − 已选项目费用,原型模拟数据)
|
||||
const annualLimit = 1600;
|
||||
// AI 推荐等级:3 强烈推荐(既往异常直接相关)> 2 建议加做(存在风险因素)> 1 可选参考(一般性补充筛查)
|
||||
const AI_LEVELS = {
|
||||
3: { label: '强烈推荐', cls: 'high', icon: '🔥', desc: '与您的既往异常发现直接相关,建议本年度务必完成。' },
|
||||
2: { label: '建议加做', cls: 'mid', icon: '✨', desc: '健康画像显示存在相关风险因素,建议在本年度体检中加做。' },
|
||||
1: { label: '可选参考', cls: 'low', icon: '✨', desc: '按年龄段与常见风险的一般性补充筛查,可结合剩余额度自行选择。' }
|
||||
};
|
||||
const projects = [
|
||||
{ id: 'general', name: '一般检查', desc: '身高、体重、血压、视力', price: 120, type: 'required', level: 'normal' },
|
||||
{ id: 'blood', name: '血常规', desc: '血红蛋白、白细胞、血小板等', price: 80, type: 'required', level: 'normal' },
|
||||
@@ -369,11 +403,11 @@
|
||||
{ id: 'glucose', name: '空腹血糖', desc: '空腹静脉血糖检测', price: 40, type: 'required', level: 'normal' },
|
||||
{ id: 'ecg', name: '心电图', desc: '十二导联心电图检查', price: 75, type: 'required', level: 'key' },
|
||||
{ id: 'xray', name: '胸部X光', desc: '胸部正位X线摄影', price: 140, type: 'optional', level: 'normal' },
|
||||
{ id: 'ultrasound', name: '腹部B超', desc: '肝胆脾胰肾超声检查', price: 180, type: 'optional', level: 'key', aiRecommend: true, aiReason: '健康画像显示 BMI 26.8(超重),且近年血脂偏高,建议加做腹部超声,重点筛查脂肪肝与胆囊病变。预计费用 ¥180,在本年度体检额度内。' },
|
||||
{ id: 'thyroid', name: '甲状腺彩超', desc: '甲状腺结构与结节筛查', price: 160, type: 'optional', level: 'key', aiRecommend: true, aiReason: '既往史显示 2024 年体检发现甲状腺结节(TI-RADS 2 类),建议每年做一次超声随访复查,观察结节变化。预计费用 ¥160,在本年度体检额度内。' },
|
||||
{ id: 'tumor', name: '肿瘤标志物', desc: '基础肿瘤风险筛查', price: 220, type: 'optional', level: 'key', aiRecommend: true, aiReason: '家族史提示直系亲属有肿瘤病史,结合您所处年龄段(45 岁以上),建议今年纳入基础肿瘤标志物筛查,做到早发现早干预。预计费用 ¥220,在本年度体检额度内。' },
|
||||
{ id: 'echo', name: '心脏彩超', desc: '心脏结构与瓣膜功能超声', price: 360, type: 'optional', level: 'key' },
|
||||
{ id: 'gastro', name: '胃幽门螺杆菌检测', desc: 'C13 呼气试验,筛查胃部风险', price: 480, type: 'optional', level: 'normal' }
|
||||
{ id: 'ultrasound', name: '腹部B超', desc: '肝胆脾胰肾超声检查', price: 180, type: 'optional', level: 'key', aiLevel: 3, aiReason: '健康画像显示 BMI 26.8(超重),且近年血脂持续偏高,属于脂肪肝与胆囊病变的高风险人群,建议本年度务必完成腹部超声重点筛查。预计费用 ¥180,在本年度体检额度内。' },
|
||||
{ id: 'thyroid', name: '甲状腺彩超', desc: '甲状腺结构与结节筛查', price: 160, type: 'optional', level: 'key', aiLevel: 2, aiReason: '既往史显示 2024 年体检发现甲状腺结节(TI-RADS 2 类),建议每年做一次超声随访复查,观察结节变化。预计费用 ¥160,在本年度体检额度内。' },
|
||||
{ id: 'tumor', name: '肿瘤标志物', desc: '基础肿瘤风险筛查', price: 220, type: 'optional', level: 'key', aiLevel: 2, aiReason: '家族史提示直系亲属有肿瘤病史,结合您所处年龄段(45 岁以上),建议今年纳入基础肿瘤标志物筛查,做到早发现早干预。预计费用 ¥220,在本年度体检额度内。' },
|
||||
{ id: 'echo', name: '心脏彩超', desc: '心脏结构与瓣膜功能超声', price: 360, type: 'optional', level: 'key', aiLevel: 1, aiReason: '近两次体检血压处于正常高值,可完成一次心脏彩超,建立心脏结构与瓣膜功能的基线资料,便于日后对比随访。预计费用 ¥360,请注意控制项目总额。' },
|
||||
{ id: 'gastro', name: '胃幽门螺杆菌检测', desc: 'C13 呼气试验,筛查胃部风险', price: 480, type: 'optional', level: 'normal', aiLevel: 1, aiReason: '幽门螺杆菌是胃癌明确的危险因素,国内感染率较高。如从未检测过,建议先做一次 C13 呼气试验筛查,阳性可规范四联根除治疗。预计费用 ¥480,可结合剩余额度自行选择。' }
|
||||
];
|
||||
|
||||
let activeTab = 'optional';
|
||||
@@ -397,9 +431,11 @@
|
||||
}
|
||||
|
||||
function getOptionalProjects() {
|
||||
// [交互] AI 推荐项目排在列表前面
|
||||
const optional = projects.filter(project => project.type === 'optional');
|
||||
return [...optional.filter(project => project.aiRecommend), ...optional.filter(project => !project.aiRecommend)];
|
||||
// [交互] AI 推荐项目按推荐等级从高到低排在列表前面,未推荐项目保持原顺序
|
||||
return projects
|
||||
.filter(project => project.type === 'optional')
|
||||
.slice()
|
||||
.sort((a, b) => (b.aiLevel || 0) - (a.aiLevel || 0));
|
||||
}
|
||||
|
||||
function getRequiredFee() {
|
||||
@@ -443,6 +479,7 @@
|
||||
const isReadonly = project.type === 'required';
|
||||
const isSelected = selectedOptionalIds.has(project.id);
|
||||
const projectLevelText = project.level === 'key' ? '重点项目' : '一般项目';
|
||||
const aiLevel = AI_LEVELS[project.aiLevel];
|
||||
card.className = `project-card${isReadonly ? ' project-card--readonly' : ''}${isSelected ? ' selected' : ''}`;
|
||||
card.innerHTML = `
|
||||
<div class="project-card__check${isReadonly ? ' project-card__check--hidden' : ''}"></div>
|
||||
@@ -455,7 +492,7 @@
|
||||
<span class="project-card__price">${formatPrice(project.price)}</span>
|
||||
<div class="project-card__meta">
|
||||
<span class="project-card__badge${project.level === 'key' ? ' project-card__badge--key' : ''}">${projectLevelText}</span>
|
||||
${project.aiRecommend ? '<span class="project-card__badge project-card__badge--ai">✨ 推荐</span>' : ''}
|
||||
${aiLevel ? `<span class="project-card__badge project-card__badge--ai project-card__badge--ai-${aiLevel.cls}">${aiLevel.icon} ${aiLevel.label}</span>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
<span class="project-card__arrow" data-detail="${project.id}">›</span>
|
||||
@@ -523,7 +560,12 @@
|
||||
window.location.href = 'booking-hospital.html';
|
||||
}
|
||||
function openAiReason(project) {
|
||||
const level = AI_LEVELS[project.aiLevel];
|
||||
document.getElementById('aiModalProject').textContent = project.name;
|
||||
const levelEl = document.getElementById('aiModalLevel');
|
||||
levelEl.textContent = level.icon + ' ' + level.label;
|
||||
levelEl.className = 'project-card__badge project-card__badge--ai project-card__badge--ai-' + level.cls;
|
||||
document.getElementById('aiModalLevelDesc').textContent = level.desc;
|
||||
document.getElementById('aiModalReason').textContent = project.aiReason;
|
||||
document.getElementById('aiModal').classList.remove('hidden');
|
||||
}
|
||||
|
||||
@@ -130,6 +130,9 @@
|
||||
.type-card__icon--gastro {
|
||||
background: linear-gradient(135deg, #fff7e6 0%, #ffe7ba 100%);
|
||||
}
|
||||
.type-card__icon--cta {
|
||||
background: linear-gradient(135deg, #fff1f0 0%, #ffccc7 100%);
|
||||
}
|
||||
.type-card__main { flex: 1; min-width: 0; }
|
||||
.type-card__name {
|
||||
font-size: 16px;
|
||||
@@ -318,6 +321,34 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="type-card" onclick="selectType(this, 'cta')">
|
||||
<div class="type-card__header">
|
||||
<div class="type-card__icon type-card__icon--cta">🫀</div>
|
||||
<div class="type-card__main">
|
||||
<div class="type-card__name">冠脉CTA体检</div>
|
||||
<div class="type-card__badges">
|
||||
<span class="status-badge status-badge--ongoing">进行中</span>
|
||||
<span class="status-badge status-badge--appt-open">已开启预约</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="radio-dot"></div>
|
||||
</div>
|
||||
<div class="type-card__info">
|
||||
<div class="info-row">
|
||||
<span class="info-row__label">体检时间</span>
|
||||
<span class="info-row__value">2026-06-23 至 2026-08-31</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-row__label">预约时间</span>
|
||||
<span class="info-row__value">2026-06-01 至 2026-08-20</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-row__label">所属人群</span>
|
||||
<span class="info-row__value">35岁及以下-女</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -337,6 +368,8 @@
|
||||
function goNext() {
|
||||
if (selectedType === 'gastro') {
|
||||
window.location.href = 'gastro-hospital.html?from=booking-type';
|
||||
} else if (selectedType === 'cta') {
|
||||
window.location.href = 'cta-hospital.html?from=booking-type';
|
||||
} else {
|
||||
window.location.href = 'booking-hospital.html?from=booking-type';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,409 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>冠脉CTA预约 - 预约完成</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
:root {
|
||||
--primary: #13c2c2; --primary-dark: #0f9b9b; --primary-light: #e6fffb;
|
||||
--danger: #ff4d4f; --danger-light: #fff1f0;
|
||||
--text-primary: #1a1a1a; --text-secondary: #666666; --text-muted: #8c8c8c;
|
||||
--bg-page: #f0f2f5; --bg-content: #f7f9fb;
|
||||
--shadow: 0 10px 30px rgba(19, 194, 194, 0.08);
|
||||
}
|
||||
body {
|
||||
background: var(--bg-page); display: flex; justify-content: center; align-items: flex-start;
|
||||
min-height: 100vh; padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.phone-shell {
|
||||
width: 390px; min-height: 844px; background: var(--bg-content);
|
||||
border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
|
||||
overflow: hidden; position: relative; display: flex; flex-direction: column;
|
||||
}
|
||||
.phone-status-bar {
|
||||
height: 44px; background: #fff; display: flex; align-items: center;
|
||||
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
|
||||
}
|
||||
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
|
||||
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
|
||||
.nav-bar {
|
||||
height: 44px; display: flex; align-items: center; padding: 0 16px;
|
||||
background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative;
|
||||
}
|
||||
.nav-back { font-size: 18px; color: var(--text-primary); cursor: pointer; line-height: 1; text-decoration: none; }
|
||||
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; }
|
||||
.scroll-content {
|
||||
flex: 1; overflow-y: auto;
|
||||
background: linear-gradient(180deg, #effbfb 0%, #f7f9fb 180px, #f7f9fb 100%);
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
.scroll-content::-webkit-scrollbar { display: none; }
|
||||
.page-body { padding: 16px; }
|
||||
.stepper { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; padding: 16px 0; }
|
||||
.stepper__item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-decoration: none; }
|
||||
.stepper__dot {
|
||||
width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 12px; font-weight: 700; background: #e8e8e8; color: #bfbfbf; transition: all 0.25s;
|
||||
}
|
||||
.stepper__item--done .stepper__dot { background: var(--primary); color: #fff; }
|
||||
.stepper__item--done { pointer-events: none; }
|
||||
.stepper__label { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
|
||||
.stepper__item--done .stepper__label { color: var(--primary-dark); }
|
||||
.stepper__line { width: 44px; height: 3px; background: #e8e8e8; margin: 0 8px; margin-bottom: 22px; border-radius: 2px; }
|
||||
.stepper__line--done { background: var(--primary); }
|
||||
.section-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; }
|
||||
.info-card {
|
||||
background: #fff; border-radius: 20px; padding: 18px 16px; margin-bottom: 14px;
|
||||
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
|
||||
}
|
||||
.info-card__row {
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
padding: 12px 0; border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
.info-card__row:first-child { padding-top: 0; }
|
||||
.info-card__row:last-child { border-bottom: none; padding-bottom: 0; }
|
||||
.info-card__label { font-size: 13px; color: var(--text-muted); }
|
||||
.info-card__value { font-size: 14px; font-weight: 600; color: var(--text-primary); text-align: right; }
|
||||
.info-card__value--highlight { color: var(--primary-dark); }
|
||||
.tips-card {
|
||||
background: #fff; border-radius: 20px; padding: 16px; margin-bottom: 14px;
|
||||
border: 1px solid #eef5f5; box-shadow: 0 8px 24px rgba(0,0,0,0.04);
|
||||
}
|
||||
.tips-card__title { font-size: 15px; font-weight: 700; margin-bottom: 10px; }
|
||||
.tips-card__item {
|
||||
display: flex; gap: 8px; font-size: 13px; line-height: 1.7;
|
||||
color: var(--text-secondary); margin-bottom: 8px;
|
||||
}
|
||||
.tips-card__item:last-child { margin-bottom: 0; }
|
||||
.tips-card__dot {
|
||||
width: 6px; height: 6px; border-radius: 50%; background: var(--primary);
|
||||
margin-top: 8px; flex-shrink: 0;
|
||||
}
|
||||
.bottom-actions {
|
||||
position: absolute; left: 16px; right: 16px; bottom: 18px;
|
||||
display: flex; gap: 12px; padding-bottom: 16px;
|
||||
}
|
||||
.bottom-actions__btn {
|
||||
flex: 1; height: 48px; border-radius: 24px; font-size: 15px; font-weight: 600; border: none; cursor: pointer;
|
||||
}
|
||||
.bottom-actions__btn--ghost {
|
||||
background: var(--danger-light); color: var(--danger); border: 1px solid rgba(255,77,79,0.2);
|
||||
}
|
||||
.bottom-actions__btn--primary {
|
||||
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
|
||||
color: #fff; box-shadow: 0 10px 20px rgba(19,194,194,0.22);
|
||||
}
|
||||
.toast {
|
||||
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.9);
|
||||
background: rgba(0,0,0,0.75); color: #fff; padding: 14px 22px; border-radius: 12px;
|
||||
font-size: 13px; line-height: 1.6; text-align: center; z-index: 200;
|
||||
opacity: 0; pointer-events: none; transition: all 0.25s ease; max-width: 280px;
|
||||
}
|
||||
.toast.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||||
/* 原型演示状态下拉框(导航栏右上角) */
|
||||
.demo-select {
|
||||
margin-left: auto; flex-shrink: 0; font-family: inherit;
|
||||
font-size: 11px; font-weight: 600; color: var(--text-secondary);
|
||||
border: 1px solid #e8e8e8; border-radius: 12px; padding: 3px 6px;
|
||||
background: #f5f5f5; cursor: pointer; outline: none;
|
||||
}
|
||||
/* 预约结果横幅 */
|
||||
.result-banner {
|
||||
display: flex; align-items: flex-start; gap: 12px;
|
||||
border-radius: 20px; padding: 16px; margin-bottom: 14px;
|
||||
}
|
||||
.result-banner--success { background: linear-gradient(135deg, #f6ffed 0%, #ffffff 100%); border: 1px solid #b7eb8f; }
|
||||
.result-banner--fail { background: linear-gradient(135deg, #fff1f0 0%, #ffffff 100%); border: 1px solid #ffccc7; }
|
||||
.result-banner__icon {
|
||||
width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.result-banner--success .result-banner__icon { background: #52c41a; }
|
||||
.result-banner--fail .result-banner__icon { background: #ff4d4f; }
|
||||
.result-banner--success .icon-cross { display: none; }
|
||||
.result-banner--fail .icon-check { display: none; }
|
||||
.result-banner__title { font-size: 18px; font-weight: 800; margin-bottom: 4px; }
|
||||
.result-banner--success .result-banner__title { color: #389e0d; }
|
||||
.result-banner--fail .result-banner__title { color: #cf1322; }
|
||||
.result-banner__sub { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
|
||||
.result-banner__reason {
|
||||
display: none; align-items: center; gap: 6px; margin-top: 6px;
|
||||
font-size: 13px; color: var(--text-secondary);
|
||||
}
|
||||
.result-banner--fail .result-banner__reason { display: flex; }
|
||||
.reason-help {
|
||||
width: 16px; height: 16px; border-radius: 50%; border: 1px solid #ff4d4f; color: #ff4d4f;
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
font-size: 11px; font-weight: 700; cursor: pointer; flex-shrink: 0; transition: all 0.2s;
|
||||
}
|
||||
.reason-help:hover { background: #ff4d4f; color: #fff; }
|
||||
/* 失败原因详情弹窗 */
|
||||
.reason-modal {
|
||||
width: 100%; background: #fff; border-radius: 24px; padding: 22px 20px 18px;
|
||||
box-shadow: 0 20px 50px rgba(0,0,0,0.16);
|
||||
}
|
||||
.reason-modal__title { font-size: 17px; font-weight: 700; text-align: center; margin-bottom: 16px; }
|
||||
.reason-modal__item { margin-bottom: 14px; }
|
||||
.reason-modal__label { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
|
||||
.reason-modal__text { font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.6; }
|
||||
.reason-modal__text--danger { color: #cf1322; }
|
||||
.reason-modal__btn {
|
||||
width: 100%; height: 44px; border-radius: 22px; border: none; cursor: pointer;
|
||||
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff;
|
||||
font-size: 15px; font-weight: 600; margin-top: 4px;
|
||||
}
|
||||
/* 取消预约确认弹窗 */
|
||||
.modal-overlay {
|
||||
position: absolute; inset: 0; background: rgba(0,0,0,0.42); z-index: 120;
|
||||
display: flex; align-items: center; justify-content: center; padding: 24px;
|
||||
}
|
||||
.modal-overlay.hidden { display: none; }
|
||||
.cancel-modal {
|
||||
width: 100%; background: #fff; border-radius: 24px; padding: 22px 20px 18px;
|
||||
box-shadow: 0 20px 50px rgba(0,0,0,0.16);
|
||||
}
|
||||
.cancel-modal__title { font-size: 17px; font-weight: 700; text-align: center; margin-bottom: 6px; }
|
||||
.cancel-modal__desc { font-size: 12px; color: var(--text-muted); text-align: center; line-height: 1.6; margin-bottom: 14px; }
|
||||
.cancel-modal__order {
|
||||
background: #f7f9fb; border-radius: 12px; padding: 10px 14px; margin-bottom: 16px;
|
||||
font-size: 13px; font-weight: 600; color: var(--text-secondary); text-align: center;
|
||||
}
|
||||
.cancel-modal__label { font-size: 13px; font-weight: 600; margin-bottom: 10px; }
|
||||
.cancel-modal__label em { color: var(--danger); font-style: normal; }
|
||||
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
|
||||
.chip {
|
||||
padding: 7px 14px; border-radius: 16px; border: 1px solid #e8e8e8; background: #fafafa;
|
||||
font-size: 13px; color: var(--text-secondary); cursor: pointer; transition: all 0.2s; user-select: none;
|
||||
}
|
||||
.chip.selected { background: var(--primary-light); border-color: var(--primary); color: var(--primary-dark); font-weight: 600; }
|
||||
.other-input {
|
||||
display: none; width: 100%; border: 1px solid #e8e8e8; border-radius: 12px;
|
||||
padding: 10px 12px; font-size: 13px; font-family: inherit; line-height: 1.6;
|
||||
resize: none; outline: none; margin-bottom: 6px; color: var(--text-primary);
|
||||
}
|
||||
.other-input.show { display: block; }
|
||||
.other-input:focus { border-color: var(--primary); }
|
||||
.cancel-modal__err { display: none; font-size: 12px; color: var(--danger); margin-bottom: 6px; }
|
||||
.cancel-modal__err.show { display: block; }
|
||||
.cancel-modal__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; }
|
||||
.cancel-modal__btn { height: 44px; border-radius: 22px; font-size: 15px; font-weight: 600; border: none; cursor: pointer; }
|
||||
.cancel-modal__btn--ghost { background: #f5f5f5; color: var(--text-secondary); }
|
||||
.cancel-modal__btn--danger { background: var(--danger); color: #fff; box-shadow: 0 6px 16px rgba(255,77,79,0.28); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="phone-shell">
|
||||
<div class="phone-status-bar">
|
||||
<span class="time">12:00</span>
|
||||
<div class="icons">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-bar">
|
||||
<a class="nav-back" href="index.html">‹</a>
|
||||
<span class="nav-title">冠脉CTA预约</span>
|
||||
<!-- [交互] 原型演示:切换预约成功/失败两态 -->
|
||||
<select class="demo-select" id="demoSelect" title="原型演示:切换预约结果状态" onchange="setResult(this.value)">
|
||||
<option value="success">预约成功</option>
|
||||
<option value="fail">预约失败</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="scroll-content">
|
||||
<div class="page-body">
|
||||
<!-- 步骤条:全部完成(冠脉CTA免问卷,仅两步) -->
|
||||
<div class="stepper">
|
||||
<div class="stepper__item stepper__item--done" onclick="showToast()"><div class="stepper__dot">✓</div><div class="stepper__label">选择医院</div></div>
|
||||
<div class="stepper__line stepper__line--done"></div>
|
||||
<div class="stepper__item stepper__item--done" onclick="showToast()"><div class="stepper__dot">✓</div><div class="stepper__label">预约日期</div></div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 预约结果横幅:成功/失败两态,由右上角演示切换器控制 -->
|
||||
<div class="result-banner result-banner--success" id="resultBanner">
|
||||
<div class="result-banner__icon">
|
||||
<svg class="icon-check" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
<svg class="icon-cross" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="result-banner__title" id="resultTitle">预约成功</div>
|
||||
<div class="result-banner__sub" id="resultSub">已为您锁定冠脉CTA检查名额,请按预约日期准时到检</div>
|
||||
<div class="result-banner__reason">
|
||||
<span>失败原因:所选日期号源已约满</span>
|
||||
<span class="reason-help" onclick="openReasonModal()">?</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预约信息 -->
|
||||
<div class="info-card">
|
||||
<div class="section-title">预约信息</div>
|
||||
<div class="info-card__row">
|
||||
<span class="info-card__label">体检医院</span>
|
||||
<span class="info-card__value">宁夏宝石花医院</span>
|
||||
</div>
|
||||
<div class="info-card__row">
|
||||
<span class="info-card__label">体检员工</span>
|
||||
<span class="info-card__value">刘韵琴</span>
|
||||
</div>
|
||||
<div class="info-card__row">
|
||||
<span class="info-card__label">体检地址</span>
|
||||
<span class="info-card__value">银川市西夏区怀远路148号</span>
|
||||
</div>
|
||||
<div class="info-card__row">
|
||||
<span class="info-card__label">体检日期</span>
|
||||
<span class="info-card__value info-card__value--highlight">2026年3月23日</span>
|
||||
</div>
|
||||
<div class="info-card__row">
|
||||
<span class="info-card__label">体检项目</span>
|
||||
<span class="info-card__value info-card__value--highlight">冠脉CTA体检</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 体检须知:仅预约成功态显示,失败态隐藏 -->
|
||||
<div class="tips-card" id="tipsCard">
|
||||
<div class="tips-card__title">体检须知</div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查前24小时请避免剧烈运动,检查当天避免吸烟,勿饮用咖啡、浓茶等刺激性饮品。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>心率过快或心律不齐者,请遵医嘱在检查前服用控制心率药物(如β受体阻滞剂)。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查需屏气配合,请提前练习平静状态下屏气10~15秒。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>对碘对比剂过敏、甲状腺功能异常、肾功能不全或妊娠期,请提前告知医生。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>请携带本人身份证件按时前往医院。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>若需取消预约,请至少提前一天操作。</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 预约成功态底部按钮 -->
|
||||
<div class="bottom-actions" id="actionsSuccess">
|
||||
<!-- [交互] 取消预约改为二次确认弹窗,需选择或填写取消原因 -->
|
||||
<button class="bottom-actions__btn bottom-actions__btn--ghost" onclick="openCancelModal()">取消预约</button>
|
||||
<button class="bottom-actions__btn bottom-actions__btn--primary" onclick="window.location.href='my-appointments-all.html?type=cta'">查看预约详情</button>
|
||||
</div>
|
||||
<!-- [交互] 预约失败态底部按钮:重新预约,跳回冠脉CTA预约日期页 -->
|
||||
<div class="bottom-actions" id="actionsFail" style="display: none;">
|
||||
<button class="bottom-actions__btn bottom-actions__btn--primary" onclick="window.location.href='cta-date.html'">重新预约</button>
|
||||
</div>
|
||||
<div class="toast" id="stepToast">当前已预约冠脉CTA检查,无法重新选择,请先取消预约</div>
|
||||
|
||||
<!-- [交互] 点击失败原因旁的小问号,弹窗查看具体失败原因 -->
|
||||
<div class="modal-overlay hidden" id="reasonModal">
|
||||
<div class="reason-modal">
|
||||
<div class="reason-modal__title">失败原因详情</div>
|
||||
<div class="reason-modal__item">
|
||||
<div class="reason-modal__label">失败原因</div>
|
||||
<div class="reason-modal__text reason-modal__text--danger">号源争抢失败:宁夏宝石花医院 2026年3月23日 冠脉CTA检查号源已被其他员工约满</div>
|
||||
</div>
|
||||
<div class="reason-modal__item">
|
||||
<div class="reason-modal__label">发生时间</div>
|
||||
<div class="reason-modal__text">2026-03-16 12:00:35</div>
|
||||
</div>
|
||||
<div class="reason-modal__item">
|
||||
<div class="reason-modal__label">处理建议</div>
|
||||
<div class="reason-modal__text">请点击「重新预约」选择其他可约日期;冠脉CTA检查仅可预约 7~30 天内的号源,若长期无可用号源,可联系健康管理专员协调加号。</div>
|
||||
</div>
|
||||
<button class="reason-modal__btn" onclick="closeReasonModal()">知道了</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 取消预约二次确认:单选原因chips,选「其他」时填写具体原因 -->
|
||||
<div class="modal-overlay hidden" id="cancelModal">
|
||||
<div class="cancel-modal">
|
||||
<div class="cancel-modal__title">确认取消预约</div>
|
||||
<div class="cancel-modal__desc">取消后名额将释放,如仍需检查请重新预约</div>
|
||||
<div class="cancel-modal__order">宁夏宝石花医院 · 2026年3月23日</div>
|
||||
<div class="cancel-modal__label">请选择取消原因 <em>*</em></div>
|
||||
<div class="chips" id="cancelChips">
|
||||
<span class="chip" data-reason="时间冲突" onclick="selectChip(this)">时间冲突</span>
|
||||
<span class="chip" data-reason="医院选择不当" onclick="selectChip(this)">医院选择不当</span>
|
||||
<span class="chip" data-reason="日期选择不当" onclick="selectChip(this)">日期选择不当</span>
|
||||
<span class="chip" data-reason="个人健康原因" onclick="selectChip(this)">个人健康原因</span>
|
||||
<span class="chip" data-reason="other" onclick="selectChip(this)">其他</span>
|
||||
</div>
|
||||
<textarea class="other-input" id="otherInput" rows="2" maxlength="100" placeholder="请填写取消原因(必填)"></textarea>
|
||||
<div class="cancel-modal__err" id="cancelErr">请选择或填写取消原因</div>
|
||||
<div class="cancel-modal__actions">
|
||||
<button class="cancel-modal__btn cancel-modal__btn--ghost" onclick="closeCancelModal()">再想想</button>
|
||||
<button class="cancel-modal__btn cancel-modal__btn--danger" onclick="confirmCancel()">确认取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var toastTimer = null;
|
||||
function showToast() {
|
||||
var toast = document.getElementById('stepToast');
|
||||
toast.classList.add('show');
|
||||
clearTimeout(toastTimer);
|
||||
toastTimer = setTimeout(function() { toast.classList.remove('show'); }, 2200);
|
||||
}
|
||||
|
||||
// [交互] 原型演示:切换预约成功/失败两态(横幅、底部按钮、体检须知联动)
|
||||
function setResult(state) {
|
||||
var fail = state === 'fail';
|
||||
var banner = document.getElementById('resultBanner');
|
||||
banner.classList.toggle('result-banner--fail', fail);
|
||||
banner.classList.toggle('result-banner--success', !fail);
|
||||
document.getElementById('resultTitle').textContent = fail ? '预约失败' : '预约成功';
|
||||
document.getElementById('resultSub').style.display = fail ? 'none' : '';
|
||||
document.getElementById('actionsSuccess').style.display = fail ? 'none' : 'flex';
|
||||
document.getElementById('actionsFail').style.display = fail ? 'flex' : 'none';
|
||||
// 预约失败时隐藏体检须知(未成功到检,须知无意义)
|
||||
document.getElementById('tipsCard').style.display = fail ? 'none' : '';
|
||||
document.getElementById('stepToast').textContent = fail
|
||||
? '预约未成功,请点击下方「重新预约」按钮重新预约'
|
||||
: '当前已预约冠脉CTA检查,无法重新选择,请先取消预约';
|
||||
}
|
||||
|
||||
function openReasonModal() {
|
||||
document.getElementById('reasonModal').classList.remove('hidden');
|
||||
}
|
||||
function closeReasonModal() {
|
||||
document.getElementById('reasonModal').classList.add('hidden');
|
||||
}
|
||||
|
||||
// [交互] 取消预约二次确认:原因单选 + 其他原因填写 + 校验 + 确认后返回预约日期页重新选择
|
||||
var cancelReason = null;
|
||||
function selectChip(el) {
|
||||
var chips = document.querySelectorAll('#cancelChips .chip');
|
||||
for (var i = 0; i < chips.length; i++) chips[i].classList.remove('selected');
|
||||
el.classList.add('selected');
|
||||
cancelReason = el.dataset.reason;
|
||||
document.getElementById('otherInput').classList.toggle('show', cancelReason === 'other');
|
||||
hideCancelErr();
|
||||
}
|
||||
function hideCancelErr() {
|
||||
document.getElementById('cancelErr').classList.remove('show');
|
||||
}
|
||||
function openCancelModal() {
|
||||
cancelReason = null;
|
||||
var chips = document.querySelectorAll('#cancelChips .chip');
|
||||
for (var i = 0; i < chips.length; i++) chips[i].classList.remove('selected');
|
||||
var input = document.getElementById('otherInput');
|
||||
input.value = '';
|
||||
input.classList.remove('show');
|
||||
hideCancelErr();
|
||||
document.getElementById('cancelModal').classList.remove('hidden');
|
||||
}
|
||||
function closeCancelModal() {
|
||||
document.getElementById('cancelModal').classList.add('hidden');
|
||||
}
|
||||
function confirmCancel() {
|
||||
var input = document.getElementById('otherInput');
|
||||
if (!cancelReason || (cancelReason === 'other' && !input.value.trim())) {
|
||||
document.getElementById('cancelErr').classList.add('show');
|
||||
return;
|
||||
}
|
||||
closeCancelModal();
|
||||
var toast = document.getElementById('stepToast');
|
||||
toast.textContent = '预约已取消';
|
||||
showToast();
|
||||
setTimeout(function() {
|
||||
window.location.href = 'cta-date.html';
|
||||
}, 1200);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,350 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>冠脉CTA预约 - 预约日期</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
:root {
|
||||
--primary: #13c2c2;
|
||||
--primary-dark: #0f9b9b;
|
||||
--primary-light: #e6fffb;
|
||||
--text-primary: #1a1a1a;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #8c8c8c;
|
||||
--border: #e8f3f3;
|
||||
--bg-page: #f0f2f5;
|
||||
--bg-content: #f7f9fb;
|
||||
--shadow: 0 10px 30px rgba(19, 194, 194, 0.08);
|
||||
}
|
||||
body {
|
||||
background: var(--bg-page); display: flex; justify-content: center;
|
||||
align-items: flex-start; min-height: 100vh; padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.phone-shell {
|
||||
width: 390px; min-height: 844px; background: var(--bg-content);
|
||||
border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
|
||||
overflow: hidden; position: relative; display: flex; flex-direction: column;
|
||||
}
|
||||
.phone-status-bar {
|
||||
height: 44px; background: #fff; display: flex; align-items: center;
|
||||
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
|
||||
}
|
||||
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
|
||||
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
|
||||
.nav-bar {
|
||||
height: 44px; display: flex; align-items: center; padding: 0 16px;
|
||||
background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative;
|
||||
}
|
||||
.nav-back { font-size: 18px; color: var(--text-primary); cursor: pointer; line-height: 1; text-decoration: none; }
|
||||
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: var(--text-primary); }
|
||||
.scroll-content { flex: 1; overflow-y: auto; background: linear-gradient(180deg, #effbfb 0%, #f7f9fb 180px, #f7f9fb 100%); padding-bottom: 120px; }
|
||||
.scroll-content::-webkit-scrollbar { display: none; }
|
||||
.page-body { padding: 16px; }
|
||||
.stepper { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; padding: 16px 0; }
|
||||
.stepper__item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-decoration: none; }
|
||||
.stepper__item--future { cursor: default; pointer-events: none; opacity: 0.45; }
|
||||
.stepper__dot {
|
||||
width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 12px; font-weight: 700; background: #e8e8e8; color: #bfbfbf; transition: all 0.25s;
|
||||
}
|
||||
.stepper__item--done .stepper__dot { background: var(--primary); color: #fff; }
|
||||
.stepper__item--active { cursor: default; pointer-events: none; }
|
||||
.stepper__item--active .stepper__dot {
|
||||
width: 34px; height: 34px; font-size: 14px;
|
||||
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff;
|
||||
box-shadow: 0 0 0 6px rgba(19,194,194,0.2);
|
||||
}
|
||||
.stepper__label { font-size: 12px; color: var(--text-muted); white-space: nowrap; transition: all 0.2s; }
|
||||
.stepper__item--done .stepper__label { color: var(--primary-dark); }
|
||||
.stepper__item--active .stepper__label {
|
||||
color: var(--primary-dark); font-weight: 700; font-size: 13px;
|
||||
background: var(--primary-light); padding: 2px 10px; border-radius: 10px;
|
||||
}
|
||||
.stepper__item--done:hover .stepper__dot { transform: scale(1.12); box-shadow: 0 0 0 4px rgba(19,194,194,0.15); }
|
||||
.stepper__item--done:hover .stepper__label { text-decoration: underline; text-underline-offset: 3px; }
|
||||
.stepper__line { width: 44px; height: 3px; background: #e8e8e8; margin: 0 8px; margin-bottom: 22px; border-radius: 2px; }
|
||||
.stepper__line--done { background: var(--primary); }
|
||||
.section-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; margin-top: 6px; }
|
||||
.summary-card {
|
||||
background: #fff; border-radius: 20px; padding: 18px 16px; margin-bottom: 14px;
|
||||
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
|
||||
}
|
||||
.summary-list { display: flex; flex-direction: column; gap: 14px; }
|
||||
.summary-item { display: flex; justify-content: space-between; gap: 12px; }
|
||||
.summary-item__label { font-size: 13px; color: var(--text-muted); flex-shrink: 0; }
|
||||
.summary-item__value { font-size: 14px; font-weight: 600; text-align: right; line-height: 1.6; }
|
||||
/* 预约状态条 */
|
||||
.status-card {
|
||||
background: #fff; border-radius: 20px; padding: 14px 16px; margin-bottom: 14px;
|
||||
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
|
||||
}
|
||||
.status-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
||||
.status-badge {
|
||||
display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700;
|
||||
padding: 4px 12px; border-radius: 12px; flex-shrink: 0;
|
||||
}
|
||||
.status-badge--open { background: #f6ffed; color: #389e0d; border: 1px solid #b7eb8f; }
|
||||
.status-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: #52c41a; }
|
||||
.status-range { font-size: 12px; color: var(--text-secondary); font-weight: 600; }
|
||||
.status-tip {
|
||||
display: flex; align-items: center; gap: 6px; margin-top: 10px; padding-top: 10px;
|
||||
border-top: 1px dashed #f0f0f0; font-size: 12px; color: var(--text-muted); line-height: 1.5;
|
||||
}
|
||||
.status-tip svg { flex-shrink: 0; }
|
||||
.date-card {
|
||||
background: #fff; border-radius: 20px; padding: 18px 16px;
|
||||
box-shadow: var(--shadow); border: 1px solid rgba(19,194,194,0.06);
|
||||
}
|
||||
.calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
|
||||
.calendar-header__month { font-size: 17px; font-weight: 700; color: var(--text-primary); }
|
||||
.calendar-header__nav { display: flex; gap: 8px; }
|
||||
.calendar-header__btn {
|
||||
width: 32px; height: 32px; border-radius: 10px; border: 1px solid #e8e8e8;
|
||||
background: #fff; display: flex; align-items: center; justify-content: center;
|
||||
cursor: pointer; font-size: 14px; color: var(--text-secondary); transition: all 0.2s;
|
||||
}
|
||||
.calendar-header__btn:hover { border-color: var(--primary); color: var(--primary); }
|
||||
.calendar-header__btn:disabled { opacity: 0.3; pointer-events: none; }
|
||||
.calendar-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-bottom: 8px; }
|
||||
.calendar-weekday { text-align: center; font-size: 12px; font-weight: 600; color: var(--text-muted); padding: 6px 0; }
|
||||
.calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
|
||||
.calendar-cell {
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
height: 52px; border-radius: 12px; cursor: pointer; transition: all 0.2s;
|
||||
border: 2px solid transparent; background: #f9fbfb; position: relative;
|
||||
}
|
||||
.calendar-cell:hover { border-color: var(--primary); }
|
||||
.calendar-cell.selected { background: var(--primary); border-color: var(--primary); }
|
||||
.calendar-cell.selected .calendar-cell__day,
|
||||
.calendar-cell.selected .calendar-cell__slots { color: #fff; }
|
||||
.calendar-cell.disabled { opacity: 0.3; pointer-events: none; background: #f5f5f5; }
|
||||
.calendar-cell.empty { background: transparent; pointer-events: none; }
|
||||
.calendar-cell__day { font-size: 15px; font-weight: 700; color: var(--text-primary); line-height: 1; }
|
||||
.calendar-cell__slots { font-size: 10px; color: var(--primary-dark); font-weight: 600; margin-top: 2px; }
|
||||
.calendar-cell__full { font-size: 10px; color: var(--text-muted); font-weight: 600; margin-top: 2px; }
|
||||
.calendar-cell.today .calendar-cell__day { color: var(--primary-dark); }
|
||||
.calendar-cell.today { border-color: rgba(19,194,194,0.3); }
|
||||
.bottom-actions {
|
||||
position: absolute; left: 16px; right: 16px; bottom: 18px;
|
||||
display: flex; gap: 12px; padding-bottom: 16px;
|
||||
}
|
||||
.bottom-actions__btn { flex: 1; height: 48px; border-radius: 24px; font-size: 15px; font-weight: 600; border: none; cursor: pointer; }
|
||||
.bottom-actions__btn--ghost { background: #fff; color: var(--primary-dark); border: 2px solid #d0eded; }
|
||||
.bottom-actions__btn--primary {
|
||||
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
|
||||
color: #fff; box-shadow: 0 10px 20px rgba(19,194,194,0.22);
|
||||
}
|
||||
.modal-overlay {
|
||||
position: absolute; inset: 0; background: rgba(0,0,0,0.42); z-index: 120;
|
||||
display: flex; align-items: center; justify-content: center; padding: 24px;
|
||||
}
|
||||
.modal-overlay.hidden { display: none; }
|
||||
.confirm-modal { width: 100%; background: #fff; border-radius: 24px; padding: 22px 20px 18px; box-shadow: 0 20px 50px rgba(0,0,0,0.16); }
|
||||
.confirm-modal__title { font-size: 18px; font-weight: 700; text-align: center; margin-bottom: 8px; }
|
||||
.confirm-modal__desc { font-size: 13px; color: var(--text-muted); text-align: center; line-height: 1.6; margin-bottom: 18px; }
|
||||
.confirm-modal__info { background: #f7f9fb; border-radius: 16px; padding: 14px 16px; margin-bottom: 18px; }
|
||||
.confirm-modal__row { display: flex; justify-content: space-between; align-items: center; font-size: 14px; color: var(--text-secondary); margin-bottom: 12px; }
|
||||
.confirm-modal__row:last-child { margin-bottom: 0; }
|
||||
.confirm-modal__value { font-size: 15px; font-weight: 700; color: var(--text-primary); }
|
||||
.confirm-modal__value--highlight { color: var(--primary-dark); }
|
||||
.confirm-modal__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
||||
.confirm-modal__btn { height: 44px; border-radius: 22px; font-size: 15px; font-weight: 600; border: none; cursor: pointer; }
|
||||
.confirm-modal__btn--ghost { background: #f5f5f5; color: var(--text-secondary); }
|
||||
.confirm-modal__btn--primary { background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff; }
|
||||
.toast {
|
||||
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(0.9);
|
||||
background: rgba(0,0,0,0.75); color: #fff; padding: 14px 22px; border-radius: 12px;
|
||||
font-size: 13px; line-height: 1.6; text-align: center; z-index: 200;
|
||||
opacity: 0; pointer-events: none; transition: all 0.25s ease; max-width: 280px;
|
||||
}
|
||||
.toast.show { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="phone-shell">
|
||||
<div class="phone-status-bar">
|
||||
<span class="time">12:00</span>
|
||||
<div class="icons">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-bar">
|
||||
<a class="nav-back" href="cta-hospital.html">‹</a>
|
||||
<span class="nav-title">冠脉CTA预约</span>
|
||||
</div>
|
||||
<div class="scroll-content">
|
||||
<div class="page-body">
|
||||
<div class="stepper">
|
||||
<a class="stepper__item stepper__item--done" href="cta-hospital.html"><div class="stepper__dot">✓</div><div class="stepper__label">选择医院</div></a>
|
||||
<div class="stepper__line stepper__line--done"></div>
|
||||
<div class="stepper__item stepper__item--active"><div class="stepper__dot">2</div><div class="stepper__label">预约日期</div></div>
|
||||
</div>
|
||||
|
||||
<div class="summary-card">
|
||||
<div class="section-title">预约信息</div>
|
||||
<div class="summary-list">
|
||||
<div class="summary-item"><div class="summary-item__label">体检类型</div><div class="summary-item__value">冠脉CTA体检</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检医院</div><div class="summary-item__value">宁夏宝石花医院</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 预约状态与可预约日期范围,日期范围由脚本按「最早7天后」规则动态生成 -->
|
||||
<div class="status-card">
|
||||
<div class="status-row">
|
||||
<span class="status-badge status-badge--open"><span class="status-badge__dot"></span>可预约</span>
|
||||
<span class="status-range" id="rangeText"></span>
|
||||
</div>
|
||||
<div class="status-tip">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8c8c8c" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
|
||||
<span>冠脉CTA检查需提前预约,最早仅可预约7天后的日期,超出范围日期不可选择</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="date-card">
|
||||
<div class="calendar-header">
|
||||
<span class="calendar-header__month" id="calendarMonth"></span>
|
||||
<div class="calendar-header__nav">
|
||||
<button class="calendar-header__btn" id="prevMonth">‹</button>
|
||||
<button class="calendar-header__btn" id="nextMonth">›</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calendar-weekdays">
|
||||
<span class="calendar-weekday">一</span><span class="calendar-weekday">二</span>
|
||||
<span class="calendar-weekday">三</span><span class="calendar-weekday">四</span>
|
||||
<span class="calendar-weekday">五</span><span class="calendar-weekday">六</span>
|
||||
<span class="calendar-weekday">日</span>
|
||||
</div>
|
||||
<div class="calendar-grid" id="calendarGrid"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-actions">
|
||||
<button class="bottom-actions__btn bottom-actions__btn--ghost" onclick="location.href='cta-hospital.html'">上一步</button>
|
||||
<button class="bottom-actions__btn bottom-actions__btn--primary" onclick="openConfirm()">确定预约</button>
|
||||
</div>
|
||||
<div class="modal-overlay hidden" id="confirmModal">
|
||||
<div class="confirm-modal">
|
||||
<div class="confirm-modal__title">确认预约信息</div>
|
||||
<div class="confirm-modal__desc">请确认以下冠脉CTA预约信息无误</div>
|
||||
<div class="confirm-modal__info">
|
||||
<div class="confirm-modal__row"><span>体检类型</span><span class="confirm-modal__value">冠脉CTA体检</span></div>
|
||||
<div class="confirm-modal__row"><span>体检医院</span><span class="confirm-modal__value">宁夏宝石花医院</span></div>
|
||||
<div class="confirm-modal__row"><span>预约日期</span><span class="confirm-modal__value confirm-modal__value--highlight" id="confirmDate">--</span></div>
|
||||
</div>
|
||||
<div class="confirm-modal__actions">
|
||||
<button class="confirm-modal__btn confirm-modal__btn--ghost" onclick="closeConfirm()">取消</button>
|
||||
<button class="confirm-modal__btn confirm-modal__btn--primary" onclick="showSuccessToast()">确认预约</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toast" id="successToast">预约成功!请按时前往医院进行冠脉CTA检查</div>
|
||||
</div>
|
||||
<script>
|
||||
var today = new Date(2026, 2, 16);
|
||||
// 冠脉CTA预约窗口:最早7天后,最晚30天后
|
||||
var minBookDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
|
||||
var maxBookDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
|
||||
function fmtDate(d) {
|
||||
var m = d.getMonth() + 1; var day = d.getDate();
|
||||
return d.getFullYear() + '-' + (m < 10 ? '0' + m : m) + '-' + (day < 10 ? '0' + day : day);
|
||||
}
|
||||
document.getElementById('rangeText').textContent =
|
||||
'可预约日期:' + fmtDate(minBookDate) + ' 至 ' + fmtDate(maxBookDate);
|
||||
var currentYear = today.getFullYear();
|
||||
var currentMonth = today.getMonth();
|
||||
var selectedDate = null;
|
||||
var grid = document.getElementById('calendarGrid');
|
||||
var monthLabel = document.getElementById('calendarMonth');
|
||||
var prevBtn = document.getElementById('prevMonth');
|
||||
var nextBtn = document.getElementById('nextMonth');
|
||||
var toastTimer = null;
|
||||
|
||||
function getSlots(year, month, day) {
|
||||
var d = new Date(year, month, day);
|
||||
var dow = d.getDay();
|
||||
// 早于7天后或超出30天窗口均不可约
|
||||
if (d < minBookDate) return -1;
|
||||
if (d > maxBookDate) return -1;
|
||||
if (dow === 0 || dow === 6) return 0;
|
||||
var seed = (day * 7 + month * 13) % 20;
|
||||
if (seed < 3) return 0;
|
||||
return seed + 2;
|
||||
}
|
||||
|
||||
function renderCalendar() {
|
||||
grid.innerHTML = '';
|
||||
monthLabel.textContent = currentYear + '年' + (currentMonth + 1) + '月';
|
||||
prevBtn.disabled = (currentYear === minBookDate.getFullYear() && currentMonth <= minBookDate.getMonth());
|
||||
nextBtn.disabled = (currentYear > maxBookDate.getFullYear()) ||
|
||||
(currentYear === maxBookDate.getFullYear() && currentMonth >= maxBookDate.getMonth());
|
||||
var firstDay = new Date(currentYear, currentMonth, 1);
|
||||
var startDow = firstDay.getDay();
|
||||
startDow = startDow === 0 ? 6 : startDow - 1;
|
||||
var daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
|
||||
for (var i = 0; i < startDow; i++) {
|
||||
var empty = document.createElement('div');
|
||||
empty.className = 'calendar-cell empty';
|
||||
grid.appendChild(empty);
|
||||
}
|
||||
for (var day = 1; day <= daysInMonth; day++) {
|
||||
(function(d) {
|
||||
var cell = document.createElement('div');
|
||||
var slots = getSlots(currentYear, currentMonth, d);
|
||||
var isToday = (currentYear === today.getFullYear() && currentMonth === today.getMonth() && d === today.getDate());
|
||||
var isDisabled = slots <= 0;
|
||||
var isFull = slots === 0;
|
||||
var isPast = slots === -1;
|
||||
var cls = 'calendar-cell';
|
||||
if (isToday) cls += ' today';
|
||||
if (isDisabled) cls += ' disabled';
|
||||
if (selectedDate && selectedDate.y === currentYear && selectedDate.m === currentMonth && selectedDate.d === d) cls += ' selected';
|
||||
cell.className = cls;
|
||||
var slotsHtml = '';
|
||||
if (isPast) slotsHtml = '';
|
||||
else if (isFull) slotsHtml = '<span class="calendar-cell__full">不可约</span>';
|
||||
else if (slots > 0) slotsHtml = '<span class="calendar-cell__slots">余' + slots + '</span>';
|
||||
cell.innerHTML = '<span class="calendar-cell__day">' + d + '</span>' + slotsHtml;
|
||||
if (!isDisabled) {
|
||||
cell.addEventListener('click', function() {
|
||||
selectedDate = { y: currentYear, m: currentMonth, d: d };
|
||||
renderCalendar();
|
||||
});
|
||||
}
|
||||
grid.appendChild(cell);
|
||||
})(day);
|
||||
}
|
||||
}
|
||||
|
||||
prevBtn.addEventListener('click', function() {
|
||||
currentMonth--;
|
||||
if (currentMonth < 0) { currentMonth = 11; currentYear--; }
|
||||
renderCalendar();
|
||||
});
|
||||
nextBtn.addEventListener('click', function() {
|
||||
currentMonth++;
|
||||
if (currentMonth > 11) { currentMonth = 0; currentYear++; }
|
||||
renderCalendar();
|
||||
});
|
||||
|
||||
// 默认选中最早可预约日期(7天后)
|
||||
selectedDate = { y: minBookDate.getFullYear(), m: minBookDate.getMonth(), d: minBookDate.getDate() };
|
||||
renderCalendar();
|
||||
|
||||
function openConfirm() {
|
||||
if (!selectedDate) return;
|
||||
document.getElementById('confirmDate').textContent = selectedDate.y + '年' + (selectedDate.m + 1) + '月' + selectedDate.d + '日';
|
||||
document.getElementById('confirmModal').classList.remove('hidden');
|
||||
}
|
||||
function closeConfirm() { document.getElementById('confirmModal').classList.add('hidden'); }
|
||||
function showSuccessToast() {
|
||||
closeConfirm();
|
||||
window.location.href = 'cta-date-selected.html';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,220 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>冠脉CTA预约</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
:root {
|
||||
--primary: #13c2c2;
|
||||
--primary-dark: #0f9b9b;
|
||||
--primary-light: #e6fffb;
|
||||
--text-primary: #1a1a1a;
|
||||
--text-secondary: #666666;
|
||||
--text-muted: #8c8c8c;
|
||||
--border: #e8f3f3;
|
||||
--bg-page: #f0f2f5;
|
||||
--bg-content: #f7f9fb;
|
||||
--shadow: 0 10px 30px rgba(19, 194, 194, 0.08);
|
||||
}
|
||||
body {
|
||||
background: var(--bg-page);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.phone-shell {
|
||||
width: 390px; min-height: 844px; background: var(--bg-content);
|
||||
border-radius: 44px; box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
|
||||
overflow: hidden; position: relative; display: flex; flex-direction: column;
|
||||
}
|
||||
.phone-status-bar {
|
||||
height: 44px; background: #fff; display: flex; align-items: center;
|
||||
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
|
||||
}
|
||||
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
|
||||
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
|
||||
.nav-bar {
|
||||
height: 44px; display: flex; align-items: center; padding: 0 16px;
|
||||
background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; position: relative;
|
||||
}
|
||||
.nav-back { font-size: 18px; color: var(--text-primary); cursor: pointer; line-height: 1; text-decoration: none; }
|
||||
.nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; color: var(--text-primary); }
|
||||
.nav-right {
|
||||
position: absolute; right: 16px; font-size: 13px; color: var(--primary);
|
||||
font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 4px;
|
||||
}
|
||||
.scroll-content { flex: 1; overflow-y: auto; background: linear-gradient(180deg, #effbfb 0%, #f7f9fb 180px, #f7f9fb 100%); padding-bottom: 120px; }
|
||||
.scroll-content::-webkit-scrollbar { display: none; }
|
||||
.page-body { padding: 16px; }
|
||||
.stepper { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; padding: 16px 0; }
|
||||
.stepper__item { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-decoration: none; }
|
||||
.stepper__item--future { cursor: default; pointer-events: none; opacity: 0.45; }
|
||||
.stepper__dot {
|
||||
width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 12px; font-weight: 700; background: #e8e8e8; color: #bfbfbf; transition: all 0.25s;
|
||||
}
|
||||
.stepper__item--done .stepper__dot { background: var(--primary); color: #fff; }
|
||||
.stepper__item--active { cursor: default; pointer-events: none; }
|
||||
.stepper__item--active .stepper__dot {
|
||||
width: 34px; height: 34px; font-size: 14px;
|
||||
background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%); color: #fff;
|
||||
box-shadow: 0 0 0 6px rgba(19,194,194,0.2);
|
||||
}
|
||||
.stepper__label { font-size: 12px; color: var(--text-muted); white-space: nowrap; transition: all 0.2s; }
|
||||
.stepper__item--done .stepper__label { color: var(--primary-dark); }
|
||||
.stepper__item--active .stepper__label {
|
||||
color: var(--primary-dark); font-weight: 700; font-size: 13px;
|
||||
background: var(--primary-light); padding: 2px 10px; border-radius: 10px;
|
||||
}
|
||||
.stepper__line { width: 44px; height: 3px; background: #e8e8e8; margin: 0 8px; margin-bottom: 22px; border-radius: 2px; }
|
||||
.stepper__line--done { background: var(--primary); }
|
||||
.section-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; margin-top: 6px; }
|
||||
.hospital-card {
|
||||
background: #fff; border-radius: 18px; padding: 16px; margin-bottom: 12px;
|
||||
border: 2px solid transparent; box-shadow: var(--shadow); cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: space-between; transition: all 0.25s ease;
|
||||
}
|
||||
.hospital-card.active { border-color: var(--primary); background: var(--primary-light); }
|
||||
.hospital-card__info { display: flex; align-items: center; gap: 12px; }
|
||||
.hospital-card__icon {
|
||||
width: 42px; height: 42px; border-radius: 14px;
|
||||
background: linear-gradient(135deg, #e6fffb 0%, #b5f5ec 100%);
|
||||
display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0;
|
||||
}
|
||||
.hospital-card__name { font-size: 15px; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; }
|
||||
.hospital-card__addr { font-size: 12px; color: var(--text-muted); }
|
||||
.radio-dot {
|
||||
width: 22px; height: 22px; border-radius: 50%; border: 2px solid #d9d9d9;
|
||||
display: flex; align-items: center; justify-content: center; transition: all 0.25s ease; flex-shrink: 0;
|
||||
}
|
||||
.hospital-card.active .radio-dot { border-color: var(--primary); background: var(--primary); }
|
||||
.radio-dot::after { content: ''; width: 8px; height: 8px; border-radius: 50%; background: #fff; opacity: 0; transition: opacity 0.25s ease; }
|
||||
.hospital-card.active .radio-dot::after { opacity: 1; }
|
||||
.bottom-actions { position: absolute; left: 16px; right: 16px; bottom: 18px; padding-bottom: 16px; }
|
||||
.bottom-actions__btn {
|
||||
width: 100%; height: 48px; border-radius: 24px; font-size: 15px; font-weight: 600;
|
||||
border: none; cursor: pointer; background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
|
||||
color: #fff; box-shadow: 0 10px 20px rgba(19, 194, 194, 0.22);
|
||||
}
|
||||
.modal-overlay {
|
||||
position: absolute; inset: 0; background: rgba(0,0,0,0.45); z-index: 100;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.modal-overlay.hidden { display: none; }
|
||||
.modal-card { width: 340px; background: #fff; border-radius: 24px; padding: 24px 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.18); }
|
||||
.modal-card__title { font-size: 18px; font-weight: 700; text-align: center; margin-bottom: 6px; }
|
||||
.modal-card__sub { font-size: 13px; color: var(--text-muted); text-align: center; margin-bottom: 20px; }
|
||||
.modal-field { display: flex; justify-content: space-between; align-items: center; padding: 14px 0; border-bottom: 1px solid #f0f0f0; }
|
||||
.modal-field:last-of-type { border-bottom: none; }
|
||||
.modal-field__label { font-size: 14px; color: var(--text-muted); }
|
||||
.modal-field__value { font-size: 14px; color: var(--text-primary); font-weight: 600; }
|
||||
.modal-confirm-btn {
|
||||
margin-top: 20px; width: 100%; height: 44px; border-radius: 22px; font-size: 15px; font-weight: 600;
|
||||
border: none; cursor: pointer; background: linear-gradient(135deg, #13c2c2 0%, #36cfc9 100%);
|
||||
color: #fff; box-shadow: 0 8px 20px rgba(19, 194, 194, 0.2);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="phone-shell">
|
||||
<div class="phone-status-bar">
|
||||
<span class="time">12:00</span>
|
||||
<div class="icons">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-bar">
|
||||
<a class="nav-back" href="booking-type.html">‹</a>
|
||||
<span class="nav-title">冠脉CTA预约</span>
|
||||
<span class="nav-right" onclick="openModal()">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
||||
个人信息
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="scroll-content">
|
||||
<div class="page-body">
|
||||
<!-- 冠脉CTA免问卷:仅「选择医院 → 预约日期」两步 -->
|
||||
<div class="stepper">
|
||||
<a class="stepper__item stepper__item--active" href="cta-hospital.html"><div class="stepper__dot">1</div><div class="stepper__label">选择医院</div></a>
|
||||
<div class="stepper__line"></div>
|
||||
<div class="stepper__item stepper__item--future"><div class="stepper__dot">2</div><div class="stepper__label">预约日期</div></div>
|
||||
</div>
|
||||
|
||||
<div class="section-title">选择医院</div>
|
||||
<div class="hospital-card active" onclick="selectHospital(this)">
|
||||
<div class="hospital-card__info">
|
||||
<div class="hospital-card__icon">🏥</div>
|
||||
<div>
|
||||
<div class="hospital-card__name">宁夏宝石花医院</div>
|
||||
<div class="hospital-card__addr">宁夏银川市</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="radio-dot"></div>
|
||||
</div>
|
||||
<div class="hospital-card" onclick="selectHospital(this)">
|
||||
<div class="hospital-card__info">
|
||||
<div class="hospital-card__icon">🏥</div>
|
||||
<div>
|
||||
<div class="hospital-card__name">CQ星龙园医院</div>
|
||||
<div class="hospital-card__addr">陕西西安市</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="radio-dot"></div>
|
||||
</div>
|
||||
<div class="hospital-card" onclick="selectHospital(this)">
|
||||
<div class="hospital-card__info">
|
||||
<div class="hospital-card__icon">🏥</div>
|
||||
<div>
|
||||
<div class="hospital-card__name">唐都医院</div>
|
||||
<div class="hospital-card__addr">陕西西安市</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="radio-dot"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom-actions">
|
||||
<button class="bottom-actions__btn" onclick="goNext()">下一步</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-overlay hidden" id="personModal">
|
||||
<div class="modal-card">
|
||||
<div class="modal-card__title">确认个人信息</div>
|
||||
<div class="modal-card__sub">请核对以下信息,确认无误后继续预约</div>
|
||||
<div class="modal-field"><span class="modal-field__label">姓名</span><span class="modal-field__value">刘韵琴</span></div>
|
||||
<div class="modal-field"><span class="modal-field__label">单位</span><span class="modal-field__value">CQ能源第一采油厂</span></div>
|
||||
<div class="modal-field"><span class="modal-field__label">身份证号</span><span class="modal-field__value">6101021994********</span></div>
|
||||
<div class="modal-field"><span class="modal-field__label">性别</span><span class="modal-field__value">女</span></div>
|
||||
<div class="modal-field"><span class="modal-field__label">年龄</span><span class="modal-field__value">32</span></div>
|
||||
<button class="modal-confirm-btn" onclick="closeModal()">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
if (new URLSearchParams(window.location.search).get('from') === 'booking-type') {
|
||||
document.getElementById('personModal').classList.remove('hidden');
|
||||
}
|
||||
function selectHospital(el) {
|
||||
document.querySelectorAll('.hospital-card').forEach(c => c.classList.remove('active'));
|
||||
el.classList.add('active');
|
||||
}
|
||||
// [交互] 冠脉CTA无问卷环节,选择医院后直接进入预约日期
|
||||
function goNext() {
|
||||
location.href = 'cta-date.html';
|
||||
}
|
||||
function openModal() { document.getElementById('personModal').classList.remove('hidden'); }
|
||||
function closeModal() { document.getElementById('personModal').classList.add('hidden'); }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
.scroll-content::-webkit-scrollbar { display: none; }
|
||||
.page-body { padding: 16px; }
|
||||
/* 年度体检计划 Banner 轮播:常规体检 / 胃肠镜体检 / 未开启计划占位,共三张滑动切换 */
|
||||
/* 年度体检计划 Banner 轮播:常规体检 / 胃肠镜体检 / 冠脉CTA体检 / 未开启计划占位,共四张滑动切换 */
|
||||
.banner {
|
||||
position: relative;
|
||||
border-radius: 20px;
|
||||
@@ -127,6 +127,8 @@
|
||||
}
|
||||
.banner-slide--routine { background: linear-gradient(135deg, #0eb5b0 0%, #35d6c5 100%); }
|
||||
.banner-slide--gastro { background: linear-gradient(135deg, #12a5c4 0%, #3cc3dc 100%); }
|
||||
/* 冠脉CTA体检:暖红渐变,呼应心脏/冠脉意象,与青绿的常规、蓝青的胃肠镜区分 */
|
||||
.banner-slide--cta { background: linear-gradient(135deg, #e8544f 0%, #ff8a65 100%); }
|
||||
.banner-slide--waiting { background: linear-gradient(135deg, #93a1b3 0%, #c3ccd8 100%); }
|
||||
/* 右侧大号水印图标 + 圆环装饰,营造 banner 图氛围 */
|
||||
.banner-slide__deco {
|
||||
@@ -454,7 +456,7 @@
|
||||
|
||||
<div class="scroll-content">
|
||||
<div class="page-body">
|
||||
<!-- [交互] 左右滑动切换三张计划 Banner,点击圆点跳转到对应张 -->
|
||||
<!-- [交互] 左右滑动切换四张计划 Banner,点击圆点跳转到对应张 -->
|
||||
<div class="banner">
|
||||
<div class="banner__track" id="bannerTrack">
|
||||
<!-- 第一张:常规体检 | [交互] 点击进入: reports.html(已体检,查看报告) -->
|
||||
@@ -492,7 +494,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第三张:未开启年度体检计划占位图 -->
|
||||
<!-- 第三张:冠脉CTA体检 | [交互] 点击进入: my-appointments-all.html?type=cta(已预约,查看预约) -->
|
||||
<div class="banner-slide banner-slide--cta" onclick="location.href='my-appointments-all.html?type=cta'">
|
||||
<span class="banner-slide__ring"></span>
|
||||
<span class="banner-slide__deco">🫀</span>
|
||||
<div class="banner-slide__title">单位已拟定2026年度冠脉CTA体检计划</div>
|
||||
<div class="banner-slide__date">🗓 体检日期:2026-10-08 至 2026-12-20</div>
|
||||
<!-- 圆圈进度(右下角):已预约 = 60%(已选项目20%→已预约60%→体检中80%→已体检100%),dashoffset = 131.9 × 40% ≈ 52.8 -->
|
||||
<div class="banner-progress">
|
||||
<svg width="52" height="52" viewBox="0 0 52 52" fill="none">
|
||||
<circle cx="26" cy="26" r="21" stroke="rgba(255,255,255,0.35)" stroke-width="4"/>
|
||||
<circle cx="26" cy="26" r="21" stroke="#ffffff" stroke-width="4" stroke-linecap="round" stroke-dasharray="131.9" stroke-dashoffset="52.8" transform="rotate(-90 26 26)"/>
|
||||
</svg>
|
||||
<span class="banner-progress__text">已预约</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第四张:未开启年度体检计划占位图 -->
|
||||
<div class="banner-slide banner-slide--waiting">
|
||||
<span class="banner-slide__deco">🌱</span>
|
||||
<div class="banner-waiting__icon">🌱</div>
|
||||
@@ -505,6 +523,7 @@
|
||||
<span class="banner__dot is-active"></span>
|
||||
<span class="banner__dot"></span>
|
||||
<span class="banner__dot"></span>
|
||||
<span class="banner__dot"></span>
|
||||
</div>
|
||||
|
||||
<!-- [交互] 胃肠镜医院预选通知条:仅管理员开启预选计划期间展示;
|
||||
@@ -601,11 +620,15 @@
|
||||
(function () {
|
||||
var track = document.getElementById('bannerTrack');
|
||||
var dots = document.querySelectorAll('#bannerDots .banner__dot');
|
||||
// 各张计划对应的圆点主色(常规青绿/胃肠镜蓝青/冠脉CTA暖红/占位灰)
|
||||
var DOT_COLORS = ['#13c2c2', '#12a5c4', '#e8544f', '#93a1b3'];
|
||||
// 滚动时按滚动位置判定当前展示张数,同步高亮圆点
|
||||
track.addEventListener('scroll', function () {
|
||||
var index = Math.round(track.scrollLeft / track.clientWidth);
|
||||
dots.forEach(function (dot, i) {
|
||||
dot.classList.toggle('is-active', i === index);
|
||||
var active = i === index;
|
||||
dot.classList.toggle('is-active', active);
|
||||
dot.style.background = active ? DOT_COLORS[index] : '';
|
||||
});
|
||||
});
|
||||
// 点击圆点平滑滚动到对应张
|
||||
|
||||
@@ -119,6 +119,29 @@
|
||||
}
|
||||
.hero-card__title { font-size: 14px; font-weight: 700; color: #0d7878; }
|
||||
.hero-card__range { margin-left: auto; font-size: 10px; color: var(--text-muted); }
|
||||
/* 年份区间选择器:开始/结束两个下拉,选项互相联动保证区间合法 */
|
||||
.year-picker__sep { font-size: 10px; color: var(--text-muted); }
|
||||
.year-select {
|
||||
border: 1px solid var(--border); background: #fff; border-radius: 8px;
|
||||
font-size: 11px; font-weight: 700; color: var(--primary-dark);
|
||||
padding: 2px 18px 2px 6px; font-family: inherit; cursor: pointer; outline: none;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%238c8c8c'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat; background-position: right 5px center;
|
||||
}
|
||||
.year-select:focus { border-color: var(--primary); }
|
||||
/* 顶部年份选择条 */
|
||||
.year-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: #fff;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 10px 14px;
|
||||
box-shadow: var(--paper-shadow);
|
||||
}
|
||||
.year-bar__label { font-size: 12px; font-weight: 700; color: var(--text-secondary); }
|
||||
.hero-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
@@ -317,36 +340,46 @@
|
||||
</div>
|
||||
<div class="scroll-content">
|
||||
<div class="page-body">
|
||||
<!-- ① AI 纵向总结卡 -->
|
||||
<!-- ① 年份选择(置于最顶部,选择区间后整页重渲染) -->
|
||||
<div class="year-bar">
|
||||
<span class="year-bar__label">体检年份</span>
|
||||
<select class="year-select" id="yearFrom" aria-label="开始年份"></select>
|
||||
<span class="year-picker__sep">-</span>
|
||||
<select class="year-select" id="yearTo" aria-label="结束年份"></select>
|
||||
</div>
|
||||
|
||||
<!-- ② AI 纵向总结卡 -->
|
||||
<div class="hero-card">
|
||||
<div class="hero-card__head">
|
||||
<span class="hero-card__ai-badge">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.9 5.6L19.5 10l-5.6 1.9L12 17.5l-1.9-5.6L4.5 10l5.6-1.9z"/></svg>
|
||||
AI
|
||||
</span>
|
||||
<span class="hero-card__title">五年纵向对比总结</span>
|
||||
<span class="hero-card__range">2021 - 2025</span>
|
||||
<span class="hero-card__title" id="heroTitle">五年纵向对比总结</span>
|
||||
</div>
|
||||
<div class="hero-card__range" id="heroRangeMeta" style="margin-left:0;padding:8px 14px 0;"></div>
|
||||
<div class="hero-stats">
|
||||
<div class="hero-stat hero-stat--danger">
|
||||
<div class="hero-stat__value">5</div>
|
||||
<div class="hero-stat__label">今年异常</div>
|
||||
<div class="hero-stat__value" id="statAbn">5</div>
|
||||
<div class="hero-stat__label">期末异常</div>
|
||||
</div>
|
||||
<div class="hero-stat hero-stat--warn">
|
||||
<div class="hero-stat__value">3</div>
|
||||
<div class="hero-stat__label">恶化趋势</div>
|
||||
<div class="hero-stat__value" id="statWorse">3</div>
|
||||
<div class="hero-stat__label">变化趋势</div>
|
||||
</div>
|
||||
<div class="hero-stat hero-stat--danger">
|
||||
<div class="hero-stat__value">1</div>
|
||||
<div class="hero-stat__value" id="statNew">1</div>
|
||||
<div class="hero-stat__label">新增异常</div>
|
||||
</div>
|
||||
<div class="hero-stat hero-stat--success">
|
||||
<div class="hero-stat__value">2</div>
|
||||
<div class="hero-stat__value" id="statBetter">2</div>
|
||||
<div class="hero-stat__label">转好恢复</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- [交互] 总结文案随所选年份区间由脚本按区间数据重新生成 -->
|
||||
<div class="hero-card__text">
|
||||
近五年您的心脑血管代谢相关指标呈持续上行趋势:总胆固醇、甘油三酯、BMI 连续三年上升,低密度脂蛋白今年首次越限,尿酸已连续四年高于正常范围;颈部影像提示生理曲度变直已持续两年。好消息是去年轻度偏高的转氨酶(ALT/AST)今年均回归正常。建议将血脂与体重管理列为本年度健康干预的第一优先级。
|
||||
<p id="heroLead"></p>
|
||||
<p id="heroNotes"></p>
|
||||
</div>
|
||||
<div class="hero-card__ai-note">内容由 AI 基于历年体检数据生成,仅供参考,不构成诊断依据</div>
|
||||
</div>
|
||||
@@ -356,7 +389,6 @@
|
||||
<div class="filter-row">
|
||||
<button class="filter-chip is-active" data-f="all" type="button" onclick="applyFilter(this)">全部</button>
|
||||
<button class="filter-chip" data-f="abn" type="button" onclick="applyFilter(this)">异常</button>
|
||||
<button class="filter-chip" data-f="worse" type="button" onclick="applyFilter(this)">恶化趋势</button>
|
||||
<button class="filter-chip" data-f="normal" type="button" onclick="applyFilter(this)">正常</button>
|
||||
</div>
|
||||
|
||||
@@ -390,11 +422,11 @@
|
||||
{ name: '血常规', keys: ['hgb', 'wbc', 'plt'] }
|
||||
];
|
||||
var NUM = {
|
||||
bmi: { name: 'BMI', unit: 'kg/m²', ref: [18.5, 23.9], v: [23.1, 23.8, 24.5, 25.2, 25.8], badge: ['恶化趋势', 'worse'] },
|
||||
bmi: { name: 'BMI', unit: 'kg/m²', ref: [18.5, 23.9], v: [23.1, 23.8, 24.5, 25.2, 25.8], badge: ['变化趋势', 'worse'] },
|
||||
sbp: { name: '收缩压', unit: 'mmHg', ref: [90, 139], v: [112, 115, 118, 116, 120], badge: ['平稳', 'stable'] },
|
||||
dbp: { name: '舒张压', unit: 'mmHg', ref: [60, 89], v: [72, 74, 73, 76, 78], badge: ['平稳', 'stable'] },
|
||||
tc: { name: '总胆固醇 TC', unit: 'mmol/L', ref: [3.1, 5.7], v: [4.62, 4.95, 5.36, 5.78, 6.10], badge: ['恶化趋势', 'worse'] },
|
||||
tg: { name: '甘油三酯 TG', unit: 'mmol/L', ref: [0.4, 1.7], v: [1.20, 1.35, 1.55, 1.72, 2.08], badge: ['恶化趋势', 'worse'] },
|
||||
tc: { name: '总胆固醇 TC', unit: 'mmol/L', ref: [3.1, 5.7], v: [4.62, 4.95, 5.36, 5.78, 6.10], badge: ['变化趋势', 'worse'] },
|
||||
tg: { name: '甘油三酯 TG', unit: 'mmol/L', ref: [0.4, 1.7], v: [1.20, 1.35, 1.55, 1.72, 2.08], badge: ['变化趋势', 'worse'] },
|
||||
hdl: { name: '高密度脂蛋白 HDL-C', unit: 'mmol/L', ref: [1.04, 1.55], v: [1.35, 1.30, 1.26, 1.22, 1.18], badge: ['平稳', 'stable'] },
|
||||
ldl: { name: '低密度脂蛋白 LDL-C', unit: 'mmol/L', ref: [0, 3.4], v: [2.80, 3.00, 3.10, 3.35, 3.92], badge: ['新增异常', 'new'] },
|
||||
glu: { name: '空腹血糖 GLU', unit: 'mmol/L', ref: [3.9, 6.1], v: [5.0, 5.1, 4.9, 5.3, 5.2], badge: ['平稳', 'stable'] },
|
||||
@@ -419,59 +451,99 @@
|
||||
];
|
||||
|
||||
function isAbn(item, vi) { return item.v[vi] < item.ref[0] || item.v[vi] > item.ref[1]; }
|
||||
// 组内排序权重:异常在前,恶化 > 新增 > 连续异常 > 转好 > 平稳
|
||||
// ===== 所选年份区间(原型仅有 2021-2025 五年体检数据,可选范围以此为准)=====
|
||||
var sel = { from: YEARS[0], to: YEARS[YEARS.length - 1] };
|
||||
function range() {
|
||||
var a = YEARS.indexOf(sel.from), b = YEARS.indexOf(sel.to);
|
||||
return { a: a, b: b, n: b - a + 1, ys: YEARS.slice(a, b + 1) };
|
||||
}
|
||||
// 取指标在当前区间内的数值序列
|
||||
function vals(it) { var r = range(); return it.v.slice(r.a, r.b + 1); }
|
||||
// 区间内是否呈不利走向(端点对比方向性变化),随所选区间动态计算
|
||||
function deltaWorse(key) {
|
||||
var it = NUM[key], vv = vals(it);
|
||||
if (vv.length < 2) return false;
|
||||
var first = vv[0], last = vv[vv.length - 1];
|
||||
var hi = it.ref[1], lo = it.ref[0];
|
||||
if (hi < Infinity && last > hi) return last > first;
|
||||
return last < lo ? last < first : false;
|
||||
}
|
||||
// 组内排序权重:期末异常在前;区间内不利走向 > 期末新增 > 区间内全程异常 > 区间内转好 > 静态分级兜底
|
||||
function weight(key) {
|
||||
var it = NUM[key], b = it.badge[1];
|
||||
var abn = isAbn(it, 4) ? 0 : 1;
|
||||
var order = { worse: 0, new: 1, keep: 2, better: 3, stable: 4 }[b];
|
||||
var it = NUM[key], r = range(), e = r.b, s = r.a;
|
||||
var lastAbn = isAbn(it, e), firstAbn = isAbn(it, s);
|
||||
var abn = lastAbn ? 0 : 1;
|
||||
var order;
|
||||
if (deltaWorse(key)) order = 0;
|
||||
else if (lastAbn && !firstAbn) order = 1;
|
||||
else if (lastAbn) order = 2;
|
||||
else if (!lastAbn && firstAbn) order = 3;
|
||||
else order = 4 + ({ worse: 0, new: 1, keep: 2, better: 3, stable: 4 }[it.badge[1]] || 4);
|
||||
return abn * 10 + order;
|
||||
}
|
||||
// 缩略趋势线(纯内联 SVG,异常点标红)
|
||||
// 缩略趋势线(纯内联 SVG,按所选区间取点,异常点标红)
|
||||
function sparkline(item) {
|
||||
var w = 96, h = 34, pad = 5;
|
||||
var min = Math.min.apply(null, item.v), max = Math.max.apply(null, item.v);
|
||||
var vs = vals(item);
|
||||
var min = Math.min.apply(null, vs), max = Math.max.apply(null, vs);
|
||||
if (max === min) max = min + 1;
|
||||
var step = (w - pad * 2) / 4;
|
||||
var pts = item.v.map(function (v, i) {
|
||||
return (pad + i * step).toFixed(1) + ',' + (h - pad - (v - min) / (max - min) * (h - pad * 2)).toFixed(1);
|
||||
});
|
||||
var dots = item.v.map(function (v, i) {
|
||||
var cx = pad + i * step, cy = h - pad - (v - min) / (max - min) * (h - pad * 2);
|
||||
return '<circle cx="' + cx.toFixed(1) + '" cy="' + cy.toFixed(1) + '" r="2.6" fill="' + ((v < item.ref[0] || v > item.ref[1]) ? '#ff4d4f' : '#13c2c2') + '"/>';
|
||||
var step = vs.length > 1 ? (w - pad * 2) / (vs.length - 1) : 0;
|
||||
function X(i) { return pad + i * step; }
|
||||
function Y(v) { return h - pad - (v - min) / (max - min) * (h - pad * 2); }
|
||||
var pts = vs.map(function (v, i) { return X(i).toFixed(1) + ',' + Y(v).toFixed(1); });
|
||||
var dots = vs.map(function (v, i) {
|
||||
return '<circle cx="' + X(i).toFixed(1) + '" cy="' + Y(v).toFixed(1) + '" r="2.6" fill="' + ((v < item.ref[0] || v > item.ref[1]) ? '#ff4d4f' : '#13c2c2') + '"/>';
|
||||
}).join('');
|
||||
return '<svg width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '"><polyline points="' + pts.join(' ') + '" fill="none" stroke="#13c2c2" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>' + dots + '</svg>';
|
||||
}
|
||||
function fmtV(v) { return v >= 100 ? String(Math.round(v)) : String(v); }
|
||||
// 区间端点对比:返回 {last, delta, worse, newAbn, keepAbn, better, n}
|
||||
function endCompare(it) {
|
||||
var r = range(), vv = vals(it);
|
||||
var first = vv[0], last = vv[vv.length - 1];
|
||||
var hi = it.ref[1], lo = it.ref[0];
|
||||
var lastAbn = last < lo || last > hi, firstAbn = first < lo || first > hi;
|
||||
var worse = (hi < Infinity && last > hi) ? last > first : (last < lo ? last < first : false);
|
||||
var allAbn = vv.every(function (v) { return v < lo || v > hi; });
|
||||
return { r: r, last: last, delta: last - first, worse: worse, newAbn: lastAbn && !firstAbn, keepAbn: lastAbn && firstAbn && allAbn, better: !lastAbn && firstAbn };
|
||||
}
|
||||
function fmtDelta(it, d) {
|
||||
var dec = it.v[0] >= 100 || Math.abs(d) >= 10 ? 0 : (Math.abs(d) >= 1 ? 1 : 2);
|
||||
return (d > 0 ? '+' : '') + d.toFixed(dec);
|
||||
}
|
||||
|
||||
// ===== 渲染数值指标分组(大类折叠卡,默认收起;筛选时自动展开有匹配项的大类)=====
|
||||
// ===== 渲染数值指标分组(大类折叠卡,默认全部展开;点击大类头可收起)=====
|
||||
var filter = 'all';
|
||||
function renderGroups() {
|
||||
var e = range().b;
|
||||
var html = '';
|
||||
CATS.forEach(function (cat) {
|
||||
var keys = cat.keys.slice().sort(function (a, b) { return weight(a) - weight(b); });
|
||||
var abnCount = cat.keys.filter(function (k) { return isAbn(NUM[k], 4); }).length;
|
||||
var abnCount = cat.keys.filter(function (k) { return isAbn(NUM[k], e); }).length;
|
||||
var cards = '';
|
||||
var shown = 0;
|
||||
keys.forEach(function (key) {
|
||||
var it = NUM[key];
|
||||
var abn = isAbn(it, 4);
|
||||
var show = filter === 'all' || (filter === 'abn' && abn) || (filter === 'worse' && it.badge[1] === 'worse') || (filter === 'normal' && !abn);
|
||||
var last = it.v[e];
|
||||
var abn = isAbn(it, e);
|
||||
var show = filter === 'all' || (filter === 'abn' && abn) || (filter === 'normal' && !abn);
|
||||
if (!show) return;
|
||||
var arrow = abn ? (it.v[4] > it.ref[1] ? ' ↑' : ' ↓') : '';
|
||||
shown++;
|
||||
var arrow = abn ? (last > it.ref[1] ? ' ↑' : ' ↓') : '';
|
||||
cards += '<div class="metric-card" data-key="' + key + '" onclick="goDetail(\'' + key + '\')">'
|
||||
+ '<div class="metric-card__top"><span class="metric-card__name">' + it.name + '</span>'
|
||||
+ '<span class="badge badge--' + it.badge[1] + '">' + it.badge[0] + '</span></div>'
|
||||
+ '<div class="metric-card__bottom"><div>'
|
||||
+ '<div class="metric-card__value' + (abn ? ' is-abn' : '') + '">' + fmtV(it.v[4]) + arrow + '<span class="metric-card__unit">' + it.unit + '</span></div>'
|
||||
+ '<div class="metric-card__value' + (abn ? ' is-abn' : '') + '">' + fmtV(last) + arrow + '<span class="metric-card__unit">' + it.unit + '</span></div>'
|
||||
+ '<div class="metric-card__ref">参考 ' + it.ref[0] + '-' + it.ref[1] + '</div></div>'
|
||||
+ '<div class="metric-card__spark">' + sparkline(it) + '</div>'
|
||||
+ '</div></div>';
|
||||
});
|
||||
if (!cards) return;
|
||||
var collapsed = filter === 'all' ? ' is-collapsed' : '';
|
||||
html += '<div class="cat-group' + collapsed + '">'
|
||||
html += '<div class="cat-group">'
|
||||
+ '<div class="cat-group__head" onclick="toggleCat(this)">' + cat.name
|
||||
+ '<small>' + cat.keys.length + ' 项</small>'
|
||||
+ (abnCount ? '<span class="cat-group__abn">异常 ' + abnCount + '</span>' : '')
|
||||
+ '<small>' + shown + ' 项</small>'
|
||||
+ (filter !== 'normal' && abnCount ? '<span class="cat-group__abn">异常 ' + abnCount + '</span>' : '')
|
||||
+ '<span class="cat-group__arrow">▾</span></div>'
|
||||
+ '<div class="cat-group__body">' + cards + '</div></div>';
|
||||
});
|
||||
@@ -485,25 +557,133 @@
|
||||
btn.classList.add('is-active');
|
||||
filter = btn.getAttribute('data-f');
|
||||
renderGroups();
|
||||
renderQual();
|
||||
}
|
||||
// [交互] 点击指标卡进入详情页,携带当前区间(详情页同步按区间渲染)
|
||||
function goDetail(item) {
|
||||
location.href = 'indicator-compare-detail.html?item=' + encodeURIComponent(item) + '&from=' + sel.from + '&to=' + sel.to;
|
||||
}
|
||||
// [交互] 点击指标卡进入详情页(与报告页行级入口同一目标页)
|
||||
function goDetail(item) { location.href = 'indicator-compare-detail.html?item=' + encodeURIComponent(item); }
|
||||
|
||||
// ===== 渲染定性项目区 =====
|
||||
// ===== 渲染定性项目区(圆点与结论均随区间变化)=====
|
||||
function renderQual() {
|
||||
var r = range();
|
||||
var html = '';
|
||||
QUAL.forEach(function (q) {
|
||||
var dots = q.st.map(function (s) { return '<i class="is-' + s + '"></i>'; }).join('');
|
||||
var st = q.st.slice(r.a, r.b + 1);
|
||||
// 按当前筛选过滤定性项目:以区间末年的状态判断是否有异常
|
||||
var curAbn = st[st.length - 1] === 'a';
|
||||
if (!(filter === 'all' || (filter === 'abn' && curAbn) || (filter === 'normal' && !curAbn))) return;
|
||||
var dots = st.map(function (s) { return '<i class="is-' + s + '"></i>'; }).join('');
|
||||
// 区间内结论按圆点序列动态生成
|
||||
var n = st.length, tail = 0, head = -1;
|
||||
for (var i = n - 1; i >= 0 && st[i] === 'a'; i--) tail++;
|
||||
for (var j = 0; j < n; j++) { if (st[j] === 'a') { head = j; break; } }
|
||||
var desc;
|
||||
var preAbn = q.st.slice(0, r.a).indexOf('a') !== -1;
|
||||
if (!tail) {
|
||||
desc = head !== -1
|
||||
? r.ys[head] + ' 年曾异常,' + r.ys[n - 1] + ' 年已恢复正常'
|
||||
: (preAbn ? '所选区间未见异常' : '历年未见异常');
|
||||
} else if (tail === n) {
|
||||
desc = n === 1 ? '该年度存在异常' : (preAbn && head === 0 ? '异常持续 ' + (n + r.a) + ' 年(区间起点前已检出)' : '持续 ' + n + ' 年');
|
||||
} else {
|
||||
desc = r.ys[head] + ' 年检出,至 ' + r.ys[n - 1 - tail] + ' 年恢复';
|
||||
}
|
||||
html += '<div class="qual-card" onclick="goDetail(\'' + q.key + '\')">'
|
||||
+ '<div class="qual-card__main"><div class="qual-card__name">' + q.name + '</div>'
|
||||
+ '<div class="qual-card__desc' + (q.warn ? ' is-warn' : '') + '">' + q.desc + '</div></div>'
|
||||
+ '<div class="qual-card__desc' + (tail ? ' is-warn' : '') + '">' + desc + '</div></div>'
|
||||
+ '<div class="qual-dots">' + dots + '</div>'
|
||||
+ '<div class="qual-years">21-25</div></div>';
|
||||
+ '<div class="qual-years">' + r.ys[0].slice(2) + '-' + r.ys[n - 1].slice(2) + '</div></div>';
|
||||
});
|
||||
document.getElementById('qualBody').innerHTML = html;
|
||||
document.getElementById('qualBody').innerHTML = html || '<div class="metric-card__ref" style="text-align:center;padding:16px 0">该筛选条件下暂无定性项目</div>';
|
||||
}
|
||||
renderGroups();
|
||||
renderQual();
|
||||
|
||||
// ===== AI 总结文案(按所选区间数据生成,模拟端点对比口径)=====
|
||||
function buildSummary() {
|
||||
var r = range();
|
||||
var nums = Object.keys(NUM).map(function (k) {
|
||||
var it = NUM[k];
|
||||
return { key: k, it: it, cmp: endCompare(it) };
|
||||
});
|
||||
var abnNums = nums.filter(function (x) { var l = x.cmp.last; return l < x.it.ref[0] || l > x.it.ref[1]; });
|
||||
var lead;
|
||||
if (r.n === 1) {
|
||||
// 单年度:只报当年结果,不做趋势对比
|
||||
lead = r.ys[0] + ' 年度体检共 ' + abnNums.length + ' 项指标处于参考范围之外' +
|
||||
(abnNums.length ? ':' + abnNums.map(function (x) { return x.it.name; }).join('、') + '。' : '。');
|
||||
} else {
|
||||
lead = '在 ' + r.ys[0] + '–' + r.ys[r.n - 1] + ' 共 ' + r.n + ' 次体检中,您的多项指标呈持续上行趋势:' +
|
||||
nums.filter(function (x) { return x.cmp.worse; }).map(function (x) { return x.it.name; }).join('、') +
|
||||
' 较 ' + r.ys[0] + ' 年分别升高 ' +
|
||||
nums.filter(function (x) { return x.cmp.worse; }).map(function (x) { return fmtDelta(x.it, x.cmp.delta); }).join(' / ') +
|
||||
';期末共 ' + abnNums.length + ' 项指标处于参考范围之外。';
|
||||
}
|
||||
var notes = r.n > 1 ? nums.filter(function (x) { return x.cmp.newAbn || x.cmp.keepAbn || x.cmp.better; }).map(function (x) {
|
||||
var y = r.n + ' 年间';
|
||||
if (x.cmp.newAbn) return x.it.name + y + '首次越限';
|
||||
if (x.cmp.keepAbn) return x.it.name + y + '持续高于正常范围';
|
||||
return x.it.name + y + '回归正常范围';
|
||||
}) : [];
|
||||
var qualNotes = QUAL.map(function (q) {
|
||||
var st = q.st.slice(r.a, r.b + 1);
|
||||
var n = st.length, tail = 0, head = -1;
|
||||
for (var i = n - 1; i >= 0 && st[i] === 'a'; i--) tail++;
|
||||
for (var j = 0; j < n; j++) { if (st[j] === 'a') { head = j; break; } }
|
||||
if (tail === n && n > 1) return q.name + '异常持续 ' + n + ' 年';
|
||||
if (tail && head > 0 && n > 1) return q.name + '自 ' + r.ys[head] + ' 年起异常';
|
||||
return '';
|
||||
}).filter(Boolean);
|
||||
var all = notes.concat(qualNotes);
|
||||
var fallback = r.n === 1 ? '当年各指标与检查结论详见下方明细。' : '区间内各指标与检查结论未见明显异常波动。';
|
||||
return { lead: lead, notes: all.length ? all.join(';') + '。' : fallback };
|
||||
}
|
||||
|
||||
// ===== 区间应用:联动下拉选项、整页重渲染 =====
|
||||
function fillYearSelect(selEl, list) {
|
||||
selEl.innerHTML = list.map(function (y) { return '<option value="' + y + '">' + y + '</option>'; }).join('');
|
||||
}
|
||||
function applyRange() {
|
||||
var r = range();
|
||||
document.getElementById('heroTitle').textContent = r.n + ' 年纵向对比总结';
|
||||
document.getElementById('heroRangeMeta').textContent =
|
||||
r.ys[0] + ' - ' + r.ys[r.n - 1] + ' · 覆盖 ' + r.n + ' 次体检';
|
||||
var nums = Object.keys(NUM).map(function (k) { return { it: NUM[k], cmp: endCompare(NUM[k]) }; });
|
||||
document.getElementById('statAbn').textContent = nums.filter(function (x) {
|
||||
return x.cmp.last < x.it.ref[0] || x.cmp.last > x.it.ref[1];
|
||||
}).length;
|
||||
document.getElementById('statWorse').textContent = nums.filter(function (x) { return x.cmp.worse; }).length;
|
||||
document.getElementById('statNew').textContent = nums.filter(function (x) { return x.cmp.newAbn; }).length;
|
||||
document.getElementById('statBetter').textContent = nums.filter(function (x) { return x.cmp.better; }).length;
|
||||
var sum = buildSummary();
|
||||
document.getElementById('heroLead').textContent = sum.lead;
|
||||
document.getElementById('heroNotes').textContent = sum.notes;
|
||||
renderGroups();
|
||||
renderQual();
|
||||
}
|
||||
(function initYearPicker() {
|
||||
var fromSel = document.getElementById('yearFrom');
|
||||
var toSel = document.getElementById('yearTo');
|
||||
fromSel.addEventListener('change', function () {
|
||||
sel.from = fromSel.value;
|
||||
// 开始年不得晚于结束年:自动顶到结束年,并反向刷新选项
|
||||
if (Number(sel.from) > Number(sel.to)) { sel.to = sel.from; toSel.value = sel.to; }
|
||||
fillYearSelect(toSel, YEARS.filter(function (y) { return Number(y) >= Number(sel.from); }));
|
||||
toSel.value = sel.to;
|
||||
applyRange();
|
||||
});
|
||||
toSel.addEventListener('change', function () {
|
||||
sel.to = toSel.value;
|
||||
if (Number(sel.to) < Number(sel.from)) { sel.from = sel.to; fromSel.value = sel.from; }
|
||||
fillYearSelect(fromSel, YEARS.filter(function (y) { return Number(y) <= Number(sel.to); }));
|
||||
fromSel.value = sel.from;
|
||||
applyRange();
|
||||
});
|
||||
fillYearSelect(fromSel, YEARS);
|
||||
fillYearSelect(toSel, YEARS);
|
||||
fromSel.value = sel.from;
|
||||
toSel.value = sel.to;
|
||||
})();
|
||||
applyRange();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
/* 顶部体检类型 Tab */
|
||||
.type-tabs {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 8px;
|
||||
padding: 5px;
|
||||
background: rgba(255,255,255,0.92);
|
||||
@@ -384,10 +384,11 @@
|
||||
</div>
|
||||
|
||||
<div class="scroll-content">
|
||||
<!-- [交互] 点击切换 常规体检/胃肠镜体检 详情 -->
|
||||
<!-- [交互] 点击切换 常规体检/胃肠镜体检/冠脉CTA体检 详情 -->
|
||||
<div class="type-tabs">
|
||||
<button class="type-tabs__btn type-tabs__btn--active" type="button" id="tabRoutine" onclick="setType('routine')">常规体检</button>
|
||||
<button class="type-tabs__btn" type="button" id="tabGastro" onclick="setType('gastro')">胃肠镜体检</button>
|
||||
<button class="type-tabs__btn" type="button" id="tabCta" onclick="setType('cta')">冠脉CTA体检</button>
|
||||
</div>
|
||||
|
||||
<!-- ======================= 常规体检 · 待体检 ======================= -->
|
||||
@@ -554,6 +555,72 @@
|
||||
<button class="rebook-btn" style="width:auto;padding:0 40px;" type="button" onclick="location.href='gastro-hospital.html'">立即预约</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ======================= 冠脉CTA体检 · 待体检 ======================= -->
|
||||
<div class="panel hidden" data-type="cta" data-status="pending">
|
||||
<div class="summary-card">
|
||||
<div class="section-title">冠脉CTA体检</div>
|
||||
<div class="summary-list">
|
||||
<div class="summary-item"><div class="summary-item__label">体检医院</div><div class="summary-item__value">宁夏宝石花医院</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检员工</div><div class="summary-item__value">刘韵琴</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检地址</div><div class="summary-item__value">银川市西夏区怀远路148号</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检日期</div><div class="summary-item__value">2026年3月23日</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检项目</div><div class="summary-item__value">冠脉CTA体检</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">状态</div><div class="summary-item__value" style="color:#fa8c16;">待体检</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips-card">
|
||||
<div class="tips-card__title">体检须知</div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查前24小时请避免剧烈运动,检查当天避免吸烟,勿饮用咖啡、浓茶等刺激性饮品。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>心率过快或心律不齐者,请遵医嘱在检查前服用控制心率药物(如β受体阻滞剂)。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>检查需屏气配合,请提前练习平静状态下屏气10~15秒。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>对碘对比剂过敏、甲状腺功能异常、肾功能不全或妊娠期,请提前告知医生。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>请携带本人身份证件按时前往医院。</span></div>
|
||||
<div class="tips-card__item"><span class="tips-card__dot"></span><span>若需取消预约,请至少提前一天操作。</span></div>
|
||||
</div>
|
||||
<div class="progress-card">
|
||||
<div class="section-title">项目列表</div>
|
||||
<div class="project-list">
|
||||
<div class="project-item"><div class="project-item__icon project-item__icon--pending">●</div><div class="project-item__name">冠脉钙化积分扫描</div><div class="project-item__status project-item__status--pending">未检</div></div>
|
||||
<div class="project-item"><div class="project-item__icon project-item__icon--pending">●</div><div class="project-item__name">冠脉CTA成像</div><div class="project-item__status project-item__status--pending">未检</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ======================= 冠脉CTA体检 · 已完成 ======================= -->
|
||||
<div class="panel hidden" data-type="cta" data-status="done">
|
||||
<div class="summary-card">
|
||||
<div class="section-title">冠脉CTA体检</div>
|
||||
<div class="summary-list">
|
||||
<div class="summary-item"><div class="summary-item__label">体检医院</div><div class="summary-item__value">宁夏宝石花医院</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检员工</div><div class="summary-item__value">刘韵琴</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检地址</div><div class="summary-item__value">银川市西夏区怀远路148号</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检日期</div><div class="summary-item__value">2026年3月23日</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">体检项目</div><div class="summary-item__value">冠脉CTA体检</div></div>
|
||||
<div class="summary-item"><div class="summary-item__label">状态</div><div class="summary-item__value" style="color:#52c41a;">已体检</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-card">
|
||||
<div class="section-title">项目列表</div>
|
||||
<div class="project-list">
|
||||
<div class="project-item"><div class="project-item__icon project-item__icon--done">✓</div><div class="project-item__name">冠脉钙化积分扫描</div><div class="project-item__status project-item__status--done">已体检</div></div>
|
||||
<div class="project-item"><div class="project-item__icon project-item__icon--done">✓</div><div class="project-item__name">冠脉CTA成像</div><div class="project-item__status project-item__status--done">已体检</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ======================= 冠脉CTA体检 · 无预约信息 ======================= -->
|
||||
<div class="panel hidden" data-type="cta" data-status="none">
|
||||
<div class="empty">
|
||||
<div class="empty__icon">
|
||||
<svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="#bfbfbf" stroke-width="1.6"><rect x="3" y="4" width="18" height="17" rx="3"/><path d="M3 9h18"/><path d="M8 2v4M16 2v4"/><path d="M9 15l2.2 2.2L15 13.5"/></svg>
|
||||
</div>
|
||||
<div class="empty__title">暂无冠脉CTA体检预约</div>
|
||||
<div class="empty__desc">您还没有预约冠脉CTA体检,预约成功后可在此查看预约详情、体检须知与检查项目。</div>
|
||||
<!-- [交互] 点击跳转至: cta-hospital.html(进入冠脉CTA预约流程) -->
|
||||
<button class="rebook-btn" style="width:auto;padding:0 40px;" type="button" onclick="location.href='cta-hospital.html'">立即预约</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -604,6 +671,7 @@
|
||||
currentType = type;
|
||||
document.getElementById('tabRoutine').classList.toggle('type-tabs__btn--active', type === 'routine');
|
||||
document.getElementById('tabGastro').classList.toggle('type-tabs__btn--active', type === 'gastro');
|
||||
document.getElementById('tabCta').classList.toggle('type-tabs__btn--active', type === 'cta');
|
||||
applyView();
|
||||
}
|
||||
|
||||
@@ -689,13 +757,13 @@
|
||||
fillProgress('r', ROUTINE_PROJECTS, 5); // 常规·待体检 5/26
|
||||
fillProgress('rd', ROUTINE_PROJECTS, 26); // 常规·已完成 26/26
|
||||
|
||||
// [交互] URL 参数直达:?type=routine|gastro&status=pending|done|none
|
||||
// [交互] URL 参数直达:?type=routine|gastro|cta&status=pending|done|none
|
||||
(function initFromUrl() {
|
||||
if (!window.URLSearchParams) { return; }
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var pType = params.get('type');
|
||||
var pStatus = params.get('status');
|
||||
if (pType === 'routine' || pType === 'gastro') { setType(pType); }
|
||||
if (pType === 'routine' || pType === 'gastro' || pType === 'cta') { setType(pType); }
|
||||
if (pStatus === 'pending' || pStatus === 'done' || pStatus === 'none') {
|
||||
setDemoStatus(pStatus);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>冠脉CTA体检报告</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
:root {
|
||||
--primary: #20c7c7;
|
||||
--primary-dark: #119b9b;
|
||||
--primary-light: #e8fbfb;
|
||||
--border: #cfeeee;
|
||||
--line: #dff3f3;
|
||||
--bg-page: #f0f2f5;
|
||||
--bg-content: #f6fbfb;
|
||||
--text-primary: #1a1a1a;
|
||||
--text-secondary: #666;
|
||||
--text-muted: #8c8c8c;
|
||||
--success: #52c41a;
|
||||
--paper-shadow: 0 8px 24px rgba(17, 155, 155, 0.08);
|
||||
}
|
||||
body {
|
||||
background: var(--bg-page);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.phone-shell {
|
||||
width: 390px;
|
||||
min-height: 844px;
|
||||
background: var(--bg-content);
|
||||
border-radius: 44px;
|
||||
box-shadow: 0 20px 60px rgba(0,0,0,0.25), inset 0 0 0 2px #e0e0e0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.phone-status-bar {
|
||||
height: 44px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.phone-status-bar .time { font-size: 15px; font-weight: 700; }
|
||||
.phone-status-bar .icons { display: flex; gap: 6px; align-items: center; }
|
||||
.nav-bar {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
}
|
||||
.nav-back {
|
||||
font-size: 18px;
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
.nav-title {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.nav-action {
|
||||
margin-left: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--primary-dark);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
.scroll-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
background: linear-gradient(180deg, #ecfbfb 0%, #f7fbfb 160px, #f7fbfb 100%);
|
||||
}
|
||||
.scroll-content::-webkit-scrollbar { display: none; }
|
||||
.page-body { padding: 14px; }
|
||||
|
||||
/* 报告卡片 */
|
||||
.report-paper {
|
||||
background: #fff;
|
||||
border-radius: 20px;
|
||||
box-shadow: var(--paper-shadow);
|
||||
border: 1px solid rgba(32, 199, 199, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
.report-header {
|
||||
padding: 18px 16px 14px;
|
||||
background: linear-gradient(180deg, #fbffff 0%, #f4ffff 100%);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.report-header__top {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.report-header__title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
color: #0f7d7d;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.report-header__sub {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.report-tag--cta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 62px;
|
||||
height: 28px;
|
||||
padding: 0 10px;
|
||||
border-radius: 14px;
|
||||
background: #e6fffb;
|
||||
color: #08979c;
|
||||
border: 1px solid #87e8de;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 章节 */
|
||||
.report-section {
|
||||
padding: 14px 16px 0;
|
||||
}
|
||||
.report-section__title {
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
margin: 0 -16px 12px;
|
||||
background: linear-gradient(90deg, #78e3e3 0%, #a4eded 100%);
|
||||
color: #0c7070;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.report-section__title--score {
|
||||
background: linear-gradient(90deg, #ffd591 0%, #ffe7ba 100%);
|
||||
color: #ad6800;
|
||||
}
|
||||
.report-section__title--vessel {
|
||||
background: linear-gradient(90deg, #b5f5ec 0%, #d9f9f4 100%);
|
||||
color: #006d75;
|
||||
}
|
||||
|
||||
/* 检查字段 */
|
||||
.field-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
.field-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.field-item__label {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
font-weight: 600;
|
||||
}
|
||||
.field-item__value-wrap {
|
||||
position: relative;
|
||||
}
|
||||
.field-item__value {
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
color: var(--text-primary);
|
||||
background: #f9fffe;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
min-height: 40px;
|
||||
max-height: 76px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
.field-item.is-expanded .field-item__value {
|
||||
max-height: 600px;
|
||||
}
|
||||
.field-item__fade {
|
||||
position: absolute;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
height: 32px;
|
||||
background: linear-gradient(180deg, rgba(249,255,254,0) 0%, rgba(249,255,254,0.96) 60%);
|
||||
pointer-events: none;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
.field-item.is-expanded .field-item__fade {
|
||||
display: none;
|
||||
}
|
||||
.field-item__toggle {
|
||||
display: none;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
bottom: 8px;
|
||||
border: none;
|
||||
background: #f9fffe;
|
||||
color: var(--primary-dark);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
z-index: 1;
|
||||
}
|
||||
.field-item__toggle.is-visible {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
/* 冠脉病变分段列表 */
|
||||
.vessel-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
.vessel-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
background: #f9fffe;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.vessel-item__name { font-size: 13px; font-weight: 700; color: var(--text-primary); width: 128px; flex-shrink: 0; }
|
||||
.vessel-item__desc { flex: 1; font-size: 12px; color: var(--text-secondary); line-height: 1.6; }
|
||||
.vessel-item__grade {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.vessel-item__grade--ok { background: #f6ffed; color: #52c41a; border: 1px solid #b7eb8f; }
|
||||
.vessel-item__grade--warn { background: #fff7e6; color: #fa8c16; border: 1px solid #ffd591; }
|
||||
|
||||
/* 影像报告 */
|
||||
.image-section__label {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.image-view-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 14px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: #f9fffe;
|
||||
color: var(--primary-dark);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
margin-bottom: 14px;
|
||||
transition: border-color 0.2s, background 0.2s;
|
||||
}
|
||||
.image-view-link:hover { border-color: var(--primary); background: var(--primary-light); }
|
||||
|
||||
/* 分割线 */
|
||||
.divider {
|
||||
height: 1px;
|
||||
background: var(--line);
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
/* 返回按钮 */
|
||||
.back-btn-wrap {
|
||||
padding: 10px 16px 18px;
|
||||
}
|
||||
.back-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
border: none;
|
||||
border-radius: 23px;
|
||||
background: linear-gradient(135deg, #13c2c2, #36cfc9);
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8px 20px rgba(19, 194, 194, 0.22);
|
||||
}
|
||||
.bottom-spacer { height: 20px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="phone-shell">
|
||||
<div class="phone-status-bar">
|
||||
<span class="time">12:00</span>
|
||||
<div class="icons">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 6l5 5 5-5"/><path d="M4 9l3 3 3-3" opacity="0.5"/></svg>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="1" y="6" width="18" height="12" rx="2"/><path d="M21 10v4"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-bar">
|
||||
<!-- [交互] 返回按钮:返回体检报告列表 -->
|
||||
<span class="nav-back" onclick="location.href='reports.html'">‹</span>
|
||||
<span class="nav-title">冠脉CTA报告</span>
|
||||
<!-- [交互] 下载按钮:下载冠脉CTA报告 -->
|
||||
<a class="nav-action" href="javascript:void(0)">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||
下载
|
||||
</a>
|
||||
</div>
|
||||
<div class="scroll-content">
|
||||
<div class="page-body">
|
||||
<div class="report-paper">
|
||||
<!-- 报告头部 -->
|
||||
<div class="report-header">
|
||||
<div class="report-header__top">
|
||||
<div>
|
||||
<div class="report-header__title">2025年冠脉CTA报告</div>
|
||||
<div class="report-header__sub">姓名:张旭
|
||||
<br>性别:男
|
||||
<br>年龄:32
|
||||
<br>身份证号:430626198503250024
|
||||
<br>体检日期:2025-03-21
|
||||
<br>体检医院:CQ星龙园医院
|
||||
</div>
|
||||
</div>
|
||||
<span class="report-tag--cta">冠脉CTA体检</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== 检查所见 ========== -->
|
||||
<div class="report-section">
|
||||
<div class="report-section__title">检查所见</div>
|
||||
<div class="field-list">
|
||||
<div class="field-item" id="field-technique">
|
||||
<div class="field-item__label">扫描技术与图像质量</div>
|
||||
<div class="field-item__value-wrap">
|
||||
<div class="field-item__value">回顾性心电门控冠脉CTA扫描,扫描范围自气管分叉至心尖部。扫描时心率68次/分,屏气良好,图像质量满足诊断要求。冠脉分布:右侧型。</div>
|
||||
<div class="field-item__fade"></div>
|
||||
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-item" id="field-cardiac">
|
||||
<div class="field-item__label">心脏及心外所见</div>
|
||||
<div class="field-item__value-wrap">
|
||||
<div class="field-item__value">各心腔大小未见扩大,左心耳未见血栓,主动脉及瓣膜未见明显钙化,心包少量积液。双肺下叶少许条索影。</div>
|
||||
<div class="field-item__fade"></div>
|
||||
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- ========== 钙化积分 ========== -->
|
||||
<div class="report-section">
|
||||
<div class="report-section__title report-section__title--score">冠状动脉钙化积分</div>
|
||||
<div class="field-list">
|
||||
<div class="field-item" id="field-agatston">
|
||||
<div class="field-item__label">Agatston 总积分</div>
|
||||
<div class="field-item__value-wrap">
|
||||
<div class="field-item__value">Agatston 总积分约 86 分(轻度钙化)。其中LAD约52分,RCA约28分,LCX约6分,LM未见明显钙化。</div>
|
||||
<div class="field-item__fade"></div>
|
||||
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- ========== 冠脉病变 ========== -->
|
||||
<div class="report-section">
|
||||
<div class="report-section__title report-section__title--vessel">冠脉病变</div>
|
||||
<div class="vessel-list">
|
||||
<div class="vessel-item"><div class="vessel-item__name">左主干 LM</div><div class="vessel-item__desc">未见斑块及狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">左前降支 LAD 近段</div><div class="vessel-item__desc">混合斑块,管腔狭窄约30%</div><span class="vessel-item__grade vessel-item__grade--warn">轻度狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">左前降支 LAD 中段</div><div class="vessel-item__desc">管壁光滑,未见狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">第一对角支 D1</div><div class="vessel-item__desc">钙化斑块,管腔狭窄<25%</div><span class="vessel-item__grade vessel-item__grade--ok">未见明显狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">左回旋支 LCX 近段</div><div class="vessel-item__desc">管壁光滑,未见狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">左回旋支 LCX 远段</div><div class="vessel-item__desc">少量钙化斑块,管腔未见明显狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见明显狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">右冠状动脉 RCA 近段</div><div class="vessel-item__desc">钙化斑块,管腔狭窄约40%</div><span class="vessel-item__grade vessel-item__grade--warn">轻度狭窄</span></div>
|
||||
<div class="vessel-item"><div class="vessel-item__name">右冠状动脉 RCA 中远段</div><div class="vessel-item__desc">管壁光滑,未见狭窄</div><span class="vessel-item__grade vessel-item__grade--ok">未见狭窄</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- ========== 诊断结论 ========== -->
|
||||
<div class="report-section">
|
||||
<div class="report-section__title">诊断结论</div>
|
||||
<div class="field-list">
|
||||
<div class="field-item" id="field-conclusion">
|
||||
<div class="field-item__label">影像诊断</div>
|
||||
<div class="field-item__value-wrap">
|
||||
<div class="field-item__value">1. 冠状动脉粥样硬化表现;2. LAD近段混合斑块伴管腔约30%狭窄,RCA近段钙化斑块伴约40%狭窄,余所见冠脉未见明显狭窄;3. 冠状动脉轻度钙化(Agatston 总积分约86分);4. CAD-RADS 2。</div>
|
||||
<div class="field-item__fade"></div>
|
||||
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field-item" id="field-advice">
|
||||
<div class="field-item__label">健康建议</div>
|
||||
<div class="field-item__value-wrap">
|
||||
<div class="field-item__value">建议低盐低脂饮食,规律有氧运动,控制血压、血脂、血糖;他汀类用药及随访方案请心内科门诊评估,结合危险因素决定下一步功能学检查。</div>
|
||||
<div class="field-item__fade"></div>
|
||||
<button class="field-item__toggle" type="button" onclick="toggleField(this)">展开</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- ========== 影像报告 ========== -->
|
||||
<div class="report-section">
|
||||
<div class="report-section__title">影像报告</div>
|
||||
<div class="image-section__label">冠脉CTA原始图像</div>
|
||||
<div class="image-view-link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
查看
|
||||
</div>
|
||||
<div class="image-section__label">三维重建图像</div>
|
||||
<div class="image-view-link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
查看
|
||||
</div>
|
||||
<div class="image-section__label">钙化积分报告</div>
|
||||
<div class="image-view-link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
查看
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<div class="back-btn-wrap">
|
||||
<!-- [交互] 返回报告列表按钮 -->
|
||||
<button class="back-btn" onclick="location.href='reports.html'">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>
|
||||
返回报告列表
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-spacer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// [交互] 展开/收起字段内容
|
||||
function toggleField(btn) {
|
||||
var item = btn.closest('.field-item');
|
||||
var fade = item.querySelector('.field-item__fade');
|
||||
var isExpanded = item.classList.toggle('is-expanded');
|
||||
btn.innerHTML = isExpanded
|
||||
? '收起 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>'
|
||||
: '展开 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>';
|
||||
if (fade) fade.style.display = isExpanded ? 'none' : '';
|
||||
}
|
||||
|
||||
// 页面加载后,检测哪些字段内容超过3行,仅对超出的显示展开按钮
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var items = document.querySelectorAll('.field-item');
|
||||
items.forEach(function(item) {
|
||||
var value = item.querySelector('.field-item__value');
|
||||
var btn = item.querySelector('.field-item__toggle');
|
||||
if (!value || !btn) return;
|
||||
// scrollHeight 为完整内容高度,clientHeight 为可见高度
|
||||
if (value.scrollHeight > value.clientHeight + 2) {
|
||||
btn.classList.add('is-visible');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -104,6 +104,7 @@
|
||||
border-radius: 11px; font-size: 11px; font-weight: 600; white-space: nowrap; flex-shrink: 0;
|
||||
}
|
||||
.report-tag--gastro { background: #e6fffb; color: #08979c; border: 1px solid #87e8de; }
|
||||
.report-tag--cta { background: #fff1f0; color: #cf1322; border: 1px solid #ffa39e; }
|
||||
.report-tag--regular { background: #e6f7ff; color: #096dd9; border: 1px solid #91d5ff; }
|
||||
.report-item__arrow { font-size: 18px; color: #c6c6c6; flex-shrink: 0; }
|
||||
.bottom-spacer { height: 28px; }
|
||||
@@ -134,7 +135,7 @@
|
||||
<div class="sum-card__divider"></div>
|
||||
<div class="sum-card__meta">
|
||||
<div><span class="k">起始年份</span><span class="v">2012</span></div>
|
||||
<div><span class="k">报告总数</span><span class="v">11 份</span></div>
|
||||
<div><span class="k">报告总数</span><span class="v">12 份</span></div>
|
||||
</div>
|
||||
<svg class="sum-card__timeline" width="96" height="36" viewBox="0 0 96 36">
|
||||
<line x1="8" y1="11" x2="88" y2="11" stroke="rgba(255,255,255,0.4)" stroke-width="2" stroke-linecap="round"/>
|
||||
@@ -179,6 +180,20 @@
|
||||
</div>
|
||||
<span class="report-item__arrow">›</span>
|
||||
</div>
|
||||
<!-- [交互] 点击跳转至: report-cta.html(冠脉CTA报告) -->
|
||||
<div class="report-item" onclick="location.href='report-cta.html'">
|
||||
<div class="report-item__icon" style="background:#fff1f0;color:#cf1322;">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/><path d="M3.2 12h5.3l1.5-3 2.5 6 1.5-3h5.3"/></svg>
|
||||
</div>
|
||||
<div class="report-item__content">
|
||||
<div class="report-item__header">
|
||||
<span class="report-item__title">2025年度体检报告</span>
|
||||
<span class="report-tag report-tag--cta">冠脉CTA体检</span>
|
||||
</div>
|
||||
<div class="report-item__meta">CQ星龙园医院</div>
|
||||
</div>
|
||||
<span class="report-item__arrow">›</span>
|
||||
</div>
|
||||
<!-- [交互] 点击跳转至: report-query.html(常规体检) -->
|
||||
<div class="report-item" onclick="location.href='report-query.html'">
|
||||
<div class="report-item__icon" style="background:#e6f7ff;color:#096dd9;">
|
||||
|
||||
Reference in New Issue
Block a user