金融产品设计及数字化营销沙盘
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

110 lines
3.3 KiB

import { reactive, readonly } from 'vue';
import { RouteRecordRaw } from 'vue-router';
import { accountLogin, accountRefreshToken, LoginParam, queryCurrentUser } from '@/api/login';
import {
setAccessToken,
removeAccessToken,
getRefreshToken,
setRefreshToken,
getRefreshAt,
setRefreshAt,
getAccessAt,
setAccessAt,
getSessionTimeout,
setSessionTimeout,
removeSessionTimeout,
removeRefreshToken,
removeRefreshAt,
} from '@/utils/auth';
export interface CurrentUser {
username?: string;
avatar?: string;
permissions?: string[];
loginDate?: Date;
loginIp?: string;
}
const state = reactive<CurrentUser>({});
const setCurrentUser = (user: CurrentUser): void => {
Object.assign(state, user);
};
export const currentUser = readonly(state);
export const login = async (params: LoginParam): Promise<any> => {
const data = await accountLogin(params);
if (data.status === 0) {
const { result } = data;
const now = new Date().getTime();
setAccessToken(result.accessToken);
setRefreshToken(result.refreshToken);
setSessionTimeout(result.sessionTimeout);
setAccessAt(now);
setRefreshAt(now);
}
return data;
};
export const logout = (): void => {
removeRefreshAt();
removeAccessToken();
removeRefreshToken();
removeSessionTimeout();
setCurrentUser({});
};
// 刷新间隔时间。默认 5 分钟。
const interval = 5 * 60 * 1000;
let refreshInterval: any;
/**
* RefreshToken 刷新机制。
*
* 1. 自动定时刷新。永不过期。
* 2. 访问时刷新。30分钟过期。
*/
const runRefreshToken = async () => {
const refreshToken = getRefreshToken();
// refreshToken不存在,不刷新。
if (!refreshToken) return;
const accessAt = getAccessAt();
const now = new Date().getTime();
// 超过时间没有访问,退出登录。默认为 30 分钟。
if (now - accessAt > getSessionTimeout() * 60 * 1000) {
logout();
return;
}
// 记录刷新时间,用于重新加载页面时,初始化Interval。
setRefreshAt(now);
const data = await accountRefreshToken({ refreshToken });
if (data.status !== 0) return;
const { result } = data;
setAccessToken(result.accessToken);
setRefreshToken(result.refreshToken);
};
export const initRefreshInterval = (): void => {
let afterTime = getRefreshAt() + interval - new Date().getTime();
if (afterTime < 0) afterTime = 0;
setTimeout(() => {
runRefreshToken();
if (!refreshInterval) refreshInterval = setInterval(runRefreshToken, interval);
}, afterTime);
};
export const fetchCurrentUser = async (): Promise<any> => {
const user = await queryCurrentUser();
if (user) {
setCurrentUser({ username: user.username, avatar: user.avatar, permissions: user.permissions, loginDate: user.loginDate, loginIp: user.loginIp });
} else {
removeAccessToken();
}
return user;
};
export const hasCurrentUser = (): boolean => state.username !== undefined;
export const hasPermission = (requiresPermission: string | undefined): boolean => !requiresPermission || (state.permissions?.includes(requiresPermission) ?? false);
export const perm = (requiresPermission: string | undefined): boolean => !hasPermission(requiresPermission);
export const isShowMenu = (route: RouteRecordRaw): boolean => !route.meta?.hidden && hasPermission(route.meta?.requiresPermission);