// pages/profile/index.js Page({ // 分享给朋友/群聊 onShareAppMessage() { return { title: '鸡蛋贸易平台 - 个人中心,查看我的信息', path: '/pages/profile/index', imageUrl: '/images/你有好蛋.png' } }, // 分享到朋友圈 onShareTimeline() { return { title: '鸡蛋贸易平台 - 个人中心,查看我的信息', query: '', imageUrl: '/images/你有好蛋.png' } }, data: { userInfo: {}, userType: '', userTags: [], needPhoneAuth: false, // 是否需要重新授权手机号 locationInfo: '', // 位置信息 hasLocationAuth: false, // 是否已经授权位置 isInPersonnel: false, // 用户手机号是否在personnel表中 currentAvatarIndex: 0, // 当前显示的头像索引,默认显示第一张 rawAvatarUrl: null, // 存储原始的头像URL数据(可能是数组) // 固定的头像URL数组 avatarUrls: [ "https://my-supplier-photos.oss-cn-chengdu.aliyuncs.com/products/%E6%B5%B7%E8%93%9D%E7%81%B0/image/7a2a8a17a83ba4d3d4270828531e2041.jpeg", "https://my-supplier-photos.oss-cn-chengdu.aliyuncs.com/products/%E4%BC%8A%E8%8E%8E%E7%B2%89/image/1b2a0ba28eaa17c16c3674985ccee05c.jpeg" ] }, onLoad() { this.loadUserInfo(); this.checkLocationAuth(); }, onShow() { this.loadUserInfo(); this.checkLocationAuth(); // 更新自定义tabBar状态 if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 4 }); } // 更新全局tab状态 const app = getApp(); app.updateCurrentTab('profile'); }, // 隐藏电话号码中间4位 hidePhoneNumber(phoneNumber) { if (!phoneNumber) return '' const phoneStr = String(phoneNumber) if (phoneStr.length !== 11) return phoneStr return phoneStr.substring(0, 3) + '****' + phoneStr.substring(7) }, // 处理头像URL,确保正确解析数组形式的OSS URL processAvatarUrl(avatarUrl) { if (!avatarUrl) { return 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'; } // 如果是字符串,尝试解析为JSON数组 if (typeof avatarUrl === 'string') { // 去除字符串两端的空格和引号 let cleanedUrl = avatarUrl.trim(); // 去除可能存在的前后引号 if ((cleanedUrl.startsWith('"') && cleanedUrl.endsWith('"')) || (cleanedUrl.startsWith('`') && cleanedUrl.endsWith('`'))) { cleanedUrl = cleanedUrl.substring(1, cleanedUrl.length - 1); } try { const parsedUrl = JSON.parse(cleanedUrl); // 如果解析成功且是数组且不为空,使用第一个元素 if (Array.isArray(parsedUrl) && parsedUrl.length > 0) { // 清理第一个元素中的空格和引号 let firstUrl = parsedUrl[0]; if (typeof firstUrl === 'string') { firstUrl = firstUrl.trim(); if ((firstUrl.startsWith('"') && firstUrl.endsWith('"')) || (firstUrl.startsWith('`') && firstUrl.endsWith('`'))) { firstUrl = firstUrl.substring(1, firstUrl.length - 1); } } return firstUrl; } // 如果解析成功但不是数组,直接返回清理后的URL return cleanedUrl; } catch (e) { // 解析失败,返回清理后的URL return cleanedUrl; } } // 如果是数组且不为空,使用第一个元素 if (Array.isArray(avatarUrl) && avatarUrl.length > 0) { let firstUrl = avatarUrl[0]; if (typeof firstUrl === 'string') { // 清理第一个元素中的空格和引号 firstUrl = firstUrl.trim(); if ((firstUrl.startsWith('"') && firstUrl.endsWith('"')) || (firstUrl.startsWith('`') && firstUrl.endsWith('`'))) { firstUrl = firstUrl.substring(1, firstUrl.length - 1); } } return firstUrl; } // 其他情况返回默认头像 return 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'; }, // 加载用户信息 loadUserInfo() { console.log('开始加载用户信息') const app = getApp() // 从本地存储获取用户信息 const localUserInfo = wx.getStorageSync('userInfo') || {} if (app.globalData.userInfo) { const userInfo = { ...app.globalData.userInfo } // 使用固定的头像URL数组 const avatarUrls = this.data.avatarUrls; // 保持用户当前的头像URL,如果没有则使用第一张作为默认 if (!userInfo.avatarUrl) { userInfo.avatarUrl = avatarUrls[0]; } userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber) // 根据当前的avatarUrl更新currentAvatarIndex let currentAvatarIndex = 0; if (userInfo.avatarUrl) { const index = avatarUrls.indexOf(userInfo.avatarUrl); if (index !== -1) { currentAvatarIndex = index; } } this.setData({ userInfo, rawAvatarUrl: avatarUrls, currentAvatarIndex: currentAvatarIndex }) // 更新全局状态中的头像URL,确保下次加载时使用处理后的URL app.globalData.userInfo = userInfo; wx.setStorageSync('userInfo', userInfo); } else { const userInfo = { ...localUserInfo } // 使用固定的头像URL数组 const avatarUrls = this.data.avatarUrls; // 保持用户当前的头像URL,如果没有则使用第一张作为默认 if (!userInfo.avatarUrl) { userInfo.avatarUrl = avatarUrls[0]; } userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber) // 根据当前的avatarUrl更新currentAvatarIndex let currentAvatarIndex = 0; if (userInfo.avatarUrl) { const index = avatarUrls.indexOf(userInfo.avatarUrl); if (index !== -1) { currentAvatarIndex = index; } } app.globalData.userInfo = userInfo wx.setStorageSync('userInfo', userInfo); this.setData({ userInfo, needPhoneAuth: !userInfo.phoneNumber, rawAvatarUrl: avatarUrls, currentAvatarIndex: currentAvatarIndex }) } // 加载用户类型和标签 const userId = wx.getStorageSync('userId') const openid = wx.getStorageSync('openid') console.log('加载用户信息 - userId:', userId, 'openid:', openid ? '已获取' : '未获取') if (userId && openid) { // 从服务器获取最新的用户信息,确保身份由数据库决定 this.refreshUserInfoFromServer(openid, userId) // 确保users存储结构存在 let users = wx.getStorageSync('users') if (!users) { users = {} wx.setStorageSync('users', users) } if (!users[userId]) { users[userId] = { type: '' } wx.setStorageSync('users', users) } // 先显示本地存储的用户类型,但会被服务器返回的最新值覆盖 const user = users[userId] const currentType = this.formatUserType(user.type) this.setData({ userType: currentType }) console.log('加载用户信息 - 当前本地存储的用户类型:', currentType) // 先使用本地存储的用户类型更新标签,后续会被服务器返回的最新值覆盖 this.updateUserTags(userId, user.type) } // 检查用户手机号是否在personnel表中 this.checkPhoneInPersonnel() }, // 检查用户手机号是否在personnel表中 checkPhoneInPersonnel() { const userInfo = this.data.userInfo const phoneNumber = userInfo.phoneNumber if (!phoneNumber) { this.setData({ isInPersonnel: false }) return } console.log('开始检查手机号是否在personnel表中:', phoneNumber) // 引入API服务 const API = require('../../utils/api.js') API.checkPhoneInPersonnel(phoneNumber).then(isInPersonnel => { console.log('用户手机号是否在personnel表中:', isInPersonnel) this.setData({ isInPersonnel }) }).catch(err => { console.error('检查personnel表失败:', err) this.setData({ isInPersonnel: false }) }) }, // 更新用户标签 updateUserTags(userId, userType) { // 确保tags存储结构存在 let tags = wx.getStorageSync('tags') if (!tags) { tags = {} wx.setStorageSync('tags', tags) } if (!tags[userId]) { tags[userId] = [] wx.setStorageSync('tags', tags) } const userTags = tags[userId] || [] console.log('加载用户信息 - 原始标签:', userTags) // 使用indexOf替代includes以解决Babel兼容性问题 let firstCategoryTag = [] // 查找第一个偏好品类标签 for (let i = 0; i < userTags.length; i++) { if (userTags[i].indexOf('偏好品类') !== -1) { firstCategoryTag = [userTags[i]] break } } // 合并保留的标签 let filteredTags = [...firstCategoryTag] // 始终根据当前用户类型显示对应的身份标签 if (userType && userType !== '') { let identityLabel = '身份:not_set' switch (userType) { case 'buyer': identityLabel = '身份:买家'; break case 'seller': identityLabel = '身份:卖家'; break } filteredTags.push(identityLabel) console.log('加载用户信息 - 根据当前用户类型显示身份标签:', identityLabel) } console.log('加载用户信息 - 过滤后的标签:', filteredTags) this.setData({ userTags: filteredTags }) }, // 从服务器刷新用户信息并同步身份数据 refreshUserInfoFromServer(openid, userId) { const API = require('../../utils/api.js') API.getUserInfo(openid).then(res => { console.log('从服务器获取用户信息成功:', res) console.log('服务器返回的完整数据:', JSON.stringify(res)) if (res.success && res.data) { const serverUserInfo = res.data console.log('服务器返回的用户信息:', JSON.stringify(serverUserInfo)) console.log('是否包含idcardstatus:', 'idcardstatus' in serverUserInfo) console.log('是否包含reason:', 'reason' in serverUserInfo) // 更新本地用户信息 const app = getApp() // 先保存当前的头像URL const currentAvatarUrl = app.globalData.userInfo.avatarUrl; // 构建更新后的用户信息,优先使用服务器返回的值 const updatedUserInfo = { ...app.globalData.userInfo, ...serverUserInfo } // 使用固定的头像URL数组 const avatarUrls = this.data.avatarUrls; // 检查服务器返回的用户信息中是否包含avatarUrl let finalAvatarUrl = updatedUserInfo.avatarUrl; // 如果服务器返回的avatarUrl为空字符串或null,且本地有,则使用本地的 if ((!finalAvatarUrl || finalAvatarUrl === '') && currentAvatarUrl) { finalAvatarUrl = currentAvatarUrl; } // 如果两者都没有,则使用第一张作为默认 else if (!finalAvatarUrl || finalAvatarUrl === '') { finalAvatarUrl = avatarUrls[0]; } // 更新头像URL updatedUserInfo.avatarUrl = finalAvatarUrl; // 添加隐藏的电话号码 updatedUserInfo.hiddenPhoneNumber = this.hidePhoneNumber(updatedUserInfo.phoneNumber) app.globalData.userInfo = updatedUserInfo wx.setStorageSync('userInfo', updatedUserInfo) this.setData({ userInfo: updatedUserInfo, rawAvatarUrl: avatarUrls }) // 检查服务器返回的用户信息是否包含位置信息 if (serverUserInfo.address) { // 更新位置信息 this.setData({ locationInfo: serverUserInfo.address }); wx.setStorageSync('locationInfo', serverUserInfo.address); console.log('从服务器获取位置信息:', serverUserInfo.address); } // 同步更新用户身份信息(当前身份由数据库决定) if (serverUserInfo.type) { this.syncUserTypeFromServer(userId, serverUserInfo.type) } // 重新检查用户手机号是否在personnel表中 this.checkPhoneInPersonnel() console.log('用户信息已更新,昵称:', updatedUserInfo.name, '手机号:', updatedUserInfo.phoneNumber, '身份:', serverUserInfo.type, '头像URL:', finalAvatarUrl) } }).catch(err => { console.error('从服务器获取用户信息失败:', err) // 如果getUserInfo失败,尝试使用validateUserLogin作为备选 API.validateUserLogin().then(res => { console.log('使用validateUserLogin获取用户信息成功:', res) if (res.success && res.data) { const serverUserInfo = res.data // 更新本地用户信息 const app = getApp() // 先保存当前的头像URL const currentAvatarUrl = app.globalData.userInfo.avatarUrl; const updatedUserInfo = { ...app.globalData.userInfo, ...serverUserInfo } // 使用固定的头像URL数组 const avatarUrls = this.data.avatarUrls; // 检查服务器返回的用户信息中是否包含avatarUrl let finalAvatarUrl = updatedUserInfo.avatarUrl; // 如果服务器返回的avatarUrl为空字符串或null,且本地有,则使用本地的 if ((!finalAvatarUrl || finalAvatarUrl === '') && currentAvatarUrl) { finalAvatarUrl = currentAvatarUrl; } // 如果两者都没有,则使用第一张作为默认 else if (!finalAvatarUrl || finalAvatarUrl === '') { finalAvatarUrl = avatarUrls[0]; } // 更新头像URL updatedUserInfo.avatarUrl = finalAvatarUrl; // 添加隐藏的电话号码 updatedUserInfo.hiddenPhoneNumber = this.hidePhoneNumber(updatedUserInfo.phoneNumber) app.globalData.userInfo = updatedUserInfo wx.setStorageSync('userInfo', updatedUserInfo) this.setData({ userInfo: updatedUserInfo, rawAvatarUrl: avatarUrls }) // 检查服务器返回的用户信息是否包含位置信息 if (serverUserInfo.address) { // 更新位置信息 this.setData({ locationInfo: serverUserInfo.address }); wx.setStorageSync('locationInfo', serverUserInfo.address); console.log('从服务器(备选方案)获取位置信息:', serverUserInfo.address); } // 同步更新用户身份信息(当前身份由数据库决定) if (serverUserInfo.type) { this.syncUserTypeFromServer(userId, serverUserInfo.type) } // 重新检查用户手机号是否在personnel表中 this.checkPhoneInPersonnel() console.log('用户信息已更新(备选方案):', updatedUserInfo, '头像URL:', finalAvatarUrl) } }).catch(validateErr => { console.error('从服务器获取用户信息失败(包括备选方案):', validateErr) // 如果服务器请求失败,继续使用本地缓存的信息 }) }) }, // 从服务器同步用户身份信息 syncUserTypeFromServer(userId, serverType) { if (!userId || !serverType) { console.error('同步用户身份信息失败: 参数不完整') return } console.log('从服务器同步用户身份信息:', { userId, serverType }) // 更新本地存储的用户身份 let users = wx.getStorageSync('users') || {} if (!users[userId]) { users[userId] = {} } // 如果当前类型是 Colleague,直接返回,不允许从服务器同步覆盖 if (users[userId].type === 'Colleague') { console.log('当前用户是 Colleague 类型,不允许从服务器同步覆盖用户类型') return } // 移除serverType中的customer(如果存在) let processedServerType = serverType.replace(/,?customer/g, '').replace(/^,|,$/g, '') // 构建新的用户类型 let newUserType = processedServerType // 只有当新构建的用户类型与本地不同时才更新 if (users[userId].type !== newUserType) { users[userId].type = newUserType wx.setStorageSync('users', users) // 更新全局用户类型 const app = getApp() app.globalData.userType = newUserType // 更新页面显示的用户类型 this.setData({ userType: this.formatUserType(newUserType) }) console.log('用户身份已从服务器同步并保留客服标识:', newUserType) } else { console.log('用户身份与服务器一致,无需更新:', newUserType) } // 更新用户标签,确保传入正确的参数 this.updateUserTags(userId, newUserType) }, // 格式化用户类型显示 formatUserType(type) { switch (type) { case 'buyer': return '买家'; case 'seller': return '卖家'; case 'both': return '买卖家'; case 'buyer+seller': return '买卖家'; default: return type || 'not_set'; } }, // 设置为买家 setAsBuyer() { this.switchUserType('buyer', 'buyer') }, // 设置为卖家 setAsSeller() { this.switchUserType('seller', 'seller') }, // 切换用户类型的通用方法 switchUserType(newType, typeName) { const userId = wx.getStorageSync('userId') const openid = wx.getStorageSync('openid') if (!userId || !openid) { wx.navigateTo({ url: '/pages/index/index' }) return } // 显示操作中的提示 wx.showLoading({ title: 'Switching...' }) // 引入API服务 const API = require('../../utils/api.js') // 使用API更新用户类型,确保与服务器同步 API.updateUserType(newType).then(res => { console.log('用户类型更新成功:', res) // 更新页面显示 const app = getApp() this.setData({ userType: this.formatUserType(app.globalData.userType) }) // 更新用户标签 this.updateUserTags(userId, app.globalData.userType) wx.showToast({ title: `Switched to ${typeName}`, icon: 'success', duration: 2000 }) }).catch(err => { console.error('用户类型更新失败:', err) wx.showToast({ title: 'Failed to switch, please retry', icon: 'none', duration: 2000 }) }).finally(() => { wx.hideLoading() }) }, // 上传用户类型到服务器 uploadUserTypeToServer(openid, userId, userInfo, type) { // 引入API服务 const API = require('../../utils/api.js') // 构造上传数据 const uploadData = { userId: userId, openid: openid, ...userInfo, type: type, timestamp: Date.now() } // 调用API上传用户信息 API.uploadUserInfo(uploadData).then(res => { console.log('用户类型更新成功:', res) }).catch(err => { console.error('用户类型更新失败:', err) wx.showToast({ title: '身份更新失败,请重试', icon: 'none', duration: 2000 }) }) }, // 处理手机号授权结果 async onPhoneNumberResult(e) { console.log('手机号授权结果:', e) // 首先检查用户是否拒绝授权 if (e.detail.errMsg !== 'getPhoneNumber:ok') { console.log('用户拒绝授权手机号') wx.showToast({ title: '您已拒绝授权,操作已取消', icon: 'none' }) // 直接返回,取消所有后续操作 return } wx.showLoading({ title: '登录中...', mask: true }) try { // 引入API服务 const API = require('../../utils/api.js') // 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; 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.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) { 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://my-supplier-photos.oss-cn-chengdu.aliyuncs.com/products/%E6%B5%B7%E8%93%9D%E7%81%B0/image/7a2a8a17a83ba4d3d4270828531e2041.jpeg', 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 }) // 重新加载用户信息以更新UI this.loadUserInfo() wx.hideLoading() // 登录成功后检查位置授权状态,确保位置信息正确显示 this.checkLocationAuth(); // 根据服务器返回的结果显示不同的提示 if (hasPhoneConflict) { wx.showModal({ title: '登录成功', content: '您的手机号已被其他账号绑定', showCancel: false, confirmText: '我知道了', success(res) { if (res.confirm) { console.log('用户点击了我知道了'); } } }); } else { 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) } } }, // 上传用户信息到服务器 uploadUserInfoToServer(userInfo, userId, type) { // 返回Promise以便调用者可以进行错误处理 return new Promise((resolve, reject) => { try { // 引入API服务 const API = require('../../utils/api.js') // 获取openid const openid = wx.getStorageSync('openid') // 验证必要参数 if (!userId || !openid) { const error = new Error('缺少必要的用户信息'); console.error('用户信息上传失败:', error); reject(error); return; } // 构造上传数据(不包含头像URL,避免登录时覆盖用户选择的头像) const uploadData = { userId: userId, openid: openid, name: userInfo.name, phoneNumber: userInfo.phoneNumber, // 添加phoneNumber字段,满足服务器要求 type: type, timestamp: Date.now() } // 调用API上传用户信息 API.uploadUserInfo(uploadData).then(res => { console.log('用户信息上传成功:', res) resolve(res); }).catch(err => { console.error('用户信息上传失败:', err) reject(err); }) } catch (error) { console.error('上传用户信息时发生异常:', error); reject(error); } }); }, // 修改用户名称 onEditName() { const currentName = this.data.userInfo.name || '未登录'; wx.showModal({ title: '修改用户名称', editable: true, placeholderText: '请输入新的名称最多10个字符', confirmText: '确认', cancelText: '取消', success: (res) => { if (res.confirm) { // 移除首尾空格并过滤多余空格 let newName = res.content.trim(); newName = newName.replace(/\s+/g, ' '); // 验证昵称不能为空 if (!newName) { wx.showToast({ title: '名称不能为空', icon: 'none', duration: 2000 }); return; } // 验证昵称长度 if (newName.length > 10) { wx.showToast({ title: '名称长度不能超过10个字符', icon: 'none', duration: 2000 }); return; } // 检查名称是否变化 if (newName === currentName) { wx.showToast({ title: '名称未变化', icon: 'none', duration: 2000 }); return; } // 显示加载提示 wx.showLoading({ title: '正在更新...', mask: true }); // 更新用户信息 this.updateName(newName).finally(() => { // 无论成功失败,都隐藏加载提示 wx.hideLoading(); }); } } }); }, // 检查位置授权状态 checkLocationAuth() { const that = this; // 检查用户是否登录 const userInfo = this.data.userInfo; const isLoggedIn = userInfo && userInfo.phoneNumber; if (!isLoggedIn) { // 未登录状态,重置位置信息 that.setData({ hasLocationAuth: false, locationInfo: '' }); return; } wx.getSetting({ success(res) { if (res.authSetting['scope.userLocation']) { // 用户已经授权位置 that.setData({ hasLocationAuth: true }); // 从本地存储读取位置信息,不自动获取当前位置 const savedLocationInfo = wx.getStorageSync('locationInfo'); if (savedLocationInfo) { that.setData({ locationInfo: savedLocationInfo }); } } else { // 用户未授权位置 that.setData({ hasLocationAuth: false }); } } }); }, // 请求位置授权 requestLocationAuth() { const that = this; console.log('开始请求位置授权'); wx.showLoading({ title: '请求授权中...', mask: true }); // 添加超时机制,确保加载提示不会一直显示 const loadingTimeout = setTimeout(() => { wx.hideLoading(); console.error('位置授权请求超时'); wx.showToast({ title: '请求超时,请重试', icon: 'none' }); }, 10000); // 10秒超时 // 检查用户是否已经拒绝过授权 wx.getSetting({ success(res) { clearTimeout(loadingTimeout); if (res.authSetting['scope.userLocation'] === false) { // 用户已经拒绝过授权,直接引导到设置页面 wx.hideLoading(); wx.showModal({ title: '需要位置授权', content: '请在设置中开启位置授权,以便我们为您提供相关服务', showCancel: true, cancelText: '取消', confirmText: '去授权', success: (res) => { if (res.confirm) { // 打开设置页面让用户手动开启授权 wx.openSetting({ success: (settingRes) => { console.log('设置页面返回结果:', settingRes); if (settingRes.authSetting['scope.userLocation']) { // 用户在设置中开启了位置授权 that.setData({ hasLocationAuth: true }); wx.showToast({ title: '授权成功', icon: 'success', duration: 1500 }); // 从本地存储读取位置信息,不自动获取当前位置 const savedLocationInfo = wx.getStorageSync('locationInfo'); if (savedLocationInfo) { that.setData({ locationInfo: savedLocationInfo }); } else { // 如果本地没有位置信息,再获取当前位置 that.getUserLocation(); } } else { // 用户在设置中仍未开启位置授权 that.setData({ hasLocationAuth: false }); wx.showToast({ title: '您已拒绝位置授权', icon: 'none' }); } }, fail: (err) => { console.error('打开设置失败:', err); that.setData({ hasLocationAuth: false }); wx.showToast({ title: '打开设置失败', icon: 'none' }); } }); } else { // 用户点击了取消 that.setData({ hasLocationAuth: false }); } } }); } else { // 用户未拒绝过授权,调用 authorize wx.authorize({ scope: 'scope.userLocation', success() { clearTimeout(loadingTimeout); console.log('位置授权成功'); wx.hideLoading(); that.setData({ hasLocationAuth: true }); wx.showToast({ title: '授权成功', icon: 'success', duration: 1500 }); // 从本地存储读取位置信息,不自动获取当前位置 const savedLocationInfo = wx.getStorageSync('locationInfo'); if (savedLocationInfo) { that.setData({ locationInfo: savedLocationInfo }); } else { // 如果本地没有位置信息,再获取当前位置 that.getUserLocation(); } }, fail(err) { clearTimeout(loadingTimeout); console.log('位置授权失败:', err); wx.hideLoading(); // 授权失败,弹出模态框引导用户重新授权 wx.showModal({ title: '需要位置授权', content: '请在设置中开启位置授权,以便我们为您提供相关服务', showCancel: true, cancelText: '取消', confirmText: '去授权', success: (res) => { if (res.confirm) { // 打开设置页面让用户手动开启授权 wx.openSetting({ success: (settingRes) => { console.log('设置页面返回结果:', settingRes); if (settingRes.authSetting['scope.userLocation']) { // 用户在设置中开启了位置授权 that.setData({ hasLocationAuth: true }); wx.showToast({ title: '授权成功', icon: 'success', duration: 1500 }); // 从本地存储读取位置信息,不自动获取当前位置 const savedLocationInfo = wx.getStorageSync('locationInfo'); if (savedLocationInfo) { that.setData({ locationInfo: savedLocationInfo }); } else { // 如果本地没有位置信息,再获取当前位置 that.getUserLocation(); } } else { // 用户在设置中仍未开启位置授权 that.setData({ hasLocationAuth: false }); wx.showToast({ title: '您已拒绝位置授权', icon: 'none' }); } }, fail: (err) => { console.error('打开设置失败:', err); that.setData({ hasLocationAuth: false }); wx.showToast({ title: '打开设置失败', icon: 'none' }); } }); } else { // 用户点击了取消 that.setData({ hasLocationAuth: false }); } } }); } }); } }, fail(err) { clearTimeout(loadingTimeout); console.error('获取设置失败:', err); wx.hideLoading(); wx.showToast({ title: '获取设置失败', icon: 'none' }); } }); }, // 获取用户当前位置 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 }); // 检查openid是否存在 let openid = wx.getStorageSync('openid'); if (!openid) { // 尝试从用户信息中获取openid const globalUserInfo = wx.getStorageSync('userInfo'); openid = globalUserInfo?.openid; } // 确保openid存在 if (!openid) { console.error('位置上传失败: 未找到openid'); wx.hideLoading(); wx.showToast({ title: '位置上传失败,请先登录', icon: 'none', duration: 2000 }); return; } // 调用逆地理编码API获取详细地址,然后统一上传 that.reverseGeocode(latitude, longitude, openid); }, fail() { wx.hideLoading(); wx.showToast({ title: '获取位置失败', icon: 'none' }); } }); } else { // 用户未授权位置,调用请求授权函数 that.requestLocationAuth(); } } }); }, // 逆地理编码获取详细地址并上传到数据库 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; that.setData({ locationInfo: address }); // 将地址信息保存到本地存储 wx.setStorageSync('locationInfo', address); // 保存地址信息到数据库 const api = require('../../utils/api.js'); const locationUpdateData = { openid: openid, latitude: latitude, longitude: longitude, address: address }; console.log('保存地址到数据库:', locationUpdateData); // 调用API保存地址信息 api.request('/api/user/update-location', 'POST', locationUpdateData) .then(res => { console.log('地址保存成功:', res); // 显示上传成功提示 wx.showToast({ title: '位置更新成功', icon: 'success', duration: 1500 }); }).catch(err => { console.error('地址保存失败:', err); // 显示上传失败提示 wx.showToast({ title: '位置上传失败', icon: 'none', duration: 2000 }); }); } else { wx.showToast({ title: '获取地址失败', icon: 'none' }); } }, fail() { wx.hideLoading(); wx.showToast({ title: '获取地址失败', icon: 'none' }); } }); }, // 更新用户名称 updateName(newName) { return new Promise((resolve, reject) => { try { // 更新本地和全局用户信息 const app = getApp(); const updatedUserInfo = { ...this.data.userInfo, name: newName }; // 保存到本地存储和全局状态 app.globalData.userInfo = updatedUserInfo; wx.setStorageSync('userInfo', updatedUserInfo); // 更新页面显示 this.setData({ userInfo: updatedUserInfo }); // 更新服务器信息 const userId = wx.getStorageSync('userId'); const currentUserType = this.data.userType; // 如果有用户ID,则上传到服务器 if (userId) { // 使用Promise链处理上传 this.uploadUserInfoToServer(updatedUserInfo, userId, currentUserType) .then(() => { wx.showToast({ title: '名称修改成功', icon: 'success', duration: 2000 }); resolve(); }) .catch((err) => { console.error('服务器同步失败,但本地已更新:', err); // 即使服务器同步失败,本地也已成功更新 wx.showToast({ title: '本地更新成功,服务器同步稍后进行', icon: 'none', duration: 3000 }); resolve(); // 即使服务器失败,也视为成功,因为本地已经更新 }); } else { // 没有用户ID,只更新本地 console.warn('没有用户ID,仅更新本地用户名称'); wx.showToast({ title: '名称修改成功', icon: 'success', duration: 2000 }); resolve(); } } catch (error) { console.error('更新用户名称失败:', error); wx.showToast({ title: '更新失败,请稍后重试', icon: 'none', duration: 2000 }); reject(error); } }); }, // 跳转到收藏页面 goToFavorites() { wx.switchTab({ url: '/pages/favorites/index' }); }, // 跳转到订单页面 goToOrders() { wx.navigateTo({ url: '/pages/order/index' }); }, // 跳转到货源管理页面 navigateToGoods() { wx.navigateTo({ url: '/pages/goods/index' }); }, // 退出登录 logout() { wx.showModal({ title: '退出登录', content: '确定要退出登录吗?', success: (res) => { if (res.confirm) { // 保存位置信息,避免退出登录后丢失 const savedLocationInfo = wx.getStorageSync('locationInfo'); const savedUserLocation = wx.getStorageSync('userLocation'); // 清除本地缓存 wx.clearStorageSync(); // 恢复位置信息 if (savedLocationInfo) { wx.setStorageSync('locationInfo', savedLocationInfo); } if (savedUserLocation) { wx.setStorageSync('userLocation', savedUserLocation); } // 重置全局用户信息 const app = getApp(); app.globalData.userInfo = {}; app.globalData.userType = ''; // 重新加载页面 this.setData({ userInfo: {}, userType: '', userTags: [], needPhoneAuth: true, locationInfo: '', hasLocationAuth: false, isInPersonnel: false }); wx.showToast({ title: '退出登录成功', icon: 'success', duration: 2000 }); } } }); }, // 手动选择位置 chooseLocation() { const that = this; wx.chooseLocation({ success(res) { console.log('用户选择的位置信息:', res); const name = res.name; const address = res.address; const latitude = res.latitude; const longitude = res.longitude; // 将位置信息存储到本地 wx.setStorageSync('userLocation', { latitude, longitude }); // 更新页面显示 const locationInfo = `${name} ${address}`; that.setData({ locationInfo }); // 将地址信息保存到本地存储 wx.setStorageSync('locationInfo', locationInfo); // 检查openid是否存在 let openid = wx.getStorageSync('openid'); if (!openid) { // 尝试从用户信息中获取openid const globalUserInfo = wx.getStorageSync('userInfo'); openid = globalUserInfo?.openid; } // 确保openid存在 if (!openid) { console.error('位置上传失败: 未找到openid'); wx.showToast({ title: '位置上传失败,请先登录', icon: 'none', duration: 2000 }); return; } // 保存地址信息到数据库 const api = require('../../utils/api.js'); const locationUpdateData = { openid: openid, latitude: latitude, longitude: longitude, address: locationInfo }; console.log('保存手动选择的地址到数据库:', locationUpdateData); // 调用API保存地址信息 api.request('/api/user/update-location', 'POST', locationUpdateData) .then(res => { console.log('地址保存成功:', res); // 显示上传成功提示 wx.showToast({ title: '位置选择成功', icon: 'success', duration: 1500 }); }).catch(err => { console.error('地址保存失败:', err); // 显示上传失败提示 wx.showToast({ title: '位置上传失败', icon: 'none', duration: 2000 }); }); }, fail(err) { console.error('选择位置失败:', err); if (err.errMsg === 'chooseLocation:fail auth deny') { wx.showToast({ title: '需要位置授权才能选择地点', icon: 'none', duration: 2000 }); // 引导用户重新授权 that.requestLocationAuth(); } else { wx.showToast({ title: '选择位置失败', icon: 'none', duration: 2000 }); } } }); }, // 跳转到个人认证页面 navigateToAuthentication() { wx.navigateTo({ url: '/pages/profile/authentication/index' }); }, // 点击头像切换图片 onAvatarClick() { console.log('开始切换头像'); // 使用固定的头像URL数组 const avatarUrls = this.data.avatarUrls; console.log('头像URL数组:', avatarUrls); // 检查是否有至少两张图片可以切换 if (avatarUrls.length < 2) { wx.showToast({ title: '没有足够的头像可以切换', icon: 'none', duration: 2000 }); return; } // 先根据当前的avatarUrl更新currentAvatarIndex,确保它们保持一致 let currentAvatarIndex = 0; const currentAvatarUrl = this.data.userInfo.avatarUrl; if (currentAvatarUrl) { const index = avatarUrls.indexOf(currentAvatarUrl); if (index !== -1) { currentAvatarIndex = index; // 更新currentAvatarIndex到页面数据 this.setData({ currentAvatarIndex: currentAvatarIndex }); console.log('根据当前avatarUrl更新currentAvatarIndex:', currentAvatarIndex); } } // 切换到下一张头像 let nextIndex = currentAvatarIndex + 1; if (nextIndex >= avatarUrls.length) { nextIndex = 0; // 如果已经是最后一张,回到第一张 } console.log('当前头像索引:', currentAvatarIndex); console.log('下一张头像索引:', nextIndex); console.log('下一张头像URL:', avatarUrls[nextIndex]); // 显示切换头像的提示 const avatarType = nextIndex === 0 ? '男' : '女'; wx.showModal({ title: '切换头像', content: `确定要切换到${avatarType}头像吗?`, success: (res) => { if (res.confirm) { console.log('用户确认切换头像'); // 切换到下一张图片 const app = getApp(); // 只更新显示用的avatarUrl const updatedUserInfo = { ...this.data.userInfo, avatarUrl: avatarUrls[nextIndex] // 直接使用下一张图片用于显示 }; // 更新页面显示 this.setData({ userInfo: updatedUserInfo, currentAvatarIndex: nextIndex }); console.log('页面显示已更新'); // 将选中的头像URL写入数据库 console.log('准备更新头像到数据库:', avatarUrls[nextIndex]); this.updateAvatarInDatabase(avatarUrls[nextIndex]); wx.showToast({ title: '头像切换成功', icon: 'success', duration: 2000 }); } } }); }, // 将头像URL更新到数据库 updateAvatarInDatabase(avatarUrl) { console.log('开始更新头像到数据库:', avatarUrl); const API = require('../../utils/api.js'); const openid = wx.getStorageSync('openid'); const userId = wx.getStorageSync('userId'); console.log('用户信息:', { openid, userId }); if (!openid) { console.error('更新头像失败:缺少openid'); return; } // 构造更新数据 const updateData = { openid: openid, userId: userId, avatarUrl: avatarUrl }; console.log('构造的更新数据:', updateData); // 调用API更新用户信息 console.log('准备调用API.uploadUserInfo'); API.uploadUserInfo(updateData).then(res => { console.log('更新头像到数据库成功:', res); // 更新本地存储和全局数据中的头像URL const app = getApp(); app.globalData.userInfo.avatarUrl = avatarUrl; wx.setStorageSync('userInfo', app.globalData.userInfo); console.log('更新本地存储和全局数据中的头像URL成功:', avatarUrl); }).catch(err => { console.error('更新头像到数据库失败:', err); wx.showToast({ title: '更新头像失败,请重试', icon: 'none', duration: 2000 }); }); }, })