主要更新: 1. 按H5网页端完全重构匹配功能(match页面) - 4种匹配类型: 创业合伙/资源对接/导师顾问/团队招募 - 资源对接等类型弹出手机号/微信号输入框 - 去掉重新匹配按钮,改为返回按钮 2. 修复所有卡片对齐和宽度问题 - 目录页附录卡片居中 - 首页阅读进度卡片满宽度 - 我的页面菜单卡片对齐 - 推广中心分享卡片统一宽度 3. 修复目录页图标和文字对齐 - section-icon固定40rpx宽高 - section-title与图标垂直居中 4. 更新真实完整文章标题(62篇) - 从book目录读取真实markdown文件名 - 替换之前的简化标题 5. 新增文章数据API - /api/db/chapters - 获取完整书籍结构 - 支持按ID获取单篇文章内容
260 lines
9.6 KiB
TypeScript
260 lines
9.6 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import { useRouter } from "next/navigation"
|
||
import { ChevronLeft, Phone, MessageCircle, CreditCard, Check, X, Loader2, Shield } from "lucide-react"
|
||
import { useStore } from "@/lib/store"
|
||
|
||
export default function SettingsPage() {
|
||
const router = useRouter()
|
||
const { user, updateUser, logout } = useStore()
|
||
|
||
// 绑定弹窗状态
|
||
const [showBindModal, setShowBindModal] = useState(false)
|
||
const [bindType, setBindType] = useState<"phone" | "wechat" | "alipay">("phone")
|
||
const [bindValue, setBindValue] = useState("")
|
||
const [isBinding, setIsBinding] = useState(false)
|
||
const [bindError, setBindError] = useState("")
|
||
|
||
// 绑定账号
|
||
const handleBind = async () => {
|
||
if (!bindValue.trim()) {
|
||
setBindError("请输入内容")
|
||
return
|
||
}
|
||
|
||
if (bindType === "phone" && !/^1[3-9]\d{9}$/.test(bindValue)) {
|
||
setBindError("请输入正确的手机号")
|
||
return
|
||
}
|
||
|
||
if (bindType === "wechat" && bindValue.length < 6) {
|
||
setBindError("微信号至少6位")
|
||
return
|
||
}
|
||
|
||
if (bindType === "alipay" && !bindValue.includes("@") && !/^1[3-9]\d{9}$/.test(bindValue)) {
|
||
setBindError("请输入正确的支付宝账号")
|
||
return
|
||
}
|
||
|
||
setIsBinding(true)
|
||
setBindError("")
|
||
|
||
try {
|
||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||
|
||
if (updateUser && user) {
|
||
const updates: any = {}
|
||
if (bindType === "phone") updates.phone = bindValue
|
||
if (bindType === "wechat") updates.wechat = bindValue
|
||
if (bindType === "alipay") updates.alipay = bindValue
|
||
updateUser(user.id, updates)
|
||
}
|
||
|
||
setShowBindModal(false)
|
||
setBindValue("")
|
||
alert("绑定成功!")
|
||
} catch (error) {
|
||
setBindError("绑定失败,请重试")
|
||
} finally {
|
||
setIsBinding(false)
|
||
}
|
||
}
|
||
|
||
const openBindModal = (type: "phone" | "wechat" | "alipay") => {
|
||
setBindType(type)
|
||
setBindValue("")
|
||
setBindError("")
|
||
setShowBindModal(true)
|
||
}
|
||
|
||
// 检查是否有绑定任何支付方式
|
||
const hasAnyPaymentBound = user?.wechat || user?.alipay
|
||
|
||
return (
|
||
<div className="min-h-screen bg-black text-white pb-24">
|
||
{/* Header */}
|
||
<header className="sticky top-0 z-40 bg-black/90 backdrop-blur-xl border-b border-white/5">
|
||
<div className="px-4 py-3 flex items-center">
|
||
<button
|
||
onClick={() => router.back()}
|
||
className="w-8 h-8 rounded-full bg-white/10 flex items-center justify-center"
|
||
>
|
||
<ChevronLeft className="w-5 h-5 text-white" />
|
||
</button>
|
||
<h1 className="flex-1 text-center text-lg font-semibold text-white">设置</h1>
|
||
<div className="w-8" />
|
||
</div>
|
||
</header>
|
||
|
||
<main className="px-4 py-4 space-y-4">
|
||
{/* 账号绑定 */}
|
||
<div className="rounded-2xl bg-[#1c1c1e] border border-white/5 overflow-hidden">
|
||
<div className="px-4 py-3 border-b border-white/5">
|
||
<div className="flex items-center gap-2">
|
||
<Shield className="w-4 h-4 text-[#00CED1]" />
|
||
<span className="text-white font-medium">账号绑定</span>
|
||
</div>
|
||
<p className="text-white/40 text-xs mt-1">绑定后可用于提现和找伙伴功能</p>
|
||
</div>
|
||
|
||
{/* 手机号 */}
|
||
<button
|
||
onClick={() => openBindModal("phone")}
|
||
className="w-full flex items-center justify-between p-4 border-b border-white/5 active:bg-white/5"
|
||
>
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${
|
||
user?.phone ? "bg-[#00CED1]/20" : "bg-white/10"
|
||
}`}>
|
||
<Phone className={`w-4 h-4 ${user?.phone ? "text-[#00CED1]" : "text-white/40"}`} />
|
||
</div>
|
||
<div className="text-left">
|
||
<p className="text-white text-sm">手机号</p>
|
||
<p className="text-white/40 text-xs">
|
||
{user?.phone || "未绑定"}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
{user?.phone ? (
|
||
<Check className="w-5 h-5 text-[#00CED1]" />
|
||
) : (
|
||
<span className="text-[#00CED1] text-xs">去绑定</span>
|
||
)}
|
||
</button>
|
||
|
||
{/* 微信号 */}
|
||
<button
|
||
onClick={() => openBindModal("wechat")}
|
||
className="w-full flex items-center justify-between p-4 border-b border-white/5 active:bg-white/5"
|
||
>
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${
|
||
user?.wechat ? "bg-[#07C160]/20" : "bg-white/10"
|
||
}`}>
|
||
<MessageCircle className={`w-4 h-4 ${user?.wechat ? "text-[#07C160]" : "text-white/40"}`} />
|
||
</div>
|
||
<div className="text-left">
|
||
<p className="text-white text-sm">微信号</p>
|
||
<p className="text-white/40 text-xs">
|
||
{user?.wechat || "未绑定"}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
{user?.wechat ? (
|
||
<Check className="w-5 h-5 text-[#07C160]" />
|
||
) : (
|
||
<span className="text-[#07C160] text-xs">去绑定</span>
|
||
)}
|
||
</button>
|
||
|
||
{/* 支付宝 */}
|
||
<button
|
||
onClick={() => openBindModal("alipay")}
|
||
className="w-full flex items-center justify-between p-4 active:bg-white/5"
|
||
>
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-8 h-8 rounded-full flex items-center justify-center ${
|
||
user?.alipay ? "bg-[#1677FF]/20" : "bg-white/10"
|
||
}`}>
|
||
<CreditCard className={`w-4 h-4 ${user?.alipay ? "text-[#1677FF]" : "text-white/40"}`} />
|
||
</div>
|
||
<div className="text-left">
|
||
<p className="text-white text-sm">支付宝</p>
|
||
<p className="text-white/40 text-xs">
|
||
{user?.alipay || "未绑定"}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
{user?.alipay ? (
|
||
<Check className="w-5 h-5 text-[#1677FF]" />
|
||
) : (
|
||
<span className="text-[#1677FF] text-xs">去绑定</span>
|
||
)}
|
||
</button>
|
||
</div>
|
||
|
||
{/* 绑定提示 */}
|
||
{!hasAnyPaymentBound && (
|
||
<div className="p-4 rounded-xl bg-orange-500/10 border border-orange-500/20">
|
||
<p className="text-orange-400 text-xs">
|
||
提示:绑定至少一个支付方式(微信或支付宝)才能使用提现功能
|
||
</p>
|
||
</div>
|
||
)}
|
||
|
||
{/* 退出登录 */}
|
||
<button
|
||
onClick={() => {
|
||
logout()
|
||
router.push("/")
|
||
}}
|
||
className="w-full py-3 rounded-xl bg-[#1c1c1e] text-red-400 font-medium border border-red-400/30"
|
||
>
|
||
退出登录
|
||
</button>
|
||
</main>
|
||
|
||
{/* 绑定弹窗 */}
|
||
{showBindModal && (
|
||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||
<div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => !isBinding && setShowBindModal(false)} />
|
||
<div className="relative w-full max-w-sm bg-[#1c1c1e] rounded-2xl overflow-hidden">
|
||
<div className="flex items-center justify-between p-4 border-b border-white/10">
|
||
<h3 className="text-lg font-semibold text-white">
|
||
绑定{bindType === "phone" ? "手机号" : bindType === "wechat" ? "微信号" : "支付宝"}
|
||
</h3>
|
||
<button
|
||
onClick={() => !isBinding && setShowBindModal(false)}
|
||
className="w-8 h-8 rounded-full bg-white/10 flex items-center justify-center"
|
||
>
|
||
<X className="w-4 h-4 text-white/60" />
|
||
</button>
|
||
</div>
|
||
|
||
<div className="p-5">
|
||
<div className="mb-4">
|
||
<label className="block text-white/40 text-xs mb-2">
|
||
{bindType === "phone" ? "手机号" : bindType === "wechat" ? "微信号" : "支付宝账号"}
|
||
</label>
|
||
<input
|
||
type={bindType === "phone" ? "tel" : "text"}
|
||
value={bindValue}
|
||
onChange={(e) => setBindValue(e.target.value)}
|
||
placeholder={
|
||
bindType === "phone" ? "请输入11位手机号" :
|
||
bindType === "wechat" ? "请输入微信号" :
|
||
"请输入支付宝账号"
|
||
}
|
||
className="w-full px-4 py-3 rounded-xl bg-black/30 border border-white/10 text-white placeholder-white/30 focus:outline-none focus:border-[#00CED1]/50"
|
||
disabled={isBinding}
|
||
/>
|
||
</div>
|
||
|
||
{bindError && (
|
||
<p className="text-red-400 text-sm mb-4">{bindError}</p>
|
||
)}
|
||
|
||
<button
|
||
onClick={handleBind}
|
||
disabled={isBinding || !bindValue}
|
||
className="w-full py-3 rounded-xl bg-[#00CED1] text-black font-medium flex items-center justify-center gap-2 disabled:opacity-50"
|
||
>
|
||
{isBinding ? (
|
||
<>
|
||
<Loader2 className="w-4 h-4 animate-spin" />
|
||
绑定中...
|
||
</>
|
||
) : (
|
||
"确认绑定"
|
||
)}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|