docs(mp): 新增小程序全页面 HTML 原型 + UI 优化指南

- 新增 12 个核心页面原型(登录/首页/咨询/预约/商城/健康等)
- 新增医生端分包原型(核心 + 临床两个分包)
- 新增 AI 客服对话页原型
- 新增 MP UI 优化指南文档
- 更新 wiki 基础设施和小程序文档
This commit is contained in:
iven
2026-05-17 00:51:07 +08:00
parent 710b2e2423
commit aa27c5174c
93 changed files with 15506 additions and 70 deletions

View File

@@ -0,0 +1,547 @@
# HMS 小程序 UI 优化实施指南
> 基于 `docs/design/mp-*.html` 高保真原型稿,指导全局性 UI 优化。
> 核心原则:**先建组件库,再逐页替换**,避免逐页手写导致风格不一致。
## 1. 原型稿索引
所有原型文件在 `docs/design/` 目录下,双击浏览器即可预览:
| 文件 | 涵盖页面 | 屏幕数 |
|------|---------|--------|
| `mp-00-visitor.html` | **访客端**轮播图×3 + 访客首页 + 访客"我的" | 5 |
| `mp-redesign-home.html` | 首页/健康/消息/我的4个TabBar主页面 | 4 |
| `mp-01-login.html` | 登录页(初始状态 + 填写中) | 2 |
| `mp-02-consultation.html` | 咨询列表 + 聊天详情 | 2 |
| `mp-03-appointment.html` | 预约列表 + 预约创建 + 预约详情 | 3 |
| `mp-04-article-report.html` | 文章列表 + 详情 + AI报告列表 + 详情 | 4 |
| `mp-05-mall.html` | 积分商城主页 | 1 |
| `mp-06-health-pkg.html` | 告警/日常监测/设备同步/体征录入/趋势 | 5 |
| `mp-07-profile-health.html` | 健康记录/诊断/用药/报告列表/报告详情 | 5 |
| `mp-08-profile-dialysis.html` | 透析记录列表+详情/随访列表+详情 | 4 |
| `mp-09-profile-other.html` | 家庭管理/添加/知情同意/事件/长者模式/设置 | 6 |
| `mp-10-mall-pkg.html` | 商品详情/兑换确认/订单列表/咨询详情 | 4 |
| `mp-11-doctor-core.html` | 医生工作台/待办/咨询/随访/患者 | 5 |
| `mp-12-doctor-clinical.html` | 告警列表+详情/透析列表+创建/处方列表+详情 | 6 |
**总计 14 个文件52 个屏幕,覆盖 58+ 页面(含访客端)。**
## 2. 设计 Token全局变量
从原型稿中提取的完整 Token 系统,所有页面必须严格遵循:
### 2.1 色彩体系
```scss
// === 患者端主色(暖陶土) ===
$color-primary: #C4623A;
$color-primary-light: #F0DDD4;
$color-primary-dark: #8B3E1F;
// === 医生端主色(靛蓝) ===
$color-doctor-primary: #3A6B8C;
$color-doctor-primary-light: #D4E5F0;
$color-doctor-primary-dark: #2A4F6A;
// === 中性色 ===
$color-bg: #F5F0EB; // 页面背景
$color-card: #FFFFFF; // 卡片背景
$color-surface: #EDE8E2; // 表面/次要背景
$color-border: #E8E2DC; // 边框
$color-border-light: #F0EBE5; // 浅边框
// === 文字色 ===
$color-text: #2D2A26; // 主文字
$color-text-secondary: #5A554F; // 次要文字
$color-text-tertiary: #78716C; // 辅助文字
// === 语义色 ===
$color-success: #5B7A5E; // 正常/成功
$color-success-light: #E8F0E8;
$color-warning: #C4873A; // 警告/偏高
$color-warning-light: #FFF3E0;
$color-danger: #B54A4A; // 危险/异常
$color-danger-light: #FDEAEA;
// === 功能色 ===
$color-wechat: #07C160; // 微信绿
```
### 2.2 字体系统
```scss
$font-display: "Georgia, 'Times New Roman', serif"; // 标题/数字
$font-body: "-apple-system, 'PingFang SC', sans-serif"; // 正文
// 字号规范11级
$font-size-xs: 10px; // 极小标注
$font-size-sm: 11px; // 标签/状态
$font-size-base-sm: 12px; // 辅助文字
$font-size-base: 13px; // 正文小
$font-size-body: 14px; // 正文
$font-size-md: 15px; // 小标题/按钮
$font-size-lg: 16px; // 卡片标题
$font-size-xl: 18px; // 区块标题
$font-size-2xl: 22px; // 页面子标题
$font-size-3xl: 26px; // 页面主标题
$font-size-4xl: 28px; // 大号数字(积分等)
$font-size-5xl: 30px; // 体征数值
```
### 2.3 圆角与间距
```scss
$radius-lg: 16px; // 卡片/大按钮
$radius-md: 12px; // 输入框/中等容器
$radius-sm: 8px; // 小元素/标签
$radius-full: 999px; // 胶囊标签/圆形
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 12px;
$spacing-lg: 16px;
$spacing-xl: 20px;
$spacing-2xl: 24px;
$page-padding: 20px; // 页面左右内边距
$card-padding: 16px; // 卡片内边距
$card-padding-lg: 20px; // 大卡片内边距
$section-gap: 16px; // 区块间距
$item-gap: 8px; // 列表项间距
```
### 2.4 阴影
```scss
$shadow-card: 0 2px 12px rgba(45,42,38,0.06); // 普通卡片
$shadow-card-sm: 0 1px 4px rgba(45,42,38,0.04); // 轻量卡片
$shadow-button: 0 4px 16px rgba(196,98,58,0.3); // 主按钮
$shadow-tab-active: 0 2px 8px rgba(196,98,58,0.25); // 选中Tab
```
## 3. 全局组件库(必须先建立)
> **铁律:以下组件必须先在 `src/components/ui/` 和 `src/components/patterns/` 中建好,
> 然后所有页面只引用组件,不允许在页面文件中硬编码样式。**
### 3.1 基础 UI 组件
#### `NavBar` — 子页面导航栏
```
高度: 44px
左侧: 返回箭头(‹ 字符或图标color: $color-primary
中央: 页面标题font: serif 18px boldcolor: $color-text
右侧: 可选操作按钮
底部: 1px solid $color-border-light
```
**原型参考**: 所有 mp-02~12 文件的导航栏
#### `PageHeader` — TabBar 页面标题
```
font: serif 26px/700
color: $color-text
margin-bottom: 20px
padding: 20px 20px 0
```
**原型参考**: mp-redesign-home.html 的"上午好,张三"/"健康数据"/"消息"/页面标题
#### `ContentCard` — 内容卡片容器
```
background: $color-card
border-radius: $radius-lg
padding: $card-padding-lg
box-shadow: $shadow-card
```
**原型参考**: 所有文件中的白色圆角卡片
#### `StatusTag` — 状态标签
```
fontSize: 11px
padding: 2px 8px
borderRadius: $radius-full
fontWeight: 500
变体:
- success: bg=$color-success-light, color=$color-success
- warning: bg=$color-warning-light, color=$color-warning
- danger: bg=$color-danger-light, color=$color-danger
- neutral: bg=$color-surface, color=$color-text-tertiary
- primary: bg=$color-primary-light, color=$color-primary
```
**原型参考**: 所有文件中的"正常"/"偏高"/"待就诊"/"已完成"等标签
#### `SectionTitle` — 区块标题
```
font: serif 18px/700
color: $color-text
margin-bottom: 12px
```
**原型参考**: mp-redesign-home.html 的"今日体征"/"近 7 天趋势"
#### `FormInput` — 表单输入框
```
height: 56px (血压等大号) 或 48px (普通)
background: $color-card
border: 1.5px solid $color-border
border-radius: $radius-lg
padding: 0 16px
font-size: 16px
focus 状态:
border-color: $color-primary
label:
font-size: 13px, color: $color-text-tertiary, margin-bottom: 6px
```
**原型参考**: mp-01-login.html 的手机号/验证码输入, mp-03-appointment.html 的表单
#### `PrimaryButton` — 主操作按钮
```
height: 54px (登录) 或 52px (普通)
border-radius: 14px
background: $color-primary
color: #fff
font-size: 18px (登录) 或 17px (普通)
font-weight: 600
box-shadow: $shadow-button
医生端变体:
background: $color-doctor-primary
```
**原型参考**: 所有文件的底部主按钮
#### `SecondaryButton` — 次操作按钮
```
同 PrimaryButton 尺寸
background: transparent
border: 2px solid $color-primary
color: $color-primary
```
**原型参考**: mp-redesign-home.html 的"预约挂号"按钮
### 3.2 复合组件
#### `TabFilter` — 筛选/切换标签
```
两种样式:
样式A (填充型 - 如体征类型切换):
- 选中: bg=$color-primary, color=#fff, box-shadow=$shadow-tab-active
- 未选: bg=$color-surface, color=$color-text-secondary
- 高度: 44px, borderRadius: $radius-md
样式B (pill型 - 如文章分类):
- 选中: bg=$color-primary, color=#fff
- 未选: bg=$color-surface, color=$color-text-secondary
- 高度: 32px, borderRadius: $radius-full, padding: 0 16px
样式C (段控型 - 如消息页咨询/通知):
- 外框: bg=$color-surface, borderRadius: $radius-sm, padding: 3px
- 选中: bg=$color-card, box-shadow
- 未选: transparent
- 高度: 40px
```
**原型参考**: mp-redesign-home.html HealthA 的体征Tab, MessagesA 的咨询/通知
#### `ListItem` — 列表项
```
background: $color-card
border-radius: $radius-lg
padding: 16px
box-shadow: $shadow-card-sm
margin-bottom: $item-gap
布局: 左侧头像/图标 + 中间内容(flex:1) + 右侧状态/箭头
分隔线(多个item在一张卡片内时):
border-bottom: 1px solid $color-border-light, 最后一项无
未读态: opacity 1
已读态: opacity 0.7
```
**原型参考**: mp-02-consultation.html, mp-07-profile-health.html 的列表项
#### `InfoRow` — 信息行(左标签右值)
```
display: flex, justify-content: space-between, align-items: center
padding: 12px 0
border-bottom: 1px solid $color-border-light (最后一项无)
标签: font-size: 14px, color: $color-text-secondary
值: font-size: 15px, color: $color-text
```
**原型参考**: mp-03-appointment.html 详情页, mp-12-doctor-clinical.html 处方详情
#### `ProgressRing` — 环形进度
```
尺寸: 64px (小号) / 80px (大号)
SVG: 两个 circle, 底层 $color-border, 上层 $color-primary
lineWidth: 4px
中心: 数字/文字, font: serif bold, color: $color-primary
```
**原型参考**: mp-redesign-home.html 首页"今日已记录 3/4"
#### `AlertCard` — 提醒/提示卡片
```
三种样式:
样式A (渐变型 - 智能提醒):
background: linear-gradient(135deg, $color-primary, $color-primary-dark)
color: #fff, borderRadius: $radius-lg
样式B (左边框型 - AI建议/提示):
background: $color-success-light
borderLeft: 4px solid $color-success
样式C (全边框型 - 温馨提示):
background: $color-warning-light
borderRadius: $radius-md
```
**原型参考**: mp-redesign-home.html 首页智能提醒, HealthA 的AI建议, mp-03-appointment.html 温馨提示
#### `ChatBubble` — 聊天气泡
```
医生/对方消息:
- background: $color-card
- border-radius: $radius-lg (左上 $radius-sm)
- 左对齐, maxWidth: 75%
我的消息:
- background: $color-primary-light
- border-radius: $radius-lg (右上 $radius-sm)
- 右对齐, maxWidth: 75%
```
**原型参考**: mp-02-consultation.html, mp-10-mall-pkg.html 咨询详情
#### `VitalCard` — 体征数据卡片2x2网格用
```
background: $color-card
border-radius: $radius-lg
padding: 14px 16px
布局:
- 标签名: 13px, $color-text-secondary
- 数值: serif 30px/700, $color-text
- 单位: 12px, $color-text-tertiary
- 状态标签: StatusTag
```
**原型参考**: mp-redesign-home.html 首页体征2x2网格
#### `GradientHeader` — 渐变头部卡片
```
background: linear-gradient(135deg, $color-primary 0%, $color-primary-dark 100%)
border-radius: $radius-lg
padding: 18px
color: #fff
```
**原型参考**: mp-05-mall.html 积分卡, mp-redesign-home.html 首页智能提醒
### 3.3 页面骨架组件
#### `PageShell` — 页面外壳(已存在,需更新样式)
```
使用 Token 变量更新现有 PageShell 的背景色、内边距等
```
#### `SubPageLayout` — 子页面布局
```
NavBar (固定顶部)
内容区 (scroll-view, padding: $page-padding)
可选底部操作栏 (fixed bottom)
```
## 4. 实施步骤(严格按顺序执行)
### Phase 0: 建立 SCSS 变量文件30分钟
1. 创建 `src/styles/_tokens.scss`,写入 §2 中的所有设计 Token
2. 创建 `src/styles/_mixins.scss`,封装常用样式组合:
```scss
@mixin card { background: $color-card; border-radius: $radius-lg; box-shadow: $shadow-card; }
@mixin page-padding { padding: $page-padding; }
@mixin nav-bar { height: 44px; display: flex; align-items: center; justify-content: center; border-bottom: 1px solid $color-border-light; }
```
3. 在 `app.scss` 中 import tokens 和 mixins
### Phase 1: 更新/创建全局组件2-3小时
按以下顺序逐一实现 §3 中的组件,**每个组件写完后立即替换 2-3 个引用页面验证效果**
1. `NavBar` → 替换所有子页面的导航栏
2. `StatusTag` → 替换所有状态标签
3. `ContentCard` → 替换所有卡片容器
4. `FormInput` → 替换所有表单输入
5. `PrimaryButton` / `SecondaryButton` → 替换所有按钮
6. `TabFilter` → 替换所有筛选标签
7. `ListItem` → 替换所有列表项
8. `InfoRow` → 替换所有信息行
9. `SectionTitle` / `PageHeader` → 替换所有标题
10. `ProgressRing` → 替换进度环
11. `AlertCard` → 替换提示卡片
12. `ChatBubble` → 替换聊天气泡
13. `VitalCard` → 替换体征卡片
14. `GradientHeader` → 替换渐变头部
### Phase 2: 逐页替换样式(每个页面 15-30 分钟)
按页面重要性排序,逐页将硬编码样式替换为组件引用:
**第一批 — 主 TabBar 页面(已有组件基础):**
1. `pages/index/index` → 参照 mp-redesign-home.html HomeA
2. `pages/health/index` → 参照 mp-redesign-home.html HealthA
3. `pages/messages/index` → 参照 mp-redesign-home.html MessagesA
4. `pages/profile/index` → 参照 mp-redesign-home.html ProfileA
**第二批 — 高频功能页面:**
5. `pages/login/index` → 参照 mp-01-login.html
6. `pages/consultation/index` → 参照 mp-02-consultation.html
7. `pages/appointment/index` → 参照 mp-03-appointment.html 列表
8. `pages/appointment/create/index` → 参照 mp-03-appointment.html 创建
9. `pages/appointment/detail/index` → 参照 mp-03-appointment.html 详情
**第三批 — 内容页面:**
10. `pages/article/index` + `detail` → 参照 mp-04-article-report.html
11. `pages/ai-report/list` + `detail` → 参照 mp-04-article-report.html
12. `pages/mall/index` → 参照 mp-05-mall.html
**第四批 — 健康分包:**
13-17. `pages/pkg-health/*` (5个) → 参照 mp-06-health-pkg.html
**第五批 — 个人中心分包:**
18-33. `pages/pkg-profile/*` (16个) → 参照 mp-07/08/09
**第六批 — 商城/咨询分包:**
34-37. `pages/pkg-mall/*` + `pages/pkg-consultation/detail` → 参照 mp-10-mall-pkg.html
**第七批 — 医生端:**
38-47. `pages/pkg-doctor-core/*` + `pages/pkg-doctor-clinical/*` → 参照 mp-11/12
### Phase 3: 全局验证1小时
1. **一致性检查**: 打开所有页面截图对比原型,确认风格统一
2. **长者模式**: 所有 58 个页面的关怀模式适配(字号 ≥ 22px
3. **暗色/亮色**: Token 通过 CSS 变量支持主题切换
4. **交叉页面导航**: 确保页面间跳转无样式断裂
## 5. 医生端 vs 患者端
医生端页面pkg-doctor-core / pkg-doctor-clinical使用不同的主色
```scss
// 在医生端页面入口设置 CSS 变量覆盖
--color-primary: #3A6B8C; // 替代 #C4623A
--color-primary-light: #D4E5F0; // 替代 #F0DDD4
--color-primary-dark: #2A4F6A; // 替代 #8B3E1F
```
这样所有引用 Token 的组件在医生端自动变色,**无需为医生端写单独的组件**。
## 6. 关键约束
1. **不允许在页面文件中硬编码颜色值** — 全部通过 Token 变量引用
2. **不允许跳过组件直接写样式** — 先建组件再引用
3. **每个组件必须支持 CSS 变量覆盖** — 医生端/关怀模式/主题切换都靠这个
4. **先更新 3-5 个页面验证组件可用** — 再批量替换剩余页面
5. **58 个页面中 66 个已迁移到统一组件库** — 在现有基础上更新 Token 和组件样式即可
## 7. 访客端Guest Mode
> **原型参考**: `mp-00-visitor.html`5 个屏幕)
访客端是用户未登录时看到的界面,核心目标是**引导转化登录**。与已登录页面有以下差异:
### 7.1 访客首页 vs 登录首页对比
| 维度 | 访客首页 | 登录首页 |
|------|---------|---------|
| 顶部 | 全屏 Swiper 轮播(品牌形象/智慧健康/温馨环境) | 智能提醒卡片 + 体征概览 |
| 内容 | 健康文章推荐(公开数据)+ 平台功能介绍卡片 | 今日体征网格 + 趋势图 + 快捷入口 |
| 底部 | 无快捷入口,有"登录享更多"CTA | 预约挂号/查看报告等快捷入口 |
| TabBar | 首页/健康(灰化)/消息(灰化)/我的 | 首页/健康/消息/我的(全部可用)|
### 7.2 访客专属组件
#### `BannerSwiper` — 轮播图组件
```
高度: 180px
borderRadius: $radius-lg
indicatorDots: 底部居中,活跃色 $color-primary
autoplay: true, interval: 4000ms
轮播项3个渐变背景 slides:
- 品牌形象: linear-gradient(135deg, #C4623A, #8B3E1F),大标题+副标题
- 智慧健康: linear-gradient(135deg, #3A6B8C, #2A4F6A),数据卡片展示
- 温馨就医: linear-gradient(135deg, #5B7A5E, #3D5A40),场景描述
数据来源: /api/v1/public/banners公开端点无需认证
```
**原型参考**: mp-00-visitor.html 前 3 个 Swiper slides
#### `FeatureCard` — 功能介绍卡片
```
background: $color-card
borderRadius: $radius-lg
padding: 20px
box-shadow: $shadow-card
textAlign: center
布局: 图标(40px圆形背景) + 标题(16px bold) + 描述(13px tertiary)
```
**原型参考**: mp-00-visitor.html 访客首页底部 3 个功能卡片
#### `LoginCTA` — 登录引导按钮
```
background: $color-primary
color: #fff
borderRadius: $radius-full
padding: 14px 32px
fontSize: 16px
fontWeight: 600
boxShadow: $shadow-button
textAlign: center
文字: "登录享更多健康服务"
点击: navigateTo login 页面
```
**原型参考**: mp-00-visitor.html 访客首页底部 + 访客"我的"页
### 7.3 访客"我的"页
访客态的个人中心与登录态完全不同:
```
头像区域:
- 未登录: 显示 "?" 圆形图标(bg: $color-surface, color: $color-text-tertiary)
- 登录后: 真实头像
登录提示卡:
- 标题: "登录后即可查看"
- 副标题: "健康数据、预约记录、咨询消息等"
- 按钮: "立即登录" (PrimaryButton)
菜单列表:
- 仅显示公开菜单(关于我们/隐私政策/使用条款)
- 隐藏所有需认证菜单(健康记录/家庭管理/设备绑定等)
```
**原型参考**: mp-00-visitor.html 最后一个屏幕
### 7.4 访客端实施要点
1. **`isGuest` 状态判断**: 在 `GuestHome` 页面中通过 `useAuth()` 检查登录态,未登录渲染访客布局
2. **轮播图数据**: 调用 `/api/v1/public/banners` 公开端点获取轮播图数据
3. **灰化 Tab**: 健康页/消息页在访客态显示"请先登录"提示 + 登录按钮
4. **登录转化**: 所有交互触发点(查看详情/预约/咨询)统一拦截跳转登录页
5. **组件复用**: BannerSwiper 组件同时用于访客首页和登录首页,通过 props 控制样式差异
6. **TabBar 页面路由**: 访客态和登录态共享同一路由,通过 `isGuest` 条件渲染不同内容
### 7.5 访客端实施优先级
排在 Phase 2 第一批(主 TabBar 页面)之后、第二批之前:
```
Phase 1.5 — 访客端:
1. 创建 BannerSwiper 组件 → src/components/ui/BannerSwiper/
2. 创建 FeatureCard 组件 → src/components/ui/FeatureCard/
3. 创建 LoginCTA 组件 → src/components/ui/LoginCTA/
4. 更新 GuestHome 页面 → 参照 mp-00-visitor.html 访客首页
5. 更新 Profile 页 isGuest 分支 → 参照 mp-00-visitor.html 访客"我的"
```

View File

@@ -0,0 +1,321 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 访客端</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 600px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 48px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 访客端</div>
<div class="note">访客端设计:未登录用户看到的是品牌展示+功能引导+登录转化。首页轮播+资讯+功能卡片,"我的"页面显示登录引导。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 393, height = 852, time = '9:41', battery = 85, darkStatus = false }) {
const sc = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: sc }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={sc}/><path d="M3 7.5a7 7 0 0110 0" stroke={sc} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={sc} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${sc}`, borderRadius: 3, padding: 1 }}><div style={{ width: `${battery}%`, height: '100%', background: sc, borderRadius: 1 }} /></div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 访客首页轮播1 — 品牌形象 ───
function GuestSlide1() {
return (
<div style={{ height: '100%', background: `linear-gradient(135deg, ${T.pri} 0%, ${T.priD} 60%, #5A3A2A 100%)`, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', padding: '0 24px 60px', position: 'relative' }}>
{/* 装饰圆 */}
<div style={{ position: 'absolute', top: 40, right: -20, width: 160, height: 160, borderRadius: 80, background: 'rgba(255,255,255,0.08)' }} />
<div style={{ position: 'absolute', top: 80, right: 20, width: 80, height: 80, borderRadius: 40, background: 'rgba(255,255,255,0.06)' }} />
<div style={{ position: 'absolute', bottom: 120, left: -30, width: 120, height: 120, borderRadius: 60, background: 'rgba(255,255,255,0.05)' }} />
{/* 内容 */}
<div style={{ position: 'relative', zIndex: 2 }}>
<div style={{ fontFamily: T.serif, fontSize: 32, fontWeight: 700, color: '#fff', marginBottom: 8, lineHeight: 1.2 }}>温润守护</div>
<div style={{ fontFamily: T.serif, fontSize: 32, fontWeight: 700, color: '#fff', marginBottom: 16, lineHeight: 1.2 }}>健康同行</div>
<div style={{ fontSize: 14, color: 'rgba(255,255,255,0.8)', lineHeight: 1.6 }}>专业的健康管理平台<br/>让每一位患者享受智能化的关怀服务</div>
</div>
{/* 指示点 */}
<div style={{ display: 'flex', gap: 6, marginTop: 20 }}>
<div style={{ width: 24, height: 4, borderRadius: 2, background: '#fff' }} />
<div style={{ width: 8, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.4)' }} />
<div style={{ width: 8, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.4)' }} />
</div>
</div>
);
}
// ─── 访客首页:完整页 ───
function GuestHome() {
return (
<div style={{ height: '100%', background: T.bg, overflowY: 'auto' }}>
{/* 轮播区域 */}
<div style={{ height: 280, position: 'relative' }}>
<GuestSlide1 />
</div>
{/* 健康资讯 */}
<div style={{ padding: '20px 20px 0' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>健康资讯</span>
<span style={{ fontSize: 13, color: T.tx3 }}>更多 </span>
</div>
{/* 带封面的文章 */}
{[
{ title: '高血压患者日常饮食指南', summary: '科学饮食,轻松控制血压水平', hasCover: true },
{ title: '血液透析的日常注意事项', summary: '透析患者必知的生活管理要点', hasCover: true },
].map((article, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', marginBottom: 10, boxShadow: '0 1px 4px rgba(45,42,38,0.04)', display: 'flex' }}>
<div style={{ width: 110, minHeight: 80, background: T.surface, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ fontSize: 11, color: T.tx3 }}>配图</span>
</div>
<div style={{ padding: '12px 14px', flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
<div style={{ fontSize: 15, fontWeight: 600, color: T.tx, marginBottom: 4, lineHeight: 1.4 }}>{article.title}</div>
<div style={{ fontSize: 13, color: T.tx2, lineHeight: 1.5 }}>{article.summary}</div>
</div>
</div>
))}
{/* 功能介绍卡片 — 3 个横排 */}
<div style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx, marginTop: 20, marginBottom: 12 }}>我们的服务</div>
<div style={{ display: 'flex', gap: 10 }}>
{[
{ icon: '健', title: '健康数据管理', desc: '记录体征', bg: T.accL, color: T.acc },
{ icon: '约', title: '智能预约排班', desc: '在线预约', bg: T.priL, color: T.pri },
{ icon: '智', title: 'AI 健康分析', desc: '趋势解读', bg: T.wrnL, color: T.wrn },
].map((item, i) => (
<div key={i} style={{ flex: 1, background: T.card, borderRadius: T.r, padding: 16, textAlign: 'center', boxShadow: '0 1px 4px rgba(45,42,38,0.04)' }}>
<div style={{ width: 40, height: 40, borderRadius: 20, background: item.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 8px' }}>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: item.color }}>{item.icon}</span>
</div>
<div style={{ fontSize: 13, fontWeight: 600, color: T.tx, marginBottom: 2 }}>{item.title}</div>
<div style={{ fontSize: 12, color: T.tx3 }}>{item.desc}</div>
</div>
))}
</div>
</div>
{/* 登录引导 */}
<div style={{ padding: '28px 20px 40px', textAlign: 'center' }}>
<div style={{ fontSize: 14, color: T.tx3, marginBottom: 16 }}>登录后即可使用完整健康管理服务</div>
<div style={{ height: 52, borderRadius: 14, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 17, fontWeight: 600, boxShadow: `0 4px 16px rgba(196,98,58,0.3)` }}>立即登录</div>
</div>
{/* TabBar — 无选中态 */}
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 80, background: '#fff', borderTop: `1px solid ${T.bdL}`, display: 'flex', alignItems: 'center', justifyContent: 'space-around', paddingBottom: 10 }}>
{['首页','健康','消息','我的'].map((t, i) => (
<div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2, color: i === 0 ? T.pri : T.tx3, fontSize: 10 }}>
<div style={{ width: 24, height: 24, borderRadius: 6, background: i === 0 ? T.pri : T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', color: i === 0 ? '#fff' : T.tx3, fontSize: 12 }} />
<span>{t}</span>
</div>
))}
</div>
</div>
);
}
// ─── 访客首页轮播2 — 智慧健康 ───
function GuestSlide2() {
return (
<div style={{ height: '100%', background: `linear-gradient(135deg, ${T.acc} 0%, #3A5A3E 60%, #2A3A2E 100%)`, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', padding: '0 24px 60px', position: 'relative' }}>
<div style={{ position: 'absolute', top: 50, right: 10, width: 140, height: 140, borderRadius: 70, background: 'rgba(255,255,255,0.08)' }} />
<div style={{ position: 'relative', zIndex: 2 }}>
<div style={{ fontFamily: T.serif, fontSize: 32, fontWeight: 700, color: '#fff', marginBottom: 16, lineHeight: 1.2 }}>智慧健康管理</div>
<div style={{ fontSize: 14, color: 'rgba(255,255,255,0.8)', lineHeight: 1.6 }}>AI 驱动个性化健康方案<br/>智能分析您的健康趋势</div>
</div>
<div style={{ display: 'flex', gap: 6, marginTop: 20 }}>
<div style={{ width: 8, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.4)' }} />
<div style={{ width: 24, height: 4, borderRadius: 2, background: '#fff' }} />
<div style={{ width: 8, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.4)' }} />
</div>
</div>
);
}
// ─── 访客首页轮播3 — 就医体验 ───
function GuestSlide3() {
return (
<div style={{ height: '100%', background: `linear-gradient(135deg, #6B8E9B 0%, #3A5A6A 60%, #2A3A4A 100%)`, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', padding: '0 24px 60px', position: 'relative' }}>
<div style={{ position: 'absolute', top: 60, left: 20, width: 100, height: 100, borderRadius: 50, background: 'rgba(255,255,255,0.06)' }} />
<div style={{ position: 'relative', zIndex: 2 }}>
<div style={{ fontFamily: T.serif, fontSize: 32, fontWeight: 700, color: '#fff', marginBottom: 16, lineHeight: 1.2 }}>温馨就医环境</div>
<div style={{ fontSize: 14, color: 'rgba(255,255,255,0.8)', lineHeight: 1.6 }}>舒适安全的治疗体验<br/>专业团队全程陪伴</div>
</div>
<div style={{ display: 'flex', gap: 6, marginTop: 20 }}>
<div style={{ width: 8, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.4)' }} />
<div style={{ width: 8, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.4)' }} />
<div style={{ width: 24, height: 4, borderRadius: 2, background: '#fff' }} />
</div>
</div>
);
}
// ─── 访客"我的"页面 ───
function GuestProfile() {
const menuGroups = [
{
title: '健康服务',
items: [
{ label: '健康资讯', icon: '文', bg: T.priL, color: T.pri },
{ label: '关于我们', icon: '关', bg: T.accL, color: T.acc },
],
},
{
title: '支持',
items: [
{ label: '帮助中心', icon: '帮', bg: T.surface, color: T.tx3 },
{ label: '意见反馈', icon: '反', bg: T.surface, color: T.tx3 },
{ label: '设置', icon: '齿', bg: T.surface, color: T.tx3 },
],
},
];
return (
<div style={{ height: '100%', background: T.bg, overflowY: 'auto' }}>
<div style={{ padding: '20px 20px 100px' }}>
{/* 未登录用户卡片 */}
<div style={{ background: T.card, borderRadius: T.r, padding: 20, boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16, display: 'flex', alignItems: 'center', gap: 16 }}>
<div style={{ width: 60, height: 60, borderRadius: 30, background: T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: T.tx3 }}>?</span>
</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 22, fontWeight: 700, color: T.tx, fontFamily: T.serif, marginBottom: 2 }}>未登录</div>
<div style={{ fontSize: 14, color: T.tx3 }}>点击登录开启健康管理之旅</div>
</div>
<span style={{ color: T.tx3, fontSize: 16 }}></span>
</div>
{/* 登录引导卡 */}
<div style={{ background: `linear-gradient(135deg, ${T.priL} 0%, #E8C8B8 100%)`, borderRadius: T.r, padding: 20, marginBottom: 24, display: 'flex', alignItems: 'center', gap: 16 }}>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx, marginBottom: 4 }}>登录享受完整服务</div>
<div style={{ fontSize: 13, color: T.tx2, lineHeight: 1.5 }}>体征记录 · 智能分析 · 在线咨询 · 预约挂号</div>
</div>
<div style={{ height: 44, padding: '0 20px', borderRadius: T.rSm, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 15, fontWeight: 600, flexShrink: 0 }}>登录</div>
</div>
{/* 分组菜单 */}
{menuGroups.map((group, gi) => (
<div key={gi} style={{ marginBottom: 14 }}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx2, marginBottom: 8, paddingLeft: 4 }}>{group.title}</div>
<div style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', boxShadow: '0 1px 4px rgba(45,42,38,0.04)' }}>
{group.items.map((item, ii) => (
<div key={ii} style={{
display: 'flex', alignItems: 'center', gap: 14, padding: '14px 16px',
borderBottom: ii < group.items.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<div style={{ width: 36, height: 36, borderRadius: T.rSm, background: item.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: item.color }}>{item.icon}</span>
</div>
<span style={{ flex: 1, fontSize: 15, color: T.tx }}>{item.label}</span>
<span style={{ color: T.tx3, fontSize: 14 }}></span>
</div>
))}
</div>
</div>
))}
</div>
{/* TabBar */}
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 80, background: '#fff', borderTop: `1px solid ${T.bdL}`, display: 'flex', alignItems: 'center', justifyContent: 'space-around', paddingBottom: 10 }}>
{['首页','健康','消息','我的'].map((t, i) => (
<div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2, color: i === 3 ? T.pri : T.tx3, fontSize: 10 }}>
<div style={{ width: 24, height: 24, borderRadius: 6, background: i === 3 ? T.pri : T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', color: i === 3 ? '#fff' : T.tx3, fontSize: 12 }} />
<span>{t}</span>
</div>
))}
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">访客首页 轮播 1</span>
<IosFrame time="9:41" battery={85} darkStatus={true}>
<GuestSlide1 />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">访客首页 完整页</span>
<IosFrame time="9:41" battery={85}>
<GuestHome />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">访客首页 轮播 2</span>
<IosFrame time="9:41" battery={85} darkStatus={true}>
<GuestSlide2 />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">访客首页 轮播 3</span>
<IosFrame time="9:41" battery={85} darkStatus={true}>
<GuestSlide3 />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">访客"我的"页面</span>
<IosFrame time="9:41" battery={85}>
<GuestProfile />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,217 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 登录页</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 600px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 48px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 登录页</div>
<div class="note">温润东方风设计系统 — 登录是用户体验的起点,简洁、温暖、无压力。手机号+验证码+微信一键登录三种方式。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 393, height = 852, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 登录页:初始状态 ───
function LoginInitial() {
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column', padding: '80px 28px 40px' }}>
{/* Logo 区域 */}
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: 56 }}>
<div style={{ width: 80, height: 80, borderRadius: 40, background: `linear-gradient(135deg, ${T.priL} 0%, ${T.pri} 100%)`, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 20, boxShadow: `0 4px 16px rgba(196,98,58,0.25)` }}>
<span style={{ fontFamily: T.serif, fontSize: 36, fontWeight: 700, color: '#fff' }}>H</span>
</div>
<div style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: T.tx, marginBottom: 8 }}>HMS 健康</div>
<div style={{ fontSize: 14, color: T.tx3 }}>您的专属健康管家</div>
</div>
{/* 手机号输入 */}
<div style={{ marginBottom: 12 }}>
<div style={{ height: 56, background: T.card, border: `1.5px solid ${T.bd}`, borderRadius: T.r, display: 'flex', alignItems: 'center', padding: '0 16px' }}>
<span style={{ fontSize: 16, color: T.tx, fontWeight: 500, marginRight: 12, minWidth: 36 }}>+86</span>
<div style={{ width: 1, height: 24, background: T.bd, marginRight: 12 }} />
<span style={{ fontSize: 16, color: T.tx3 }}>请输入手机号</span>
</div>
</div>
{/* 验证码输入 */}
<div style={{ marginBottom: 24 }}>
<div style={{ height: 56, background: T.card, border: `1.5px solid ${T.bd}`, borderRadius: T.r, display: 'flex', alignItems: 'center', padding: '0 16px', justifyContent: 'space-between' }}>
<span style={{ fontSize: 16, color: T.tx3 }}>请输入验证码</span>
<span style={{ fontSize: 14, color: T.pri, fontWeight: 600, padding: '6px 0' }}>获取验证码</span>
</div>
</div>
{/* 登录按钮 */}
<div style={{ height: 54, borderRadius: 16, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 18, fontWeight: 600, boxShadow: `0 4px 16px rgba(196,98,58,0.3)`, marginBottom: 16 }}>登录</div>
{/* 分隔线 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 16 }}>
<div style={{ flex: 1, height: 1, background: T.bdL }} />
<span style={{ fontSize: 12, color: T.tx3 }}></span>
<div style={{ flex: 1, height: 1, background: T.bdL }} />
</div>
{/* 微信一键登录 */}
<div style={{ height: 54, borderRadius: 16, background: '#07C160', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, color: '#fff', fontSize: 18, fontWeight: 600, marginBottom: 24 }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="#fff"><path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098 10.16 10.16 0 002.837.403c.276 0 .543-.027.811-.05a6.42 6.42 0 01-.246-1.79c0-3.558 3.39-6.451 7.585-6.451.258 0 .507.022.76.042C16.706 4.882 13.075 2.188 8.691 2.188zm-2.85 4.56a1.1 1.1 0 110 2.2 1.1 1.1 0 010-2.2zm5.7 0a1.1 1.1 0 110 2.2 1.1 1.1 0 010-2.2zm4.3 4.378c-3.652 0-6.615 2.472-6.615 5.517s2.963 5.517 6.615 5.517a7.8 7.8 0 002.222-.323.626.626 0 01.52.072l1.38.809a.236.236 0 00.121.039.213.213 0 00.21-.214c0-.052-.02-.103-.035-.153l-.283-1.073a.427.427 0 01.155-.483C21.855 19.882 22.84 18.2 22.84 16.643c0-3.045-2.963-5.517-6.615-5.517h.006zm-2.41 3.2a.895.895 0 110 1.79.895.895 0 010-1.79zm4.82 0a.895.895 0 110 1.79.895.895 0 010-1.79z"/></svg>
微信一键登录
</div>
{/* 用户协议 */}
<div style={{ fontSize: 12, color: T.tx3, textAlign: 'center', lineHeight: 1.8 }}>
登录即同意 <span style={{ color: T.pri }}>用户协议</span> <span style={{ color: T.pri }}></span>
</div>
{/* 弹性空间 */}
<div style={{ flex: 1 }} />
{/* 开发模式 */}
<div style={{ textAlign: 'center', padding: '12px', border: `1px dashed ${T.bd}`, borderRadius: T.rSm }}>
<span style={{ fontSize: 13, color: T.tx3 }}>开发模式快速登录 </span>
</div>
</div>
);
}
// ─── 登录页:填写中状态 ───
function LoginFilled() {
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column', padding: '80px 28px 40px' }}>
{/* Logo 区域 */}
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: 56 }}>
<div style={{ width: 80, height: 80, borderRadius: 40, background: `linear-gradient(135deg, ${T.priL} 0%, ${T.pri} 100%)`, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 20, boxShadow: `0 4px 16px rgba(196,98,58,0.25)` }}>
<span style={{ fontFamily: T.serif, fontSize: 36, fontWeight: 700, color: '#fff' }}>H</span>
</div>
<div style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: T.tx, marginBottom: 8 }}>HMS 健康</div>
<div style={{ fontSize: 14, color: T.tx3 }}>您的专属健康管家</div>
</div>
{/* 手机号 — 已填写 */}
<div style={{ marginBottom: 12 }}>
<div style={{ height: 56, background: T.card, border: `1.5px solid ${T.pri}`, borderRadius: T.r, display: 'flex', alignItems: 'center', padding: '0 16px' }}>
<span style={{ fontSize: 16, color: T.tx, fontWeight: 500, marginRight: 12, minWidth: 36 }}>+86</span>
<div style={{ width: 1, height: 24, background: T.bd, marginRight: 12 }} />
<span style={{ fontSize: 16, color: T.tx, letterSpacing: 2 }}>138 1234 5678</span>
</div>
</div>
{/* 验证码 — 已填写 */}
<div style={{ marginBottom: 24 }}>
<div style={{ height: 56, background: T.card, border: `1.5px solid ${T.pri}`, borderRadius: T.r, display: 'flex', alignItems: 'center', padding: '0 16px', justifyContent: 'space-between' }}>
<span style={{ fontSize: 16, color: T.tx, letterSpacing: 6 }}>6285</span>
<span style={{ fontSize: 14, color: T.tx3 }}>58s 后重发</span>
</div>
</div>
{/* 登录按钮 */}
<div style={{ height: 54, borderRadius: 16, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 18, fontWeight: 600, boxShadow: `0 4px 16px rgba(196,98,58,0.3)`, marginBottom: 16 }}>登录</div>
{/* 分隔线 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 16 }}>
<div style={{ flex: 1, height: 1, background: T.bdL }} />
<span style={{ fontSize: 12, color: T.tx3 }}></span>
<div style={{ flex: 1, height: 1, background: T.bdL }} />
</div>
{/* 微信一键登录 */}
<div style={{ height: 54, borderRadius: 16, background: '#07C160', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, color: '#fff', fontSize: 18, fontWeight: 600, marginBottom: 24 }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="#fff"><path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098 10.16 10.16 0 002.837.403c.276 0 .543-.027.811-.05a6.42 6.42 0 01-.246-1.79c0-3.558 3.39-6.451 7.585-6.451.258 0 .507.022.76.042C16.706 4.882 13.075 2.188 8.691 2.188zm-2.85 4.56a1.1 1.1 0 110 2.2 1.1 1.1 0 010-2.2zm5.7 0a1.1 1.1 0 110 2.2 1.1 1.1 0 010-2.2zm4.3 4.378c-3.652 0-6.615 2.472-6.615 5.517s2.963 5.517 6.615 5.517a7.8 7.8 0 002.222-.323.626.626 0 01.52.072l1.38.809a.236.236 0 00.121.039.213.213 0 00.21-.214c0-.052-.02-.103-.035-.153l-.283-1.073a.427.427 0 01.155-.483C21.855 19.882 22.84 18.2 22.84 16.643c0-3.045-2.963-5.517-6.615-5.517h.006zm-2.41 3.2a.895.895 0 110 1.79.895.895 0 010-1.79zm4.82 0a.895.895 0 110 1.79.895.895 0 010-1.79z"/></svg>
微信一键登录
</div>
{/* 用户协议 */}
<div style={{ fontSize: 12, color: T.tx3, textAlign: 'center', lineHeight: 1.8 }}>
登录即同意 <span style={{ color: T.pri }}>用户协议</span> <span style={{ color: T.pri }}></span>
</div>
<div style={{ flex: 1 }} />
<div style={{ textAlign: 'center', padding: '12px', border: `1px dashed ${T.bd}`, borderRadius: T.rSm }}>
<span style={{ fontSize: 13, color: T.tx3 }}>开发模式快速登录 </span>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">登录 初始状态</span>
<IosFrame time="9:41" battery={85}>
<LoginInitial />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">登录 填写中</span>
<IosFrame time="9:41" battery={84}>
<LoginFilled />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,329 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 在线咨询</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 600px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 48px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 在线咨询</div>
<div class="note">温润东方风设计系统 — 咨询列表页 + 咨询详情(聊天)页。左侧为咨询列表,右侧为与王医生的聊天详情。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 393, height = 852, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 咨询列表页 ───
function ConsultationList() {
const doctors = [
{ name: '王医生', dept: '心内科', avatar: '王', avatarBg: '#C4623A', lastMsg: '您的检查报告已出,建议...', time: '10分钟前', unread: 2, opacity: 1 },
{ name: '李医生', dept: '肾内科', avatar: '李', avatarBg: '#5B7A5E', lastMsg: '复查结果整体平稳', time: '昨天', unread: 0, opacity: 0.7 },
{ name: '张医生', dept: '全科', avatar: '张', avatarBg: '#C4873A', lastMsg: '门诊随访已完成', time: '3天前', unread: 0, opacity: 0.7 },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
{/* 导航栏 */}
<div style={{ padding: '16px 20px 12px', background: T.card, borderBottom: `1px solid ${T.bdL}` }}>
<div style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx, textAlign: 'center' }}>在线咨询</div>
</div>
{/* 搜索栏 */}
<div style={{ padding: '12px 20px 4px' }}>
<div style={{ height: 44, background: T.surface, borderRadius: T.r, display: 'flex', alignItems: 'center', padding: '0 14px', gap: 8 }}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
<span style={{ fontSize: 14, color: T.tx3 }}>搜索医生或科室</span>
</div>
</div>
{/* 咨询列表 */}
<div style={{ flex: 1, padding: '8px 20px 20px', display: 'flex', flexDirection: 'column', gap: 8 }}>
{doctors.map((doc, i) => (
<div key={i} style={{
background: T.card,
borderRadius: T.r,
padding: 16,
opacity: doc.opacity,
boxShadow: '0 1px 4px rgba(0,0,0,0.04)',
display: 'flex',
alignItems: 'center',
gap: 14,
position: 'relative',
}}>
{/* 头像 */}
<div style={{
width: 48, height: 48, borderRadius: 24,
background: doc.avatarBg,
display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
}}>
<span style={{ color: '#fff', fontSize: 20, fontWeight: 600, fontFamily: T.sans }}>{doc.avatar}</span>
</div>
{/* 信息 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 4 }}>
<span style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>{doc.name}<span style={{ color: T.tx3, fontWeight: 400, fontSize: 13, marginLeft: 6 }}>· {doc.dept}</span></span>
<span style={{ fontSize: 12, color: T.tx3 }}>{doc.time}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<span style={{ fontSize: 14, color: T.tx2, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 200 }}>{doc.lastMsg}</span>
{doc.unread > 0 && (
<div style={{
minWidth: 20, height: 20, borderRadius: 10,
background: T.dan, display: 'flex', alignItems: 'center', justifyContent: 'center',
padding: '0 6px', flexShrink: 0,
}}>
<span style={{ color: '#fff', fontSize: 12, fontWeight: 600 }}>{doc.unread}</span>
</div>
)}
</div>
</div>
</div>
))}
{/* 底部提示 */}
<div style={{ textAlign: 'center', padding: '20px 0 8px' }}>
<span style={{ fontSize: 12, color: T.tx3 }}> 3 位咨询医生</span>
</div>
</div>
</div>
);
}
// ─── 咨询详情(聊天页) ───
function ChatDetail() {
const messages = [
{ from: 'doctor', text: '张先生您好,您的血常规报告已出。' },
{ from: 'me', text: '好的,有什么需要注意的吗?' },
{ from: 'doctor', text: '血红蛋白略有下降,建议补充铁剂,下月复查。' },
{ from: 'doctor', text: '我帮您开个处方,注意按时服用。' },
{ from: 'me', text: '谢谢医生!' },
];
const timeMarkers = ['今天 09:32', null, null, '09:45', null];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
{/* 导航栏 */}
<div style={{
padding: '16px 20px 12px',
background: T.card,
borderBottom: `1px solid ${T.bdL}`,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}>
{/* 返回箭头 */}
<div style={{ width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={T.tx} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
</div>
{/* 标题 */}
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx }}>王医生·心内科</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 4, marginTop: 2 }}>
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.acc }} />
<span style={{ fontSize: 11, color: T.acc }}>在线</span>
</div>
</div>
{/* 更多 */}
<div style={{ width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round"><circle cx="12" cy="5" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="12" cy="19" r="1"/></svg>
</div>
</div>
{/* 聊天区域 */}
<div style={{ flex: 1, padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 4, overflow: 'auto' }}>
{/* 日期标记 */}
<div style={{ textAlign: 'center', margin: '4px 0 12px' }}>
<span style={{ fontSize: 11, color: T.tx3, background: T.surface, padding: '3px 12px', borderRadius: 10 }}>今天 09:30</span>
</div>
{messages.map((msg, i) => (
<React.Fragment key={i}>
{/* 时间标记 */}
{timeMarkers[i] && i > 0 && (
<div style={{ textAlign: 'center', margin: '8px 0' }}>
<span style={{ fontSize: 11, color: T.tx3, background: T.surface, padding: '3px 12px', borderRadius: 10 }}>{timeMarkers[i]}</span>
</div>
)}
{msg.from === 'doctor' ? (
/* 医生消息 — 左对齐 */
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginBottom: 4 }}>
<div style={{
width: 36, height: 36, borderRadius: 18,
background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
}}>
<span style={{ color: '#fff', fontSize: 15, fontWeight: 600 }}></span>
</div>
<div style={{
background: T.card,
borderRadius: '4px 16px 16px 16px',
padding: '10px 14px',
maxWidth: '72%',
boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
}}>
<span style={{ fontSize: 15, color: T.tx, lineHeight: 1.6 }}>{msg.text}</span>
</div>
</div>
) : (
/* 我的消息 — 右对齐 */
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'flex-end', gap: 10, marginBottom: 4 }}>
<div style={{
background: T.priL,
borderRadius: '16px 4px 16px 16px',
padding: '10px 14px',
maxWidth: '72%',
}}>
<span style={{ fontSize: 15, color: T.tx, lineHeight: 1.6 }}>{msg.text}</span>
</div>
</div>
)}
</React.Fragment>
))}
{/* 正在输入提示 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 4 }}>
<div style={{
width: 36, height: 36, borderRadius: 18,
background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
}}>
<span style={{ color: '#fff', fontSize: 15, fontWeight: 600 }}></span>
</div>
<div style={{
background: T.card, borderRadius: '4px 16px 16px 16px',
padding: '10px 16px', display: 'flex', gap: 4, alignItems: 'center',
}}>
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.tx3, animation: 'pulse 1.4s infinite' }} />
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.tx3, animation: 'pulse 1.4s infinite 0.2s' }} />
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.tx3, animation: 'pulse 1.4s infinite 0.4s' }} />
</div>
</div>
</div>
{/* 底部输入栏 */}
<div style={{
background: T.card,
borderTop: `1px solid ${T.bdL}`,
padding: '10px 16px',
display: 'flex',
alignItems: 'center',
gap: 10,
}}>
{/* 附加按钮 */}
<div style={{ width: 36, height: 36, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v8M8 12h8"/></svg>
</div>
{/* 输入框 */}
<div style={{
flex: 1, height: 40, background: T.surface, borderRadius: 20,
display: 'flex', alignItems: 'center', padding: '0 14px',
}}>
<span style={{ fontSize: 14, color: T.tx3 }}>输入消息...</span>
</div>
{/* 发送按钮 */}
<div style={{
width: 40, height: 40, borderRadius: 20,
background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
}}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M22 2L11 13"/><path d="M22 2L15 22L11 13L2 9L22 2Z"/></svg>
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">咨询列表</span>
<IosFrame time="9:41" battery={85}>
<ConsultationList />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">咨询详情 聊天</span>
<IosFrame time="9:45" battery={84}>
<ChatDetail />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
<style>
@keyframes pulse {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
</style>
</body>
</html>

View File

@@ -0,0 +1,398 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — AI 客服咨询</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 700px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 48px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
@keyframes pulse { 0%,80%,100% { opacity: 0.3; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · AI 客服咨询</div>
<div class="note">
温润东方风设计系统 — 消息 Tab 改为 AI 客服单窗口(无列表),通知迁移至「我的」页面。<br/>
左:欢迎状态(首次进入)· 中:对话进行中 · 右:个人中心通知入口
</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const F = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
status: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
island: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
body: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
home: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function Phone({ children, w = 393, h = 852, time = '9:41', battery = 85, dark = false }) {
const c = dark ? '#fff' : '#000';
return (
<div style={F.wrapper}>
<div style={{ ...F.screen, width: w, height: h }}>
<div style={{ ...F.status, color: c }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={c}/><path d="M3 7.5a7 7 0 0110 0" stroke={c} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={c} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${c}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: c, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={F.island} />
<div style={F.body}>{children}</div>
<div style={F.home} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
dan: '#B54A4A', danL: '#FDEAEA',
white: '#FFFFFF',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 占位:三屏容器 ───
function App() {
return (
<div className="screens">
{/* 左屏:欢迎状态 */}
<div className="screen-wrap">
<Phone><WelcomeChat /></Phone>
<div className="screen-label">首次进入 · 欢迎状态</div>
</div>
{/* 中屏:对话进行中 */}
<div className="screen-wrap">
<Phone><ActiveChat /></Phone>
<div className="screen-label">对话进行中</div>
</div>
{/* 右屏:个人中心通知入口 */}
<div className="screen-wrap">
<Phone><ProfileWithNotify /></Phone>
<div className="screen-label">个人中心 · 通知入口</div>
</div>
</div>
);
}
// ─── 共享:聊天导航栏 ───
function ChatNav() {
return (
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '16px 20px 12px', background: T.card, borderBottom: `1px solid ${T.bdL}`, flexShrink: 0 }}>
{/* 返回 */}
<div style={{ width: 32, height: 32, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ fontSize: 24, fontWeight: 300, color: T.tx }}></span>
</div>
{/* 标题 + 在线状态 */}
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx }}>健康助手 · 小华</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 4, marginTop: 2 }}>
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.acc }} />
<span style={{ fontSize: 11, color: T.acc }}>24小时在线</span>
</div>
</div>
{/* 占位 */}
<div style={{ width: 32 }} />
</div>
);
}
// ─── 共享:底部输入栏 ───
function ChatBar() {
return (
<div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 16px', paddingBottom: 24, background: T.card, borderTop: `1px solid ${T.bdL}`, flexShrink: 0 }}>
<div style={{ width: 36, height: 36, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ fontSize: 22, color: T.tx3, fontWeight: 300 }}>+</span>
</div>
<div style={{ flex: 1, height: 40, background: T.surface, borderRadius: 20, padding: '0 14px', display: 'flex', alignItems: 'center' }}>
<span style={{ color: T.tx3, fontSize: 14 }}>输入您的问题...</span>
</div>
<div style={{ width: 40, height: 40, borderRadius: 20, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', opacity: 0.5 }}>
<span style={{ color: T.white, fontSize: 20, fontWeight: 700 }}></span>
</div>
</div>
);
}
// ─── 共享AI 头像 ───
function AiAvatar({ size = 36 }) {
return (
<div style={{ width: size, height: size, borderRadius: size / 2, background: `linear-gradient(135deg, ${T.pri}, ${T.priD})`, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ color: T.white, fontSize: size * 0.42, fontWeight: 600 }}></span>
</div>
);
}
// ─── 左屏:欢迎状态 ───
function WelcomeChat() {
const quickActions = [
{ icon: '📋', label: '查看报告' },
{ icon: '💊', label: '用药咨询' },
{ icon: '📅', label: '预约挂号' },
{ icon: '🔔', label: '健康提醒' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<ChatNav />
<div style={{ flex: 1, padding: '24px 20px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 0 }}>
{/* AI 大头像 */}
<div style={{ width: 72, height: 72, borderRadius: 36, background: `linear-gradient(135deg, ${T.pri}, ${T.priD})`, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `0 8px 24px rgba(196, 98, 58, 0.25)` }}>
<span style={{ color: T.white, fontSize: 32, fontWeight: 600, fontFamily: T.serif }}></span>
</div>
{/* 问候语 */}
<div style={{ marginTop: 16, textAlign: 'center' }}>
<div style={{ fontSize: 17, fontWeight: 600, color: T.tx }}>您好我是小华</div>
<div style={{ fontSize: 13, color: T.tx3, marginTop: 6, lineHeight: 1.6 }}>您的专属健康助手随时为您解答<br/>健康问题预约服务报告解读等</div>
</div>
{/* 分割线 */}
<div style={{ width: 32, height: 1, background: T.bd, margin: '20px 0 16px' }} />
{/* 快捷问题 */}
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 12 }}>您可能想问</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, justifyContent: 'center', maxWidth: 320 }}>
{quickActions.map((a, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '8px 14px', background: T.card, borderRadius: T.r, border: `1px solid ${T.bdL}`, fontSize: 13, color: T.tx2, cursor: 'pointer' }}>
<span style={{ fontSize: 15 }}>{a.icon}</span>
<span>{a.label}</span>
</div>
))}
</div>
</div>
<ChatBar />
</div>
);
}
// ─── 占位组件(后续步骤填充)───
// ─── 中屏:对话进行中 ───
function ActiveChat() {
const messages = [
{ from: 'ai', text: '您好!我是健康助手小华,请问有什么可以帮助您的?' },
{ from: 'user', text: '我最近体检报告出来了,想了解一下指标情况' },
{ from: 'ai', text: '好的,我来帮您解读最近的体检报告。请稍等,正在为您查询…', card: true },
{ from: 'user', text: '好的' },
{ from: 'ai', text: '已为您找到最近的体检报告2026-05-10。整体来看各项指标基本正常有几个需要关注的点\n\n1. 空腹血糖略偏高6.2 mmol/L建议关注饮食\n2. 维生素D偏低可适当补充\n3. 其余指标均在正常范围内\n\n如需详细解读某项指标请告诉我。' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<ChatNav />
<div style={{ flex: 1, padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 4, overflow: 'auto' }}>
{/* 日期标记 */}
<div style={{ textAlign: 'center', margin: '4px 0 12px' }}>
<span style={{ fontSize: 11, color: T.tx3, background: T.surface, padding: '3px 12px', borderRadius: 10 }}>今天 09:30</span>
</div>
{messages.map((msg, i) => (
<React.Fragment key={i}>
{/* 时间间隔 */}
{i === 3 && (
<div style={{ textAlign: 'center', margin: '8px 0' }}>
<span style={{ fontSize: 11, color: T.tx3, background: T.surface, padding: '3px 12px', borderRadius: 10 }}>09:35</span>
</div>
)}
{msg.from === 'ai' ? (
/* AI 消息 — 左对齐 */
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginBottom: 4 }}>
<AiAvatar />
<div style={{ maxWidth: 260 }}>
<div style={{
background: T.card,
borderRadius: '4px 16px 16px 16px',
padding: '10px 14px',
boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
}}>
{msg.card ? (
/* 带卡片的内容 */
<div>
<span style={{ fontSize: 15, color: T.tx, lineHeight: 1.6 }}>{msg.text}</span>
{/* 报告卡片 */}
<div style={{ marginTop: 8, padding: '10px 12px', background: T.surface, borderRadius: T.rSm, borderLeft: `3px solid ${T.pri}` }}>
<div style={{ fontSize: 13, fontWeight: 600, color: T.tx }}>2026年度健康体检</div>
<div style={{ fontSize: 11, color: T.tx3, marginTop: 2 }}>2026-05-10 · 综合</div>
</div>
</div>
) : (
<span style={{ fontSize: 15, color: T.tx, lineHeight: 1.6, whiteSpace: 'pre-line' }}>{msg.text}</span>
)}
</div>
</div>
</div>
) : (
/* 用户消息 — 右对齐 */
<div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 4 }}>
<div style={{ maxWidth: 260, background: T.priL, borderRadius: '16px 4px 16px 16px', padding: '10px 14px' }}>
<span style={{ fontSize: 15, color: T.tx, lineHeight: 1.6 }}>{msg.text}</span>
</div>
</div>
)}
</React.Fragment>
))}
{/* AI 正在输入 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 4 }}>
<AiAvatar />
<div style={{ background: T.card, borderRadius: '4px 16px 16px 16px', padding: '10px 16px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
<div style={{ display: 'flex', gap: 4, alignItems: 'center' }}>
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.tx3, animation: 'pulse 1.4s infinite' }} />
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.tx3, animation: 'pulse 1.4s infinite 0.2s' }} />
<div style={{ width: 6, height: 6, borderRadius: 3, background: T.tx3, animation: 'pulse 1.4s infinite 0.4s' }} />
</div>
</div>
</div>
</div>
<ChatBar />
</div>
);
}
// ─── 右屏:个人中心 · 通知入口 ───
function ProfileWithNotify() {
const user = { name: '张三', phone: '138****6789' };
const menuGroups = [
{
label: null,
items: [
{ icon: '🔔', label: '消息通知', badge: 3, color: T.pri },
],
},
{
label: '健康管理',
items: [
{ icon: '📊', label: '健康记录', color: '#C4623A' },
{ icon: '📄', label: '我的报告', color: '#5B7A5E' },
{ icon: '🤖', label: 'AI 分析', color: '#C4873A' },
],
},
{
label: '就诊服务',
items: [
{ icon: '📅', label: '我的预约', color: '#3A6B8C' },
{ icon: '🔄', label: '我的随访', color: '#7A5B7A' },
],
},
{
label: '生活服务',
items: [
{ icon: '🎁', label: '积分商城', color: '#C4873A' },
{ icon: '🏃', label: '线下活动', color: '#5B7A5E' },
],
},
{
label: '账号',
items: [
{ icon: '👤', label: '就诊人管理', color: T.tx2 },
{ icon: '⚙️', label: '设置', color: T.tx2 },
],
},
];
return (
<div style={{ height: '100%', background: T.bg }}>
{/* 用户卡片 */}
<div style={{ padding: '20px 20px 16px', display: 'flex', alignItems: 'center', gap: 14 }}>
<div style={{ width: 56, height: 56, borderRadius: 28, background: `linear-gradient(135deg, ${T.pri}, ${T.priD})`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ color: T.white, fontSize: 24, fontWeight: 600 }}>{user.name.charAt(0)}</span>
</div>
<div>
<div style={{ fontSize: 18, fontWeight: 600, color: T.tx }}>{user.name}</div>
<div style={{ fontSize: 13, color: T.tx3, marginTop: 2 }}>{user.phone}</div>
</div>
<div style={{ marginLeft: 'auto', color: T.tx3, fontSize: 20 }}></div>
</div>
{/* 统计行 */}
<div style={{ display: 'flex', gap: 10, padding: '0 20px 16px' }}>
{[
{ label: '健康积分', value: '1,280' },
{ label: '连续打卡', value: '15天' },
].map((s, i) => (
<div key={i} style={{ flex: 1, background: T.card, borderRadius: T.r, padding: '14px 16px' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.pri }}>{s.value}</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>{s.label}</div>
</div>
))}
</div>
{/* 菜单列表 */}
<div style={{ padding: '0 20px' }}>
{menuGroups.map((group, gi) => (
<div key={gi} style={{ marginBottom: 12 }}>
{group.label && <div style={{ fontSize: 12, color: T.tx3, marginBottom: 6, paddingLeft: 4 }}>{group.label}</div>}
<div style={{ background: T.card, borderRadius: T.r, overflow: 'hidden' }}>
{group.items.map((item, ii) => (
<div key={ii} style={{
display: 'flex', alignItems: 'center', padding: '14px 16px',
borderBottom: ii < group.items.length - 1 ? `1px solid ${T.bdL}` : 'none',
cursor: 'pointer',
}}>
{/* 图标 */}
<div style={{
width: 32, height: 32, borderRadius: T.rXs,
background: `${item.color}15`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 16, marginRight: 12,
}}>
{item.icon}
</div>
{/* 标签 */}
<span style={{ flex: 1, fontSize: 15, color: T.tx }}>{item.label}</span>
{/* 角标 */}
{item.badge && (
<div style={{
minWidth: 18, height: 18, borderRadius: 9,
background: T.dan, display: 'flex', alignItems: 'center', justifyContent: 'center',
padding: '0 5px', marginRight: 8,
}}>
<span style={{ fontSize: 11, color: T.white, fontWeight: 600 }}>{item.badge}</span>
</div>
)}
{/* 箭头 */}
<span style={{ color: T.tx3, fontSize: 16 }}></span>
</div>
))}
</div>
</div>
))}
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,462 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 预约挂号</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; }
.note { color: #666; font-size: 12px; max-width: 900px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 40px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 预约挂号</div>
<div class="note">预约列表 + 预约创建 + 预约详情 — 温润东方风设计系统,三屏并排展示完整挂号流程</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 393, height = 852, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用导航栏 ───
function NavBar({ title }) {
return (
<div style={{
height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center',
borderBottom: `1px solid ${T.bdL}`, background: T.bg, position: 'relative',
}}>
<svg style={{ position: 'absolute', left: 16, top: '50%', transform: 'translateY(-50%)' }}
width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M15 19l-7-7 7-7" stroke={T.tx} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
// ─── 状态标签 ───
function StatusTag({ label, variant }) {
const styles = {
pending: { bg: T.accL, color: T.acc },
done: { bg: T.surface, color: T.tx3 },
cancel: { bg: T.danL, color: T.dan },
};
const s = styles[variant] || styles.pending;
return (
<span style={{
display: 'inline-block', padding: '3px 10px', borderRadius: 20,
background: s.bg, color: s.color, fontSize: 12, fontWeight: 600,
}}>
{label}
</span>
);
}
// ─── 屏幕一:预约列表页 ───
function AppointmentList() {
const tabs = ['全部', '待就诊', '已完成', '已取消'];
const activeTab = 0;
const appointments = [
{ doctor: '李医生', dept: '肾内科', status: 'pending', statusLabel: '待就诊',
date: '5月10日 周六', time: '09:00 - 09:30', location: '门诊楼3层 心内科诊室' },
{ doctor: '王医生', dept: '心内科', status: 'done', statusLabel: '已完成',
date: '5月6日 周二', time: '14:00 - 14:30', location: '门诊楼2层 心内科诊室' },
{ doctor: '张医生', dept: '全科', status: 'cancel', statusLabel: '已取消',
date: '4月28日 周一', time: '10:00 - 10:30', location: '' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="我的预约" />
{/* 状态筛选 Tab */}
<div style={{
display: 'flex', gap: 8, padding: '14px 20px', background: T.bg,
}}>
{tabs.map((tab, i) => (
<div key={i} style={{
flex: 1, height: 36, borderRadius: 20, display: 'flex', alignItems: 'center',
justifyContent: 'center', fontSize: 14, fontWeight: 600,
background: i === activeTab ? T.pri : T.surface,
color: i === activeTab ? '#fff' : T.tx2,
cursor: 'pointer',
}}>
{tab}
</div>
))}
</div>
{/* 卡片列表 */}
<div style={{ flex: 1, overflow: 'auto', padding: '4px 20px 100px' }}>
{appointments.map((a, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '18px 20px',
marginBottom: 12, boxShadow: '0 2px 12px rgba(45,42,38,0.06)',
}}>
{/* 头部:医生+科室 + 状态 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div style={{
width: 40, height: 40, borderRadius: 20,
background: `linear-gradient(135deg, ${T.priL} 0%, ${T.pri} 100%)`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: '#fff' }}>
{a.doctor[0]}
</span>
</div>
<div>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx, fontFamily: T.sans }}>
{a.doctor}
</div>
<div style={{ fontSize: 13, color: T.tx3, marginTop: 2 }}>{a.dept}</div>
</div>
</div>
<StatusTag label={a.statusLabel} variant={a.status} />
</div>
{/* 时间 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<rect x="3" y="4" width="18" height="18" rx="2" stroke={T.tx3} strokeWidth="1.5"/>
<path d="M3 10h18M16 2v4M8 2v4" stroke={T.tx3} strokeWidth="1.5" strokeLinecap="round"/>
</svg>
<span style={{ fontSize: 14, color: T.tx2 }}>{a.date} {a.time}</span>
</div>
{/* 地点 */}
{a.location && (
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 13a3 3 0 100-6 3 3 0 000 6z" stroke={T.tx3} strokeWidth="1.5"/>
<path d="M12 22s-8-5.5-8-11a8 8 0 1116 0c0 5.5-8 11-8 11z" stroke={T.tx3} strokeWidth="1.5"/>
</svg>
<span style={{ fontSize: 14, color: T.tx2 }}>{a.location}</span>
</div>
)}
</div>
))}
</div>
{/* 浮动按钮 */}
<div style={{
position: 'absolute', bottom: 50, right: 24, width: 56, height: 56,
borderRadius: 28, background: T.pri, display: 'flex', alignItems: 'center',
justifyContent: 'center', boxShadow: `0 4px 20px rgba(196,98,58,0.4)`, zIndex: 5,
}}>
<svg width="26" height="26" viewBox="0 0 24 24" fill="none">
<path d="M12 5v14M5 12h14" stroke="#fff" strokeWidth="2.5" strokeLinecap="round"/>
</svg>
</div>
</div>
);
}
// ─── 屏幕二:预约创建页 ───
function AppointmentCreate() {
const timeSlots = {
morning: [
{ time: '09:00', selected: true },
{ time: '09:30', selected: false },
{ time: '10:00', selected: false },
],
afternoon: [
{ time: '14:00', selected: false },
{ time: '14:30', selected: false, disabled: true },
{ time: '15:00', selected: false, disabled: true },
],
};
function FormField({ label, placeholder, value, showArrow = true }) {
return (
<div style={{ marginBottom: 18 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>{label}</div>
<div style={{
height: 56, background: T.card, border: `1.5px solid ${T.bd}`, borderRadius: T.r,
display: 'flex', alignItems: 'center', padding: '0 16px', justifyContent: 'space-between',
}}>
<span style={{ fontSize: 16, color: value ? T.tx : T.tx3 }}>{value || placeholder}</span>
{showArrow && (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 9l6 6 6-6" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
)}
</div>
</div>
);
}
function TimeSlot({ time, selected, disabled }) {
return (
<div style={{
flex: 1, height: 44, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 15, fontWeight: 600,
background: disabled ? T.surface : selected ? T.pri : T.card,
color: disabled ? T.tx3 + '88' : selected ? '#fff' : T.tx2,
border: disabled ? 'none' : selected ? 'none' : `1.5px solid ${T.bd}`,
opacity: disabled ? 0.5 : 1,
}}>
{time}
</div>
);
}
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="预约挂号" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 120px' }}>
<FormField label="选择科室" placeholder="请选择科室" />
<FormField label="选择医生" placeholder="请选择医生" />
<FormField label="选择日期" placeholder="请选择日期" />
{/* 时段选择 */}
<div style={{ marginBottom: 18 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>选择时段</div>
{/* 上午 */}
<div style={{ marginBottom: 10 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 8 }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" style={{ verticalAlign: 'middle', marginRight: 4 }}>
<circle cx="12" cy="12" r="5" stroke={T.wrn} strokeWidth="1.5"/>
<path d="M12 2v2M12 20v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M2 12h2M20 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" stroke={T.wrn} strokeWidth="1.5" strokeLinecap="round"/>
</svg>
上午
</div>
<div style={{ display: 'flex', gap: 10 }}>
{timeSlots.morning.map((s, i) => <TimeSlot key={i} {...s} />)}
</div>
</div>
{/* 下午 */}
<div>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 8 }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" style={{ verticalAlign: 'middle', marginRight: 4 }}>
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" stroke={T.tx3} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
下午
</div>
<div style={{ display: 'flex', gap: 10 }}>
{timeSlots.afternoon.map((s, i) => <TimeSlot key={i} {...s} />)}
</div>
</div>
</div>
<FormField label="就诊人" placeholder="请选择就诊人" value="张三" />
{/* 备注 */}
<div style={{ marginBottom: 18 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>备注</div>
<div style={{
minHeight: 100, background: T.card, border: `1.5px solid ${T.bd}`, borderRadius: T.r,
padding: '14px 16px', fontSize: 16, color: T.tx3, lineHeight: 1.6,
}}>
请输入病情描述选填
</div>
</div>
</div>
{/* 底部按钮 */}
<div style={{
position: 'absolute', bottom: 34, left: 0, right: 0,
padding: '12px 20px', background: T.bg,
borderTop: `1px solid ${T.bdL}`,
}}>
<div style={{
height: 54, borderRadius: 16, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: '#fff', fontSize: 18, fontWeight: 600,
boxShadow: `0 4px 16px rgba(196,98,58,0.3)`,
}}>
确认预约
</div>
</div>
</div>
);
}
// ─── 屏幕三:预约详情页 ───
function AppointmentDetail() {
const infoItems = [
{ label: '科室', value: '肾内科' },
{ label: '医生', value: '李明华 主任医师' },
{ label: '日期', value: '2025年5月10日周六' },
{ label: '时间', value: '09:00 - 09:30' },
{ label: '地点', value: '门诊楼3层 心内科诊室305' },
{ label: '就诊人', value: '张三' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="预约详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 100px' }}>
{/* 状态大卡片 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '24px 20px',
boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16,
display: 'flex', flexDirection: 'column', alignItems: 'center',
}}>
{/* 状态图标 */}
<div style={{
width: 56, height: 56, borderRadius: 28, background: T.accL,
display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 12,
}}>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none">
<rect x="3" y="4" width="18" height="18" rx="2" stroke={T.acc} strokeWidth="1.8"/>
<path d="M3 10h18M16 2v4M8 2v4" stroke={T.acc} strokeWidth="1.8" strokeLinecap="round"/>
<path d="M8 14l2 2 4-4" stroke={T.acc} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
<StatusTag label="待就诊" variant="pending" />
</div>
{/* 信息列表 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '6px 20px',
boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16,
}}>
{infoItems.map((item, i) => (
<div key={i} style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
padding: '15px 0',
borderBottom: i < infoItems.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<span style={{ fontSize: 14, color: T.tx3, minWidth: 56 }}>{item.label}</span>
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500, textAlign: 'right' }}>{item.value}</span>
</div>
))}
</div>
{/* 温馨提示 */}
<div style={{
background: T.accL, borderRadius: T.r, padding: '16px 18px',
display: 'flex', gap: 12,
}}>
<div style={{ flexShrink: 0, marginTop: 1 }}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<circle cx="12" cy="12" r="10" stroke={T.acc} strokeWidth="1.5"/>
<path d="M12 16v-4M12 8h.01" stroke={T.acc} strokeWidth="2" strokeLinecap="round"/>
</svg>
</div>
<div>
<div style={{ fontSize: 14, fontWeight: 600, color: T.acc, marginBottom: 4 }}>温馨提示</div>
<div style={{ fontSize: 13, color: T.acc, lineHeight: 1.7, opacity: 0.85 }}>
请提前15分钟到达携带医保卡和既往病历
</div>
</div>
</div>
</div>
{/* 底部操作 */}
<div style={{
position: 'absolute', bottom: 34, left: 0, right: 0,
padding: '12px 20px', background: T.bg,
borderTop: `1px solid ${T.bdL}`,
display: 'flex', gap: 12,
}}>
<div style={{
flex: 1, height: 54, borderRadius: 16,
border: `1.5px solid ${T.dan}`, background: 'transparent',
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: T.dan, fontSize: 16, fontWeight: 600,
}}>
取消预约
</div>
<div style={{
flex: 1, height: 54, borderRadius: 16, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: '#fff', fontSize: 16, fontWeight: 600,
boxShadow: `0 4px 16px rgba(196,98,58,0.3)`,
}}>
导航到科室
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">预约列表</span>
<IosFrame time="9:41" battery={85}>
<AppointmentList />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">预约创建</span>
<IosFrame time="9:42" battery={84}>
<AppointmentCreate />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">预约详情</span>
<IosFrame time="9:43" battery={83}>
<AppointmentDetail />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,430 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 文章与AI报告</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 900px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 36px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
::-webkit-scrollbar { width: 0; height: 0; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 文章与 AI 报告</div>
<div class="note">温润东方风设计系统 — 文章列表/详情 + AI 报告列表/详情,四屏并排展示。内容为王,阅读体验优先。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 370, height = 800, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用导航栏 ───
function NavBar({ title }) {
return (
<div style={{
height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center',
borderBottom: `1px solid ${T.bdL}`, position: 'relative', background: T.bg,
flexShrink: 0
}}>
<svg style={{ position: 'absolute', left: 16, top: '50%', transform: 'translateY(-50%)' }} width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M15 19l-7-7 7-7" stroke={T.tx} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
// ─── 屏幕1文章列表 ───
function ArticleList() {
const categories = ['全部', '高血压', '糖尿病', '肾病', '透析'];
const articles = [
{ title: '高血压患者日常饮食指南', source: '健康时报', date: '5月8日', summary: '科学饮食是控制血压的关键,低盐、低脂、高纤维...' },
{ title: '血液透析的日常注意事项', source: '肾病频道', date: '5月7日', summary: '透析患者需要特别注意水分控制与营养补充...' },
{ title: '糖尿病患者如何科学运动', source: '医学前沿', date: '5月5日', summary: '规律运动有助控制血糖,但需注意运动强度...' },
{ title: '肾脏健康的十个信号', source: '健康管理', date: '5月3日', summary: '早期发现肾脏问题至关重要,关注这些预警信号...' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="健康资讯" />
{/* 分类标签 */}
<div style={{
display: 'flex', gap: 8, padding: '12px 16px', flexShrink: 0,
overflowX: 'auto', background: T.bg
}}>
{categories.map((cat, i) => (
<div key={cat} style={{
padding: '8px 18px', borderRadius: 20, flexShrink: 0, fontSize: 14,
fontWeight: i === 0 ? 600 : 400,
background: i === 0 ? T.pri : T.surface,
color: i === 0 ? '#fff' : T.tx2,
fontFamily: T.sans,
boxShadow: i === 0 ? `0 2px 8px rgba(196,98,58,0.2)` : 'none',
transition: 'all 0.2s',
}}>{cat}</div>
))}
</div>
{/* 文章列表 */}
<div style={{ flex: 1, overflow: 'auto', padding: '0 16px 16px' }}>
{articles.map((a, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: 14, marginBottom: 12,
display: 'flex', gap: 14,
boxShadow: '0 1px 4px rgba(0,0,0,0.04)',
}}>
{/* 缩略图占位 */}
<div style={{
width: 80, height: 80, borderRadius: T.rXs, flexShrink: 0,
background: T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center',
}}>
<span style={{ fontSize: 12, color: T.tx3 }}>配图</span>
</div>
{/* 文字区 */}
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minWidth: 0 }}>
<div>
<div style={{
fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx,
lineHeight: 1.35, marginBottom: 4,
display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
}}>{a.title}</div>
<div style={{
fontSize: 13, color: T.tx2, lineHeight: 1.4,
whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
}}>{a.summary}</div>
</div>
<div style={{ display: 'flex', gap: 12, fontSize: 12, color: T.tx3 }}>
<span>{a.source}</span>
<span>{a.date}</span>
</div>
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕2文章详情 ───
function ArticleDetail() {
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column', position: 'relative' }}>
<NavBar title="文章详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 16px 80px' }}>
{/* 文章标题 */}
<div style={{
fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.tx,
lineHeight: 1.4, marginBottom: 12,
}}>高血压患者日常饮食指南</div>
{/* 元信息 */}
<div style={{ display: 'flex', gap: 16, fontSize: 13, color: T.tx3, marginBottom: 16 }}>
<span>健康时报</span>
<span>2026年5月8日</span>
<span>1.2k 阅读</span>
</div>
{/* 分隔线 */}
<div style={{ height: 1, background: T.bdL, marginBottom: 20 }} />
{/* 正文 */}
<div style={{ fontSize: 15, color: T.tx2, lineHeight: 1.8, fontFamily: T.sans }}>
<p style={{ marginBottom: 16, textIndent: '2em' }}>
高血压是一种常见的慢性疾病合理的饮食习惯对于控制血压至关重要研究表明低盐低脂高纤维的饮食模式能够有效降低血压水平减少心血管疾病的发生风险
</p>
<p style={{ marginBottom: 16, textIndent: '2em' }}>
建议每日食盐摄入量控制在5克以内多食用新鲜蔬果全谷物和优质蛋白避免高钠加工食品如腌制品方便面等同时适量补充富含钾钙的食物如香蕉菠菜和牛奶
</p>
<p style={{ textIndent: '2em' }}>
除了饮食调节还应注意控制总热量摄入维持健康体重每周进行至少150分钟的中等强度有氧运动如快走游泳等定期监测血压遵医嘱服药...
</p>
</div>
</div>
{/* 底部浮动栏 */}
<div style={{
position: 'absolute', bottom: 34, left: 0, right: 0, height: 60,
background: T.card, borderTop: `1px solid ${T.bdL}`,
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 32,
padding: '0 16px',
}}>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2 }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="none">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" stroke={T.tx3} strokeWidth="1.8" fill="none"/>
</svg>
<span style={{ fontSize: 11, color: T.tx3 }}>收藏</span>
</div>
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2 }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="none">
<path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8" stroke={T.tx3} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
<polyline points="16,6 12,2 8,6" stroke={T.tx3} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
<line x1="12" y1="2" x2="12" y2="15" stroke={T.tx3} strokeWidth="1.8" strokeLinecap="round"/>
</svg>
<span style={{ fontSize: 11, color: T.tx3 }}>分享</span>
</div>
</div>
</div>
);
}
// ─── 屏幕3AI报告列表 ───
function AIReportList() {
const reports = [
{ type: '综合评估', typeColor: T.acc, typeBg: T.accL, title: '5月健康综合评估', date: '5月8日', summary: '整体健康状况良好,血压需持续关注,建议保持低盐饮食...' },
{ type: '化验解读', typeColor: T.pri, typeBg: T.priL, title: '血常规化验解读', date: '5月6日', summary: '血红蛋白略低,建议补充铁剂,注意营养均衡...' },
{ type: '趋势分析', typeColor: T.wrn, typeBg: T.wrnL, title: '近30天血压趋势', date: '5月1日', summary: '收缩压呈下降趋势,控制效果良好,请继续保持...' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="AI 健康报告" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px' }}>
{reports.map((r, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12,
boxShadow: '0 1px 4px rgba(0,0,0,0.04)',
position: 'relative',
}}>
{/* 类型标签 */}
<div style={{
display: 'inline-block', padding: '3px 10px', borderRadius: 6,
background: r.typeBg, color: r.typeColor, fontSize: 12, fontWeight: 600,
marginBottom: 10,
}}>{r.type}</div>
{/* 标题 */}
<div style={{
fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx,
marginBottom: 6, lineHeight: 1.35,
}}>{r.title}</div>
{/* 日期 */}
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 8 }}>{r.date}</div>
{/* 摘要 */}
<div style={{
fontSize: 13, color: T.tx2, lineHeight: 1.5,
display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
}}>{r.summary}</div>
{/* 右箭头 */}
<svg style={{ position: 'absolute', right: 16, top: '50%', transform: 'translateY(-50%)' }} width="18" height="18" viewBox="0 0 24 24" fill="none">
<path d="M9 5l7 7-7 7" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕4AI报告详情 ───
function AIReportDetail() {
const score = 85;
const circumference = 2 * Math.PI * 52;
const offset = circumference - (score / 100) * circumference;
const indicators = [
{ label: '血压', value: '130/85 mmHg', status: '偏高', statusType: 'warn' },
{ label: '血糖', value: '5.6 mmol/L', status: '正常', statusType: 'good' },
{ label: '血红蛋白', value: '110 g/L', status: '偏低', statusType: 'warn' },
{ label: '心率', value: '72 bpm', status: '正常', statusType: 'good' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column', position: 'relative' }}>
<NavBar title="报告详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 80px' }}>
{/* 报告头部 */}
<div style={{
background: T.card, borderRadius: T.r, padding: 20, marginBottom: 12,
boxShadow: '0 1px 4px rgba(0,0,0,0.04)', textAlign: 'center',
}}>
<div style={{
display: 'inline-block', padding: '4px 14px', borderRadius: 6,
background: T.accL, color: T.acc, fontSize: 13, fontWeight: 600,
marginBottom: 12,
}}>综合评估</div>
<div style={{
fontFamily: T.serif, fontSize: 20, fontWeight: 700, color: T.tx,
marginBottom: 4,
}}>5月健康综合评估</div>
<div style={{ fontSize: 13, color: T.tx3 }}>2026年5月8日</div>
</div>
{/* 综合评分环 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '24px 20px', marginBottom: 12,
boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', flexDirection: 'column',
alignItems: 'center',
}}>
<svg width="140" height="140" viewBox="0 0 140 140" style={{ marginBottom: 12 }}>
{/* 背景圆 */}
<circle cx="70" cy="70" r="52" fill="none" stroke={T.bdL} strokeWidth="10" />
{/* 进度圆 */}
<circle cx="70" cy="70" r="52" fill="none"
stroke={T.acc} strokeWidth="10" strokeLinecap="round"
strokeDasharray={circumference} strokeDashoffset={offset}
transform="rotate(-90 70 70)"
style={{ transition: 'stroke-dashoffset 1s ease' }}
/>
{/* 中心文字 */}
<text x="70" y="64" textAnchor="middle" fontFamily={T.serif} fontSize="36" fontWeight="700" fill={T.tx}>{score}</text>
<text x="70" y="86" textAnchor="middle" fontFamily={T.sans} fontSize="14" fill={T.tx3}>/100</text>
</svg>
<div style={{
fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.acc,
}}>良好</div>
</div>
{/* 分析结论 */}
<div style={{
background: T.accL, borderRadius: T.r, padding: '14px 16px', marginBottom: 12,
borderLeft: `4px solid ${T.acc}`,
}}>
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 700, color: T.acc, marginBottom: 8 }}>分析结论</div>
<div style={{ fontSize: 14, color: T.tx2, lineHeight: 1.7 }}>
<div style={{ marginBottom: 6, display: 'flex', gap: 6 }}>
<span style={{ color: T.acc, fontWeight: 700 }}>&bull;</span>
<span>血压控制良好建议继续保持低盐饮食</span>
</div>
<div style={{ display: 'flex', gap: 6 }}>
<span style={{ color: T.acc, fontWeight: 700 }}>&bull;</span>
<span>血红蛋白略有下降建议补充铁剂</span>
</div>
</div>
</div>
{/* 详细指标 */}
<div style={{
background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12,
boxShadow: '0 1px 4px rgba(0,0,0,0.04)',
}}>
<div style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx, marginBottom: 14 }}>详细指标</div>
{indicators.map((ind, i) => (
<div key={i} style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '12px 0',
borderBottom: i < indicators.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500, minWidth: 72 }}>{ind.label}</span>
<span style={{ fontSize: 14, color: T.tx2, flex: 1, textAlign: 'center' }}>{ind.value}</span>
<div style={{
padding: '3px 10px', borderRadius: 6, fontSize: 12, fontWeight: 600,
background: ind.statusType === 'good' ? T.accL : T.wrnL,
color: ind.statusType === 'good' ? T.acc : T.wrn,
}}>{ind.status}</div>
</div>
))}
</div>
</div>
{/* 底部按钮 */}
<div style={{
position: 'absolute', bottom: 34, left: 0, right: 0,
padding: '12px 16px', background: T.bg,
}}>
<div style={{
height: 50, borderRadius: T.r, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: '#fff', fontSize: 16, fontWeight: 600, fontFamily: T.sans,
boxShadow: `0 4px 16px rgba(196,98,58,0.3)`,
gap: 8,
}}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
<path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8" stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
<polyline points="16,6 12,2 8,6" stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
<line x1="12" y1="2" x2="12" y2="15" stroke="#fff" strokeWidth="1.8" strokeLinecap="round"/>
</svg>
分享给医生
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">文章列表</span>
<IosFrame time="9:41" battery={85}>
<ArticleList />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">文章详情</span>
<IosFrame time="9:42" battery={84}>
<ArticleDetail />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">AI 报告列表</span>
<IosFrame time="9:43" battery={83}>
<AIReportList />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">AI 报告详情</span>
<IosFrame time="9:44" battery={82}>
<AIReportDetail />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

328
docs/design/mp-05-mall.html Normal file
View File

@@ -0,0 +1,328 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 积分商城</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 600px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 48px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 积分商城</div>
<div class="note">温润东方风设计系统 — 积分商城主页。从"我的"页面进入的子页面,展示积分余额、快捷操作、分类筛选和商品兑换网格。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 393, height = 852, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 图标组件 ───
function IconCheckin({ size = 24, color = '#fff' }) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M9 11l3 3L22 4"/>
<path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11"/>
</svg>
);
}
function IconTask({ size = 24, color = '#fff' }) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<path d="M9 12l2 2 4-4"/>
</svg>
);
}
function IconHistory({ size = 24, color = '#fff' }) {
return (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10"/>
<polyline points="12 6 12 12 16 14"/>
</svg>
);
}
// ─── 商品占位图 SVG ───
function ProductPlaceholder({ label }) {
const iconMap = {
'健康体检套餐': (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
</svg>
),
'血压计': (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
</svg>
),
'维生素D3': (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<rect x="8" y="2" width="8" height="4" rx="1"/>
<path d="M6 6h12v14a2 2 0 01-2 2H8a2 2 0 01-2-2V6z"/>
<path d="M10 11h4"/>
</svg>
),
'健康食谱书': (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M4 19.5A2.5 2.5 0 016.5 17H20"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/>
<path d="M8 7h8M8 11h6"/>
</svg>
),
'运动手环': (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<rect x="7" y="2" width="10" height="20" rx="5"/>
<path d="M12 8v4l2 2"/>
</svg>
),
'保温杯': (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M8 2h8v3H8z"/>
<path d="M7 5h10l-1 15H8L7 5z"/>
<path d="M10 9h4"/>
</svg>
),
};
return (
<div style={{ width: '100%', aspectRatio: '1', background: T.surface, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative' }}>
{iconMap[label] || (
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#C4623A" strokeWidth="1.5"><rect x="3" y="3" width="18" height="18" rx="3"/></svg>
)}
<div style={{ position: 'absolute', bottom: 6, left: 0, right: 0, textAlign: 'center', fontSize: 9, color: T.tx3, fontWeight: 500 }}>{label}</div>
</div>
);
}
// ─── 积分商城主页 ───
function MallPage() {
const categories = ['全部', '健康', '生活', '食品'];
const [activeCategory, setActiveCategory] = React.useState(0);
const quickActions = [
{ icon: <IconCheckin size={22} color="#fff" />, label: '签到打卡', bg: T.acc, shadow: 'rgba(91,122,94,0.3)' },
{ icon: <IconTask size={22} color="#fff" />, label: '积分任务', bg: T.pri, shadow: 'rgba(196,98,58,0.3)' },
{ icon: <IconHistory size={22} color="#fff" />, label: '兑换记录', bg: T.wrn, shadow: 'rgba(196,135,58,0.3)' },
];
const products = [
{ name: '健康体检套餐', points: 800, price: 299, tag: '热门' },
{ name: '血压计', points: 1200, price: 199 },
{ name: '维生素D3', points: 300, price: 89 },
{ name: '健康食谱书', points: 500, price: 68, tag: '新品' },
{ name: '运动手环', points: 2000, price: 399 },
{ name: '保温杯', points: 600, price: 128, tag: '新品' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
{/* ── 导航栏 ── */}
<div style={{ padding: '12px 20px 8px', display: 'flex', alignItems: 'center', gap: 8, background: T.bg }}>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.tx} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M15 18l-6-6 6-6"/>
</svg>
<div style={{ flex: 1, textAlign: 'center', fontFamily: T.serif, fontSize: 26, fontWeight: 700, color: T.tx, paddingRight: 24 }}>积分商城</div>
</div>
{/* ── 可滚动内容区 ── */}
<div style={{ flex: 1, overflow: 'auto', padding: '8px 20px 24px' }}>
{/* ── 积分卡片 ── */}
<div style={{
background: `linear-gradient(135deg, ${T.pri} 0%, ${T.priD} 100%)`,
borderRadius: T.r,
padding: '24px 24px 20px',
marginBottom: 20,
boxShadow: `0 8px 24px rgba(196,98,58,0.25)`,
position: 'relative',
overflow: 'hidden',
}}>
{/* 装饰圆 */}
<div style={{ position: 'absolute', top: -20, right: -20, width: 100, height: 100, borderRadius: 50, background: 'rgba(255,255,255,0.08)' }} />
<div style={{ position: 'absolute', bottom: -30, right: 40, width: 80, height: 80, borderRadius: 40, background: 'rgba(255,255,255,0.05)' }} />
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', position: 'relative', zIndex: 1 }}>
<div>
<div style={{ fontSize: 13, color: 'rgba(255,255,255,0.7)', marginBottom: 8, letterSpacing: 1 }}>我的积分</div>
<div style={{ fontFamily: T.serif, fontSize: 42, fontWeight: 700, color: '#fff', lineHeight: 1 }}>1,280</div>
</div>
<div style={{
display: 'flex', alignItems: 'center', gap: 4,
background: 'rgba(255,255,255,0.2)', borderRadius: 20,
padding: '6px 14px', fontSize: 13, color: '#fff', fontWeight: 500,
}}>
积分明细
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M9 18l6-6-6-6"/>
</svg>
</div>
</div>
</div>
{/* ── 快捷操作 ── */}
<div style={{ display: 'flex', justifyContent: 'space-around', marginBottom: 24 }}>
{quickActions.map((action, i) => (
<div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
<div style={{
width: 52, height: 52, borderRadius: 26,
background: action.bg,
display: 'flex', alignItems: 'center', justifyContent: 'center',
boxShadow: `0 4px 12px ${action.shadow}`,
}}>
{action.icon}
</div>
<span style={{ fontSize: 12, color: T.tx2, fontWeight: 500 }}>{action.label}</span>
</div>
))}
</div>
{/* ── 分类标签 ── */}
<div style={{ display: 'flex', gap: 10, marginBottom: 20, overflowX: 'auto' }}>
{categories.map((cat, i) => (
<div
key={i}
onClick={() => setActiveCategory(i)}
style={{
padding: '7px 18px',
borderRadius: 20,
fontSize: 14,
fontWeight: activeCategory === i ? 600 : 400,
background: activeCategory === i ? T.pri : T.surface,
color: activeCategory === i ? '#fff' : T.tx2,
whiteSpace: 'nowrap',
transition: 'all 0.2s',
cursor: 'pointer',
}}
>
{cat}
</div>
))}
</div>
{/* ── 商品网格 ── */}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
{products.map((product, i) => (
<div key={i} style={{
background: T.card,
borderRadius: T.rSm,
overflow: 'hidden',
boxShadow: '0 2px 8px rgba(0,0,0,0.04)',
}}>
{/* 商品图 */}
<div style={{ position: 'relative' }}>
<ProductPlaceholder label={product.name} />
{product.tag && (
<div style={{
position: 'absolute', top: 8, left: 8,
background: product.tag === '热门' ? T.dan : T.acc,
color: '#fff', fontSize: 10, fontWeight: 600,
padding: '2px 8px', borderRadius: 6,
}}>
{product.tag}
</div>
)}
</div>
{/* 商品信息 */}
<div style={{ padding: '10px 12px 14px' }}>
<div style={{
fontSize: 14, fontWeight: 600, color: T.tx,
lineHeight: 1.4, marginBottom: 8,
display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
height: 40,
}}>
{product.name}
</div>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.pri }}>
{product.points}
</span>
<span style={{ fontSize: 11, color: T.pri, fontWeight: 500 }}>积分</span>
</div>
<div style={{ fontSize: 12, color: T.tx3, textDecoration: 'line-through', marginTop: 2 }}>
¥{product.price}
</div>
</div>
</div>
))}
</div>
{/* ── 底部留白 ── */}
<div style={{ height: 16 }} />
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">积分商城 主页</span>
<IosFrame time="9:41" battery={85}>
<MallPage />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,664 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 健康分包</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; }
.note { color: #666; font-size: 12px; max-width: 1200px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 32px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 健康分包</div>
<div class="note">告警列表 + 日常监测 + 设备同步 + 体征录入 + 趋势分析 — 五屏并排展示健康分包核心功能</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 360, height = 780, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用导航栏 ───
function NavBar({ title }) {
return (
<div style={{
height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center',
borderBottom: `1px solid ${T.bdL}`, background: T.bg, position: 'relative',
}}>
<svg style={{ position: 'absolute', left: 16, top: '50%', transform: 'translateY(-50%)' }}
width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M15 19l-7-7 7-7" stroke={T.tx} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
// ─── 屏幕一:告警列表 ───
function AlertList() {
const alerts = [
{ level: 'HIGH', desc: '收缩压持续偏高(>140mmHg', time: '今天 08:30', bg: T.danL, color: T.dan, label: '高' },
{ level: 'MEDIUM', desc: '血糖餐后值偏高8.2mmol/L', time: '昨天 19:00', bg: T.wrnL, color: T.wrn, label: '中' },
{ level: 'LOW', desc: '体重较上周增加 0.5kg', time: '3天前', bg: T.accL, color: T.acc, label: '低' },
{ level: 'LOW', desc: '心率偏低55bpm', time: '5天前', bg: T.accL, color: T.acc, label: '低' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="健康告警" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 100px' }}>
{/* 统计概览 */}
<div style={{
display: 'flex', gap: 10, marginBottom: 16,
}}>
<div style={{ flex: 1, background: T.danL, borderRadius: T.rSm, padding: '12px 14px', textAlign: 'center' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.dan }}>1</div>
<div style={{ fontSize: 12, color: T.dan, marginTop: 2 }}>高级</div>
</div>
<div style={{ flex: 1, background: T.wrnL, borderRadius: T.rSm, padding: '12px 14px', textAlign: 'center' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.wrn }}>1</div>
<div style={{ fontSize: 12, color: T.wrn, marginTop: 2 }}>中级</div>
</div>
<div style={{ flex: 1, background: T.accL, borderRadius: T.rSm, padding: '12px 14px', textAlign: 'center' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.acc }}>2</div>
<div style={{ fontSize: 12, color: T.acc, marginTop: 2 }}>低级</div>
</div>
</div>
{/* 告警卡片列表 */}
{alerts.map((a, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px',
marginBottom: 10, boxShadow: '0 2px 12px rgba(45,42,38,0.06)',
display: 'flex', alignItems: 'center', gap: 14,
}}>
{/* 严重程度标签 */}
<div style={{
minWidth: 40, height: 40, borderRadius: T.rSm,
background: a.bg, display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
}}>
<span style={{ fontSize: 14, fontWeight: 700, color: a.color }}>{a.label}</span>
</div>
{/* 内容 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 15, fontWeight: 500, color: T.tx, lineHeight: 1.4, marginBottom: 4 }}>
{a.desc}
</div>
<div style={{ fontSize: 12, color: T.tx3 }}>{a.time}</div>
</div>
{/* 箭头 */}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" style={{ flexShrink: 0 }}>
<path d="M9 5l7 7-7 7" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕二:日常监测 ───
function DailyMonitoring() {
const vitals = [
{ label: '血压', value: '130/85', unit: 'mmHg', status: '偏高', statusType: 'wrn' },
{ label: '心率', value: '72', unit: 'bpm', status: '正常', statusType: 'acc' },
{ label: '血糖', value: '5.6', unit: 'mmol/L', status: '正常', statusType: 'acc' },
{ label: '体重', value: '—', unit: 'kg', status: '未记录', statusType: 'empty' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="日常监测" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 100px' }}>
{/* 日期选择横条 */}
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
background: T.card, borderRadius: T.r, padding: '12px 16px',
marginBottom: 16, boxShadow: '0 2px 12px rgba(45,42,38,0.06)',
}}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path d="M15 19l-7-7 7-7" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 17, fontWeight: 600, color: T.tx, fontFamily: T.serif }}>5月8日</div>
<div style={{ fontSize: 13, color: T.tx3, marginTop: 2 }}>周四</div>
</div>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path d="M9 5l7 7-7 7" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
{/* 今日概览卡片 */}
<div style={{
background: T.card, borderRadius: T.r, padding: 20,
boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16,
display: 'flex', alignItems: 'center', gap: 18,
}}>
{/* 进度环 */}
<div style={{ width: 68, height: 68, position: 'relative', flexShrink: 0 }}>
<svg width="68" height="68" viewBox="0 0 68 68">
<circle cx="34" cy="34" r="29" fill="none" stroke={T.bd} strokeWidth="4.5" />
<circle cx="34" cy="34" r="29" fill="none" stroke={T.pri} strokeWidth="4.5"
strokeDasharray={`${0.75 * 2 * Math.PI * 29} ${0.25 * 2 * Math.PI * 29}`}
strokeDashoffset="0" strokeLinecap="round" transform="rotate(-90 34 34)" />
</svg>
<div style={{
position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.pri,
}}>3/4</div>
</div>
<div>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx, marginBottom: 6 }}>今日已记录 3 项体征</div>
<div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
{['血压 ✓','心率 ✓','血糖 ✓','体重'].map((t, i) => (
<span key={i} style={{
fontSize: 11, padding: '3px 8px', borderRadius: 999,
background: i < 3 ? T.accL : T.surface,
color: i < 3 ? T.acc : T.tx3, fontWeight: 500,
}}>{t}</span>
))}
</div>
</div>
</div>
{/* 体征 2x2 网格 */}
<div style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx, marginBottom: 10 }}>今日体征</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
{vitals.map((v, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '14px 16px',
boxShadow: '0 1px 4px rgba(45,42,38,0.04)',
}}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6 }}>{v.label}</div>
<div style={{ display: 'flex', alignItems: 'baseline', marginBottom: 6 }}>
<span style={{
fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: T.tx, lineHeight: 1,
opacity: v.statusType === 'empty' ? 0.3 : 1,
}}>{v.value}</span>
<span style={{ fontSize: 12, color: T.tx3, marginLeft: 3 }}>{v.unit}</span>
</div>
<span style={{
fontSize: 11, padding: '2px 8px', borderRadius: 999, fontWeight: 500,
background: v.statusType === 'acc' ? T.accL : v.statusType === 'wrn' ? T.wrnL : T.surface,
color: v.statusType === 'acc' ? T.acc : v.statusType === 'wrn' ? T.wrn : T.tx3,
}}>{v.status}</span>
</div>
))}
</div>
</div>
</div>
);
}
// ─── 屏幕三:设备同步 ───
function DeviceSync() {
const devices = [
{ name: 'BCM 血压计', connected: true, lastSync: '5分钟前' },
{ name: '欧姆龙 血糖仪', connected: false, lastSync: null },
];
// 生成心率波形 SVG path
const wavePoints = [];
for (let x = 0; x <= 300; x += 2) {
let y = 40;
// 模拟心电图 QRS 波形
const cycle = x % 80;
if (cycle >= 30 && cycle < 35) y = 40 - 8;
else if (cycle >= 35 && cycle < 40) y = 40 + 28;
else if (cycle >= 40 && cycle < 45) y = 40 - 18;
else if (cycle >= 45 && cycle < 50) y = 40 + 5;
else y = 40 + Math.sin(x * 0.05) * 2;
wavePoints.push(`${x === 0 ? 'M' : 'L'}${x},${y}`);
}
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="设备同步" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 100px' }}>
{/* 已连接设备卡片 */}
<div style={{
background: T.card, borderRadius: T.r, padding: 18,
boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16,
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
<span style={{ fontSize: 15, fontWeight: 600, color: T.tx }}>当前设备</span>
<span style={{
display: 'inline-block', padding: '3px 10px', borderRadius: 20,
background: T.accL, color: T.acc, fontSize: 12, fontWeight: 600,
}}>已连接</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{
width: 48, height: 48, borderRadius: T.rSm, background: T.accL,
display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
}}>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<rect x="2" y="6" width="20" height="12" rx="2" stroke={T.acc} strokeWidth="1.5"/>
<path d="M6 10h2M10 10h2M6 14h8" stroke={T.acc} strokeWidth="1.5" strokeLinecap="round"/>
</svg>
</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>BCM 血压计</div>
<div style={{ fontSize: 13, color: T.tx3, marginTop: 2 }}>最后同步5分钟前</div>
</div>
</div>
</div>
{/* 可用设备列表 */}
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx2, marginBottom: 8, paddingLeft: 2 }}>可用设备</div>
<div style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', boxShadow: '0 1px 4px rgba(45,42,38,0.04)', marginBottom: 20 }}>
{devices.map((d, i) => (
<div key={i} style={{
display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px',
borderBottom: i < devices.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<div style={{
width: 40, height: 40, borderRadius: T.rSm,
background: d.connected ? T.accL : T.surface,
display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
}}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<rect x="2" y="6" width="20" height="12" rx="2" stroke={d.connected ? T.acc : T.tx3} strokeWidth="1.5"/>
<path d="M6 10h2M10 10h2M6 14h8" stroke={d.connected ? T.acc : T.tx3} strokeWidth="1.5" strokeLinecap="round"/>
</svg>
</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 15, fontWeight: 500, color: T.tx }}>{d.name}</div>
</div>
<span style={{
fontSize: 13, color: d.connected ? T.acc : T.tx3, fontWeight: 500,
}}>{d.connected ? '已连接' : '未连接'}</span>
</div>
))}
</div>
{/* 实时数据区 — 心率波形 */}
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx2, marginBottom: 8, paddingLeft: 2 }}>实时数据</div>
<div style={{
background: T.card, borderRadius: T.r, padding: 18,
boxShadow: '0 1px 4px rgba(45,42,38,0.04)', marginBottom: 20,
}}>
<div style={{
background: T.bg, borderRadius: T.rSm, padding: '12px 8px',
height: 90, display: 'flex', alignItems: 'center', justifyContent: 'center',
marginBottom: 12, overflow: 'hidden',
}}>
<svg width="100%" height="80" viewBox="0 0 300 80" preserveAspectRatio="none" style={{ overflow: 'visible' }}>
<path d={wavePoints.join(' ')} fill="none" stroke={T.pri} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
<div style={{ textAlign: 'center' }}>
<span style={{ fontFamily: T.serif, fontSize: 36, fontWeight: 700, color: T.tx }}>72</span>
<span style={{ fontSize: 14, color: T.tx3, marginLeft: 4 }}>bpm</span>
</div>
</div>
{/* 同步数据按钮 */}
<div style={{
height: 52, borderRadius: 16, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: '#fff', fontSize: 17, fontWeight: 600,
boxShadow: `0 4px 16px rgba(196,98,58,0.3)`,
}}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" style={{ marginRight: 8 }}>
<path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0118.8-4.3M22 12.5a10 10 0 01-18.8 4.3"
stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
同步数据
</div>
</div>
</div>
);
}
// ─── 屏幕四:体征录入 ───
function VitalInput() {
const types = ['血压', '心率', '血糖', '体重'];
const activeType = 0;
const periods = ['早晨', '晚上'];
const activePeriod = 0;
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="记录体征" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 120px' }}>
{/* 体征类型选择 */}
<div style={{ display: 'flex', gap: 8, marginBottom: 20 }}>
{types.map((t, i) => (
<div key={i} style={{
flex: 1, height: 40, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 14, fontWeight: 600,
background: i === activeType ? T.pri : T.surface,
color: i === activeType ? '#fff' : T.tx2,
}}>{t}</div>
))}
</div>
{/* 血压录入表单 */}
<div style={{
background: T.card, borderRadius: T.r, padding: 20,
boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16,
}}>
{/* 收缩压 */}
<div style={{ marginBottom: 18 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>收缩压高压</div>
<div style={{
height: 60, background: T.bg, border: `2px solid ${T.bd}`, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', padding: '0 16px',
}}>
<span style={{ fontFamily: T.serif, fontSize: 30, fontWeight: 700, color: T.tx }}>130</span>
<span style={{ fontSize: 13, color: T.tx3, marginLeft: 6 }}>mmHg</span>
</div>
</div>
{/* 舒张压 */}
<div style={{ marginBottom: 18 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>舒张压低压</div>
<div style={{
height: 60, background: T.bg, border: `2px solid ${T.bd}`, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', padding: '0 16px',
}}>
<span style={{ fontFamily: T.serif, fontSize: 30, fontWeight: 700, color: T.tx }}>85</span>
<span style={{ fontSize: 13, color: T.tx3, marginLeft: 6 }}>mmHg</span>
</div>
</div>
{/* 测量时段 */}
<div style={{ marginBottom: 18 }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>测量时段</div>
<div style={{ display: 'flex', gap: 10 }}>
{periods.map((p, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 15, fontWeight: 600,
background: i === activePeriod ? T.pri : T.surface,
color: i === activePeriod ? '#fff' : T.tx2,
}}>{p}</div>
))}
</div>
</div>
{/* 备注 */}
<div>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 6, fontWeight: 500 }}>备注</div>
<div style={{
minHeight: 72, background: T.bg, border: `2px solid ${T.bd}`, borderRadius: T.rSm,
padding: '12px 16px', fontSize: 15, color: T.tx3, lineHeight: 1.6,
}}>
添加备注选填
</div>
</div>
</div>
{/* 参考范围提示 */}
<div style={{
background: T.surface, borderRadius: T.rSm, padding: '12px 16px',
display: 'flex', alignItems: 'flex-start', gap: 8,
}}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" style={{ flexShrink: 0, marginTop: 1 }}>
<circle cx="12" cy="12" r="10" stroke={T.tx3} strokeWidth="1.5"/>
<path d="M12 16v-4M12 8h.01" stroke={T.tx3} strokeWidth="2" strokeLinecap="round"/>
</svg>
<div style={{ fontSize: 12, color: T.tx3, lineHeight: 1.7 }}>
参考范围收缩压 90-140 / 舒张压 60-90 mmHg
</div>
</div>
</div>
{/* 底部保存按钮 */}
<div style={{
position: 'absolute', bottom: 34, left: 0, right: 0,
padding: '12px 16px', background: T.bg,
borderTop: `1px solid ${T.bdL}`,
}}>
<div style={{
height: 52, borderRadius: 16, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: '#fff', fontSize: 17, fontWeight: 600,
boxShadow: `0 4px 16px rgba(196,98,58,0.3)`,
}}>
保存
</div>
</div>
</div>
);
}
// ─── 屏幕五:趋势分析 ───
function TrendAnalysis() {
const timeRanges = ['7天', '30天', '90天'];
const activeRange = 0;
const trendData = [132, 128, 135, 130, 138, 126, 130];
const days = ['一','二','三','四','五','六','日'];
const maxV = Math.max(...trendData);
const threshold = 140;
const stats = [
{ label: '平均值', value: '130', unit: 'mmHg' },
{ label: '最高值', value: '138', unit: 'mmHg' },
{ label: '最低值', value: '126', unit: 'mmHg' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="趋势分析" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 100px' }}>
{/* 时间段选择 */}
<div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
{timeRanges.map((t, i) => (
<div key={i} style={{
flex: 1, height: 40, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 14, fontWeight: 600,
background: i === activeRange ? T.pri : T.surface,
color: i === activeRange ? '#fff' : T.tx2,
}}>{t}</div>
))}
</div>
{/* 趋势图 */}
<div style={{
background: T.card, borderRadius: T.r, padding: 18,
boxShadow: '0 2px 12px rgba(45,42,38,0.06)', marginBottom: 16,
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 14 }}>收缩压趋势</div>
{/* 柱状图 */}
<div style={{
position: 'relative', height: 140, background: T.bg, borderRadius: T.rSm,
padding: '12px 8px', display: 'flex', alignItems: 'flex-end',
}}>
{/* 阈值标线 */}
<div style={{
position: 'absolute', left: 8, right: 8,
bottom: `${12 + (threshold / maxV) * 100}px`,
borderTop: `1.5px dashed ${T.wrn}`, opacity: 0.6,
}} />
<div style={{
position: 'absolute', right: 12,
bottom: `${18 + (threshold / maxV) * 100}px`,
fontSize: 10, color: T.wrn, opacity: 0.7,
}}>140</div>
{trendData.map((v, i) => {
const hPct = Math.max(10, (v / maxV) * 100);
const isWarn = v >= threshold;
return (
<div key={i} style={{
flex: 1, display: 'flex', flexDirection: 'column',
alignItems: 'center', height: '100%', justifyContent: 'flex-end',
}}>
<div style={{
width: 26, borderRadius: '6px 6px 0 0', minHeight: 8,
height: `${hPct}%`, background: isWarn ? T.wrn : T.pri,
opacity: isWarn ? 1 : 0.7, transition: 'height 0.3s',
}} />
<span style={{ fontSize: 11, color: T.tx3, marginTop: 6 }}>{days[i]}</span>
</div>
);
})}
</div>
{/* 图例 */}
<div style={{ display: 'flex', justifyContent: 'center', gap: 16, marginTop: 12 }}>
<span style={{ fontSize: 11, color: T.tx3 }}>
<span style={{ display: 'inline-block', width: 10, height: 10, borderRadius: 2, background: T.pri, marginRight: 4, verticalAlign: 'middle' }} />正常
</span>
<span style={{ fontSize: 11, color: T.tx3 }}>
<span style={{ display: 'inline-block', width: 10, height: 10, borderRadius: 2, background: T.wrn, marginRight: 4, verticalAlign: 'middle' }} />偏高
</span>
<span style={{ fontSize: 11, color: T.tx3 }}>
<span style={{ display: 'inline-block', width: 10, height: 0, borderTop: '1.5px dashed ' + T.wrn, marginRight: 4, verticalAlign: 'middle' }} />阈值
</span>
</div>
</div>
{/* 统计摘要卡片 */}
<div style={{
display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, marginBottom: 16,
}}>
{stats.map((s, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.rSm, padding: '14px 12px',
textAlign: 'center', boxShadow: '0 1px 4px rgba(45,42,38,0.04)',
}}>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 4 }}>{s.label}</div>
<div>
<span style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.tx }}>{s.value}</span>
<span style={{ fontSize: 11, color: T.tx3, marginLeft: 2 }}>{s.unit}</span>
</div>
</div>
))}
</div>
{/* 趋势指示 */}
<div style={{
background: T.accL, borderRadius: T.r, padding: '16px 18px',
display: 'flex', alignItems: 'center', gap: 12,
}}>
<div style={{
width: 40, height: 40, borderRadius: 20, background: T.acc,
display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
}}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path d="M12 19V5M5 12l7-7 7 7" stroke="#fff" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
<div>
<div style={{ fontSize: 15, fontWeight: 600, color: T.acc, marginBottom: 2 }}>
趋势下降
</div>
<div style={{ fontSize: 13, color: T.acc, opacity: 0.8 }}>
7 日收缩压呈下降趋势保持良好
</div>
</div>
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">告警列表</span>
<IosFrame time="9:41" battery={85}>
<AlertList />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">日常监测</span>
<IosFrame time="9:42" battery={84}>
<DailyMonitoring />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">设备同步</span>
<IosFrame time="9:43" battery={83}>
<DeviceSync />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">体征录入</span>
<IosFrame time="9:44" battery={82}>
<VitalInput />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">趋势分析</span>
<IosFrame time="9:45" battery={81}>
<TrendAnalysis />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,440 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 健康记录</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 800px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 36px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 健康记录</div>
<div class="note">温润东方风设计系统 — 个人中心健康记录模块。5 个屏幕:健康记录列表、诊断记录、用药记录、检查报告列表、报告详情。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 360, height = 780, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用组件 ───
function NavBar({ title }) {
return (
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', background: T.bg, borderBottom: `1px solid ${T.bdL}`, flexShrink: 0 }}>
<svg style={{ position: 'absolute', left: 16 }} width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.tx} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M15 18l-6-6 6-6"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
function Tag({ label, color = T.acc, bg = T.accL }) {
return (
<span style={{ display: 'inline-block', fontSize: 11, color, background: bg, padding: '2px 8px', borderRadius: 6, fontWeight: 500 }}>{label}</span>
);
}
// ─── 屏幕1健康记录列表 ───
function HealthRecordList() {
const records = [
{ date: '5月8日', time: '09:30', type: '体征记录', tagColor: T.acc, tagBg: T.accL, summary: '血压 130/85, 心率 72, 血糖 5.6', icon: '♥' },
{ date: '5月6日', time: '14:00', type: '化验单', tagColor: T.pri, tagBg: T.priL, summary: '血常规:血红蛋白 110g/L', icon: '📋' },
{ date: '5月1日', time: '10:00', type: '体征记录', tagColor: T.acc, tagBg: T.accL, summary: '血压 128/82, 心率 70', icon: '♥' },
{ date: '4月28日', time: '16:00', type: '体检报告', tagColor: T.wrn, tagBg: T.wrnL, summary: '年度体检(综合)', icon: '📄' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="健康记录" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 24px' }}>
{/* 顶部摘要 */}
<div style={{ background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 24, boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 4 }}>本月记录</div>
<div style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: T.pri }}>12</div>
</div>
<div style={{ display: 'flex', gap: 16 }}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>体征</div>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>8</div>
</div>
<div style={{ width: 1, background: T.bdL }} />
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>化验</div>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>3</div>
</div>
<div style={{ width: 1, background: T.bdL }} />
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>报告</div>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>1</div>
</div>
</div>
</div>
</div>
{/* 时间线 */}
<div style={{ position: 'relative', paddingLeft: 24 }}>
{/* 竖线 */}
<div style={{ position: 'absolute', left: 7, top: 6, bottom: 6, width: 2, background: `linear-gradient(to bottom, ${T.pri} 0%, ${T.bd} 100%)`, borderRadius: 1 }} />
{records.map((rec, i) => (
<div key={i} style={{ position: 'relative', marginBottom: i < records.length - 1 ? 20 : 0 }}>
{/* 圆点 */}
<div style={{ position: 'absolute', left: -24, top: 4, width: 16, height: 16, borderRadius: 8, background: T.card, border: `3px solid ${T.pri}`, zIndex: 1 }} />
{/* 日期行 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
<span style={{ fontSize: 13, fontWeight: 600, color: T.tx }}>{rec.date}</span>
<span style={{ fontSize: 12, color: T.tx3 }}>{rec.time}</span>
<Tag label={rec.type} color={rec.tagColor} bg={rec.tagBg} />
</div>
{/* 卡片 */}
<div style={{ background: T.card, borderRadius: T.rSm, padding: '14px 16px', boxShadow: '0 1px 8px rgba(0,0,0,0.04)' }}>
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
<span style={{ fontSize: 18, lineHeight: 1 }}>{rec.icon}</span>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 14, fontWeight: 500, color: T.tx, marginBottom: 4 }}>{rec.type}</div>
<div style={{ fontSize: 13, color: T.tx2, lineHeight: 1.5 }}>{rec.summary}</div>
</div>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M9 18l6-6-6-6"/>
</svg>
</div>
</div>
</div>
))}
</div>
</div>
</div>
);
}
// ─── 屏幕2诊断记录 ───
function DiagnosisRecords() {
const diagnoses = [
{ name: '高血压 II 级', date: '2024-03-15', doctor: '王医生', dept: '心内科', status: '进行中', statusColor: T.wrn, statusBg: T.wrnL },
{ name: '2型糖尿病', date: '2023-08-20', doctor: '李医生', dept: '内分泌科', status: '已控制', statusColor: T.acc, statusBg: T.accL },
{ name: '慢性肾病 III 期', date: '2023-05-10', doctor: '张医生', dept: '肾内科', status: '进行中', statusColor: T.wrn, statusBg: T.wrnL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="诊断记录" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 24px' }}>
{/* 统计栏 */}
<div style={{ display: 'flex', gap: 12, marginBottom: 20 }}>
<div style={{ flex: 1, background: T.card, borderRadius: T.rSm, padding: '14px 16px', textAlign: 'center', boxShadow: '0 1px 8px rgba(0,0,0,0.04)' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.wrn }}>2</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>进行中</div>
</div>
<div style={{ flex: 1, background: T.card, borderRadius: T.rSm, padding: '14px 16px', textAlign: 'center', boxShadow: '0 1px 8px rgba(0,0,0,0.04)' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.acc }}>1</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>已控制</div>
</div>
</div>
{diagnoses.map((d, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14, boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 10 }}>
<div style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx, lineHeight: 1.3 }}>{d.name}</div>
<Tag label={d.status} color={d.statusColor} bg={d.statusBg} />
</div>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 8 }}>诊断日期{d.date}</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</svg>
<span style={{ fontSize: 13, color: T.tx2 }}>{d.doctor} · {d.dept}</span>
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕3用药记录 ───
function MedicationRecords() {
const currentMeds = [
{ name: '缬沙坦', dose: '80mg', freq: '每日一次', note: '早餐后', forDisease: '高血压', active: true },
{ name: '二甲双胍', dose: '500mg', freq: '每日两次', note: '', forDisease: '糖尿病', active: true },
];
const historyMeds = [
{ name: '阿莫西林', dose: '250mg', freq: '每日三次', note: '7天', forDisease: '呼吸道感染', active: false },
];
function MedCard({ med }) {
return (
<div style={{ background: T.card, borderRadius: T.rSm, padding: '16px 18px', marginBottom: 10, boxShadow: '0 1px 8px rgba(0,0,0,0.04)', borderLeft: `3px solid ${med.active ? T.acc : T.bd}` }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8 }}>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{med.name}</span>
<span style={{ fontSize: 14, color: T.tx2 }}>{med.dose}</span>
</div>
<Tag label={med.active ? '用药中' : '已停药'} color={med.active ? T.acc : T.tx3} bg={med.active ? T.accL : T.surface} />
</div>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6 }}>
{med.freq}{med.note ? ` · ${med.note}` : ''}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M9 11l3 3L22 4"/>
</svg>
<span style={{ fontSize: 12, color: T.tx3 }}>{med.forDisease}</span>
</div>
</div>
);
}
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="用药记录" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 24px' }}>
{/* 当前用药 */}
<div style={{ fontSize: 13, fontWeight: 600, color: T.tx3, marginBottom: 12, letterSpacing: '0.05em' }}>当前用药</div>
{currentMeds.map((med, i) => <MedCard key={i} med={med} />)}
{/* 分隔 */}
<div style={{ height: 24 }} />
{/* 历史用药 */}
<div style={{ fontSize: 13, fontWeight: 600, color: T.tx3, marginBottom: 12, letterSpacing: '0.05em' }}>历史用药</div>
{historyMeds.map((med, i) => <MedCard key={i} med={med} />)}
</div>
</div>
);
}
// ─── 屏幕4检查报告列表 ───
function ExamReportList() {
const reports = [
{ type: '血常规', date: '5月6日', abnormal: 2, tagBg: T.wrnL, tagColor: T.wrn, tagLabel: '2项异常' },
{ type: '肝功能', date: '5月6日', abnormal: 0, tagBg: T.accL, tagColor: T.acc, tagLabel: '全部正常' },
{ type: '肾功能', date: '5月6日', abnormal: 1, tagBg: T.wrnL, tagColor: T.wrn, tagLabel: '1项异常' },
{ type: '尿常规', date: '4月20日', abnormal: 0, tagBg: T.accL, tagColor: T.acc, tagLabel: '全部正常' },
];
const typeColors = {
'血常规': { bg: '#FDE8E8', color: '#C53030' },
'肝功能': { bg: '#E8F0E8', color: '#5B7A5E' },
'肾功能': { bg: '#FFF3E0', color: '#C4873A' },
'尿常规': { bg: '#E8E0F0', color: '#7A5B8A' },
};
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="检查报告" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 24px' }}>
{/* 筛选标签 */}
<div style={{ display: 'flex', gap: 8, marginBottom: 18, overflowX: 'auto' }}>
{['全部', '异常', '正常'].map((f, i) => (
<div key={i} style={{ padding: '6px 16px', borderRadius: 999, fontSize: 13, fontWeight: 500, background: i === 0 ? T.pri : T.card, color: i === 0 ? '#fff' : T.tx2, whiteSpace: 'nowrap', boxShadow: i === 0 ? 'none' : '0 1px 4px rgba(0,0,0,0.06)' }}>
{f}
</div>
))}
</div>
{reports.map((r, i) => {
const tc = typeColors[r.type] || { bg: T.surface, color: T.tx2 };
return (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12, boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
{/* 类型标签 */}
<div style={{ width: 48, height: 48, borderRadius: T.rSm, background: tc.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontSize: 13, fontWeight: 600, color: tc.color }}>{r.type.slice(0, 1)}</span>
</div>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }}>
<span style={{ fontSize: 15, fontWeight: 600, color: T.tx }}>{r.type}</span>
<Tag label={r.tagLabel} color={r.tagColor} bg={r.tagBg} />
</div>
<div style={{ fontSize: 12, color: T.tx3 }}>检查日期{r.date}</div>
</div>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M9 18l6-6-6-6"/>
</svg>
</div>
</div>
);
})}
</div>
</div>
);
}
// ─── 屏幕5报告详情血常规 ───
function ReportDetail() {
const header = {
type: '血常规',
date: '2026年5月6日 14:00',
org: 'HMS 健康管理中心',
};
const items = [
{ name: '白细胞', value: '6.8', unit: '×10⁹/L', range: '3.5-9.5', status: 'normal' },
{ name: '红细胞', value: '4.2', unit: '×10¹²/L', range: '4.3-5.8', status: 'low' },
{ name: '血红蛋白', value: '110', unit: 'g/L', range: '130-175', status: 'low' },
{ name: '血小板', value: '210', unit: '×10⁹/L', range: '125-350', status: 'normal' },
{ name: '中性粒细胞', value: '65', unit: '%', range: '40-75', status: 'normal' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="报告详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 24px' }}>
{/* 报告头部 */}
<div style={{ background: `linear-gradient(135deg, ${T.pri} 0%, ${T.priD} 100%)`, borderRadius: T.r, padding: '20px 22px', marginBottom: 20, color: '#fff', position: 'relative', overflow: 'hidden' }}>
<div style={{ position: 'absolute', top: -20, right: -20, width: 80, height: 80, borderRadius: 40, background: 'rgba(255,255,255,0.08)' }} />
<div style={{ fontFamily: T.serif, fontSize: 20, fontWeight: 700, marginBottom: 8 }}>{header.type}</div>
<div style={{ fontSize: 13, opacity: 0.85, marginBottom: 4 }}>{header.date}</div>
<div style={{ fontSize: 12, opacity: 0.7 }}>{header.org}</div>
</div>
{/* 异常提示 */}
<div style={{ background: T.wrnL, borderRadius: T.rSm, padding: '12px 16px', marginBottom: 18, display: 'flex', alignItems: 'center', gap: 8 }}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.wrn} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/>
<line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
</svg>
<span style={{ fontSize: 13, color: T.wrn, fontWeight: 500 }}>2 项指标偏低请关注</span>
</div>
{/* 指标列表 */}
<div style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
{/* 表头 */}
<div style={{ display: 'flex', padding: '12px 18px', borderBottom: `1px solid ${T.bdL}`, fontSize: 11, color: T.tx3, fontWeight: 600 }}>
<div style={{ flex: 1 }}>指标</div>
<div style={{ width: 52, textAlign: 'center' }}>结果</div>
<div style={{ width: 56, textAlign: 'center' }}>单位</div>
<div style={{ width: 64, textAlign: 'center' }}>参考范围</div>
<div style={{ width: 48, textAlign: 'center' }}>状态</div>
</div>
{items.map((item, i) => {
const isAbnormal = item.status !== 'normal';
return (
<div key={i} style={{
display: 'flex',
padding: '14px 18px',
alignItems: 'center',
borderBottom: i < items.length - 1 ? `1px solid ${T.bdL}` : 'none',
background: isAbnormal ? T.wrnL : 'transparent',
borderLeft: isAbnormal ? `3px solid ${T.wrn}` : '3px solid transparent',
}}>
<div style={{ flex: 1, fontSize: 13, fontWeight: 500, color: T.tx }}>{item.name}</div>
<div style={{ width: 52, textAlign: 'center', fontSize: 14, fontWeight: 600, color: isAbnormal ? T.wrn : T.tx }}>{item.value}</div>
<div style={{ width: 56, textAlign: 'center', fontSize: 11, color: T.tx3 }}>{item.unit}</div>
<div style={{ width: 64, textAlign: 'center', fontSize: 11, color: T.tx3 }}>{item.range}</div>
<div style={{ width: 48, textAlign: 'center' }}>
{isAbnormal ? (
<span style={{ fontSize: 11, color: T.wrn, fontWeight: 600 }}>偏低</span>
) : (
<span style={{ fontSize: 11, color: T.acc }}>正常</span>
)}
</div>
</div>
);
})}
</div>
{/* 底部按钮 */}
<div style={{ marginTop: 24 }}>
<div style={{ background: T.pri, borderRadius: T.rSm, padding: '14px 0', textAlign: 'center', color: '#fff', fontSize: 15, fontWeight: 600, boxShadow: `0 4px 16px rgba(196,98,58,0.3)` }}>
咨询医生
</div>
</div>
</div>
</div>
);
}
// ─── 组装 ───
function App() {
const screens = [
{ label: '1 · 健康记录列表', component: <HealthRecordList /> },
{ label: '2 · 诊断记录', component: <DiagnosisRecords /> },
{ label: '3 · 用药记录', component: <MedicationRecords /> },
{ label: '4 · 检查报告', component: <ExamReportList /> },
{ label: '5 · 报告详情', component: <ReportDetail /> },
];
return (
<div class="screens">
{screens.map((s, i) => (
<div class="screen-wrap" key={i}>
<IosFrame width={360} height={780}>{s.component}</IosFrame>
<div class="screen-label">{s.label}</div>
</div>
))}
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,313 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 透析管理 + 随访管理</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 900px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 32px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.screen-label { color: #888; font-size: 11px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 透析管理 + 随访管理</div>
<div class="note">温润东方风设计系统 — 个人中心透析与随访模块。4 个屏幕:透析记录列表、透析详情、随访列表、随访详情。</div>
<div id="root"></div>
<script type="text/babel">
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── iOS 设备框 ───
const FS = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 370, height = 800, time = '9:41', battery = 85 }) {
return (
<div style={FS.wrapper}>
<div style={{ ...FS.screen, width, height }}>
<div style={{ ...FS.statusBar, color: '#000' }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill="#000"/><path d="M3 7.5a7 7 0 0110 0" stroke="#000" strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke="#000" strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: '1.5px solid #000', borderRadius: 3, padding: 1, position: 'relative' }}><div style={{ width: `${battery}%`, height: '100%', background: '#000', borderRadius: 1 }} /></div>
</div>
</div>
<div style={FS.dynamicIsland} />
<div style={FS.content}>{children}</div>
<div style={FS.homeIndicator} />
</div>
</div>
);
}
// ─── 通用组件 ───
function NavBar({ title }) {
return (
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', borderBottom: `1px solid ${T.bdL}`, position: 'relative', padding: '0 16px', flexShrink: 0 }}>
<span style={{ position: 'absolute', left: 16, color: T.pri, fontSize: 22, fontFamily: T.serif, lineHeight: 1 }}></span>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
function Tag({ text, bg, color }) {
return <span style={{ display: 'inline-block', padding: '2px 10px', borderRadius: T.rXs, fontSize: 11, fontWeight: 600, background: bg, color }}>{text}</span>;
}
function InfoRow({ label, value }) {
return (
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '10px 0', borderBottom: `1px solid ${T.bdL}` }}>
<span style={{ fontSize: 13, color: T.tx3 }}>{label}</span>
<span style={{ fontSize: 13, color: T.tx, fontWeight: 500 }}>{value}</span>
</div>
);
}
function Card({ children, style }) {
return <div style={{ background: T.card, borderRadius: T.r, padding: 16, ...style }}>{children}</div>;
}
// ─── 屏幕1: 透析记录列表 ───
function DialysisList() {
const records = [
{ date: '5/8', day: '周四', mode: 'HD', time: '08:00-12:00', ultra: '2.3L', status: '已完成', sc: T.acc },
{ date: '5/5', day: '周一', mode: 'HD', time: '08:00-12:00', ultra: '2.1L', status: '已完成', sc: T.acc },
{ date: '5/3', day: '周六', mode: 'HDF', time: '08:00-12:30', ultra: '2.5L', status: '已完成', sc: T.acc },
];
return (
<div style={{ background: T.bg, minHeight: '100%', padding: '0 16px 16px' }}>
<NavBar title="透析记录" />
<div style={{ height: 12 }} />
{/* 月度筛选 */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 24, padding: '10px 0' }}>
<span style={{ fontSize: 16, color: T.tx3 }}></span>
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx }}>2026年5月</span>
<span style={{ fontSize: 16, color: T.tx3 }}></span>
</div>
<div style={{ height: 8 }} />
{/* 统计条 */}
<div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
{[['本月透析', '3次', T.priL, T.priD], ['累计透析', '156次', T.accL, T.acc], ['本月超滤', '6.9L', T.wrnL, T.wrn]].map(([l, v, bg, c]) => (
<div key={l} style={{ flex: 1, background: T.card, borderRadius: T.rSm, padding: '10px 0', textAlign: 'center' }}>
<div style={{ fontSize: 18, fontWeight: 700, color: c, fontFamily: T.serif }}>{v}</div>
<div style={{ fontSize: 10, color: T.tx3, marginTop: 2 }}>{l}</div>
</div>
))}
</div>
{records.map((r, i) => (
<Card key={i} style={{ marginBottom: 10 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<div style={{ width: 44, height: 44, borderRadius: T.rSm, background: T.priL, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ fontSize: 14, fontWeight: 700, color: T.priD, fontFamily: T.serif, lineHeight: 1 }}>{r.date.split('/')[1]}</span>
<span style={{ fontSize: 9, color: T.priD }}>5</span>
</div>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<span style={{ fontSize: 14, fontWeight: 600, color: T.tx }}>{r.day}</span>
<Tag text={r.mode} bg={r.mode === 'HDF' ? T.wrnL : T.priL} color={r.mode === 'HDF' ? T.wrn : T.priD} />
</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 3 }}>{r.time}</div>
</div>
</div>
<div style={{ textAlign: 'right' }}>
<Tag text={r.status} bg={T.accL} color={r.sc} />
<div style={{ fontSize: 11, color: T.tx3, marginTop: 4 }}>超滤 {r.ultra}</div>
</div>
</div>
</Card>
))}
</div>
);
}
// ─── 屏幕2: 透析详情 ───
function DialysisDetail() {
const grid = [
['透析时长', '4h'], ['血流量', '250ml/min'], ['超滤量', '2.3L'],
['透前体重', '67.3kg'], ['透后体重', '65.0kg'], ['静脉压', '150mmHg'],
];
return (
<div style={{ background: T.bg, minHeight: '100%', padding: '0 16px 16px' }}>
<NavBar title="透析详情" />
<div style={{ height: 12 }} />
{/* 状态卡片 */}
<Card style={{ marginBottom: 10 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontFamily: T.serif, fontSize: 20, fontWeight: 700, color: T.tx }}>5月8日 周四</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>HD 模式 · 08:00 - 12:00</div>
</div>
<Tag text="已完成" bg={T.accL} color={T.acc} />
</div>
</Card>
{/* 数据网格 */}
<Card style={{ marginBottom: 10 }}>
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 700, color: T.tx, marginBottom: 10 }}>透析参数</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8 }}>
{grid.map(([l, v]) => (
<div key={l} style={{ background: T.bg, borderRadius: T.rSm, padding: '10px 8px', textAlign: 'center' }}>
<div style={{ fontSize: 15, fontWeight: 700, color: T.pri, fontFamily: T.serif }}>{v}</div>
<div style={{ fontSize: 10, color: T.tx3, marginTop: 2 }}>{l}</div>
</div>
))}
</div>
</Card>
{/* 生命体征 */}
<Card style={{ marginBottom: 10 }}>
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 700, color: T.tx, marginBottom: 8 }}>生命体征</div>
{[['透前', '145/90', '82', T.wrnL, T.wrn], ['透后', '128/78', '75', T.accL, T.acc]].map(([label, bp, hr, bg, c]) => (
<div key={label} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 0', borderBottom: `1px solid ${T.bdL}` }}>
<span style={{ fontSize: 11, fontWeight: 600, color: c, background: bg, padding: '2px 8px', borderRadius: T.rXs }}>{label}</span>
<span style={{ fontSize: 13, color: T.tx2 }}>血压 <b style={{ color: T.tx }}>{bp}</b> mmHg</span>
<span style={{ fontSize: 13, color: T.tx2 }}>心率 <b style={{ color: T.tx }}>{hr}</b> bpm</span>
</div>
))}
</Card>
{/* 护士备注 */}
<Card>
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 700, color: T.tx, marginBottom: 6 }}>护士备注</div>
<div style={{ background: T.surface, borderRadius: T.rSm, padding: 12, fontSize: 13, color: T.tx2, lineHeight: 1.6 }}>
透析过程顺利患者无不适主诉超滤达标生命体征平稳
</div>
</Card>
</div>
);
}
// ─── 屏幕3: 随访列表 ───
function FollowUpList() {
const items = [
{ type: '门诊', typeBg: T.priL, typeC: T.priD, title: '肾功能复查', date: '5/12', status: '待完成', stBg: T.wrnL, stC: T.wrn },
{ type: '电话', typeBg: T.accL, typeC: T.acc, title: '血压控制随访', date: '5/8', status: '已完成', stBg: T.accL, stC: T.acc },
{ type: '门诊', typeBg: T.priL, typeC: T.priD, title: '血常规复查', date: '4/25', status: '已完成', stBg: T.accL, stC: T.acc },
];
return (
<div style={{ background: T.bg, minHeight: '100%', padding: '0 16px 16px' }}>
<NavBar title="我的随访" />
<div style={{ height: 12 }} />
{/* 状态筛选 */}
<div style={{ display: 'flex', gap: 8, marginBottom: 14 }}>
{['全部', '待完成', '已完成'].map((t, i) => (
<div key={t} style={{ padding: '6px 16px', borderRadius: 20, fontSize: 12, fontWeight: 600, background: i === 0 ? T.pri : T.card, color: i === 0 ? '#fff' : T.tx2, border: `1px solid ${i === 0 ? T.pri : T.bd}` }}>{t}</div>
))}
</div>
{items.map((it, i) => (
<Card key={i} style={{ marginBottom: 10 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
<Tag text={it.type + '随访'} bg={it.typeBg} color={it.typeC} />
<Tag text={it.status} bg={it.stBg} color={it.stC} />
</div>
<div style={{ fontSize: 15, fontWeight: 600, color: T.tx, marginBottom: 4 }}>{it.title}</div>
<div style={{ fontSize: 12, color: T.tx3 }}>计划日期{it.date}</div>
</div>
<span style={{ fontSize: 16, color: T.bd }}></span>
</div>
</Card>
))}
</div>
);
}
// ─── 屏幕4: 随访详情 ───
function FollowUpDetail() {
const checklist = [
{ done: true, text: '携带医保卡' },
{ done: false, text: '空腹8小时' },
{ done: false, text: '携带上次化验单' },
];
return (
<div style={{ background: T.bg, minHeight: '100%', padding: '0 16px 16px', display: 'flex', flexDirection: 'column' }}>
<NavBar title="随访详情" />
<div style={{ height: 12 }} />
{/* 状态 */}
<Card style={{ marginBottom: 10 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>肾功能复查</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>门诊随访</div>
</div>
<Tag text="待完成" bg={T.wrnL} color={T.wrn} />
</div>
</Card>
{/* 信息 */}
<Card style={{ marginBottom: 10 }}>
<InfoRow label="随访类型" value="门诊随访" />
<InfoRow label="计划日期" value="2026年5月12日" />
<InfoRow label="负责医生" value="王医生" />
<InfoRow label="随访内容" value="肾功能指标复查,评估透析效果" />
</Card>
{/* 准备清单 */}
<Card style={{ marginBottom: 16 }}>
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 700, color: T.tx, marginBottom: 10 }}>就诊准备清单</div>
{checklist.map((c, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 0', borderBottom: i < checklist.length - 1 ? `1px solid ${T.bdL}` : 'none' }}>
<div style={{ width: 20, height: 20, borderRadius: 6, border: `2px solid ${c.done ? T.acc : T.bd}`, background: c.done ? T.accL : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 12, color: c.done ? T.acc : 'transparent' }}>
{c.done ? '✓' : ''}
</div>
<span style={{ fontSize: 13, color: c.done ? T.tx2 : T.tx, textDecoration: c.done ? 'line-through' : 'none' }}>{c.text}</span>
</div>
))}
</Card>
{/* 底部按钮 */}
<div style={{ marginTop: 'auto', padding: '12px 0 8px' }}>
<div style={{ background: T.pri, color: '#fff', textAlign: 'center', padding: '14px 0', borderRadius: T.r, fontSize: 15, fontWeight: 600, fontFamily: T.sans, letterSpacing: 1 }}>
确认完成
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
const screens = [
{ label: '透析记录列表', el: <DialysisList />, w: 370, h: 800 },
{ label: '透析详情', el: <DialysisDetail />, w: 370, h: 800 },
{ label: '随访列表', el: <FollowUpList />, w: 370, h: 800 },
{ label: '随访详情', el: <FollowUpDetail />, w: 370, h: 800 },
];
return (
<div class="screens">
{screens.map((s) => (
<div class="screen-wrap" key={s.label}>
<IosFrame width={s.w} height={s.h}>{s.el}</IosFrame>
<div class="screen-label">{s.label}</div>
</div>
))}
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,481 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 个人中心其他</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 900px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 40px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 个人中心其他页面</div>
<div class="note">温润东方风设计系统 — 个人中心子页面原型。6 个屏幕:家庭管理 / 添加家庭成员 / 知情同意 / 事件记录 / 长者模式 / 设置。</div>
<div id="root"></div>
<script type="text/babel">
// ─── 设计 Token ───
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 340, height = 740, time = '9:41', battery = 85, darkStatus = false }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
// ─── 导航栏组件 ───
function NavBar({ title, dark = false }) {
const color = dark ? '#fff' : T.tx;
return (
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', borderBottom: `1px solid ${T.bdL}`, background: dark ? 'transparent' : T.card }}>
<svg style={{ position: 'absolute', left: 16, top: 12 }} width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color }}>{title}</span>
</div>
);
}
// ─── 右箭头图标 ───
function ArrowRight({ color = T.tx3 }) {
return <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>;
}
// ─── 开关组件 ───
function Toggle({ on = false, color = T.pri }) {
return (
<div style={{ width: 48, height: 28, borderRadius: 14, background: on ? color : '#D1D5DB', position: 'relative', transition: 'background 0.2s', flexShrink: 0 }}>
<div style={{ width: 24, height: 24, borderRadius: 12, background: '#fff', position: 'absolute', top: 2, left: on ? 22 : 2, boxShadow: '0 1px 3px rgba(0,0,0,0.15)', transition: 'left 0.2s' }} />
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 屏幕1家庭管理
// ═══════════════════════════════════════════════════════════════
function FamilyPage() {
const patients = [
{ name: '张三', relation: '本人', phone: '138****1234', isDefault: true, color: T.pri },
{ name: '张父', relation: '父亲', phone: '139****5678', isDefault: false, color: T.acc },
{ name: '张母', relation: '母亲', phone: '136****9012', isDefault: false, color: T.wrn },
];
return (
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
<NavBar title="就诊人管理" />
<div style={{ padding: '16px' }}>
{patients.map((p, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12, boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 12 }}>
{/* 头像 */}
<div style={{ width: 48, height: 48, borderRadius: 24, background: p.isDefault ? T.priL : T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontSize: 18, fontWeight: 700, color: p.isDefault ? T.priD : T.tx2, fontFamily: T.serif }}>{p.name[0]}</span>
</div>
{/* 信息 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
<span style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>{p.name}</span>
<span style={{ fontSize: 12, color: T.tx3, background: T.surface, padding: '2px 8px', borderRadius: 6 }}>{p.relation}</span>
{p.isDefault && (
<span style={{ fontSize: 11, color: T.priD, background: T.priL, padding: '2px 8px', borderRadius: 6, fontWeight: 600 }}>默认</span>
)}
</div>
<span style={{ fontSize: 13, color: T.tx3 }}>{p.phone}</span>
</div>
{/* 箭头 */}
<ArrowRight />
</div>
))}
{/* 添加就诊人按钮 */}
<div style={{ border: `2px dashed ${T.bd}`, borderRadius: T.r, padding: '16px 0', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, marginTop: 4, cursor: 'pointer' }}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={T.pri} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
<span style={{ fontSize: 15, color: T.pri, fontWeight: 500 }}>添加就诊人</span>
</div>
</div>
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 屏幕2添加家庭成员
// ═══════════════════════════════════════════════════════════════
function FamilyAddPage() {
const FieldStyle = { width: '100%', height: 56, background: T.card, border: `1.5px solid ${T.bd}`, borderRadius: T.r, padding: '0 16px', fontSize: 15, color: T.tx, outline: 'none', fontFamily: T.sans };
return (
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
<NavBar title="添加就诊人" />
<div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
{/* 姓名 */}
<div>
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>姓名</label>
<input style={FieldStyle} placeholder="请输入真实姓名" />
</div>
{/* 关系 */}
<div>
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>关系</label>
<div style={{ ...FieldStyle, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: T.tx3 }}>
<span>请选择关系</span>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
</div>
</div>
{/* 手机号 */}
<div>
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>手机号</label>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<div style={{ height: 56, background: T.surface, borderRadius: T.r, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '0 14px', fontSize: 14, color: T.tx, fontWeight: 600, flexShrink: 0, border: `1.5px solid ${T.bd}` }}>
+86
</div>
<input style={{ ...FieldStyle, flex: 1 }} placeholder="请输入手机号" type="tel" />
</div>
</div>
{/* 身份证号 */}
<div>
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>身份证号</label>
<input style={FieldStyle} placeholder="请输入身份证号" />
</div>
{/* 出生日期 */}
<div>
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>出生日期</label>
<div style={{ ...FieldStyle, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: T.tx3 }}>
<span>请选择出生日期</span>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
</div>
</div>
{/* 性别 */}
<div>
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>性别</label>
<div style={{ display: 'flex', gap: 12 }}>
{['男', '女'].map((g, i) => (
<div key={g} style={{ flex: 1, height: 56, borderRadius: T.r, border: i === 0 ? `2px solid ${T.pri}` : `1.5px solid ${T.bd}`, background: i === 0 ? T.priL : T.card, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, cursor: 'pointer' }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={i === 0 ? T.pri : T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
{i === 0 ? (<><circle cx="10.5" cy="10.5" r="7"/><line x1="16" y1="16" x2="21" y2="21"/></>) : (<><circle cx="12" cy="12" r="7"/><line x1="8" y1="8" x2="16" y2="16"/></>)}
</svg>
<span style={{ fontSize: 15, fontWeight: 600, color: i === 0 ? T.pri : T.tx2 }}>{g}</span>
</div>
))}
</div>
</div>
{/* 保存按钮 */}
<div style={{ marginTop: 10 }}>
<div style={{ height: 56, borderRadius: T.r, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `0 4px 16px rgba(196,98,58,0.3)`, cursor: 'pointer' }}>
<span style={{ fontSize: 17, fontWeight: 600, color: '#fff' }}>保存</span>
</div>
</div>
</div>
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 屏幕3知情同意
// ═══════════════════════════════════════════════════════════════
function ConsentsPage() {
const consents = [
{ title: '血液透析知情同意书', date: '2025-04-01', status: 'signed', icon: 'blood' },
{ title: '透析血管通路知情同意书', date: '2025-04-01', status: 'signed', icon: 'vein' },
{ title: '数据共享知情同意书', date: '', status: 'pending', icon: 'data' },
];
return (
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
<NavBar title="知情同意书" />
<div style={{ padding: 16 }}>
{consents.map((c, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12, boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 12 }}>
{/* 图标 */}
<div style={{ width: 44, height: 44, borderRadius: T.rSm, background: c.status === 'signed' ? T.accL : T.wrnL, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={c.status === 'signed' ? T.acc : T.wrn} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/>
</svg>
</div>
{/* 信息 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 4, lineHeight: 1.4 }}>{c.title}</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
{c.date && <span style={{ fontSize: 12, color: T.tx3 }}>{c.date}</span>}
<span style={{ fontSize: 11, fontWeight: 600, color: c.status === 'signed' ? T.acc : T.wrn, background: c.status === 'signed' ? T.accL : T.wrnL, padding: '2px 8px', borderRadius: 6 }}>
{c.status === 'signed' ? '已签署' : '待签署'}
</span>
</div>
</div>
<ArrowRight />
</div>
))}
{/* 底部提示 */}
<div style={{ textAlign: 'center', marginTop: 20, padding: '0 20px' }}>
<p style={{ fontSize: 12, color: T.tx3, lineHeight: 1.8 }}>签署后的同意书具有法律效力请仔细阅读后再签署</p>
</div>
</div>
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 屏幕4事件记录
// ═══════════════════════════════════════════════════════════════
function EventsPage() {
const events = [
{ date: '5月8日', desc: '开始透析治疗', color: T.pri, bg: T.priL, type: '治疗' },
{ date: '4月15日', desc: '调整透析方案', color: T.acc, bg: T.accL, type: '方案' },
{ date: '3月20日', desc: '完成血管通路手术', color: T.wrn, bg: T.wrnL, type: '手术' },
{ date: '2月10日', desc: '首次门诊', color: T.pri, bg: T.priL, type: '门诊' },
{ date: '2024-12-01', desc: '确诊慢性肾病', color: T.dan, bg: T.danL, type: '诊断' },
];
return (
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
<NavBar title="事件记录" />
<div style={{ padding: '16px 16px 16px 24px' }}>
{/* 时间线 */}
<div style={{ position: 'relative' }}>
{/* 竖线 */}
<div style={{ position: 'absolute', left: 7, top: 12, bottom: 12, width: 2, background: T.bdL, borderRadius: 1 }} />
{events.map((e, i) => (
<div key={i} style={{ position: 'relative', paddingLeft: 28, marginBottom: i < events.length - 1 ? 20 : 0 }}>
{/* 圆点 */}
<div style={{ position: 'absolute', left: 0, top: 6, width: 16, height: 16, borderRadius: 8, background: e.color, border: `3px solid ${e.bg}`, boxShadow: `0 0 0 2px ${e.bg}`, zIndex: 1 }} />
{/* 事件卡片 */}
<div style={{ background: T.card, borderRadius: T.rSm, padding: 14, boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
<span style={{ fontSize: 13, color: T.tx3, fontWeight: 500 }}>{e.date}</span>
<span style={{ fontSize: 11, color: e.color, background: e.bg, padding: '2px 8px', borderRadius: 6, fontWeight: 600 }}>{e.type}</span>
</div>
<div style={{ fontSize: 15, fontWeight: 600, color: T.tx, lineHeight: 1.4 }}>{e.desc}</div>
</div>
</div>
))}
</div>
</div>
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 屏幕5长者模式
// ═══════════════════════════════════════════════════════════════
function ElderModePage() {
return (
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
<NavBar title="关怀模式" />
<div style={{ padding: 16 }}>
{/* 说明区域 */}
<div style={{ background: T.accL, borderLeft: `4px solid ${T.acc}`, borderRadius: '0 T.rSm T.rSm 0', padding: '14px 16px', marginBottom: 20 }}>
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={T.acc} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 1 }}>
<circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/>
</svg>
<span style={{ fontSize: 13, color: T.acc, lineHeight: 1.7, fontWeight: 500 }}>开启关怀模式后字体将放大界面更简洁方便阅读</span>
</div>
</div>
{/* 模式开关卡片 */}
<div style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 16, boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ width: 40, height: 40, borderRadius: 12, background: T.priL, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={T.pri} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
</div>
<div>
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>关怀模式</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>放大字号简化界面</div>
</div>
</div>
<Toggle on={true} color={T.pri} />
</div>
{/* 字号预览 */}
<div style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 16, boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 12, fontWeight: 500 }}>字号预览</div>
{/* 标准字号 */}
<div style={{ marginBottom: 14 }}>
<span style={{ fontSize: 11, color: T.tx3, display: 'block', marginBottom: 4 }}>标准</span>
<div style={{ background: T.surface, borderRadius: T.rXs, padding: '10px 14px' }}>
<span style={{ fontSize: 15, color: T.tx }}>血压 130/85 mmHg</span>
</div>
</div>
{/* 放大字号 */}
<div>
<span style={{ fontSize: 11, color: T.pri, display: 'block', marginBottom: 4, fontWeight: 600 }}>关怀模式</span>
<div style={{ background: T.priL, borderRadius: T.rXs, padding: '12px 14px' }}>
<span style={{ fontSize: 22, color: T.priD, fontWeight: 600 }}>血压 130/85 mmHg</span>
</div>
</div>
</div>
{/* 其他设置 */}
<div style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
{/* 高对比度 */}
<div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: `1px solid ${T.bdL}` }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ width: 36, height: 36, borderRadius: 10, background: T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx2} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a10 10 0 000 20z"/></svg>
</div>
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500 }}>高对比度模式</span>
</div>
<Toggle on={false} />
</div>
{/* 语音播报 */}
<div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ width: 36, height: 36, borderRadius: 10, background: T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx2} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07"/></svg>
</div>
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500 }}>语音播报</span>
</div>
<Toggle on={false} />
</div>
</div>
</div>
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 屏幕6设置
// ═══════════════════════════════════════════════════════════════
function SettingsPage() {
const settingsGroups = [
[
{ icon: 'shield', iconBg: T.acc, label: '账号与安全', value: '' },
{ icon: 'bell', iconBg: T.wrn, label: '消息通知', value: '' },
{ icon: 'eye', iconBg: T.pri, label: '隐私设置', value: '' },
],
[
{ icon: 'globe', iconBg: '#6B8ABF', label: '语言', value: '简体中文' },
{ icon: 'trash', iconBg: T.tx3, label: '清除缓存', value: '12.3 MB' },
{ icon: 'info', iconBg: T.tx2, label: '关于 HMS', value: '' },
],
];
const iconPaths = {
shield: <><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></>,
bell: <><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></>,
eye: <><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"/></>,
globe: <><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></>,
trash: <><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></>,
info: <><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></>,
};
return (
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
<NavBar title="设置" />
<div style={{ padding: 16 }}>
{settingsGroups.map((group, gi) => (
<div key={gi} style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', marginBottom: 16, boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
{group.map((item, ii) => (
<div key={ii} style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: ii < group.length - 1 ? `1px solid ${T.bdL}` : 'none' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ width: 34, height: 34, borderRadius: 10, background: item.iconBg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">{iconPaths[item.icon]}</svg>
</div>
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500 }}>{item.label}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
{item.value && <span style={{ fontSize: 13, color: T.tx3 }}>{item.value}</span>}
<ArrowRight />
</div>
</div>
))}
</div>
))}
{/* 版本号 + 退出登录 */}
<div style={{ textAlign: 'center', marginTop: 20 }}>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 16 }}>v1.0.0</div>
<div style={{ height: 48, borderRadius: T.r, border: `1.5px solid ${T.dan}`, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
<span style={{ fontSize: 15, fontWeight: 600, color: T.dan }}>退出登录</span>
</div>
</div>
</div>
</div>
);
}
// ═══════════════════════════════════════════════════════════════
// 主渲染
// ═══════════════════════════════════════════════════════════════
function App() {
const screens = [
{ label: '家庭管理', component: <FamilyPage /> },
{ label: '添加家庭成员', component: <FamilyAddPage /> },
{ label: '知情同意', component: <ConsentsPage /> },
{ label: '事件记录', component: <EventsPage /> },
{ label: '长者模式', component: <ElderModePage /> },
{ label: '设置', component: <SettingsPage /> },
];
return (
<div className="screens">
{screens.map((s, i) => (
<div key={i} className="screen-wrap">
<IosFrame width={340} height={740}>
{s.component}
</IosFrame>
<div className="screen-label">{s.label}</div>
</div>
))}
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,211 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 积分商城分包</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#1a1a1a;font-family:-apple-system,'PingFang SC',sans-serif;display:flex;flex-direction:column;align-items:center;padding:40px 20px;gap:24px}
.page-title{color:#999;font-size:13px;letter-spacing:.15em;text-transform:uppercase}
.note{color:#666;font-size:12px;max-width:800px;text-align:center;line-height:1.8}
.screens{display:flex;gap:32px;flex-wrap:wrap;justify-content:center;align-items:flex-start}
.screen-wrap{display:flex;flex-direction:column;align-items:center;gap:10px}
.screen-label{color:#888;font-size:11px;font-style:italic}
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 积分商城分包</div>
<div class="note">商品详情 + 兑换确认 + 订单列表 + 咨询聊天详情</div>
<div id="root"></div>
<script type="text/babel">
const T={pri:'#C4623A',priL:'#F0DDD4',priD:'#8B3E1F',bg:'#F5F0EB',card:'#FFFFFF',surface:'#EDE8E2',tx:'#2D2A26',tx2:'#5A554F',tx3:'#78716C',bd:'#E8E2DC',bdL:'#F0EBE5',acc:'#5B7A5E',accL:'#E8F0E8',wrn:'#C4873A',wrnL:'#FFF3E0',dan:'#B54A4A',danL:'#FDEAEA',serif:"Georgia,'Times New Roman',serif",sans:"-apple-system,'PingFang SC',sans-serif",r:16,rSm:12,rXs:8};
const F={w:{display:'inline-block',padding:12,background:'#000',borderRadius:60,boxShadow:'0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)',position:'relative'},s:{position:'relative',borderRadius:48,overflow:'hidden',background:'#fff'},c:{position:'absolute',top:54,left:0,right:0,bottom:34,overflow:'auto'}};
function Frame({children,w=370,h=800}){
return(<div style={F.w}><div style={{...F.s,width:w,height:h}}>
<div style={{position:'absolute',top:0,left:0,right:0,height:54,display:'flex',alignItems:'center',justifyContent:'space-between',padding:'0 32px',fontSize:16,fontWeight:600,zIndex:20,pointerEvents:'none',color:'#000'}}>
<span>9:41</span>
<div style={{display:'flex',alignItems:'center',gap:6}}><div style={{width:26,height:12,border:'1.5px solid #000',borderRadius:3,padding:1}}><div style={{width:'85%',height:'100%',background:'#000',borderRadius:1}}/></div></div>
</div>
<div style={{position:'absolute',top:12,left:'50%',transform:'translateX(-50%)',width:124,height:36,background:'#000',borderRadius:999,zIndex:30}}/>
<div style={F.c}>{children}</div>
<div style={{position:'absolute',bottom:10,left:'50%',transform:'translateX(-50%)',width:140,height:5,background:'rgba(0,0,0,0.3)',borderRadius:999,zIndex:10}}/>
</div></div>);
}
function Nav({t}){
return(<div style={{height:44,display:'flex',alignItems:'center',justifyContent:'center',borderBottom:`1px solid ${T.bdL}`,position:'relative'}}>
<span style={{position:'absolute',left:16,color:T.pri,fontSize:20}}></span>
<span style={{fontFamily:T.serif,fontSize:18,fontWeight:700,color:T.tx}}>{t}</span>
</div>);
}
function Tag({label,color=T.acc,bg=T.accL}){
return <span style={{display:'inline-block',padding:'2px 8px',borderRadius:6,fontSize:11,fontWeight:600,color,background:bg}}>{label}</span>;
}
// ── 屏幕1: 商品详情 ──
function ProductDetail(){
return(<div style={{background:T.bg,fontFamily:T.sans}}>
<Nav t="商品详情"/>
<div style={{background:T.surface,height:280,display:'flex',alignItems:'center',justifyContent:'center'}}>
<div style={{width:180,height:180,borderRadius:T.r,background:T.bd,display:'flex',alignItems:'center',justifyContent:'center',flexDirection:'column',gap:8}}>
<div style={{fontSize:36,opacity:.3}}>🩺</div>
<span style={{fontSize:12,color:T.tx3}}>智能血压计</span>
</div>
</div>
<div style={{padding:20,background:T.card,borderRadius:'20px 20px 0 0',marginTop:-16,position:'relative'}}>
<div style={{fontFamily:T.serif,fontSize:20,fontWeight:700,color:T.tx,marginBottom:8}}>智能血压计</div>
<div style={{display:'flex',alignItems:'baseline',gap:10,marginBottom:16}}>
<span style={{fontFamily:T.serif,fontSize:24,fontWeight:700,color:T.pri}}>1,200 积分</span>
<span style={{fontSize:14,color:T.tx3,textDecoration:'line-through'}}>¥199</span>
</div>
<div style={{fontSize:13,color:T.tx2,lineHeight:1.8,marginBottom:20}}>医用级精度蓝牙连接手机自动记录数据支持多人使用大屏显示操作简便适合家庭日常监测</div>
<div style={{display:'flex',flexDirection:'column',gap:10,padding:'14px 16px',background:T.bg,borderRadius:T.rSm,marginBottom:16}}>
{[['品牌','乐心'],['规格','臂式'],['库存','36件']].map(([k,v])=>(
<div key={k} style={{display:'flex',justifyContent:'space-between',fontSize:13}}><span style={{color:T.tx3}}>{k}</span><span style={{color:T.tx,fontWeight:500}}>{v}</span></div>
))}
</div>
<div style={{padding:12,background:T.wrnL,borderRadius:T.rSm,borderLeft:`3px solid ${T.wrn}`}}>
<div style={{fontSize:12,color:T.wrn,fontWeight:600,marginBottom:4}}>温馨提示</div>
<div style={{fontSize:11,color:T.tx2,lineHeight:1.6}}>积分兑换商品不支持退换货请确认需求后再兑换商品将在 7 个工作日内寄出</div>
</div>
</div>
<div style={{position:'sticky',bottom:0,background:T.card,borderTop:`1px solid ${T.bdL}`,padding:'12px 20px',display:'flex',alignItems:'center',gap:12}}>
<div style={{width:48,height:48,border:`1px solid ${T.bd}`,borderRadius:T.rSm,display:'flex',alignItems:'center',justifyContent:'center',fontSize:20}}></div>
<div style={{flex:1,height:48,background:T.pri,borderRadius:T.r,display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontFamily:T.serif,fontSize:16,fontWeight:700}}>立即兑换</div>
</div>
</div>);
}
// ── 屏幕2: 兑换确认 ──
function ExchangeConfirm(){
return(<div style={{background:T.bg,fontFamily:T.sans}}>
<Nav t="确认兑换"/>
<div style={{padding:16}}>
<div style={{display:'flex',gap:12,padding:14,background:T.card,borderRadius:T.r,marginBottom:16,boxShadow:'0 1px 4px rgba(0,0,0,0.04)'}}>
<div style={{width:72,height:72,borderRadius:T.rSm,background:T.surface,display:'flex',alignItems:'center',justifyContent:'center',fontSize:24}}>🩺</div>
<div style={{flex:1}}>
<div style={{fontFamily:T.serif,fontSize:15,fontWeight:700,color:T.tx,marginBottom:4}}>智能血压计</div>
<div style={{fontSize:13,color:T.pri,fontWeight:600}}>1,200 积分</div>
<div style={{fontSize:11,color:T.tx3,marginTop:2}}>×1</div>
</div>
</div>
<div style={{padding:16,background:T.card,borderRadius:T.r,marginBottom:16}}>
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}}>
<span style={{fontSize:14,fontWeight:600,color:T.tx}}>收货信息</span>
<span style={{fontSize:12,color:T.pri,fontWeight:500}}>修改地址 </span>
</div>
<div style={{fontSize:13,color:T.tx,fontWeight:500,marginBottom:2}}>张三 · 138****1234</div>
<div style={{fontSize:12,color:T.tx3,lineHeight:1.5}}>北京市朝阳区建国路88号健康大厦12层</div>
</div>
<div style={{padding:16,background:T.card,borderRadius:T.r,marginBottom:24}}>
<div style={{fontSize:14,fontWeight:600,color:T.tx,marginBottom:12}}>兑换明细</div>
{[['商品积分','1,200'],['运费','¥0.00'],['应扣积分','1,200'],['剩余积分','80']].map(([k,v],i)=>(
<div key={k} style={{display:'flex',justifyContent:'space-between',paddingBottom:i<3?8:0,marginBottom:i<3?8:0,borderBottom:i<3?`1px dashed ${T.bdL}`:'none'}}>
<span style={{fontSize:13,color:T.tx3}}>{k}</span>
<span style={{fontSize:13,color:i===2?T.pri:i===3?T.acc:T.tx,fontWeight:i>=2?600:400}}>{v}</span>
</div>
))}
</div>
<div style={{height:50,background:T.pri,borderRadius:T.r,display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontFamily:T.serif,fontSize:16,fontWeight:700}}>确认兑换</div>
</div>
</div>);
}
// ── 屏幕3: 订单列表 ──
function OrderList(){
const tabs=['全部','待发货','已发货','已完成'];
const orders=[
{id:'HX20260515001',name:'智能血压计',pts:'1,200',status:'待发货',statusBg:T.wrnL,statusColor:T.wrn,date:'2026-05-15'},
{id:'HX20260510002',name:'维生素D3 60粒',pts:'360',status:'已发货',statusBg:T.accL,statusColor:T.acc,date:'2026-05-10'},
{id:'HX20260428003',name:'健康手册',pts:'150',status:'已完成',statusBg:T.bg,statusColor:T.tx3,date:'2026-04-28'},
];
return(<div style={{background:T.bg,fontFamily:T.sans}}>
<Nav t="兑换记录"/>
<div style={{display:'flex',padding:'0 16px',gap:0,background:T.card,borderBottom:`1px solid ${T.bdL}`}}>
{tabs.map((t,i)=>(
<div key={t} style={{flex:1,textAlign:'center',padding:'12px 0',fontSize:13,fontWeight:i===0?600:400,color:i===0?T.pri:T.tx3,borderBottom:i===0?`2px solid ${T.pri}`:'2px solid transparent'}}>{t}</div>
))}
</div>
<div style={{padding:16,display:'flex',flexDirection:'column',gap:12}}>
{orders.map(o=>(
<div key={o.id} style={{padding:16,background:T.card,borderRadius:T.r,boxShadow:'0 1px 4px rgba(0,0,0,0.04)'}}>
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}}>
<span style={{fontSize:11,color:T.tx3}}>订单号 {o.id}</span>
<Tag label={o.status} color={o.statusColor} bg={o.statusBg}/>
</div>
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
<div>
<div style={{fontSize:14,fontWeight:600,color:T.tx,marginBottom:2}}>{o.name}</div>
<div style={{fontSize:12,color:T.tx3}}>{o.date}</div>
</div>
<div style={{fontFamily:T.serif,fontSize:16,fontWeight:700,color:T.pri}}>{o.pts} <span style={{fontSize:11,fontWeight:400}}>积分</span></div>
</div>
</div>
))}
</div>
</div>);
}
// ── 屏幕4: 咨询聊天详情 ──
function ChatDetail(){
const Bubble=({left,children})=>(
<div style={{display:'flex',justifyContent:left?'flex-start':'flex-end',padding:'0 16px',marginBottom:10}}>
<div style={{maxWidth:'75%',padding:'10px 14px',borderRadius:left?'4px 16px 16px 16px':'16px 4px 16px 16px',background:left?T.card:T.priL,color:T.tx,fontSize:13,lineHeight:1.6}}>{children}</div>
</div>
);
return(<div style={{background:T.bg,fontFamily:T.sans,height:'100%',display:'flex',flexDirection:'column'}}>
<div style={{height:44,display:'flex',alignItems:'center',justifyContent:'center',borderBottom:`1px solid ${T.bdL}`,position:'relative',background:T.card}}>
<span style={{position:'absolute',left:16,color:T.pri,fontSize:20}}></span>
<div style={{display:'flex',alignItems:'center',gap:8}}>
<span style={{fontFamily:T.serif,fontSize:16,fontWeight:700,color:T.tx}}>王医生 · 心内科</span>
<div style={{width:8,height:8,background:T.acc,borderRadius:'50%'}}/>
</div>
</div>
<div style={{flex:1,overflow:'auto',padding:'16px 0'}}>
<div style={{textAlign:'center',fontSize:11,color:T.tx3,marginBottom:16}}>今天 10:32</div>
<Bubble left>化验结果已出您的血红蛋白偏低95g/L属于轻度贫血</Bubble>
<Bubble left={false}>需要怎么处理呢严重吗</Bubble>
<Bubble left>不算严重建议补充铁剂配合维生素C促进吸收我给您开个处方</Bubble>
<div style={{padding:'0 16px',marginBottom:10}}>
<div style={{padding:14,background:T.card,borderRadius:T.r,borderLeft:`3px solid ${T.acc}`}}>
<div style={{fontSize:12,color:T.acc,fontWeight:600,marginBottom:6}}>处方建议</div>
<div style={{fontSize:14,fontWeight:600,color:T.tx,marginBottom:4}}>硫酸亚铁片</div>
<div style={{fontSize:12,color:T.tx2,lineHeight:1.5}}>用法每次1片每日3次饭后服用</div>
<div style={{fontSize:11,color:T.tx3,marginTop:6}}>疗程4周后复查血常规</div>
</div>
</div>
<Bubble left={false}>好的谢谢王医生</Bubble>
</div>
<div style={{padding:'10px 16px',background:T.card,borderTop:`1px solid ${T.bdL}`,display:'flex',alignItems:'center',gap:10}}>
<div style={{flex:1,height:40,background:T.bg,borderRadius:20,padding:'0 16px',display:'flex',alignItems:'center',fontSize:13,color:T.tx3}}>输入消息</div>
<div style={{width:40,height:40,background:T.pri,borderRadius:20,display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontSize:16}}></div>
</div>
</div>);
}
// ── 渲染 ──
const screens=[
{label:'1 · 商品详情',el:<ProductDetail/>},
{label:'2 · 兑换确认',el:<ExchangeConfirm/>},
{label:'3 · 订单列表',el:<OrderList/>},
{label:'4 · 咨询聊天详情',el:<ChatDetail/>},
];
ReactDOM.createRoot(document.getElementById('root')).render(
<div class="screens">
{screens.map((s,i)=>(
<div class="screen-wrap" key={i}>
<Frame w={370} h={800}>{s.el}</Frame>
<div class="screen-label">{s.label}</div>
</div>
))}
</div>
);
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 KiB

View File

@@ -0,0 +1,481 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 医生端</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 1100px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 32px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
::-webkit-scrollbar { width: 0; height: 0; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 医生端核心页面</div>
<div class="note">温润东方风设计系统 — 医生端变体深靛蓝主色替代暖橙。5 个屏幕:医生工作台、待办收件箱、在线咨询、随访管理、患者管理。专业而温暖的医疗工作界面。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 360, height = 780, time = '9:41', battery = 85, darkStatus = false, label }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div className="screen-wrap">
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
{label && <div className="screen-label">{label}</div>}
</div>
);
}
// ─── 设计 Token — 医生端变体 ───
const T = {
pri: '#3A6B8C', priL: '#D4E5F0', priD: '#2A4F6A',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用组件 ───
function NavBar({ title }) {
return (
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', background: T.bg, borderBottom: `1px solid ${T.bdL}`, flexShrink: 0 }}>
<svg style={{ position: 'absolute', left: 16 }} width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.tx} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M15 18l-6-6 6-6"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
function Tag({ children, color, bg, fontSize = 11 }) {
return (
<span style={{ display: 'inline-block', padding: '2px 8px', borderRadius: 6, fontSize, fontWeight: 600, color, background: bg, lineHeight: 1.6 }}>{children}</span>
);
}
function BottomTabBar({ tabs, active }) {
const icons = {
'工作台': (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/>
</svg>
),
'患者': (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/>
</svg>
),
'消息': (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/>
</svg>
),
'我的': (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/>
</svg>
),
};
return (
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 70, background: T.card, borderTop: `1px solid ${T.bdL}`, display: 'flex', alignItems: 'flex-start', justifyContent: 'space-around', paddingTop: 8, paddingBottom: 28, zIndex: 10 }}>
{tabs.map((tab) => {
const isActive = tab === active;
return (
<div key={tab} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3 }}>
<div style={{ color: isActive ? T.pri : T.tx3, display: 'flex' }}>{icons[tab]}</div>
<span style={{ fontSize: 11, fontWeight: isActive ? 600 : 400, color: isActive ? T.pri : T.tx3 }}>{tab}</span>
</div>
);
})}
</div>
);
}
// ─── 图标组件 ───
function IconPatient() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.pri} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 11h-6"/>
</svg>
);
}
function IconConsult() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.acc} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/>
</svg>
);
}
function IconFollowUp() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.wrn} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>
</svg>
);
}
function IconDialysis() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.dan} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/>
</svg>
);
}
// ─── 屏幕1医生工作台 ───
function DoctorHome() {
const stats = [
{ label: '待处理', value: '12', color: T.wrn },
{ label: '咨询中', value: '3', color: T.pri },
{ label: '今日患者', value: '8', color: T.acc },
{ label: '随访到期', value: '5', color: T.dan },
];
const shortcuts = [
{ icon: <IconPatient />, label: '患者管理', bg: T.priL },
{ icon: <IconConsult />, label: '在线咨询', bg: T.accL },
{ icon: <IconFollowUp />, label: '随访管理', bg: T.wrnL },
{ icon: <IconDialysis />, label: '透析管理', bg: T.danL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
{/* 问候区 */}
<div style={{ padding: '16px 20px 0' }}>
<div style={{ fontFamily: T.serif, fontSize: 26, fontWeight: 700, color: T.tx, marginBottom: 4 }}>工作台</div>
<div style={{ fontSize: 14, color: T.tx3 }}>2026年5月16日 星期六</div>
</div>
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 80px' }}>
{/* 今日概览 */}
<div style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 16, boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
<div style={{ fontSize: 13, fontWeight: 600, color: T.tx2, marginBottom: 14, fontFamily: T.sans }}>今日概览</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
{stats.map((s) => (
<div key={s.label} style={{ background: T.bg, borderRadius: T.rSm, padding: '14px 12px', textAlign: 'center' }}>
<div style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: s.color, lineHeight: 1.1 }}>{s.value}</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 4 }}>{s.label}</div>
</div>
))}
</div>
</div>
{/* 快捷操作 */}
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
{shortcuts.map((s) => (
<div key={s.label} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
<div style={{ width: 52, height: 52, borderRadius: 26, background: s.bg, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
{s.icon}
</div>
<span style={{ fontSize: 12, color: T.tx2 }}>{s.label}</span>
</div>
))}
</div>
{/* 待办提醒 */}
<div style={{ fontSize: 13, fontWeight: 600, color: T.tx2, marginBottom: 10, fontFamily: T.sans }}>待办提醒</div>
<div style={{ background: T.priL, borderRadius: T.r, padding: '14px 16px', marginBottom: 10, borderLeft: `4px solid ${T.pri}` }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill={T.pri}><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
<div>
<div style={{ fontSize: 14, fontWeight: 500, color: T.tx }}>3 位患者血压异常待处理</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>需要立即关注</div>
</div>
</div>
</div>
<div style={{ background: T.wrnL, borderRadius: T.r, padding: '14px 16px', borderLeft: `4px solid ${T.wrn}` }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill={T.wrn}><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
<div>
<div style={{ fontSize: 14, fontWeight: 500, color: T.tx }}>2 份随访报告待审核</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>截止今日 18:00</div>
</div>
</div>
</div>
</div>
<BottomTabBar tabs={['工作台', '患者', '消息', '我的']} active="工作台" />
</div>
);
}
// ─── 屏幕2待办收件箱 ───
function ActionInbox() {
const filterTabs = ['全部', '异常', '随访', '咨询'];
const todos = [
{ type: '异常', typeColor: T.dan, typeBg: T.danL, patient: '张三', desc: '收缩压 158mmHg', time: '10分钟前', urgent: true },
{ type: '随访', typeColor: T.acc, typeBg: T.accL, patient: '李四', desc: '肾功能复查到期', time: '昨天', urgent: false },
{ type: '咨询', typeColor: T.pri, typeBg: T.priL, patient: '王五', desc: '咨询透析方案', time: '昨天', urgent: false },
{ type: '异常', typeColor: T.dan, typeBg: T.danL, patient: '赵六', desc: '血糖 15.2mmol/L', time: '2天前', urgent: true },
{ type: '随访', typeColor: T.acc, typeBg: T.accL, patient: '钱七', desc: '透析处方到期', time: '3天前', urgent: false },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="待办事项" />
{/* 筛选标签 */}
<div style={{ display: 'flex', gap: 8, padding: '12px 20px', flexShrink: 0 }}>
{filterTabs.map((tab, i) => (
<div key={tab} style={{
padding: '6px 16px', borderRadius: 20, fontSize: 13, fontWeight: i === 0 ? 600 : 400,
background: i === 0 ? T.pri : T.card, color: i === 0 ? '#fff' : T.tx2,
border: `1px solid ${i === 0 ? T.pri : T.bd}`, cursor: 'pointer',
}}>{tab}</div>
))}
</div>
{/* 待办列表 */}
<div style={{ flex: 1, overflow: 'auto', padding: '0 20px 20px' }}>
{todos.map((todo, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: '14px 16px', marginBottom: 10, boxShadow: '0 1px 8px rgba(0,0,0,0.03)', display: 'flex', alignItems: 'center', gap: 12 }}>
{/* 类型标签 */}
<Tag color={todo.typeColor} bg={todo.typeBg} fontSize={11}>{todo.type}</Tag>
{/* 内容 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<span style={{ fontSize: 15, fontWeight: 600, color: T.tx }}>{todo.patient}</span>
{todo.urgent && <Tag color="#fff" bg={T.dan} fontSize={10}>紧急</Tag>}
</div>
<div style={{ fontSize: 13, color: T.tx2, marginTop: 3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{todo.desc}</div>
</div>
{/* 时间 */}
<div style={{ fontSize: 11, color: T.tx3, flexShrink: 0, textAlign: 'right', minWidth: 52 }}>
<div>{todo.time}</div>
</div>
{/* 箭头 */}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
<path d="M9 18l6-6-6-6"/>
</svg>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕3在线咨询列表 ───
function ConsultList() {
const statusTabs = ['进行中', '已结束'];
const consults = [
{ name: '张三', msg: '好的,谢谢医生', time: '10分钟前', unread: 1, avatar: '张', avatarBg: T.priL },
{ name: '王五', msg: '透析方案已调整', time: '1小时前', unread: 0, avatar: '王', avatarBg: T.accL },
{ name: '赵六', msg: '血糖控制情况如何', time: '昨天', unread: 3, avatar: '赵', avatarBg: T.wrnL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="在线咨询" />
{/* 状态 Tab */}
<div style={{ display: 'flex', gap: 0, padding: '12px 20px 0', flexShrink: 0 }}>
{statusTabs.map((tab, i) => (
<div key={tab} style={{
flex: 1, textAlign: 'center', padding: '10px 0', fontSize: 14, fontWeight: i === 0 ? 600 : 400,
color: i === 0 ? T.pri : T.tx3,
borderBottom: i === 0 ? `2.5px solid ${T.pri}` : `1.5px solid ${T.bdL}`,
}}>{tab}</div>
))}
</div>
{/* 咨询列表 */}
<div style={{ flex: 1, overflow: 'auto', padding: '12px 20px 20px' }}>
{consults.map((c, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: '14px 16px', marginBottom: 10, boxShadow: '0 1px 8px rgba(0,0,0,0.03)', display: 'flex', alignItems: 'center', gap: 12 }}>
{/* 头像 */}
<div style={{ width: 44, height: 44, borderRadius: 22, background: c.avatarBg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.pri }}>{c.avatar}</span>
</div>
{/* 内容 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontSize: 15, fontWeight: 600, color: T.tx }}>{c.name}</span>
<span style={{ fontSize: 12, color: T.tx3 }}>{c.time}</span>
</div>
<div style={{ fontSize: 13, color: T.tx2, marginTop: 4, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{c.msg}</div>
</div>
{/* 未读 */}
{c.unread > 0 && (
<div style={{ minWidth: 20, height: 20, borderRadius: 10, background: T.dan, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontSize: 11, fontWeight: 700, color: '#fff' }}>{c.unread}</span>
</div>
)}
{/* 箭头 */}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
<path d="M9 18l6-6-6-6"/>
</svg>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕4随访管理 ───
function FollowUpList() {
const filterTabs = ['待随访', '已完成', '已过期'];
const followUps = [
{ patient: '张三', type: '门诊随访', date: '5月10日', status: '待随访', statusColor: T.pri, statusBg: T.priL, data: '血压 130/85' },
{ patient: '李四', type: '电话随访', date: '5月8日', status: '已完成', statusColor: T.acc, statusBg: T.accL, data: '血压 125/80' },
{ patient: '王五', type: '线上随访', date: '5月5日', status: '已过期', statusColor: T.dan, statusBg: T.danL, data: '血糖 8.2' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="随访管理" />
{/* 筛选标签 */}
<div style={{ display: 'flex', gap: 8, padding: '12px 20px', flexShrink: 0 }}>
{filterTabs.map((tab, i) => (
<div key={tab} style={{
padding: '6px 16px', borderRadius: 20, fontSize: 13, fontWeight: i === 0 ? 600 : 400,
background: i === 0 ? T.pri : T.card, color: i === 0 ? '#fff' : T.tx2,
border: `1px solid ${i === 0 ? T.pri : T.bd}`, cursor: 'pointer',
}}>{tab}</div>
))}
</div>
{/* 随访卡片列表 */}
<div style={{ flex: 1, overflow: 'auto', padding: '0 20px 20px' }}>
{followUps.map((f, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: '16px', marginBottom: 10, boxShadow: '0 1px 8px rgba(0,0,0,0.03)' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8 }}>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<span style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>{f.patient}</span>
<Tag color={f.statusColor} bg={f.statusBg}>{f.status}</Tag>
</div>
<div style={{ fontSize: 13, color: T.tx3, marginTop: 4 }}>{f.type}</div>
</div>
<div style={{ textAlign: 'right' }}>
<div style={{ fontSize: 13, color: T.tx2, fontWeight: 500 }}>{f.date}</div>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: T.bg, borderRadius: T.rSm, padding: '10px 12px' }}>
<div style={{ fontSize: 12, color: T.tx3 }}>最近数据</div>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx }}>{f.data}</div>
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕5患者管理 ───
function PatientList() {
const patients = [
{ name: '张三', age: 58, gender: '男', diagnosis: '高血压 · 慢性肾病III期', lastVisit: '5月8日', initial: '张', bg: T.priL },
{ name: '李四', age: 65, gender: '男', diagnosis: '2型糖尿病 · 肾功能不全', lastVisit: '5月6日', initial: '李', bg: T.accL },
{ name: '王五', age: 72, gender: '女', diagnosis: '高血压 · 血液透析', lastVisit: '5月5日', initial: '王', bg: T.wrnL },
{ name: '赵六', age: 45, gender: '男', diagnosis: '2型糖尿病', lastVisit: '4月28日', initial: '赵', bg: T.danL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="患者管理" />
{/* 搜索栏 */}
<div style={{ padding: '12px 20px', flexShrink: 0 }}>
<div style={{ background: T.card, borderRadius: 12, height: 42, display: 'flex', alignItems: 'center', padding: '0 14px', gap: 10, border: `1px solid ${T.bd}` }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/>
</svg>
<span style={{ fontSize: 14, color: T.tx3 }}>搜索患者姓名</span>
</div>
</div>
{/* 患者列表 */}
<div style={{ flex: 1, overflow: 'auto', padding: '0 20px 20px' }}>
{patients.map((p, i) => (
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: '14px 16px', marginBottom: 10, boxShadow: '0 1px 8px rgba(0,0,0,0.03)', display: 'flex', alignItems: 'center', gap: 12 }}>
{/* 头像 */}
<div style={{ width: 46, height: 46, borderRadius: 23, background: p.bg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ fontFamily: T.serif, fontSize: 20, fontWeight: 700, color: T.pri }}>{p.initial}</span>
</div>
{/* 内容 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<span style={{ fontSize: 15, fontWeight: 600, color: T.tx }}>{p.name}</span>
<span style={{ fontSize: 12, color: T.tx3 }}>{p.age} · {p.gender}</span>
</div>
<div style={{ fontSize: 13, color: T.pri, marginTop: 4, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.diagnosis}</div>
<div style={{ fontSize: 12, color: T.tx3, marginTop: 3 }}>最近 {p.lastVisit}</div>
</div>
{/* 箭头 */}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
<path d="M9 18l6-6-6-6"/>
</svg>
</div>
))}
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div className="screens">
<IosFrame width={360} height={780} label="医生工作台">
<DoctorHome />
</IosFrame>
<IosFrame width={360} height={780} label="待办收件箱">
<ActionInbox />
</IosFrame>
<IosFrame width={360} height={780} label="在线咨询">
<ConsultList />
</IosFrame>
<IosFrame width={360} height={780} label="随访管理">
<FollowUpList />
</IosFrame>
<IosFrame width={360} height={780} label="患者管理">
<PatientList />
</IosFrame>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

BIN
docs/design/mp-11-top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 KiB

View File

@@ -0,0 +1,646 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 医生端临床</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 1200px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 36px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
/* Scrollbar hide */
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 医生端临床</div>
<div class="note">医生端深靛蓝设计系统 — 临床管理模块。6 个屏幕:告警列表、告警详情、透析列表、透析创建、处方列表、处方详情。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 340, height = 740, time = '9:41', battery = 85, darkStatus = false, label }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div class="screen-wrap">
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div className="no-scrollbar" style={{ ...iosFrameStyles.content }}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
{label && <div class="screen-label">{label}</div>}
</div>
);
}
// ─── 设计 Token — 医生端靛蓝变体 ───
const T = {
pri: '#3A6B8C', priL: '#D4E5F0', priD: '#2A4F6A',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用组件 ───
function NavBar({ title }) {
return (
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', background: T.bg, borderBottom: `1px solid ${T.bdL}`, flexShrink: 0 }}>
<svg style={{ position: 'absolute', left: 16 }} width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.tx} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M15 18l-6-6 6-6"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
function Tag({ label, color = T.acc, bg = T.accL }) {
return (
<span style={{ display: 'inline-block', fontSize: 11, color, background: bg, padding: '2px 8px', borderRadius: 6, fontWeight: 500 }}>{label}</span>
);
}
function FilterTabs({ tabs, active = 0 }) {
return (
<div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
{tabs.map((t, i) => (
<div key={i} style={{
padding: '6px 14px', borderRadius: 20, fontSize: 13, fontWeight: i === active ? 600 : 400,
color: i === active ? '#fff' : T.tx2, background: i === active ? T.pri : T.card,
border: `1px solid ${i === active ? T.pri : T.bd}`, cursor: 'pointer', transition: 'all 0.2s',
}}>{t}</div>
))}
</div>
);
}
function InfoRow({ label, value }) {
return (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 0', borderBottom: `1px solid ${T.bdL}` }}>
<span style={{ fontSize: 13, color: T.tx3 }}>{label}</span>
<span style={{ fontSize: 14, color: T.tx, fontWeight: 500 }}>{value}</span>
</div>
);
}
function FormField({ label, value, placeholder, multiline }) {
return (
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>{label}</div>
<div style={{
height: multiline ? 80 : 52, background: T.card, border: `1.5px solid ${T.bd}`,
borderRadius: T.r, display: 'flex', alignItems: multiline ? 'flex-start' : 'center',
padding: multiline ? '14px 16px' : '0 16px', fontSize: 14, color: value ? T.tx : T.tx3,
fontFamily: T.sans, lineHeight: multiline ? 1.5 : 1,
}}>{value || placeholder}</div>
</div>
);
}
function ActionButton({ label, primary, danger, style: extraStyle }) {
const isDanger = danger;
const isPrimary = primary;
return (
<div style={{
height: 48, borderRadius: T.r, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 15, fontWeight: 600, cursor: 'pointer',
background: isDanger ? 'transparent' : (isPrimary ? T.pri : 'transparent'),
color: isDanger ? T.dan : (isPrimary ? '#fff' : T.pri),
border: isDanger ? `1.5px solid ${T.dan}` : (isPrimary ? 'none' : `1.5px solid ${T.pri}`),
...extraStyle,
}}>{label}</div>
);
}
// ─── 屏幕1告警列表 ───
function AlertList() {
const alerts = [
{ patient: '张三', type: '血压异常', urgency: '紧急', urgencyColor: T.dan, urgencyBg: T.danL,
value: '158', unit: 'mmHg', ref: '参考 <140', time: '10分钟前', status: '待处理', statusColor: T.dan, statusBg: T.danL },
{ patient: '赵六', type: '血糖异常', urgency: '紧急', urgencyColor: T.dan, urgencyBg: T.danL,
value: '15.2', unit: 'mmol/L', ref: '参考 <7.0', time: '2小时前', status: '待处理', statusColor: T.dan, statusBg: T.danL },
{ patient: '李四', type: '体重异常', urgency: '普通', urgencyColor: T.wrn, urgencyBg: T.wrnL,
value: '+2.3', unit: 'kg', ref: '周变化', time: '昨天', status: '已处理', statusColor: T.acc, statusBg: T.accL },
{ patient: '陈七', type: '血压异常', urgency: '紧急', urgencyColor: T.dan, urgencyBg: T.danL,
value: '162', unit: 'mmHg', ref: '参考 <140', time: '昨天', status: '待处理', statusColor: T.dan, statusBg: T.danL },
{ patient: '周八', type: '心率异常', urgency: '普通', urgencyColor: T.wrn, urgencyBg: T.wrnL,
value: '108', unit: 'bpm', ref: '参考 60-100', time: '2天前', status: '已处理', statusColor: T.acc, statusBg: T.accL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="异常告警" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 筛选标签 */}
<FilterTabs tabs={['全部', '高优', '中优', '低优']} active={0} />
{/* 统计栏 */}
<div style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
{[
{ label: '今日', value: '8', color: T.pri },
{ label: '待处理', value: '5', color: T.dan },
{ label: '已处理', value: '3', color: T.acc },
].map((s, i) => (
<div key={i} style={{ flex: 1, background: T.card, borderRadius: T.rSm, padding: '12px 14px', textAlign: 'center', boxShadow: '0 1px 8px rgba(0,0,0,0.04)' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: s.color }}>{s.value}</div>
<div style={{ fontSize: 11, color: T.tx3, marginTop: 2 }}>{s.label}</div>
</div>
))}
</div>
{/* 告警列表 */}
{alerts.map((a, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', borderLeft: `4px solid ${a.urgencyColor}`,
}}>
{/* 头部:患者 + 类型 + 紧急度 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{a.patient}</span>
<Tag label={a.type} color={T.pri} bg={T.priL} />
</div>
<Tag label={a.urgency} color={a.urgencyColor} bg={a.urgencyBg} />
</div>
{/* 异常值 */}
<div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 10 }}>
<span style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: a.urgencyColor }}>{a.value}</span>
<span style={{ fontSize: 13, color: T.tx2 }}>{a.unit}</span>
<span style={{ fontSize: 12, color: T.tx3, marginLeft: 4 }}>{a.ref}</span>
</div>
{/* 底部:时间 + 状态 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontSize: 12, color: T.tx3 }}>{a.time}</span>
<Tag label={a.status} color={a.statusColor} bg={a.statusBg} />
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕2告警详情 ───
function AlertDetail() {
const history = [
{ date: '5/8', value: '158/95', note: '偏高', color: T.dan },
{ date: '5/7', value: '145/90', note: '偏高', color: T.wrn },
{ date: '5/6', value: '132/85', note: '正常', color: T.acc },
{ date: '5/5', value: '138/88', note: '偏高', color: T.wrn },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="告警详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 患者信息 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 14,
}}>
<div style={{
width: 44, height: 44, borderRadius: 22, background: T.priL,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.pri,
}}></div>
<div style={{ flex: 1 }}>
<div style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx, marginBottom: 3 }}>张三</div>
<div style={{ fontSize: 13, color: T.tx3 }}>58 · · 高血压 · 慢性肾病III期</div>
</div>
</div>
{/* 告警信息卡片 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', borderLeft: `4px solid ${T.dan}`,
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
<span style={{ fontSize: 14, fontWeight: 600, color: T.tx }}>告警信息</span>
<Tag label="紧急" color={T.dan} bg={T.danL} />
</div>
<InfoRow label="类型" value="血压异常" />
<InfoRow label="触发时间" value="今天 08:30" />
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 0' }}>
<span style={{ fontSize: 13, color: T.tx3 }}>异常值</span>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
<span style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.dan }}>158</span>
<span style={{ fontSize: 13, color: T.tx2 }}>mmHg</span>
<span style={{ fontSize: 12, color: T.tx3, marginLeft: 4 }}>参考 &lt;140</span>
</div>
</div>
</div>
{/* 近期数据 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 12 }}>近期数据</div>
{history.map((h, i) => (
<div key={i} style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
padding: '10px 0', borderBottom: i < history.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<span style={{ fontSize: 13, color: T.tx2, width: 40 }}>{h.date}</span>
<span style={{ fontFamily: T.serif, fontSize: 15, fontWeight: 600, color: T.tx, flex: 1 }}>{h.value}</span>
<Tag label={h.note} color={h.color} bg={h.color === T.dan ? T.danL : (h.color === T.wrn ? T.wrnL : T.accL)} />
</div>
))}
</div>
{/* 处理意见 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 10 }}>处理意见</div>
<div style={{
height: 72, background: T.bg, borderRadius: T.rSm, border: `1px solid ${T.bd}`,
padding: '12px 14px', fontSize: 13, color: T.tx3, lineHeight: 1.5,
}}>请输入处理意见...</div>
</div>
{/* 操作按钮 */}
<div style={{ display: 'flex', gap: 12 }}>
<ActionButton label="标记已处理" primary style={{ flex: 1 }} />
<ActionButton label="联系患者" style={{ flex: 1 }} />
</div>
</div>
</div>
);
}
// ─── 屏幕3透析列表 ───
function DialysisList() {
const records = [
{ patient: '张三', bed: '3床', mode: 'HD', time: '08:00-12:00', status: '进行中', statusColor: T.wrn, statusBg: T.wrnL,
detail: '超滤 1.8L/2.3L' },
{ patient: '李四', bed: '5床', mode: 'HDF', time: '08:30-12:30', status: '进行中', statusColor: T.wrn, statusBg: T.wrnL,
detail: '超滤 1.2L/2.0L' },
{ patient: '王五', bed: '1床', mode: 'HD', time: '13:00-17:00', status: '待开始', statusColor: T.tx3, statusBg: T.surface,
detail: null },
{ patient: '赵六', bed: '2床', mode: 'HD', time: '08:00-12:00', status: '已完成', statusColor: T.acc, statusBg: T.accL,
detail: '超滤 2.1L' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="透析管理" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 今日统计 */}
<div style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
{[
{ label: '已透析', value: '5', color: T.acc },
{ label: '进行中', value: '2', color: T.wrn },
{ label: '待开始', value: '3', color: T.tx3 },
].map((s, i) => (
<div key={i} style={{
flex: 1, background: T.card, borderRadius: T.rSm, padding: '14px 14px', textAlign: 'center',
boxShadow: '0 1px 8px rgba(0,0,0,0.04)',
}}>
<div style={{ fontFamily: T.serif, fontSize: 24, fontWeight: 700, color: s.color }}>{s.value}</div>
<div style={{ fontSize: 11, color: T.tx3, marginTop: 2 }}>{s.label}</div>
</div>
))}
</div>
{/* 透析记录 */}
{records.map((r, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
{/* 头部 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{r.patient}</span>
<Tag label={r.bed} color={T.priD} bg={T.priL} />
</div>
<Tag label={r.status} color={r.statusColor} bg={r.statusBg} />
</div>
{/* 信息行 */}
<div style={{ display: 'flex', gap: 16, marginBottom: r.detail ? 10 : 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
<span style={{ fontSize: 12, color: T.tx3 }}>模式</span>
<span style={{ fontSize: 13, fontWeight: 600, color: T.pri }}>{r.mode}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
<span style={{ fontSize: 12, color: T.tx3 }}>时段</span>
<span style={{ fontSize: 13, color: T.tx }}>{r.time}</span>
</div>
</div>
{/* 关键指标 */}
{r.detail && (
<div style={{
background: T.bg, borderRadius: T.rXs, padding: '8px 12px',
fontSize: 13, color: T.tx2,
}}>
{r.detail}
</div>
)}
</div>
))}
{/* FAB */}
<div style={{
position: 'sticky', bottom: 10, display: 'flex', justifyContent: 'flex-end', pointerEvents: 'none',
}}>
<div style={{
width: 52, height: 52, borderRadius: 26, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
boxShadow: '0 4px 20px rgba(58,107,140,0.4)', pointerEvents: 'auto', cursor: 'pointer',
}}>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.5" strokeLinecap="round">
<path d="M12 5v14M5 12h14"/>
</svg>
</div>
</div>
</div>
</div>
);
}
// ─── 屏幕4透析创建 ───
function DialysisCreate() {
const modes = ['HD', 'HDF', 'HF'];
const activeMode = 0;
const dialysate = ['碳酸氢盐', '醋酸盐'];
const anticoagulant = ['低分子肝素', '普通肝素', '无'];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="新增透析记录" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
<FormField label="患者选择" value="张三" placeholder="请选择患者" />
{/* 透析模式 — 按钮横排 */}
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>透析模式</div>
<div style={{ display: 'flex', gap: 10 }}>
{modes.map((m, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 14, fontWeight: i === activeMode ? 600 : 400,
color: i === activeMode ? '#fff' : T.tx2,
background: i === activeMode ? T.pri : T.card,
border: `1.5px solid ${i === activeMode ? T.pri : T.bd}`,
cursor: 'pointer',
}}>{m}</div>
))}
</div>
</div>
<FormField label="床位号" value="3床" placeholder="请输入床位号" />
<FormField label="开始时间" value="08:00" placeholder="请选择时间" />
<FormField label="计划时长" value="4小时" placeholder="请输入时长" />
<FormField label="血流量" value="250 ml/min" placeholder="请输入血流量" />
{/* 透析液选择 */}
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>透析液</div>
<div style={{ display: 'flex', gap: 10 }}>
{dialysate.map((d, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 13, fontWeight: i === 0 ? 600 : 400,
color: i === 0 ? '#fff' : T.tx2,
background: i === 0 ? T.pri : T.card,
border: `1.5px solid ${i === 0 ? T.pri : T.bd}`,
cursor: 'pointer',
}}>{d}</div>
))}
</div>
</div>
{/* 抗凝剂选择 */}
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>抗凝剂</div>
<div style={{ display: 'flex', gap: 8 }}>
{anticoagulant.map((a, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 12, fontWeight: i === 0 ? 600 : 400,
color: i === 0 ? '#fff' : T.tx2,
background: i === 0 ? T.pri : T.card,
border: `1.5px solid ${i === 0 ? T.pri : T.bd}`,
cursor: 'pointer',
}}>{a}</div>
))}
</div>
</div>
<FormField label="目标超滤量" value="2.3 L" placeholder="请输入目标超滤量" />
{/* 底部按钮 */}
<div style={{ marginTop: 8 }}>
<ActionButton label="开始透析" primary />
</div>
</div>
</div>
);
}
// ─── 屏幕5处方列表 ───
function PrescriptionList() {
const prescriptions = [
{ patient: '张三', id: 'PX-20250401', mode: 'HD', freq: '每周3次', date: '4月1日', status: '生效中', statusColor: T.acc, statusBg: T.accL },
{ patient: '李四', id: 'PX-20250315', mode: 'HDF', freq: '每周2次', date: '3月15日', status: '生效中', statusColor: T.acc, statusBg: T.accL },
{ patient: '王五', id: 'PX-20250201', mode: 'HD', freq: '每周3次', date: '2月1日', status: '已停用', statusColor: T.tx3, statusBg: T.surface },
{ patient: '赵六', id: 'PX-20250110', mode: 'HDF', freq: '每周2次', date: '1月10日', status: '生效中', statusColor: T.acc, statusBg: T.accL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="透析处方" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 筛选 */}
<FilterTabs tabs={['生效中', '全部']} active={0} />
{/* 处方卡片 */}
{prescriptions.map((p, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
{/* 头部 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{p.patient}</span>
<span style={{ fontSize: 12, color: T.tx3 }}>{p.id}</span>
</div>
<Tag label={p.status} color={p.statusColor} bg={p.statusBg} />
</div>
{/* 信息行 */}
<div style={{ display: 'flex', gap: 20, marginBottom: 4 }}>
<div>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>透析模式</div>
<div style={{ fontSize: 14, fontWeight: 600, color: T.pri }}>{p.mode}</div>
</div>
<div>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>频率</div>
<div style={{ fontSize: 14, color: T.tx }}>{p.freq}</div>
</div>
<div>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>生效日期</div>
<div style={{ fontSize: 14, color: T.tx }}>{p.date}</div>
</div>
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕6处方详情 ───
function PrescriptionDetail() {
const params = [
{ label: '处方编号', value: 'PX-20250401' },
{ label: '透析模式', value: '血液透析HD' },
{ label: '频率', value: '每周 3 次(周一/三/五)' },
{ label: '单次时长', value: '4 小时' },
{ label: '血流量', value: '250 ml/min' },
{ label: '透析液流速', value: '500 ml/min' },
{ label: '透析液', value: '碳酸氢盐' },
{ label: '抗凝剂', value: '低分子肝素 4000IU' },
{ label: '干体重', value: '65.0 kg' },
{ label: '目标超滤', value: '2.0-2.5 L' },
{ label: 'Kt/V 目标', value: '≥1.2' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="处方详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 患者信息 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 14,
}}>
<div style={{
width: 44, height: 44, borderRadius: 22, background: T.priL,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.pri,
}}></div>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx }}>张三</span>
<Tag label="生效中" color={T.acc} bg={T.accL} />
</div>
<div style={{ fontSize: 13, color: T.tx3 }}>58 · </div>
</div>
</div>
{/* 详细参数 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '4px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, padding: '14px 0 4px' }}>处方参数</div>
{params.map((p, i) => (
<div key={i} style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
padding: '11px 0', borderBottom: i < params.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<span style={{ fontSize: 13, color: T.tx3 }}>{p.label}</span>
<span style={{ fontSize: 14, color: T.tx, fontWeight: 500, textAlign: 'right', maxWidth: '55%' }}>{p.value}</span>
</div>
))}
</div>
{/* 医生信息 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '16px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 3 }}>开方医生</div>
<div style={{ fontSize: 14, color: T.tx, fontWeight: 500 }}>李医生 · 肾内科</div>
</div>
<div style={{ textAlign: 'right' }}>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 3 }}>生效日期</div>
<div style={{ fontSize: 14, color: T.tx, fontWeight: 500 }}>2025年4月1日</div>
</div>
</div>
</div>
{/* 底部操作 */}
<div style={{ display: 'flex', gap: 12 }}>
<ActionButton label="调整处方" primary style={{ flex: 1 }} />
<ActionButton label="停用处方" danger style={{ flex: 1 }} />
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div class="screens">
<IosFrame label="告警列表" time="9:41" battery={85}>
<AlertList />
</IosFrame>
<IosFrame label="告警详情" time="9:41" battery={85}>
<AlertDetail />
</IosFrame>
<IosFrame label="透析列表" time="9:42" battery={84}>
<DialysisList />
</IosFrame>
<IosFrame label="透析创建" time="9:43" battery={84}>
<DialysisCreate />
</IosFrame>
<IosFrame label="处方列表" time="9:43" battery={83}>
<PrescriptionList />
</IosFrame>
<IosFrame label="处方详情" time="9:44" battery={83}>
<PrescriptionDetail />
</IosFrame>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>

View File

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康 - HMS 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<span class="nav-bar__title">健康</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- 1. User Greeting Card -->
<div class="section">
<div class="card card--pressable">
<div class="flex-between mb-sm">
<div>
<div style="font-size: var(--font-h2); font-weight: 600; color: var(--tx);">张伟, 上午好!</div>
<div style="font-size: var(--font-body); color: var(--tx2); margin-top: 4px;">今日健康评分 85分</div>
</div>
<div style="font-size: 48px; line-height: 1;">😊</div>
</div>
<div class="progress">
<div class="progress__bar" style="width: 85%"></div>
</div>
</div>
</div>
<!-- 2. Stat Grid (2x2) -->
<div class="section">
<div class="stat-grid" style="grid-template-columns: repeat(2, 1fr);">
<div class="stat-card stat-card--primary">
<div class="stat-card__value">68.5</div>
<div class="stat-card__label">体重 kg</div>
</div>
<div class="stat-card stat-card--success">
<div class="stat-card__value">23.1</div>
<div class="stat-card__label">BMI 正常</div>
</div>
<div class="stat-card stat-card--warning">
<div class="stat-card__value">6,842</div>
<div class="stat-card__label">步数 步</div>
</div>
<div class="stat-card" style="">
<div class="stat-card__value" style="color: var(--info)">7.2</div>
<div class="stat-card__label">睡眠 小时</div>
</div>
</div>
</div>
<!-- 3. 今日提醒 Section -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">今日提醒</div>
</div>
<div class="card-list">
<div class="list-item card--pressable">
<div class="list-item__icon list-item__icon--amber">💊</div>
<div class="list-item__content">
<div class="list-item__title">用药提醒</div>
<div class="list-item__desc">降压药 每日一次 · 08:00</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">待服用</span>
</div>
</div>
<div class="list-item card--pressable">
<div class="list-item__icon list-item__icon--blue">📋</div>
<div class="list-item__content">
<div class="list-item__title">复查提醒</div>
<div class="list-item__desc">血常规检查 · 2026-05-20</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">即将到期</span>
</div>
</div>
</div>
</div>
<!-- 5. 体征趋势 Section -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">体征趋势</div>
<div class="section-title__action">查看 &gt;</div>
</div>
<div class="card">
<div style="font-size: var(--font-body-sm); color: var(--tx3); margin-bottom: var(--gap-sm);">近7天血压趋势</div>
<!-- CSS Bar Chart -->
<div style="display: flex; align-items: flex-end; justify-content: space-between; height: 100px; gap: 8px; padding: 0 4px;">
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 60px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 40px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周一</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 55px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 38px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周二</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 65px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 42px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周三</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 58px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 36px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周四</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 52px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 34px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周五</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 60px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 40px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周六</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; flex: 1; gap: 2px;">
<div style="width: 100%; background: var(--pri-light); border-radius: 4px 4px 0 0; height: 56px;"></div>
<div style="width: 100%; background: var(--pri); border-radius: 4px 4px 0 0; height: 37px;"></div>
<div style="font-size: 10px; color: var(--tx3); margin-top: 4px;">周日</div>
</div>
</div>
<div class="flex-row mt-sm" style="gap: var(--gap-md); justify-content: center;">
<div class="flex-row" style="gap: 4px;">
<div style="width: 12px; height: 12px; background: var(--pri-light); border-radius: 2px;"></div>
<span style="font-size: 11px; color: var(--tx3);">收缩压</span>
</div>
<div class="flex-row" style="gap: 4px;">
<div style="width: 12px; height: 12px; background: var(--pri); border-radius: 2px;"></div>
<span style="font-size: 11px; color: var(--tx3);">舒张压</span>
</div>
</div>
</div>
</div>
<!-- 7. 最新报告 Section -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">最新报告</div>
<div class="section-title__action">全部 &gt;</div>
</div>
<div class="card card--pressable">
<div class="flex-between mb-xs">
<div class="list-item__title">血常规检查</div>
<span class="tag tag--success">正常</span>
</div>
<div class="list-item__desc">2026-05-10</div>
</div>
</div>
</div>
</div>
<!-- Tab Bar -->
<div class="tab-bar">
<div class="tab-bar__item">
<div class="tab-bar__icon">🏠</div>
<div class="tab-bar__label">首页</div>
</div>
<div class="tab-bar__item tab-bar__item--active">
<div class="tab-bar__icon">❤️</div>
<div class="tab-bar__label">健康</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">💬</div>
<div class="tab-bar__label">消息</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">👤</div>
<div class="tab-bar__label">我的</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>首页 - HMS 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<span class="nav-bar__title">首页</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- 1. Banner / Swiper -->
<div class="section">
<div class="banner">
<div class="banner__content">
<div class="banner__title">关注您的健康每一天</div>
<div class="banner__subtitle">全面健康管理,从今天开始</div>
<div class="banner__dots">
<div class="banner__dot banner__dot--active"></div>
<div class="banner__dot"></div>
<div class="banner__dot"></div>
</div>
</div>
</div>
</div>
<!-- 2. Quick Entry Grid -->
<div class="section">
<div class="quick-grid">
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--orange">📊</div>
<div class="quick-item__label">健康档案</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--green">📅</div>
<div class="quick-item__label">在线预约</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--blue">💊</div>
<div class="quick-item__label">用药提醒</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--amber">📈</div>
<div class="quick-item__label">趋势分析</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--orange">🏥</div>
<div class="quick-item__label">体检报告</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--green">💬</div>
<div class="quick-item__label">在线咨询</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--blue">🛒</div>
<div class="quick-item__label">积分商城</div>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--amber">📋</div>
<div class="quick-item__label">更多服务</div>
</div>
</div>
</div>
<!-- 3. 健康概览 Section -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">健康概览</div>
<div class="section-title__action">查看更多 &gt;</div>
</div>
<div class="stat-grid">
<div class="stat-card stat-card--primary">
<div class="stat-card__value">128/82</div>
<div class="stat-card__label">血压 mmHg</div>
</div>
<div class="stat-card stat-card--success">
<div class="stat-card__value">72</div>
<div class="stat-card__label">心率 次/分</div>
</div>
<div class="stat-card" style="">
<div class="stat-card__value" style="color: var(--info)">5.6</div>
<div class="stat-card__label">血糖 mmol/L</div>
</div>
</div>
</div>
<!-- 5. 近期预约 Section -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">近期预约</div>
<div class="section-title__action">全部 &gt;</div>
</div>
<div class="card card--pressable">
<div class="flex-between mb-xs">
<div class="list-item__title">张三 主任医师 · 心内科</div>
<span class="tag tag--success">已确认</span>
</div>
<div class="list-item__desc">2026-05-18 周一 09:30</div>
</div>
</div>
<!-- 7. 健康文章 Section -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">健康文章</div>
<div class="section-title__action">更多 &gt;</div>
</div>
<div class="card-list">
<div class="card card--pressable">
<div class="list-item__title">高血压日常管理指南</div>
<div class="list-item__desc mt-xs">5分钟阅读</div>
</div>
<div class="card card--pressable">
<div class="list-item__title">糖尿病患者饮食建议</div>
<div class="list-item__desc mt-xs">3分钟阅读</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tab Bar -->
<div class="tab-bar">
<div class="tab-bar__item tab-bar__item--active">
<div class="tab-bar__icon">🏠</div>
<div class="tab-bar__label">首页</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">❤️</div>
<div class="tab-bar__label">健康</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">💬</div>
<div class="tab-bar__label">消息</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">👤</div>
<div class="tab-bar__label">我的</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,149 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>消息 - HMS 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<span class="nav-bar__title">消息</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- 1. Search Section -->
<div class="section">
<div class="search-bar">
<div class="search-bar__icon">🔍</div>
<input class="search-bar__input" type="text" placeholder="搜索消息...">
</div>
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">系统通知</div>
<div class="filter-pill">预约提醒</div>
<div class="filter-pill">健康提醒</div>
<div class="filter-pill">咨询回复</div>
</div>
</div>
<!-- 3. Message List -->
<div class="section">
<div class="card-list">
<!-- Message 1: 预约确认 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">📋</div>
<div class="list-item__content">
<div class="list-item__title">预约确认通知</div>
<div class="list-item__desc">您的预约已确认,请按时就诊</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已确认</span>
<span class="time-label">2分钟前</span>
</div>
</div>
<!-- Message 2: 用药提醒 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--amber">💊</div>
<div class="list-item__content">
<div class="list-item__title">用药提醒</div>
<div class="list-item__desc">今日降压药已到服用时间</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">待服用</span>
<span class="time-label">1小时前</span>
</div>
</div>
<!-- Message 3: 检查报告 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">📊</div>
<div class="list-item__content">
<div class="list-item__title">检查报告</div>
<div class="list-item__desc">您的血常规报告已出</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">查看</span>
<span class="time-label">昨天</span>
</div>
</div>
<!-- Message 4: 咨询回复 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--orange">💬</div>
<div class="list-item__content">
<div class="list-item__title">咨询回复</div>
<div class="list-item__desc">李医生回复了您的咨询</div>
</div>
<div class="list-item__right">
<span class="tag tag--default">回复</span>
<span class="time-label">昨天</span>
</div>
</div>
<!-- Message 5: 体检提醒 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--red">🏥</div>
<div class="list-item__content">
<div class="list-item__title">体检提醒</div>
<div class="list-item__desc">您有一项体检即将到期</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">即将到期</span>
<span class="time-label">3天前</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Tab Bar -->
<div class="tab-bar">
<div class="tab-bar__item">
<div class="tab-bar__icon">🏠</div>
<div class="tab-bar__label">首页</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">❤️</div>
<div class="tab-bar__label">健康</div>
</div>
<div class="tab-bar__item tab-bar__item--active">
<div class="tab-bar__icon">💬</div>
<div class="tab-bar__label">消息</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">👤</div>
<div class="tab-bar__label">我的</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的 - HMS 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<span class="nav-bar__title">我的</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell" style="padding-bottom: 0;">
<!-- 1. User Profile Card -->
<div class="section">
<div class="card text-center" style="display: flex; flex-direction: column; align-items: center; padding: var(--gap-lg) var(--card-pad);">
<div class="avatar avatar--lg" style="margin-bottom: var(--gap-sm);"></div>
<div style="font-size: var(--font-h1); font-weight: 600; color: var(--tx); margin-bottom: 4px;">张伟</div>
<div style="font-size: var(--font-body-sm); color: var(--tx3); margin-bottom: var(--gap-sm);">138****6789</div>
<div style="display: flex; gap: var(--gap-xs);">
<span class="tag tag--success">已认证</span>
<span class="tag tag--warning">VIP会员</span>
</div>
</div>
</div>
<!-- 2. Points Card -->
<div class="section">
<div class="card" style="background: linear-gradient(135deg, var(--pri) 0%, var(--pri-dark) 100%); padding: var(--gap-md) var(--card-pad);">
<div style="display: flex; align-items: center; justify-content: space-between;">
<div>
<div style="font-size: var(--font-body-sm); color: rgba(255,255,255,0.8); margin-bottom: 4px;">我的积分</div>
<div style="font-size: var(--font-display); font-weight: 700; color: #fff; font-family: var(--font-serif); line-height: 1;">2,580</div>
</div>
<div style="font-size: var(--font-body-sm); color: rgba(255,255,255,0.9); display: flex; align-items: center; gap: 4px; cursor: pointer;">
去兑换 &gt;
</div>
</div>
</div>
</div>
<!-- 3a. Menu Section: 健康管理 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">健康管理</div>
</div>
<div style="border-radius: var(--card-r); overflow: hidden; box-shadow: var(--shadow-sm);">
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">📋</div>
<div class="menu-item__text">健康档案</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">📄</div>
<div class="menu-item__text">体检报告</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">💊</div>
<div class="menu-item__text">用药记录</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">🔬</div>
<div class="menu-item__text">诊断记录</div>
<div class="menu-item__arrow">&gt;</div>
</div>
</div>
</div>
<!-- 3b. Menu Section: 透析管理 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">透析管理</div>
</div>
<div style="border-radius: var(--card-r); overflow: hidden; box-shadow: var(--shadow-sm);">
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">🩺</div>
<div class="menu-item__text">透析记录</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">📝</div>
<div class="menu-item__text">透析处方</div>
<div class="menu-item__arrow">&gt;</div>
</div>
</div>
</div>
<!-- 3c. Menu Section: 其他 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">其他</div>
</div>
<div style="border-radius: var(--card-r); overflow: hidden; box-shadow: var(--shadow-sm);">
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">👨‍👩‍👧</div>
<div class="menu-item__text">家人管理</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">📅</div>
<div class="menu-item__text">随访记录</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">📑</div>
<div class="menu-item__text">知情同意书</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">🎉</div>
<div class="menu-item__text">线下活动</div>
<div class="menu-item__arrow">&gt;</div>
</div>
</div>
</div>
<!-- 3d. Menu Section: 设置 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">设置</div>
</div>
<div style="border-radius: var(--card-r); overflow: hidden; box-shadow: var(--shadow-sm);">
<div class="menu-item" style="border-bottom: 1px solid var(--bd-light);">
<div class="menu-item__icon">👴</div>
<div class="menu-item__text">长者模式</div>
<div class="menu-item__extra">已关闭</div>
<div class="menu-item__arrow">&gt;</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">⚙️</div>
<div class="menu-item__text">设置</div>
<div class="menu-item__arrow">&gt;</div>
</div>
</div>
</div>
<!-- Bottom spacing for tab bar -->
<div style="height: 34px;"></div>
</div>
</div>
<!-- Tab Bar -->
<div class="tab-bar">
<div class="tab-bar__item">
<div class="tab-bar__icon">🏠</div>
<div class="tab-bar__label">首页</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">❤️</div>
<div class="tab-bar__label">健康</div>
</div>
<div class="tab-bar__item">
<div class="tab-bar__icon">💬</div>
<div class="tab-bar__label">消息</div>
</div>
<div class="tab-bar__item tab-bar__item--active">
<div class="tab-bar__icon">👤</div>
<div class="tab-bar__label">我的</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>创建预约 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">创建预约 · appointment-create</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">创建预约</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 表单卡片 -->
<div class="card mb-md">
<div class="form-group">
<label class="form-label form-label--required">选择科室</label>
<select class="form-select">
<option value="">请选择科室 &#9660;</option>
<option value="cardiology">心内科</option>
<option value="nephrology">肾内科</option>
<option value="endocrine">内分泌科</option>
<option value="general">内科</option>
<option value="surgery">外科</option>
</select>
</div>
<div class="form-group">
<label class="form-label form-label--required">选择医生</label>
<select class="form-select" disabled>
<option value="">请先选择科室 &#9660;</option>
</select>
</div>
<div class="form-group">
<label class="form-label form-label--required">就诊日期</label>
<input class="form-input" type="text" placeholder="请选择日期">
</div>
<div class="form-group">
<label class="form-label form-label--required">就诊时段</label>
<select class="form-select">
<option value="">请选择时段 &#9660;</option>
<option value="am">上午 08:00-12:00</option>
<option value="pm">下午 14:00-17:00</option>
</select>
</div>
<div class="form-group">
<label class="form-label">挂号类型</label>
<select class="form-select">
<option value="general">普通号</option>
<option value="expert">专家号</option>
<option value="special">特需号</option>
</select>
</div>
<div class="form-group" style="margin-bottom:0;">
<label class="form-label">病情描述</label>
<textarea class="form-textarea" placeholder="请简要描述您的症状,如持续时间、严重程度、既往病史等,方便医生提前了解您的病情..."></textarea>
</div>
</div>
<!-- 温馨提示 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<span class="section-title__text">温馨提示</span>
</div>
<div class="card card--outlined" style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
请携带医保卡和既往病历提前15分钟到达候诊区。首次就诊需在前台完成建档登记建议提前通过线上完善个人健康档案信息以便就诊时医生快速了解您的健康状况。
</div>
</div>
<!-- 提交按钮 -->
<button class="btn btn--primary btn--full mt-md">确认预约</button>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>预约详情 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">预约详情 · appointment-detail</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">预约详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 状态卡片 -->
<div class="card mb-md" style="text-align:center;padding:var(--gap-lg) var(--card-pad);">
<span class="tag tag--success" style="font-size:var(--font-body-sm);padding:8px 24px;margin-bottom:12px;">已确认</span>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:12px;">预约编号: APT20260518001</div>
</div>
<!-- 医生信息卡片 -->
<div class="card mb-md">
<div class="flex-row mb-sm">
<div class="avatar" style="background:var(--info-light);color:var(--info);"></div>
<div style="margin-left:14px;flex:1;">
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx);">李四 副主任医师</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px;">心内科 &middot; 第一人民医院</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px;">&#11088; 4.8 &middot; 接诊 856 次</div>
</div>
</div>
</div>
<!-- 详细信息卡片 -->
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">就诊日期</span>
<span class="info-row__value">2026年5月18日 周一</span>
</div>
<div class="info-row">
<span class="info-row__label">就诊时间</span>
<span class="info-row__value">09:30 - 10:00</span>
</div>
<div class="info-row">
<span class="info-row__label">就诊地点</span>
<span class="info-row__value">门诊楼3层301室</span>
</div>
<div class="info-row">
<span class="info-row__label">挂号类型</span>
<span class="info-row__value">专家号</span>
</div>
<div class="info-row">
<span class="info-row__label">挂号费用</span>
<span class="info-row__value" style="color:var(--pri);font-weight:600;">&yen;50.00</span>
</div>
</div>
<!-- 操作按钮 -->
<div style="display:flex;gap:12px;margin-top:var(--section-gap);">
<button class="btn btn--outline" style="flex:1;color:var(--danger);border-color:var(--danger);">取消预约</button>
<button class="btn btn--primary" style="flex:1;">导航到院</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,145 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>预约列表 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">预约列表 · appointment</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">预约列表</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 搜索栏 -->
<div class="search-bar">
<span class="search-bar__icon">&#128269;</span>
<input class="search-bar__input" type="text" placeholder="搜索预约...">
</div>
<!-- 筛选标签 -->
<div class="filter-pills">
<span class="filter-pill filter-pill--active">全部</span>
<span class="filter-pill">待确认</span>
<span class="filter-pill">已确认</span>
<span class="filter-pill">已完成</span>
<span class="filter-pill">已取消</span>
</div>
<!-- 预约卡片列表 -->
<div class="card-list mt-md">
<!-- 预约1: 已确认 -->
<div class="card card--pressable">
<div class="flex-row flex-between mb-sm">
<div class="flex-row">
<div class="avatar avatar--sm" style="background:var(--info-light);color:var(--info);"></div>
<div style="margin-left:10px;">
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx);">李四</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);">副主任医师 &middot; 心内科</div>
</div>
</div>
<span class="tag tag--success">已确认</span>
</div>
<div class="info-row">
<span class="info-row__label">日期时间</span>
<span class="info-row__value">2026-05-18 周一 09:30</span>
</div>
<div class="info-row">
<span class="info-row__label">就诊地点</span>
<span class="info-row__value">门诊楼3层301室</span>
</div>
<div class="info-row">
<span class="info-row__label">挂号类型</span>
<span class="info-row__value">专家号</span>
</div>
<div style="text-align:right;margin-top:12px;">
<button class="btn btn--primary btn--sm">查看详情</button>
</div>
</div>
<!-- 预约2: 待确认 -->
<div class="card card--pressable">
<div class="flex-row flex-between mb-sm">
<div class="flex-row">
<div class="avatar avatar--sm" style="background:var(--success-light);color:var(--success);"></div>
<div style="margin-left:10px;">
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx);">王五</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);">主任医师 &middot; 肾内科</div>
</div>
</div>
<span class="tag tag--warning">待确认</span>
</div>
<div class="info-row">
<span class="info-row__label">日期时间</span>
<span class="info-row__value">2026-05-20 周三 14:00</span>
</div>
<div class="info-row">
<span class="info-row__label">就诊地点</span>
<span class="info-row__value">门诊楼5层502室</span>
</div>
<div class="info-row">
<span class="info-row__label">挂号类型</span>
<span class="info-row__value">专家号</span>
</div>
<div style="text-align:right;margin-top:12px;">
<button class="btn btn--outline btn--sm" style="color:var(--danger);border-color:var(--danger);">取消预约</button>
</div>
</div>
<!-- 预约3: 已完成 -->
<div class="card card--pressable">
<div class="flex-row flex-between mb-sm">
<div class="flex-row">
<div class="avatar avatar--sm" style="background:var(--warning-light);color:var(--warning);"></div>
<div style="margin-left:10px;">
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx);">赵六</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);">主治医师 &middot; 内分泌科</div>
</div>
</div>
<span class="tag tag--default">已完成</span>
</div>
<div class="info-row">
<span class="info-row__label">日期时间</span>
<span class="info-row__value">2026-05-15 周四 10:30</span>
</div>
<div class="info-row">
<span class="info-row__label">就诊地点</span>
<span class="info-row__value">门诊楼2层205室</span>
</div>
<div class="info-row">
<span class="info-row__label">挂号类型</span>
<span class="info-row__value">普通号</span>
</div>
<div style="text-align:right;margin-top:12px;">
<button class="btn btn--primary btn--sm">查看详情</button>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线咨询 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">在线咨询 · consultation</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">在线咨询</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 搜索栏 -->
<div class="search-bar">
<span class="search-bar__icon">&#128269;</span>
<input class="search-bar__input" type="text" placeholder="搜索医生/科室...">
</div>
<!-- 筛选标签 -->
<div class="filter-pills">
<span class="filter-pill filter-pill--active">全部</span>
<span class="filter-pill">内科</span>
<span class="filter-pill">外科</span>
<span class="filter-pill">心内科</span>
<span class="filter-pill">肾内科</span>
</div>
<!-- 医生卡片列表 -->
<div class="card-list mt-md">
<!-- 医生1 -->
<div class="card card--pressable">
<div class="flex-row mb-sm">
<div class="avatar avatar--sm" style="background:var(--pri-light);color:var(--pri);"></div>
<div class="flex-1" style="margin-left:12px;">
<div class="flex-row flex-between">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx);">张三</span>
<span style="font-size:var(--font-body-sm);color:var(--tx2);">主任医师</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px;">心内科 &middot; 第一人民医院</div>
</div>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:12px;">&#11088; 4.9 &middot; 接诊 1,286 次</div>
<div class="flex-row flex-between">
<div style="display:flex;gap:8px;">
<span class="tag tag--info">图文咨询 &yen;30/次</span>
<span class="tag tag--info">视频咨询 &yen;50/次</span>
</div>
</div>
<div style="text-align:right;margin-top:12px;">
<button class="btn btn--primary btn--sm">立即咨询</button>
</div>
</div>
<!-- 医生2 -->
<div class="card card--pressable">
<div class="flex-row mb-sm">
<div class="avatar avatar--sm" style="background:var(--success-light);color:var(--success);"></div>
<div class="flex-1" style="margin-left:12px;">
<div class="flex-row flex-between">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx);">李明</span>
<span style="font-size:var(--font-body-sm);color:var(--tx2);">副主任医师</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px;">肾内科 &middot; 第一人民医院</div>
</div>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:12px;">&#11088; 4.8 &middot; 接诊 936 次</div>
<div class="flex-row flex-between">
<div style="display:flex;gap:8px;">
<span class="tag tag--info">图文咨询 &yen;25/次</span>
<span class="tag tag--info">视频咨询 &yen;45/次</span>
</div>
</div>
<div style="text-align:right;margin-top:12px;">
<button class="btn btn--primary btn--sm">立即咨询</button>
</div>
</div>
<!-- 医生3 -->
<div class="card card--pressable">
<div class="flex-row mb-sm">
<div class="avatar avatar--sm" style="background:var(--warning-light);color:var(--warning);"></div>
<div class="flex-1" style="margin-left:12px;">
<div class="flex-row flex-between">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx);">王芳</span>
<span style="font-size:var(--font-body-sm);color:var(--tx2);">主治医师</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px;">内分泌科 &middot; 第一人民医院</div>
</div>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:12px;">&#11088; 4.7 &middot; 接诊 758 次</div>
<div class="flex-row flex-between">
<div style="display:flex;gap:8px;">
<span class="tag tag--info">图文咨询 &yen;20/次</span>
</div>
</div>
<div style="text-align:right;margin-top:12px;">
<button class="btn btn--primary btn--sm">立即咨询</button>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">登录页 · login</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="content">
<div class="page-shell" style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:calc(812px - 44px - 34px);">
<!-- Logo 区域 -->
<div style="text-align:center;margin-bottom:48px;">
<div class="avatar avatar--lg" style="width:88px;height:88px;font-size:42px;margin:0 auto 20px;background:var(--pri);color:var(--white);">H</div>
<div style="font-size:var(--font-h1);font-weight:600;color:var(--tx);margin-bottom:8px;">健康管理</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);">您的健康管家</div>
</div>
<!-- 手机号登录表单 -->
<div style="width:100%;max-width:320px;">
<div class="form-group">
<input class="form-input" type="tel" placeholder="请输入手机号" maxlength="11">
</div>
<div class="form-group" style="display:flex;gap:12px;">
<input class="form-input" type="text" placeholder="请输入验证码" maxlength="6" style="flex:1;">
<button class="btn btn--outline btn--sm" style="white-space:nowrap;flex-shrink:0;">获取验证码</button>
</div>
<button class="btn btn--primary btn--full" style="margin-top:8px;">登录/注册</button>
</div>
<!-- 分割线 -->
<div style="display:flex;align-items:center;width:100%;max-width:320px;margin:32px 0;gap:16px;">
<div style="flex:1;height:1px;background:var(--bd);"></div>
<span style="font-size:var(--font-body-sm);color:var(--tx3);white-space:nowrap;">其他登录方式</span>
<div style="flex:1;height:1px;background:var(--bd);"></div>
</div>
<!-- 微信登录 -->
<div style="width:100%;max-width:320px;">
<button class="btn btn--outline btn--full" style="border-color:#07C160;color:#07C160;">
<span style="margin-right:8px;">&#x1F7E2;</span> 微信一键登录
</button>
</div>
<!-- 底部协议链接 -->
<div style="margin-top:40px;font-size:var(--font-cap);color:var(--tx3);text-align:center;">
登录即代表同意
<a href="user-agreement.html" style="color:var(--pri);text-decoration:none;">用户协议</a>
<a href="privacy-policy.html" style="color:var(--pri);text-decoration:none;">隐私政策</a>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>积分商城 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">积分商城 · mall</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">积分商城</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 积分余额卡片 -->
<div class="card mb-md" style="background:linear-gradient(135deg, var(--pri) 0%, var(--pri-dark) 100%);color:var(--white);">
<div style="font-size:var(--font-body-sm);opacity:0.85;margin-bottom:8px;">可用积分</div>
<div style="font-size:48px;font-weight:700;font-family:var(--font-serif);line-height:1;">2,580</div>
<div style="font-size:var(--font-body-sm);opacity:0.75;margin-top:8px;">兑换好礼,健康常伴</div>
</div>
<!-- 热门兑换 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<span class="section-title__text">热门兑换</span>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
<!-- 商品1 -->
<div class="card card--pressable" style="padding:0;overflow:hidden;">
<div style="width:100%;height:140px;background:var(--surface-alt);display:flex;align-items:center;justify-content:center;font-size:36px;color:var(--tx3);">
&#129697;
</div>
<div style="padding:12px;">
<div style="font-size:var(--font-body);font-weight:500;color:var(--tx);">智能血压计</div>
<div style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;margin-top:4px;">1,200 积分</div>
</div>
</div>
<!-- 商品2 -->
<div class="card card--pressable" style="padding:0;overflow:hidden;">
<div style="width:100%;height:140px;background:var(--surface-alt);display:flex;align-items:center;justify-content:center;font-size:36px;color:var(--tx3);">
&#9201;
</div>
<div style="padding:12px;">
<div style="font-size:var(--font-body);font-weight:500;color:var(--tx);">健康手环</div>
<div style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;margin-top:4px;">800 积分</div>
</div>
</div>
<!-- 商品3 -->
<div class="card card--pressable" style="padding:0;overflow:hidden;">
<div style="width:100%;height:140px;background:var(--surface-alt);display:flex;align-items:center;justify-content:center;font-size:36px;color:var(--tx3);">
&#128138;
</div>
<div style="padding:12px;">
<div style="font-size:var(--font-body);font-weight:500;color:var(--tx);">维生素D补充剂</div>
<div style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;margin-top:4px;">350 积分</div>
</div>
</div>
<!-- 商品4 -->
<div class="card card--pressable" style="padding:0;overflow:hidden;">
<div style="width:100%;height:140px;background:var(--surface-alt);display:flex;align-items:center;justify-content:center;font-size:36px;color:var(--tx3);">
&#127973;
</div>
<div style="padding:12px;">
<div style="font-size:var(--font-body);font-weight:500;color:var(--tx);">体检套餐券</div>
<div style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;margin-top:4px;">2,000 积分</div>
</div>
</div>
</div>
</div>
<!-- 兑换记录 -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<span class="section-title__text">兑换记录</span>
<span class="section-title__action">全部 &gt;</span>
</div>
<div class="card-list">
<div class="list-item">
<div class="list-item__icon list-item__icon--orange">&#129697;</div>
<div class="list-item__content">
<div class="list-item__title">智能血压计</div>
<div class="list-item__desc">2026-05-10</div>
</div>
<div class="list-item__right">
<span style="font-size:var(--font-body);font-weight:500;color:var(--danger);">-1,200积分</span>
<span class="tag tag--success tag--sm">兑换成功</span>
</div>
</div>
<div class="list-item">
<div class="list-item__icon list-item__icon--orange">&#127973;</div>
<div class="list-item__content">
<div class="list-item__title">体检套餐券</div>
<div class="list-item__desc">2026-04-28</div>
</div>
<div class="list-item__right">
<span style="font-size:var(--font-body);font-weight:500;color:var(--danger);">-2,000积分</span>
<span class="tag tag--success tag--sm">兑换成功</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>隐私政策 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">隐私政策 · privacy-policy</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">隐私政策</span>
</div>
<div class="content">
<div class="page-shell">
<h1 style="font-size:var(--font-h1);font-weight:600;color:var(--tx);text-align:center;margin-bottom:8px;">健康管理平台隐私政策</h1>
<p style="font-size:var(--font-cap);color:var(--tx3);text-align:center;margin-bottom:var(--gap-lg);">更新日期2026年1月1日</p>
<!-- 一、我们收集的信息 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">一、我们收集的信息</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
为向您提供健康管理服务,我们会收集以下类型的信息:您注册时提供的身份信息(姓名、手机号码、身份证号)、基本健康信息(年龄、性别、身高、体重)以及您通过平台录入的健康数据(血压、血糖、心率、体检报告、用药记录等)。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
在您使用预约挂号、在线咨询、随访管理等服务时,我们会收集您的就诊记录、咨询内容、医生诊断信息等相关医疗健康数据。这些信息的收集对于提供准确的医疗服务是必要的。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
我们还会自动收集设备信息(设备型号、操作系统版本)、日志信息(访问时间、页面浏览记录)和位置信息(用于推荐就近医疗机构)。以上信息的收集均经过您的授权同意,您可以在系统设置中随时关闭相关权限。
</p>
</div>
<!-- 二、信息的使用 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">二、信息的使用</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
我们收集的信息将用于:为您提供健康管理服务(健康数据记录与追踪、趋势分析、异常提醒)、预约挂号与在线咨询服务、个性化健康建议推送、随访管理和复诊提醒等核心医疗健康服务功能。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
在您授权同意的前提下,我们还可能将您的信息用于:改善服务体验和产品质量、开发新的健康管理功能、进行与健康相关的科学研究(所有研究数据均经过脱敏处理,不会识别到特定个人)。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
我们承诺不会将您的个人健康信息用于向您推送商业广告,不会将您的数据出售给任何第三方。所有数据使用均严格限定在本政策声明的范围内,超出范围的使用将再次征得您的明确同意。
</p>
</div>
<!-- 三、信息的共享 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">三、信息的共享</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
除以下情形外,我们不会与任何第三方共享您的个人信息:经您事先同意的共享、为提供您要求的服务而必需的共享(如与预约医院、咨询医生共享您的挂号和健康档案信息)、与关联公司共享(仅限于提供统一健康管理服务的目的)。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
根据法律法规规定或行政、司法机关的强制性要求,我们可能需要共享您的个人信息。在此类情况下,我们将要求接收方对您的信息采取保密措施,并仅用于法律规定的目的。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
我们与第三方服务提供商共享信息时,将签署严格的保密协议和数据保护协议,要求第三方仅可在约定的范围内处理您的信息,并采取不低于本平台标准的安全保护措施。我们将定期评估第三方的数据保护能力。
</p>
</div>
<!-- 四、您的权利 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">四、您的权利</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
您对您的个人信息享有知情权、访问权、更正权、删除权、可携带权和撤回同意的权利。您可以通过平台的"个人中心"或"隐私设置"功能,查看、修改、导出或删除您的个人信息和健康数据。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
您有权撤回之前授予我们的信息收集和使用同意。撤回同意不会影响之前基于同意已进行的信息处理活动的合法性。但撤回同意可能导致您无法继续使用部分需要相关个人信息的服务功能。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
如果您认为我们对您的信息处理违反了法律法规或本政策,您有权向相关主管部门进行投诉或举报。您也可以通过平台客服渠道(客服电话: 400-000-0000与我们取得联系我们将在15个工作日内予以回复。
</p>
</div>
<!-- 五、信息安全 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">五、信息安全</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
我们采用业界领先的技术手段保护您的信息安全包括但不限于传输层加密TLS 1.3、数据存储加密AES-256-GCM、多因素身份验证、访问权限控制和安全审计日志。所有敏感个人健康信息均经过加密存储和传输。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
我们建立了完善的数据安全管理制度,对员工进行定期安全培训,严格限制员工对用户个人信息的访问权限。仅经授权的人员方可访问必要的个人信息,且所有访问行为均有记录并接受审计。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
如不幸发生个人信息安全事件,我们将按照法律法规的要求,及时向您告知安全事件的基本情况、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议以及对您的补救措施。我们将以推送通知、短信或邮件方式通知您。
</p>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户协议 - 健康管理</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">用户协议 · user-agreement</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">用户协议</span>
</div>
<div class="content">
<div class="page-shell">
<h1 style="font-size:var(--font-h1);font-weight:600;color:var(--tx);text-align:center;margin-bottom:8px;">健康管理平台用户服务协议</h1>
<p style="font-size:var(--font-cap);color:var(--tx3);text-align:center;margin-bottom:var(--gap-lg);">更新日期2026年1月1日</p>
<!-- 一、服务条款的确认和接纳 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">一、服务条款的确认和接纳</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
本协议是您与健康管理平台(以下简称"本平台")之间关于使用本平台服务所订立的协议。请您仔细阅读本协议,在确认充分理解并同意后再开始使用本平台服务。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
您一旦使用本平台服务,即视为您已阅读并同意本协议的约束。本平台有权在必要时修改本协议内容,修改后的协议一经公布即有效替代原协议。您可以随时在本平台查阅最新版本的服务协议。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
本平台提供的健康信息服务仅供健康管理和参考之用,不能替代专业医疗机构执业医师的诊断和治疗建议。如有身体不适,请及时前往正规医疗机构就诊。
</p>
</div>
<!-- 二、用户注册 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">二、用户注册</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
用户注册时需提供真实、准确、完整的个人资料,并保持资料的及时更新。因注册信息不真实、不准确或不完整而引起的问题,由用户自行承担相应责任。本平台将对用户提交的注册信息进行严格保密。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
用户应妥善保管账号和密码,因用户保管不当造成的任何损失由用户自行承担。如发现账号被非法使用或存在安全漏洞,请立即通知本平台。每个用户仅可注册一个账号,禁止转让、售卖或出借账号。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
用户在使用本平台医疗服务时,应提供真实有效的身份信息和健康数据,确保医疗服务的准确性和安全性。虚假信息可能导致误诊或其他健康风险。
</p>
</div>
<!-- 三、隐私保护 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">三、隐私保护</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
本平台高度重视用户隐私保护,严格遵守《中华人民共和国个人信息保护法》、《中华人民共和国数据安全法》及相关法律法规。我们采取先进的技术手段保护您的个人信息安全,包括但不限于数据加密、访问控制和安全审计。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
我们收集的用户健康信息仅用于提供健康管理服务、改善服务质量及经您同意的其他用途。未经您的明确授权,我们不会向任何第三方披露您的个人健康信息,法律法规另有规定的除外。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
您可以随时查看、修改或删除您的个人信息。如需注销账号,可通过平台设置功能或联系客服办理。注销后我们将依法删除您的个人信息或进行匿名化处理。详细的隐私保护政策请参阅《隐私政策》。
</p>
</div>
<!-- 四、免责声明 -->
<div class="section">
<h2 style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx);margin-bottom:12px;">四、免责声明</h2>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
本平台提供的所有健康资讯、数据分析报告、健康建议等内容均基于公开医学文献和通用健康知识,仅供健康管理和日常参考,不构成任何形式的医疗诊断或治疗方案。用户应根据自身情况,在专业医师指导下进行医疗决策。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;margin-bottom:12px;">
因不可抗力、系统故障、网络中断等原因导致服务中断或数据丢失的,本平台不承担赔偿责任,但将尽最大努力减少用户损失。本平台不对第三方链接的内容或服务负责。
</p>
<p style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.8;">
用户因不当使用本平台服务或违反本协议约定而导致的任何直接或间接损失,由用户自行承担全部责任。本平台保留在法律允许范围内对免责条款进行解释的权利。
</p>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康告警 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">健康告警</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">紧急</div>
<div class="filter-pill">重要</div>
<div class="filter-pill">一般</div>
</div>
<!-- Alert Card List -->
<div class="card-list card-list--md">
<!-- Alert 1: Danger / 紧急 -->
<div class="card" style="border-left:4px solid var(--danger)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">血压持续偏高</span>
<span class="tag tag--error">紧急</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.6;margin-bottom:var(--gap-xs)">近3天收缩压持续高于140mmHg建议尽快就医</div>
<div class="time-label">2小时前 &middot; 自动检测</div>
</div>
<!-- Alert 2: Warning / 重要 -->
<div class="card" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">血糖异常波动</span>
<span class="tag tag--warning">重要</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.6;margin-bottom:var(--gap-xs)">今日餐后血糖8.9mmol/L较昨日上升2.1</div>
<div class="time-label">4小时前 &middot; 自动检测</div>
</div>
<!-- Alert 3: Warning / 重要 -->
<div class="card" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">心率过快提醒</span>
<span class="tag tag--warning">重要</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.6;margin-bottom:var(--gap-xs)">静息心率95次/分,高于正常范围</div>
<div class="time-label">昨天 &middot; 设备同步</div>
</div>
<!-- Alert 4: Info / 一般 -->
<div class="card" style="border-left:4px solid var(--info)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">用药计划调整</span>
<span class="tag tag--info">一般</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.6;margin-bottom:var(--gap-xs)">根据最新检查结果,建议调整用药方案</div>
<div class="time-label">3天前 &middot; 医生建议</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>日常监测 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">日常监测</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Date Selector (Horizontal Scroll) -->
<div style="display:flex;gap:var(--gap-xs);margin-bottom:var(--gap-md);overflow-x:auto;-webkit-overflow-scrolling:touch">
<div class="filter-pill">5/14</div>
<div class="filter-pill">5/15</div>
<div class="filter-pill filter-pill--active">5/16</div>
<div class="filter-pill">5/17</div>
<div class="filter-pill">5/18</div>
</div>
<!-- Summary Card -->
<div class="card mb-lg">
<div class="flex-between" style="margin-bottom:var(--gap-sm)">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:500">今日完成 3/5 项</span>
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600">60%</span>
</div>
<div class="progress">
<div class="progress__bar" style="width:60%"></div>
</div>
</div>
<!-- Pending Tasks -->
<div class="section">
<div class="section-title">
<div class="section-title__bar" style="background:var(--warning)"></div>
<div class="section-title__text">待完成</div>
<span class="badge">2</span>
</div>
<div class="card-list">
<!-- Pending Task 1 -->
<div class="list-item" style="border-left:3px solid var(--warning)">
<div class="list-item__icon list-item__icon--amber">&#x1FA78;</div>
<div class="list-item__content">
<div class="list-item__title">血糖测量</div>
<div class="list-item__desc">请记录餐后血糖</div>
</div>
<div class="list-item__right">
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Pending Task 2 -->
<div class="list-item" style="border-left:3px solid var(--warning)">
<div class="list-item__icon list-item__icon--amber">&#x1F48A;</div>
<div class="list-item__content">
<div class="list-item__title">用药打卡</div>
<div class="list-item__desc">降压药 &middot; 待服用</div>
</div>
<div class="list-item__right">
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
<!-- Completed Tasks -->
<div class="section">
<div class="section-title">
<div class="section-title__bar" style="background:var(--success)"></div>
<div class="section-title__text">已完成</div>
</div>
<div class="card-list">
<!-- Completed Task 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green" style="font-size:18px">&#x2705;</div>
<div class="list-item__content">
<div class="list-item__title">血压测量</div>
<div class="list-item__desc">125/82 mmHg &middot; 08:30</div>
</div>
<div class="list-item__right">
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<!-- Completed Task 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green" style="font-size:18px">&#x2705;</div>
<div class="list-item__content">
<div class="list-item__title">体重记录</div>
<div class="list-item__desc">68.5 kg &middot; 07:15</div>
</div>
<div class="list-item__right">
<span class="tag tag--default tag--sm">已记录</span>
</div>
</div>
<!-- Completed Task 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green" style="font-size:18px">&#x2705;</div>
<div class="list-item__content">
<div class="list-item__title">心率测量</div>
<div class="list-item__desc">72 次/分 &middot; 08:35</div>
</div>
<div class="list-item__right">
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,152 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设备同步 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">设备同步</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Connection Status Card -->
<div class="card mb-lg">
<div class="flex-row" style="gap:var(--gap-sm);margin-bottom:var(--gap-md)">
<div class="list-item__icon list-item__icon--blue" style="font-size:24px">&#x1F4E1;</div>
<div style="flex:1">
<div style="font-size:var(--font-body);font-weight:600;color:var(--success)">蓝牙已连接</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-top:4px">华为智能手表 Band 8</div>
</div>
</div>
<div class="info-row">
<span class="info-row__label">电量</span>
<span class="info-row__value" style="display:flex;align-items:center;gap:8px">
<div class="progress" style="width:60px">
<div class="progress__bar" style="width:75%;background:var(--success)"></div>
</div>
<span style="font-size:var(--font-body-sm);color:var(--tx)">75%</span>
</span>
</div>
<div class="info-row">
<span class="info-row__label">最后同步</span>
<span class="info-row__value">2分钟前</span>
</div>
<div style="margin-top:var(--gap-md)">
<button class="btn btn--primary btn--sm" style="width:100%">同步数据</button>
</div>
</div>
<!-- Today's Sync Data -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">今日同步数据</div>
</div>
<div class="card">
<div class="info-row">
<span class="info-row__label">步数</span>
<span class="info-row__value text-pri font-serif font-bold">6,842 步</span>
</div>
<div class="info-row">
<span class="info-row__label">心率</span>
<span class="info-row__value">72 次/分</span>
</div>
<div class="info-row">
<span class="info-row__label">血氧</span>
<span class="info-row__value">98%</span>
</div>
<div class="info-row">
<span class="info-row__label">睡眠</span>
<span class="info-row__value">7.2 小时</span>
</div>
<div class="info-row">
<span class="info-row__label">压力</span>
<span class="info-row__value" style="display:flex;align-items:center;gap:8px">
45
<span class="tag tag--success tag--sm">较低</span>
</span>
</div>
</div>
</div>
<!-- Sync History -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">同步历史</div>
</div>
<div class="card-list">
<!-- History 1 -->
<div class="list-item">
<div class="list-item__content">
<div class="list-item__title">05/16 08:30</div>
<div class="list-item__desc">5项数据已同步</div>
</div>
<div class="list-item__right">
<span class="tag tag--success tag--sm">成功</span>
</div>
</div>
<!-- History 2 -->
<div class="list-item">
<div class="list-item__content">
<div class="list-item__title">05/15 20:15</div>
<div class="list-item__desc">5项数据已同步</div>
</div>
<div class="list-item__right">
<span class="tag tag--success tag--sm">成功</span>
</div>
</div>
<!-- History 3 -->
<div class="list-item">
<div class="list-item__content">
<div class="list-item__title">05/14 08:45</div>
<div class="list-item__desc">3项数据已同步</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning tag--sm">部分失败</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>体征录入 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">体征录入</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Category Selector Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill filter-pill--active">血压</div>
<div class="filter-pill">血糖</div>
<div class="filter-pill">心率</div>
<div class="filter-pill">体重</div>
<div class="filter-pill">体温</div>
</div>
<!-- Blood Pressure Form Card -->
<div class="card mb-lg">
<div style="font-size:var(--font-h2);font-weight:600;color:var(--tx);margin-bottom:var(--gap-md)">血压记录</div>
<!-- 测量时间 -->
<div class="form-group">
<label class="form-label form-label--required">测量时间</label>
<input type="text" class="form-input" value="2026-05-16 09:30" readonly>
</div>
<!-- 收缩压 -->
<div class="form-group">
<label class="form-label form-label--required">收缩压</label>
<div style="position:relative">
<input type="text" class="form-input" placeholder="请输入收缩压" style="padding-right:60px">
<span style="position:absolute;right:16px;top:50%;transform:translateY(-50%);font-size:var(--font-body-sm);color:var(--tx3)">mmHg</span>
</div>
</div>
<!-- 舒张压 -->
<div class="form-group">
<label class="form-label form-label--required">舒张压</label>
<div style="position:relative">
<input type="text" class="form-input" placeholder="请输入舒张压" style="padding-right:60px">
<span style="position:absolute;right:16px;top:50%;transform:translateY(-50%);font-size:var(--font-body-sm);color:var(--tx3)">mmHg</span>
</div>
</div>
<!-- 测量时段 -->
<div class="form-group">
<label class="form-label">测量时段</label>
<select class="form-select">
<option>早晨</option>
<option>中午</option>
<option>晚上</option>
<option>睡前</option>
</select>
</div>
<!-- 备注 -->
<div class="form-group" style="margin-bottom:0">
<label class="form-label">备注</label>
<textarea class="form-textarea" placeholder="添加备注..." style="min-height:80px"></textarea>
</div>
</div>
<!-- Recent Records -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">最近记录</div>
</div>
<div class="card">
<div class="info-row">
<span class="info-row__label">05/16 08:30</span>
<span class="info-row__value" style="display:flex;align-items:center;gap:8px">
125/82 mmHg
<span class="tag tag--success tag--sm">正常</span>
</span>
</div>
<div class="info-row">
<span class="info-row__label">05/15 20:15</span>
<span class="info-row__value" style="display:flex;align-items:center;gap:8px">
132/88 mmHg
<span class="tag tag--warning tag--sm">偏高</span>
</span>
</div>
<div class="info-row">
<span class="info-row__label">05/15 07:45</span>
<span class="info-row__value" style="display:flex;align-items:center;gap:8px">
120/78 mmHg
<span class="tag tag--success tag--sm">正常</span>
</span>
</div>
</div>
</div>
<!-- Submit Button -->
<div style="margin-top:var(--gap-lg)">
<button class="btn btn--primary btn--full">保存记录</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,150 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>趋势分析 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">趋势分析</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Metric Selector Pills -->
<div class="filter-pills mb-sm">
<div class="filter-pill filter-pill--active">血压</div>
<div class="filter-pill">血糖</div>
<div class="filter-pill">心率</div>
<div class="filter-pill">体重</div>
<div class="filter-pill">血氧</div>
</div>
<!-- Time Range Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill">7天</div>
<div class="filter-pill filter-pill--active">30天</div>
<div class="filter-pill">90天</div>
<div class="filter-pill">1年</div>
</div>
<!-- Chart Card -->
<div class="card mb-md">
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx);margin-bottom:var(--gap-sm)">近30天收缩压趋势</div>
<!-- CSS Bar Chart -->
<div style="height:200px;display:flex;align-items:flex-end;gap:12px;padding:16px 0 0;position:relative">
<!-- Reference line at ~140 mmHg (high threshold) -->
<div style="position:absolute;top:20px;left:0;right:0;border-top:1.5px dashed var(--danger);opacity:0.4"></div>
<div style="position:absolute;top:16px;right:0;font-size:11px;color:var(--danger);opacity:0.6">140</div>
<!-- Bars -->
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:130px;background:var(--pri);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">4/16</span>
</div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:145px;background:var(--danger);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">4/20</span>
</div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:125px;background:var(--pri);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">4/24</span>
</div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:150px;background:var(--danger);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">4/28</span>
</div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:120px;background:var(--pri);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">5/2</span>
</div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:135px;background:var(--pri);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">5/6</span>
</div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px">
<div style="width:100%;height:118px;background:var(--pri);border-radius:4px 4px 0 0;opacity:0.85"></div>
<span style="font-size:11px;color:var(--tx3)">5/10</span>
</div>
</div>
<div style="font-size:11px;color:var(--tx3);margin-top:8px;text-align:center">单位: mmHg</div>
</div>
<!-- Stats Row -->
<div class="stat-grid mb-lg">
<div class="stat-card stat-card--primary">
<div class="stat-card__value">128</div>
<div class="stat-card__label">平均值 mmHg</div>
</div>
<div class="stat-card stat-card--danger">
<div class="stat-card__value">145</div>
<div class="stat-card__label">最高值 mmHg</div>
</div>
<div class="stat-card stat-card--success">
<div class="stat-card__value">118</div>
<div class="stat-card__label">最低值 mmHg</div>
</div>
</div>
<!-- Abnormal Records -->
<div class="section">
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">异常记录</div>
</div>
<div class="card-list">
<!-- Record 1 -->
<div class="card">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--tx2)">2026-05-08 14:30</span>
<span class="tag tag--error">偏高</span>
</div>
<div style="font-size:var(--font-body);color:var(--tx);font-weight:500">收缩压 152 mmHg</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:4px">超出正常范围 (90-140 mmHg)</div>
</div>
<!-- Record 2 -->
<div class="card">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--tx2)">2026-04-25 08:15</span>
<span class="tag tag--error">偏高</span>
</div>
<div style="font-size:var(--font-body);color:var(--tx);font-weight:500">收缩压 148 mmHg</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:4px">超出正常范围 (90-140 mmHg)</div>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>待办事项 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">待办事项</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">紧急</div>
<div class="filter-pill">今日</div>
<div class="filter-pill">本周</div>
</div>
<!-- Action Card List -->
<div class="card-list card-list--md">
<!-- Action 1: 紧急 -->
<div class="card card--pressable" style="border-left:4px solid var(--danger)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">📋 报告审核</span>
<span class="tag tag--error">紧急</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:4px">王刚 - 血常规报告</div>
<div class="flex-between">
<span class="time-label">今日 10:30</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Action 2: 紧急 -->
<div class="card card--pressable" style="border-left:4px solid var(--danger)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">📝 方案调整</span>
<span class="tag tag--error">紧急</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:4px">刘洋 - 透析方案</div>
<div class="flex-between">
<span class="time-label">今日 09:00</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Action 3: 重要 -->
<div class="card card--pressable" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">📅 随访计划</span>
<span class="tag tag--warning">重要</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:4px">陈红 - 制定2周随访计划</div>
<div class="flex-between">
<span class="time-label">本周五</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Action 4: 重要 -->
<div class="card card--pressable" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">💊 用药审核</span>
<span class="tag tag--warning">重要</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:4px">赵丽 - 新处方审核</div>
<div class="flex-between">
<span class="time-label">明日</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Action 5: 一般 -->
<div class="card card--pressable" style="border-left:4px solid var(--info)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">📊 数据分析</span>
<span class="tag tag--info">一般</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:4px">张伟 - 月度趋势分析</div>
<div class="flex-between">
<span class="time-label">本周</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>咨询详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title"></span>
</div>
<!-- Patient Info Bar (sticky) -->
<div style="display:flex;align-items:center;gap:var(--gap-xs);padding:var(--gap-xs) var(--page-pad);background:var(--card);border-bottom:1px solid var(--bd-light);position:sticky;top:0;z-index:10">
<div class="avatar avatar--sm"></div>
<div>
<span style="font-size:var(--font-body);font-weight:500;color:var(--tx)">张伟</span>
<span style="font-size:var(--font-body-sm);color:var(--tx3);margin-left:8px">55岁 · 高血压2级</span>
</div>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Chat List -->
<div class="chat-list">
<!-- Left bubble 1 -->
<div style="display:flex;flex-direction:column;align-items:flex-start">
<div class="chat-bubble chat-bubble--left">医生您好,我最近血压有点高,经常头晕。</div>
<span class="time-label" style="margin-top:4px;margin-left:4px">09:30</span>
</div>
<!-- Right bubble 1 -->
<div style="display:flex;flex-direction:column;align-items:flex-end">
<div class="chat-bubble chat-bubble--right">您好,请问头晕是什么时候开始的?有测量过血压吗?</div>
<span class="time-label" style="margin-top:4px;margin-right:4px">09:32</span>
</div>
<!-- Left bubble 2 -->
<div style="display:flex;flex-direction:column;align-items:flex-start">
<div class="chat-bubble chat-bubble--left">大概一周前开始的今早测了155/95。</div>
<span class="time-label" style="margin-top:4px;margin-left:4px">09:35</span>
</div>
<!-- Right bubble 2 -->
<div style="display:flex;flex-direction:column;align-items:flex-end">
<div class="chat-bubble chat-bubble--right">血压偏高,建议您先调整生活方式:低盐饮食、适当运动。我先给您调整一下用药方案,一周后复查。</div>
<span class="time-label" style="margin-top:4px;margin-right:4px">09:38</span>
</div>
<!-- Left bubble 3 -->
<div style="display:flex;flex-direction:column;align-items:flex-start">
<div class="chat-bubble chat-bubble--left">好的,谢谢医生!</div>
<span class="time-label" style="margin-top:4px;margin-left:4px">09:40</span>
</div>
</div>
</div>
</div>
<!-- Chat Input Bar (sticky bottom) -->
<div class="chat-input-bar">
<input class="chat-input-bar__field" type="text" placeholder="输入回复内容..." />
<button class="btn btn--primary btn--sm">发送</button>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>咨询列表 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">咨询列表</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Search -->
<div class="search-bar">
<span class="search-bar__icon">🔍</span>
<input class="search-bar__input" type="text" placeholder="搜索患者..." />
</div>
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">待回复</div>
<div class="filter-pill">进行中</div>
<div class="filter-pill">已结束</div>
</div>
<!-- Consultation Card List -->
<div class="card-list card-list--md mt-md">
<!-- Consultation 1: 待回复 -->
<div class="card card--pressable" style="position:relative">
<div style="display:flex;align-items:center;gap:var(--gap-sm)">
<div class="avatar avatar--sm"></div>
<div style="flex:1;min-width:0">
<div class="flex-between">
<span style="font-size:var(--font-body);font-weight:500;color:var(--tx)">张伟</span>
<div style="display:flex;align-items:center;gap:6px">
<span class="time-label">5分钟前</span>
<span class="badge">1</span>
</div>
</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:2px">心内科咨询</div>
</div>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-top:var(--gap-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">医生,我最近血压有点高...</div>
<div style="margin-top:var(--gap-xs);display:flex;justify-content:flex-end">
<span class="tag tag--warning">待回复</span>
</div>
</div>
<!-- Consultation 2: 已结束 -->
<div class="card card--pressable">
<div style="display:flex;align-items:center;gap:var(--gap-sm)">
<div class="avatar avatar--sm"></div>
<div style="flex:1;min-width:0">
<div class="flex-between">
<span style="font-size:var(--font-body);font-weight:500;color:var(--tx)">刘洋</span>
<span class="time-label">1小时前</span>
</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:2px">用药咨询</div>
</div>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-top:var(--gap-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">好的,谢谢医生</div>
<div style="margin-top:var(--gap-xs);display:flex;justify-content:flex-end">
<span class="tag tag--success">已结束</span>
</div>
</div>
<!-- Consultation 3: 进行中 -->
<div class="card card--pressable">
<div style="display:flex;align-items:center;gap:var(--gap-sm)">
<div class="avatar avatar--sm"></div>
<div style="flex:1;min-width:0">
<div class="flex-between">
<span style="font-size:var(--font-body);font-weight:500;color:var(--tx)">赵丽</span>
<span class="time-label">昨天</span>
</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:2px">检查咨询</div>
</div>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-top:var(--gap-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">想问一下报告怎么看</div>
<div style="margin-top:var(--gap-xs);display:flex;justify-content:flex-end">
<span class="tag tag--info">进行中</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>随访详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">随访详情</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Status Card -->
<div class="card mb-md" style="display:flex;align-items:center;justify-content:space-between">
<span class="tag tag--success" style="font-size:var(--font-body-sm);padding:6px 16px">已完成</span>
<span style="font-size:var(--font-body-sm);color:var(--tx3)">随访编号: FU20260515001</span>
</div>
<!-- Patient Card -->
<div class="card mb-md" style="display:flex;align-items:center;gap:var(--gap-sm)">
<div class="avatar"></div>
<div style="flex:1;min-width:0">
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx)">张伟 · 55岁</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:2px">高血压2级</div>
</div>
<span class="list-item__arrow">&rsaquo;</span>
</div>
<!-- Detail Card -->
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">随访方式</span>
<span class="info-row__value">电话随访</span>
</div>
<div class="info-row">
<span class="info-row__label">计划日期</span>
<span class="info-row__value">2026-05-15</span>
</div>
<div class="info-row">
<span class="info-row__label">完成日期</span>
<span class="info-row__value">2026-05-15 14:30</span>
</div>
<div class="info-row">
<span class="info-row__label">执行医生</span>
<span class="info-row__value">李明 主任医师</span>
</div>
</div>
<!-- Section: 随访内容 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">随访内容</div>
</div>
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">血压</span>
<span class="info-row__value">135/85 mmHg</span>
</div>
<div class="info-row">
<span class="info-row__label">心率</span>
<span class="info-row__value">76 次/分</span>
</div>
<div class="info-row">
<span class="info-row__label">体重</span>
<span class="info-row__value">72.5 kg</span>
</div>
<div class="info-row">
<span class="info-row__label">用药依从性</span>
<span class="info-row__value">良好</span>
</div>
<div class="info-row">
<span class="info-row__label">不良反应</span>
<span class="info-row__value"></span>
</div>
</div>
<!-- Section: 医生建议 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">医生建议</div>
</div>
<div class="card">
<div style="font-size:var(--font-body);color:var(--tx);line-height:1.7">患者血压控制较前改善继续当前方案2周后复查。注意低盐饮食每日监测血压。</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>随访列表 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">随访列表</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Search -->
<div class="search-bar">
<span class="search-bar__icon">🔍</span>
<input class="search-bar__input" type="text" placeholder="搜索患者..." />
</div>
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">待执行</div>
<div class="filter-pill">进行中</div>
<div class="filter-pill">已完成</div>
</div>
<!-- Followup Card List -->
<div class="card-list card-list--md mt-md">
<!-- Followup 1 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">王刚</span>
<span class="tag tag--warning">待执行</span>
</div>
<div style="display:flex;align-items:center;gap:var(--gap-xs);margin-bottom:4px">
<span class="chip">📞 电话随访</span>
<span class="chip">高血压3级</span>
</div>
<div class="flex-between">
<span class="time-label">计划日期: 2026-05-18</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Followup 2 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">陈红</span>
<span class="tag tag--info">进行中</span>
</div>
<div style="display:flex;align-items:center;gap:var(--gap-xs);margin-bottom:4px">
<span class="chip">🏥 门诊随访</span>
<span class="chip">2型糖尿病</span>
</div>
<div class="flex-between">
<span class="time-label">计划日期: 2026-05-20</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Followup 3 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">张伟</span>
<span class="tag tag--success">已完成</span>
</div>
<div style="display:flex;align-items:center;gap:var(--gap-xs);margin-bottom:4px">
<span class="chip">📞 电话随访</span>
<span class="chip">高血压2级</span>
</div>
<div class="flex-between">
<span class="time-label">计划日期: 2026-05-15</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Followup 4 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx)">赵丽</span>
<span class="tag tag--warning">待执行</span>
</div>
<div style="display:flex;align-items:center;gap:var(--gap-xs);margin-bottom:4px">
<span class="chip">🏠 家庭随访</span>
<span class="chip">冠心病</span>
</div>
<div class="flex-between">
<span class="time-label">计划日期: 2026-05-22</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,174 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>医生工作台 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">医生工作台</span>
<div class="nav-bar__actions">
<div style="position:relative;cursor:pointer">
<span style="font-size:20px">&#x1F464;</span>
<div class="badge" style="position:absolute;top:-6px;right:-8px">3</div>
</div>
</div>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Doctor Welcome Card -->
<div class="card mb-md" style="display:flex;align-items:center;gap:var(--gap-sm)">
<div class="avatar"></div>
<div style="flex:1;min-width:0">
<div style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx)">李明 主任医师</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px">心内科 · 第一人民医院</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-top:6px">今日待诊 <span class="font-serif font-bold">8</span> 人 · 已完成 <span class="font-serif font-bold">3</span></div>
</div>
</div>
<!-- Stat Grid -->
<div class="stat-grid mb-md">
<div class="stat-card stat-card--primary">
<div class="stat-card__value">12</div>
<div class="stat-card__label">待处理</div>
</div>
<div class="stat-card">
<div class="stat-card__value" style="color:var(--info)">8</div>
<div class="stat-card__label">今日预约</div>
</div>
<div class="stat-card">
<div class="stat-card__value" style="color:var(--warning)">5</div>
<div class="stat-card__label">咨询消息</div>
</div>
<div class="stat-card">
<div class="stat-card__value" style="color:var(--danger)">2</div>
<div class="stat-card__label">告警提醒</div>
</div>
</div>
<!-- Section: 待办事项 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div>
<div class="section-title__text">待办事项</div>
</div>
<div class="section-title__action">全部 &rsaquo;</div>
</div>
<div class="card-list mb-md">
<!-- Todo 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--amber">
<span>📋</span>
</div>
<div class="list-item__content">
<div class="list-item__title">患者王刚 - 复查报告审核</div>
<div class="list-item__desc">10:30</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">待处理</span>
</div>
</div>
<!-- Todo 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--red">
<span>⚠️</span>
</div>
<div class="list-item__content">
<div class="list-item__title">患者刘洋 - 透析方案调整</div>
<div class="list-item__desc">09:00</div>
</div>
<div class="list-item__right">
<span class="tag tag--error">紧急</span>
</div>
</div>
<!-- Todo 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">
<span>📝</span>
</div>
<div class="list-item__content">
<div class="list-item__title">患者陈红 - 随访计划制定</div>
<div class="list-item__desc">昨天</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">进行中</span>
</div>
</div>
</div>
<!-- Section: 今日预约 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div>
<div class="section-title__text">今日预约</div>
</div>
<div class="section-title__action">全部 &rsaquo;</div>
</div>
<div class="card-list">
<!-- Appointment 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">
<span></span>
</div>
<div class="list-item__content">
<div class="list-item__title">09:30 张伟</div>
<div class="list-item__desc">心内科门诊 · 初诊</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
</div>
</div>
<!-- Appointment 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--amber">
<span>🕐</span>
</div>
<div class="list-item__content">
<div class="list-item__title">10:00 赵芳</div>
<div class="list-item__desc">心内科门诊 · 复诊</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">待诊</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>患者详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">患者详情</span>
<div class="nav-bar__actions">
<span style="font-size:var(--font-body-sm);color:var(--pri);cursor:pointer">📝 编辑</span>
</div>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Patient Header Card -->
<div class="card mb-md" style="text-align:center">
<div class="avatar avatar--lg" style="margin:0 auto var(--gap-sm)"></div>
<div style="display:flex;align-items:center;justify-content:center;gap:8px;margin-bottom:6px">
<span style="font-size:var(--font-body-lg);font-weight:600;color:var(--tx)">王刚</span>
<span class="tag tag--error">高危</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3)">男 · 58岁 · ID: P20240001</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:4px">联系电话: 138****5678</div>
</div>
<!-- Quick Action Buttons -->
<div class="quick-grid mb-md">
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--orange">📋</div>
<span class="quick-item__label">健康档案</span>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--blue">📊</div>
<span class="quick-item__label">检验报告</span>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--green">💊</div>
<span class="quick-item__label">用药方案</span>
</div>
<div class="quick-item">
<div class="quick-item__icon quick-item__icon--amber">📅</div>
<span class="quick-item__label">随访计划</span>
</div>
</div>
<!-- Section: 基本信息 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">基本信息</div>
</div>
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">诊断</span>
<span class="info-row__value">高血压3级 · 冠心病</span>
</div>
<div class="info-row">
<span class="info-row__label">过敏史</span>
<span class="info-row__value">青霉素过敏</span>
</div>
<div class="info-row">
<span class="info-row__label">血型</span>
<span class="info-row__value">A型</span>
</div>
<div class="info-row">
<span class="info-row__label">紧急联系人</span>
<span class="info-row__value">王丽 (配偶) 139****1234</span>
</div>
</div>
<!-- Section: 最新检查 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div>
<div class="section-title__text">最新检查</div>
</div>
<div class="section-title__action">全部 &rsaquo;</div>
</div>
<div class="card mb-md" style="display:flex;align-items:center;gap:var(--gap-sm)">
<div class="list-item__icon list-item__icon--blue">
<span>🧪</span>
</div>
<div style="flex:1;min-width:0">
<div style="font-size:var(--font-body);font-weight:500;color:var(--tx)">血常规</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:2px">2026-05-10</div>
</div>
<span class="tag tag--warning">部分异常</span>
</div>
<!-- Section: 近期随访 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">近期随访</div>
</div>
<div class="card">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);font-weight:500;color:var(--tx)">电话随访</span>
<span class="time-label">2026-05-12</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);line-height:1.6">血压控制欠佳,建议调整用药</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>患者列表 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">患者列表</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Search -->
<div class="search-bar">
<span class="search-bar__icon">🔍</span>
<input class="search-bar__input" type="text" placeholder="搜索患者姓名/ID..." />
</div>
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">在诊</div>
<div class="filter-pill">透析</div>
<div class="filter-pill">随访中</div>
<div class="filter-pill">高危</div>
</div>
<!-- Patient Card List -->
<div class="card-list card-list--md mt-md">
<!-- Patient 1 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">王刚</div>
<div class="list-item__desc">男 58岁 · 高血压3级 · 冠心病</div>
</div>
<div class="list-item__right">
<span class="tag tag--error">高危</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Patient 2 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">刘洋</div>
<div class="list-item__desc">男 45岁 · 慢性肾病4期</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">透析中</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Patient 3 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">陈红</div>
<div class="list-item__desc">女 62岁 · 2型糖尿病 · 高血压</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">随访中</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Patient 4 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">张伟</div>
<div class="list-item__desc">男 55岁 · 高血压2级</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">稳定</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Patient 5 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">赵丽</div>
<div class="list-item__desc">女 70岁 · 冠心病 · 心衰</div>
</div>
<div class="list-item__right">
<span class="tag tag--default">在诊</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
<!-- Pagination -->
<div class="pagination">
<button class="pagination__btn" disabled>上一页</button>
<span class="pagination__info">第 1 / 3 页</span>
<button class="pagination__btn">下一页</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>告警详情 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / alert-detail</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">告警详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 告警头部卡片 -->
<div class="card mb-sm" style="background: var(--danger-light);">
<div class="flex-row gap-xs mb-xs">
<span class="tag tag--error">紧急</span>
</div>
<div class="font-bold" style="font-size: var(--font-h1); color: var(--danger);">血钾异常告警</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">告警时间: 2026-05-16 09:50</div>
</div>
<!-- 患者信息 -->
<div class="card mb-sm" style="display: flex; align-items: center; gap: var(--gap-sm);">
<div class="avatar"></div>
<div class="flex-1">
<div class="font-bold" style="font-size: var(--font-body-lg);">刘洋 · 男 45岁</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">慢性肾病4期</div>
</div>
</div>
<!-- 告警详情 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">告警详情</span>
</div>
<div class="card">
<div class="info-row">
<span class="info-row__label">异常指标</span>
<span class="info-row__value">血钾 (K&#8314;)</span>
</div>
<div class="info-row">
<span class="info-row__label">检测值</span>
<span class="info-row__value text-danger font-bold">5.8 mmol/L</span>
</div>
<div class="info-row">
<span class="info-row__label">正常范围</span>
<span class="info-row__value">3.5 - 5.3 mmol/L</span>
</div>
<div class="info-row">
<span class="info-row__label">偏离程度</span>
<span class="info-row__value text-danger">+0.5 mmol/L (&#8593;9.4%)</span>
</div>
<div class="info-row">
<span class="info-row__label">检测时间</span>
<span class="info-row__value">2026-05-16 07:30</span>
</div>
</div>
<!-- 建议措施 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">建议措施</span>
</div>
<div class="card">
<div style="font-size: var(--font-body); line-height: 2;">
<div>1. 立即通知主管医生</div>
<div>2. 复查电解质</div>
<div>3. 评估透析方案</div>
<div>4. 必要时紧急透析</div>
</div>
</div>
<!-- 操作按钮 -->
<div style="margin-top: var(--gap-lg); display: flex; flex-direction: column; gap: var(--gap-sm);">
<button class="btn btn--primary btn--full">标记已处理</button>
<button class="btn btn--outline btn--full">转交同事</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,88 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>临床告警 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / alerts</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">临床告警</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 过滤标签 -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">紧急</div>
<div class="filter-pill">重要</div>
<div class="filter-pill">一般</div>
</div>
<!-- 告警列表 -->
<div class="card-list" style="margin-top: var(--gap-md);">
<!-- 告警1: 紧急 (红色左边框) -->
<div class="card card--pressable" style="border-left: 3px solid var(--danger);">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">血钾异常</span>
<span class="tag tag--error">紧急</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">患者刘洋血钾5.8mmol/L需紧急处理</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">10分钟前</div>
</div>
<!-- 告警2: 重要 (琥珀色左边框) -->
<div class="card card--pressable" style="border-left: 3px solid var(--warning);">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">透析参数异常</span>
<span class="tag tag--warning">重要</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">患者王芳透析中超滤量偏差&#62;15%</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">1小时前</div>
</div>
<!-- 告警3: 重要 (琥珀色左边框) -->
<div class="card card--pressable" style="border-left: 3px solid var(--warning);">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">用药冲突</span>
<span class="tag tag--warning">重要</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">患者张伟新处方与现有用药存在潜在交互</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2小时前</div>
</div>
<!-- 告警4: 一般 (蓝色左边框) -->
<div class="card card--pressable" style="border-left: 3px solid var(--info);">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">检查到期</span>
<span class="tag tag--info">一般</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">3名患者本周需复查肾功能</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">今天</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>创建透析记录 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / dialysis-create</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">创建透析记录</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 患者选择 -->
<div class="card mb-sm">
<div class="form-group" style="margin-bottom: 0;">
<label class="form-label form-label--required">选择患者</label>
<select class="form-select">
<option selected>刘洋 - 男 45岁</option>
<option>王芳 - 女 52岁</option>
<option>张强 - 男 60岁</option>
</select>
</div>
</div>
<!-- 透析基本信息表单 -->
<div class="card">
<div class="form-group">
<label class="form-label form-label--required">透析方式</label>
<select class="form-select">
<option>HD (血液透析)</option>
<option selected>HDF (血液透析滤过)</option>
<option>HF (血液滤过)</option>
</select>
</div>
<div class="form-group">
<label class="form-label form-label--required">透析日期</label>
<input class="form-input" type="date" value="2026-05-16">
</div>
<div class="form-group">
<label class="form-label form-label--required">开始时间</label>
<input class="form-input" type="time" value="08:00">
</div>
<div class="form-group">
<label class="form-label form-label--required">预计时长</label>
<select class="form-select">
<option>2小时</option>
<option>3小时</option>
<option>3.5小时</option>
<option selected>4小时</option>
<option>4.5小时</option>
<option>5小时</option>
</select>
</div>
<div class="form-group">
<label class="form-label form-label--required">血管通路</label>
<select class="form-select">
<option selected>动静脉内瘘</option>
<option>中心静脉导管</option>
<option>人工血管</option>
</select>
</div>
<div class="form-group">
<label class="form-label">透析器型号</label>
<select class="form-select">
<option>FX60</option>
<option selected>FX80</option>
<option>FX100</option>
</select>
</div>
<div class="form-group">
<label class="form-label form-label--required">抗凝方式</label>
<select class="form-select">
<option selected>低分子肝素</option>
<option>普通肝素</option>
<option>无抗凝</option>
</select>
</div>
<div class="form-group" style="margin-bottom: 0;">
<label class="form-label">抗凝剂量</label>
<input class="form-input" type="text" value="4000 IU" placeholder="输入剂量">
</div>
</div>
<!-- 透析参数 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">透析参数</span>
</div>
<div class="card">
<div class="form-group">
<label class="form-label">目标血流量</label>
<input class="form-input" type="text" value="280 ml/min" placeholder="输入血流量">
</div>
<div class="form-group">
<label class="form-label">目标超滤量</label>
<input class="form-input" type="text" value="2500 ml" placeholder="输入超滤量">
</div>
<div class="form-group" style="margin-bottom: 0;">
<label class="form-label">透析液流量</label>
<select class="form-select">
<option>300 ml/min</option>
<option>400 ml/min</option>
<option selected>500 ml/min</option>
<option>600 ml/min</option>
</select>
</div>
</div>
<!-- 提交按钮 -->
<div style="margin-top: var(--gap-lg);">
<button class="btn btn--primary btn--full">保存透析记录</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透析详情 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / dialysis-detail</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">透析详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 状态卡片 -->
<div class="card mb-sm">
<div class="flex-between">
<span class="tag tag--success">已完成</span>
<span class="text-tx3" style="font-size: var(--font-body-sm);">透析编号: D20260515001</span>
</div>
</div>
<!-- 患者信息卡片 -->
<div class="card mb-sm" style="display: flex; align-items: center; gap: var(--gap-sm);">
<div class="avatar"></div>
<div class="flex-1">
<div class="font-bold" style="font-size: var(--font-body-lg);">王芳 · 52岁 · 女</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">慢性肾病5期</div>
</div>
</div>
<!-- 透析基本信息 -->
<div class="card">
<div class="info-row">
<span class="info-row__label">透析方式</span>
<span class="info-row__value">HDF (血液透析滤过)</span>
</div>
<div class="info-row">
<span class="info-row__label">透析时长</span>
<span class="info-row__value">4小时</span>
</div>
<div class="info-row">
<span class="info-row__label">血管通路</span>
<span class="info-row__value">动静脉内瘘</span>
</div>
<div class="info-row">
<span class="info-row__label">透析器</span>
<span class="info-row__value">FX80</span>
</div>
<div class="info-row">
<span class="info-row__label">抗凝方式</span>
<span class="info-row__value">低分子肝素</span>
</div>
<div class="info-row">
<span class="info-row__label">透析液</span>
<span class="info-row__value">碳酸氢盐</span>
</div>
</div>
<!-- 透析参数 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">透析参数</span>
</div>
<div class="card">
<div class="info-row">
<span class="info-row__label">血流量</span>
<span class="info-row__value">280 ml/min</span>
</div>
<div class="info-row">
<span class="info-row__label">透析液流量</span>
<span class="info-row__value">500 ml/min</span>
</div>
<div class="info-row">
<span class="info-row__label">超滤量</span>
<span class="info-row__value">2500 ml</span>
</div>
<div class="info-row">
<span class="info-row__label">透析前体重</span>
<span class="info-row__value">65.2 kg</span>
</div>
<div class="info-row">
<span class="info-row__label">透析后体重</span>
<span class="info-row__value">62.7 kg</span>
</div>
<div class="info-row">
<span class="info-row__label">干体重</span>
<span class="info-row__value">62.5 kg</span>
</div>
</div>
<!-- 生命体征监测 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">生命体征监测</span>
</div>
<div class="stat-grid">
<div class="stat-card">
<div class="stat-card__label">透析前</div>
<div class="stat-card__value font-serif" style="font-size: var(--font-body); color: var(--tx);">BP 155/90</div>
<div class="stat-card__label">HR 82</div>
</div>
<div class="stat-card">
<div class="stat-card__label">透析中</div>
<div class="stat-card__value font-serif" style="font-size: var(--font-body); color: var(--tx);">BP 135/80</div>
<div class="stat-card__label">HR 78</div>
</div>
<div class="stat-card">
<div class="stat-card__label">透析后</div>
<div class="stat-card__value font-serif" style="font-size: var(--font-body); color: var(--tx);">BP 128/75</div>
<div class="stat-card__label">HR 72</div>
</div>
</div>
<!-- 并发症 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">并发症</span>
</div>
<div class="card">
<div class="text-tx2" style="font-size: var(--font-body); line-height: 1.6;">透析过程顺利,无低血压、肌肉痉挛等并发症。</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透析记录 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / dialysis</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">透析记录</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 搜索栏 -->
<div class="search-bar">
<span class="search-bar__icon">&#128269;</span>
<input class="search-bar__input" type="text" placeholder="搜索患者...">
</div>
<!-- 过滤标签 -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">进行中</div>
<div class="filter-pill">已完成</div>
<div class="filter-pill">已取消</div>
</div>
<!-- 透析记录列表 -->
<div class="card-list" style="margin-top: var(--gap-md);">
<!-- 卡片1: 进行中 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">刘洋</span>
<span class="tag tag--info">进行中</span>
</div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">HD透析 · 4小时</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-16 08:00</div>
<div class="divider"></div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">血管通路: 动静脉内瘘</div>
</div>
<!-- 卡片2: 待开始 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">张强</span>
<span class="tag tag--warning">待开始</span>
</div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">HD透析 · 3.5小时</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-16 10:00</div>
<div class="divider"></div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">血管通路: 中心静脉导管</div>
</div>
<!-- 卡片3: 已完成 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">王芳</span>
<span class="tag tag--success">已完成</span>
</div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">HDF透析 · 4小时</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-15 14:00</div>
<div class="divider"></div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">超滤量: 2500ml</div>
</div>
<!-- 卡片4: 已取消 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">陈明</span>
<span class="tag tag--default">已取消</span>
</div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">HD透析 · 4小时</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-15 08:00</div>
<div class="divider"></div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">原因: 患者请假</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<button class="pagination__btn" disabled>上一页</button>
<span class="pagination__info">1 / 2</span>
<button class="pagination__btn">下一页</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>创建处方 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / prescription-create</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">创建处方</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 患者选择 -->
<div class="card mb-sm">
<div class="form-group" style="margin-bottom: 0;">
<label class="form-label form-label--required">选择患者</label>
<select class="form-select">
<option selected>王刚 - 男 58岁</option>
<option>刘洋 - 男 45岁</option>
<option>陈红 - 女 63岁</option>
</select>
</div>
</div>
<!-- 基本信息表单 -->
<div class="card">
<div class="form-group">
<label class="form-label form-label--required">诊断</label>
<input class="form-input" type="text" value="高血压3级">
</div>
<div class="form-group" style="margin-bottom: 0;">
<label class="form-label">有效天数</label>
<select class="form-select">
<option>7天</option>
<option>14天</option>
<option selected>30天</option>
<option>60天</option>
<option>90天</option>
</select>
</div>
</div>
<!-- 添加药品 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">添加药品</span>
</div>
<div class="card">
<div class="form-group">
<label class="form-label form-label--required">药品名称</label>
<input class="form-input" type="text" placeholder="搜索药品...">
</div>
<div class="form-group">
<label class="form-label">规格</label>
<input class="form-input" type="text" value="5mg">
</div>
<div class="form-group">
<label class="form-label">用法</label>
<select class="form-select">
<option selected>口服</option>
<option>注射</option>
<option>外用</option>
<option>舌下含服</option>
</select>
</div>
<div class="form-group">
<label class="form-label">频次</label>
<select class="form-select">
<option selected>每日一次 (qd)</option>
<option>每日两次 (bid)</option>
<option>每日三次 (tid)</option>
<option>每晚一次 (qn)</option>
<option>必要时 (prn)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">单次剂量</label>
<input class="form-input" type="text" value="1片">
</div>
<div class="form-group">
<label class="form-label">用量天数</label>
<input class="form-input" type="number" value="30">
</div>
<button class="btn btn--outline btn--sm btn--full">添加药品</button>
</div>
<!-- 已添加药品列表 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">已添加药品</span>
</div>
<div class="card mb-sm" style="display: flex; align-items: center; justify-content: space-between;">
<div>
<div class="font-bold" style="font-size: var(--font-body);">氨氯地平片 5mg</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">口服 · 每日一次 · 30天</div>
</div>
<div style="width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; color: var(--danger); font-size: 20px; cursor: pointer;">&#215;</div>
</div>
<!-- 医嘱备注 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">医嘱备注</span>
</div>
<div class="card">
<textarea class="form-textarea" placeholder="输入医嘱备注..." rows="3"></textarea>
</div>
<!-- 提交按钮 -->
<div style="margin-top: var(--gap-lg);">
<button class="btn btn--primary btn--full">保存处方</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>处方详情 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / prescription-detail</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">处方详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 状态卡片 -->
<div class="card mb-sm">
<div class="flex-between">
<span class="tag tag--success">活跃</span>
<span class="text-tx3" style="font-size: var(--font-body-sm);">处方编号: RX20260510001</span>
</div>
</div>
<!-- 患者信息 -->
<div class="card mb-sm" style="display: flex; align-items: center; gap: var(--gap-sm);">
<div class="avatar"></div>
<div class="flex-1">
<div class="font-bold" style="font-size: var(--font-body-lg);">王刚 · 58岁 · 男</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">高血压3级</div>
</div>
</div>
<!-- 处方信息 -->
<div class="card">
<div class="info-row">
<span class="info-row__label">开方日期</span>
<span class="info-row__value">2026-05-10</span>
</div>
<div class="info-row">
<span class="info-row__label">开方医生</span>
<span class="info-row__value">李明 主任医师</span>
</div>
<div class="info-row">
<span class="info-row__label">有效期至</span>
<span class="info-row__value">2026-08-10</span>
</div>
<div class="info-row">
<span class="info-row__label">诊断</span>
<span class="info-row__value">高血压3级 · 冠心病</span>
</div>
</div>
<!-- 药品明细 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">药品明细</span>
</div>
<!-- 药品1 -->
<div class="card mb-sm">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body);">氨氯地平片</span>
<span class="tag tag--info">长期用药</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">5mg</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">每日一次 · 口服</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">30天用量</div>
</div>
<!-- 药品2 -->
<div class="card mb-sm">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body);">缬沙坦胶囊</span>
<span class="tag tag--info">长期用药</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">80mg</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">每日一次 · 口服</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">30天用量</div>
</div>
<!-- 医嘱备注 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">医嘱备注</span>
</div>
<div class="card">
<div class="text-tx2" style="font-size: var(--font-body); line-height: 1.6;">低盐低脂饮食定期监测血压和肾功能。避免剧烈运动。2周后复查。</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>处方列表 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / prescription</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">处方列表</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 搜索栏 -->
<div class="search-bar">
<span class="search-bar__icon">&#128269;</span>
<input class="search-bar__input" type="text" placeholder="搜索患者/药品...">
</div>
<!-- 过滤标签 -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">活跃</div>
<div class="filter-pill">已停用</div>
<div class="filter-pill">已过期</div>
</div>
<!-- 处方列表 -->
<div class="card-list" style="margin-top: var(--gap-md);">
<!-- 处方1: 活跃 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">王刚</span>
<span class="tag tag--success">活跃</span>
</div>
<div class="font-bold text-tx2" style="font-size: var(--font-body-sm);">降压方案</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">氨氯地平 5mg qd + 缬沙坦 80mg qd</div>
<div class="divider"></div>
<div class="flex-between">
<span class="text-tx3" style="font-size: var(--font-cap);">2026-05-10</span>
<span class="text-tx2" style="font-size: var(--font-cap);">有效期至 2026-08-10</span>
</div>
</div>
<!-- 处方2: 活跃 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">刘洋</span>
<span class="tag tag--success">活跃</span>
</div>
<div class="font-bold text-tx2" style="font-size: var(--font-body-sm);">肾病方案</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">骨化三醇 0.25μg qd + 碳酸钙 600mg bid</div>
<div class="divider"></div>
<div class="flex-between">
<span class="text-tx3" style="font-size: var(--font-cap);">2026-05-08</span>
<span class="text-tx3" style="font-size: var(--font-cap);"></span>
</div>
</div>
<!-- 处方3: 即将过期 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">陈红</span>
<span class="tag tag--warning">即将过期</span>
</div>
<div class="font-bold text-tx2" style="font-size: var(--font-body-sm);">降糖方案</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-body-sm);">二甲双胍 500mg tid</div>
<div class="divider"></div>
<div class="flex-between">
<span class="text-tx3" style="font-size: var(--font-cap);">2026-04-15</span>
<span class="text-warning" style="font-size: var(--font-cap);">有效期至 2026-05-20</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,143 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>报告详情 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / report-detail</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">报告详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 报告头卡片 -->
<div class="card mb-sm">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">血常规 + 肝肾功能</span>
<span class="tag tag--success">已审核</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">患者: 王刚 · 男 58岁</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">采样时间: 2026-05-16 07:30</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">审核医生: 李明</div>
</div>
<!-- 血常规 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">血常规</span>
</div>
<div class="card">
<div class="info-row">
<span class="info-row__label">白细胞 (WBC)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">6.5 &#215;10&#8313;/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">红细胞 (RBC)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">4.2 &#215;10&#185;&#178;/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">血红蛋白 (HGB)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">135 g/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">血小板 (PLT)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">198 &#215;10&#8313;/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">中性粒细胞</span>
<div class="flex-row gap-xs">
<span class="info-row__value">68%</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
</div>
<!-- 肝肾功能 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">肝肾功能</span>
</div>
<div class="card">
<div class="info-row">
<span class="info-row__label">谷丙转氨酶 (ALT)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">28 U/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">谷草转氨酶 (AST)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">22 U/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">肌酐 (Cr)</span>
<div class="flex-row gap-xs">
<span class="info-row__value text-danger">112 &#181;mol/L</span>
<span class="tag tag--warning tag--sm">偏高 &#8593;</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">尿素氮 (BUN)</span>
<div class="flex-row gap-xs">
<span class="info-row__value">7.8 mmol/L</span>
<span class="tag tag--success tag--sm">正常</span>
</div>
</div>
<div class="info-row">
<span class="info-row__label">尿酸 (UA)</span>
<div class="flex-row gap-xs">
<span class="info-row__value text-danger">420 &#181;mol/L</span>
<span class="tag tag--warning tag--sm">偏高 &#8593;</span>
</div>
</div>
</div>
<!-- 医生备注 -->
<div class="section-title" style="margin-top: var(--section-gap);">
<div class="section-title__bar"></div>
<span class="section-title__text">医生备注</span>
</div>
<div class="card">
<div class="text-tx2" style="font-size: var(--font-body); line-height: 1.6;">肾功能指标轻度异常建议2周后复查继续监测。</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>检验报告 - HMS医生端</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="page-label">05-pkg-doctor-clinical / report</div>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&#8249;</div>
<span class="nav-bar__title">检验报告</span>
</div>
<div class="content">
<div class="page-shell">
<!-- 搜索栏 -->
<div class="search-bar">
<span class="search-bar__icon">&#128269;</span>
<input class="search-bar__input" type="text" placeholder="搜索患者...">
</div>
<!-- 过滤标签 -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">待审核</div>
<div class="filter-pill">已审核</div>
<div class="filter-pill">异常</div>
</div>
<!-- 报告列表 -->
<div class="card-list" style="margin-top: var(--gap-md);">
<!-- 报告1: 待审核 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">王刚</span>
<span class="tag tag--warning">待审核</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">血常规 + 肝肾功能</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-16</div>
<div class="divider"></div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">送检医生: 李明</div>
</div>
<!-- 报告2: 异常 -->
<div class="card card--pressable" style="border-left: 3px solid var(--danger);">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">刘洋</span>
<span class="tag tag--error">异常</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">电解质 + 甲状旁腺</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-16</div>
<div class="divider"></div>
<div class="text-danger" style="font-size: var(--font-body-sm);">血钾 5.8mmol/L &#8593;</div>
</div>
<!-- 报告3: 已审核 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">陈红</span>
<span class="tag tag--success">已审核</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">糖化血红蛋白</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-15</div>
<div class="divider"></div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">HbA1c 7.2%</div>
</div>
<!-- 报告4: 已审核 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span class="font-bold" style="font-size: var(--font-body-lg);">张伟</span>
<span class="tag tag--success">已审核</span>
</div>
<div class="text-tx2" style="font-size: var(--font-body-sm);">血脂全套</div>
<div class="text-tx3 mt-xs" style="font-size: var(--font-cap);">2026-05-14</div>
<div class="divider"></div>
<div class="text-tx3" style="font-size: var(--font-body-sm);">LDL-C 3.2mmol/L</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">商品详情</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell" style="padding-bottom:calc(var(--page-pad) + 80px)">
<!-- Product Image -->
<div class="card card--none mb-md" style="height:280px;background:var(--surface-alt);display:flex;align-items:center;justify-content:center;border-radius:var(--card-r);overflow:hidden">
<span style="font-size:var(--font-body-lg);color:var(--tx3)">&#x1F4F8; 商品图片</span>
</div>
<!-- Product Info -->
<div class="card mb-md">
<div style="font-size:var(--font-h1);font-weight:700;color:var(--tx);margin-bottom:var(--gap-xs)">智能电子血压计</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:var(--gap-sm)">欧姆龙 U722 &middot; 上臂式全自动</div>
<div class="flex-row" style="gap:var(--gap-sm);align-items:baseline">
<span style="font-size:var(--font-num-lg);font-weight:700;color:var(--pri);font-family:var(--font-serif)">1,200</span>
<span style="font-size:var(--font-body);color:var(--pri);font-weight:600">积分</span>
<span style="font-size:var(--font-body-sm);color:var(--tx3);text-decoration:line-through">市场价 &yen;299</span>
</div>
</div>
<!-- Section: Product Details -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">商品详情</div>
</div>
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">品牌</span>
<span class="info-row__value">欧姆龙</span>
</div>
<div class="info-row">
<span class="info-row__label">型号</span>
<span class="info-row__value">U722</span>
</div>
<div class="info-row">
<span class="info-row__label">测量方式</span>
<span class="info-row__value">上臂式</span>
</div>
<div class="info-row">
<span class="info-row__label">精度</span>
<span class="info-row__value">&plusmn;3mmHg</span>
</div>
<div class="info-row">
<span class="info-row__label">记忆功能</span>
<span class="info-row__value">60组</span>
</div>
<div class="info-row">
<span class="info-row__label">适用人群</span>
<span class="info-row__value">成人</span>
</div>
</div>
</div>
<!-- Bottom Action Bar (Sticky) -->
<div style="position:sticky;bottom:0;background:var(--card);padding:var(--gap-sm) var(--page-pad) calc(var(--gap-sm) + 34px);border-top:0.5px solid var(--bd-light);z-index:10">
<button class="btn btn--primary btn--full">立即兑换</button>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>兑换记录 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">兑换记录</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">待发货</div>
<div class="filter-pill">已发货</div>
<div class="filter-pill">已完成</div>
</div>
<!-- Exchange Card List -->
<div class="card-list card-list--md">
<!-- Exchange 1: Completed -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">智能电子血压计</span>
<span class="tag tag--success">已完成</span>
</div>
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;font-family:var(--font-serif)">-1,200积分</span>
<span class="time-label">2026-05-10</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3)">快递单号: SF1234567890</div>
</div>
<!-- Exchange 2: Shipped -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">维生素D补充剂</span>
<span class="tag tag--info">已发货</span>
</div>
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;font-family:var(--font-serif)">-350积分</span>
<span class="time-label">2026-05-14</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3)">预计5月17日送达</div>
</div>
<!-- Exchange 3: Pending -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">健康手环</span>
<span class="tag tag--warning">待发货</span>
</div>
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;font-family:var(--font-serif)">-800积分</span>
<span class="time-label">2026-05-16</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3)">正在备货中</div>
</div>
</div>
<!-- Pagination -->
<div class="pagination">
<button class="pagination__btn" disabled>&lsaquo; 上一页</button>
<span class="pagination__info">1 / 1</span>
<button class="pagination__btn" disabled>下一页 &rsaquo;</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>订单列表 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">订单列表</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">待处理</div>
<div class="filter-pill">配送中</div>
<div class="filter-pill">已完成</div>
<div class="filter-pill">已取消</div>
</div>
<!-- Order Card List -->
<div class="card-list card-list--md">
<!-- Order 1: Completed -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--tx2);font-family:var(--font-serif)">ORD20260510001</span>
<span class="time-label">2026-05-10</span>
</div>
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:var(--gap-xs)">智能电子血压计 &times; 1</div>
<div class="flex-between">
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;font-family:var(--font-serif)">-1,200积分</span>
<span class="tag tag--success">已完成</span>
</div>
</div>
<!-- Order 2: Shipping -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--tx2);font-family:var(--font-serif)">ORD20260514002</span>
<span class="time-label">2026-05-14</span>
</div>
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:var(--gap-xs)">维生素D补充剂 &times; 2</div>
<div class="flex-between">
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;font-family:var(--font-serif)">-700积分</span>
<span class="tag tag--info">配送中</span>
</div>
</div>
<!-- Order 3: Pending -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body-sm);color:var(--tx2);font-family:var(--font-serif)">ORD20260516003</span>
<span class="time-label">2026-05-16</span>
</div>
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:var(--gap-xs)">健康手环 &times; 1</div>
<div class="flex-between">
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:600;font-family:var(--font-serif)">-800积分</span>
<span class="tag tag--warning">待处理</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>知情同意书 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">知情同意书</span>
</div>
<div class="content">
<div class="page-shell">
<div class="card-list">
<!-- Consent 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128196;</div>
<div class="list-item__content">
<div class="list-item__title">透析治疗知情同意书</div>
<div class="list-item__desc">2026-01-15 签署</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已签署</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Consent 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128196;</div>
<div class="list-item__content">
<div class="list-item__title">血液透析知情同意书</div>
<div class="list-item__desc">2026-01-15 签署</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已签署</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Consent 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128196;</div>
<div class="list-item__content">
<div class="list-item__title">隐私数据处理同意书</div>
<div class="list-item__desc">2025-12-01 签署</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已签署</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>诊断记录 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">诊断记录</span>
</div>
<div class="content">
<div class="page-shell">
<div class="card-list">
<!-- Diagnosis 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--amber">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">高血压2级</div>
<div class="list-item__desc">2026-05-10 &middot; 李明 主任医师</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">活跃</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Diagnosis 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">2型糖尿病</div>
<div class="list-item__desc">2025-12-15 &middot; 王芳 副主任医师</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">管理中</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Diagnosis 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">高脂血症</div>
<div class="list-item__desc">2025-12-01 &middot; 李明 主任医师</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已控制</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Diagnosis 4 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">高血压1级</div>
<div class="list-item__desc">2020-03-20 &middot; 张三 主任医师</div>
</div>
<div class="list-item__right">
<span class="tag tag--default">历史</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>处方详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">处方详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Header Card -->
<div class="card mb-md">
<div class="flex-row" style="gap:var(--gap-sm);margin-bottom:var(--gap-xs)">
<span style="font-size:var(--font-h1);font-weight:600;color:var(--tx)">标准HDF处方</span>
<span class="tag tag--success">活跃</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3)">生效日期: 2026-05-01</div>
</div>
<!-- Detail Card -->
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">透析方式</span>
<span class="info-row__value">HDF</span>
</div>
<div class="info-row">
<span class="info-row__label">血流量</span>
<span class="info-row__value">280 ml/min</span>
</div>
<div class="info-row">
<span class="info-row__label">透析液流量</span>
<span class="info-row__value">500 ml/min</span>
</div>
<div class="info-row">
<span class="info-row__label">透析器</span>
<span class="info-row__value">FX80</span>
</div>
<div class="info-row">
<span class="info-row__label">抗凝</span>
<span class="info-row__value">低分子肝素 4000IU</span>
</div>
<div class="info-row">
<span class="info-row__label">目标超滤</span>
<span class="info-row__value">2500 ml</span>
</div>
<div class="info-row">
<span class="info-row__label">干体重</span>
<span class="info-row__value">62.5 kg</span>
</div>
</div>
<!-- Section: 备注 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">备注</div>
</div>
<div class="card">
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">
每周3次周一/三/五。注意监测血压和血钾。
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透析处方 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">透析处方</span>
</div>
<div class="content">
<div class="page-shell">
<div class="card-list">
<!-- Prescription 1: Active -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">标准HDF处方</div>
<div class="list-item__desc">2026-05-01生效 &middot; 血流量280ml/min &middot; 4小时</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">活跃</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Prescription 2: Ended -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">HD调整处方</div>
<div class="list-item__desc">2026-03-15 至 2026-04-30</div>
</div>
<div class="list-item__right">
<span class="tag tag--default">已结束</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Prescription 3: Ended -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">初始HD处方</div>
<div class="list-item__desc">2025-12-01 至 2026-03-14</div>
</div>
<div class="list-item__right">
<span class="tag tag--default">已结束</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透析详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">透析详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Status Card -->
<div class="card mb-md">
<div class="flex-row" style="gap:var(--gap-sm)">
<span class="tag tag--success">已完成</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:var(--gap-xs)">记录编号: D20260515001</div>
</div>
<!-- Info Card -->
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">透析方式</span>
<span class="info-row__value">HDF</span>
</div>
<div class="info-row">
<span class="info-row__label">时长</span>
<span class="info-row__value">4小时</span>
</div>
<div class="info-row">
<span class="info-row__label">血管通路</span>
<span class="info-row__value">动静脉内瘘</span>
</div>
<div class="info-row">
<span class="info-row__label">透析器</span>
<span class="info-row__value">FX80</span>
</div>
<div class="info-row">
<span class="info-row__label">超滤量</span>
<span class="info-row__value">2500ml</span>
</div>
</div>
<!-- Section: 体重变化 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">体重变化</div>
</div>
<div class="stat-grid mb-md">
<div class="stat-card stat-card--warning">
<div class="stat-card__value">65.2</div>
<div class="stat-card__label">透前 (kg)</div>
</div>
<div class="stat-card stat-card--success">
<div class="stat-card__value">62.7</div>
<div class="stat-card__label">透后 (kg)</div>
</div>
<div class="stat-card stat-card--primary">
<div class="stat-card__value">62.5</div>
<div class="stat-card__label">干体重 (kg)</div>
</div>
</div>
<!-- Section: 并发症 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">并发症</div>
</div>
<div class="card">
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">
透析过程顺利,无并发症。
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透析记录 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">透析记录</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">近1月</div>
<div class="filter-pill">近3月</div>
</div>
<!-- Record Cards -->
<div class="card-list mt-md">
<!-- Record 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#129516;</div>
<div class="list-item__content">
<div class="list-item__title">HDF透析</div>
<div class="list-item__desc">2026-05-15 &middot; 4小时 &middot; 超滤2500ml</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Record 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#129516;</div>
<div class="list-item__content">
<div class="list-item__title">HD透析</div>
<div class="list-item__desc">2026-05-12 &middot; 4小时 &middot; 超滤2300ml</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Record 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#129516;</div>
<div class="list-item__content">
<div class="list-item__title">HD透析</div>
<div class="list-item__desc">2026-05-09 &middot; 3.5小时 &middot; 超滤2100ml</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
<!-- Pagination -->
<div class="pagination">
<button class="pagination__btn" disabled>&lsaquo; 上一页</button>
<span class="pagination__info">1 / 5</span>
<button class="pagination__btn">下一页 &rsaquo;</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>长者模式 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">长者模式</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Toggle Card -->
<div class="card card--lg mb-md" style="text-align:center;padding:var(--gap-xl) var(--card-pad)">
<div style="font-size:var(--font-h1);font-weight:600;color:var(--tx);margin-bottom:var(--gap-xs)">长者模式</div>
<div style="font-size:var(--font-body);color:var(--tx2);margin-bottom:var(--gap-md);line-height:var(--line-height)">
开启后字体和图标将放大,操作更便捷
</div>
<div style="display:inline-flex;align-items:center;gap:var(--gap-sm);background:var(--success-light);padding:var(--gap-xs) var(--gap-md);border-radius:var(--r-pill)">
<div style="width:10px;height:10px;border-radius:50%;background:var(--success)"></div>
<span style="font-size:var(--font-body);color:var(--success);font-weight:500">已开启</span>
</div>
</div>
<!-- Section: 模式说明 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">模式说明</div>
</div>
<div class="card mb-lg">
<div style="display:flex;flex-direction:column;gap:var(--gap-md)">
<div class="flex-row" style="gap:var(--gap-sm)">
<div style="width:32px;height:32px;border-radius:var(--r-sm);background:var(--pri-light);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0">&#128290;</div>
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">字号放大 1.35 倍,确保文字清晰可读</div>
</div>
<div class="flex-row" style="gap:var(--gap-sm)">
<div style="width:32px;height:32px;border-radius:var(--r-sm);background:var(--pri-light);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0">&#128433;</div>
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">触摸目标放大至 56px减少误操作</div>
</div>
<div class="flex-row" style="gap:var(--gap-sm)">
<div style="width:32px;height:32px;border-radius:var(--r-sm);background:var(--pri-light);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0">&#128244;</div>
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">页面间距增加,信息更加疏朗</div>
</div>
</div>
</div>
<!-- Toggle Button -->
<button class="btn btn--primary btn--full">切换长者模式</button>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>线下活动 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">线下活动</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">即将开始</div>
<div class="filter-pill">进行中</div>
<div class="filter-pill">已结束</div>
</div>
<!-- Event Cards -->
<div class="card-list mt-md">
<!-- Event 1 -->
<div class="card card--pressable">
<div class="flex-row" style="gap:var(--gap-sm);margin-bottom:var(--gap-xs)">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx);flex:1">高血压患者健康讲座</span>
<span class="tag tag--warning">即将开始</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">2026-05-20 14:00</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-xs)">第一人民医院3楼会议室</div>
<div style="font-size:var(--font-cap);color:var(--tx2)">主讲: 李明主任 &middot; 限额30人</div>
</div>
<!-- Event 2 -->
<div class="card card--pressable">
<div class="flex-row" style="gap:var(--gap-sm);margin-bottom:var(--gap-xs)">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx);flex:1">肾友会线下交流活动</span>
<span class="tag tag--info">报名中</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">2026-05-25 09:00</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-xs)">社区健康中心</div>
<div style="font-size:var(--font-cap);color:var(--tx2)">已有18人报名</div>
</div>
<!-- Event 3 -->
<div class="card card--pressable">
<div class="flex-row" style="gap:var(--gap-sm);margin-bottom:var(--gap-xs)">
<span style="font-size:var(--font-body);font-weight:600;color:var(--tx);flex:1">糖尿病饮食工作坊</span>
<span class="tag tag--success">已结束</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">2026-05-10 10:00</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-xs)">营养科示教室</div>
<div style="font-size:var(--font-cap);color:var(--tx2)">参与人数: 25人</div>
</div>
</div>
<!-- More Button -->
<div class="mt-lg">
<button class="btn btn--outline btn--full">查看更多活动</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>添加家人 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">添加家人</span>
</div>
<div class="content">
<div class="page-shell">
<div class="card">
<!-- 姓名 -->
<div class="form-group">
<label class="form-label form-label--required">姓名</label>
<input class="form-input" type="text" placeholder="请输入家人姓名">
</div>
<!-- 关系 -->
<div class="form-group">
<label class="form-label form-label--required">关系</label>
<select class="form-select">
<option value="">请选择关系</option>
<option value="spouse">配偶</option>
<option value="child">子女</option>
<option value="parent">父母</option>
<option value="other">其他</option>
</select>
</div>
<!-- 身份证号 -->
<div class="form-group">
<label class="form-label">身份证号</label>
<input class="form-input" type="text" placeholder="请输入身份证号">
</div>
<!-- 联系电话 -->
<div class="form-group">
<label class="form-label">联系电话</label>
<input class="form-input" type="tel" placeholder="请输入联系电话">
</div>
<!-- 血型 -->
<div class="form-group">
<label class="form-label">血型</label>
<select class="form-select">
<option value="">请选择血型</option>
<option value="A">A型</option>
<option value="B">B型</option>
<option value="AB">AB型</option>
<option value="O">O型</option>
</select>
</div>
<!-- 过敏史 -->
<div class="form-group">
<label class="form-label">过敏史</label>
<textarea class="form-textarea" placeholder="请描述过敏情况,如无请填"""></textarea>
</div>
</div>
<!-- Submit Button -->
<div class="mt-lg">
<button class="btn btn--primary btn--full">提交</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,90 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>家人管理 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">家人管理</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Family Member List -->
<div class="card-list">
<!-- Member 1: 王丽 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">王丽</div>
<div class="list-item__desc">配偶 &middot; 55岁</div>
<div class="mt-xs" style="font-size:var(--font-cap);color:var(--tx3)">血缘关系: 配偶</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已认证</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Member 2: 王小明 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">王小明</div>
<div class="list-item__desc">子女 &middot; 28岁</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已认证</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Member 3: 张母 -->
<div class="list-item">
<div class="avatar"></div>
<div class="list-item__content">
<div class="list-item__title">张母</div>
<div class="list-item__desc">母亲 &middot; 78岁</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">待认证</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
<!-- Add Button -->
<div class="mt-lg">
<button class="btn btn--outline btn--full">+ 添加家人</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>随访详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">随访详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Status Card -->
<div class="card mb-md">
<div class="flex-row" style="gap:var(--gap-sm)">
<span class="tag tag--success">已完成</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:var(--gap-xs)">随访编号: FU20260510001</div>
</div>
<!-- Info Card -->
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">随访方式</span>
<span class="info-row__value">电话随访</span>
</div>
<div class="info-row">
<span class="info-row__label">计划日期</span>
<span class="info-row__value">2026-05-10</span>
</div>
<div class="info-row">
<span class="info-row__label">完成日期</span>
<span class="info-row__value">2026-05-10 14:30</span>
</div>
<div class="info-row">
<span class="info-row__label">执行医生</span>
<span class="info-row__value">李明</span>
</div>
</div>
<!-- Section: 随访记录 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">随访记录</div>
</div>
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">血压</span>
<span class="info-row__value">128/82 mmHg</span>
</div>
<div class="info-row">
<span class="info-row__label">心率</span>
<span class="info-row__value">72 次/分</span>
</div>
<div class="info-row">
<span class="info-row__label">用药依从性</span>
<span class="info-row__value">良好</span>
</div>
</div>
<!-- Section: 医生建议 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">医生建议</div>
</div>
<div class="card">
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">
血压控制良好,继续当前治疗方案。建议低盐饮食,每日监测血压,下次随访安排在一个月后。
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>随访记录 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">随访记录</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">待执行</div>
<div class="filter-pill">已完成</div>
</div>
<!-- Follow-up Cards -->
<div class="card-list mt-md">
<!-- Follow-up 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--amber">&#128222;</div>
<div class="list-item__content">
<div class="list-item__title">电话随访</div>
<div class="list-item__desc">2026-05-18</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">待执行</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Follow-up 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#127973;</div>
<div class="list-item__content">
<div class="list-item__title">门诊随访</div>
<div class="list-item__desc">2026-05-10</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Follow-up 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128222;</div>
<div class="list-item__content">
<div class="list-item__title">电话随访</div>
<div class="list-item__desc">2026-04-25</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>健康档案 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">健康档案</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Profile Summary Card -->
<div class="card mb-md">
<div class="flex-row" style="gap:var(--gap-sm)">
<div class="avatar avatar--lg"></div>
<div>
<div style="font-size:var(--font-h1);font-weight:600;color:var(--tx)">张伟</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-top:4px">&middot; 55岁</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:4px">建档日期: 2025-12-01</div>
</div>
</div>
</div>
<!-- Section: 基本信息 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">基本信息</div>
</div>
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">血型</span>
<span class="info-row__value">A型</span>
</div>
<div class="info-row">
<span class="info-row__label">身高</span>
<span class="info-row__value">172 cm</span>
</div>
<div class="info-row">
<span class="info-row__label">体重</span>
<span class="info-row__value">68.5 kg</span>
</div>
<div class="info-row">
<span class="info-row__label">BMI</span>
<span class="info-row__value">23.1</span>
</div>
<div class="info-row">
<span class="info-row__label">过敏史</span>
<span class="info-row__value">青霉素</span>
</div>
</div>
<!-- Section: 既往病史 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">既往病史</div>
</div>
<div class="card mb-md">
<div style="display:flex;flex-wrap:wrap;gap:var(--gap-xs)">
<span class="chip">高血压2级 (2020年)</span>
<span class="chip">2型糖尿病 (2022年)</span>
</div>
</div>
<!-- Section: 家族史 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">家族史</div>
</div>
<div class="card">
<div style="display:flex;flex-wrap:wrap;gap:var(--gap-xs)">
<span class="chip">父亲: 高血压</span>
<span class="chip">母亲: 糖尿病</span>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用药记录 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">用药记录</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Section: 当前用药 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">当前用药</div>
</div>
<div class="card-list mb-md">
<div class="list-item">
<div class="list-item__icon list-item__icon--orange">&#128138;</div>
<div class="list-item__content">
<div class="list-item__title">氨氯地平片 5mg</div>
<div class="list-item__desc">每日一次 &middot; 08:00</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">长期</span>
</div>
</div>
<div class="list-item">
<div class="list-item__icon list-item__icon--orange">&#128138;</div>
<div class="list-item__content">
<div class="list-item__title">缬沙坦胶囊 80mg</div>
<div class="list-item__desc">每日一次 &middot; 08:00</div>
</div>
<div class="list-item__right">
<span class="tag tag--info">长期</span>
</div>
</div>
</div>
<!-- Section: 今日打卡 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">今日打卡</div>
</div>
<div class="card-list mb-md">
<div class="list-item">
<div class="list-item__icon list-item__icon--green" style="font-size:24px">&#9989;</div>
<div class="list-item__content">
<div class="list-item__title">氨氯地平</div>
<div class="list-item__desc">08:05 已服用</div>
</div>
</div>
<div class="list-item">
<div class="list-item__icon list-item__icon--amber" style="font-size:24px">&#11036;</div>
<div class="list-item__content">
<div class="list-item__title">缬沙坦</div>
<div class="list-item__desc">待服用</div>
</div>
</div>
</div>
<!-- Section: 用药历史 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">用药历史</div>
</div>
<div class="card-list">
<div class="list-item">
<div class="list-item__content">
<div class="list-item__title">05/15</div>
<div class="list-item__desc">全部已服</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
</div>
</div>
<div class="list-item">
<div class="list-item__content">
<div class="list-item__title">05/14</div>
<div class="list-item__desc">全部已服</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">已完成</span>
</div>
</div>
<div class="list-item">
<div class="list-item__content">
<div class="list-item__title">05/13</div>
<div class="list-item__desc">部分漏服</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">漏服</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>报告详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">报告详情</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Header Card -->
<div class="card mb-md">
<div class="flex-row" style="gap:var(--gap-sm);margin-bottom:var(--gap-xs)">
<span style="font-size:var(--font-h1);font-weight:600;color:var(--tx)">2026年度体检报告</span>
<span class="tag tag--success">正常</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:var(--gap-xs)">检查日期: 2026-03-15</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-top:var(--gap-2xs)">检查机构: 第一人民医院</div>
</div>
<!-- Section: 检查项目 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">检查项目</div>
</div>
<div class="card mb-md">
<div class="info-row">
<span class="info-row__label">血常规</span>
<span class="info-row__value"><span class="tag tag--success">正常</span></span>
</div>
<div class="info-row">
<span class="info-row__label">肝肾功能</span>
<span class="info-row__value"><span class="tag tag--success">正常</span></span>
</div>
<div class="info-row">
<span class="info-row__label">心电图</span>
<span class="info-row__value"><span class="tag tag--success">正常</span></span>
</div>
<div class="info-row">
<span class="info-row__label">腹部B超</span>
<span class="info-row__value"><span class="tag tag--success">正常</span></span>
</div>
</div>
<!-- Section: 医生建议 -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">医生建议</div>
</div>
<div class="card">
<div style="font-size:var(--font-body);color:var(--tx2);line-height:var(--line-height)">
各项指标基本正常,建议继续保持健康生活方式,半年后复查。
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>体检报告 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">体检报告</span>
</div>
<div class="content">
<div class="page-shell">
<!-- Search Bar -->
<div class="search-bar">
<span class="search-bar__icon">&#128269;</span>
<input class="search-bar__input" type="text" placeholder="搜索体检报告">
</div>
<!-- Filter Pills -->
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">血常规</div>
<div class="filter-pill">肝肾功能</div>
<div class="filter-pill">影像</div>
</div>
<!-- Report Cards -->
<div class="card-list mt-md">
<!-- Report 1 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--green">&#128203;</div>
<div class="list-item__content">
<div class="list-item__title">2026年度体检报告</div>
<div class="list-item__desc">2026-03-15</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">正常</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Report 2 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--orange">&#128300;</div>
<div class="list-item__content">
<div class="list-item__title">血常规检查</div>
<div class="list-item__desc">2026-05-10</div>
</div>
<div class="list-item__right">
<span class="tag tag--warning">部分异常</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
<!-- Report 3 -->
<div class="list-item">
<div class="list-item__icon list-item__icon--blue">&#128257;</div>
<div class="list-item__content">
<div class="list-item__title">腹部B超</div>
<div class="list-item__desc">2026-02-20</div>
</div>
<div class="list-item__right">
<span class="tag tag--success">正常</span>
<span class="list-item__arrow">&rsaquo;</span>
</div>
</div>
</div>
<!-- Pagination -->
<div class="pagination">
<button class="pagination__btn" disabled>&lsaquo; 上一页</button>
<span class="pagination__info">1 / 3</span>
<button class="pagination__btn">下一页 &rsaquo;</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设置 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">设置</span>
</div>
<div class="content">
<div class="page-shell" style="padding:0">
<!-- Account Section -->
<div style="padding:var(--page-pad);padding-bottom:var(--gap-xs)">
<div class="section-title" style="margin-bottom:0">
<div class="section-title__text" style="font-size:var(--font-body-sm);color:var(--tx3)">账号与安全</div>
</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#128274;</div>
<div class="menu-item__text">修改密码</div>
<div class="menu-item__arrow">&rsaquo;</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#128241;</div>
<div class="menu-item__text">绑定手机</div>
<div class="menu-item__extra">138****8888</div>
<div class="menu-item__arrow">&rsaquo;</div>
</div>
<div class="menu-item" style="border-bottom:none">
<div class="menu-item__icon" style="color:var(--success)">&#128172;</div>
<div class="menu-item__text">微信绑定</div>
<div class="menu-item__extra">已绑定</div>
<div class="menu-item__arrow">&rsaquo;</div>
</div>
<div style="height:var(--gap-sm);background:var(--bg)"></div>
<!-- Notification Section -->
<div style="padding:var(--page-pad);padding-bottom:var(--gap-xs)">
<div class="section-title" style="margin-bottom:0">
<div class="section-title__text" style="font-size:var(--font-body-sm);color:var(--tx3)">通知设置</div>
</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#128276;</div>
<div class="menu-item__text">预约提醒</div>
<div class="menu-item__extra" style="color:var(--success)">已开启</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#128138;</div>
<div class="menu-item__text">用药提醒</div>
<div class="menu-item__extra" style="color:var(--success)">已开启</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#9888;</div>
<div class="menu-item__text">健康告警</div>
<div class="menu-item__extra" style="color:var(--success)">已开启</div>
</div>
<div class="menu-item" style="border-bottom:none">
<div class="menu-item__icon">&#128240;</div>
<div class="menu-item__text">文章推送</div>
<div class="menu-item__extra">已关闭</div>
</div>
<div style="height:var(--gap-sm);background:var(--bg)"></div>
<!-- Other Section -->
<div style="padding:var(--page-pad);padding-bottom:var(--gap-xs)">
<div class="section-title" style="margin-bottom:0">
<div class="section-title__text" style="font-size:var(--font-body-sm);color:var(--tx3)">其他</div>
</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#128196;</div>
<div class="menu-item__text">清除缓存</div>
<div class="menu-item__extra">12.3 MB</div>
<div class="menu-item__arrow">&rsaquo;</div>
</div>
<div class="menu-item">
<div class="menu-item__icon">&#8505;</div>
<div class="menu-item__text">关于我们</div>
<div class="menu-item__arrow">&rsaquo;</div>
</div>
<div class="menu-item" style="border-bottom:none">
<div class="menu-item__icon" style="color:var(--danger)">&#128682;</div>
<div class="menu-item__text" style="color:var(--danger)">退出登录</div>
</div>
<!-- Version -->
<div style="text-align:center;padding:var(--gap-xl) 0 var(--gap-lg)">
<span style="font-size:var(--font-cap);color:var(--tx3)">v1.2.0</span>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI 报告详情 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">AI 报告详情</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell" style="padding-bottom:calc(var(--page-pad) + 80px)">
<!-- Report Header -->
<div class="card mb-md">
<div class="flex-between mb-sm">
<span style="font-size:var(--font-h1);font-weight:700;color:var(--tx)">血常规智能解读</span>
<span class="tag tag--warning">需关注</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">生成时间: 2026-05-16 10:30</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3)">基于 2026-05-16 血常规检验报告</div>
</div>
<!-- Section: AI Summary -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">AI 分析摘要</div>
</div>
<div class="card mb-md" style="background:var(--warning-light)">
<div style="font-size:var(--font-body);color:var(--tx);line-height:1.7">共检测 22 项指标,其中 19 项正常3 项需关注。整体结果基本正常,建议关注以下指标变化。</div>
</div>
<!-- Section: Key Indicators -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">重点关注指标</div>
</div>
<div class="card-list card-list--md mb-md">
<!-- Indicator 1 -->
<div class="card" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">白细胞 (WBC)</span>
<span class="tag tag--warning">偏低 &darr;</span>
</div>
<div style="font-size:var(--font-num);font-weight:700;color:var(--pri);font-family:var(--font-serif);margin-bottom:var(--gap-xs)">3.2 &times;10&sup9;/L</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">正常范围: 4.0-10.0</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2)">建议: 关注免疫功能,必要时复查</div>
</div>
<!-- Indicator 2 -->
<div class="card" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">血红蛋白 (HGB)</span>
<span class="tag tag--warning">偏低 &darr;</span>
</div>
<div style="font-size:var(--font-num);font-weight:700;color:var(--pri);font-family:var(--font-serif);margin-bottom:var(--gap-xs)">118 g/L</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">正常范围: 120-160</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2)">建议: 适当补充铁剂和蛋白质</div>
</div>
<!-- Indicator 3 -->
<div class="card" style="border-left:4px solid var(--warning)">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">血小板 (PLT)</span>
<span class="tag tag--warning">偏低 &darr;</span>
</div>
<div style="font-size:var(--font-num);font-weight:700;color:var(--pri);font-family:var(--font-serif);margin-bottom:var(--gap-xs)">98 &times;10&sup9;/L</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:var(--gap-2xs)">正常范围: 100-300</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2)">建议: 2周后复查血小板</div>
</div>
</div>
<!-- Section: AI Advice -->
<div class="section-title">
<div class="section-title__bar"></div>
<div class="section-title__text">AI 建议</div>
</div>
<div class="card mb-md">
<div style="font-size:var(--font-body);color:var(--tx);line-height:2">
1. 建议加强营养摄入,适当补充铁剂<br>
2. 2周后复查血常规<br>
3. 避免剧烈运动,注意休息<br>
4. 如有头晕、乏力等症状,请及时就医
</div>
</div>
</div>
<!-- Bottom Actions -->
<div style="position:sticky;bottom:0;background:var(--card);padding:var(--gap-sm) var(--page-pad) calc(var(--gap-sm) + 34px);border-top:0.5px solid var(--bd-light);display:flex;gap:var(--gap-sm);z-index:10">
<button class="btn btn--outline" style="flex:1">分享给医生</button>
<button class="btn btn--primary" style="flex:1">下载报告</button>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI 分析报告 · HMS</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<!-- Status Bar -->
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<!-- Nav Bar -->
<div class="nav-bar">
<div class="nav-bar__back">&lsaquo;</div>
<span class="nav-bar__title">AI 分析报告</span>
</div>
<!-- Content -->
<div class="content">
<div class="page-shell">
<!-- Search -->
<div class="search-bar mb-sm">
<span class="search-bar__icon">&#x1F50D;</span>
<input type="text" class="search-bar__input" placeholder="搜索报告...">
</div>
<!-- Filter Pills -->
<div class="filter-pills mb-md">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">化验解读</div>
<div class="filter-pill">趋势分析</div>
<div class="filter-pill">健康评估</div>
</div>
<!-- Report Card List -->
<div class="card-list card-list--md">
<!-- Report 1 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">血常规智能解读</span>
<span class="tag tag--warning">需关注</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:var(--gap-xs)">AI分析发现3项指标需关注</div>
<div class="flex-between">
<span class="time-label">2026-05-16</span>
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:500">查看详情 &rarr;</span>
</div>
</div>
<!-- Report 2 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">肾功能趋势分析</span>
<span class="tag tag--info">趋势分析</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:var(--gap-xs)">近3个月肌酐呈上升趋势</div>
<div class="flex-between">
<span class="time-label">2026-05-15</span>
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:500">查看详情 &rarr;</span>
</div>
</div>
<!-- Report 3 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">综合健康评估</span>
<span class="tag tag--success">良好</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:var(--gap-xs)">您的健康评分: 82/100</div>
<div class="flex-between">
<span class="time-label">2026-05-10</span>
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:500">查看详情 &rarr;</span>
</div>
</div>
<!-- Report 4 -->
<div class="card card--pressable">
<div class="flex-between mb-xs">
<span style="font-size:var(--font-body);color:var(--tx);font-weight:600">血糖管理报告</span>
<span class="tag tag--success">达标</span>
</div>
<div style="font-size:var(--font-body-sm);color:var(--tx2);margin-bottom:var(--gap-xs)">近30天血糖控制达标率85%</div>
<div class="flex-between">
<span class="time-label">2026-05-01</span>
<span style="font-size:var(--font-body-sm);color:var(--pri);font-weight:500">查看详情 &rarr;</span>
</div>
</div>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=375, initial-scale=1">
<title>文章详情 - HMS小程序原型</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back"></div>
<span class="nav-bar__title">文章详情</span>
</div>
<div class="content">
<div class="page-shell">
<div style="margin-bottom:var(--gap-md)">
<h1 style="font-size:var(--font-h1);font-weight:700;color:var(--tx);line-height:1.4;margin-bottom:12px">高血压日常管理指南</h1>
<div class="flex-row gap-xs" style="flex-wrap:wrap">
<span class="tag tag--info">心内科</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">5分钟阅读</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">2026-05-15</span>
</div>
<div style="font-size:var(--font-cap);color:var(--tx3);margin-top:8px">李明 主任医师 审阅</div>
</div>
<div class="card" style="line-height:2;font-size:var(--font-body);color:var(--tx)">
<p style="margin-bottom:var(--gap-md)">高血压是一种常见的慢性疾病,长期血压控制不佳会增加心脑血管疾病的风险。以下是一些日常管理建议:</p>
<p style="font-weight:600;margin-bottom:8px">一、规律用药</p>
<p style="margin-bottom:var(--gap-md)">遵医嘱按时服药,不可自行停药或调整剂量。建议设置用药提醒。</p>
<p style="font-weight:600;margin-bottom:8px">二、低盐饮食</p>
<p style="margin-bottom:var(--gap-md)">每日钠盐摄入量控制在6g以下。减少加工食品和外卖的摄入。</p>
<p style="font-weight:600;margin-bottom:8px">三、适量运动</p>
<p style="margin-bottom:var(--gap-md)">每周进行150分钟中等强度有氧运动如快走、游泳等。避免剧烈运动。</p>
<p style="font-weight:600;margin-bottom:8px">四、定期监测</p>
<p style="margin-bottom:var(--gap-md)">建议每日早晚各测一次血压,记录数据供医生参考。</p>
<p style="font-weight:600;margin-bottom:8px">五、情绪管理</p>
<p>保持心情平和,避免过度紧张和焦虑。可以通过冥想、深呼吸等方式放松。</p>
</div>
<div style="display:flex;gap:var(--gap-sm);margin-top:var(--gap-lg)">
<button class="btn btn--outline" style="flex:1">收藏</button>
<button class="btn btn--primary" style="flex:1">分享</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=375, initial-scale=1">
<title>健康文章 - HMS小程序原型</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back"></div>
<span class="nav-bar__title">健康文章</span>
</div>
<div class="content">
<div class="page-shell">
<div class="search-bar">
<span class="search-bar__icon">🔍</span>
<input class="search-bar__input" type="text" placeholder="搜索文章...">
</div>
<div class="filter-pills">
<div class="filter-pill filter-pill--active">全部</div>
<div class="filter-pill">高血压</div>
<div class="filter-pill">糖尿病</div>
<div class="filter-pill">肾病</div>
<div class="filter-pill">饮食</div>
<div class="filter-pill">运动</div>
</div>
<div class="card-list mt-md">
<div class="card card--pressable">
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:6px">高血压日常管理指南</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden">详细介绍高血压患者在日常生活中的注意事项,包括饮食、运动、用药等方面的科学建议。</div>
<div class="flex-row gap-xs">
<span class="tag tag--info">高血压</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">5分钟阅读</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">2026-05-15</span>
</div>
</div>
<div class="card card--pressable">
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:6px">糖尿病患者饮食建议</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden">科学的饮食控制是糖尿病管理的基础,本文为您详细介绍如何合理安排每日膳食。</div>
<div class="flex-row gap-xs">
<span class="tag tag--success">饮食</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">3分钟阅读</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">2026-05-14</span>
</div>
</div>
<div class="card card--pressable">
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:6px">透析患者的生活质量提升</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden">通过合理的生活方式调整,透析患者也可以拥有良好的生活质量。</div>
<div class="flex-row gap-xs">
<span class="tag tag--info">肾病</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">8分钟阅读</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">2026-05-12</span>
</div>
</div>
<div class="card card--pressable">
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:6px">运动与心血管健康</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden">适量运动对心血管系统的保护作用已被大量研究证实。</div>
<div class="flex-row gap-xs">
<span class="tag tag--warning">运动</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">6分钟阅读</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">2026-05-10</span>
</div>
</div>
<div class="card card--pressable">
<div style="font-size:var(--font-body);color:var(--tx);font-weight:600;margin-bottom:6px">如何正确测量血压</div>
<div style="font-size:var(--font-body-sm);color:var(--tx3);margin-bottom:8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden">正确的血压测量方法对高血压的诊断和管理至关重要。</div>
<div class="flex-row gap-xs">
<span class="tag tag--info">高血压</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">4分钟阅读</span>
<span style="font-size:var(--font-cap);color:var(--tx3)">2026-05-08</span>
</div>
</div>
</div>
<div class="pagination">
<button class="pagination__btn" disabled>上一页</button>
<span class="pagination__info">1 / 3</span>
<button class="pagination__btn">下一页</button>
</div>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=375, initial-scale=1">
<title>咨询详情 - HMS小程序原型</title>
<link rel="stylesheet" href="../shared/tokens.css">
<link rel="stylesheet" href="../shared/components.css">
<link rel="stylesheet" href="../shared/frame.css">
</head>
<body>
<div class="phone">
<div class="status-bar">
<div class="status-bar__left">9:41</div>
<div class="status-bar__center"></div>
<div class="status-bar__right">
<div class="status-bar__signal">
<div class="status-bar__bar" style="height:4px"></div>
<div class="status-bar__bar" style="height:6px"></div>
<div class="status-bar__bar" style="height:9px"></div>
<div class="status-bar__bar" style="height:12px"></div>
</div>
<div class="status-bar__battery"><div class="status-bar__battery-fill"></div></div>
</div>
</div>
<div class="nav-bar">
<div class="nav-bar__back"></div>
<span class="nav-bar__title">咨询详情</span>
</div>
<div class="content">
<div style="display:flex;align-items:center;gap:var(--gap-xs);padding:var(--gap-xs) var(--page-pad);background:var(--card);border-bottom:1px solid var(--bd-light);position:sticky;top:0;z-index:10">
<div class="avatar avatar--sm"></div>
<div>
<div style="font-size:var(--font-body);font-weight:600;color:var(--tx)">张医生 · 心内科</div>
</div>
<span class="tag tag--success" style="margin-left:auto">在线</span>
</div>
<div class="page-shell">
<div class="chat-list">
<div style="text-align:center;margin-bottom:var(--gap-sm)">
<span style="font-size:var(--font-cap);color:var(--tx3);background:var(--surface-alt);padding:4px 12px;border-radius:var(--r-pill)">今天 09:00</span>
</div>
<div class="chat-bubble chat-bubble--left">
您好,请问您哪里不舒服?
</div>
<div class="chat-bubble chat-bubble--right">
医生您好,我最近一周血压有点偏高,经常头晕头痛。
</div>
<div class="chat-bubble chat-bubble--left">
请问您目前有服用降压药吗?血压最高到过多少?
</div>
<div class="chat-bubble chat-bubble--right">
在吃氨氯地平每天一片。今早测了155/95。
</div>
<div class="chat-bubble chat-bubble--left">
了解了。血压确实偏高,建议:<br>1. 增加缬沙坦80mg每日一次<br>2. 低盐饮食<br>3. 一周后复查<br>我先给您开个处方。
</div>
<div class="chat-bubble chat-bubble--right">
好的,谢谢医生!
</div>
</div>
<div style="height:80px"></div>
</div>
<div class="chat-input-bar">
<input class="chat-input-bar__field" type="text" placeholder="输入消息...">
<button class="btn btn--primary btn--sm">发送</button>
</div>
</div>
<div class="home-indicator"></div>
</div>
</body>
</html>

View File

@@ -0,0 +1,568 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序原型稿 · 页面导航</title>
<style>
:root {
--pri: #C4623A;
--success: #5B7A5E;
--bg: #F5F0EB;
--card: #FFFFFF;
--tx: #2D2A26;
--tx2: #5A554F;
--tx3: #78716C;
--bd: #E8E2DC;
--bd-light: #F0EBE5;
--info: #3B82F6;
--warning: #C4873A;
--danger: #B54A4A;
--card-r: 12px;
--shadow-sm: 0 1px 4px rgba(45,42,38,0.04);
--shadow-md: 0 2px 12px rgba(45,42,38,0.08);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
background: var(--bg);
color: var(--tx);
line-height: 1.6;
min-height: 100vh;
}
.page-header {
background: var(--card);
border-bottom: 1px solid var(--bd);
padding: 40px 0 32px;
text-align: center;
}
.page-header h1 {
font-size: 28px;
font-weight: 700;
color: var(--tx);
letter-spacing: -0.02em;
margin-bottom: 8px;
}
.page-header p {
font-size: 14px;
color: var(--tx3);
}
.page-header .stats {
display: flex;
justify-content: center;
gap: 32px;
margin-top: 20px;
}
.page-header .stat {
text-align: center;
}
.page-header .stat-value {
font-size: 24px;
font-weight: 700;
color: var(--pri);
}
.page-header .stat-label {
font-size: 12px;
color: var(--tx3);
margin-top: 2px;
}
.container {
max-width: 960px;
margin: 0 auto;
padding: 32px 24px 64px;
}
.section {
margin-bottom: 40px;
}
.section-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
padding-left: 16px;
position: relative;
}
.section-header::before {
content: '';
position: absolute;
left: 0;
top: 2px;
bottom: 2px;
width: 4px;
border-radius: 2px;
background: var(--accent-color);
}
.section-header h2 {
font-size: 18px;
font-weight: 600;
color: var(--tx);
}
.section-header .count {
font-size: 13px;
font-weight: 500;
color: var(--tx3);
background: var(--bd-light);
padding: 2px 10px;
border-radius: 12px;
margin-left: 4px;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 12px;
}
.card-grid.compact {
grid-template-columns: repeat(auto-fill, minmax(175px, 1fr));
}
.link-card {
display: block;
background: var(--card);
border: 1px solid var(--bd-light);
border-radius: var(--card-r);
padding: 16px;
text-decoration: none;
box-shadow: var(--shadow-sm);
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
.link-card::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--accent-color);
opacity: 0;
transition: opacity 0.2s ease;
}
.link-card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
border-color: var(--bd);
}
.link-card:hover::after {
opacity: 1;
}
.link-card .card-name {
font-size: 15px;
font-weight: 600;
color: var(--tx);
margin-bottom: 4px;
}
.link-card .card-path {
font-size: 12px;
color: var(--tx3);
font-family: "SF Mono", "Fira Code", "Cascadia Code", monospace;
word-break: break-all;
}
.link-card:hover .card-name {
color: var(--accent-color);
}
.footer {
text-align: center;
padding: 32px 0 48px;
font-size: 13px;
color: var(--tx3);
}
.footer a {
color: var(--pri);
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
@media (max-width: 640px) {
.page-header { padding: 28px 16px 24px; }
.page-header h1 { font-size: 22px; }
.page-header .stats { gap: 20px; }
.page-header .stat-value { font-size: 20px; }
.container { padding: 20px 16px 48px; }
.card-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
.card-grid.compact { grid-template-columns: repeat(2, 1fr); }
.link-card { padding: 12px; }
.link-card .card-name { font-size: 14px; }
.link-card .card-path { font-size: 11px; }
}
</style>
</head>
<body>
<header class="page-header">
<h1>HMS 小程序原型稿 · 页面导航</h1>
<p>Health Management System — 微信患者端 / 医护端原型页面一览</p>
<div class="stats">
<div class="stat">
<div class="stat-value">59</div>
<div class="stat-label">原型页面</div>
</div>
<div class="stat">
<div class="stat-value">8</div>
<div class="stat-label">页面分组</div>
</div>
<div class="stat">
<div class="stat-value">66</div>
<div class="stat-label">小程序页面</div>
</div>
</div>
</header>
<div class="container">
<!-- 1. Tab 页面 -->
<section class="section" style="--accent-color: #C4623A;">
<div class="section-header">
<h2>Tab 页面</h2>
<span class="count">4 页</span>
</div>
<div class="card-grid">
<a class="link-card" href="01-tabs/home.html">
<div class="card-name">首页</div>
<div class="card-path">pages/index/index</div>
</a>
<a class="link-card" href="01-tabs/health.html">
<div class="card-name">健康</div>
<div class="card-path">pages/health/index</div>
</a>
<a class="link-card" href="01-tabs/messages.html">
<div class="card-name">消息</div>
<div class="card-path">pages/messages/index</div>
</a>
<a class="link-card" href="01-tabs/profile.html">
<div class="card-name">我的</div>
<div class="card-path">pages/profile/index</div>
</a>
</div>
</section>
<!-- 2. 主包页面 -->
<section class="section" style="--accent-color: #5B7A5E;">
<div class="section-header">
<h2>主包页面</h2>
<span class="count">8 页</span>
</div>
<div class="card-grid">
<a class="link-card" href="02-main/login.html">
<div class="card-name">登录</div>
<div class="card-path">pages/login/index</div>
</a>
<a class="link-card" href="02-main/consultation.html">
<div class="card-name">咨询</div>
<div class="card-path">pages/consultation/index</div>
</a>
<a class="link-card" href="02-main/mall.html">
<div class="card-name">商城</div>
<div class="card-path">pages/mall/index</div>
</a>
<a class="link-card" href="02-main/appointment.html">
<div class="card-name">预约列表</div>
<div class="card-path">pages/appointment/index</div>
</a>
<a class="link-card" href="02-main/appointment-create.html">
<div class="card-name">创建预约</div>
<div class="card-path">pages/appointment/create</div>
</a>
<a class="link-card" href="02-main/appointment-detail.html">
<div class="card-name">预约详情</div>
<div class="card-path">pages/appointment/detail</div>
</a>
<a class="link-card" href="02-main/user-agreement.html">
<div class="card-name">用户协议</div>
<div class="card-path">pages/user-agreement</div>
</a>
<a class="link-card" href="02-main/privacy-policy.html">
<div class="card-name">隐私政策</div>
<div class="card-path">pages/privacy-policy</div>
</a>
</div>
</section>
<!-- 3. 健康子包 -->
<section class="section" style="--accent-color: #3B82F6;">
<div class="section-header">
<h2>健康子包</h2>
<span class="count">5 页</span>
</div>
<div class="card-grid">
<a class="link-card" href="03-pkg-health/trend.html">
<div class="card-name">趋势分析</div>
<div class="card-path">pages/pkg-health/trend</div>
</a>
<a class="link-card" href="03-pkg-health/input.html">
<div class="card-name">体征录入</div>
<div class="card-path">pages/pkg-health/input</div>
</a>
<a class="link-card" href="03-pkg-health/daily-monitoring.html">
<div class="card-name">日常监测</div>
<div class="card-path">pages/pkg-health/daily-monitoring</div>
</a>
<a class="link-card" href="03-pkg-health/alerts.html">
<div class="card-name">健康告警</div>
<div class="card-path">pages/pkg-health/alerts</div>
</a>
<a class="link-card" href="03-pkg-health/device-sync.html">
<div class="card-name">设备同步</div>
<div class="card-path">pages/pkg-health/device-sync</div>
</a>
</div>
</section>
<!-- 4. 医生端核心 -->
<section class="section" style="--accent-color: #C4873A;">
<div class="section-header">
<h2>医生端核心</h2>
<span class="count">8 页</span>
</div>
<div class="card-grid">
<a class="link-card" href="04-pkg-doctor-core/index.html">
<div class="card-name">工作台</div>
<div class="card-path">pages/pkg-doctor/index</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/patients.html">
<div class="card-name">患者列表</div>
<div class="card-path">pages/pkg-doctor/patients</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/patient-detail.html">
<div class="card-name">患者详情</div>
<div class="card-path">pages/pkg-doctor/patient-detail</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/consultation.html">
<div class="card-name">咨询列表</div>
<div class="card-path">pages/pkg-doctor/consultation</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/consultation-detail.html">
<div class="card-name">咨询详情</div>
<div class="card-path">pages/pkg-doctor/consultation-detail</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/followup.html">
<div class="card-name">随访列表</div>
<div class="card-path">pages/pkg-doctor/followup</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/followup-detail.html">
<div class="card-name">随访详情</div>
<div class="card-path">pages/pkg-doctor/followup-detail</div>
</a>
<a class="link-card" href="04-pkg-doctor-core/action-inbox.html">
<div class="card-name">待办事项</div>
<div class="card-path">pages/pkg-doctor/action-inbox</div>
</a>
</div>
</section>
<!-- 5. 医生端临床 -->
<section class="section" style="--accent-color: #B54A4A;">
<div class="section-header">
<h2>医生端临床</h2>
<span class="count">10 页</span>
</div>
<div class="card-grid compact">
<a class="link-card" href="05-pkg-doctor-clinical/dialysis.html">
<div class="card-name">透析记录列表</div>
<div class="card-path">pages/pkg-doctor-clinical/dialysis</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/dialysis-detail.html">
<div class="card-name">透析详情</div>
<div class="card-path">pages/pkg-doctor-clinical/dialysis/detail</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/dialysis-create.html">
<div class="card-name">创建透析记录</div>
<div class="card-path">pages/pkg-doctor-clinical/dialysis/create</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/prescription.html">
<div class="card-name">处方列表</div>
<div class="card-path">pages/pkg-doctor-clinical/prescription</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/prescription-detail.html">
<div class="card-name">处方详情</div>
<div class="card-path">pages/pkg-doctor-clinical/prescription/detail</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/prescription-create.html">
<div class="card-name">创建处方</div>
<div class="card-path">pages/pkg-doctor-clinical/prescription/create</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/report.html">
<div class="card-name">检验报告列表</div>
<div class="card-path">pages/pkg-doctor-clinical/report</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/report-detail.html">
<div class="card-name">检验报告详情</div>
<div class="card-path">pages/pkg-doctor-clinical/report/detail</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/alerts.html">
<div class="card-name">临床告警列表</div>
<div class="card-path">pages/pkg-doctor-clinical/alerts</div>
</a>
<a class="link-card" href="05-pkg-doctor-clinical/alert-detail.html">
<div class="card-name">告警详情</div>
<div class="card-path">pages/pkg-doctor-clinical/alerts/detail</div>
</a>
</div>
</section>
<!-- 6. 商城子包 -->
<section class="section" style="--accent-color: #C4623A;">
<div class="section-header">
<h2>商城子包</h2>
<span class="count">3 页</span>
</div>
<div class="card-grid">
<a class="link-card" href="06-pkg-mall/detail.html">
<div class="card-name">商品详情</div>
<div class="card-path">pages/pkg-mall/detail</div>
</a>
<a class="link-card" href="06-pkg-mall/exchange.html">
<div class="card-name">兑换记录</div>
<div class="card-path">pages/pkg-mall/exchange</div>
</a>
<a class="link-card" href="06-pkg-mall/orders.html">
<div class="card-name">订单列表</div>
<div class="card-path">pages/pkg-mall/orders</div>
</a>
</div>
</section>
<!-- 7. 个人中心子包 -->
<section class="section" style="--accent-color: #5B7A5E;">
<div class="section-header">
<h2>个人中心子包</h2>
<span class="count">17 页</span>
</div>
<div class="card-grid compact">
<a class="link-card" href="07-pkg-profile/family.html">
<div class="card-name">家人管理</div>
<div class="card-path">pages/pkg-profile/family</div>
</a>
<a class="link-card" href="07-pkg-profile/family-add.html">
<div class="card-name">添加家人</div>
<div class="card-path">pages/pkg-profile/family-add</div>
</a>
<a class="link-card" href="07-pkg-profile/reports.html">
<div class="card-name">体检报告</div>
<div class="card-path">pages/pkg-profile/reports</div>
</a>
<a class="link-card" href="07-pkg-profile/report-detail.html">
<div class="card-name">报告详情</div>
<div class="card-path">pages/pkg-profile/report-detail</div>
</a>
<a class="link-card" href="07-pkg-profile/followups.html">
<div class="card-name">随访记录</div>
<div class="card-path">pages/pkg-profile/followups</div>
</a>
<a class="link-card" href="07-pkg-profile/followup-detail.html">
<div class="card-name">随访详情</div>
<div class="card-path">pages/pkg-profile/followup-detail</div>
</a>
<a class="link-card" href="07-pkg-profile/medication.html">
<div class="card-name">用药记录</div>
<div class="card-path">pages/pkg-profile/medication</div>
</a>
<a class="link-card" href="07-pkg-profile/settings.html">
<div class="card-name">设置</div>
<div class="card-path">pages/pkg-profile/settings</div>
</a>
<a class="link-card" href="07-pkg-profile/dialysis-records.html">
<div class="card-name">透析记录</div>
<div class="card-path">pages/pkg-profile/dialysis-records</div>
</a>
<a class="link-card" href="07-pkg-profile/dialysis-record-detail.html">
<div class="card-name">透析详情</div>
<div class="card-path">pages/pkg-profile/dialysis-record-detail</div>
</a>
<a class="link-card" href="07-pkg-profile/dialysis-prescriptions.html">
<div class="card-name">透析处方</div>
<div class="card-path">pages/pkg-profile/dialysis-prescriptions</div>
</a>
<a class="link-card" href="07-pkg-profile/dialysis-prescription-detail.html">
<div class="card-name">处方详情</div>
<div class="card-path">pages/pkg-profile/dialysis-prescription-detail</div>
</a>
<a class="link-card" href="07-pkg-profile/consents.html">
<div class="card-name">知情同意书</div>
<div class="card-path">pages/pkg-profile/consents</div>
</a>
<a class="link-card" href="07-pkg-profile/health-records.html">
<div class="card-name">健康档案</div>
<div class="card-path">pages/pkg-profile/health-records</div>
</a>
<a class="link-card" href="07-pkg-profile/diagnoses.html">
<div class="card-name">诊断记录</div>
<div class="card-path">pages/pkg-profile/diagnoses</div>
</a>
<a class="link-card" href="07-pkg-profile/elder-mode.html">
<div class="card-name">长者模式</div>
<div class="card-path">pages/pkg-profile/elder-mode</div>
</a>
<a class="link-card" href="07-pkg-profile/events.html">
<div class="card-name">线下活动</div>
<div class="card-path">pages/pkg-profile/events</div>
</a>
</div>
</section>
<!-- 8. 其他子包 -->
<section class="section" style="--accent-color: #78716C;">
<div class="section-header">
<h2>其他子包</h2>
<span class="count">5 页</span>
</div>
<div class="card-grid">
<a class="link-card" href="08-pkg-other/ai-report-list.html">
<div class="card-name">AI报告列表</div>
<div class="card-path">pages/ai-report/list</div>
</a>
<a class="link-card" href="08-pkg-other/ai-report-detail.html">
<div class="card-name">AI报告详情</div>
<div class="card-path">pages/ai-report/detail</div>
</a>
<a class="link-card" href="08-pkg-other/article-list.html">
<div class="card-name">文章列表</div>
<div class="card-path">pages/article/index</div>
</a>
<a class="link-card" href="08-pkg-other/article-detail.html">
<div class="card-name">文章详情</div>
<div class="card-path">pages/article/detail</div>
</a>
<a class="link-card" href="08-pkg-other/consultation-detail.html">
<div class="card-name">咨询详情</div>
<div class="card-path">pages/pkg-consultation/detail</div>
</a>
</div>
</section>
</div>
<footer class="footer">
<p>HMS Health Management System &middot; 小程序原型稿 &middot; <a href="../../">返回文档</a></p>
</footer>
</body>
</html>

View File

@@ -0,0 +1,760 @@
/* ============================================
HMS 小程序统一组件库 · Component Classes
全局统一,所有页面共享,不允许自定义独特样式
============================================ */
/* ── PageShell ── */
.page-shell {
min-height: 100%;
background: var(--bg);
padding: var(--page-pad);
padding-bottom: calc(var(--page-pad) + 34px); /* safe-area */
box-sizing: border-box;
}
.page-shell--sm { padding: var(--gap-sm); }
.page-shell--none { padding: 0; }
.page-shell--lg { padding: var(--gap-lg); }
/* ── ContentCard ── */
.card {
background: var(--card);
border-radius: var(--card-r);
box-shadow: var(--shadow-sm);
padding: var(--card-pad);
transition: opacity 0.15s, transform 0.15s;
}
.card--outlined {
box-shadow: none;
border: 1px solid var(--bd);
}
.card--elevated {
box-shadow: var(--shadow-md);
}
.card--sm { padding: var(--card-pad-sm); }
.card--lg { padding: var(--card-pad-lg); }
.card--none { padding: 0; }
.card--pressable { cursor: pointer; }
.card--pressable:active {
opacity: 0.85;
transform: scale(0.98);
}
/* ── StatusTag ── */
.tag {
display: inline-flex;
align-items: center;
border-radius: var(--r-pill);
font-size: var(--font-micro);
font-weight: 500;
padding: 4px 12px;
line-height: 1;
white-space: nowrap;
}
.tag--sm { font-size: 11px; padding: 2px 8px; }
.tag--success { background: #ECFDF5; color: var(--success); }
.tag--warning { background: #FFF7ED; color: var(--warning); }
.tag--error { background: #FEF2F2; color: var(--danger); }
.tag--info { background: var(--info-light); color: var(--info); }
.tag--default { background: #F5F5F4; color: var(--tx3); }
/* ── SectionTitle ── */
.section-title {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: var(--gap-sm);
}
.section-title__bar {
width: 3px;
height: 20px;
background: var(--pri);
border-radius: 2px;
flex-shrink: 0;
}
.section-title__text {
font-size: var(--font-h2);
font-weight: 600;
color: var(--tx);
}
.section-title__subtitle {
font-size: var(--font-body-sm);
color: var(--tx3);
margin-top: 2px;
}
.section-title__action {
margin-left: auto;
font-size: var(--font-body-sm);
color: var(--pri);
min-height: var(--touch-min);
display: flex;
align-items: center;
cursor: pointer;
}
/* ── SearchSection ── */
.search-bar {
display: flex;
align-items: center;
background: var(--card);
border-radius: var(--card-r);
height: var(--input-h);
padding: 0 var(--gap-sm);
box-shadow: var(--shadow-sm);
gap: 8px;
}
.search-bar__icon {
font-size: 20px;
color: var(--tx3);
flex-shrink: 0;
}
.search-bar__input {
flex: 1;
border: none;
outline: none;
font-size: var(--font-body);
color: var(--tx);
background: transparent;
font-family: var(--font-family);
}
.search-bar__input::placeholder { color: var(--tx3); }
/* Filter tabs (pill variant) */
.filter-pills {
display: flex;
gap: var(--gap-xs);
margin-top: var(--gap-sm);
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.filter-pill {
padding: 8px 20px;
border-radius: var(--r-pill);
font-size: var(--font-body-sm);
color: var(--tx3);
background: var(--card);
border: 1px solid var(--bd);
white-space: nowrap;
cursor: pointer;
transition: all 0.15s;
}
.filter-pill--active {
background: var(--pri);
color: var(--white);
border-color: var(--pri);
}
/* ── CardList ── */
.card-list {
display: flex;
flex-direction: column;
gap: var(--gap-sm);
}
.card-list--md { gap: var(--gap-md); }
/* ── PaginationBar ── */
.pagination {
display: flex;
align-items: center;
justify-content: center;
gap: var(--gap-sm);
margin-top: var(--gap-md);
}
.pagination__btn {
background: var(--card);
border: 1px solid var(--bd);
border-radius: var(--r-sm);
padding: 0 16px;
height: var(--touch-min);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-body-sm);
color: var(--tx);
cursor: pointer;
}
.pagination__btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.pagination__info {
font-size: var(--font-body-sm);
color: var(--tx3);
}
/* ── PageHeader ── */
.page-header {
display: flex;
align-items: center;
height: var(--touch-min);
padding: 0 var(--page-pad);
background: var(--bg);
position: sticky;
top: 0;
z-index: 10;
}
.page-header__back {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
color: var(--tx);
cursor: pointer;
margin-right: 4px;
}
.page-header__title {
font-size: var(--font-h1);
font-weight: 600;
color: var(--tx);
}
.page-header__actions {
margin-left: auto;
display: flex;
gap: var(--gap-xs);
}
/* ── EmptyState ── */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--gap-2xl) var(--gap-xl);
text-align: center;
}
.empty-state__icon {
width: 80px;
height: 80px;
border-radius: 50%;
background: var(--surface-alt);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-hero);
font-family: var(--font-serif);
color: var(--tx3);
margin-bottom: var(--gap-lg);
}
.empty-state__text {
font-size: var(--font-num);
color: var(--tx2);
margin-bottom: var(--gap-xs);
}
.empty-state__hint {
font-size: var(--font-h2);
color: var(--tx3);
}
.empty-state__action {
margin-top: var(--gap-lg);
}
/* ── ErrorState ── */
.error-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--gap-2xl) var(--gap-xl);
text-align: center;
}
.error-state__icon {
font-size: var(--font-display);
margin-bottom: var(--gap-lg);
}
.error-state__text {
font-size: var(--font-body-lg);
color: var(--tx2);
}
.error-state__action {
margin-top: var(--gap-lg);
}
/* ── LoadingCard (Skeleton) ── */
.skeleton {
background: var(--card);
border-radius: var(--card-r);
padding: var(--card-pad);
animation: skeleton-pulse 1.5s infinite;
}
@keyframes skeleton-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.skeleton__line {
background: var(--bd-light);
border-radius: 4px;
margin-bottom: 10px;
}
.skeleton__line--title { width: 60%; height: 16px; }
.skeleton__line--text { width: 100%; height: 12px; }
.skeleton__line--short { width: 40%; height: 12px; }
.skeleton__avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--bd-light);
flex-shrink: 0;
}
/* ── Buttons ── */
.btn {
display: flex;
align-items: center;
justify-content: center;
height: var(--btn-h);
border-radius: var(--r-pill);
font-size: var(--font-body-lg);
font-weight: 600;
border: none;
cursor: pointer;
transition: opacity 0.15s;
font-family: var(--font-family);
padding: 0 var(--gap-lg);
}
.btn:active { opacity: 0.85; }
.btn--primary {
background: var(--pri);
color: var(--white);
}
.btn--outline {
background: transparent;
color: var(--pri);
border: 2px solid var(--pri);
}
.btn--sm {
height: 36px;
font-size: var(--font-body-sm);
padding: 0 16px;
}
.btn--full { width: 100%; }
.btn--danger {
background: var(--danger);
color: var(--white);
}
/* ── Form Fields ── */
.form-group {
margin-bottom: var(--gap-md);
}
.form-label {
font-size: var(--font-body);
color: var(--tx2);
margin-bottom: var(--gap-xs);
display: block;
}
.form-label--required::after {
content: '*';
color: var(--danger);
margin-left: 4px;
}
.form-input {
width: 100%;
height: var(--input-h);
border: 1px solid var(--bd);
border-radius: var(--r-sm);
padding: 0 var(--gap-md);
font-size: var(--font-body);
color: var(--tx);
background: var(--card);
box-sizing: border-box;
font-family: var(--font-family);
outline: none;
transition: border-color 0.15s;
}
.form-input:focus { border-color: var(--pri); }
.form-input::placeholder { color: var(--tx3); }
.form-textarea {
width: 100%;
min-height: 120px;
border: 1px solid var(--bd);
border-radius: var(--r-sm);
padding: var(--gap-sm);
font-size: var(--font-body);
color: var(--tx);
background: var(--card);
box-sizing: border-box;
font-family: var(--font-family);
outline: none;
resize: vertical;
transition: border-color 0.15s;
}
.form-textarea:focus { border-color: var(--pri); }
.form-select {
width: 100%;
height: var(--input-h);
border: 1px solid var(--bd);
border-radius: var(--r-sm);
padding: 0 var(--gap-md);
font-size: var(--font-body);
color: var(--tx);
background: var(--card);
box-sizing: border-box;
font-family: var(--font-family);
outline: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%2378716C' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 16px center;
}
/* ── Stat Card (数据统计卡片) ── */
.stat-card {
background: var(--card);
border-radius: var(--card-r);
padding: var(--card-pad);
box-shadow: var(--shadow-sm);
text-align: center;
}
.stat-card__value {
font-size: var(--font-num-lg);
font-weight: 700;
color: var(--tx);
font-family: var(--font-serif);
font-variant-numeric: tabular-nums;
}
.stat-card__label {
font-size: var(--font-cap);
color: var(--tx3);
margin-top: 4px;
}
.stat-card--primary .stat-card__value { color: var(--pri); }
.stat-card--success .stat-card__value { color: var(--success); }
.stat-card--danger .stat-card__value { color: var(--danger); }
.stat-card--warning .stat-card__value { color: var(--warning); }
/* ── Stat Grid ── */
.stat-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: var(--gap-sm);
}
/* ── Info Row (详情信息行) ── */
.info-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--gap-sm) 0;
border-bottom: 1px solid var(--bd-light);
}
.info-row:last-child { border-bottom: none; }
.info-row__label {
font-size: var(--font-body-sm);
color: var(--tx3);
flex-shrink: 0;
}
.info-row__value {
font-size: var(--font-body);
color: var(--tx);
text-align: right;
word-break: break-all;
}
/* ── List Item (列表项) ── */
.list-item {
display: flex;
align-items: center;
gap: var(--gap-sm);
padding: var(--gap-sm);
background: var(--card);
border-radius: var(--card-r);
box-shadow: var(--shadow-sm);
cursor: pointer;
transition: opacity 0.15s;
}
.list-item:active { opacity: 0.85; }
.list-item__icon {
width: 44px;
height: 44px;
border-radius: var(--r-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
flex-shrink: 0;
}
.list-item__icon--orange { background: var(--pri-light); }
.list-item__icon--green { background: var(--success-light); }
.list-item__icon--blue { background: var(--info-light); }
.list-item__icon--red { background: var(--danger-light); }
.list-item__icon--amber { background: var(--warning-light); }
.list-item__content { flex: 1; min-width: 0; }
.list-item__title {
font-size: var(--font-body);
color: var(--tx);
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.list-item__desc {
font-size: var(--font-body-sm);
color: var(--tx3);
margin-top: 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.list-item__right {
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 4px;
}
.list-item__arrow {
color: var(--tx3);
font-size: 14px;
margin-left: 4px;
}
/* ── Menu Item (设置菜单项) ── */
.menu-item {
display: flex;
align-items: center;
height: 64px;
padding: 0 var(--page-pad);
background: var(--card);
cursor: pointer;
border-bottom: 1px solid var(--bd-light);
}
.menu-item:active { opacity: 0.85; }
.menu-item__icon {
font-size: 22px;
margin-right: var(--gap-sm);
width: 28px;
text-align: center;
}
.menu-item__text {
flex: 1;
font-size: var(--font-body);
color: var(--tx);
}
.menu-item__extra {
font-size: var(--font-body-sm);
color: var(--tx3);
margin-right: 8px;
}
.menu-item__arrow {
color: var(--tx3);
font-size: 14px;
}
/* ── Avatar ── */
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--pri-light);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-h1);
color: var(--pri);
font-weight: 600;
flex-shrink: 0;
}
.avatar--lg { width: 72px; height: 72px; font-size: 36px; }
.avatar--sm { width: 36px; height: 36px; font-size: 18px; }
/* ── Divider ── */
.divider {
height: 1px;
background: var(--bd-light);
margin: var(--gap-sm) 0;
}
/* ── Section (带标题的内容区) ── */
.section {
margin-bottom: var(--section-gap);
}
/* ── Quick Entry Grid (快捷入口网格) ── */
.quick-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--gap-sm);
}
.quick-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
cursor: pointer;
}
.quick-item__icon {
width: 52px;
height: 52px;
border-radius: var(--r);
display: flex;
align-items: center;
justify-content: center;
font-size: 26px;
}
.quick-item__icon--orange { background: var(--pri-light); }
.quick-item__icon--green { background: var(--success-light); }
.quick-item__icon--blue { background: var(--info-light); }
.quick-item__icon--amber { background: var(--warning-light); }
.quick-item__icon--red { background: var(--danger-light); }
.quick-item__label {
font-size: var(--font-body-sm);
color: var(--tx2);
}
/* ── Banner / Swiper ── */
.banner {
width: 100%;
height: 160px;
border-radius: var(--card-r);
overflow: hidden;
background: linear-gradient(135deg, var(--pri) 0%, var(--pri-dark) 100%);
display: flex;
align-items: center;
justify-content: center;
color: var(--white);
}
.banner__content {
padding: var(--gap-lg);
text-align: center;
}
.banner__title {
font-size: var(--font-h1);
font-weight: 600;
margin-bottom: 8px;
}
.banner__subtitle {
font-size: var(--font-body-sm);
opacity: 0.85;
}
.banner__dots {
display: flex;
justify-content: center;
gap: 6px;
margin-top: var(--gap-sm);
}
.banner__dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: rgba(255,255,255,0.4);
}
.banner__dot--active { background: var(--white); width: 16px; border-radius: 3px; }
/* ── Chat (咨询对话) ── */
.chat-list { display: flex; flex-direction: column; gap: var(--gap-sm); }
.chat-bubble {
max-width: 75%;
padding: var(--gap-sm);
border-radius: var(--r-sm);
font-size: var(--font-body);
line-height: var(--line-height);
word-break: break-all;
}
.chat-bubble--left {
background: var(--card);
color: var(--tx);
align-self: flex-start;
border-bottom-left-radius: 4px;
}
.chat-bubble--right {
background: var(--pri);
color: var(--white);
align-self: flex-end;
border-bottom-right-radius: 4px;
}
.chat-input-bar {
display: flex;
align-items: center;
gap: var(--gap-xs);
padding: var(--gap-sm) var(--page-pad);
background: var(--card);
border-top: 1px solid var(--bd-light);
position: sticky;
bottom: 0;
}
.chat-input-bar__field {
flex: 1;
height: 40px;
border: 1px solid var(--bd);
border-radius: var(--r-pill);
padding: 0 16px;
font-size: var(--font-body);
outline: none;
font-family: var(--font-family);
}
/* ── Time / Date display ── */
.time-label {
font-size: var(--font-cap);
color: var(--tx3);
}
/* ── Progress Bar ── */
.progress {
height: 6px;
background: var(--bd-light);
border-radius: 3px;
overflow: hidden;
}
.progress__bar {
height: 100%;
background: var(--pri);
border-radius: 3px;
transition: width 0.3s;
}
/* ── Notification Badge ── */
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
border-radius: 9px;
background: var(--danger);
color: var(--white);
font-size: 11px;
font-weight: 600;
padding: 0 5px;
}
/* ── Chip (小标签) ── */
.chip {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
border-radius: var(--r-sm);
font-size: var(--font-body-sm);
background: var(--surface-alt);
color: var(--tx2);
}
/* ── Utility ── */
.text-pri { color: var(--pri); }
.text-success { color: var(--success); }
.text-danger { color: var(--danger); }
.text-warning { color: var(--warning); }
.text-tx3 { color: var(--tx3); }
.text-tx2 { color: var(--tx2); }
.text-center { text-align: center; }
.text-right { text-align: right; }
.font-serif { font-family: var(--font-serif); }
.font-bold { font-weight: 600; }
.mt-xs { margin-top: var(--gap-xs); }
.mt-sm { margin-top: var(--gap-sm); }
.mt-md { margin-top: var(--gap-md); }
.mt-lg { margin-top: var(--gap-lg); }
.mb-xs { margin-bottom: var(--gap-xs); }
.mb-sm { margin-bottom: var(--gap-sm); }
.mb-md { margin-bottom: var(--gap-md); }
.mb-lg { margin-bottom: var(--gap-lg); }
.gap-xs { gap: var(--gap-xs); }
.gap-sm { gap: var(--gap-sm); }
.flex-row { display: flex; align-items: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.flex-1 { flex: 1; min-width: 0; }
.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

View File

@@ -0,0 +1,243 @@
/* ============================================
HMS 小程序原型 · Phone Frame Simulator
模拟微信小程序外观375×812 iPhone视口
============================================ */
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--font-family);
font-size: var(--font-body);
line-height: var(--line-height);
color: var(--tx);
background: #E8E2DC;
display: flex;
justify-content: center;
align-items: flex-start;
min-height: 100vh;
padding: 24px;
}
/* ── Phone Frame ── */
.phone {
width: 375px;
min-height: 812px;
background: var(--bg);
border-radius: 40px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(45, 42, 38, 0.25), 0 0 0 1px rgba(45, 42, 38, 0.1);
display: flex;
flex-direction: column;
position: relative;
}
/* ── Status Bar ── */
.status-bar {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 24px 0;
background: var(--card);
font-size: 14px;
font-weight: 600;
color: var(--tx);
position: relative;
z-index: 20;
}
.status-bar__left { width: 54px; }
.status-bar__center {
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 8px;
width: 120px;
height: 32px;
background: #1a1a1a;
border-radius: 20px;
}
.status-bar__right {
display: flex;
align-items: center;
gap: 6px;
width: 72px;
justify-content: flex-end;
}
.status-bar__battery {
width: 24px;
height: 12px;
border: 1.5px solid var(--tx);
border-radius: 3px;
position: relative;
}
.status-bar__battery::after {
content: '';
position: absolute;
right: -4px;
top: 3px;
width: 2px;
height: 4px;
background: var(--tx);
border-radius: 0 1px 1px 0;
}
.status-bar__battery-fill {
position: absolute;
left: 1.5px;
top: 1.5px;
bottom: 1.5px;
width: 65%;
background: var(--tx);
border-radius: 1px;
}
.status-bar__signal {
display: flex;
align-items: flex-end;
gap: 1.5px;
height: 12px;
}
.status-bar__bar {
width: 3px;
background: var(--tx);
border-radius: 1px;
}
/* ── Nav Bar ── */
.nav-bar {
height: 44px;
display: flex;
align-items: center;
justify-content: center;
background: var(--card);
padding: 0 var(--page-pad);
position: relative;
border-bottom: 0.5px solid var(--bd-light);
z-index: 15;
}
.nav-bar--bg { background: var(--bg); border-bottom: none; }
.nav-bar__title {
font-size: 17px;
font-weight: 600;
color: var(--tx);
}
.nav-bar__back {
position: absolute;
left: 8px;
top: 50%;
transform: translateY(-50%);
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: var(--tx);
cursor: pointer;
}
.nav-bar__home {
position: absolute;
left: 42px;
top: 50%;
transform: translateY(-50%);
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
color: var(--tx);
}
.nav-bar__actions {
position: absolute;
right: var(--page-pad);
top: 50%;
transform: translateY(-50%);
display: flex;
gap: var(--gap-xs);
}
/* ── Content Area ── */
.content {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* ── Tab Bar ── */
.tab-bar {
display: flex;
align-items: flex-start;
justify-content: space-around;
height: var(--tabbar-safe);
padding-top: 6px;
padding-bottom: 34px;
background: var(--card);
border-top: 0.5px solid var(--bd-light);
position: relative;
z-index: 15;
}
.tab-bar__item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
cursor: pointer;
min-width: 56px;
}
.tab-bar__icon {
font-size: 22px;
color: var(--tx3);
height: 28px;
display: flex;
align-items: center;
justify-content: center;
}
.tab-bar__label {
font-size: 10px;
color: var(--tx3);
}
.tab-bar__item--active .tab-bar__icon,
.tab-bar__item--active .tab-bar__label {
color: var(--pri);
}
/* ── Home Indicator ── */
.home-indicator {
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
width: 134px;
height: 5px;
background: var(--tx);
border-radius: 3px;
opacity: 0.2;
}
/* ── Page Label (原型标注) ── */
.page-label {
position: fixed;
top: 24px;
left: 50%;
transform: translateX(-50%);
background: rgba(45, 42, 38, 0.8);
color: white;
padding: 6px 16px;
border-radius: 20px;
font-size: 13px;
font-weight: 500;
z-index: 100;
pointer-events: none;
white-space: nowrap;
}
/* ── Responsive ── */
@media (max-width: 500px) {
body { padding: 0; background: var(--bg); }
.phone {
width: 100%;
min-height: 100vh;
border-radius: 0;
box-shadow: none;
}
.page-label { display: none; }
}

View File

@@ -0,0 +1,93 @@
/* ============================================
HMS 小程序 Design Tokens
温润东方 · Warm Eastern Design
来源: apps/miniprogram/src/styles/tokens.scss + variables.scss
============================================ */
:root {
/* ── Primary · 赤陶橙 ── */
--pri: #C4623A;
--pri-light: #F0DDD4;
--pri-dark: #8B3E1F;
--pri-surface: #F5F0EB;
/* ── Success · 鼠尾草绿 ── */
--success: #5B7A5E;
--success-light: #E8F0E8;
--success-dark: #3D5A40;
/* ── Surfaces ── */
--bg: #F5F0EB;
--card: #FFFFFF;
--white: #FFFFFF;
--surface-alt: #EDE8E2;
/* ── Text ── */
--tx: #2D2A26;
--tx2: #5A554F;
--tx3: #78716C;
/* ── Borders ── */
--bd: #E8E2DC;
--bd-light: #F0EBE5;
/* ── Semantic ── */
--danger: #B54A4A;
--danger-light: #FDEAEA;
--warning: #C4873A;
--warning-light: #FFF3E0;
--info: #3B82F6;
--info-light: #EFF6FF;
/* ── Typography Scale (11级) ── */
--font-display: 72px;
--font-hero: 48px;
--font-h1: 28px;
--font-h2: 24px;
--font-body-lg: 28px;
--font-body: 22px;
--font-body-sm: 18px;
--font-num: 30px;
--font-num-lg: 34px;
--font-cap: 14px;
--font-micro: 12px;
--font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
--font-serif: Georgia, 'Times New Roman', serif;
--line-height: 1.5;
/* ── Spacing ── */
--gap-2xs: 4px;
--gap-xs: 8px;
--gap-sm: 16px;
--gap-md: 20px;
--section-gap: 28px;
--gap-lg: 32px;
--gap-xl: 40px;
--gap-2xl: 56px;
--page-pad: 28px;
/* ── Radius ── */
--r-xs: 8px;
--r-sm: 12px;
--r: 16px;
--r-lg: 20px;
--r-pill: 999px;
/* ── Shadows ── */
--shadow-sm: 0 1px 4px rgba(45, 42, 38, 0.04);
--shadow-md: 0 2px 12px rgba(45, 42, 38, 0.08);
--shadow-lg: 0 8px 32px rgba(45, 42, 38, 0.12);
/* ── Structural ── */
--touch-min: 48px;
--btn-h: 56px;
--input-h: 56px;
--card-pad: 28px;
--card-pad-sm: 20px;
--card-pad-lg: 32px;
--card-r: 12px;
--tabbar-h: 56px;
--tabbar-safe: 100px;
--navbar-h: 44px;
--statusbar-h: 44px;
}