1
This commit is contained in:
+9
-11
@@ -202,30 +202,28 @@ export const userLogin = (loginData, config = {}) => {
|
||||
* })
|
||||
*/
|
||||
export const wxLogin = (wxData, config = {}) => {
|
||||
return executeAuthRequest('/auth/wx-login', wxData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.WX_LOGIN, config)
|
||||
return executeAuthRequest('/wechat/user/mini/login', wxData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.WX_LOGIN, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信手机号授权登录
|
||||
* @description 使用微信手机号授权进行登录认证,适用于小程序环境
|
||||
* 更新用户手机号
|
||||
* @description 通过微信手机号授权更新已登录用户的手机号,需要用户已登录
|
||||
* @param {PhoneAuthData} phoneData 手机号授权数据对象
|
||||
* @param {string} phoneData.code 微信登录凭证code
|
||||
* @param {string} phoneData.encryptedData 加密的手机号数据
|
||||
* @param {string} phoneData.iv 初始向量
|
||||
* @param {Object} [config={}] 自定义请求配置
|
||||
* @returns {Promise<AuthResult>} 返回认证结果,包含token和用户信息
|
||||
* @returns {Promise<string>} 返回解密后的手机号
|
||||
* @example
|
||||
* // 微信手机号登录
|
||||
* const result = await wxPhoneLogin({
|
||||
* code: 'wx_code_123',
|
||||
* // 更新用户手机号
|
||||
* const phoneNumber = await updatePhoneNumber({
|
||||
* encryptedData: 'encrypted_phone_data',
|
||||
* iv: 'initial_vector'
|
||||
* })
|
||||
*
|
||||
* @since 2.0.0 新增的登录流程重构功能
|
||||
* @since 2.0.0 重构为手机号更新功能
|
||||
*/
|
||||
export const wxPhoneLogin = (phoneData, config = {}) => {
|
||||
return executeAuthRequest('/auth/wx-phone-login', phoneData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.PHONE_VERIFY, config)
|
||||
export const updatePhoneNumber = (phoneData, config = {}) => {
|
||||
return executeAuthRequest('/user/wechat/mini/phone-update', phoneData, 'AUTHENTICATED_SESSION', AUTH_LOADING_TEXTS.PHONE_VERIFY, config)
|
||||
}
|
||||
|
||||
// ==================== 用户注册相关API ====================
|
||||
|
||||
+27
-50
@@ -6,7 +6,7 @@
|
||||
const ENV_CONFIG = {
|
||||
// 开发环境
|
||||
development: {
|
||||
baseURL: 'https://dev-api.pet-ai.com',
|
||||
baseURL: 'http://localhost:8888',
|
||||
timeout: 30000
|
||||
},
|
||||
// 测试环境
|
||||
@@ -57,32 +57,7 @@ export const HTTP_CONFIG = {
|
||||
*/
|
||||
export const NO_AUTH_APIS = [
|
||||
// 用户认证相关
|
||||
'/auth/login',
|
||||
'/auth/register',
|
||||
'/auth/wx-login',
|
||||
'/auth/wx-phone-login', // 微信手机号登录
|
||||
'/auth/refresh',
|
||||
'/auth/reset-password', // 重置密码
|
||||
|
||||
// 短信验证相关
|
||||
'/sms/send', // 发送短信验证码
|
||||
'/sms/verify', // 验证短信验证码
|
||||
|
||||
// 公开浏览的接口
|
||||
'/ai/knowledge', // AI知识库
|
||||
'/adoption/pets', // 浏览待领养宠物
|
||||
'/adoption/pets/search', // 搜索宠物
|
||||
'/adoption/pets/filter', // 筛选宠物
|
||||
'/adoption/organizations', // 领养机构列表
|
||||
'/reviews', // 查看评价
|
||||
'/reviews/*', // 查看特定对象的评价
|
||||
|
||||
// 系统相关
|
||||
'/system/config', // 系统配置
|
||||
'/system/version', // 版本信息
|
||||
'/system/check-update', // 检查更新
|
||||
'/common/regions', // 地区数据
|
||||
'/common/upload-config' // 上传配置
|
||||
'/wechat/user/mini/login', // 微信小程序登录
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -90,30 +65,7 @@ export const NO_AUTH_APIS = [
|
||||
* 这些接口在调用时如果未登录会自动跳转到登录页面
|
||||
*/
|
||||
export const AUTH_REQUIRED_APIS = [
|
||||
// 用户个人信息相关
|
||||
'/profile/info', // 获取用户信息
|
||||
'/profile/update', // 更新用户信息
|
||||
'/profile/avatar', // 更新头像
|
||||
'/profile/stats', // 用户统计信息
|
||||
|
||||
// 宠物管理相关
|
||||
'/pets/create', // 创建宠物
|
||||
'/pets/update', // 更新宠物信息
|
||||
'/pets/delete', // 删除宠物
|
||||
'/pets/my', // 我的宠物列表
|
||||
|
||||
// 领养相关
|
||||
'/adoption/apply', // 申请领养
|
||||
'/adoption/my-applications', // 我的申请
|
||||
'/adoption/my-pets', // 我发布的宠物
|
||||
|
||||
// 收藏和关注
|
||||
'/favorites/*', // 收藏相关
|
||||
'/follows/*', // 关注相关
|
||||
|
||||
// 消息和通知
|
||||
'/messages/*', // 消息相关
|
||||
'/notifications/*' // 通知相关
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -142,6 +94,31 @@ export function checkApiAuth(url) {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查接口是否需要强制登录
|
||||
* @param {String} url 接口URL
|
||||
* @returns {Boolean} 是否需要强制登录
|
||||
*/
|
||||
export function checkAuthRequiredApi(url) {
|
||||
// 移除查询参数,只保留路径
|
||||
const path = url.split('?')[0]
|
||||
|
||||
// 检查是否在需要强制登录的列表中
|
||||
for (const authApi of AUTH_REQUIRED_APIS) {
|
||||
// 支持通配符匹配
|
||||
if (authApi.includes('*')) {
|
||||
const regex = new RegExp('^' + authApi.replace(/\*/g, '.*') + '$')
|
||||
if (regex.test(path)) {
|
||||
return true
|
||||
}
|
||||
} else if (path === authApi || path.startsWith(authApi + '/')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加不需要鉴权的接口
|
||||
* @param {String|Array} apis 接口路径或接口路径数组
|
||||
|
||||
+133
-22
@@ -1,7 +1,109 @@
|
||||
// HTTP请求配置和拦截器
|
||||
// 基于uView-next的luch-request库实现
|
||||
|
||||
import { HTTP_CONFIG, checkApiAuth } from './config.js'
|
||||
import { HTTP_CONFIG, checkApiAuth, AUTH_REQUIRED_APIS } from './config.js'
|
||||
|
||||
/**
|
||||
* 清理认证数据
|
||||
*/
|
||||
function clearAuthData() {
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
|
||||
uni.removeStorageSync('loginStep')
|
||||
uni.removeStorageSync('wxLoginCode')
|
||||
uni.removeStorageSync('wxUserInfo')
|
||||
uni.removeStorageSync('loginDate')
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查接口是否需要强制登录
|
||||
* @param {String} url 接口URL
|
||||
* @returns {Boolean} 是否需要强制登录
|
||||
*/
|
||||
function checkAuthRequiredApi(url) {
|
||||
// 移除查询参数,只保留路径
|
||||
const path = url.split('?')[0]
|
||||
|
||||
// 检查是否在需要强制登录的列表中
|
||||
for (const authApi of AUTH_REQUIRED_APIS) {
|
||||
// 支持通配符匹配
|
||||
if (authApi.includes('*')) {
|
||||
const regex = new RegExp('^' + authApi.replace(/\*/g, '.*') + '$')
|
||||
if (regex.test(path)) {
|
||||
return true
|
||||
}
|
||||
} else if (path === authApi || path.startsWith(authApi + '/')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否已完成登录
|
||||
* @returns {Boolean} 是否已完成登录
|
||||
*/
|
||||
function isUserLoggedIn() {
|
||||
const token = uni.getStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
const loginStep = uni.getStorageSync('loginStep')
|
||||
|
||||
// 检查是否有有效的token和完成的登录流程
|
||||
return !!(token && (loginStep === 'profile_completed' || loginStep === 'phone_authed'))
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试自动登录
|
||||
* @returns {Promise<Boolean>} 是否登录成功
|
||||
*/
|
||||
async function tryAutoLogin() {
|
||||
try {
|
||||
return await autoLogin()
|
||||
} catch (error) {
|
||||
console.error('自动登录失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理需要鉴权的情况
|
||||
*/
|
||||
function handleAuthRequired() {
|
||||
const loginStep = uni.getStorageSync('loginStep')
|
||||
|
||||
// 根据当前登录状态决定跳转页面
|
||||
let targetPage = '/pages/login/login'
|
||||
let toastMessage = '请先登录'
|
||||
|
||||
switch (loginStep) {
|
||||
case 'wx_logged':
|
||||
targetPage = '/pages/auth/phone-auth'
|
||||
toastMessage = '请完成手机号授权'
|
||||
break
|
||||
case 'phone_authed':
|
||||
case 'phone_skipped':
|
||||
targetPage = '/pages/profile/user-info?mode=setup'
|
||||
toastMessage = '请完善个人信息'
|
||||
break
|
||||
default:
|
||||
targetPage = '/pages/login/login'
|
||||
toastMessage = '请先登录'
|
||||
}
|
||||
|
||||
// 显示提示并跳转
|
||||
uni.showToast({
|
||||
title: toastMessage,
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({ url: targetPage }).catch(() => {
|
||||
uni.reLaunch({ url: targetPage })
|
||||
})
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化HTTP配置
|
||||
@@ -24,20 +126,34 @@ export default (vm) => {
|
||||
config.data = config.data || {}
|
||||
config.custom = config.custom || {}
|
||||
|
||||
|
||||
|
||||
// 自动检查接口是否需要鉴权(如果没有明确指定)
|
||||
if (config.custom.auth === undefined) {
|
||||
config.custom.auth = checkApiAuth(config.url)
|
||||
}
|
||||
|
||||
// 根据custom参数中配置的是否需要token,添加对应的请求头
|
||||
if (config.custom.auth) {
|
||||
// 从本地存储获取token
|
||||
// 检查是否为需要强制登录的接口
|
||||
const isAuthRequiredApi = checkAuthRequiredApi(config.url)
|
||||
|
||||
// 如果是需要强制登录的接口,检查登录状态
|
||||
if (isAuthRequiredApi) {
|
||||
if (!isUserLoggedIn()) {
|
||||
console.log('访问需要鉴权的接口但未完成登录,跳转到登录流程:', config.url)
|
||||
handleAuthRequired()
|
||||
return Promise.reject({
|
||||
message: '需要登录',
|
||||
code: 'AUTH_REQUIRED',
|
||||
url: config.url
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 添加Authorization请求头
|
||||
if (config.custom.auth !== false) {
|
||||
const token = uni.getStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
if (token) {
|
||||
config.header.Authorization = `Bearer ${token}`
|
||||
} else {
|
||||
// 如果需要token但没有token,可以跳转到登录页
|
||||
console.warn('需要token但未找到,请先登录')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +168,11 @@ export default (vm) => {
|
||||
return config
|
||||
}, config => {
|
||||
// 请求错误处理
|
||||
// 如果是AUTH_REQUIRED错误,不显示loading
|
||||
if (config.code === 'AUTH_REQUIRED') {
|
||||
// 不显示loading,因为会跳转页面
|
||||
return Promise.reject(config)
|
||||
}
|
||||
return Promise.reject(config)
|
||||
})
|
||||
|
||||
@@ -76,13 +197,9 @@ export default (vm) => {
|
||||
|
||||
// 特殊状态码处理
|
||||
if (data.code === 401) {
|
||||
// token过期,清除本地token并跳转到登录页
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
|
||||
uni.reLaunch({
|
||||
url: HTTP_CONFIG.loginPage
|
||||
})
|
||||
// token过期,清除本地认证信息并跳转到登录流程
|
||||
clearAuthData()
|
||||
handleAuthRequired()
|
||||
return Promise.reject(data)
|
||||
}
|
||||
|
||||
@@ -116,14 +233,8 @@ export default (vm) => {
|
||||
break
|
||||
case 401:
|
||||
errorMessage = '未授权,请重新登录'
|
||||
// 清除本地认证信息
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
|
||||
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
|
||||
// 跳转到登录页
|
||||
uni.reLaunch({
|
||||
url: HTTP_CONFIG.loginPage
|
||||
})
|
||||
clearAuthData()
|
||||
handleAuthRequired()
|
||||
break
|
||||
case 403:
|
||||
errorMessage = '拒绝访问'
|
||||
|
||||
Reference in New Issue
Block a user