109 lines
3.1 KiB
TypeScript
109 lines
3.1 KiB
TypeScript
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: '账户同步',
|
|
asset_operation_consume: '资产操作消耗',
|
|
asset_operation_refund: '资产操作退回',
|
|
redeem_code_reward: '兑换码奖励',
|
|
puzzle_author_incentive_claim: '拼图作者奖励',
|
|
daily_task_reward: '每日任务奖励',
|
|
} satisfies Record<ProfileWalletLedgerEntry['sourceType'], string>;
|
|
|
|
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)}`;
|
|
}
|
|
|
|
export function buildRechargeProductValueLabel(product: ProfileRechargeProduct) {
|
|
if (product.kind === 'membership') {
|
|
return `${product.durationDays}天`;
|
|
}
|
|
|
|
return `${product.pointsAmount}${
|
|
product.bonusPoints > 0 ? `+${product.bonusPoints}` : ''
|
|
}泥点`;
|
|
}
|
|
|
|
export function buildMembershipLabel(
|
|
membership: ProfileMembership | null | undefined,
|
|
formatTime: (value: string) => string,
|
|
) {
|
|
if (membership?.status !== 'active') {
|
|
return '普通用户';
|
|
}
|
|
|
|
return membership.expiresAt
|
|
? `会员至 ${formatTime(membership.expiresAt)}`
|
|
: '会员已生效';
|
|
}
|