Files
2026-09-12 20:12:36 +08:00

12 KiB
Raw Permalink Blame History

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/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。标准 CRUD 模块继承 BaseService(src/common/base_service.py,含 page/detail/add/update/remove/update_status/list 模板方法 + before_/after_/_detail_dict/_enrich_page_records 覆写钩子),模块级代理函数暴露给 router 调用(router 零改动)。
  • 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 (src/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

  • 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/middleware/ — 中间件包(按职责拆分:auth.py 登录校验 + 白名单、demo.py 演示模式、transaction.py AOP 事务、operation_log.py 操作日志 + @operation_log 标题装饰器、errors.py 异常处理)。对外统一 from src.middleware import ...。
  • 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 <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
  • 统一约定:所有响应(含认证/权限失败 401/403)返回 HTTP 200 + 业务 code,不返回对应 HTTP 状态码——前端按 code 判断(401 重登、403 无权限)。若需按 HTTP 状态码防护(WAF/代理),应解析业务 code 而非 HTTP status
  • 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/<domain>/<name>/models.py inheriting BaseModel + BaseDB
  2. Create service in src/modules/<domain>/<name>/service.py(入参数据/出参数据 + raise BizError):
    • 标准 CRUD 模块:class XxxService(BaseService) 指定 repository/form/status_form/model_name,差异逻辑覆写钩子,末尾暴露模块级代理函数(如 get_xxx_page = XxxService.get_page)供 router 调用
    • 深度定制模块(如 user/auth):保持模块级函数 + raise BizError
  3. Create repository in src/modules/<domain>/<name>/repository.py inheriting BaseRepository(标准模块需实现 page(params) 与 list_enabled())
  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(唯一性校验用 XxxRepository.exists_by(filters, exclude_id),禁止直接 Model.query——查询只允许在 Repository 层)
  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_* — 数据库连接,多库支持(config/database.py 的 _build_database_url() 按 DB_DRIVER 构建 URL):mysql(默认)/postgresql/mssql/sqlite/oracle(oracledb 驱动,thin 模式无需 Oracle Client;DB_DATABASE 填 SERVICE_NAME)。切换只需改 DB_DRIVER + 账号,然后运行 python scripts/setup_db.py(create_all 建表 + 种子数据,幂等)。注意:flask db migrate/upgrade(方案 B)仍针对 MySQL,新建其它库请用 scripts/setup_db.py
  • 跨库数据迁移:python scripts/migrate_db.py --src-driver=mysql --src-host=127.0.0.1 --src-port=3306 --src-db=<源库名> --src-user=root --src-pass=<密码> --dst-driver=postgresql --dst-host=127.0.0.1 --dst-port=5432 --dst-db=<目标库名> --dst-user=postgres --dst-pass=<密码> --drop-target-first。CLI 显式参数、不依赖 .env;源/目标均支持 mysql/postgresql/mssql/sqlite/oracle(别名 postgres=postgresql、sqlserver=mssql、sqlite3=sqlite),自动建目标库 + create_all 建表 + 逐表泵数据 + 按方言重置自增(PG setval / MSSQL CHECKIDENT / Oracle 补 sequence+触发器)+ 逐表行数校验;先加 --dry-run 干跑核对计划
  • 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