zizi 063ec4edf2 docs(rename): ③ 文档/契约漂移清理——contracts+docs+根文档 yudao 标识同步 com.wanxiang.huijing(follow-up,脚本)
- 范围:全仓除已完成的 game-cloud/game-admin(及排除区);91 文件
- cn.iocoder.yudao→com.wanxiang.huijing / cn.wanxiang.game→com.wanxiang.huijing.game / cn.iocoder.cloud→com.wanxiang / Yudao*→Huijing* / bare yudao→huijing
- 含 contracts/api-schemas(apiInterface FQCN)、docs/architecture+agent-specs(含中文名,git ls-files -z 修复)、AGENTS.md/CLAUDE.md 等根文档
- 保留不动:上游归属 URL(gitee/github yudaocode·YunaiV,改则断链+违反署名)、game-cloud Flyway 迁移注释(保 checksum)、lockfile(装包重生)
- 纯文档/字符串,零构建影响(game-cloud/game-admin 字节码未动)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 14:32:44 +00:00

275 lines
15 KiB
YAML
Raw 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.

openapi: 3.0.3
# 契约 #1 API | 模块:feed(游戏流/双轨专区浏览/推荐)| owner:WS(feed),全员 review
# 端:/app-api(产品端 game-studio,用户 Token;匿名玩家亦可浏览游戏流)/admin-api(管理端 game-admin,RBAC 精选池运营)
# 前缀由 huijing 框架按 controller.app/admin 包名自动添加;本文件 path 直接写含前缀的完整对外路径
# 错误码段:feed = 1-103-***-***(本模块独占,禁止与他模块重叠)
# 响应统一 Huijing CommonResult 信封:{ code, data, msg };code=0 成功
# 脊柱对接:消费 project 已发布(status=4) + zone(双轨:1官方精选/2UGC普通,game_zone/game_project_zone 已建表);
# 游戏流分页(cursor) + 按 quality_score(telemetry 回灌)降序排序;排序结果可走 game_feed_rank 缓存,否则直接读 project/zone。
# 边界 OUT:不存游戏本体/Zone 实体(读 project)|不算 quality_score(消费 telemetry)|不裁决举报(转 compliance)。
info:
title: 绘境AI feed 模块 API
version: 1.0.0
description: >-
游戏流(竖屏即玩、cursor 分页/去重、quality_score 排序)+ 双轨专区浏览(官方精选/UGC 普通)
+ 互动信号写入(赞/藏/享/举报→权重)+ 分享页/OG 元数据 + 精选池运营。
覆盖产品功能 P-FED-01/02/03/04/05/06/07/08/09/10/11/13、P-PLZ-01/02、P-OPN-03。
前端据此 vite-plugin-mock 自动生成 mock。
servers:
- url: http://localhost:48080
description: 本地(Swagger/Knife4j http://localhost:48080/doc.html)
paths:
# ===========================================================================
# 游戏流(脊柱主路:消费 project status=4 + quality_score 排序 → 竖屏 cursor 流)
# ===========================================================================
/app-api/feed/stream:
get:
tags: [app-feed]
summary: 游戏流(竖屏即玩,cursor 分页,按 quality_score 降序;P-FED-01/02/13)
description: >-
默认混合流:仅取 project status=4 已发布、compliance 未下架的游戏;
排序优先读 game_feed_rank 缓存(Redis TTL 60s 兜底),否则直接按 quality_score 降序 + 新人保底/冷启动兜底。
游戏本体元信息(标题/封面/作者/包地址)来自 project 契约 #1,feed 不持久化本体。
parameters:
- { name: cursor, in: query, required: false, schema: { type: string }, description: 'cursor 游标(首屏不传;透传上页 nextCursor 翻页,T-FED-06)' }
- { name: size, in: query, required: false, schema: { type: integer, default: 10, minimum: 1, maximum: 30 }, description: 单页条数(预加载三容器,默认 10) }
responses:
'200':
description: 成功(游戏流卡片 + 下一页游标)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultFeedStream' }
/app-api/feed/zones:
get:
tags: [app-feed]
summary: 双轨专区列表(官方精选 / UGC 普通;P-PLZ-01/02)
description: 读 project 契约 #1 的 game_zone(type=1官方精选 2UGC普通、status=1启用),按 sort 升序返回;feed 不拥有 Zone 实体。
responses:
'200':
description: 成功
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultZoneList' }
/app-api/feed/zone/stream:
get:
tags: [app-feed]
summary: 按 Zone 分区游戏流(双区独立候选,cursor 分页;P-PLZ-01/02 · T-FED-15)
description: >-
指定专区内的游戏流,候选集 = game_project_zone(zone_id) ∩ project(status=4) ∩ compliance 未下架,
同样按 quality_score 降序 + cursor 分页。授权 IP / UGC 双区候选互相隔离。
parameters:
- { name: zoneId, in: query, required: true, schema: { type: integer, format: int64 }, description: 专区 ID(game_zone.id) }
- { name: cursor, in: query, required: false, schema: { type: string }, description: cursor 游标 }
- { name: size, in: query, required: false, schema: { type: integer, default: 10, minimum: 1, maximum: 30 } }
responses:
'200':
description: 成功
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultFeedStream' }
# ===========================================================================
# 互动信号写入(赞/藏/享/举报 → 权重;P-FED-03/04/05/06 · T-FED-08)
# ===========================================================================
/app-api/feed/interact:
post:
tags: [app-feed]
summary: 互动信号写入(点赞/收藏/分享/举报 → 排序权重;P-FED-03/04/05/06)
description: >-
同步写互动信号流水(game_feed_interact_log,幂等去重)并产出排序加权信号;举报(action=report)同步转 compliance 受理(T-CMP-10),
feed 不裁决。累计计数最终态归 project/community,本端只负责"信号→权重"。
前端同时通过 telemetry 契约 #5 批量上报对应事件(like/favorite/share/report),两路互不替代。
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/FeedInteractReqVO' }
responses:
'200':
description: 成功(返回该游戏该动作的最新聚合计数)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultInteractResult' }
# ===========================================================================
# 分享页 / OG 元数据 + 渠道参数(P-FED-05/07/08/09 · T-FED-09/10)
# ===========================================================================
/app-api/feed/share/{gameId}:
get:
tags: [app-feed]
summary: 分享落地页 OG 元数据 + 带渠道参数的分享链接(P-FED-07/08/09)
description: >-
返回独立分享链接(含 utm/channel 渠道参数,T-FED-10)与 OG 元数据(标题/封面/描述,供落地页 SSR 渲染、社交平台抓取)。
游戏元信息读 project 契约 #1;仅 status=4 已发布可分享,否则返回 1-103-002-001。
parameters:
- { name: gameId, in: path, required: true, schema: { type: integer, format: int64 } }
- { name: channel, in: query, required: false, schema: { type: string }, description: '渠道标识(写入分享链接 utm_source,用于渠道归因 T-FED-10)' }
responses:
'200':
description: 成功
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultShareMeta' }
# ===========================================================================
# 精选池运营(管理端 RBAC;P-OPN-03 · T-FED-14)
# ===========================================================================
/admin-api/feed/featured/page:
get:
tags: [admin-feed]
summary: 精选池列表(管理端 RBAC;P-OPN-03)
description: 分页查看当前进入精选池的游戏(game_feed_rank.pinned=1 或 project.featured=1 的运营加权项)。
parameters:
- { name: zoneId, in: query, required: false, schema: { type: integer, format: int64 }, description: 按专区筛选 }
- { name: pageNo, in: query, required: false, schema: { type: integer, default: 1 } }
- { name: pageSize, in: query, required: false, schema: { type: integer, default: 10 } }
responses:
'200':
description: 成功
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultFeaturedPage' }
/admin-api/feed/featured:
post:
tags: [admin-feed]
summary: 精选池置顶/取消 + 运营加权(管理端 RBAC;P-OPN-03 · T-FED-14)
description: >-
运营对单个游戏在游戏流/专区流中置顶或取消(写 game_feed_rank.pinned 与 boost 加权因子)。
仅 project status=4 已发布可入精选;非法目标返回 1-103-003-001。不改 project 本体,仅写排序覆盖层。
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/FeaturedReqVO' }
responses:
'200':
description: 成功
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultBoolean' }
components:
schemas:
# ---- Huijing CommonResult 信封 ----
CommonResultBoolean:
type: object
properties:
code: { type: integer, description: '0=成功,非0=错误码 1-103-***-***' }
data: { type: boolean }
msg: { type: string }
CommonResultFeedStream:
type: object
properties:
code: { type: integer }
data: { $ref: '#/components/schemas/FeedStreamRespVO' }
msg: { type: string }
CommonResultZoneList:
type: object
properties:
code: { type: integer }
data: { type: array, items: { $ref: '#/components/schemas/ZoneRespVO' } }
msg: { type: string }
CommonResultInteractResult:
type: object
properties:
code: { type: integer }
data: { $ref: '#/components/schemas/InteractResultRespVO' }
msg: { type: string }
CommonResultShareMeta:
type: object
properties:
code: { type: integer }
data: { $ref: '#/components/schemas/ShareMetaRespVO' }
msg: { type: string }
CommonResultFeaturedPage:
type: object
properties:
code: { type: integer }
data:
type: object
properties:
list: { type: array, items: { $ref: '#/components/schemas/FeedCardRespVO' } }
total: { type: integer, format: int64 }
msg: { type: string }
# ---- 游戏流 ----
FeedStreamRespVO:
type: object
description: 游戏流分页结果(cursor 模型,不返回 total,避免深翻页代价)
properties:
list: { type: array, items: { $ref: '#/components/schemas/FeedCardRespVO' } }
nextCursor: { type: string, description: '下一页游标;为空串表示已到底(T-FED-06)' }
hasMore: { type: boolean, description: 是否还有下一页 }
FeedCardRespVO:
type: object
description: 游戏流单卡(首屏封面 + 即玩入口;本体元信息源自 project 契约 #1,feed 不持久化)
properties:
gameId: { type: integer, format: int64, description: 游戏 ID(project.id) }
versionId: { type: integer, format: int64, description: 当前生效版本 ID(project.currentVersionId,供 runtime 即玩加载) }
title: { type: string, description: 标题(来自 project) }
coverUrl: { type: string, description: 封面图 URL(首屏卡片展示,P-FED-11) }
authorName: { type: string, description: 作者昵称(来自 project 作者元信息) }
packageUrl: { type: string, description: GamePackage manifest URL(runtime 加载,加载进度反馈 P-FED-10) }
zoneId: { type: integer, format: int64, description: 所属专区 ID(双轨归类) }
qualityScore: { type: number, format: float, description: '运营质量分(0-100),由 telemetry 回灌,作为 FeedCard 排序依据(仅展示/调试用);≠ aigc 生成质量分(0-1),两者量纲不同,不可混用' }
playCount: { type: integer, format: int64, description: 累计试玩数(project 回写) }
likeCount: { type: integer, format: int64, description: 累计点赞数(project 回写) }
liked: { type: boolean, description: 当前用户是否已赞(登录态;匿名恒为 false) }
favorited: { type: boolean, description: 当前用户是否已收藏(登录态) }
# ---- 专区 ----
ZoneRespVO:
type: object
description: 专区(读 project 契约 #1 game_zone,feed 不拥有 Zone 实体)
properties:
id: { type: integer, format: int64 }
name: { type: string, description: 专区名称 }
type: { type: integer, description: '专区类型(双轨):1官方精选 2UGC普通' }
sort: { type: integer, description: 排序(升序) }
# ---- 互动 ----
FeedInteractReqVO:
type: object
required: [gameId, action]
properties:
gameId: { type: integer, format: int64, description: 目标游戏 ID }
action: { type: integer, enum: [1, 2, 3, 4], description: '互动动作:1点赞 2收藏 3分享 4举报' }
active: { type: boolean, default: true, description: '是否激活(点赞/收藏可取消:true=赞/藏,false=取消;分享/举报恒 true)' }
reason: { type: string, maxLength: 200, description: '举报理由(action=4 时必填,转 compliance 受理 T-CMP-10)' }
InteractResultRespVO:
type: object
description: 互动后该游戏该动作的最新聚合(计数最终态归 project/community,本端回显便于前端即时刷新)
properties:
gameId: { type: integer, format: int64 }
action: { type: integer, description: '1点赞 2收藏 3分享 4举报' }
active: { type: boolean, description: 该用户当前对该动作的激活态 }
totalCount: { type: integer, format: int64, description: 该动作累计计数 }
# ---- 分享 ----
ShareMetaRespVO:
type: object
description: 分享落地页 OG 元数据 + 带渠道参数的分享链接(T-FED-09/10)
properties:
gameId: { type: integer, format: int64 }
shareUrl: { type: string, description: '独立分享链接(含 utm/channel 渠道参数,P-FED-07)' }
ogTitle: { type: string, description: 'OG 标题(社交平台抓取)' }
ogImage: { type: string, description: 'OG 封面图 URL' }
ogDescription: { type: string, description: 'OG 描述' }
channel: { type: string, description: 回显的渠道标识(渠道归因 T-FED-10) }
versionId: { type: integer, format: int64, description: '当前生效版本 ID(GAP-3,与 FeedItem.versionId 同源 project.currentVersionId;仅已发布游戏回填,未发布或无生效版本留空,供分享落地页直达即玩加载)' }
# ---- 精选池运营 ----
FeaturedReqVO:
type: object
required: [gameId, pinned]
properties:
gameId: { type: integer, format: int64, description: 目标游戏 ID(须 project status=4 已发布) }
zoneId: { type: integer, format: int64, description: '作用专区 ID;不传表示作用于默认混合流' }
pinned: { type: boolean, description: 'true=置顶进精选池 / false=取消置顶' }
boost: { type: number, format: float, description: '运营加权因子(叠加到 quality_score 排序,默认 0)' }