554 lines
14 KiB
Markdown
554 lines
14 KiB
Markdown
# 上线全流程规划文档
|
||
|
||
> 当前项目是一个跑在本地的 Demo。本文档说明要成为一个**真正可上线运营的产品**,还需要做哪些工作。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [文件上传与存储](#1-文件上传与存储)
|
||
2. [医生端查看与解读](#2-医生端查看与解读)
|
||
3. [历史记录与数据持久化](#3-历史记录与数据持久化)
|
||
4. [页面过渡动画](#4-页面过渡动画)
|
||
5. [联网与 App 化](#5-联网与-app-化)
|
||
6. [安全与鉴权](#6-安全与鉴权)
|
||
7. [消息推送](#7-消息推送)
|
||
8. [运维与监控](#8-运维与监控)
|
||
9. [开发流程规范化](#9-开发流程规范化)
|
||
10. [完整上线检查清单](#10-完整上线检查清单)
|
||
|
||
---
|
||
|
||
## 1. 文件上传与存储
|
||
|
||
### 现状
|
||
|
||
- 患者点"上传报告",选了文件但**没有真正存到服务器**
|
||
- 后端只记录了空的 `imageUrls: []`
|
||
- 没有文件存储服务对接
|
||
|
||
### 需要做的事
|
||
|
||
#### 1.1 MinIO 对接(已在本地装了,没接代码)
|
||
|
||
MinIO 是一个兼容 AWS S3 的对象存储服务,适合存图片、PDF 等文件。
|
||
|
||
**后端需要新增:**
|
||
|
||
```
|
||
backend/src/HealthManager.Infrastructure/Services/FileStorageService.cs ← 新建
|
||
```
|
||
|
||
核心功能:
|
||
- `UploadAsync(Stream fileStream, string fileName)` → 上传到 MinIO,返回文件 URL
|
||
- `GetFileUrl(string objectKey)` → 获取文件访问地址
|
||
- `DeleteAsync(string objectKey)` → 删除文件
|
||
|
||
**流程:**
|
||
```
|
||
患者选图片 → 前端调 POST /api/files/upload → 后端接收文件流
|
||
→ 上传到 MinIO → 得到 URL → 报告保存时把 URL 存入 imageUrls
|
||
→ 医生点查看 → 前端直接通过 URL 加载图片
|
||
```
|
||
|
||
#### 1.2 新增文件上传接口
|
||
|
||
```
|
||
POST /api/files/upload ← 上传单个文件,返回 { url, key }
|
||
POST /api/files/upload-multiple ← 上传多个文件
|
||
GET /api/files/{key} ← 下载/预览文件
|
||
DELETE /api/files/{key} ← 删除文件
|
||
```
|
||
|
||
#### 1.3 前端改造
|
||
|
||
```
|
||
ReportUploadPage.tsx:
|
||
选文件 → 调上传接口 → 拿到 URL 数组
|
||
→ 调创建报告接口 { title, category, imageUrls: ["url1", "url2"] }
|
||
→ 显示上传进度条
|
||
```
|
||
|
||
#### 1.4 文件大小和类型限制
|
||
|
||
| 限制项 | 建议值 |
|
||
|--------|--------|
|
||
| 单文件最大 | 10MB |
|
||
| 允许格式 | jpg, png, pdf |
|
||
| 每人每天上限 | 20 个文件 |
|
||
|
||
---
|
||
|
||
## 2. 医生端查看与解读
|
||
|
||
### 现状
|
||
|
||
- 医生能看到报告标题和状态
|
||
- 但看不到图片(因为根本没存图)
|
||
- 解读功能比较简陋
|
||
|
||
### 需要做的事
|
||
|
||
#### 2.1 图片查看器
|
||
|
||
医生点报告后,应该能看到所有上传的图片:
|
||
```
|
||
ReportDetailPage.tsx:
|
||
- 图片缩略图列表(来自 imageUrls)
|
||
- 点击放大查看
|
||
- 支持左右翻页
|
||
```
|
||
|
||
#### 2.2 报告解读界面增强
|
||
|
||
```
|
||
当前:只有一个文本框,写一句话
|
||
需要:
|
||
- 逐项填写检查结果(血压、血糖、血脂...)
|
||
- 异常项自动标红
|
||
- 风险等级(正常/关注/异常)
|
||
- 建议措施的富文本编辑器
|
||
- 解读完成后自动通知患者
|
||
```
|
||
|
||
#### 2.3 报告历史
|
||
|
||
医生端需要:
|
||
- 按患者查看历史报告列表
|
||
- 按时间/类型筛选
|
||
- 对比不同时间点的报告变化趋势
|
||
|
||
---
|
||
|
||
## 3. 历史记录与数据持久化
|
||
|
||
### 现状
|
||
|
||
- 数据存在本地 PostgreSQL
|
||
- 没有定期备份
|
||
- 健康数据会无限增长
|
||
|
||
### 需要做的事
|
||
|
||
#### 3.1 数据库备份
|
||
|
||
```bash
|
||
# 自动备份脚本(Linux 服务器上跑)
|
||
pg_dump HealthManager > /backup/health_$(date +%Y%m%d).sql
|
||
|
||
# 每天凌晨 3 点自动执行(crontab)
|
||
0 3 * * * /opt/scripts/backup-db.sh
|
||
|
||
# 保留最近 30 天,旧自动删除
|
||
```
|
||
|
||
#### 3.2 历史数据归档
|
||
|
||
健康记录表会越来越大,需要归档策略:
|
||
- 1 年以上的健康数据 → 移到归档表或压缩存储
|
||
- 3 年以上的 → 可选择性清理
|
||
- 报告和相关文件 → 永久保留
|
||
|
||
#### 3.3 数据导出
|
||
|
||
患者应该能导出自己的数据:
|
||
```
|
||
GET /api/health-records/export?format=csv
|
||
GET /api/health-records/export?format=pdf
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 页面过渡动画
|
||
|
||
### 现状
|
||
|
||
- 有 CSS 动画定义但未完全启用
|
||
- 页面切换比较生硬
|
||
|
||
### 需要做的事
|
||
|
||
#### 4.1 路由过渡动画
|
||
|
||
使用 `framer-motion`(已安装)实现:
|
||
|
||
```tsx
|
||
// 页面进入:从右滑入 + 淡入
|
||
// 页面离开:向左滑出 + 淡出
|
||
// 返回时:从左滑入
|
||
|
||
<AnimatePresence mode="wait">
|
||
<motion.div
|
||
key={location.pathname}
|
||
initial={{ opacity: 0, x: 50 }}
|
||
animate={{ opacity: 1, x: 0 }}
|
||
exit={{ opacity: 0, x: -50 }}
|
||
transition={{ duration: 0.25 }}
|
||
>
|
||
<Outlet />
|
||
</motion.div>
|
||
</AnimatePresence>
|
||
```
|
||
|
||
#### 4.2 组件级动画
|
||
|
||
| 场景 | 动画 |
|
||
|------|------|
|
||
| 列表加载 | 骨架屏(Skeleton)闪烁,数据来到后列表项依次弹出 |
|
||
| 卡片点击 | 缩放+阴影变化,给"按下去"的反馈 |
|
||
| 数字变化 | 健康数据变化时数字滚动动画 |
|
||
| 按钮点击 | 涟漪效果(ripple effect) |
|
||
| 消息发送 | 气泡从输入框弹入对话区 |
|
||
| 下拉刷新 | 顶部旋转加载指示器 |
|
||
| Toast 提示 | 从顶部滑入,2.5 秒后滑出 |
|
||
|
||
#### 4.3 页面切换保留状态
|
||
|
||
当前切换到别的 Tab 再回来,数据会重新加载。需要:
|
||
- 首页数据缓存 30 秒,切回来直接用
|
||
- 列表页记住滚动位置
|
||
|
||
---
|
||
|
||
## 5. 联网与 App 化
|
||
|
||
### 现状
|
||
|
||
- 前端 `npm run dev` 跑在本地
|
||
- 后端 `dotnet run` 跑在本地
|
||
- 只能用 `localhost` 访问
|
||
|
||
### 需要做的事
|
||
|
||
#### 5.1 部署到服务器
|
||
|
||
**最简单方案:一台 Linux 云服务器(阿里云/腾讯云)**
|
||
|
||
```
|
||
服务器配置建议:
|
||
- 2核 CPU
|
||
- 4GB 内存
|
||
- 40GB SSD
|
||
- Ubuntu 22.04
|
||
```
|
||
|
||
需要安装的东西和本地一样:
|
||
- PostgreSQL 18
|
||
- Redis
|
||
- MinIO
|
||
- .NET 10 Runtime
|
||
- Nginx(作为反代和静态文件服务)
|
||
|
||
#### 5.2 Nginx 配置
|
||
|
||
```
|
||
把所有服务统一到一个域名下:
|
||
|
||
https://api.chatmed.online → 后端 API (5000端口)
|
||
https://patient.chatmed.online → 患者前端 (打包成静态文件)
|
||
https://doctor.chatmed.online → 医生前端 (打包成静态文件)
|
||
https://files.chatmed.online → MinIO (9000端口)
|
||
```
|
||
|
||
#### 5.3 前端打包部署
|
||
|
||
现在跑的是开发模式(Vite dev server),上线要用生产模式:
|
||
|
||
```bash
|
||
# 患者端
|
||
cd frontend-patient
|
||
npm run build # 生成 dist/ 文件夹
|
||
# 把 dist/ 里的文件放到 Nginx 的目录下
|
||
|
||
# 医生端同理
|
||
cd frontend-doctor
|
||
npm run build
|
||
```
|
||
|
||
#### 5.4 打包成手机 App
|
||
|
||
如果要在手机上像 App 一样用(不是浏览器打开),两种方案:
|
||
|
||
**方案 A:PWA(推荐,最简单)**
|
||
|
||
在网页基础上加个配置文件,用户浏览器打开后可以"添加到主屏幕",就像真的 App:
|
||
|
||
```json
|
||
// public/manifest.json
|
||
{
|
||
"name": "健康管家",
|
||
"short_name": "健康管家",
|
||
"start_url": "/",
|
||
"display": "standalone", // 全屏,没有浏览器地址栏
|
||
"background_color": "#F2F5FA",
|
||
"theme_color": "#1E6BFF",
|
||
"icons": [
|
||
{ "src": "/icon-192.png", "sizes": "192x192" },
|
||
{ "src": "/icon-512.png", "sizes": "512x512" }
|
||
]
|
||
}
|
||
```
|
||
|
||
再加一个 Service Worker 实现**离线缓存**——没网也能看历史数据。
|
||
|
||
**方案 B:套壳 App(推荐给小白用户)**
|
||
|
||
用 Capacitor 把网页包成一个真实的 APK/IPA:
|
||
|
||
```bash
|
||
npm install @capacitor/core @capacitor/cli
|
||
npx cap init
|
||
npx cap add android # 生成 Android 项目
|
||
npx cap add ios # 生成 iOS 项目
|
||
npx cap sync # 把前端代码同步进去
|
||
```
|
||
|
||
然后分别在 Android Studio 和 Xcode 里打包成 `.apk` 和 `.ipa`,可以上传到应用商店。
|
||
|
||
| 对比 | PWA | Capacitor 套壳 |
|
||
|------|-----|---------------|
|
||
| 开发成本 | 低(只需配置) | 中(需原生打包环境) |
|
||
| 用户安装方式 | 网页上点"添加到桌面" | 应用商店下载 |
|
||
| 离线支持 | 有 | 有 |
|
||
| 推送通知 | iOS 支持有限 | 完整支持 |
|
||
| 应用商店上架 | 不能 | 能 |
|
||
| **建议** | **先做这个,快速验证** | **验证完再做这个** |
|
||
|
||
---
|
||
|
||
## 6. 安全与鉴权
|
||
|
||
### 现状
|
||
|
||
- JWT 登录,30 分钟过期
|
||
- 密码是 SHA256(Demo 够用,上线不够)
|
||
- 没有 HTTPS
|
||
- 没有接口限流
|
||
- 手机验证码是假的(不验证)
|
||
|
||
### 需要做的事
|
||
|
||
#### 6.1 HTTPS + 域名
|
||
|
||
```bash
|
||
# 用 Let's Encrypt 免费申请 SSL 证书
|
||
# 所有请求强制走 HTTPS
|
||
# 后端、前端、MinIO 全部 HTTPS
|
||
```
|
||
|
||
#### 6.2 密码安全
|
||
|
||
```
|
||
当前方案:SHA256(password)
|
||
上线方案:bcrypt 或 Argon2(加盐哈希,防彩虹表攻击)
|
||
```
|
||
|
||
#### 6.3 真实短信验证码
|
||
|
||
接腾讯云短信 / 阿里云短信:
|
||
```
|
||
POST /api/auth/send-sms → 调短信平台API → 用户手机收到验证码
|
||
验证码 5 分钟过期
|
||
同一号码 60 秒内不能重复发送
|
||
```
|
||
|
||
#### 6.4 接口安全
|
||
|
||
| 措施 | 说明 |
|
||
|------|------|
|
||
| 限流 | 同一 IP 每分钟最多 60 次请求 |
|
||
| 登录限流 | 同一手机号 5 次失败后锁定 15 分钟 |
|
||
| 敏感操作二次验证 | 修改手机号、删除数据需要再输入验证码 |
|
||
| SQL 注入防护 | EF Core 已自带参数化查询 |
|
||
| XSS 防护 | 前端 React 已自带转义 |
|
||
| CORS | 只允许自己域名 |
|
||
|
||
#### 6.5 数据脱敏
|
||
|
||
```
|
||
日志里不能记录手机号、密码、真实姓名
|
||
显示时手机号中间四位打星号:138****8000
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 消息推送
|
||
|
||
### 现状
|
||
|
||
- 通知存在数据库里,前端轮询拉取
|
||
- 用户不打开 App 就看不到新消息
|
||
|
||
### 需要做的事
|
||
|
||
#### 7.1 WebSocket 实时推送
|
||
|
||
当前已有 SignalR(`/hubs/chat`),需要扩展到:
|
||
- 新消息实时弹窗
|
||
- 医生解读完成 → 患者立即收到通知
|
||
- 用药提醒时间到了 → 推送通知
|
||
|
||
#### 7.2 App 推送(离线也能收到)
|
||
|
||
| 平台 | 推送服务 |
|
||
|------|---------|
|
||
| Android | Firebase Cloud Messaging (FCM) |
|
||
| iOS | Apple Push Notification Service (APNs) |
|
||
| 国内 Android | 华为/小米/OPPO 推送(不用 FCM) |
|
||
|
||
后端需要新增一个 PushService,统一处理各类推送。
|
||
|
||
---
|
||
|
||
## 8. 运维与监控
|
||
|
||
### 需要做的事
|
||
|
||
#### 8.1 日志系统
|
||
|
||
```
|
||
当前:控制台输出
|
||
需要:Serilog 写入文件 + 集中收集
|
||
├── 请求日志(谁、什么时候、调了什么接口)
|
||
├── 错误日志(哪出错了、堆栈信息)
|
||
└── 慢查询日志(哪些 SQL 耗时超过 500ms)
|
||
```
|
||
|
||
#### 8.2 健康检查
|
||
|
||
```
|
||
GET /health → 检查数据库连接、Redis连接、MinIO连接
|
||
返回 { status: "healthy", db: "ok", redis: "ok", minio: "ok" }
|
||
```
|
||
|
||
自动化监控:每 30 秒检查一次,挂了自动发短信/邮件报警。
|
||
|
||
#### 8.3 性能监控
|
||
|
||
```
|
||
.NET: Application Insights 或 Prometheus
|
||
PostgreSQL: pg_stat_statements 插件
|
||
前端: Web Vitals (LCP, FID, CLS)
|
||
```
|
||
|
||
#### 8.4 自动部署
|
||
|
||
```bash
|
||
# 当 git push 到 main 分支时,服务器自动:
|
||
1. git pull 拉取最新代码
|
||
2. dotnet build 编译后端
|
||
3. npm run build 编译前端
|
||
4. 重启服务
|
||
```
|
||
|
||
用 GitHub Actions 或 Jenkins 实现。
|
||
|
||
---
|
||
|
||
## 9. 开发流程规范化
|
||
|
||
### 当前
|
||
|
||
- 直接在 main 分支上改代码
|
||
- 没有测试
|
||
- 没有代码审查
|
||
|
||
### 需要建立
|
||
|
||
#### 9.1 分支管理
|
||
|
||
```
|
||
main ← 生产环境,只有经过测试的代码才合并进来
|
||
develop ← 开发环境
|
||
feature/* ← 每个新功能一个分支(如 feature/file-upload)
|
||
bugfix/* ← 修 Bug 的分支
|
||
release/* ← 准备上线的版本
|
||
```
|
||
|
||
#### 9.2 提交规范
|
||
|
||
```
|
||
feat: 文件上传功能
|
||
fix: 修复医生看不到报告的bug
|
||
docs: 更新使用手册
|
||
style: 调整首页配色
|
||
refactor: 重构健康数据服务
|
||
test: 添加登录接口测试
|
||
```
|
||
|
||
#### 9.3 自动化测试
|
||
|
||
```
|
||
单元测试:关键业务逻辑(如风险等级计算)
|
||
集成测试:API 接口(用 xUnit + WebApplicationFactory)
|
||
E2E 测试:核心用户流程(用 Playwright)
|
||
```
|
||
|
||
#### 9.4 代码审查
|
||
|
||
每个 PR 至少一个人 Review 后才能合并。
|
||
|
||
---
|
||
|
||
## 10. 完整上线检查清单
|
||
|
||
### 阶段一:Demo 完善(当前 → 2周内)
|
||
|
||
- [x] 后端 API 全功能
|
||
- [x] 患者前端全功能
|
||
- [x] 医生前端全功能
|
||
- [ ] 文件上传到 MinIO
|
||
- [ ] 医生端图片查看
|
||
- [ ] 页面过渡动画
|
||
- [ ] 上报 Bug 修复
|
||
|
||
### 阶段二:内部测试(2-4周)
|
||
|
||
- [ ] 部署到测试服务器
|
||
- [ ] 配置 HTTPS + 域名
|
||
- [ ] 手机号验证码真实对接
|
||
- [ ] 密码改用 bcrypt
|
||
- [ ] 接口限流
|
||
- [ ] 3-5 个真实用户测试
|
||
- [ ] 收集反馈,修复问题
|
||
|
||
### 阶段三:上线准备(4-6周)
|
||
|
||
- [ ] 部署到生产服务器(2核4G起步)
|
||
- [ ] 数据库自动备份
|
||
- [ ] 日志和监控就位
|
||
- [ ] PWA 配置(可添加到手机桌面)
|
||
- [ ] 性能压测(模拟 100 个用户同时用)
|
||
- [ ] 隐私协议 + 用户协议页面
|
||
- [ ] 操作手册终稿
|
||
|
||
### 阶段四:正式运营(6-8周+)
|
||
|
||
- [ ] 上线运营
|
||
- [ ] 用户反馈渠道
|
||
- [ ] 定期数据备份验证
|
||
- [ ] 根据数据做功能迭代
|
||
- [ ] 考虑 App 应用商店上架(Capacitor 打包)
|
||
- [ ] 如果需要,接微信小程序
|
||
|
||
---
|
||
|
||
## 总结:Demo vs 上线 差异一览
|
||
|
||
| 维度 | 当前 Demo | 上线产品 |
|
||
|------|----------|---------|
|
||
| 文件存储 | 没存,imageUrls 为空 | MinIO 存储,返回真实 URL |
|
||
| 网络 | localhost | 域名 + HTTPS |
|
||
| 鉴权 | JWT + SHA256 密码 | JWT + bcrypt + 短信验证码 |
|
||
| 推送 | 前端轮询 | SignalR 实时 + App 离线推送 |
|
||
| 前端 | Vite dev server | Nginx 静态文件 / PWA / App |
|
||
| 数据库 | 本地 PostgreSQL | 服务器 PostgreSQL + 每日备份 |
|
||
| 日志 | 控制台 | 文件 + 集中收集 |
|
||
| 测试 | 无 | 单元 + 集成 + E2E |
|
||
| 部署 | 手动 dotnet run | 自动化 CI/CD |
|
||
| 监控 | 无 | 健康检查 + 性能 + 报警 |
|
||
| 动画 | 基础 CSS | framer-motion 全页面动画 |
|
||
| 安全 | CORS | 限流 + HTTPS + 脱敏 + 审计 |
|
||
|
||
**最优先要做的三件事**:① 文件上传存 MinIO → ② 部署到服务器 → ③ HTTPS + 真实短信
|