From e065ae6e58c492d968e5791a5e5bd15d631e859d 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: Sat, 27 Dec 2025 15:39:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BD=8D=E7=BD=AE=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E5=8A=9F=E8=83=BD=EF=BC=9A=E6=B7=BB=E5=8A=A0requestLo?= =?UTF-8?q?cationAuth=E3=80=81getUserLocation=E5=92=8CreverseGeocode?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/index/index.js | 426 +++++++++++++++++++++++++++++++++++------ pages/index/index.wxml | 41 ++-- pages/index/index.wxss | 14 +- 3 files changed, 396 insertions(+), 85 deletions(-) diff --git a/pages/index/index.js b/pages/index/index.js index 954f1c7..12fce49 100644 --- a/pages/index/index.js +++ b/pages/index/index.js @@ -814,6 +814,14 @@ Page({ // 查看商品详情 viewGoodsDetail: function(e) { + // 检查登录状态 + if (this.data.needPhoneAuth) { + this.setData({ + showOneKeyLoginModal: true + }) + return; + } + const item = e.currentTarget.dataset.item // 确保productId存在,优先使用id,其次使用productId const productId = String(item.id || item.productId || '') @@ -1269,18 +1277,6 @@ Page({ } } }); - } else { - wx.showModal({ - title: '登录成功', - content: '欢迎使用鸡蛋贸易平台', - showCancel: false, - confirmText: '开始使用', - success(res) { - if (res.confirm) { - console.log('用户点击了开始使用'); - } - } - }); } // 用户登录成功,但已移除类型选择和跳转功能 @@ -1952,62 +1948,384 @@ Page({ // 手机号授权处理 async onPhoneNumberResult(e) { console.log('手机号授权结果:', e) - if (e.detail.errMsg === 'getPhoneNumber:ok') { - // 用户同意授权,获取加密数据 - const phoneData = e.detail - wx.showLoading({ title: '获取手机号中...' }) + // 首先检查用户是否拒绝授权 + if (e.detail.errMsg !== 'getPhoneNumber:ok') { + console.log('用户拒绝授权手机号') + wx.showToast({ + title: '您已拒绝授权,操作已取消', + icon: 'none' + }) + // 直接返回,取消所有后续操作 + return + } - try { - // 引入API服务 - const API = require('../../utils/api.js') + wx.showLoading({ + title: '登录中...', + mask: true + }) - // 上传到服务器解密 - const res = await API.uploadPhoneNumberData(phoneData) + try { + // 引入API服务 + const API = require('../../utils/api.js') - wx.hideLoading() + // 1. 先执行微信登录获取code + const loginRes = await new Promise((resolve, reject) => { + wx.login({ + success: resolve, + fail: reject + }) + }) - if (res.success && res.phoneNumber) { - console.log('获取手机号成功:', res.phoneNumber) + if (!loginRes.code) { + throw new Error('获取登录code失败') + } - // 保存手机号到用户信息 - const app = getApp() - const userInfo = app.globalData.userInfo || wx.getStorageSync('userInfo') || {} - userInfo.phoneNumber = res.phoneNumber - - // 更新本地和全局用户信息 - app.globalData.userInfo = userInfo - wx.setStorageSync('userInfo', userInfo) - - // 获取userId - const userId = wx.getStorageSync('userId') - const users = wx.getStorageSync('users') || {} - const currentUserType = users[userId] && users[userId].type ? users[userId].type : '' - - // 同时更新服务器用户信息,确保上传完成 - console.log('开始更新服务器用户信息...') - if (!this.data.testMode) { - await this.uploadUserInfoToServer(userInfo, userId, currentUserType) - console.log('服务器用户信息更新完成') - } else { - console.log('测试模式下跳过服务器用户信息更新') - } + console.log('获取登录code成功:', loginRes.code) - wx.showToast({ title: '手机号绑定成功', icon: 'success' }) + // 2. 使用code换取openid + const openidRes = await API.getOpenid(loginRes.code) + + // 增强版响应处理逻辑,支持多种返回格式 + let openid = null; + let userId = null; + let sessionKey = null; + + // 优先从data字段获取数据 + if (openidRes && openidRes.data && typeof openidRes.data === 'object') { + openid = openidRes.data.openid || openidRes.data.OpenID || null; + userId = openidRes.data.userId || openidRes.data.userid || null; + sessionKey = openidRes.data.session_key || openidRes.data.sessionKey || null; + } + + // 如果data为空或不存在,尝试从响应对象直接获取 + if (!openid && openidRes && typeof openidRes === 'object') { + console.warn('服务器返回格式可能不符合预期,data字段为空或不存在,但尝试从根对象提取信息:', openidRes); + openid = openidRes.openid || openidRes.OpenID || null; + userId = openidRes.userId || openidRes.userid || null; + sessionKey = openidRes.session_key || openidRes.sessionKey || null; + } + + // 检查服务器状态信息 + const isSuccess = openidRes && (openidRes.success === true || openidRes.code === 200); + + if (!openid) { + throw new Error('获取openid失败: ' + (openidRes && openidRes.message ? openidRes.message : '未知错误')) + } + + // 存储openid和session_key + wx.setStorageSync('openid', openid) + if (sessionKey) { + wx.setStorageSync('sessionKey', sessionKey) + } + + // 确保始终使用从服务器获取的正式用户ID,不再生成临时ID + if (userId) { + wx.setStorageSync('userId', userId) + } else { + const app = getApp(); + if (app.globalData.userInfo && app.globalData.userInfo.userId) { + const serverUserId = String(app.globalData.userInfo.userId); + wx.setStorageSync('userId', serverUserId); + userId = serverUserId; + console.log('使用从全局获取的正式用户ID:', serverUserId); } else { - console.error('获取手机号失败:', res) - wx.showToast({ title: '获取手机号失败', icon: 'none' }) + console.warn('未找到有效的用户ID,请确保用户已授权登录'); + } + } + + console.log('获取openid成功并存储:', openid) + + // 3. 上传手机号加密数据到服务器解密 + const phoneData = { + ...e.detail, + openid: openid, + sessionKey: sessionKey || '' + } + + console.log('准备上传手机号加密数据到服务器') + const phoneRes = await API.uploadPhoneNumberData(phoneData) + + // 改进手机号解密结果的处理逻辑 + if (!phoneRes || (!phoneRes.success && !phoneRes.phoneNumber)) { + // 如果服务器返回格式不标准但包含手机号,也接受 + if (!(phoneRes && phoneRes.phoneNumber)) { + throw new Error('获取手机号失败: ' + (phoneRes && phoneRes.message ? phoneRes.message : '未知错误')) } + } + + // 检查是否有手机号冲突 + const hasPhoneConflict = phoneRes.phoneNumberConflict || false + const isNewPhone = phoneRes.isNewPhone || true + const phoneNumber = phoneRes.phoneNumber || null + + console.log('手机号解密结果:', { + phoneNumber: phoneNumber, + hasPhoneConflict: hasPhoneConflict, + isNewPhone: isNewPhone + }) + + // 4. 获取用户微信名称和头像 + let userProfile = null; + try { + userProfile = await new Promise((resolve, reject) => { + wx.getUserProfile({ + desc: '用于完善会员资料', + success: resolve, + fail: reject + }); + }); + console.log('获取用户信息成功:', userProfile); } catch (err) { - wx.hideLoading() - console.error('获取手机号失败:', err) - wx.showToast({ title: '获取手机号失败', icon: 'none' }) + console.warn('获取用户信息失败:', err); + // 如果获取失败,使用默认值 + } + + // 5. 创建用户信息 + const app = getApp() + const existingUserInfo = app.globalData.userInfo || wx.getStorageSync('userInfo') || {} + const userInfo = { + // 优先使用最新获取的微信头像和昵称,如果没有获取到则使用本地存储的 + name: (userProfile ? (userProfile.userInfo.name || userProfile.userInfo.nickName) : existingUserInfo.name) || '微信用户', + avatarUrl: (userProfile ? userProfile.userInfo.avatarUrl : existingUserInfo.avatarUrl) || 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0', + gender: (userProfile ? userProfile.userInfo.gender : existingUserInfo.gender) || 0, + country: (userProfile ? userProfile.userInfo.country : existingUserInfo.country) || '', + province: (userProfile ? userProfile.userInfo.province : existingUserInfo.province) || '', + city: (userProfile ? userProfile.userInfo.city : existingUserInfo.city) || '', + language: (userProfile ? userProfile.userInfo.language : existingUserInfo.language) || 'zh_CN', + phoneNumber: phoneNumber + } + + // 6. 获取用户类型 + const users = wx.getStorageSync('users') || {} + let currentUserType = users[userId] && users[userId].type ? users[userId].type : '' + + // 如果没有用户类型,尝试从全局获取 + if (!currentUserType) { + currentUserType = app.globalData.userType || '' + } + + // 7. 保存用户信息并等待上传完成 + console.log('开始保存用户信息并上传到服务器...') + await this.uploadUserInfoToServer(userInfo, userId, currentUserType) + console.log('用户信息保存并上传完成') + + // 更新本地和全局用户信息 + app.globalData.userInfo = userInfo + wx.setStorageSync('userInfo', userInfo) + + // 更新页面状态 + this.setData({ + needPhoneAuth: false, + userInfo: userInfo, + showOneKeyLoginModal: false + }) + + wx.hideLoading() + + const that = this; + wx.showModal({ + title: '登录成功', + content: '🥚 允许获取位置,为你优先展示附近新鲜鸡蛋供应商、自提门店及精准配送时效,无需手动填地址,位置信息仅用于优化购物体验,隐私有保障,放心开启~', + showCancel: true, + cancelText: '取消', + confirmText: '允许', + success(res) { + if (res.confirm) { + console.log('用户点击了允许'); + that.requestLocationAuth(); + } else if (res.cancel) { + console.log('用户点击了取消'); + } + } + }); + + } catch (error) { + wx.hideLoading() + console.error('登录过程中发生错误:', error) + + // 更具体的错误提示 + let errorMsg = '登录失败,请重试' + if (error.message.includes('网络')) { + errorMsg = '网络连接失败,请检查网络后重试' + } else if (error.message.includes('服务器')) { + errorMsg = '服务器连接失败,请稍后重试' + } else if (error.message.includes('openid')) { + 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) } - } else { - console.log('用户拒绝授权手机号') } }, + // 上传用户信息到服务器 + uploadUserInfoToServer(userInfo, userId, type) { + return new Promise((resolve, reject) => { + try { + const API = require('../../utils/api.js') + const openid = wx.getStorageSync('openid') + + if (!userId || !openid) { + const error = new Error('缺少必要的用户信息'); + console.error('用户信息上传失败:', error); + reject(error); + return; + } + + const uploadData = { + userId: userId, + openid: openid, + name: userInfo.name, + avatarUrl: userInfo.avatarUrl, + phoneNumber: userInfo.phoneNumber, + type: type, + timestamp: Date.now() + } + + API.uploadUserInfo(uploadData).then(res => { + console.log('用户信息上传成功:', res) + resolve(res); + }).catch(err => { + console.error('用户信息上传失败:', err) + reject(err); + }) + } catch (error) { + console.error('上传用户信息时发生异常:', error); + reject(error); + } + }); + }, + + // 请求位置授权 + requestLocationAuth() { + const that = this; + wx.authorize({ + scope: 'scope.userLocation', + success() { + that.setData({ hasLocationAuth: true }); + that.getUserLocation(); + }, + fail() { + wx.showModal({ + title: '需要位置授权', + content: '请在设置中开启位置授权', + showCancel: true, + cancelText: '取消', + confirmText: '去授权', + success: (res) => { + if (res.confirm) { + wx.openSetting({ + success: (settingRes) => { + if (settingRes.authSetting['scope.userLocation']) { + that.setData({ hasLocationAuth: true }); + that.getUserLocation(); + } else { + that.setData({ hasLocationAuth: false }); + wx.showToast({ title: '您已拒绝位置授权', icon: 'none' }); + } + }, + fail: () => { + that.setData({ hasLocationAuth: false }); + wx.showToast({ title: '打开设置失败', icon: 'none' }); + } + }); + } else { + that.setData({ hasLocationAuth: false }); + } + } + }); + } + }); + }, + + // 获取用户当前位置 + getUserLocation() { + const that = this; + wx.getSetting({ + success(res) { + if (res.authSetting['scope.userLocation']) { + wx.showLoading({ title: '获取位置中...' }); + wx.getLocation({ + type: 'gcj02', + success(res) { + const latitude = res.latitude; + const longitude = res.longitude; + wx.setStorageSync('userLocation', { latitude, longitude }); + + let openid = wx.getStorageSync('openid'); + if (!openid) { + const globalUserInfo = wx.getStorageSync('userInfo'); + openid = globalUserInfo?.openid; + } + + if (!openid) { + wx.hideLoading(); + wx.showToast({ title: '位置上传失败,请先登录', icon: 'none' }); + return; + } + + that.reverseGeocode(latitude, longitude, openid); + }, + fail() { + wx.hideLoading(); + wx.showToast({ title: '获取位置失败', icon: 'none' }); + } + }); + } + } + }); + }, + + // 逆地理编码 + reverseGeocode(latitude, longitude, openid) { + const that = this; + wx.request({ + url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77`, + success(res) { + wx.hideLoading(); + if (res.data.status === 0) { + const address = res.data.result.address; + wx.setStorageSync('locationInfo', address); + + const API = require('../../utils/api.js'); + const locationUpdateData = { + openid: openid, + latitude: latitude, + longitude: longitude, + address: address + }; + + API.request('/api/user/update-location', 'POST', locationUpdateData) + .then(res => { + wx.showToast({ title: '位置更新成功', icon: 'success' }); + }).catch(err => { + wx.showToast({ title: '位置上传失败', icon: 'none' }); + }); + } else { + wx.showToast({ title: '获取地址失败', icon: 'none' }); + } + }, + fail() { + wx.hideLoading(); + wx.showToast({ title: '获取地址失败', icon: 'none' }); + } + }); + }, diff --git a/pages/index/index.wxml b/pages/index/index.wxml index 78497b2..62683c6 100644 --- a/pages/index/index.wxml +++ b/pages/index/index.wxml @@ -195,16 +195,9 @@ bindtap="onAdClick" data-ad="ad_slot_1" > - 广告 - - - 🔍 - 暂无相关商品 - 试试调整搜索条件或地区筛选 - - 广告 @@ -328,31 +320,30 @@ - - - - - 提示 - 请先登录后再操作 - - - - - - - - + 授权登录 - 请授权获取您的手机号用于登录 + 授权您的手机号后才能查看商品详情 - - + + + diff --git a/pages/index/index.wxss b/pages/index/index.wxss index 2b6c2f6..5db8200 100644 --- a/pages/index/index.wxss +++ b/pages/index/index.wxss @@ -970,9 +970,9 @@ wx-button:not([size=mini]) { .auth-modal-container { background-color: #fff; border-radius: 24rpx; - width: 85%; - max-width: 520rpx; - padding: 50rpx 40rpx; + width: 90%; + max-width: 600rpx; + padding: 50rpx 20rpx; box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.18); } @@ -1005,7 +1005,8 @@ wx-button:not([size=mini]) { font-weight: 600; line-height: 1.6; border-radius: 12rpx; - padding: 24rpx 0; + padding: 30rpx 0; + width: 100%; box-shadow: 0 4rpx 12rpx rgba(7, 193, 96, 0.3); } @@ -1016,8 +1017,9 @@ wx-button:not([size=mini]) { font-weight: 500; line-height: 1.6; border-radius: 12rpx; - padding: 24rpx 0; - border: 2rpx solid #e5e5e5; + padding: 30rpx 0; + width: 100%; + border: 4rpx solid #e5e5e5; } /* 头像选择样式 */