---
description: API 接口封装规范 - 接口定义、类型管理、请求封装。
globs: ["**/api/**/*.ts", "**/services/**/*.ts", "**/service/**/*.ts"]
alwaysApply: false
---

# API 接口封装规范

该规则用于 API 接口开发：

**当创建新接口时：**

- 函数命名：`动词 + 资源 + Api`
- 类型独立文件：`xxx.types.ts`
- 接口按业务模块拆分

**当用户提供 Apifox 链接时：**

- 调用 `apifox.get-api-by-url` 自动生成类型
- 未安装则提示：`npx @anthropic/mcp gallery` 选择 apifox

**当编写注释时：**

- 仅注释不能自解释的内容
- 枚举值、业务规则、特殊限制需注释

---

## 📁 文件组织

**方案 A：按模块平铺**（小型项目）

```
{api目录}/
├── user.ts           # 接口函数
├── user.types.ts     # 类型定义
├── types.ts          # 公共类型
└── index.ts          # 统一导出
```

**方案 B：按模块分目录**（大型项目）

```
{api目录}/modules/user/
├── index.ts      # 接口定义
└── types.ts      # 类型定义
```

> 📋 具体存放路径详见 @foundation/project.mdc

---

## 🎨 设计策略

### 1. 接口命名

**函数命名**：`动词 + 资源 + Api`

| 操作     | HTTP 方法 | 命名示例           |
| -------- | --------- | ------------------ |
| 查询列表 | GET       | `getUserListApi`   |
| 查询详情 | GET       | `getUserDetailApi` |
| 创建     | POST      | `createUserApi`    |
| 更新     | PUT/PATCH | `updateUserApi`    |
| 删除     | DELETE    | `deleteUserApi`    |

### 2. 注释规范

**接口注释**：

| 场景       | 是否注释  | 示例                   |
| ---------- | --------- | ---------------------- |
| 功能自解释 | ❌ 不需要 | `getUserInfoApi`       |
| 有特殊说明 | ✅ 需要   | 需权限、有限制、需加密 |

```typescript
// ✅ 无需注释：函数名已自解释
export function getUserInfoApi() {}

// ✅ 需要注释：有特殊说明
/** @note 需要管理员权限 */
export function deleteUserApi(id: number) {}
```

**类型注释**：

| 场景          | 是否注释  | 示例                    |
| ------------- | --------- | ----------------------- |
| 字段自解释    | ❌ 不需要 | `username`、`keyword`   |
| 枚举/格式说明 | ✅ 需要   | `status: 0-禁用 1-正常` |

```typescript
export interface UserListParams extends PageParams {
  keyword?: string;
  /** 0-禁用 1-正常 */
  status?: number;
}
```

> 📋 注释规范详见 @foundation/comment.mdc

### 3. 类型组织

**接口与类型分离**：

```
user.ts        → 接口函数
user.types.ts  → 类型定义（Params、Result、Entity）
```

**类型命名约定**：

| 类型用途 | 命名规则                       | 示例                      |
| -------- | ------------------------------ | ------------------------- |
| 请求参数 | `Xxx + Params`                 | `LoginParams`             |
| 响应数据 | `Xxx + Result` / 实体名        | `LoginResult`、`UserInfo` |
| 公共分页 | `PageParams` / `PageResult<T>` | -                         |

### 4. 分页接口

```typescript
// types.ts - 公共类型
export interface PageParams {
  page: number;
  pageSize: number;
}

export interface PageResult<T> {
  list: T[];
  total: number;
}

// user.ts
export function getUserListApi(params: UserListParams) {
  return request.get<PageResult<UserInfo>>("/users", { params });
}
```

### 5. 类型复用

```typescript
// 部分更新：Partial
export function updateProfileApi(data: Partial<UserInfo>) {}

// 排除字段：Omit
export function createArticleApi(data: Omit<Article, "id" | "createdAt">) {}

// 选取字段：Pick
export function updatePasswordApi(data: Pick<UserInfo, "password">) {}
```

---

## ✅ 检查清单

### 命名与文件

- ✅ 接口函数以 `Api` 结尾
- ✅ 接口按业务模块拆分文件
- ✅ 类型定义独立文件（`xxx.types.ts`）
- ❌ 禁止所有接口写在一个文件中
- ❌ 禁止类型与接口混在同一文件

### 注释

- ✅ 不能自解释的场景必须有注释
- ❌ 禁止注释自解释的内容（如 `/** 用户名 */ username`）

### 调用

- ❌ 禁止在组件中直接调用 HTTP 客户端（必须通过 Api 函数）

---

## 📋 标准模板

### 接口定义

```typescript
// api/user.ts
import request from "@/utils/request";
import type {
  LoginParams,
  LoginResult,
  UserInfo,
  UserListParams,
} from "./user.types";
import type { PageResult } from "./types";

export function loginApi(params: LoginParams) {
  return request.post<LoginResult>("/user/login", params);
}

export function getUserListApi(params: UserListParams) {
  return request.get<PageResult<UserInfo>>("/users", { params });
}

export function createUserApi(data: Omit<UserInfo, "id">) {
  return request.post<UserInfo>("/users", data);
}

/** @note 需要管理员权限 */
export function deleteUserApi(id: number) {
  return request.delete(`/users/${id}`);
}
```

### 类型定义

```typescript
// api/user.types.ts
import type { PageParams } from "./types";

export interface LoginParams {
  username: string;
  /** 需 MD5 加密 */
  password: string;
}

export interface UserInfo {
  id: number;
  username: string;
  nickname: string;
  /** 0-禁用 1-正常 */
  status: number;
}

export interface UserListParams extends PageParams {
  keyword?: string;
  /** 0-禁用 1-正常 */
  status?: number;
}
```
