11 KiB
11 KiB
HealthManager 患者前端 — 技术文档
移动端 H5 应用,患者用手机浏览器打开。
目录
1. 技术选型
| 库 | 版本 | 做什么 |
|---|---|---|
| React | 19 | UI 框架 |
| TypeScript | 6 | 类型安全 |
| Vite | 8 | 构建工具 |
| Zustand | 5 | 状态管理 |
| React Router | 7 | 路由(页面跳转) |
| ECharts | 6 | 图表(趋势图、饼图) |
| Framer Motion | 12 | 动画 |
| dayjs | 2 | 日期处理 |
2. 文件结构
src/
├── main.tsx ← React 应用入口
├── App.tsx ← 根组件,渲染路由
├── router/
│ ├── index.tsx ← URL 和页面的映射关系
│ └── AuthGuard.tsx ← 路由守卫:没登录→跳登录页
├── stores/
│ ├── auth.store.ts ← 认证状态:用户、令牌、登录/登出
│ └── notification.store.ts ← 通知状态
├── services/
│ ├── api-client.ts ← 底层 HTTP 请求(封装 fetch)
│ ├── auth.service.ts ← 登录/注册/资料 API
│ ├── health.service.ts ← 健康数据 API
│ ├── medication.service.ts ← 药物 API
│ ├── consultation.service.ts ← 咨询 API
│ ├── report.service.ts ← 报告 API
│ ├── followup.service.ts ← 随访 API
│ ├── notification.service.ts ← 通知 API
│ ├── exercise-diet.service.ts← 运动饮食 API
│ └── device.service.ts ← 设备 API
├── types/
│ ├── user.ts, health.ts, medication.ts, consultation.ts
│ ├── report.ts, followup.ts, notification.ts, device.ts
│ ├── calendar.ts, exercise-diet.ts
│ └── index.ts ← 统一导出
├── utils/
│ ├── format.ts ← 日期/数字格式化
│ ├── validator.ts ← 手机号/验证码格式校验
│ └── constants.ts ← 常量(测量类型、健康贴士等)
├── hooks/
│ ├── useAuth.ts ← 获取认证状态
│ └── useCountdown.ts ← 验证码倒计时
├── components/
│ ├── common/
│ │ ├── Button.tsx ← 按钮(支持 loading 状态)
│ │ ├── Card.tsx ← 卡片容器
│ │ ├── Badge.tsx ← 角标(红点/数字)
│ │ ├── Input.tsx ← 输入框(带标签+错误提示)
│ │ ├── Toast.tsx ← 轻提示
│ │ └── Empty.tsx ← 空状态占位
│ ├── layout/
│ │ ├── AppLayout.tsx ← 主布局:TabBar + 内容区
│ │ ├── StackLayout.tsx ← 子页面布局:返回按钮 + 内容区
│ │ ├── TabBar.tsx ← 底部导航栏(首页/健康/服务/我的)
│ │ └── PageHeader.tsx ← 页面标题栏
│ └── charts/
│ ├── LineChart.tsx ← ECharts 折线图
│ ├── BarChart.tsx ← ECharts 柱状图
│ └── PieChart.tsx ← ECharts 饼图
└── pages/
├── auth/
│ ├── LoginPage.tsx ← 登录页
│ └── RegisterPage.tsx ← 注册页
├── home/
│ ├── HomePage.tsx ← 仪表盘首页
│ └── DeviceBindingPage.tsx ← 设备绑定
├── health/ ← 健康模块
├── medication/ ← 用药模块
├── services/ ← 服务模块(问诊/报告/随访)
├── exercise-diet/ ← 运动饮食
├── profile/ ← 个人中心
└── notifications/ ← 通知
3. 关键文件详解
3.1 services/api-client.ts — HTTP 请求客户端
所有前端 API 调用的基础,封装了原生 fetch。
核心逻辑:
- 公开接口(login/register/send-sms/refresh)不附加 Authorization 头
- 其他请求自动从 localStorage 读取 JWT 令牌,加到
Authorization: Bearer xxx - 发送 HTTP 请求到
http://localhost:5000 - 如果返回 401(未认证)→ 清除 localStorage,跳转登录页
- 把服务器返回的 JSON 统一包装成
{ code, data, message }
四个方法:get、post、put、del
3.2 services/auth.service.ts — 认证服务
| 函数 | 做的事 |
|---|---|
login(phone, smsCode) |
调 POST /api/auth/login → 返回 {token, user} |
register(phone, smsCode, name) |
调 POST /api/auth/register |
getProfile() |
调 GET /api/auth/me → 更新 localStorage 中的用户资料 |
updateProfile(data) |
调 PUT /api/auth/me → 更新姓名/性别/身高/体重/病史 |
logout() |
清除 localStorage 的 hrt_auth |
3.3 services/health.service.ts — 健康数据服务
| 函数 | API | 说明 |
|---|---|---|
getRecords({type, startDate, endDate}) |
GET /health-records |
查记录列表 |
addRecord(record) |
POST /health-records |
添加记录。自动把 value 转成 JSON 字符串 |
getLatestStats() |
GET /health-records?days=7 |
拉取 7 天数据,客户端计算各类型的均值和趋势 |
getTrendData(type, days) |
GET /health-records?type=&days= |
趋势图数据 |
Value 解析逻辑:parseValue() 根据 type 解析 JSON:
blood_pressure→{systolic, diastolic}对象- 其他类型 →
{value}中的数字
3.4 services/medication.service.ts — 用药服务
| 函数 | API | 说明 |
|---|---|---|
getMedications() |
GET /medications |
药物列表 |
addMedication(data) |
POST /medications |
添加药物 |
markTaken(medicationId, slot) |
POST /medications/{id}/take |
打卡 |
getAdherence(medicationId) |
GET /medications/{id}/adherence |
依从率 |
3.5 services/consultation.service.ts — 咨询
| 函数 | API | 说明 |
|---|---|---|
getDoctors() |
GET /consultations/doctors |
可接诊医生列表 |
getConsultation(doctorId) |
GET /consultations |
查与某医生的活跃咨询 |
startConsultation(doctorId) |
POST /consultations |
发起新咨询 |
sendMessage(consultationId, text) |
POST /consultations/{id}/messages |
发送消息 |
getDoctorReply(consultationId) |
GET /consultations/{id}/messages |
拉取最新消息,找医生的回复 |
3.6 stores/auth.store.ts — 认证状态
状态数据:user, token, isAuthenticated
操作方法:
login(phone, code)→ 调 API → 保存 token → 再拉完整用户资料register(phone, code, name)→ 同上logout()→ 清除所有数据updateProfile(data)→ 只更新内存中的用户对象
持久化:Zustand persist 中间件 → localStorage 的 hrt_auth 键。刷新页面不丢登录状态。
3.7 router/index.tsx — 路由
分为三类:
- 公开路由(无需登录):
/login、/register - Tab 路由(需登录,底部导航栏):
/home、/health、/services、/profile - Stack 路由(需登录,有返回按钮):所有子页面如
/health/records/add、/services/consultation/chat/:doctorId等
AuthGuard 组件包裹在需要登录的路由外,未登录自动跳 /login。
4. 页面详解
登录页 LoginPage.tsx
- 输入手机号 + 短信验证码
- 点"获取验证码" → 60 秒倒计时
- 验证码任意输入(演示版)
- 成功后跳首页
首页 HomePage.tsx
- 健康概览卡片(蓝色渐变):最新血压 + 心率,异常值变色
- 快捷操作(6 个):测血压、记用药、在线问诊、报告解读、健康日历、运动饮食
- 健康小贴士:随机展示,点击换下一条
- 通知角标:未读通知红点
健康中心 HealthHubPage.tsx
6 种测量类型卡片 → 点击进记录列表 → 点"+ 录入" → 填数值 → 保存
趋势图 TrendChartPage.tsx
- ECharts 折线图,可选 7/14/30/90 天
- 血压同时显示收缩压+舒张压两条线,140 警戒线
药物管理
- 列表:分"进行中/已结束"Tab
- 添加:选常用药或手动输入,设剂量、频次(每日1~3次)、服药时间点
- 详情:依从率饼图,近30天服药记录
在线问诊
- 医生列表:按科室筛选 → 点医生 → 进聊天
- 聊天:对话气泡,自动滚底
- 发送后 1.5 秒模拟医生回复(演示版)
报告管理
- 上传:填标题 → 选类别 → 点虚线框选图片 → 提交
- 列表:分状态 Tab 查看
- 详情:查看解读结果
个人中心 ProfilePage.tsx
- 用户信息卡片(点击进入编辑)
- 身体数据展示
- 菜单:用药、通知、设备、设置、关于
- 退出登录
编辑资料 EditProfilePage.tsx
可修改:姓名、性别、生日、身高(cm)、体重(kg)、病史(顿号分隔)
5. 状态管理
| Store | 存储键 | 持久化 | 内容 |
|---|---|---|---|
auth.store |
hrt_auth |
✓ localStorage | user, token, isAuthenticated |
notification.store |
— | ✗ 内存 | notifications[], unreadCount |
通知不持久化——每次打开应用重新从服务器拉取。
6. API 调用方式
前端 services → api-client.ts → fetch() → http://localhost:5000 → 后端 Controller
- 所有 API 请求经过
api-client.ts统一处理 - 自动带 JWT 令牌(公开接口除外)
- 401 自动清除登录态并跳转登录页
- 响应统一为
{ code, data, message }格式
7. 常见问题 FAQ
Q1: 前端怎么调后端 API?
前端 services/ 下的每个 service 文件封装了一类 API 调用。底层都通过 api-client.ts 发 HTTP 请求到 http://localhost:5000。
Q2: 怎么测这个前端?
cd frontend-patient
npm run dev
# 浏览器打开 http://localhost:5173
# F12 → 左上角 📱 图标 → 选 iPhone 12 Pro 模拟手机
Q3: 演示账号是什么?
手机号 13800138000,验证码随便填(1234 就行)。
Q4: 为什么某些页面打开是空白的?
打开 F12 看 Console 有没有红色报错。最常见原因:
- 后端没启动(
ERR_CONNECTION_REFUSED) - 令牌过期(401 Unauthorized)→ 清 localStorage 重新登录
Q5: 怎么改颜色/样式?
全局 CSS 变量在 src/assets/styles/variables.css:
- 主色
--color-primary: #1E6BFF - 背景
--color-bg: #F2F5FA - 改一个地方,全局生效
文档版本:v1.0 | 最后更新:2026-05-20 | 患者前端技术文档