Files
soul-yongping/next-project/components/modules/distribution/auto-withdraw-modal.tsx
2026-02-09 14:43:35 +08:00

292 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 { X, Settings, CheckCircle, AlertCircle, Zap } from "lucide-react"
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 { useStore } from "@/lib/store"
interface AutoWithdrawModalProps {
isOpen: boolean
onClose: () => void
}
interface AutoWithdrawConfig {
enabled: boolean
minAmount: number
method: 'wechat' | 'alipay'
account: string
name: string
}
export function AutoWithdrawModal({ isOpen, onClose }: AutoWithdrawModalProps) {
const { user } = useStore()
const [config, setConfig] = useState<AutoWithdrawConfig>({
enabled: false,
minAmount: 100,
method: 'wechat',
account: '',
name: '',
})
const [isLoading, setIsLoading] = useState(false)
const [isSuccess, setIsSuccess] = useState(false)
const [error, setError] = useState<string | null>(null)
// 加载已保存的配置
useEffect(() => {
if (isOpen && user?.id) {
const savedConfig = localStorage.getItem(`auto_withdraw_config_${user.id}`)
if (savedConfig) {
try {
setConfig(JSON.parse(savedConfig))
} catch {
// 忽略解析错误
}
}
}
}, [isOpen, user?.id])
if (!isOpen) return null
const handleSave = async () => {
if (!user?.id) return
// 验证
if (config.enabled) {
if (config.minAmount < 10) {
setError('最低提现金额不能少于10元')
return
}
if (!config.account) {
setError('请填写提现账号')
return
}
if (!config.name) {
setError('请填写真实姓名')
return
}
}
setIsLoading(true)
setError(null)
try {
// 保存配置到本地存储
localStorage.setItem(`auto_withdraw_config_${user.id}`, JSON.stringify(config))
// 如果启用了自动提现,也发送到服务器
if (config.enabled) {
await fetch('/api/distribution/auto-withdraw-config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId: user.id,
...config,
}),
})
}
setIsSuccess(true)
} catch (err) {
setError('保存失败,请重试')
console.error('保存自动提现配置失败:', err)
} finally {
setIsLoading(false)
}
}
const handleClose = () => {
setIsSuccess(false)
setError(null)
onClose()
}
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
{/* 遮罩 */}
<div
className="absolute inset-0 bg-black/80 backdrop-blur-sm"
onClick={handleClose}
/>
{/* 弹窗内容 */}
<div className="relative w-full max-w-md bg-gradient-to-b from-[#1a1a2e] to-[#0f0f1a] rounded-2xl overflow-hidden shadow-2xl border border-white/10 animate-in fade-in zoom-in-95 duration-200">
{/* 关闭按钮 */}
<button
onClick={handleClose}
className="absolute top-4 right-4 p-2 rounded-full bg-white/5 hover:bg-white/10 transition-colors z-10"
>
<X className="w-5 h-5 text-gray-400" />
</button>
{isSuccess ? (
/* 成功状态 */
<div className="p-8 flex flex-col items-center text-center">
<div className="w-20 h-20 bg-green-500/20 rounded-full flex items-center justify-center mb-4">
<CheckCircle className="w-10 h-10 text-green-400" />
</div>
<h3 className="text-xl font-bold text-white mb-2"></h3>
<p className="text-gray-400 text-sm mb-6">
{config.enabled
? `当可提现金额达到 ¥${config.minAmount} 时,将自动打款到您的${config.method === 'wechat' ? '微信' : '支付宝'}账户`
: '自动提现已关闭'
}
</p>
<Button
onClick={handleClose}
className="w-full bg-[#38bdac] hover:bg-[#2da396] text-white"
>
</Button>
</div>
) : (
/* 设置表单 */
<div className="p-6">
{/* 标题 */}
<div className="flex items-center gap-3 mb-6">
<div className="w-12 h-12 bg-[#38bdac]/20 rounded-xl flex items-center justify-center">
<Zap className="w-6 h-6 text-[#38bdac]" />
</div>
<div>
<h3 className="text-lg font-bold text-white"></h3>
<p className="text-sm text-gray-400"></p>
</div>
</div>
{/* 错误提示 */}
{error && (
<div className="mb-4 p-3 bg-red-500/10 border border-red-500/20 rounded-lg flex items-center gap-2">
<AlertCircle className="w-4 h-4 text-red-400" />
<span className="text-sm text-red-400">{error}</span>
</div>
)}
<div className="space-y-5">
{/* 启用开关 */}
<div className="flex items-center justify-between p-4 bg-white/5 rounded-xl">
<div className="flex items-center gap-3">
<Settings className="w-5 h-5 text-gray-400" />
<span className="text-white font-medium"></span>
</div>
<Switch
checked={config.enabled}
onCheckedChange={(checked) => setConfig({ ...config, enabled: checked })}
/>
</div>
{config.enabled && (
<>
{/* 最低金额 */}
<div className="space-y-2">
<Label className="text-gray-400"></Label>
<div className="relative">
<span className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 font-medium">¥</span>
<Input
type="number"
min="10"
step="10"
value={config.minAmount}
onChange={(e) => setConfig({ ...config, minAmount: Number(e.target.value) })}
className="pl-8 bg-white/5 border-white/10 text-white h-12"
placeholder="100"
/>
</div>
<p className="text-xs text-gray-500">10</p>
</div>
{/* 提现方式 */}
<div className="space-y-2">
<Label className="text-gray-400"></Label>
<div className="flex gap-3">
<button
type="button"
onClick={() => setConfig({ ...config, method: 'wechat' })}
className={`flex-1 py-3 px-4 rounded-xl border text-sm font-medium transition-all ${
config.method === 'wechat'
? 'border-green-500 bg-green-500/10 text-green-400'
: 'border-white/10 bg-white/5 text-gray-400 hover:bg-white/10'
}`}
>
<div className="flex items-center justify-center gap-2">
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
<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 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098c1.044.303 2.166.468 3.339.468h.319c-.081-.3-.126-.613-.126-.94 0-3.497 3.32-6.336 7.42-6.336.168 0 .335.005.5.015-.591-3.61-4.195-6.286-8.615-6.286z"/>
<path d="M18.695 9.37c-3.442 0-6.236 2.302-6.236 5.145 0 2.843 2.794 5.145 6.236 5.145.852 0 1.666-.135 2.412-.384a.632.632 0 01.523.072l1.394.816a.235.235 0 00.122.04.214.214 0 00.213-.215c0-.052-.021-.104-.035-.155l-.285-1.082a.434.434 0 01.156-.484c1.34-.987 2.195-2.443 2.195-4.073 0-2.843-2.794-5.145-6.236-5.145z"/>
</svg>
</div>
</button>
<button
type="button"
onClick={() => setConfig({ ...config, method: 'alipay' })}
className={`flex-1 py-3 px-4 rounded-xl border text-sm font-medium transition-all ${
config.method === 'alipay'
? 'border-blue-500 bg-blue-500/10 text-blue-400'
: 'border-white/10 bg-white/5 text-gray-400 hover:bg-white/10'
}`}
>
<div className="flex items-center justify-center gap-2">
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
<path d="M19.5 3h-15A1.5 1.5 0 003 4.5v15A1.5 1.5 0 004.5 21h15a1.5 1.5 0 001.5-1.5v-15A1.5 1.5 0 0019.5 3zm-8.35 13.42c-2.16 0-3.92-1.75-3.92-3.92s1.76-3.92 3.92-3.92 3.92 1.75 3.92 3.92-1.76 3.92-3.92 3.92zm6.52.98c-.87-.4-1.75-.8-2.64-1.18.67-.91 1.16-1.96 1.44-3.08h-2.16v-.85h2.58v-.5h-2.58v-.99h1.85c-.1-.35-.25-.68-.44-.99h-1.41V8.96h3.23v.85h1.16v.85h-1.7c.19.31.34.64.44.99h1.26v.85h-2.33c-.28 1.12-.77 2.17-1.44 3.08.89.38 1.77.78 2.64 1.18-.31.55-.63 1.1-.9 1.64z"/>
</svg>
</div>
</button>
</div>
</div>
{/* 收款账号 */}
<div className="space-y-2">
<Label className="text-gray-400">
{config.method === 'wechat' ? '微信openid' : '支付宝账号'}
</Label>
<Input
value={config.account}
onChange={(e) => setConfig({ ...config, account: e.target.value })}
className="bg-white/5 border-white/10 text-white h-12"
placeholder={config.method === 'wechat' ? '请输入微信openid' : '请输入支付宝账号'}
/>
{config.method === 'wechat' && (
<p className="text-xs text-gray-500">openid</p>
)}
</div>
{/* 真实姓名 */}
<div className="space-y-2">
<Label className="text-gray-400"></Label>
<Input
value={config.name}
onChange={(e) => setConfig({ ...config, name: e.target.value })}
className="bg-white/5 border-white/10 text-white h-12"
placeholder="请输入收款人真实姓名"
/>
<p className="text-xs text-gray-500"></p>
</div>
</>
)}
</div>
{/* 保存按钮 */}
<Button
onClick={handleSave}
disabled={isLoading}
className="w-full mt-6 h-12 bg-[#38bdac] hover:bg-[#2da396] text-white font-medium"
>
{isLoading ? '保存中...' : '保存设置'}
</Button>
{/* 提示 */}
<div className="mt-4 p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
<p className="text-xs text-yellow-400/80 leading-relaxed">
💡
openid
</p>
</div>
</div>
)}
</div>
</div>
)
}