chore: 基线提交(重构前代码快照)
- git 初始化 + .gitignore 补全(根 .env / logs / instance / __pycache__ 等) - 修复 utils/.gitignore 误将整个 utils/ 源码层忽略的问题,补入全部工具源码(含 ip2region.xdb) - 含后端全部代码:application / extensions / utils / config / migrations - 含前端 ui/(后续整体迁走) - 不含根 .env(含密钥,本地保留) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,383 @@
|
||||
# Flask+EleVue 使用文档
|
||||
|
||||
## 目录
|
||||
|
||||
- [环境配置](#环境配置)
|
||||
- [基础配置](#基础配置)
|
||||
- [数据库配置](#数据库配置)
|
||||
- [Redis缓存配置](#redis缓存配置)
|
||||
- [邮件配置](#邮件配置)
|
||||
- [短信配置(阿里云)](#短信配置阿里云)
|
||||
- [JWT令牌配置](#jwt令牌配置)
|
||||
- [登录白名单配置](#登录白名单配置)
|
||||
- [权限验证配置](#权限验证配置)
|
||||
- [启动方式](#启动方式)
|
||||
- [开发环境](#开发环境)
|
||||
- [生产环境](#生产环境)
|
||||
- [Docker部署](#docker部署)
|
||||
- [Gunicorn参数调优](#gunicorn参数调优)
|
||||
- [应用流程](#应用流程)
|
||||
- [启动流程](#启动流程)
|
||||
- [请求处理流程](#请求处理流程)
|
||||
- [AOP事务管理](#aop事务管理)
|
||||
- [邮件服务](#邮件服务)
|
||||
- [短信服务](#短信服务)
|
||||
|
||||
---
|
||||
|
||||
## 环境配置
|
||||
|
||||
所有配置项在项目根目录 `.env` 文件中管理,应用启动时由 `python-dotenv` 自动加载。
|
||||
|
||||
### 基础配置
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `FLASK_NAME` | Flask+EleVue旗舰版 | 应用名称 |
|
||||
| `FLASK_VERSION` | v2.8.0 | 应用版本 |
|
||||
| `FLASK_SECRET_KEY` | - | 应用秘钥,用于Session加密和CSRF保护,必须≥16字符 |
|
||||
| `FLASK_HOST` | 127.0.0.1 | 运行地址。`0.0.0.0` 允许外部访问 |
|
||||
| `FLASK_PORT` | 8021 | 运行端口 |
|
||||
| `FLASK_ENV` | development | 环境标识:`development` / `production` |
|
||||
| `FLASK_DEBUG` | True | 调试模式。**生产环境必须设为 False** |
|
||||
| `FLASK_USE_RELOADER` | False | 自动重启(仅 DEBUG=True 时生效) |
|
||||
| `PROXY_NUM` | 0 | 可信代理层数。Nginx后设为1 |
|
||||
| `CORS_ALLOWED_ORIGINS` | - | CORS允许的源,逗号分隔。配置后支持携带凭证 |
|
||||
| `FLASK_DEMO` | False | 演示模式,True时限制写操作 |
|
||||
| `CAPTCHA_BYPASS_CODE` | 618618 | 万能验证码(仅DEMO模式生效,生产环境必须为空) |
|
||||
| `FLASK_UPLOAD_DIR` | - | 文件上传存储目录 |
|
||||
| `FLASK_FILE_URL` | - | 图片域名,用于生成完整URL |
|
||||
| `UPLOAD_ALLOWED_EXTS` | .jpg,.jpeg,.png,... | 允许上传的文件扩展名 |
|
||||
| `UPLOAD_MAX_SIZE_MB` | 10 | 上传文件大小上限(MB) |
|
||||
|
||||
### 数据库配置
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `DB_DRIVER` | mysql | 数据库驱动:`mysql` / `pgsql` / `sqlite` |
|
||||
| `DB_HOST` | 127.0.0.1 | 数据库地址 |
|
||||
| `DB_PORT` | 3306 | 数据库端口 |
|
||||
| `DB_DATABASE` | - | 数据库名称 |
|
||||
| `DB_USERNAME` | root | 数据库账号 |
|
||||
| `DB_PASSWORD` | - | 数据库密码 |
|
||||
| `DB_PREFIX` | flask_ | 表前缀 |
|
||||
| `DB_DEBUG` | True | 是否打印SQL日志 |
|
||||
| `DB_SSL` | False | 是否启用SSL加密连接 |
|
||||
|
||||
连接池高级参数(取消注释即可生效):
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `DB_POOL_SIZE` | 10 | 常驻连接数 |
|
||||
| `DB_MAX_OVERFLOW` | 10 | 最大额外连接数 |
|
||||
| `DB_POOL_RECYCLE` | 1800 | 连接回收时间(秒),应小于MySQL的wait_timeout |
|
||||
| `DB_POOL_TIMEOUT` | 30 | 获取连接超时(秒) |
|
||||
| `DB_POOL_PRE_PING` | True | 使用前检测连接存活 |
|
||||
|
||||
### Redis缓存配置
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `REDIS_HOST` | 127.0.0.1 | Redis地址 |
|
||||
| `REDIS_PORT` | 6379 | Redis端口 |
|
||||
| `REDIS_PASSWORD` | - | Redis密码 |
|
||||
| `REDIS_INDEX` | 0 | 库索引(0-15) |
|
||||
| `REDIS_AUTH` | True | 是否需要认证 |
|
||||
| `REDIS_DECODE_RESPONSES` | True | 是否自动解码 |
|
||||
|
||||
### 邮件配置
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `MAIL_MAILER` | smtp | 邮寄方式:`smtp` / `sendmail` |
|
||||
| `MAIL_SERVER` | smtp.163.com | SMTP服务器地址 |
|
||||
| `MAIL_PORT` | 465 | SMTP端口(465=SSL,587=TLS) |
|
||||
| `MAIL_USE_SSL` | True | 是否启用SSL |
|
||||
| `MAIL_USERNAME` | - | 授权邮箱用户名 |
|
||||
| `MAIL_PASSWORD` | - | 授权码(非登录密码) |
|
||||
| `MAIL_ENCRYPTION` | - | 加密方式:`ssl` / `tls` |
|
||||
| `MAIL_FROM_NAME` | - | 发件人名称 |
|
||||
| `MAIL_FROM_ADDRESS` | - | 发件人地址 |
|
||||
|
||||
### 短信配置(阿里云)
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `SMS_PROVIDER` | aliyun | 短信服务商(当前仅支持aliyun) |
|
||||
| `SMS_ALIYUN_ACCESS_KEY_ID` | - | 阿里云 AccessKey ID |
|
||||
| `SMS_ALIYUN_ACCESS_KEY_SECRET` | - | 阿里云 AccessKey Secret |
|
||||
| `SMS_ALIYUN_SIGN_NAME` | - | 短信签名(需在阿里云审核通过) |
|
||||
| `SMS_ALIYUN_ENDPOINT` | dysmsapi.aliyuncs.com | 接入点 |
|
||||
| `SMS_ALIYUN_CONNECT_TIMEOUT` | 10000 | 连接超时(毫秒) |
|
||||
| `SMS_ALIYUN_READ_TIMEOUT` | 10000 | 读取超时(毫秒) |
|
||||
|
||||
### JWT令牌配置
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `JWT_SALT` | - | JWT签名密钥,至少32字节,务必使用强随机密钥 |
|
||||
| `JWT_EXPIRE_MINUTES` | 20 | 令牌过期时间(分钟) |
|
||||
|
||||
生成密钥:
|
||||
|
||||
```bash
|
||||
python -c "import secrets; print(secrets.token_urlsafe(48))"
|
||||
```
|
||||
|
||||
### 登录白名单配置
|
||||
|
||||
白名单路径免登录验证,支持三种匹配模式:
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|--------|------|
|
||||
| `LOGIN_WHITELIST_EXACT` | 精确匹配,逗号分隔。如 `/login,/captcha` |
|
||||
| `LOGIN_WHITELIST_PREFIX` | 前缀匹配,逗号分隔。如 `/public,/static` |
|
||||
| `LOGIN_WHITELIST_WILDCARD` | 通配符匹配,`*` 匹配任意字符,`?` 匹配单字符 |
|
||||
| `LOGIN_WHITELIST_DEBUG` | 是否打印匹配调试日志 |
|
||||
| `LOGIN_WHITELIST_LOG_ACCESS` | 白名单请求是否记录访问日志 |
|
||||
|
||||
### 权限验证配置
|
||||
|
||||
| 配置项 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `PERMISSION_ENABLED` | True | 是否启用权限验证。False时所有请求放行 |
|
||||
| `INTERNAL_API_KEY` | - | 内部调用API密钥,请求头携带 `X-Internal-API-Key` |
|
||||
| `INTERNAL_ALLOWED_IPS` | 127.0.0.1 | 内部调用白名单IP,逗号分隔 |
|
||||
|
||||
---
|
||||
|
||||
## 启动方式
|
||||
|
||||
### 开发环境
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 启动后端(默认 127.0.0.1:8021)
|
||||
python app.py
|
||||
```
|
||||
|
||||
`python app.py` 执行 `__main__` 块,使用 `app.run()` 启动 Werkzeug 开发服务器。
|
||||
|
||||
开发环境支持 debug 模式和自动重载,由 `.env` 中 `FLASK_DEBUG` 和 `FLASK_USE_RELOADER` 控制。
|
||||
|
||||
前端开发服务器:
|
||||
|
||||
```bash
|
||||
cd ui
|
||||
pnpm install
|
||||
pnpm run dev # 默认 localhost:8001,自动代理 /api 到后端 :8021
|
||||
```
|
||||
|
||||
### 生产环境
|
||||
|
||||
```bash
|
||||
gunicorn -c gunicorn.conf.py app:app
|
||||
```
|
||||
|
||||
Gunicorn 通过 `app:app` 导入 Flask 应用对象,**不执行 `__main__` 块**。`gunicorn.conf.py` 中配置了 gevent worker,支持高并发。
|
||||
|
||||
关键区别:
|
||||
|
||||
| | 开发环境 | 生产环境 |
|
||||
|---|---------|---------|
|
||||
| 启动命令 | `python app.py` | `gunicorn -c gunicorn.conf.py app:app` |
|
||||
| WSGI服务器 | Werkzeug | Gunicorn + gevent |
|
||||
| Debug | 可开启 | 必须关闭 |
|
||||
| 自动重载 | 可开启 | 不支持 |
|
||||
| 并发模型 | 单进程 | 多worker + 协程 |
|
||||
|
||||
### Docker部署
|
||||
|
||||
```bash
|
||||
cd docker
|
||||
|
||||
# 构建并启动
|
||||
docker-compose up -d --build
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f flask_elevue
|
||||
|
||||
# 重新构建(代码更新后)
|
||||
docker-compose up -d --build
|
||||
|
||||
# 停止
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
Docker 容器内使用 Gunicorn 启动,Dockerfile 和 docker-compose.yml 已配置好 gevent worker。
|
||||
|
||||
### Gunicorn参数调优
|
||||
|
||||
所有参数通过环境变量覆盖,无需修改配置文件:
|
||||
|
||||
| 环境变量 | 默认值 | 说明 |
|
||||
|----------|--------|------|
|
||||
| `GUNICORN_BIND` | 0.0.0.0:8021 | 监听地址 |
|
||||
| `GUNICORN_WORKERS` | 2*CPU+1 | worker数量 |
|
||||
| `GUNICORN_WORKER_CONNECTIONS` | 1000 | 每worker协程数 |
|
||||
| `GUNICORN_MAX_REQUESTS` | 1000 | 处理请求数后重启(防内存泄漏) |
|
||||
| `GUNICORN_MAX_REQUESTS_JITTER` | 50 | 重启抖动,避免同时重启 |
|
||||
| `GUNICORN_TIMEOUT` | 120 | worker超时(秒) |
|
||||
| `GUNICORN_GRACEFUL_TIMEOUT` | 30 | 优雅关闭超时(秒) |
|
||||
| `GUNICORN_LOG_LEVEL` | info | 日志级别 |
|
||||
| `GUNICORN_ACCESS_LOG` | - | 访问日志路径(- 为stdout) |
|
||||
| `GUNICORN_ERROR_LOG` | - | 错误日志路径(- 为stderr) |
|
||||
|
||||
Docker 中通过 docker-compose.yml 的 `environment` 注入:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
GUNICORN_WORKERS: 4
|
||||
GUNICORN_WORKER_CONNECTIONS: 2000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 应用流程
|
||||
|
||||
### 启动流程
|
||||
|
||||
```
|
||||
app.py
|
||||
└─ create_app() # 应用工厂
|
||||
├─ Flask 核心对象创建
|
||||
├─ Redis 配置
|
||||
├─ 数据库配置加载
|
||||
├─ JSON 序列化器设置
|
||||
├─ CORS 跨域配置
|
||||
├─ ProxyFix 可信代理配置
|
||||
├─ register_operation_log() # 操作日志中间件(先于事务注册)
|
||||
├─ register_transaction() # AOP 事务拦截器
|
||||
├─ register_blueprint() # 蓝图自动发现与注册
|
||||
├─ register_extends() # 扩展初始化(DB/Redis/Mail/...)
|
||||
├─ register_middleware() # 登录验证中间件
|
||||
└─ register_error_handlers() # 全局异常处理
|
||||
```
|
||||
|
||||
### 请求处理流程
|
||||
|
||||
```
|
||||
HTTP 请求
|
||||
└─ before_request
|
||||
├─ 操作日志记录(记录请求信息)
|
||||
├─ AOP事务标记(标记事务开始)
|
||||
├─ 登录验证(check_login,白名单路径跳过)
|
||||
└─ 权限验证(check_permission 装饰器,超管/内部调用跳过)
|
||||
└─ View 路由处理
|
||||
└─ Service 业务逻辑
|
||||
└─ Model 数据操作(flush,不commit)
|
||||
└─ after_request
|
||||
├─ AOP事务提交/回滚(POST/PUT/DELETE/PATCH,2xx且code=0时提交)
|
||||
└─ 操作日志写入
|
||||
└─ 响应返回
|
||||
```
|
||||
|
||||
### AOP事务管理
|
||||
|
||||
框架通过 `application/middleware/transaction.py` 实现声明式事务管理,**业务代码无需手动 commit/rollback**。
|
||||
|
||||
- `before_request`:标记事务活跃
|
||||
- `after_request`:
|
||||
- 写操作(POST/PUT/DELETE/PATCH)且 HTTP 2xx 且响应 `code==0` → 自动提交
|
||||
- 业务失败(`R.failed` 返回 HTTP 200 但 `code=1`)→ 自动回滚
|
||||
- `teardown_request`:未处理异常时回滚
|
||||
|
||||
`BaseDB.save()` 和 `BaseDB.save_all()` 仅调用 `db.session.flush()`,由 AOP 拦截器统一提交。
|
||||
|
||||
特殊场景可使用:
|
||||
- `@transactional` 装饰器
|
||||
- `@transactional_response` 装饰器
|
||||
- `TransactionContext` 上下文管理器
|
||||
|
||||
---
|
||||
|
||||
## 邮件服务
|
||||
|
||||
邮件服务封装在 `application/services/mail_svc.py`,基于 Flask-Mail,供业务模块和定时任务直接调用。
|
||||
|
||||
**调用方式:**
|
||||
|
||||
```python
|
||||
from application.services import mail_svc
|
||||
|
||||
# 简单文本邮件
|
||||
mail_svc.send_mail(to='user@example.com', subject='标题', body='内容')
|
||||
|
||||
# HTML 邮件
|
||||
mail_svc.send_mail(to='user@example.com', subject='标题', html='<h1>Hello</h1>')
|
||||
|
||||
# 多收件人 + 抄送
|
||||
mail_svc.send_mail(
|
||||
to=['a@example.com', 'b@example.com'],
|
||||
subject='标题',
|
||||
body='内容',
|
||||
cc=['cc@example.com'],
|
||||
)
|
||||
```
|
||||
|
||||
**参数说明:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `to` | str / List[str] | 是 | 收件人 |
|
||||
| `subject` | str | 是 | 邮件主题 |
|
||||
| `body` | str | 否* | 纯文本正文 |
|
||||
| `html` | str | 否* | HTML正文(与body至少提供一个) |
|
||||
| `cc` | str / List[str] | 否 | 抄送 |
|
||||
| `bcc` | str / List[str] | 否 | 密送 |
|
||||
| `reply_to` | str | 否 | 回复地址 |
|
||||
|
||||
返回 `True` 表示发送成功,`False` 表示失败(异常已捕获并记录日志)。
|
||||
|
||||
**前置条件:** `.env` 中配置 `MAIL_SERVER`、`MAIL_USERNAME`、`MAIL_PASSWORD`。
|
||||
|
||||
---
|
||||
|
||||
## 短信服务
|
||||
|
||||
短信服务封装在 `application/services/sms_svc.py`,基于阿里云短信 SDK,供业务模块和定时任务直接调用。
|
||||
|
||||
**调用方式:**
|
||||
|
||||
```python
|
||||
from application.services import sms_svc
|
||||
|
||||
# 模板短信
|
||||
sms_svc.send_sms(
|
||||
phone='13800138000',
|
||||
template_code='SMS_123456',
|
||||
template_params={'code': '123456'}
|
||||
)
|
||||
|
||||
# 指定签名(覆盖默认签名)
|
||||
sms_svc.send_sms(
|
||||
phone='13800138000',
|
||||
template_code='SMS_123456',
|
||||
template_params={'code': '123456'},
|
||||
sign_name='我的应用'
|
||||
)
|
||||
|
||||
# 群发(多号码)
|
||||
sms_svc.send_sms(
|
||||
phone=['13800138000', '13900139000'],
|
||||
template_code='SMS_123456',
|
||||
template_params={'name': '张三'}
|
||||
)
|
||||
```
|
||||
|
||||
**参数说明:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `phone` | str / List[str] | 是 | 手机号,支持单个或多个 |
|
||||
| `template_code` | str | 是 | 短信模板CODE(阿里云控制台获取) |
|
||||
| `template_params` | dict | 否 | 模板变量,如 `{'code': '123456'}` 对应 `${code}` |
|
||||
| `sign_name` | str | 否 | 短信签名,默认使用配置中的 `SMS_ALIYUN_SIGN_NAME` |
|
||||
|
||||
返回 `True` 表示全部发送成功,`False` 表示至少一条失败。
|
||||
|
||||
**前置条件:**
|
||||
1. `.env` 中配置 `SMS_ALIYUN_ACCESS_KEY_ID`、`SMS_ALIYUN_ACCESS_KEY_SECRET`、`SMS_ALIYUN_SIGN_NAME`
|
||||
2. 安装依赖:`pip install alibabacloud-dysmsapi20170525 alibabacloud-tea-openapi`(已包含在 requirements.txt)
|
||||
Reference in New Issue
Block a user