import AddOutlined from "@mui/icons-material/AddOutlined"; import Alert from "@mui/material/Alert"; import Button from "@mui/material/Button"; import Dialog from "@mui/material/Dialog"; import DialogActions from "@mui/material/DialogActions"; import DialogContent from "@mui/material/DialogContent"; import DialogTitle from "@mui/material/DialogTitle"; import MenuItem from "@mui/material/MenuItem"; import TextField from "@mui/material/TextField"; import { useEffect, useMemo, useRef, useState } from "react"; import { buildCoinSellerRechargeExchangeRatePayload, validateCoinSellerRechargeExchangeRatePayload, } from "../format.js"; const EMPTY_CONFIG = { tiers: [], whitelist: [] }; export function FinanceCoinSellerExchangeRateDialog({ apps, initialAppCode, open, onClose, onLoad, onSave }) { const rowSequence = useRef(0); const [appCode, setAppCode] = useState(""); const [config, setConfig] = useState(EMPTY_CONFIG); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); useEffect(() => { if (open) { setAppCode(initialAppCode || apps[0]?.appCode || ""); setError(""); } }, [apps, initialAppCode, open]); useEffect(() => { if (!open || !appCode) { return undefined; } let active = true; setLoading(true); setError(""); onLoad(appCode) .then((data) => { if (!active) { return; } setConfig({ tiers: (data?.tiers || []).map((item) => withRowID(item, rowSequence)), whitelist: (data?.whitelist || []).map((item) => withRowID(item, rowSequence)), }); }) .catch((loadError) => { if (active) { setConfig(EMPTY_CONFIG); setError(loadError.message || "加载金币汇率配置失败"); } }) .finally(() => { if (active) { setLoading(false); } }); return () => { active = false; }; }, [appCode, onLoad, open]); const payload = useMemo(() => buildCoinSellerRechargeExchangeRatePayload(config), [config]); const submit = async (event) => { event.preventDefault(); const validationMessage = validateCoinSellerRechargeExchangeRatePayload(payload); if (validationMessage) { setError(validationMessage); return; } setSaving(true); setError(""); try { await onSave(appCode, payload); onClose(); } catch (saveError) { setError(saveError.message || "保存金币汇率配置失败"); } finally { setSaving(false); } }; const updateRow = (group, id, key, value) => { setConfig((current) => ({ ...current, [group]: current[group].map((item) => (item.id === id ? { ...item, [key]: value } : item)), })); setError(""); }; const addRow = (group) => { const item = group === "tiers" ? { coinsPerUsd: "", maxUsdAmount: "", minUsdAmount: "" } : { coinsPerUsd: "", userId: "" }; setConfig((current) => ({ ...current, [group]: [...current[group], withRowID(item, rowSequence)] })); setError(""); }; const removeRow = (group, id) => { setConfig((current) => ({ ...current, [group]: current[group].filter((item) => item.id !== id) })); setError(""); }; const disabled = loading || saving; return ( 币商充值金币汇率
{error ? {error} : null} setAppCode(event.target.value)} > {apps.map((app) => ( {app.appName || app.appCode} ))} addRow("tiers")} onRemove={(id) => removeRow("tiers", id)} renderRow={(item) => ( <> updateRow("tiers", item.id, "minUsdAmount", event.target.value)} /> updateRow("tiers", item.id, "maxUsdAmount", event.target.value)} /> updateRow("tiers", item.id, "coinsPerUsd", event.target.value)} /> )} /> addRow("whitelist")} onRemove={(id) => removeRow("whitelist", id)} renderRow={(item) => ( <> updateRow("whitelist", item.id, "userId", event.target.value)} /> updateRow("whitelist", item.id, "coinsPerUsd", event.target.value)} /> )} />
); } function RateSection({ actionLabel, columns, disabled, onAdd, onRemove, renderRow, rows, title }) { return (

{title}

{columns.map((column) => ( {column} ))} 操作
{rows.length ? ( rows.map((item) => (
{renderRow(item)}
)) ) : (
当前无数据
)}
); } function withRowID(item, rowSequence) { rowSequence.current += 1; return { ...item, id: `rate-row-${rowSequence.current}` }; }