feat(mp): Veepoo M2 BLE 管线扩展 — 精准睡眠数据 + 自动测量 + UI 重构

- 新增 VeepooBridge API:精准睡眠读取(readPreciseSleepData)、B3自动测量配置
  (readAutoTestConfig/setAutoTestConfig)、开关设置(setAutoHeartRate/BP/Temp)、
  体温自动数据读取(readAutoTemperatureData),共 10 个新 API
- 新增 SDK 事件类型:SDK_EVENT_SLEEP(4)、SDK_EVENT_AUTO_TEST(54)
- VeepooPipeline 新增:readSleepData/readAllSleepData(enableAutoMeasurement
  睡眠数据 Promise 化读取 + 自动测量一键开启
- VeepooHistoryReader 新增:uploadSleepReadings 睡眠数据上传
- stores/veepoo.ts 实装:注册 onSleepData 回调、syncHistory 实际读取+上传、
  readSleepData 状态管理、enableAutoMeasurement、连接后自动触发三件事
- 原生页面(native/pkg-veepoo):_onReady 后自动读取 3 天睡眠 + 开启自动测量,
  新增 _readSleepData/_handleSleepEvent/_enableAutoMeasurement
- UI 重构:测量页药丸式选择器+SVG 圆环仪表盘+健康评估标签
- 数据上传页:2 列结果卡片网格+彩色条标识+睡眠数据卡片(★评分+总时长)
- 修复上传按钮无响应 bug:patientId 增加 URL fallback + 错误提示不再静默
- 设计原型:docs/design/veepoo-measure-prototype.html(4 状态预览)
This commit is contained in:
iven
2026-05-31 21:48:06 +08:00
parent 6d073840aa
commit 92ffd8cecb
14 changed files with 3419 additions and 603 deletions

View File

@@ -0,0 +1,879 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Veepoo M2 手环 — 测量页 & 上传页原型</title>
<style>
/* ═══════════════════════════════════════
Design Token — 复刻小程序 var(--tk-*)
═══════════════════════════════════════ */
:root {
--tk-pri: #C4623A;
--tk-pri-l: #F0DDD4;
--tk-pri-d: #8B3E1F;
--tk-pri-surface: #F5F0EB;
--tk-acc: #5B7A5E;
--tk-acc-l: #E8F0E8;
--tk-bg: #F5F0EB;
--tk-card: #FFFFFF;
--tk-tx: #2D2A26;
--tk-tx2: #5A554F;
--tk-tx3: #78716C;
--tk-bd: #E8E2DC;
--tk-dan: #B54A4A;
--tk-dan-l: #FDEAEA;
--tk-wrn: #C4873A;
--tk-wrn-l: #FFF3E0;
--tk-font-h2: 22px;
--tk-font-body-lg: 18px;
--tk-font-body: 16px;
--tk-font-body-sm: 14px;
--tk-font-num: 30px;
--tk-font-num-lg: 34px;
--tk-font-cap: 13px;
--tk-font-micro: 11px;
--tk-line-height: 1.5;
--tk-card-radius: 16px;
--tk-gap-sm: 12px;
--tk-gap-md: 16px;
--tk-gap-lg: 24px;
--tk-gap-xl: 32px;
--tk-page-padding: 20px;
--tk-shadow-sm: 0 1px 4px rgba(45,42,38,0.06);
--tk-shadow-md: 0 2px 12px rgba(45,42,38,0.10);
--tk-shadow-btn: 0 4px 16px rgba(196,98,58,0.3);
--tk-duration-fast: 150ms;
--tk-duration-normal: 200ms;
--tk-easing: cubic-bezier(0.16,1,0.3,1);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, 'PingFang SC', 'Helvetica Neue', sans-serif;
background: #E8E2DC;
display: flex;
gap: 40px;
justify-content: center;
align-items: flex-start;
padding: 40px;
flex-wrap: wrap;
}
/* ═══════════════════════════════════════
Phone Frame — 模拟小程序容器
═══════════════════════════════════════ */
.phone {
width: 375px;
height: 812px;
background: var(--tk-bg);
border-radius: 40px;
overflow: hidden;
position: relative;
box-shadow: 0 20px 60px rgba(0,0,0,0.15), 0 0 0 1px rgba(0,0,0,0.05);
flex-shrink: 0;
}
.phone-inner {
height: 100%;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.phone-label {
text-align: center;
font-size: 13px;
color: var(--tk-tx3);
margin-bottom: 12px;
font-weight: 500;
}
/* 状态栏 */
.status-bar {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-size: 14px;
font-weight: 600;
color: var(--tk-tx);
}
.status-bar-right {
display: flex;
gap: 4px;
align-items: center;
font-size: 12px;
}
/* ═══════════════════════════════════════
页面 1 — 测量页面(就绪态 + 测量中心率)
═══════════════════════════════════════ */
.measure-page {
background: var(--tk-bg);
min-height: 100%;
padding-bottom: 40px;
}
/* 设备状态栏 */
.device-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px var(--tk-page-padding);
background: var(--tk-card);
border-bottom: 1px solid var(--tk-bd);
}
.device-bar__left {
display: flex;
align-items: center;
gap: 8px;
}
.device-bar__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--tk-acc);
}
.device-bar__name {
font-size: var(--tk-font-body);
font-weight: 600;
color: var(--tk-tx);
}
.device-bar__battery {
font-size: var(--tk-font-cap);
color: var(--tk-tx3);
margin-left: 4px;
}
.device-bar__disconnect {
font-size: var(--tk-font-cap);
color: var(--tk-tx3);
padding: 6px 12px;
background: transparent;
border: 1px solid var(--tk-bd);
border-radius: 999px;
cursor: pointer;
}
/* 指标选择器 — 横向滚动药丸 */
.selector {
display: flex;
gap: 0;
padding: var(--tk-gap-md) var(--tk-page-padding);
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.selector::-webkit-scrollbar { display: none; }
.selector__pill {
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 10px 14px;
border-radius: 16px;
cursor: pointer;
transition: all var(--tk-duration-normal) var(--tk-easing);
position: relative;
min-width: 64px;
}
.selector__pill--active {
background: var(--tk-card);
box-shadow: var(--tk-shadow-md);
}
.selector__pill--done::after {
content: '✓';
position: absolute;
top: 4px;
right: 6px;
font-size: 10px;
color: #fff;
background: var(--tk-acc);
width: 16px;
height: 16px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.selector__icon {
width: 36px;
height: 36px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
color: #fff;
transition: transform var(--tk-duration-normal) var(--tk-easing);
}
.selector__pill--active .selector__icon {
transform: scale(1.15);
}
.selector__label {
font-size: var(--tk-font-cap);
color: var(--tk-tx3);
white-space: nowrap;
}
.selector__pill--active .selector__label {
color: var(--tk-tx);
font-weight: 600;
}
/* 仪表盘区域 */
.gauge-section {
display: flex;
flex-direction: column;
align-items: center;
padding: var(--tk-gap-md) 0 var(--tk-gap-lg);
}
.gauge {
position: relative;
width: 220px;
height: 220px;
}
.gauge__ring-bg {
fill: none;
stroke: var(--tk-bd);
stroke-width: 10;
}
.gauge__ring-progress {
fill: none;
stroke-width: 10;
stroke-linecap: round;
transition: stroke-dasharray 0.4s ease-out;
}
.gauge__center {
position: absolute;
inset: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.gauge__value {
font-family: Georgia, 'Times New Roman', serif;
font-size: 52px;
font-weight: 700;
color: var(--tk-tx);
line-height: 1;
}
.gauge__unit {
font-size: var(--tk-font-body-sm);
color: var(--tk-tx3);
margin-top: 4px;
}
/* 测量中脉冲动画 */
.gauge--measuring {
animation: gauge-breathe 2s ease-in-out infinite;
}
@keyframes gauge-breathe {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.03); }
}
/* 测量进度条 */
.progress-bar {
width: 240px;
height: 4px;
background: var(--tk-bd);
border-radius: 2px;
margin-top: var(--tk-gap-md);
overflow: hidden;
}
.progress-bar__fill {
height: 100%;
border-radius: 2px;
transition: width 0.3s ease-out;
}
/* 健康评估标签 */
.assessment {
margin-top: var(--tk-gap-md);
padding: 8px 20px;
border-radius: 999px;
font-size: var(--tk-font-body-sm);
font-weight: 500;
}
.assessment--normal {
background: var(--tk-acc-l);
color: var(--tk-acc);
}
.assessment--warning {
background: var(--tk-wrn-l);
color: var(--tk-wrn);
}
.assessment--danger {
background: var(--tk-dan-l);
color: var(--tk-dan);
}
/* 免责声明 */
.disclaimer {
text-align: center;
padding: 0 var(--tk-page-padding);
margin: var(--tk-gap-sm) 0 var(--tk-gap-lg);
}
.disclaimer__text {
font-size: var(--tk-font-micro);
color: var(--tk-tx3);
line-height: 1.5;
}
/* 操作按钮 */
.actions {
padding: 0 var(--tk-page-padding);
display: flex;
flex-direction: column;
gap: var(--tk-gap-sm);
}
.btn {
height: 52px;
border-radius: 16px;
border: none;
font-size: var(--tk-font-body-lg);
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
transition: opacity var(--tk-duration-fast);
}
.btn:active { opacity: 0.85; }
.btn--primary {
background: var(--tk-pri);
color: #fff;
box-shadow: var(--tk-shadow-btn);
}
.btn--secondary {
background: var(--tk-card);
color: var(--tk-tx);
border: 1px solid var(--tk-bd);
}
.btn--text {
background: transparent;
color: var(--tk-tx3);
height: 44px;
font-size: var(--tk-font-body-sm);
}
/* ═══════════════════════════════════════
页面 2 — 数据上传页面
═══════════════════════════════════════ */
.upload-page {
background: var(--tk-bg);
min-height: 100%;
padding-bottom: 40px;
}
/* 页面标题区 */
.page-header {
padding: var(--tk-gap-lg) var(--tk-page-padding) var(--tk-gap-md);
}
.page-header__title {
font-family: Georgia, 'Times New Roman', serif;
font-size: var(--tk-font-h2);
font-weight: 700;
color: var(--tk-tx);
line-height: 1.3;
}
.page-header__subtitle {
font-size: var(--tk-font-body-sm);
color: var(--tk-tx3);
margin-top: 4px;
}
/* 结果卡片网格 */
.results-grid {
padding: 0 var(--tk-page-padding);
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--tk-gap-sm);
}
.result-card {
background: var(--tk-card);
border-radius: var(--tk-card-radius);
padding: var(--tk-gap-md);
box-shadow: var(--tk-shadow-sm);
position: relative;
overflow: hidden;
}
.result-card--full {
grid-column: 1 / -1;
}
.result-card__badge {
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
border-radius: 0 4px 4px 0;
}
.result-card__label {
font-size: var(--tk-font-cap);
color: var(--tk-tx2);
margin-bottom: 8px;
padding-left: 8px;
}
.result-card__value-row {
display: flex;
align-items: baseline;
gap: 4px;
padding-left: 8px;
}
.result-card__value {
font-family: Georgia, 'Times New Roman', serif;
font-size: var(--tk-font-num-lg);
font-weight: 700;
color: var(--tk-tx);
line-height: 1;
}
.result-card__unit {
font-size: var(--tk-font-cap);
color: var(--tk-tx3);
}
.result-card__tag {
display: inline-flex;
align-items: center;
gap: 3px;
margin-top: 8px;
margin-left: 8px;
padding: 2px 8px;
border-radius: 999px;
font-size: var(--tk-font-micro);
font-weight: 500;
}
.result-card__tag--normal {
background: var(--tk-acc-l);
color: var(--tk-acc);
}
.result-card__tag--warning {
background: var(--tk-wrn-l);
color: var(--tk-wrn);
}
/* 未测量占位 */
.result-card--empty {
opacity: 0.5;
}
.result-card__placeholder {
padding-left: 8px;
font-size: var(--tk-font-body-sm);
color: var(--tk-tx3);
}
/* 底部上传播区 */
.upload-footer {
padding: var(--tk-gap-lg) var(--tk-page-padding) var(--tk-gap-xl);
}
.upload-footer__hint {
font-size: var(--tk-font-cap);
color: var(--tk-tx3);
text-align: center;
margin-bottom: var(--tk-gap-sm);
}
.upload-footer__time {
font-size: var(--tk-font-micro);
color: var(--tk-tx3);
text-align: center;
margin-top: var(--tk-gap-sm);
}
/* ═══════════════════════════════════════
长者模式覆盖
═══════════════════════════════════════ */
.elder-mode {
--tk-font-h2: 25px;
--tk-font-body-lg: 22px;
--tk-font-body: 22px;
--tk-font-body-sm: 19px;
--tk-font-num: 34px;
--tk-font-num-lg: 40px;
--tk-font-cap: 18px;
--tk-font-micro: 17px;
}
.elder-mode .selector {
flex-wrap: wrap;
gap: var(--tk-gap-sm);
}
.elder-mode .selector__pill {
min-width: 80px;
padding: 14px 18px;
}
.elder-mode .gauge {
width: 260px;
height: 260px;
}
.elder-mode .gauge__value {
font-size: 64px;
}
.elder-mode .results-grid {
grid-template-columns: 1fr;
}
.elder-mode .btn {
height: 60px;
}
/* ═══════════════════════════════════════
状态切换按钮(原型交互用)
═══════════════════════════════════════ */
.state-switcher {
display: flex;
gap: 8px;
padding: 12px var(--tk-page-padding);
background: var(--tk-card);
border-top: 1px solid var(--tk-bd);
position: sticky;
bottom: 0;
}
.state-btn {
flex: 1;
height: 36px;
border-radius: 8px;
border: 1px solid var(--tk-bd);
background: var(--tk-bg);
font-size: 12px;
color: var(--tk-tx2);
cursor: pointer;
}
.state-btn--active {
background: var(--tk-pri);
color: #fff;
border-color: var(--tk-pri);
}
</style>
</head>
<body>
<!-- ══════════════════════════════════════════════════════════════
页面 1 — 测量页面(就绪态,正在测量心率)
══════════════════════════════════════════════════════════════ -->
<div>
<div class="phone-label">页面 1 · 测量页(就绪态 — 心率测量中)</div>
<div class="phone">
<div class="phone-inner">
<!-- 状态栏 -->
<div class="status-bar">
<span>9:41</span>
<div class="status-bar-right">
<span>●●●●</span>
<span>WiFi</span>
<span>85%</span>
</div>
</div>
<div class="measure-page">
<!-- 设备状态栏 -->
<div class="device-bar">
<div class="device-bar__left">
<div class="device-bar__dot"></div>
<span class="device-bar__name">M2 手环</span>
<span class="device-bar__battery">85%</span>
</div>
<button class="device-bar__disconnect">断开</button>
</div>
<!-- 5 指标选择器 -->
<div class="selector">
<!-- 心率(选中 + 已完成) -->
<div class="selector__pill selector__pill--active selector__pill--done">
<div class="selector__icon" style="background: #EF4444;"></div>
<span class="selector__label">心率</span>
</div>
<!-- 血氧(已完成) -->
<div class="selector__pill selector__pill--done">
<div class="selector__icon" style="background: #3B82F6;">O₂</div>
<span class="selector__label">血氧</span>
</div>
<!-- 血压 -->
<div class="selector__pill">
<div class="selector__icon" style="background: #8B5CF6;"></div>
<span class="selector__label">血压</span>
</div>
<!-- 体温 -->
<div class="selector__pill">
<div class="selector__icon" style="background: #F59E0B;">T</div>
<span class="selector__label">体温</span>
</div>
<!-- 压力 -->
<div class="selector__pill">
<div class="selector__icon" style="background: #6366F1;">~</div>
<span class="selector__label">压力</span>
</div>
</div>
<!-- 仪表盘 -->
<div class="gauge-section">
<div class="gauge gauge--measuring">
<svg width="220" height="220" viewBox="0 0 220 220">
<circle cx="110" cy="110" r="100" class="gauge__ring-bg"/>
<circle cx="110" cy="110" r="100" class="gauge__ring-progress"
stroke="#EF4444"
stroke-dasharray="471"
stroke-dashoffset="141"
transform="rotate(-90 110 110)"/>
</svg>
<div class="gauge__center">
<span class="gauge__value" style="color: #EF4444;">72</span>
<span class="gauge__unit">bpm</span>
</div>
</div>
<!-- 进度条 -->
<div class="progress-bar">
<div class="progress-bar__fill" style="width: 70%; background: #EF4444;"></div>
</div>
<!-- 评估标签 -->
<div class="assessment assessment--normal">♥ 心率正常</div>
</div>
<!-- 免责声明 -->
<div class="disclaimer">
<p class="disclaimer__text">测量数据仅供参考,不作为医学诊断依据。如有不适请及时就医。</p>
</div>
<!-- 操作按钮 -->
<div class="actions">
<button class="btn btn--primary" style="background: #EF4444; box-shadow: 0 4px 16px rgba(239,68,68,0.3);">
停止测量
</button>
<button class="btn btn--secondary">
完成并查看结果
</button>
</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════
页面 2 — 数据上传页面(测量结果汇总)
══════════════════════════════════════════════════════════════ -->
<div>
<div class="phone-label">页面 2 · 数据上传页(结果汇总 + 上传)</div>
<div class="phone">
<div class="phone-inner">
<!-- 状态栏 -->
<div class="status-bar">
<span>9:41</span>
<div class="status-bar-right">
<span>●●●●</span>
<span>WiFi</span>
<span>85%</span>
</div>
</div>
<div class="upload-page">
<!-- 页面标题 -->
<div class="page-header">
<h1 class="page-header__title">测量结果</h1>
<p class="page-header__subtitle">Veepoo M2 · 刚刚完成测量</p>
</div>
<!-- 结果卡片网格 -->
<div class="results-grid">
<!-- 心率 — 已测量,正常 -->
<div class="result-card">
<div class="result-card__badge" style="background: #EF4444;"></div>
<div class="result-card__label">心率</div>
<div class="result-card__value-row">
<span class="result-card__value">72</span>
<span class="result-card__unit">bpm</span>
</div>
<div class="result-card__tag result-card__tag--normal">● 正常</div>
</div>
<!-- 血氧 — 已测量,正常 -->
<div class="result-card">
<div class="result-card__badge" style="background: #3B82F6;"></div>
<div class="result-card__label">血氧</div>
<div class="result-card__value-row">
<span class="result-card__value">98</span>
<span class="result-card__unit">%</span>
</div>
<div class="result-card__tag result-card__tag--normal">● 正常</div>
</div>
<!-- 血压 — 已测量,注意 -->
<div class="result-card result-card--full">
<div class="result-card__badge" style="background: #8B5CF6;"></div>
<div class="result-card__label">血压</div>
<div class="result-card__value-row">
<span class="result-card__value">135</span>
<span class="result-card__unit">/ 88 mmHg</span>
</div>
<div class="result-card__tag result-card__tag--warning">● 偏高</div>
</div>
<!-- 体温 — 未测量 -->
<div class="result-card result-card--empty">
<div class="result-card__badge" style="background: #F59E0B; opacity: 0.3;"></div>
<div class="result-card__label">体温</div>
<div class="result-card__placeholder">未测量</div>
</div>
<!-- 压力 — 未测量 -->
<div class="result-card result-card--empty">
<div class="result-card__badge" style="background: #6366F1; opacity: 0.3;"></div>
<div class="result-card__label">压力</div>
<div class="result-card__placeholder">未测量</div>
</div>
</div>
<!-- 底部上传播区 -->
<div class="upload-footer">
<p class="upload-footer__hint">测量数据将上传至您的健康档案</p>
<button class="btn btn--primary">
上传测量数据3 项)
</button>
<p class="upload-footer__time">测量时间2026-05-30 14:35</p>
</div>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════
页面 3 — 测量页面(未连接态)
══════════════════════════════════════════════════════════════ -->
<div>
<div class="phone-label">页面 1 · 测量页(未连接态)</div>
<div class="phone">
<div class="phone-inner">
<div class="status-bar">
<span>9:41</span>
<div class="status-bar-right">
<span>●●●●</span>
<span>WiFi</span>
<span>85%</span>
</div>
</div>
<div class="measure-page" style="display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 720px;">
<!-- 蓝牙脉冲动画 -->
<div style="position: relative; width: 120px; height: 120px; margin-bottom: 28px;">
<div style="position: absolute; inset: 0; border-radius: 50%; border: 3px solid var(--tk-pri); animation: pulse-ring 2s ease-out infinite;"></div>
<div style="position: absolute; inset: 20px; border-radius: 50%; background: var(--tk-pri); display: flex; align-items: center; justify-content: center;">
<span style="color: #fff; font-size: 20px; font-weight: 700;">BT</span>
</div>
</div>
<h2 style="font-family: Georgia, serif; font-size: var(--tk-font-h2); font-weight: 700; color: var(--tk-tx); margin-bottom: 8px;">
M2 手环健康测量
</h2>
<p style="font-size: var(--tk-font-body-sm); color: var(--tk-tx3); margin-bottom: 32px; text-align: center; padding: 0 40px;">
请确保手环已佩戴且蓝牙已开启
</p>
<button class="btn btn--primary" style="width: 200px;">
连接 M2 手环
</button>
</div>
</div>
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════
页面 4 — 测量页面(血压已测量完成态)
══════════════════════════════════════════════════════════════ -->
<div>
<div class="phone-label">页面 1 · 测量页(血压测量完成)</div>
<div class="phone">
<div class="phone-inner">
<div class="status-bar">
<span>9:42</span>
<div class="status-bar-right">
<span>●●●●</span>
<span>WiFi</span>
<span>85%</span>
</div>
</div>
<div class="measure-page">
<div class="device-bar">
<div class="device-bar__left">
<div class="device-bar__dot"></div>
<span class="device-bar__name">M2 手环</span>
<span class="device-bar__battery">85%</span>
</div>
<button class="device-bar__disconnect">断开</button>
</div>
<!-- 5 指标选择器 — 血压选中 -->
<div class="selector">
<div class="selector__pill selector__pill--done">
<div class="selector__icon" style="background: #EF4444;"></div>
<span class="selector__label">心率</span>
</div>
<div class="selector__pill selector__pill--done">
<div class="selector__icon" style="background: #3B82F6;">O₂</div>
<span class="selector__label">血氧</span>
</div>
<div class="selector__pill selector__pill--active selector__pill--done">
<div class="selector__icon" style="background: #8B5CF6;"></div>
<span class="selector__label">血压</span>
</div>
<div class="selector__pill">
<div class="selector__icon" style="background: #F59E0B;">T</div>
<span class="selector__label">体温</span>
</div>
<div class="selector__pill">
<div class="selector__icon" style="background: #6366F1;">~</div>
<span class="selector__label">压力</span>
</div>
</div>
<!-- 仪表盘 — 血压完成态 -->
<div class="gauge-section">
<div class="gauge">
<svg width="220" height="220" viewBox="0 0 220 220">
<circle cx="110" cy="110" r="100" class="gauge__ring-bg"/>
<circle cx="110" cy="110" r="100" class="gauge__ring-progress"
stroke="#8B5CF6"
stroke-dasharray="471"
stroke-dashoffset="0"
transform="rotate(-90 110 110)"/>
</svg>
<div class="gauge__center">
<span class="gauge__value" style="color: #8B5CF6;">135<span style="font-size: 24px; color: var(--tk-tx3);">/</span>88</span>
<span class="gauge__unit">mmHg</span>
</div>
</div>
<!-- 评估标签 — 偏高 -->
<div class="assessment assessment--warning">↕ 血压偏高,建议关注</div>
</div>
<div class="disclaimer">
<p class="disclaimer__text">测量数据仅供参考,不作为医学诊断依据。如有不适请及时就医。</p>
</div>
<div class="actions">
<button class="btn btn--primary" style="background: #8B5CF6; box-shadow: 0 4px 16px rgba(139,92,246,0.3);">
重新测量
</button>
<button class="btn btn--secondary">
完成并查看结果
</button>
</div>
</div>
</div>
</div>
</div>
<style>
@keyframes pulse-ring {
0% { transform: scale(1); opacity: 1; }
100% { transform: scale(1.4); opacity: 0; }
}
</style>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB