topfans/frontend/store/modules/user.js

226 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { loginApi, registerApi } from '@/utils/api'
import { resetAllGuides } from '@/utils/guideConfig'
import { getPreloadApi } from '@/utils/preloadApi/index'
const state = {
token: uni.getStorageSync('access_token') || '',
starId: uni.getStorageSync('star_id') || null,
userInfo: (() => {
const userStr = uni.getStorageSync('user')
if (userStr) {
try {
return JSON.parse(userStr)
} catch (e) {
return null
}
}
return null
})()
}
const getters = {
isLoggedIn: (state) => {
return !!state.token
}
}
const mutations = {
SET_TOKEN(state, token) {
state.token = token
// 缓存到 storage
if (token) {
uni.setStorageSync('access_token', token)
} else {
uni.removeStorageSync('access_token')
}
},
SET_USER_INFO(state, userInfo) {
// ★ 新增:检查用户切换,清理旧用户缓存
const oldUserStr = uni.getStorageSync('user')
let oldUserId = null
if (oldUserStr) {
try { const old = JSON.parse(oldUserStr); oldUserId = old?.uid || null } catch (e) {}
}
const newUserId = userInfo?.uid || null
if (oldUserId && newUserId && oldUserId !== newUserId) {
try {
const api = getPreloadApi()
if (api) { api.invalidatePrefix('me.'); api.clearForUser(oldUserId) }
} catch (e) {}
}
state.userInfo = userInfo
// 缓存到 storage
if (userInfo) {
uni.setStorageSync('user', JSON.stringify(userInfo))
// 单独缓存 star_id方便其他地方直接读取
const starId = userInfo?.fan_identity?.star_id ?? null
state.starId = starId
if (starId !== null) {
uni.setStorageSync('star_id', starId)
} else {
uni.removeStorageSync('star_id')
}
} else {
uni.removeStorageSync('user')
uni.removeStorageSync('star_id')
state.starId = null
}
},
CLEAR_AUTH(state) {
// ★ 新增:先清理 preload 缓存(在清 token 之前spec §6.5 constraint #2
const userStr = uni.getStorageSync('user')
let userId = null
if (userStr) {
try { const user = JSON.parse(userStr); userId = user?.uid || null } catch (e) {}
}
if (userId) {
try {
const api = getPreloadApi()
if (api) api.clearUser(userId)
} catch (e) {}
}
state.token = ''
state.userInfo = null
state.starId = null
// 清除所有引导相关存储(传入 userId 确保正确清除)
// 注userId 已在上面 preload 清理块中从 storage 读取,此处复用
resetAllGuides(userId)
// 清除 storage
uni.removeStorageSync('access_token')
uni.removeStorageSync('user')
uni.removeStorageSync('star_id')
// 清除登录手机号
uni.removeStorageSync('login_mobile')
// 清除 gallery_owner_id
uni.removeStorageSync('gallery_owner_id')
// 清除每日登录打卡记录
const today = new Date().toISOString().split('T')[0]
uni.removeStorageSync(`daily_login_completed_${today}`)
// 重置 TopfansWelcome 相关标记让登出后再登录quickLogin / 注册)能再次展示欢迎页
// 同时清掉 storage 和内存标记,避免 password 登录误触发(见 store/modules/user.js 注释表)
uni.removeStorageSync('needs_welcome')
try {
const app = getApp()
if (app && app.globalData) {
app.globalData.welcomeShownThisSession = false
}
} catch (e) {
// getApp() 在非 App 上下文不可用,忽略即可
}
}
}
const actions = {
// 登录
async login({ commit }, { mobile, password }) {
try {
const res = await loginApi(mobile, password)
if (res.code === 0 && res.data) {
// 缓存 access_token
const accessToken = res.data.access_token
uni.setStorageSync('access_token', accessToken)
commit('SET_TOKEN', accessToken)
// 缓存用户信息
const user = res.data.user
// 缓存登录手机号
const loginMobile = mobile
uni.setStorageSync('login_mobile', loginMobile)
uni.setStorageSync('user', JSON.stringify(user))
commit('SET_USER_INFO', user)
return Promise.resolve(res)
} else {
// 返回错误信息,包含 message
return Promise.reject(new Error(res.message || '登录失败'))
}
} catch (error) {
// 处理网络错误或HTTP错误
// 如果错误响应包含 message使用它否则使用默认错误信息
if (error.message) {
return Promise.reject(new Error(error.message))
}
return Promise.reject(new Error('登录失败,请检查网络连接'))
}
},
// 注册
async register({ commit }, { mobile, password, star_id, nickname, verify_token = '', avatar_url = '' }) {
try {
const res = await registerApi(mobile, password, star_id, nickname, verify_token, avatar_url)
if (res.code === 0 && res.data) {
// 缓存 access_token
const accessToken = res.data.access_token
uni.setStorageSync('access_token', accessToken)
commit('SET_TOKEN', accessToken)
// 缓存用户信息
const user = res.data.user
// 缓存登录手机号
const loginMobile = mobile
// uni.setStorageSync('login_mobile', loginMobile)
uni.setStorageSync('user', JSON.stringify(user))
commit('SET_USER_INFO', user)
return Promise.resolve(res)
} else {
// 处理昵称已存在的情况
if (res.code === 3) {
return Promise.reject({ code: 3, message: res.message || '昵称已存在' })
}
return Promise.reject(new Error(res.message || '注册失败'))
}
} catch (error) {
// 处理HTTP 409错误
if (error.statusCode === 409 || error.code === 3) {
return Promise.reject({ code: 3, message: error.message || '昵称已存在' })
}
return Promise.reject(error)
}
},
// 登出
logout({ commit }) {
commit('CLEAR_AUTH')
},
// 检查登录状态(从 storage 恢复)
checkLoginStatus({ commit, state }) {
// 从 storage 恢复 token
const token = uni.getStorageSync('access_token')
if (token && token !== state.token) {
commit('SET_TOKEN', token)
}
// 从 storage 恢复 userInfo
const userStr = uni.getStorageSync('user')
if (userStr) {
try {
const userInfo = JSON.parse(userStr)
if (userInfo && (!state.userInfo || JSON.stringify(userInfo) !== JSON.stringify(state.userInfo))) {
commit('SET_USER_INFO', userInfo)
}
} catch (e) {
console.error('恢复用户信息失败:', e)
}
}
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
}