13 KiB
13 KiB
AI 开发提示词 — 项目架构与模块开发规范
在向 AI 提出开发需求时,将以下提示词附加在需求描述之后,AI 即可按照项目架构规范生成代码,避免多人协作时的合并冲突。
提示词内容(复制到你的需求后面)
## 项目架构与模块开发规范
### 一、项目概述
Under18 是一个前后端分离的 RBAC 权限管理脚手架,提供用户、角色、权限、字典、标签、日志等通用功能模块。采用模块化自动注册架构,新增功能模块时**严禁修改任何共享/公共文件**,所有新代码必须放在独立模块文件中。
**技术栈:**
- 后端:FastAPI + SQLAlchemy(异步)+ PostgreSQL + Alembic
- 前端:Vue 3 + Vite 5 + Element Plus + Pinia + Vue Router 4
- 缓存:cachetools.TTLCache(进程内,替代 Redis)
- 认证:JWT(HS256),Access Token 120min + Refresh Token 7天
### 二、后端规范(FastAPI)
#### 2.1 分层架构
API 层 (app/api/{模块名}.py) — 路由定义、参数校验(Schema)、权限注入、响应封装 ↓ 调用 Service 层 (app/services/{模块名}_service.py) — 纯业务逻辑,静态方法,接收 AsyncSession ↓ 操作 Model 层 (app/models/{模块名}.py) — ORM 映射,继承 Base + TimestampMixin + SoftDeleteMixin
#### 2.2 新增模块只需创建以下独立文件,不需要修改任何已有文件:
1. **`backend/app/models/{模块名}.py`** — ORM 模型定义
- 从 `app.core.database` 导入 `Base`
- 从 `app.models.mixins` 导入 `TimestampMixin, SoftDeleteMixin`(日志类模型可不加 SoftDeleteMixin)
- 模型类继承:`class SysXxx(Base, TimestampMixin, SoftDeleteMixin)`
- 关联表(many-to-many)使用 `Table()` 定义在同一文件中
- 每个模型需实现 `to_dict()` 方法手动序列化
- 表名统一使用 `sys_` 前缀
2. **`backend/app/schemas/{模块名}.py`** — Pydantic 请求/响应模型
- 每个模块的 schema 独立一个文件
- 命名规范:`XxxCreateRequest`、`XxxUpdateRequest`、`XxxQueryRequest`
- 从 `app.schemas.response` 导入 `PageQuery` 作为分页查询基类
3. **`backend/app/services/{模块名}_service.py`** — 业务逻辑层
- 类名必须以 `Service` 结尾(如 `ArticleService`),全部使用 `@staticmethod`
- 从 `app.models.{模块名}` 导入模型(不要从 app.models 或 app.models.models 导入)
- 从 `app.schemas.{模块名}` 导入 schema(不要从 app.schemas.request 导入)
- 所有方法第一个参数为 `db: AsyncSession`
- 调用方式:`ArticleService.get_list(db, ...)`
4. **`backend/app/api/{模块名}.py`** — API 路由
- 必须导出名为 `router` 的 `APIRouter` 实例
- 示例:`router = APIRouter(prefix="/xxx", tags=["XXX管理"])`
- 所有路由自动加上 `/api` 前缀(由 `api_router = APIRouter(prefix="/api")` 控制)
- 从 `app.core.deps` 导入 `get_current_user`、`require_permission`
- 从 `app.schemas.response` 导入 `success`、`error`、`page_result`
- 路由文件会被 `app/api/__init__.py` 自动扫描注册,**不要修改 __init__.py**
#### 2.3 自动注册机制
| 层 | 扫描规则 | 约定 |
|----|---------|------|
| API 路由 | 扫描 `app/api/` 下所有 `.py`,查找 `router` 变量 | 文件必须导出 `router = APIRouter(...)` |
| Model | 扫描 `app/models/` 下所有 `.py`(跳过 `__init__.py` 和 `mixins.py`) | 确保模型被导入到 Base.metadata |
| Service | 扫描 `app/services/` 下所有 `_service.py`,收集以 `Service` 结尾的类 | 可直接 `from app.services import XxxService` |
**因此绝对不需要修改任何 `__init__.py` 文件。**
#### 2.4 已有模型导入路径
```python
from app.models.user import SysUser, sys_user_role # 用户 + 用户角色关联表
from app.models.role import SysRole, sys_role_permission # 角色 + 角色权限关联表
from app.models.permission import SysPermission # 权限
from app.models.dict import SysDictType, SysDictData # 字典类型 + 字典数据
from app.models.log import SysOperationLog, SysLoginLog # 操作日志 + 登录日志
from app.models.tag import SysTag, sys_tag_object # 标签 + 标签对象关联表
from app.models.mixins import TimestampMixin, SoftDeleteMixin # 通用混入
2.5 响应格式统一
from app.schemas.response import success, error, page_result
# 成功:return success(data=xxx)
# 失败:return error(message="xxx", code=400)
# 分页:return page_result(items=xxx, total=xxx, page=xxx, page_size=xxx)
响应体格式:
{ "code": 200, "message": "success", "data": {...} }
{ "code": 200, "message": "success", "data": { "items": [], "total": 0, "page": 1, "page_size": 10 } }
{ "code": 400, "message": "错误信息", "data": null }
2.6 权限校验
- 路由级:
dependencies=[Depends(require_permission("模块:资源:操作"))] - 按钮级:前端使用
v-permission="'模块:资源:操作'"指令 - 权限编码格式:
模块:资源:操作,如content:article:list - 超级管理员豁免:角色为
admin的用户自动拥有全部权限
2.7 认证与安全
- 密码加密:
SHA-256(password + user_salt + global_salt),双重加盐 - Token 体系:Access Token(120min)+ Refresh Token(7天),HS256 算法
- 登录安全:连续3次失败强制验证码;同IP 10次失败锁定30分钟;每IP每分钟限20次登录请求
- 获取客户端IP:使用
SecurityMiddleware._get_client_ip(request)
2.8 数据库与配置
- 数据库:PostgreSQL,异步驱动 asyncpg,连接由
app.core.database管理 - 迁移:Alembic,通过
alembic revision --autogenerate生成 - 配置:唯一来源
config.yaml,环境变量UNDER18_<键名>可覆盖 - 依赖注入:
get_db()提供 AsyncSession,get_current_user()提供当前用户
2.9 路由定义注意事项
- 批量操作路由(如
/batch、/clear/all)必须定义在通配符路由(如/{id})之前,否则会被通配符匹配拦截
三、前端规范(Vue3 + Vite)
3.1 新增模块只需创建以下独立文件,不需要修改任何已有文件:
-
frontend/src/router/modules/{模块名}.js— 路由配置- 必须
export default一个路由配置对象 - 会被
router/index.js通过import.meta.glob自动扫描加载 - 不要修改
router/index.js
- 必须
-
frontend/src/views/{模块路径}/{子路由}/index.vue— 页面组件- 视图文件路径必须与路由中的
component导入路径一致
- 视图文件路径必须与路由中的
-
frontend/src/api/{模块名}.js— API 调用函数- 从
@/utils/request导入 axios 实例 - 函数命名:
getXxxList、createXxx、updateXxx、deleteXxx
- 从
3.2 路由配置模板
// frontend/src/router/modules/{模块名}.js
export default {
path: '/{模块路径}',
component: () => import('@/layout/index.vue'),
redirect: '/{模块路径}/{默认子路由}',
meta: { title: '{菜单名称}', icon: '{ElementPlus图标名}' },
children: [
{
path: '{子路由}',
name: '{路由名}',
component: () => import('@/views/{模块路径}/{子路由}/index.vue'),
meta: { title: '{页面标题}', icon: '{图标}', permission: '{权限码}' },
},
],
}
3.3 侧边栏与权限
- 侧边栏菜单从
router/modules/下的路由配置自动生成,不需要修改 Sidebar.vue - 路由级权限:
meta.permission字段 +filterRoutes()过滤无权限路由 - 按钮级权限:
v-permission="'模块:资源:操作'"指令,无权限则隐藏元素
3.4 Store 与工具
- 用户状态:
store/user.js— token、userInfo、权限列表,手动同步 localStorage - 应用状态:
store/app.js— 侧边栏折叠、设备类型 - HTTP 请求:
utils/request.js— Axios 封装,自动添加 Bearer Token,统一错误处理(401弹窗重新登录、403无权限、429限流、500服务异常) - 日期格式化:
utils/index.js的formatDate()函数 - 防抖:
utils/index.js的debounce()函数
3.5 样式约定
- 主题色:
#2d9d5e(绿色系),通过 CSS 变量覆盖 Element Plus 默认主题 - 布局变量:
--sidebar-width: 220px,--header-height: 56px - 新页面样式使用
<style scoped>,全局样式放在styles/目录
四、禁止修改的文件清单
以下文件是公共注册文件或核心基础设施,多人同时修改会导致严重合并冲突,绝对禁止修改:
后端:
app/api/__init__.py— 路由自动注册app/models/__init__.py— 模型自动注册app/services/__init__.py— 服务自动注册app/schemas/response.py— 通用响应格式app/core/目录下所有文件 — 核心基础设施(数据库、安全、中间件、缓存、依赖注入、配置)app/main.py— 应用入口
前端:
src/router/index.js— 路由自动注册入口 + 守卫src/layout/目录下所有文件 — 布局组件(侧边栏、顶栏)src/utils/目录下所有文件 — 通用工具src/store/目录下所有文件 — 全局状态管理src/styles/目录下所有文件 — 全局样式src/main.js— 应用入口
五、命名规范速查
| 层 | 文件名 | 类/变量名 | 数据库表名 |
|---|---|---|---|
| Model | {模块名}.py |
Sys{Entity} |
sys_{entity} |
| Schema | {模块名}.py |
{Entity}CreateRequest / {Entity}UpdateRequest |
— |
| Service | {模块名}_service.py |
{Entity}Service |
— |
| API | {模块名}.py |
router = APIRouter(prefix="/模块/资源") |
— |
| 权限编码 | — | 模块:资源:操作 |
— |
| 前端路由 | modules/{模块名}.js |
export default { path: '/模块路径', ... } |
— |
| 前端API | api/{模块名}.js |
getXxxList / createXxx / updateXxx / deleteXxx |
— |
---
## 使用示例
假设你要开发一个"文章管理"模块,向 AI 提问时这样写:
> 请帮我开发一个"文章管理"功能模块,包含文章的增删改查,文章有标题、内容、分类、状态(草稿/发布)等字段。
>
> [粘贴上面的提示词内容]
AI 就会:
- 创建 `backend/app/models/article.py`(不碰 models/__init__.py)
- 创建 `backend/app/schemas/article.py`(独立文件)
- 创建 `backend/app/services/article_service.py`(不碰 services/__init__.py)
- 创建 `backend/app/api/article.py`(不碰 api/__init__.py)
- 创建 `frontend/src/router/modules/article.js`(不碰 router/index.js)
- 创建 `frontend/src/views/article/index.vue`
- 创建 `frontend/src/api/article.js`
每个文件都是独立的,不同人开发不同模块,零冲突!
---
## 六、部署与启动注意事项
### 6.1 前端启动问题:根目录误装 node_modules
**问题描述:** 在项目根目录(`under18/`)下执行 `npm install` 会生成根目录的 `package.json`、`package-lock.json` 和 `node_modules/`,导致 `npx vite` 使用根目录的 Vite(版本可能不一致且依赖不完整)而非 `frontend/node_modules/` 中完整版本的 Vite,表现为 Vite 启动后所有请求返回 404。
**典型场景:** 在根目录安装全局依赖(如 `npm install echarts`)时误装到了根目录而非 `frontend/` 目录。
**正确做法:**
- 前端依赖安装必须在 `frontend/` 目录下执行:`cd frontend && npm install xxx --save`
- 启动前端时使用 frontend 自带的 Vite:`cd frontend && npx vite` 或 `cd frontend && node_modules/.bin/vite`
- **禁止在项目根目录下执行 `npm install`**
**如已误装,清理方法:**
```bash
# 删除根目录下误装的文件
rm package.json package-lock.json
rm -rf node_modules/
6.2 后端启动:PYTHONPATH 设置
问题描述: 直接在 backend/ 目录执行 uvicorn app.main:app 可能报 ModuleNotFoundError: No module named 'app',因为 Python 找不到 app 包。
正确启动方式:
cd backend
set PYTHONPATH=c:\Users\hunter\Desktop\under18\backend # Windows
# export PYTHONPATH=/path/to/under18/backend # Linux/Mac
venv/Scripts/python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
6.3 完整启动流程
前置条件:
- 数据库使用远程 PostgreSQL(
config.yaml中配置的111.229.199.210:12345),无需本地启动 - Python 虚拟环境位于项目根目录
venv/ - 前端依赖已安装在
frontend/node_modules/
启动步骤:
# 1. 启动后端
cd c:\Users\hunter\Desktop\under18\backend
set PYTHONPATH=c:\Users\hunter\Desktop\under18\backend
c:\Users\hunter\Desktop\under18\venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
# 2. 启动前端(新终端)
cd c:\Users\hunter\Desktop\under18\frontend
npx vite --host 0.0.0.0 --port 5173
# 或使用完整路径:node_modules\.bin\vite --host 0.0.0.0 --port 5173
# 3. 访问
# 前端:http://localhost:5173
# 后端API文档:http://127.0.0.1:8000/api/docs
# 后端健康检查:http://127.0.0.1:8000/api/health
6.4 生产构建
cd frontend
npm run build # 输出到 frontend/dist/
构建产物为静态文件,需配合 Nginx 等Web服务器部署,并配置 /api 反向代理到后端。