后台:撤回审核页价格客户端二次回退,改为哑渲染服务端字段
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled

- AdminGameDistributionReviewPage.tsx:删除新增的 resolveFrozenPriceMudPoints,恢复「价格不在这里二次叠加」的单一实现
  (服务端 version_detail_payload 已把版本冻结价优先、缺字段按 0 归一写进 game.priceMudPoints,M4 已明确客户端不得复刻该语义)
- AdminGameDistributionReviewPage.test.tsx:详情价格用例改为直接编码「客户端保持哑渲染」约束
  - 服务端下发 game.priceMudPoints = 30 → 详情显示「30 泥点」(列表侧由价格列用例覆盖同一字段)
  - 对抗用例:冻结资料故意传 frozenMetadata.priceMudPoints = 999,断言仍显示 30 且不出现「999 泥点」
This commit is contained in:
2026-10-06 02:21:44 +08:00
parent b4bf37671d
commit 4d901eec65
2 changed files with 10 additions and 21 deletions
@@ -472,14 +472,16 @@ test('试玩加载超过上限后给出超时说明与重建会话入口', async
}
});
test('详情价格取版本冻结价,不回退游戏行当前价', async () => {
test('详情价格只渲染服务端下发的 priceMudPoints,不按冻结资料二次取价', async () => {
vi.mocked(getAdminGameDistributionVersion).mockResolvedValue({
// 游戏行现价与待审版本冻结价刻意取不同值:两者相同的话,无论实现取哪个字段
// 用例都会绿,无法证明审核页展示的是这一版审核通过后真正生效的价格。
game: { ...detailResponse.game, priceMudPoints: 999 },
// 服务端 `version_detail_payload` 已把「待审版本冻结价优先、缺字段按 0」归一写进
// `game.priceMudPoints`,审核页只渲染这个字段。
game: { ...detailResponse.game, priceMudPoints: 30 },
version: {
...detailResponse.version,
frozenMetadata: { title: '测试游戏', priceMudPoints: 30 },
// 对抗用例:冻结资料里的价格与服务端归一结果故意不同(999 ≠ 30)。客户端若自行
// 复刻「冻结价优先」,就会显示 999 —— 这里必须仍然是服务端字段的 30。
frozenMetadata: { title: '测试游戏', priceMudPoints: 999 },
},
});
@@ -496,6 +498,7 @@ test('详情价格取版本冻结价,不回退游戏行当前价', async () =>
expect(screen.getByText('价格')).toBeTruthy();
expect(screen.getByText('30 泥点')).toBeTruthy();
expect(screen.queryByText('999 泥点')).toBeNull();
expect(screen.queryByText('免费')).toBeNull();
});
@@ -100,25 +100,11 @@ function applyFrozenGameMetadata(
typeof metadata.orientation === 'string'
? metadata.orientation
: game.orientation,
// 价格口径与服务端 `version_detail_payload` 对齐,并在客户端再兜一次:审核页展示的是
// 这一版审核通过后会生效的价格,所以版本冻结价优先;快照没冻结价才回落游戏行价,
// 两者都缺时交给 `formatPriceMudPoints` 按免费展示。
priceMudPoints: resolveFrozenPriceMudPoints(game, metadata),
// 价格不在这里二次叠加:服务端 `version_detail_payload` 已按「版本冻结价优先、
// 缺字段按 0」把结果归一写进 `game.priceMudPoints`,客户端直接沿用该字段。
};
}
/** 版本冻结价优先、游戏行价兜底;只取值,不改「`0` 表示免费」的展示口径。 */
function resolveFrozenPriceMudPoints(
game: AdminGameDistributionGameDetail,
metadata: Record<string, unknown>,
) {
const frozenPriceMudPoints = metadata.priceMudPoints;
return typeof frozenPriceMudPoints === 'number' &&
Number.isFinite(frozenPriceMudPoints)
? frozenPriceMudPoints
: game.priceMudPoints;
}
function formatBytes(value: number) {
if (value >= 1024 * 1024) {
return `${(value / (1024 * 1024)).toFixed(1)} MiB`;