重构(平台入口): 平台侧与 AGC 壳改用三池余额,退役 legacy 总额写入通道

- 平台入口与钱包 store 不再从充值中心响应读 walletBalance,合计改为按三池派生
- AGC 账户钱包同步:只透传 mudPointBalance,删掉 RechargeContent 的 walletBalance 排除项
- 删除已无生产调用方的 applyLegacyWalletBalanceSnapshot 与对应测试;明细读取失败不再伪造「只有总额」的中间态
- 图片编辑器与平台入口测试 fixture 改为三池形状,钱包面板断言改用「永久泥点 / 月度泥点」

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-10-02 19:03:30 +08:00
parent 3b9d645042
commit 144068187c
16 changed files with 116 additions and 196 deletions
@@ -339,19 +339,18 @@ describe('ImageCanvasEditorView', () => {
updatedAt: null,
});
getPlatformProfileRechargeCenterMock.mockResolvedValue({
walletBalance: 1234,
mudPointBalance: {
totalPoints: 1234,
permanentPoints: 1000,
limitedPoints: 214,
limitedExpiresAt: '2026-07-31T16:00:00Z',
monthlyPoints: 214,
monthlyResetsAt: '2026-07-31T16:00:00Z',
dailyFreePoints: 20,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-07-12T16:00:00Z',
},
membership: {
status: 'normal',
tier: 'normal',
plan: 'normal',
startedAt: null,
expiresAt: null,
updatedAt: null,
@@ -359,11 +358,12 @@ describe('ImageCanvasEditorView', () => {
cycleResetsAt: null,
cycleGrantedPoints: 0,
cycleRemainingPoints: 0,
cyclePeriodDays: 30,
cycleIndex: 1,
cycleCount: 1,
cycleKind: 'monthly',
},
pointProducts: [],
membershipProducts: [],
benefits: [],
membershipPlans: [],
latestOrder: null,
hasPointsRecharged: false,
});
@@ -635,10 +635,9 @@ describe('ImageCanvasEditorView', () => {
usePlatformWalletStore
.getState()
.applyWalletBalanceSnapshot(walletSnapshot!, {
totalPoints: 1234,
permanentPoints: 1000,
limitedPoints: 214,
limitedExpiresAt: '2026-07-31T16:00:00Z',
monthlyPoints: 214,
monthlyResetsAt: '2026-07-31T16:00:00Z',
dailyFreePoints: 20,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-07-12T16:00:00Z',
@@ -703,18 +702,12 @@ describe('ImageCanvasEditorView', () => {
expect(openAccountModal).toHaveBeenCalledTimes(1);
});
it('shows the owner-matched legacy wallet total without inventing breakdown rows', async () => {
it('shows the breakdown read failure without inventing rows', async () => {
const user = userEvent.setup();
usePlatformWalletStore.getState().setWalletOwner('user-1');
const walletSnapshot = usePlatformWalletStore
.getState()
.captureWalletBalanceSnapshot('user-1');
usePlatformWalletStore
.getState()
.applyLegacyWalletBalanceSnapshot(walletSnapshot!, 37);
getPlatformProfileRechargeCenterMock.mockResolvedValue({
walletBalance: 37,
});
getPlatformProfileRechargeCenterMock.mockRejectedValue(
new Error('network down'),
);
render(
<AuthUiContext.Provider
value={createAuthValue({
@@ -736,7 +729,7 @@ describe('ImageCanvasEditorView', () => {
);
const walletButton = await screen.findByRole('button', {
name: '泥点 37',
name: '泥点 --',
});
await user.hover(walletButton);
@@ -745,7 +738,7 @@ describe('ImageCanvasEditorView', () => {
});
expect(within(details).getByText('泥点明细读取失败')).toBeTruthy();
expect(within(details).queryByText('充值中心响应缺少泥点余额')).toBeNull();
expect(within(details).queryByText('不限时泥点')).toBeNull();
expect(within(details).queryByText('永久泥点')).toBeNull();
expect(within(details).queryByText('每日免费泥点')).toBeNull();
});
@@ -786,10 +779,9 @@ describe('ImageCanvasEditorView', () => {
usePlatformWalletStore
.getState()
.applyWalletBalanceSnapshot(walletSnapshot!, {
totalPoints: 1234,
permanentPoints: 1000,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 234,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-07-12T16:00:00Z',
@@ -823,8 +815,8 @@ describe('ImageCanvasEditorView', () => {
const details = await screen.findByRole('dialog', {
name: '泥点账户详情',
});
expect(within(details).getByText('不限时泥点')).toBeTruthy();
expect(within(details).queryByText('限时泥点')).toBeNull();
expect(within(details).getByText('永久泥点')).toBeTruthy();
expect(within(details).getByText('月度泥点')).toBeTruthy();
expect(within(details).getByText('每日免费泥点')).toBeTruthy();
await user.click(within(details).getByRole('button', { name: '使用详情' }));
@@ -17,8 +17,8 @@ import { useImageCanvasContextStore } from './useImageCanvasContextStore.ts';
const walletBreakdown = {
totalPoints: 1_234,
permanentPoints: 1_000,
limitedPoints: 214,
limitedExpiresAt: '2026-07-31T16:00:00Z',
monthlyPoints: 214,
monthlyResetsAt: '2026-07-31T16:00:00Z',
dailyFreePoints: 20,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-07-12T16:00:00Z',
@@ -105,10 +105,6 @@ describe('ImageCanvasTopbarView', () => {
const user = userEvent.setup();
const props = renderTopbar({
walletBalance: 12_345,
walletBreakdown: {
...walletBreakdown,
totalPoints: 12_345,
},
});
const walletChip = screen.getByRole('button', {
name: '泥点 12,345',
@@ -118,8 +114,8 @@ describe('ImageCanvasTopbarView', () => {
await user.hover(walletChip);
const details = screen.getByRole('dialog', { name: '泥点账户详情' });
expect(within(details).getByText('不限时泥点')).toBeTruthy();
expect(within(details).queryByText('限时泥点')).toBeNull();
expect(within(details).getByText('永久泥点')).toBeTruthy();
expect(within(details).getByText('月度泥点')).toBeTruthy();
expect(within(details).getByText('每日免费泥点')).toBeTruthy();
await user.click(within(details).getByRole('button', { name: '使用详情' }));
@@ -77,8 +77,8 @@ describe('PlatformActiveProfileView', () => {
mudPointBalance={{
totalPoints: 108,
permanentPoints: 88,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 20,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-04T00:00:00+08:00',
@@ -15,7 +15,7 @@ import { useCallback, useRef, useState } from 'react';
import type {
AuthUser,
ProfileDashboardSummary,
ProfileMudPointBalance,
ProfileMudPointBalanceView,
} from '@/packages/shared/src';
import profileClockImage from '../../../media/profile/_Image (1).png';
@@ -66,7 +66,7 @@ type PlatformActiveProfileViewProps = {
isLoadingDashboard: boolean;
isLoadingWalletBalance: boolean;
legacyWalletBalance: number | null;
mudPointBalance: ProfileMudPointBalance | null;
mudPointBalance: ProfileMudPointBalanceView | null;
onLogin: () => void;
onOpenApiKeys: () => void;
onOpenCommunity: () => void;
@@ -248,7 +248,7 @@ function formatDashboardCount(value: number) {
}
function formatWalletBalance(
balance: ProfileMudPointBalance | null,
balance: ProfileMudPointBalanceView | null,
legacyBalance: number | null,
isLoading: boolean,
) {
@@ -41,7 +41,13 @@ const profileClientMock = vi.hoisted(() => ({
const profileCenterMock = vi.hoisted(() => ({
isWalletLedgerOpen: false,
rechargeCenter: null as { walletBalance: number } | null,
rechargeCenter: null as {
mudPointBalance?: {
dailyFreePoints: number;
monthlyPoints: number;
permanentPoints: number;
};
} | null,
}));
const gameDistributionMock = vi.hoisted(() => ({
@@ -245,12 +251,10 @@ describe('PlatformEntryActiveFlowShell', () => {
updatedAt: null,
});
profileClientMock.getPlatformProfileRechargeCenter.mockResolvedValue({
walletBalance: 888,
mudPointBalance: {
totalPoints: 207,
permanentPoints: 180,
limitedPoints: 7,
limitedExpiresAt: '2026-08-31T16:00:00Z',
monthlyPoints: 7,
monthlyResetsAt: '2026-08-31T16:00:00Z',
dailyFreePoints: 20,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-04T00:00:00+08:00',
@@ -294,7 +298,14 @@ describe('PlatformEntryActiveFlowShell', () => {
authUiMock.value.canAccessProtectedData = true;
profileClientMock.getPlatformProfileDashboard.mockResolvedValue(null);
profileClientMock.getPlatformProfileRechargeCenter.mockResolvedValue({
walletBalance: 37,
mudPointBalance: {
permanentPoints: 37,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-04T00:00:00+08:00',
},
});
profileCenterMock.isWalletLedgerOpen = true;
@@ -338,10 +349,9 @@ describe('PlatformEntryActiveFlowShell', () => {
profileClientMock.getPlatformProfileDashboard.mockResolvedValue(null);
profileClientMock.getPlatformProfileRechargeCenter.mockResolvedValue({
mudPointBalance: {
totalPoints: 66,
permanentPoints: 66,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-04T00:00:00+08:00',
@@ -379,10 +389,9 @@ describe('PlatformEntryActiveFlowShell', () => {
});
resolveNextOwner({
mudPointBalance: {
totalPoints: 67,
permanentPoints: 67,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-04T00:00:00+08:00',
@@ -406,10 +415,9 @@ describe('PlatformEntryActiveFlowShell', () => {
profileClientMock.getPlatformProfileDashboard.mockResolvedValue(null);
profileClientMock.getPlatformProfileRechargeCenter.mockResolvedValue({
mudPointBalance: {
totalPoints: 10,
permanentPoints: 10,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-04T00:00:00+08:00',
@@ -22,6 +22,7 @@ import { PlatformProfileRechargeModal } from '../../../packages/shared/src/compo
import { PlatformProfileReferralModal } from '../../../packages/shared/src/components/PlatformProfileReferralModal';
import { PlatformProfileWalletLedgerModal } from '../../../packages/shared/src/components/PlatformProfileWalletLedgerModal';
import type { ProfileDashboardSummary } from '../../../packages/shared/src/contracts/runtime';
import { resolveProfileMudPointDisplayTotal } from '../../../packages/shared/src/utils/mudPoints';
import {
hasAppHistoryBackEntry,
pushAppHistoryPath,
@@ -376,7 +377,9 @@ export function PlatformEntryFlowShellImpl({
});
const legacyWalletBalance = walletOwnerMatchesCurrentUser
? (storedLegacyWalletBalance ??
profileCenter.rechargeCenter?.walletBalance ??
resolveProfileMudPointDisplayTotal(
profileCenter.rechargeCenter?.mudPointBalance,
) ??
null)
: null;
@@ -32,10 +32,9 @@ function deferred<T>() {
function mudPointBalance(totalPoints: number) {
return {
totalPoints,
permanentPoints: totalPoints,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-07T00:00:00+08:00',
@@ -52,7 +51,6 @@ function nativeRechargeResponse(totalPoints = 80, orderId = 'order-a') {
expirationCheckedAt: null,
},
center: {
walletBalance: totalPoints,
mudPointBalance: mudPointBalance(totalPoints),
},
wechatNativePayment: {
@@ -76,14 +74,13 @@ describe('usePlatformProfileCenterController recharge fallback', () => {
);
});
test('keeps the response legacy balance when no shared snapshot exists', async () => {
test('keeps the response three-pool balance when no shared snapshot exists', async () => {
usePlatformWalletStore.getState().setWalletOwner('user-a');
profileClientMocks.getPlatformProfileRechargeCenter.mockResolvedValue({
walletBalance: 37,
mudPointBalance: mudPointBalance(37),
membership: null,
pointProducts: [],
membershipProducts: [],
benefits: [],
membershipPlans: [],
latestOrder: null,
hasPointsRecharged: false,
});
@@ -92,7 +89,9 @@ describe('usePlatformProfileCenterController recharge fallback', () => {
act(() => result.current.loadRechargeCenter());
await waitFor(() => {
expect(result.current.rechargeCenter?.walletBalance).toBe(37);
expect(
result.current.rechargeCenter?.mudPointBalance?.permanentPoints,
).toBe(37);
});
});
@@ -198,7 +197,9 @@ describe('usePlatformProfileCenterController recharge fallback', () => {
expect(result.current.submittingRechargeProductId).toBeNull();
expect(result.current.nativeWechatPayment?.orderId).toBe('order-b');
expect(result.current.rechargePaymentResult).toBeNull();
expect(result.current.rechargeCenter?.walletBalance).toBe(90);
expect(
result.current.rechargeCenter?.mudPointBalance?.permanentPoints,
).toBe(90);
expect(usePlatformWalletStore.getState()).toMatchObject({
ownerUserId: 'user-b',
mudPointBalance: mudPointBalance(90),
@@ -19,19 +19,17 @@ vi.mock('../../services/platform-entry/platformProfileClient', async () => {
});
const rechargeCenter: ProfileRechargeCenterResponse = {
walletBalance: 100,
mudPointBalance: {
totalPoints: 100,
permanentPoints: 100,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 0,
dailyFreeResetsAt: null,
},
membership: {
status: 'normal',
tier: 'normal',
plan: 'normal',
startedAt: null,
expiresAt: null,
updatedAt: null,
@@ -39,11 +37,12 @@ const rechargeCenter: ProfileRechargeCenterResponse = {
cycleResetsAt: null,
cycleGrantedPoints: 0,
cycleRemainingPoints: 0,
cyclePeriodDays: 30,
cycleIndex: 1,
cycleCount: 1,
cycleKind: 'monthly',
},
pointProducts: [],
membershipProducts: [],
benefits: [],
membershipPlans: [],
latestOrder: null,
hasPointsRecharged: false,
};
@@ -1864,8 +1864,6 @@ export function usePlatformProfileCenterController({
}
return {
...rechargeCenter,
walletBalance:
mudPointBalance?.totalPoints ?? rechargeCenter.walletBalance,
mudPointBalance: mudPointBalance ?? rechargeCenter.mudPointBalance,
};
}, [mudPointBalance, rechargeCenter, walletOwnerMatchesCurrentUser]);
+2 -4
View File
@@ -22,12 +22,10 @@ beforeEach(() => {
vi.clearAllMocks();
usePlatformWalletStore.getState().resetWalletBalance();
profileClientMocks.getPlatformProfileRechargeCenter.mockResolvedValue({
walletBalance: 42,
mudPointBalance: {
totalPoints: 42,
permanentPoints: 42,
limitedPoints: 0,
limitedExpiresAt: null,
monthlyPoints: 0,
monthlyResetsAt: null,
dailyFreePoints: 0,
dailyFreeResetPoints: 20,
dailyFreeResetsAt: '2026-08-08T00:00:00+08:00',