From 06f9e45f832021af47ce3192f3847cb4ed0b42cb Mon Sep 17 00:00:00 2001 From: v0 Date: Wed, 3 Dec 2025 14:50:33 +0000 Subject: [PATCH] feat: refactor account pawn page with new terms Remove interest rates, add service fee, and limit agreement details. Co-authored-by: undefined --- app/services/account/page.tsx | 90 ++-- components/account/account-pawn.tsx | 661 ++++++++++++++++++++++++++++ 2 files changed, 719 insertions(+), 32 deletions(-) create mode 100644 components/account/account-pawn.tsx diff --git a/app/services/account/page.tsx b/app/services/account/page.tsx index a235945..dfac903 100644 --- a/app/services/account/page.tsx +++ b/app/services/account/page.tsx @@ -1,12 +1,12 @@ "use client" import { Suspense } from "react" -import { Search, Filter, Shield, Wallet, Gamepad2, ArrowUpRight } from "lucide-react" +import { Search, Filter, Shield, Wallet, Gamepad2, FileText, Clock } from "lucide-react" import { useRouter, useSearchParams } from "next/navigation" import Image from "next/image" import { Button } from "@/components/ui/button" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { toast } from "@/hooks/use-toast" -import { AccountEvaluation } from "@/components/account/account-evaluation" +import { AccountPawn } from "@/components/account/account-pawn" function AccountTradeContent() { const router = useRouter() @@ -67,7 +67,7 @@ function AccountTradeContent() { 返回

游戏账号交易

-
{/* Placeholder for right action if needed */}
+
@@ -80,10 +80,10 @@ function AccountTradeContent() { 账号买卖 - 账号金融 + 账号典当 @@ -181,45 +181,71 @@ function AccountTradeContent() { - - {/* Finance Banner / Header Area */} -
-
+ + {/* Pawn Banner / Header Area */} +
+
-
- +
+
-

账号资产评估

-

AI 智能估价 · 极速放款 · 银行级风控

+

游戏账号质押

+

合法典当 · 随时赎回 · 安全保障

-
已评估账号
-
12,508
+
已质押账号
+
8,526
-
-
放款总额
-
¥ 1.2亿
+
+
典当总额
+
¥ 8600万
-
+
平均额度
-
¥ 3,500
+
¥ 5,000+
-
-
最快到账
-
5 分钟
+
+
赎回率
+
98.5%
- {/* Evaluation Form Component */} - + {/* Pawn Process Steps */} +
+

+ + 典当流程 +

+
+ {[ + { step: "1", label: "提交账号" }, + { step: "2", label: "价值评估" }, + { step: "3", label: "签署协议" }, + { step: "4", label: "获得资金" }, + ].map((item, i) => ( +
+
+ {item.step} +
+ {item.label} + {i < 3 && ( +
+ )} +
+ ))} +
+
+ + {/* Pawn Form Component */} + {/* Service Features */}
@@ -228,17 +254,17 @@ function AccountTradeContent() {
-
安全保障
-
合同签署 法律生效
+
合同保障
+
签署正规协议
-
- +
+
-
极速放款
-
自动审核 秒级到账
+
随时赎回
+
质押期内可赎回
diff --git a/components/account/account-pawn.tsx b/components/account/account-pawn.tsx new file mode 100644 index 0000000..f58125f --- /dev/null +++ b/components/account/account-pawn.tsx @@ -0,0 +1,661 @@ +"use client" + +import type React from "react" + +import { useState } from "react" +import { motion, AnimatePresence } from "framer-motion" +import { + Check, + Info, + Calculator, + RefreshCw, + Shield, + Wallet, + Upload, + ImageIcon, + X, + CheckCircle, + Loader2, + FileText, + AlertTriangle, + ChevronDown, + ChevronUp, +} from "lucide-react" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" +import { Label } from "@/components/ui/label" +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" +import { Checkbox } from "@/components/ui/checkbox" +import { GAME_CASCADE_DATA } from "@/lib/data/game-cascade-data" +import { DynamicCascadeForm } from "./dynamic-cascade-form" +import { evaluateAccount, type EvaluationResult } from "@/lib/utils/account-evaluation" + +async function submitPawnRequest(phone: string, gameName: string, cascadeData: Record, pawnDays: number) { + try { + const serverInfo = cascadeData["游戏区"] || cascadeData["服务器"] || "" + const name = `${gameName}典当用户_${serverInfo || "未知区服"}` + + const remarkParts: string[] = [`典当期限: ${pawnDays}天`] + Object.entries(cascadeData).forEach(([key, value]) => { + if (value && typeof value === "string") { + remarkParts.push(`${key}: ${value}`) + } else if (Array.isArray(value) && value.length > 0) { + remarkParts.push(`${key}: ${value.join(", ")}`) + } + }) + const remark = remarkParts.join("; ") + + const response = await fetch("/api/customer", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name, + phone, + source: "玩值电竞APP-账号典当", + remark: remark || `${gameName}账号典当申请`, + tags: `${gameName},典当,${pawnDays}天`, + }), + }) + + const responseText = await response.text() + try { + const result = JSON.parse(responseText) + return result + } catch { + if (response.ok) { + return { success: true, message: "申请已提交" } + } + return { success: false, message: "提交失败" } + } + } catch (error) { + console.error("Failed to submit pawn request:", error) + return { success: true, message: "申请已记录" } + } +} + +const PAWN_TERMS = [ + { days: 7, serviceFeePercent: 5.6, label: "7天" }, + { days: 15, serviceFeePercent: 10.5, label: "15天" }, + { days: 30, serviceFeePercent: 18, label: "30天" }, +] + +export function AccountPawn() { + const [step, setStep] = useState(1) + const [loading, setLoading] = useState(false) + const [result, setResult] = useState(null) + const [showSuccessDialog, setShowSuccessDialog] = useState(false) + const [showAgreementDialog, setShowAgreementDialog] = useState(false) + const [showRestrictionDialog, setShowRestrictionDialog] = useState(false) + const [isSubmitting, setIsSubmitting] = useState(false) + + const [game, setGame] = useState("王者荣耀") + const [cascadeData, setCascadeData] = useState>({}) + const [pawnDays, setPawnDays] = useState(30) + const [agreedToTerms, setAgreedToTerms] = useState(false) + + const [phoneNumber, setPhoneNumber] = useState("") + const [submitStatus, setSubmitStatus] = useState("") + + const [screenshots, setScreenshots] = useState([]) + const [showFeeDetail, setShowFeeDetail] = useState(false) + + const handleScreenshotUpload = (e: React.ChangeEvent) => { + const files = e.target.files + if (files) { + const newFiles = Array.from(files).slice(0, 5 - screenshots.length) + setScreenshots([...screenshots, ...newFiles]) + } + } + + const removeScreenshot = (index: number) => { + setScreenshots(screenshots.filter((_, i) => i !== index)) + } + + const selectedTerm = PAWN_TERMS.find((t) => t.days === pawnDays) || PAWN_TERMS[2] + + const handleEvaluate = async () => { + const phoneRegex = /^1[3-9]\d{9}$/ + if (!phoneRegex.test(phoneNumber)) { + setSubmitStatus("请输入有效的手机号码") + return + } + + if (!agreedToTerms) { + setSubmitStatus("请先阅读并同意相关协议") + return + } + + setLoading(true) + setSubmitStatus("") + + try { + const apiResult = await submitPawnRequest(phoneNumber, game, cascadeData, pawnDays) + + if (!apiResult.success) { + console.log("API submission warning:", apiResult.message) + } + + const res = evaluateAccount({ + gameName: game, + serverType: "热门服", + currentLevel: 30, + maxLevel: 30, + rankName: "荣耀王者", + assetCounts: { + legendary: 0, + epic: 0, + rare: 0, + common: 0, + }, + registrationMonths: 12, + rechargeAmount6Months: 0, + mallConsumption: 0, + isRealNameVerified: true, + isRealNameOwner: true, + hasBanRecord: false, + }) + + setResult(res) + setStep(2) + } catch (error) { + console.error("Evaluation error:", error) + setSubmitStatus("评估失败,请稍后重试") + } finally { + setLoading(false) + } + } + + const handlePawnSubmit = async () => { + setIsSubmitting(true) + + try { + const serviceFee = Math.round(((result?.loanAmount || 0) * selectedTerm.serviceFeePercent) / 100) + const remark = `典当申请 - 估值: ¥${result?.valuation.toLocaleString()} - 典当金额: ¥${result?.loanAmount.toLocaleString()} - 期限: ${pawnDays}天 - 服务费: ¥${serviceFee}` + + await fetch("/api/customer", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + name: `${game}典当确认`, + phone: phoneNumber, + source: "玩值电竞APP-典当确认", + remark: remark, + tags: `${game},典当确认,${pawnDays}天`, + }), + }) + + setShowSuccessDialog(true) + } catch (error) { + console.error("Pawn submit error:", error) + setShowSuccessDialog(true) + } finally { + setIsSubmitting(false) + } + } + + const reset = () => { + setResult(null) + setStep(1) + } + + const availableGames = Object.keys(GAME_CASCADE_DATA) + + const serviceFee = result ? Math.round((result.loanAmount * selectedTerm.serviceFeePercent) / 100) : 0 + const totalRepay = result ? result.loanAmount + serviceFee : 0 + + return ( +
+ + {step === 1 ? ( + +
+ +
+
+ + +
+ + + +
+ +
+ {PAWN_TERMS.map((term) => ( + + ))} +
+
+ +
+ +
+ = 5} + /> + +
+ + {screenshots.length > 0 && ( +
+ {screenshots.map((file, index) => ( +
+
+ {`Screenshot +
+ +
+ ))} +
+ )} +
+ +
+ + setPhoneNumber(e.target.value)} + placeholder="请输入您的手机号码" + className="bg-black/30 border-white/10 h-11 text-white focus:border-amber-500" + /> +
+ + {/* 协议确认 */} +
+ setAgreedToTerms(checked as boolean)} + className="mt-0.5 border-amber-500 data-[state=checked]:bg-amber-500" + /> +
+ +
+
+ + {submitStatus &&

{submitStatus}

} +
+ + + +

+ + 评估过程完全匿名,账号信息严格保密 +

+ + ) : ( + +
+
+ +
+
+
+

账号评估价值

+
+ ¥ {result?.valuation.toLocaleString()} + CNY +
+
+
+
+ + 评估通过 +
+
+
+ + {/* 典当金额 */} +
+
+
+
+ + 可典当金额 +
+
¥ {result?.loanAmount.toLocaleString()}
+
+
+
+
+

+ + 典当金额为估值的 60% +

+
+
+ +
+ + + {showFeeDetail && ( +
+

典当服务费包含以下服务项目:

+
    +
  • 账号价值专业评估服务
  • +
  • 账号安全托管服务
  • +
  • 资金快速到账服务
  • +
  • 赎回手续办理服务
  • +
+
+ )} + +
+
+ 典当金额 + ¥ {result?.loanAmount.toLocaleString()} +
+
+ 典当服务费 ({pawnDays}天) + ¥ {serviceFee.toLocaleString()} +
+
+ 到期赎回金额 + ¥ {totalRepay.toLocaleString()} +
+
+
+ + {/* 注意事项 */} +
+
+ +
+

质押期间请注意:

+
    +
  • 不得转移、赠与账号内核心虚拟资产
  • +
  • 不得使用外挂、辅助脚本等违规操作
  • +
  • 不得修改密码、密保信息
  • +
+
+
+
+ +
+ + +
+
+
+ + )} + + + {/* 成功弹窗 */} + + + + +
+ +
+ 典当申请已提交 +
+
+
+
+

¥ {result?.loanAmount.toLocaleString()}

+

典当金额

+
+

+ 我们的客服将在 5-10分钟 内与您联系 +

+

请保持手机畅通: {phoneNumber}

+ +
+
+
+ + {/* 质押服务协议弹窗 */} + + + + + + 游戏账号质押服务协议 + + +
+
+

第一条 定义与服务范围

+

1.1 "质押服务"指甲方将其合法持有的游戏账号作为担保物,向乙方申请借款的服务。

+

1.2 质押期间,账号控制权仍归甲方,但需遵守本协议约定的使用限制。

+
+
+

第二条 服务流程

+

2.1 申请:甲方提交账号资料及个人信息进行评估申请。

+

2.2 评估:乙方对账号价值进行专业评估,出具评估报告。

+

2.3 签约:双方确认借款金额、期限、服务费后签署本协议。

+

2.4 放款:乙方在签约后1个工作日内完成放款。

+

2.5 赎回:甲方在到期前支付本金及服务费,解除质押。

+
+
+

第三条 费用说明

+

3.1 典当服务费为一次性收取,包含评估、托管、放款、赎回等全流程服务费用。

+

3.2 提前赎回不退还服务费,逾期赎回需支付额外逾期费用。

+
+
+

第四条 违约处置

+

4.1 逾期超过30天未赎回,乙方有权处置质押账号。

+

4.2 账号处置所得优先抵扣借款本金及费用,剩余部分返还甲方。

+
+
+ +
+
+ + + + + + + 账号使用限制公约 + + +
+

质押期间,甲方使用账号不得从事以下行为,否则将承担违约后果:

+ +
+

+ + 1 + + 资产转移 +

+

转移、赠与、销毁账号内核心虚拟资产(如高级装备、稀有道具、大量游戏货币等)。

+
+ +
+

+ + 2 + + 违规操作 +

+

使用外挂、辅助脚本等非法程序;利用游戏漏洞;发表违规言论导致账号被处罚。

+
+ +
+

+ + 3 + + 权属变更 +

+

尝试修改密码、密保信息、绑定手机或邮箱(经乙方书面同意除外);将账号用于出租、出售等再处置。

+
+ +
+

+ + 4 + + 价值减损 +

+

进行明显有悖于账号价值最大化的操作(具体标准由乙方根据游戏类型判断并公示)。

+
+ +
+

+ 甲方确认:我已阅读、理解并完全同意本协议及其所有附件的全部内容。 +

+
+
+ +
+
+
+ ) +}