Add two API design documents: 接口文档_TypeA.md (comprehensive v1 API spec) and 接口文档_TypeB.md (Juwan API design).
27 KiB
聚玩 后端 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,最大 100offset:默认 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_LIMITED(429)INTERNAL_ERROR(500)
2. 核心数据模型(摘要)
以下为接口层建议使用的字段集合。为了匹配真实落地场景,对演示模型做了两处补充:
- 订单补充
quantity,用于表达服务数量(演示前端已有数量输入) - 服务
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-Type:
multipart/form-data
表单字段:
file:文件二进制purpose:avatar | 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=pendingPOST /v1/admin/verifications/{verificationId}/approvePOST /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
查询参数(可选):
shopIdgameId或gameNamestatus:available | 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
查询参数(可选):
gameId或gameNamedispatchMode:manual | 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
查询参数(可选):
playerIdshopIdgameId
响应:分页 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}/employeesDELETE /v1/shops/{shopId}/employees/{playerId}
移除建议约束:
- 存在进行中订单时,服务端可拒绝移除并返回
INVALID_STATUS或VALIDATION_FAILED - 移除行为建议记录审计字段(操作者、原因、时间)
服务端校验建议:
allowMultiShop=false时,禁止玩家同时存在多个有效 shop 归属allowIndependentOrders=false时,玩家只能接本店订单(见 7.6)
7. 订单
7.1 订单列表
GET /v1/orders
查询参数(可选):
status(可重复):例如status=pending_accept&status=in_progressasRole:consumer | 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_payment→pending_accept→in_progress→pending_close→pending_review→completed- 取消:
pending_payment | pending_accept→cancelled - 争议:
in_progress | pending_close→disputed→(店主/平台处理)→pending_review
动作与允许迁移:
PAY:pending_payment→pending_acceptACCEPT:pending_accept→in_progressREQUEST_CLOSE:in_progress→pending_closeCONFIRM_CLOSE:pending_close→pending_review(或超时自动进入)CANCEL_PRE_ACCEPT:pending_payment | pending_accept→cancelled(已扣款场景需退款)OPEN_DISPUTE:in_progress | pending_close→disputedRESOLVE_DISPUTE:disputed→pending_reviewSUBMIT_REVIEW:pending_review→completed(双方评价均提交后揭晓)
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
查询参数(可选):
authorIdtag(可重复)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 | systemunreadOnly=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 | refundshopId:按店铺过滤(店主视角)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:最低评分sort:composite | rating | orders | price_asc | price_desclimit/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 校验收发权限