feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

View File

@@ -0,0 +1,380 @@
# 考培练系统后端开发规范
## 1. 代码规范
### 1.1 Python代码规范
- **格式化工具**:使用 Black 进行代码格式化,配置行长度为 88
- **导入排序**:使用 isort 进行导入排序
- **类型检查**:使用 mypy 进行静态类型检查
- **代码检查**:使用 flake8 进行代码质量检查
### 1.2 命名规范
```python
# 文件名:使用小写字母和下划线
user_service.py
# 类名:使用大驼峰命名法
class UserService:
pass
# 函数和变量:使用小写字母和下划线
def get_user_by_id(user_id: int) -> User:
pass
# 常量:使用大写字母和下划线
MAX_RETRY_COUNT = 3
# 私有成员:使用单下划线前缀
def _validate_input(data: dict) -> bool:
pass
```
### 1.3 文档字符串规范
```python
def create_user(
username: str,
email: str,
password: str,
role: UserRole = UserRole.TRAINEE
) -> User:
"""
创建新用户
Args:
username: 用户名长度3-20个字符
email: 用户邮箱,必须是有效的邮箱格式
password: 密码最少8个字符
role: 用户角色,默认为学员
Returns:
User: 创建成功的用户对象
Raises:
ValidationError: 输入参数验证失败
DuplicateError: 用户名或邮箱已存在
"""
pass
```
## 2. API开发规范
### 2.1 RESTful API设计原则
- 使用名词而非动词
- 使用复数形式
- 使用标准HTTP方法
- 合理使用HTTP状态码
```python
# 好的例子
GET /api/v1/users # 获取用户列表
GET /api/v1/users/{id} # 获取单个用户
POST /api/v1/users # 创建用户
PUT /api/v1/users/{id} # 更新用户
DELETE /api/v1/users/{id} # 删除用户
# 错误的例子
GET /api/v1/getUsers # 不要使用动词
POST /api/v1/user/create # 不要在URL中包含动作
```
### 2.2 统一响应格式
```python
from typing import Optional, Any
from pydantic import BaseModel
class ResponseModel(BaseModel):
"""统一API响应模型"""
code: int = 200
message: str = "success"
data: Optional[Any] = None
class ErrorResponse(BaseModel):
"""错误响应模型"""
code: int
message: str
details: Optional[str] = None
trace_id: Optional[str] = None
# 成功响应示例
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"username": "张三",
"email": "zhangsan@example.com"
}
}
# 错误响应示例
{
"code": 400,
"message": "参数验证失败",
"details": "用户名长度必须在3-20个字符之间",
"trace_id": "abc123def456"
}
```
### 2.3 API版本控制
- 使用URL路径进行版本控制`/api/v1/`, `/api/v2/`
- 保持向后兼容,避免破坏性更改
- 废弃的API需要提前通知并设置过渡期
## 3. 数据库规范
### 3.1 表命名规范
- 使用复数形式:`users`, `courses`, `exams`
- 关联表使用下划线连接:`user_courses`, `exam_questions`
- 避免使用MySQL保留字
### 3.2 字段命名规范
- 使用蛇形命名法:`user_name`, `created_at`
- 主键统一使用 `id`
- 外键使用 `表名_id` 格式:`user_id`, `course_id`
### 3.3 必需字段
每个表必须包含以下字段:
```sql
id BIGINT PRIMARY KEY AUTO_INCREMENT -- 主键
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 创建时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 更新时间
created_by BIGINT -- 创建人ID可选
updated_by BIGINT -- 更新人ID可选
is_deleted BOOLEAN DEFAULT FALSE -- 软删除标记(如需要)
```
### 3.4 索引规范
- 为外键字段创建索引
- 为经常查询的字段创建索引
- 避免创建过多索引影响写入性能
- 索引命名:`idx_表名_字段名`
## 4. 异常处理规范
### 4.1 自定义异常类
```python
# app/core/exceptions.py
class BaseAPIException(Exception):
"""API异常基类"""
def __init__(
self,
code: int,
message: str,
details: str = None
):
self.code = code
self.message = message
self.details = details
super().__init__(message)
class ValidationError(BaseAPIException):
"""参数验证异常"""
def __init__(self, message: str, details: str = None):
super().__init__(400, message, details)
class NotFoundError(BaseAPIException):
"""资源不存在异常"""
def __init__(self, resource: str):
super().__init__(404, f"{resource}不存在")
class PermissionError(BaseAPIException):
"""权限不足异常"""
def __init__(self, message: str = "权限不足"):
super().__init__(403, message)
```
### 4.2 全局异常处理
```python
# app/core/middleware.py
from fastapi import Request
from fastapi.responses import JSONResponse
async def global_exception_handler(request: Request, exc: Exception):
"""全局异常处理器"""
if isinstance(exc, BaseAPIException):
return JSONResponse(
status_code=exc.code,
content={
"code": exc.code,
"message": exc.message,
"details": exc.details,
"trace_id": request.state.trace_id
}
)
# 记录未预期的异常
logger.error(f"未处理的异常: {exc}", exc_info=True)
return JSONResponse(
status_code=500,
content={
"code": 500,
"message": "服务器内部错误",
"trace_id": request.state.trace_id
}
)
```
## 5. 日志规范
### 5.1 日志级别使用
- **DEBUG**: 调试信息,仅在开发环境使用
- **INFO**: 一般信息如API请求、重要业务操作
- **WARNING**: 警告信息如已废弃的API调用
- **ERROR**: 错误信息,需要关注但不影响系统运行
- **CRITICAL**: 严重错误,可能导致系统无法正常运行
### 5.2 结构化日志
```python
import structlog
logger = structlog.get_logger()
# 使用结构化日志
logger.info(
"用户登录成功",
user_id=user.id,
username=user.username,
ip_address=request.client.host,
user_agent=request.headers.get("user-agent")
)
# 记录错误信息
logger.error(
"数据库连接失败",
error=str(e),
database_url=settings.DATABASE_URL,
retry_count=retry_count,
exc_info=True # 包含完整堆栈信息
)
```
### 5.3 日志格式配置
```python
# app/core/logger.py
import structlog
def configure_logging():
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.processors.JSONRenderer()
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
```
## 6. 测试规范
### 6.1 测试文件组织
```
tests/
├── unit/ # 单元测试
│ ├── test_services/
│ └── test_utils/
├── integration/ # 集成测试
│ ├── test_api/
│ └── test_database/
└── e2e/ # 端到端测试
└── test_workflows/
```
### 6.2 测试命名规范
```python
# 测试文件名test_模块名.py
test_user_service.py
# 测试类名Test + 被测试类名
class TestUserService:
pass
# 测试方法名test_应该_做什么_当什么条件
def test_should_create_user_when_valid_data(self):
pass
def test_should_raise_error_when_duplicate_username(self):
pass
```
### 6.3 测试覆盖率要求
- 核心业务逻辑:≥ 90%
- API接口≥ 80%
- 工具函数:≥ 70%
- 总体覆盖率:≥ 80%
## 7. Git提交规范
### 7.1 提交信息格式
```
<type>(<scope>): <subject>
<body>
<footer>
```
### 7.2 Type类型
- **feat**: 新功能
- **fix**: 修复bug
- **docs**: 文档更新
- **style**: 代码格式调整
- **refactor**: 代码重构
- **test**: 测试相关
- **chore**: 构建过程或辅助工具的变动
### 7.3 示例
```
feat(user): 添加用户批量导入功能
- 支持Excel文件导入
- 支持CSV文件导入
- 添加导入进度显示
- 添加错误信息导出
Closes #123
```
## 8. 代码审查清单
提交代码前,请确保:
### 基础检查
- [ ] 代码通过 Black 格式化
- [ ] 代码通过 isort 导入排序
- [ ] 代码通过 mypy 类型检查
- [ ] 代码通过 flake8 质量检查
### 功能检查
- [ ] 所有函数都有完整的文档字符串
- [ ] 所有函数都有类型注解
- [ ] API响应格式符合统一标准
- [ ] 错误处理使用统一的异常类
### 测试检查
- [ ] 编写了相应的单元测试
- [ ] 测试覆盖率符合要求
- [ ] 所有测试通过
### 安全检查
- [ ] 没有硬编码的密钥或密码
- [ ] SQL查询使用参数化查询
- [ ] 敏感操作有权限检查
### 性能检查
- [ ] 数据库查询使用了适当的索引
- [ ] 避免了N+1查询问题
- [ ] 大量数据处理使用了分页或流式处理
### 日志检查
- [ ] 关键操作有日志记录
- [ ] 错误信息包含完整的上下文
- [ ] 日志级别使用恰当