import { useEffect, useState } from "react"; import { Alert, Button, Card, Form, Input, Typography } from "antd"; import { KeyRound } from "lucide-react"; import { useNavigate, useParams } from "react-router"; import { ApiError, authApi } from "../api"; import { useRuntime } from "../app/RuntimeProvider"; interface FormValues { password: string; confirm: string; } function readAndClearToken(activationId: string): string { const storageKey = `tiku-activation:${activationId}`; const fragment = new URLSearchParams(window.location.hash.replace(/^#/, "")); const fromUrl = fragment.get("token"); if (fromUrl) sessionStorage.setItem(storageKey, fromUrl); if (window.location.hash) history.replaceState( null, "", window.location.pathname + window.location.search, ); return fromUrl || sessionStorage.getItem(storageKey) || ""; } const errorMessages: Record = { activation_invalid: "建站密钥无效,请联系平台重新获取。", activation_expired: "建站密钥已经过期,请联系平台重新签发。", activation_consumed: "建站密钥已经使用,不能再次激活。", activation_password_invalid: "密码至少 8 位,并同时包含字母和数字。", }; export default function ActivationPage() { const { activationId = "" } = useParams(); const { runtime } = useRuntime(); const navigate = useNavigate(); const [token, setToken] = useState(""); const [error, setError] = useState(""); const [submitting, setSubmitting] = useState(false); useEffect(() => { setToken(readAndClearToken(activationId)); }, [activationId]); const submit = async (values: FormValues) => { if (!token) { setError("链接中没有可用的建站密钥,请联系平台重新获取。"); return; } setSubmitting(true); setError(""); try { await authApi.completeOwnerActivation({ activationId, token, newPassword: values.password, }); sessionStorage.removeItem(`tiku-activation:${activationId}`); navigate("/manage/onboarding", { replace: true }); } catch (reason) { const code = reason instanceof ApiError ? reason.code : ""; setError(errorMessages[code] ?? "激活失败,请联系平台服务人员。"); } finally { setSubmitting(false); } }; return (
{runtime?.tenantName} 激活管理员账号
设置管理员密码后,将自动登录并进入建站向导。一次性密钥使用后立即失效。 {!token && ( )} {error && ( )}
({ validator: (_, value) => value === getFieldValue("password") ? Promise.resolve() : Promise.reject(new Error("两次密码不一致")), }), ]} >
); }