优化画布泥点入口
让画布顶部泥点余额按钮复用创作页充值和兑换码入口 抽取账户充值支付结果与确认弹窗组件供创作页和画布页共用 补充画布泥点入口回归测试和编辑器技术文档
This commit is contained in:
@@ -9,10 +9,11 @@
|
||||
- 主站新增 `/editor/canvas` 路由,进入独立图片画布编辑器阶段。
|
||||
- 主站新增 `/project` 项目页,从“我的”页项目入口进入,展示当前用户所有图片画布工程;点击项目进入 `/editor/canvas?projectid=<projectId>`。
|
||||
- 创作 Tab 顶部提供编辑器入口,入口只负责跳转,不参与玩法创作链路。
|
||||
- 编辑器顶部栏采用紧凑高度,项目标题和重命名入口贴近返回项目按钮;右侧常驻展示当前账号泥点余额,样式对齐创作主页顶部钱包 chip。
|
||||
- 编辑器顶部栏采用紧凑高度,项目标题和重命名入口贴近返回项目按钮;右侧常驻展示当前账号泥点余额,样式对齐创作主页顶部钱包 chip,点击后复用创作主页右上角泥点入口的账户充值 / 兑换码弹窗与支付确认反馈。
|
||||
- 编辑器左侧为图片素材栏,可展开 / 收起;移动端优先保持素材栏可折叠。
|
||||
- 中央画布支持背景拖拽平移、滚轮缩放、缩放百分比菜单、显示所有元素和固定比例缩放。
|
||||
- 画布左下角提供 Lovart 式状态控件:背景色圆点、素材 / 图层入口、小地图开关;小地图显示图层缩略分布和当前视口框,点击小地图执行显示所有元素。
|
||||
- 画布 chrome 的边框、hover / 选中态、吸附 / 框选参考线、生成类按钮和通用 active 控件使用陶泥儿暖色主题(以 `--platform-accent`、陶土橙主按钮和深棕文字为基准),不得回退为黑色或蓝色主题;元素类型自身的识别色可继续保留。
|
||||
- 画布中的图片可展示、悬浮显示图片 Resolution 尺寸与边框,点击后在图片上方显示浮动工具栏;浮动工具栏只保留当前可执行的编辑动作,不放调整 / 复制 / 删除 / 查看信息占位按钮。图片右上角素材类型标签、图片信息角标和悬浮尺寸标签在画布缩小时必须按 viewport 反向缩放,保持屏幕可读尺寸;无 `assetKind` 的素材右上角显示 `未知` 标签,点击标签弹出独立标签选择菜单并可写回图层 `assetKind`,不能触发图层选择 / 拖拽事件;图片信息角标使用圆形 `i` 图标,不使用中括号或花括号样式。图片不再维护独立展示 `Size` 字段,画布显示宽高统一取 `originalWidth/originalHeight`(图片信息中的 `Resolution`)。
|
||||
- 默认工具为选择模式;底部工具栏采用 AI 画布工作流工具组:选择、抓手、上传、生成图片、生成视频、生成音乐、生成规范、生成角色形象、生成图标素材、生成 UI 设计图。底部栏不再展示文字工具、形状标注工具和导出工具;上传与生成图片之间、生成音乐与生成规范之间各有一个半图标高度分割线。
|
||||
- 鼠标中键拖拽始终平移画布;长按 Space 临时进入抓手模式,松开后恢复原工具。
|
||||
|
||||
@@ -3371,7 +3371,6 @@ describe('ImageCanvasEditorView generation integration', () => {
|
||||
if (!metadataCornerButton) {
|
||||
throw new Error('metadata corner button should exist');
|
||||
}
|
||||
expect(metadataCornerButton.className).toContain('bg-black/55');
|
||||
expect(metadataCornerButton.className).toContain(
|
||||
'image-canvas-editor__metadata-corner',
|
||||
);
|
||||
|
||||
@@ -109,6 +109,7 @@ function createTopbarProps(): ImageCanvasTopbarViewProps {
|
||||
resetProjectRenameError: vi.fn(),
|
||||
exportCanvasAssets: vi.fn(),
|
||||
onOpenShortcuts: vi.fn(),
|
||||
onOpenWallet: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,37 @@ describe('ImageCanvasEditorView', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('opens the same account wallet entry from the canvas topbar mud point button', async () => {
|
||||
render(
|
||||
<AuthUiContext.Provider
|
||||
value={createAuthValue({
|
||||
user: {
|
||||
id: 'user-1',
|
||||
publicUserCode: 'U001',
|
||||
displayName: '测试用户',
|
||||
avatarUrl: null,
|
||||
phoneNumberMasked: '138****0000',
|
||||
loginMethod: 'password',
|
||||
bindingStatus: 'active',
|
||||
wechatBound: false,
|
||||
},
|
||||
canAccessProtectedData: true,
|
||||
})}
|
||||
>
|
||||
<ImageCanvasEditorView />
|
||||
</AuthUiContext.Provider>,
|
||||
);
|
||||
|
||||
const walletButton = await screen.findByRole('button', {
|
||||
name: '泥点余额 1,234泥点',
|
||||
});
|
||||
|
||||
fireEvent.click(walletButton);
|
||||
|
||||
expect(await screen.findByRole('dialog', { name: '兑换码' })).toBeTruthy();
|
||||
expect(screen.getByPlaceholderText('输入兑换码')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('opens the login modal immediately when entering the editor while logged out', async () => {
|
||||
const openLoginModal = vi.fn();
|
||||
|
||||
@@ -329,6 +360,7 @@ describe('ImageCanvasEditorView', () => {
|
||||
originalHeight: 1024,
|
||||
zIndex: 3,
|
||||
sourceType: 'generated',
|
||||
sourceResourceId: 'resource-generated',
|
||||
prompt: '明亮主视觉',
|
||||
model: 'gpt-image-2',
|
||||
provider: 'VectorEngine',
|
||||
@@ -347,6 +379,7 @@ describe('ImageCanvasEditorView', () => {
|
||||
originalHeight: 120,
|
||||
zIndex: 4,
|
||||
sourceType: 'generated',
|
||||
sourceResourceId: 'resource-failed',
|
||||
},
|
||||
],
|
||||
resources: [],
|
||||
@@ -376,7 +409,8 @@ describe('ImageCanvasEditorView', () => {
|
||||
});
|
||||
const originalFetch = globalThis.fetch;
|
||||
const fetchMock = vi.fn(async (url: string) => {
|
||||
if (url === '/generated-ok.png') {
|
||||
const pathname = new URL(url, 'http://localhost').pathname;
|
||||
if (pathname === '/generated-ok.png') {
|
||||
return new Response(new Blob(['generated'], { type: 'image/png' }));
|
||||
}
|
||||
return new Response(null, { status: 404 });
|
||||
|
||||
@@ -14,9 +14,17 @@ import {
|
||||
type EditorAssetSnapshot,
|
||||
loadEditorGenerationPricing,
|
||||
} from '../../services/image-editor/editorProjectClient';
|
||||
import { shouldShowRechargeEntry } from '../../services/payment/paymentPlatform';
|
||||
import { getPlatformProfileDashboard } from '../../services/platform-entry/platformProfileClient';
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import { PlatformDangerConfirmDialog } from '../common/PlatformDangerConfirmDialog';
|
||||
import { PlatformProfileRechargeModal } from '../platform-entry/PlatformProfileRechargeModal';
|
||||
import { PlatformProfileRewardCodeRedeemModal } from '../platform-entry/PlatformProfileRewardCodeRedeemModal';
|
||||
import {
|
||||
PlatformRechargePaymentConfirmationMask,
|
||||
PlatformRechargePaymentResultDialog,
|
||||
} from '../platform-entry/PlatformRechargePaymentStatusDialogs';
|
||||
import { usePlatformProfileCenterController } from '../platform-entry/usePlatformProfileCenterController';
|
||||
import { formatDashboardCount } from '../rpg-entry/rpgEntryProfileDashboardPresentation';
|
||||
import {
|
||||
canvasAssetKindOrNull,
|
||||
@@ -93,6 +101,7 @@ export function ImageCanvasEditorView() {
|
||||
const publicationReferenceButtonRef = useRef<HTMLButtonElement | null>(null);
|
||||
const iconSpecButtonRef = useRef<HTMLButtonElement | null>(null);
|
||||
const selectedLayerIdRef = useRef<string | null>(null);
|
||||
const showRechargeEntry = shouldShowRechargeEntry();
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
@@ -167,6 +176,56 @@ export function ImageCanvasEditorView() {
|
||||
},
|
||||
[],
|
||||
);
|
||||
const refreshEditorWalletBalance = useCallback(() => {
|
||||
if (!authUiRef.current?.canAccessProtectedData || !authUiRef.current.user) {
|
||||
return;
|
||||
}
|
||||
void getPlatformProfileDashboard({
|
||||
authImpact: 'local',
|
||||
skipRefresh: true,
|
||||
notifyAuthStateChange: false,
|
||||
clearAuthOnUnauthorized: false,
|
||||
})
|
||||
.then((dashboard) => {
|
||||
setWalletBalanceLabel(
|
||||
`${formatDashboardCount(dashboard.walletBalance)}泥点`,
|
||||
);
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}, []);
|
||||
const {
|
||||
activeRechargeTab,
|
||||
buyRechargeProduct,
|
||||
confirmNativeWechatPayment,
|
||||
isLoadingRechargeCenter,
|
||||
isRechargeOpen,
|
||||
isRewardCodeOpen,
|
||||
isSubmittingRewardCode,
|
||||
loadRechargeCenter,
|
||||
nativeWechatPayment,
|
||||
openRechargeOrRewardCodeModal,
|
||||
rechargeCenter,
|
||||
rechargeError,
|
||||
rechargePaymentResult,
|
||||
rewardCodeError,
|
||||
rewardCodeInput,
|
||||
rewardCodeSuccess,
|
||||
setActiveRechargeTab,
|
||||
setIsRechargeOpen,
|
||||
setIsRewardCodeOpen,
|
||||
setRechargePaymentResult,
|
||||
setRewardCodeInput,
|
||||
submittingRechargeProductId,
|
||||
submitRewardCode,
|
||||
wechatRechargeOrderConfirmationState,
|
||||
} = usePlatformProfileCenterController({
|
||||
activeTab: 'editor-canvas',
|
||||
isAuthenticated: Boolean(authUi?.user),
|
||||
showRechargeEntry,
|
||||
onRechargeSuccess: refreshEditorWalletBalance,
|
||||
requestLogin: () => authUiRef.current?.openLoginModal(),
|
||||
currentUser: authUi?.user ?? null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!authUi || authUi.user || authUi.canAccessProtectedData) {
|
||||
@@ -1256,6 +1315,7 @@ export function ImageCanvasEditorView() {
|
||||
resetProjectRenameError,
|
||||
exportCanvasAssets,
|
||||
onOpenShortcuts: () => setIsShortcutDialogOpen(true),
|
||||
onOpenWallet: openRechargeOrRewardCodeModal,
|
||||
};
|
||||
const stageProps = {
|
||||
canvasViewportRef,
|
||||
@@ -1400,6 +1460,43 @@ export function ImageCanvasEditorView() {
|
||||
open={isShortcutDialogOpen}
|
||||
onClose={() => setIsShortcutDialogOpen(false)}
|
||||
/>
|
||||
{isRewardCodeOpen ? (
|
||||
<PlatformProfileRewardCodeRedeemModal
|
||||
value={rewardCodeInput}
|
||||
isSubmitting={isSubmittingRewardCode}
|
||||
error={rewardCodeError}
|
||||
success={rewardCodeSuccess}
|
||||
onChange={setRewardCodeInput}
|
||||
onSubmit={submitRewardCode}
|
||||
onClose={() => setIsRewardCodeOpen(false)}
|
||||
/>
|
||||
) : null}
|
||||
{isRechargeOpen ? (
|
||||
<PlatformProfileRechargeModal
|
||||
center={rechargeCenter}
|
||||
isLoading={isLoadingRechargeCenter}
|
||||
error={rechargeError}
|
||||
submittingProductId={submittingRechargeProductId}
|
||||
nativePayment={nativeWechatPayment}
|
||||
activeTab={activeRechargeTab}
|
||||
onTabChange={setActiveRechargeTab}
|
||||
onClose={() => setIsRechargeOpen(false)}
|
||||
onRetry={loadRechargeCenter}
|
||||
onBuy={buyRechargeProduct}
|
||||
onConfirmNativePayment={confirmNativeWechatPayment}
|
||||
/>
|
||||
) : null}
|
||||
{rechargePaymentResult ? (
|
||||
<PlatformRechargePaymentResultDialog
|
||||
result={rechargePaymentResult}
|
||||
onClose={() => setRechargePaymentResult(null)}
|
||||
/>
|
||||
) : null}
|
||||
{wechatRechargeOrderConfirmationState ? (
|
||||
<PlatformRechargePaymentConfirmationMask
|
||||
orderId={wechatRechargeOrderConfirmationState.orderId}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ function renderTopbar(
|
||||
resetProjectRenameError: vi.fn(),
|
||||
exportCanvasAssets: vi.fn(),
|
||||
onOpenShortcuts: vi.fn(),
|
||||
onOpenWallet: vi.fn(),
|
||||
...overrides,
|
||||
};
|
||||
|
||||
@@ -77,16 +78,21 @@ describe('ImageCanvasTopbarView', () => {
|
||||
});
|
||||
|
||||
it('shows the current mud point balance in the topbar', () => {
|
||||
renderTopbar({
|
||||
const props = renderTopbar({
|
||||
walletBalanceLabel: '1.2万泥点',
|
||||
});
|
||||
|
||||
const walletChip = screen.getByLabelText('泥点余额 1.2万泥点');
|
||||
const walletChip = screen.getByRole('button', {
|
||||
name: '泥点余额 1.2万泥点',
|
||||
});
|
||||
|
||||
expect(walletChip.textContent).toBe('1.2万泥点');
|
||||
expect(walletChip.querySelector('img')?.getAttribute('src')).toBe(
|
||||
'/creation-home/topbar-wallet.png',
|
||||
);
|
||||
|
||||
fireEvent.click(walletChip);
|
||||
|
||||
expect(props.onOpenWallet).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('submits, resets, and cancels project rename edits', () => {
|
||||
@@ -132,6 +138,7 @@ describe('ImageCanvasTopbarView', () => {
|
||||
resetProjectRenameError={vi.fn()}
|
||||
exportCanvasAssets={exportCanvasAssets}
|
||||
onOpenShortcuts={vi.fn()}
|
||||
onOpenWallet={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -163,6 +170,7 @@ describe('ImageCanvasTopbarView', () => {
|
||||
resetProjectRenameError={vi.fn()}
|
||||
exportCanvasAssets={exportCanvasAssets}
|
||||
onOpenShortcuts={vi.fn()}
|
||||
onOpenWallet={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ export type ImageCanvasTopbarViewProps = {
|
||||
resetProjectRenameError: () => void;
|
||||
exportCanvasAssets: () => void | Promise<void>;
|
||||
onOpenShortcuts: () => void;
|
||||
onOpenWallet: () => void;
|
||||
};
|
||||
|
||||
export function ImageCanvasTopbarView({
|
||||
@@ -53,6 +54,7 @@ export function ImageCanvasTopbarView({
|
||||
resetProjectRenameError,
|
||||
exportCanvasAssets,
|
||||
onOpenShortcuts,
|
||||
onOpenWallet,
|
||||
}: ImageCanvasTopbarViewProps) {
|
||||
const hasExportableLayer = layers.some(
|
||||
(layer) => layer.src.trim().length > 0,
|
||||
@@ -167,8 +169,10 @@ export function ImageCanvasTopbarView({
|
||||
{assetExportStatus.message}
|
||||
</PlatformStatusMessage>
|
||||
) : null}
|
||||
<div
|
||||
<button
|
||||
type="button"
|
||||
className="image-canvas-editor__wallet-chip"
|
||||
onClick={onOpenWallet}
|
||||
aria-label={walletAriaLabel}
|
||||
aria-busy={isWalletBalanceLoading}
|
||||
aria-live="polite"
|
||||
@@ -180,7 +184,7 @@ export function ImageCanvasTopbarView({
|
||||
draggable={false}
|
||||
/>
|
||||
<span>{walletDisplayLabel}</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { PlatformAcknowledgeStatusDialog } from '../common/PlatformAcknowledgeStatusDialog';
|
||||
import { PlatformStatusDialog } from '../common/PlatformStatusDialog';
|
||||
import type { RechargePaymentResult } from './usePlatformProfileCenterController';
|
||||
|
||||
const PROFILE_MODAL_OVERLAY_CLASS =
|
||||
'platform-modal-backdrop !items-center !justify-center !px-4 !py-6';
|
||||
|
||||
export function PlatformRechargePaymentResultDialog({
|
||||
result,
|
||||
onClose,
|
||||
}: {
|
||||
result: RechargePaymentResult;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const status =
|
||||
result.kind === 'success'
|
||||
? 'success'
|
||||
: result.kind === 'pending'
|
||||
? 'loading'
|
||||
: result.kind === 'cancel'
|
||||
? 'cancel'
|
||||
: 'error';
|
||||
|
||||
return (
|
||||
<PlatformAcknowledgeStatusDialog
|
||||
status={status}
|
||||
title={result.title}
|
||||
description={result.message}
|
||||
onClose={onClose}
|
||||
actionSurface="profile"
|
||||
zIndexClassName="z-[90]"
|
||||
overlayClassName={PROFILE_MODAL_OVERLAY_CLASS}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function PlatformRechargePaymentConfirmationMask({
|
||||
orderId,
|
||||
}: {
|
||||
orderId: string;
|
||||
}) {
|
||||
return (
|
||||
<PlatformStatusDialog
|
||||
status="confirming"
|
||||
title="正在确认支付"
|
||||
description={`订单 ${orderId} 正在同步到账状态,请先停留在当前页面。`}
|
||||
onClose={() => undefined}
|
||||
closeDisabled
|
||||
zIndexClassName="z-[95]"
|
||||
overlayClassName={PROFILE_MODAL_OVERLAY_CLASS}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -74,7 +74,6 @@ import {
|
||||
import { shouldShowRechargeEntry } from '../../services/payment/paymentPlatform';
|
||||
import type { CustomWorldProfile } from '../../types';
|
||||
import { useAuthUi } from '../auth/AuthUiContext';
|
||||
import { PlatformAcknowledgeStatusDialog } from '../common/PlatformAcknowledgeStatusDialog';
|
||||
import { PlatformAsyncStatePanel } from '../common/PlatformAsyncStatePanel';
|
||||
import { CopyFeedbackButton } from '../common/CopyFeedbackButton';
|
||||
import { LegalDocumentModal } from '../common/LegalDocumentModal';
|
||||
@@ -95,7 +94,6 @@ import {
|
||||
PlatformOptionSegment,
|
||||
PlatformUnderlineTabRail,
|
||||
} from '../common/PlatformSegmentedTabPresets';
|
||||
import { PlatformStatusDialog } from '../common/PlatformStatusDialog';
|
||||
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
|
||||
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||
import { PlatformTextField } from '../common/PlatformTextField';
|
||||
@@ -134,13 +132,16 @@ import { PlatformProfileQrScannerModal } from '../platform-entry/PlatformProfile
|
||||
import { PlatformProfileRechargeModal } from '../platform-entry/PlatformProfileRechargeModal';
|
||||
import { PlatformProfileReferralModal } from '../platform-entry/PlatformProfileReferralModal';
|
||||
import { PlatformProfileRewardCodeRedeemModal } from '../platform-entry/PlatformProfileRewardCodeRedeemModal';
|
||||
import {
|
||||
PlatformRechargePaymentConfirmationMask,
|
||||
PlatformRechargePaymentResultDialog,
|
||||
} from '../platform-entry/PlatformRechargePaymentStatusDialogs';
|
||||
import { PlatformProfileTaskCenterModal } from '../platform-entry/PlatformProfileTaskCenterModal';
|
||||
import { PlatformProfileWalletLedgerModal } from '../platform-entry/PlatformProfileWalletLedgerModal';
|
||||
import type { ExternalGenerationQueueStatus } from '../platform-entry/platformExternalGenerationQueueStatusModel';
|
||||
import { getInitialPlatformDesktopLayout } from '../platform-entry/platformEntryResponsive';
|
||||
import {
|
||||
type ProfilePopupPanel,
|
||||
type RechargePaymentResult,
|
||||
usePlatformProfileCenterController,
|
||||
} from '../platform-entry/usePlatformProfileCenterController';
|
||||
import { ResolvedAssetImage } from '../ResolvedAssetImage';
|
||||
@@ -2465,9 +2466,6 @@ function cropAvatarImage(params: {
|
||||
});
|
||||
}
|
||||
|
||||
const PROFILE_MODAL_OVERLAY_CLASS =
|
||||
'platform-modal-backdrop !items-center !justify-center !px-4 !py-6';
|
||||
|
||||
function ProfileNicknameModal({
|
||||
value,
|
||||
error,
|
||||
@@ -2536,49 +2534,6 @@ function ProfileNicknameModal({
|
||||
);
|
||||
}
|
||||
|
||||
function RechargePaymentResultModal({
|
||||
result,
|
||||
onClose,
|
||||
}: {
|
||||
result: RechargePaymentResult;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const status =
|
||||
result.kind === 'success'
|
||||
? 'success'
|
||||
: result.kind === 'pending'
|
||||
? 'loading'
|
||||
: result.kind === 'cancel'
|
||||
? 'cancel'
|
||||
: 'error';
|
||||
|
||||
return (
|
||||
<PlatformAcknowledgeStatusDialog
|
||||
status={status}
|
||||
title={result.title}
|
||||
description={result.message}
|
||||
onClose={onClose}
|
||||
actionSurface="profile"
|
||||
zIndexClassName="z-[90]"
|
||||
overlayClassName={PROFILE_MODAL_OVERLAY_CLASS}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function RechargePaymentConfirmationMask({ orderId }: { orderId: string }) {
|
||||
return (
|
||||
<PlatformStatusDialog
|
||||
status="confirming"
|
||||
title="正在确认支付"
|
||||
description={`订单 ${orderId} 正在同步到账状态,请先停留在当前页面。`}
|
||||
onClose={() => undefined}
|
||||
closeDisabled
|
||||
zIndexClassName="z-[95]"
|
||||
overlayClassName={PROFILE_MODAL_OVERLAY_CLASS}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function RpgEntryHomeView({
|
||||
activeTab,
|
||||
activeDesktopNavTab,
|
||||
@@ -4920,14 +4875,14 @@ export function RpgEntryHomeView({
|
||||
/>
|
||||
) : null;
|
||||
const rechargePaymentResultModal: ReactNode = rechargePaymentResult ? (
|
||||
<RechargePaymentResultModal
|
||||
<PlatformRechargePaymentResultDialog
|
||||
result={rechargePaymentResult}
|
||||
onClose={() => setRechargePaymentResult(null)}
|
||||
/>
|
||||
) : null;
|
||||
const rechargePaymentConfirmationMask: ReactNode =
|
||||
wechatRechargeOrderConfirmationState ? (
|
||||
<RechargePaymentConfirmationMask
|
||||
<PlatformRechargePaymentConfirmationMask
|
||||
orderId={wechatRechargeOrderConfirmationState.orderId}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
+180
-133
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user