import type { ProfileMembership, ProfileRechargeProduct, ProfileWalletLedgerEntry, ProfileWalletLedgerResponse, } from '../../../packages/shared/src/contracts/runtime'; const PROFILE_WALLET_LEDGER_SOURCE_LABELS = { new_user_registration_reward: '注册赠送', points_recharge: '泥点充值', invite_inviter_reward: '邀请奖励', invite_invitee_reward: '填写邀请码奖励', snapshot_sync: '账户同步', membership_period_grant: '会员周期发放', membership_period_reset: '会员周期重置', daily_free_grant: '每日免费发放', daily_free_reset: '每日免费重置', asset_operation_consume: '资产操作消耗', asset_operation_refund: '资产操作退回', redeem_code_reward: '兑换码奖励', puzzle_author_incentive_claim: '拼图作者奖励', daily_task_reward: '每日任务奖励', } satisfies Record; export type ProfileWalletLedgerEntryPresentation = { amountLabel: string; balanceLabel: string; createdAt: string; id: string; isIncome: boolean; sourceLabel: string; }; export type ProfileWalletLedgerPresentation = { balance: number; balanceLabel: string; entries: ProfileWalletLedgerEntryPresentation[]; }; export function getWalletLedgerSourceLabel( sourceType: string | null | undefined, ) { const normalizedSourceType = sourceType?.trim() ?? ''; if (!normalizedSourceType) { return '未知来源'; } return ( PROFILE_WALLET_LEDGER_SOURCE_LABELS[ normalizedSourceType as ProfileWalletLedgerEntry['sourceType'] ] ?? normalizedSourceType ); } export function formatWalletLedgerAmount(amountDelta: number) { return amountDelta > 0 ? `+${amountDelta}` : `${amountDelta}`; } export function buildWalletLedgerEntryPresentation( entry: ProfileWalletLedgerEntry, ): ProfileWalletLedgerEntryPresentation { return { amountLabel: formatWalletLedgerAmount(entry.amountDelta), balanceLabel: `余额 ${entry.balanceAfter}`, createdAt: entry.createdAt, id: entry.id, isIncome: entry.amountDelta > 0, sourceLabel: getWalletLedgerSourceLabel(entry.sourceType), }; } export function buildWalletLedgerPresentation( ledger: ProfileWalletLedgerResponse | null, fallbackBalance: number, ): ProfileWalletLedgerPresentation { const entries = ledger?.entries ?? []; const balance = entries[0]?.balanceAfter ?? fallbackBalance; return { balance, balanceLabel: `${balance}泥点`, entries: entries.map(buildWalletLedgerEntryPresentation), }; } export function formatRechargePrice(priceCents: number) { const yuan = priceCents / 100; return `¥${Number.isInteger(yuan) ? yuan.toFixed(0) : yuan.toFixed(2)}`; } function formatMembershipPeriodPrefix(periodDays: number) { if (periodDays === 30) { return '每月'; } if (periodDays === 7) { return '每周'; } if (periodDays > 0) { return `每${periodDays}天`; } return '每周期'; } export function buildRechargeProductValueLabel(product: ProfileRechargeProduct) { if (product.kind === 'membership') { const membershipPeriodPoints = product.membershipPeriodPoints; const membershipPeriodDays = product.membershipPeriodDays > 0 ? product.membershipPeriodDays : product.durationDays; return membershipPeriodPoints > 0 ? `${formatMembershipPeriodPrefix(membershipPeriodDays)}${membershipPeriodPoints}泥点` : `${product.durationDays}天`; } return `${product.pointsAmount}${ product.bonusPoints > 0 ? `+${product.bonusPoints}` : '' }泥点`; } export function getMembershipTierLabel(tier: ProfileMembership['tier']) { switch (tier) { case 'starter': return 'Starter'; case 'basic': return 'Basic'; case 'pro': return 'Pro'; case 'ultimate': return 'Ultimate'; case 'month': return '月卡'; case 'season': return '季卡'; case 'year': return '年卡'; default: return '普通用户'; } } export function buildMembershipLabel( membership: ProfileMembership | null | undefined, formatTime: (value: string) => string, ) { if (membership?.status !== 'active') { return '普通用户'; } const tierLabel = membership.tier === 'normal' ? '会员' : getMembershipTierLabel(membership.tier); const resetLabel = membership.cycleResetsAt ? ` · ${formatTime(membership.cycleResetsAt)}重置` : ''; if (membership.tier === 'normal') { return membership.expiresAt ? `会员至 ${formatTime(membership.expiresAt)}${resetLabel}` : `会员已生效${resetLabel}`; } return membership.expiresAt ? `${tierLabel} 至 ${formatTime(membership.expiresAt)}${resetLabel}` : `${tierLabel} 已生效${resetLabel}`; } export function buildMembershipCycleLabel( membership: ProfileMembership | null | undefined, formatTime: (value: string) => string, ) { if (membership?.status !== 'active') { return '普通用户'; } if (membership.cycleRemainingPoints > 0) { const resetLabel = membership.cycleResetsAt ? ` · ${formatTime(membership.cycleResetsAt)}重置` : ''; return `本周期剩余 ${membership.cycleRemainingPoints} 泥点${resetLabel}`; } return buildMembershipLabel(membership, formatTime); }