9.3 KiB
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)
# 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/)
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
cd docker
docker-compose up -d
Architecture
Backend Structure (Three-Layer Pattern)
Each business module follows a strict View -> Service -> Model separation:
src/modules/<domain>/<name>/router.py— Route controllers (Flask Blueprint). Registered under/api/v1prefix (seesrc/routes/v1.py). Each file defines routes decorated with@check_permission("sys:module:action"). Routers parse request params, delegate to service functions, and wrap withR.ok()/R.failed(). Write operations checkFLASK_DEMOfirst (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 fromBaseModel+BaseDB(insrc/common/). Table names useDB_PREFIX(defaultflask_) + 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 (src/core/middleware.py) registered via register_transaction(app). Business code never calls commit/rollback directly.
before_request: marks transaction activeafter_request: auto-commits on POST/PUT/DELETE/PATCH only if HTTP 2xx ANDcode==0in response JSON; auto-rollbacks on business failures (R.failedreturns HTTP 200 butcode=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/v1routes -> 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(含ArrayFieldJSON 序列化)。src/common/constants/— 共享常量:PAGE_SIZE=10,DEFAULT_PASSWORD="123456",MESSAGE_OK/FAIL,SERIALIZE_EXCLUDE_FIELDS.config/— Split intobase.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.envvia python-dotenv.config/__init__.pyloads.envbefore 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 useshttp.request()fromutils/http/axios/. The HTTP client auto-prependsVITE_GLOB_API_URL_PREFIX(/api) and sends JWT asAuthorization: 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.tstransforms backend menu tree into Vue Router routes;asyncImportRouteusesimport.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 === 0for success;code=401triggers re-login - Permission strings follow pattern:
sys:module:action(e.g.,sys:user:page,sys:role:add) - Frontend proxies
/apiprefix to backend via Vite dev server proxy (configured inui/.env.developmentasVITE_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 onlyto_dict()returns snake_case keys; services useconvert_snake_to_camelwhen frontend needs camelCase
Adding a New Module
- Create model in
src/modules/<domain>/<name>/models.pyinheritingBaseModel+BaseDB - Create service in
src/modules/<domain>/<name>/service.py(入参数据/出参数据 + raise BizError) - Create repository in
src/modules/<domain>/<name>/repository.pyinheritingBaseRepository - Create router in
src/modules/<domain>/<name>/router.pywith routes and permission decorators - Create schema in
src/modules/<domain>/<name>/schema.pyinheritingBaseFormif input validation needed - Add the blueprint to
BLUEPRINTSlist insrc/routes/v1.py - Add frontend API in
ui/src/api/{module}/, views inui/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 startDB_*— MySQL connection (database:djangoadmin.flask.elevue, prefix:flask_)REDIS_*— Redis connectionJWT_SALT— JWT signing key;JWT_EXPIRE_MINUTES(default 20)FLASK_DEMO— Demo mode restricts write operationsPERMISSION_ENABLED— Toggle auth middlewareINTERNAL_API_KEY— Key for scheduler/internal calls (sent asX-Internal-API-KeyorX-Scheduler-Keyheader)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