e67475aad6d469cc73c3208e9ebac351e381260b
## 改动摘要 - 新增自定义异常类用于菜单验证错误的精确识别 - 修改 create_menu 服务函数,使用异常替代返回 None - 修改 API 端点捕获异常并返回详细错误信息 ## 详细改动 ### 1. 新增异常类 (api/app/exceptions/menu_exceptions.py) 创建了以下异常类以区分不同的验证失败场景: - `MenuValidationError`: 基础菜单验证异常类 - `EmptyMenuCodeError`: 菜单编码为空 - `EmptyMenuNameError`: 菜单名称为空 - `DuplicateMenuCodeError`: 菜单编码重复 - `RemovedMenuCodeError`: 使用已移除的菜单编码 - `SelfParentError`: 菜单将自己设为父菜单 - `ParentNotFoundError`: 父菜单不存在 ### 2. 修改服务层 (api/app/services/legacy_admin_rbac_service.py) - 在 create_menu 函数中,将所有返回 None 的地方替换为抛出对应的异常 - 为数据库异常添加更具体的错误上下文 - 修改返回类型从 `MenuPublic | None` 为 `MenuPublic` ### 3. 修改 API 端点 (api/app/api/v1/admin.py) - 在 create_menu_endpoint 中捕获 MenuValidationError 异常 - 返回详细的错误信息,包括具体的字段名(如有) - 替换原来的模糊错误信息"Invalid menu payload or duplicate menu code" ## 测试验证 - 已通过 Python 语法检查 - 所有修改的文件编译通过 - 异常类可以正常导入 ## 解决的问题 修复了 Issue FL-198 中描述的问题: - 之前:所有创建失败都返回同一个模糊错误"Invalid menu payload or duplicate menu code" - 现在:返回具体的错误原因,如"菜单编码 'xxx' 已存在 (字段: code)"、"父菜单 'xxx' 不存在 (字段: parent_id)"等 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
fquiz
基于 Next.js + Python(FastAPI)的全栈 Monorepo,内置用户管理与登录认证。
目录结构
.
├── web/ # Next.js 16 + TypeScript + App Router(登录态与用户管理页)
├── api/ # FastAPI 服务(JWT + Refresh Session + RBAC)
├── scripts/dev.sh # 前后端一键并行启动脚本
├── .env.example # 根环境变量模板
└── package.json # Monorepo 根脚本
技术栈
- 前端:Next.js 16、React 19、TypeScript
- 后端:FastAPI、SQLAlchemy、PostgreSQL/SQLite、Pydantic Settings
- 认证:JWT Access Token(15m)+ Refresh Session(HttpOnly Cookie, 轮换)
- 权限:RBAC(roles / permissions / user_roles / role_permissions)
环境要求
- Node.js >= 20
- Python >= 3.10
- Python 需要可用的
venv和pip(Debian/Ubuntu 可安装python3-venv)
快速开始
-
克隆仓库并进入目录。
-
安装前端依赖:
npm --prefix web install -
配置环境变量:
cp .env.example .env cp web/.env.local.example web/.env.local -
准备 Python 环境并安装依赖(示例):
python3 -m venv .venv source .venv/bin/activate python -m pip install -r api/requirements.txt -
一键启动前后端:
npm run dev
前端 UI 约定
- 后台与业务页面统一使用 Radix 体系组件(优先
@radix-ui/themes,必要时使用@radix-ui/react-*primitives)。 - 不再使用
web/src/components/ui/*自定义 UI 封装层(button/input/select/dialog/table/checkbox/textarea 等)。
认证接口
POST /api/v1/auth/registerPOST /api/v1/auth/loginPOST /api/v1/auth/refreshPOST /api/v1/auth/logoutGET /api/v1/auth/mePOST /api/v1/users(需要user.manage,支持管理员自定义用户ID并校验重复)GET /api/v1/users(需要user.manage)GET /api/v1/users/{id}(本人或user.manage)PATCH /api/v1/users/{id}(需要user.manage)POST /api/v1/users/{id}/password(需要user.manage,重置用户密码)DELETE /api/v1/users/{id}(需要user.manage,删除用户)POST /api/v1/users/{id}/roles(需要user.manage)
初始化管理员(可选):
- 在
.env设置INITIAL_ADMIN_EMAIL、INITIAL_ADMIN_USER_ID、INITIAL_ADMIN_USERNAME、INITIAL_ADMIN_PASSWORD - 默认值:
INITIAL_ADMIN_USER_ID=admin、INITIAL_ADMIN_USERNAME=管理员 - API 启动时会自动创建并赋予
admin角色
Docker Compose 部署
- 开发部署目录:
deploy/dev-deploy - 生产部署目录:
deploy/pro-deploy
-
准备环境变量:
cp deploy/dev-deploy/.env deploy/dev-deploy/.env.local cp deploy/dev-deploy/.env.dev deploy/dev-deploy/.env.dev.local -
构建并启动容器:
docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml up --build -d -
查看运行状态和日志:
docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml ps docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml logs -f -
访问服务:
- 前端:
http://localhost:3000 - 后端:
http://localhost:8000/health - PostgreSQL:默认连接外部库(
DB_HOST/DB_PORT/DB_NAME/DB_SCHEMA/DB_USERNAME/DB_PASSWORD) - 本地 PostgreSQL:
localhost:5434(可通过deploy/dev-deploy/.env的POSTGRES_PORT覆盖)
-
停止并清理:
docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml down
说明:
NEXT_PUBLIC_API_BASE_URL在 Next.js 中是构建期注入;如果修改该值,需要重新执行docker compose --env-file deploy/dev-deploy/.env -f deploy/dev-deploy/compose.yml up --build。- 若未显式设置
DATABASE_URL,API 会使用DB_*变量自动组装 PostgreSQL 连接,并将DB_SCHEMA作为search_path(等价 JDBC 的currentSchema语义)。 - 若出现跨域(CORS)错误,请在
.env配置:API_CORS_ORIGINS:精确来源列表(逗号分隔),如https://admin.example.com,http://localhost:3000API_CORS_ORIGIN_REGEX:来源正则(可选),如https://.*\\.example\\.com- 支持在
API_CORS_ORIGINS中使用通配符(如https://*.example.com)或*(仅建议开发调试)
- 默认镜像源已配置为
docker.m.daocloud.io,并默认使用pgvector镜像;如你网络环境可直连 Docker Hub,可在deploy/dev-deploy/.env中覆盖POSTGRES_IMAGE / PYTHON_BASE_IMAGE / NODE_BASE_IMAGE。
Description
Languages
Python
60%
TypeScript
37%
CSS
2%
JavaScript
0.4%
TeX
0.3%
Other
0.1%