Files
juwan-frontend/接口文档_TypeA.md
T
zetaloop 2995cfdb6d docs(api): add TypeA and TypeB API docs
Add two API design documents: 接口文档_TypeA.md (comprehensive v1 API spec) and 接口文档_TypeB.md (Juwan API design).
2026-02-26 05:42:12 +08:00

27 KiB
Raw Blame History

聚玩 后端 API 接口文档(v1 设计)

最后更新:2026-02-25 文档版本:0.1

本文档面向真实后端落地,覆盖当前前端演示项目已使用的接口形态,以及计划内但前端尚未接通的关键能力(认证、上传、通知推送、邀请流程等)。接口以可实现、可演进为目标,尽量与前端现有数据模型保持对齐,同时补足演示阶段缺失的安全边界与数据契约。

1. 通用约定

1.1 Base URL 与版本

  • Base URL{API_BASE}/v1
  • 生产环境建议通过配置注入 {API_BASE},前端不硬编码域名

1.2 数据格式

  • 请求与响应:application/json; charset=utf-8
  • 时间:ISO 8601 字符串(示例:2026-02-25T12:34:56.789Z
  • ID:不限定格式,统一使用 string。示例沿用演示项目风格:ord-1700000000000-1

1.3 鉴权与身份视角

鉴权采用 Bearer Token

Authorization: Bearer <access_token>

多身份视角(consumer/player/owner)用于列表筛选与权限校验。服务端以登录用户的已认证角色为准,客户端可选传递当前视角:

X-Actor-Role: consumer | player | owner

约定:

  • X-Actor-Role 仅用于表达前端当前视角,服务端需要校验该角色是否在用户已认证角色集合中
  • 未提供 X-Actor-Role 时,服务端默认以用户的主角色或 consumer 视角处理

1.4 分页

列表接口统一支持:

  • limit:默认 20,最大 100
  • offset:默认 0

响应统一携带:

{
  "items": [],
  "meta": { "total": 0, "offset": 0, "limit": 20 }
}

1.5 幂等

涉及资金、下单、创建类操作建议支持幂等键:

Idempotency-Key: <uuid>

服务端应以 (userId, Idempotency-Key) 维度去重,返回相同结果。

1.6 错误响应

错误响应使用 HTTP 状态码表达大类,响应体提供机器可读 code 与人类可读 message

{
  "code": "AUTH_REQUIRED",
  "message": "请先登录",
  "requestId": "req_xxx"
}

code 推荐复用前端演示项目中已有的 ReasonCode(便于迁移):

  • AUTH_REQUIRED:未登录或 token 失效(401
  • ROLE_FORBIDDEN:身份不允许(403
  • NOT_PARTICIPANT:非资源参与方(403
  • NOT_FOUND:资源不存在(404
  • INVALID_STATUS:状态机不允许该操作(409
  • ALREADY_DONE:重复提交(409
  • DUPLICATE_REQUEST:幂等冲突或短时间重复请求(409
  • VALIDATION_FAILED:参数校验失败(422
  • PAYMENT_FAILED:支付失败(409/422
  • DISPUTE_LOCKED:争议锁定导致操作受限(409

服务端可扩展:

  • RATE_LIMITED429
  • INTERNAL_ERROR500

2. 核心数据模型(摘要)

以下为接口层建议使用的字段集合。为了匹配真实落地场景,对演示模型做了两处补充:

  1. 订单补充 quantity,用于表达服务数量(演示前端已有数量输入)
  2. 服务 unit 不限制为固定枚举,推荐使用字符串并约束可选值集合

2.1 User

{
  "id": "u1",
  "username": "chen",
  "nickname": "小陈",
  "avatar": "/avatars/u1.png",
  "role": "consumer",
  "verifiedRoles": ["consumer", "player"],
  "verificationStatus": { "player": "approved", "owner": "pending" },
  "phone": "138****0000",
  "bio": "简介",
  "createdAt": "2026-02-25T12:00:00.000Z"
}

2.2 PlayerService

{
  "id": "svc-1",
  "playerId": "u5",
  "gameId": "g1",
  "gameName": "英雄联盟",
  "title": "LOL双排上分",
  "description": "服务描述",
  "price": 25,
  "unit": "局",
  "rankRange": "黄金-铂金",
  "availability": ["工作日晚上9点后", "周末全天"]
}

unit 推荐值:小时(服务端可按业务扩展)。

2.3 Order

{
  "id": "ord-1",
  "consumerId": "u1",
  "consumerName": "小陈",
  "playerId": "u6",
  "playerName": "Winter",
  "shopId": "shop2",
  "shopName": "Yuki 小屋",
  "service": { "id": "s4", "playerId": "u6", "gameId": "g2", "gameName": "王者荣耀", "title": "王者双排稳上星", "description": "...", "price": 18, "unit": "星", "availability": [] },
  "quantity": 3,
  "status": "pending_accept",
  "totalPrice": 54,
  "note": "3星,我用鲁班",
  "createdAt": "2026-02-25T12:00:00.000Z",
  "acceptedAt": null,
  "closedAt": null,
  "completedAt": null
}

status 取值与状态机见 7.5。

2.4 Dispute(详情态)

争议详情建议返回扩展字段,匹配前端现有展示与时间线:

{
  "id": "disp-1",
  "orderId": "ord-1",
  "initiatorId": "u1",
  "initiatorName": "小陈",
  "reason": "争议原因",
  "evidence": ["https://cdn/.../a.png"],
  "respondentReason": "回应理由",
  "respondentEvidence": ["https://cdn/.../b.png"],
  "status": "reviewing",
  "result": null,
  "appealReason": null,
  "appealedAt": null,
  "createdAt": "2026-02-25T12:00:00.000Z",
  "timeline": [
    { "id": "timeline-1", "type": "created", "content": "小陈 提交争议", "createdAt": "2026-02-25T12:00:00.000Z" },
    { "id": "timeline-2", "type": "response", "content": "对方已提交回应材料", "createdAt": "2026-02-25T12:10:00.000Z" }
  ]
}

2.5 Game

{
  "id": "g1",
  "name": "英雄联盟",
  "icon": "lol",
  "category": "MOBA"
}

2.6 Player

{
  "id": "u5",
  "user": { "id": "u5", "username": "jun", "nickname": "俊俊", "avatar": "/avatars/u5.png", "role": "player", "createdAt": "..." },
  "rating": 4.2,
  "totalOrders": 156,
  "completionRate": 0.94,
  "status": "available",
  "games": ["英雄联盟", "王者荣耀"],
  "services": [],
  "shopId": "shop1",
  "shopName": "老王游戏工作室",
  "tags": ["准时上线"]
}

2.7 Shop

{
  "id": "shop1",
  "owner": { "id": "u10", "username": "wang", "nickname": "老王", "avatar": "/avatars/u10.png", "role": "owner", "createdAt": "..." },
  "name": "老王游戏工作室",
  "banner": "/banners/shop1.jpg",
  "description": "店铺简介",
  "rating": 4.7,
  "totalOrders": 3842,
  "playerCount": 14,
  "commissionType": "percentage",
  "commissionValue": 15,
  "allowMultiShop": false,
  "allowIndependentOrders": false,
  "dispatchMode": "manual",
  "announcements": ["公告1"],
  "templateConfig": {
    "sections": [
      { "type": "intro", "enabled": true, "order": 1 },
      { "type": "players", "enabled": true, "order": 2 }
    ]
  }
}

2.8 Review

{
  "id": "rev-1",
  "orderId": "ord-1",
  "fromUserId": "u1",
  "fromUserName": "小陈",
  "fromUserAvatar": "/avatars/u1.png",
  "toUserId": "u6",
  "rating": 5,
  "content": "体验很好",
  "sealed": true,
  "createdAt": "..."
}

2.9 Post

{
  "id": "post-1",
  "author": { "id": "u1", "username": "chen", "nickname": "小陈", "avatar": "/avatars/u1.png", "role": "consumer", "createdAt": "..." },
  "authorRole": "consumer",
  "title": "标题",
  "content": "内容",
  "images": ["https://cdn.../p1.png"],
  "tags": ["英雄联盟", "攻略"],
  "linkedOrderId": "ord-1",
  "quotedPostId": null,
  "likeCount": 10,
  "commentCount": 2,
  "liked": false,
  "pinned": false,
  "createdAt": "..."
}

2.10 Comment

{
  "id": "comment-1",
  "postId": "post-1",
  "author": { "id": "u2", "username": "ling", "nickname": "玲玲", "avatar": "/avatars/u2.png", "role": "consumer", "createdAt": "..." },
  "content": "评论内容",
  "likeCount": 0,
  "liked": false,
  "createdAt": "..."
}

2.11 Notification

{
  "id": "notif-1",
  "type": "order",
  "title": "订单待接单",
  "content": "xxx 已支付,等待接单",
  "read": false,
  "link": "/order/ord-1",
  "createdAt": "..."
}

2.12 Favorite

{
  "id": "fav-1",
  "userId": "u1",
  "targetType": "player",
  "targetId": "u6",
  "createdAt": "..."
}

2.13 WalletTransaction(建议扩展字段)

{
  "id": "tx-1",
  "type": "payment",
  "amount": -54,
  "orderId": "ord-1",
  "shopId": "shop2",
  "description": "支付订单 ord-1",
  "createdAt": "..."
}

2.14 ChatSession

{
  "id": "chat-ord-1",
  "type": "order",
  "orderId": "ord-1",
  "participants": [
    { "id": "u1", "name": "小陈", "avatar": "/avatars/u1.png" },
    { "id": "u6", "name": "Winter", "avatar": "/avatars/u6.png" }
  ],
  "lastMessage": "你好",
  "lastMessageAt": "...",
  "unreadCount": 0,
  "readonly": false
}

2.15 ChatMessage

{
  "id": "msg-1",
  "sessionId": "chat-ord-1",
  "senderId": "u1",
  "senderName": "小陈",
  "senderAvatar": "/avatars/u1.png",
  "type": "text",
  "content": "你好",
  "createdAt": "..."
}

2.16 File(上传结果)

{
  "id": "file-1",
  "url": "https://cdn.example.com/files/file-1.png",
  "contentType": "image/png",
  "size": 123456
}

3. 上传(文件/图片)

演示前端目前大量使用 URL.createObjectURL 或固定占位路径。切真实后端时,建议统一通过上传接口获得可复现的 URL,再写入业务资源(头像、帖子图片、聊天图片、争议证据、认证材料等)。

3.1 上传文件

POST /v1/files

  • Auth:需要
  • Content-Typemultipart/form-data

表单字段:

  • file:文件二进制
  • purposeavatar | post_image | chat_image | dispute_evidence | verification_material

响应:

{
  "id": "file-1",
  "url": "https://cdn.example.com/files/file-1.png",
  "contentType": "image/png",
  "size": 123456
}

约束建议:

  • 图片类限制 MIME 与大小(例如单张 ≤ 5MB)
  • 上传结果 URL 建议为不可枚举地址或带访问控制

4. Auth(登录/注册/会话)

4.1 注册

POST /v1/auth/register

请求:

{
  "username": "chen",
  "password": "******",
  "nickname": "小陈"
}

响应:

{
  "accessToken": "token...",
  "refreshToken": "token...",
  "user": { "id": "u1", "username": "chen", "nickname": "小陈", "avatar": "", "role": "consumer", "createdAt": "..." }
}

4.2 登录

POST /v1/auth/login

请求:

{
  "username": "chen",
  "password": "******",
  "remember": true
}

响应同 4.1。

4.3 刷新 token

POST /v1/auth/refresh

请求:

{ "refreshToken": "token..." }

响应:

{ "accessToken": "token..." }

4.4 获取当前用户

GET /v1/auth/me

响应:User

4.5 退出登录

POST /v1/auth/logout

响应:

{ "ok": true }

4.6 找回密码(计划内)

前端已有找回密码页面的 UI 行为,真实后端建议提供:

  • POST /v1/auth/password/forgot:发送验证码或重置链接
  • POST /v1/auth/password/reset:提交新密码

5. 用户与设置

5.1 获取用户信息

GET /v1/users/{userId}

响应:User

5.2 更新个人资料

PATCH /v1/users/me

请求:

{
  "nickname": "新昵称",
  "bio": "新简介",
  "avatar": "https://cdn.../avatar.png"
}

响应:User

5.3 更新通知偏好与外观偏好

PATCH /v1/users/me/preferences

请求:

{
  "notificationPrefs": { "order": true, "community": true, "system": false },
  "themePreference": "system"
}

响应:

{ "ok": true }

5.4 身份认证(打手/店主)

演示前端的身份认证页面包含真实姓名、身份证号、游戏资质描述与证明材料占位。真实后端建议将认证作为独立资源管理,并避免在任何对外接口返回敏感字段(例如身份证号原文与证件照片的可公开 URL)。

GET /v1/verifications/me

响应示例:

{
  "items": [
    { "id": "ver-1", "role": "player", "status": "pending", "reason": null, "createdAt": "..." }
  ],
  "meta": { "total": 1, "offset": 0, "limit": 20 }
}

POST /v1/verifications

请求示例:

{
  "role": "player",
  "realName": "张三",
  "idNumber": "110***********1234",
  "qualificationText": "段位、经历等",
  "materialFileIds": ["file-1", "file-2", "file-3"]
}

响应:

{
  "id": "ver-1",
  "role": "player",
  "status": "pending",
  "createdAt": "..."
}

审核(平台后台,计划内):

  • GET /v1/admin/verifications?status=pending
  • POST /v1/admin/verifications/{verificationId}/approve
  • POST /v1/admin/verifications/{verificationId}/reject(携带 reason

6. 店铺、打手、服务

6.1 游戏列表

GET /v1/games

响应:

{
  "items": [{ "id": "g1", "name": "英雄联盟", "icon": "lol", "category": "MOBA" }],
  "meta": { "total": 1, "offset": 0, "limit": 20 }
}

6.2 打手列表 / 详情

GET /v1/players

查询参数(可选):

  • shopId
  • gameIdgameName
  • statusavailable | busy | offline

响应:分页 items: Player[]

GET /v1/players/{playerId}

响应:Player(可选包含 services 简要信息,或通过 6.4 获取)

6.2.1 更新打手状态(计划内)

PATCH /v1/players/me/status

  • Auth:需要
  • 允许角色:player

请求:

{ "status": "available" }

响应:

{ "ok": true }

6.3 店铺列表 / 详情

GET /v1/shops

查询参数(可选):

  • gameIdgameName
  • dispatchModemanual | auto

响应:分页 items: Shop[]

GET /v1/shops/{shopId}

响应:Shop

6.3.1 创建店铺(计划内)

POST /v1/shops

  • Auth:需要
  • 允许角色:owner

请求:

{
  "name": "我的店铺",
  "description": "店铺简介",
  "banner": "https://cdn.../banner.png"
}

响应:Shop

6.4 服务列表 / 详情

GET /v1/services

查询参数(可选):

  • playerId
  • shopId
  • gameId

响应:分页 items: PlayerService[]

GET /v1/services/{serviceId}

响应:PlayerService

6.5 服务管理(打手/店主)

POST /v1/services

  • Auth:需要
  • 允许角色:player(创建自己的服务),owner(为自己店铺的员工创建服务)

请求:

{
  "playerId": "u6",
  "gameId": "g2",
  "title": "王者双排稳上星",
  "description": "描述",
  "price": 18,
  "unit": "星",
  "rankRange": "钻石-星耀",
  "availability": ["每天下午3点到凌晨"]
}

响应:PlayerService

PATCH /v1/services/{serviceId}:更新服务
DELETE /v1/services/{serviceId}:删除服务

6.6 店铺管理(店主)

GET /v1/shops/me

  • Auth:需要
  • 允许角色:owner

响应:Shop

PATCH /v1/shops/{shopId}

用于店铺规则、抽成、派单模式、公告等更新。建议服务端按字段做权限与范围校验。

请求示例(规则设置页):

{
  "allowMultiShop": true,
  "allowIndependentOrders": true,
  "dispatchMode": "auto",
  "commissionType": "percentage",
  "commissionValue": 12
}

请求示例(模板编辑页):

{
  "templateConfig": {
    "sections": [
      { "type": "intro", "enabled": true, "order": 1 },
      { "type": "players", "enabled": true, "order": 2 }
    ]
  }
}

请求示例(公告编辑):

{
  "announcements": ["公告1", "公告2"]
}

响应:Shop

6.7 员工邀请与店铺归属(计划内,替代直接改字段)

演示前端当前通过直接修改 player.shopId/shopName 模拟邀请,真实后端建议改为显式的邀请与同意流。

POST /v1/shops/{shopId}/employee-invitations

请求:

{ "playerId": "u7", "message": "欢迎加入" }

响应:

{
  "id": "inv-1",
  "shopId": "shop1",
  "playerId": "u7",
  "status": "pending",
  "createdAt": "..."
}

GET /v1/employee-invitations/me:当前用户收到的邀请
POST /v1/employee-invitations/{invitationId}/accept:接受邀请
POST /v1/employee-invitations/{invitationId}/reject:拒绝邀请

店铺员工列表与移除(店主):

  • GET /v1/shops/{shopId}/employees
  • DELETE /v1/shops/{shopId}/employees/{playerId}

移除建议约束:

  • 存在进行中订单时,服务端可拒绝移除并返回 INVALID_STATUSVALIDATION_FAILED
  • 移除行为建议记录审计字段(操作者、原因、时间)

服务端校验建议:

  • allowMultiShop=false 时,禁止玩家同时存在多个有效 shop 归属
  • allowIndependentOrders=false 时,玩家只能接本店订单(见 7.6

7. 订单

7.1 订单列表

GET /v1/orders

查询参数(可选):

  • status(可重复):例如 status=pending_accept&status=in_progress
  • asRoleconsumer | player | owner(等价于 X-Actor-Role,二选一)
  • shopId:店主视角下可选

响应:分页 items: Order[]

权限:

  • consumer:仅可见自己下的单
  • player:仅可见自己作为打手的单
  • owner:仅可见自己店铺的单

7.2 订单详情

GET /v1/orders/{orderId}

响应:Order

7.3 下单与支付

POST /v1/orders

  • Auth:需要(consumer 视角)

请求:

{
  "serviceId": "s4",
  "quantity": 3,
  "note": "3星,我用鲁班",
  "payNow": true,
  "paymentMethod": "wallet"
}

响应:Order(创建成功时建议直接返回 pending_accept 状态)

7.4 订单动作(状态机)

以下接口建议返回更新后的 Order。

POST /v1/orders/{orderId}/pay
POST /v1/orders/{orderId}/accept
POST /v1/orders/{orderId}/close/request
POST /v1/orders/{orderId}/close/confirm
POST /v1/orders/{orderId}/cancel

状态约束建议与演示状态机一致(见 7.5)。

7.5 状态机(与前端演示一致)

订单状态:

  • pending_paymentpending_acceptin_progresspending_closepending_reviewcompleted
  • 取消:pending_payment | pending_acceptcancelled
  • 争议:in_progress | pending_closedisputed →(店主/平台处理)→ pending_review

动作与允许迁移:

  • PAYpending_paymentpending_accept
  • ACCEPTpending_acceptin_progress
  • REQUEST_CLOSEin_progresspending_close
  • CONFIRM_CLOSEpending_closepending_review(或超时自动进入)
  • CANCEL_PRE_ACCEPTpending_payment | pending_acceptcancelled(已扣款场景需退款)
  • OPEN_DISPUTEin_progress | pending_closedisputed
  • RESOLVE_DISPUTEdisputedpending_review
  • SUBMIT_REVIEWpending_reviewcompleted(双方评价均提交后揭晓)

7.6 店铺规则在订单侧的执行(计划内)

当玩家已挂靠店铺且 allowIndependentOrders=false 时:

  • 玩家不得接店铺外的独立订单
  • 服务的可见范围建议由服务端控制(例如只暴露店铺内服务)

dispatchMode=auto 时:

  • 接单动作可由服务端自动分配给某位员工,并记录分配原因与时间

8. 评价(密封机制)

8.1 按订单查看评价

GET /v1/orders/{orderId}/reviews

响应:分页 items: Review[]

约束建议:

  • sealed=true 且双方未同时提交时,对非作者隐藏 content(可返回空字符串或省略字段)

8.2 提交评价

POST /v1/orders/{orderId}/reviews

请求:

{ "rating": 5, "content": "体验很好" }

响应:

{ "ok": true }

8.3 按打手查看评价

GET /v1/users/{userId}/reviews

查询参数(可选):

  • targetRole=player

响应:分页 items: Review[]

9. 争议

9.1 发起争议

POST /v1/orders/{orderId}/dispute

请求:

{
  "reason": "争议原因",
  "evidence": ["https://cdn.../a.png"]
}

响应:Dispute(详情态)

9.2 获取争议详情

GET /v1/orders/{orderId}/dispute

响应:Dispute(详情态)

9.3 提交回应材料

POST /v1/disputes/{disputeId}/response

请求:

{
  "reason": "回应理由",
  "evidence": ["https://cdn.../b.png"]
}

响应:

{ "ok": true }

9.4 提交申诉

POST /v1/disputes/{disputeId}/appeal

请求:

{ "reason": "申诉理由" }

响应:

{ "ok": true }

9.5 仲裁(店主/平台)

演示前端用定时器自动推进争议状态。真实后端建议提供显式仲裁接口,并落审计字段。

POST /v1/disputes/{disputeId}/resolve

请求:

{
  "result": "partial_refund",
  "refundAmount": 10,
  "note": "处理说明"
}

响应:Dispute(详情态)

9.6 争议列表(店主/平台)

GET /v1/disputes

查询参数(可选):

  • status=open | reviewing | resolved | appealed

响应:分页 items: Dispute(详情态或摘要态)[]

10. 社区(帖子/评论/点赞/置顶)

10.1 帖子列表

GET /v1/posts

查询参数(可选):

  • authorId
  • tag(可重复)
  • sort=latest | hot

响应:分页 items: Post[]

10.2 帖子详情

GET /v1/posts/{postId}

响应:Post

10.3 发帖

POST /v1/posts

请求:

{
  "title": "标题",
  "content": "内容",
  "images": ["https://cdn.../p1.png"],
  "tags": ["英雄联盟", "攻略"],
  "linkedOrderId": "ord-1",
  "quotedPostId": "post-1"
}

约束建议:

  • linkedOrderId 仅允许 consumer 且订单已完成
  • quotedPostId 必须存在,且引用关系不应形成环

响应:Post

10.4 点赞(帖子)

PUT /v1/posts/{postId}/like:点赞(幂等)
DELETE /v1/posts/{postId}/like:取消点赞(幂等)

响应:

{ "ok": true }

10.5 置顶(计划内)

PUT /v1/posts/{postId}/pin:作者置顶(建议限制每人最多 N 条)
DELETE /v1/posts/{postId}/pin:取消置顶

响应:

{ "ok": true }

10.6 评论列表与发表评论

GET /v1/posts/{postId}/comments:分页评论列表

POST /v1/posts/{postId}/comments

请求:

{ "content": "评论内容" }

响应:Comment

10.7 点赞(评论)

PUT /v1/comments/{commentId}/like
DELETE /v1/comments/{commentId}/like

响应:

{ "ok": true }

11. 收藏(关注)

演示前端以 Favorite 表达收藏打手或店铺。后端建议以当前用户为主语管理收藏关系。

11.1 获取我的收藏

GET /v1/favorites/me

查询参数(可选):

  • targetType=player | shop

响应:分页 items: Favorite[]

11.2 收藏与取消收藏

PUT /v1/favorites/{targetType}/{targetId}:收藏(幂等)
DELETE /v1/favorites/{targetType}/{targetId}:取消收藏(幂等)

响应:

{ "ok": true }

11.3 获取某用户的公开收藏(可选)

GET /v1/users/{userId}/favorites

约束建议:

  • 默认仅允许本人读取
  • 若产品需要公开展示,可增加用户侧开关并在此接口执行隐私校验

12. 通知

12.1 通知列表

GET /v1/notifications

查询参数(可选):

  • type=order | community | system
  • unreadOnly=1

响应:分页 items: Notification[]

12.2 标记已读

POST /v1/notifications/{notificationId}/read
POST /v1/notifications/read-all

响应:

{ "ok": true }

12.3 Web Push 订阅(计划内)

POST /v1/push/subscriptions

请求(示例,按 Web Push 标准字段落地):

{
  "endpoint": "https://push.service/...",
  "keys": { "p256dh": "...", "auth": "..." },
  "userAgent": "..."
}

响应:

{ "id": "push-1", "ok": true }

DELETE /v1/push/subscriptions/{subscriptionId}

13. 钱包与交易

13.1 获取钱包信息

GET /v1/wallets/me

响应示例:

{
  "consumerBalance": 275,
  "earningsBalance": 0
}

13.2 交易流水

GET /v1/wallets/me/transactions

查询参数(可选):

  • type=topup | payment | income | withdrawal | refund
  • shopId:按店铺过滤(店主视角)
  • orderId:按订单过滤

响应:分页 items: WalletTransaction[]

建议在 WalletTransaction 中补充结构化字段,替代前端演示中的 description 解析:

{
  "id": "tx-1",
  "type": "payment",
  "amount": -54,
  "orderId": "ord-1",
  "shopId": "shop2",
  "description": "支付订单 ord-1",
  "createdAt": "..."
}

13.3 充值(计划内真实支付)

POST /v1/wallets/me/topups

请求:

{ "amount": 100, "channel": "mock" }

响应:

{ "ok": true, "transactionId": "tx-1" }

13.4 提现

POST /v1/wallets/me/withdrawals

请求:

{ "amount": 320, "destination": { "type": "bank_card", "maskedNo": "****1234" } }

响应:

{ "ok": true, "transactionId": "tx-2" }

14. 搜索

演示项目唯一的 HTTP 链路是 /api/search。真实后端建议提供等价能力,并保留相同查询语义,便于迁移。

GET /v1/search

查询参数:

  • q:关键词
  • game:可重复,游戏名或 id(建议最终统一为 id)
  • min/max:价格区间(字符串或数字均可,推荐数字)
  • online=1:仅在线
  • minRating:最低评分
  • sortcomposite | rating | orders | price_asc | price_desc
  • limit/offset

响应(与前端 SearchResponse 对齐):

{
  "items": [
    {
      "type": "player",
      "player": { "id": "u5", "user": { "id": "u5", "nickname": "俊俊", "avatar": "", "username": "", "role": "player", "createdAt": "..." }, "rating": 4.2, "totalOrders": 156, "completionRate": 0.94, "status": "available", "games": ["英雄联盟"], "services": [], "tags": [] },
      "minPrice": 25,
      "unit": "局",
      "rating": 4.2,
      "orders": 156
    },
    {
      "type": "shop",
      "shop": { "id": "shop1", "owner": { "id": "u10", "nickname": "老王", "avatar": "", "username": "", "role": "owner", "createdAt": "..." }, "name": "老王游戏工作室", "description": "店铺简介", "rating": 4.7, "totalOrders": 3842, "playerCount": 14, "commissionType": "percentage", "commissionValue": 15, "allowMultiShop": false, "allowIndependentOrders": false, "dispatchMode": "manual", "announcements": [], "templateConfig": { "sections": [] } },
      "minPrice": 25,
      "unit": "局",
      "rating": 4.7,
      "orders": 3842,
      "games": ["英雄联盟", "王者荣耀"],
      "hasAvailable": true
    }
  ],
  "meta": { "total": 2, "offset": 0, "limit": 12 }
}

15. 聊天

演示计划提到 WebSocket + 持久化。真实后端建议提供 REST 用于会话与历史消息,WebSocket 用于实时收发。

15.1 会话列表

GET /v1/chat/sessions

响应:分页 items: ChatSession[]

服务端必须按当前用户过滤会话参与者,避免返回无关会话。

15.2 会话消息

GET /v1/chat/sessions/{sessionId}/messages

响应:分页 items: ChatMessage[]

15.3 发送消息(HTTP 兜底)

POST /v1/chat/sessions/{sessionId}/messages

请求:

{ "type": "text", "content": "你好" }

或:

{ "type": "image", "content": "https://cdn.../img.png" }

响应:ChatMessage

15.4 咨询会话(计划内)

POST /v1/chat/sessions

请求:

{ "type": "consultation", "targetUserId": "u5" }

响应:ChatSession

15.5 WebSocket(建议)

GET /v1/ws/chat(升级为 WebSocket

  • 鉴权:在 query 或 headers 里携带 access token
  • 服务端按 sessionId 与 participant 校验收发权限