diff --git a/Cunkebao/app/components/auth-check.tsx b/Cunkebao/app/components/auth-check.tsx new file mode 100644 index 000000000..114002b90 --- /dev/null +++ b/Cunkebao/app/components/auth-check.tsx @@ -0,0 +1,27 @@ +"use client" + +import { useEffect } from "react" +import { useRouter, usePathname } from "next/navigation" + +export function AuthCheck({ children }: { children: React.ReactNode }) { + const router = useRouter() + const pathname = usePathname() + + useEffect(() => { + // 排除不需要登录的页面 + const publicPaths = ['/login', '/register', '/forgot-password'] + if (publicPaths.includes(pathname)) { + return + } + + const token = localStorage.getItem('token') + if (!token) { + // 如果没有token,重定向到登录页面,并携带当前页面URL作为回调 + const currentPath = window.location.pathname + window.location.search + router.push(`/login?redirect=${encodeURIComponent(currentPath)}`) + return + } + }, [router, pathname]) + + return <>{children} +} \ No newline at end of file diff --git a/Cunkebao/app/components/ui/toast.ts b/Cunkebao/app/components/ui/toast.ts new file mode 100644 index 000000000..c24286d76 --- /dev/null +++ b/Cunkebao/app/components/ui/toast.ts @@ -0,0 +1,14 @@ +const ToastViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ToastViewport.displayName = ToastPrimitives.Viewport.displayName \ No newline at end of file diff --git a/Cunkebao/app/devices/[id]/page.tsx b/Cunkebao/app/devices/[id]/page.tsx index e94f9ba95..8058b7f5b 100644 --- a/Cunkebao/app/devices/[id]/page.tsx +++ b/Cunkebao/app/devices/[id]/page.tsx @@ -95,6 +95,17 @@ export default function DeviceDetailPage() { }) const [tabChangeLoading, setTabChangeLoading] = useState(false) + // 添加登录检查 + useEffect(() => { + const token = localStorage.getItem('token') + if (!token) { + // 如果没有token,重定向到登录页面,并携带当前页面URL作为回调 + const currentPath = window.location.pathname + window.location.search + router.push(`/login?redirect=${encodeURIComponent(currentPath)}`) + return + } + }, [router]) + useEffect(() => { if (!params.id) return diff --git a/Cunkebao/app/layout.tsx b/Cunkebao/app/layout.tsx index 482ed3213..b678c2dea 100644 --- a/Cunkebao/app/layout.tsx +++ b/Cunkebao/app/layout.tsx @@ -5,6 +5,8 @@ import type React from "react" import ErrorBoundary from "./components/ErrorBoundary" import { AuthProvider } from "@/app/components/AuthProvider" import LayoutWrapper from "./components/LayoutWrapper" +import { AuthCheck } from "@/app/components/auth-check" +import { Toaster } from "sonner" export const metadata: Metadata = { title: "存客宝", @@ -21,10 +23,13 @@ export default function RootLayout({ - - {children} - + + + {children} + + + ) diff --git a/Cunkebao/package-lock.json b/Cunkebao/package-lock.json index 7c3729c0c..ddce715f6 100644 --- a/Cunkebao/package-lock.json +++ b/Cunkebao/package-lock.json @@ -58,7 +58,7 @@ "react-resizable-panels": "^2.1.7", "recharts": "latest", "regenerator-runtime": "latest", - "sonner": "^1.7.1", + "sonner": "^1.7.4", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.6", @@ -6084,6 +6084,7 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.7.4.tgz", "integrity": "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw==", + "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" diff --git a/Cunkebao/package.json b/Cunkebao/package.json index 334e73080..7c299a71f 100644 --- a/Cunkebao/package.json +++ b/Cunkebao/package.json @@ -59,7 +59,7 @@ "react-resizable-panels": "^2.1.7", "recharts": "latest", "regenerator-runtime": "latest", - "sonner": "^1.7.1", + "sonner": "^1.7.4", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.6",