From b6733d27d2fee46eb6bec22336c0d00e4dd880ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?= <15778543+xufeiyang6017@user.noreply.gitee.com> Date: Wed, 28 Jan 2026 17:24:01 +0800 Subject: [PATCH] Add login verification and partnerstatus check for evaluate2/one page --- pages/evaluate2/one.js | 347 ++++++++++++++++++++++++++++++++++++++- pages/evaluate2/one.wxml | 23 +++ pages/evaluate2/one.wxss | 92 +++++++++++ 3 files changed, 461 insertions(+), 1 deletion(-) diff --git a/pages/evaluate2/one.js b/pages/evaluate2/one.js index 47fceb9..16cdbb4 100644 --- a/pages/evaluate2/one.js +++ b/pages/evaluate2/one.js @@ -5,7 +5,8 @@ Page({ loading: false, error: '', categories: [], - selectedCategory: '' + selectedCategory: '', + showOneKeyLoginModal: false // 是否显示登录弹窗 }, onLoad(options) { let productName = ''; @@ -455,9 +456,353 @@ Page({ const category = e.currentTarget.dataset.category; console.log('选择分类:', category); + // 检查用户登录状态 + const openid = wx.getStorageSync('openid'); + const userId = wx.getStorageSync('userId'); + + if (!openid || !userId) { + // 用户未登录,显示登录弹窗 + console.log('用户未登录,显示登录弹窗'); + this.setData({ + showOneKeyLoginModal: true + }); + return; + } + + // 检查用户合作状态 + const userInfo = wx.getStorageSync('userInfo') || {}; + const partnerStatus = userInfo.partnerstatus || ''; + + if (partnerStatus !== 'approved') { + // 合作状态未批准,显示提示 + wx.showModal({ + title: '提示', + content: '需要入住成功才能查看', + confirmText: '立即入驻', + success: function(res) { + if (res.confirm) { + wx.navigateTo({ + url: '/pages/profile/authentication/index' + }); + } + } + }); + return; + } + // 跳转到商品列表页面,并传递分类参数 wx.redirectTo({ url: `/pages/evaluate2/product-list?category=${encodeURIComponent(category)}` }); + }, + + // 关闭登录弹窗 + closeOneKeyLoginModal() { + this.setData({ + showOneKeyLoginModal: false + }); + }, + + // 处理登录授权 + 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 API = require('../../utils/api'); + 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('用户点击了我知道了'); + } + } + }); + } + + // 1. 登录成功提示 + wx.showToast({ + title: '登录成功', + icon: 'success', + duration: 1500 + }); + + // 2. 从服务器获取最新用户信息 + const userInfoRes = await API.getUserInfo(openid); + + // 3. 获取服务器返回的partnerstatus + const serverUserInfo = userInfoRes.data; + const partnerStatus = serverUserInfo.partnerstatus || 'pending'; + + // 4. 更新本地缓存 + const localUserInfo = wx.getStorageSync('userInfo') || {}; + const updatedUserInfo = { + ...localUserInfo, + partnerstatus: partnerStatus + }; + wx.setStorageSync('userInfo', updatedUserInfo); + + // 5. 检查partnerstatus值 + if (partnerStatus !== 'approved') { + // 显示入驻提示 + setTimeout(() => { + wx.showModal({ + title: '提示', + content: '需要入住成功才能查看', + confirmText: '立即入驻', + success: function(res) { + if (res.confirm) { + wx.navigateTo({ + url: '/pages/profile/authentication/index' + }); + } + } + }); + }, 2000); + } + } + } catch (error) { + wx.hideLoading(); + console.error('登录失败:', error); + wx.showToast({ + title: '登录失败,请重试', + icon: 'none', + duration: 2000 + }); + } + }, + + // 保存用户信息 + async saveUserInfo(userInfo, userType = 'buyer') { + return new Promise(async (resolve, reject) => { + try { + const storedUserId = wx.getStorageSync('userId'); + const users = wx.getStorageSync('users') || {}; + + // 更新用户信息 + users[storedUserId] = { + ...users[storedUserId], + ...userInfo, + type: userType, + lastLogin: new Date().toISOString() + }; + + // 保存到本地存储 + wx.setStorageSync('users', users); + wx.setStorageSync('userInfo', userInfo); + + // 上传用户信息到服务器 + const API = require('../../utils/api'); + const submitData = { + openid: wx.getStorageSync('openid'), + userId: storedUserId, + ...userInfo, + type: userType + }; + + await API.request('/api/user/update', 'POST', submitData).then(res => { + console.log('用户信息上传成功:', res); + resolve({ success: true, message: '用户信息保存成功' }); + }).catch(err => { + console.error('用户信息上传失败:', err); + // 即使服务器上传失败,也继续流程,只在本地保存 + resolve({ success: false, message: '本地保存成功,服务器同步失败' }); + }); + } catch (error) { + console.error('保存用户信息失败:', error); + reject(error); + } + }); } }); \ No newline at end of file diff --git a/pages/evaluate2/one.wxml b/pages/evaluate2/one.wxml index 4180588..6eaf083 100644 --- a/pages/evaluate2/one.wxml +++ b/pages/evaluate2/one.wxml @@ -6,6 +6,29 @@ + + + + 授权登录 + 授权您的手机号后才能使用完整功能 + + + + + + + diff --git a/pages/evaluate2/one.wxss b/pages/evaluate2/one.wxss index 67a8107..d8e7fad 100644 --- a/pages/evaluate2/one.wxss +++ b/pages/evaluate2/one.wxss @@ -557,4 +557,96 @@ /* 调整规格网格布局,确保不被导航栏遮挡 */ .spec-section { margin-bottom: 40rpx; +} + +/* 登录弹窗样式 */ +.auth-modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; +} + +.auth-modal-container { + background: rgba(255, 255, 255, 0.95); + border-radius: 20rpx; + padding: 48rpx; + width: 80%; + max-width: 500rpx; + box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2); + backdrop-filter: blur(12rpx); + border: 1rpx solid rgba(255, 255, 255, 0.3); +} + +.auth-modal-title { + font-size: 36rpx; + font-weight: 700; + text-align: center; + margin-bottom: 24rpx; + color: #2c3e50; + letter-spacing: 2rpx; +} + +.auth-modal-content { + font-size: 28rpx; + text-align: center; + margin-bottom: 48rpx; + color: #666; + line-height: 1.5; + padding: 0 20rpx; +} + +.auth-modal-buttons { + display: flex; + flex-direction: column; + gap: 24rpx; +} + +.auth-primary-button { + background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%); + color: white; + border: none; + border-radius: 12rpx; + padding: 24rpx; + font-size: 30rpx; + font-weight: 700; + min-height: 88rpx; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4rpx 16rpx rgba(96, 165, 250, 0.4); + transition: all 0.3s ease; +} + +.auth-primary-button:hover { + transform: translateY(-2rpx); + box-shadow: 0 8rpx 24rpx rgba(96, 165, 250, 0.6); +} + +.auth-cancel-button { + background: rgba(255, 255, 255, 0.9); + color: #2c3e50; + border: 2rpx solid #e2e8f0; + border-radius: 12rpx; + padding: 24rpx; + font-size: 28rpx; + font-weight: 600; + min-height: 88rpx; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); +} + +.auth-cancel-button:hover { + background: rgba(236, 240, 241, 0.8); + transform: translateY(-2rpx); + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); } \ No newline at end of file