This commit is contained in:
yvan 2025-09-05 23:35:32 +08:00
parent dba965344a
commit 2b4a3b6f1b
7 changed files with 246 additions and 53 deletions

View File

@ -52,7 +52,11 @@
const loginRes = await new Promise((resolve, reject) => {
uni.login({
success: resolve,
fail: reject
fail: (error) => {
console.warn('微信登录失败:', error)
// rejectresolve
resolve({ code: null, error })
}
})
})

View File

@ -150,6 +150,33 @@ const executeAuthRequest = (url, data = {}, template = 'PUBLIC_AUTH', loadingTex
return uni.$u.http.post(url, data, requestConfig)
}
/**
* 执行认证请求支持不同HTTP方法
* @param {string} method HTTP方法
* @param {string} url 请求URL
* @param {Object} data 请求数据
* @param {string} template 配置模板
* @param {string} loadingText loading文本
* @param {Object} config 自定义配置
* @returns {Promise} 请求Promise
*/
const executeAuthRequestWithMethod = (method, url, data = {}, template = 'PUBLIC_AUTH', loadingText = null, config = {}) => {
const requestConfig = createAuthConfig(template, config, loadingText)
switch (method.toUpperCase()) {
case 'GET':
return uni.$u.http.get(url, requestConfig)
case 'POST':
return uni.$u.http.post(url, data, requestConfig)
case 'PUT':
return uni.$u.http.put(url, data, requestConfig)
case 'DELETE':
return uni.$u.http.delete(url, requestConfig)
default:
return uni.$u.http.post(url, data, requestConfig)
}
}
// ==================== API方法 ====================
// ==================== 用户登录相关API ====================
@ -205,6 +232,27 @@ export const wxLogin = (wxData, config = {}) => {
return executeAuthRequest('/wechat/user/mini/login', wxData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.WX_LOGIN, config)
}
/**
* 微信手机号登录
* @description 通过微信手机号授权进行登录获取用户token和信息
* @param {PhoneLoginData} phoneData 手机号登录数据对象
* @param {string} phoneData.code 微信登录code
* @param {string} phoneData.encryptedData 加密的手机号数据
* @param {string} phoneData.iv 初始向量
* @param {Object} [config={}] 自定义请求配置
* @returns {Promise<Object>} 返回登录结果包含token和用户信息
* @example
* // 微信手机号登录
* const result = await wxPhoneLogin({
* code: 'wx_login_code',
* encryptedData: 'encrypted_phone_data',
* iv: 'initial_vector'
* })
*/
export const wxPhoneLogin = (phoneData, config = {}) => {
return executeAuthRequest('/wechat/user/mini/phone-login', phoneData, 'PUBLIC_AUTH', AUTH_LOADING_TEXTS.PHONE_LOGIN, config)
}
/**
* 更新用户手机号
* @description 通过微信手机号授权更新已登录用户的手机号需要用户已登录
@ -226,6 +274,45 @@ export const updatePhoneNumber = (phoneData, config = {}) => {
return executeAuthRequest('/user/wechat/mini/phone-update', phoneData, 'AUTHENTICATED_SESSION', AUTH_LOADING_TEXTS.PHONE_VERIFY, config)
}
/**
* 获取用户信息
* @description 获取当前登录用户的详细信息
* @param {Object} [config={}] 自定义请求配置
* @returns {Promise<Object>} 返回用户信息
* @example
* // 获取用户信息
* const userInfo = await getUserInfo()
*
* @since 2.0.0 微信小程序用户信息接口
*/
export const getUserInfo = (config = {}) => {
return executeAuthRequestWithMethod('GET', '/user/wechat/mini/userinfo', {}, 'AUTHENTICATED_SESSION', '获取用户信息中...', config)
}
/**
* 更新用户信息
* @description 更新当前登录用户的信息
* @param {Object} userData 用户数据对象
* @param {string} [userData.nickname] 用户昵称
* @param {string} [userData.avatar] 用户头像URL
* @param {number} [userData.gender] 性别0-未知1-2-
* @param {string} [userData.city] 城市
* @param {string} [userData.province] 省份
* @param {string} [userData.country] 国家
* @param {Object} [config={}] 自定义请求配置
* @returns {Promise<Object>} 返回更新结果
* @example
* // 更新用户昵称
* const result = await updateUserInfo({
* nickname: '新昵称'
* })
*
* @since 2.0.0 微信小程序用户信息更新接口
*/
export const updateUserInfo = (userData, config = {}) => {
return executeAuthRequestWithMethod('PUT', '/user/wechat/mini/userinfo', userData, 'AUTHENTICATED_SESSION', '更新用户信息中...', config)
}
// ==================== 用户注册相关API ====================
/**
@ -391,5 +478,6 @@ export const AUTH_CONFIG = {
*/
export const AUTH_UTILS = {
createAuthConfig,
executeAuthRequest
executeAuthRequest,
executeAuthRequestWithMethod
}

View File

@ -230,6 +230,27 @@ export const getUserInfo = (config = {}) => {
return executeGetRequest('/user/info', {}, 'AUTHENTICATED_QUERY_WITH_LOADING', config)
}
/**
* 获取微信用户信息
* @description 获取当前登录用户的微信相关信息包括微信昵称头像等
* @param {Object} [config={}] 自定义请求配置
* @param {Object} [config.custom] 自定义请求选项
* @param {boolean} [config.custom.loading] 是否显示loading默认false
* @param {boolean} [config.custom.toast] 是否显示错误提示默认true
* @returns {Promise<Object>} 返回微信用户信息对象
* @example
* // 基本用法
* const wxUserInfo = await getWxUserInfo()
*
* // 自定义配置
* const wxUserInfo = await getWxUserInfo({
* custom: { loading: true }
* })
*/
export const getWxUserInfo = (config = {}) => {
return executeGetRequest('/user/wechat/mini/userinfo', {}, 'AUTHENTICATED_QUERY', config)
}
/**
* 更新用户基本信息
* @description 更新用户的基本信息如昵称头像个人简介等

View File

@ -65,7 +65,10 @@ export const NO_AUTH_APIS = [
* 这些接口在调用时如果未登录会自动跳转到登录页面
*/
export const AUTH_REQUIRED_APIS = [
// 微信小程序用户相关接口
'/user/wechat/mini/userinfo', // 获取用户信息
'/user/wechat/mini/phone-update', // 更新手机号
'/user/wechat/mini/check-unionid', // 检查UnionID
]
/**

View File

@ -7,6 +7,8 @@ import { HTTP_CONFIG, checkApiAuth, AUTH_REQUIRED_APIS } from './config.js'
* 清理认证数据
*/
function clearAuthData() {
console.log('HTTP拦截器: 清理认证数据被调用')
console.trace('调用堆栈:')
uni.removeStorageSync(HTTP_CONFIG.storageKeys.token)
uni.removeStorageSync(HTTP_CONFIG.storageKeys.refreshToken)
uni.removeStorageSync(HTTP_CONFIG.storageKeys.userInfo)
@ -188,8 +190,8 @@ export default (vm) => {
// 统一的响应数据处理
if (data.code !== undefined) {
// 如果服务端返回的状态码不等于200则reject()
if (data.code !== 200) {
// 如果服务端返回的状态码不等于0成功则reject()
if (data.code !== 0) {
// 如果没有显式定义custom的toast参数为false的话默认对报错进行toast弹出提示
if (custom?.toast !== false) {
uni.$u.toast(data.message || '请求失败')

View File

@ -62,7 +62,7 @@
<script>
import { ref } from 'vue'
import { updatePhoneNumber } from '@/http/api/auth.js'
import { wxPhoneLogin } from '@/http/api/auth.js'
import {
savePhoneAuthData,
markPhoneSkipped,
@ -164,53 +164,48 @@ export default {
}
}
// API
// API
const phoneData = {
code: loginCode,
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
}
console.log(phoneData)
console.log('准备调用手机号更新API:', {
hasEncryptedData: !!phoneData.encryptedData,
hasIv: !!phoneData.iv,
apiUrl: '/user/wechat/mini/phone-update'
})
// API
const phoneNumber = await updatePhoneNumber({
encryptedData: phoneData.encryptedData,
iv: phoneData.iv
}, {
// API
const result = await wxPhoneLogin(phoneData, {
custom: {
loading: false, // 使loading
catch: true // catch
}
})
console.log('手机号更新成功:', phoneNumber)
//
if (result && result.token) {
//
savePhoneAuthData({
token: result.token,
refreshToken: result.refreshToken,
userInfo: result.userInfo || result
})
//
const userInfo = authStore.userInfo
if (userInfo) {
userInfo.phone = phoneNumber
authStore.setUserInfo(userInfo)
uni.showToast({
title: '手机号授权成功',
icon: 'success',
duration: 1500
})
//
setTimeout(() => {
uni.navigateTo({
url: '/pages/profile/user-info?mode=setup'
})
}, 1500)
} else {
throw new Error('手机号登录失败')
}
uni.showToast({
title: '手机号更新成功',
icon: 'success'
})
//
setTimeout(() => {
uni.navigateBack()
}, 1500)
} catch (error) {
console.error('手机号更新失败:', error)
console.error('手机号授权失败:', error)
handleError(error)
} finally {
authorizing.value = false

View File

@ -2,7 +2,7 @@
<view class="profile-container page-container-unified">
<!-- 用户信息卡片 -->
<view class="user-info-card">
<view class="user-avatar-section" :class="{ 'logged-in': userInfo.nickName }" @click="handleUserAction">
<view class="user-avatar-section" :class="{ 'logged-in': isLoggedIn }" @click="handleUserAction">
<view class="avatar-wrapper">
<u-avatar
:src="userInfo.avatarUrl || ''"
@ -13,19 +13,19 @@
color="white"
font-size="40"
></u-avatar>
<view class="online-status" v-if="userInfo.nickName">
<view class="online-status" v-if="isLoggedIn">
<view class="status-dot"></view>
</view>
<!-- 登录提示图标仅在未登录时显示 -->
<view class="login-hint" v-if="!userInfo.nickName">
<view class="login-hint" v-if="!isLoggedIn">
<text class="hint-icon">👋</text>
</view>
</view>
</view>
<view class="user-info-section">
<view class="user-name">{{ userInfo.nickName || '点击头像登录' }}</view>
<view class="user-status">{{ userInfo.nickName ? '已登录' : '未登录' }}</view>
<view class="login-days" v-if="userInfo.nickName">已使用 {{ loginDays }} </view>
<view class="user-name">{{ isLoggedIn ? (userInfo.nickName || '用户') : '点击头像登录' }}</view>
<view class="user-status">{{ isLoggedIn ? '已登录' : '未登录' }}</view>
<view class="login-days" v-if="isLoggedIn">已使用 {{ loginDays }} </view>
</view>
</view>
@ -143,7 +143,7 @@
<script>
import { reactive, ref, onMounted, computed } from 'vue'
import { uploadImage } from '@/http/api/common.js'
import { updateUserInfo } from '@/http/api/profile.js'
import { getUserInfo, getWxUserInfo, updateUserInfo } from '@/http/api/profile.js'
export default {
name: 'ProfilePage',
@ -156,6 +156,11 @@ export default {
const loginDays = ref(0)
//
const isLoggedIn = computed(() => {
return !!uni.getStorageSync('token')
})
@ -182,12 +187,69 @@ export default {
//
const initPage = () => {
loadUserInfo()
loadUserStats()
const token = uni.getStorageSync('token')
if (token) {
// token
loadUserInfo()
loadUserStats()
} else {
// token
const savedUserInfo = uni.getStorageSync('userInfo')
if (savedUserInfo) {
userInfo.value = savedUserInfo
}
}
}
const loadUserInfo = () => {
//
const loadUserInfo = async () => {
const token = uni.getStorageSync('token')
if (!token) {
return
}
try {
//
const wxUserInfo = await getWxUserInfo({
custom: {
loading: false,
toast: false
}
})
if (wxUserInfo) {
userInfo.value = wxUserInfo
//
uni.setStorageSync('userInfo', wxUserInfo)
uni.setStorageSync('wxUserInfo', wxUserInfo)
calculateLoginDays()
return
}
} catch (error) {
console.log('获取微信用户信息失败,尝试获取基本用户信息:', error)
//
try {
const apiUserInfo = await getUserInfo({
custom: {
loading: false,
toast: false
}
})
if (apiUserInfo) {
userInfo.value = apiUserInfo
//
uni.setStorageSync('userInfo', apiUserInfo)
calculateLoginDays()
return
}
} catch (basicError) {
console.log('获取基本用户信息也失败,使用本地缓存:', basicError)
}
}
// API
const savedUserInfo = uni.getStorageSync('userInfo')
if (savedUserInfo) {
userInfo.value = savedUserInfo
@ -267,9 +329,16 @@ export default {
})
}
const handleUserAction = () => {
// API
navigateTo('/pages/profile/user-info')
const handleUserAction = async () => {
const token = uni.getStorageSync('token')
if (token) {
// token
navigateTo('/pages/profile/user-info')
} else {
// token
navigateTo('/pages/login/login')
}
}
//
@ -323,11 +392,13 @@ export default {
//
const refreshData = () => {
// initPage
loadUserStats()
}
//
const onShow = () => {
// loadUserInfo
refreshData()
}
@ -365,6 +436,7 @@ export default {
return {
userInfo,
loginDays,
isLoggedIn,
petStats,
familyStats,
adoptionStats,
@ -384,11 +456,19 @@ export default {
//
onShow() {
this.onShow()
//
const token = uni.getStorageSync('token')
if (token) {
// token
this.loadUserInfo()
}
this.refreshData()
},
onPullDownRefresh() {
this.onPullDownRefresh()
this.refreshData()
uni.stopPullDownRefresh()
}
}
</script>