# FastForge **Repository Path**: cnjyzxh/FastForge ## Basic Information - **Project Name**: FastForge - **Description**: 类似于Java 诺依框架的 Python 后端开发框架 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-25 - **Last Updated**: 2026-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Python FastAPI Vue3 License 离线部署

⚒️ FastForge · 速造

以 FastAPI 为砧,锻造成型 —— 类若依(RuoYi) Python 全栈快速开发框架
模型即 API · 内置若依级系统管理与监控 · Vue3 动态路由前端 · Docker 一键起

--- ## 📖 框架简介 **FastForge(速造)** 是一套从零构建的**类若依全栈脚手架**:后端沿用若依/Spring Boot 的设计语言(`BaseModel + BaseController + R 统一响应 + 权限/日志/缓存装饰器`),并**内置了一整套可直接演示、可整体复刻到业务项目**的后台管理页面与系统模块——克隆即得一套「诺依」式管理后台。 ``` 定义模型 → 创建控制器 → RESTful API 即刻就绪(新增业务页三步:模型+控制器+菜单行) ``` ### 技术栈 | 层 | 技术 | 版本 | |---|---|---| | 后端 | FastAPI + SQLAlchemy + pydantic-settings | ≥ 0.110 / 2.0 | | 鉴权 | PyJWT(HS256) + Redis 会话 + passlib[bcrypt] | — | | 数据库 | MySQL / MariaDB | ≥ 5.7(容器内置 mariadb:10.11) | | 缓存/调度 | Redis 7 / APScheduler | — | | 前端 | Vue3 + Element Plus + Pinia + Vue Router + Vite | 3.4 / 2.7 | | 部署 | Docker Compose(mysql/redis/backend/web 四容器) | — | --- ## 🚀 使用方式(速造是"开发基座",本身不常驻运行) > 定位:速造是**派生业务项目的脚手架**,不作为业务服务常驻、不占用业务端口。 > 本仓库始终保持"模板/主库"形态,供项目派生与对照;需要时临时起一份演示,用完即停。 **A. 派生开发(推荐,标准姿势)** — 把速造作为新项目的起点: ```bash mkdir -p /home/pher/新项目 && cd /home/pher/新项目 git clone http://192.168.101.106/root/FastForge.git FastForge cd FastForge git remote add upstream http://192.168.101.106/root/FastForge.git # 保留升级通道 # 然后按「后端使用说明」加业务模块(模型+控制器+菜单行+页面)即可开发 ``` **B. 仅参考 / 演示** — 临时起一份对照界面(用完即停,不常驻): ```bash WEB_PORT=8080 HTTPS_PORT=8443 docker compose up -d --build # 宿主 80/443 被占时用变量避开 # 访问 http://localhost:8080 (admin/admin123、demo/demo123) docker compose down # 完事即停;数据卷保留 ``` **C. 框架升级同步** — 已派生项目跟进主库更新:`git fetch upstream && git merge upstream/master`(冲突一般集中在 BaseController 等核心文件,逐处解决即可)。 ### 🎯 适用边界:什么时候该用速造,什么时候别硬套 速造适合**"管理后台型"业务系统**——多实体增删改查 + 多角色权限 + 需要现成管理界面的项目;它**不是万能模板**,选型前先对照: **✅ 适合派生速造的信号** - 业务以"实体 CRUD + 数据台账"为主,需要统一的 列表/详情/增改删/导出 接口与页面 - 需要多角色分级权限、操作留痕审计、数据范围隔离 - 希望直接获得系统管理页面(用户/角色/菜单/字典/日志等)而不重复造轮子 - 部署环境允许 MySQL/MariaDB + Redis - 需要一个正式构建的 Vue3 + Element Plus 管理前端 **⚠️ 不适合 / 别硬套的反模式** | 项目形态 | 原因 | |---|---| | 单文件/单容器轻工具(如 7890 导航代理:nginx 配置生成 + 单页 CDN Vue + SQLite) | 迁移需换 DB/加 Redis/前端工程化,重构成本高、收益趋零,破坏已验证的轻量部署 | | 核心是硬件/设备/集成/协议生成逻辑 | 业务与自动 CRUD 无关,速造通用设施用不上 | | 刻意零构建(无前端工程链) | 引入构建与依赖链反而增加运维 | | 已有自研认证/审计/权限并稳定运行 | 替换现有稳定实现属于负收益重构 | **同源项目的正确姿势(点状移植,不做整体重构)** - 已是速造模式的独立项目(如 计分考核重构:BaseController+R+PG,自研业务与多端)→ **按需 diff 移植增量**(如 BaseController 增强、操作/登录日志落库),不要整套跟进 sys 模块/动态菜单——它们已有业务定制的权限与路由体系 - 独立仓库无法 `git merge upstream`(如 jfkh-restruct 与主库非同源)→ 用补丁式搬运:改哪些文件、加什么表,先出移植清单再动 > 选型口诀:**后台管理系统 → 派生速造;轻量工具/集成型控制面 → 自研保持轻量;同源 FastForge 老项目 → 点状移植增量。** ### 演示实例入口(临时启动时) | 入口 | 地址 | 说明 | |---|---|---| | Web 管理后台 | http://localhost(默认 80,可 `WEB_PORT` 覆盖) | 登录后进入全部系统模块 | | API 文档 | 同域 `/api/v1/docs`(Nginx 反代,无需另开端口) | Swagger UI | | HTTPS | https://localhost(默认 443,可 `HTTPS_PORT` 覆盖) | 需先执行 `./scripts/gen-ssl.sh`,见下 | | MySQL(调试) | compose 默认不发布;调试时放开 13306 | fastforge/fastforge123 | **演示账号** | 账号 | 密码 | 角色 | 说明 | |---|---|---|---| | admin | admin123 | 超级管理员 | 全量菜单与数据,不可删停 | | demo | demo123 | 普通用户(common) | 演示权限差异:仅"首页+用户管理",数据范围=仅本人 | > 首次启动自动完成:建表(新表 `create_all` / 旧表补列 `ensure_columns`)→ 种子(分片幂等,老库可安全重跑)。 ### 🔒 HTTPS(自签证书,可选) 仓库默认纯 HTTP;需要 HTTPS 时: ```bash ./scripts/gen-ssl.sh # 生成 SAN 含本机 IP 的自签证书 → certs/ docker compose up -d --build frontend # entrypoint 检测到证书即自动启用 443 ``` - 无证书时 frontend 容器**自动退回纯 HTTP(80)**,不会因缺证书启动失败 - 证书存 `certs/`(不入库,`.gitignore` 排除);将来换正式证书放同路径同名文件即可 - 自签证书浏览器会提示"不受信任",属内网/开发用途的正常现象 --- ## 🧩 能力总览 ### 框架核心能力 | 能力 | 说明 | |---|---| | **模型即 API** | 模型 + 控制器两文件 → 自动获得 `列表/详情/新增/编辑/删除/导出` 六组接口 | | **R 统一响应** | `R.ok()` / `R.page()` / `R.fail()` / `R.warn()` / `R.unauthorized()` / `R.export()` | | **BaseModel** | 自动时间戳/创建者审计、软删除(del_flag)、增强序列化、敏感字段排除 | | **JWT + Redis 会话** | access/refresh 双 Token;写操作自动鉴权(GET 默认放行,见「安全与取舍」) | | **权限体系** | 角色-菜单授权(多对多);数据范围 scope 1-5;按钮级权限标识(perms) | | **操作日志/登录日志** | 写操作自动落库(注册制);登录登出记录(含 IP/UA 解析) | | **缓存/调度** | `@cacheable/@cache_evict/@cache_put` 装饰器;APScheduler 定时任务+任务日志 | | **装饰器生态** | `@log_operation` / `@check_permission` / `@skip_jwt` | | **自动发现** | models/ 与 api/ 目录自动扫描注册(`*_router` 变量约定) | | **非致命降级** | Redis/DB 不可用时框架仍可启动,开发/离线演示无障碍 | | **Excel** | 通用导出 + 模板(openpyxl) | ### 内置系统管理模块(开箱即用) | 分组 | 模块 | 数据表 | |---|---|---| | 系统管理 | 用户管理 | sys_user、sys_user_post | | 系统管理 | 角色管理(菜单授权/数据范围) | sys_role、sys_role_menu、sys_role_dept | | 系统管理 | 菜单 / 字典 / 部门 / 岗位 / 参数 / 公告 | sys_menu、sys_dict_*、sys_dept、sys_post、sys_config、sys_notice | | 日志管理 | 操作日志 / 登录日志 | sys_oper_log、sys_login_log | | 系统监控 | 在线用户 / 定时任务 / 服务监控 / 缓存监控 | sys_job、sys_job_log | --- ## 🏗️ 项目结构 ``` FastForge/ ├── docker-compose.yml # mysql + redis + backend + web 编排 ├── server/ # ── FastAPI 后端 ── │ ├── app.py # 入口:python app.py 或 uvicorn app:app │ ├── app/ │ │ ├── __init__.py # create_app 工厂(建表→迁移→日志注册→调度→种子) │ │ ├── config.py # 多环境配置(.env / pydantic-settings) │ │ ├── core/ # 框架核心:database/crud/response/security/deps/exceptions │ │ ├── models/ # SQLAlchemy 模型(sys_* 系统表 + 业务模型放这里) │ │ ├── api/ # 控制器(base.py 基类 + sys_*/monitor/common) │ │ ├── middleware/ # auth(JWT) / logging(操作日志) / crypto(可选加密) │ │ ├── utils/ # redis_client / excel / user_agent / 自动导入 │ │ └── scheduler.py # APScheduler 定时任务调度器 │ ├── migrations/ # Alembic(可选项,开发期以 create_all 为主) │ ├── seed_data.py # 系统管理演示数据(分片幂等) │ ├── requirements.txt # 依赖(含 apscheduler/psutil/python-multipart) │ └── README.md # 后端框架完整文档 ├── frontend/ # ── Vue3 前端 ── │ ├── src/ │ │ ├── api/ # axios 封装(auth/system/common) + R 响应解包 │ │ ├── router/index.js # 静态路由 + 动态菜单注册(后端菜单驱动) │ │ ├── store/user.js # Pinia:token/用户/菜单/权限 │ │ ├── layout/ # 布局:侧边栏/顶栏/多页签 TagsView/动态菜单 │ │ ├── directive/ # v-hasPermi / v-hasRole 按钮级权限指令 │ │ └── views/ # 页面组件(与 sys_menu.component 字段一一对应) │ └── nginx.conf # API 反代 + SPA 回退 + 静态缓存 ├── docs/ # 补齐方案 / 复刻指南 └── uploads/ # 通用上传文件持久化目录(容器挂载卷) ``` ### 请求链路 ``` 浏览器 ── 18090(nginx) ──/api/──► backend:5090 │ auth 中间件(写操作 JWT) ▼ BaseController(自动CRUD) ── BaseCRUD ──► MySQL │ 自动操作日志 │ 数据权限过滤 │ Redis 会话/缓存 ▼ R.ok/page/fail 统一响应 ──► 前端拦截器解包 ``` --- ## 🛠️ 后端使用说明 ### 1. 新增一个业务模块(两文件) **① 定义模型** `server/app/models/demo_product.py`: ```python """业务模块示例:产品""" from sqlalchemy import Column, String, Integer from app.models.base import BaseModel class DemoProduct(BaseModel): __tablename__ = "demo_product" product_id = Column(String(32), primary_key=True, comment="产品ID") # 留空自动生成 product_name = Column(String(64), comment="产品名称") price = Column(String(20), comment="价格") status = Column(String(1), default="0", comment="状态(0上架 1下架)") del_flag = Column(String(1), default="0", comment="删除标志(0存在 1删除)") # 软删除 remark = Column(String(255), comment="备注") ENABLE_DATA_SCOPE = True # 可选:列表/导出按登录角色数据范围过滤 ``` > `BaseModel` 已自动提供:`create_time/create_by/update_time/update_by/create_dept` 审计字段与增强序列化。 **② 创建控制器** `server/app/api/demo_product.py`: ```python """业务模块示例:产品控制器""" from app.api.base import BaseController from app.models.demo_product import DemoProduct class DemoProductController(BaseController): model_class = DemoProduct router_prefix = "/demo/product" # 最终路径 /api/v1/demo/product/... router_tags = ["产品管理"] list_filter_fields = ["product_name", "status"] # 列表 query 精确过滤 default_order_by = "create_time" default_order_desc = True demo_product_router = DemoProductController().router # 变量必须以 _router 结尾 ``` **重启后端即自动获得 6 组接口:** | 方法 | 路径 | 说明 | |---|---|---| | GET | `/api/v1/demo/product/list` | 分页列表(`page_num/page_size`,最大每页 100) | | GET | `/api/v1/demo/product/{id}` | 详情(字符串/数字主键均支持) | | POST | `/api/v1/demo/product/` | 新增(主键留空自动生成;自动审计) | | PUT | `/api/v1/demo/product/` | 编辑(动态识别主键) | | DELETE | `/api/v1/demo/product/{ids}` | 批量删除(逗号分隔,软删除) | | GET | `/api/v1/demo/product/export` | 导出 Excel | 所有写操作 **自动记录操作日志**;返回结构统一为: ```json { "code": 200, "msg": "查询成功", "rows": [...], "total": 10 } // 列表 { "code": 200, "msg": "创建成功", "data": { ... } } // 单项 ``` ### 2. 进阶扩展(按需选用) **业务钩子**(覆写方法即可,写操作前后注入逻辑): ```python class DemoProductController(BaseController): ... def before_create(self, data, db): data["price"] = data.get("price") or "0" # 默认值 return data def after_create(self, obj, db, rel=None): # rel 为 rel_fields 透传的关联数据 pass def before_update(self, obj_id, data, db): ... def before_delete(self, obj_ids, db): if "seed" in obj_ids: return "内置数据不允许删除" # 返回字符串=拒绝原因 return None ``` **声明式扩展**: ```python list_filter_fields = ["name", "status"] # query 参数精确过滤 rel_fields = ["post_ids"] # 提交中剥离关联数组 → 透传 after_create/update(obj, db, rel) default_order_by / default_order_desc # 列表默认排序 log_operation_enabled = False # 关闭自动操作日志(如日志表自身) ``` **装饰器**: ```python @cacheable("product:cache", key="#product_id", timeout=600) # 读缓存 @cache_evict("product:cache", key="#product_id") # 清缓存 @log_operation(title="产品管理", business_type=1) # 手动操作日志 @check_permission("demo:product:add") # 权限点校验 @skip_jwt("/auth/login") # 登录类白名单 ``` ### 3. 权限与数据范围 - **菜单即权限**:`sys_menu` 三类型 `M(目录)/C(菜单)/F(按钮)`;`F` 行 `perms`(如 `system:user:add`)下发到前端按钮 `v-hasPermi`。 - **角色授权**:角色管理页「菜单授权」将 `role_id ↔ menu_id` 写入 `sys_role_menu`;用户可见菜单 = 其角色授权集(无授权记录的老角色回退 `role_keys` 白名单,兼容旧库)。`admin` 角色恒全量。 - **数据范围**(`SysRole.data_scope`,模型 `ENABLE_DATA_SCOPE=True` 时列表/导出生效): | scope | 含义 | 过滤口径 | |---|---|---| | 1 | 全部数据 | 不过滤 | | 2 | 自定义 | `create_dept IN (角色已选部门)` | | 3 | 本部门 | `create_dept = 当前用户部门` | | 4 | 本部门及以下 | `create_dept IN (本部门+全部下级)`(登录时计算) | | 5 | 仅本人 | `create_by = 当前用户` | ### 4. 登录与会话契约(前端依赖,勿随意变更) | 接口 | 说明 | |---|---| | POST `/api/v1/auth/login` | `{username,password}` → `{access_token, refresh_token}`;失败/成功写登录日志 | | GET `/api/v1/auth/userinfo` | 请求头带 `Authorization: Bearer ` → `{user, roles, perms, menus}`(menus 为原始嵌套树,含 F 按钮) | | POST `/api/v1/auth/logout` | 清理 Redis 会话 + 记登出日志 | ### 5. 定时任务 `sys_job` 表驱动(APScheduler):任务 = cron 表达式 + HTTP 目标 URL,启动自动加载 `status=0` 任务;每次执行写入 `sys_job_log`。页面「定时任务」支持立即执行/暂停/恢复;也可在代码中直接调用 `app.scheduler.register_job(...)`。 ### 6. 通用上传/下载 `POST /api/v1/common/upload`(multipart,白名单后缀,按 `UPLOAD_MAX_SIZE_MB` 限流)→ 返回可下载 URL `/api/v1/common/download/.`;文件持久化于 `uploads/`(compose 已挂卷)。 --- ## 🖥️ 前端使用说明 ### 运行方式 - 生产:随 `docker compose` 起 `web` 容器(Nginx 托管构建产物,`/api` 反代后端) - 开发:`cd frontend && npm install && npm run dev`(vite 已代理 `/api → localhost:15090`) ### 新增一个业务页面(三步) 1. **后端加菜单行**(页面管理或直接种子 SQL):`sys_menu` 增加一条 `C` 型记录 - `path`(绝对路由地址,如 `/demo/product`);`component`(**相对 `views/` 的组件路径**,如 `demo/product/index`);`perms`(如 `demo:product:list`);`icon`(Element Plus 图标 PascalCase 名,如 `Goods`) 2. **放页面组件** `frontend/src/views/demo/product/index.vue`(参考现有 `views/system/post` 的搜索卡+表格+弹窗三段式) 3. **按钮权限**:写操作按钮加 `v-hasPermi="'demo:product:add'"`(无权限自动移除) 刷新登录后,侧边栏与路由自动出现(无需改前端路由表)。 ### 关键约定 > 前端视觉 / 布局 / 组件 / 按钮权限规范统一见 **`DESIGN.md`**(本表不再重复罗列视觉类条目),以下仅列 API / 契约速查: | 约定 | 说明 | |---|---| | API 封装 | `src/api/system.js`:分页参数页面传 `page/page_size`,封装层转后端 `page_num/page_size` | | R 解包 | `api/request.js` 拦截器:`code===200` 时列表返回 `{rows,total}`、单项返回 `data` | | Token | `localStorage.ff_token`;写请求自动携带 `Authorization: Bearer` | --- ## ⚙️ 配置说明(server/.env) | 变量 | 默认 | 说明 | |---|---|---| | `APP_ENV` | development | development / production / testing | | `URL_PREFIX` | /api/v1 | 全局接口前缀 | | `SERVER_PORT` | 5090 | 后端端口 | | `DB_USER/PASSWORD/SERVER/NAME` | — | 数据库(容器内为 mysql:3306) | | `REDIS_HOST/PORT` | localhost:6379 | Redis | | `JWT_SECRET_KEY` | change-me | **生产必须替换 ≥32 字节随机串** | | `ACCESS_TOKEN_EXPIRE_HOURS` | 2(仓库 .env 示例为 12) | 登录有效期(小时) | | `UPLOAD_DIR` / `UPLOAD_MAX_SIZE_MB` | uploads / 20 | 上传目录与单文件上限 | | `JOB_ENABLED` | true | 定时任务调度总开关 | | `CAPTCHA_ENABLED` | false | 登录图形验证码(预留开关) | | `APP_ENCRYPT` | false | 请求体 RSA+AES 加解密(需前后端同步升级) | --- ## 📋 日志与排障 应用日志统一落在 **`server/logs/`**(Docker 部署时 compose 已挂宿主 `./logs` 持久化),按天轮转: | 文件 | 级别/内容 | 用途 | |---|---|---| | `app_YYYYMMDD.log` | INFO+(启动/建表/seed/调度/业务/异常 traceback) | 全局运行轨迹 | | `access_YYYYMMDD.log` | 每请求一行:`req ip user METHOD url -> status 耗时ms` | 谁在何时调了哪个接口、是否慢 | | `error_YYYYMMDD.log` | 仅 ERROR/CRITICAL | 排障直接看这里 | **磁盘配额(默认总计 ≤ 1GB)**:超过上限自动按文件最旧优先删除,清到 80% 防抖动。触发时机:进程启动一次 + 每日轮转点。 | 配置 | 默认 | 说明 | |---|---|---| | `LOG_DIR` | `logs` | 日志目录 | | `LOG_MAX_BYTES` | `1073741824`(1G) | 日志总量上限 | | `LOG_RECYCLE_FACTOR` | `0.8` | 超限清理目标比例 | 排障三步: 1. `tail -f logs/error_*.log`(错误与 traceback) 2. `grep "<接口路径或用户id>" logs/access_*.log`(该请求状态与耗时) 3. 业务上下文看 `logs/app_*.log`(含请求 ID `req=` 可跨行串联) 实现:`server/app/utils/log_config.py`(QuotaTimedRotatingFileHandler)、`server/app/middleware/access_log.py`;单测 `server/tests/test_log_quota.py`(`cd server && python3 -m pytest`)。 --- ## 🐳 部署与运维 ### Docker 服务 | 服务 | 镜像 | 端口 | 说明 | |---|---|---|---| | web | nginx:alpine | 18090→80 | 前端产物 + `/api` 反代 | | backend | 自建 | 15090→5090 | uvicorn,自动建表/迁移/种子/调度 | | mysql | mariadb:10.11 | 13306→3306(仅调试) | 数据卷持久化 | | redis | redis:7-alpine | — | 会话与缓存 | ### 生产 Checklist - [ ] 修改 `JWT_SECRET_KEY` 为随机长串(`python -c "import secrets;print(secrets.token_hex(32))"`) - [ ] `APP_ENV=production`、`APP_DEBUG=false`、设置强数据库密码 - [ ] 配置 `CORS_ALLOWED_ORIGINS` 为实际域名 - [ ] 上传/日志卷持久化(compose 已挂 `uploads`,日志建议挂卷或接入收集) - [ ] 离线环境:`pip download -r requirements.txt` 预置依赖;前端已无外部 CDN ### 常见问题(FAQ) | 现象 | 处理 | |---|---| | 新加了模型列,重启后报"Unknown column" | 新表自动建;**老表加列**在 `app/core/database.py` 的 `_COLUMN_MIGRATIONS` 登记一条 `ALTER` 即可(启动幂等补列) | | 新增菜单后刷新不出现 | 确认菜单 `status/visible='0'`、`del_flag='0'`;该角色需「菜单授权」含该行;admin 恒全量 | | 前端子路由白屏/资源 404 | 勿把 vite build 改回 `--base=./`(动态子路由需绝对资源路径) | | 登录后菜单空白 | 检查角色 `sys_role_menu` 授权是否为空且无 `role_keys` 回退(非 admin 角色) | | demo 登录看不到新增菜单 | common 角色未授权 → 用 admin 在「角色管理→菜单授权」勾选 | | 定时任务不执行 | 看 `sys_job.status='0'`、`JOB_ENABLED=true`;任务日志页查失败原因(目标 URL 需后端可达) | | 想让某个写接口不记日志 | 控制器 `log_operation_enabled = False` | --- ## 🔒 安全与取舍(已知项) - **GET 默认免鉴权**(内网/离线演示定位),写操作(POST/PUT/DELETE)强制 JWT——若需全量鉴权在 `middleware/auth.py` 扩展 - 用户-**角色为单角色**(历史决策);角色-菜单/角色-部门为多对多 - 数据表无外键约束(全库约定,应用层保证一致性),保留软删除语义 - 演示用 docker 密钥仅限内网;对外部署务必走上方 Checklist --- ## 📚 相关文档 | 文档 | 内容 | |---|---| | `server/README.md` | 后端框架完整技术文档(架构图/安全说明/离线部署/与同类框架对比) | | `docs/若依级完整体系补齐方案.md` | 系统模块与前端补齐的设计方案 | | `docs/若依级完整脚手架-复刻指南.md` | **复刻到新业务项目**的完整步骤 + 演示走查清单 + 开发约定速查 | | `DESIGN.md` | **前端设计规范**(配色/组件/布局/避坑准则),AI 生成页面必读;配套 `preview.html` 可视化预览 | | `API.md` | **后端接口规范**(R 响应契约/六接口/控制器/鉴权/避坑),AI 生成接口必读 | | `DB.md` | **数据库与模型规范**(模型写法/软删除/建表迁移/避坑),AI 生成模型必读 | | `TEST.md` | **测试规范**(SQLite 测试基座/CRUD 链路回归/避坑),新增模型接口后必补测试 | | `QWEN.md` | 项目级 AI 指令(生成页面前必读 `DESIGN.md` 等速查约定) | | `FastForge(速造)框架说明.txt` | 早期框架设计说明 | **许可**:MIT License © 2026 FastForge