upload project source code
This commit is contained in:
174
前端源码/uni-app/utils/auth.ts
Normal file
174
前端源码/uni-app/utils/auth.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* 登录状态管理工具
|
||||
*/
|
||||
|
||||
import router from '@/router';
|
||||
|
||||
const TOKEN_KEY = 'token';
|
||||
const USER_INFO_KEY = 'userInfo';
|
||||
const TOKEN_EXPIRE_TIME_KEY = 'tokenExpireTime';
|
||||
|
||||
const normalizeAvatarUrl = (avatar: any): any => {
|
||||
if (typeof avatar !== 'string') return avatar;
|
||||
const url = avatar.trim();
|
||||
if (!url) return url;
|
||||
if (!url.startsWith('http://')) return url;
|
||||
|
||||
const host = url.slice('http://'.length).split('/')[0] || '';
|
||||
const isLocalhost = host.startsWith('localhost') || host.startsWith('127.0.0.1');
|
||||
const isPrivateIp =
|
||||
host.startsWith('10.') ||
|
||||
host.startsWith('192.168.') ||
|
||||
/^172\.(1[6-9]|2\d|3[0-1])\./.test(host);
|
||||
if (isLocalhost || isPrivateIp) return url;
|
||||
|
||||
return 'https://' + url.slice('http://'.length);
|
||||
};
|
||||
|
||||
const normalizeUserInfo = (userInfo: any): any => {
|
||||
if (!userInfo || typeof userInfo !== 'object') return userInfo;
|
||||
const next = { ...userInfo };
|
||||
if ('avatar' in next) {
|
||||
next.avatar = normalizeAvatarUrl((next as any).avatar);
|
||||
}
|
||||
return next;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取 token
|
||||
*/
|
||||
export const getToken = (): string | null => {
|
||||
try {
|
||||
return localStorage.getItem(TOKEN_KEY) || null;
|
||||
} catch (e) {
|
||||
console.error('获取 token 失败:', e);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置 token
|
||||
*/
|
||||
export const setToken = (token: string, expireTime?: number): void => {
|
||||
try {
|
||||
localStorage.setItem(TOKEN_KEY, token);
|
||||
if (expireTime) {
|
||||
localStorage.setItem(TOKEN_EXPIRE_TIME_KEY, String(expireTime));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('设置 token 失败:', e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 清除 token
|
||||
*/
|
||||
export const clearToken = (): void => {
|
||||
try {
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
localStorage.removeItem(TOKEN_EXPIRE_TIME_KEY);
|
||||
localStorage.removeItem(USER_INFO_KEY);
|
||||
} catch (e) {
|
||||
console.error('清除 token 失败:', e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查 token 是否存在
|
||||
*/
|
||||
export const hasToken = (): boolean => {
|
||||
return !!getToken();
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查 token 是否过期
|
||||
* @param expireTime token 过期时间戳(毫秒),如果不传则从存储中读取
|
||||
*/
|
||||
export const isTokenExpired = (expireTime?: number): boolean => {
|
||||
try {
|
||||
const expireStr = expireTime ? String(expireTime) : localStorage.getItem(TOKEN_EXPIRE_TIME_KEY);
|
||||
if (!expireStr) {
|
||||
// 如果没有过期时间,认为 token 有效(由后端验证)
|
||||
return false;
|
||||
}
|
||||
const expire = Number(expireStr);
|
||||
return Date.now() >= expire;
|
||||
} catch (e) {
|
||||
console.error('检查 token 过期失败:', e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查是否已登录(token 存在且未过期)
|
||||
*/
|
||||
export const isLoggedIn = (): boolean => {
|
||||
return hasToken() && !isTokenExpired();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export const getUserInfo = (): any | null => {
|
||||
try {
|
||||
const v = localStorage.getItem(USER_INFO_KEY);
|
||||
if (!v) return null;
|
||||
return normalizeUserInfo(JSON.parse(v));
|
||||
} catch (e) {
|
||||
console.error('获取用户信息失败:', e);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置用户信息
|
||||
*/
|
||||
export const setUserInfo = (userInfo: any): void => {
|
||||
try {
|
||||
localStorage.setItem(USER_INFO_KEY, JSON.stringify(normalizeUserInfo(userInfo)));
|
||||
} catch (e) {
|
||||
console.error('设置用户信息失败:', e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 跳转到登录页
|
||||
* @param force 为 true 时即使当前已在 /login 也 replace 一次(用于退出登录后刷新登录态)
|
||||
*/
|
||||
export const navigateToLogin = (options?: { redirect?: string; force?: boolean }): void => {
|
||||
try {
|
||||
const currentRoute = router.currentRoute.value.path;
|
||||
|
||||
if (options?.force || currentRoute !== '/login') {
|
||||
const redirect = options?.redirect ?? (currentRoute !== '/login' ? currentRoute : '/');
|
||||
router.replace({
|
||||
path: '/login',
|
||||
query: { redirect: encodeURIComponent(redirect) }
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('跳转登录页失败:', e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 退出登录:仅前端清空 token / 用户信息并进入登录页(不请求后端)
|
||||
*/
|
||||
export const logout = (): void => {
|
||||
clearToken();
|
||||
navigateToLogin({ force: true, redirect: '/' });
|
||||
};
|
||||
|
||||
/**
|
||||
* 需要登录的页面路径列表(白名单外的页面都需要登录)
|
||||
*/
|
||||
const LOGIN_WHITELIST = ['/login'];
|
||||
|
||||
/**
|
||||
* 检查页面是否需要登录
|
||||
*/
|
||||
export const isPageRequireLogin = (path: string): boolean => {
|
||||
return !LOGIN_WHITELIST.some((whitelistPath) => path.includes(whitelistPath));
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user