diff --git a/app/analytics/page.tsx b/app/analytics/page.tsx
index c290ed4..dbe235a 100644
--- a/app/analytics/page.tsx
+++ b/app/analytics/page.tsx
@@ -14,6 +14,7 @@ import { ProjectSelector } from '@/app/components/ui/ProjectSelector';
import { TagSelector } from '@/app/components/ui/TagSelector';
import { useSearchParams } from 'next/navigation';
import { useShortUrlStore } from '@/app/utils/store';
+import ClientRouteGuard from '@/app/components/ClientRouteGuard';
// 事件类型定义
interface Event {
@@ -1109,12 +1110,14 @@ function AnalyticsContent() {
// Main page component with Suspense
export default function AnalyticsPage() {
return (
-
-
-
- }>
-
-
+
+
+
+
+ }>
+
+
+
);
}
\ No newline at end of file
diff --git a/app/components/ClientRouteGuard.tsx b/app/components/ClientRouteGuard.tsx
new file mode 100644
index 0000000..36b66c7
--- /dev/null
+++ b/app/components/ClientRouteGuard.tsx
@@ -0,0 +1,45 @@
+'use client';
+
+import { useEffect, useState } from 'react';
+import { useRouter } from 'next/navigation';
+
+// 这个组件会检查 localStorage 中是否有认证令牌,如果没有则重定向到登录页面
+export default function ClientRouteGuard({ children }: { children: React.ReactNode }) {
+ const router = useRouter();
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ // 检查 localStorage 中是否有认证令牌
+ const checkAuth = () => {
+ // 查找 Supabase 认证令牌
+ const hasAuthToken = !!localStorage.getItem('sb-mwwvqwevplndzvmqmrxa-auth-token') ||
+ !!localStorage.getItem('sb-auth-token');
+
+ if (!hasAuthToken) {
+ // 如果没有令牌,重定向到登录页面
+ router.push('/login');
+ } else {
+ setIsAuthenticated(true);
+ }
+ setIsLoading(false);
+ };
+
+ checkAuth();
+ }, [router]);
+
+ // 显示加载状态
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ // 只有当用户已认证时才显示子组件
+ return isAuthenticated ? <>{children}> : null;
+}
\ No newline at end of file
diff --git a/app/create-shorturl/page.tsx b/app/create-shorturl/page.tsx
index f6dc1d1..c6cbd80 100644
--- a/app/create-shorturl/page.tsx
+++ b/app/create-shorturl/page.tsx
@@ -3,10 +3,10 @@
import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/lib/auth';
-import { ProtectedRoute } from '@/lib/auth';
import { limqRequest } from '@/lib/api';
import { TeamSelector } from '@/app/components/ui/TeamSelector';
import { ProjectSelector } from '@/app/components/ui/ProjectSelector';
+import ClientRouteGuard from '@/app/components/ClientRouteGuard';
interface ShortUrlData {
originalUrl: string;
@@ -21,9 +21,9 @@ interface ShortUrlData {
export default function CreateShortUrlPage() {
return (
-
+
-
+
);
}
diff --git a/app/links/page.tsx b/app/links/page.tsx
index dcd25cb..31e135c 100644
--- a/app/links/page.tsx
+++ b/app/links/page.tsx
@@ -7,6 +7,7 @@ import { Loader2, ExternalLink, Search } from 'lucide-react';
import { TeamSelector } from '@/app/components/ui/TeamSelector';
import { useRouter } from 'next/navigation';
import { useShortUrlStore, ShortUrlData } from '@/app/utils/store';
+import ClientRouteGuard from '@/app/components/ClientRouteGuard';
// Define attribute type to avoid using 'any'
interface LinkAttributes {
@@ -102,6 +103,14 @@ const convertClickHouseToShortLink = (data: Record): ShortLink
};
export default function LinksPage() {
+ return (
+
+
+
+ );
+}
+
+function LinksPageContent() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [links, setLinks] = useState([]);