充值弹窗
This commit is contained in:
parent
f5d06e1e52
commit
97915b5980
@ -7,7 +7,6 @@ import Tabs from "@mui/material/Tabs";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useRechargeProductsPage } from "@/features/payment/hooks/useRechargeProductsPage.js";
|
||||
import { ThirdPartyPaymentContent } from "@/features/payment/pages/ThirdPartyPaymentPage.jsx";
|
||||
import styles from "@/features/payment/payment.module.css";
|
||||
import { Button } from "@/shared/ui/Button.jsx";
|
||||
import {
|
||||
@ -51,10 +50,25 @@ const audienceOptions = [
|
||||
["coin_seller", "币商"],
|
||||
];
|
||||
|
||||
const productTabConfigs = {
|
||||
google: {
|
||||
createLabel: "新增 Google 商品",
|
||||
dialogEditTitle: "编辑 Google 商品",
|
||||
dialogCreateTitle: "新增 Google 商品",
|
||||
platform: "android",
|
||||
},
|
||||
third_party: {
|
||||
createLabel: "新增三方商品",
|
||||
dialogEditTitle: "编辑三方商品",
|
||||
dialogCreateTitle: "新增三方商品",
|
||||
platform: "web",
|
||||
},
|
||||
};
|
||||
|
||||
export function RechargeProductConfigPage() {
|
||||
const page = useRechargeProductsPage();
|
||||
const [activeProductTab, setActiveProductTab] = useState("google");
|
||||
const googleProductPlatform = "android";
|
||||
const activeProductConfig = productTabConfigs[activeProductTab] || productTabConfigs.google;
|
||||
const { platform, setPlatform } = page;
|
||||
const items = page.data?.items || [];
|
||||
const regionLabels = useMemo(() => regionLabelMap(page.regionOptions), [page.regionOptions]);
|
||||
@ -64,14 +78,15 @@ export function RechargeProductConfigPage() {
|
||||
const canSubmit = page.editingItem ? page.abilities.canUpdateProduct : page.abilities.canCreateProduct;
|
||||
const openCreate = () => {
|
||||
page.openCreate();
|
||||
page.setForm({ platform: googleProductPlatform });
|
||||
page.setForm({ platform: activeProductConfig.platform });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (activeProductTab === "google" && platform !== googleProductPlatform) {
|
||||
setPlatform(googleProductPlatform);
|
||||
// 商品接口已经支持按 platform 区分 Google / 三方档位;tab 只负责把查询和新建表单固定到对应平台。
|
||||
if (platform !== activeProductConfig.platform) {
|
||||
setPlatform(activeProductConfig.platform);
|
||||
}
|
||||
}, [activeProductTab, googleProductPlatform, platform, setPlatform]);
|
||||
}, [activeProductConfig.platform, platform, setPlatform]);
|
||||
|
||||
return (
|
||||
<AdminListPage>
|
||||
@ -81,17 +96,11 @@ export function RechargeProductConfigPage() {
|
||||
<Tab label="三方" value="third_party" />
|
||||
</Tabs>
|
||||
</div>
|
||||
{activeProductTab === "google" ? (
|
||||
<>
|
||||
<AdminListToolbar
|
||||
actions={
|
||||
page.abilities.canCreateProduct ? (
|
||||
<Button
|
||||
startIcon={<AddOutlined fontSize="small" />}
|
||||
variant="primary"
|
||||
onClick={openCreate}
|
||||
>
|
||||
新增 Google 商品
|
||||
<Button startIcon={<AddOutlined fontSize="small" />} variant="primary" onClick={openCreate}>
|
||||
{activeProductConfig.createLabel}
|
||||
</Button>
|
||||
) : null
|
||||
}
|
||||
@ -112,18 +121,12 @@ export function RechargeProductConfigPage() {
|
||||
/>
|
||||
</AdminListBody>
|
||||
</DataState>
|
||||
</>
|
||||
) : (
|
||||
<ThirdPartyPaymentContent embedded />
|
||||
)}
|
||||
|
||||
{activeProductTab === "google" ? (
|
||||
<AdminFormDialog
|
||||
loading={saving}
|
||||
open={Boolean(page.activeAction)}
|
||||
size="compact"
|
||||
submitDisabled={!canSubmit || saving}
|
||||
title={page.editingItem ? "编辑 Google 商品" : "新增 Google 商品"}
|
||||
title={page.editingItem ? activeProductConfig.dialogEditTitle : activeProductConfig.dialogCreateTitle}
|
||||
onClose={page.closeDialog}
|
||||
onSubmit={page.submitProduct}
|
||||
>
|
||||
@ -214,7 +217,6 @@ export function RechargeProductConfigPage() {
|
||||
/>
|
||||
</AdminFormSection>
|
||||
</AdminFormDialog>
|
||||
) : null}
|
||||
</AdminListPage>
|
||||
);
|
||||
}
|
||||
|
||||
111
src/features/payment/pages/RechargeProductConfigPage.test.jsx
Normal file
111
src/features/payment/pages/RechargeProductConfigPage.test.jsx
Normal file
@ -0,0 +1,111 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { afterEach, expect, test, vi } from "vitest";
|
||||
import { RechargeProductConfigPage } from "@/features/payment/pages/RechargeProductConfigPage.jsx";
|
||||
import { useRechargeProductsPage } from "@/features/payment/hooks/useRechargeProductsPage.js";
|
||||
|
||||
vi.mock("@/features/payment/hooks/useRechargeProductsPage.js", () => ({
|
||||
useRechargeProductsPage: vi.fn(),
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("recharge product page defaults to google product list", () => {
|
||||
vi.mocked(useRechargeProductsPage).mockReturnValue(pageFixture());
|
||||
|
||||
render(<RechargeProductConfigPage />);
|
||||
|
||||
expect(screen.getByRole("tab", { name: "Google", selected: true })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "新增 Google 商品" })).toBeInTheDocument();
|
||||
expect(screen.getAllByText("coins_480000").length).toBeGreaterThan(0);
|
||||
expect(screen.queryByText("支付汇率全球同步")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("third-party tab reuses product dialog and locks create platform to web", () => {
|
||||
const page = pageFixture();
|
||||
vi.mocked(useRechargeProductsPage).mockReturnValue(page);
|
||||
|
||||
render(<RechargeProductConfigPage />);
|
||||
|
||||
fireEvent.click(screen.getByRole("tab", { name: "三方" }));
|
||||
|
||||
expect(screen.getByRole("tab", { name: "三方", selected: true })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "新增三方商品" })).toBeInTheDocument();
|
||||
expect(screen.queryByText("支付汇率全球同步")).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "新增三方商品" }));
|
||||
|
||||
expect(page.openCreate).toHaveBeenCalledTimes(1);
|
||||
expect(page.setForm).toHaveBeenCalledWith({ platform: "web" });
|
||||
});
|
||||
|
||||
function pageFixture() {
|
||||
return {
|
||||
abilities: {
|
||||
canCreateProduct: true,
|
||||
canDeleteProduct: true,
|
||||
canUpdateProduct: true,
|
||||
},
|
||||
activeAction: "",
|
||||
audienceType: "",
|
||||
closeDialog: vi.fn(),
|
||||
data: {
|
||||
items: [
|
||||
{
|
||||
amountUsdt: "5.99",
|
||||
audienceType: "normal",
|
||||
coinAmount: 480000,
|
||||
description: "480,000 coins",
|
||||
enabled: true,
|
||||
platform: "android",
|
||||
productCode: "coins_480000",
|
||||
productId: 1,
|
||||
productName: "coins_480000",
|
||||
regionIds: [1, 2],
|
||||
updatedAtMs: 1760000000000,
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
},
|
||||
editingItem: null,
|
||||
error: null,
|
||||
form: {
|
||||
amountUsdt: "",
|
||||
audienceType: "normal",
|
||||
coinAmount: "",
|
||||
description: "",
|
||||
enabled: true,
|
||||
platform: "android",
|
||||
productName: "",
|
||||
regionIds: [],
|
||||
},
|
||||
keyword: "",
|
||||
loading: false,
|
||||
loadingAction: "",
|
||||
loadingRegions: false,
|
||||
openCreate: vi.fn(),
|
||||
openEdit: vi.fn(),
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
platform: "android",
|
||||
regionId: "",
|
||||
regionOptions: [
|
||||
{ label: "中东 · ME · 1", name: "中东", value: "1" },
|
||||
{ label: "欧洲美区 · EU · 2", name: "欧洲美区", value: "2" },
|
||||
],
|
||||
reload: vi.fn(),
|
||||
removeProduct: vi.fn(),
|
||||
resetFilters: vi.fn(),
|
||||
setAudienceType: vi.fn(),
|
||||
setForm: vi.fn(),
|
||||
setKeyword: vi.fn(),
|
||||
setPage: vi.fn(),
|
||||
setPlatform: vi.fn(),
|
||||
setRegionId: vi.fn(),
|
||||
setStatus: vi.fn(),
|
||||
status: "",
|
||||
submitProduct: vi.fn(),
|
||||
toggleProductEnabled: vi.fn(),
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user