forked from 77media/video-flow
121 lines
3.7 KiB
TypeScript
121 lines
3.7 KiB
TypeScript
'use client';
|
||
|
||
import { useEffect, useState } from 'react';
|
||
import { useRouter, usePathname } from 'next/navigation';
|
||
import { clearAuthData, getUserProfile, isAuthenticated, getCurrentUser } from '@/lib/auth';
|
||
import GlobalLoad from '../common/GlobalLoad';
|
||
import { message } from 'antd';
|
||
import { errorHandle } from '@/api/errorHandle';
|
||
import { setUserProperties } from '@/utils/analytics';
|
||
|
||
interface AuthGuardProps {
|
||
children: React.ReactNode;
|
||
}
|
||
|
||
export default function AuthGuard({ children }: AuthGuardProps) {
|
||
const [isLoading, setIsLoading] = useState(true);
|
||
const [isAuthorized, setIsAuthorized] = useState(false);
|
||
const router = useRouter();
|
||
const pathname = usePathname();
|
||
|
||
// 不需要鉴权的页面
|
||
const publicPaths = ['/','/login', '/signup', '/forgot-password', '/Terms', '/Privacy', '/activate', '/users/oauth/callback'];
|
||
const isPublicPath = publicPaths.includes(pathname);
|
||
|
||
/**
|
||
* 设置用户GA属性
|
||
* 基于实际userData结构: {"id":"8f61686734d340d0820f0fe980368629","userId":"8f61686734d340d0820f0fe980368629","username":"Orange","email":"moviflow68@test.com","isActive":1,"authType":"LOCAL","lastLogin":"2025-09-28T16:28:51.870731"}
|
||
*/
|
||
const setUserAnalyticsProperties = (userData: any) => {
|
||
if (!userData || !userData.id) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
setUserProperties(userData.id, {
|
||
// 基础用户信息
|
||
user_id: userData.id,
|
||
email: userData.email,
|
||
username: userData.username,
|
||
// 认证信息
|
||
auth_type: userData.authType || 'LOCAL',
|
||
is_active: userData.isActive || 1,
|
||
// 登录信息
|
||
last_login: userData.lastLogin || new Date().toISOString(),
|
||
// 页面信息
|
||
current_page: pathname,
|
||
// 用户状态
|
||
user_status: userData.isActive === 1 ? 'active' : 'inactive',
|
||
// 会话信息
|
||
session_id: `${userData.id}_${Date.now()}`
|
||
});
|
||
} catch (error) {}
|
||
};
|
||
|
||
useEffect(() => {
|
||
const verifyAuth = async () => {
|
||
// 如果是公共页面,不需要鉴权
|
||
if (isPublicPath) {
|
||
setIsAuthorized(true);
|
||
setIsLoading(false);
|
||
return;
|
||
}
|
||
|
||
// 检查是否有token
|
||
if (!isAuthenticated()) {
|
||
router.push('/login');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 调用鉴权接口验证token
|
||
const user = await getUserProfile();
|
||
if (user) {
|
||
setIsAuthorized(true);
|
||
|
||
// 设置用户GA属性(页面首次加载时)
|
||
setUserAnalyticsProperties(user);
|
||
} else {
|
||
router.push('/login');
|
||
}
|
||
} catch (errorCode:any) {
|
||
// 强制的领导要求,401和502都跳转到登录页 其他的不管
|
||
if(errorCode.message == 401||errorCode.message == 502){
|
||
router.push('/login');
|
||
clearAuthData();
|
||
} else {
|
||
// 如果API调用失败但不是认证错误,尝试使用本地存储的用户数据
|
||
const localUser = getCurrentUser();
|
||
if (localUser && localUser.id) {
|
||
console.log('API调用失败,使用本地用户数据设置GA属性');
|
||
setUserAnalyticsProperties(localUser);
|
||
setIsAuthorized(true);
|
||
}
|
||
}
|
||
errorHandle(errorCode.message)
|
||
} finally {
|
||
setIsLoading(false);
|
||
}
|
||
};
|
||
|
||
verifyAuth();
|
||
}, [pathname, router, isPublicPath]);
|
||
|
||
// 显示加载状态
|
||
if (isLoading) {
|
||
return (
|
||
<div className="flex items-center justify-center min-h-screen">
|
||
<GlobalLoad show={true} progress={0} />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// 如果未授权,返回null(会由router处理跳转)
|
||
if (!isAuthorized) {
|
||
return null;
|
||
}
|
||
|
||
// 授权通过,渲染子组件
|
||
return <>{children}</>;
|
||
}
|