765 lines
37 KiB
Markdown
765 lines
37 KiB
Markdown
# 聚玩 (Juwan) API 设计文档
|
||
|
||
## 1. 文档概述
|
||
本文档为“聚玩”游戏陪玩平台的后端 API 设计规范,旨在指导后端开发人员实现真实的 API 接口,以替换当前纯前端的 Mock 系统。
|
||
- **基础路径 (Base URL)**: `/api/v1`
|
||
- **数据格式**: `application/json`
|
||
|
||
## 2. 全局约定
|
||
|
||
### 2.1 认证与授权 (Auth)
|
||
- 采用 JWT (JSON Web Token) 进行无状态认证。
|
||
- 客户端在请求头中携带 Token:`Authorization: Bearer <access_token>`。
|
||
- 刷新令牌 (Refresh Token) 存储在 HttpOnly Cookie 中,用于获取新的 Access Token。
|
||
- 接口权限标识:
|
||
- 🔒:需要登录认证。
|
||
- 🛡️:需要管理员权限。
|
||
|
||
### 2.2 错误响应格式
|
||
所有失败的请求均返回统一的 JSON 结构,并附带 HTTP 状态码(如 400, 401, 403, 404, 500)。
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"reasonCode": "AUTH_REQUIRED",
|
||
"message": "请先登录"
|
||
}
|
||
```
|
||
**ReasonCode 枚举值**:
|
||
- `AUTH_REQUIRED`: 未登录或 Token 失效
|
||
- `NOT_FOUND`: 资源不存在
|
||
- `NOT_PARTICIPANT`: 非参与者(无权操作该订单/会话等)
|
||
- `ROLE_FORBIDDEN`: 角色权限不足
|
||
- `INVALID_STATUS`: 状态不合法(如订单状态不允许当前操作)
|
||
- `ALREADY_DONE`: 操作已完成(如已评价)
|
||
- `DISPUTE_LOCKED`: 处于争议状态,操作被锁定
|
||
- `PAYMENT_FAILED`: 支付失败或余额不足
|
||
- `IDEMPOTENT_NOOP`: 幂等操作(重复请求,无副作用)
|
||
- `VALIDATION_FAILED`: 参数校验失败
|
||
- `DUPLICATE_REQUEST`: 重复请求
|
||
|
||
### 2.3 分页规范
|
||
采用 `offset` 和 `limit` 进行分页(与前端 `SearchResponse` 保持一致)。
|
||
**请求参数**:`?offset=0&limit=20`
|
||
**响应格式**:
|
||
```json
|
||
{
|
||
"items": [...],
|
||
"meta": {
|
||
"total": 100,
|
||
"offset": 0,
|
||
"limit": 20
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.4 文件上传
|
||
- **端点**: `POST /api/v1/upload`
|
||
- **Content-Type**: `multipart/form-data`
|
||
- **参数**: `file` (文件), `type` (枚举: `avatar`, `chat`, `post`, `verification`, `dispute`)
|
||
- **响应**: 返回文件的 CDN URL。
|
||
|
||
### 2.5 时间戳格式
|
||
所有时间字段均采用 ISO 8601 格式的 UTC 时间字符串,例如:`2024-03-20T12:00:00.000Z`。
|
||
|
||
### 2.6 角色系统 (UserRole)
|
||
- `consumer`: 普通消费者(老板)
|
||
- `player`: 陪玩打手
|
||
- `owner`: 店铺店长
|
||
- `admin`: 平台管理员(隐藏角色,用于后台管理)
|
||
|
||
---
|
||
|
||
## 3. 数据模型
|
||
|
||
### 3.1 User (用户)
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------------ | ---------- | ---------------------------------------------------- |
|
||
| id | string | 用户唯一标识 |
|
||
| username | string | 登录用户名 |
|
||
| nickname | string | 昵称 |
|
||
| avatar | string | 头像 URL |
|
||
| role | UserRole | 当前激活的角色 |
|
||
| verifiedRoles | UserRole[] | 已认证的角色列表 |
|
||
| verificationStatus | object | 各角色的认证状态 (`pending`, `approved`, `rejected`) |
|
||
| phone | string | 手机号 (可选) |
|
||
| bio | string | 个人简介 (可选) |
|
||
| createdAt | string | 注册时间 |
|
||
|
||
### 3.2 Game (游戏)
|
||
| 字段 | 类型 | 说明 |
|
||
| -------- | ------ | ----------------------------------- |
|
||
| id | string | 游戏 ID |
|
||
| name | string | 游戏名称 |
|
||
| icon | string | 游戏图标 URL |
|
||
| category | string | 分类 (`MOBA`, `FPS`, `动作`, `RPG`) |
|
||
|
||
### 3.3 Player & PlayerService (打手与服务)
|
||
**PlayerService**:
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------ | -------- | --------------------------- |
|
||
| id | string | 服务 ID |
|
||
| playerId | string | 打手 ID |
|
||
| gameId | string | 游戏 ID |
|
||
| gameName | string | 游戏名称 |
|
||
| title | string | 服务标题 |
|
||
| description | string | 服务描述 |
|
||
| price | number | 价格 |
|
||
| unit | string | 计价单位 (`局`, `星`, `次`) |
|
||
| rankRange | string | 段位范围 (可选) |
|
||
| availability | string[] | 可接单时间段 |
|
||
|
||
**Player**:
|
||
| 字段 | 类型 | 说明 |
|
||
| -------------- | --------------- | ------------------------------------- |
|
||
| id | string | 打手 ID |
|
||
| user | User | 关联的用户信息 |
|
||
| rating | number | 综合评分 |
|
||
| totalOrders | number | 总接单数 |
|
||
| completionRate | number | 完单率 (0-1) |
|
||
| status | string | 状态 (`available`, `busy`, `offline`) |
|
||
| games | string[] | 擅长游戏 ID 列表 |
|
||
| services | PlayerService[] | 提供的服务列表 |
|
||
| shopId | string | 所属店铺 ID (可选) |
|
||
| shopName | string | 所属店铺名称 (可选) |
|
||
| tags | string[] | 个人标签 |
|
||
|
||
### 3.4 Shop (店铺)
|
||
| 字段 | 类型 | 说明 |
|
||
| ---------------------- | -------- | -------------------------------- |
|
||
| id | string | 店铺 ID |
|
||
| owner | User | 店长信息 |
|
||
| name | string | 店铺名称 |
|
||
| banner | string | 店铺招牌图 (可选) |
|
||
| description | string | 店铺简介 |
|
||
| rating | number | 综合评分 |
|
||
| totalOrders | number | 总单量 |
|
||
| playerCount | number | 打手数量 |
|
||
| commissionType | string | 抽成方式 (`fixed`, `percentage`) |
|
||
| commissionValue | number | 抽成数值 |
|
||
| allowMultiShop | boolean | 是否允许打手兼职 |
|
||
| allowIndependentOrders | boolean | 是否允许打手私下接单 |
|
||
| dispatchMode | string | 派单模式 (`manual`, `auto`) |
|
||
| announcements | string[] | 店铺公告列表 |
|
||
| templateConfig | object | 店铺主页模板配置 |
|
||
|
||
### 3.5 Order (订单)
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------ | ------------- | ------------------- |
|
||
| id | string | 订单 ID |
|
||
| consumerId | string | 消费者 ID |
|
||
| consumerName | string | 消费者昵称 |
|
||
| playerId | string | 打手 ID |
|
||
| playerName | string | 打手昵称 |
|
||
| shopId | string | 店铺 ID (可选) |
|
||
| shopName | string | 店铺名称 (可选) |
|
||
| service | PlayerService | 购买的服务快照 |
|
||
| status | OrderStatus | 订单状态 |
|
||
| totalPrice | number | 订单总价 |
|
||
| note | string | 备注 (可选) |
|
||
| createdAt | string | 创建时间 |
|
||
| acceptedAt | string | 接单时间 (可选) |
|
||
| closedAt | string | 申请结算时间 (可选) |
|
||
| completedAt | string | 完成时间 (可选) |
|
||
|
||
**OrderStatus 枚举**: `pending_payment`, `pending_accept`, `in_progress`, `pending_close`, `pending_review`, `disputed`, `completed`, `cancelled`
|
||
|
||
### 3.6 Review (评价)
|
||
| 字段 | 类型 | 说明 |
|
||
| -------------- | ------- | -------------------------------------- |
|
||
| id | string | 评价 ID |
|
||
| orderId | string | 关联订单 ID |
|
||
| fromUserId | string | 评价人 ID |
|
||
| fromUserName | string | 评价人昵称 |
|
||
| fromUserAvatar | string | 评价人头像 |
|
||
| toUserId | string | 被评价人 ID |
|
||
| rating | number | 评分 (1-5) |
|
||
| content | string | 评价内容 (可选) |
|
||
| sealed | boolean | 是否处于密封状态(双方未互评前不可见) |
|
||
| createdAt | string | 评价时间 |
|
||
|
||
### 3.7 Dispute & DisputeRecord (争议)
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------------ | -------- | ---------------------------------------------------------- |
|
||
| id | string | 争议 ID |
|
||
| orderId | string | 关联订单 ID |
|
||
| initiatorId | string | 发起人 ID |
|
||
| initiatorName | string | 发起人昵称 |
|
||
| reason | string | 争议原因 |
|
||
| evidence | string[] | 证据图片 URL 列表 |
|
||
| status | string | 状态 (`open`, `reviewing`, `resolved`, `appealed`) |
|
||
| result | string | 仲裁结果 (`full_refund`, `full_payment`, `partial_refund`) |
|
||
| respondentReason | string | 被诉方回应理由 (可选) |
|
||
| respondentEvidence | string[] | 被诉方证据 (可选) |
|
||
| appealReason | string | 申诉理由 (可选) |
|
||
| appealedAt | string | 申诉时间 (可选) |
|
||
| timeline | object[] | 争议处理时间线 |
|
||
| createdAt | string | 创建时间 |
|
||
|
||
### 3.8 ChatSession & ChatMessage (聊天)
|
||
**ChatSession**:
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------- | -------- | ---------------------------------- |
|
||
| id | string | 会话 ID |
|
||
| type | string | 会话类型 (`order`, `consultation`) |
|
||
| orderId | string | 关联订单 ID (仅 order 类型) |
|
||
| participants | object[] | 参与者列表 `{id, name, avatar}` |
|
||
| lastMessage | string | 最后一条消息内容 |
|
||
| lastMessageAt | string | 最后一条消息时间 |
|
||
| unreadCount | number | 未读消息数 |
|
||
| readonly | boolean | 是否只读(如订单完成/咨询超时后) |
|
||
|
||
**ChatMessage**:
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------ | ------ | ------------------------------------ |
|
||
| id | string | 消息 ID |
|
||
| sessionId | string | 会话 ID |
|
||
| senderId | string | 发送者 ID |
|
||
| senderName | string | 发送者昵称 |
|
||
| senderAvatar | string | 发送者头像 |
|
||
| type | string | 消息类型 (`text`, `image`, `system`) |
|
||
| content | string | 消息内容 |
|
||
| createdAt | string | 发送时间 |
|
||
|
||
### 3.9 Post & Comment (社区)
|
||
**Post**:
|
||
| 字段 | 类型 | 说明 |
|
||
| ------------- | -------- | ---------------------- |
|
||
| id | string | 帖子 ID |
|
||
| author | User | 作者信息 |
|
||
| authorRole | UserRole | 作者发帖时的角色 |
|
||
| title | string | 标题 |
|
||
| content | string | 内容 |
|
||
| images | string[] | 图片列表 |
|
||
| tags | string[] | 标签列表 |
|
||
| linkedOrderId | string | 关联的订单 ID (秀单帖) |
|
||
| quotedPostId | string | 引用的帖子 ID (引用帖) |
|
||
| likeCount | number | 点赞数 |
|
||
| commentCount | number | 评论数 |
|
||
| liked | boolean | 当前用户是否已赞 |
|
||
| pinned | boolean | 是否被作者置顶 |
|
||
| createdAt | string | 发布时间 |
|
||
|
||
**Comment**:
|
||
| 字段 | 类型 | 说明 |
|
||
| --------- | ------- | ---------------- |
|
||
| id | string | 评论 ID |
|
||
| postId | string | 关联帖子 ID |
|
||
| author | User | 评论者信息 |
|
||
| content | string | 评论内容 |
|
||
| likeCount | number | 点赞数 |
|
||
| liked | boolean | 当前用户是否已赞 |
|
||
| createdAt | string | 评论时间 |
|
||
|
||
### 3.10 WalletTransaction (钱包流水)
|
||
| 字段 | 类型 | 说明 |
|
||
| ----------- | ------ | ----------------------------------------------------------- |
|
||
| id | string | 流水 ID |
|
||
| type | string | 类型 (`topup`, `payment`, `income`, `withdrawal`, `refund`) |
|
||
| amount | number | 金额 (正数为收入/充值/退款,负数为支出/提现) |
|
||
| description | string | 描述 |
|
||
| orderId | string | 关联订单 ID (可选,用于结构化统计,替代前端正则匹配) |
|
||
| createdAt | string | 发生时间 |
|
||
|
||
### 3.11 Favorite (收藏)
|
||
| 字段 | 类型 | 说明 |
|
||
| ---------- | ------ | ------------------------------- |
|
||
| id | string | 收藏 ID |
|
||
| userId | string | 用户 ID |
|
||
| targetType | string | 收藏目标类型 (`player`, `shop`) |
|
||
| targetId | string | 收藏目标 ID |
|
||
| createdAt | string | 收藏时间 |
|
||
|
||
### 3.12 Notification (通知)
|
||
| 字段 | 类型 | 说明 |
|
||
| --------- | ------- | ----------------------------------------- |
|
||
| id | string | 通知 ID |
|
||
| type | string | 通知类型 (`order`, `community`, `system`) |
|
||
| title | string | 通知标题 |
|
||
| content | string | 通知内容 |
|
||
| read | boolean | 是否已读 |
|
||
| link | string | 关联跳转链接 (可选) |
|
||
| createdAt | string | 通知时间 |
|
||
---
|
||
|
||
## 4. 认证与用户
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ------ | ------------------------------------- | ---- | --------------------------------- |
|
||
| POST | `/auth/register` | | 用户注册 |
|
||
| POST | `/auth/login` | | 用户登录,返回 JWT |
|
||
| POST | `/auth/logout` | 🔒 | 退出登录,清除 Cookie |
|
||
| POST | `/auth/refresh` | | 刷新 Token |
|
||
| POST | `/auth/forgot-password` | | 忘记密码(发送验证码) |
|
||
| POST | `/auth/reset-password` | | 重置密码 |
|
||
| GET | `/users/me` | 🔒 | 获取当前登录用户信息 |
|
||
| PUT | `/users/me` | 🔒 | 更新个人资料 (昵称, 头像, 简介等) |
|
||
| POST | `/users/me/switch-role` | 🔒 | 切换当前激活角色 |
|
||
| POST | `/users/me/verification` | 🔒 | 提交角色认证材料 |
|
||
| GET | `/users/me/verification` | 🔒 | 获取认证状态 |
|
||
| PUT | `/users/me/preferences/notifications` | 🔒 | 更新通知偏好设置 |
|
||
| PUT | `/users/me/preferences/theme` | 🔒 | 更新主题偏好设置 |
|
||
| GET | `/users/:id` | | 获取指定用户信息 |
|
||
| POST | `/users/:id/follow` | 🔒 | 关注用户 |
|
||
| DELETE | `/users/:id/follow` | 🔒 | 取消关注用户 |
|
||
|
||
**请求示例:登录**
|
||
```json
|
||
// POST /api/v1/auth/login
|
||
{
|
||
"phone": "13800138000",
|
||
"password": "...",
|
||
"remember": true
|
||
}
|
||
```
|
||
**响应示例:登录成功**
|
||
```json
|
||
{
|
||
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
|
||
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2g...",
|
||
"user": {
|
||
"id": "u1",
|
||
"username": "zhangsan",
|
||
"nickname": "张三",
|
||
"avatar": "https://cdn.juwan.com/avatars/u1.jpg",
|
||
"role": "consumer",
|
||
"verifiedRoles": ["consumer", "player"],
|
||
"verificationStatus": { "consumer": "approved", "player": "approved" },
|
||
"createdAt": "2024-01-15T08:00:00.000Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
**请求示例:提交认证材料**
|
||
```json
|
||
// POST /api/v1/users/me/verification
|
||
{
|
||
"role": "player",
|
||
"materials": {
|
||
"idCardFront": "https://cdn.juwan.com/uploads/xxx.jpg",
|
||
"idCardBack": "https://cdn.juwan.com/uploads/yyy.jpg",
|
||
"gameScreenshot": "https://cdn.juwan.com/uploads/zzz.jpg"
|
||
}
|
||
}
|
||
```
|
||
|
||
**请求示例:切换角色**
|
||
```json
|
||
// POST /api/v1/users/me/switch-role
|
||
{ "role": "player" }
|
||
```
|
||
|
||
**请求示例:更新通知偏好**
|
||
```json
|
||
// PUT /api/v1/users/me/preferences/notifications
|
||
{ "order": true, "community": true, "system": false }
|
||
```
|
||
---
|
||
|
||
## 5. 游戏数据
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | ------------ | ---- | ----------------------- |
|
||
| GET | `/games` | | 获取游戏列表 (支持分页) |
|
||
| GET | `/games/:id` | | 获取指定游戏详情 |
|
||
|
||
---
|
||
|
||
## 6. 打手与服务
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ------ | ----------------------- | ---- | ------------------------------------------------- |
|
||
| GET | `/players` | | 获取打手列表 (支持分页、筛选) |
|
||
| GET | `/players/:id` | | 获取打手公开主页详情 |
|
||
| PUT | `/players/me/status` | 🔒 | 更新打手接单状态 (`available`, `busy`, `offline`) |
|
||
| GET | `/services` | | 获取所有服务列表 |
|
||
| GET | `/services/:id` | | 获取服务详情 |
|
||
| GET | `/players/:id/services` | | 获取指定打手的服务列表 |
|
||
| POST | `/services` | 🔒 | 创建服务 (仅 player) |
|
||
| PUT | `/services/:id` | 🔒 | 更新服务 (仅 player) |
|
||
| DELETE | `/services/:id` | 🔒 | 删除服务 (仅 player) |
|
||
|
||
---
|
||
|
||
## 7. 店铺系统
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ------ | ------------------------------- | ---- | --------------------------- |
|
||
| GET | `/shops` | | 获取店铺列表 |
|
||
| GET | `/shops/:id` | | 获取店铺公开主页详情 |
|
||
| GET | `/users/:id/shop` | | 获取指定店长的店铺 |
|
||
| POST | `/shops` | 🔒 | 创建店铺 (仅 owner) |
|
||
| PUT | `/shops/:id` | 🔒 | 更新店铺基础信息及规则 |
|
||
| PUT | `/shops/:id/template` | 🔒 | 更新店铺主页模板配置 |
|
||
| PUT | `/shops/:id/announcements` | 🔒 | 更新店铺公告 |
|
||
| POST | `/shops/:id/invitations` | 🔒 | 邀请打手加入店铺 |
|
||
| POST | `/shops/invitations/:id/accept` | 🔒 | 打手接受店铺邀请 |
|
||
| DELETE | `/shops/:id/players/:playerId` | 🔒 | 将打手移出店铺 |
|
||
| GET | `/shops/:id/income-stats` | 🔒 | 获取店铺收入统计 (仅 owner) |
|
||
|
||
| GET | `/shops/mine` | 🔒 | 获取当前登录店主的店铺详情 |
|
||
| GET | `/shops/:id/players` | | 获取店铺下的打手列表 |
|
||
| POST | `/shops/:id/announcements` | 🔒 | 新增店铺公告 |
|
||
| DELETE | `/shops/:id/announcements/:index` | 🔒 | 删除店铺公告 |
|
||
| DELETE | `/shops/invitations/:id` | 🔒 | 拒绝店铺邀请 (打手调用) |
|
||
|
||
**请求示例:更新店铺规则**
|
||
```json
|
||
// PUT /api/v1/shops/:id
|
||
{
|
||
"name": "星耀电竞工作室",
|
||
"description": "专业英雄联盟代练工作室",
|
||
"commissionType": "percentage",
|
||
"commissionValue": 15,
|
||
"allowMultiShop": false,
|
||
"allowIndependentOrders": true,
|
||
"dispatchMode": "auto"
|
||
}
|
||
```
|
||
**请求示例:更新店铺模板**
|
||
```json
|
||
// PUT /api/v1/shops/:id/template
|
||
{
|
||
"sections": [
|
||
{ "type": "banner", "enabled": true, "order": 0 },
|
||
{ "type": "intro", "enabled": true, "order": 1 },
|
||
{ "type": "services", "enabled": true, "order": 2 },
|
||
{ "type": "players", "enabled": true, "order": 3 },
|
||
{ "type": "announcements", "enabled": false, "order": 4 },
|
||
{ "type": "reviews", "enabled": true, "order": 5 }
|
||
]
|
||
}
|
||
```
|
||
**响应示例:店铺收入统计**
|
||
```json
|
||
// GET /api/v1/shops/:id/income-stats
|
||
{
|
||
"monthlyIncome": 12800.00,
|
||
"pendingSettlement": 3200.00,
|
||
"totalWithdrawn": 54000.00,
|
||
"totalOrders": 156,
|
||
"completedOrders": 142
|
||
}
|
||
```
|
||
---
|
||
|
||
## 8. 订单系统
|
||
|
||
### 8.1 订单状态机 (Order State Machine)
|
||
|
||
| 当前状态 | 触发动作 | 下一状态 | 允许的角色 | 副作用 |
|
||
| ----------------- | ----------------------------- | ---------------- | ---------------- | -------------------------------------------------- |
|
||
| `pending_payment` | `PAY` | `pending_accept` | consumer | CLEAR_TIMEOUT, SCHEDULE_TIMEOUT |
|
||
| `pending_accept` | `ACCEPT` | `in_progress` | player, owner | CLEAR_TIMEOUT, SYNC_CHAT_SESSION |
|
||
| `pending_accept` | `CANCEL_PRE_ACCEPT` | `cancelled` | consumer | CLEAR_TIMEOUT |
|
||
| `pending_accept` | `AUTO_TIMEOUT_PENDING_ACCEPT` | `cancelled` | system | CLEAR_TIMEOUT |
|
||
| `in_progress` | `REQUEST_CLOSE` | `pending_close` | consumer, player | CLEAR_TIMEOUT, SCHEDULE_TIMEOUT, SYNC_CHAT_SESSION |
|
||
| `in_progress` | `OPEN_DISPUTE` | `disputed` | consumer, player | CLEAR_TIMEOUT, SYNC_CHAT_SESSION |
|
||
| `pending_close` | `CONFIRM_CLOSE` | `pending_review` | consumer, player | CLEAR_TIMEOUT, SCHEDULE_TIMEOUT, SYNC_CHAT_SESSION |
|
||
| `pending_close` | `OPEN_DISPUTE` | `disputed` | consumer, player | CLEAR_TIMEOUT, SYNC_CHAT_SESSION |
|
||
| `pending_close` | `AUTO_TIMEOUT_PENDING_CLOSE` | `pending_review` | system | CLEAR_TIMEOUT, SCHEDULE_TIMEOUT, SYNC_CHAT_SESSION |
|
||
| `pending_review` | `SUBMIT_REVIEW` | `completed` | consumer, player | CLEAR_TIMEOUT, PAYOUT_INCOME, SYNC_CHAT_SESSION |
|
||
| `pending_review` | `AUTO_TIMEOUT_PENDING_REVIEW` | `completed` | system | CLEAR_TIMEOUT, PAYOUT_INCOME, SYNC_CHAT_SESSION |
|
||
| `disputed` | `RESOLVE_DISPUTE` | `pending_review` | owner, admin | CLEAR_TIMEOUT, SCHEDULE_TIMEOUT, SYNC_CHAT_SESSION |
|
||
|
||
### 8.2 超时配置 (Timeout Configs)
|
||
后端需实现定时任务(如 Redis 延迟队列)来处理以下超时逻辑:
|
||
- `ORDER_ACCEPT_TIMEOUT_MS`: 待接单超时自动取消(默认 5 分钟)。
|
||
- `ORDER_CLOSE_TIMEOUT_MS`: 申请结算后对方未确认,超时自动进入待评价(默认 24 小时)。
|
||
- `ORDER_REVIEW_TIMEOUT_MS`: 待评价超时自动好评并完成订单(默认 72 小时)。
|
||
|
||
### 8.3 订单接口
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | --------------------------- | ---- | ----------------------------------- |
|
||
| GET | `/orders` | 🔒 | 获取当前用户的订单列表 |
|
||
| GET | `/orders/:id` | 🔒 | 获取订单详情 |
|
||
| POST | `/orders` | 🔒 | 创建订单 (状态: `pending_payment`) |
|
||
| POST | `/orders/paid` | 🔒 | 创建并直接支付订单 (快捷下单) |
|
||
| POST | `/orders/:id/pay` | 🔒 | 支付订单 (`PAY`) |
|
||
| POST | `/orders/:id/accept` | 🔒 | 接单 (`ACCEPT`) |
|
||
| POST | `/orders/:id/request-close` | 🔒 | 申请结算 (`REQUEST_CLOSE`) |
|
||
| POST | `/orders/:id/confirm-close` | 🔒 | 确认结算 (`CONFIRM_CLOSE`) |
|
||
| POST | `/orders/:id/cancel` | 🔒 | 接单前取消 (`CANCEL_PRE_ACCEPT`) |
|
||
| POST | `/orders/:id/reorder` | 🔒 | 再来一单 (基于原订单快速创建新订单) |
|
||
`GET /orders` 支持查询参数:`role` (consumer/player/owner)、`status` (状态过滤)、`offset`、`limit`。后端根据 Token 中的 userId 和 role 参数自动过滤,不允许查看他人订单。
|
||
|
||
**请求示例:创建并支付订单 (快捷下单)**
|
||
```json
|
||
// POST /api/v1/orders/paid
|
||
{
|
||
"playerId": "p1",
|
||
"shopId": "shop1",
|
||
"serviceId": "svc1",
|
||
"quantity": 3,
|
||
"note": "希望晚上8点后开始"
|
||
}
|
||
```
|
||
**响应示例:订单创建成功**
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"order": {
|
||
"id": "ord-20240320-001",
|
||
"consumerId": "u1",
|
||
"consumerName": "张三",
|
||
"playerId": "p1",
|
||
"playerName": "小明",
|
||
"shopId": "shop1",
|
||
"shopName": "星耀电竞",
|
||
"service": { "id": "svc1", "title": "英雄联盟代练", "price": 50, "unit": "局" },
|
||
"status": "pending_accept",
|
||
"totalPrice": 150,
|
||
"createdAt": "2024-03-20T12:00:00.000Z"
|
||
}
|
||
}
|
||
```
|
||
**请求示例:再来一单**
|
||
```json
|
||
// POST /api/v1/orders/:id/reorder
|
||
// 无请求体,后端基于原订单的 playerId、serviceId、shopId 创建新订单
|
||
```
|
||
---
|
||
|
||
## 9. 争议仲裁
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | ------------------------ | ---- | ------------------------- |
|
||
| GET | `/disputes` | 🔒 | 获取当前用户的争议列表 |
|
||
| GET | `/orders/:id/dispute` | 🔒 | 获取指定订单的争议详情 |
|
||
| POST | `/orders/:id/dispute` | 🔒 | 发起争议 (`OPEN_DISPUTE`) |
|
||
| POST | `/disputes/:id/response` | 🔒 | 被诉方提交回应及证据 |
|
||
| POST | `/disputes/:id/appeal` | 🔒 | 对仲裁结果发起申诉 |
|
||
|
||
**争议处理时间线 (Timeline)**:
|
||
- `created`: 争议发起
|
||
- `response`: 被诉方回应
|
||
- `reviewing`: 店长/平台介入审查
|
||
- `resolved`: 给出仲裁结果
|
||
- `appealed`: 发起申诉,转交平台管理员
|
||
**请求示例:发起争议**
|
||
```json
|
||
// POST /api/v1/orders/:id/dispute
|
||
{
|
||
"reason": "打手未按约定时间上线",
|
||
"evidence": [
|
||
"https://cdn.juwan.com/uploads/evidence1.jpg",
|
||
"https://cdn.juwan.com/uploads/evidence2.jpg"
|
||
]
|
||
}
|
||
```
|
||
**请求示例:被诉方回应**
|
||
```json
|
||
// POST /api/v1/disputes/:id/response
|
||
{
|
||
"reason": "当时网络故障,已与客户沟通并补时",
|
||
"evidence": ["https://cdn.juwan.com/uploads/response1.jpg"]
|
||
}
|
||
```
|
||
**请求示例:申诉**
|
||
```json
|
||
// POST /api/v1/disputes/:id/appeal
|
||
{
|
||
"reason": "仲裁结果不合理,请求平台复核"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 10. 评价系统
|
||
|
||
**密封机制 (Sealed Mechanics)**:
|
||
评价提交后默认为 `sealed: true`。只有当双方都完成评价,或者评价超时(`ORDER_REVIEW_TIMEOUT_MS`)后,评价才会解封并公开显示。
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | --------------------- | ---- | ------------------------------------ |
|
||
| POST | `/orders/:id/review` | 🔒 | 提交评价 (`SUBMIT_REVIEW`) |
|
||
| GET | `/reviews` | | 获取公开评价列表 |
|
||
| GET | `/orders/:id/reviews` | 🔒 | 获取指定订单的评价(受密封机制限制) |
|
||
| GET | `/users/:id/reviews` | | 获取指定用户收到的评价 |
|
||
|
||
---
|
||
|
||
## 11. 聊天系统
|
||
|
||
### 11.1 会话类型
|
||
- **`order`**: 订单会话。随订单创建而建立,订单完成后变为只读。
|
||
- **`consultation`**: 咨询会话。用户在下单前与打手沟通。24小时无回复自动关闭。可升级为订单会话。
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | ----------------------------- | ---- | ----------------------------------- |
|
||
| GET | `/chat/sessions` | 🔒 | 获取当前用户的会话列表 |
|
||
| GET | `/chat/sessions/:id` | 🔒 | 获取会话详情 |
|
||
| GET | `/chat/sessions/:id/messages` | 🔒 | 获取会话历史消息 (分页) |
|
||
| POST | `/chat/sessions/order` | 🔒 | 确保订单会话存在 (不存在则创建) |
|
||
| POST | `/chat/sessions/consultation` | 🔒 | 创建咨询会话 |
|
||
| POST | `/chat/sessions/:id/upgrade` | 🔒 | 将咨询会话升级为订单会话 |
|
||
| POST | `/chat/sessions/:id/messages` | 🔒 | 发送消息 (文本/图片) |
|
||
| GET | `/shops/:id/chat-sessions` | 🔒 | 店长查看员工的业务会话 (需员工同意) |
|
||
|
||
---
|
||
|
||
## 12. 社区系统
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ------ | --------------------- | ---- | ------------------------------------- |
|
||
| GET | `/posts` | | 获取帖子列表 (支持分页、标签筛选) |
|
||
| GET | `/posts/:id` | | 获取帖子详情 |
|
||
| POST | `/posts` | 🔒 | 发布帖子 (支持普通帖、秀单帖、引用帖) |
|
||
| POST | `/posts/:id/like` | 🔒 | 点赞帖子 |
|
||
| DELETE | `/posts/:id/like` | 🔒 | 取消点赞帖子 |
|
||
| POST | `/posts/:id/pin` | 🔒 | 作者置顶帖子 (最多 N 条) |
|
||
| DELETE | `/posts/:id/pin` | 🔒 | 取消置顶 |
|
||
| GET | `/posts/:id/comments` | | 获取帖子评论列表 |
|
||
| POST | `/posts/:id/comments` | 🔒 | 发表评论 |
|
||
| POST | `/comments/:id/like` | 🔒 | 点赞评论 |
|
||
| DELETE | `/comments/:id/like` | 🔒 | 取消点赞评论 |
|
||
| GET | `/users/:id/posts` | | 获取指定用户的帖子列表 |
|
||
`GET /posts` 支持查询参数:`tags` (标签过滤)、`gameId` (游戏过滤)、`sortBy` (new/hot)、`offset`、`limit`。
|
||
**请求示例:发布秀单帖**
|
||
```json
|
||
// POST /api/v1/posts
|
||
{
|
||
"title": "超棒的代练体验",
|
||
"content": "从银到铂金,只用了三天!",
|
||
"images": ["https://cdn.juwan.com/uploads/post1.jpg"],
|
||
"tags": ["英雄联盟", "代练"],
|
||
"linkedOrderId": "ord-20240320-001"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 13. 收藏与关注
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ------ | ---------------------------- | ---- | ---------------------------------- |
|
||
| GET | `/favorites` | 🔒 | 获取当前用户的收藏列表 (打手/店铺) |
|
||
| POST | `/favorites` | 🔒 | 添加收藏 |
|
||
| DELETE | `/favorites/:id` | 🔒 | 取消收藏 |
|
||
| GET | `/users/:id/favorites/check` | 🔒 | 检查是否已收藏指定目标 |
|
||
**请求示例:添加收藏**
|
||
```json
|
||
// POST /api/v1/favorites
|
||
{ "targetType": "player", "targetId": "p1" }
|
||
```
|
||
**检查收藏状态**
|
||
```
|
||
GET /api/v1/users/u1/favorites/check?targetType=player&targetId=p1
|
||
→ { "favorited": true }
|
||
```
|
||
|
||
---
|
||
|
||
## 14. 搜索与发现
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | --------- | ---- | ------------ |
|
||
| GET | `/search` | | 统一搜索接口 |
|
||
|
||
**请求参数**:
|
||
- `q`: 搜索关键词
|
||
- `selectedGames`: 游戏 ID 数组
|
||
- `min`, `max`: 价格区间
|
||
- `onlyOnline`: 是否仅看在线 (`true`/`false`)
|
||
- `minRating`: 最低评分
|
||
- `sort`: 排序方式 (`composite`, `rating`, `orders`, `price_asc`, `price_desc`)
|
||
- `offset`, `limit`: 分页参数
|
||
| GET | `/recommendations/home` | | 首页推荐信息流 (混合打手与店铺卡片) |
|
||
**响应示例:搜索结果**
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"type": "player",
|
||
"player": { "id": "p1", "user": {...}, "rating": 4.8, "status": "available", ... },
|
||
"minPrice": 30,
|
||
"unit": "局",
|
||
"rating": 4.8,
|
||
"orders": 256
|
||
},
|
||
{
|
||
"type": "shop",
|
||
"shop": { "id": "shop1", "name": "星耀电竞", ... },
|
||
"minPrice": 25,
|
||
"unit": "局",
|
||
"rating": 4.6,
|
||
"orders": 1024,
|
||
"games": ["英雄联盟", "CS2"],
|
||
"hasAvailable": true
|
||
}
|
||
],
|
||
"meta": { "total": 42, "offset": 0, "limit": 12 }
|
||
}
|
||
```
|
||
---
|
||
|
||
## 15. 钱包与资金
|
||
|
||
### 15.1 收入计算公式 (Income Calculation)
|
||
订单完成后,系统根据店铺规则计算打手实际收入:
|
||
- **无店铺 (独立接单)**: `income = totalPrice`
|
||
- **比例抽成 (percentage)**: `income = totalPrice * (1 - commissionValue / 100)`
|
||
- **固定抽成 (fixed)**: `income = Math.max(0, totalPrice - commissionValue)`
|
||
剩余部分作为店铺收入(若有店铺)。
|
||
|
||
### 15.2 钱包接口
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | ---------------------- | ---- | ------------------------------------- |
|
||
| GET | `/wallet/balance` | 🔒 | 获取当前余额 |
|
||
| GET | `/wallet/transactions` | 🔒 | 获取资金流水 (包含结构化的 `orderId`) |
|
||
| POST | `/wallet/topup` | 🔒 | 充值 |
|
||
| POST | `/wallet/withdraw` | 🔒 | 提现 |
|
||
|
||
---
|
||
|
||
## 16. 通知系统
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | ---------------------------------- | ---- | ------------------ |
|
||
| GET | `/notifications` | 🔒 | 获取通知列表 |
|
||
| PUT | `/notifications/:id/read` | 🔒 | 标记单条通知为已读 |
|
||
| PUT | `/notifications/read-all` | 🔒 | 标记所有通知为已读 |
|
||
| POST | `/notifications/push-subscription` | 🔒 | 订阅 Web Push 推送 |
|
||
|
||
---
|
||
|
||
## 17. 管理后台 (Admin)
|
||
|
||
| 方法 | 路径 | 权限 | 说明 |
|
||
| ---- | ---------------------------------- | ---- | -------------------------- |
|
||
| GET | `/admin/verifications` | 🛡️ | 获取待审核的认证申请 |
|
||
| POST | `/admin/verifications/:id/approve` | 🛡️ | 批准认证申请 |
|
||
| POST | `/admin/verifications/:id/reject` | 🛡️ | 拒绝认证申请 |
|
||
| GET | `/admin/disputes` | 🛡️ | 获取需要平台介入的争议列表 |
|
||
| POST | `/admin/disputes/:id/resolve` | 🛡️ | 平台管理员给出最终仲裁结果 |
|
||
|
||
---
|
||
|
||
## 18. WebSocket 事件
|
||
|
||
客户端连接到 `wss://api.juwan.com/api/v1/ws`,通过 JWT 鉴权。
|
||
|
||
**下发事件类型**:
|
||
- `chat:message`: 收到新聊天消息。
|
||
- `order:status_changed`: 订单状态变更(触发前端重新拉取订单详情)。
|
||
- `notification:new`: 收到新系统通知。
|
||
- `dispute:updated`: 争议状态或时间线更新。
|
||
- `wallet:balance_changed`: 余额变动通知。
|
||
|
||
---
|
||
|
||
## 19. 安全与校验清单
|
||
|
||
1. **数据隔离 (Data Isolation)**:
|
||
- 用户只能查询自己的订单、钱包流水、私聊会话。
|
||
- 店长只能查询本店铺的订单和员工数据。
|
||
2. **并发控制 (Concurrency Control)**:
|
||
- 订单状态流转必须使用乐观锁或数据库事务,防止并发导致状态机错乱。
|
||
- 钱包扣款必须保证原子性,防止超扣。
|
||
3. **权限校验 (Authorization)**:
|
||
- 严格校验 `Actor` 的 `role`。例如,只有 `player` 才能创建服务,只有 `owner` 才能修改店铺规则。
|
||
- 订单操作必须校验操作者是否为该订单的 `consumerId`、`playerId` 或关联的 `shopId` 的店长。
|
||
4. **幂等性 (Idempotency)**:
|
||
- 支付、接单、结算等核心操作必须保证幂等性,重复请求返回 `IDEMPOTENT_NOOP`。
|