# 服务层架构文档
> **前端服务层** - 统一的 API 交互层,基于 TypeScript 和面向对象设计
## 架构设计
### 设计理念
服务层采用**分层架构**和**继承模式**,遵循以下核心原则:
1. **单一职责** - 每个服务模块负责一个业务领域
2. **类型安全** - 全量 TypeScript 类型定义,杜绝 `any`
3. **统一规范** - 所有服务遵循相同的设计模式
4. **错误分类** - 细粒度错误类型,便于精确处理
5. **可扩展性** - 基于继承的设计,易于添加新服务
---
## 架构分层
```mermaid
graph TB
subgraph UI["业务组件层"]
Components["React Components
Hooks & Contexts"]
end
subgraph Services["服务层 (Services Layer)"]
direction LR
Auth["AuthService
认证服务"]
Admin["AdminService
管理员服务"]
Merchant["MerchantService
商户服务"]
Transaction["TransactionService
交易服务"]
Dispute["DisputeService
争议服务"]
User["UserService
用户服务"]
Config["ConfigService
配置服务"]
end
subgraph BaseLayer["服务基类"]
BaseService["BaseService
• get() post() put() delete()
• rawGet() rawPost()"]
end
subgraph Core["核心层 (Core Layer)"]
direction LR
ApiClient["api-client.ts
• 请求/响应拦截
• 错误处理
• 请求去重
• 401重定向"]
Errors["errors.ts
• ApiErrorBase
• NetworkError
• ValidationError
• 等7种错误"]
Types["types.ts
• ApiResponse
• PaginationParams
• RequestConfig"]
CoreConfig["config.ts
• baseURL
• timeout
• credentials"]
end
Backend["Backend API
(Go + Gin)"]
Components -->|调用| Auth
Components -->|调用| Admin
Components -->|调用| Merchant
Components -->|调用| Transaction
Components -->|调用| Dispute
Components -->|调用| User
Components -->|调用| Config
Auth -.->|继承| BaseService
Admin -.->|继承| BaseService
Merchant -.->|继承| BaseService
Transaction -.->|继承| BaseService
Dispute -.->|继承| BaseService
User -.->|继承| BaseService
Config -.->|继承| BaseService
BaseService -->|使用| ApiClient
BaseService -->|使用| Errors
BaseService -->|使用| Types
ApiClient -->|读取| CoreConfig
ApiClient ==>|HTTP 请求| Backend
style UI fill:#e1f5ff
style Services fill:#fff9e6
style BaseLayer fill:#f0f0f0
style Core fill:#e8f5e9
style Backend fill:#ffebee
```
---
## 目录结构
```
lib/services/
├── core/ # 核心基础设施层
│ ├── api-client.ts # HTTP 客户端(请求拦截、错误处理)
│ ├── base.service.ts # 服务基类(封装 CRUD 方法)
│ ├── config.ts # API 配置(环境变量、超时等)
│ ├── errors.ts # 错误类型定义(7种错误类型)
│ ├── types.ts # 核心类型(ApiResponse、分页等)
│ └── index.ts # 核心模块导出
│
├── auth/ # 认证服务模块
│ ├── auth.service.ts # OAuth 认证、登录、登出
│ ├── types.ts # User、OAuthLoginUrlResponse 等
│ └── index.ts # 模块导出 + 文档
│
├── admin/ # 管理员服务模块
│ ├── admin.service.ts # 系统配置、用户积分配置管理
│ ├── types.ts # SystemConfig、UserPayConfig 等
│ └── index.ts # 模块导出 + 文档
│
├── merchant/ # 商户服务模块
│ ├── merchant.service.ts # API Key、支付链接、订单管理
│ ├── types.ts # MerchantAPIKey、PaymentLink 等
│ └── index.ts # 模块导出 + 文档
│
├── transaction/ # 交易服务模块
│ ├── transaction.service.ts # 交易记录
│ ├── types.ts # Order、TransactionQueryParams 等
│ └── index.ts # 模块导出 + 文档
│
├── dispute/ # 争议服务模块
│ ├── dispute.service.ts # 创建争议、退款审核
│ ├── types.ts # Dispute、DisputeWithOrder 等
│ └── index.ts # 模块导出 + 文档
│
├── user/ # 用户服务模块
│ ├── user.service.ts # 用户设置(支付密钥等)
│ ├── types.ts # UpdatePayKeyRequest 等
│ └── index.ts # 模块导出 + 文档
│
├── config/ # 配置服务模块
│ ├── config.service.ts # 获取公共配置
│ ├── types.ts # PublicConfigResponse
│ └── index.ts # 模块导出 + 文档
│
├── index.ts # 统一导出入口
└── README.md # 本文档
```
---
## 核心模块详解
### 1. BaseService - 服务基类
**职责**:为所有业务服务提供统一的 HTTP 方法封装
**关键设计**:
```typescript
export class BaseService {
protected static readonly basePath: string = '';
// 标准 RESTful 方法
protected static async get(path: string, params?: Record): Promise
protected static async post(path: string, data?: unknown): Promise
protected static async put(path: string, data?: unknown): Promise
protected static async patch(path: string, data?: unknown): Promise
protected static async delete(path: string, params?: Record): Promise
// 特殊端点支持(不遵循标准响应格式)
protected static async rawGet(url: string, params?: unknown): Promise
protected static async rawPost(url: string, data?: unknown): Promise
}
```
**设计优势**:
- ✅ 子类只需设置 `basePath`,无需重复实现 HTTP 逻辑
- ✅ 统一的响应解包(`response.data.data`)
- ✅ 类型安全的泛型设计
- ✅ 支持特殊端点(如 `/api.php`)
---
### 2. API Client - HTTP 客户端
**职责**:提供全局唯一的 Axios 实例,处理所有 HTTP 请求
**核心功能**:
#### 请求拦截器
- 自动添加 Cancel Token(支持请求取消)
- 请求去重(避免重复请求)
#### 响应拦截器
- **401 自动重定向** - 未授权时自动跳转登录页
- **错误分类** - 将 HTTP 状态码映射为具体错误类型
- **统一响应格式** - 解析 `ApiResponse` 结构
#### 错误处理映射
| HTTP 状态码 | 错误类型 | 说明 |
|------------|---------|------|
| 400 | `ValidationError` | 参数验证失败 |
| 401 | 自动重定向 | 跳转到登录页 |
| 403 | `ForbiddenError` | 权限不足 |
| 404 | `NotFoundError` | 资源不存在 |
| 5xx | `ServerError` | 服务器错误 |
| 超时 | `TimeoutError` | 请求超时 |
| 网络 | `NetworkError` | 网络连接失败 |
---
### 3. 错误类型层级
```
ApiErrorBase (基类)
├── NetworkError (网络连接错误)
├── TimeoutError (请求超时)
├── UnauthorizedError (401 - 未授权)
├── ForbiddenError (403 - 权限不足)
├── NotFoundError (404 - 资源不存在)
├── ValidationError (400 - 参数验证失败)
└── ServerError (5xx - 服务器错误)
```
**设计优势**:
- 支持 `instanceof` 类型判断
- 携带详细错误信息(`error_code`、`details`)
- 便于前端精确处理不同错误场景
---
## 开发规范
### 1. 服务类规范
#### 必须遵循
```typescript
export class SomeService extends BaseService {
// 1. 必须继承 BaseService
// 2. basePath 必须是 protected static readonly
protected static readonly basePath = '/api/v1/resource';
// 3. 方法必须是 static async
// 4. 返回类型必须明确(禁止 any)
static async getAll(): Promise {
return this.get('/');
}
// 5. 参数类型必须明确定义在 types.ts
static async create(request: CreateResourceRequest): Promise {
return this.post('/', request);
}
}
```
#### 方法命名规范
| 操作 | 命名 | 示例 |
|------|------|------|
| 获取列表 | `list*` 或 `getAll` | `listAPIKeys()` |
| 获取单个 | `get*` 或 `getById` | `getAPIKey(id)` |
| 创建 | `create*` | `createAPIKey(request)` |
| 更新 | `update*` | `updateAPIKey(id, request)` |
| 删除 | `delete*` | `deleteAPIKey(id)` |
| 特殊操作 | 动词开头 | `payMerchantOrder()` |
#### 方法排序规范
```typescript
export class SomeService extends BaseService {
protected static readonly basePath = '/api/v1/resource';
// 1. CRUD 操作(按 Create → Read → Update → Delete)
static async create() { }
static async list() { }
static async get() { }
static async update() { }
static async delete() { }
// 2. 其他业务方法(按业务逻辑分组)
static async someAction() { }
}
```
---
### 2. 类型定义规范
#### types.ts 文件结构
```typescript
// 1. 类型别名(Type Aliases)
export type ResourceStatus = 'active' | 'inactive' | 'pending';
// 2. 枚举(Enums) - 使用 const enum 提升性能
export const enum ResourceLevel {
Basic = 1,
Premium = 2,
Enterprise = 3,
}
// 3. 接口(Interfaces) - 按业务逻辑分组
/**
* 资源信息
*/
export interface Resource {
/** 资源 ID */
id: number;
/** 资源名称 */
name: string;
/** 状态 */
status: ResourceStatus;
/** 创建时间 */
created_at: string;
}
/**
* 创建资源请求
*/
export interface CreateResourceRequest {
/** 资源名称(最大 50 字符) */
name: string;
/** 描述(可选,最大 200 字符) */
description?: string;
}
```
#### 注释规范
- ✅ 所有 interface 必须有 JSDoc 描述
- ✅ 所有字段必须有行内注释
- ✅ 包含约束信息(长度、范围、格式等)
- ✅ 可选字段使用 `?` 标记
---
### 3. JSDoc 注释规范
**标准模板**:
```typescript
/**
* [一句话描述方法功能]
*
* @param paramName - 参数说明
* @returns 返回值说明
* @throws {ErrorType} 错误条件说明
*
* @example
* ```typescript
* // 使用示例
* const result = await Service.method({ param: 'value' });
* ```
*
* @remarks [可选]
* - 业务规则或注意事项
*/
```
**示例**:
```typescript
/**
* 创建商户 API Key
*
* @param request - API Key 配置
* @returns 创建的 API Key 信息
* @throws {UnauthorizedError} 当未登录时
* @throws {ValidationError} 当参数验证失败时
*
* @example
* ```typescript
* const apiKey = await MerchantService.createAPIKey({
* app_name: '我的应用',
* app_homepage_url: 'https://example.com'
* });
* ```
*
* @remarks
* - app_name 最大 20 字符
* - 需要登录权限
*/
static async createAPIKey(request: CreateAPIKeyRequest): Promise
```
---
### 4. 模块 index.ts 规范
**标准格式**:
```typescript
/**
* [模块名] 服务模块
*
* @description
* 提供 [业务领域] 相关的功能,包括:
* - 功能点1
* - 功能点2
* - 功能点3
*
* @example
* ```typescript
* import { ServiceName } from '@/lib/services';
*
* // 使用示例(展示最常用的1-2个方法)
* const result = await ServiceName.commonMethod();
* ```
*
* @remarks [可选]
* - 特殊说明(如权限要求等)
*/
export { ServiceName } from './service-name.service';
export type * from './types';
// 或明确导出
export type {
Type1,
Type2,
} from './types';
```
---
## 创建新服务指南
### Step 1: 创建目录和文件
```bash
mkdir lib/services/resource
touch lib/services/resource/types.ts
touch lib/services/resource/resource.service.ts
touch lib/services/resource/index.ts
```
### Step 2: 定义类型(types.ts)
```typescript
export interface Resource {
id: number;
name: string;
}
export interface CreateResourceRequest {
name: string;
}
```
### Step 3: 实现服务(resource.service.ts)
```typescript
import { BaseService } from '../core/base.service';
import type { Resource, CreateResourceRequest } from './types';
export class ResourceService extends BaseService {
protected static readonly basePath = '/api/v1/resources';
static async list(): Promise {
return this.get('/');
}
static async create(request: CreateResourceRequest): Promise {
return this.post('/', request);
}
}
```
### Step 4: 导出模块(index.ts)
```typescript
/**
* 资源服务模块
*
* @description
* 提供资源管理相关的功能,包括:
* - 资源列表查询
* - 资源创建
*/
export { ResourceService } from './resource.service';
export type * from './types';
```
### Step 5: 注册到统一入口(services/index.ts)
```typescript
import { ResourceService } from './resource';
const services = {
// ... existing services
resource: ResourceService, // 新增
};
export default services;
export { ResourceService } from './resource';
export type * from './resource';
```
---
## 使用示例
```typescript
import services from '@/lib/services';
// 调用服务
const user = await services.auth.getUserInfo();
const transactions = await services.transaction.getTransactions({
page: 1,
page_size: 20
});
// 错误处理
import { UnauthorizedError, ValidationError } from '@/lib/services';
try {
await services.merchant.createAPIKey(request);
} catch (error) {
if (error instanceof UnauthorizedError) {
router.push('/login');
} else if (error instanceof ValidationError) {
toast.error(error.message);
}
}
```
---
## 注意事项
### 禁止事项
- ❌ 使用 `any` 类型
- ❌ 直接使用 `apiClient`(除非在 `BaseService` 内部)
- ❌ 绕过 BaseService 实现 HTTP 请求
- ❌ 在业务组件中直接导入 axios
### 必须遵循
- ✅ 所有服务继承 `BaseService`
- ✅ 使用 `protected static readonly basePath`
- ✅ 方法必须有完整的 JSDoc 注释
- ✅ 类型定义必须在 `types.ts` 中
- ✅ 通过 `services` 对象调用服务
---
## 相关文档
- [TypeScript 官方文档](https://www.typescriptlang.org/)
- [Axios 文档](https://axios-http.com/)
- [JSDoc 规范](https://jsdoc.app/)