Files
soul/app/admin/payment/page.tsx

376 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState, useEffect } from "react"
import { useStore } from "@/lib/store"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import {
Save,
RefreshCw,
Smartphone,
CreditCard,
ExternalLink,
Bitcoin,
Globe,
Copy,
Check,
HelpCircle,
} from "lucide-react"
export default function PaymentConfigPage() {
const { settings, updateSettings, fetchSettings } = useStore()
const [loading, setLoading] = useState(false)
const [localSettings, setLocalSettings] = useState(settings.paymentMethods)
const [copied, setCopied] = useState("")
useEffect(() => {
setLocalSettings(settings.paymentMethods)
}, [settings.paymentMethods])
const handleSave = async () => {
setLoading(true)
updateSettings({ paymentMethods: localSettings })
await new Promise((resolve) => setTimeout(resolve, 800))
setLoading(false)
alert("配置已保存!")
}
const handleRefresh = async () => {
setLoading(true)
await fetchSettings()
setLoading(false)
}
const handleCopy = (text: string, field: string) => {
navigator.clipboard.writeText(text)
setCopied(field)
setTimeout(() => setCopied(""), 2000)
}
const updateWechat = (field: string, value: any) => {
setLocalSettings((prev) => ({
...prev,
wechat: { ...prev.wechat, [field]: value },
}))
}
const updateAlipay = (field: string, value: any) => {
setLocalSettings((prev) => ({
...prev,
alipay: { ...prev.alipay, [field]: value },
}))
}
const updateUsdt = (field: string, value: any) => {
setLocalSettings((prev) => ({
...prev,
usdt: { ...prev.usdt, [field]: value },
}))
}
const updatePaypal = (field: string, value: any) => {
setLocalSettings((prev) => ({
...prev,
paypal: { ...prev.paypal, [field]: value },
}))
}
return (
<div className="p-8 max-w-5xl mx-auto">
<div className="flex justify-between items-center mb-8">
<div>
<h1 className="text-2xl font-bold mb-2 text-white"></h1>
<p className="text-gray-400">USDTPayPal等支付参数</p>
</div>
<div className="flex gap-3">
<Button
variant="outline"
onClick={handleRefresh}
className="border-gray-600 text-gray-300 hover:bg-gray-700/50 bg-transparent"
>
<RefreshCw className={`w-4 h-4 mr-2 ${loading ? "animate-spin" : ""}`} />
</Button>
<Button onClick={handleSave} className="bg-[#38bdac] hover:bg-[#2da396] text-white">
<Save className="w-4 h-4 mr-2" />
</Button>
</div>
</div>
<div className="mb-6 bg-[#07C160]/10 border border-[#07C160]/30 rounded-xl p-4">
<div className="flex items-start gap-3">
<HelpCircle className="w-5 h-5 text-[#07C160] flex-shrink-0 mt-0.5" />
<div className="text-sm">
<p className="font-medium mb-2 text-[#07C160]"></p>
<ol className="text-[#07C160]/80 space-y-1 list-decimal list-inside">
<li></li>
<li>"..." "群二维码"</li>
<li>"..." "发送到电脑"</li>
<li>URL</li>
<li>使</li>
</ol>
<p className="text-[#07C160]/60 mt-2">7使</p>
</div>
</div>
</div>
<Tabs defaultValue="wechat" className="space-y-6">
<TabsList className="bg-[#0f2137] border border-gray-700/50 p-1 grid grid-cols-4 w-full">
<TabsTrigger
value="wechat"
className="data-[state=active]:bg-[#07C160]/20 data-[state=active]:text-[#07C160] text-gray-400"
>
<Smartphone className="w-4 h-4 mr-2" />
</TabsTrigger>
<TabsTrigger
value="alipay"
className="data-[state=active]:bg-[#1677FF]/20 data-[state=active]:text-[#1677FF] text-gray-400"
>
<CreditCard className="w-4 h-4 mr-2" />
</TabsTrigger>
<TabsTrigger
value="usdt"
className="data-[state=active]:bg-[#26A17B]/20 data-[state=active]:text-[#26A17B] text-gray-400"
>
<Bitcoin className="w-4 h-4 mr-2" />
USDT
</TabsTrigger>
<TabsTrigger
value="paypal"
className="data-[state=active]:bg-[#003087]/20 data-[state=active]:text-[#169BD7] text-gray-400"
>
<Globe className="w-4 h-4 mr-2" />
PayPal
</TabsTrigger>
</TabsList>
{/* 微信支付配置 */}
<TabsContent value="wechat" className="space-y-4">
<Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<div className="space-y-1">
<CardTitle className="text-[#07C160] flex items-center gap-2">
<Smartphone className="w-5 h-5" />
</CardTitle>
<CardDescription className="text-gray-400"></CardDescription>
</div>
<Switch checked={localSettings.wechat.enabled} onCheckedChange={(c) => updateWechat("enabled", c)} />
</CardHeader>
<CardContent className="space-y-4">
{/* API配置 */}
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label className="text-gray-300">AppID</Label>
<Input
className="bg-[#0a1628] border-gray-700 text-white font-mono text-sm"
value={localSettings.wechat.websiteAppId || ""}
onChange={(e) => updateWechat("websiteAppId", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"></Label>
<Input
className="bg-[#0a1628] border-gray-700 text-white font-mono text-sm"
value={localSettings.wechat.merchantId || ""}
onChange={(e) => updateWechat("merchantId", e.target.value)}
/>
</div>
</div>
{/* 跳转链接配置 - 重点 */}
<div className="border-t border-gray-700/50 pt-4 space-y-4">
<h4 className="text-white font-medium flex items-center gap-2">
<ExternalLink className="w-4 h-4 text-[#38bdac]" />
</h4>
<div className="space-y-2">
<Label className="text-gray-300">/</Label>
<Input
className="bg-[#0a1628] border-gray-700 text-white placeholder:text-gray-500"
placeholder="https://收款码图片URL 或 weixin://支付链接"
value={localSettings.wechat.qrCode || ""}
onChange={(e) => updateWechat("qrCode", e.target.value)}
/>
<p className="text-xs text-gray-500">URL</p>
</div>
<div className="space-y-2 bg-[#07C160]/5 p-4 rounded-xl border border-[#07C160]/20">
<Label className="text-[#07C160] font-medium"></Label>
<Input
className="bg-[#0a1628] border-[#07C160]/30 text-white placeholder:text-gray-500"
placeholder="https://weixin.qq.com/g/... 或微信群二维码图片URL"
value={localSettings.wechat.groupQrCode || ""}
onChange={(e) => updateWechat("groupQrCode", e.target.value)}
/>
<p className="text-xs text-[#07C160]/70"></p>
</div>
</div>
</CardContent>
</Card>
</TabsContent>
{/* 支付宝配置 */}
<TabsContent value="alipay" className="space-y-4">
<Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<div className="space-y-1">
<CardTitle className="text-[#1677FF] flex items-center gap-2">
<CreditCard className="w-5 h-5" />
</CardTitle>
<CardDescription className="text-gray-400"></CardDescription>
</div>
<Switch checked={localSettings.alipay.enabled} onCheckedChange={(c) => updateAlipay("enabled", c)} />
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label className="text-gray-300"> (PID)</Label>
<div className="flex gap-2">
<Input
className="bg-[#0a1628] border-gray-700 text-white font-mono text-sm"
value={localSettings.alipay.partnerId || ""}
onChange={(e) => updateAlipay("partnerId", e.target.value)}
/>
<Button
size="icon"
variant="outline"
className="border-gray-700 bg-transparent"
onClick={() => handleCopy(localSettings.alipay.partnerId || "", "pid")}
>
{copied === "pid" ? (
<Check className="w-4 h-4 text-green-500" />
) : (
<Copy className="w-4 h-4 text-gray-400" />
)}
</Button>
</div>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> (Key)</Label>
<Input
type="password"
className="bg-[#0a1628] border-gray-700 text-white font-mono text-sm"
value={localSettings.alipay.securityKey || ""}
onChange={(e) => updateAlipay("securityKey", e.target.value)}
/>
</div>
</div>
<div className="border-t border-gray-700/50 pt-4 space-y-4">
<h4 className="text-white font-medium flex items-center gap-2">
<ExternalLink className="w-4 h-4 text-[#38bdac]" />
</h4>
<div className="space-y-2">
<Label className="text-gray-300">/</Label>
<Input
className="bg-[#0a1628] border-gray-700 text-white placeholder:text-gray-500"
placeholder="https://qr.alipay.com/... 或收款码图片URL"
value={localSettings.alipay.qrCode || ""}
onChange={(e) => updateAlipay("qrCode", e.target.value)}
/>
<p className="text-xs text-gray-500"></p>
</div>
</div>
</CardContent>
</Card>
</TabsContent>
{/* USDT配置 */}
<TabsContent value="usdt" className="space-y-4">
<Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<div className="space-y-1">
<CardTitle className="text-[#26A17B] flex items-center gap-2">
<Bitcoin className="w-5 h-5" />
USDT配置
</CardTitle>
<CardDescription className="text-gray-400"></CardDescription>
</div>
<Switch checked={localSettings.usdt.enabled} onCheckedChange={(c) => updateUsdt("enabled", c)} />
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label className="text-gray-300"></Label>
<select
className="w-full bg-[#0a1628] border border-gray-700 text-white rounded-md p-2"
value={localSettings.usdt.network}
onChange={(e) => updateUsdt("network", e.target.value)}
>
<option value="TRC20">TRC20 ()</option>
<option value="ERC20">ERC20 ()</option>
<option value="BEP20">BEP20 ()</option>
</select>
</div>
<div className="space-y-2">
<Label className="text-gray-300"></Label>
<Input
className="bg-[#0a1628] border-gray-700 text-white font-mono text-sm"
placeholder="T... (TRC20地址)"
value={localSettings.usdt.address || ""}
onChange={(e) => updateUsdt("address", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> (1 USD = ? CNY)</Label>
<Input
type="number"
className="bg-[#0a1628] border-gray-700 text-white"
value={localSettings.usdt.exchangeRate}
onChange={(e) => updateUsdt("exchangeRate", Number.parseFloat(e.target.value) || 7.2)}
/>
</div>
</CardContent>
</Card>
</TabsContent>
{/* PayPal配置 */}
<TabsContent value="paypal" className="space-y-4">
<Card className="bg-[#0f2137] border-gray-700/50 shadow-xl">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<div className="space-y-1">
<CardTitle className="text-[#169BD7] flex items-center gap-2">
<Globe className="w-5 h-5" />
PayPal配置
</CardTitle>
<CardDescription className="text-gray-400">PayPal收款账户</CardDescription>
</div>
<Switch checked={localSettings.paypal.enabled} onCheckedChange={(c) => updatePaypal("enabled", c)} />
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label className="text-gray-300">PayPal邮箱</Label>
<Input
className="bg-[#0a1628] border-gray-700 text-white"
placeholder="your@email.com"
value={localSettings.paypal.email || ""}
onChange={(e) => updatePaypal("email", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> (1 USD = ? CNY)</Label>
<Input
type="number"
className="bg-[#0a1628] border-gray-700 text-white"
value={localSettings.paypal.exchangeRate}
onChange={(e) => updatePaypal("exchangeRate", Number.parseFloat(e.target.value) || 7.2)}
/>
</div>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
)
}