225 lines
6.8 KiB
JavaScript
225 lines
6.8 KiB
JavaScript
import { loginApi, registerApi, getOssPresignedUrlApi } from '@/utils/api'
|
||
import { downloadAndCacheAvatar } from '@/utils/avatarCache'
|
||
|
||
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) {
|
||
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) {
|
||
state.token = ''
|
||
state.userInfo = null
|
||
state.starId = null
|
||
// 清除 storage
|
||
uni.removeStorageSync('access_token')
|
||
uni.removeStorageSync('user')
|
||
uni.removeStorageSync('star_id')
|
||
// 清除登录手机号
|
||
uni.removeStorageSync('login_mobile')
|
||
}
|
||
}
|
||
|
||
const actions = {
|
||
// 登录
|
||
async login({ commit }, { mobile, password }) {
|
||
try {
|
||
const res = await loginApi(mobile, password)
|
||
if (res.code === 200 && 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 = user.mobile_masked || mobile
|
||
uni.setStorageSync('login_mobile', loginMobile)
|
||
|
||
uni.setStorageSync('user', JSON.stringify(user))
|
||
commit('SET_USER_INFO', user)
|
||
|
||
// 处理头像缓存
|
||
if (user.avatar_url) {
|
||
try {
|
||
// 获取真实的预签名URL
|
||
const urlRes = await getOssPresignedUrlApi(user.avatar_url, 3600, 'avatar')
|
||
if (urlRes.code === 200 && urlRes.data && urlRes.data.url) {
|
||
// 下载并缓存头像
|
||
const localPath = await downloadAndCacheAvatar(user.avatar_url, urlRes.data.url)
|
||
|
||
// 触发头像更新事件,通知Header刷新
|
||
setTimeout(() => {
|
||
uni.$emit('avatarUpdated', {
|
||
uid: user.uid,
|
||
avatarUrl: user.avatar_url,
|
||
localPath: localPath
|
||
})
|
||
}, 100)
|
||
}
|
||
} catch (avatarError) {
|
||
console.error('头像缓存失败,但不影响登录:', avatarError)
|
||
// 头像缓存失败不影响登录流程
|
||
}
|
||
}
|
||
|
||
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 }) {
|
||
try {
|
||
const res = await registerApi(mobile, password, star_id, nickname)
|
||
if (res.code === 200 && 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 = user.mobile_masked || mobile
|
||
uni.setStorageSync('login_mobile', loginMobile)
|
||
|
||
uni.setStorageSync('user', JSON.stringify(user))
|
||
commit('SET_USER_INFO', user)
|
||
|
||
// 处理头像缓存
|
||
if (user.avatar_url) {
|
||
try {
|
||
// 获取真实的预签名URL
|
||
const urlRes = await getOssPresignedUrlApi(user.avatar_url, 3600, 'avatar')
|
||
if (urlRes.code === 200 && urlRes.data && urlRes.data.url) {
|
||
// 下载并缓存头像
|
||
const localPath = await downloadAndCacheAvatar(user.avatar_url, urlRes.data.url)
|
||
|
||
// 触发头像更新事件,通知Header刷新
|
||
setTimeout(() => {
|
||
uni.$emit('avatarUpdated', {
|
||
uid: user.uid,
|
||
avatarUrl: user.avatar_url,
|
||
localPath: localPath
|
||
})
|
||
}, 100)
|
||
}
|
||
} catch (avatarError) {
|
||
console.error('头像缓存失败,但不影响注册:', avatarError)
|
||
// 头像缓存失败不影响注册流程
|
||
}
|
||
}
|
||
|
||
return Promise.resolve(res)
|
||
} else {
|
||
// 处理昵称已存在的情况
|
||
if (res.code === 409) {
|
||
return Promise.reject({ code: 409, message: res.message || '昵称已存在' })
|
||
}
|
||
return Promise.reject(new Error(res.message || '注册失败'))
|
||
}
|
||
} catch (error) {
|
||
// 处理HTTP 409错误
|
||
if (error.statusCode === 409 || error.code === 409) {
|
||
return Promise.reject({ code: 409, 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
|
||
}
|
||
|