auth.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /**
  2. * 认证工具类
  3. * 用于管理用户登录状态、token存储和登录检查
  4. * 使用微信官方最新登录方式:
  5. * 1. wx.login() 获取code
  6. * 2. button open-type="chooseAvatar" 获取头像
  7. * 3. input type="nickname" 获取昵称
  8. * 4. button open-type="getPhoneNumber" 获取手机号
  9. */
  10. import { wxLogin } from './api.js'
  11. const TOKEN_KEY = 'user_token'
  12. const USER_INFO_KEY = 'user_info'
  13. /**
  14. * 保存用户token到本地存储
  15. * @param {string} token - 用户登录token
  16. */
  17. export const setToken = (token) => {
  18. uni.setStorageSync(TOKEN_KEY, token)
  19. }
  20. /**
  21. * 获取本地存储的token
  22. * @returns {string|null} token或null
  23. */
  24. export const getToken = () => {
  25. return uni.getStorageSync(TOKEN_KEY) || null
  26. }
  27. /**
  28. * 移除本地存储的token
  29. */
  30. export const removeToken = () => {
  31. uni.removeStorageSync(TOKEN_KEY)
  32. }
  33. /**
  34. * 保存用户信息到本地存储
  35. * @param {object} userInfo - 用户信息对象
  36. */
  37. export const setUserInfo = (userInfo) => {
  38. uni.setStorageSync(USER_INFO_KEY, JSON.stringify(userInfo))
  39. }
  40. /**
  41. * 获取本地存储的用户信息
  42. * @returns {object|null} 用户信息对象或null
  43. */
  44. export const getUserInfo = () => {
  45. const userInfo = uni.getStorageSync(USER_INFO_KEY)
  46. return userInfo ? JSON.parse(userInfo) : null
  47. }
  48. /**
  49. * 移除本地存储的用户信息
  50. */
  51. export const removeUserInfo = () => {
  52. uni.removeStorageSync(USER_INFO_KEY)
  53. }
  54. /**
  55. * 检查用户是否已登录
  56. * @returns {boolean} 是否已登录
  57. */
  58. export const isLoggedIn = () => {
  59. return !!getToken()
  60. }
  61. /**
  62. * 清除所有登录信息(退出登录)
  63. */
  64. export const logout = () => {
  65. removeToken()
  66. removeUserInfo()
  67. }
  68. /**
  69. * 微信静默登录
  70. * 流程:
  71. * 1. 用户点击授权手机号按钮
  72. * 2. 调用 wx.login() 获取 code
  73. * 3. 获取手机号授权 phoneCode
  74. * 4. 将 code 和 phoneCode 发送到后端
  75. * 5. 后端通过 code 获取 openid 和 unionid
  76. * 6. 后端通过 phoneCode 获取手机号和用户信息(昵称、头像等)
  77. * 7. 后端保存所有信息到数据库并返回 token
  78. *
  79. * @param {string} code - 微信登录code(通过wx.login获取)
  80. * @param {string} phoneCode - 手机号授权code(通过getPhoneNumber获取)
  81. * @returns {Promise<boolean>} 登录是否成功
  82. */
  83. export const wxAuthLogin = async (code, phoneCode) => {
  84. try {
  85. console.log('[微信登录] ========== 开始登录 ==========')
  86. console.log('[微信登录] 接收到的参数:')
  87. console.log(' - code:', code)
  88. console.log(' - phoneCode:', phoneCode)
  89. // 验证必需参数
  90. if (!code) {
  91. console.error('[微信登录] 错误:code为空!')
  92. throw new Error('微信登录code为空,请重试')
  93. }
  94. if (!phoneCode) {
  95. console.error('[微信登录] 错误:phoneCode为空!')
  96. throw new Error('手机号授权code为空,请重试')
  97. }
  98. // 构建请求参数
  99. const loginParams = {
  100. code: code, // 微信登录code,后端用于获取 openid 和 unionid
  101. phoneCode: phoneCode // 手机号授权code,后端用于获取手机号、昵称、头像等
  102. }
  103. console.log('[微信登录] 准备发送到后端的参数:', JSON.stringify(loginParams))
  104. // 调用后端登录接口
  105. const result = await wxLogin(loginParams)
  106. console.log('[微信登录] 后端响应:', result)
  107. // 保存token和用户信息
  108. if (result.code === 200 && result.data && result.data.token) {
  109. setToken(result.data.token)
  110. if (result.data.userInfo) {
  111. setUserInfo(result.data.userInfo)
  112. }
  113. console.log('[微信登录] 登录成功,token已保存')
  114. // 显示成功提示
  115. uni.showToast({
  116. title: '登录成功',
  117. icon: 'success',
  118. duration: 1500
  119. })
  120. return true
  121. } else {
  122. console.error('[微信登录] 后端返回格式错误:', result)
  123. throw new Error(result.message || '登录返回数据格式错误')
  124. }
  125. } catch (error) {
  126. console.error('[微信登录] ========== 登录失败 ==========')
  127. console.error('[微信登录] 错误详情:', error)
  128. uni.showToast({
  129. title: error.message || '登录失败,请稍后重试',
  130. icon: 'none',
  131. duration: 2000
  132. })
  133. return false
  134. }
  135. }
  136. /**
  137. * 检查登录状态,未登录则提示用户登录
  138. * @param {function} callback - 登录成功后的回调函数
  139. * @returns {boolean} 是否已登录
  140. */
  141. export const checkLogin = (callback) => {
  142. if (isLoggedIn()) {
  143. return true
  144. }
  145. // 未登录,提示用户需要登录
  146. uni.showModal({
  147. title: '登录提示',
  148. content: '此功能需要登录后使用,请点击"立即登录"按钮进行授权',
  149. showCancel: false,
  150. confirmText: '我知道了'
  151. })
  152. return false
  153. }
  154. /**
  155. * 显示需要登录的提示(用于页面遮罩层)
  156. * 返回一个标识,表示是否需要显示登录按钮
  157. */
  158. export const needLogin = () => {
  159. return !isLoggedIn()
  160. }