## 考培练系统后端（FastAPI）

简要说明：本项目为考培练系统的后端服务，基于 FastAPI 开发，配套前端为 Vue3。支持本地开发与测试，默认仅在 localhost 环境运行。

### 如何运行（How to Run）

1. 进入项目目录：
```bash
cd kaopeilian-backend
```

2. 可选：创建并激活虚拟环境（推荐）
```bash
python3 -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
```

3. 安装依赖：
```bash
pip install -r requirements.txt
```

4. 运行主程序 `main.py`：
```bash
python app/main.py
```

可选运行方式（等价）：
```bash
uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
```

启动后访问接口文档：
```
http://localhost:8000/docs
```

> 提示：如需设置数据库连接，请使用本地开发 DSN：`mysql+aiomysql://root:root@localhost:3306/kaopeilian?charset=utf8mb4`，可在 `local_config.py` 或环境变量 `DATABASE_URL` 中覆盖。

### 如何测试（How to Test）

1. 安装测试依赖（如未安装）：
```bash
pip install pytest
```

2. 仅运行 `test_main.py`：
```bash
pytest tests/test_main.py
```

（或运行全部测试）
```bash
pytest
```

# 考培练系统后端

## 项目概述

考培练系统是一个革命性的员工能力提升平台，通过集成Coze和Dify双AI平台，实现智能化的培训、考核和陪练功能。

## 系统账户

系统预置了以下测试账户：

| 角色       | 用户名     | 密码           | 权限说明                     |
| ---------- | ---------- | -------------- | ---------------------------- |
| 超级管理员 | superadmin | Superadmin123! | 系统最高权限，可管理所有功能 |
| 系统管理员 | admin      | Admin123!      | 可管理除“系统管理”模块外的全部功能（管理员仪表盘、用户管理、岗位管理、系统日志） |
| 测试学员   | testuser   | TestPass123!   | 可学习课程、参加考试和训练   |

**注意**：

- 这些账户支持两种密码加密方式（bcrypt 和 SHA256）
- 使用 `create_system_accounts.py` 创建 bcrypt 加密的账户（推荐用于生产环境）
- 使用 `create_simple_users.py` 创建 SHA256 加密的账户（用于 simple_main.py）

## 技术栈

- **后端框架**: Python 3.8+ + FastAPI
- **数据库**: MySQL 8.0 + Redis
- **ORM**: SQLAlchemy 2.0
- **AI平台**: Coze（陪练和对话） + Dify（考试和评估）
- **认证**: JWT
- **文档转换**: LibreOffice（用于Office文档在线预览）
- **部署**: Docker

## 项目结构

```
kaopeilian-backend/
├── app/                      # 应用主目录
│   ├── api/                  # API路由
│   │   └── v1/              # API v1版本
│   │       ├── training.py   # 陪练模块API
│   │       └── ...          # 其他模块API
│   ├── config/              # 配置管理
│   │   ├── settings.py      # 系统配置
│   │   └── database.py      # 数据库配置
│   ├── core/                # 核心功能
│   │   ├── deps.py          # 依赖注入
│   │   ├── exceptions.py    # 异常定义
│   │   └── ...
│   ├── models/              # 数据库模型
│   │   ├── base.py          # 基础模型
│   │   ├── training.py      # 陪练模型
│   │   └── ...
│   ├── schemas/             # Pydantic模式
│   │   ├── base.py          # 基础模式
│   │   ├── training.py      # 陪练模式
│   │   └── ...
│   ├── services/            # 业务逻辑
│   │   ├── base_service.py  # 基础服务类
│   │   ├── training_service.py # 陪练服务
│   │   └── ai/              # AI平台集成
│   │       ├── coze/        # Coze集成
│   │       └── dify/        # Dify集成
│   └── main.py              # 应用入口
├── tests/                   # 测试目录
├── migrations/              # 数据库迁移
├── requirements.txt         # 生产依赖
├── requirements-dev.txt     # 开发依赖
├── Makefile                # 开发命令
└── README.md              # 项目说明
```

## 快速开始

### 1. 环境准备

- Python 3.8+
- MySQL 8.0
- Redis

### 2. 安装依赖

```bash
# 安装生产依赖
make install

# 或安装开发依赖（包含测试和代码检查工具）
make install-dev
```

### 3. 配置环境变量

复制环境变量示例文件并修改配置：

```bash
cp .env.example .env
```

主要配置项：

- 数据库连接：`DATABASE_URL`
- Redis连接：`REDIS_URL`
- JWT密钥：`SECRET_KEY`
- Coze配置：`COZE_API_TOKEN`, `COZE_TRAINING_BOT_ID`
- Dify配置：`DIFY_API_KEY`

### 4. 数据库初始化

```bash
# 运行数据库迁移
make migrate
# 数据库结构说明更新

- 统一主键：根据当前 ORM 定义，所有表主键均为 `INT AUTO_INCREMENT`。
- 用户相关引用：`teams.leader_id`、`exams.user_id`、`user_teams.user_id` 统一为 `INT`。
- 陪练模块：
  - `training_scenes.status` 使用枚举 `DRAFT/ACTIVE/INACTIVE`；
  - `training_sessions.status` 使用枚举 `CREATED/IN_PROGRESS/COMPLETED/CANCELLED/ERROR`；
  - `training_messages.role` 使用 `USER/ASSISTANT/SYSTEM`；`type` 使用 `TEXT/VOICE/SYSTEM`；
  - `training_sessions.user_id` 和 `training_reports.user_id` 为 `INT`（取消 `training_sessions.user_id` 外键）；
  - `training_reports.session_id` 对 `training_sessions.id` 唯一外键保持不变。

如需全量初始化，请使用 `scripts/init_database_unified.sql`。
```

### 5. 启动服务

```bash
# 开发模式（自动重载）
make run

# 或直接运行
python -m app.main
```

服务将在 http://localhost:8000 启动

## 数据库连接信息

- 公网数据库（当前使用）
  - Host: `120.79.247.16` 或 `aiedu.ireborn.com.cn`
  - Port: `3306`
  - User: `root`
  - Password: `Kaopeilian2025!@#`
  - Database: `kaopeilian`
  - DSN (Python SQLAlchemy): `mysql+aiomysql://root:Kaopeilian2025%21%40%23@120.79.247.16:3306/kaopeilian?charset=utf8mb4`

- 本地数据库（备用）
  - Host: `127.0.0.1`
  - Port: `3306`
  - User: `root`
  - Password: `root`
  - Database: `kaopeilian`
  - DSN (Python SQLAlchemy): `mysql+aiomysql://root:root@localhost:3306/kaopeilian?charset=utf8mb4`

- 配置写入位置
  - 代码内用于本地开发覆盖：`local_config.py` 中的 `os.environ["DATABASE_URL"]`
  - Docker 开发环境：`docker-compose.dev.yml` 中 `backend.environment.DATABASE_URL`
  - 运行时环境变量文件：`.env`（如存在，将被容器挂载）

> 提示：开发测试环境仅用于本机 `localhost` 访问，已开启代码自动重载。

## 文件管理

### 文件存储结构
- **基础路径**: `/kaopeilian-backend/uploads/`
- **课程资料**: `uploads/courses/{course_id}/{filename}`
- **文件命名规则**: `{时间戳}_{8位哈希}.{扩展名}`
  - 示例: `20250922213126_e21775bc.pdf`

### 文件上传
- **上传接口**: 
  - 通用上传: `POST /api/v1/upload/file`
  - 课程资料上传: `POST /api/v1/upload/course/{course_id}/materials`
- **支持格式**: pdf、doc、docx、ppt、pptx、xls、xlsx、txt、md、zip、mp4、mp3、png、jpg、jpeg
- **大小限制**: 50MB
- **静态访问路径**: `http://localhost:8000/static/uploads/{相对路径}`

### 文件删除策略
1. **删除资料时**：
   - 软删除数据库记录（标记 `is_deleted=true`）
   - 同步删除物理文件
   - 文件删除失败仅记录日志，不影响业务流程

2. **删除课程时**：
   - 软删除课程记录
   - 删除整个课程文件夹 (`uploads/courses/{course_id}/`)
   - 使用 `shutil.rmtree` 递归删除
   - 文件夹删除失败仅记录日志，不影响业务流程

### 相关配置
- **上传路径配置**: `app/core/config.py` 中的 `UPLOAD_PATH` 属性
- **静态文件服务**: `app/main.py` 中使用 `StaticFiles` 挂载
- **文件上传模块**: `app/api/v1/upload.py`

### 文档预览功能

#### 支持的文件格式
- **直接预览**: PDF、TXT、Markdown (md, mdx)、HTML、CSV、VTT、Properties
- **转换预览**: Word (doc, docx)、Excel (xls, xlsx) - 通过LibreOffice转换为PDF后预览

#### 系统依赖
- **LibreOffice**: 用于Office文档转换
  - libreoffice-writer: Word文档支持
  - libreoffice-calc: Excel文档支持
  - libreoffice-impress: PowerPoint文档支持（未启用）
  - libreoffice-core: 核心组件
- **中文字体**: 支持中文文档预览
  - fonts-wqy-zenhei: 文泉驿正黑
  - fonts-wqy-microhei: 文泉驿微米黑

#### 预览API
- 获取预览信息: `GET /api/v1/preview/material/{material_id}`
- 检查转换服务: `GET /api/v1/preview/check-converter`

#### 转换缓存机制
- 转换后的PDF存储在: `uploads/converted/{course_id}/{material_id}.pdf`
- 仅在源文件更新时重新转换
- 转换失败时自动降级为下载模式

## API文档

启动服务后，可以访问：

- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc

## 开发指南

### 代码规范

```bash
# 格式化代码
make format

# 运行代码检查
make lint

# 运行类型检查
make type-check
```

### 测试

```bash
# 运行测试
make test

# 运行测试并生成覆盖率报告
make test-cov
```

### 模块开发流程

1. 在 `app/models/` 创建数据模型
2. 在 `app/schemas/` 创建Pydantic模式
3. 在 `app/services/` 实现业务逻辑
4. 在 `app/api/v1/` 创建API路由
5. 编写测试用例
6. 更新API契约文档

## 已实现功能

### 陪练模块 (Training)

- **场景管理**

  - 获取场景列表（支持分类、状态筛选）
  - 创建/更新/删除场景（管理员权限）
  - 获取场景详情
- **会话管理**

  - 开始陪练会话
  - 结束陪练会话
  - 获取会话列表
  - 获取会话详情
- **消息管理**

  - 获取会话消息列表
  - 支持文本/语音消息
- **报告管理**

  - 生成陪练报告
  - 获取报告列表
  - 获取报告详情

## 待实现功能

- [ ] 用户认证模块 (Auth)
- [ ] 用户管理模块 (User)
- [ ] 课程管理模块 (Course)
- [ ] 考试模块 (Exam)
- [ ] 数据分析模块 (Analytics)
- [ ] 系统管理模块 (Admin)
- [ ] Coze网关模块
- [ ] WebSocket实时通信

## 部署
## 常见问题与排错

### 1. 登录失败相关

- 报错 Unknown column 'users.is_deleted'：请更新数据库，确保 `users` 表包含 `is_deleted` 与 `deleted_at` 字段（参见 `scripts/init_database_unified.sql` 或执行迁移）。
- 默认账户无法登录：重置默认账户密码哈希或运行 `create_system_accounts.py`。默认账户见上方“系统账户”。

### 2. 依赖冲突（httpx 与 cozepy）

- `cozepy==0.2.0` 依赖 `httpx<0.25.0`，请将 `requirements.txt` 中 `httpx` 固定为 `0.24.1`，并避免在 `requirements-dev.txt` 再次指定其他版本。

### 3. Docker 拉取镜像超时

- 可先本地直接运行后端（确保本机 MySQL/Redis 就绪），调通后再处理 Docker 网络问题。


### Docker部署

```bash
# 构建镜像
docker build -t kaopeilian-backend .

# 运行容器
docker run -d -p 8000:8000 --env-file .env kaopeilian-backend
```

### Docker Compose部署

```bash
# 启动所有服务
docker-compose up -d

# 查看日志
docker-compose logs -f
```

## 贡献指南

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

### 提交规范

- `feat`: 新功能
- `fix`: 修复bug
- `docs`: 文档更新
- `style`: 代码格式调整
- `refactor`: 代码重构
- `test`: 测试相关
- `chore`: 构建过程或辅助工具的变动

## 许可证

本项目采用 MIT 许可证
