Files
Genarrative/src/components/platform-entry/platformProfileFundsModel.ts
T
kdletters 9c9c8f468a 恢复平台个人页并阻断旧业务回流
恢复创作、项目、我的平台侧栏与现役搜索
恢复全宽个人页及资料编辑、充值兑换、社区反馈和 API Key 入口
迁移平台资料、钱包和设置客户端并移除旧创作依赖
新增 Vite 与 ESLint 退役模块门禁并补齐界面和搜索测试
同步旧创作退役方案、平台入口决策与踩坑记录
2026-07-18 17:29:06 +08:00

128 lines
3.8 KiB
TypeScript

import type {
ProfileWalletLedgerEntry,
ProfileWalletLedgerResponse,
} from '../../../packages/shared/src/contracts/runtime';
const PLATFORM_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: '资产操作退回',
recharge_refund_recovery: '充值退款追回',
redeem_code_reward: '兑换码奖励',
puzzle_author_incentive_claim: '拼图作者奖励',
daily_task_reward: '每日任务奖励',
} satisfies Record<ProfileWalletLedgerEntry['sourceType'], string>;
export type PlatformWalletLedgerEntryPresentation = {
amountLabel: string;
balanceLabel: string;
createdAt: string;
id: string;
isIncome: boolean;
sourceLabel: string;
};
export type PlatformWalletLedgerPresentation = {
balance: number;
balanceLabel: string;
entries: PlatformWalletLedgerEntryPresentation[];
};
function getPlatformWalletLedgerSourceLabel(
sourceType: string | null | undefined,
) {
const normalizedSourceType = sourceType?.trim() ?? '';
if (!normalizedSourceType) {
return '未知来源';
}
return (
PLATFORM_WALLET_LEDGER_SOURCE_LABELS[
normalizedSourceType as ProfileWalletLedgerEntry['sourceType']
] ?? normalizedSourceType
);
}
function buildPlatformWalletLedgerEntryPresentation(
entry: ProfileWalletLedgerEntry,
): PlatformWalletLedgerEntryPresentation {
return {
amountLabel:
entry.amountDelta > 0 ? `+${entry.amountDelta}` : `${entry.amountDelta}`,
balanceLabel: `余额 ${entry.balanceAfter}`,
createdAt: entry.createdAt,
id: entry.id,
isIncome: entry.amountDelta > 0,
sourceLabel: getPlatformWalletLedgerSourceLabel(entry.sourceType),
};
}
export function buildPlatformWalletLedgerPresentation(
ledger: ProfileWalletLedgerResponse | null,
fallbackBalance: number,
): PlatformWalletLedgerPresentation {
const entries = ledger?.entries ?? [];
const balance = entries[0]?.balanceAfter ?? fallbackBalance;
return {
balance,
balanceLabel: `${balance}泥点`,
entries: entries.map(buildPlatformWalletLedgerEntryPresentation),
};
}
export function formatPlatformRechargePrice(priceCents: number) {
const yuan = priceCents / 100;
return `¥${Number.isInteger(yuan) ? yuan.toFixed(0) : yuan.toFixed(2)}`;
}
function parsePlatformProfileDate(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;
}
export function formatPlatformProfileTime(value: string | null) {
if (!value) {
return '未记录';
}
const date = parsePlatformProfileDate(value);
if (!date) {
return value;
}
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}`;
}