This commit is contained in:
2026-04-29 20:56:59 +08:00
parent fb6f455530
commit 730f485f48
200 changed files with 9881 additions and 2221 deletions

View File

@@ -12,6 +12,9 @@ import {
} from '../../services/publicWorkCode';
import type { CustomWorldProfile } from '../../types';
export const PLATFORM_WORK_NAME_DISPLAY_LIMIT = 8;
export const PLATFORM_WORK_TAG_DISPLAY_LIMIT = 4;
export type PlatformWorldCardLike =
| CustomWorldGalleryCard
| CustomWorldLibraryEntry<CustomWorldProfile>
@@ -33,6 +36,7 @@ export type PlatformPuzzleGalleryCard = {
playCount?: number;
remixCount?: number;
likeCount?: number;
recentPlayCount7d?: number;
visibility: 'published';
publishedAt: string | null;
updatedAt: string;
@@ -53,6 +57,7 @@ export type PlatformBigFishGalleryCard = {
playCount?: number;
remixCount?: number;
likeCount?: number;
recentPlayCount7d?: number;
visibility: 'published';
publishedAt: string | null;
updatedAt: string;
@@ -99,6 +104,7 @@ export function mapPuzzleWorkToPlatformGalleryCard(
playCount: work.playCount ?? 0,
remixCount: work.remixCount ?? 0,
likeCount: work.likeCount ?? 0,
recentPlayCount7d: work.recentPlayCount7d ?? 0,
visibility: 'published',
publishedAt: work.publishedAt,
updatedAt: work.updatedAt,
@@ -114,7 +120,7 @@ export function mapBigFishWorkToPlatformGalleryCard(
profileId: work.sourceSessionId,
publicWorkCode: buildBigFishPublicWorkCode(work.sourceSessionId),
ownerUserId: work.ownerUserId,
authorDisplayName: '大鱼创作者',
authorDisplayName: '大鱼陶泥主',
worldName: work.title,
subtitle: work.subtitle || '大鱼吃小鱼',
summaryText: work.summary,
@@ -123,6 +129,7 @@ export function mapBigFishWorkToPlatformGalleryCard(
playCount: work.playCount ?? 0,
remixCount: work.remixCount ?? 0,
likeCount: work.likeCount ?? 0,
recentPlayCount7d: work.recentPlayCount7d ?? 0,
visibility: 'published',
publishedAt: work.publishedAt ?? work.updatedAt,
updatedAt: work.updatedAt,
@@ -134,7 +141,10 @@ export function resolvePlatformWorldStats(entry: PlatformWorldCardLike) {
playCount: 'playCount' in entry ? (entry.playCount ?? 0) : 0,
remixCount: 'remixCount' in entry ? (entry.remixCount ?? 0) : 0,
likeCount: 'likeCount' in entry ? (entry.likeCount ?? 0) : 0,
recentPlayCount7d:
'recentPlayCount7d' in entry ? (entry.recentPlayCount7d ?? 0) : 0,
publishedAt: entry.publishedAt ?? null,
updatedAt: entry.updatedAt ?? null,
};
}
@@ -158,6 +168,44 @@ export function resolvePlatformWorldLeadPortrait(entry: PlatformWorldCardLike) {
return buildCustomWorldPlayableCharacters(entry.profile)[0]?.portrait ?? '';
}
function limitPlatformDisplayText(value: string, maxLength: number) {
const normalized = value.trim();
const chars = Array.from(normalized);
if (chars.length <= maxLength) {
return normalized;
}
return chars.slice(0, maxLength).join('');
}
export function formatPlatformWorkDisplayName(value: string) {
return limitPlatformDisplayText(value, PLATFORM_WORK_NAME_DISPLAY_LIMIT);
}
export function formatPlatformWorkDisplayTag(value: string) {
return limitPlatformDisplayText(value, PLATFORM_WORK_TAG_DISPLAY_LIMIT);
}
export function formatPlatformWorkDisplayTags(
tags: string[],
limit = tags.length,
) {
return [
...new Set(
tags
.map((tag) => formatPlatformWorkDisplayTag(tag))
.filter(Boolean),
),
].slice(0, limit);
}
export function buildPlatformWorldDisplayTags(
entry: PlatformWorldCardLike,
limit = 3,
) {
return formatPlatformWorkDisplayTags(buildPlatformWorldTags(entry), limit);
}
export function buildPlatformWorldTags(entry: PlatformWorldCardLike) {
if (isBigFishGalleryEntry(entry)) {
return entry.themeTags.length > 0 ? entry.themeTags.slice(0, 3) : ['大鱼'];
@@ -184,20 +232,50 @@ export function buildPlatformWorldTags(entry: PlatformWorldCardLike) {
.slice(0, 3);
}
function parsePlatformWorldDate(value: string) {
const normalized = value.trim();
const numericTimestamp = normalized.match(/^(-?\d+(?:\.\d+)?)(?:Z)?$/u);
if (numericTimestamp?.[1]) {
const rawTimestamp = Number(numericTimestamp[1]);
if (Number.isFinite(rawTimestamp)) {
const absoluteTimestamp = Math.abs(rawTimestamp);
const timestampMs =
absoluteTimestamp >= 1_000_000_000_000_000
? rawTimestamp / 1000
: absoluteTimestamp >= 1_000_000_000_000
? rawTimestamp
: absoluteTimestamp >= 1_000_000_000
? rawTimestamp * 1000
: Number.NaN;
const date = new Date(timestampMs);
if (!Number.isNaN(date.getTime())) {
return date;
}
}
}
const date = new Date(normalized);
return Number.isNaN(date.getTime()) ? null : date;
}
function formatPlatformDateOnly(date: Date) {
const year = date.getUTCFullYear();
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
const day = String(date.getUTCDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
export function formatPlatformWorldTime(value: string | null) {
if (!value) {
return '未发布';
}
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
const date = parsePlatformWorldDate(value);
if (!date) {
return value;
}
return date.toLocaleDateString('zh-CN', {
month: '2-digit',
day: '2-digit',
});
return formatPlatformDateOnly(date);
}
export function resolvePlatformPublicWorkCode(