1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-20 21:06:48 +08:00
parent 1c72066bab
commit 75944b1f1f
102 changed files with 9648 additions and 1540 deletions

View File

@@ -0,0 +1,76 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { buildCustomWorldCoverImageSrc, resolveCustomWorldCoverPresentation } from './customWorldLibraryMetadata.js';
function createProfile() {
return {
id: 'profile-cover-test',
name: '潮雾群岛',
subtitle: '封面规则测试',
summary: '验证作品库封面优先级。',
tone: '潮湿、压抑',
playerGoal: '查明旧航道真相。',
playableNpcs: [
{
id: 'playable-1',
name: '林潮',
imageSrc: '/images/roles/linchao.webp',
},
],
camp: {
imageSrc: '/images/camp/camp.webp',
},
landmarks: [
{
imageSrc: '/images/landmark/docks.webp',
},
],
sceneChapterBlueprints: [
{
id: 'scene-chapter-1',
acts: [
{
id: 'act-1',
backgroundImageSrc: '/images/scene/act-1.webp',
backgroundAssetId: 'asset-scene-act-1',
},
],
},
],
};
}
test('resolveCustomWorldCoverPresentation 优先使用开局场景第一幕图片', () => {
const profile = createProfile();
const result = resolveCustomWorldCoverPresentation(profile);
assert.equal(result.imageSrc, '/images/scene/act-1.webp');
assert.equal(result.renderMode, 'scene_with_roles');
assert.deepEqual(result.characterImageSrcs, ['/images/roles/linchao.webp']);
});
test('buildCustomWorldCoverImageSrc 在第一幕图片缺失时按营地图与地标图回退', () => {
const profile = createProfile();
profile.sceneChapterBlueprints = [
{
id: 'scene-chapter-1',
acts: [
{
id: 'act-1',
backgroundImageSrc: '',
backgroundAssetId: '',
},
],
},
];
assert.equal(buildCustomWorldCoverImageSrc(profile), '/images/camp/camp.webp');
profile.camp = {
imageSrc: '',
};
assert.equal(buildCustomWorldCoverImageSrc(profile), '/images/landmark/docks.webp');
});

View File

@@ -39,7 +39,23 @@ function normalizeCoverCharacterRoleIds(
return [...availableIds].slice(0, 3);
}
function resolveOpeningSceneFirstActImageSrc(profile: CustomWorldProfileRecord) {
const sceneChapters = readArray(profile.sceneChapterBlueprints);
const firstSceneChapter = sceneChapters.find(isRecord) ?? null;
const firstAct = firstSceneChapter
? readArray(firstSceneChapter.acts).find(isRecord) ?? null
: null;
return firstAct ? readImageSrc(firstAct.backgroundImageSrc) : null;
}
function resolveOpeningSceneImageSrc(profile: CustomWorldProfileRecord) {
// 默认封面优先取开局场景第一幕图,保证创作草稿、作品库和正式结果页看到的是同一张“开场镜头”。
const firstActImage = resolveOpeningSceneFirstActImageSrc(profile);
if (firstActImage) {
return firstActImage;
}
const campImage = isRecord(profile.camp)
? readImageSrc(profile.camp.imageSrc)
: null;