Browse Source

修复 goods-detail 页面登录功能

- 在 goods-detail 页面实现完整的登录处理逻辑
- 登录成功后不跳转页面,保持用户体验流畅
- 修正登录弹窗的事件绑定(onPhoneNumberResult -> onGetPhoneNumber)
- 清理大图片文件解决包大小超限问题
- 登录成功后自动刷新收藏状态并触发全局事件通知
pull/3/head
徐飞洋 2 months ago
parent
commit
785a93e0aa
  1. BIN
      images/1.jpg
  2. BIN
      images/2.jpg
  3. BIN
      images/3.jpg
  4. BIN
      images/4.jpg
  5. 318
      pages/goods-detail/goods-detail.js
  6. 2
      pages/goods-detail/goods-detail.wxml

BIN
images/1.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

BIN
images/2.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

BIN
images/3.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

BIN
images/4.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

318
pages/goods-detail/goods-detail.js

@ -1024,6 +1024,324 @@ Page({
} }
}, },
// 处理登录授权
async onGetPhoneNumber(e) {
console.log('收到手机号授权事件:', e.detail);
// 关闭手机号授权弹窗
this.setData({ showOneKeyLoginModal: false })
// 用户点击拒绝授权
if (e.detail.errMsg === 'getPhoneNumber:fail user deny') {
wx.showToast({
title: '需要授权手机号才能使用',
icon: 'none',
duration: 2000
})
return
}
// 处理没有权限的情况
if (e.detail.errMsg === 'getPhoneNumber:fail no permission') {
wx.showToast({
title: '当前环境无法获取手机号权限',
icon: 'none',
duration: 3000
})
return
}
// 检查是否已经登录,避免重复授权
const existingOpenid = wx.getStorageSync('openid')
const existingUserId = wx.getStorageSync('userId')
const existingUserInfo = wx.getStorageSync('userInfo')
if (existingOpenid && existingUserId && existingUserInfo && existingUserInfo.phoneNumber) {
console.log('用户已登录且手机号有效,登录流程已完成')
wx.showToast({
title: '您已登录',
icon: 'success',
duration: 1500
})
return
}
wx.showLoading({
title: '登录中...',
mask: true
})
try {
if (e.detail.errMsg === 'getPhoneNumber:ok') {
// 用户同意授权,实际处理授权流程
console.log('用户同意授权获取手机号')
// 1. 先执行微信登录获取code
const loginRes = await new Promise((resolve, reject) => {
wx.login({
success: resolve,
fail: reject
})
})
if (!loginRes.code) {
throw new Error('获取登录code失败')
}
console.log('获取登录code成功:', loginRes.code)
// 2. 使用code换取openid
const openidRes = await API.getOpenid(loginRes.code)
// 改进错误处理逻辑,更宽容地处理服务器返回格式
let openid = null;
let userId = null;
console.log('openidRes完整响应:', JSON.stringify(openidRes));
if (openidRes && typeof openidRes === 'object') {
// 适配服务器返回格式:{success: true, code: 200, message: '获取openid成功', data: {openid, userId}}
if (openidRes.data && typeof openidRes.data === 'object') {
console.log('识别到标准服务器返回格式,从data字段提取信息');
openid = openidRes.data.openid || openidRes.data.OpenID || null;
userId = openidRes.data.userId || null;
} else {
// 尝试从响应对象中直接提取openid
console.log('尝试从根对象直接提取openid');
openid = openidRes.openid || openidRes.OpenID || null;
userId = openidRes.userId || null;
}
}
if (!openid) {
console.error('无法从服务器响应中提取openid,完整响应:', JSON.stringify(openidRes));
throw new Error(`获取openid失败: 服务器返回数据格式可能不符合预期`);
}
console.log('获取openid成功:', openid)
// 3. 存储openid和session_key
wx.setStorageSync('openid', openid)
// 从服务器返回中获取session_key
if (openidRes && openidRes.session_key) {
wx.setStorageSync('sessionKey', openidRes.session_key)
} else if (openidRes && openidRes.data && openidRes.data.session_key) {
wx.setStorageSync('sessionKey', openidRes.data.session_key)
}
// 优先使用从服务器响应data字段中提取的userId
if (userId) {
wx.setStorageSync('userId', userId)
console.log('使用从服务器data字段提取的userId:', userId)
} else if (openidRes && openidRes.userId) {
wx.setStorageSync('userId', openidRes.userId)
console.log('使用服务器根对象中的userId:', openidRes.userId)
} else {
// 生成临时userId
const tempUserId = 'user_' + Date.now()
wx.setStorageSync('userId', tempUserId)
console.log('生成临时userId:', tempUserId)
}
// 4. 上传手机号加密数据到服务器解密
const phoneData = {
...e.detail,
openid: openid
}
console.log('准备上传手机号加密数据到服务器')
const phoneRes = await API.uploadPhoneNumberData(phoneData)
// 改进手机号解密结果的处理逻辑
if (!phoneRes || (!phoneRes.success && !phoneRes.phoneNumber)) {
// 如果服务器返回格式不标准但包含手机号,也接受
if (phoneRes && phoneRes.phoneNumber) {
console.warn('服务器返回格式可能不符合预期,但成功获取手机号');
} else {
throw new Error('获取手机号失败: ' + (phoneRes && phoneRes.message ? phoneRes.message : '未知错误'))
}
}
// 检查是否有手机号冲突
const hasPhoneConflict = phoneRes.phoneNumberConflict || false
const isNewPhone = phoneRes.isNewPhone || true
const phoneNumber = phoneRes.phoneNumber || null
// 如果有手机号冲突且没有返回手机号,使用实际返回的手机号
const finalPhoneNumber = phoneNumber
console.log('手机号解密结果:', {
phoneNumber: finalPhoneNumber,
hasPhoneConflict: hasPhoneConflict,
isNewPhone: isNewPhone
})
// 5. 获取用户微信名称和头像
let userProfile = null;
try {
userProfile = await new Promise((resolve, reject) => {
wx.getUserProfile({
desc: '用于完善会员资料',
success: resolve,
fail: reject
});
});
console.log('获取用户信息成功:', userProfile);
} catch (err) {
console.warn('获取用户信息失败:', err);
// 如果获取失败,使用默认值
}
// 6. 创建用户信息
const tempUserInfo = {
name: userProfile ? (userProfile.userInfo.name || userProfile.userInfo.nickName) : '微信用户',
// 获取微信头像失败时使用微信默认头像
avatarUrl: userProfile ? userProfile.userInfo.avatarUrl : 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0',
gender: userProfile ? userProfile.userInfo.gender : 0,
country: userProfile ? userProfile.userInfo.country : '',
province: userProfile ? userProfile.userInfo.province : '',
city: userProfile ? userProfile.userInfo.city : '',
language: userProfile ? userProfile.userInfo.language : 'zh_CN',
phoneNumber: finalPhoneNumber
}
// 7. 保存用户信息
const storedUserId = wx.getStorageSync('userId')
const users = wx.getStorageSync('users') || {}
const currentUserType = users[storedUserId] && users[storedUserId].type ? users[storedUserId].type : 'buyer'
console.log('用户身份类型:', currentUserType)
// 8. 保存用户信息到本地和服务器
console.log('开始保存用户信息...')
await this.saveUserInfo(tempUserInfo, currentUserType)
console.log('用户信息保存完成')
wx.hideLoading()
// 根据服务器返回的结果显示不同的提示
if (phoneRes && phoneRes.phoneNumberConflict) {
wx.showModal({
title: '登录成功',
content: '您的手机号已被其他账号绑定',
showCancel: false,
confirmText: '我知道了',
success(res) {
if (res.confirm) {
console.log('用户点击了我知道了');
}
}
});
}
// 显示登录成功提示
wx.showToast({
title: '登录成功',
icon: 'success',
duration: 1500
})
// 登录成功后,重新加载商品详情以刷新收藏状态
const productId = String(this.data.goodsDetail.id || this.data.goodsDetail.productId);
this.loadGoodsFavoriteStatus(productId);
// 触发全局事件,通知其他页面登录状态已更改
const app = getApp();
if (app && app.eventBus) {
app.eventBus.emit('userLoginStatusChanged', {
isLoggedIn: true,
userId: storedUserId,
phoneNumber: finalPhoneNumber
});
}
} else {
// 用户拒绝授权或其他情况
console.log('手机号授权失败:', e.detail.errMsg)
// 不再抛出错误,而是显示友好的提示
wx.hideLoading()
wx.showToast({
title: '需要授权手机号才能使用',
icon: 'none',
duration: 2000
})
return
}
} catch (error) {
wx.hideLoading()
console.error('登录过程中发生错误:', error)
// 更具体的错误提示
let errorMsg = '登录失败,请重试'
if (error.message.includes('网络')) {
errorMsg = '网络连接失败,请检查网络后重试'
} else if (error.message.includes('服务器')) {
errorMsg = '服务器连接失败,请稍后重试'
}
wx.showToast({
title: errorMsg,
icon: 'none',
duration: 3000
})
// 清除可能已经保存的不完整信息
try {
wx.removeStorageSync('openid')
wx.removeStorageSync('sessionKey')
wx.removeStorageSync('userId')
} catch (e) {
console.error('清除临时登录信息失败:', e)
}
}
},
// 保存用户信息的方法
async saveUserInfo(userInfo, userType) {
return new Promise((resolve, reject) => {
// 1. 保存到本地users对象
const users = wx.getStorageSync('users') || {};
const userId = wx.getStorageSync('userId');
if (!userId) {
reject(new Error('用户ID不存在'));
return;
}
// 合并用户信息
users[userId] = {
...users[userId],
...userInfo,
type: userType || 'buyer',
updatedAt: new Date().toISOString()
};
wx.setStorageSync('users', users);
// 2. 保存到全局userInfo对象
wx.setStorageSync('userInfo', {
...userInfo,
userType: userType || 'buyer'
});
// 3. 上传到服务器
const API = require('../../utils/api.js');
API.uploadUserInfo({
userId: userId,
...userInfo,
type: userType || 'buyer'
}).then(res => {
console.log('用户信息上传成功:', res);
resolve(res);
}).catch(err => {
console.error('用户信息上传失败:', err);
// 即使服务器上传失败,也继续流程,只在本地保存
resolve({ success: false, message: '本地保存成功,服务器同步失败' });
});
});
},
// 返回上一页 // 返回上一页
goBack() { goBack() {
wx.navigateBack(); wx.navigateBack();

2
pages/goods-detail/goods-detail.wxml

@ -145,7 +145,7 @@
<button <button
class="auth-primary-button" class="auth-primary-button"
open-type="getPhoneNumber" open-type="getPhoneNumber"
bindgetphonenumber="onPhoneNumberResult" bindgetphonenumber="onGetPhoneNumber"
> >
授权手机号 授权手机号
</button> </button>

Loading…
Cancel
Save