refactor: 收口个人数据展示模型

This commit is contained in:
2026-06-03 17:30:28 +08:00
parent 4f59a0e791
commit a178942033
6 changed files with 250 additions and 72 deletions

View File

@@ -134,6 +134,13 @@ import {
import { getInitialPlatformDesktopLayout } from '../platform-entry/platformEntryResponsive';
import { ResolvedAssetImage } from '../ResolvedAssetImage';
import { RpgEntryBrandLogo } from './RpgEntryBrandLogo';
import {
buildProfileDashboardPresentation,
formatCompactPlayTime,
formatPlayedWorkId,
formatPlayedWorkType,
formatTotalPlayTimeHours,
} from './rpgEntryProfileDashboardPresentation';
import {
buildProfileTaskCardSummary,
buildProfileTaskProgressLabel,
@@ -1758,46 +1765,6 @@ function formatSnapshotTime(value: string | null | undefined) {
});
}
function formatCompactPlayTime(playTimeMs: number) {
const totalMinutes = Math.max(0, Math.floor(playTimeMs / 60000));
const days = totalMinutes / 1440;
if (days >= 10) {
return `${Math.floor(days)}`;
}
if (days >= 1) {
return `${days.toFixed(days >= 3 ? 0 : 1)}`;
}
const hours = totalMinutes / 60;
if (hours >= 1) {
return `${hours.toFixed(hours >= 10 ? 0 : 1)}小时`;
}
return `${Math.max(0, totalMinutes)}`;
}
// “游戏时长”固定使用小时,避免短时长切到分钟或长时长切到天。
function formatTotalPlayTimeHours(playTimeMs: number) {
const roundedHours = Math.max(0, Math.round(playTimeMs / 360000) / 10);
return `${roundedHours.toLocaleString('zh-CN', {
maximumFractionDigits: 1,
})}小时`;
}
function formatDashboardCount(value: number) {
const normalizedValue = Math.max(0, Math.round(value));
if (normalizedValue >= 100000000) {
return `${(normalizedValue / 100000000).toFixed(1)}亿`;
}
if (normalizedValue >= 10000) {
return `${(normalizedValue / 10000).toFixed(1)}`;
}
return normalizedValue.toLocaleString('zh-CN');
}
function normalizeProfileInviteQueryCode(value: string | null | undefined) {
return (value ?? '')
.trim()
@@ -1816,27 +1783,6 @@ function readProfileInviteCodeFromLocationSearch(search: string) {
return '';
}
function formatPlayedWorkType(value: string | null | undefined) {
const normalizedValue = (value ?? '').toLowerCase();
if (normalizedValue === 'puzzle') {
return '拼图';
}
if (normalizedValue === 'match3d' || normalizedValue === 'match_3d') {
return '抓鹅';
}
if (normalizedValue === 'square-hole' || normalizedValue === 'square_hole') {
return '方洞';
}
if (normalizedValue === 'big_fish' || normalizedValue === 'big-fish') {
return '大鱼';
}
return 'RPG';
}
function formatPlayedWorkId(work: ProfilePlayedWorkSummary) {
return work.profileId?.trim() || work.worldKey;
}
function buildPublicUserCode(user: AuthUser | null | undefined) {
if (user?.publicUserCode?.trim()) {
return user.publicUserCode.trim();
@@ -3839,11 +3785,11 @@ export function RpgEntryHomeView({
const activeLegalDocument = activeLegalDocumentId
? getLegalDocument(activeLegalDocumentId)
: null;
const remainingNarrativeCoins = profileDashboard?.walletBalance ?? 0;
const totalPlayTime = formatTotalPlayTimeHours(
profileDashboard?.totalPlayTimeMs ?? 0,
const profileDashboardPresentation = useMemo(
() => buildProfileDashboardPresentation(profileDashboard),
[profileDashboard],
);
const playedWorkCount = profileDashboard?.playedWorldCount ?? 0;
const remainingNarrativeCoins = profileDashboardPresentation.walletBalance;
const profileTaskCardSummary = useMemo(
() => buildProfileTaskCardSummary(taskCenter),
[taskCenter],
@@ -5960,7 +5906,7 @@ export function RpgEntryHomeView({
<ProfileStatCard
cardKey="wallet"
label="泥点余额"
value={formatDashboardCount(remainingNarrativeCoins)}
value={profileDashboardPresentation.walletBalanceLabel}
icon={Coins}
imageSrc={profilePointImage}
onClick={openWalletLedgerPanel}
@@ -5968,7 +5914,7 @@ export function RpgEntryHomeView({
<ProfileStatCard
cardKey="playTime"
label="累计游戏时长"
value={totalPlayTime}
value={profileDashboardPresentation.totalPlayTimeLabel}
icon={Clock3}
imageSrc={profileClockImage}
onClick={onOpenProfileDashboardCard}
@@ -5976,7 +5922,7 @@ export function RpgEntryHomeView({
<ProfileStatCard
cardKey="playedWorks"
label="已玩游戏数量"
value={`${formatDashboardCount(playedWorkCount)}`}
value={profileDashboardPresentation.playedWorkCountLabel}
icon={BookOpen}
imageSrc={profileGamepadImage}
onClick={onOpenProfileDashboardCard}
@@ -6612,12 +6558,16 @@ export function RpgEntryHomeView({
type="button"
onClick={openUserSurface}
className="platform-mobile-create-wallet-chip inline-flex shrink-0 items-center gap-1.5 rounded-full border border-[#f0cfae] bg-[#fff5eb] px-2.5 py-1.5 text-xs font-black text-[#b65f2c] shadow-[0_10px_22px_rgba(174,111,73,0.12)]"
aria-label={`${formatDashboardCount(remainingNarrativeCoins)}泥点`}
aria-label={
profileDashboardPresentation.walletBalanceWithUnitLabel
}
>
<span className="grid h-6 w-6 place-items-center rounded-full bg-[#ffe0ab] text-[#cf7b34]">
<Coins className="h-3.5 w-3.5" />
</span>
<span>{formatDashboardCount(remainingNarrativeCoins)}</span>
<span>
{profileDashboardPresentation.walletBalanceWithUnitLabel}
</span>
</button>
) : !isAuthenticated ? (
<button
@@ -6778,12 +6728,16 @@ export function RpgEntryHomeView({
type="button"
onClick={openUserSurface}
className="platform-desktop-create-wallet-chip platform-desktop-search inline-flex items-center gap-2 px-3 py-2.5 text-xs font-black text-[#b65f2c]"
aria-label={`${formatDashboardCount(remainingNarrativeCoins)}泥点`}
aria-label={
profileDashboardPresentation.walletBalanceWithUnitLabel
}
>
<span className="grid h-7 w-7 place-items-center rounded-full bg-[#ffe0ab] text-[#cf7b34]">
<Coins className="h-3.5 w-3.5" />
</span>
<span>{formatDashboardCount(remainingNarrativeCoins)}</span>
<span>
{profileDashboardPresentation.walletBalanceWithUnitLabel}
</span>
</button>
) : null}
<button