366 lines
9.9 KiB
JavaScript
366 lines
9.9 KiB
JavaScript
/**
|
|
* 登录状态管理工具
|
|
* 用于管理用户登录流程中的状态和数据传递
|
|
*/
|
|
|
|
// 登录步骤常量
|
|
export const LOGIN_STEPS = {
|
|
NOT_LOGGED: 'not_logged', // 未登录
|
|
WX_LOGGED: 'wx_logged', // 微信登录完成
|
|
PHONE_AUTHED: 'phone_authed', // 手机号授权完成
|
|
PHONE_SKIPPED: 'phone_skipped', // 跳过手机号授权
|
|
PROFILE_COMPLETED: 'profile_completed' // 个人信息完善完成
|
|
}
|
|
|
|
// 存储键名常量
|
|
export const STORAGE_KEYS = {
|
|
LOGIN_STEP: 'loginStep',
|
|
WX_LOGIN_CODE: 'wxLoginCode',
|
|
TOKEN: 'token',
|
|
REFRESH_TOKEN: 'refreshToken',
|
|
PHONE_NUMBER: 'phoneNumber',
|
|
WX_USER_INFO: 'wxUserInfo',
|
|
USER_INFO: 'userInfo',
|
|
LOGIN_DATE: 'loginDate'
|
|
}
|
|
|
|
/**
|
|
* 获取当前登录步骤
|
|
* @returns {string} 当前登录步骤
|
|
*/
|
|
export const getCurrentLoginStep = () => {
|
|
return uni.getStorageSync(STORAGE_KEYS.LOGIN_STEP) || LOGIN_STEPS.NOT_LOGGED
|
|
}
|
|
|
|
/**
|
|
* 设置登录步骤
|
|
* @param {string} step 登录步骤
|
|
*/
|
|
export const setLoginStep = (step) => {
|
|
console.log('设置登录步骤:', step)
|
|
uni.setStorageSync(STORAGE_KEYS.LOGIN_STEP, step)
|
|
}
|
|
|
|
/**
|
|
* 检查用户是否已完成登录流程
|
|
* @returns {boolean} 是否已完成登录
|
|
*/
|
|
export const isLoginCompleted = () => {
|
|
const step = getCurrentLoginStep()
|
|
return step === LOGIN_STEPS.PROFILE_COMPLETED
|
|
}
|
|
|
|
/**
|
|
* 检查用户是否需要继续登录流程
|
|
* @returns {boolean} 是否需要继续登录
|
|
*/
|
|
export const needsContinueLogin = () => {
|
|
const step = getCurrentLoginStep()
|
|
return step !== LOGIN_STEPS.NOT_LOGGED && step !== LOGIN_STEPS.PROFILE_COMPLETED
|
|
}
|
|
|
|
/**
|
|
* 获取下一个应该跳转的页面
|
|
* @returns {string|null} 页面路径,如果不需要跳转则返回null
|
|
*/
|
|
export const getNextPage = () => {
|
|
const step = getCurrentLoginStep()
|
|
|
|
switch (step) {
|
|
case LOGIN_STEPS.WX_LOGGED:
|
|
return '/pages/auth/phone-auth'
|
|
case LOGIN_STEPS.PHONE_AUTHED:
|
|
case LOGIN_STEPS.PHONE_SKIPPED:
|
|
return '/pages/profile/user-info?mode=setup'
|
|
case LOGIN_STEPS.PROFILE_COMPLETED:
|
|
return '/pages/profile/profile'
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 保存微信登录信息
|
|
* @param {Object} loginData 登录数据
|
|
*/
|
|
export const saveWxLoginData = (loginData) => {
|
|
const { code } = loginData
|
|
|
|
uni.setStorageSync(STORAGE_KEYS.WX_LOGIN_CODE, code)
|
|
uni.setStorageSync(STORAGE_KEYS.LOGIN_DATE, new Date().toISOString())
|
|
setLoginStep(LOGIN_STEPS.WX_LOGGED)
|
|
|
|
console.log('保存微信登录数据:', { code, step: LOGIN_STEPS.WX_LOGGED })
|
|
}
|
|
|
|
/**
|
|
* 保存手机号授权信息
|
|
* @param {Object} phoneData 手机号数据
|
|
*/
|
|
export const savePhoneAuthData = (phoneData) => {
|
|
const { token, refreshToken, userInfo } = phoneData
|
|
|
|
if (token) {
|
|
uni.setStorageSync(STORAGE_KEYS.TOKEN, token)
|
|
}
|
|
|
|
if (refreshToken) {
|
|
uni.setStorageSync(STORAGE_KEYS.REFRESH_TOKEN, refreshToken)
|
|
}
|
|
|
|
if (userInfo) {
|
|
if (userInfo.phoneNumber) {
|
|
uni.setStorageSync(STORAGE_KEYS.PHONE_NUMBER, userInfo.phoneNumber)
|
|
}
|
|
|
|
// 保存微信用户信息供后续使用
|
|
const wxUserInfo = {
|
|
phoneNumber: userInfo.phoneNumber || '',
|
|
openid: userInfo.openid || '',
|
|
nickName: userInfo.nickName || '',
|
|
avatarUrl: userInfo.avatarUrl || ''
|
|
}
|
|
uni.setStorageSync(STORAGE_KEYS.WX_USER_INFO, wxUserInfo)
|
|
uni.setStorageSync(STORAGE_KEYS.USER_INFO, userInfo)
|
|
}
|
|
|
|
// 根据用户信息完善状态设置登录步骤
|
|
if (userInfo && userInfo.profileCompleted) {
|
|
setLoginStep(LOGIN_STEPS.PROFILE_COMPLETED)
|
|
} else {
|
|
setLoginStep(LOGIN_STEPS.PHONE_AUTHED)
|
|
}
|
|
|
|
console.log('保存手机号授权数据:', { token: !!token, refreshToken: !!refreshToken, userInfo: !!userInfo })
|
|
}
|
|
|
|
/**
|
|
* 标记手机号授权被跳过
|
|
*/
|
|
export const markPhoneSkipped = () => {
|
|
setLoginStep(LOGIN_STEPS.PHONE_SKIPPED)
|
|
console.log('标记手机号授权被跳过')
|
|
}
|
|
|
|
/**
|
|
* 保存用户信息完善数据
|
|
* @param {Object} profileData 用户信息数据
|
|
*/
|
|
export const saveProfileData = (profileData) => {
|
|
uni.setStorageSync(STORAGE_KEYS.USER_INFO, profileData)
|
|
setLoginStep(LOGIN_STEPS.PROFILE_COMPLETED)
|
|
|
|
console.log('保存用户信息完善数据:', profileData)
|
|
}
|
|
|
|
/**
|
|
* 清理登录流程中的临时数据
|
|
* @deprecated 使用 http/utils/auth-helper.js 中的 clearTempLoginData 替代
|
|
*/
|
|
export const clearTempLoginData = () => {
|
|
const { clearTempLoginData } = require('../http/utils/auth-helper.js')
|
|
clearTempLoginData()
|
|
}
|
|
|
|
/**
|
|
* 检查并验证token有效性
|
|
* @returns {Promise<boolean>} token是否有效
|
|
* @deprecated 使用 http/utils/auth-helper.js 中的 validateToken 替代
|
|
*/
|
|
export const validateToken = async () => {
|
|
const { validateToken } = await import('../http/utils/auth-helper.js')
|
|
return await validateToken()
|
|
}
|
|
|
|
/**
|
|
* 尝试刷新token
|
|
* @returns {Promise<boolean>} 是否刷新成功
|
|
*/
|
|
export const tryRefreshToken = async () => {
|
|
const refreshToken = uni.getStorageSync(STORAGE_KEYS.REFRESH_TOKEN)
|
|
if (!refreshToken) {
|
|
return false
|
|
}
|
|
|
|
try {
|
|
const { refreshToken: refreshTokenApi } = await import('@/http/api/auth.js')
|
|
const result = await refreshTokenApi({
|
|
custom: {
|
|
loading: false,
|
|
toast: false
|
|
}
|
|
})
|
|
|
|
if (result && result.token) {
|
|
uni.setStorageSync(STORAGE_KEYS.TOKEN, result.token)
|
|
if (result.refreshToken) {
|
|
uni.setStorageSync(STORAGE_KEYS.REFRESH_TOKEN, result.refreshToken)
|
|
}
|
|
console.log('Token刷新成功')
|
|
return true
|
|
}
|
|
return false
|
|
} catch (error) {
|
|
console.log('Token刷新失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 自动登录(用于用户再次进入小程序)
|
|
* @returns {Promise<boolean>} 是否登录成功
|
|
*/
|
|
export const autoLogin = async () => {
|
|
console.log('开始自动登录检查')
|
|
|
|
// 1. 检查token有效性
|
|
if (await validateToken()) {
|
|
console.log('Token有效,自动登录成功')
|
|
return true
|
|
}
|
|
|
|
// 2. 尝试刷新token
|
|
if (await tryRefreshToken()) {
|
|
console.log('Token刷新成功,自动登录成功')
|
|
return true
|
|
}
|
|
|
|
// 3. 尝试使用微信code重新登录(不需要手机号授权)
|
|
try {
|
|
const loginRes = await new Promise((resolve, reject) => {
|
|
uni.login({
|
|
success: resolve,
|
|
fail: reject
|
|
})
|
|
})
|
|
|
|
if (loginRes.code) {
|
|
const { wxLogin } = await import('@/http/api/auth.js')
|
|
const result = await wxLogin({
|
|
code: loginRes.code
|
|
}, {
|
|
custom: {
|
|
loading: false,
|
|
toast: false
|
|
}
|
|
})
|
|
|
|
if (result && result.token) {
|
|
// 保存新的登录信息
|
|
uni.setStorageSync(STORAGE_KEYS.TOKEN, result.token)
|
|
if (result.refreshToken) {
|
|
uni.setStorageSync(STORAGE_KEYS.REFRESH_TOKEN, result.refreshToken)
|
|
}
|
|
if (result.userInfo) {
|
|
uni.setStorageSync(STORAGE_KEYS.WX_USER_INFO, result.userInfo)
|
|
uni.setStorageSync(STORAGE_KEYS.USER_INFO, result.userInfo)
|
|
// 如果用户已完善过信息,设置为已完成状态
|
|
if (result.userInfo.profileCompleted) {
|
|
setLoginStep(LOGIN_STEPS.PROFILE_COMPLETED)
|
|
} else {
|
|
setLoginStep(LOGIN_STEPS.PHONE_AUTHED)
|
|
}
|
|
}
|
|
console.log('微信code登录成功,自动登录成功')
|
|
return true
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.log('微信code登录失败:', error)
|
|
}
|
|
|
|
console.log('自动登录失败,需要用户手动登录')
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* 完全重置登录状态(用于登出)
|
|
*/
|
|
export const resetLoginState = () => {
|
|
uni.removeStorageSync(STORAGE_KEYS.LOGIN_STEP)
|
|
uni.removeStorageSync(STORAGE_KEYS.WX_LOGIN_CODE)
|
|
uni.removeStorageSync(STORAGE_KEYS.TOKEN)
|
|
uni.removeStorageSync(STORAGE_KEYS.REFRESH_TOKEN)
|
|
uni.removeStorageSync(STORAGE_KEYS.PHONE_NUMBER)
|
|
uni.removeStorageSync(STORAGE_KEYS.WX_USER_INFO)
|
|
uni.removeStorageSync(STORAGE_KEYS.USER_INFO)
|
|
uni.removeStorageSync(STORAGE_KEYS.LOGIN_DATE)
|
|
|
|
console.log('重置登录状态')
|
|
}
|
|
|
|
/**
|
|
* 获取登录流程的状态信息(用于内部检查)
|
|
* @returns {Object} 状态信息
|
|
*/
|
|
const getLoginStateInfo = () => {
|
|
return {
|
|
currentStep: getCurrentLoginStep(),
|
|
wxLoginCode: uni.getStorageSync(STORAGE_KEYS.WX_LOGIN_CODE),
|
|
hasToken: !!uni.getStorageSync(STORAGE_KEYS.TOKEN),
|
|
hasPhoneNumber: !!uni.getStorageSync(STORAGE_KEYS.PHONE_NUMBER),
|
|
hasWxUserInfo: !!uni.getStorageSync(STORAGE_KEYS.WX_USER_INFO),
|
|
hasUserInfo: !!uni.getStorageSync(STORAGE_KEYS.USER_INFO),
|
|
loginDate: uni.getStorageSync(STORAGE_KEYS.LOGIN_DATE)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查并处理登录流程的断点续传
|
|
* @returns {string|null} 需要跳转的页面路径,如果不需要跳转则返回null
|
|
*/
|
|
export const checkAndResumeLogin = () => {
|
|
const currentStep = getCurrentLoginStep()
|
|
|
|
// 如果已完成登录或未开始登录,不需要续传
|
|
if (currentStep === LOGIN_STEPS.PROFILE_COMPLETED || currentStep === LOGIN_STEPS.NOT_LOGGED) {
|
|
return null
|
|
}
|
|
|
|
// 检查数据完整性
|
|
const stateInfo = getLoginStateInfo()
|
|
console.log('检查登录断点续传:', stateInfo)
|
|
|
|
// 根据当前步骤和数据完整性决定下一步
|
|
switch (currentStep) {
|
|
case LOGIN_STEPS.WX_LOGGED:
|
|
// 检查是否有微信登录凭证
|
|
if (!stateInfo.wxLoginCode) {
|
|
console.warn('微信登录凭证丢失,重置登录状态')
|
|
setLoginStep(LOGIN_STEPS.NOT_LOGGED)
|
|
return null
|
|
}
|
|
// 检查登录凭证是否过期(超过30分钟)
|
|
const loginDate = uni.getStorageSync(STORAGE_KEYS.LOGIN_DATE)
|
|
if (loginDate) {
|
|
const loginTime = new Date(loginDate).getTime()
|
|
const now = new Date().getTime()
|
|
const timeDiff = now - loginTime
|
|
// 如果超过30分钟,认为登录凭证过期
|
|
if (timeDiff > 30 * 60 * 1000) {
|
|
console.warn('微信登录凭证已过期,重置登录状态')
|
|
setLoginStep(LOGIN_STEPS.NOT_LOGGED)
|
|
return null
|
|
}
|
|
}
|
|
return '/pages/auth/phone-auth'
|
|
|
|
case LOGIN_STEPS.PHONE_AUTHED:
|
|
// 检查是否有token
|
|
if (!stateInfo.hasToken) {
|
|
console.warn('Token丢失,回退到手机号授权')
|
|
setLoginStep(LOGIN_STEPS.WX_LOGGED)
|
|
return '/pages/auth/phone-auth'
|
|
}
|
|
return '/pages/profile/user-info?mode=setup'
|
|
|
|
case LOGIN_STEPS.PHONE_SKIPPED:
|
|
return '/pages/profile/user-info?mode=setup&phoneSkipped=true'
|
|
|
|
default:
|
|
console.warn('未知的登录步骤:', currentStep)
|
|
setLoginStep(LOGIN_STEPS.NOT_LOGGED)
|
|
return null
|
|
}
|
|
}
|