37 KiB
聚玩 (Juwan) API 设计文档
1. 文档概述
本文档为“聚玩”游戏陪玩平台的后端 API 设计规范,旨在指导后端开发人员实现真实的 API 接口,以替换当前纯前端的 Mock 系统。
- 基础路径 (Base URL):
/api/v1 - 数据格式:
application/json
2. 全局约定
2.1 认证与授权 (Auth)
- 采用 Cookie
JToken进行认证(Phase 2 接入后端时实现)。 - Phase 1 阶段仅为纯前端 Mock,不涉及真实后端交互。
- 接口权限标识:
- 🔒:需要登录认证。
- 🛡️:需要管理员权限。
2.2 错误响应格式
所有失败的请求均返回统一的 JSON 结构,并附带 HTTP 状态码(如 400, 401, 403, 404, 500)。
{
"code": 401,
"msg": "请先登录"
}
常见错误码 (code):
401: 未登录或 Token 失效403: 角色权限不足或非参与者404: 资源不存在400: 参数校验失败、状态不合法、重复请求等500: 服务器内部错误
2.3 分页规范
采用 offset 和 limit 进行分页(与前端 SearchResponse 保持一致)。
请求参数:?offset=0&limit=20
响应格式:
{
"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 或文件 ID。
- 访问端点:
GET /api/v1/files/:fileId(获取文件内容)
2.5 时间戳格式
所有时间字段均采用 ISO 8601 格式的 UTC 时间字符串,例如:2024-03-20T12:00:00.000Z。
2.6 角色系统 (UserRole)
consumer: 普通消费者(老板)player: 陪玩打手owner: 店铺店长admin: 平台管理员(隐藏角色,用于后台管理)
2.7 ID 规范
所有 ID 均由后端使用 Snowflake 算法生成,类型为 int64。在前端交互和 JSON 序列化时,统一作为 string 处理,以避免精度丢失。
3. 数据模型
3.1 User (用户)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 用户唯一标识 |
| username | string | 登录用户名 |
| string | 邮箱地址 (可选) | |
| nickname | string | 昵称 |
| avatar | string | 头像 URL |
| role | UserRole | 当前激活的角色 |
| verifiedRoles | UserRole[] | 已认证的角色列表 |
| verificationStatus | object | 各角色的认证状态 (pending, approved, rejected) |
| 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 |
用户注册 (username + email + password + vcode) | |
| POST | /auth/login |
用户登录 (username + password) | |
| POST | /auth/logout |
🔒 | 退出登录,清除 Cookie |
| POST | /auth/forgot-password/send |
忘记密码(发送验证码到邮箱) | |
| POST | /auth/reset-password |
重置密码 (email + vcode + newPassword) | |
| POST | /email/verification-code/send |
发送邮箱验证码 | |
| 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 |
🔒 | 取消关注用户 |
请求示例:登录
// POST /api/v1/auth/login
{
"username": "zhangsan",
"password": "..."
}
响应示例:登录成功
{
"user": {
"id": "u1",
"username": "zhangsan",
"email": "zhangsan@example.com",
"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"
}
}
请求示例:提交认证材料
// 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"
}
}
请求示例:切换角色
// POST /api/v1/users/me/switch-role
{ "role": "player" }
请求示例:更新通知偏好
// 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 | 🔒 | 拒绝店铺邀请 (打手调用) |
请求示例:更新店铺规则
// PUT /api/v1/shops/:id
{
"name": "星耀电竞工作室",
"description": "专业英雄联盟代练工作室",
"commissionType": "percentage",
"commissionValue": 15,
"allowMultiShop": false,
"allowIndependentOrders": true,
"dispatchMode": "auto"
}
请求示例:更新店铺模板
// 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 }
]
}
响应示例:店铺收入统计
// 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 参数自动过滤,不允许查看他人订单。 |
请求示例:创建并支付订单 (快捷下单)
// POST /api/v1/orders/paid
{
"playerId": "p1",
"shopId": "shop1",
"serviceId": "svc1",
"quantity": 3,
"note": "希望晚上8点后开始"
}
响应示例:订单创建成功
{
"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"
}
}
请求示例:再来一单
// 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: 发起申诉,转交平台管理员 请求示例:发起争议
// POST /api/v1/orders/:id/dispute
{
"reason": "打手未按约定时间上线",
"evidence": [
"https://cdn.juwan.com/uploads/evidence1.jpg",
"https://cdn.juwan.com/uploads/evidence2.jpg"
]
}
请求示例:被诉方回应
// POST /api/v1/disputes/:id/response
{
"reason": "当时网络故障,已与客户沟通并补时",
"evidence": ["https://cdn.juwan.com/uploads/response1.jpg"]
}
请求示例:申诉
// 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。 |
|||
| 请求示例:发布秀单帖 |
// 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 |
🔒 | 检查是否已收藏指定目标 |
| 请求示例:添加收藏 |
// 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| | 首页推荐信息流 (混合打手与店铺卡片) | 响应示例:搜索结果
{
"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. 安全与校验清单
- 数据隔离 (Data Isolation):
- 用户只能查询自己的订单、钱包流水、私聊会话。
- 店长只能查询本店铺的订单和员工数据。
- 并发控制 (Concurrency Control):
- 订单状态流转必须使用乐观锁或数据库事务,防止并发导致状态机错乱。
- 钱包扣款必须保证原子性,防止超扣。
- 权限校验 (Authorization):
- 严格校验
Actor的role。例如,只有player才能创建服务,只有owner才能修改店铺规则。 - 订单操作必须校验操作者是否为该订单的
consumerId、playerId或关联的shopId的店长。
- 严格校验
- 幂等性 (Idempotency):
- 支付、接单、结算等核心操作必须保证幂等性,重复请求返回
IDEMPOTENT_NOOP。
- 支付、接单、结算等核心操作必须保证幂等性,重复请求返回