From 33b7e4d0b9d45392cb4a95b425a570dabdb53541 Mon Sep 17 00:00:00 2001 From: zetaloop Date: Sun, 22 Feb 2026 08:16:14 +0800 Subject: [PATCH] feat(auth): complete verification state machine with resubmit flow --- app/(account)/verify/page.tsx | 117 +++++++++++++++++++++++++++------- store/auth.ts | 47 ++++++++++++++ 2 files changed, 140 insertions(+), 24 deletions(-) diff --git a/app/(account)/verify/page.tsx b/app/(account)/verify/page.tsx index e339823..1224acb 100644 --- a/app/(account)/verify/page.tsx +++ b/app/(account)/verify/page.tsx @@ -1,7 +1,7 @@ "use client" import { CheckCircle, Clock, ShieldCheck, Upload } from "lucide-react" -import { useState } from "react" +import { useEffect, useRef, useState } from "react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" @@ -22,30 +22,40 @@ import { useAuthStore } from "@/store/auth" export default function VerifyPage() { const [verifyRole, setVerifyRole] = useState("") const verificationStatus = useAuthStore((state) => state.verificationStatus) + const verificationReasons = useAuthStore((state) => state.verificationReasons) + const verifiedRoles = useAuthStore((state) => state.verifiedRoles) const submitVerification = useAuthStore((state) => state.submitVerification) - const submitted = Object.values(verificationStatus).includes("pending") + const approveVerification = useAuthStore((state) => state.approveVerification) + const timersRef = useRef>>(new Map()) - if (submitted) { - return ( -
-

身份认证

- - - -

认证申请已提交

-

- 我们将在 1-3 个工作日内审核你的申请,审核结果将通过通知中心告知 -

- - - 审核中 - -
-
-
- ) + useEffect( + () => () => { + timersRef.current.forEach((timer) => { + clearTimeout(timer) + }) + timersRef.current.clear() + }, + [], + ) + + const submitWithMockApproval = (role: UserRole) => { + submitVerification(role) + const oldTimer = timersRef.current.get(role) + if (oldTimer) { + clearTimeout(oldTimer) + } + const timer = setTimeout(() => { + approveVerification(role) + timersRef.current.delete(role) + }, 3000) + timersRef.current.set(role, timer) } + const roleMeta: { role: UserRole; label: string }[] = [ + { role: "player", label: "打手认证" }, + { role: "owner", label: "店主认证" }, + ] + return (

身份认证

@@ -66,6 +76,59 @@ export default function VerifyPage() { + + + 认证状态 + + + {roleMeta.map((item) => { + const status = verificationStatus[item.role] + const reason = verificationReasons[item.role] + + return ( +
+
+ {item.label} + {status === "approved" || verifiedRoles.includes(item.role) ? ( + + 已通过 + + ) : status === "pending" ? ( + + + 审核中 + + ) : status === "rejected" ? ( + + 未通过 + + ) : ( + 未申请 + )} +
+ + {status === "rejected" && ( +

驳回原因:{reason}

+ )} + + {status === "rejected" && ( + + )} +
+ ) + })} +
+
+ 申请认证 @@ -122,13 +185,19 @@ export default function VerifyPage() { diff --git a/store/auth.ts b/store/auth.ts index 6954454..1782449 100644 --- a/store/auth.ts +++ b/store/auth.ts @@ -6,9 +6,12 @@ interface AuthState { currentRole: UserRole verifiedRoles: UserRole[] verificationStatus: Partial> + verificationReasons: Partial> user: User | null switchRole: (role: UserRole) => void submitVerification: (role: UserRole) => void + approveVerification: (role: UserRole) => void + rejectVerification: (role: UserRole, reason: string) => void login: (user: User, verifiedRoles?: UserRole[]) => void logout: () => void } @@ -18,6 +21,7 @@ export const useAuthStore = create((set, get) => ({ currentRole: "consumer", verifiedRoles: ["consumer"], verificationStatus: { consumer: "approved" }, + verificationReasons: {}, user: null, switchRole: (role) => { const { verifiedRoles } = get() @@ -31,11 +35,52 @@ export const useAuthStore = create((set, get) => ({ return state } + const nextReasons = { ...state.verificationReasons } + delete nextReasons[role] + return { verificationStatus: { ...state.verificationStatus, [role]: "pending", }, + verificationReasons: nextReasons, + } + }), + approveVerification: (role) => + set((state) => { + if (state.verifiedRoles.includes(role) && state.verificationStatus[role] === "approved") { + return state + } + + const nextReasons = { ...state.verificationReasons } + delete nextReasons[role] + + return { + verifiedRoles: state.verifiedRoles.includes(role) + ? state.verifiedRoles + : [...state.verifiedRoles, role], + verificationStatus: { + ...state.verificationStatus, + [role]: "approved", + }, + verificationReasons: nextReasons, + } + }), + rejectVerification: (role, reason) => + set((state) => { + if (state.verifiedRoles.includes(role)) { + return state + } + + return { + verificationStatus: { + ...state.verificationStatus, + [role]: "rejected", + }, + verificationReasons: { + ...state.verificationReasons, + [role]: reason.trim() || "认证资料不完整,请补充后重试", + }, } }), login: (user, verifiedRoles = ["consumer"]) => @@ -51,6 +96,7 @@ export const useAuthStore = create((set, get) => ({ }, {}, ), + verificationReasons: {}, }), logout: () => set({ @@ -58,6 +104,7 @@ export const useAuthStore = create((set, get) => ({ currentRole: "consumer", verifiedRoles: ["consumer"], verificationStatus: { consumer: "approved" }, + verificationReasons: {}, user: null, }), }))