# AI 代码规范模板 > 本文档是通用的 AI 协作与代码规范模板,适用于 TypeScript、Java、React、Vue 等技术栈。 > 使用时请根据项目实际情况进行调整。 --- ## 📋 目录 ### 第一部分:通用规范 - [1. AI 协作基本原则](#1-ai-协作基本原则) - [2. 通用编码规范](#2-通用编码规范) - [3. 文件与文档管理](#3-文件与文档管理) ### 第二部分:语言特定规范 - [4. TypeScript 规范](#4-typescript-规范) - [5. Java 规范](#5-java-规范) ### 第三部分:框架特定规范 - [6. React 规范](#6-react-规范) - [7. Vue 规范](#7-vue-规范) ### 第四部分:工程化规范 - [8. Git 提交规范](#8-git-提交规范) - [9. API 设计规范](#9-api-设计规范) - [10. 测试规范](#10-测试规范) ### 附录 - [附录 A:代码审查清单](#附录-a代码审查清单) - [附录 B:常见任务快速参考](#附录-b常见任务快速参考) - [附录 C:模板使用说明](#附录-c模板使用说明) --- # 第一部分:通用规范 ## 1. AI 协作基本原则 ### 1.1 语言要求(强制) #### 输出语言 - **所有输出必须使用中文**,包括: - 代码注释(**强制:所有代码注释必须使用中文,解释清晰详细**) - 文档说明 - 与用户交流 - 错误信息和日志输出 #### 思考语言 - **思考过程也必须使用中文**: - 分析问题时用中文思考 - 解释代码逻辑时用中文 - 讨论设计方案时用中文 #### 代码中的字符串 - 根据业务需求决定(支持国际化的项目使用翻译键) - 注释和文档必须使用中文 ### 1.2 思考与沟通方式 #### 思考过程要求 - 分析问题时,用中文描述问题、分析思路、得出结论 - 解释代码时,用中文说明逻辑、设计意图、实现方式 - 讨论方案时,用中文描述优缺点、选择理由 #### 工作流程 1. **理解需求**:用中文理解用户需求,明确任务目标 2. **分析问题**:用中文分析问题,梳理相关代码和架构 3. **设计方案**:用中文设计解决方案,考虑边界情况 4. **实现代码**:编写代码,添加中文注释 5. **测试验证**:用中文描述测试结果和发现的问题 6. **更新文档**:用中文更新相关文档 ### 1.3 问答与开发流程 #### 用户询问"如何实现"时的处理流程 **当用户询问如何实现某个功能时,必须遵循以下流程:** 1. **分析需求**:用中文理解用户需求,明确要实现的功能 2. **制定详细开发计划**:必须包含以下内容: - **需要修改的文件列表** - **需要新增的文件列表** - **需要删除的文件列表** - **每个文件的作用说明** - **对整体结构的影响** 3. **展示开发计划**:以清晰的格式展示给用户 4. **等待用户确认**:**在用户明确同意之前,绝对不能修改任何代码** 5. **用户同意后执行**:只有在用户明确表示同意后,才能开始修改代码 #### 开发计划格式模板 ```markdown ## 开发计划 ### 需要修改的文件 1. `src/xxx/xxx.ts` - 修改:添加新的 `xxxMethod()` 方法 - 作用:提供某某功能 ### 需要新增的文件 1. `src/xxx/index.ts` - 作用:实现某某功能 - 内容:包含 XxxClass 类 ### 需要删除的文件 1. `src/old/xxx.ts` - 原因:已被新组件替代 - **处理方式**:移动到 `.recycle/YYYY-MM-DD/` 文件夹 ### 对整体结构的影响 - **架构影响**:说明对现有架构的影响 - **功能影响**:说明对现有功能的影响 - **文档更新**:需要更新哪些文档 - **风险点**:可能的风险和注意事项 请确认是否按照此计划进行开发? ``` #### 用户直接要求修改时的处理 **当用户直接要求修改代码时**(如"帮我修改XXX"、"实现XXX功能"),可以: - 直接执行代码修改 - 但仍需遵循其他规范 - 删除文件时仍需移动到回收文件夹 --- ## 2. 通用编码规范 ### 2.1 代码可读性 #### 基本原则 - **优先保证代码可读性**,有时可以不使用高级函数,使用低级函数 - **必须添加详细的中文注释**,解释代码逻辑和设计意图 - 函数、类、接口必须有文档注释(使用中文) - 复杂逻辑必须添加行内注释说明 #### 代码组织 - 单个文件不宜超过 **500 行** - 单个函数不宜超过 **50 行** - 单行代码不宜超过 **120 字符** - 嵌套层级不宜超过 **4 层** ### 2.2 命名规范 #### 通用命名规则 | 类型 | 命名方式 | 示例 | |-----|---------|------| | 类名 | 大驼峰 (PascalCase) | `UserManager`, `OrderService` | | 接口名 | 大驼峰,可选 `I` 前缀 | `IUserService`, `UserRepository` | | 类型/枚举 | 大驼峰 | `UserStatus`, `OrderType` | | 函数/方法 | 小驼峰 (camelCase) | `getUserInfo`, `handleSubmit` | | 变量 | 小驼峰 | `userName`, `isActive`, `itemCount` | | 常量 | 全大写下划线 | `MAX_COUNT`, `API_BASE_URL` | | 私有属性 | 下划线前缀或 `#` | `_cache`, `#privateField` | | 文件名 | 小写短横线或小写 | `user-manager.ts`, `index.ts` | | CSS 类名 | 小写短横线 (kebab-case) | `user-card`, `btn-primary` | #### 命名语义化 ```typescript // ✅ 好的命名 - 语义清晰 const userList: User[] = []; const isLoading: boolean = false; const maxRetryCount: number = 3; function calculateTotalPrice(items: Item[]): number { } function validateUserInput(input: string): boolean { } // ❌ 不好的命名 - 语义不清 const list: any[] = []; const flag: boolean = false; const num: number = 3; function calc(arr: any[]): number { } function check(str: string): boolean { } ``` #### 布尔值命名 - 使用 `is`、`has`、`can`、`should`、`will` 等前缀 - 例如:`isActive`、`hasPermission`、`canEdit`、`shouldUpdate` #### 函数命名 - 动词开头,表明行为 - 查询:`get`、`find`、`query`、`fetch`、`load` - 创建:`create`、`add`、`insert`、`save` - 更新:`update`、`modify`、`set`、`change` - 删除:`delete`、`remove`、`clear`、`reset` - 判断:`is`、`has`、`can`、`should`、`validate`、`check` - 转换:`to`、`convert`、`parse`、`format` - 事件:`handle`、`on`、`trigger`、`emit` ### 2.3 注释规范 #### 文档注释(JSDoc / JavaDoc) **TypeScript / JavaScript:** ```typescript /** * 计算订单总价 * * @description 根据商品列表计算总价,包含折扣计算 * @param items - 商品列表 * @param discount - 折扣比例(0-1),默认为 1(无折扣) * @returns 计算后的总价 * @throws {Error} 当商品列表为空时抛出错误 * @example * const total = calculateTotal(items, 0.8); // 8折 */ function calculateTotal(items: CartItem[], discount: number = 1): number { if (items.length === 0) { throw new Error('商品列表不能为空'); } // 计算原价总和 const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0); // 应用折扣 return subtotal * discount; } ``` **Java:** ```java /** * 计算订单总价 * *

根据商品列表计算总价,包含折扣计算

* * @param items 商品列表 * @param discount 折扣比例(0-1),默认为 1(无折扣) * @return 计算后的总价 * @throws IllegalArgumentException 当商品列表为空时抛出 * @since 1.0.0 * @author AI Assistant */ public BigDecimal calculateTotal(List items, BigDecimal discount) { // 实现逻辑 } ``` #### 行内注释 ```typescript // 单行注释:解释接下来一行或几行代码的作用 /* * 多行注释: * 用于解释复杂的逻辑块 * 或临时禁用代码 */ // TODO: 待完成的功能 // FIXME: 需要修复的问题 // HACK: 临时解决方案,需要优化 // NOTE: 重要说明 // DEPRECATED: 已废弃,请使用新方法 ``` #### 注释原则 - **解释为什么,而不是是什么**:代码本身说明做什么,注释说明为什么 - **保持注释与代码同步**:代码修改后必须更新注释 - **不要注释显而易见的代码**:避免无意义的注释 - **复杂业务逻辑必须注释**:特别是涉及特定业务规则的代码 ### 2.4 错误处理 #### 基本原则 - 所有异步操作必须有错误处理 - 错误信息必须清晰、有意义,使用中文 - 区分可恢复错误和不可恢复错误 - 不要吞掉异常(空 catch 块) #### TypeScript 错误处理 ```typescript // ✅ 正确的错误处理 async function fetchUserData(userId: string): Promise { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { // 根据状态码抛出具体错误 if (response.status === 404) { throw new Error(`用户不存在:${userId}`); } throw new Error(`请求失败:${response.status}`); } return await response.json(); } catch (error) { // 记录错误日志 console.error('获取用户数据失败:', error); // 重新抛出或返回默认值 throw error; } } // ❌ 错误的错误处理 async function badFetch(userId: string) { try { const res = await fetch(`/api/users/${userId}`); return await res.json(); } catch (e) { // 空 catch 块,吞掉了错误 } } ``` #### Java 错误处理 ```java // ✅ 正确的错误处理 public User getUserById(Long id) { try { return userRepository.findById(id) .orElseThrow(() -> new BusinessException("用户不存在:" + id)); } catch (DataAccessException e) { log.error("查询用户失败,ID:{}", id, e); throw new ServiceException("数据库查询异常", e); } } // 自定义业务异常 public class BusinessException extends RuntimeException { private final String code; public BusinessException(String message) { super(message); this.code = "BUSINESS_ERROR"; } public BusinessException(String code, String message) { super(message); this.code = code; } } ``` ### 2.5 日志规范 #### 日志级别 | 级别 | 使用场景 | |-----|---------| | `ERROR` | 错误,影响功能正常运行 | | `WARN` | 警告,潜在问题但不影响运行 | | `INFO` | 重要业务信息,如用户操作、接口调用 | | `DEBUG` | 调试信息,开发环境使用 | | `TRACE` | 详细追踪信息,极少使用 | #### 日志内容要求 ```typescript // ✅ 好的日志 logger.info(`用户登录成功,用户ID:${userId},IP:${clientIp}`); logger.error(`订单创建失败,订单号:${orderId},原因:${error.message}`, error); logger.warn(`库存不足,商品ID:${productId},当前库存:${stock},请求数量:${quantity}`); // ❌ 不好的日志 logger.info('success'); // 信息不完整 logger.error(error); // 缺少上下文 console.log('here'); // 调试代码未清理 ``` #### 日志原则 - 包含足够的上下文信息(ID、参数等) - 敏感信息脱敏(密码、手机号等) - 生产环境不使用 `console.log` - 异常日志要包含堆栈信息 ### 2.6 安全规范 #### 输入验证 ```typescript // ✅ 验证所有外部输入 function processUserInput(input: unknown): string { // 类型检查 if (typeof input !== 'string') { throw new Error('输入必须是字符串'); } // 长度检查 if (input.length > 1000) { throw new Error('输入长度超出限制'); } // 内容清理 return sanitize(input); } ``` #### XSS 防护 ```typescript // ❌ 危险:直接插入 HTML element.innerHTML = userInput; // ✅ 安全:使用 textContent 或转义 element.textContent = userInput; // 或 element.innerHTML = escapeHtml(userInput); ``` #### 敏感数据处理 ```typescript // ❌ 不要在日志中输出敏感信息 console.log(`用户密码:${password}`); // ✅ 脱敏处理 console.log(`手机号:${phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')}`); ``` --- ## 3. 文件与文档管理 ### 3.1 文件删除规范(强制) **严禁直接删除文件,必须遵循以下流程:** #### 步骤 1:创建回收文件夹 在项目根目录创建 `.recycle/` 文件夹(如果不存在) #### 步骤 2:按日期组织 - 在 `.recycle/` 下按日期创建子文件夹 - 格式:`YYYY-MM-DD`(如 `2024-01-15`) - 同一天删除的文件存放在同一个日期文件夹中 #### 步骤 3:移动文件而非删除 ```bash # ❌ 错误方式 rm src/old-file.ts # ✅ 正确方式 DATE=$(date +%Y-%m-%d) mkdir -p .recycle/$DATE/src mv src/old-file.ts .recycle/$DATE/src/old-file.ts ``` #### 步骤 4:保持目录结构 在日期文件夹中保持原文件的目录结构 例如:`src/components/old.ts` → `.recycle/2024-01-15/src/components/old.ts` #### 回收文件夹结构示例 ``` .recycle/ ├── 2024-01-15/ │ ├── README.md # 可选:记录删除原因 │ └── src/ │ └── components/ │ └── old-component.ts └── 2024-02-20/ └── src/ └── services/ └── old-service.ts ``` ### 3.2 文档更新规则 #### 必须更新的情况 | 操作 | 需要更新的文档 | |-----|--------------| | 新增文件 | 在相关文档中添加文件描述 | | 删除文件 | 从文档中移除对应条目 | | 修改文件功能 | 更新对应文件的描述 | | 新增组件/模块 | 添加说明,创建详细文档 | | 修改 API | 同步更新 API 文档 | | 修改架构 | 更新架构设计部分 | | 修改配置 | 更新配置说明 | #### 更新方式 1. 修改代码后,**立即**更新相关文档 2. 确保文档与代码保持一致 3. 如果发现文档过时,优先更新文档 --- # 第二部分:语言特定规范 ## 4. TypeScript 规范 ### 4.1 类型定义规范 #### 优先使用 interface 定义对象类型 ```typescript // ✅ 推荐:使用 interface interface UserInfo { id: string; name: string; email: string; age?: number; // 可选属性 readonly createdAt: Date; // 只读属性 } // 接口继承 interface AdminUser extends UserInfo { role: 'admin'; permissions: string[]; } ``` #### 使用 type 定义联合类型、交叉类型 ```typescript // 联合类型 type Status = 'pending' | 'processing' | 'completed' | 'failed'; type ID = string | number; // 交叉类型 type UserWithMeta = UserInfo & { metadata: Record; }; // 工具类型 type PartialUser = Partial; type RequiredUser = Required; type ReadonlyUser = Readonly; type UserKeys = keyof UserInfo; ``` ### 4.2 避免 any,使用正确的类型 ```typescript // ❌ 避免使用 any function processData(data: any): any { return data.value; } // ✅ 使用 unknown + 类型守卫 function processData(data: unknown): string { if (typeof data === 'object' && data !== null && 'value' in data) { return String((data as { value: unknown }).value); } throw new Error('无效的数据格式'); } // ✅ 使用泛型 function processData(data: T): string { return data.value; } ``` ### 4.3 泛型使用 ```typescript // 基础泛型 function identity(value: T): T { return value; } // 泛型约束 function getProperty(obj: T, key: K): T[K] { return obj[key]; } // 泛型接口 interface Repository { findById(id: string): Promise; findAll(): Promise; save(entity: T): Promise; delete(id: string): Promise; } // 泛型类 class BaseService { constructor(private repository: Repository) {} async getById(id: string): Promise { return this.repository.findById(id); } } ``` ### 4.4 模块导入导出 ```typescript // ✅ 导入顺序(按此顺序组织) // 1. Node.js 内置模块 import path from 'path'; import fs from 'fs'; // 2. 第三方库 import React from 'react'; import axios from 'axios'; // 3. 项目内部模块 - 绝对路径 import { UserService } from '@/services/user'; import { formatDate } from '@/utils/date'; // 4. 项目内部模块 - 相对路径 import { Button } from '../components/Button'; import { useAuth } from './hooks/useAuth'; // 5. 类型导入 import type { User, UserRole } from '@/types'; // 6. 样式文件 import './styles.css'; ``` ```typescript // ✅ 导出方式 // 命名导出 - 推荐用于工具函数、类型等 export function formatDate(date: Date): string { } export interface UserInfo { } export const MAX_COUNT = 100; // 默认导出 - 推荐用于组件、类 export default class UserService { } export default function UserCard() { } // 重新导出 export { UserService } from './user-service'; export * from './types'; export { default as Button } from './Button'; ``` ### 4.5 异步编程 ```typescript // ✅ 使用 async/await async function fetchUserData(userId: string): Promise { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } return await response.json(); } catch (error) { console.error('获取用户数据失败:', error); throw error; } } // ✅ 并行请求 async function fetchMultipleUsers(ids: string[]): Promise { const promises = ids.map(id => fetchUserData(id)); return Promise.all(promises); } // ✅ 带超时的请求 async function fetchWithTimeout( promise: Promise, timeoutMs: number ): Promise { const timeout = new Promise((_, reject) => { setTimeout(() => reject(new Error('请求超时')), timeoutMs); }); return Promise.race([promise, timeout]); } ``` ### 4.6 枚举与常量 ```typescript // ✅ 字符串枚举 - 推荐 enum OrderStatus { Pending = 'PENDING', Processing = 'PROCESSING', Completed = 'COMPLETED', Cancelled = 'CANCELLED' } // ✅ const 枚举 - 编译时内联 const enum Direction { Up = 'UP', Down = 'DOWN', Left = 'LEFT', Right = 'RIGHT' } // ✅ 常量对象 + as const - 更灵活 const HTTP_STATUS = { OK: 200, CREATED: 201, BAD_REQUEST: 400, UNAUTHORIZED: 401, NOT_FOUND: 404, INTERNAL_ERROR: 500 } as const; type HttpStatusCode = typeof HTTP_STATUS[keyof typeof HTTP_STATUS]; ``` --- ## 5. Java 规范 ### 5.1 包结构与命名 #### 标准包结构 ``` com.company.project ├── controller/ # 控制器层 │ └── UserController.java ├── service/ # 服务层 │ ├── UserService.java # 接口 │ └── impl/ │ └── UserServiceImpl.java # 实现 ├── repository/ # 数据访问层 │ └── UserRepository.java ├── model/ # 数据模型 │ ├── entity/ # 数据库实体 │ │ └── User.java │ ├── dto/ # 数据传输对象 │ │ ├── UserDTO.java │ │ └── UserCreateRequest.java │ └── vo/ # 视图对象 │ └── UserVO.java ├── config/ # 配置类 │ └── WebConfig.java ├── common/ # 公共模块 │ ├── exception/ # 异常类 │ ├── util/ # 工具类 │ └── constant/ # 常量类 └── Application.java # 启动类 ``` #### 类命名规范 | 类型 | 命名规则 | 示例 | |-----|---------|------| | 控制器 | `Xxx Controller` | `UserController` | | 服务接口 | `XxxService` | `UserService` | | 服务实现 | `XxxServiceImpl` | `UserServiceImpl` | | 数据访问 | `XxxRepository` / `XxxMapper` | `UserRepository` | | 实体类 | `Xxx` | `User`, `Order` | | DTO | `XxxDTO` / `XxxRequest` / `XxxResponse` | `UserDTO` | | VO | `XxxVO` | `UserVO` | | 工具类 | `XxxUtil` / `XxxUtils` / `XxxHelper` | `DateUtils` | | 常量类 | `XxxConstants` | `ApiConstants` | | 枚举 | `XxxEnum` / `XxxType` / `XxxStatus` | `OrderStatus` | | 异常 | `XxxException` | `BusinessException` | ### 5.2 类设计原则 #### 实体类 ```java /** * 用户实体 * * @author AI Assistant * @since 1.0.0 */ @Data @Entity @Table(name = "t_user") public class User implements Serializable { private static final long serialVersionUID = 1L; /** * 用户ID */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; /** * 用户名 */ @Column(nullable = false, length = 50) private String username; /** * 邮箱 */ @Column(nullable = false, unique = true) private String email; /** * 状态:0-禁用,1-启用 */ private Integer status; /** * 创建时间 */ @CreatedDate private LocalDateTime createdAt; /** * 更新时间 */ @LastModifiedDate private LocalDateTime updatedAt; } ``` #### 服务类 ```java /** * 用户服务实现 */ @Slf4j @Service @RequiredArgsConstructor public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; /** * 根据ID获取用户 * * @param id 用户ID * @return 用户信息 * @throws BusinessException 用户不存在时抛出 */ @Override @Transactional(readOnly = true) public UserVO getUserById(Long id) { log.info("查询用户信息,ID:{}", id); User user = userRepository.findById(id) .orElseThrow(() -> new BusinessException("用户不存在:" + id)); return convertToVO(user); } /** * 创建用户 * * @param request 创建请求 * @return 用户ID */ @Override @Transactional(rollbackFor = Exception.class) public Long createUser(UserCreateRequest request) { log.info("创建用户,用户名:{}", request.getUsername()); // 检查用户名是否存在 if (userRepository.existsByUsername(request.getUsername())) { throw new BusinessException("用户名已存在"); } // 创建用户实体 User user = new User(); user.setUsername(request.getUsername()); user.setEmail(request.getEmail()); user.setPassword(passwordEncoder.encode(request.getPassword())); user.setStatus(1); // 保存并返回ID User saved = userRepository.save(user); log.info("用户创建成功,ID:{}", saved.getId()); return saved.getId(); } } ``` ### 5.3 异常处理 #### 自定义异常体系 ```java /** * 基础业务异常 */ @Getter public class BusinessException extends RuntimeException { private final String code; private final String message; public BusinessException(String message) { super(message); this.code = "BUSINESS_ERROR"; this.message = message; } public BusinessException(String code, String message) { super(message); this.code = code; this.message = message; } } /** * 全局异常处理器 */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { /** * 处理业务异常 */ @ExceptionHandler(BusinessException.class) public Result handleBusinessException(BusinessException e) { log.warn("业务异常:{}", e.getMessage()); return Result.fail(e.getCode(), e.getMessage()); } /** * 处理参数校验异常 */ @ExceptionHandler(MethodArgumentNotValidException.class) public Result handleValidationException(MethodArgumentNotValidException e) { String message = e.getBindingResult().getFieldErrors().stream() .map(error -> error.getField() + ": " + error.getDefaultMessage()) .collect(Collectors.joining(", ")); log.warn("参数校验失败:{}", message); return Result.fail("VALIDATION_ERROR", message); } /** * 处理未知异常 */ @ExceptionHandler(Exception.class) public Result handleException(Exception e) { log.error("系统异常:", e); return Result.fail("SYSTEM_ERROR", "系统繁忙,请稍后重试"); } } ``` ### 5.4 Controller 规范 ```java /** * 用户管理接口 */ @Slf4j @RestController @RequestMapping("/api/v1/users") @RequiredArgsConstructor @Tag(name = "用户管理", description = "用户相关接口") public class UserController { private final UserService userService; /** * 获取用户详情 * * @param id 用户ID * @return 用户信息 */ @GetMapping("/{id}") @Operation(summary = "获取用户详情") public Result getUser(@PathVariable Long id) { return Result.success(userService.getUserById(id)); } /** * 获取用户列表 * * @param query 查询条件 * @return 用户列表 */ @GetMapping @Operation(summary = "获取用户列表") public Result> listUsers(@Valid UserQuery query) { return Result.success(userService.listUsers(query)); } /** * 创建用户 * * @param request 创建请求 * @return 用户ID */ @PostMapping @Operation(summary = "创建用户") public Result createUser(@Valid @RequestBody UserCreateRequest request) { return Result.success(userService.createUser(request)); } /** * 更新用户 * * @param id 用户ID * @param request 更新请求 * @return 操作结果 */ @PutMapping("/{id}") @Operation(summary = "更新用户") public Result updateUser( @PathVariable Long id, @Valid @RequestBody UserUpdateRequest request) { userService.updateUser(id, request); return Result.success(); } /** * 删除用户 * * @param id 用户ID * @return 操作结果 */ @DeleteMapping("/{id}") @Operation(summary = "删除用户") public Result deleteUser(@PathVariable Long id) { userService.deleteUser(id); return Result.success(); } } ``` ### 5.5 统一响应格式 ```java /** * 统一响应结果 * * @param 数据类型 */ @Data @NoArgsConstructor @AllArgsConstructor public class Result implements Serializable { private static final long serialVersionUID = 1L; /** * 状态码 */ private String code; /** * 消息 */ private String message; /** * 数据 */ private T data; /** * 时间戳 */ private long timestamp = System.currentTimeMillis(); /** * 成功响应 */ public static Result success(T data) { Result result = new Result<>(); result.setCode("SUCCESS"); result.setMessage("操作成功"); result.setData(data); return result; } /** * 成功响应(无数据) */ public static Result success() { return success(null); } /** * 失败响应 */ public static Result fail(String code, String message) { Result result = new Result<>(); result.setCode(code); result.setMessage(message); return result; } } ``` --- # 第三部分:框架特定规范 ## 6. React 规范 ### 6.1 组件设计原则 #### 函数组件 + TypeScript ```tsx /** * 用户卡片组件 * * @description 展示用户基本信息的卡片组件 */ interface UserCardProps { /** 用户信息 */ user: User; /** 是否显示详情 */ showDetails?: boolean; /** 编辑回调 */ onEdit?: (user: User) => void; /** 删除回调 */ onDelete?: (userId: string) => void; /** 子元素 */ children?: React.ReactNode; } const UserCard: React.FC = ({ user, showDetails = false, onEdit, onDelete, children }) => { // 组件逻辑 return (
{/* 组件内容 */}
); }; export default UserCard; ``` #### 组件文件结构 ``` components/ └── UserCard/ ├── index.tsx # 组件主文件 ├── UserCard.tsx # 组件实现(可选,复杂组件时分离) ├── UserCard.module.css # 样式文件(CSS Modules) ├── UserCard.test.tsx # 测试文件 ├── types.ts # 类型定义(复杂时分离) └── hooks.ts # 组件专用 Hooks(可选) ``` ### 6.2 Hooks 使用规范 #### Hooks 使用顺序 ```tsx function UserProfile({ userId }: { userId: string }) { // 1. useState - 状态定义 const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // 2. useRef - 引用 const containerRef = useRef(null); // 3. useContext - 上下文 const { theme } = useContext(ThemeContext); // 4. 自定义 Hooks const { data, isLoading } = useQuery(['user', userId], fetchUser); // 5. useCallback - 缓存回调 const handleEdit = useCallback(() => { // 处理编辑 }, [userId]); // 6. useMemo - 缓存计算结果 const displayName = useMemo(() => { return user ? `${user.firstName} ${user.lastName}` : ''; }, [user]); // 7. useEffect - 副作用 useEffect(() => { // 副作用逻辑 return () => { // 清理函数 }; }, [userId]); // 8. 条件渲染和返回 if (loading) return ; if (error) return ; return
{/* 内容 */}
; } ``` #### 自定义 Hook 规范 ```tsx /** * 用户数据获取 Hook * * @param userId 用户ID * @returns 用户数据、加载状态、错误信息 */ function useUser(userId: string) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; async function fetchUser() { try { setLoading(true); setError(null); const data = await userApi.getUser(userId); if (!cancelled) { setUser(data); } } catch (err) { if (!cancelled) { setError(err instanceof Error ? err : new Error('未知错误')); } } finally { if (!cancelled) { setLoading(false); } } } fetchUser(); // 清理函数:防止组件卸载后设置状态 return () => { cancelled = true; }; }, [userId]); return { user, loading, error }; } ``` ### 6.3 状态管理 #### 本地状态 vs 全局状态 ```tsx // ✅ 本地状态:组件内部使用,不需要共享 const [isOpen, setIsOpen] = useState(false); const [inputValue, setInputValue] = useState(''); // ✅ 全局状态:多个组件共享,使用状态管理库 // 例如:用户信息、主题设置、购物车等 ``` #### 使用 Zustand(推荐) ```tsx import { create } from 'zustand'; /** * 用户状态 Store */ interface UserStore { user: User | null; isAuthenticated: boolean; login: (user: User) => void; logout: () => void; updateUser: (updates: Partial) => void; } const useUserStore = create((set) => ({ user: null, isAuthenticated: false, login: (user) => set({ user, isAuthenticated: true }), logout: () => set({ user: null, isAuthenticated: false }), updateUser: (updates) => set((state) => ({ user: state.user ? { ...state.user, ...updates } : null })) })); // 使用 function UserProfile() { const { user, logout } = useUserStore(); // ... } ``` ### 6.4 性能优化 ```tsx // ✅ 使用 React.memo 避免不必要的重渲染 const UserCard = React.memo(function UserCard({ user }: UserCardProps) { return
{user.name}
; }); // ✅ 使用 useCallback 缓存回调函数 const handleClick = useCallback((id: string) => { // 处理点击 }, [/* 依赖项 */]); // ✅ 使用 useMemo 缓存计算结果 const sortedItems = useMemo(() => { return [...items].sort((a, b) => a.name.localeCompare(b.name)); }, [items]); // ✅ 列表渲染使用稳定的 key {items.map((item) => ( // ✅ 使用唯一 ID // // ❌ 避免使用索引 ))} // ✅ 懒加载组件 const HeavyComponent = React.lazy(() => import('./HeavyComponent')); function App() { return ( }> ); } ``` --- ## 7. Vue 规范 ### 7.1 组件设计(Vue 3 Composition API) #### 单文件组件结构 ```vue ``` ### 7.2 组合式函数(Composables) ```typescript // composables/useUser.ts import { ref, computed, watch } from 'vue'; import type { Ref } from 'vue'; import type { User } from '@/types'; import { userApi } from '@/api'; /** * 用户数据组合式函数 * * @param userId 用户ID(响应式引用) * @returns 用户数据、加载状态、错误信息、刷新方法 */ export function useUser(userId: Ref | string) { const user = ref(null); const loading = ref(false); const error = ref(null); // 获取用户数据 async function fetchUser(id: string) { loading.value = true; error.value = null; try { user.value = await userApi.getUser(id); } catch (err) { error.value = err instanceof Error ? err : new Error('获取用户失败'); user.value = null; } finally { loading.value = false; } } // 刷新数据 function refresh() { const id = typeof userId === 'string' ? userId : userId.value; return fetchUser(id); } // 计算属性 const displayName = computed(() => { if (!user.value) return ''; return `${user.value.firstName} ${user.value.lastName}`; }); // 侦听 userId 变化 if (typeof userId !== 'string') { watch(userId, (newId) => { if (newId) { fetchUser(newId); } }, { immediate: true }); } else { // 立即获取数据 fetchUser(userId); } return { user, loading, error, displayName, refresh }; } ``` ### 7.3 Pinia 状态管理 ```typescript // stores/user.ts import { defineStore } from 'pinia'; import type { User } from '@/types'; import { userApi } from '@/api'; /** * 用户状态 Store */ export const useUserStore = defineStore('user', { // 状态 state: () => ({ currentUser: null as User | null, isAuthenticated: false, loading: false }), // 计算属性 getters: { /** 用户显示名称 */ displayName(): string { if (!this.currentUser) return '游客'; return `${this.currentUser.firstName} ${this.currentUser.lastName}`; }, /** 是否是管理员 */ isAdmin(): boolean { return this.currentUser?.role === 'admin'; } }, // 方法 actions: { /** * 用户登录 */ async login(credentials: { username: string; password: string }) { this.loading = true; try { const user = await userApi.login(credentials); this.currentUser = user; this.isAuthenticated = true; } finally { this.loading = false; } }, /** * 用户登出 */ logout() { this.currentUser = null; this.isAuthenticated = false; }, /** * 更新用户信息 */ updateUser(updates: Partial) { if (this.currentUser) { this.currentUser = { ...this.currentUser, ...updates }; } } } }); // 使用 Setup Store 语法(更灵活) export const useUserStore2 = defineStore('user', () => { // 状态 const currentUser = ref(null); const isAuthenticated = ref(false); // 计算属性 const displayName = computed(() => { return currentUser.value?.name ?? '游客'; }); // 方法 async function login(credentials: LoginCredentials) { const user = await userApi.login(credentials); currentUser.value = user; isAuthenticated.value = true; } function logout() { currentUser.value = null; isAuthenticated.value = false; } return { currentUser, isAuthenticated, displayName, login, logout }; }); ``` --- # 第四部分:工程化规范 ## 8. Git 提交规范 ### 8.1 提交信息格式 ``` ():