Cursor rule
.cursor/rules/comments.mdc[object Object]
Cursor rules
Quality
46/100
Scores the file, not the repository.Length
1,716 words
26 headings · 11 code blocksRepository
0
— · pushed 377 days agoLast changed
3 days ago
First indexed 3 days ago.123456# SoybeanAdmin React 注释规范78## 概述910本文档定义了 SoybeanAdmin React 项目的注释规范,旨在提高代码的可读性、可维护性和团队协作效率。良好的注释是代码自文档化的重要组成部分。1112## 注释基本原则1314### 🎯 核心原则15161. **注释要说明"为什么",而不是"做什么"**172. **注释应该是代码的补充,而不是重复**183. **保持注释与代码同步更新**194. **使用中文注释,提高团队理解效率**205. **遵循统一的注释格式和风格**2122### ⚡ 何时需要注释2324```typescript25// ✅ 需要注释的场景26// 1. 复杂的业务逻辑27// 2. 算法实现28// 3. 魔法数字和常量29// 4. API 接口说明30// 5. 公共组件和工具函数31// 6. 临时解决方案(TODO/FIXME)3233// ❌ 不需要注释的场景34// 1. 自解释的代码35// 2. 简单的变量赋值36// 3. 显而易见的操作37```3839## JSDoc 注释规范4041### 📝 函数注释4243**规则:使用 JSDoc 风格,包含描述、参数、返回值**4445```typescript46// ✅ 正确示例47/**48 * 格式化日期49 * @param date 日期对象、时间戳或日期字符串50 * @param format 格式化模板,默认为 'YYYY-MM-DD HH:mm:ss'51 * @returns 格式化后的日期字符串52 * @example53 * formatDate(new Date(), 'YYYY-MM-DD') // '2024-01-15'54 * formatDate(1642204800000, 'MM/DD/YYYY') // '01/15/2022'55 */56export const formatDate = (57 date: Date | number | string,58 format = 'YYYY-MM-DD HH:mm:ss'59): string => {60 // 实现逻辑61 return dayjs(date).format(format);62};6364/**65 * 防抖函数 - 在指定时间内多次调用只执行最后一次66 * @param fn 要防抖的函数67 * @param delay 延迟时间(毫秒)68 * @returns 防抖后的函数69 * @example70 * const debouncedSearch = debounce(search, 300);71 * debouncedSearch('keyword'); // 300ms 后执行72 */73export const debounce = <T extends (...args: any[]) => any>(74 fn: T,75 delay: number76): T => {77 let timeoutId: NodeJS.Timeout;78 return ((...args: Parameters<T>) => {79 clearTimeout(timeoutId);80 timeoutId = setTimeout(() => fn(...args), delay);81 }) as T;82};8384/**85 * 深拷贝对象或数组86 * @param obj 要拷贝的对象87 * @returns 深拷贝后的新对象88 * @throws {Error} 当对象包含循环引用时抛出错误89 */90export const deepClone = <T>(obj: T): T => {91 if (obj === null || typeof obj !== 'object') return obj;92 // 实现逻辑93};9495// ❌ 错误示例96// 缺少注释97export const formatDate = (date: Date, format: string) => {98 return dayjs(date).format(format);99};100101// 注释过于简单,没有提供有用信息102/**103 * 格式化日期104 */105export const formatDate = (date: Date, format: string) => {106 return dayjs(date).format(format);107};108```109110### 🏗️ 类和接口注释111112```typescript113// ✅ 正确示例114/**115 * 用户信息接口116 * @description 定义用户的基本信息结构117 */118interface UserInfo {119 /** 用户唯一标识 */120 id: string;121 /** 用户名 */122 name: string;123 /** 邮箱地址 */124 email: string;125 /** 用户角色 */126 role: 'admin' | 'user' | 'guest';127 /** 账户创建时间 */128 createTime: string;129 /** 最后更新时间 */130 updateTime: string;131 /** 是否激活 */132 isActive: boolean;133}134135/**136 * API 响应数据结构137 * @template T 响应数据的类型138 */139interface ApiResponse<T = any> {140 /** 响应状态码 */141 code: number;142 /** 响应消息 */143 message: string;144 /** 响应数据 */145 data: T;146 /** 请求是否成功 */147 success: boolean;148}149150/**151 * 用户服务类152 * @description 处理用户相关的 API 请求153 */154class UserService {155 private apiClient: ApiClient;156157 /**158 * 构造函数159 * @param apiClient API 客户端实例160 */161 constructor(apiClient: ApiClient) {162 this.apiClient = apiClient;163 }164165 /**166 * 获取用户列表167 * @param params 查询参数168 * @returns Promise<UserListResponse>169 */170 async getUserList(params: UserListParams): Promise<UserListResponse> {171 return this.apiClient.get('/users', { params });172 }173}174```175176### 🧩 组件注释177178```typescript179// ✅ 正确示例180/**181 * 用户信息卡片组件182 * @description 展示用户基本信息,支持编辑和删除操作183 * @author 张三184 * @since 1.0.0185 */186interface UserCardProps {187 /** 用户信息对象 */188 user: UserInfo;189 /** 是否显示操作按钮 */190 showActions?: boolean;191 /** 卡片尺寸 */192 size?: 'small' | 'medium' | 'large';193 /** 编辑回调函数 */194 onEdit?: (user: UserInfo) => void;195 /** 删除回调函数 */196 onDelete?: (userId: string) => void;197}198199/**200 * 用户信息卡片组件201 * @param props 组件属性202 * @returns JSX.Element203 */204const UserCard: React.FC<UserCardProps> = ({205 user,206 showActions = true,207 size = 'medium',208 onEdit,209 onDelete210}) => {211 // 处理编辑操作212 const handleEdit = useCallback(() => {213 onEdit?.(user);214 }, [user, onEdit]);215216 // 处理删除操作217 const handleDelete = useCallback(() => {218 if (window.confirm('确认删除此用户?')) {219 onDelete?.(user.id);220 }221 }, [user.id, onDelete]);222223 return (224 <Card className={`user-card user-card--${size}`}>225 {/* 用户头像区域 */}226 <div className="user-card__avatar">227 <Avatar size={size === 'large' ? 64 : 48} src={user.avatar} />228 </div>229230 {/* 用户信息区域 */}231 <div className="user-card__info">232 <h3 className="user-card__name">{user.name}</h3>233 <p className="user-card__email">{user.email}</p>234 <Tag color={user.role === 'admin' ? 'red' : 'blue'}>235 {user.role}236 </Tag>237 </div>238239 {/* 操作按钮区域 */}240 {showActions && (241 <div className="user-card__actions">242 <Button size="small" onClick={handleEdit}>243 编辑244 </Button>245 <Button size="small" danger onClick={handleDelete}>246 删除247 </Button>248 </div>249 )}250 </Card>251 );252};253254export default UserCard;255```256257### 🪝 Hook 注释258259```typescript260// ✅ 正确示例261/**262 * 用户信息管理 Hook263 * @description 提供用户信息的获取、更新和缓存功能264 * @param userId 用户ID265 * @returns 用户信息和相关操作方法266 * @example267 * const { user, loading, updateUser, refreshUser } = useUserInfo('123');268 */269export const useUserInfo = (userId: string) => {270 const [user, setUser] = useState<UserInfo | null>(null);271 const [loading, setLoading] = useState(false);272 const [error, setError] = useState<string | null>(null);273274 // 获取用户信息275 const fetchUser = useCallback(async () => {276 if (!userId) return;277278 setLoading(true);279 setError(null);280281 try {282 const userData = await fetchUserById(userId);283 setUser(userData);284 } catch (err) {285 setError(err instanceof Error ? err.message : '获取用户信息失败');286 } finally {287 setLoading(false);288 }289 }, [userId]);290291 // 更新用户信息292 const updateUser = useCallback(async (updates: Partial<UserInfo>) => {293 if (!user) return;294295 try {296 const updatedUser = await updateUserById(user.id, updates);297 setUser(updatedUser);298 return updatedUser;299 } catch (err) {300 setError(err instanceof Error ? err.message : '更新用户信息失败');301 throw err;302 }303 }, [user]);304305 useEffect(() => {306 fetchUser();307 }, [fetchUser]);308309 return {310 user,311 loading,312 error,313 updateUser,314 refreshUser: fetchUser315 };316};317```318319## 行内注释规范320321### 💬 单行注释322323```typescript324// ✅ 正确示例325// 计算用户权限等级(1-5级,5级为最高权限)326const calculateUserLevel = (permissions: string[]) => {327 // 管理员权限直接返回最高等级328 if (permissions.includes('admin')) {329 return 5;330 }331332 // 根据权限数量计算等级333 const level = Math.min(Math.floor(permissions.length / 2) + 1, 4);334 return level;335};336337// 处理API响应错误338const handleApiError = (error: ApiError) => {339 // 401 未授权,跳转到登录页340 if (error.code === 401) {341 router.push('/login');342 return;343 }344345 // 403 权限不足,显示错误提示346 if (error.code === 403) {347 notification.error({348 message: '权限不足',349 description: '您没有执行此操作的权限'350 });351 return;352 }353354 // 其他错误显示通用错误信息355 notification.error({356 message: '操作失败',357 description: error.message || '请稍后重试'358 });359};360361// ❌ 错误示例362const userName = 'admin'; // 用户名 <- 无意义的注释363const age = 25; // 年龄是25 <- 重复代码内容364// 这是一个函数 <- 太泛泛的注释365function getData() {366 return data;367}368```369370### 🏷️ 特殊标记注释371372```typescript373// ✅ 正确示例374const UserProfile: React.FC<UserProfileProps> = ({ user }) => {375 // TODO: 添加用户头像上传功能376 // 计划在下个版本中实现头像拖拽上传377378 // FIXME: 修复在移动端显示异常的问题379 // 当前在 iOS Safari 中用户信息卡片会出现布局错乱380381 // HACK: 临时解决方案 - 强制刷新组件382 // 等待 React 18 并发特性稳定后重构此部分代码383 const [forceUpdate, setForceUpdate] = useState(0);384385 // NOTE: 这里使用了特殊的数据格式386 // 服务端返回的时间格式为 Unix timestamp,需要转换387 const formattedTime = useMemo(() => {388 return dayjs.unix(user.createTime).format('YYYY-MM-DD HH:mm:ss');389 }, [user.createTime]);390391 // WARNING: 此方法会修改原始对象392 // 调用前请确认是否需要深拷贝393 const processUserData = (userData: UserInfo) => {394 userData.name = userData.name.trim();395 return userData;396 };397398 return (399 <div className="user-profile">400 {/* 用户基本信息 */}401 <div className="user-profile__basic">402 <h2>{user.name}</h2>403 <p>{user.email}</p>404 </div>405406 {/* 用户详细信息 */}407 <div className="user-profile__details">408 <p>创建时间: {formattedTime}</p>409 <p>用户角色: {user.role}</p>410 </div>411 </div>412 );413};414```415416### 📝 特殊标记说明417418| 标记 | 用途 | 示例 |419|------|------|------|420| `TODO` | 计划添加的功能 | `// TODO: 添加数据导出功能` |421| `FIXME` | 需要修复的问题 | `// FIXME: 修复内存泄漏问题` |422| `HACK` | 临时解决方案 | `// HACK: 绕过第三方库的bug` |423| `NOTE` | 重要说明 | `// NOTE: 此API在v2.0中已废弃` |424| `WARNING` | 警告信息 | `// WARNING: 此操作不可逆` |425| `OPTIMIZE` | 性能优化点 | `// OPTIMIZE: 考虑使用虚拟滚动` |426| `REVIEW` | 需要代码审查 | `// REVIEW: 确认业务逻辑是否正确` |427428429## API 和配置注释430431### 🌐 API 接口注释432433```typescript434// ✅ 正确示例435/**436 * 用户相关 API 接口437 */438export const userApi = {439 /**440 * 获取用户列表441 * @param params 查询参数442 * @param params.page 页码,从1开始443 * @param params.pageSize 每页数量,默认20444 * @param params.keyword 搜索关键词,支持用户名和邮箱搜索445 * @param params.role 用户角色筛选446 * @param params.status 用户状态筛选447 * @returns Promise<UserListResponse> 用户列表数据448 * @example449 * const result = await userApi.fetchUserList({450 * page: 1,451 * pageSize: 20,452 * keyword: 'admin'453 * });454 */455 fetchUserList: (params: UserListParams) => {456 return request<UserListResponse>({457 url: '/api/users',458 method: 'GET',459 params460 });461 },462463 /**464 * 根据ID获取用户详情465 * @param id 用户ID466 * @returns Promise<UserInfo> 用户详细信息467 * @throws {ApiError} 当用户不存在时抛出404错误468 */469 fetchUserById: (id: string) => {470 return request<UserInfo>({471 url: `/api/users/${id}`,472 method: 'GET'473 });474 },475476 /**477 * 创建新用户478 * @param userData 用户数据479 * @returns Promise<UserInfo> 创建成功的用户信息480 * @throws {ValidationError} 当数据验证失败时抛出400错误481 */482 createUser: (userData: CreateUserData) => {483 return request<UserInfo>({484 url: '/api/users',485 method: 'POST',486 data: userData487 });488 }489};490```491492### ⚙️ 配置文件注释493494```typescript495// ✅ 正确示例496/**497 * 应用配置498 * @description 包含应用的基本配置信息499 */500export const appConfig = {501 /** 应用名称 */502 name: 'SoybeanAdmin',503504 /** 应用版本 */505 version: '1.0.0',506507 /** 应用描述 */508 description: '基于 React + TypeScript 的后台管理系统',509510 /** 默认语言 */511 defaultLang: 'zh-CN',512513 /** 是否启用国际化 */514 enableI18n: true,515516 /**517 * 分页配置518 * @description 表格分页的默认配置519 */520 pagination: {521 /** 默认页码 */522 defaultPage: 1,523 /** 默认每页数量 */524 defaultPageSize: 20,525 /** 每页数量选项 */526 pageSizeOptions: ['10', '20', '50', '100'],527 /** 是否显示快速跳转 */528 showQuickJumper: true,529 /** 是否显示总数 */530 showTotal: true531 },532533 /**534 * 请求配置535 * @description HTTP请求的默认配置536 */537 request: {538 /** 请求超时时间(毫秒) */539 timeout: 10000,540 /** 基础URL */541 baseURL: import.meta.env.VITE_API_BASE_URL,542 /** 重试次数 */543 retryCount: 3,544 /** 重试间隔(毫秒) */545 retryDelay: 1000546 }547};548549/**550 * 主题配置551 * @description 定义应用的主题样式配置552 */553export const themeConfig = {554 /** 默认主题模式 */555 defaultMode: 'light' as const,556557 /** 是否启用暗色模式 */558 enableDarkMode: true,559560 /**561 * 主色调配置562 * @description 影响按钮、链接等主要元素的颜色563 */564 primaryColor: '#1890ff',565566 /**567 * 成功状态颜色568 * @description 用于成功提示、完成状态等569 */570 successColor: '#52c41a',571572 /**573 * 警告状态颜色574 * @description 用于警告提示、待处理状态等575 */576 warningColor: '#faad14',577578 /**579 * 错误状态颜色580 * @description 用于错误提示、失败状态等581 */582 errorColor: '#ff4d4f'583};584```585586## 注释最佳实践587588### ✅ 推荐做法589590```typescript591// 1. 解释复杂业务逻辑592const calculateUserScore = (user: UserInfo) => {593 // 用户评分算法:基础分数50分594 let score = 50;595596 // 根据注册时长加分(每年+10分,最多+30分)597 const yearsSinceRegistration = dayjs().diff(user.registerTime, 'year');598 score += Math.min(yearsSinceRegistration * 10, 30);599600 // 根据活跃度加分(每月活跃+5分,最多+20分)601 score += Math.min(user.activeMonths * 5, 20);602603 // 违规记录扣分(每次违规-10分)604 score -= user.violationCount * 10;605606 // 确保分数在0-100范围内607 return Math.max(0, Math.min(100, score));608};609610// 2. 解释魔法数字611const MAX_UPLOAD_SIZE = 5 * 1024 * 1024; // 5MB - 用户头像上传限制612const DEBOUNCE_DELAY = 300; // 300ms - 搜索防抖延迟,平衡用户体验和性能613614// 3. 解释复杂的正则表达式615const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // 邮箱格式验证正则616617// 4. 解释算法思路618const quickSort = (arr: number[]): number[] => {619 // 快速排序算法实现620 // 选择最后一个元素作为基准点,分为小于和大于基准的两部分621 if (arr.length <= 1) return arr;622623 const pivot = arr[arr.length - 1];624 const left = arr.slice(0, -1).filter(x => x <= pivot);625 const right = arr.slice(0, -1).filter(x => x > pivot);626627 return [...quickSort(left), pivot, ...quickSort(right)];628};629```630631### ❌ 避免的做法632633```typescript634// ❌ 不要重复代码635const userName = 'admin'; // 设置用户名为admin636637// ❌ 不要注释显而易见的代码638const sum = a + b; // 把a和b相加639640// ❌ 不要使用过时的注释641const fetchUserData = async () => {642 // 使用axios发送请求 <- 实际代码已改为fetch643 return fetch('/api/users');644};645646// ❌ 不要使用无意义的注释647// 这是一个函数648function getData() {649 return data;650}651652// ❌ 不要使用英文注释(在中文团队中)653// Get user information from server654const getUserInfo = () => {655 // Implementation656};657```658659## 注释维护660661### 🔄 注释更新原则6626631. **代码修改时同步更新注释**6642. **删除过时和无效的注释**6653. **定期审查注释的准确性**6664. **保持注释格式的一致性**667668### 📋 代码审查检查清单669670- [ ] 所有公共函数都有JSDoc注释671- [ ] 复杂业务逻辑有说明注释672- [ ] 魔法数字有解释说明673- [ ] TODO/FIXME等标记有明确描述674- [ ] 注释内容与代码实现一致675- [ ] 注释语言统一(推荐中文)676- [ ] 注释格式规范统一677678## 总结679680### 📝 注释规范速查表681682| 注释类型 | 格式 | 适用场景 |683|---------|------|----------|684| JSDoc注释 | `/** */` | 函数、类、接口、组件 |685| 单行注释 | `//` | 行内说明、简短解释 |686| 多行注释 | `/* */` | 大段说明、临时禁用代码 |687| 特殊标记 | `// TODO:` | 待办事项、问题标记 |688689### 🎯 注释质量标准690691**高质量注释的特征:**692- 解释代码的"为什么"而不是"是什么"693- 提供有价值的上下文信息694- 格式规范,易于阅读695- 与代码保持同步696- 使用合适的语言(团队统一)697698**避免的注释:**699- 重复代码内容的注释700- 过时不准确的注释701- 过于显而易见的注释702- 格式不规范的注释703- 语言不统一的注释704- 不需要头部文件注释705706遵循这些注释规范将大大提高代码的可读性和可维护性,让团队协作更加高效!707
Also in crunl/Xingyu-Frontend
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| crunl/Xingyu-Frontend.cursor/rules/api.mdc · 0 | Cursor rules | api | 45/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/componenting.mdc · 0 | Cursor rules | no sections | 45/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/naming.mdc · 0 | Cursor rules | archtypesapiui | 58/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/project.mdc · 0 | Cursor rules | no sections | 50/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/reduxing.mdc · 0 | Cursor rules | no sections | 45/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/routing.mdc · 0 | Cursor rules | no sections | 53/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/styling.mdc · 0 | Cursor rules | archui | 54/100 | 3 days ago | |
| crunl/Xingyu-Frontend.cursor/rules/typescript.mdc · 0 | Cursor rules | typesdocs | 42/100 | 3 days ago |
Diff against .cursor/rules/api.mdc Diff against .cursor/rules/componenting.mdc Diff against .cursor/rules/naming.mdc Diff against .cursor/rules/project.mdc Diff against .cursor/rules/reduxing.mdc Diff against .cursor/rules/routing.mdc Diff against .cursor/rules/styling.mdc Diff against .cursor/rules/typescript.mdc
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 3 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 3 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 3 days ago |
