docs: CLAUDE.md 更新为 src/ 新结构与 /api/v1;方案文档 P7 完成
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
> **重构状态**:项目已按《重构方案-v2.md》完成 P1-P7 全部阶段。
|
||||
> 后端源码位于 `src/`(core/common/modules/routes),API 统一 `/api/v1` 前缀,
|
||||
> 服务层为「入参数据/出参数据 + BizError」范式,全项目 flake8 零告警。
|
||||
|
||||
## Project Overview
|
||||
|
||||
DjangoAdmin Flask+EleVue is a separated frontend-backend admin framework. Backend: Flask + SQLAlchemy + MySQL + Redis. Frontend: Vue 3 + Element Plus + TypeScript + Vite + Pinia. The project is primarily documented and commented in Chinese.
|
||||
@@ -60,13 +64,14 @@ docker-compose up -d
|
||||
|
||||
Each business module follows a strict **View -> Service -> Model** separation:
|
||||
|
||||
- **`application/views/`** — Route controllers (Flask Blueprint). Each file defines routes using `@{module}_blue.route()`, decorated with `@check_permission("sys:module:action")`. Views are thin — they delegate to service functions and return `R.ok()`/`R.failed()` responses. Write operations check `FLASK_DEMO` first to block demo-mode writes.
|
||||
- **`application/services/`** — Business logic layer. Contains all query building, data transformation, and orchestration. Functions receive data from `request` object directly (not passed as parameters from views). Private helpers prefixed with `_` (e.g., `_apply_filters`, `_build_page_data`).
|
||||
- **`application/models/`** — SQLAlchemy models. All models inherit from `BaseModel` (provides id, create_user, create_time, update_user, update_time, is_delete fields) and `BaseDB` (provides save(), save_all(), delete() methods). Table names use `DB_PREFIX` (default `flask_`) + snake_case class name.
|
||||
- **`src/modules/<domain>/<name>/router.py`** — Route controllers (Flask Blueprint). Registered under `/api/v1` prefix (see `src/routes/v1.py`). Each file defines routes decorated with `@check_permission("sys:module:action")`. Routers parse request params, delegate to service functions, and wrap with `R.ok()`/`R.failed()`. Write operations check `FLASK_DEMO` first (via `@check_demo`).
|
||||
- **`src/modules/<domain>/<name>/service.py`** — Business logic layer. **服务函数「入参数据/出参数据」**(不直接读 `request`,不返回 R);业务失败 `raise BizError`;私有辅助函数以 `_` 开头。数据访问委托 repository。
|
||||
- **`src/modules/<domain>/<name>/models.py`** — SQLAlchemy models. All models inherit from `BaseModel` + `BaseDB` (in `src/common/`). Table names use `DB_PREFIX` (default `flask_`) + snake_case class name.
|
||||
- **`src/modules/<domain>/<name>/repository.py`** — 数据访问层,继承 `BaseRepository`(`src/common/base_repository.py`)。
|
||||
|
||||
### AOP Transaction Management
|
||||
|
||||
The framework uses an AOP-style transaction interceptor (`application/middleware/transaction.py`) registered via `register_transaction(app)`. **Business code never calls commit/rollback directly.**
|
||||
The framework uses an AOP-style transaction interceptor (`src/core/middleware.py`) registered via `register_transaction(app)`. **Business code never calls commit/rollback directly.**
|
||||
|
||||
- `before_request`: marks transaction active
|
||||
- `after_request`: auto-commits on POST/PUT/DELETE/PATCH only if HTTP 2xx AND `code==0` in response JSON; auto-rollbacks on business failures (`R.failed` returns HTTP 200 but `code=1`)
|
||||
@@ -76,14 +81,17 @@ The framework uses an AOP-style transaction interceptor (`application/middleware
|
||||
|
||||
### Key Backend Modules
|
||||
|
||||
- **`application/__init__.py`** — App factory (`create_app()`). Initialization order: Flask core -> Redis config -> DB config -> JSON encoder -> CORS -> ProxyFix -> AOP transaction -> register blueprints -> init extensions -> register middleware.
|
||||
- **`application/views/__init__.py`** — Auto-discovery blueprint registration. Add module name to `_blueprint_modules` list; the system dynamically imports the module and registers any `Blueprint` instance found in it. No manual `app.register_blueprint()` needed.
|
||||
- **`application/middleware/`** — `check_login` (before_request hook, JWT validation with token blacklist, whitelist matching via exact/prefix/wildcard patterns) and `check_permission` (RBAC decorator; superadmin user_id=1 bypasses all checks; internal calls via API key or IP whitelist also bypass).
|
||||
- **`application/forms/`** — WTForms validation forms. All inherit `BaseForm` (in `forms/forms.py`) which handles `ArrayField` JSON serialization. Forms are instantiated with `data=json_data` from parsed request body.
|
||||
- **`application/constants/`** — Shared constants: `PAGE_SIZE=10`, `DEFAULT_PASSWORD="123456"`, `MESSAGE_OK/FAIL`, `SERIALIZE_EXCLUDE_FIELDS` (is_delete, password, salt excluded from `to_dict()`).
|
||||
- **`src/app.py`** — App factory (`create_app()`). Initialization order: Flask core -> Redis config -> DB config -> JSON encoder -> CORS -> ProxyFix -> op_log/transaction -> register `/api/v1` routes -> init extensions -> middleware -> error handlers -> DI injection.
|
||||
- **`src/routes/v1.py`** — API v1 路由注册中心。所有业务蓝图挂载到 `/api/v1` 前缀。
|
||||
- **`src/core/middleware.py`** — `check_login` (before_request hook, JWT validation with token blacklist, whitelist matching), `check_demo`, `register_transaction` (AOP 事务), `register_operation_log` (操作日志,写入器 DI 注入), `register_error_handlers`.
|
||||
- **`src/core/permission.py`** — `check_permission` (RBAC decorator; superadmin user_id=1 bypasses; 权限数据通过 `current_app.extensions['permission_provider']` 注入,见 `src/app.py` `_inject_dependencies`).
|
||||
- **`src/core/exceptions.py`** — `BizError` 业务异常(业务层 `raise BizError` 统一转 `R.failed`)。
|
||||
- **`src/common/forms/`** — WTForms 验证表单。继承 `BaseForm`(含 `ArrayField` JSON 序列化)。
|
||||
- **`src/common/constants/`** — 共享常量:`PAGE_SIZE=10`, `DEFAULT_PASSWORD="123456"`, `MESSAGE_OK/FAIL`, `SERIALIZE_EXCLUDE_FIELDS`.
|
||||
- **`config/`** — Split into `base.py` (Flask host/port/debug/paths), `database.py` (SQLAlchemy URI, SSL options), `redis.py` (Redis URL), `auth.py` (JWT salt, permission toggle, login whitelist, internal API key). All read from `.env` via python-dotenv. `config/__init__.py` loads `.env` before any sub-module imports.
|
||||
- **`extensions/`** — Flask extension initialization: SQLAlchemy (`db`), Redis, APScheduler. All initialized via `register_extends(app)`.
|
||||
- **`utils/`** — `R` (standardized JSON response: `{code, data, msg, ok}` where code=0 is success, code=1 is failure), `jwt` (JWT token handling with blacklist), `model_utils` (models_to_list, model_to_dict, format_datetime), `request` (parse_request_body, parse_id_list), `security` (get_user_id, get_username from JWT), `case_converter` (camelCase <-> snake_case for dict keys, recursive), `regular` (WTForms error extraction), `password` (bcrypt-based encrypt/verify — imported as `from utils import password` then used as `bcrypt.verify_password()` etc.), `captcha`, `file`, `content` (rich text + file URL handling), `redis_client`, `ip`, `user_agent`, `formatter`, `json`.
|
||||
- **`src/extensions.py`** — Flask extension registration orchestration (`register_extends(app)`). 实例定义在 `src/core/`(database/redis_client/mail/scheduler)。
|
||||
- **`src/core/`** — `response`(R 统一响应)、`jwt`、`password`(bcrypt)、`security`(get_user_id/get_username)、`redis_client`。
|
||||
- **`src/common/utils/`** — `model_utils`(models_to_list/model_to_dict)、`request`(parse_request_body/parse_id_list)、`case_converter`(camelCase <-> snake_case)、`regular`(WTForms 错误提取)、`captcha`、`file`、`rich_text`、`ip`、`user_agent`、`formatter`、`json`、`ip2region`.
|
||||
|
||||
### Frontend Structure (ui/src/)
|
||||
|
||||
@@ -115,12 +123,13 @@ The framework uses an AOP-style transaction interceptor (`application/middleware
|
||||
|
||||
### Adding a New Module
|
||||
|
||||
1. Create model in `application/models/{module}.py` inheriting `BaseModel` + `BaseDB`
|
||||
2. Create service in `application/services/{module}.py` with business logic
|
||||
3. Create view in `application/views/{module}.py` with routes and permission decorators
|
||||
4. Add module name string to `_blueprint_modules` list in `application/views/__init__.py`
|
||||
5. Create form in `application/forms/{module}.py` inheriting `BaseForm` if input validation needed
|
||||
6. Add frontend API in `ui/src/api/{module}/`, views in `ui/src/views/{module}/`
|
||||
1. Create model in `src/modules/<domain>/<name>/models.py` inheriting `BaseModel` + `BaseDB`
|
||||
2. Create service in `src/modules/<domain>/<name>/service.py`(入参数据/出参数据 + raise BizError)
|
||||
3. Create repository in `src/modules/<domain>/<name>/repository.py` inheriting `BaseRepository`
|
||||
4. Create router in `src/modules/<domain>/<name>/router.py` with routes and permission decorators
|
||||
5. Create schema in `src/modules/<domain>/<name>/schema.py` inheriting `BaseForm` if input validation needed
|
||||
6. Add the blueprint to `BLUEPRINTS` list in `src/routes/v1.py`
|
||||
7. Add frontend API in `ui/src/api/{module}/`, views in `ui/src/views/{module}/`(API 前缀 /api/v1)
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
|
||||
+1
-1
@@ -357,7 +357,7 @@ from src.core.database import db # 统一 db 单例
|
||||
| **P4 服务层改造** | 26 个服务文件改「入参数据/出参数据」;router 取参包 R;引入 base_service/base_repository + BizError | **✅ 全部完成(21 模块)**:P4a 地基、P4b position 标杆(含单测)、P4c 六个批次(notice/param/link/level、article/category/file_template、dept/city、role/menu/user_role/role_menu、log/dictionary/configuration、job/auth/user)。每模块 flake8 零告警 + 应用启动 + 运行时验证。**合并模块已修复重名函数覆盖/双 import 块/路由导入 bug**。注:level 的 Excel import/export 仍返回 R(暂保留,后续统一改造) | 高(全部完成) |
|
||||
| **P5 DI 注入** | core/permission.py + op_log 接口化;app 工厂注入 menu 服务 | **✅ 已完成**:PermissionProvider 协议 + check_permission 去 menu 依赖;core/middleware.py 整合全部中间件;factory 注入 MenuPermissionProvider + record_operation_log;src/core 零 application 引用;权限/日志行为一致;flake8 零告警 | 中(已完成) |
|
||||
| **P6 API v1** | routes/v1.py + `/api/v1`;白名单/内部调用/前端前缀同步 | **✅ 已完成**:148 条路由全部挂 /api/v1;白名单已更新(/api/v1/login 等);build_full_url 内部调用自动加前缀;冒烟验证通过。**前端联动**:ui/ 需将 API 调用前缀改为 /api/v1(待 ui/ 迁移时一并处理) | 中(已完成) |
|
||||
| **P7 切尾** | 删除 application/extensions/utils;`src/wsgi.py`;gunicorn.conf 指向 src.wsgi;更新 CLAUDE.md | `gunicorn -c gunicorn.conf.py src.wsgi:app` 启动;全量回归 | 高 |
|
||||
| **P7 切尾** | 删除 application/extensions/utils;`src/wsgi.py`;gunicorn.conf 指向 src.wsgi;更新 CLAUDE.md | **✅ 已完成**:application/extensions/utils 已删除;src/app.py + src/wsgi.py + src/extensions.py 就位;gunicorn/Docker 指向 src.wsgi:app;CLAUDE.md 已更新。**全项目 flake8 0 条**;12 passed;app.py 与 src.wsgi 双入口启动 | 高(已完成) |
|
||||
| **P8 测试+文档** | tests/ 全量落地;CHANGELOG / CONTRIBUTING / API 文档 | `pytest` 通过;覆盖率报告 | 低 |
|
||||
| **P9 运维** | Docker 修复(§2.7)+ CI/CD(lint→type-check→pytest→build) | `docker-compose up -d` 健康检查通过 | 低 |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user