Files
accounts-manager-web/docs/API文档.md
cloud370 97042e3d7b chore: 更新项目配置和部署脚本
- 更新Claude设置允许pm2命令执行
- 修改package.json脚本配置,统一生产环境端口13007
- 添加pm2.sh部署脚本
- 更新API文档移除认证相关内容

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 05:38:10 +08:00

994 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 账户管理系统 API 文档
## 概述
本文档描述了账户管理系统的API接口用于Web前端对接。系统提供了账户的获取、上传、更新、删除和统计等功能。
### 基础信息
- **基础URL**: `{API_BASE_URL}`
- **数据格式**: JSON
- **字符编码**: UTF-8
### 通用响应格式
所有API接口都使用统一的响应格式
```typescript
interface ApiResponse<T> {
code: BusinessCode; // 业务状态码
message: string; // 响应消息
data: T | null; // 响应数据
}
```
#### 业务状态码 (BusinessCode)
| 状态码 | 名称 | 说明 |
|--------|------|------|
| 0 | Success | 请求成功 |
| 1001 | NoResource | 资源不存在 |
| 2001 | InvalidParams | 参数无效 |
| 3001 | ResourceConflict | 资源冲突 |
| 4001 | PermissionDenied | 权限不足 |
| 5001 | BusinessError | 业务错误 |
## 数据模型
### 账户 (Account)
账户是系统的核心数据模型,包含以下字段:
```typescript
interface Account {
id: number; // 账户ID自增主键
ownerId: string; // 所有者ID
platform: string; // 平台名称
customId: string; // 自定义ID
data: string; // 账户数据JSON格式字符串
status: string; // 账户状态
notes?: string; // 备注,可选
lockedAt?: Date; // 锁定时间,可选
createdAt: Date; // 创建时间
updatedAt: Date; // 更新时间
}
```
#### 账户状态
- `available`: 可用
- `locked`: 已锁定
- 其他自定义状态
### 分页结果 (PaginationResult)
```typescript
interface PaginationResult {
page: number; // 当前页码
pageSize: number; // 每页条数
total: number; // 总记录数
totalPages: number; // 总页数
}
```
### 统计概览 (StatsOverview)
```typescript
interface StatsOverview {
totalAccounts: number; // 总账户数
platformSummary: Record<string, number>; // 平台统计
ownerSummary: Record<string, number>; // 所有者统计
statusSummary: Record<string, number>; // 状态统计
detailedBreakdown: { // 详细统计
platform: string;
ownerId: string;
status: string;
count: number;
}[];
}
```
## API 接口
### 1. 账户获取接口
用于脚本端获取可用账户。
#### 请求
```http
GET /s/v1/{ownerId}/acquire?platform={platform}&count={count}
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| ownerId | 路径 | string | 是 | 所有者ID |
| platform | 查询 | string | 是 | 平台名称 |
| count | 查询 | number | 否 | 获取数量默认1最大100 |
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Successfully acquired 1 account.",
"data": [
{
"id": 1,
"customId": "custom123",
"data": "{\"username\":\"test\",\"password\":\"123456\"}"
}
]
}
```
无可用账户响应:
```json
{
"code": 1001,
"message": "No available accounts found for platform 'example'.",
"data": null
}
```
#### 示例
```javascript
// 使用fetch获取账户
async function acquireAccounts(ownerId, platform, count = 1) {
const response = await fetch(`/s/v1/${ownerId}/acquire?platform=${platform}&count=${count}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
return result;
}
// 调用示例
const result = await acquireAccounts('owner123', 'example', 2);
if (result.code === 0) {
console.log('获取成功:', result.data);
} else {
console.error('获取失败:', result.message);
}
```
### 2. 账户状态更新接口
用于脚本端更新账户状态。
#### 请求
```http
GET /s/v1/{ownerId}/update/{accountId}/{newStatus}?notes={notes}
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| ownerId | 路径 | string | 是 | 所有者ID |
| accountId | 路径 | number | 是 | 账户ID |
| newStatus | 路径 | string | 是 | 新状态 |
| notes | 查询 | string | 否 | 备注 |
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Account status updated to 'used'.",
"data": {
"updatedId": 1
}
}
```
权限不足响应:
```json
{
"code": 4001,
"message": "Account not found or permission denied.",
"data": null
}
```
#### 示例
```javascript
// 使用fetch更新账户状态
async function updateAccountStatus(ownerId, accountId, newStatus, notes) {
const url = `/s/v1/${ownerId}/update/${accountId}/${newStatus}`;
if (notes) {
url += `?notes=${encodeURIComponent(notes)}`;
}
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
return result;
}
// 调用示例
const result = await updateAccountStatus('owner123', 1, 'used', '测试使用');
if (result.code === 0) {
console.log('更新成功:', result.data);
} else {
console.error('更新失败:', result.message);
}
```
### 3. 账户上传接口
用于脚本端批量上传账户。
#### 请求
```http
POST /s/v1/{ownerId}/upload
```
#### 请求体
```json
[
{
"platform": "string",
"customId": "string",
"data": "string",
"status": "string"
}
]
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| ownerId | 路径 | string | 是 | 所有者ID |
| body | 请求体 | ScriptUploadItem[] | 是 | 账户数据数组 |
#### ScriptUploadItem 类型
```typescript
interface ScriptUploadItem {
platform: string; // 平台名称
customId: string; // 自定义ID
data: string; // 账户数据JSON格式字符串
status?: string; // 账户状态,可选,默认为"available"
}
```
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Successfully processed 2 accounts (1 created, 1 updated).",
"data": {
"processedCount": 2,
"createdCount": 1,
"updatedCount": 1
}
}
```
#### 示例
```javascript
// 使用fetch上传账户
async function uploadAccounts(ownerId, accounts) {
const response = await fetch(`/s/v1/${ownerId}/upload`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(accounts)
});
const result = await response.json();
return result;
}
// 调用示例
const accounts = [
{
platform: 'example',
customId: 'user123',
data: JSON.stringify({ username: 'user123', password: 'pass123' }),
status: 'available'
},
{
platform: 'example',
customId: 'user456',
data: JSON.stringify({ username: 'user456', password: 'pass456' })
}
];
const result = await uploadAccounts('owner123', accounts);
if (result.code === 0) {
console.log('上传成功:', result.data);
} else {
console.error('上传失败:', result.message);
}
```
### 4. 账户列表接口
用于Web端获取账户列表支持筛选、分页和排序。
#### 请求
```http
POST /web/v1/accounts/list
```
#### 请求体
```json
{
"filters": {
"platform": "string",
"status": ["string"],
"ownerId": "string",
"search": "string"
},
"pagination": {
"page": 1,
"pageSize": 10
},
"sort": {
"field": "id",
"order": "desc"
}
}
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| filters | 请求体 | ListAccountsFilters | 否 | 筛选条件 |
| pagination | 请求体 | object | 是 | 分页参数 |
| sort | 请求体 | object | 是 | 排序参数 |
#### ListAccountsFilters 类型
```typescript
interface ListAccountsFilters {
platform?: string; // 平台名称筛选
status?: string[]; // 状态筛选,多选
ownerId?: string; // 所有者ID筛选
search?: string; // 搜索关键词搜索customId和notes
}
```
#### 排序字段
支持以下字段排序:
- `id`: 账户ID
- `ownerId`: 所有者ID
- `platform`: 平台名称
- `customId`: 自定义ID
- `data`: 账户数据
- `status`: 账户状态
- `notes`: 备注
- `lockedAt`: 锁定时间
- `createdAt`: 创建时间
- `updatedAt`: 更新时间
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Success",
"data": {
"list": [
{
"id": 1,
"ownerId": "owner123",
"platform": "example",
"customId": "user123",
"data": "{\"username\":\"user123\",\"password\":\"pass123\"}",
"status": "available",
"notes": "测试账户",
"lockedAt": null,
"createdAt": "2023-01-01T00:00:00.000Z",
"updatedAt": "2023-01-01T00:00:00.000Z"
}
],
"pagination": {
"page": 1,
"pageSize": 10,
"total": 1,
"totalPages": 1
}
}
}
```
#### 示例
```javascript
// 使用fetch获取账户列表
async function getAccountsList(filters, pagination, sort) {
const response = await fetch('/web/v1/accounts/list', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
filters,
pagination,
sort
})
});
const result = await response.json();
return result;
}
// 调用示例
const filters = {
platform: 'example',
status: ['available'],
search: 'test'
};
const pagination = {
page: 1,
pageSize: 10
};
const sort = {
field: 'createdAt',
order: 'desc'
};
const result = await getAccountsList(filters, pagination, sort);
if (result.code === 0) {
console.log('账户列表:', result.data.list);
console.log('分页信息:', result.data.pagination);
} else {
console.error('获取失败:', result.message);
}
```
### 5. 批量删除账户接口
用于Web端批量删除账户。
#### 请求
```http
POST /web/v1/accounts/delete-batch
```
#### 请求体
```json
{
"ids": [1, 2, 3]
}
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| ids | 请求体 | number[] | 是 | 要删除的账户ID数组 |
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Successfully deleted 3 accounts.",
"data": {
"deletedCount": 3
}
}
```
#### 示例
```javascript
// 使用fetch批量删除账户
async function batchDeleteAccounts(ids) {
const response = await fetch('/web/v1/accounts/delete-batch', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ ids })
});
const result = await response.json();
return result;
}
// 调用示例
const result = await batchDeleteAccounts([1, 2, 3]);
if (result.code === 0) {
console.log('删除成功:', result.data);
} else {
console.error('删除失败:', result.message);
}
```
### 6. 批量更新账户接口
用于Web端批量更新账户。
#### 请求
```http
POST /web/v1/accounts/update-batch
```
#### 请求体
```json
{
"ids": [1, 2, 3],
"payload": {
"status": "available",
"ownerId": "newOwner",
"notes": "批量更新备注"
}
}
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| ids | 请求体 | number[] | 是 | 要更新的账户ID数组 |
| payload | 请求体 | object | 是 | 更新数据 |
#### payload 类型
```typescript
interface UpdatePayload {
status?: string; // 新状态
ownerId?: string; // 新所有者ID
notes?: string; // 新备注
}
```
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Successfully updated 3 accounts.",
"data": {
"updatedCount": 3
}
}
```
#### 示例
```javascript
// 使用fetch批量更新账户
async function batchUpdateAccounts(ids, payload) {
const response = await fetch('/web/v1/accounts/update-batch', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ ids, payload })
});
const result = await response.json();
return result;
}
// 调用示例
const ids = [1, 2, 3];
const payload = {
status: 'available',
notes: '批量更新为可用状态'
};
const result = await batchUpdateAccounts(ids, payload);
if (result.code === 0) {
console.log('更新成功:', result.data);
} else {
console.error('更新失败:', result.message);
}
```
### 7. 账户导出接口
用于Web端批量导出账户并设置状态为已导出。
#### 请求
```http
POST /web/v1/accounts/export
```
#### 请求体
```json
{
"ids": [1, 2, 3],
"mode": "text"
}
```
#### 参数
| 参数名 | 位置 | 类型 | 必填 | 说明 |
|--------|------|------|------|------|
| ids | 请求体 | number[] | 是 | 要导出的账户ID数组 |
| mode | 请求体 | string | 是 | 导出模式:"text"或"object" |
#### 导出模式说明
- `text`: 文本模式返回的data字段为字符串每行一个账户的data字段内容
- `object`: 对象模式返回的data字段为完整的账户对象数组
#### 响应
文本模式成功响应:
```json
{
"code": 0,
"message": "Successfully exported 3 accounts.",
"data": {
"exportedCount": 3,
"data": "{\"username\":\"user1\",\"password\":\"pass1\"}\n{\"username\":\"user2\",\"password\":\"pass2\"}\n{\"username\":\"user3\",\"password\":\"pass3\"}"
}
}
```
对象模式成功响应:
```json
{
"code": 0,
"message": "Successfully exported 3 accounts.",
"data": {
"exportedCount": 3,
"data": [
{
"id": 1,
"ownerId": "owner123",
"platform": "example",
"customId": "user1",
"data": "{\"username\":\"user1\",\"password\":\"pass1\"}",
"status": "exported",
"notes": "测试账户1",
"lockedAt": null,
"createdAt": "2023-01-01T00:00:00.000Z",
"updatedAt": "2023-01-01T12:00:00.000Z"
},
{
"id": 2,
"ownerId": "owner123",
"platform": "example",
"customId": "user2",
"data": "{\"username\":\"user2\",\"password\":\"pass2\"}",
"status": "exported",
"notes": "测试账户2",
"lockedAt": null,
"createdAt": "2023-01-01T00:00:00.000Z",
"updatedAt": "2023-01-01T12:00:00.000Z"
}
]
}
}
```
#### 示例
```javascript
// 使用fetch导出账户
async function exportAccounts(ids, mode) {
const response = await fetch('/web/v1/accounts/export', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ ids, mode })
});
const result = await response.json();
return result;
}
// 文本模式导出示例
const textResult = await exportAccounts([1, 2, 3], 'text');
if (textResult.code === 0) {
console.log('导出成功:', textResult.data.exportedCount);
console.log('文本数据:', textResult.data.data);
// 可以直接保存为文件或复制到剪贴板
const lines = textResult.data.data.split('\n');
lines.forEach((line, index) => {
console.log(`账户${index + 1}:`, line);
});
} else {
console.error('导出失败:', textResult.message);
}
// 对象模式导出示例
const objectResult = await exportAccounts([1, 2, 3], 'object');
if (objectResult.code === 0) {
console.log('导出成功:', objectResult.data.exportedCount);
const accounts = objectResult.data.data;
accounts.forEach(account => {
console.log(`账户ID: ${account.id}, 状态: ${account.status}`);
console.log(`数据: ${account.data}`);
});
} else {
console.error('导出失败:', objectResult.message);
}
```
### 8. 统计概览接口
用于Web端获取账户统计信息。
#### 请求
```http
GET /web/v1/stats/overview
```
#### 响应
成功响应:
```json
{
"code": 0,
"message": "Success",
"data": {
"totalAccounts": 100,
"platformSummary": {
"example": 50,
"test": 30,
"demo": 20
},
"ownerSummary": {
"owner1": 40,
"owner2": 35,
"owner3": 25
},
"statusSummary": {
"available": 70,
"locked": 20,
"used": 10
},
"detailedBreakdown": [
{
"platform": "example",
"ownerId": "owner1",
"status": "available",
"count": 20
},
{
"platform": "example",
"ownerId": "owner1",
"status": "locked",
"count": 10
}
]
}
}
```
#### 示例
```javascript
// 使用fetch获取统计概览
async function getStatsOverview() {
const response = await fetch('/web/v1/stats/overview', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
return result;
}
// 调用示例
const result = await getStatsOverview();
if (result.code === 0) {
console.log('总账户数:', result.data.totalAccounts);
console.log('平台统计:', result.data.platformSummary);
console.log('所有者统计:', result.data.ownerSummary);
console.log('状态统计:', result.data.statusSummary);
console.log('详细统计:', result.data.detailedBreakdown);
} else {
console.error('获取失败:', result.message);
}
```
## 错误处理
所有API接口在发生错误时都会返回统一的错误响应格式
```json
{
"code": "错误码",
"message": "错误信息",
"data": null
}
```
### 常见错误码
| 错误码 | 说明 | 处理建议 |
|--------|------|----------|
| 1001 | 资源不存在 | 检查请求的资源是否存在 |
| 2001 | 参数无效 | 检查请求参数是否符合要求 |
| 3001 | 资源冲突 | 检查是否有重复数据 |
| 5001 | 业务错误 | 检查业务逻辑是否正确 |
## 最佳实践
1. **错误处理**:前端应该根据返回的`code`值进行相应的错误处理,而不是依赖`message`字段。
2. **分页**在获取列表数据时合理设置分页大小建议不超过100条。
3. **批量操作**:批量操作时,建议限制单次操作的数量,避免服务器压力过大。
4. **数据格式**:账户数据字段`data`存储的是JSON格式字符串前端需要进行相应的序列化和反序列化操作。
## 类型定义
以下是完整的TypeScript类型定义可以直接在前端项目中使用
```typescript
// 业务状态码
enum BusinessCode {
Success = 0,
NoResource = 1001,
InvalidParams = 2001,
ResourceConflict = 3001,
PermissionDenied = 4001,
BusinessError = 5001,
}
// 通用响应格式
interface ApiResponse<T> {
code: BusinessCode;
message: string;
data: T | null;
}
// 账户类型
interface Account {
id: number;
ownerId: string;
platform: string;
customId: string;
data: string;
status: string;
notes?: string;
lockedAt?: Date | null;
createdAt: Date;
updatedAt: Date;
}
// 分页结果
interface PaginationResult {
page: number;
pageSize: number;
total: number;
totalPages: number;
}
// 脚本获取响应
type ScriptAcquireResponse = Pick<Account, 'id' | 'customId' | 'data'>[];
// 脚本上传项
interface ScriptUploadItem {
platform: string;
customId: string;
data: string;
status?: string;
}
// 账户列表筛选条件
interface ListAccountsFilters {
platform?: string;
status?: string[];
ownerId?: string;
search?: string;
}
// 账户列表请求体
interface ListAccountsBody {
filters: ListAccountsFilters;
pagination: {
page: number;
pageSize: number;
};
sort: {
field: keyof Account;
order: 'asc' | 'desc';
};
}
// 账户列表响应
interface ListAccountsResponse {
list: Account[];
pagination: PaginationResult;
}
// 批量删除请求体
interface BatchDeleteBody {
ids: number[];
}
// 批量更新请求体
interface BatchUpdateBody {
ids: number[];
payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes'>>;
}
// 账户导出请求体
interface ExportAccountsBody {
ids: number[];
mode: 'text' | 'object';
}
// 账户导出响应
interface ExportAccountsResponse {
exportedCount: number;
data: string | Account[];
}
// 统计概览
interface StatsOverview {
totalAccounts: number;
platformSummary: Record<string, number>;
ownerSummary: Record<string, number>;
statusSummary: Record<string, number>;
detailedBreakdown: {
platform: string;
ownerId: string;
status: string;
count: number;
}[];
}
```
## 版本历史
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0.0 | 2023-01-01 | 初始版本 |