# API设计文档

## 概述

本文档描述了 188-179 招聘系统的 API 设计规范。系统采用 RESTful API 设计风格，使用 Hono 框架实现，并通过 `@hono/zod-openapi` 自动生成 OpenAPI 文档。

## API架构

### 技术栈

- **框架**: Hono 4.x
- **验证**: Zod Schema
- **文档**: @hono/zod-openapi (自动生成OpenAPI 3.0)
- **类型**: TypeScript (完全类型安全)

### API组织结构

```
web/server.js (Hono应用)
├── /api/v1/
│   ├── /auth         # 认证相关
│   ├── /users        # 用户管理
│   ├── /orders       # 订单管理
│   ├── /companies    # 企业管理
│   ├── /platforms    # 平台管理
│   ├── /channels     # 渠道管理
│   └── /files        # 文件管理
└── /ui               # Swagger UI
```

## 通用规范

### 请求格式

#### Content-Type
```http
Content-Type: application/json
```

#### 认证头
```http
Authorization: Bearer <token>
```

### 响应格式

#### 成功响应
```json
{
  "id": 1,
  "username": "admin",
  "email": "admin@example.com"
}
```

#### 错误响应
```json
{
  "code": 400,
  "message": "参数错误"
}
```

#### Zod验证错误
```json
{
  "code": "VALIDATION_ERROR",
  "message": "参数验证失败",
  "errors": [
    {
      "path": ["username"],
      "message": "用户名不能为空"
    }
  ]
}
```

### HTTP状态码

| 状态码 | 含义 | 使用场景 |
|--------|------|----------|
| 200 | OK | 操作成功 |
| 201 | Created | 创建成功 |
| 400 | Bad Request | 请求参数错误 |
| 401 | Unauthorized | 未认证 |
| 403 | Forbidden | 权限不足 |
| 404 | Not Found | 资源不存在 |
| 500 | Internal Server Error | 服务器错误 |

## RESTful API设计

### CRUD标准接口

#### 获取列表
```http
GET /api/v1/users?page=1&pageSize=10&keyword=搜索词
```

#### 获取详情
```http
GET /api/v1/users/:id
```

#### 创建
```http
POST /api/v1/users
Content-Type: application/json

{
  "username": "newuser",
  "email": "user@example.com",
  "password": "password123"
}
```

#### 更新
```http
PUT /api/v1/users/:id
Content-Type: application/json

{
  "email": "newemail@example.com"
}
```

#### 删除
```http
DELETE /api/v1/users/:id
```

### 分页参数

| 参数 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| page | number | 1 | 页码 |
| pageSize | number | 10 | 每页数量 |
| keyword | string | - | 搜索关键词 |
| sortBy | string | createTime | 排序字段 |
| sortOrder | string | DESC | 排序方向 (ASC/DESC) |

### 分页响应
```json
{
  "data": [...],
  "pagination": {
    "total": 100,
    "current": 1,
    "pageSize": 10,
    "totalPages": 10
  }
}
```

## OpenAPI文档

### 访问Swagger UI

```
http://localhost:8080/ui
```

### Schema定义示例

```typescript
import { z } from '@hono/zod-openapi';

// 用户Schema
export const UserSchema = z.object({
  id: z.number().int().positive().openapi({
    description: '用户ID',
    example: 1
  }),
  username: z.string().max(50).openapi({
    description: '用户名',
    example: 'admin'
  }),
  email: z.string().email().nullable().openapi({
    description: '邮箱',
    example: 'admin@example.com'
  }),
  createTime: z.coerce.date<Date>().openapi({
    description: '创建时间'
  }),
  updateTime: z.coerce.date<Date>().openapi({
    description: '更新时间'
  })
});

// 创建用户DTO
export const CreateUserSchema = z.object({
  username: z.string().min(1).max(50).openapi({
    description: '用户名',
    example: 'newuser'
  }),
  email: z.string().email().optional().openapi({
    description: '邮箱',
    example: 'user@example.com'
  }),
  password: z.string().min(6).openapi({
    description: '密码',
    example: 'password123'
  })
});
```

### 路由定义示例

```typescript
import { OpenAPIHono, createRoute } from '@hono/zod-openapi';
import { z } from 'zod';

const app = new OpenAPIHono();

// 定义路由
const getUserRoute = createRoute({
  method: 'get',
  path: '/users/{id}',
  request: {
    params: z.object({
      id: z.string().openapi({
        description: '用户ID',
        example: '1'
      })
    })
  },
  responses: {
    200: {
      description: '获取成功',
      content: {
        'application/json': { schema: UserSchema }
      }
    },
    404: {
      description: '用户不存在',
      content: {
        'application/json': { schema: ErrorSchema }
      }
    }
  }
});

// 实现路由
app.openapi(getUserRoute, async (c) => {
  const { id } = c.req.valid('param');
  const user = await userService.findById(Number(id));
  if (!user) {
    return c.json({ code: 404, message: '用户不存在' }, 404);
  }
  return c.json(user, 200);
});
```

## RPC客户端

### 类型安全的API调用

UI包通过 `hc` 客户端获得类型安全的API调用：

```typescript
import { hc } from 'hono/client';
import type AppRoutes from '@d8d/server';

const client = hc<AppRoutes>('/api/v1');

// 完全类型安全
const result = await client.users.$get({
  query: { page: 1, pageSize: 10 }
});

const user = await client.users[':id'].$get({
  param: { id: '1' }
});
```

## 认证与授权

### JWT认证

```http
POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "admin",
  "password": "password123"
}
```

响应：
```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": 1,
    "username": "admin"
  }
}
```

### 使用Token

```http
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

## 错误处理

### 标准错误响应

```typescript
// 简单错误
return c.json({
  code: 404,
  message: '用户不存在'
}, 404);

// Zod验证错误
if (error instanceof z.ZodError) {
  return c.json({
    code: 'VALIDATION_ERROR',
    message: '参数验证失败',
    errors: error.errors
  }, 400);
}
```

## API版本管理

### URL版本控制

```
/api/v1/users   # 当前版本
/api/v2/users   # 未来版本
```

### 向后兼容策略

- 不移除字段，只添加新字段
- 使用可选字段扩展功能
- 废弃字段在文档中标注

## 性能优化

### 分页限制

- 默认每页10条
- 最大每页100条

### 缓存策略

- 使用Redis缓存热点数据
- 设置合理的缓存过期时间

### 限流策略

- 每用户每分钟100请求限制
- 超限返回429状态码

## 相关文档

- [数据模型](./data-models.md)
- [后端模块开发规范](../standards/backend-module-standards.md)

---

**文档版本**: 1.0
**最后更新**: 2026-01-07
