一个完整的在线医疗问诊系统,使用 Next.js、Node.js 和 Python 技术栈构建,支持图文问诊、实时消息会话、智能分诊、处方开具与审核、支付等完整业务流程。
| 服务 |
技术 |
功能描述 |
| Frontend |
Next.js 14 + TypeScript + Tailwind CSS + Zustand |
问诊室、病历、处方、支付页面 |
| Backend (Node.js) |
Express + TypeScript + MongoDB + Socket.io |
消息会话、问诊单管理、处方审核、退款处理 |
| Backend (Python) |
Flask + Scikit-learn + NLTK + Jieba |
智能分诊、药品推荐、病历结构化提取 |
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (Next.js) │
│ ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ │
│ │ 登录页 │ 首页 │ 智能分诊│ 问诊室 │ 处方页 │ 支付页 │ │
│ └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ HTTP / WebSocket
▼
┌─────────────────────────────────────────────────────────────────┐
│ Node.js Backend (Express) │
│ ┌──────────┬──────────┬──────────┬──────────┬──────────┐ │
│ │ Auth │ Consult. │ Message │ Prescrip.│ Payment │ │
│ │ 认证 │ 问诊管理 │ 消息会话 │ 处方管理 │ 支付管理 │ │
│ └──────────┴──────────┴──────────┴──────────┴──────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ MongoDB (数据存储) │ │
│ │ Users | Doctors | Patients | Consultations | Messages │ │
│ │ Prescriptions | Medicines | MedicalRecords | Payments │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Socket.io (实时通信) │ │
│ │ 消息推送 | 状态同步 | 在线状态管理 │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ HTTP API
▼
┌─────────────────────────────────────────────────────────────────┐
│ Python Backend (Flask) │
│ ┌──────────────────┬──────────────────┬──────────────────┐ │
│ │ 智能分诊服务 │ 药品推荐服务 │ 病历结构化提取 │ │
│ │ Triage Service │ Medicine Recomm. │ NLP Extraction │ │
│ │ │ │ │ │
│ │ 症状分析 │ 诊断-药品匹配 │ 主诉提取 │ │
│ │ 科室推荐 │ 症状相关性计算 │ 诊断识别 │ │
│ │ 紧急程度评估 │ 用药建议生成 │ 用药提取 │ │
│ └──────────────────┴──────────────────┴──────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
- 角色体系: 患者、医生、药师、管理员
- JWT 认证: Access Token + Refresh Token
- 权限控制: 基于角色的路由保护
- 密码安全: bcrypt 加密存储
- 症状分析: 基于症状关键词匹配
- 科室推荐: 症状-科室映射规则
- 紧急程度评估: 低/中/高/急诊四级
- 置信度计算: 基于症状数量和匹配度
- 分析摘要: 自动生成分诊建议
患者发起问诊 → 智能分诊 → 选择医生 → 支付 → 等待接诊 → 问诊中
↓
完成 ← 医生总结 ← 开具处方 ← 消息会话
- 问诊状态: pending_payment → paid → waiting_doctor → in_consultation → doctor_reviewing → completed
- 问诊类型: 图文问诊、语音问诊、视频问诊
- 实时消息: Socket.io 实时通信,支持文本、图片、文件
医生开具处方 → 药师审核 → 患者支付 → 发药
↓
审核不通过 → 退回医生
- 处方状态: draft → pending_review → reviewed → pending_payment → paid → dispensed
- 药品推荐: Python 服务基于诊断和症状推荐药品
- 库存管理: 自动扣减药品库存
- 支付方式: 支付宝、微信支付、余额、医保 (模拟)
- 支付状态: pending → processing → paid → failed → refunded
- 退款流程: 患者申请 → 审核 → 退款
- 电子病历: 结构化存储就诊信息
- 病历提取: Python 服务自动从文本中提取结构化信息
- 病历查询: 按患者/医生/时间查询
Next.js-Node.js-Python-/
├── frontend/ # Next.js 前端
│ ├── src/
│ │ ├── app/ # Next.js App Router
│ │ │ ├── consultations/ # 问诊相关页面
│ │ │ │ ├── [id]/ # 问诊室页面
│ │ │ │ └── new/ # 新建问诊页面
│ │ │ ├── dashboard/ # 首页/仪表盘
│ │ │ ├── login/ # 登录页
│ │ │ ├── register/ # 注册页
│ │ │ ├── triage/ # 智能分诊页
│ │ │ ├── globals.css # 全局样式
│ │ │ ├── layout.tsx # 根布局
│ │ │ └── page.tsx # 首页
│ │ ├── components/ # 公共组件
│ │ │ ├── Layout/ # 布局组件
│ │ │ │ ├── MainLayout.tsx # 主布局
│ │ │ │ └── Sidebar.tsx # 侧边栏
│ │ │ └── providers/ # 上下文提供者
│ │ │ └── Providers.tsx
│ │ ├── lib/ # 工具函数
│ │ │ ├── api.ts # API 封装
│ │ │ └── utils.ts # 通用工具
│ │ ├── stores/ # 状态管理 (Zustand)
│ │ │ ├── authStore.ts # 认证状态
│ │ │ ├── consultationStore.ts # 问诊状态
│ │ │ └── prescriptionStore.ts # 处方状态
│ │ └── types/ # TypeScript 类型定义
│ │ └── index.ts
│ ├── next.config.js
│ ├── package.json
│ ├── tailwind.config.ts
│ └── tsconfig.json
│
├── backend-node/ # Node.js 后端
│ ├── src/
│ │ ├── config/ # 配置
│ │ │ ├── database.ts # MongoDB 连接
│ │ │ └── env.ts # 环境变量
│ │ ├── controllers/ # 控制器
│ │ │ ├── authController.ts # 认证
│ │ │ ├── consultationController.ts # 问诊
│ │ │ ├── medicineController.ts # 药品
│ │ │ ├── messageController.ts # 消息
│ │ │ ├── paymentController.ts # 支付
│ │ │ └── prescriptionController.ts # 处方
│ │ ├── middleware/ # 中间件
│ │ │ ├── auth.ts # 认证中间件
│ │ │ └── errorHandler.ts # 错误处理
│ │ ├── models/ # 数据模型 (Mongoose)
│ │ │ ├── User.ts # 用户
│ │ │ ├── Doctor.ts # 医生
│ │ │ ├── Patient.ts # 患者
│ │ │ ├── Pharmacist.ts # 药师
│ │ │ ├── Consultation.ts # 问诊
│ │ │ ├── Message.ts # 消息
│ │ │ ├── Prescription.ts # 处方
│ │ │ ├── Medicine.ts # 药品
│ │ │ ├── MedicalRecord.ts # 病历
│ │ │ ├── Payment.ts # 支付
│ │ │ ├── Department.ts # 科室
│ │ │ └── index.ts
│ │ ├── routes/ # 路由
│ │ │ ├── authRoutes.ts # 认证路由
│ │ │ ├── consultationRoutes.ts # 问诊路由
│ │ │ ├── doctorRoutes.ts # 医生路由
│ │ │ ├── medicineRoutes.ts # 药品路由
│ │ │ ├── paymentRoutes.ts # 支付路由
│ │ │ ├── prescriptionRoutes.ts # 处方路由
│ │ │ └── index.ts
│ │ ├── socket/ # Socket.io
│ │ │ └── socketHandler.ts # Socket 处理器
│ │ ├── utils/ # 工具
│ │ │ ├── jwt.ts # JWT 工具
│ │ │ ├── response.ts # 响应封装
│ │ │ └── seedData.ts # 种子数据
│ │ ├── app.ts # Express 应用
│ │ └── server.ts # 服务器入口
│ ├── .env.example
│ ├── package.json
│ └── tsconfig.json
│
└── backend-python/ # Python 后端
├── app/
│ ├── models/ # 数据模型
│ │ └── symptoms.py # 症状库
│ ├── routes/ # 路由
│ │ └── api_routes.py # API 路由
│ ├── services/ # 服务
│ │ ├── triage_service.py # 智能分诊服务
│ │ ├── medicine_recommendation_service.py # 药品推荐服务
│ │ └── medical_record_service.py # 病历提取服务
│ ├── __init__.py
│ └── config.py # 配置
├── .env.example
├── app.py # Flask 应用入口
└── requirements.txt
- Node.js >= 18.0.0
- Python >= 3.9
- MongoDB >= 5.0
- npm 或 yarn
- pip
# 安装前端依赖
cd frontend
npm install
# 安装 Node.js 后端依赖
cd ../backend-node
npm install
# 安装 Python 后端依赖
cd ../backend-python
pip install -r requirements.txt
# Node.js 后端
cd backend-node
cp .env.example .env
# 编辑 .env,配置 MongoDB URI、JWT_SECRET 等
# Python 后端
cd ../backend-python
cp .env.example .env
# 编辑 .env,配置必要参数
# 1. 启动 MongoDB (确保已安装并运行)
# 或使用 Docker: docker run -d -p 27017:27017 mongo
# 2. 启动 Python 服务
cd backend-python
python app.py
# 服务运行在 http://localhost:5001
# 3. 启动 Node.js 服务 (新终端)
cd backend-node
npm run dev
# 服务运行在 http://localhost:3001
# 4. 启动前端 (新终端)
cd frontend
npm run dev
# 服务运行在 http://localhost:3000
开发环境启动时会自动创建以下测试账号:
| 方法 |
路径 |
说明 |
| POST |
/api/auth/login |
用户登录 |
| POST |
/api/auth/register |
用户注册 |
| POST |
/api/auth/logout |
用户登出 |
| GET |
/api/auth/me |
获取当前用户 |
| POST |
/api/auth/refresh |
刷新令牌 |
| 方法 |
路径 |
说明 |
| GET |
/api/consultations |
获取问诊列表 |
| POST |
/api/consultations |
创建问诊 |
| GET |
/api/consultations/:id |
获取问诊详情 |
| PUT |
/api/consultations/:id/status |
更新问诊状态 |
| POST |
/api/consultations/:id/cancel |
取消问诊 |
| POST |
/api/consultations/:id/refund |
申请退款 |
| 方法 |
路径 |
说明 |
| GET |
/api/consultations/:id/messages |
获取消息列表 |
| POST |
/api/consultations/:id/messages |
发送消息 |
| POST |
/api/consultations/:id/messages/read |
标记已读 |
| 方法 |
路径 |
说明 |
| GET |
/api/prescriptions |
获取处方列表 |
| POST |
/api/prescriptions |
开具处方 |
| GET |
/api/prescriptions/:id |
获取处方详情 |
| POST |
/api/prescriptions/:id/submit |
提交审核 |
| POST |
/api/prescriptions/:id/review |
审核处方 |
| POST |
/api/prescriptions/:id/dispense |
发药 |
| 方法 |
路径 |
说明 |
| GET |
/api/payments |
获取支付记录 |
| POST |
/api/payments |
创建支付订单 |
| GET |
/api/payments/:id |
获取支付详情 |
| POST |
/api/payments/:id/process |
处理支付 |
| POST |
/api/payments/:id/refund |
申请退款 |
| 方法 |
路径 |
说明 |
| POST |
/api/triage/analyze |
智能分诊分析 |
| POST |
/api/triage/quick |
快速分诊 |
| POST |
/api/medicine/recommend |
药品推荐 |
| GET |
/api/medicine/search |
搜索药品 |
| GET |
/api/medicine/:id |
获取药品详情 |
| POST |
/api/medical-records/extract |
病历结构化提取 |
| POST |
/api/medical-records/quick-extract |
快速提取 |
- 患者登录 → 访问
/login
- 智能分诊 → 输入症状 → 系统推荐科室和医生 (
/triage)
- 选择医生 → 从推荐列表选择医生
- 发起问诊 → 填写问诊单 → 创建订单 (
/consultations/new)
- 支付 → 完成支付 → 状态更新为
paid
- 等待医生接诊 → 状态
waiting_doctor
- 医生接诊 → 状态变为
in_consultation
- 消息会话 → 实时消息沟通 (
/consultations/:id)
- 医生开具处方 → 选择药品 → 提交审核
- 药师审核 → 通过 → 状态
reviewed
- 患者支付处方 → 状态
paid
- 发药 → 状态
dispensed
- 问诊完成 → 状态
completed
// 客户端连接
const socket = io('http://localhost:3001', {
query: { token: 'jwt_token' }
});
// 加入问诊房间
socket.emit('join_consultation', { consultationId: 'xxx' });
// 发送消息
socket.emit('send_message', {
consultationId: 'xxx',
type: 'text',
content: '你好医生'
});
// 接收消息
socket.on('message', (message) => {
console.log('收到消息:', message);
});
// 对方正在输入
socket.on('user_typing', (data) => {
console.log(data.userId, '正在输入');
});
┌─────────┐ ┌──────────────┐ ┌─────────┐
│ User │ │ Consultation │ │ Doctor │
├─────────┤ ├──────────────┤ ├─────────┤
│ id │◄──────│ patientId │ │ userId │
│ email │ │ doctorId │──────►│ ... │
│ name │ │ status │ └─────────┘
│ role │ │ type │
└────┬────┘ │ ... │
│ └──────┬───────┘
│ │
▼ ▼
┌─────────┐ ┌──────────────┐
│ Patient │ │ Message │
├─────────┤ ├──────────────┤
│ userId │ │ consultationId│
│ ... │ │ senderId │
└─────────┘ │ content │
│ ... │
└──────┬───────┘
│
┌──────────────┐ │ ┌──────────────┐
│ Prescription │◄────────┴────────►│ Medicine │
├──────────────┤ ├──────────────┤
│ consultationId│ │ name │
│ items[] │ │ category │
│ status │ │ price │
│ ... │ │ stock │
└──────────────┘ └──────────────┘
┌─────────────────────────────────────────┐
▼ │
pending_payment ──► paid ──► waiting_doctor ──► in_consultation
│ │ │ │
│ │ │ ▼
│ │ │ doctor_reviewing
│ │ │ │
│ │ │ ▼
└──► cancelled ◄─┴──► cancelled◄─┴──► cancelled ─► completed
│
▼
refund_pending
│
▼
refunded
draft ──► pending_review ──► reviewed ──► pending_payment ──► paid ──► dispensed
│ │ │ │
└────────────┴───────────────┴────────────────┴──► cancelled
│
▼
refunded
- JWT Token 双令牌机制 (Access Token + Refresh Token)
- 密码 bcrypt 加密存储 (盐值 10 轮)
- 登录失败次数限制
- Token 过期时间控制
- 基于角色的路由保护 (RBAC)
- 资源级权限验证 (如只能访问自己的问诊记录)
- 敏感操作二次验证
- 输入验证 (Zod/Express Validator)
- SQL/NoSQL 注入防护
- XSS 防护
- 敏感数据脱敏 (手机号、身份证号等)
- HTTPS 强制 (生产环境)
- CORS 配置
- 安全响应头 (Helmet)
- 数据库: 索引优化、连接池、读写分离
- 缓存: Redis 缓存热点数据、会话管理
- 消息: 消息异步处理、批量发送
- 前端: 代码分割、懒加载、缓存策略
- 部署: 容器化、负载均衡、水平扩展
MIT License
欢迎提交 Issue 和 Pull Request!
注意: 此项目为演示用途,生产环境使用前请进行充分的安全审计和性能测试。