user.js
5.61 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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/**
* 用户状态管理
*
* @description 管理用户登录状态、用户信息等
* @module stores/user
*/
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import Taro from '@tarojs/taro'
import { loginStatusAPI, loginAPI, getProfileAPI, logoutAPI } from '@/api/user'
import { ensureOpenidAuthorized } from '@/utils/openid'
import { isFeatureEnabled, getFeatureConfig } from '@/config/features'
export const useUserStore = defineStore('user', () => {
// ========== 状态 ==========
/** 用户信息 */
const userInfo = ref(null)
/** 是否已授权(openid) */
const isOpenid = ref(false)
/** 是否已登录 */
const isLoggedIn = ref(false)
/** 加载状态 */
const loading = ref(false)
// ========== 方法 ==========
/**
* 检查登录状态
* @description 小程序启动时检查 openid 和登录状态
* - 只触发微信授权,不跳转登录页
* - 401 由接口拦截器统一处理
* @throws {Error} 检查失败时抛出错误
*
* @example
* await userStore.checkLoginStatus()
*/
async function checkLoginStatus() {
loading.value = true
try {
// 1. 确保 openid 已授权并尝试自动登录
const user = await ensureOpenidAuthorized()
if (user) {
// miniProgramAuthAPI 返回了用户信息,说明已自动登录
userInfo.value = user
isOpenid.value = true
isLoggedIn.value = true
return
}
// 2. 查询登录状态
const res = await loginStatusAPI()
if (res.code === 1) {
isOpenid.value = res.data.is_openid
isLoggedIn.value = res.data.is_login
// 3. 如果已登录,获取用户信息
if (isLoggedIn.value) {
await fetchUserInfo()
}
// 注意:这里不跳转登录页,让用户可以浏览小程序
// 当用户操作触发接口返回 401 时,会自动跳转登录页
} else {
throw new Error(res.msg || '查询登录状态失败')
}
} catch (err) {
console.error('检查登录状态失败:', err)
throw err
} finally {
loading.value = false
}
}
/**
* 获取用户信息
* @description 调用 getProfileAPI 获取用户信息
* @throws {Error} 获取失败时抛出错误
*
* @example
* await userStore.fetchUserInfo()
*/
async function fetchUserInfo() {
try {
const res = await getProfileAPI()
if (res.code === 1) {
userInfo.value = res.data.user
} else {
throw new Error(res.msg || '获取用户信息失败')
}
} catch (err) {
console.error('获取用户信息失败:', err)
throw err
}
}
/**
* 用户登录
* @description 调用 loginAPI 进行账号密码登录
* @param {Object} loginData 登录数据
* @param {string} loginData.uuid 账号
* @param {string} loginData.password 密码
* @returns {{success: boolean, message?: string}} 登录结果
*
* @example
* const result = await userStore.login({
* uuid: '13800138000',
* password: '123456'
* })
* if (result.success) {
* console.log('登录成功')
* }
*/
async function login(loginData) {
loading.value = true
try {
const res = await loginAPI(loginData)
if (res.code === 1) {
// 登录成功,获取用户信息
await fetchUserInfo()
isLoggedIn.value = true
return { success: true }
} else {
throw new Error(res.msg || '登录失败')
}
} catch (err) {
console.error('登录失败:', err)
return { success: false, message: err.message }
} finally {
loading.value = false
}
}
/**
* 用户登出
* @description 调用 logoutAPI 并清除本地状态
*
* @example
* await userStore.logout()
*/
async function logout() {
try {
// 调用登出接口
await logoutAPI()
// 清除本地状态
userInfo.value = null
isOpenid.value = false
isLoggedIn.value = false
} catch (err) {
console.error('登出失败:', err)
}
}
/**
* TabBar 红点状态
*
* @description 根据 userInfo 中的字段计算是否显示红点
* - 只在功能开关启用时生效
* - 只处理 'me' 按钮的红点
* - 根据 unread_count 字段判断(可配置)
*
* @returns {string[]} 需要显示红点的 tab key 数组
*
* @example
* // 返回 ['me'] 表示在 '我的' 按钮显示红点
* // 返回 [] 表示不显示红点
*/
const tabBarBadges = computed(() => {
// 1. 检查功能开关
if (!isFeatureEnabled('tabbarBadge')) {
return []
}
// 2. 检查用户信息是否存在
if (!userInfo.value) {
return []
}
// 3. 获取配置的字段名和阈值
const fieldName = getFeatureConfig('tabbarBadgeField') // 'unread_count'
const threshold = getFeatureConfig('tabbarBadgeThreshold') // 1
// 4. 读取字段值
const fieldValue = userInfo.value[fieldName]
// 5. 判断是否显示红点
const badges = []
// 处理数字类型(如 unread_count: 5)
if (typeof fieldValue === 'number') {
if (fieldValue >= threshold) {
badges.push('me')
}
}
// 处理布尔类型(如 has_notification: true)
else if (typeof fieldValue === 'boolean') {
if (fieldValue) {
badges.push('me')
}
}
return badges
})
// ========== 返回 ==========
return {
// 状态
userInfo,
isOpenid,
isLoggedIn,
loading,
// 计算属性
tabBarBadges,
// 方法
checkLoginStatus,
fetchUserInfo,
login,
logout
}
})