auth.js
3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* @Date: 2025-03-20 21:11:31
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-26 16:11:58
* @FilePath: /mlaj/src/contexts/auth.js
* @Description: 认证上下文管理模块,提供用户认证状态管理、登录登出功能
*/
// 导入Vue的组合式API相关函数
import { ref, provide, inject, onMounted } from 'vue'
import { logoutAPI } from '@/api/users'
// 创建认证上下文的Symbol key,用于provide/inject依赖注入
// 使用Symbol确保key的唯一性,避免命名冲突
const authKey = Symbol('auth')
/**
* 提供认证功能的组合式函数
* 该函数创建并提供认证上下文,包含:
* 1. 用户状态管理(currentUser)
* 2. 加载状态管理(loading)
* 3. 登录登出功能
* 4. Token过期检查
*/
export function provideAuth() {
// 当前用户状态,初始为null表示未登录
const currentUser = ref(null)
// 加载状态标志,用于控制加载动画等UI展示
const loading = ref(true)
/**
* 检查登录token是否过期
* @returns {boolean} true表示token有效,false表示token已过期
*/
const checkTokenExpiration = () => {
const loginTimestamp = localStorage.getItem('loginTimestamp')
if (loginTimestamp) {
const now = Date.now()
const diff = now - parseInt(loginTimestamp)
// 检查是否超过24小时(24 * 60 * 60 * 1000 毫秒)
if (diff > 24 * 60 * 60 * 1000) {
// token过期,清理登录状态并返回false
logout()
return false
}
}
return true
}
/**
* 组件挂载时初始化用户状态
* 1. 从localStorage读取保存的用户信息
* 2. 检查token是否过期
* 3. 恢复用户状态或保持登出状态
*/
onMounted(() => {
const savedUser = localStorage.getItem('currentUser')
if (savedUser) {
// 检查token是否有效,有效则恢复用户状态
if (checkTokenExpiration()) {
currentUser.value = JSON.parse(savedUser)
}
}
// 初始化完成,关闭加载状态
loading.value = false
})
/**
* 用户登录函数
* @param {Object} userData - 用户数据对象,包含用户基本信息
* @returns {boolean} 登录是否成功
*/
const login = (userData) => {
// 更新当前用户状态
currentUser.value = userData
if (currentUser.value) {
try {
// 持久化存储用户信息和登录时间戳
localStorage.setItem('currentUser', JSON.stringify(userData))
localStorage.setItem('loginTimestamp', Date.now().toString())
} catch (error) {
console.error('Failed to save user data to localStorage:', error)
}
}
return true
}
/**
* 用户登出函数
* 清理用户状态和本地存储的认证信息
*/
const logout = async () => {
try {
const { code } = await logoutAPI()
if (code) {
// 清空当前用户状态
currentUser.value = null
// 清理本地存储的用户信息和登录时间戳
localStorage.removeItem('currentUser')
localStorage.removeItem('loginTimestamp')
}
} catch (error) {
console.error('Failed to logout:', error)
}
}
/**
* 提供认证上下文给子组件使用
* 包含:
* - currentUser: 当前用户状态
* - loading: 加载状态
* - login: 登录函数
* - logout: 登出函数
*/
provide(authKey, {
currentUser,
loading,
login,
logout
})
// 返回认证相关的状态和方法,供组件直接使用
return {
currentUser,
loading,
login,
logout
}
}
/**
* 在子组件中使用认证功能的组合式函数
* @returns {Object} 认证上下文对象,包含用户状态和认证方法
* @throws {Error} 如果在provideAuth范围外使用则抛出错误
*/
export function useAuth() {
// 注入认证上下文
const auth = inject(authKey)
// 确保在provideAuth的范围内使用
if (!auth) {
throw new Error('useAuth 必须在 provideAuth 的范围内使用')
}
return auth
}