项目尚无统一工程规范,AI 助手与研发各自发挥导致返工风险。建立 总纲 + 细则两层结构:AGENTS.md 只写硬约束与索引(14 条红线、技术栈 基线、仓库结构、命令契约),细则拆为 10 份文档覆盖 Git、代码风格、 格式化、API 与路由、数据库、测试与 CI、Review、日志、密钥、资产命名。 影响面:仅文档。约束力从本轮起对新建代码生效;与现状冲突处以文档为准。 回滚方式:git revert 本提交。
7.1 KiB
7.1 KiB
02 · 代码风格
| 项 | 内容 |
|---|---|
| 文档版本 | V1.0(2026-11-02) |
| 依据 | 技术架构 §2.2 / §2.3 / §10.1 |
| 适用范围 | apps/ packages/ prisma/ infra/ 全部 TypeScript / JavaScript |
| 强制级别 | 强制(标注「建议」的除外) |
格式问题交给 Prettier(见 03),本文只约定格式化管不到的部分。
1 命名
| 对象 | 规则 | 示例 |
|---|---|---|
| 目录 / 文件 | kebab-case | ai-routes/、script-task.service.ts |
| React 组件文件 | PascalCase.tsx | ScriptCard.tsx |
| 变量 / 函数 | camelCase | nextCursor、resolveScope() |
| 类型 / 接口 / 类 | PascalCase | MediaTask、StorageProvider |
| 常量(模块级不可变) | UPPER_SNAKE | MAX_UPLOAD_MB |
| 布尔 | is/has/can/should 前缀 |
isArchived、hasPermission |
| 事件回调 | 属性 onXxx,处理器 handleXxx |
onSelect / handleSelect |
| 异步动作 | 动词开头,返回 Promise | createBatch() |
| 数据库表 / 列 | snake_case(Prisma @@map / @map) |
media_tasks、customer_id |
| 权限点常量 | UPPER_SNAKE,与库内 code 一致 |
SCRIPT_APPROVE |
CS-01禁止拼音命名(shangpin);业务术语用 PRD 术语表英文(briefCard、videoDirection、shot)。CS-02单字母变量只允许循环下标i/j与泛型T/K/V。CS-03缩写词按单词大小写:s3Key、httpClient、ulid,不写S3Key/HttpClient混排。
2 类型
CS-04strict: true,禁止any、隐式any、@ts-ignore;确需忽略用@ts-expect-error并写原因。CS-05禁止用as做类型断言绕过检查;只允许「收窄断言」(as const、as unknown as X需注释理由)。CS-06对外导出的函数 / 方法必须显式标注返回类型,内部函数可推断。CS-07对象契约用interface,联合 / 工具 / 映射类型用type;二者不混用于同一实体。CS-08业务枚举用as const对象 + 派生联合类型,禁止 TSenum;库内枚举由字典表提供(Prisma enum 仅用于永不扩展的封闭集合,需迁移评审说明)。CS-09泛型参数 ≥ 2 个或含义不清时必须命名(<TInput, TOutput>),禁止全用T。CS-10禁止在业务代码中出现object、Function、{}作为类型;用具体形状或Record<string, unknown>。
3 函数与结构
CS-11函数单一职责,建议 ≤ 50 行;超过则拆分。CS-12参数 > 3 个必须用对象参数;可选参数不用位置占位。CS-13嵌套 ≤ 3 层,用早返回替代else链。CS-14禁止魔法值:数字 / 字符串常量抽到constants或读取系统配置(PRD R-26)。CS-15单文件 ≤ 400 行;超出按职责拆分(Controller / Service / Repository 各自成文件)。CS-16禁止循环依赖;跨包引用只从包index.ts出口导入。
4 错误处理
CS-17统一抛AppError(code, message, details?),code取错误码表(见 04 §4);禁止throw new Error('...')直接面向用户。CS-18禁止catch后空吞;要么处理、要么包装后重抛,并保留cause。CS-19async函数必须有await或显式void;禁止 floating promise。CS-20外部调用(AI / 存储 / ffmpeg)必须设置超时 + 分类重试;内容违规类错误不重试。CS-21任务(BullMQ)处理器必须幂等:以taskItemId为幂等键,重复执行结果一致。CS-22前端错误:路由级 ErrorBoundary + 请求层统一 toast,禁止页面内零散alert。
5 注释与文档
CS-23注释解释为什么,不复述代码;业务规则必须引用 PRD 编号:// R-04 查询必须带 customer_id。CS-24导出 API 写 JSDoc(用途、参数、错误码、副作用);内部实现按需。CS-25TODO 格式:// TODO(@owner, 2026-12-01): 原因与后续;禁止无主 TODO。CS-26禁止提交注释掉的整段代码;历史查 git。CS-27不写「本次改动」「新增」这类时间性注释,注释描述当下状态。
6 导入顺序
按组排序,组间空行,组内按字母序(由 ESLint simple-import-sort 自动修复):
1. Node 内置(node:fs)
2. 第三方(@nestjs/*、zod)
3. workspace 包(@lingxi/shared、@lingxi/ui)
4. 应用内绝对路径(~/ 或 @/)
5. 相对路径(./、../)
6. 样式 / 资源(*.css、*.svg?raw)
CS-28禁止import * as X整包导入(图标包、UI 包尤甚,会破坏 tree-shaking)。CS-29图标只从packages/ui/icons.ts导入语义名(import { IconScript } from '@lingxi/ui/icons'),禁直接引remixicon具体路径。CS-30禁export *聚合无审阅的公共 API;index.ts显式列出导出。
7 React / 前端
CS-31只用函数组件 + Hooks;禁 class 组件、禁React.FC(返回类型写ReactNode/JSX.Element)。CS-32服务端数据只用 TanStack Query(useQuery/useMutation);禁止在useEffect里手写 fetch + 自建缓存。CS-33全局状态只放跨页共享且非服务端数据(Zustand);页面内状态用useState/useReducer,禁止为省 props 上全局。CS-34列表key用业务 ID,禁止index。CS-35组件文件导出一个主组件;子组件同文件时用内部函数,跨文件复用必须提为独立组件。CS-36样式只用 Semi design token(cssVar)/ CSS Modules;禁止散落十六进制色值、禁止行内 style 做主题。CS-37文案集中在packages/ui/locale(zh-CN),组件内不写死中文用户可见文案(日志与注释除外)。CS-38表单走packages/form-engine的 schema 渲染;禁止在业务页面手写动态字段映射(会绕过白名单校验)。
8 后端
CS-39分层职责:Controller 只解析入参 / 组装响应;Service 承载业务规则与状态机;Repository 是唯一访问 Prisma 的层。CS-40Repository 方法必须接收ScopeContext作为首个参数,禁止在 Repository 内部从全局取当前用户。CS-41模块间只通过 Service 接口或领域事件通信;禁止跨模块注入PrismaService直接查表。CS-42状态迁移集中在 Service 的状态机函数内,禁止 Controller 直接改status字段。CS-43事务边界在 Service;事务内禁止外部 IO(AI 调用、HTTP、对象存储)。CS-44队列任务只做「可重试的纯执行」,业务校验与成本预占在 API 层完成。
9 检查清单
- 命名符合 §1,无拼音、无缩写混排
- 无
any/@ts-ignore/ 滥用as - 函数 ≤ 50 行、文件 ≤ 400 行、嵌套 ≤ 3 层
- 错误统一
AppError,无空 catch - 队列任务幂等,外部调用有超时
- 图标 / UI 从统一出口导入
- 业务规则注释带 R-xx
- 无魔数、无硬编码阈值