227 lines
11 KiB
Markdown
227 lines
11 KiB
Markdown
# 项目规则
|
||
|
||
## 架构图优先规则
|
||
|
||
**任何任务开始前,必须先查阅架构影响地图,通过图定位代码和模块。**
|
||
|
||
1. **先图后码**:执行任何分析、修改、搜索任务时,首先运行 `npm run arch:scan` 更新 arch.db,再通过 `npm run arch:query` 查询目标模块、函数、依赖关系,结合阅读 `docs/architecture/004_architecture_impact_map.md` 定位架构设计意图,最后按图索骥读取源码
|
||
2. **图未覆盖则先补图**:如果发现项目中存在 arch.db 未记录的模块、函数、表、路由等,**必须先运行 `npm run arch:scan` 重新扫描**,然后检查 004 是否需要补充
|
||
3. **改码必同步图**:对源码的任何修改完成后,必须运行 `npm run arch:scan` 更新 arch.db;若架构设计意图有变化,同步更新 004
|
||
|
||
### 架构文档清单
|
||
|
||
| 文档 | 用途 |
|
||
|------|------|
|
||
| `docs/architecture/004_architecture_impact_map.md` | 架构设计意图唯一源(人类可读) |
|
||
| `docs/architecture/006_k12_feature_checklist.md` | 标准功能模块清单 |
|
||
| `docs/architecture/007_gap_audit_report.md` | 差距审计报告 |
|
||
| `docs/architecture/008_module_role_mapping.md` | 模块角色映射 |
|
||
| `docs/architecture/roadmap/` | 长远规划(tech-debt/decoupling/pending-features) |
|
||
| `docs/architecture/audit/` | 架构审查报告与归档(含已废弃的 005 JSON、004 V1) |
|
||
| `docs/troubleshooting/known-issues.md` | 已知问题速查(场景→技术映射 + 工作经验日志) |
|
||
|
||
> 注:005_architecture_data.json 已废弃归档至 `audit/archive/`,结构化数据查询统一通过 arch.db
|
||
|
||
### 需要同步图的场景
|
||
|
||
- 新增/删除/重命名导出函数、组件、Hook、类型
|
||
- 修改函数签名(参数、返回类型)
|
||
- 修改权限点(Permissions 常量)或角色-权限映射
|
||
- 新增/删除数据库表
|
||
- 新增/删除路由页面或 API 路由
|
||
- 修改模块间依赖关系
|
||
- 新增模块
|
||
|
||
### 同步方式
|
||
|
||
- 修改源码后运行 `npm run arch:scan` 更新 arch.db(强制)
|
||
- 若架构设计意图变化,同步更新 `docs/architecture/004_architecture_impact_map.md`
|
||
- 若发现新的"场景→技术"映射或工作经验,更新 `docs/troubleshooting/known-issues.md`
|
||
|
||
## 架构元数据库规则(arch.db)
|
||
|
||
**arch.db 是代码结构唯一源,AI 工作前必须运行 `npm run arch:scan` 更新。**
|
||
|
||
1. **arch.db 取代 005 JSON**:模块、函数、调用关系、依赖关系、技术标签查询 arch.db,不手动维护结构化数据文件
|
||
2. **查询命令**:
|
||
- `npm run arch:query -- sql "<SQL>"` 自定义 SQL 查询
|
||
- `npm run arch:query -- module-deps` 查模块依赖
|
||
- `npm run arch:query -- module-reverse-deps <module>` 查反向依赖
|
||
- `npm run arch:query -- symbol-refs <symbol>` 查符号引用链
|
||
- `npm run arch:query -- tech-usage <tag>` 查技术使用
|
||
- `npm run arch:query -- violations` 查架构违规
|
||
3. **arch.db 不替代 004**:arch.db 是"代码现状",004 是"设计意图",两者互补
|
||
|
||
## 编码规范
|
||
|
||
**详细规范见 `docs/standards/coding-standards.md`,以下为核心强制规则。**
|
||
|
||
### 代码质量规则
|
||
|
||
- 每次修改后运行 `npm run lint` 和 `npx tsc --noEmit` 确保零错误
|
||
- Server Action 必须使用 `requirePermission()` 进行权限校验
|
||
- 前端组件禁止使用 `role === "xxx"` 硬编码,统一使用 `usePermission().hasPermission()`
|
||
- 单文件行数遵循企业级规范:
|
||
- 配置文件、常量文件、类型定义文件:无限制
|
||
- React 组件:建议 ≤ 500 行(复杂表单/大型表格可放宽至 800 行)
|
||
- Server Actions / Data Access 模块:建议 ≤ 800 行
|
||
- 工具函数:建议 ≤ 40 行
|
||
- 自定义 Hook:建议 ≤ 80 行
|
||
- 超过建议行数时应考虑拆分(如 data-access 拆分为多个按职责划分的文件)
|
||
- 硬性上限:任何文件不超过 1000 行,超过必须拆分
|
||
|
||
### 架构分层规则
|
||
|
||
- 严格三层架构,依赖方向单向:`app → modules → shared`
|
||
- `app/` 只能调用 `modules/` 的 Server Actions 和 data-access,不直接访问 DB
|
||
- `modules/` 之间通过对方 data-access 通信,**不直接查询对方 DB 表**
|
||
- `shared/` 是被依赖方,**不得反向依赖** `@/auth`、`@/proxy` 或任何 `modules/*`
|
||
|
||
### 模块标准结构
|
||
|
||
```
|
||
src/modules/[module]/
|
||
├─ actions.ts # Server Actions(编排层)
|
||
├─ data-access.ts # 数据访问层(可拆分为 data-access-*.ts)
|
||
├─ schema.ts # Zod 验证(可选)
|
||
├─ types.ts # 类型定义
|
||
├─ components/ # 模块专属组件
|
||
└─ hooks/ # 模块专属 Hook(可选)
|
||
```
|
||
|
||
### TypeScript 规则
|
||
|
||
- **禁止 `any`**:未知类型用 `unknown` 并做类型守卫
|
||
- **禁止 `as` 断言**(除非从 `unknown` 转换或测试中,需注释原因)
|
||
- **函数返回值必须显式标注**,特别是 `Promise<T>`
|
||
- **仅用于类型的导入必须使用 `import type`**
|
||
- **可选链后禁止跟非空断言 `!`**
|
||
|
||
### 命名规范
|
||
|
||
- 目录:kebab-case(`user-profile/`)
|
||
- 组件文件:PascalCase(`UserProfile.tsx`)
|
||
- Hook 文件:camelCase(`useAuth.ts`)
|
||
- 变量/函数:camelCase,布尔值用 `is/has/can/should` 前缀
|
||
- 常量:UPPER_SNAKE_CASE(`MAX_RETRY_COUNT`)
|
||
- 类/接口:PascalCase,接口不加 `I` 前缀
|
||
|
||
### 组件规范
|
||
|
||
- 组件必须为纯函数,使用 `function` 声明
|
||
- 页面组件(`page.tsx`)使用默认导出;其余组件使用具名导出
|
||
- 默认服务端组件,需要交互时才添加 `"use client"`(必须位于文件第一行)
|
||
- **不使用 `React.FC`**,直接用函数声明 + 显式标注 props 类型
|
||
|
||
### Server Action 规范
|
||
|
||
- 每个 Action 必须调用 `requirePermission()` 进行权限校验
|
||
- 输入使用 Zod 验证,验证失败返回结构化错误
|
||
- 返回值统一采用 `ActionState<T>` 类型
|
||
- 使用 `revalidatePath` 精确刷新缓存
|
||
|
||
### Tailwind 规范
|
||
|
||
- 使用 `cn()` 工具函数管理条件类名
|
||
- **禁止**字符串拼接动态类名(`bg-${color}-500`)
|
||
- **禁止**使用任意值(`w-[137px]`),除非有充分理由并注释
|
||
- 设计令牌在 `src/app/styles/tokens/` 目录中分层定义,通过 `@theme inline` 暴露为 Tailwind 类
|
||
|
||
### 设计令牌规范(强制)
|
||
|
||
- **禁止硬编码颜色**: TSX/TS/CSS 中不得出现 `#hex` 颜色字面量,统一使用 `hsl(var(--*))` 或 Tailwind 类 `bg-*`
|
||
- **禁止硬编码字体**: 不得出现 `'Inter'`/`'Fraunces'`/`'JetBrains Mono'` 字面量,使用 `var(--font-family-sans/serif/mono)`
|
||
- **禁止硬编码字号**: 不得出现 `font-size: Npx`,使用 `var(--font-size-1~9)`
|
||
- **禁止 Tailwind 任意值**: 不得使用 `w-[Npx]`/`h-[Npx]`/`p-[Npx]` 等,映射到 `--space-*` 或 Tailwind 默认阶梯
|
||
- **豁免场景**(需 `// eslint-disable-next-line no-restricted-syntax -- <reason>` 注释):
|
||
- PWA manifest(`src/app/manifest.ts`)
|
||
- 邮件 HTML 内联样式(`src/modules/notifications/channels/email-channel.ts`)
|
||
- 图表 SVG 固定画布尺寸(recharts 选择器中的 `#ccc`/`#fff`)
|
||
- loading.tsx 占位骨架
|
||
- Dialog 固定宽度等无法令牌化的设计固定尺寸
|
||
- **令牌文件分布**: `src/app/styles/tokens/`(primitive/semantic-light/semantic-dark/lesson-preparation/tailwind-theme/index)
|
||
- **令牌分层**:
|
||
- Layer 1 Primitive(`primitive.css`):原始色板/字号/间距/阴影,业务代码不直接引用
|
||
- Layer 2 Semantic(`semantic-light.css` + `semantic-dark.css`):语义令牌,业务代码唯一引用入口
|
||
- 模块命名空间(`lesson-preparation.css`):`--lp-*` 令牌,明暗双份
|
||
- Tailwind 暴露(`tailwind-theme.css`):`@theme inline` 将 Semantic 令牌暴露为 `bg-*`/`text-*`/`font-*` 类
|
||
- **改令牌必同步图**: 修改令牌定义后,同步更新 `docs/architecture/004_architecture_impact_map.md` 与 arch.db(`npm run arch:scan`)
|
||
- **ESLint 强制约束**:
|
||
- `no-restricted-syntax`: 禁止 `#hex` 字面量
|
||
- `design-tokens/no-hardcoded-fonts`: 禁止 `'Inter'`/`'Fraunces'`/`'JetBrains Mono'` 字面量(单词边界匹配,不影响 `Interval`/`Interactive` 等标识符)
|
||
- 白名单:`primitive.css`(令牌定义)、`email-channel.ts`(邮件 HTML)、`manifest.ts`(PWA)
|
||
|
||
### 安全规范
|
||
|
||
- **禁止 `dangerlySetInnerHTML`**(如必须使用,先用 DOMPurify 清洗)
|
||
- JWT/session ID 存储在 httpOnly + Secure + SameSite=Strict 的 Cookie 中
|
||
- 服务端环境变量不加 `NEXT_PUBLIC_` 前缀
|
||
- 环境变量使用 `@t3-oss/env-nextjs` + Zod 校验(已实现于 `src/env.mjs`)
|
||
|
||
### 提交规范
|
||
|
||
- 使用 Conventional Commits 格式:`feat(scope): description`
|
||
- 类型:`feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `test`, `perf`, `ci`
|
||
- 提交前必须运行 `npm run lint` 和 `npx tsc --noEmit` 确保零错误
|
||
|
||
## 问题记录规则
|
||
|
||
**所有工作完成后,必须将遇到的问题记录到 `docs/troubleshooting/known-issues.md`(索引式速查手册)。**
|
||
|
||
### 必须记录的场景
|
||
|
||
| 场景 | 记录要求 |
|
||
|------|---------|
|
||
| 构建报错(dev/build/lint/tsc) | 记录到"全局经验"对应主题分区 |
|
||
| 运行时异常(白屏/API 报错/数据加载失败) | 记录到"模块经验"对应模块分区 |
|
||
| 框架/库版本兼容问题 | 记录到"全局经验: Next.js 配置与运行时" |
|
||
| 依赖配置问题(serverExternalPackages/webpackIgnore 等) | 记录到"全局经验: Next.js 配置与运行时" |
|
||
| 架构约束违规 | 记录到"全局经验"对应主题分区 |
|
||
|
||
### 记录格式
|
||
|
||
索引式表格,指明"场景→技术/规则"映射,不写多行代码示例:
|
||
|
||
```markdown
|
||
### X.X 主题分区
|
||
|
||
| 场景 | 技术/规则 |
|
||
|------|----------|
|
||
| 简述场景 | 正确做法(一句话) |
|
||
```
|
||
|
||
### 记录要求
|
||
|
||
- **索引式**:场景→技术/规则映射,不写代码示例和错误示范列
|
||
- **去重**:同类问题在原条目补充,不重复创建
|
||
- **引用架构规则**:架构分层、模块结构等规则引用 004 和 project_rules,不重复
|
||
- **工作经验日志**:在"工作经验日志"区按时间倒序追加(50 条上限),记录"做了什么/学到什么/下次注意"
|
||
|
||
## AI 工作强制流程
|
||
|
||
**所有 AI 工作必须遵循此流程,违反即违规。**
|
||
|
||
### 阶段 1: 上下文加载
|
||
|
||
1. `npm run arch:scan` 更新 arch.db
|
||
2. `npm run arch:query -- module-deps` 查目标模块依赖
|
||
3. `npm run arch:query -- symbol-refs <目标函数>` 查调用链
|
||
4. 阅读 `src/modules/[模块]/README.md` 读模块工作流程
|
||
5. 查 `docs/troubleshooting/known-issues.md` "模块经验" 分区读相关经验
|
||
|
||
### 阶段 2: 执行工作
|
||
|
||
1. 按规划执行
|
||
2. 修改代码后立即运行 `npm run arch:scan` 更新 arch.db
|
||
3. 运行 `npx tsc --noEmit` 和 `npm run lint` 确保零错误
|
||
|
||
### 阶段 3: 经验沉淀(强制,不可跳过)
|
||
|
||
1. 在 `docs/troubleshooting/known-issues.md` "工作经验日志" 区追加一条记录:
|
||
- 日期 + 时间
|
||
- 模块
|
||
- 做了什么 + 学到什么
|
||
2. 若发现新的"场景→技术"映射 → 提炼到对应模块分区
|
||
3. 若发现新的架构决策 → 更新 004
|
||
4. 若代码结构变化 → `npm run arch:scan` 确认 arch.db 已更新
|