auth.js
6.16 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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
* @Date: 2025-03-20 21:11:31
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-03 12:55:25
* @FilePath: /mlaj/src/contexts/auth.js
* @Description: 认证上下文管理模块,提供用户认证状态管理、登录登出功能
*/
// 导入Vue的组合式API相关函数
import { ref, provide, inject, onMounted } from 'vue'
import { logoutAPI, getUserInfoAPI } from '@/api/users'
import { getAuthInfoAPI } from '@/api/auth'
import { clearAuthHeaders, setAuthHeaders } from '@/utils/axios'
// 创建认证上下文的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(async () => {
const savedUser = localStorage.getItem('currentUser')
if (savedUser) {
// // 检查token是否有效,有效则恢复用户状态
// if (checkTokenExpiration()) {
// currentUser.value = JSON.parse(savedUser)
// }
// 从服务器获取用户信息并更新本地存储
const { code, data } = await getUserInfoAPI();
if (code) {
currentUser.value = { ...data.user, ...data.checkin }
localStorage.setItem('currentUser', JSON.stringify(currentUser.value))
// 重新设置认证头
const userInfo = JSON.parse(localStorage.getItem('user_info') || '{}')
if (userInfo.user_id && userInfo.HTTP_USER_TOKEN) {
setAuthHeaders(userInfo.user_id, userInfo.HTTP_USER_TOKEN)
}
} else {
logout()
}
} else {
const { code, data } = await getAuthInfoAPI();
if(code) {
// 查询用户是否授权, 从服务器获取用户信息并更新本地存储
if (data.openid_has) {
currentUser.value = { ...data.user, ...data.checkin }
localStorage.setItem('currentUser', JSON.stringify(currentUser.value))
// 重新设置认证头
const userInfo = JSON.parse(localStorage.getItem('user_info') || '{}')
if (userInfo.user_id && userInfo.HTTP_USER_TOKEN) {
setAuthHeaders(userInfo.user_id, userInfo.HTTP_USER_TOKEN)
}
}
// 判断用户是否已经登录
if (data?.user?.id) {
// 已登录,更新用户状态
currentUser.value = { ...data.user, ...data.checkin }
localStorage.setItem('currentUser', JSON.stringify(currentUser.value))
// 重新设置认证头
const userInfo = JSON.parse(localStorage.getItem('user_info') || '{}')
if (userInfo.user_id && userInfo.HTTP_USER_TOKEN) {
setAuthHeaders(userInfo.user_id, userInfo.HTTP_USER_TOKEN)
}
}
}
}
// 初始化完成,关闭加载状态
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('将用户数据保存到本地存储失败:', error)
}
}
return true
}
/**
* 用户登出函数
* 清理用户状态和本地存储的认证信息
*/
const logout = async () => {
try {
const { code } = await logoutAPI()
if (code) {
// 清空当前用户状态
currentUser.value = null
// 清理本地存储的用户信息和登录时间戳
localStorage.removeItem('currentUser')
localStorage.removeItem('user_info')
// localStorage.removeItem('loginTimestamp')
// 清除认证请求头
clearAuthHeaders()
}
} catch (error) {
console.error('注销失败:', error)
// 即使API调用失败,也要清理本地状态
currentUser.value = null
localStorage.removeItem('currentUser')
localStorage.removeItem('user_info')
clearAuthHeaders()
}
}
/**
* 提供认证上下文给子组件使用
* 包含:
* - 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
}