登录页面自动检查状态,未登录时才显示二维码区域
- 挂载时先 checkLoginCookie(轻量,不开浏览器) - 有 cookie 则调 refreshStatus 验证实际状态,完成后标记 initialCheckDone - 无 cookie 直接标记 initialCheckDone(确定未登录,无需开浏览器) - 二维码登录卡片仅在 initialCheckDone=true 且未登录时渲染,检查期间不显示
This commit is contained in:
+56
-45
@@ -14,14 +14,23 @@ export function LoginPage() {
|
|||||||
const { token } = useAuth();
|
const { token } = useAuth();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
// Whether the initial login check has completed (used to decide when to show QR section)
|
||||||
|
const [initialCheckDone, setInitialCheckDone] = useState(false);
|
||||||
|
|
||||||
// Auto-check cookie on mount (lightweight, no browser opened)
|
// Auto-check cookie on mount (lightweight, no browser opened)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
void checkLoginCookie().then((res) => {
|
void checkLoginCookie().then((res) => {
|
||||||
if (res.success && res.data?.hasCookies) {
|
if (res.success && res.data?.hasCookies) {
|
||||||
void refreshStatus(); // Only open browser if cookies exist
|
// Cookies exist — open browser to verify actual login state
|
||||||
|
void refreshStatus().finally(() => setInitialCheckDone(true));
|
||||||
|
} else {
|
||||||
|
// No cookies — definitely not logged in, no need to open a browser
|
||||||
|
setInitialCheckDone(true);
|
||||||
}
|
}
|
||||||
}).catch(() => {});
|
}).catch(() => {
|
||||||
|
setInitialCheckDone(true);
|
||||||
|
});
|
||||||
}, [token, refreshStatus]);
|
}, [token, refreshStatus]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -167,53 +176,55 @@ export function LoginPage() {
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* QR Code Login */}
|
{/* QR Code Login — only shown after check completes and user is not logged in */}
|
||||||
<Card>
|
{token && initialCheckDone && !status?.loggedIn && (
|
||||||
<h2 className="text-sm font-semibold text-dark-muted uppercase tracking-wider mb-4">
|
<Card>
|
||||||
二维码登录
|
<h2 className="text-sm font-semibold text-dark-muted uppercase tracking-wider mb-4">
|
||||||
</h2>
|
二维码登录
|
||||||
|
</h2>
|
||||||
|
|
||||||
{!qrData && !qrLoading && (
|
{!qrData && !qrLoading && (
|
||||||
<div className="text-center py-8">
|
<div className="text-center py-8">
|
||||||
<p className="text-dark-muted mb-4">点击按钮生成登录二维码</p>
|
<p className="text-dark-muted mb-4">点击按钮生成登录二维码</p>
|
||||||
<Button onClick={() => void handleGetQR()} disabled={status?.loggedIn}>
|
<Button onClick={() => void handleGetQR()}>
|
||||||
获取二维码
|
获取二维码
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{qrLoading && (
|
|
||||||
<div className="flex flex-col items-center py-8 gap-3">
|
|
||||||
<Spinner size="lg" />
|
|
||||||
<p className="text-sm text-dark-muted">生成二维码中...</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{qrData && (
|
|
||||||
<div className="flex flex-col items-center gap-4">
|
|
||||||
<div className="bg-white rounded-xl p-4">
|
|
||||||
<img src={qrData} alt="登录二维码" className="w-64 h-64" />
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-dark-muted">使用小红书 App 扫码登录</p>
|
)}
|
||||||
{polling && (
|
|
||||||
<div className="flex items-center gap-3">
|
{qrLoading && (
|
||||||
<Spinner size="sm" />
|
<div className="flex flex-col items-center py-8 gap-3">
|
||||||
<span className="text-sm text-dark-accent">
|
<Spinner size="lg" />
|
||||||
等待扫码... {formatCountdown(countdown)}
|
<p className="text-sm text-dark-muted">生成二维码中...</p>
|
||||||
</span>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{qrData && (
|
||||||
|
<div className="flex flex-col items-center gap-4">
|
||||||
|
<div className="bg-white rounded-xl p-4">
|
||||||
|
<img src={qrData} alt="登录二维码" className="w-64 h-64" />
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-dark-muted">使用小红书 App 扫码登录</p>
|
||||||
|
{polling && (
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<Spinner size="sm" />
|
||||||
|
<span className="text-sm text-dark-accent">
|
||||||
|
等待扫码... {formatCountdown(countdown)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button variant="ghost" size="sm" onClick={() => void handleGetQR()}>
|
||||||
|
刷新二维码
|
||||||
|
</Button>
|
||||||
|
<Button variant="ghost" size="sm" onClick={stopPolling}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<Button variant="ghost" size="sm" onClick={() => void handleGetQR()}>
|
|
||||||
刷新二维码
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="sm" onClick={stopPolling}>
|
|
||||||
取消
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</Card>
|
||||||
</Card>
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user