mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-26 05:54:42 +08:00
@@ -1,46 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function AuthProvider({ children }: Props) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
// 登录页或 API 路径不做校验,避免死循环
|
||||
if (pathname.startsWith('/login')) return;
|
||||
|
||||
const password = localStorage.getItem('password');
|
||||
const fullPath =
|
||||
typeof window !== 'undefined'
|
||||
? window.location.pathname + window.location.search
|
||||
: pathname;
|
||||
|
||||
// 有密码时验证
|
||||
(async () => {
|
||||
try {
|
||||
const res = await fetch('/api/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password }),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
// 校验未通过,清理并跳转登录
|
||||
localStorage.removeItem('password');
|
||||
router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`);
|
||||
}
|
||||
} catch (error) {
|
||||
// 网络错误等也认为未登录
|
||||
router.replace(`/login?redirect=${encodeURIComponent(fullPath)}`);
|
||||
}
|
||||
})();
|
||||
}, [pathname, router]);
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
@@ -2,13 +2,9 @@
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
import { useSiteName } from './SiteNameContext';
|
||||
import { ThemeToggle } from './ThemeToggle';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
const MobileHeader = () => {
|
||||
const siteName = useSiteName();
|
||||
return (
|
||||
<header className='md:hidden relative w-full bg-white/70 backdrop-blur-xl border-b border-gray-200/50 shadow-sm dark:bg-gray-900/70 dark:border-gray-700/50'>
|
||||
<div className='h-12 flex items-center justify-center'>
|
||||
@@ -16,7 +12,7 @@ const MobileHeader = () => {
|
||||
href='/'
|
||||
className='text-2xl font-bold text-green-600 tracking-tight hover:opacity-80 transition-opacity'
|
||||
>
|
||||
{siteName}
|
||||
MoonTV
|
||||
</Link>
|
||||
</div>
|
||||
<div className='absolute top-1/2 right-4 -translate-y-1/2'>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
Clover,
|
||||
Film,
|
||||
@@ -24,8 +22,6 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { useSiteName } from './SiteNameContext';
|
||||
|
||||
interface SidebarContextType {
|
||||
isCollapsed: boolean;
|
||||
}
|
||||
@@ -37,17 +33,13 @@ const SidebarContext = createContext<SidebarContextType>({
|
||||
export const useSidebar = () => useContext(SidebarContext);
|
||||
|
||||
// 可替换为你自己的 logo 图片
|
||||
interface LogoProps {
|
||||
siteName: string;
|
||||
}
|
||||
|
||||
const Logo = ({ siteName }: LogoProps) => (
|
||||
const Logo = () => (
|
||||
<Link
|
||||
href='/'
|
||||
className='flex items-center justify-center h-16 select-none hover:opacity-80 transition-opacity duration-200'
|
||||
>
|
||||
<span className='text-2xl font-bold text-green-600 tracking-tight'>
|
||||
{siteName}
|
||||
MoonTV
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
@@ -64,8 +56,6 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
@@ -168,8 +158,6 @@ const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
||||
{ icon: VenetianMask, label: '日漫', href: '/douban?type=tv&tag=日本动画' },
|
||||
];
|
||||
|
||||
const siteName = useSiteName();
|
||||
|
||||
return (
|
||||
<SidebarContext.Provider value={contextValue}>
|
||||
{/* 在移动端隐藏侧边栏 */}
|
||||
@@ -193,7 +181,7 @@ const Sidebar = ({ onToggle, activePath = '/' }: SidebarProps) => {
|
||||
}`}
|
||||
>
|
||||
<div className='w-[calc(100%-4rem)] flex justify-center'>
|
||||
{!isCollapsed && <Logo siteName={siteName} />}
|
||||
{!isCollapsed && <Logo />}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
|
||||
/**
|
||||
* 站点名称上下文,默认值为 "MoonTV"。
|
||||
* 不包含 "use client",以便既能被 Server Component 引用,也能被 Client Component 引用。
|
||||
*/
|
||||
export const SiteNameContext = createContext<string>('MoonTV');
|
||||
|
||||
interface ProviderProps {
|
||||
value: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function SiteNameProvider({ value, children }: ProviderProps) {
|
||||
return (
|
||||
<SiteNameContext.Provider value={value}>
|
||||
{children}
|
||||
</SiteNameContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useSiteName = () => useContext(SiteNameContext);
|
||||
Reference in New Issue
Block a user