# CLAUDE.md 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. ## Development Commands ### Backend (Python/Flask) ```bash # Install dependencies pip install -r requirements.txt # Run dev server (default: 127.0.0.1:8021) python app.py # Database migrations (Flask-Migrate/Alembic) flask db init # Initialize migration repository (already done) flask db migrate # Generate migration from model changes flask db upgrade # Apply migrations flask db downgrade # Rollback migration ``` ### Frontend (Vue 3 / ui/) ```bash cd ui # Install dependencies (uses pnpm) pnpm install # Run dev server (default: localhost:8001, proxies /api to backend :8021) pnpm run dev # Build for production pnpm run build:prod # Lint pnpm run lint:eslint pnpm run lint:prettier pnpm run lint:stylelint # Type check pnpm run type:check ``` ### Docker ```bash cd docker docker-compose up -d ``` ## Architecture ### Backend Structure (Three-Layer Pattern) Each business module follows a strict **View -> Service -> Model** separation: - **`src/modules///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///service.py`** — Business logic layer. **服务函数「入参数据/出参数据」**(不直接读 `request`,不返回 R);业务失败 `raise BizError`;私有辅助函数以 `_` 开头。数据访问委托 repository。 - **`src/modules///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///repository.py`** — 数据访问层,继承 `BaseRepository`(`src/common/base_repository.py`)。 ### AOP Transaction Management 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`) - `teardown_request`: rollback on unhandled exceptions `BaseDB.save()` and `BaseDB.save_all()` call `db.session.flush()` only — the AOP interceptor handles commit. For special cases, use `@transactional` decorator, `@transactional_response` decorator, or `TransactionContext` context manager. ### Key Backend Modules - **`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. - **`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/) - **`api/`** — Axios API calls organized by module. Each function uses `http.request()` from `utils/http/axios/`. The HTTP client auto-prepends `VITE_GLOB_API_URL_PREFIX` (`/api`) and sends JWT as `Authorization: Bearer `. - **`views/`** — Page components matching backend modules (system, content, monitor, etc.). - **`router/`** — Vue Router with dynamic route generation from backend menu data. `generator-routers.ts` transforms backend menu tree into Vue Router routes; `asyncImportRoute` uses `import.meta.glob('../views/**/*.{vue,tsx}')` for lazy loading. - **`store/`** — Pinia stores: `user` (auth state), `asyncRoute` (dynamic routes), `projectSetting`, `tabsView`, `lockscreen`, `ossConfig`. - **`components/`** — Reusable UI components. - **`layout/`** — Main layout shell (sidebar, header, content area). - **`hooks/`** — Composable functions. - **`utils/`** — Frontend utilities (HTTP client with interceptors, date formatting, etc.). ### API Conventions - Backend routes follow RESTful patterns: `GET /{module}/page`, `GET /{module}/detail/`, `POST /{module}/add`, `PUT /{module}/update`, `DELETE /{module}/delete/`, `PUT /{module}/status`, `GET /{module}/list` - All responses use `R.ok(data=...)` / `R.failed(msg=...)` format with `{code, data, msg, ok}` structure - Frontend response handler checks `code === 0` for success; `code=401` triggers re-login - Permission strings follow pattern: `sys:module:action` (e.g., `sys:user:page`, `sys:role:add`) - Frontend proxies `/api` prefix to backend via Vite dev server proxy (configured in `ui/.env.development` as `VITE_PROXY=[["/api","http://127.0.0.1:8021/"]]`) ### Naming Conventions - Backend service functions: snake_case (e.g., `get_user_page`, `add_user`) - Backend model tables: `flask_` prefix + snake_case (e.g., `flask_user`, `flask_role`) - Service layer uses camelCase for parameters/return keys (matching frontend), snake_case for DB fields - Private service functions prefixed with `_` (e.g., `_apply_filters`, `_build_page_data`) - `BaseModel.__init__` auto-converts camelCase kwargs to snake_case and filters to valid model columns only - `to_dict()` returns snake_case keys; services use `convert_snake_to_camel` when frontend needs camelCase ### Adding a New Module 1. Create model in `src/modules///models.py` inheriting `BaseModel` + `BaseDB` 2. Create service in `src/modules///service.py`(入参数据/出参数据 + raise BizError) 3. Create repository in `src/modules///repository.py` inheriting `BaseRepository` 4. Create router in `src/modules///router.py` with routes and permission decorators 5. Create schema in `src/modules///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 All config is in `.env` at project root. Key settings: - `FLASK_HOST` / `FLASK_PORT` (default 127.0.0.1:8021) - `FLASK_SECRET_KEY` — must be >= 16 chars or app refuses to start - `DB_*` — MySQL connection (database: `djangoadmin.flask.elevue`, prefix: `flask_`) - `REDIS_*` — Redis connection - `JWT_SALT` — JWT signing key; `JWT_EXPIRE_MINUTES` (default 20) - `FLASK_DEMO` — Demo mode restricts write operations - `PERMISSION_ENABLED` — Toggle auth middleware - `INTERNAL_API_KEY` — Key for scheduler/internal calls (sent as `X-Internal-API-Key` or `X-Scheduler-Key` header) - `LOGIN_WHITELIST_*` — Paths exempt from login check (exact, prefix, wildcard patterns) - `PROXY_NUM` — Trusted proxy count for ProxyFix (0=none, 1=Nginx) Frontend env in `ui/.env.development`: `VITE_PORT=8001`, `VITE_PROXY`, `VITE_GLOB_API_URL_PREFIX=/api`