import { useEffect, useState } from 'react' import { CursorFollower } from './components/CursorFollower' import { LoginPage } from './components/LoginPage' import { BlogPage } from './components/BlogPage' import { StartPage } from './components/StartPage' import { useAuth } from './hooks/useAuth' import { checkGate } from './api/gate' function App() { // 登录态从 localStorage/sessionStorage 恢复:已登录直接进博客页。 const auth = useAuth() // 是否显示登录页。入口 hash 是否合法由后端判定,故初值为 false,等校验通过再开。 const [showLogin, setShowLogin] = useState(false) const signOut = auth.signOut // 监听地址栏 hash:把 `#` 后那串发给后端校验,命中合法开发者才放行到登录页。 // 合法 hash 列表只存在后端,前端不写死,扒 JS 也看不到合法值。 useEffect(() => { let alive = true const check = async () => { const hash = window.location.hash.replace(/^#/, '') const ok = hash ? await checkGate(hash) : false // 防竞态:异步返回时若组件已卸载或 hash 又变了,丢弃这次结果。 if (alive && hash === window.location.hash.replace(/^#/, '')) { setShowLogin(ok) } } check() window.addEventListener('hashchange', check) return () => { alive = false window.removeEventListener('hashchange', check) } }, []) // 回到导航页:清掉登录态,并抹掉地址栏里的密钥(防止留在历史里被看到)。 const goStart = () => { signOut() setShowLogin(false) if (window.location.hash) { history.replaceState(null, '', window.location.pathname + window.location.search) } } let view if (auth.username) { view = } else if (showLogin) { view = } else { view = } return ( <> {view} ) } export default App