ALIEZ 1 mês atrás
pai
commit
6d5d223e14

+ 18 - 4
src/app/[locale]/account/page.tsx

@@ -169,9 +169,24 @@ export default function AccountPage() {
 
   // 高级状态色系:针对黑底优化
   function getStatusStyle(status: OrderRecord["status"] | WithdrawalRecord["status"]) {
-    const s = String(status);
-    if (s === "2" || s === "3") return "text-emerald-400 border-emerald-400/30 bg-emerald-400/10";
-    if (s === "4" || s === "5") return "text-rose-400 border-rose-400/30 bg-rose-400/10";
+    const s = String(status).trim();
+    const sLower = s.toLowerCase();
+
+    // 已完成:绿色
+    if (s === "2" || sLower === "completed" || sLower === "success") {
+      return "text-emerald-400 border-emerald-400/30 bg-emerald-400/10";
+    }
+    // 已拒绝/已失败:红色(含:3/4/5 以及 failed/rejected/cancelled 字符串)
+    if (
+      s === "3" || // 已拒绝 / 支付失败(支付失败在 order-api 中为 3)
+      s === "4" ||
+      s === "5" ||
+      sLower === "failed" ||
+      sLower === "rejected" ||
+      sLower === "cancelled"
+    ) {
+      return "text-rose-400 border-rose-400/30 bg-rose-400/10";
+    }
     return "text-amber-400 border-amber-400/30 bg-amber-400/10";
   }
 
@@ -443,7 +458,6 @@ export default function AccountPage() {
                       </div>
                       <div className="p-6">
                         <h3 className="line-clamp-1 text-[15px] font-bold text-white group-hover:text-[#f3deae] transition-colors">{c.title}</h3>
-                        <p className="mt-2 line-clamp-1 text-[11px] font-medium text-slate-500 uppercase tracking-wide">Course ID: {c.goodsId}</p>
                       </div>
                     </Link>
                   ))

+ 2 - 3
src/app/[locale]/account/purchased-courses/page.tsx

@@ -147,9 +147,8 @@ export default function PurchasedCoursesPage() {
                   <div className="flex flex-col flex-1 p-6">
                     <h3 className="line-clamp-2 text-base font-bold text-white group-hover:text-[#f3deae] transition-colors leading-snug">{c.title}</h3>
                     <p className="mt-3 line-clamp-2 text-xs text-slate-400 leading-relaxed">{c.introduction || "暂无课程介绍"}</p>
-                    <div className="mt-auto pt-6 flex items-center justify-between">
-                       <span className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">ID: {c.goodsId}</span>
-                       <span className="text-xs font-bold text-[#b89458] group-hover:text-[#f3deae] transition-colors">立即学习 →</span>
+                    <div className="mt-auto pt-6 flex items-center justify-end">
+                      <span className="text-xs font-bold text-[#b89458] group-hover:text-[#f3deae] transition-colors">立即学习 →</span>
                     </div>
                   </div>
                 </Link>

+ 422 - 82
src/app/[locale]/account/withdraw-apply/page.tsx

@@ -14,12 +14,12 @@ import {
 } from "@/lib/withdrawal-api";
 import { cn } from "@/lib/utils";
 
-// 保留原有的所有辅助函数 (channelGroupLabel, groupOrder, formatAmountRange 等)
 function channelGroupLabel(channel: WithdrawChannel): string {
   const type = channel.type;
   const code = (channel.code || "").toUpperCase();
   const name = `${channel.name || ""} ${channel.enName || ""}`.toUpperCase();
   const aliHint = code.includes("ALI") || code.includes("ALIPAY") || name.includes("ALIPAY");
+
   if (type === "BANK_TELEGRAPHIC") return "国际转账";
   if (type === "BANK") return "网银支付";
   if (type === "DIGITAL_CURRENCY") return "数字货币";
@@ -29,26 +29,60 @@ function channelGroupLabel(channel: WithdrawChannel): string {
   if (type === "UCARD_WALLET") return "电子卡";
   return "其他";
 }
+
 function groupOrder(label: string): number {
-  if (label === "数字货币") return 1; if (label === "网银支付") return 2; if (label === "国际转账") return 3;
-  if (label === "电子钱包") return 4; if (label === "电子卡") return 5; if (label === "支付宝") return 6; return 99;
+  if (label === "数字货币") return 1;
+  if (label === "网银支付") return 2;
+  if (label === "国际转账") return 3;
+  if (label === "电子钱包") return 4;
+  if (label === "电子卡") return 5;
+  if (label === "支付宝") return 6;
+  return 99;
 }
+
 function formatAmountRange(item: WithdrawChannel): string {
-  const min = item.minAmount || 0; const max = item.maxAmount > 0 ? item.maxAmount : "-"; return `$${min} - $${max} ${item.currency || "USD"}`;
+  const min = item.minAmount || 0;
+  const max = item.maxAmount > 0 ? item.maxAmount : "-";
+  return `$${min} - $${max} ${item.currency || "USD"}`;
 }
+
 function formatFee(item: WithdrawChannel): string {
-  if (item.feeType === 1) return `${item.free ?? 0}%`; if (item.feeType === 2) return `$${item.feeAmount ?? 0}`;
-  if (item.free !== null && item.free !== undefined) return `${item.free}%`; return "0%";
+  if (item.feeType === 1) return `${item.free ?? 0}%`;
+  if (item.feeType === 2) return `$${item.feeAmount ?? 0}`;
+  if (item.free !== null && item.free !== undefined) return `${item.free}%`;
+  return "0%";
 }
+
 function sanitizeHtml(input: string): string {
-  if (!input) return ""; return input.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "").replace(/\son\w+="[^"]*"/gi, "").replace(/\son\w+='[^']*'/gi, "");
+  if (!input) return "";
+  return input
+    .replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "")
+    .replace(/\son\w+="[^"]*"/gi, "")
+    .replace(/\son\w+='[^']*'/gi, "");
+}
+
+function isWalletType(type: string): boolean {
+  return type === "CHANNEL_TYPE_WALLET" || type === "CHANNEL_TYPE_ALI_WALLET";
+}
+
+function isBankType(type: string): boolean {
+  return type === "BANK";
+}
+
+function isCardType(type: string): boolean {
+  return type === "CHANNEL_TYPE_CARD";
+}
+
+function isDigitalCurrencyType(type: string): boolean {
+  return type === "DIGITAL_CURRENCY";
 }
-function isWalletType(type: string) { return type === "CHANNEL_TYPE_WALLET" || type === "CHANNEL_TYPE_ALI_WALLET"; }
-function isBankType(type: string) { return type === "BANK"; }
-function isCardType(type: string) { return type === "CHANNEL_TYPE_CARD"; }
-function isDigitalCurrencyType(type: string) { return type === "DIGITAL_CURRENCY"; }
+
 function savedAccountType(type: string): number | null {
-  if (type === "BANK") return 1; if (type === "BANK_TELEGRAPHIC") return 2; if (type === "CHANNEL_TYPE_CARD") return 3; if (type === "DIGITAL_CURRENCY") return 4; return null;
+  if (type === "BANK") return 1;
+  if (type === "BANK_TELEGRAPHIC") return 2;
+  if (type === "CHANNEL_TYPE_CARD") return 3;
+  if (type === "DIGITAL_CURRENCY") return 4;
+  return null;
 }
 
 export default function WithdrawApplyPage() {
@@ -56,11 +90,11 @@ export default function WithdrawApplyPage() {
   const [channelsLoading, setChannelsLoading] = useState(false);
   const [channelsError, setChannelsError] = useState<string | null>(null);
   const [walletBalance, setWalletBalance] = useState<number | null>(null);
-  
+  const [walletBalanceLoading, setWalletBalanceLoading] = useState(false);
+
   const [savedAccounts] = useState<SavedWithdrawAccount[]>([]);
   const [bankOptions, setBankOptions] = useState<WithdrawBankOption[]>([]);
 
-  // 表单状态
   const [selectedChannelId, setSelectedChannelId] = useState("");
   const [selectedSavedId, setSelectedSavedId] = useState("");
   const [selectedBankCode, setSelectedBankCode] = useState("");
@@ -69,7 +103,6 @@ export default function WithdrawApplyPage() {
   const [amount, setAmount] = useState("");
   const [agree, setAgree] = useState(false);
   const [agreeExtra, setAgreeExtra] = useState(false);
-  // ... 其他银行/电汇字段
   const [agencyNo, setAgencyNo] = useState("");
   const [cpf, setCpf] = useState("");
   const [bankUnameInput, setBankUnameInput] = useState("");
@@ -89,12 +122,33 @@ export default function WithdrawApplyPage() {
   const [confirmOpen, setConfirmOpen] = useState(false);
   const [expandedGroup, setExpandedGroup] = useState<string>("数字货币");
   const [applyDialogOpen, setApplyDialogOpen] = useState(false);
-  const [resultDialog, setResultDialog] = useState({ open: false, status: "success", title: "", message: "" });
+  const [resultDialog, setResultDialog] = useState<{
+    open: boolean;
+    status: "success" | "error";
+    title: string;
+    message: string;
+  }>({
+    open: false,
+    status: "success",
+    title: "",
+    message: "",
+  });
+
+  const selectedChannel = useMemo(
+    () => channels.find((item) => item.id === selectedChannelId) ?? null,
+    [channels, selectedChannelId],
+  );
+
+  const selectedSavedAccount = useMemo(
+    () => savedAccounts.find((item) => item.id === selectedSavedId) ?? null,
+    [savedAccounts, selectedSavedId],
+  );
 
-  const selectedChannel = useMemo(() => channels.find((item) => item.id === selectedChannelId) ?? null, [channels, selectedChannelId]);
-  const selectedSavedAccount = useMemo(() => savedAccounts.find((item) => item.id === selectedSavedId) ?? null, [savedAccounts, selectedSavedId]);
   const filteredSavedAccounts = useMemo(() => {
-    if (!selectedChannel) return []; const type = savedAccountType(selectedChannel.type); if (type === null) return []; return savedAccounts.filter((item) => item.type === type);
+    if (!selectedChannel) return [];
+    const type = savedAccountType(selectedChannel.type);
+    if (type === null) return [];
+    return savedAccounts.filter((item) => item.type === type);
   }, [savedAccounts, selectedChannel]);
 
   const shouldRequireSavedAccount = false;
@@ -103,92 +157,243 @@ export default function WithdrawApplyPage() {
   const needCpf = selectedChannel?.code === "PAY_RETAILER_REMIT_PAY_KEY_BRW";
 
   function resetApplyForm() {
-    setSelectedSavedId(""); setSelectedBankCode(""); setAddressName(""); setAddress(""); setAmount(""); setAgree(false); setAgreeExtra(false); setAgencyNo(""); setCpf(""); setBankUnameInput(""); setBankCardNumInput(""); setBankNameInput(""); setBankBranchNameInput(""); setSwiftCodeInput(""); setCustomBankCodeInput(""); setBankAddrInput(""); setTelegraphicCurrency("USD"); setCardUnameInput(""); setCardNumInput(""); setCardCvvInput(""); setCardExpiryInput("");
+    setSelectedSavedId("");
+    setSelectedBankCode("");
+    setAddressName("");
+    setAddress("");
+    setAmount("");
+    setAgree(false);
+    setAgreeExtra(false);
+    setAgencyNo("");
+    setCpf("");
+    setBankUnameInput("");
+    setBankCardNumInput("");
+    setBankNameInput("");
+    setBankBranchNameInput("");
+    setSwiftCodeInput("");
+    setCustomBankCodeInput("");
+    setBankAddrInput("");
+    setTelegraphicCurrency("USD");
+    setCardUnameInput("");
+    setCardNumInput("");
+    setCardCvvInput("");
+    setCardExpiryInput("");
   }
 
   useEffect(() => {
     let cancelled = false;
     async function loadBase() {
-      setChannelsLoading(true); setChannelsError(null);
+      setWalletBalanceLoading(true);
+      setChannelsLoading(true);
+      setChannelsError(null);
       try {
-        const [balanceResult, channelsResult] = await Promise.all([fetchWalletBalance(), fetchWithdrawChannels()]);
+        const [balanceResult, channelsResult] = await Promise.all([
+          fetchWalletBalance(),
+          fetchWithdrawChannels(),
+        ]);
         if (cancelled) return;
-        setWalletBalance(balanceResult); setChannels(channelsResult);
+        setWalletBalance(balanceResult);
+        setChannels(channelsResult);
       } catch (e) {
-        if (!cancelled) setChannelsError((e as Error)?.message || "通道加载失败");
+        if (cancelled) return;
+        const err = e as Error;
+        setChannelsError(err?.message || "领取通道加载失败");
+        setChannels([]);
+        setWalletBalance(null);
       } finally {
-        if (!cancelled) setChannelsLoading(false);
+        if (!cancelled) {
+          setWalletBalanceLoading(false);
+          setChannelsLoading(false);
+        }
       }
     }
-    void loadBase(); return () => { cancelled = true; };
+    void loadBase();
+    return () => {
+      cancelled = true;
+    };
   }, []);
 
   useEffect(() => {
-    if (!selectedChannel || !applyDialogOpen) { setBankOptions([]); setSelectedBankCode(""); return; }
-    resetApplyForm();
-    if (!selectedChannel.bankValid) return;
+    if (!selectedChannel || !applyDialogOpen) {
+      setBankOptions([]);
+      setSelectedBankCode("");
+      return;
+    }
+    const currentChannel = selectedChannel;
+    resetApplyForm(); // 重置表单状态
+
+    if (!currentChannel.bankValid) {
+      setBankOptions([]);
+      setSelectedBankCode("");
+      return;
+    }
     let cancelled = false;
     async function loadBankOptions() {
       try {
-        const list = await fetchWithdrawBankOptions(selectedChannel!.code);
-        if (cancelled) return; setBankOptions(list); setSelectedBankCode((prev) => prev || list[0]?.code || "");
-      } catch { if (!cancelled) setBankOptions([]); }
+        const list = await fetchWithdrawBankOptions(currentChannel.code);
+        if (cancelled) return;
+        setBankOptions(list);
+        setSelectedBankCode((prev) => prev || list[0]?.code || "");
+      } catch {
+        if (cancelled) return;
+        setBankOptions([]);
+      }
     }
-    void loadBankOptions(); return () => { cancelled = true; };
+    void loadBankOptions();
+    return () => {
+      cancelled = true;
+    };
   }, [selectedChannel, applyDialogOpen]);
 
   useEffect(() => {
     if (!selectedSavedAccount) return;
     if (!isBankType(selectedChannel?.type || "") && !isBankTelegraphic) return;
-    setBankUnameInput(selectedSavedAccount.bankUname || ""); setBankCardNumInput(selectedSavedAccount.bankCardNum || ""); setBankNameInput(selectedSavedAccount.bankName || ""); setBankBranchNameInput(selectedSavedAccount.bankBranchName || ""); setSwiftCodeInput(selectedSavedAccount.swiftCode || ""); setCustomBankCodeInput(selectedSavedAccount.customBankCode || ""); setBankAddrInput(selectedSavedAccount.bankAddr || "");
+    setBankUnameInput(selectedSavedAccount.bankUname || "");
+    setBankCardNumInput(selectedSavedAccount.bankCardNum || "");
+    setBankNameInput(selectedSavedAccount.bankName || "");
+    setBankBranchNameInput(selectedSavedAccount.bankBranchName || "");
+    setSwiftCodeInput(selectedSavedAccount.swiftCode || "");
+    setCustomBankCodeInput(selectedSavedAccount.customBankCode || "");
+    setBankAddrInput(selectedSavedAccount.bankAddr || "");
   }, [selectedSavedAccount, selectedChannel?.type, isBankTelegraphic]);
 
   function validate(): string | null {
     if (!selectedChannel) return "请选择领取通道";
     if (!/^[0-9]+([.][0-9]{1,2})?$/.test(amount.trim())) return "请输入正确的领取金额";
     const amountNum = Number(amount);
-    if (!Number.isFinite(amountNum) || amountNum <= 0) return "金额必须大于0";
-    if (selectedChannel.minAmount > 0 && amountNum < selectedChannel.minAmount) return `不能低于 ${selectedChannel.minAmount}`;
-    if (selectedChannel.maxAmount > 0 && amountNum > selectedChannel.maxAmount) return `不能高于 ${selectedChannel.maxAmount}`;
+    if (!Number.isFinite(amountNum) || amountNum <= 0) return "领取金额必须大于 0";
+    if (selectedChannel.minAmount > 0 && amountNum < selectedChannel.minAmount) {
+      return `领取金额不能低于 ${selectedChannel.minAmount}`;
+    }
+    if (selectedChannel.maxAmount > 0 && amountNum > selectedChannel.maxAmount) {
+      return `领取金额不能高于 ${selectedChannel.maxAmount}`;
+    }
     if (isWalletType(selectedChannel.type) && !address.trim()) return "请填写领取地址";
-    if (isDigitalCurrencyType(selectedChannel.type)) { if (!addressName.trim()) return "请填写区块链名称"; if (!address.trim()) return "请填写钱包地址"; }
-    if (isBankType(selectedChannel.type)) { if (!bankUnameInput.trim()) return "请输入户名"; if (!bankCardNumInput.trim()) return "请输入卡号"; if (!bankNameInput.trim()) return "请输入银行名称"; if (!bankBranchNameInput.trim()) return "请输入支行"; }
-    if (isBankTelegraphic) { if (!swiftCodeInput.trim() || !bankAddrInput.trim()) return "请完善电汇信息"; }
-    if (!agree) return "请同意领取条款"; if (!agreeExtra) return "请确认信息无误";
+    if (isDigitalCurrencyType(selectedChannel.type) && !addressName.trim()) return "请填写区块链名称";
+    if (isDigitalCurrencyType(selectedChannel.type) && !address.trim()) return "请填写钱包地址";
+    if (shouldRequireSavedAccount && filteredSavedAccounts.length === 0) {
+      return "当前通道暂无可用收款信息,请更换通道或先补充收款信息";
+    }
+    if (shouldShowSavedAccountSelector && !selectedSavedId) return "请选择收款信息";
+    if (isBankType(selectedChannel.type)) {
+      if (!bankUnameInput.trim()) return "请输入户名";
+      if (!bankCardNumInput.trim()) return "请输入银行卡号";
+      if (!bankNameInput.trim()) return "请输入银行名称";
+      if (!bankBranchNameInput.trim()) return "请输入支行名称";
+    }
+    if (isBankTelegraphic) {
+      if (!bankUnameInput.trim()) return "请输入户名";
+      if (!bankCardNumInput.trim()) return "请输入银行卡号";
+      if (!bankNameInput.trim()) return "请输入银行名称";
+      if (!swiftCodeInput.trim()) return "请输入Swift Code";
+      if (!customBankCodeInput.trim()) return "请输入银行代码";
+      if (!bankAddrInput.trim()) return "请输入银行地址";
+    }
+    if (isBankTelegraphic && !agencyNo.trim()) return "请填写 Account Agency NO";
+    if (isBankTelegraphic && needCpf && !cpf.trim()) return "请填写 CPF";
+    if (isCardType(selectedChannel.type)) {
+      if (!cardUnameInput.trim()) return "请输入信用卡户名";
+      if (!cardNumInput.trim()) return "请输入信用卡账户";
+      if (!cardCvvInput.trim()) return "请输入CVV";
+      if (!cardExpiryInput.trim()) return "请输入到期年份/月 份";
+    }
+    if (!agree) return "请先勾选并同意领取条款";
+    if (!agreeExtra) return "请勾选第二条领取确认条款";
     return null;
   }
 
   async function doSubmit() {
     if (!selectedChannel) return;
-    const payload: Record<string, unknown> = { payType: selectedChannel.code, amount: Number(amount), currency: selectedChannel.type === "BANK_TELEGRAPHIC" ? "USD" : selectedChannel.currency, agree2: true };
-    // ... 组装 payload 的逻辑保持原样
+    const amountNum = Number(amount);
+    const payload: Record<string, unknown> = {
+      payType: selectedChannel.code,
+      amount: amountNum,
+      currency: selectedChannel.type === "BANK_TELEGRAPHIC" ? "USD" : selectedChannel.currency,
+      agree2: true,
+    };
+    if (selectedBankCode) payload.bankCode = selectedBankCode;
     if (address.trim()) payload.address = address.trim();
     if (addressName.trim()) payload.addressName = addressName.trim();
-    if (isBankType(selectedChannel.type)) { payload.bankUname = bankUnameInput; payload.bankCardNum = bankCardNumInput; payload.bankName = bankNameInput; payload.bankBranchName = bankBranchNameInput; }
-    
+    if (selectedSavedAccount) {
+      payload.id = selectedSavedAccount.id;
+      payload.bankUname = selectedSavedAccount.bankUname;
+      payload.bankCardNum = selectedSavedAccount.bankCardNum;
+      payload.bankName = selectedSavedAccount.bankName;
+      payload.bankBranchName = selectedSavedAccount.bankBranchName;
+      payload.bankAddr = selectedSavedAccount.bankAddr;
+      payload.swiftCode = selectedSavedAccount.swiftCode;
+      payload.customBankCode = selectedSavedAccount.customBankCode;
+      payload.addressName = selectedSavedAccount.addressName;
+      payload.address = payload.address ?? selectedSavedAccount.address;
+      payload.cvv = selectedSavedAccount.cvv;
+      payload.expiryYearMonth = selectedSavedAccount.expiryYearMonth;
+    }
+    if (isBankType(selectedChannel.type)) {
+      payload.bankUname = bankUnameInput.trim();
+      payload.bankCardNum = bankCardNumInput.trim();
+      payload.bankName = bankNameInput.trim();
+      payload.bankBranchName = bankBranchNameInput.trim();
+    }
+    if (isBankTelegraphic) {
+      payload.bankUname = bankUnameInput.trim();
+      payload.bankCardNum = bankCardNumInput.trim();
+      payload.bankName = bankNameInput.trim();
+      payload.swiftCode = swiftCodeInput.trim();
+      payload.customBankCode = customBankCodeInput.trim();
+      payload.bankAddr = bankAddrInput.trim();
+      payload.currency = telegraphicCurrency || "USD";
+      payload.agencyNo = agencyNo.trim();
+      if (needCpf) payload.cpf = cpf.trim();
+    }
+    if (isCardType(selectedChannel.type)) {
+      payload.bankUname = cardUnameInput.trim();
+      payload.bankCardNum = cardNumInput.trim();
+      payload.cvv = cardCvvInput.trim();
+      payload.expiryYearMonth = cardExpiryInput.trim();
+    }
     setSubmitting(true);
     try {
-      await submitWithdrawApply({ requestUrl: selectedChannel.requestUrl, payload });
-      setResultDialog({ open: true, status: "success", title: "提交成功", message: "申请已提交审核。" });
+      await submitWithdrawApply({
+        requestUrl: selectedChannel.requestUrl,
+        payload,
+      });
+      setResultDialog({
+        open: true,
+        status: "success",
+        title: "提交成功",
+        message: "领取申请已提交,请等待平台审核。",
+      });
       resetApplyForm();
     } catch (e) {
-      setResultDialog({ open: true, status: "error", title: "提交失败", message: (e as Error).message });
+      const err = e as Error;
+      setResultDialog({
+        open: true,
+        status: "error",
+        title: "提交失败",
+        message: err.message || "领取申请失败,请稍后重试。",
+      });
     } finally {
-      setSubmitting(false); setConfirmOpen(false);
+      setSubmitting(false);
+      setConfirmOpen(false);
     }
   }
 
   const channelGroups = useMemo(() => {
     const groups: Record<string, WithdrawChannel[]> = {};
-    for (const item of channels) { const key = channelGroupLabel(item); if (!groups[key]) groups[key] = []; groups[key].push(item); }
+    for (const item of channels) {
+      const key = channelGroupLabel(item);
+      if (!groups[key]) groups[key] = [];
+      groups[key].push(item);
+    }
     return Object.entries(groups).sort((a, b) => groupOrder(a[0]) - groupOrder(b[0]));
   }, [channels]);
 
-  // 表单通用 Input 组件
-  const InputCls = "mt-2 w-full rounded-xl border border-white/10 bg-black/20 px-4 py-3 text-sm text-white placeholder-slate-500 focus:border-[#b89458] focus:outline-none focus:ring-1 focus:ring-[#b89458]";
+  // 高定表单样式
+  const InputCls = "mt-2 w-full rounded-xl border border-white/10 bg-[#0a1120] px-4 py-3.5 text-sm text-white placeholder-slate-600 focus:border-[#b89458] focus:outline-none focus:ring-1 focus:ring-[#b89458] transition-all";
 
   return (
     <div className="min-h-screen bg-[#050b14] pb-24 text-slate-300 font-sans relative">
+      {/* 沉浸式全局光晕 */}
       <div className="pointer-events-none fixed inset-0 z-0">
         <div className="absolute left-1/4 top-0 h-[500px] w-[500px] rounded-full bg-blue-900/10 blur-[120px]" />
         <div className="absolute right-1/4 bottom-0 h-[500px] w-[500px] rounded-full bg-[#b89458]/5 blur-[120px]" />
@@ -198,13 +403,19 @@ export default function WithdrawApplyPage() {
         <div className="flex flex-col md:flex-row md:items-center justify-between gap-6 mb-8">
           <div>
             <h1 className="font-serif text-3xl font-bold text-white">发起领取申请</h1>
-            <p className="mt-2 text-sm text-slate-400">当前可领取余额: <span className="font-bold text-[#f3deae] text-lg ml-1">${(walletBalance ?? 0).toFixed(2)}</span></p>
+            <p className="mt-2 text-sm text-slate-400">
+              当前可领取余额: 
+              <span className="font-bold text-[#f3deae] text-lg ml-2">
+                {walletBalanceLoading ? "..." : `$${(walletBalance ?? 0).toFixed(2)}`}
+              </span>
+            </p>
           </div>
           <Link href="/account" className="inline-flex items-center justify-center gap-2 rounded-full border border-white/10 bg-white/5 px-6 py-3 text-sm font-semibold text-slate-300 transition hover:bg-white/10 hover:text-white backdrop-blur-md">
             <ArrowLeft size={16} /> 返回控制中心
           </Link>
         </div>
 
+        {/* 提款通道列表 */}
         <section className="rounded-[2.5rem] border border-white/10 bg-white/5 p-6 md:p-10 backdrop-blur-2xl shadow-2xl">
           <h2 className="text-xl font-bold text-white mb-6">选择提款通道</h2>
           
@@ -230,7 +441,9 @@ export default function WithdrawApplyPage() {
                         <thead className="text-slate-400 border-b border-white/10">
                           <tr>
                             <th className="pb-3 px-4 font-semibold">通道类型</th>
+                            <th className="pb-3 px-4 font-semibold">描述</th>
                             <th className="pb-3 px-4 font-semibold">限额</th>
+                            <th className="pb-3 px-4 font-semibold">处理时间</th>
                             <th className="pb-3 px-4 font-semibold">手续费</th>
                             <th className="pb-3 px-4 font-semibold text-right">操作</th>
                           </tr>
@@ -244,7 +457,9 @@ export default function WithdrawApplyPage() {
                                   <span className="font-bold text-slate-200">{item.name || item.code}</span>
                                 </div>
                               </td>
+                              <td className="py-4 px-4 text-slate-400">{item.enName || item.name || "-"}</td>
                               <td className="py-4 px-4 font-medium text-slate-300">{formatAmountRange(item)}</td>
+                              <td className="py-4 px-4 font-medium text-slate-300">{item.fundingTime || "1 hours"}</td>
                               <td className="py-4 px-4 font-medium text-[#b89458]">{formatFee(item)}</td>
                               <td className="py-4 px-4 text-right">
                                 <button
@@ -267,67 +482,192 @@ export default function WithdrawApplyPage() {
         </section>
       </div>
 
-      {/* 填写表单大弹窗 */}
+      {/* ================= 填写表单大弹窗 (完美对齐设计图) ================= */}
       {applyDialogOpen && selectedChannel && (
         <div className="fixed inset-0 z-50 flex items-center justify-center bg-[#050b14]/90 p-4 backdrop-blur-md overflow-y-auto">
-          <div className="my-auto w-full max-w-2xl overflow-hidden rounded-[2.5rem] border border-white/10 bg-[#0a1120] shadow-2xl">
-            <div className="flex items-center justify-between border-b border-white/5 p-6 md:px-8">
-              <h2 className="text-xl font-bold text-white flex items-center gap-2"><Wallet className="text-[#b89458]"/> 填写提款信息</h2>
-              <button onClick={() => setApplyDialogOpen(false)} className="text-sm font-bold text-slate-500 hover:text-white">关闭</button>
+          <div className="my-auto w-full max-w-2xl overflow-hidden rounded-[2.5rem] border border-white/10 bg-[#121826] shadow-2xl">
+            
+            {/* 弹窗 Header */}
+            <div className="flex items-center justify-between p-8 pb-6">
+              <h2 className="text-[1.35rem] font-bold text-white flex items-center gap-3">
+                <Wallet className="text-[#d9be88]"/> 填写提款信息
+              </h2>
+              <button onClick={() => setApplyDialogOpen(false)} className="text-sm font-bold text-slate-500 hover:text-white transition-colors">
+                关闭
+              </button>
             </div>
             
-            <div className="p-6 md:p-8 max-h-[70vh] overflow-y-auto space-y-6 custom-scrollbar">
-               {/* 提示信息 */}
-               <div className="rounded-2xl border border-[#b89458]/30 bg-[#b89458]/10 p-5 text-sm text-[#f3deae] leading-relaxed">
-                  当前通道: <span className="font-bold ml-1">{selectedChannel.name || selectedChannel.code}</span>
+            {/* 弹窗 Body */}
+            <div className="px-8 max-h-[65vh] overflow-y-auto space-y-6 custom-scrollbar">
+               
+               {/* 余额显示框 (补充) */}
+               <div className="flex items-center justify-between rounded-2xl border border-white/5 bg-[#1a2130] p-4 text-sm">
+                  <span className="text-slate-400 font-medium">账户余额</span>
+                  <span className="font-bold text-white tracking-wide">
+                    {walletBalanceLoading ? "..." : `$ ${(walletBalance ?? 0).toFixed(2)}`}
+                  </span>
+               </div>
+
+               {/* 当前通道提示框 (完美还原设计图样式) */}
+               <div className="rounded-2xl border border-[#b89458]/30 bg-[#1c1d24] p-5 text-sm">
+                  <span className="text-slate-400">当前通道:</span>
+                  <span className="font-bold text-[#d9be88] ml-2 tracking-wide">{selectedChannel.name || selectedChannel.code}</span>
                </div>
+
+               {/* 如果有说明文字则展示 */}
+               {selectedChannel.introduce || selectedChannel.enIntroduce ? (
+                  <div
+                    className="rounded-2xl border border-white/5 bg-[#1a2130] p-4 text-sm leading-7 text-slate-300"
+                    dangerouslySetInnerHTML={{
+                      __html: sanitizeHtml(selectedChannel.introduce || selectedChannel.enIntroduce || ""),
+                    }}
+                  />
+               ) : null}
                
                {/* 表单渲染区域 */}
-               <div className="space-y-5">
+               <div className="space-y-6">
+                 
+                 {/* ====== 补充:银行下拉选项 ====== */}
+                 {bankOptions.length > 0 && (
+                  <div>
+                    <label className="text-sm font-bold text-slate-300">银行通道</label>
+                    <select
+                      value={selectedBankCode}
+                      onChange={(e) => setSelectedBankCode(e.target.value)}
+                      className={cn(InputCls, "appearance-none")}
+                    >
+                      <option value="" className="bg-[#0a1120] text-slate-400">请选择银行通道</option>
+                      {bankOptions.map((item) => (
+                        <option key={item.code} value={item.code} className="bg-[#0a1120] text-white">
+                          {item.name || item.enName || item.code}
+                        </option>
+                      ))}
+                    </select>
+                  </div>
+                 )}
+
+                 {/* ====== 补充:历史收款信息下拉选项 ====== */}
+                 {shouldShowSavedAccountSelector && (
+                  <div>
+                    <label className="text-sm font-bold text-slate-300">收款信息</label>
+                    <select
+                      value={selectedSavedId}
+                      onChange={(e) => setSelectedSavedId(e.target.value)}
+                      className={cn(InputCls, "appearance-none")}
+                    >
+                      <option value="" className="bg-[#0a1120] text-slate-400">请选择收款信息</option>
+                      {filteredSavedAccounts.map((item) => (
+                        <option key={item.id} value={item.id} disabled={item.type === 4 && item.authStatus === 0} className="bg-[#0a1120] text-white">
+                          {item.type === 4
+                            ? `${item.addressName || "-"} - ${item.address || "-"}`
+                            : `${item.bankName || "-"} - ${item.bankCardNum || "-"}`}
+                        </option>
+                      ))}
+                    </select>
+                  </div>
+                 )}
+
+                 {/* 数字货币 */}
                  {isDigitalCurrencyType(selectedChannel.type) && (
                    <div className="grid gap-5 md:grid-cols-2">
                      <div><label className="text-sm font-bold text-slate-300">区块链网络</label><input className={InputCls} placeholder="例如: TRC20" value={addressName} onChange={(e)=>setAddressName(e.target.value)} /></div>
                      <div><label className="text-sm font-bold text-slate-300">收款钱包地址</label><input className={InputCls} placeholder="请输入您的钱包地址" value={address} onChange={(e)=>setAddress(e.target.value)} /></div>
                    </div>
                  )}
+
+                 {/* 电子钱包 */}
+                 {isWalletType(selectedChannel.type) && (
+                   <div>
+                     <label className="text-sm font-bold text-slate-300">领取地址 / 账号</label>
+                     <input className={InputCls} placeholder="请输入账号或地址" value={address} onChange={(e) => setAddress(e.target.value)} />
+                   </div>
+                 )}
+
+                 {/* 普通银行 */}
                  {isBankType(selectedChannel.type) && (
                    <div className="grid gap-5 md:grid-cols-2">
-                     <div><label className="text-sm font-bold text-slate-300">开户姓名</label><input className={InputCls} value={bankUnameInput} onChange={(e)=>setBankUnameInput(e.target.value)} /></div>
-                     <div><label className="text-sm font-bold text-slate-300">银行卡号</label><input className={InputCls} value={bankCardNumInput} onChange={(e)=>setBankCardNumInput(e.target.value)} /></div>
-                     <div><label className="text-sm font-bold text-slate-300">银行名称</label><input className={InputCls} value={bankNameInput} onChange={(e)=>setBankNameInput(e.target.value)} /></div>
-                     <div><label className="text-sm font-bold text-slate-300">支行信息</label><input className={InputCls} value={bankBranchNameInput} onChange={(e)=>setBankBranchNameInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">户名</label><input className={InputCls} placeholder="持卡人姓名" value={bankUnameInput} onChange={(e)=>setBankUnameInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">银行卡号</label><input className={InputCls} placeholder="请输入卡号" value={bankCardNumInput} onChange={(e)=>setBankCardNumInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">银行名称</label><input className={InputCls} placeholder="例如: 招商银行" value={bankNameInput} onChange={(e)=>setBankNameInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">支行信息</label><input className={InputCls} placeholder="例如: 深圳分行" value={bankBranchNameInput} onChange={(e)=>setBankBranchNameInput(e.target.value)} /></div>
+                   </div>
+                 )}
+
+                 {/* 电汇银行 */}
+                 {isBankTelegraphic && (
+                   <>
+                     <div className="grid gap-5 md:grid-cols-2">
+                        <div><label className="text-sm font-bold text-slate-300">户名</label><input className={InputCls} value={bankUnameInput} onChange={(e)=>setBankUnameInput(e.target.value)} /></div>
+                        <div><label className="text-sm font-bold text-slate-300">银行卡号</label><input className={InputCls} value={bankCardNumInput} onChange={(e)=>setBankCardNumInput(e.target.value)} /></div>
+                        <div><label className="text-sm font-bold text-slate-300">银行名称</label><input className={InputCls} value={bankNameInput} onChange={(e)=>setBankNameInput(e.target.value)} /></div>
+                        <div><label className="text-sm font-bold text-slate-300">Swift Code</label><input className={InputCls} value={swiftCodeInput} onChange={(e)=>setSwiftCodeInput(e.target.value)} /></div>
+                        <div><label className="text-sm font-bold text-slate-300">银行代码</label><input className={InputCls} value={customBankCodeInput} onChange={(e)=>setCustomBankCodeInput(e.target.value)} /></div>
+                        <div><label className="text-sm font-bold text-slate-300">银行地址</label><input className={InputCls} value={bankAddrInput} onChange={(e)=>setBankAddrInput(e.target.value)} /></div>
+                     </div>
+                     <div className="grid gap-5 md:grid-cols-2">
+                        <div><label className="text-sm font-bold text-slate-300">Account Agency NO</label><input className={InputCls} value={agencyNo} onChange={(e)=>setAgencyNo(e.target.value)} /></div>
+                        {needCpf && <div><label className="text-sm font-bold text-slate-300">CPF</label><input className={InputCls} value={cpf} onChange={(e)=>setCpf(e.target.value)} /></div>}
+                     </div>
+                   </>
+                 )}
+
+                 {/* 信用卡 */}
+                 {isCardType(selectedChannel.type) && (
+                   <div className="grid gap-5 md:grid-cols-2">
+                     <div><label className="text-sm font-bold text-slate-300">信用卡户名</label><input className={InputCls} placeholder="John Doe" value={cardUnameInput} onChange={(e)=>setCardUnameInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">信用卡账号</label><input className={InputCls} placeholder="xxxx xxxx xxxx xxxx" value={cardNumInput} onChange={(e)=>setCardNumInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">CVV</label><input className={InputCls} placeholder="123" value={cardCvvInput} onChange={(e)=>setCardCvvInput(e.target.value)} /></div>
+                     <div><label className="text-sm font-bold text-slate-300">到期月份/年份</label><input className={InputCls} placeholder="09/30" value={cardExpiryInput} onChange={(e)=>setCardExpiryInput(e.target.value)} /></div>
                    </div>
                  )}
                  
-                 {/* 金额 */}
+                 {/* 金额输入框 (还原设计图) */}
                  <div>
-                    <label className="text-sm font-bold text-slate-300">提取金额 ({selectedChannel.currency || "USD"})</label>
+                    <label className="text-[13px] font-bold text-slate-300">提取金额 ({selectedChannel.currency || "USD"})</label>
                     <div className="relative mt-2">
-                      <span className="absolute left-4 top-3.5 text-slate-500 font-bold">$</span>
-                      <input type="number" className={cn(InputCls, "pl-8 text-xl font-bold text-[#f3deae] mt-0")} placeholder="0.00" value={amount} onChange={(e)=>setAmount(e.target.value)} />
+                      <span className="absolute left-4 top-4 text-slate-500 font-bold text-lg">$</span>
+                      <input 
+                        type="number" 
+                        className={cn(InputCls, "pl-9 text-xl font-bold text-white mt-0 h-14")} 
+                        placeholder="0.00" 
+                        value={amount} 
+                        onChange={(e)=>setAmount(e.target.value)} 
+                      />
                     </div>
                  </div>
 
-                 {/* 条款 */}
-                 <div className="mt-6 space-y-4 rounded-2xl bg-white/5 p-5">
+                 {/* 条款复选框 */}
+                 <div className="mt-6 space-y-4 rounded-2xl bg-[#1a2130] p-5">
                    <label className="flex items-start gap-3 text-sm text-slate-400 cursor-pointer group">
-                     <input type="checkbox" checked={agree} onChange={(e)=>setAgree(e.target.checked)} className="mt-1 h-4 w-4 rounded border-white/20 bg-black/50 text-[#b89458] focus:ring-[#b89458]" />
-                     <span className="group-hover:text-slate-300 transition-colors">我已仔细核对上述收款信息,因填写错误导致的资金损失由本人承担。</span>
+                     <div className="relative flex items-center justify-center">
+                        <input type="checkbox" checked={agree} onChange={(e)=>setAgree(e.target.checked)} className="peer appearance-none h-4 w-4 rounded border border-slate-500 bg-transparent checked:bg-white checked:border-white transition-all cursor-pointer" />
+                        <CheckCircle2 size={12} className="absolute text-slate-900 opacity-0 peer-checked:opacity-100 pointer-events-none" />
+                     </div>
+                     <span className="group-hover:text-slate-300 transition-colors leading-tight">我已仔细核对上述收款信息,因填写错误导致的资金损失由本人承担。</span>
                    </label>
                    <label className="flex items-start gap-3 text-sm text-slate-400 cursor-pointer group">
-                     <input type="checkbox" checked={agreeExtra} onChange={(e)=>setAgreeExtra(e.target.checked)} className="mt-1 h-4 w-4 rounded border-white/20 bg-black/50 text-[#b89458] focus:ring-[#b89458]" />
-                     <span className="group-hover:text-slate-300 transition-colors">我知悉并同意提款手续费规则,且了解资金到账受区块网络/银行处理时间影响。</span>
+                     <div className="relative flex items-center justify-center">
+                        <input type="checkbox" checked={agreeExtra} onChange={(e)=>setAgreeExtra(e.target.checked)} className="peer appearance-none h-4 w-4 rounded border border-slate-500 bg-transparent checked:bg-white checked:border-white transition-all cursor-pointer" />
+                        <CheckCircle2 size={12} className="absolute text-slate-900 opacity-0 peer-checked:opacity-100 pointer-events-none" />
+                     </div>
+                     <span className="group-hover:text-slate-300 transition-colors leading-tight">我知悉并同意提款手续费规则,且了解资金到账受区块网络/银行处理时间影响。</span>
                    </label>
                  </div>
                </div>
             </div>
             
-            <div className="border-t border-white/5 p-6 bg-black/20 flex gap-4">
-              <button onClick={() => setApplyDialogOpen(false)} className="flex-1 rounded-xl bg-white/10 py-4 font-bold text-white hover:bg-white/20 transition-all">取消</button>
+            {/* 弹窗 Footer 按钮区 */}
+            <div className="p-8 pt-6 flex gap-4">
+              <button 
+                onClick={() => setApplyDialogOpen(false)} 
+                className="flex-[0.8] rounded-xl bg-[#2a2f3a] py-4 text-sm font-bold text-white hover:bg-white/20 transition-all"
+              >
+                取消
+              </button>
               <button 
                 onClick={() => { const msg = validate(); if(msg) { alert(msg); return; } setConfirmOpen(true); }}
                 disabled={submitting} 
-                className="flex-[2] rounded-xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] py-4 font-bold text-[#5c461a] shadow-lg hover:opacity-90 transition-all disabled:opacity-50"
+                className="flex-[1.2] rounded-xl bg-[#d9be88] py-4 text-sm font-bold text-[#1c1d24] shadow-lg hover:opacity-90 transition-all disabled:opacity-50"
               >
                 校验并进入最后确认
               </button>
@@ -336,7 +676,7 @@ export default function WithdrawApplyPage() {
         </div>
       )}
 
-      {/* 二次确认弹窗 */}
+      {/* ================= 二次确认弹窗 ================= */}
       {confirmOpen && (
         <div className="fixed inset-0 z-[60] flex items-center justify-center bg-[#050b14]/80 p-4 backdrop-blur-md">
            <div className="w-full max-w-sm rounded-[2.5rem] border border-white/10 bg-[#0a1120] text-center shadow-2xl overflow-hidden">
@@ -355,7 +695,7 @@ export default function WithdrawApplyPage() {
         </div>
       )}
       
-      {/* 结果弹窗 */}
+      {/* ================= 结果弹窗 ================= */}
       {resultDialog.open && (
          <div className="fixed inset-0 z-[70] flex items-center justify-center bg-[#050b14]/80 p-4 backdrop-blur-md">
             <div className="w-full max-w-sm rounded-[2.5rem] border border-white/10 bg-[#0a1120] text-center shadow-2xl overflow-hidden p-10">

+ 101 - 28
src/app/[locale]/account/withdrawals/page.tsx

@@ -1,7 +1,6 @@
 "use client";
 
 import { useEffect, useState } from "react";
-import { useTranslations } from "next-intl";
 import { Link } from "@/i18n/navigation";
 import { useAuth } from "@/providers/auth-provider";
 import { History, ArrowLeft, Loader2 } from "lucide-react";
@@ -15,7 +14,6 @@ import { cn } from "@/lib/utils";
 const PAGE_SIZE = 10;
 
 export default function AccountWithdrawalsPage() {
-  const t = useTranslations("account");
   const { user, isReady } = useAuth();
   const [records, setRecords] = useState<WithdrawalRecord[]>([]);
   const [loading, setLoading] = useState(false);
@@ -29,7 +27,10 @@ export default function AccountWithdrawalsPage() {
       setLoading(true);
       setError(null);
       try {
-        const list = await fetchWithdrawalList({ current: page, row: PAGE_SIZE });
+        const list = await fetchWithdrawalList({
+          current: page,
+          row: PAGE_SIZE,
+        });
         if (cancelled) return;
         setRecords(list);
       } catch (e) {
@@ -41,17 +42,29 @@ export default function AccountWithdrawalsPage() {
       }
     }
     void loadRecords();
-    return () => { cancelled = true; };
+    return () => {
+      cancelled = true;
+    };
   }, [user, page]);
 
-  if (!isReady) return <div className="min-h-screen bg-[#050b14] flex items-center justify-center text-slate-500"><Loader2 className="animate-spin" /></div>;
+  if (!isReady)
+    return (
+      <div className="min-h-screen bg-[#050b14] flex items-center justify-center text-slate-500">
+        <Loader2 className="animate-spin" />
+      </div>
+    );
 
   if (!user) {
-     return (
+    return (
       <div className="min-h-screen bg-[#050b14] flex items-center justify-center px-4 font-sans">
         <div className="w-full max-w-md rounded-[2.5rem] border border-white/10 bg-white/5 p-10 text-center backdrop-blur-2xl">
           <h2 className="text-2xl font-bold text-white mb-6">您尚未登录</h2>
-          <Link href="/auth/login" className="inline-block rounded-full bg-[#f3deae] px-10 py-4 text-sm font-bold text-[#5c461a] shadow-lg">立即登录</Link>
+          <Link
+            href="/auth/login"
+            className="inline-block rounded-full bg-[#f3deae] px-10 py-4 text-sm font-bold text-[#5c461a] shadow-lg"
+          >
+            立即登录
+          </Link>
         </div>
       </div>
     );
@@ -61,9 +74,23 @@ export default function AccountWithdrawalsPage() {
   const hasNext = records.length >= PAGE_SIZE;
 
   function getStatusStyle(status: number | string) {
-    const s = String(status);
-    if (s === "2" || s === "3") return "text-emerald-400 border-emerald-400/30 bg-emerald-400/10";
-    if (s === "4" || s === "5") return "text-rose-400 border-rose-400/30 bg-rose-400/10";
+    const s = String(status).trim();
+    const sLower = s.toLowerCase();
+
+    // 已完成:绿色;已拒绝/已失败/已取消:红色(当前页面要求“已拒绝”为红色)
+    if (s === "2" || sLower === "completed" || sLower === "success") {
+      return "text-emerald-400 border-emerald-400/30 bg-emerald-400/10";
+    }
+    if (
+      s === "3" || // 已拒绝
+      s === "4" ||
+      s === "5" ||
+      sLower === "failed" ||
+      sLower === "rejected" ||
+      sLower === "cancelled"
+    ) {
+      return "text-rose-400 border-rose-400/30 bg-rose-400/10";
+    }
     return "text-amber-400 border-amber-400/30 bg-amber-400/10";
   }
 
@@ -77,17 +104,32 @@ export default function AccountWithdrawalsPage() {
       <div className="site-container relative z-10 pt-16">
         <div className="flex items-center justify-between mb-8">
           <div>
-            <h1 className="font-serif text-3xl font-bold text-white">全部领取记录</h1>
-            <p className="mt-2 text-sm text-slate-400">追踪您的每一笔资金变动状态</p>
+            <h1 className="font-serif text-3xl font-bold text-white">
+              全部领取记录
+            </h1>
+            <p className="mt-2 text-sm text-slate-400">
+              追踪您的每一笔资金变动状态
+            </p>
           </div>
-          <Link href="/account" className="flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-5 py-2.5 text-sm font-semibold text-slate-300 transition hover:bg-white/10 hover:text-white backdrop-blur-md">
+          <Link
+            href="/account"
+            className="flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-5 py-2.5 text-sm font-semibold text-slate-300 transition hover:bg-white/10 hover:text-white backdrop-blur-md"
+          >
             <ArrowLeft size={16} /> 返回控制中心
           </Link>
         </div>
 
         <section className="rounded-[2.5rem] border border-white/10 bg-white/5 p-6 md:p-10 backdrop-blur-2xl shadow-2xl">
-          {loading ? <div className="py-20 flex justify-center text-slate-500"><Loader2 className="animate-spin h-8 w-8" /></div> : null}
-          {error ? <div className="mb-6 rounded-2xl border border-rose-500/20 bg-rose-500/10 p-4 text-sm text-rose-400">{error}</div> : null}
+          {loading ? (
+            <div className="py-20 flex justify-center text-slate-500">
+              <Loader2 className="animate-spin h-8 w-8" />
+            </div>
+          ) : null}
+          {error ? (
+            <div className="mb-6 rounded-2xl border border-rose-500/20 bg-rose-500/10 p-4 text-sm text-rose-400">
+              {error}
+            </div>
+          ) : null}
 
           {!loading && !error && records.length === 0 ? (
             <div className="py-20 flex flex-col items-center justify-center rounded-[2rem] border border-dashed border-white/10 bg-white/5 text-slate-500">
@@ -99,29 +141,46 @@ export default function AccountWithdrawalsPage() {
           {!loading && !error && records.length > 0 ? (
             <div className="space-y-4">
               {records.map((w) => (
-                <div key={w.serial} className="group rounded-[1.5rem] border border-white/5 bg-white/5 p-6 transition-all hover:bg-white/10">
+                <div
+                  key={w.serial}
+                  className="group rounded-[1.5rem] border border-white/5 bg-white/5 p-6 transition-all hover:bg-white/10"
+                >
                   <div className="flex flex-col md:flex-row md:items-center justify-between gap-6">
                     <div className="flex items-start gap-5">
                       <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-white/5 text-teal-400">
                         <History size={22} />
                       </div>
                       <div>
-                        <p className="text-base font-bold text-white group-hover:text-teal-400 transition-colors">{w.details}</p>
+                        <p className="text-base font-bold text-white group-hover:text-teal-400 transition-colors">
+                          {w.details}
+                        </p>
                         <div className="mt-2 flex flex-wrap items-center gap-x-4 gap-y-2 text-xs font-medium text-slate-500">
                           <span>流水号: {w.serial}</span>
                           <span className="hidden sm:inline">•</span>
                           <span>申请: {w.addTime || "-"}</span>
-                          {w.payTime && <><span className="hidden sm:inline">•</span><span>到账: {w.payTime}</span></>}
+                          {w.payTime && (
+                            <>
+                              <span className="hidden sm:inline">•</span>
+                              <span>到账: {w.payTime}</span>
+                            </>
+                          )}
                         </div>
                       </div>
                     </div>
                     <div className="flex items-center justify-between md:justify-end gap-6 md:border-l md:border-white/5 md:pl-6">
-                       <div className="text-right">
-                          <p className="text-xl font-bold text-white tracking-tight">${w.amount}</p>
-                          <span className={cn("inline-block mt-1.5 rounded-full border px-3 py-1 text-[10px] font-bold uppercase tracking-widest", getStatusStyle(w.status))}>
-                            {getWithdrawalStatusLabel(w.status)}
-                          </span>
-                       </div>
+                      <div className="text-right">
+                        <p className="text-xl font-bold text-white tracking-tight">
+                          ${w.amount}
+                        </p>
+                        <span
+                          className={cn(
+                            "inline-block mt-1.5 rounded-full border px-3 py-1 text-[10px] font-bold uppercase tracking-widest",
+                            getStatusStyle(w.status),
+                          )}
+                        >
+                          {getWithdrawalStatusLabel(w.status)}
+                        </span>
+                      </div>
                     </div>
                   </div>
                 </div>
@@ -132,13 +191,27 @@ export default function AccountWithdrawalsPage() {
           {/* 分页 */}
           {!loading && !error && (hasPrev || hasNext) && (
             <div className="mt-10 flex items-center justify-center gap-4 border-t border-white/5 pt-8">
-              <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={!hasPrev || loading} className="rounded-xl border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold transition hover:bg-white/10 disabled:opacity-30">上一页</button>
-              <span className="text-sm font-medium text-slate-500">第 <span className="text-white">{page}</span> 页</span>
-              <button onClick={() => setPage(p => p + 1)} disabled={!hasNext || loading} className="rounded-xl border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold transition hover:bg-white/10 disabled:opacity-30">下一页</button>
+              <button
+                onClick={() => setPage((p) => Math.max(1, p - 1))}
+                disabled={!hasPrev || loading}
+                className="rounded-xl border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold transition hover:bg-white/10 disabled:opacity-30"
+              >
+                上一页
+              </button>
+              <span className="text-sm font-medium text-slate-500">
+                第 <span className="text-white">{page}</span> 页
+              </span>
+              <button
+                onClick={() => setPage((p) => p + 1)}
+                disabled={!hasNext || loading}
+                className="rounded-xl border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold transition hover:bg-white/10 disabled:opacity-30"
+              >
+                下一页
+              </button>
             </div>
           )}
         </section>
       </div>
     </div>
   );
-}
+}

+ 62 - 35
src/app/[locale]/auth/forgot-password/page.tsx

@@ -5,6 +5,9 @@ import { Link } from "@/i18n/navigation";
 import { useState } from "react";
 import { ApiError } from "@/lib/api";
 import { sendForgotPasswordEmail } from "@/lib/auth-api";
+import { KeyRound, CheckCircle2 } from "lucide-react";
+
+const InputCls = "mt-2 w-full rounded-xl border border-white/10 bg-black/20 px-4 py-3.5 text-sm text-white placeholder-slate-500 focus:border-[#b89458] focus:outline-none focus:ring-1 focus:ring-[#b89458] transition-all";
 
 export default function ForgotPasswordPage() {
   const t = useTranslations("auth");
@@ -33,41 +36,65 @@ export default function ForgotPasswordPage() {
   }
 
   return (
-    <div className="auth-page-shell">
-      <h1 className="font-serif text-2xl font-semibold text-[var(--navy)]">{t("forgotTitle")}</h1>
-      <p className="mt-2 text-sm text-[var(--muted)]">{t("forgotHint")}</p>
-      {!done ? (
-        <form
-          onSubmit={onSubmit}
-          className="mt-8 space-y-4"
-        >
-          <div>
-            <label className="text-sm font-medium">{t("email")}</label>
-            <input
-              type="email"
-              required
-              value={email}
-              onChange={(e) => setEmail(e.target.value)}
-              className="mt-1 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
-            />
+    <div className="min-h-screen bg-[#050b14] flex flex-col items-center justify-center p-4 relative font-sans overflow-hidden">
+      {/* 环境光晕 */}
+      <div className="pointer-events-none fixed inset-0 z-0">
+        <div className="absolute left-1/2 top-1/2 h-[600px] w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-[#b89458]/10 blur-[150px]" />
+      </div>
+
+      <div className="relative z-10 w-full max-w-md">
+        <div className="mb-8 flex justify-center">
+          <div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] text-[#5c461a] shadow-lg shadow-[#b89458]/20">
+            <KeyRound size={28} />
+          </div>
+        </div>
+
+        <div className="rounded-[2.5rem] border border-white/10 bg-[#0a1120]/80 p-8 md:p-10 backdrop-blur-2xl shadow-2xl">
+          <div className="text-center mb-8">
+            <h1 className="font-serif text-2xl font-bold text-white">{t("forgotTitle")}</h1>
+            <p className="mt-2 text-sm text-slate-400">{t("forgotHint")}</p>
           </div>
-          <button
-            type="submit"
-            disabled={submitting}
-            className="w-full rounded-full bg-[var(--navy)] py-3 text-sm font-semibold text-white"
-          >
-            {submitting ? "发送中..." : t("resetBtn")}
-          </button>
-          {err ? <p className="text-sm text-red-600">{err}</p> : null}
-        </form>
-      ) : (
-        <p className="mt-8 text-sm text-emerald-700">发送重置邮件。</p>
-      )}
-      <p className="mt-8 text-center text-sm">
-        <Link href="/auth/login" className="text-[var(--accent)] hover:underline">
-          {t("toLogin")}
-        </Link>
-      </p>
+
+          {!done ? (
+            <form onSubmit={onSubmit} className="space-y-5">
+              <div>
+                <label className="text-sm font-bold text-slate-300 ml-1">{t("email")}</label>
+                <input
+                  type="email"
+                  required
+                  value={email}
+                  onChange={(e) => setEmail(e.target.value)}
+                  className={InputCls}
+                  placeholder="admin@example.com"
+                />
+              </div>
+
+              {err && <div className="rounded-xl border border-rose-500/30 bg-rose-500/10 p-3 text-center text-sm font-medium text-rose-400">{err}</div>}
+
+              <button
+                type="submit"
+                disabled={submitting}
+                className="w-full rounded-2xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] py-4 text-sm font-bold text-[#5c461a] shadow-xl shadow-[#b89458]/10 transition-transform hover:scale-[1.02] disabled:opacity-50 disabled:hover:scale-100 mt-6"
+              >
+                {submitting ? "发送中..." : t("resetBtn")}
+              </button>
+            </form>
+          ) : (
+            <div className="rounded-2xl border border-emerald-500/30 bg-emerald-500/10 p-6 text-center">
+              <CheckCircle2 size={40} className="mx-auto mb-4 text-emerald-400" />
+              <p className="text-base font-bold text-emerald-400">邮件已发送</p>
+              <p className="mt-2 text-sm text-emerald-500/80">请前往您的邮箱查收密码重置链接。</p>
+            </div>
+          )}
+
+          <p className="mt-8 text-center text-sm text-slate-400">
+            想起密码了?{" "}
+            <Link href="/auth/login" className="font-bold text-white hover:text-[#f3deae] transition-colors">
+              {t("toLogin")}
+            </Link>
+          </p>
+        </div>
+      </div>
     </div>
   );
-}
+}

+ 96 - 66
src/app/[locale]/auth/login/page.tsx

@@ -6,6 +6,7 @@ import { Link } from "@/i18n/navigation";
 import { useSearchParams } from "next/navigation";
 import { Suspense, useEffect, useState } from "react";
 import { useAuth } from "@/providers/auth-provider";
+import { Eye, EyeOff, LogIn, CheckCircle2 } from "lucide-react";
 
 const REGISTER_BANNER_MS = 3000;
 
@@ -16,6 +17,8 @@ function safePostLoginPath(raw: string | null): string | null {
   return raw;
 }
 
+const InputCls = "mt-2 w-full rounded-xl border border-white/10 bg-black/20 px-4 py-3.5 text-sm text-white placeholder-slate-500 focus:border-[#b89458] focus:outline-none focus:ring-1 focus:ring-[#b89458] transition-all";
+
 function LoginForm() {
   const t = useTranslations("auth");
   const router = useRouter();
@@ -26,6 +29,7 @@ function LoginForm() {
   const showRegisterBanner = fromRegister && !registerBannerDismissed;
   const [email, setEmail] = useState("");
   const [password, setPassword] = useState("");
+  const [showPassword, setShowPassword] = useState(false);
   const [err, setErr] = useState<string | null>(null);
   const [submitting, setSubmitting] = useState(false);
   const canSubmit = email.trim().length > 0 && password.length > 0 && !submitting;
@@ -57,70 +61,98 @@ function LoginForm() {
   };
 
   return (
-    <div className="auth-page-shell">
-      <div className="rounded-2xl border border-[var(--border)] bg-[var(--card)] p-6 shadow-card sm:p-8">
-        <h1 className="font-serif text-2xl font-semibold text-[var(--navy)]">{t("loginTitle")}</h1>
-        {showRegisterBanner && (
-          <p
-            className="mt-4 rounded-lg border border-emerald-200 bg-emerald-50 px-3 py-2.5 text-sm text-emerald-900"
-            role="status"
-          >
-            {t("loginAfterRegister")}
-          </p>
-        )}
-        <form onSubmit={onSubmit} className="mt-8 space-y-4">
-          <div>
-            <label className="text-sm font-medium">{t("email")}</label>
-            <input
-              type="email"
-              required
-              value={email}
-              onChange={(e) => {
-                setEmail(e.target.value);
-                if (err) setErr(null);
-              }}
-              onBlur={() => setEmail((v) => v.trim())}
-              autoComplete="email"
-              className="mt-1 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
-            />
+    <div className="min-h-screen bg-[#050b14] flex flex-col items-center justify-center p-4 relative font-sans overflow-hidden">
+      {/* 沉浸式环境光晕 */}
+      <div className="pointer-events-none fixed inset-0 z-0">
+        <div className="absolute left-1/2 top-1/2 h-[600px] w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-[#b89458]/10 blur-[150px]" />
+      </div>
+
+      <div className="relative z-10 w-full max-w-md">
+        <div className="mb-8 flex justify-center">
+          <div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] text-[#5c461a] shadow-lg shadow-[#b89458]/20">
+            <LogIn size={28} className="translate-x-[2px]" />
           </div>
-          <div>
-            <label className="text-sm font-medium">{t("password")}</label>
-            <input
-              type="password"
-              required
-              value={password}
-              onChange={(e) => {
-                setPassword(e.target.value);
-                if (err) setErr(null);
-              }}
-              autoComplete="current-password"
-              className="mt-1 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
-            />
+        </div>
+
+        <div className="rounded-[2.5rem] border border-white/10 bg-[#0a1120]/80 p-8 md:p-10 backdrop-blur-2xl shadow-2xl">
+          <div className="text-center mb-8">
+            <h1 className="font-serif text-2xl font-bold text-white">{t("loginTitle")}</h1>
+            <p className="mt-2 text-sm text-slate-400">登录您的交易账户以继续学习</p>
           </div>
-          {err && (
-            <p className="text-sm text-red-600" role="alert" aria-live="polite">
-              {err}
-            </p>
+
+          {showRegisterBanner && (
+            <div className="mb-6 flex items-center justify-center gap-2 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-3 text-sm font-medium text-emerald-400" role="status">
+              <CheckCircle2 size={16} /> {t("loginAfterRegister")}
+            </div>
           )}
-          <button
-            type="submit"
-            disabled={!canSubmit}
-            className="w-full rounded-full bg-[var(--navy)] py-3 text-sm font-semibold text-white transition-opacity disabled:cursor-not-allowed disabled:opacity-60"
-          >
-            {submitting ? `${t("loginBtn")}...` : t("loginBtn")}
-          </button>
-        </form>
-        <p className="mt-4 text-center text-sm text-[var(--muted)]">
-          <Link href="/auth/forgot-password" className="underline">
-            {t("forgotTitle")}
-          </Link>
-        </p>
-        <p className="mt-6 text-center text-sm">
-          <Link href="/auth/register" className="text-[var(--accent)] hover:underline">
-            {t("toRegister")}
-          </Link>
-        </p>
+
+          <form onSubmit={onSubmit} className="space-y-5">
+            <div>
+              <label className="text-sm font-bold text-slate-300 ml-1">{t("email")}</label>
+              <input
+                type="email"
+                required
+                value={email}
+                onChange={(e) => { setEmail(e.target.value); if (err) setErr(null); }}
+                onBlur={() => setEmail((v) => v.trim())}
+                autoComplete="email"
+                placeholder="admin@example.com"
+                className={InputCls}
+              />
+            </div>
+            <div>
+              <label className="text-sm font-bold text-slate-300 ml-1 flex justify-between">
+                <span>{t("password")}</span>
+                <Link href="/auth/forgot-password" className="text-[#b89458] hover:text-[#f3deae] transition-colors font-medium">
+                  {t("forgotTitle")}
+                </Link>
+              </label>
+              <div className="relative mt-2">
+                <input
+                  type={showPassword ? "text" : "password"}
+                  required
+                  value={password}
+                  onChange={(e) => {
+                    setPassword(e.target.value);
+                    if (err) setErr(null);
+                  }}
+                  autoComplete="current-password"
+                  placeholder="输入密码"
+                  className={`${InputCls} mt-0 pr-12`}
+                />
+                <button
+                  type="button"
+                  onClick={() => setShowPassword((v) => !v)}
+                  className="absolute right-3 top-1/2 -translate-y-1/2 rounded-md p-1 text-slate-400 hover:text-white focus:outline-none focus:ring-1 focus:ring-[#b89458]"
+                  aria-label={showPassword ? "隐藏密码" : "显示密码"}
+                >
+                  {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
+                </button>
+              </div>
+            </div>
+
+            {err && (
+              <div className="rounded-xl border border-rose-500/30 bg-rose-500/10 p-3 text-center text-sm font-medium text-rose-400" role="alert">
+                {err}
+              </div>
+            )}
+
+            <button
+              type="submit"
+              disabled={!canSubmit}
+              className="w-full rounded-2xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] py-4 text-sm font-bold text-[#5c461a] shadow-xl shadow-[#b89458]/10 transition-transform hover:scale-[1.02] disabled:opacity-50 disabled:hover:scale-100 mt-6"
+            >
+              {submitting ? `${t("loginBtn")}中...` : t("loginBtn")}
+            </button>
+          </form>
+
+          <p className="mt-8 text-center text-sm text-slate-400">
+            还没有账户?{" "}
+            <Link href="/auth/register" className="font-bold text-white hover:text-[#f3deae] transition-colors">
+              {t("toRegister")}
+            </Link>
+          </p>
+        </div>
       </div>
     </div>
   );
@@ -135,14 +167,12 @@ export default function LoginPage() {
   return (
     <Suspense
       fallback={
-        <div className="auth-page-shell">
-          <div className="rounded-2xl border border-[var(--border)] bg-[var(--card)] p-6 shadow-card sm:p-8">
-            <div className="h-8 w-40 animate-pulse rounded bg-[var(--border)]" />
-          </div>
+        <div className="min-h-screen bg-[#050b14] flex items-center justify-center">
+          <div className="h-8 w-40 animate-pulse rounded-full bg-white/10" />
         </div>
       }
     >
       <LoginFormWithSearchParamsKey />
     </Suspense>
   );
-}
+}

+ 96 - 125
src/app/[locale]/auth/register/page.tsx

@@ -8,8 +8,11 @@ import { useAuth } from "@/providers/auth-provider";
 import { ApiError } from "@/lib/api";
 import { isRegisterPasswordValid } from "@/lib/password-rules";
 import { sendRegisterVerificationCode } from "@/lib/register-api";
+import { Eye, EyeOff, UserPlus, CheckCircle2 } from "lucide-react";
+import { cn } from "@/lib/utils";
 
 const SEND_CODE_COOLDOWN_SEC = 60;
+const InputCls = "mt-2 w-full rounded-xl border border-white/10 bg-black/20 px-4 py-3.5 text-sm text-white placeholder-slate-500 focus:border-[#b89458] focus:outline-none focus:ring-1 focus:ring-[#b89458] transition-all";
 
 export default function RegisterPage() {
   const t = useTranslations("auth");
@@ -17,6 +20,7 @@ export default function RegisterPage() {
   const { register, logout } = useAuth();
   const [email, setEmail] = useState("");
   const [password, setPassword] = useState("");
+  const [showPassword, setShowPassword] = useState(false);
   const [code, setCode] = useState("");
   const [err, setErr] = useState<string | null>(null);
   const [sendCooldown, setSendCooldown] = useState(0);
@@ -25,42 +29,30 @@ export default function RegisterPage() {
   const [registerSuccess, setRegisterSuccess] = useState(false);
   const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
   const canSendCode = emailValid && !sendingCode && sendCooldown <= 0;
-  const canSubmit =
-    email.trim().length > 0 &&
-    code.trim().length > 0 &&
-    password.length > 0 &&
-    !submitting;
+  const canSubmit = email.trim().length > 0 && code.trim().length > 0 && password.length > 0 && !submitting;
 
   useEffect(() => {
     if (sendCooldown <= 0) return;
-    const id = window.setInterval(() => {
-      setSendCooldown((s) => (s <= 1 ? 0 : s - 1));
-    }, 1000);
+    const id = window.setInterval(() => setSendCooldown((s) => (s <= 1 ? 0 : s - 1)), 1000);
     return () => window.clearInterval(id);
   }, [sendCooldown]);
 
   useEffect(() => {
     if (!registerSuccess) return;
-    const t = window.setTimeout(() => {
-      router.push("/auth/login?registered=1");
-    }, 1600);
-    return () => window.clearTimeout(t);
+    const tm = window.setTimeout(() => router.push("/auth/login?registered=1"), 1600);
+    return () => window.clearTimeout(tm);
   }, [registerSuccess, router]);
 
   const onSendCode = async () => {
     if (!canSendCode) return;
     setErr(null);
-    if (!emailValid) {
-      setErr(t("errorInvalidEmail"));
-      return;
-    }
+    if (!emailValid) { setErr(t("errorInvalidEmail")); return; }
     setSendingCode(true);
     try {
       await sendRegisterVerificationCode(email.trim());
       setSendCooldown(SEND_CODE_COOLDOWN_SEC);
     } catch (e) {
-      const msg = e instanceof ApiError ? e.message : t("errorApi");
-      setErr(msg);
+      setErr(e instanceof ApiError ? e.message : t("errorApi"));
     } finally {
       setSendingCode(false);
     }
@@ -70,18 +62,9 @@ export default function RegisterPage() {
     e.preventDefault();
     if (!canSubmit) return;
     setErr(null);
-    if (!isRegisterPasswordValid(password)) {
-      setErr(t("errorWeakPassword"));
-      return;
-    }
+    if (!isRegisterPasswordValid(password)) { setErr(t("errorWeakPassword")); return; }
     setSubmitting(true);
-    const r = await register({
-      country: "CN",
-      email: email.trim(),
-      password,
-      name: "学员",
-      code: code.trim(),
-    });
+    const r = await register({ country: "CN", email: email.trim(), password, name: "学员", code: code.trim() });
     if (!r.ok) {
       if (r.message) setErr(r.message);
       else if (r.error === "invalid_email") setErr(t("errorInvalidEmail"));
@@ -98,110 +81,98 @@ export default function RegisterPage() {
 
   if (registerSuccess) {
     return (
-      <div className="auth-page-shell">
-        <div className="rounded-2xl border border-[var(--border)] bg-[var(--card)] p-6 shadow-card sm:p-8">
-          <h1 className="font-serif text-2xl font-semibold text-[var(--navy)]">{t("registerTitle")}</h1>
-          <div
-            className="mt-8 rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-5 text-center"
-            role="status"
-          >
-            <p className="font-medium text-emerald-900">{t("registerSuccessTitle")}</p>
-            <p className="mt-2 text-sm text-emerald-800/90">{t("registerSuccessHint")}</p>
-          </div>
+      <div className="min-h-screen bg-[#050b14] flex flex-col items-center justify-center p-4 relative font-sans overflow-hidden">
+        <div className="pointer-events-none fixed inset-0 z-0"><div className="absolute left-1/2 top-1/2 h-[600px] w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-[#b89458]/10 blur-[150px]" /></div>
+        <div className="relative z-10 w-full max-w-md rounded-[2.5rem] border border-white/10 bg-[#0a1120]/80 p-10 text-center backdrop-blur-2xl shadow-2xl">
+          <div className="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-400"><CheckCircle2 size={40} /></div>
+          <h1 className="font-serif text-2xl font-bold text-white mb-2">{t("registerSuccessTitle")}</h1>
+          <p className="text-sm text-slate-400">{t("registerSuccessHint")}</p>
         </div>
       </div>
     );
   }
 
   return (
-    <div className="auth-page-shell">
-      <div className="rounded-2xl border border-[var(--border)] bg-[var(--card)] p-6 shadow-card sm:p-8">
-        <h1 className="font-serif text-2xl font-semibold text-[var(--navy)]">{t("registerTitle")}</h1>
-        <p className="mt-2 text-sm text-[var(--muted)]">{t("registerEmailOnlyHint")}</p>
-        <form onSubmit={onSubmit} className="mt-8 space-y-4">
-          <div>
-            <label className="text-sm font-medium">{t("email")}</label>
-            <input
-              type="email"
-              required
-              value={email}
-              onChange={(e) => {
-                setEmail(e.target.value);
-                if (err) setErr(null);
-              }}
-              onBlur={() => setEmail((v) => v.trim())}
-              autoComplete="email"
-              className="mt-1 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
-            />
-          </div>
-          <div>
-            <label className="text-sm font-medium">{t("code")}</label>
-            <div className="mt-1 flex gap-2">
-              <input
-                required
-                value={code}
-                onChange={(e) => {
-                  const normalized = e.target.value.replace(/\D/g, "").slice(0, 6);
-                  setCode(normalized);
-                  if (err) setErr(null);
-                }}
-                className="flex-1 rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
-                placeholder="000000"
-                inputMode="numeric"
-                autoComplete="one-time-code"
-              />
-              <button
-                type="button"
-                disabled={!canSendCode}
-                onClick={onSendCode}
-                className="shrink-0 rounded-lg border border-[var(--border)] px-3 text-xs disabled:cursor-not-allowed disabled:opacity-50"
-              >
-                {sendingCode
-                  ? `${t("sendCode")}...`
-                  : sendCooldown > 0
-                  ? t("sendCodeCooldown", { sec: sendCooldown })
-                  : t("sendCode")}
-              </button>
-            </div>
+    <div className="min-h-screen bg-[#050b14] flex flex-col items-center justify-center p-4 relative font-sans overflow-hidden py-16">
+      <div className="pointer-events-none fixed inset-0 z-0">
+        <div className="absolute left-1/2 top-1/2 h-[600px] w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-full bg-[#b89458]/10 blur-[150px]" />
+      </div>
+
+      <div className="relative z-10 w-full max-w-md">
+        <div className="mb-8 flex justify-center">
+          <div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] text-[#5c461a] shadow-lg shadow-[#b89458]/20">
+            <UserPlus size={28} className="translate-x-[2px]" />
           </div>
-          <div>
-            <label className="text-sm font-medium">{t("password")}</label>
-            <input
-              type="password"
-              required
-              autoComplete="new-password"
-              value={password}
-              onChange={(e) => {
-                setPassword(e.target.value);
-                if (err) setErr(null);
-              }}
-              className="mt-1 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm"
-            />
-            <ul className="mt-2 list-disc space-y-1 pl-5 text-xs text-[var(--muted)]">
-              <li>{t("passwordRuleLen")}</li>
-              <li>{t("passwordRuleCase")}</li>
-              <li>{t("passwordRuleMix")}</li>
-            </ul>
+        </div>
+
+        <div className="rounded-[2.5rem] border border-white/10 bg-[#0a1120]/80 p-8 md:p-10 backdrop-blur-2xl shadow-2xl">
+          <div className="text-center mb-8">
+            <h1 className="font-serif text-2xl font-bold text-white">{t("registerTitle")}</h1>
+            <p className="mt-2 text-sm text-slate-400">{t("registerEmailOnlyHint")}</p>
           </div>
-          {err && (
-            <p className="text-sm text-red-600" role="alert" aria-live="polite">
-              {err}
-            </p>
-          )}
-          <button
-            type="submit"
-            disabled={!canSubmit}
-            className="w-full rounded-full bg-[var(--navy)] py-3 text-sm font-semibold text-white transition-opacity disabled:cursor-not-allowed disabled:opacity-60"
-          >
-            {submitting ? `${t("registerBtn")}...` : t("registerBtn")}
-          </button>
-        </form>
-        <p className="mt-6 text-center text-sm">
-          <Link href="/auth/login" className="text-[var(--accent)] hover:underline">
-            {t("toLogin")}
-          </Link>
-        </p>
+
+          <form onSubmit={onSubmit} className="space-y-5">
+            <div>
+              <label className="text-sm font-bold text-slate-300 ml-1">{t("email")}</label>
+              <input type="email" required value={email} onChange={(e) => { setEmail(e.target.value); if (err) setErr(null); }} onBlur={() => setEmail((v) => v.trim())} autoComplete="email" className={InputCls} placeholder="admin@example.com" />
+            </div>
+
+            <div>
+              <label className="text-sm font-bold text-slate-300 ml-1">{t("code")}</label>
+              <div className="mt-2 flex gap-3">
+                <input required value={code} onChange={(e) => { setCode(e.target.value.replace(/\D/g, "").slice(0, 6)); if (err) setErr(null); }} className={cn(InputCls, "mt-0 flex-1")} placeholder="000000" inputMode="numeric" autoComplete="one-time-code" />
+                <button type="button" disabled={!canSendCode} onClick={onSendCode} className="shrink-0 rounded-xl border border-white/10 bg-white/5 px-4 text-xs font-bold text-white transition-colors hover:bg-white/10 disabled:cursor-not-allowed disabled:opacity-50">
+                  {sendingCode ? `${t("sendCode")}...` : sendCooldown > 0 ? t("sendCodeCooldown", { sec: sendCooldown }) : t("sendCode")}
+                </button>
+              </div>
+            </div>
+
+            <div>
+              <label className="text-sm font-bold text-slate-300 ml-1">{t("password")}</label>
+              <div className="relative mt-2">
+                <input
+                  type={showPassword ? "text" : "password"}
+                  required
+                  autoComplete="new-password"
+                  value={password}
+                  onChange={(e) => {
+                    setPassword(e.target.value);
+                    if (err) setErr(null);
+                  }}
+                  className={`${InputCls} mt-0 pr-12`}
+                  placeholder="设置密码"
+                />
+                <button
+                  type="button"
+                  onClick={() => setShowPassword((v) => !v)}
+                  className="absolute right-3 top-1/2 -translate-y-1/2 rounded-md p-1 text-slate-400 hover:text-white focus:outline-none focus:ring-1 focus:ring-[#b89458]"
+                  aria-label={showPassword ? "隐藏密码" : "显示密码"}
+                >
+                  {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
+                </button>
+              </div>
+              <ul className="mt-3 list-disc space-y-1.5 pl-5 text-xs font-medium text-slate-500">
+                <li>{t("passwordRuleLen")}</li>
+                <li>{t("passwordRuleCase")}</li>
+                <li>{t("passwordRuleMix")}</li>
+              </ul>
+            </div>
+
+            {err && <div className="rounded-xl border border-rose-500/30 bg-rose-500/10 p-3 text-center text-sm font-medium text-rose-400" role="alert">{err}</div>}
+
+            <button type="submit" disabled={!canSubmit} className="w-full rounded-2xl bg-gradient-to-br from-[#f3deae] to-[#d9be88] py-4 text-sm font-bold text-[#5c461a] shadow-xl shadow-[#b89458]/10 transition-transform hover:scale-[1.02] disabled:opacity-50 disabled:hover:scale-100 mt-6">
+              {submitting ? `${t("registerBtn")}中...` : t("registerBtn")}
+            </button>
+          </form>
+
+          <p className="mt-8 text-center text-sm text-slate-400">
+            已有账户?{" "}
+            <Link href="/auth/login" className="font-bold text-white hover:text-[#f3deae] transition-colors">
+              {t("toLogin")}
+            </Link>
+          </p>
+        </div>
       </div>
     </div>
   );
-}
+}