diff --git a/src/features/payment/pages/RechargeProductConfigPage.jsx b/src/features/payment/pages/RechargeProductConfigPage.jsx
index e5bde54..7fc774d 100644
--- a/src/features/payment/pages/RechargeProductConfigPage.jsx
+++ b/src/features/payment/pages/RechargeProductConfigPage.jsx
@@ -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 (
@@ -81,140 +96,127 @@ export function RechargeProductConfigPage() {
- {activeProductTab === "google" ? (
- <>
- }
- variant="primary"
- onClick={openCreate}
- >
- 新增 Google 商品
-
- ) : null
- }
+ } variant="primary" onClick={openCreate}>
+ {activeProductConfig.createLabel}
+
+ ) : null
+ }
+ />
+
+
+ item.productId}
/>
-
-
- item.productId}
- />
-
-
- >
- ) : (
-
- )}
-
- {activeProductTab === "google" ? (
-
-
-
- page.setForm({ productName: event.target.value })}
- />
- page.setForm({ platform: event.target.value })}
- >
-
-
-
-
- page.setForm({ audienceType: event.target.value })}
- >
-
-
-
-
-
-
-
- page.setForm({ amountUsdt: event.target.value })}
- />
- page.setForm({ coinAmount: event.target.value })}
- />
-
-
-
- page.setForm({ regionIds })}
- />
- page.setForm({ enabled: checked })}
- />
-
-
+
+
+
+
+
page.setForm({ description: event.target.value })}
+ label="产品名称"
+ required
+ value={page.form.productName}
+ onChange={(event) => page.setForm({ productName: event.target.value })}
/>
-
-
- ) : null}
+ page.setForm({ platform: event.target.value })}
+ >
+
+
+
+
+ page.setForm({ audienceType: event.target.value })}
+ >
+
+
+
+
+
+
+
+ page.setForm({ amountUsdt: event.target.value })}
+ />
+ page.setForm({ coinAmount: event.target.value })}
+ />
+
+
+
+ page.setForm({ regionIds })}
+ />
+ page.setForm({ enabled: checked })}
+ />
+
+
+ page.setForm({ description: event.target.value })}
+ />
+
+
);
}
diff --git a/src/features/payment/pages/RechargeProductConfigPage.test.jsx b/src/features/payment/pages/RechargeProductConfigPage.test.jsx
new file mode 100644
index 0000000..c280b08
--- /dev/null
+++ b/src/features/payment/pages/RechargeProductConfigPage.test.jsx
@@ -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();
+
+ 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();
+
+ 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(),
+ };
+}