"use client"; import Link from "next/link"; import { FormEvent, useEffect, useState } from "react"; import { ArrowRight } from "@/components/icons"; import { PreviewNotice, StatusCard } from "@/components/ui"; const apiBase = process.env.NEXT_PUBLIC_API_BASE_URL ?? "/api/v1"; type User = { email: string; role: "user" | "admin"; plan: "free" | "vip"; status: string; email_verified: boolean; phone_verified: boolean }; type Usage = { period_start: string; period_end: string; limit: number; adjustment: number; used: number; reserved: number; available: number; plan: string }; export function AccountPanel() { const [csrf, setCsrf] = useState(""); const [user, setUser] = useState(null); const [usage, setUsage] = useState(null); const [error, setError] = useState(""); const [passwordMessage, setPasswordMessage] = useState(""); async function load() { const csrfResponse = await fetch(`${apiBase}/auth/csrf`, { credentials: "include" }); const csrfBody = await csrfResponse.json(); setCsrf(csrfBody.csrf_token ?? ""); const [meResponse, usageResponse] = await Promise.all([ fetch(`${apiBase}/auth/me`, { credentials: "include" }), fetch(`${apiBase}/account/usage`, { credentials: "include" }), ]); if (!meResponse.ok) throw new Error("请先登录后查看账户"); setUser(await meResponse.json()); if (usageResponse.ok) setUsage(await usageResponse.json()); } useEffect(() => { load().catch((loadError) => setError(loadError instanceof Error ? loadError.message : "无法加载账户")); }, []); async function logout() { await fetch(`${apiBase}/auth/logout`, { method: "POST", credentials: "include", headers: { "X-CSRF-Token": csrf } }); window.location.assign("/login"); } async function changePassword(event: FormEvent) { event.preventDefault(); const form = event.currentTarget; setPasswordMessage(""); const data = new FormData(form); const response = await fetch(`${apiBase}/auth/password/change`, { method: "POST", credentials: "include", headers: { "Content-Type": "application/json", "X-CSRF-Token": csrf }, body: JSON.stringify({ current_password: data.get("current_password"), new_password: data.get("new_password") }) }); const body = await response.json().catch(() => ({})); if (!response.ok) setPasswordMessage(body.error?.message ?? "密码修改失败"); else { setPasswordMessage("密码已修改,其他会话已撤销"); form.reset(); } } if (error) return
{error}。前往登录
; if (!user || !usage) return
; return <>

Profile

基本资料

邮箱
{user.email}
角色
{user.role}
额度周期
{new Date(usage.period_start).toLocaleDateString()} 至 {new Date(usage.period_end).toLocaleDateString()}

Usage

额度明细

打开工作台

Security

修改密码

{passwordMessage ?

{passwordMessage}

: null}
; }