# AI-前端代码评审指南

## 介绍

随着 `Ai` 的蓬勃发展，我们团队也需要与时俱进，采用更先进的评审工具来评审代码，节约管理人员的时间成本，可以投入到更有价值的业务中去，因为本次试行了借助 `Ai` 评审代码，提高效率

## 前端代码评审指南

````md
# 前端代码评审指南 - POS系统（多人评审版）

## 评审背景

本项目为 **POS系统前端**，基于 Vue 3 + TypeScript + Vite 的企业级管理平台。

## 职级定义与评分权重

评审采用**百分制**，根据不同职级设定不同的评分标准和能力期望：

### 职级能力模型

| 职级 | 经验要求 | 核心能力期望 | 代码质量基线 |
|------|----------|--------------|--------------|
| **初级 (P4)** | 0-2年 | 能独立完成简单功能，在指导下完成复杂功能 | 代码规范、无明显Bug |
| **中级 (P5)** | 2-5年 | 能独立负责模块，具备问题排查能力 | 结构清晰、可维护、有自测意识 |
| **高级 (P6)** | 5-8年 | 能负责复杂模块，具备技术方案设计能力 | 设计合理、性能意识、可扩展 |
| **专家 (P7+)** | 8年以上 | 能主导技术方案，具备架构思维 | 架构优雅、技术引领、质量标杆 |

### 各职级达标分数线

| 职级 | 达标分数 | 优秀分数 | 备注 |
|------|----------|----------|------|
| 初级 (P4) | ≥ 60分 | ≥ 75分 | 重点关注基础规范和功能正确性 |
| 中级 (P5) | ≥ 70分 | ≥ 80分 | 重点关注代码质量和可维护性 |
| 高级 (P6) | ≥ 80分 | ≥ 88分 | 重点关注设计合理性和性能优化 |
| 专家 (P7+) | ≥ 85分 | ≥ 92分 | 重点关注架构优雅和技术引领 |

### 各职级评分细则权重

#### 初级 (P4) - 基础能力导向

| 维度 | 分值 | 评分重点 |
|------|------|----------|
| 代码规范与风格 | **20** | 命名规范、文件后缀、基础格式 |
| Vue 3 最佳实践 | **15** | 正确使用 Composition API、响应式基础 |
| TypeScript 规范 | **10** | 有类型定义、避免明显错误的 any |
| 组件设计 | **10** | 基础组件拆分、Props/Emits 定义 |
| 状态管理 | **10** | 正确使用 Store、避免明显错误 |
| API 与请求 | **10** | 使用统一请求、基础错误处理 |
| 样式规范 | **10** | 使用 Tailwind、样式不混乱 |
| 安全性 | **5** | 无明显的 XSS、敏感信息泄露 |
| 性能优化 | **5** | 无明显的性能问题 |
| 加分项 | **5** | 学习态度好、有改进意识 |
| **总分** | **100** | |

#### 中级 (P5) - 质量意识导向

| 维度 | 分值 | 评分重点 |
|------|------|----------|
| 代码规范与风格 | **12** | 规范执行、团队协作一致性 |
| Vue 3 最佳实践 | **13** | 熟练使用 Composition API、生命周期管理 |
| TypeScript 规范 | **12** | 类型定义完整、减少 any |
| 组件设计 | **13** | 组件粒度合理、复用性考虑 |
| 状态管理 | **10** | Store 组织清晰、响应式正确使用 |
| API 与请求 | **10** | 错误处理完善、类型安全 |
| 样式规范 | **10** | 样式隔离、主题适配 |
| 安全性 | **8** | 安全意识、防护措施到位 |
| 性能优化 | **10** | 有性能意识、避免内存泄漏 |
| 代码审查项 | **2** | 有自测意识、注释清晰 |
| **总分** | **100** | |

#### 高级 (P6) - 设计能力导向

| 维度 | 分值 | 评分重点 |
|------|------|----------|
| 代码规范与风格 | **10** | 规范执行、团队规范推动 |
| Vue 3 最佳实践 | **12** | 最佳实践推广、复杂场景处理 |
| TypeScript 规范 | **12** | 类型系统深入使用、复用类型定义 |
| 组件设计 | **15** | 组件架构设计、高复用性 |
| 状态管理 | **10** | 复杂状态设计、持久化策略 |
| API 与请求 | **10** | 请求封装优化、统一错误处理策略 |
| 样式规范 | **8** | 样式系统设计、主题规范 |
| 安全性 | **8** | 安全最佳实践、敏感数据处理 |
| 性能优化 | **12** | 性能优化措施、渲染优化 |
| 架构设计 | **3** | 模块设计合理性 |
| **总分** | **100** | |

#### 专家 (P7+) - 架构引领导向

| 维度 | 分值 | 评分重点 |
|------|------|----------|
| 代码规范与风格 | **8** | 团队规范制定、代码质量标杆 |
| Vue 3 最佳实践 | **10** | 深度优化、框架最佳实践输出 |
| TypeScript 规范 | **10** | 类型系统架构、复杂类型设计 |
| 组件设计 | **15** | 组件库建设、架构模式设计 |
| 状态管理 | **10** | 全局状态架构、复杂场景解决方案 |
| API 与请求 | **10** | 请求层架构、错误处理体系 |
| 样式规范 | **7** | 设计系统建设、主题架构 |
| 安全性 | **10** | 安全架构、风险评估 |
| 性能优化 | **15** | 性能架构、优化体系 |
| 技术引领 | **5** | 技术创新、方案引领 |
| **总分** | **100** | |

## 技术栈

- **框架**: Vue 3.5.13 + TypeScript
- **构建工具**: Vite 4.3.3
- **UI 组件库**: Element Plus 2.13.3
- **状态管理**: Pinia 2.0.32
- **路由**: Vue Router 4.x
- **样式**: Tailwind CSS 3.4.17 + SCSS
- **HTTP 请求**: Axios（统一封装于 src/utils/request.ts）
- **代码规范**: oxlint + ESLint + Stylelint

## 项目目录结构

```
src/
├── api/           # API 接口定义（按模块分类）
├── assets/        # 静态资源（图片、样式、图标等）
├── components/    # 全局组件
├── directive/     # 自定义指令
├── hooks/         # 组合式函数 (Composables)
├── i18n/          # 国际化配置
├── layout/        # 布局组件
├── router/        # 路由配置
├── stores/        # Pinia 状态管理
├── theme/         # 主题配置
├── types/         # TypeScript 类型定义
├── utils/         # 工具函数
└── views/         # 页面视图
```

## 评审输入格式

请按以下格式提供评审信息：

```yaml
评审时间: 2026-03-27 14:30
评审人员:
  - 姓名: 开发人员A
    职级: 初级/中级/高级/专家  # 必填，用于确定评分标准
    负责目录:
      - src/views/module1/
      - src/api/module1/
      - src/components/componentA/
  - 姓名: 开发人员B
    职级: 中级
    负责目录:
      - src/views/module2/
      - src/hooks/customHooks/
```

**职级说明**：
- **初级 (P4)**：0-2年经验，能独立完成简单功能，在指导下完成复杂功能
- **中级 (P5)**：2-5年经验，能独立负责模块，具备问题排查能力
- **高级 (P6)**：5-8年经验，能负责复杂模块，具备技术方案设计能力
- **专家 (P7+)**：8年以上经验，能主导技术方案，具备架构思维

## 代码统计说明

评审时将统计以下代码指标（过滤注释和空行）：

| 指标 | 说明 |
|------|------|
| **总行数** | 文件所有行数（包含注释和空行） |
| **有效代码行** | 排除单行注释 `//`、多行注释 `/* */`、HTML注释 `<!-- -->`、空行后的实际代码行 |
| **注释行** | 纯注释行数（不含代码的注释） |
| **空行** | 空白行数 |
| **注释率** | 注释行 / 有效代码行 × 100% |

## 评审维度

### 1. 代码规范与风格

- [ ] **命名规范**: 组件名使用 PascalCase，变量/函数使用 camelCase，常量使用 UPPER_SNAKE_CASE
- [ ] **文件后缀**: TypeScript 文件必须使用 `.ts` 后缀
- [ ] **代码格式**: 是否符合 Biome/ESLint 规范，运行 `npm run lint:check` 是否通过
- [ ] **样式规范**: 是否符合 Stylelint 规范
- [ ] **注释规范**: 关键逻辑是否有注释，注释是否清晰

### 2. Vue 3 最佳实践

- [ ] **Composition API**: 是否使用 `<script setup>` 语法
- [ ] **响应式**: 是否正确使用 `ref`/`reactive`/`computed`，避免响应式丢失
- [ ] **生命周期**: 是否正确使用 `onMounted`/`onUnmounted` 等生命周期钩子
- [ ] **自动导入**: Vue/Vue Router/Pinia API 是否正确使用自动导入
- [ ] **组件通信**: 父子组件通信是否规范（props/emits），避免滥用 provide/inject

### 3. TypeScript 规范

- [ ] **类型定义**: 是否有适当的类型定义，避免使用 `any`
- [ ] **接口定义**: API 返回数据是否定义接口类型
- [ ] **类型复用**: 是否在 `src/types/` 中复用通用类型
- [ ] **泛型使用**: 复杂场景是否正确使用泛型

### 4. 组件设计

- [ ] **组件拆分**: 组件粒度是否合理，避免过大或过度拆分
- [ ] **Props 设计**: Props 是否定义类型和默认值，是否单向数据流
- [ ] **Emits 定义**: 事件是否明确定义，命名是否规范
- [ ] **组件复用**: 是否考虑组件复用性，避免重复代码
- [ ] **全局组件**: 如需全局使用，是否在 `src/components/index.ts` 中注册

### 5. 状态管理 (Pinia)

- [ ] **Store 组织**: 状态是否按功能拆分到不同 store 文件
- [ ] **Actions 使用**: 异步操作是否放在 actions 中
- [ ] **持久化**: 需持久化的状态是否使用 `pinia-plugin-persist`
- [ ] **响应式**: 是否正确解构 store 状态（使用 `storeToRefs`）

### 6. API 与请求

- [ ] **API 组织**: API 是否按模块分类存放在 `src/api/` 下
- [ ] **统一请求**: 是否使用 `src/utils/request.ts` 中的 request 函数
- [ ] **错误处理**: 是否处理请求错误，包括网络错误和业务错误
- [ ] **类型安全**: API 函数是否有返回值类型定义

### 7. 样式规范

- [ ] **Tailwind 使用**: 是否优先使用 Tailwind CSS 类名
- [ ] **SCSS 规范**: 自定义 SCSS 是否符合规范，变量是否复用
- [ ] **样式隔离**: 组件样式是否使用 `<style scoped>`
- [ ] **主题适配**: 是否适配暗黑模式和主题切换

### 8. 安全性

- [ ] **XSS 防护**: 用户输入是否正确处理，避免 v-html 直接渲染用户输入
- [ ] **敏感信息**: 是否泄露密钥、token 等敏感信息
- [ ] **权限控制**: 敏感操作是否添加权限校验（v-auth 指令）

### 9. 性能优化

- [ ] **懒加载**: 路由和组件是否使用懒加载
- [ ] **防抖节流**: 高频操作是否使用防抖/节流
- [ ] **内存泄漏**: 是否正确清理定时器、事件监听、订阅
- [ ] **计算缓存**: 复杂计算是否使用 `computed`

### 问题评级定义（按职级调整）

同一问题对不同职级的要求不同：

| 严重程度 | 定义 | 初级 (P4) 扣分 | 中级 (P5) 扣分 | 高级 (P6) 扣分 | 专家 (P7+) 扣分 |
|----------|------|----------------|----------------|----------------|-----------------|
| **阻塞** | 导致功能不可用、安全漏洞、数据丢失 | 每项-10 | 每项-10 | 每项-10 | 每项-10 |
| **严重** | 明显Bug、性能严重问题、错误的使用模式 | 每项-5 | 每项-6 | 每项-7 | 每项-8 |
| **一般** | 代码质量问题、可维护性差、类型不完善 | 每项-2 | 每项-3 | 每项-4 | 每项-5 |
| **建议** | 优化建议、更好的实现方式 | 每项-0.5 | 每项-1 | 每项-2 | 每项-3 |

**职级能力豁免说明**：
- **初级 (P4)**：对复杂设计模式、架构设计方面的建议性问题可以豁免
- **中级 (P5)**：对架构层面的建议性问题可以豁免，但需关注代码质量
- **高级 (P6)**：不允许有明显的代码质量问题，性能优化是必备要求
- **专家 (P7+)**：所有维度都应达到标杆水平，建议性问题也作为扣分项

## 单人评审输出格式

### 问题详情格式

```markdown
#### 问题 #{序号}

| 项目 | 内容 |
|------|------|
| **文件路径** | `src/xxx/xxx.vue` |
| **问题类型** | [规范/功能/性能/安全/可维护性] |
| **严重程度** | [阻塞/严重/一般/建议] |
| **适用职级** | [初级/中级/高级/专家] - 标明此问题对该职级的要求（如：高级以上应避免） |
| **代码位置** | 第 X 行 或 `函数名/代码片段` |

**问题描述**:
具体描述问题

**当前代码**:
```ts
// 有问题的代码示例
```

**建议修改**:
```ts
// 修改后的代码示例
```
```

### 单人评审总结格式

```markdown
### 【{开发人员姓名}】评审总结

**评审职级**: 初级/中级/高级/专家
**达标分数线**: XX分（根据职级确定）

#### 评分卡

> 根据被评审人职级，使用对应的评分权重表（见上文"各职级评分细则权重"）

**初级 (P4) 评分卡示例**：

| 维度 | 分值 | 得分 | 扣分原因 |
|------|------|------|----------|
| 代码规范与风格 | 20 | ? | |
| Vue 3 最佳实践 | 15 | ? | |
| TypeScript 规范 | 10 | ? | |
| 组件设计 | 10 | ? | |
| 状态管理 | 10 | ? | |
| API 与请求 | 10 | ? | |
| 样式规范 | 10 | ? | |
| 安全性 | 5 | ? | |
| 性能优化 | 5 | ? | |
| 加分项 | 5 | ? | |
| **总分** | **100** | **?** | |

**中级 (P5) 评分卡示例**：

| 维度 | 分值 | 得分 | 扣分原因 |
|------|------|------|----------|
| 代码规范与风格 | 12 | ? | |
| Vue 3 最佳实践 | 13 | ? | |
| TypeScript 规范 | 12 | ? | |
| 组件设计 | 13 | ? | |
| 状态管理 | 10 | ? | |
| API 与请求 | 10 | ? | |
| 样式规范 | 10 | ? | |
| 安全性 | 8 | ? | |
| 性能优化 | 10 | ? | |
| 代码审查项 | 2 | ? | |
| **总分** | **100** | **?** | |

**高级 (P6) 评分卡示例**：

| 维度 | 分值 | 得分 | 扣分原因 |
|------|------|------|----------|
| 代码规范与风格 | 10 | ? | |
| Vue 3 最佳实践 | 12 | ? | |
| TypeScript 规范 | 12 | ? | |
| 组件设计 | 15 | ? | |
| 状态管理 | 10 | ? | |
| API 与请求 | 10 | ? | |
| 样式规范 | 8 | ? | |
| 安全性 | 8 | ? | |
| 性能优化 | 12 | ? | |
| 架构设计 | 3 | ? | |
| **总分** | **100** | **?** | |

**专家 (P7+) 评分卡示例**：

| 维度 | 分值 | 得分 | 扣分原因 |
|------|------|------|----------|
| 代码规范与风格 | 8 | ? | |
| Vue 3 最佳实践 | 10 | ? | |
| TypeScript 规范 | 10 | ? | |
| 组件设计 | 15 | ? | |
| 状态管理 | 10 | ? | |
| API 与请求 | 10 | ? | |
| 样式规范 | 7 | ? | |
| 安全性 | 10 | ? | |
| 性能优化 | 15 | ? | |
| 技术引领 | 5 | ? | |
| **总分** | **100** | **?** | |

#### 统计信息

- **评审职级**: 初级/中级/高级/专家
- **达标分数线**: XX分
- **文件总数**: X 个
- **有效代码行**: X 行
- **问题总数**: X 个（阻塞: X, 严重: X, 一般: X, 建议: X）
- **实际得分**: XX 分
- **通过状态**: [通过 / 有条件通过 / 不通过]

**职级能力评估**：

| 评估项 | 评价 | 说明 |
|--------|------|------|
| 基础能力 | [达标/待提升/不达标] | 代码规范、基础功能实现 |
| 质量意识 | [达标/待提升/不达标] | 代码质量、可维护性 |
| 设计能力 | [达标/待提升/不达标] | 架构设计、组件设计（根据职级要求） |
| 性能意识 | [达标/待提升/不达标] | 性能优化、资源管理 |
| 安全意识 | [达标/待提升/不达标] | 安全防护、敏感数据处理 |

#### 主要问题摘要

1. **问题类别**: 简要描述
2. **问题类别**: 简要描述
3. **问题类别**: 简要描述

#### 改进建议

**短期改进（本次代码需修改）**：
1. 建议内容...
2. 建议内容...

**中长期成长建议（根据职级定向培养）**：

| 职级 | 成长方向 | 具体建议 |
|------|----------|----------|
| 初级 (P4) | 基础夯实 | 加强代码规范学习、熟悉Vue3基础API、培养自测习惯 |
| 中级 (P5) | 质量提升 | 深入学习TypeScript、关注代码可维护性、学习设计模式 |
| 高级 (P6) | 架构思维 | 提升组件架构能力、深入性能优化、培养技术方案设计能力 |
| 专家 (P7+) | 技术引领 | 输出最佳实践、推动团队技术升级、解决复杂技术难题 |

**推荐学习资源**：
- [根据问题类型推荐具体文档/文章/代码示例]

---

#### 评审结论

| 结论项 | 内容 |
|--------|------|
| **是否通过** | [通过 / 有条件通过 / 不通过] |
| **是否达标** | [达标 / 不达标] - 是否达到该职级的达标分数线 |
| **职级匹配度** | [匹配 / 基本匹配 / 不匹配] - 当前代码质量与职级期望的匹配程度 |
| **下次评审重点** | [列出下次需要重点关注的维度] |

**有条件通过说明**（如适用）：
- 必须在 X 日内修复阻塞和严重问题
- 建议在一周内完成一般问题的改进
```

---

## 多人评审汇总格式

当多个评审人员同时评审时，使用以下汇总格式：

```markdown
## 多人评审汇总报告

**评审时间**: 2026-03-27
**评审范围**: POS系统前端代码

### 人员评分汇总

| 姓名 | 职级 | 达标线 | 实际得分 | 问题数(阻/严/一/建) | 通过状态 | 是否达标 |
|------|------|--------|----------|---------------------|----------|----------|
| 人员A | 初级 | 60 | 72 | 0/1/3/5 | 通过 | 是 |
| 人员B | 中级 | 70 | 68 | 0/2/5/3 | 有条件通过 | 否 |
| 人员C | 高级 | 80 | 85 | 0/0/2/4 | 通过 | 是 |

### 共性问题

1. **问题描述**: 在多个人员代码中出现的问题
  - 涉及人员: A, B, C
  - 建议措施: 团队培训/规范更新

### 团队能力评估

| 维度 | 评估 | 说明 |
|------|------|------|
| 整体代码质量 | [优/良/中/差] | |
| 规范执行度 | [优/良/中/差] | |
| 技术能力分布 | [均衡/有短板] | |

### 团队改进建议

1. 针对共性问题的改进措施...
2. 团队培训计划...
```

---

*提示：评审时请参考 CLAUDE.md 文件中的项目架构规范*

````

## Vue 3 代码评审规范约定

````
---
name: vue-code-review-conventions
description: |
  Vue 3 + TypeScript + Pinia 代码评审规范约定。当进行 Vue 3 项目代码评审、代码检查、
  或编写 buy-goods 等业务模块代码时，使用该 skill 来确保代码符合团队规范。
  该 skill 总结了常见代码问题，帮助避免拼写错误、状态管理问题、类型不一致等问题。
---

# Vue 3 代码评审规范约定

本 skill 用于约定 Vue 3 + TypeScript + Pinia 项目的代码规范，防止常见错误和代码质量问题。

## 1. Vue 3 组合式 API 规范

### 1.1 defineEmits 使用规范

**错误示例（拼写错误）:**
```vue
<!-- 错误：defineEmits 拼写错误，缺少 't' -->
const emit = defineEmis<{...}>();
```

**正确示例:**
```vue
<!-- 正确：使用 defineEmits -->
const emit = defineEmits<{
  (e: "click", id: string): void;
  (e: "update", value: number): void;
}>();
```

**约定:**
- 拼写必须是 `defineEmits`，不是 `defineEmis`
- 类型定义使用 TypeScript 类型字面量
- 定义位置应放在使用它的函数之前，增强可读性

### 1.2 emit 定义位置

**错误示例:**
```vue
<script setup lang="ts">
const handleClick = () => {
  emit('click'); // emit 在下方定义，可读性差
};

const emit = defineEmits(['click']);
</script>
```

**正确示例:**
```vue
<script setup lang="ts">
// emit 定义放在使用之前
const emit = defineEmits<{
  (e: 'click'): void;
}>();

const handleClick = () => {
  emit('click');
};
</script>
```

## 2. Pinia 状态管理规范

### 2.1 Store 风格约定

**推荐：使用 Setup Store（Composition API 风格）**

```ts
// store/counter.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

export const useCounterStore = defineStore('counter', () => {
  // State
  const count = ref(0);
  
  // Getters
  const doubleCount = computed(() => count.value * 2);
  
  // Actions
  function increment() {
    count.value++;
  }
  
  function reset() {
    count.value = 0;
  }
  
  return {
    count,
    doubleCount,
    increment,
    reset,
  };
});
```

**不推荐：Options Store（除非维护旧代码）**

```ts
// 不推荐，除非项目已有大量 Options Store
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++;
    },
  },
});
```

### 2.2 禁止直接修改 Store State

**错误示例:**
```vue
<script setup lang="ts">
import { useStore } from '@/stores/store';

const store = useStore();

// 错误：直接修改 store state
store.selectedAttrVals = {};
store.count = 10;
</script>
```

**正确示例:**
```ts
// store/index.ts
export const useStore = defineStore('store', () => {
  const selectedAttrVals = ref<Record<string, any>>({});
  const count = ref(0);
  
  // 通过 action 修改状态
  function resetSelectedAttrVals() {
    selectedAttrVals.value = {};
  }
  
  function setCount(value: number) {
    count.value = value;
  }
  
  return {
    selectedAttrVals,
    count,
    resetSelectedAttrVals,
    setCount,
  };
});
```

```vue
<script setup lang="ts">
const store = useStore();

// 正确：通过 action 修改
store.resetSelectedAttrVals();
store.setCount(10);
</script>
```

## 3. TypeScript 规范

### 3.1 类型定义一致性

**错误示例:**
```ts
// 类型定义不一致，使用字符串字面量而非类型
backendDiningWay(): BackendDiningWay {
  const map: Record<DiningWay, BackendDiningWay> = {
    '1': 'DINE_IN', // 应该引用类型定义
    '2': 'TAKEOUT',
  };
  return map[this.filters.diningWayId];
}
```

**正确示例:**
```ts
// types/dining.ts
export enum DiningWay {
  DINE_IN = '1',
  TAKEOUT = '2',
  DELIVERY = '3',
}

export enum BackendDiningWay {
  DINE_IN = 'DINE_IN',
  TAKEOUT = 'TAKEOUT',
  DELIVERY = 'DELIVERY',
}

// store/index.ts
import { DiningWay, BackendDiningWay } from '@/types/dining';

backendDiningWay(): BackendDiningWay {
  const map: Record<DiningWay, BackendDiningWay> = {
    [DiningWay.DINE_IN]: BackendDiningWay.DINE_IN,
    [DiningWay.TAKEOUT]: BackendDiningWay.TAKEOUT,
  };
  return map[this.filters.diningWayId];
}
```

### 3.2 避免使用 any 类型

**错误示例:**
```ts
// 丢失类型安全
this.cartRawData = commonUtil.deepCopy(data); // 返回 any
const list: any[] = await fetchList(); // 应避免 any
```

**正确示例:**
```ts
interface CartRawData {
  items: CartItem[];
  total: number;
}

// 使用泛型指定类型
this.cartRawData = commonUtil.deepCopy<CartRawData>(data);

// 或类型断言
this.cartRawData = commonUtil.deepCopy(data) as CartRawData;

// 定义明确的返回类型
async function fetchList(): Promise<ListItem[]> {
  return await api.getList();
}
```

### 3.3 参数命名规范

**错误示例:**
```ts
// 下划线前缀表示"未使用"，但这里使用了
const handleSpecConfirm = async (_siteGoodsId: number, _selectedItems: SelectedSpecItem[]) => {
  console.log(_siteGoodsId); // 实际使用了，不应该加下划线
};
```

**正确示例:**
```ts
// 正常命名
const handleSpecConfirm = async (siteGoodsId: number, selectedItems: SelectedSpecItem[]) => {
  console.log(siteGoodsId);
};

// 真正未使用的参数才使用下划线
const handleClick = (_event: MouseEvent) => {
  // _event 确实未使用
  doSomething();
};
```

### 3.4 避免命名冲突

**错误示例:**
```ts
// 参数名 goods 与 state 属性 goodsList 冲突，易混淆
async fetchGoodsList(params: { siteId: number }) {
  const { goods } = await api.getGoods(params); // goods 容易与 goodsList 混淆
  this.goodsList = goods;
  console.log(goods.length); // 可读性差
}
```

**正确示例:**
```ts
async fetchGoodsList(params: { siteId: number }) {
  const { goods: items } = await api.getGoods(params); // 重命名避免冲突
  this.goodsList = items;
  console.log(items.length);
}

// 或更清晰的方式
async fetchGoodsList(params: { siteId: number }) {
  const response = await api.getGoods(params);
  this.goodsList = response.goods;
}
```

## 4. 调试与日志规范

### 4.1 移除生产环境调试代码

**错误示例:**
```ts
// 生产环境不应有 console.log
function syncData() {
  console.log(this.data, '==syncData==');
  // ...
}
```

**正确示例:**
```ts
// 方式 1：使用条件编译
import { isDev } from '@/utils/env';

function syncData() {
  if (isDev()) {
    console.log(this.data, '==syncData==');
  }
  // ...
}

// 方式 2：使用日志工具
import { logger } from '@/utils/logger';

function syncData() {
  logger.debug('syncData', this.data);
  // ...
}
```

## 5. API 与 Mock 规范

### 5.1 分离 Mock 与真实 API

**不推荐示例:**
```ts
// api/goods.ts
const USE_MOCK = false;

export function getGoodsList(params) {
  if (USE_MOCK) return Promise.resolve(mock.getGoodsList());
  return request({ url: '/api/goods', params });
}
```

**推荐做法:**

**方案 1：使用 MSW (Mock Service Worker)**
```ts
// 开发环境使用 MSW 拦截请求
// mocks/handlers.ts
import { http, HttpResponse } from 'msw';

export const handlers = [
  http.get('/api/goods', () => {
    return HttpResponse.json(mockGoodsList);
  }),
];
```

**方案 2：分离到独立文件**
```
api/
  goods/
    index.ts       # 真实 API
    mock.ts        # Mock 数据
    mock-api.ts    # Mock 实现（仅在开发环境引入）
```

```ts
// api/goods/index.ts
export function getGoodsList(params: GoodsParams) {
  return request<GoodsItem[]>({ url: '/api/goods', params });
}

// api/goods/mock-api.ts（仅在开发环境使用）
import { getGoodsList as realGetGoodsList } from './index';

export function getGoodsList(params: GoodsParams) {
  if (import.meta.env.DEV) {
    return Promise.resolve(mockGetGoodsList());
  }
  return realGetGoodsList(params);
}
```

## 6. 可访问性规范

### 6.1 确保键盘导航

**问题示例:**
```vue
<!-- 使用 div + v-debounce，键盘无法访问 -->
<div v-debounce="handleClick" class="btn">
  {{ buttonText }}
</div>
```

**正确示例:**
```vue
<!-- 使用 button 元素，天然支持键盘 -->
<button v-debounce="handleClick" class="btn">
  {{ buttonText }}
</button>

<!-- 或使用 div 但添加键盘支持 -->
<div
  v-debounce="handleClick"
  role="button"
  tabindex="0"
  @keydown.enter="handleClick"
  @keydown.space="handleClick"
>
  {{ buttonText }}
</div>
```

## 7. 代码检查清单

### 提交前自查

- [ ] `defineEmits` 拼写正确，不是 `defineEmis`
- [ ] emit 定义在使用之前
- [ ] 没有直接修改 store state，通过 action 修改
- [ ] console.log 已移除或添加了环境判断
- [ ] 没有使用 `any` 类型，已使用具体类型
- [ ] 参数命名规范，未使用无意义的下划线前缀
- [ ] 类型定义统一在 types/ 目录，不直接使用字符串字面量
- [ ] Mock 代码与真实 API 分离

### 常见拼写易错点

| 正确 | 错误 |
|------|------|
| `defineEmits` | `defineEmis`（缺少 t） |
| `computed` | `computed` |
| `watch` | `watch` |
| `ref` | `ref` |

````

## 参考


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ougege.gitbook.io/blog/docs/articles/ren-gong-zhi-neng/ai-qian-duan-dai-ma-ping-shen-zhi-nan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
