"use client" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Separator } from "@/components/ui/separator" import { requestWithAuth } from "@/lib/api" import { getWalletBalance, listWalletTransactions } from "@/lib/api/transactions" import { toApiError } from "@/lib/errors" import { notifyInfo, notifySuccess } from "@/lib/toast" import type { WalletTransaction } from "@/lib/types" import { useAuthStore } from "@/store/auth" import { ArrowDownLeft, ArrowUpRight, CreditCard, DollarSign, RefreshCw, Wallet, } from "lucide-react" import { useCallback, useEffect, useMemo, useState } from "react" const typeLabels: Record = { topup: "充值", payment: "支付", income: "收入", withdrawal: "提现", refund: "退款", } const typeIcons: Record = { topup: ArrowDownLeft, payment: ArrowUpRight, income: ArrowDownLeft, withdrawal: ArrowUpRight, refund: ArrowDownLeft, } export default function WalletPage() { const { currentRole } = useAuthStore() const isConsumer = currentRole === "consumer" const [balance, setBalance] = useState(null) const [transactions, setTransactions] = useState([]) const [isLoading, setIsLoading] = useState(false) const [loadError, setLoadError] = useState(null) const [selectedAmount, setSelectedAmount] = useState(null) const [customAmount, setCustomAmount] = useState("") const [lastRefreshedAt, setLastRefreshedAt] = useState(null) const filteredTransactions = useMemo(() => { return transactions.filter((tx) => { if (isConsumer) { return ["topup", "payment", "refund"].includes(tx.type) } return ["income", "withdrawal"].includes(tx.type) }) }, [isConsumer, transactions]) const loadWalletData = useCallback(async (options?: { showToast?: boolean }) => { setIsLoading(true) setLoadError(null) try { const res = await requestWithAuth(async () => { const [b, items] = await Promise.all([ getWalletBalance(), listWalletTransactions({ offset: 0, limit: 1000 }), ]) return { balance: b, transactions: items } }) if (!res) { setLoadError("请先登录") return } setBalance(res.balance) setTransactions(res.transactions) if (options?.showToast) notifySuccess("交易记录已刷新") } catch (error) { setLoadError(toApiError(error).msg) } finally { setIsLoading(false) } }, []) useEffect(() => { void loadWalletData() }, [loadWalletData]) const handleTopUp = (rawAmount?: number) => { const amount = rawAmount ?? Number(customAmount) if (!Number.isFinite(amount) || amount <= 0) return notifyInfo("充值暂未开放") setCustomAmount("") setSelectedAmount(null) } const handleWithdraw = () => { notifyInfo("提现暂未开放") setCustomAmount("") } return (

钱包

{isConsumer ? "账户余额" : "收入余额"}

{balance === null ? ( -- ) : ( <>¥{balance.toFixed(2)} )}

{loadError &&

{loadError}

}
{isConsumer ? ( ) : ( )}
{isConsumer ? ( 快捷充值
{[50, 100, 200, 500, 1000, 2000].map((amount) => ( ))}
{ setCustomAmount(event.target.value) setSelectedAmount(null) }} />
) : ( 收入概览

本月收入

¥1,280.00

待结算

¥320.00

已提现

¥5,400.00

)} 交易记录 {lastRefreshedAt && (

最近刷新:{lastRefreshedAt}

)} {isLoading ? (
加载中...
) : filteredTransactions.length > 0 ? ( filteredTransactions.map((tx) => { const Icon = typeIcons[tx.type] const isIncome = Number(tx.amount) > 0 return (
{Icon ? : }

{tx.description}

{new Date(tx.createdAt).toLocaleString("zh-CN")}

{isIncome ? "+" : ""}¥{Math.abs(Number(tx.amount)).toFixed(2)}

{typeLabels[tx.type]}
) }) ) : (
暂无交易记录
)}
) }