Files
Mycontent/app/admin/payment/page.tsx
2025-12-29 14:01:37 +08:00

249 lines
12 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 } from "lucide-react"
export default function PaymentConfigPage() {
const { settings, updateSettings, fetchSettings } = useStore()
const [loading, setLoading] = useState(false)
const [localSettings, setLocalSettings] = useState(settings.paymentMethods)
// Sync with store on mount
useEffect(() => {
setLocalSettings(settings.paymentMethods)
}, [settings.paymentMethods])
const handleSave = async () => {
setLoading(true)
// Update store (and local storage)
updateSettings({ paymentMethods: localSettings })
// Simulate API call delay
await new Promise(resolve => setTimeout(resolve, 800))
setLoading(false)
alert("配置已保存!")
}
const handleRefresh = async () => {
setLoading(true)
await fetchSettings()
setLoading(false)
}
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 }
}))
}
return (
<div className="p-8 max-w-5xl mx-auto text-white">
<div className="flex justify-between items-center mb-8">
<div>
<h1 className="text-2xl font-bold mb-2"></h1>
<p className="text-gray-400">USDT支付参数</p>
</div>
<div className="flex gap-4">
<Button variant="outline" onClick={handleRefresh} className="border-gray-600 text-gray-300 hover:text-white 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="grid grid-cols-1 gap-8">
{/* Wechat Pay */}
<Card className="bg-[#1e293b] border-gray-700">
<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">
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"><path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .167-.054l1.903-1.114a.864.864 0 0 1 .717-.098 10.16 10.16 0 0 0 2.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178A1.17 1.17 0 0 1 4.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178 1.17 1.17 0 0 1-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 0 1 .598.082l1.584.926a.272.272 0 0 0 .14.047c.134 0 .24-.111.24-.247 0-.06-.023-.12-.038-.177l-.327-1.233a.582.582 0 0 1-.023-.156.49.49 0 0 1 .201-.398C23.024 18.48 24 16.82 24 14.98c0-3.21-2.931-5.837-6.656-6.088V8.89c-.135-.01-.269-.03-.406-.03zm-2.53 3.274c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.97-.982zm4.844 0c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.969-.982z"/></svg>
</CardTitle>
<CardDescription className="text-gray-400">API密钥</CardDescription>
</div>
<Switch
checked={localSettings.wechat.enabled}
onCheckedChange={(c) => updateWechat('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"> AppID</Label>
<Input
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="wx..."
value={localSettings.wechat.websiteAppId || ''}
onChange={(e) => updateWechat('websiteAppId', e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> AppSecret</Label>
<Input
type="password"
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="......"
value={localSettings.wechat.websiteAppSecret || ''}
onChange={(e) => updateWechat('websiteAppSecret', e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> (MchId)</Label>
<Input
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="160..."
value={localSettings.wechat.merchantId || ''}
onChange={(e) => updateWechat('merchantId', e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300">API v3 </Label>
<Input
type="password"
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="......"
value={localSettings.wechat.apiKey || ''}
onChange={(e) => updateWechat('apiKey', e.target.value)}
/>
</div>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> URL ()</Label>
<Input
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="/images/wechat-pay.png"
value={localSettings.wechat.qrCode || ''}
onChange={(e) => updateWechat('qrCode', e.target.value)}
/>
<p className="text-xs text-gray-500"></p>
</div>
</CardContent>
</Card>
{/* Alipay */}
<Card className="bg-[#1e293b] border-gray-700">
<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">
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"><path d="M8.77 20.62l9.92-4.33c-.12-.33-.24-.66-.38-.99-.14-.33-.3-.66-.47-.99H8.08c-2.2 0-3.99-1.79-3.99-3.99V8.08c0-2.2 1.79-3.99 3.99-3.99h7.84c2.2 0 3.99 1.79 3.99 3.99v2.24h-8.66c-.55 0-1 .45-1 1s.45 1 1 1h10.66c-.18 1.73-.71 3.36-1.53 4.83l-2.76 1.2c-.74-1.69-1.74-3.24-2.93-4.6-.52-.59-1.11-1.13-1.76-1.59H4.09v4.24c0 2.2 1.79 3.99 3.99 3.99h.69v.23z"/></svg>
</CardTitle>
<CardDescription className="text-gray-400">PID及密钥</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>
<Input
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="2088..."
value={localSettings.alipay.partnerId || ''}
onChange={(e) => updateAlipay('partnerId', e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> (Key)</Label>
<Input
type="password"
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="......"
value={localSettings.alipay.securityKey || ''}
onChange={(e) => updateAlipay('securityKey', e.target.value)}
/>
</div>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> URL ()</Label>
<Input
className="bg-[#0f172a] border-gray-600 text-white"
placeholder="/images/alipay.png"
value={localSettings.alipay.qrCode || ''}
onChange={(e) => updateAlipay('qrCode', e.target.value)}
/>
</div>
</CardContent>
</Card>
{/* USDT */}
<Card className="bg-[#1e293b] border-gray-700">
<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">
<span className="font-bold"></span> 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="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label className="text-gray-300"></Label>
<Input
className="bg-[#0f172a] border-gray-600 text-white"
value={localSettings.usdt.network || 'TRC20'}
onChange={(e) => updateUsdt('network', e.target.value)}
/>
</div>
<div className="space-y-2">
<Label className="text-gray-300"> (USD -&gt; CNY)</Label>
<Input
type="number"
className="bg-[#0f172a] border-gray-600 text-white"
value={localSettings.usdt.exchangeRate || 7.2}
onChange={(e) => updateUsdt('exchangeRate', parseFloat(e.target.value))}
/>
</div>
</div>
<div className="space-y-2">
<Label className="text-gray-300"></Label>
<Input
className="bg-[#0f172a] border-gray-600 text-white font-mono"
placeholder="T..."
value={localSettings.usdt.address || ''}
onChange={(e) => updateUsdt('address', e.target.value)}
/>
</div>
</CardContent>
</Card>
</div>
</div>
)
}