Files
soul-yongping/app/login/page.tsx

184 lines
6.4 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 } from "react"
import { useRouter } from "next/navigation"
import Link from "next/link"
import { useStore } from "@/lib/store"
import { ChevronLeft, Phone, User, Hash } from "lucide-react"
export default function LoginPage() {
const router = useRouter()
const { login, register } = useStore()
const [mode, setMode] = useState<"login" | "register">("login")
const [phone, setPhone] = useState("")
const [code, setCode] = useState("")
const [nickname, setNickname] = useState("")
const [referralCode, setReferralCode] = useState("")
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const handleSubmit = async () => {
setError("")
setLoading(true)
try {
// 管理员登录(使用 code 作为密码,调用后台 API 并写 Cookie
if (phone.toLowerCase() === "admin") {
try {
const res = await fetch("/api/admin", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username: phone, password: code }),
credentials: "include",
})
const data = await res.json()
if (res.ok && data.success) {
router.push("/admin")
return
}
} catch {
// fallthrough to error
}
setError("管理员密码错误")
return
}
if (mode === "login") {
if (!code.trim()) {
setError("请输入密码")
return
}
const success = await login(phone, code)
if (success) {
router.push("/")
} else {
setError("密码错误或用户不存在")
}
} else {
if (!nickname.trim()) {
setError("请输入昵称")
return
}
if (!code.trim()) {
setError("请设置密码(至少 6 位)")
return
}
if (code.trim().length < 6) {
setError("密码至少 6 位")
return
}
const success = await register(phone, nickname, code, referralCode || undefined)
if (success) {
router.push("/")
} else {
setError("该手机号已注册")
}
}
} finally {
setLoading(false)
}
}
return (
<div className="min-h-screen bg-black text-white flex flex-col">
{/* 顶部导航 */}
<header className="flex items-center px-4 py-3">
<button
onClick={() => router.back()}
className="w-9 h-9 rounded-full bg-[#1c1c1e] flex items-center justify-center"
>
<ChevronLeft className="w-5 h-5 text-gray-400" />
</button>
</header>
{/* 主内容 */}
<main className="flex-1 px-6 pt-8">
<h1 className="text-2xl font-bold mb-2">{mode === "login" ? "登录" : "注册"}</h1>
<p className="text-gray-500 text-sm mb-8">
{mode === "login" ? "登录后查看购买记录和收益" : "注册后开始阅读真实商业故事"}
</p>
<div className="space-y-4">
{/* 手机号 */}
<div className="relative">
<Phone className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-500" />
<input
type="tel"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="手机号"
className="w-full pl-12 pr-4 py-3.5 bg-[#1c1c1e] rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#30d158]/50"
/>
</div>
{/* 昵称(注册时显示) */}
{mode === "register" && (
<div className="relative">
<User className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-500" />
<input
type="text"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
placeholder="昵称"
className="w-full pl-12 pr-4 py-3.5 bg-[#1c1c1e] rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#30d158]/50"
/>
</div>
)}
{/* 密码 */}
<div className="relative">
<Hash className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-500" />
<input
type="password"
value={code}
onChange={(e) => setCode(e.target.value)}
placeholder={mode === "login" ? "密码" : "设置密码(至少 6 位)"}
className="w-full pl-12 pr-4 py-3.5 bg-[#1c1c1e] rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#30d158]/50"
/>
</div>
{/* 邀请码(注册时显示) */}
{mode === "register" && (
<div className="relative">
<Hash className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-500" />
<input
type="text"
value={referralCode}
onChange={(e) => setReferralCode(e.target.value)}
placeholder="邀请码(选填)"
className="w-full pl-12 pr-4 py-3.5 bg-[#1c1c1e] rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#30d158]/50"
/>
</div>
)}
{/* 错误提示 */}
{error && <p className="text-red-500 text-sm">{error}</p>}
{/* 提交按钮 */}
<button
onClick={handleSubmit}
disabled={loading || !phone}
className="w-full py-3.5 bg-[#30d158] text-white font-medium rounded-xl active:scale-[0.98] transition-transform disabled:opacity-50"
>
{loading ? "处理中..." : mode === "login" ? "登录" : "注册"}
</button>
{/* 忘记密码 / 切换模式 */}
<div className="text-center space-y-2">
{mode === "login" && (
<div>
<Link href="/login/forgot" className="text-[#30d158] text-sm">
</Link>
</div>
)}
<button onClick={() => setMode(mode === "login" ? "register" : "login")} className="text-[#30d158] text-sm block mx-auto">
{mode === "login" ? "没有账号?去注册" : "已有账号?去登录"}
</button>
</div>
</div>
</main>
</div>
)
}