From 8d0e0fb779a40f7c80023b0f07b8980a8675df91 Mon Sep 17 00:00:00 2001 From: mtvpls Date: Sat, 30 May 2026 21:18:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=89=AB=E7=A0=81=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/tv/login/page.tsx | 25 +++++++++----- src/components/tv/TVLayout.tsx | 62 +++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/app/tv/login/page.tsx b/src/app/tv/login/page.tsx index 823dc60..6e421d6 100644 --- a/src/app/tv/login/page.tsx +++ b/src/app/tv/login/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Loader2, RefreshCw, Smartphone } from 'lucide-react'; +import { Loader2, Smartphone } from 'lucide-react'; import { useRouter, useSearchParams } from 'next/navigation'; import { useCallback, useEffect, useState } from 'react'; @@ -20,7 +20,11 @@ export default function TVLoginPage() { setStatus('正在生成二维码...'); const res = await fetch('/api/auth/qr/create', { method: 'POST' }); const data = await res.json(); - setQr(data); + const qrUrl = + typeof window === 'undefined' + ? data.qrUrl + : `${window.location.origin}/qr-login?token=${encodeURIComponent(data.token)}`; + setQr({ ...data, qrUrl }); setLeft(Math.max(0, Math.ceil((data.expiresAt - Date.now()) / 1000))); setStatus('请使用手机扫码登录'); }, []); @@ -29,9 +33,16 @@ export default function TVLoginPage() { useEffect(() => { if (!qr) return; - const timer = window.setInterval(() => setLeft(Math.max(0, Math.ceil((qr.expiresAt - Date.now()) / 1000))), 1000); + const timer = window.setInterval(() => { + const remaining = Math.max(0, Math.ceil((qr.expiresAt - Date.now()) / 1000)); + setLeft(remaining); + if (remaining <= 0) { + window.clearInterval(timer); + create(); + } + }, 1000); return () => window.clearInterval(timer); - }, [qr]); + }, [create, qr]); useEffect(() => { if (!qr) return; @@ -53,21 +64,17 @@ export default function TVLoginPage() { const qrImg = qr ? `/api/auth/qr/image?data=${encodeURIComponent(qr.qrUrl)}` : ''; return ( - +
手机确认 · 电视自动登录

扫码登录

用已登录的手机浏览器扫描右侧二维码,在手机上确认后,电视端会自动进入。

{status}

-
{qrImg ? 扫码登录二维码 :
}
剩余 {left} 秒
-
{qr?.qrUrl}
diff --git a/src/components/tv/TVLayout.tsx b/src/components/tv/TVLayout.tsx index 570f241..6698ac6 100644 --- a/src/components/tv/TVLayout.tsx +++ b/src/components/tv/TVLayout.tsx @@ -27,38 +27,46 @@ const navItems = [ { label: '私人影库', href: '/tv/private', icon: Heart }, ]; -export default function TVLayout({ children }: { children: ReactNode }) { +export default function TVLayout({ + children, + showNav = true, +}: { + children: ReactNode; + showNav?: boolean; +}) { const pathname = usePathname(); return (
-
- -
-
{children}
+ {showNav && ( +
+ +
+ )} +
{children}
);