import AddOutlined from "@mui/icons-material/AddOutlined"; import DeleteOutlineOutlined from "@mui/icons-material/DeleteOutlineOutlined"; import EditOutlined from "@mui/icons-material/EditOutlined"; import MenuItem from "@mui/material/MenuItem"; import TextField from "@mui/material/TextField"; import { useMemo } from "react"; import { useRechargeProductsPage } from "@/features/payment/hooks/useRechargeProductsPage.js"; import { Button } from "@/shared/ui/Button.jsx"; import { AdminFormAmountField, AdminFormDialog, AdminFormFieldGrid, AdminFormSection, AdminFormSwitchField, } from "@/shared/ui/AdminFormDialog.jsx"; import { AdminActionIconButton, AdminListBody, AdminListPage, AdminListToolbar, AdminRowActions, } from "@/shared/ui/AdminListLayout.jsx"; import { DataState } from "@/shared/ui/DataState.jsx"; import { DataTable } from "@/shared/ui/DataTable.jsx"; import { MultiValueAutocomplete } from "@/shared/ui/MultiValueAutocomplete.jsx"; import { AdminSwitch } from "@/shared/ui/AdminSwitch.jsx"; import { createRegionColumnFilter } from "@/shared/ui/RegionFilterControl.jsx"; import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js"; import { formatMillis } from "@/shared/utils/time.js"; const statusOptions = [ ["", "全部状态"], ["active", "上架"], ["disabled", "下架"], ]; const platformOptions = [ ["", "全部平台"], ["web", "Web"], ["android", "Android"], ["ios", "iOS"], ]; const audienceOptions = [ ["", "全部用户类型"], ["normal", "普通用户"], ["coin_seller", "币商"], ]; export function RechargeProductConfigPage() { const page = useRechargeProductsPage(); const items = page.data?.items || []; const regionLabels = useMemo(() => regionLabelMap(page.regionOptions), [page.regionOptions]); const regionValues = useMemo(() => page.regionOptions.map((option) => option.value), [page.regionOptions]); const columns = useMemo(() => productColumns(page, regionLabels), [page, regionLabels]); const saving = page.loadingAction === "create" || page.loadingAction === "edit"; const canSubmit = page.editingItem ? page.abilities.canUpdateProduct : page.abilities.canCreateProduct; return ( } variant="primary" onClick={page.openCreate} > 新增内购 ) : null } /> item.productId} /> page.setForm({ productName: event.target.value })} /> page.setForm({ platform: event.target.value })} > Web Android iOS 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 })} /> ); } function productColumns(page, regionLabels) { const columns = [ { key: "product", label: "产品", render: (item) => , filter: createTextColumnFilter({ placeholder: "搜索产品、描述", value: page.keyword, onChange: page.setKeyword, }), width: "minmax(240px, 1.2fr)", }, { key: "amount", label: "金额 / 金币", render: (item) => ( ), width: "minmax(160px, 0.75fr)", }, { key: "platform", label: "平台", render: (item) => platformLabel(item.platform), filter: createOptionsColumnFilter({ options: platformOptions, placeholder: "搜索平台", value: page.platform, onChange: page.setPlatform, }), width: "minmax(120px, 0.55fr)", }, { key: "audienceType", label: "用户类型", render: (item) => audienceLabel(item.audienceType), filter: createOptionsColumnFilter({ options: audienceOptions, placeholder: "搜索用户类型", value: page.audienceType, onChange: page.setAudienceType, }), width: "minmax(130px, 0.6fr)", }, { key: "regionIds", label: "支持区域", render: (item) => regionListLabel(regionLabels, item.regionIds), filter: createRegionColumnFilter({ loading: page.loadingRegions, options: page.regionOptions, value: page.regionId, onChange: page.setRegionId, }), width: "minmax(220px, 1fr)", }, { key: "status", label: "状态", render: (item) => , filter: createOptionsColumnFilter({ options: statusOptions, placeholder: "搜索状态", value: page.status, onChange: page.setStatus, }), width: "minmax(110px, 0.5fr)", }, { key: "description", label: "描述", render: (item) => item.description || "-", width: "minmax(180px, 0.9fr)", }, { key: "updatedAtMs", label: "更新时间", render: (item) => formatMillis(item.updatedAtMs), width: "minmax(160px, 0.75fr)", }, ]; if (!page.abilities.canUpdateProduct && !page.abilities.canDeleteProduct) { return columns; } return [ ...columns, { key: "actions", label: "操作", render: (item) => , width: "minmax(96px, 0.45fr)", }, ]; } function ProductStatusSwitch({ item, page }) { const checked = Boolean(item.enabled); const disabled = !page.abilities.canUpdateProduct || page.loadingAction === `status:${item.productId}`; return ( page.toggleProductEnabled(item, event.target.checked)} /> ); } function ProductActions({ item, page }) { const deleting = page.loadingAction === `delete:${item.productId}`; return ( {page.abilities.canUpdateProduct ? ( page.openEdit(item)} > ) : null} {page.abilities.canDeleteProduct ? ( page.removeProduct(item)} > ) : null} ); } function Stack({ primary, secondary }) { return (
{primary || "-"} {secondary || "-"}
); } function platformLabel(value) { if (value === "web") { return "Web"; } if (value === "android") { return "Android"; } if (value === "ios") { return "iOS"; } return value || "-"; } function audienceLabel(value) { if (value === "coin_seller") { return "币商"; } if (value === "normal") { return "普通用户"; } return value || "普通用户"; } function regionLabelMap(options) { return options.reduce((labels, option) => { labels[String(option.value)] = option.name || option.label; return labels; }, {}); } function regionListLabel(labels, regionIds = []) { if (!regionIds.length) { return "-"; } return regionIds.map((regionId) => labels[String(regionId)] || `区域 ${regionId}`).join("、"); } function formatNumber(value) { const numberValue = Number(value || 0); return Number.isFinite(numberValue) ? numberValue.toLocaleString() : "-"; } function formatMicroAmount(value) { const numberValue = Number(value || 0); if (!Number.isFinite(numberValue) || numberValue <= 0) { return "0"; } return String(numberValue / 1_000_000).replace(/\.?0+$/, ""); }