# 项目规则

## 架构图优先规则

**任何任务开始前，必须先查阅架构影响地图，通过图定位代码和模块。**

1. **先图后码**：执行任何分析、修改、搜索任务时，首先阅读 `docs/architecture/004_architecture_impact_map.md` 或 `docs/architecture/005_architecture_data.json`，从图中定位目标模块、函数、依赖关系，再按图索骥读取源码
2. **图未覆盖则先补图**：如果发现项目中存在架构图未记录的模块、函数、表、路由等，**必须优先完善架构图信息**，然后再继续后续工作
3. **改码必同步图**：对源码的任何修改完成后，必须同步更新 004 和 005 两个架构文档

### 架构文档清单

| 文档 | 用途 |
|------|------|
| `docs/architecture/004_architecture_impact_map.md` | 人类可读的架构影响地图 |
| `docs/architecture/005_architecture_data.json` | AI 友好格式的结构化数据 |
| `docs/architecture/006_k12_feature_checklist.md` | 标准功能模块清单 |
| `docs/architecture/007_gap_audit_report.md` | 差距审计报告 |
| `docs/architecture/audit/01_decoupling_roadmap.md` | 解耦路线图 |

### 需要同步图的场景

- 新增/删除/重命名导出函数、组件、Hook、类型
- 修改函数签名（参数、返回类型）
- 修改权限点（Permissions 常量）或角色-权限映射
- 新增/删除数据库表
- 新增/删除路由页面或 API 路由
- 修改模块间依赖关系
- 新增模块

### 同步方式

- 修改 Markdown 文档中对应的模块章节
- 修改 JSON 文档中对应的节点（`modules.*.exports`、`permissions`、`dependencyMatrix`、`routes`、`dbTables` 等）
- 确保两个文档内容一致

## 编码规范

**详细规范见 `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/globals.css` 中使用 CSS 变量定义

### 安全规范

- **禁止 `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 报错/数据加载失败） | 记录错误现象 + 正确写法 |
| 框架/库版本兼容问题 | 记录错误现象 + 正确写法 |
| 依赖配置问题（serverExternalPackages/webpackIgnore 等） | 记录错误现象 + 正确写法 |
| 架构约束违规 | 记录错误现象 + 正确写法 |

### 记录格式

以**规则表**形式记录，指明正确做法，无需详细解释原因：

```markdown
## 问题分类标题

| 规则 | 正确写法 | 错误写法 |
|------|---------|---------|
| 简述规则 | 代码示例 | 代码示例 |
```

### 记录要求

- **速查手册风格**：只指明方向，不做新手指导
- **去重**：同类问题在原条目补充，不重复创建
- **可操作**：正确写法需具体到代码示例
