refactor: 收口视觉小说详情 session 映射
This commit is contained in:
@@ -537,6 +537,7 @@ import {
|
||||
buildJumpHopPendingSession,
|
||||
buildPuzzleRuntimeWorkFromSession,
|
||||
buildSquareHoleProfileFromSession,
|
||||
buildVisualNovelSessionFromWorkDetail,
|
||||
buildWoodenFishPendingSession,
|
||||
buildWoodenFishSessionFromWorkDetail,
|
||||
} from './platformMiniGameSessionMappingModel';
|
||||
@@ -736,22 +737,6 @@ const PUZZLE_DRAFT_GENERATION_POINT_COST = 2;
|
||||
const MATCH3D_DRAFT_GENERATION_POINT_COST = 10;
|
||||
const BARK_BATTLE_DRAFT_GENERATION_POINT_COST = 3;
|
||||
|
||||
function mapVisualNovelWorkDetailToSession(
|
||||
work: VisualNovelWorkDetail,
|
||||
): VisualNovelAgentSessionSnapshot {
|
||||
return {
|
||||
sessionId: work.sourceSessionId?.trim() || work.workId,
|
||||
ownerUserId: work.summary.ownerUserId,
|
||||
sourceMode: work.draft.sourceMode,
|
||||
status: 'ready',
|
||||
messages: [],
|
||||
draft: work.draft,
|
||||
pendingAction: null,
|
||||
createdAt: work.createdAt,
|
||||
updatedAt: work.summary.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
function mergePuzzleWorkSummary(
|
||||
current: PuzzleWorkSummary,
|
||||
updated: PuzzleWorkSummary,
|
||||
@@ -11094,7 +11079,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
try {
|
||||
const { work } = await getVisualNovelWorkDetail(item.profileId);
|
||||
setVisualNovelWork(work);
|
||||
setVisualNovelSession(mapVisualNovelWorkDetailToSession(work));
|
||||
setVisualNovelSession(buildVisualNovelSessionFromWorkDetail(work));
|
||||
enterCreateTab();
|
||||
setSelectionStage('visual-novel-result');
|
||||
} catch (error) {
|
||||
|
||||
@@ -12,6 +12,10 @@ import type {
|
||||
SquareHoleResultDraft,
|
||||
SquareHoleSessionSnapshot,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type {
|
||||
VisualNovelResultDraft,
|
||||
VisualNovelWorkDetail,
|
||||
} from '../../../packages/shared/src/contracts/visualNovel';
|
||||
import type {
|
||||
WoodenFishAudioAsset,
|
||||
WoodenFishImageAsset,
|
||||
@@ -22,6 +26,7 @@ import {
|
||||
buildJumpHopPendingSession,
|
||||
buildPuzzleRuntimeWorkFromSession,
|
||||
buildSquareHoleProfileFromSession,
|
||||
buildVisualNovelSessionFromWorkDetail,
|
||||
buildWoodenFishPendingSession,
|
||||
buildWoodenFishSessionFromWorkDetail,
|
||||
} from './platformMiniGameSessionMappingModel';
|
||||
@@ -222,6 +227,126 @@ function buildSquareHoleSession(
|
||||
};
|
||||
}
|
||||
|
||||
function buildVisualNovelDraft(
|
||||
overrides: Partial<VisualNovelResultDraft> = {},
|
||||
): VisualNovelResultDraft {
|
||||
return {
|
||||
profileId: 'visual-novel-profile-1',
|
||||
workTitle: '雪线电台',
|
||||
workDescription: '旧电台牵出雪夜列车谜案。',
|
||||
workTags: ['雪夜', '电台'],
|
||||
coverImageSrc: '/visual-novel-cover.png',
|
||||
sourceMode: 'idea',
|
||||
sourceAssetIds: ['asset-source-1'],
|
||||
world: {
|
||||
title: '北境终点线',
|
||||
summary: '边境小城与旧电台。',
|
||||
background: '十二年前的雪崩留下夜间广播。',
|
||||
premise: '玩家需要在日出前找出列车停摆的原因。',
|
||||
literaryStyle: '克制冷光感。',
|
||||
playerRole: '临时广播员',
|
||||
defaultTone: '安静紧张',
|
||||
},
|
||||
characters: [
|
||||
{
|
||||
characterId: 'vn-char-1',
|
||||
name: '林遥',
|
||||
gender: '女',
|
||||
role: 'main',
|
||||
appearance: '灰色长外套。',
|
||||
personality: '谨慎敏锐。',
|
||||
tone: '短句多。',
|
||||
background: '旧电台夜班实习生。',
|
||||
relationshipToPlayer: '临时搭档',
|
||||
imageAssets: [],
|
||||
defaultExpression: 'calm',
|
||||
isPlayerVisible: false,
|
||||
},
|
||||
],
|
||||
scenes: [
|
||||
{
|
||||
sceneId: 'vn-scene-1',
|
||||
name: '风雪站台',
|
||||
description: '站灯忽明忽暗。',
|
||||
backgroundImageSrc: null,
|
||||
musicSrc: null,
|
||||
ambientSoundSrc: null,
|
||||
availability: 'opening',
|
||||
phaseIds: ['vn-phase-1'],
|
||||
},
|
||||
],
|
||||
storyPhases: [
|
||||
{
|
||||
phaseId: 'vn-phase-1',
|
||||
title: '重启站台',
|
||||
goal: '确认列车为何停在废弃站台。',
|
||||
summary: '玩家抵达风雪站台。',
|
||||
entryCondition: '开场进入',
|
||||
exitCondition: '找到车长日志',
|
||||
sceneIds: ['vn-scene-1'],
|
||||
characterIds: ['vn-char-1'],
|
||||
suggestedChoices: ['检查广播柜'],
|
||||
},
|
||||
],
|
||||
opening: {
|
||||
sceneId: 'vn-scene-1',
|
||||
narration: '雪落得很慢。',
|
||||
speakerCharacterId: 'vn-char-1',
|
||||
firstDialogue: '你听见了吗?',
|
||||
initialChoices: [
|
||||
{
|
||||
choiceId: 'vn-choice-1',
|
||||
text: '靠近广播柜。',
|
||||
actionHint: 'inspect_radio',
|
||||
},
|
||||
],
|
||||
},
|
||||
runtimeConfig: {
|
||||
textModeEnabled: true,
|
||||
defaultTextMode: false,
|
||||
maxHistoryEntries: 80,
|
||||
maxAssistantStepCountPerTurn: 8,
|
||||
allowFreeTextAction: true,
|
||||
allowHistoryRegeneration: true,
|
||||
attributePanelMode: 'template_config',
|
||||
saveArchiveEnabled: true,
|
||||
},
|
||||
publishReady: true,
|
||||
validationIssues: [],
|
||||
updatedAt: '2026-06-01T13:00:00.000Z',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function buildVisualNovelWorkDetail(
|
||||
overrides: Partial<VisualNovelWorkDetail> = {},
|
||||
): VisualNovelWorkDetail {
|
||||
const draft = buildVisualNovelDraft();
|
||||
return {
|
||||
workId: 'visual-novel-work-1',
|
||||
summary: {
|
||||
runtimeKind: 'visual-novel',
|
||||
profileId: 'visual-novel-profile-1',
|
||||
ownerUserId: 'user-visual-novel-1',
|
||||
title: draft.workTitle,
|
||||
description: draft.workDescription,
|
||||
coverImageSrc: draft.coverImageSrc,
|
||||
tags: draft.workTags,
|
||||
publishStatus: 'draft',
|
||||
publishReady: draft.publishReady,
|
||||
playCount: 0,
|
||||
updatedAt: '2026-06-01T13:30:00.000Z',
|
||||
publishedAt: null,
|
||||
},
|
||||
sourceSessionId: ' visual-novel-session-1 ',
|
||||
authorDisplayName: '视觉小说作者',
|
||||
sourceAssetIds: draft.sourceAssetIds,
|
||||
draft,
|
||||
createdAt: '2026-06-01T12:50:00.000Z',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
const woodenFishImageAsset: WoodenFishImageAsset = {
|
||||
assetId: 'asset-hit',
|
||||
imageSrc: '/hit.png',
|
||||
@@ -427,6 +552,33 @@ describe('platformMiniGameSessionMappingModel', () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
test('builds visual novel recovered session from work detail', () => {
|
||||
const work = buildVisualNovelWorkDetail();
|
||||
|
||||
expect(buildVisualNovelSessionFromWorkDetail(work)).toEqual({
|
||||
sessionId: 'visual-novel-session-1',
|
||||
ownerUserId: 'user-visual-novel-1',
|
||||
sourceMode: 'idea',
|
||||
status: 'ready',
|
||||
messages: [],
|
||||
draft: work.draft,
|
||||
pendingAction: null,
|
||||
createdAt: '2026-06-01T12:50:00.000Z',
|
||||
updatedAt: '2026-06-01T13:30:00.000Z',
|
||||
});
|
||||
});
|
||||
|
||||
test('falls back visual novel recovered session id to work id', () => {
|
||||
expect(
|
||||
buildVisualNovelSessionFromWorkDetail(
|
||||
buildVisualNovelWorkDetail({
|
||||
sourceSessionId: ' ',
|
||||
workId: 'visual-novel-work-fallback',
|
||||
}),
|
||||
).sessionId,
|
||||
).toBe('visual-novel-work-fallback');
|
||||
});
|
||||
|
||||
test('builds wooden fish pending session from work summary', () => {
|
||||
expect(buildWoodenFishPendingSession(buildWoodenFishSummary())).toEqual({
|
||||
sessionId: 'wooden-fish-session-1',
|
||||
|
||||
@@ -3,6 +3,10 @@ import type { PuzzleAgentSessionSnapshot } from '../../../packages/shared/src/co
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import type { SquareHoleSessionSnapshot } from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type { SquareHoleWorkProfile } from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import type {
|
||||
VisualNovelAgentSessionSnapshot,
|
||||
VisualNovelWorkDetail,
|
||||
} from '../../../packages/shared/src/contracts/visualNovel';
|
||||
import type {
|
||||
WoodenFishSessionSnapshotResponse,
|
||||
WoodenFishWorkProfileResponse,
|
||||
@@ -88,6 +92,22 @@ export function buildSquareHoleProfileFromSession(
|
||||
};
|
||||
}
|
||||
|
||||
export function buildVisualNovelSessionFromWorkDetail(
|
||||
work: VisualNovelWorkDetail,
|
||||
): VisualNovelAgentSessionSnapshot {
|
||||
return {
|
||||
sessionId: normalizeCreationUrlValue(work.sourceSessionId) ?? work.workId,
|
||||
ownerUserId: work.summary.ownerUserId,
|
||||
sourceMode: work.draft.sourceMode,
|
||||
status: 'ready',
|
||||
messages: [],
|
||||
draft: work.draft,
|
||||
pendingAction: null,
|
||||
createdAt: work.createdAt,
|
||||
updatedAt: work.summary.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildJumpHopPendingSession(
|
||||
item: JumpHopWorkSummaryResponse,
|
||||
): JumpHopSessionSnapshotResponse {
|
||||
|
||||
Reference in New Issue
Block a user