Files
DjangoAdmin_Flask_EleVue/CLAUDE.md
T
DjangoAdmin DevandClaude 15f2a5e097 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>
2026-08-07 12:12:06 +08:00

140 lines
9.0 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 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:
- **`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.
### 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.**
- `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
- **`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()`).
- **`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`.
### 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 <token>`.
- **`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/<id>`, `POST /{module}/add`, `PUT /{module}/update`, `DELETE /{module}/delete/<id>`, `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 `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}/`
## 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`