Files
soft/frontend-patient/技术文档-患者前端.md

299 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HealthManager 患者前端 — 技术文档
> 移动端 H5 应用,患者用手机浏览器打开。
---
## 目录
1. [技术选型](#1-技术选型)
2. [文件结构](#2-文件结构)
3. [关键文件详解](#3-关键文件详解)
4. [页面详解](#4-页面详解)
5. [状态管理](#5-状态管理)
6. [API 调用方式](#6-api-调用方式)
7. [常见问题 FAQ](#7-常见问题-faq)
---
## 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`
**核心逻辑**
1. 公开接口login/register/send-sms/refresh**不附加** Authorization 头
2. 其他请求自动从 localStorage 读取 JWT 令牌,加到 `Authorization: Bearer xxx`
3. 发送 HTTP 请求到 `http://localhost:5000`
4. 如果返回 401未认证→ 清除 localStorage跳转登录页
5. 把服务器返回的 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` — 路由
分为三类:
1. **公开路由**(无需登录):`/login``/register`
2. **Tab 路由**(需登录,底部导航栏):`/home``/health``/services``/profile`
3. **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: 怎么测这个前端?
```bash
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 | 患者前端技术文档