refactor: 收口 Bark Battle 草稿恢复映射

This commit is contained in:
2026-06-04 05:14:23 +08:00
parent 20a21ee78b
commit 9c96535073
6 changed files with 64 additions and 24 deletions

View File

@@ -18,9 +18,9 @@
## 2026-06-04 Bark Battle Work Cache 草稿状态收口 ## 2026-06-04 Bark Battle Work Cache 草稿状态收口
- 背景:`PlatformEntryFlowShellImpl.tsx` 仍内联维护 Bark Battle 草稿三图完整性、生成状态归一,以及草稿 / 已发布作品进入 runtime 前的 `BarkBattlePublishedConfig` 字段映射,导致结果页试玩、作品架启动和公开详情启动都要理解同一份资产字段清单。 - 背景:`PlatformEntryFlowShellImpl.tsx` 仍内联维护 Bark Battle 草稿三图完整性、生成状态归一、作品架摘要恢复草稿配置,以及草稿 / 已发布作品进入 runtime 前的 `BarkBattlePublishedConfig` 字段映射,导致结果页试玩、作品架启动、草稿恢复和公开详情启动都要理解同一份资产字段清单。
- 决策:扩展 `src/components/platform-entry/barkBattleWorkCache.ts`,以 `hasBarkBattleDraftRequiredImages``resolveBarkBattleDraftGenerationStatus``buildBarkBattlePublishedConfigFromDraft``buildBarkBattlePublishedConfigFromWork``buildBarkBattlePublishSnapshot``mergeBarkBattlePublishedConfigAssets` 收口 Bark Battle 纯规则。平台壳只保留 API、缓存刷新、React state、URL 和 stage 副作用。 - 决策:扩展 `src/components/platform-entry/barkBattleWorkCache.ts`,以 `hasBarkBattleDraftRequiredImages``resolveBarkBattleDraftGenerationStatus``buildBarkBattleDraftConfigFromWorkSummary``buildBarkBattlePublishedConfigFromDraft``buildBarkBattlePublishedConfigFromWork``buildBarkBattlePublishSnapshot``mergeBarkBattlePublishedConfigAssets` 收口 Bark Battle 纯规则。平台壳只保留 API、缓存刷新、React state、URL 和 stage 副作用。
- 影响范围Bark Battle 草稿生成完成、结果页保存、草稿试玩、作品架 / 公开详情启动正式 runtime以及后续 Bark Battle 资产字段或 ruleset 默认值调整。 - 影响范围Bark Battle 草稿生成完成、结果页保存、作品架摘要恢复草稿、草稿试玩、作品架 / 公开详情启动正式 runtime以及后续 Bark Battle 资产字段或 ruleset 默认值调整。
- 验证方式:`npm run test -- src/components/platform-entry/barkBattleWorkCache.test.ts`、针对 Bark Battle Work Cache Module 与平台壳执行 ESLint、`npm run typecheck``npm run check:encoding` - 验证方式:`npm run test -- src/components/platform-entry/barkBattleWorkCache.test.ts`、针对 Bark Battle Work Cache Module 与平台壳执行 ESLint、`npm run typecheck``npm run check:encoding`
- 关联文档:`docs/technical/【前端架构】BarkBattleWorkCache草稿状态收口计划-2026-06-04.md` - 关联文档:`docs/technical/【前端架构】BarkBattleWorkCache草稿状态收口计划-2026-06-04.md`

View File

@@ -67,7 +67,7 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_
平台入口个人钱包本地 delta、dashboard 乐观更新与服务端快照对账规则收口到 `src/components/platform-entry/platformProfileWalletDeltaModel.ts`,平台壳只保留 API、ref 与 state 副作用,规则见 [【前端架构】PlatformProfileWalletDeltaModel收口计划-2026-06-04.md](./technical/【前端架构】PlatformProfileWalletDeltaModel收口计划-2026-06-04.md)。 平台入口个人钱包本地 delta、dashboard 乐观更新与服务端快照对账规则收口到 `src/components/platform-entry/platformProfileWalletDeltaModel.ts`,平台壳只保留 API、ref 与 state 副作用,规则见 [【前端架构】PlatformProfileWalletDeltaModel收口计划-2026-06-04.md](./technical/【前端架构】PlatformProfileWalletDeltaModel收口计划-2026-06-04.md)。
Bark Battle 草稿三图完整性、生成状态归一、发布快照 / 发布回包资产兜底和草稿 / 已发布作品进入 runtime 前的 `BarkBattlePublishedConfig` 映射收口到 `src/components/platform-entry/barkBattleWorkCache.ts`,规则见 [【前端架构】BarkBattleWorkCache草稿状态收口计划-2026-06-04.md](./technical/【前端架构】BarkBattleWorkCache草稿状态收口计划-2026-06-04.md)。 Bark Battle 草稿三图完整性、生成状态归一、作品架摘要恢复草稿配置、发布快照 / 发布回包资产兜底和草稿 / 已发布作品进入 runtime 前的 `BarkBattlePublishedConfig` 映射收口到 `src/components/platform-entry/barkBattleWorkCache.ts`,规则见 [【前端架构】BarkBattleWorkCache草稿状态收口计划-2026-06-04.md](./technical/【前端架构】BarkBattleWorkCache草稿状态收口计划-2026-06-04.md)。
平台首页推荐 runtime 的匿名 Runtime Guest Token、已登录 background auth、非 embedded no-op 和拼图 isolated/default auth mode 计划收口到 `src/components/platform-entry/platformRecommendRuntimeAuthModel.ts`,规则见 [【前端架构】PlatformRecommendRuntimeAuthModel收口计划-2026-06-04.md](./technical/【前端架构】PlatformRecommendRuntimeAuthModel收口计划-2026-06-04.md)。 平台首页推荐 runtime 的匿名 Runtime Guest Token、已登录 background auth、非 embedded no-op 和拼图 isolated/default auth mode 计划收口到 `src/components/platform-entry/platformRecommendRuntimeAuthModel.ts`,规则见 [【前端架构】PlatformRecommendRuntimeAuthModel收口计划-2026-06-04.md](./technical/【前端架构】PlatformRecommendRuntimeAuthModel收口计划-2026-06-04.md)。

View File

@@ -2,7 +2,7 @@
## 背景 ## 背景
`PlatformEntryFlowShellImpl.tsx` 仍内联维护 Bark Battle 草稿三图完整性、生成状态归一,以及草稿 / 已发布作品进入 runtime 前的 `BarkBattlePublishedConfig` 映射。壳层因此需要同时理解三图资产字段、`partial_failed``pending_assets` 的差异、`publishedAt` 兜底和草稿试玩配置默认值。 `PlatformEntryFlowShellImpl.tsx` 仍内联维护 Bark Battle 草稿三图完整性、生成状态归一、作品架摘要恢复草稿配置,以及草稿 / 已发布作品进入 runtime 前的 `BarkBattlePublishedConfig` 映射。壳层因此需要同时理解三图资产字段、`partial_failed``pending_assets` 的差异、`publishedAt` 兜底、作品摘要字段和草稿试玩配置默认值。
这些规则属于 Bark Battle 作品摘要与草稿缓存的纯模型。若留在平台壳层,后续发布、作品架刷新、公开详情启动或草稿试玩都容易重复一份字段清单。 这些规则属于 Bark Battle 作品摘要与草稿缓存的纯模型。若留在平台壳层,后续发布、作品架刷新、公开详情启动或草稿试玩都容易重复一份字段清单。
@@ -12,6 +12,7 @@
- `hasBarkBattleDraftRequiredImages(draft)`:判断草稿是否已具备玩家形象、对手形象和竞技背景三图。 - `hasBarkBattleDraftRequiredImages(draft)`:判断草稿是否已具备玩家形象、对手形象和竞技背景三图。
- `resolveBarkBattleDraftGenerationStatus(draft, partialFailed)`:三图齐备返回 `ready`,否则按是否部分失败返回 `partial_failed``pending_assets` - `resolveBarkBattleDraftGenerationStatus(draft, partialFailed)`:三图齐备返回 `ready`,否则按是否部分失败返回 `partial_failed``pending_assets`
- `buildBarkBattleDraftConfigFromWorkSummary(work)`:把作品架摘要恢复成可编辑 / 可试玩的 `BarkBattleDraftConfig`
- `buildBarkBattlePublishedConfigFromDraft(draft)`:把草稿结果页试玩所需配置映射为 `BarkBattlePublishedConfig` - `buildBarkBattlePublishedConfigFromDraft(draft)`:把草稿结果页试玩所需配置映射为 `BarkBattlePublishedConfig`
- `buildBarkBattlePublishedConfigFromWork(work)`:把作品架 / 公开详情启动正式 runtime 所需配置映射为 `BarkBattlePublishedConfig` - `buildBarkBattlePublishedConfigFromWork(work)`:把作品架 / 公开详情启动正式 runtime 所需配置映射为 `BarkBattlePublishedConfig`
- `buildBarkBattlePublishSnapshot(draft)`:拼装发布接口所需的最终草稿快照。 - `buildBarkBattlePublishSnapshot(draft)`:拼装发布接口所需的最终草稿快照。
@@ -23,6 +24,7 @@
- 草稿三图必须同时具备 `playerCharacterImageSrc``opponentCharacterImageSrc``uiBackgroundImageSrc` 的非空值,才视为 `ready` - 草稿三图必须同时具备 `playerCharacterImageSrc``opponentCharacterImageSrc``uiBackgroundImageSrc` 的非空值,才视为 `ready`
- 未齐三图且 `partialFailed=true` 时返回 `partial_failed`,否则返回 `pending_assets` - 未齐三图且 `partialFailed=true` 时返回 `partial_failed`,否则返回 `pending_assets`
- 作品摘要恢复草稿时,`draftId` 缺失回退 `workId``description` 来自 summary三图 null 归一为 `undefined``configVersion=1``rulesetVersion='bark-battle-ruleset-v1'`
- 草稿试玩配置的 `workId` 优先使用草稿稳定 `workId`,缺失时回退 `draftId` - 草稿试玩配置的 `workId` 优先使用草稿稳定 `workId`,缺失时回退 `draftId`
- 草稿试玩配置的 `configVersion``rulesetVersion` 使用草稿值,缺失时回退 `1``bark-battle-ruleset-v1` - 草稿试玩配置的 `configVersion``rulesetVersion` 使用草稿值,缺失时回退 `1``bark-battle-ruleset-v1`
- 已发布作品配置的 `publishedAt` 缺失时回退 `updatedAt`,保持旧 runtime 启动语义。 - 已发布作品配置的 `publishedAt` 缺失时回退 `updatedAt`,保持旧 runtime 启动语义。
@@ -31,8 +33,8 @@
## Depth / Leverage / Locality ## Depth / Leverage / Locality
- **Depth**:壳层传入草稿或作品摘要,即可得到生成状态或 runtime 配置;字段归一、默认值和三图完整性藏入 Module Implementation。 - **Depth**:壳层传入草稿或作品摘要,即可得到生成状态、草稿配置或 runtime 配置;字段归一、默认值和三图完整性藏入 Module Implementation。
- **Leverage**:结果页试玩、作品架启动、公开详情启动和缓存刷新可复用同一组 Bark Battle 规则。 - **Leverage**作品架草稿恢复、结果页试玩、作品架启动、公开详情启动和缓存刷新可复用同一组 Bark Battle 规则。
- **Locality**Bark Battle 资产完整性与配置映射集中到纯测试面,后续变更三图字段或规则集默认值时无需搜索巨型平台壳。 - **Locality**Bark Battle 资产完整性与配置映射集中到纯测试面,后续变更三图字段或规则集默认值时无需搜索巨型平台壳。
## 验收 ## 验收

View File

@@ -380,6 +380,7 @@ import {
} from '../visual-novel-creation/visualNovelEntryGeneration'; } from '../visual-novel-creation/visualNovelEntryGeneration';
import { createMockVisualNovelRunFromDraft } from '../visual-novel-runtime/visualNovelMockData'; import { createMockVisualNovelRunFromDraft } from '../visual-novel-runtime/visualNovelMockData';
import { import {
buildBarkBattleDraftConfigFromWorkSummary,
buildBarkBattlePublishedConfigFromDraft, buildBarkBattlePublishedConfigFromDraft,
buildBarkBattlePublishedConfigFromWork, buildBarkBattlePublishedConfigFromWork,
buildBarkBattlePublishSnapshot, buildBarkBattlePublishSnapshot,
@@ -11006,23 +11007,7 @@ export function PlatformEntryFlowShellImpl({
return; return;
} }
const nextDraft: BarkBattleDraftConfig = { const nextDraft = buildBarkBattleDraftConfigFromWorkSummary(item);
draftId: item.draftId ?? item.workId,
workId: item.workId,
title: item.title,
description: item.summary,
themeDescription: item.themeDescription,
playerImageDescription: item.playerImageDescription,
opponentImageDescription: item.opponentImageDescription,
onomatopoeia: item.onomatopoeia,
playerCharacterImageSrc: item.playerCharacterImageSrc ?? undefined,
opponentCharacterImageSrc: item.opponentCharacterImageSrc ?? undefined,
uiBackgroundImageSrc: item.uiBackgroundImageSrc ?? undefined,
difficultyPreset: item.difficultyPreset,
configVersion: 1,
rulesetVersion: 'bark-battle-ruleset-v1',
updatedAt: item.updatedAt,
};
setBarkBattleDraftConfig(nextDraft); setBarkBattleDraftConfig(nextDraft);
enterCreateTab(); enterCreateTab();
selectionStageRef.current = isPersistedBarkBattleDraftGenerating(item) selectionStageRef.current = isPersistedBarkBattleDraftGenerating(item)

View File

@@ -6,6 +6,7 @@ import type {
BarkBattleWorkSummary, BarkBattleWorkSummary,
} from '../../../packages/shared/src/contracts/barkBattle'; } from '../../../packages/shared/src/contracts/barkBattle';
import { import {
buildBarkBattleDraftConfigFromWorkSummary,
buildBarkBattlePublishedConfigFromDraft, buildBarkBattlePublishedConfigFromDraft,
buildBarkBattlePublishedConfigFromWork, buildBarkBattlePublishedConfigFromWork,
buildBarkBattlePublishSnapshot, buildBarkBattlePublishSnapshot,
@@ -29,6 +30,7 @@ function buildBarkBattleWork(
themeDescription: '阳光草坪声浪竞技场', themeDescription: '阳光草坪声浪竞技场',
playerImageDescription: '戴红色围巾的柯基选手', playerImageDescription: '戴红色围巾的柯基选手',
opponentImageDescription: '蓝色护目镜哈士奇对手', opponentImageDescription: '蓝色护目镜哈士奇对手',
onomatopoeia: ['汪', '破阵'],
playerCharacterImageSrc: '/generated-bark-battle/player.png', playerCharacterImageSrc: '/generated-bark-battle/player.png',
opponentCharacterImageSrc: '/generated-bark-battle/opponent.png', opponentCharacterImageSrc: '/generated-bark-battle/opponent.png',
uiBackgroundImageSrc: '/generated-bark-battle/background.png', uiBackgroundImageSrc: '/generated-bark-battle/background.png',
@@ -184,6 +186,35 @@ test('builds work runtime config with publishedAt fallback', () => {
expect(config.playerCharacterImageSrc).toBe('/generated-bark-battle/player.png'); expect(config.playerCharacterImageSrc).toBe('/generated-bark-battle/player.png');
}); });
test('builds draft config from work summary with stable defaults', () => {
const config = buildBarkBattleDraftConfigFromWorkSummary(
buildBarkBattleWork({
draftId: null,
playerCharacterImageSrc: null,
opponentCharacterImageSrc: null,
uiBackgroundImageSrc: null,
}),
);
expect(config).toMatchObject({
draftId: 'BB-cache-race-12345678',
workId: 'BB-cache-race-12345678',
title: '汪汪测试杯',
description: '测试声浪赛',
themeDescription: '阳光草坪声浪竞技场',
playerImageDescription: '戴红色围巾的柯基选手',
opponentImageDescription: '蓝色护目镜哈士奇对手',
onomatopoeia: ['汪', '破阵'],
difficultyPreset: 'normal',
configVersion: 1,
rulesetVersion: 'bark-battle-ruleset-v1',
updatedAt: '2026-05-21T10:00:00.000Z',
});
expect(config.playerCharacterImageSrc).toBeUndefined();
expect(config.opponentCharacterImageSrc).toBeUndefined();
expect(config.uiBackgroundImageSrc).toBeUndefined();
});
test('builds publish snapshot without empty asset fields', () => { test('builds publish snapshot without empty asset fields', () => {
const snapshot = buildBarkBattlePublishSnapshot( const snapshot = buildBarkBattlePublishSnapshot(
buildBarkBattleDraft({ buildBarkBattleDraft({

View File

@@ -142,6 +142,28 @@ export function buildBarkBattlePublishedConfigFromWork(
}; };
} }
export function buildBarkBattleDraftConfigFromWorkSummary(
work: BarkBattleWorkSummary,
): BarkBattleDraftConfig {
return {
draftId: work.draftId ?? work.workId,
workId: work.workId,
title: work.title,
description: work.summary,
themeDescription: work.themeDescription,
playerImageDescription: work.playerImageDescription,
opponentImageDescription: work.opponentImageDescription,
onomatopoeia: work.onomatopoeia,
playerCharacterImageSrc: work.playerCharacterImageSrc ?? undefined,
opponentCharacterImageSrc: work.opponentCharacterImageSrc ?? undefined,
uiBackgroundImageSrc: work.uiBackgroundImageSrc ?? undefined,
difficultyPreset: work.difficultyPreset,
configVersion: 1,
rulesetVersion: 'bark-battle-ruleset-v1',
updatedAt: work.updatedAt,
};
}
export function shouldPreserveLocalBarkBattleWorkOnRefresh( export function shouldPreserveLocalBarkBattleWorkOnRefresh(
item: BarkBattleWorkSummary, item: BarkBattleWorkSummary,
refreshed: readonly BarkBattleWorkSummary[], refreshed: readonly BarkBattleWorkSummary[],