# 🏥 患者画像回访话术系统

[![Python](https://img.shields.io/badge/Python-3.12+-blue.svg)](https://python.org)
[![Flask](https://img.shields.io/badge/Flask-3.1.1-green.svg)](https://flask.palletsprojects.com/)
[![MySQL](https://img.shields.io/badge/MySQL-8.0-orange.svg)](https://mysql.com)
[![Docker](https://img.shields.io/badge/Docker-Compose-blue.svg)](https://docker.com)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

> 基于 Flask + MySQL 的现代化患者回访管理系统，支持多门诊管理、智能数据导出、用户权限控制等功能。

## 📋 目录

- [🎯 项目概述](#-项目概述)
- [✨ 核心功能](#-核心功能)
- [🏗️ 技术架构](#️-技术架构)
- [🚀 快速开始](#-快速开始)
- [📦 部署方式](#-部署方式)
- [🔧 配置说明](#-配置说明)
- [📊 数据库设计](#-数据库设计)
- [🔐 权限管理](#-权限管理)
- [📈 API 文档](#-api-文档)
- [🛠️ 开发指南](#️-开发指南)
  - [数据库迁移与版本管理](#数据库迁移与版本管理)
- [📝 更新日志](#-更新日志)
- [🤝 贡献指南](#-贡献指南)

## 🎯 项目概述

患者画像回访话术系统是一个专为医疗机构设计的现代化患者回访管理平台。系统支持多门诊统一管理，提供完整的患者信息录入、回访记录管理、数据统计分析等功能，帮助医疗机构提升患者服务质量和管理效率。

### 🌟 项目特色

- **🏢 多门诊支持**：统一平台管理多个门诊的患者数据
- **👥 角色权限**：管理员和门诊用户的分级权限管理
- **📊 智能导出**：一键导出 Excel 报表，支持中文文件名
- **🔄 实时同步**：基于 Flask-SQLAlchemy 的实时数据同步
- **🐳 容器化部署**：Docker Compose 一键部署，零配置启动
- **📱 响应式设计**：现代化 Web 界面，支持移动端访问

## ✨ 核心功能

### 👤 用户管理
- **多角色支持**：管理员、门诊用户两级权限
- **安全认证**：基于 Session 的用户认证机制
- **权限控制**：细粒度的功能权限管理

### 🏥 门诊管理
- **多门诊支持**：支持多个门诊的统一管理
- **门诊配置**：灵活的门诊信息配置
- **数据隔离**：不同门诊数据安全隔离

### 👥 患者管理
- **患者档案**：完整的患者信息管理
- **病历关联**：患者与病历号的关联管理
- **诊断记录**：支持 JSON 格式的诊断信息存储

### 📞 回访管理
- **回访记录**：详细的回访过程记录
- **多种方式**：支持电话、微信等多种回访方式
- **结果跟踪**：成功、不成功、放弃回访的状态管理
- **操作员记录**：完整的操作员信息追踪

### 📊 数据分析
- **统计报表**：实时的数据统计分析
- **Excel 导出**：支持中文文件名的 Excel 导出
- **内存处理**：高效的内存数据处理，无临时文件
- **多维度分析**：按门诊、时间、结果等多维度分析

## 🏗️ 技术架构

### 后端技术栈
- **Web 框架**：Flask 3.1.1
- **数据库 ORM**：Flask-SQLAlchemy 3.1.1
- **数据库迁移**：Flask-Migrate 4.0.7 (基于 Alembic)
- **数据库**：MySQL 8.0
- **数据处理**：Pandas 2.2.3, OpenPyXL 3.1.5
- **HTTP 客户端**：Requests 2.31.0

### 前端技术栈
- **模板引擎**：Jinja2
- **样式框架**：Bootstrap + 自定义 CSS
- **JavaScript**：原生 ES6+
- **图标库**：Font Awesome

### 基础设施
- **容器化**：Docker + Docker Compose
- **数据库**：MySQL 8.0 with utf8mb4
- **反向代理**：支持 Nginx 集成
- **CI/CD**：GitLab CI/CD 自动部署

### 项目结构
```
customer-recall/
├── app.py                 # 应用入口文件
├── config.py             # 配置管理
├── requirements.txt      # Python 依赖
├── Dockerfile           # Docker 镜像构建
├── docker-compose.yml   # 容器编排配置
├── .gitlab-ci.yml       # CI/CD 配置
├── routes/              # 路由模块
│   ├── __init__.py     # 路由注册
│   ├── auth.py         # 认证路由
│   ├── patient.py      # 患者管理路由
│   ├── callback.py     # 回访管理路由
│   └── api.py          # API 路由
├── database/           # 数据库模块
│   ├── models.py       # 数据模型定义
│   ├── scripts/        # 数据库管理脚本
│   │   ├── migration_manager.py  # 迁移管理器
│   │   ├── entrypoint.sh         # 容器启动脚本
│   │   └── wait-for-db.py        # 数据库就绪检查
│   └── migrations/     # Flask-Migrate 迁移文件
│       ├── env.py      # 迁移环境配置
│       └── versions/   # 版本迁移文件目录
├── templates/          # HTML 模板
│   ├── base.html       # 基础模板
│   ├── login.html      # 登录页面
│   ├── patient_list.html    # 患者列表
│   ├── patient_detail.html  # 患者详情
│   └── admin_dashboard.html # 管理员仪表板
└── data/              # 数据目录
    ├── patients/      # 患者数据
    ├── callbacks/     # 回访数据
    └── generators/    # 数据生成器
```

## 🚀 快速开始

### 环境要求
- **操作系统**：Windows 10+, macOS 10.14+, Linux (Ubuntu 18.04+)
- **Python**：3.12+ (推荐 3.12.9)
- **数据库**：MySQL 8.0+
- **容器化**：Docker & Docker Compose (推荐用于生产部署)
- **开发工具**：Git, VS Code/PyCharm (可选)

### 方式一：Docker Compose 部署（推荐）

1. **克隆项目**
```bash
git clone <repository-url>
cd customer-recall
```

2. **启动服务**
```bash
docker compose up -d
```

> 🔄 **自动化流程**：容器启动时会自动执行数据库迁移，确保数据库结构为最新版本

3. **访问系统**
- 应用地址：http://localhost:4002
- 健康检查：http://localhost:4002/api/health

### 方式二：本地开发部署

1. **创建虚拟环境**
```bash
# Linux/Mac
python -m venv venv
source venv/bin/activate

# Windows
python -m venv venv
venv\Scripts\activate
```

2. **安装依赖**
```bash
pip install -r requirements.txt
```

3. **配置数据库**
```bash
# Linux/Mac - 修改 config.py 中的数据库配置或设置环境变量
export DB_HOST=localhost
export DB_USER=callback_user
export DB_PASSWORD=your_password
export DB_NAME=callback_system

# Windows - 设置环境变量
set DB_HOST=localhost
set DB_USER=callback_user
set DB_PASSWORD=your_password
set DB_NAME=callback_system
```

4. **初始化数据库**
```bash
# 设置 Flask 应用
# Linux/Mac
export FLASK_APP=app.py

# Windows
set FLASK_APP=app.py

# 运行数据库迁移（推荐）
flask db upgrade

# 或者使用自动化迁移管理器
python database/scripts/migration_manager.py
```

5. **启动开发服务器**
```bash
# 开发模式启动（推荐）- 支持热重载
# Linux/Mac
FLASK_ENV=development python app.py

# Windows
set FLASK_ENV=development && python app.py

# 或者直接启动（已内置开发模式配置）
python app.py
```

6. **访问应用**
- 应用地址：http://localhost:5001
- 开发模式会自动启用热重载和调试功能

### 默认账户

系统预置了多个测试账户：

**管理员账户**
- 用户名：`admin`
- 密码：`admin123`
- 权限：全系统管理权限

**门诊用户示例**
- 学前街门诊：`jinqin` / `jinqin123`
- 新吴门诊：`litingting` / `litingting123`
- 更多账户请查看 `config.py` 中的 `DEFAULT_USERS`

## 📦 部署方式

### 生产环境部署

1. **环境变量配置**
```bash
# 方式一：直接设置环境变量
export FLASK_ENV=production
export SECRET_KEY=your-secret-key-here
export DB_HOST=mysql
export DB_PASSWORD=your-secure-password

# 方式二：修改 docker-compose.yml 中的环境变量
# 编辑 docker-compose.yml 文件中的 environment 部分
```

2. **生产环境启动**
```bash
docker compose up -d
```

3. **健康检查**
```bash
curl http://localhost:4002/api/health
```

### CI/CD 自动部署

项目支持 GitLab CI/CD 自动部署：

1. 配置 GitLab Runner
2. 设置环境变量：`SSH_PRIVATE_KEY`, `SSH_HOST`, `SSH_USER`, `SSH_PORT`
3. 推送到 `master` 分支自动触发部署

## 🔧 配置说明

项目使用 `config.py` 文件进行配置管理，支持环境变量覆盖默认值。

### 数据库配置

```python
# config.py - 配置优先级：环境变量 > 默认值
class Config:
    # 数据库连接配置
    DB_HOST = os.environ.get('DB_HOST', 'localhost')
    DB_PORT = int(os.environ.get('DB_PORT', '3306'))
    DB_USER = os.environ.get('DB_USER', 'callback_user')
    DB_PASSWORD = os.environ.get('DB_PASSWORD', 'dev_password_123')
    DB_NAME = os.environ.get('DB_NAME', 'callback_system')
    DB_CHARSET = os.environ.get('DB_CHARSET', 'utf8mb4')

    # 应用安全配置
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key-change-in-production'
```

### 配置方式

**方式一：环境变量（推荐）**
```bash
# Linux/Mac
export DB_HOST=localhost
export DB_PASSWORD=your_password
export SECRET_KEY=your-secret-key

# Windows
set DB_HOST=localhost
set DB_PASSWORD=your_password
set SECRET_KEY=your-secret-key
```

**方式二：直接修改 config.py**
```python
# 修改 config.py 中的默认值（不推荐用于生产环境）
DB_PASSWORD = 'your_password_here'
SECRET_KEY = 'your-secret-key-here'
```

### 门诊配置

```python
# config.py
CLINIC_CONFIG = {
    'clinic_xuexian': {'clinic_name': '学前街门诊'},
    'clinic_dafeng': {'clinic_name': '大丰门诊'},
    'clinic_dongting': {'clinic_name': '东亭门诊'},
    # ... 更多门诊配置
}
```

### 用户配置

系统使用内置的用户认证系统，预置用户配置在 `config.py` 中：

```python
# config.py - 预置用户账户
DEFAULT_USERS = [
    # 管理员账户
    {'username': 'admin', 'password': 'admin123', 'role': 'admin', 'real_name': '系统管理员'},

    # 门诊用户示例
    {'username': 'jinqin', 'password': 'jinqin123', 'role': 'clinic_user',
     'clinic_id': 'clinic_xuexian', 'real_name': '金沁', 'clinic_name': '学前街门诊'},

    # ... 更多用户配置
]
```

**用户管理特性**：
- **预置账户**：系统启动时自动创建默认用户
- **角色权限**：支持 `admin` 和 `clinic_user` 两种角色
- **门诊关联**：门诊用户与特定门诊绑定
- **密码安全**：生产环境请修改默认密码

## 📊 数据库设计

### 核心表结构

#### 用户表 (users)
- `user_id`: 用户ID (主键)
- `username`: 用户名 (唯一)
- `password_hash`: 密码哈希
- `user_type`: 用户类型
- `clinic_access`: 诊所访问权限 (JSON)

#### 门诊表 (clinics)
- `clinic_id`: 门诊ID (主键)
- `clinic_name`: 门诊名称
- `clinic_code`: 门诊代码 (唯一)
- `clinic_address`: 门诊地址
- `is_active`: 是否激活

#### 患者表 (patients)
- `patient_id`: 患者ID (主键)
- `case_number`: 病历号 (唯一)
- `patient_name`: 患者姓名
- `patient_phone`: 患者电话
- `clinic_id`: 所属门诊ID (外键)
- `diagnosis`: 诊断信息 (JSON)

#### 回访记录表 (callback_records)
- `record_id`: 记录ID (主键)
- `case_number`: 病历号 (外键)
- `callback_methods`: 回访方式 (JSON)
- `callback_result`: 回访结果
- `callback_record`: 回访记录
- `operator`: 操作员

### 数据关系
- 一个门诊可以有多个患者 (1:N)
- 一个患者可以有多条回访记录 (1:N)
- 用户与门诊通过权限配置关联

## 🔐 权限管理

### 角色定义

1. **管理员 (admin)**
   - 查看所有门诊数据
   - 导出系统数据
   - 系统配置管理
   - 用户管理

2. **门诊用户 (clinic_user)**
   - 查看所属门诊患者数据
   - 添加/编辑回访记录
   - 查看回访统计

### 权限控制

- **路由级权限**：通过装饰器控制路由访问
- **数据级权限**：根据用户所属门诊过滤数据
- **功能级权限**：不同角色显示不同功能菜单

## 📈 API 文档

### 认证 API

#### POST /login
用户登录

**请求参数**
```json
{
    "username": "string",
    "password": "string"
}
```

**响应**
```json
{
    "success": true,
    "message": "登录成功",
    "redirect_url": "/dashboard"
}
```

### 数据 API

#### GET /api/export-data
导出系统数据（管理员权限）

**响应**
- 直接返回 Excel 文件二进制流
- Content-Type: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`

#### GET /api/system-info
获取系统统计信息（管理员权限）

**响应**
```json
{
    "success": true,
    "data": {
        "total_callback_records": 100,
        "total_patients": 50,
        "total_clinics": 9,
        "system_time": "2025-01-01T00:00:00",
        "database_status": "connected"
    }
}
```

#### GET /api/health
系统健康检查

**响应**
```json
{
    "status": "healthy",
    "timestamp": "2025-01-01T00:00:00",
    "version": "1.0.0"
}
```

## 🛠️ 开发指南

### 本地开发环境搭建

1. **创建虚拟环境**
```bash
# Linux/Mac
python -m venv venv
source venv/bin/activate

# Windows
python -m venv venv
venv\Scripts\activate
```

2. **安装开发依赖**
```bash
pip install -r requirements.txt
```

3. **配置开发数据库**
```sql
-- 启动 MySQL 服务，然后创建数据库和用户
-- 连接到 MySQL
mysql -u root -p

-- 创建数据库
CREATE DATABASE callback_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 创建用户
CREATE USER 'callback_user'@'localhost' IDENTIFIED BY 'dev_password_123';

-- 授权
GRANT ALL PRIVILEGES ON callback_system.* TO 'callback_user'@'localhost';
FLUSH PRIVILEGES;
```

4. **设置环境变量**
```bash
# Linux/Mac
export FLASK_APP=app.py
export FLASK_ENV=development

# Windows
set FLASK_APP=app.py
set FLASK_ENV=development
```

5. **运行数据库迁移（如果需要）**
```bash
flask db upgrade
```

6. **启动开发服务器**
```bash
# 方式一：使用环境变量启动（推荐）
# Linux/Mac
FLASK_ENV=development python app.py

# Windows
set FLASK_ENV=development && python app.py

# 方式二：直接启动（已内置开发配置）
python app.py
```

7. **开发服务器特性**
- **热重载**：代码修改后自动重启
- **调试模式**：详细的错误信息和调试工具
- **端口配置**：默认运行在 http://localhost:5001
- **跨平台支持**：Windows、macOS、Linux 完全兼容

### 开发模式说明

项目已内置开发环境配置，支持以下特性：

```python
# app.py 中的开发配置
if __name__ == '__main__':
    app.run(
        host='0.0.0.0',      # 允许外部访问
        port=5001,           # 端口配置
        debug=True,          # 调试模式
        use_reloader=True,   # 热重载
        threaded=True        # 多线程支持
    )
```

**环境变量优先级**：
1. `FLASK_ENV=development` - 启用开发模式
2. `FLASK_DEBUG=1` - 启用调试模式
3. 代码中的默认配置

**Windows 用户注意事项**：
- 使用 `set` 命令设置环境变量
- 使用 `&&` 连接命令
- 推荐使用 PowerShell 或 Git Bash
- 虚拟环境激活脚本位于 `venv\Scripts\activate`

### 代码规范

- **Python 代码**：遵循 PEP 8 规范
- **注释规范**：使用中文注释，函数需要 docstring
- **命名规范**：
  - 变量和函数：snake_case
  - 类名：PascalCase
  - 常量：UPPER_CASE

### 数据库迁移与版本管理

项目使用 Flask-Migrate 进行数据库版本管理，支持自动化的数据库结构变更和版本控制。

#### 🔄 迁移机制概述

- **自动检测**：Flask-Migrate 自动检测模型变化
- **版本控制**：每次变更生成唯一的迁移版本
- **增量更新**：只应用新的迁移，避免重复操作
- **可回滚**：支持回退到任意历史版本
- **生产安全**：线上部署时自动执行迁移

#### 📋 迁移命令详解

```bash
# 查看当前数据库版本
flask db current

# 查看迁移历史
flask db history

# 查看最新版本
flask db heads

# 创建迁移文件（开发阶段）
flask db migrate -m "Add user nickname field"

# 应用迁移到最新版本
flask db upgrade

# 回退到指定版本
flask db downgrade <version_id>

# 回退一个版本
flask db downgrade -1

# 查看迁移详情
flask db show <version_id>

# 标记数据库状态（用于已有数据库）
flask db stamp head
```

#### 🚀 功能迭代开发流程

当需要添加新功能涉及数据库变更时，请按以下流程操作：

**1. 修改数据库模型**
```python
# 编辑 database/models.py
class User(db.Model):
    # 添加新字段
    nickname = db.Column(db.String(100), comment='用户昵称')
```

**2. 生成迁移文件**
```bash
# 自动检测模型变化并生成迁移文件
flask db migrate -m "Add nickname field to User table"
```

**3. 检查生成的迁移文件**
```bash
# 查看生成的迁移文件
ls database/migrations/versions/
# 检查迁移内容是否正确
cat database/migrations/versions/xxx_add_nickname_field.py
```

**4. 本地测试迁移**
```bash
# 执行迁移
flask db upgrade

# 验证结果
flask db current
```

**5. 提交代码**
```bash
git add .
git commit -m "feat: add nickname field to User table"
git push origin main
```

**6. 线上自动部署**
```bash
# 线上部署时会自动执行迁移
docker compose up -d --build
```

#### 🛡️ 线上部署安全机制

系统内置了智能的迁移管理机制，确保线上部署的安全性：

**首次部署到已有数据库**
- 自动检测是否存在 `alembic_version` 表
- 如果不存在，执行 `stamp` 操作标记为最新版本
- 避免重复创建已存在的表结构

**增量部署**
- 只执行新的迁移文件
- 自动跳过已应用的迁移
- 保证数据完整性

**错误处理**
- 迁移失败时容器不会启动
- 详细的错误日志便于排查问题
- 支持手动回滚和修复

#### 📊 版本管理最佳实践

**开发阶段**
```bash
# 本地开发时使用
python -m flask db migrate -m "描述性的变更信息"
python -m flask db upgrade
```

**测试阶段**
```bash
# 在测试环境验证迁移
docker compose up -d mysql  # 只启动数据库
python -m flask db upgrade  # 本地执行迁移测试
```

**生产部署**
```bash
# 生产环境自动执行（通过 entrypoint.sh）
docker compose up -d --build
```

**回滚操作**
```bash
# 如果需要回滚（谨慎操作）
flask db downgrade <previous_version_id>

# 或者删除迁移文件并手动调整数据库
rm database/migrations/versions/xxx_problematic_migration.py
flask db stamp <target_version_id>
```

#### 🔧 迁移文件管理

**迁移文件位置**
```
database/migrations/versions/
├── 001_production_baseline.py          # 生产基线版本
├── 9bd0518d29b3_add_new_features.py   # 功能增强版本
└── xxx_your_new_migration.py          # 新的迁移文件
```

**迁移文件命名规范**
- 自动生成的版本ID（如：`9bd0518d29b3`）
- 描述性的变更信息（如：`add_nickname_field_to_user_table`）
- 时间戳记录创建时间

**版本依赖关系**
- 每个迁移文件都有 `down_revision` 指向前一个版本
- 形成完整的版本链条
- 支持分支合并和冲突解决

#### ⚠️ 注意事项

**数据安全**
- 生产环境变更前务必备份数据库
- 测试环境充分验证迁移脚本
- 避免删除包含重要数据的字段

**性能考虑**
- 大表结构变更可能需要较长时间
- 考虑在低峰期执行重要迁移
- 监控迁移过程的性能影响

**团队协作**
- 迁移文件需要提交到版本控制
- 避免多人同时修改相同的表结构
- 及时同步和解决迁移冲突

### 测试

```bash
# 运行测试
python -m pytest

# 运行特定测试
python -m pytest tests/test_auth.py

# 生成覆盖率报告
python -m pytest --cov=app
```

## 🤝 贡献指南

我们欢迎所有形式的贡献！

### 贡献方式

1. **报告问题**：在 Issues 中报告 bug 或提出功能建议
2. **提交代码**：Fork 项目，创建分支，提交 Pull Request
3. **改进文档**：帮助完善项目文档
4. **测试反馈**：提供测试反馈和使用建议

### 开发流程

1. Fork 本项目
2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 创建 Pull Request

### 代码审查

- 所有 PR 需要通过代码审查
- 确保代码符合项目规范
- 添加必要的测试用例
- 更新相关文档

---

## 📞 联系我们

如有问题或建议，请通过以下方式联系：

- � **问题反馈**：提交 Issue 报告 bug 或功能建议
- � **功能建议**：在 Issues 中提出新功能需求
- 📖 **使用帮助**：查看本 README 文档或项目代码注释

---

<div align="center">

**⭐ 如果这个项目对您有帮助，请给我们一个 Star！**

Made with ❤️ for 医疗行业数字化

</div>