|
|
@@ -1,6 +1,5 @@
|
|
|
/**
|
|
|
* 认证工具类
|
|
|
- * 用于管理用户登录状态、token存储和登录检查
|
|
|
* 支持H5公众号和微信小程序双端
|
|
|
*/
|
|
|
|
|
|
@@ -24,56 +23,30 @@ import {
|
|
|
var TOKEN_KEY = 'user_token'
|
|
|
var USER_INFO_KEY = 'user_info'
|
|
|
|
|
|
-// 全局状态检查定时器
|
|
|
var statusCheckTimer = null
|
|
|
-var STATUS_CHECK_INTERVAL = 10000 // 10秒检查一次
|
|
|
-var isShowingDisabledModal = false // 防止重复弹窗
|
|
|
+var STATUS_CHECK_INTERVAL = 10000
|
|
|
+var isShowingDisabledModal = false
|
|
|
|
|
|
-/**
|
|
|
- * 保存用户token到本地存储
|
|
|
- * @param {string} token - 用户登录token
|
|
|
- */
|
|
|
export var setToken = function(token) {
|
|
|
uni.setStorageSync(TOKEN_KEY, token)
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 获取本地存储的token
|
|
|
- * @returns {string|null} token或null
|
|
|
- */
|
|
|
export var getToken = function() {
|
|
|
return uni.getStorageSync(TOKEN_KEY) || null
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 移除本地存储的token
|
|
|
- */
|
|
|
export var removeToken = function() {
|
|
|
uni.removeStorageSync(TOKEN_KEY)
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 保存用户信息到本地存储
|
|
|
- * @param {object} userInfo - 用户信息对象
|
|
|
- */
|
|
|
export var setUserInfo = function(userInfo) {
|
|
|
uni.setStorageSync(USER_INFO_KEY, JSON.stringify(userInfo))
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 获取本地存储的用户信息
|
|
|
- * @returns {object|null} 用户信息对象或null
|
|
|
- */
|
|
|
export var getUserInfo = function() {
|
|
|
var userInfo = uni.getStorageSync(USER_INFO_KEY)
|
|
|
- if (!userInfo) {
|
|
|
- return null
|
|
|
- }
|
|
|
-
|
|
|
- if (typeof userInfo === 'object') {
|
|
|
- return userInfo
|
|
|
- }
|
|
|
-
|
|
|
+ if (!userInfo) return null
|
|
|
+ if (typeof userInfo === 'object') return userInfo
|
|
|
if (typeof userInfo === 'string') {
|
|
|
try {
|
|
|
return JSON.parse(userInfo)
|
|
|
@@ -83,79 +56,46 @@ export var getUserInfo = function() {
|
|
|
return null
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
return null
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 移除本地存储的用户信息
|
|
|
- */
|
|
|
export var removeUserInfo = function() {
|
|
|
uni.removeStorageSync(USER_INFO_KEY)
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 检查用户是否已登录
|
|
|
- * @returns {boolean} 是否已登录
|
|
|
- */
|
|
|
export var isLoggedIn = function() {
|
|
|
return !!getToken()
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 清除所有登录信息(退出登录)
|
|
|
- */
|
|
|
export var logout = function() {
|
|
|
- stopStatusCheck() // 停止状态检查
|
|
|
+ stopStatusCheck()
|
|
|
removeToken()
|
|
|
removeUserInfo()
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 第一步:跳转到微信授权页面
|
|
|
- * H5公众号使用OAuth2.0网页授权
|
|
|
- */
|
|
|
-export var startH5Auth = async function() {
|
|
|
- try {
|
|
|
- console.log('[H5授权] 开始获取授权URL')
|
|
|
-
|
|
|
- // 使用固定的HTTPS回调地址(不包含hash路由)
|
|
|
- var redirectUrl = 'https://' + window.location.host + '/'
|
|
|
- console.log('[H5授权] 回调地址:', redirectUrl)
|
|
|
-
|
|
|
- var result = await getH5AuthUrl(redirectUrl)
|
|
|
-
|
|
|
+// #ifdef H5
|
|
|
+export var startH5Auth = function() {
|
|
|
+ var redirectUrl = 'https://' + window.location.host + '/'
|
|
|
+ console.log('[H5授权] 回调地址:', redirectUrl)
|
|
|
+ return getH5AuthUrl(redirectUrl).then(function(result) {
|
|
|
if (result.code === 200 && result.data) {
|
|
|
console.log('[H5授权] 获取授权URL成功,准备跳转')
|
|
|
- // 跳转到微信授权页面
|
|
|
window.location.href = result.data
|
|
|
} else {
|
|
|
throw new Error(result.message || '获取授权URL失败')
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
+ }).catch(function(error) {
|
|
|
console.error('[H5授权] 失败:', error)
|
|
|
throw error
|
|
|
- }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 第二步:处理微信授权回调
|
|
|
- * 用户授权后,微信会重定向回来并携带code参数
|
|
|
- * @param {string} code - 微信授权code
|
|
|
- * @returns {Promise<object>} 返回用户信息
|
|
|
- */
|
|
|
-export var handleH5AuthCallback = async function(code) {
|
|
|
- try {
|
|
|
- console.log('[H5回调] 处理授权回调, code:', code)
|
|
|
-
|
|
|
- var result = await h5AuthCallback(code)
|
|
|
-
|
|
|
+export var handleH5AuthCallback = function(code) {
|
|
|
+ console.log('[H5回调] 处理授权回调, code:', code)
|
|
|
+ return h5AuthCallback(code).then(function(result) {
|
|
|
console.log('[H5回调] 后端响应:', result)
|
|
|
-
|
|
|
if (result.code === 200 && result.data) {
|
|
|
var userInfo = result.data
|
|
|
-
|
|
|
- // 只返回微信用户信息,不自动登录
|
|
|
console.log('[H5回调] 获取微信用户信息成功')
|
|
|
return {
|
|
|
openid: userInfo.openid,
|
|
|
@@ -166,25 +106,18 @@ export var handleH5AuthCallback = async function(code) {
|
|
|
} else {
|
|
|
throw new Error(result.message || '授权回调处理失败')
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
+ }).catch(function(error) {
|
|
|
console.error('[H5回调] 失败:', error)
|
|
|
throw error
|
|
|
- }
|
|
|
+ })
|
|
|
}
|
|
|
+// #endif
|
|
|
|
|
|
-/**
|
|
|
- * 刷新用户状态(从后端获取最新信息)
|
|
|
- * 各页面可调用此方法确保用户状态是最新的
|
|
|
- * 如果用户被禁用(status=1),自动退出登录
|
|
|
- * @returns {Promise<object|null>} 最新的用户信息或null
|
|
|
- */
|
|
|
-export var refreshUserInfo = async function() {
|
|
|
+export var refreshUserInfo = function() {
|
|
|
if (!isLoggedIn()) {
|
|
|
- return null
|
|
|
+ return Promise.resolve(null)
|
|
|
}
|
|
|
-
|
|
|
- try {
|
|
|
- var result = await getUserInfoApi()
|
|
|
+ return getUserInfoApi().then(function(result) {
|
|
|
if (result.code === 200 && result.data) {
|
|
|
var userInfo = {
|
|
|
nickname: result.data.nickname || '',
|
|
|
@@ -192,36 +125,27 @@ export var refreshUserInfo = async function() {
|
|
|
phone: result.data.phone || '',
|
|
|
status: result.data.status || 0
|
|
|
}
|
|
|
-
|
|
|
- // 检查是否被禁用(status=1)
|
|
|
if (userInfo.status === 1) {
|
|
|
console.log('[用户状态] 账号已被禁用,自动退出登录')
|
|
|
handleUserDisabled()
|
|
|
return null
|
|
|
}
|
|
|
-
|
|
|
setUserInfo(userInfo)
|
|
|
console.log('[刷新用户状态] 成功, status:', userInfo.status)
|
|
|
return userInfo
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
+ return getUserInfo()
|
|
|
+ }).catch(function(error) {
|
|
|
console.warn('[刷新用户状态] 失败:', error.message)
|
|
|
- }
|
|
|
- return getUserInfo()
|
|
|
+ return getUserInfo()
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 处理用户被禁用的情况
|
|
|
- */
|
|
|
var handleUserDisabled = function() {
|
|
|
- if (isShowingDisabledModal) {
|
|
|
- return // 防止重复弹窗
|
|
|
- }
|
|
|
-
|
|
|
+ if (isShowingDisabledModal) return
|
|
|
isShowingDisabledModal = true
|
|
|
- stopStatusCheck() // 停止定时检查
|
|
|
- logout() // 退出登录
|
|
|
-
|
|
|
+ stopStatusCheck()
|
|
|
+ logout()
|
|
|
uni.showModal({
|
|
|
title: '账号已禁用',
|
|
|
content: '您的账号已被禁用,如有疑问请联系客服',
|
|
|
@@ -229,39 +153,36 @@ var handleUserDisabled = function() {
|
|
|
confirmText: '我知道了',
|
|
|
success: function() {
|
|
|
isShowingDisabledModal = false
|
|
|
- // 跳转到个人中心
|
|
|
uni.switchTab({ url: '/pages/mine/mine' })
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 启动全局用户状态定时检查
|
|
|
- * 每10秒检查一次用户状态,如果被禁用则自动退出
|
|
|
- */
|
|
|
-export var startStatusCheck = function() {
|
|
|
- if (statusCheckTimer) {
|
|
|
- return // 已经在运行
|
|
|
- }
|
|
|
-
|
|
|
+var checkUserStatus = function() {
|
|
|
if (!isLoggedIn()) {
|
|
|
- return // 未登录不需要检查
|
|
|
+ stopStatusCheck()
|
|
|
+ return
|
|
|
}
|
|
|
+ getUserInfoApi().then(function(result) {
|
|
|
+ if (result.code === 200 && result.data && result.data.status === 1) {
|
|
|
+ console.log('[状态检查] 检测到账号被禁用')
|
|
|
+ handleUserDisabled()
|
|
|
+ }
|
|
|
+ }).catch(function(error) {
|
|
|
+ console.warn('[状态检查] 检查失败:', error.message)
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
+export var startStatusCheck = function() {
|
|
|
+ if (statusCheckTimer) return
|
|
|
+ if (!isLoggedIn()) return
|
|
|
console.log('[状态检查] 启动定时检查')
|
|
|
-
|
|
|
- // 立即检查一次
|
|
|
checkUserStatus()
|
|
|
-
|
|
|
- // 定时检查
|
|
|
statusCheckTimer = setInterval(function() {
|
|
|
checkUserStatus()
|
|
|
}, STATUS_CHECK_INTERVAL)
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 停止全局用户状态定时检查
|
|
|
- */
|
|
|
export var stopStatusCheck = function() {
|
|
|
if (statusCheckTimer) {
|
|
|
console.log('[状态检查] 停止定时检查')
|
|
|
@@ -270,166 +191,84 @@ export var stopStatusCheck = function() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 检查用户状态(内部方法)
|
|
|
- */
|
|
|
-var checkUserStatus = async function() {
|
|
|
- if (!isLoggedIn()) {
|
|
|
- stopStatusCheck()
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- var result = await getUserInfoApi()
|
|
|
- if (result.code === 200 && result.data) {
|
|
|
- // 检查是否被禁用(status=1)
|
|
|
- if (result.data.status === 1) {
|
|
|
- console.log('[状态检查] 检测到账号被禁用')
|
|
|
- handleUserDisabled()
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.warn('[状态检查] 检查失败:', error.message)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 检查登录状态,未登录则提示用户登录
|
|
|
- * @returns {boolean} 是否已登录
|
|
|
- */
|
|
|
export var checkLogin = function() {
|
|
|
- if (isLoggedIn()) {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- // 未登录,提示用户需要登录
|
|
|
+ if (isLoggedIn()) return true
|
|
|
uni.showModal({
|
|
|
title: '登录提示',
|
|
|
content: '此功能需要登录后使用,请点击"立即登录"按钮进行授权',
|
|
|
showCancel: false,
|
|
|
confirmText: '我知道了'
|
|
|
})
|
|
|
-
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
-/**
|
|
|
- * 第一步:微信静默登录(老用户)
|
|
|
- * 调用 wx.login() 获取 code,发送到后端检查是否为老用户
|
|
|
- *
|
|
|
- * @param {string} loginCode - 微信登录code
|
|
|
- * @returns {Promise<object>} 返回 { isSign, token?, code? }
|
|
|
- */
|
|
|
-export var wxSilentLogin = async function(loginCode) {
|
|
|
- try {
|
|
|
- console.log('[静默登录] 开始检查用户状态, code:', loginCode)
|
|
|
-
|
|
|
- var result = await wxSilentLoginApi({ loginCode: loginCode })
|
|
|
+var fetchAndSaveUserInfo = function() {
|
|
|
+ return getUserInfoApi().then(function(result) {
|
|
|
+ if (result.code === 200 && result.data) {
|
|
|
+ setUserInfo(result.data)
|
|
|
+ console.log('[用户信息] 保存成功')
|
|
|
+ }
|
|
|
+ }).catch(function(error) {
|
|
|
+ console.warn('[用户信息] 获取失败:', error)
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
+export var wxSilentLogin = function(loginCode) {
|
|
|
+ console.log('[静默登录] 开始检查用户状态, code:', loginCode)
|
|
|
+ return wxSilentLoginApi({ loginCode: loginCode }).then(function(result) {
|
|
|
console.log('[静默登录] 后端响应:', result)
|
|
|
-
|
|
|
- // 老用户直接登录成功
|
|
|
if (result.code === 200 && result.data.isSign === 'true' && result.data.token) {
|
|
|
setToken(result.data.token)
|
|
|
console.log('[静默登录] 老用户登录成功')
|
|
|
-
|
|
|
- // 获取用户信息
|
|
|
- await fetchAndSaveUserInfo()
|
|
|
-
|
|
|
- // 启动状态检查
|
|
|
- startStatusCheck()
|
|
|
+ return fetchAndSaveUserInfo().then(function() {
|
|
|
+ startStatusCheck()
|
|
|
+ return result.data
|
|
|
+ })
|
|
|
}
|
|
|
-
|
|
|
return result.data
|
|
|
- } catch (error) {
|
|
|
+ }).catch(function(error) {
|
|
|
console.error('[静默登录] 失败:', error)
|
|
|
throw error
|
|
|
- }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 第二步:手机号授权登录(新用户)
|
|
|
- * 获取手机号授权后,发送到后端验证
|
|
|
- *
|
|
|
- * @param {object} params - 包含 loginCode, phoneCode, encryptedData, iv
|
|
|
- * @returns {Promise<object>} 返回 { isSign, token?, openid?, unionid?, phoneNumber? }
|
|
|
- */
|
|
|
-export var wxPhoneLogin = async function(params) {
|
|
|
- try {
|
|
|
- console.log('[手机号登录] 开始验证手机号')
|
|
|
-
|
|
|
- var result = await wxPhoneLoginApi(params)
|
|
|
-
|
|
|
+export var wxPhoneLogin = function(params) {
|
|
|
+ console.log('[手机号登录] 开始验证手机号')
|
|
|
+ return wxPhoneLoginApi(params).then(function(result) {
|
|
|
console.log('[手机号登录] 后端响应:', result)
|
|
|
-
|
|
|
- // 已注册用户直接登录成功
|
|
|
if (result.code === 200 && result.data.isSign === 'true' && result.data.token) {
|
|
|
setToken(result.data.token)
|
|
|
console.log('[手机号登录] 已注册用户登录成功')
|
|
|
-
|
|
|
- // 获取用户信息
|
|
|
- await fetchAndSaveUserInfo()
|
|
|
-
|
|
|
- // 启动状态检查
|
|
|
- startStatusCheck()
|
|
|
+ return fetchAndSaveUserInfo().then(function() {
|
|
|
+ startStatusCheck()
|
|
|
+ return result.data
|
|
|
+ })
|
|
|
}
|
|
|
-
|
|
|
return result.data
|
|
|
- } catch (error) {
|
|
|
+ }).catch(function(error) {
|
|
|
console.error('[手机号登录] 失败:', error)
|
|
|
throw error
|
|
|
- }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 第三步:完善用户信息(首次登录)
|
|
|
- * 提交完整的用户信息完成注册
|
|
|
- *
|
|
|
- * @param {object} userInfo - 包含 openid, unionid, phoneNumber, nickname, avatarUrl
|
|
|
- * @returns {Promise<boolean>} 注册是否成功
|
|
|
- */
|
|
|
-export var wxCompleteUserInfo = async function(userInfo) {
|
|
|
- try {
|
|
|
- console.log('[完善信息] 提交用户信息')
|
|
|
-
|
|
|
- var result = await wxCompleteUserInfoApi(userInfo)
|
|
|
-
|
|
|
+export var wxCompleteUserInfo = function(userInfo) {
|
|
|
+ console.log('[完善信息] 提交用户信息')
|
|
|
+ return wxCompleteUserInfoApi(userInfo).then(function(result) {
|
|
|
console.log('[完善信息] 后端响应:', result)
|
|
|
-
|
|
|
if (result.code === 200 && result.data.token) {
|
|
|
setToken(result.data.token)
|
|
|
console.log('[完善信息] 注册成功')
|
|
|
-
|
|
|
- // 获取用户信息
|
|
|
- await fetchAndSaveUserInfo()
|
|
|
-
|
|
|
- // 启动状态检查
|
|
|
- startStatusCheck()
|
|
|
-
|
|
|
- return true
|
|
|
+ return fetchAndSaveUserInfo().then(function() {
|
|
|
+ startStatusCheck()
|
|
|
+ return true
|
|
|
+ })
|
|
|
} else {
|
|
|
throw new Error(result.message || '注册失败')
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
+ }).catch(function(error) {
|
|
|
console.error('[完善信息] 失败:', error)
|
|
|
throw error
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 获取并保存用户信息
|
|
|
- * 使用 token 调用后端接口获取完整用户信息
|
|
|
- */
|
|
|
-var fetchAndSaveUserInfo = async function() {
|
|
|
- try {
|
|
|
- var result = await getUserInfoApi()
|
|
|
- if (result.code === 200 && result.data) {
|
|
|
- setUserInfo(result.data)
|
|
|
- console.log('[用户信息] 保存成功')
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.warn('[用户信息] 获取失败:', error)
|
|
|
- }
|
|
|
+ })
|
|
|
}
|
|
|
// #endif
|