/** * 登录状态管理工具 * 用于管理用户登录流程中的状态和数据传递 */ // 登录步骤常量 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} 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} 是否刷新成功 */ 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} 是否登录成功 */ 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 } }