Files
Genarrative/src/components/rpg-entry/rpgEntryWorldPresentation.ts

156 lines
3.9 KiB
TypeScript

import type {
CustomWorldGalleryCard,
CustomWorldLibraryEntry,
} from '../../../packages/shared/src/contracts/runtime';
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
import { buildCustomWorldPlayableCharacters } from '../../data/characterPresets';
import { resolveCustomWorldCampSceneImage } from '../../data/customWorldVisuals';
import { buildPuzzlePublicWorkCode } from '../../services/publicWorkCode';
import type { CustomWorldProfile } from '../../types';
export type PlatformWorldCardLike =
| CustomWorldGalleryCard
| CustomWorldLibraryEntry<CustomWorldProfile>
| PlatformPuzzleGalleryCard;
export type PlatformPuzzleGalleryCard = {
sourceType: 'puzzle';
workId: string;
profileId: string;
publicWorkCode: string;
ownerUserId: string;
authorDisplayName: string;
worldName: string;
subtitle: string;
summaryText: string;
coverImageSrc: string | null;
themeTags: string[];
visibility: 'published';
publishedAt: string | null;
updatedAt: string;
};
export type PlatformPublicGalleryCard =
| CustomWorldGalleryCard
| PlatformPuzzleGalleryCard;
export function isLibraryWorldEntry(
entry: PlatformWorldCardLike,
): entry is CustomWorldLibraryEntry<CustomWorldProfile> {
return 'profile' in entry;
}
export function isPuzzleGalleryEntry(
entry: PlatformWorldCardLike,
): entry is PlatformPuzzleGalleryCard {
return 'sourceType' in entry && entry.sourceType === 'puzzle';
}
export function mapPuzzleWorkToPlatformGalleryCard(
work: PuzzleWorkSummary,
): PlatformPuzzleGalleryCard {
return {
sourceType: 'puzzle',
workId: work.workId,
profileId: work.profileId,
publicWorkCode: buildPuzzlePublicWorkCode(work.profileId),
ownerUserId: work.ownerUserId,
authorDisplayName: work.authorDisplayName,
worldName: work.levelName,
subtitle: '拼图关卡',
summaryText: work.summary,
coverImageSrc: work.coverImageSrc,
themeTags: work.themeTags,
visibility: 'published',
publishedAt: work.publishedAt,
updatedAt: work.updatedAt,
};
}
export function resolvePlatformWorldCoverImage(entry: PlatformWorldCardLike) {
if (entry.coverImageSrc) {
return entry.coverImageSrc;
}
if (isLibraryWorldEntry(entry)) {
return resolveCustomWorldCampSceneImage(entry.profile) ?? '';
}
return '';
}
export function resolvePlatformWorldLeadPortrait(entry: PlatformWorldCardLike) {
if (!isLibraryWorldEntry(entry)) {
return '';
}
return buildCustomWorldPlayableCharacters(entry.profile)[0]?.portrait ?? '';
}
export function buildPlatformWorldTags(entry: PlatformWorldCardLike) {
if (isPuzzleGalleryEntry(entry)) {
return entry.themeTags.length > 0 ? entry.themeTags.slice(0, 3) : ['拼图'];
}
if (!isLibraryWorldEntry(entry)) {
return [
describePlatformThemeLabel(entry.themeMode),
`${entry.playableNpcCount} 角色`,
`${entry.landmarkCount} 地标`,
];
}
return [
...entry.profile.majorFactions.slice(0, 2),
...entry.profile.coreConflicts.slice(0, 1),
]
.map((value) => value.trim())
.filter(Boolean)
.slice(0, 3);
}
export function formatPlatformWorldTime(value: string | null) {
if (!value) {
return '未发布';
}
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return value;
}
return date.toLocaleDateString('zh-CN', {
month: '2-digit',
day: '2-digit',
});
}
export function resolvePlatformPublicWorkCode(
entry: PlatformWorldCardLike,
): string | null {
if (isPuzzleGalleryEntry(entry)) {
return entry.publicWorkCode;
}
return entry.publicWorkCode;
}
export function describePlatformThemeLabel(
themeMode: CustomWorldGalleryCard['themeMode'],
) {
switch (themeMode) {
case 'martial':
return '江湖';
case 'arcane':
return '灵脉';
case 'machina':
return '机巧';
case 'tide':
return '潮痕';
case 'rift':
return '裂界';
default:
return '回响';
}
}