// pages/index/index.js const API = require('../../utils/api.js'); // 媒体类型判断函数 function isVideoUrl(url) { if (!url || typeof url !== 'string') { return false; } // 转换为小写,确保大小写不敏感 const lowerUrl = url.toLowerCase(); // 支持的视频格式 const videoExtensions = ['.mp4', '.mov', '.avi', '.wmv', '.flv', '.webm', '.m4v', '.3gp']; // 检查URL是否以视频扩展名结尾 for (const ext of videoExtensions) { if (lowerUrl.endsWith(ext)) { return true; } } return false; } // 预处理单个商品的媒体URL function processGoodsMedia(goods) { if (!goods || !Array.isArray(goods)) { return []; } return goods.map(item => { // 确保imageUrls是数组 let imageUrls = item.imageUrls || []; if (!Array.isArray(imageUrls)) { imageUrls = [imageUrls]; } // 预处理媒体URL,添加类型信息 const mediaItems = imageUrls.map(url => { return { url: url, type: isVideoUrl(url) ? 'video' : 'image' }; }); return { ...item, mediaItems: mediaItems, // 确保imageUrls是数组 imageUrls: imageUrls }; }); } Page({ data: { isLoggedIn: false, currentUserType: null, showUserInfoForm: false, avatarUrl: 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0', name: '', showAuthModal: false, showOneKeyLoginModal: false, userInfo: {}, needPhoneAuth: false, testMode: true, partnerstatus: '', // 侧边栏相关 showSidebar: false, isDragging: false, startY: 0, currentY: 0, sidebarBtnTop: 500, sidebarBtnHidden: false, isPageHidden: false, hasGoodsManagePermission: false, // 搜索区域相关 searchSectionVisible: true, lastScrollTop: 0, isScrollLocked: false, // 回到顶部按钮 showBackToTop: false, scrollTop: 0, // 搜索相关 searchKeyword: '', selectedRegion: '全国', showRegionPicker: false, regions: ['全国', '北京', '上海', '广州', '深圳', '天津', '重庆', '河北', '山西', '辽宁', '吉林', '黑龙江', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '海南', '四川', '贵州', '云南', '陕西', '甘肃', '青海', '台湾', '内蒙古', '广西', '西藏', '宁夏', '新疆', '香港', '澳门'], // 商品相关 - 淘宝风格 goods: [], filteredGoods: [], selectedCategory: '全部', categories: ['全部', '粉壳', '褐壳', '绿壳', '白壳'], loadingMore: false, hasMoreData: true, page: 1, pageSize: 8, soldOutPage: 1, // 商品数据缓存 goodsCache: [], categoryQueryCache: {}, lastDataTimestamp: 0, cacheValidDuration: 5 * 60 * 1000, // 缓存有效期5分钟 // sold_out 加载状态 isQueryingSoldOut: false, soldOutPage: 1, soldOutPageSize: 8, publishedHasMore: true, // 防抖定时器 searchDebounceTimer: null, scrollDebounceTimer: null, filterDebounceTimer: null, // 请求任务管理 currentRequestTask: null, isRefreshing: false, isLoading: true, // 图片预览相关状态 previewImageUrls: [], previewImageIndex: 0, showImagePreview: false, // 高级筛选相关状态 showAdvancedFilter: false, advancedFilters: { shellColor: 'all', // 蛋壳颜色 yolkType: 'all', // 蛋黄类型 specification: 'all', // 规格 productName: 'all', // 商品名称 region: 'all', // 地区 priceRange: [0, 100], // 价格范围 sortBy: 'default' // 排序方式 }, // 自定义下拉菜单显示状态 showShellColorPicker: false, showYolkTypePicker: false, showSpecificationPicker: false, showProductNamePicker: false, showAdvancedRegionPicker: false, // 蛋壳颜色选项 shellColorOptions: [ { label: '全部颜色', value: 'all' }, { label: '绿壳', value: '绿壳' }, { label: '粉壳', value: '粉壳' }, { label: '褐壳', value: '褐壳' }, { label: '白壳', value: '白壳' } ], // 蛋黄类型选项 yolkTypeOptions: [ { label: '全部蛋黄', value: 'all' }, { label: '红心', value: '红心' }, { label: '黄心', value: '黄心' }, { label: '双色', value: '双色' } ], // 规格选项 specificationOptions: [ { label: '全部规格', value: 'all' }, { label: '格子装', value: '格子装' }, { label: '散托', value: '散托' }, { label: '不限规格', value: '不限规格' }, { label: '净重47+', value: '净重47+' }, { label: '净重46-47', value: '净重46-47' }, { label: '净重45-46', value: '净重45-46' }, { label: '净重44-45', value: '净重44-45' }, { label: '净重43-44', value: '净重43-44' }, { label: '净重42-43', value: '净重42-43' }, { label: '净重41-42', value: '净重41-42' }, { label: '净重40-41', value: '净重40-41' }, { label: '净重39-40', value: '净重39-40' }, { label: '净重38-39', value: '净重38-39' }, { label: '净重37-39', value: '净重37-39' }, { label: '净重37-38', value: '净重37-38' }, { label: '净重36-38', value: '净重36-38' }, { label: '净重36-37', value: '净重36-37' }, { label: '净重35-36', value: '净重35-36' }, { label: '净重34-35', value: '净重34-35' }, { label: '净重33-34', value: '净重33-34' }, { label: '净重32-33', value: '净重32-33' }, { label: '净重32-34', value: '净重32-34' }, { label: '净重31-32', value: '净重31-32' }, { label: '净重30-35', value: '净重30-35' }, { label: '净重30-34', value: '净重30-34' }, { label: '净重30-32', value: '净重30-32' }, { label: '净重30-31', value: '净重30-31' }, { label: '净重29-31', value: '净重29-31' }, { label: '净重29-30', value: '净重29-30' }, { label: '净重28-29', value: '净重28-29' }, { label: '净重28以下', value: '净重28以下' }, { label: '毛重52以上', value: '毛重52以上' }, { label: '毛重50-51', value: '毛重50-51' }, { label: '毛重48-49', value: '毛重48-49' }, { label: '毛重47-48', value: '毛重47-48' }, { label: '毛重46-47', value: '毛重46-47' }, { label: '毛重45-47', value: '毛重45-47' }, { label: '毛重45-46', value: '毛重45-46' }, { label: '毛重44-45', value: '毛重44-45' }, { label: '毛重43-44', value: '毛重43-44' }, { label: '毛重42-43', value: '毛重42-43' }, { label: '毛重41-42', value: '毛重41-42' }, { label: '毛重40-41', value: '毛重40-41' }, { label: '毛重38-39', value: '毛重38-39' }, { label: '毛重36-37', value: '毛重36-37' }, { label: '毛重34-35', value: '毛重34-35' }, { label: '毛重32-33', value: '毛重32-33' }, { label: '毛重30-31', value: '毛重30-31' }, { label: '毛重30以下', value: '毛重30以下' } ], // 地区选项 regionOptions: [ { label: '全国', value: 'all' }, { label: '北京', value: '北京' }, { label: '上海', value: '上海' }, { label: '广州', value: '广州' }, { label: '深圳', value: '深圳' }, { label: '天津', value: '天津' }, { label: '重庆', value: '重庆' }, { label: '河北', value: '河北' }, { label: '山西', value: '山西' }, { label: '辽宁', value: '辽宁' }, { label: '吉林', value: '吉林' }, { label: '黑龙江', value: '黑龙江' }, { label: '江苏', value: '江苏' }, { label: '浙江', value: '浙江' }, { label: '安徽', value: '安徽' }, { label: '福建', value: '福建' }, { label: '江西', value: '江西' }, { label: '山东', value: '山东' }, { label: '河南', value: '河南' }, { label: '湖北', value: '湖北' }, { label: '湖南', value: '湖南' }, { label: '广东', value: '广东' }, { label: '海南', value: '海南' }, { label: '四川', value: '四川' }, { label: '贵州', value: '贵州' }, { label: '云南', value: '云南' }, { label: '陕西', value: '陕西' }, { label: '甘肃', value: '甘肃' }, { label: '青海', value: '青海' }, { label: '台湾', value: '台湾' }, { label: '内蒙古', value: '内蒙古' }, { label: '广西', value: '广西' }, { label: '西藏', value: '西藏' }, { label: '宁夏', value: '宁夏' }, { label: '新疆', value: '新疆' }, { label: '香港', value: '香港' }, { label: '澳门', value: '澳门' } ], // 商品名称选项 productNameOptions: [ { label: '全部商品', value: 'all' }, { label: '罗曼粉', value: '罗曼粉' }, { label: '伊莎粉', value: '伊莎粉' }, { label: '罗曼灰', value: '罗曼灰' }, { label: '海蓝灰', value: '海蓝灰' }, { label: '海蓝褐', value: '海蓝褐' }, { label: '绿壳', value: '绿壳' }, { label: '粉一', value: '粉一' }, { label: '粉二', value: '粉二' }, { label: '粉八', value: '粉八' }, { label: '京粉1号', value: '京粉1号' }, { label: '京红', value: '京红' }, { label: '京粉6号', value: '京粉6号' }, { label: '京粉3号', value: '京粉3号' }, { label: '农大系列', value: '农大系列' }, { label: '黑鸡土蛋', value: '黑鸡土蛋' }, { label: '双黄蛋', value: '双黄蛋' }, { label: '大午金凤', value: '大午金凤' }, { label: '黑凤', value: '黑凤' } ], // 价格范围选项 priceOptions: [ { label: '全部价格', value: [0, 100] }, { label: '0-20元', value: [0, 20] }, { label: '20-50元', value: [20, 50] }, { label: '50-100元', value: [50, 100] }, { label: '100元以上', value: [100, 9999] } ], // 排序方式选项 sortOptions: [ { label: '默认排序', value: 'default' }, { label: '价格从低到高', value: 'price_asc' }, { label: '价格从高到低', value: 'price_desc' }, { label: '最新发布', value: 'newest' } ], }, // 跳转到聊天页面 navigateToChat() { wx.navigateTo({ url: '/pages/chat/index', success: function () { console.log('成功跳转到聊天页面'); }, fail: function (error) { console.error('跳转到聊天页面失败:', error); wx.showToast({ title: '跳转失败,请稍后重试', icon: 'none' }); } }); }, // 跳转到客服列表页面 navigateToCustomerService(e) { // 获取按钮类型(seller=我要买蛋,buyer=我要卖蛋) const userType = e.currentTarget.dataset.type; wx.navigateTo({ url: `/pages/customer-service/index?type=${userType}`, success: function () { console.log('成功跳转到客服列表页面,类型:', userType); }, fail: function (error) { console.error('跳转到客服列表页面失败:', error); wx.showToast({ title: '跳转失败,请稍后重试', icon: 'none' }); } }); }, // 跳转到我要卖蛋页面 navigateToSettlement() { wx.navigateTo({ url: '/pages/settlement/index', success: function () { console.log('成功跳转到我要卖蛋页面'); }, fail: function (error) { console.error('跳转到我要卖蛋页面失败:', error); wx.showToast({ title: '跳转失败,请稍后重试', icon: 'none' }); } }); }, // 切换侧边栏显示 toggleSidebar() { if (this.data.isDragging) { return; } const newShowSidebar = !this.data.showSidebar; if (newShowSidebar) { this.checkGoodsManagePermission(); } this.setData({ showSidebar: newShowSidebar }); }, // 检查用户是否有货源管理权限 checkGoodsManagePermission() { const users = wx.getStorageSync('users') || {}; const userId = wx.getStorageSync('userId'); let userPhone = null; if (userId && users[userId] && users[userId].phoneNumber) { userPhone = users[userId].phoneNumber; } else { const userInfo = wx.getStorageSync('userInfo'); if (userInfo && userInfo.phoneNumber) { userPhone = userInfo.phoneNumber; } else { userPhone = wx.getStorageSync('phoneNumber'); } } if (!userPhone) { console.log('用户未绑定手机号,无货源管理权限'); this.setData({ hasGoodsManagePermission: false }); return; } API.checkPersonnelByPhone(userPhone).then(res => { console.log('货源管理权限检查结果:', res); this.setData({ hasGoodsManagePermission: res.exists }); }).catch(err => { console.error('检查货源管理权限失败:', err); this.setData({ hasGoodsManagePermission: false }); }); }, // 切换按钮显示/隐藏到侧边栏 toggleSidebarBtn() { this.setData({ sidebarBtnHidden: !this.data.sidebarBtnHidden }); wx.setStorageSync('sidebarBtnHidden', !this.data.sidebarBtnHidden); }, // 触摸开始事件 handleTouchStart(e) { this.setData({ isDragging: false, startY: e.touches[0].clientY }); }, // 触摸移动事件 handleTouchMove(e) { const moveY = e.touches[0].clientY; const diffY = moveY - this.data.startY; if (Math.abs(diffY) > 20) { this.setData({ isDragging: true }); let newTop = this.data.sidebarBtnTop + diffY * 3; const systemInfo = wx.getSystemInfoSync(); const screenHeight = systemInfo.screenHeight * 2; const btnHeight = 90; const minTop = screenHeight * 0.2; const maxTop = screenHeight * 0.6; if (newTop < minTop) { newTop = minTop; } else if (newTop > maxTop) { newTop = maxTop; } this.setData({ sidebarBtnTop: newTop, startY: moveY }); } }, // 触摸结束事件 handleTouchEnd(e) { // 如果拖动距离超过屏幕高度的1/3,隐藏按钮 const moveY = e.changedTouches[0].clientY; const diffY = moveY - this.data.startY; const screenHeight = wx.getSystemInfoSync().screenHeight * 2; // 转换为rpx if (Math.abs(diffY) > screenHeight / 3) { this.setData({ sidebarBtnTop: -100 // 隐藏按钮 }); wx.setStorageSync('sidebarBtnTop', -100); wx.setStorageSync('sidebarBtnHidden', true); } else { wx.setStorageSync('sidebarBtnTop', this.data.sidebarBtnTop); wx.setStorageSync('sidebarBtnHidden', false); } this.setData({ isDragging: false }); }, onLoad() { // 获取系统信息,处理iOS特定兼容性 const systemInfo = wx.getSystemInfoSync(); const isIOS = systemInfo.system.toLowerCase().includes('ios'); const screenHeight = systemInfo.screenHeight * 2; // 设置iOS特定标志 if (isIOS) { this.setData({ isIOS: true }); } const savedBtnTop = wx.getStorageSync('sidebarBtnTop'); const savedBtnHidden = wx.getStorageSync('sidebarBtnHidden'); let defaultTop = screenHeight * 0.5; if (savedBtnTop !== '' && savedBtnTop !== -100) { const minTop = screenHeight * 0.2; const maxTop = screenHeight * 0.6; if (savedBtnTop >= minTop && savedBtnTop <= maxTop) { defaultTop = savedBtnTop; } } this.setData({ sidebarBtnTop: defaultTop, sidebarBtnHidden: false, isSearchBarFullyHidden: false, lastScrollTop: 0 }); this.checkAndRestoreLoginStatus() this.loadCategories() this.loadGoods() // 计算搜索区域高度 setTimeout(() => { const query = wx.createSelectorQuery(); query.select('.top-section-container').boundingClientRect(); query.select('.category-section').boundingClientRect(); query.exec((res) => { if (res[0] && res[1]) { const searchHeight = res[0].height; const categoryHeight = res[1].height; const totalHeight = searchHeight + categoryHeight; this.setData({ searchSectionHeight: searchHeight, categorySectionHeight: categoryHeight, totalHeaderHeight: totalHeight }); } }); }, 500); // 添加收藏状态变化事件监听 const app = getApp(); this.favoriteChangedHandler = (data) => { console.log('收到收藏状态变化通知:', data); // 更新商品列表中对应商品的收藏状态 const updatedGoods = this.data.goods.map(item => { if (String(item.productId || item.id) === data.productId) { return { ...item, isFavorite: data.isFavorite }; } return item; }); this.setData({ goods: updatedGoods }, () => { // 重新应用筛选条件,确保显示的商品收藏状态也更新 const filteredGoods = this.applyFilters(this.data.goods, true); this.setData({ filteredGoods: filteredGoods, }); }); }; app.eventBus.on('favoriteChanged', this.favoriteChangedHandler); }, onShow: function () { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 0 }); } const app = getApp(); app.updateCurrentTab('index'); app.globalData.showTabBar = true; const savedBtnHidden = wx.getStorageSync('sidebarBtnHidden'); // 只有在返回时才恢复按钮状态(刷新页面不恢复) if (this.data.isPageHidden) { this.setData({ sidebarBtnHidden: savedBtnHidden || false, isPageHidden: false }); } this.setData({ isSearchBarFullyHidden: false, lastScrollTop: 0 }); this.checkAndRestoreLoginStatus() }, onHide: function () { this.setData({ sidebarBtnHidden: true, isPageHidden: true }); }, onUnload: function () { // 页面卸载时移除收藏状态变化事件监听 const app = getApp(); if (this.favoriteChangedHandler) { app.eventBus.off('favoriteChanged', this.favoriteChangedHandler); console.log('移除收藏状态变化事件监听'); } }, onPullDownRefresh: function () { this.onRefresh() }, onRestore: function () { this.setData({ isRefreshing: false }) }, onRefresh: function () { if (this.data.isRefreshing) { return } // 保存当前筛选条件,用于后续验证一致性 const currentCategory = this.data.selectedCategory; const currentKeyword = this.data.searchKeyword; const currentRegion = this.data.selectedRegion; this.setData({ isRefreshing: true, page: 1, soldOutPage: 1, hasMoreData: true, goods: [], // 下拉刷新时清空商品数组,避免旧数据影响排序 filteredGoods: [], // 清除缓存以确保获取最新数据 categoryQueryCache: {}, lastDataTimestamp: 0, // 保存当前筛选条件,用于验证请求结果 refreshCategory: currentCategory, refreshKeyword: currentKeyword, refreshRegion: currentRegion, // 下拉刷新时确保从published状态开始加载 isQueryingSoldOut: false, publishedHasMore: true }) const timestamp = new Date().getTime(); const categoryParam = currentCategory === '全部' ? '' : currentCategory; const pageSize = this.data.pageSize; // 强制刷新:清除所有缓存并重新从数据库加载 this.setData({ // 清除商品数据缓存 goodsCache: [], // 重置缓存时间戳 lastDataTimestamp: 0 }); // 先只查询published状态的商品 const statusList = ['published']; const apiParams = { timestamp: timestamp, viewMode: 'shopping', page: 1, pageSize: pageSize, keyword: currentKeyword } // 只有非全部分类时才传递category参数 if (categoryParam) { apiParams.category = categoryParam } API.getProductList(statusList, apiParams) .then(res => { // 验证当前筛选条件是否与刷新开始时一致 if (currentCategory !== this.data.selectedCategory || currentKeyword !== this.data.searchKeyword || currentRegion !== this.data.selectedRegion) { console.log('筛选条件已变更,忽略此次刷新结果'); this.setData({ isRefreshing: false }); return; } this.setData({ isRefreshing: false }) if (res.success && res.products) { this.processRefreshData(res.products) wx.showToast({ title: '刷新成功', icon: 'success', duration: 400 }) } else if (res.products.length === 0) { // 如果published状态没有商品,则查询sold_out状态 console.log('没有published状态的商品,查询sold_out状态的商品'); const apiParams = { timestamp: timestamp, viewMode: 'shopping', page: 1, pageSize: pageSize, keyword: currentKeyword } // 只有非全部分类时才传递category参数 if (categoryParam) { apiParams.category = categoryParam } API.getProductList(['sold_out'], apiParams) .then(soldOutRes => { // 验证当前筛选条件是否与刷新开始时一致 if (currentCategory !== this.data.selectedCategory || currentKeyword !== this.data.searchKeyword || currentRegion !== this.data.selectedRegion) { console.log('筛选条件已变更,忽略此次刷新结果(sold_out)'); this.setData({ isRefreshing: false }); return; } this.setData({ isRefreshing: false }); if (soldOutRes.success && soldOutRes.products && soldOutRes.products.length > 0) { this.processRefreshData(soldOutRes.products); wx.showToast({ title: '刷新成功', icon: 'success', duration: 1500 }); } else { this.setData({ isLoading: false, loadingMore: false }); } }) .catch(err => { this.setData({ isRefreshing: false }); console.error('刷新sold_out商品数据失败:', err); wx.showToast({ title: '刷新失败,请稍后重试', icon: 'none', duration: 2000 }); }); } else { this.setData({ isLoading: false, loadingMore: false }) } }) .catch(err => { // 验证当前筛选条件是否与刷新开始时一致 if (currentCategory !== this.data.selectedCategory || currentKeyword !== this.data.searchKeyword || currentRegion !== this.data.selectedRegion) { console.log('筛选条件已变更,忽略此次刷新错误'); this.setData({ isRefreshing: false }); return; } this.setData({ isRefreshing: false }) console.error('刷新商品数据失败:', err) wx.showToast({ title: '刷新失败,请稍后重试', icon: 'none', duration: 2000 }) }) }, onReachBottom: function () { this.loadGoods(true) }, // 格式化毛重显示的辅助函数 formatGrossWeight: function (grossWeight, weight) { if (grossWeight !== null && grossWeight !== undefined && grossWeight !== '') { return grossWeight; } if (weight !== null && weight !== undefined && weight !== '') { return weight; } return ""; }, // 提取地区中的省份信息 extractProvince: function (region) { if (!region || typeof region !== 'string') { return region; } const provinceEndIndex = region.indexOf('省'); const autonomousRegionEndIndex = region.indexOf('自治区'); const municipalityEndIndex = region.indexOf('市'); const specialRegionEndIndex = region.indexOf('特别行政区'); if (provinceEndIndex !== -1) { return region.substring(0, provinceEndIndex + 1); } else if (autonomousRegionEndIndex !== -1) { return region.substring(0, autonomousRegionEndIndex + 3); } else if (specialRegionEndIndex !== -1) { return region.substring(0, specialRegionEndIndex + 5); } else if (municipalityEndIndex === 2) { return region.substring(0, municipalityEndIndex + 1); } return region; }, // 格式化商品规格显示 - 只显示前两个,后面加... formatSpecification: function (spec, yolk) { if (!spec || spec === '无') { return { displaySpec: '无', displayYolk: yolk && yolk !== '无' ? yolk : '' }; } // 按常见的分隔符分割规格 const separators = [',', ',', '、', '|', ';', ';']; let parts = [spec]; for (let separator of separators) { if (spec.includes(separator)) { parts = spec.split(separator); break; } } // 清理空值并限制为前两个 const cleanParts = parts .map(part => part.trim()) .filter(part => part && part !== '无') .slice(0, 2); let displaySpec = cleanParts.join(' | '); // 如果原规格分割后超过两个部分,添加省略号 if (cleanParts.length < parts.filter(part => part.trim() && part.trim() !== '无').length) { displaySpec += '...'; } return { displaySpec, displayYolk: yolk && yolk !== '无' ? yolk : '' }; }, // 处理商品数据 - 淘宝风格 processGoodsData: function (products, isLoadMore = false) { let newGoods = products.map(product => { const imageUrls = product.imageUrls || product.images || []; const formattedImageUrls = Array.isArray(imageUrls) ? imageUrls : [imageUrls]; // 确保商品ID的一致性 const productId = product.productId || product.id; // 预处理媒体URL,添加类型信息 const mediaItems = formattedImageUrls.map(url => { return { url: url, type: isVideoUrl(url) ? 'video' : 'image' }; }); // 计算库存总数 - 支持逗号分隔的数字字符串 const calculateTotalStock = (value) => { if (!value) return 0; if (typeof value === 'string') { // 支持逗号分隔的数字字符串,如 "23,34,24" return value.split(/[,,、]/).map(item => parseInt(item.trim()) || 0).reduce((sum, num) => sum + num, 0); } return parseInt(value) || 0; }; // 优化库存计算 - 尝试多个字段 const minOrder = calculateTotalStock(product.minOrder); const quantity = calculateTotalStock(product.quantity); const stock = calculateTotalStock(product.stock); const inventory = calculateTotalStock(product.inventory); const availableStock = calculateTotalStock(product.availableStock); const totalAvailable = calculateTotalStock(product.totalAvailable); // 优先使用最具体的库存字段 const primaryStock = quantity || minOrder || stock || inventory || availableStock || totalAvailable; const totalStock = primaryStock; // 智能库存显示 - 库存>=10000显示"库存充足",库存=0显示"暂无",其他显示具体数字 let displayStock; if (totalStock >= 10000) { // 库存>=10000时显示"库存充足" displayStock = '充足'; } else if (totalStock === 0) { // 库存=0时显示"暂无" displayStock = '暂无'; } else { // 其他情况显示具体数字 displayStock = totalStock; } // 格式化规格显示 const formattedSpec = this.formatSpecification(product.specification || product.spec || '', product.yolk || ''); return { ...product, id: productId, // 统一使用id字段 productId: productId, // 同时保留productId字段 category: product.category || '', fullRegion: product.region || '', region: product.region ? this.extractProvince(product.region) : '', grossWeight: product.grossWeight || product.weight || '', displayGrossWeight: product.grossWeight || product.weight || '', status: product.status, createdAt: product.created_at || product.createTime || null, reservedCount: product.reservedCount || product.selected || 0, reservedCountDisplay: product.reservedCount || product.selected || 0, sales: product.sales || product.reservedCount || Math.floor(Math.random() * 1000) + 100, product_contact: product.product_contact || '', contact_phone: product.contact_phone || '', supplyStatus: product.supplyStatus || '', sourceType: product.sourceType || '', negotiateStatus: '可议价', isReserved: false, isFavorite: false, currentImageIndex: 0, imageUrls: formattedImageUrls, // 添加预处理后的媒体数据,包含类型信息 mediaItems: mediaItems, totalStock: displayStock, // 使用优化后的库存显示值 originalTotalStock: totalStock, // 保留原始计算值用于调试 displaySpecification: formattedSpec.displaySpec, // 格式化后的规格 displayYolk: formattedSpec.displayYolk, // 格式化后的蛋黄 price: product.price !== undefined ? product.price : '' // 确保price字段存在 } }) // 过滤隐藏状态的商品,并确保商品对象有效 newGoods = newGoods.filter(item => { // 过滤隐藏状态的商品 if ((item.status || '').toLowerCase() === 'hidden') { return false; } // 确保商品对象有必要的字段 return item && item.id && item.name; }); // 先对新商品进行内部查重 const uniqueNewGoodsMap = new Map(); newGoods.forEach(item => { if (!uniqueNewGoodsMap.has(item.id)) { uniqueNewGoodsMap.set(item.id, item); } }); newGoods = Array.from(uniqueNewGoodsMap.values()); // 更新商品的收藏状态 this.updateGoodsFavoriteStatus(newGoods, isLoadMore) // 只在第一页或刷新时在商品列表最前面插入广告,且只插入一次 let adSlotsAdded = false; if ((!isLoadMore || this.data.page === 1) && newGoods.length > 0) { // 确保广告位在最前面 const adSlots = [ { id: 'ad_slot_1', name: '广告位1', imageUrls: ['/images/轮播图1.jpg'], mediaItems: [{ url: '/images/轮播图1.jpg', type: 'image' }], price: 0, adType: 'full_card', isAd: true }, { id: 'ad_slot_2', name: '广告位2', imageUrls: ['/images/轮播图1.jpg'], mediaItems: [{ url: '/images/轮播图1.jpg', type: 'image' }], price: 0, adType: 'half_image', isAd: true } ]; newGoods = [...adSlots, ...newGoods]; adSlotsAdded = true; } let updatedGoods = [] if (isLoadMore) { // 加载更多时,去重处理 const existingIds = new Set(this.data.goods.map(item => item.id)); const uniqueNewGoods = newGoods.filter(item => !existingIds.has(item.id)); updatedGoods = [...this.data.goods, ...uniqueNewGoods]; } else { // 首次加载或切换分类时,直接使用去重后的新商品 updatedGoods = newGoods } const filteredGoods = this.applyFilters(updatedGoods, true) const groupedGoods = this.groupGoodsForStaggeredLayout(filteredGoods); this.setData({ goods: updatedGoods, filteredGoods: filteredGoods, groupedGoods: groupedGoods, loadingMore: false, isLoading: false, isRefreshing: false, // 根据当前是否在查询售空商品来更新对应的页码 // soldOutPage 已经在 loadSoldOutData 函数中直接更新 page: this.data.isQueryingSoldOut ? this.data.page : this.data.page + 1, lastDataTimestamp: new Date().getTime() }) // 检查过滤后的非广告商品数量,如果不足6个,则自动触发上拉加载更多 // 对于已发布商品,在非加载更多模式下触发;对于售空商品,在加载更多模式下触发 const nonAdGoodsCount = filteredGoods.filter(item => !item.isAd).length; if (nonAdGoodsCount < 6 && !this.data.loadingMore && !this.data.isLoading) { if (!isLoadMore || this.data.isQueryingSoldOut) { console.log('商品数量不足6个,自动触发上拉加载更多'); // 使用setTimeout确保当前任务完成后再触发加载更多 setTimeout(() => { this.loadGoods(true); }, 100); } } }, // 处理刷新数据 - 查重并保持原有商品 processRefreshData: function (newProducts) { let newGoods = newProducts.map(product => { const imageUrls = product.imageUrls || product.images || []; const formattedImageUrls = Array.isArray(imageUrls) ? imageUrls : [imageUrls]; // 确保商品ID的一致性 const productId = product.productId || product.id; // 预处理媒体URL,添加类型信息 const mediaItems = formattedImageUrls.map(url => { return { url: url, type: isVideoUrl(url) ? 'video' : 'image' }; }); // 计算库存总数 - 支持逗号分隔的数字字符串 const calculateTotalStock = (value) => { if (!value) return 0; if (typeof value === 'string') { // 支持逗号分隔的数字字符串,如 "23,34,24" return value.split(/[,,、]/).map(item => parseInt(item.trim()) || 0).reduce((sum, num) => sum + num, 0); } return parseInt(value) || 0; }; // 优化库存计算 - 尝试多个字段 const minOrder = calculateTotalStock(product.minOrder); const quantity = calculateTotalStock(product.quantity); const stock = calculateTotalStock(product.stock); const inventory = calculateTotalStock(product.inventory); const availableStock = calculateTotalStock(product.availableStock); const totalAvailable = calculateTotalStock(product.totalAvailable); // 优先使用最具体的库存字段 const primaryStock = quantity || minOrder || stock || inventory || availableStock || totalAvailable; const totalStock = primaryStock; // 智能库存显示 - 库存>=10000显示"库存充足",库存=0显示"暂无",其他显示具体数字 let displayStock; if (totalStock >= 10000) { // 库存>=10000时显示"库存充足" displayStock = '充足'; } else if (totalStock === 0) { // 库存=0时显示"暂无" displayStock = '暂无'; } else { // 其他情况显示具体数字 displayStock = totalStock; } // 格式化规格显示 const formattedSpec = this.formatSpecification(product.specification || product.spec || '', product.yolk || ''); return { ...product, id: productId, // 统一使用id字段 productId: productId, // 同时保留productId字段 category: product.category || '', fullRegion: product.region || '', region: product.region ? this.extractProvince(product.region) : '', grossWeight: product.grossWeight || product.weight || '', displayGrossWeight: product.grossWeight || product.weight || '', status: product.status, createdAt: product.created_at || product.createTime || null, reservedCount: product.reservedCount || product.selected || 0, reservedCountDisplay: product.reservedCount || product.selected || 0, sales: product.sales || product.reservedCount || Math.floor(Math.random() * 1000) + 100, product_contact: product.product_contact || '', contact_phone: product.contact_phone || '', supplyStatus: product.supplyStatus || '', sourceType: product.sourceType || '', negotiateStatus: '可议价', isReserved: false, isFavorite: false, currentImageIndex: 0, imageUrls: formattedImageUrls, // 添加预处理后的媒体数据,包含类型信息 mediaItems: mediaItems, totalStock: displayStock, // 使用优化后的库存显示值 originalTotalStock: totalStock, // 保留原始计算值用于调试 displaySpecification: formattedSpec.displaySpec, // 格式化后的规格 displayYolk: formattedSpec.displayYolk, // 格式化后的蛋黄 price: product.price !== undefined ? product.price : '' // 确保price字段存在 } }) // 过滤隐藏状态的商品,并确保商品对象有效 newGoods = newGoods.filter(item => { // 过滤隐藏状态的商品 if ((item.status || '').toLowerCase() === 'hidden') { return false; } // 确保商品对象有必要的字段 return item && item.id && item.name; }); // 对新商品进行内部查重 const newGoodsMap = new Map(); newGoods.forEach(item => { if (!newGoodsMap.has(item.id)) { newGoodsMap.set(item.id, item); } }); // 下拉刷新时完全使用新获取的商品数据,不再与旧数据合并 const newGoodsOnly = Array.from(newGoodsMap.values()); // 对新数据进行过滤和排序 const filteredGoods = this.applyFilters(newGoodsOnly, true) const groupedGoods = this.groupGoodsForStaggeredLayout(filteredGoods); const currentCategory = this.data.selectedCategory === '全部' ? '' : this.data.selectedCategory; const currentKeyword = this.data.searchKeyword; const cacheKey = `${currentCategory}_${currentKeyword}`; // 下拉刷新后检查返回的商品数量,决定是否还有更多published商品 const hasMorePublished = newGoodsOnly.length >= this.data.pageSize; this.setData({ goods: newGoodsOnly, filteredGoods: filteredGoods, groupedGoods: groupedGoods, loadingMore: false, isLoading: false, page: this.data.page + 1, // 确保下拉刷新后继续加载published状态商品 isQueryingSoldOut: !hasMorePublished, publishedHasMore: hasMorePublished, // 如果切换到售空商品,重置售空商品页码 soldOutPage: !hasMorePublished ? 1 : this.data.soldOutPage, // 更新缓存时间戳 lastDataTimestamp: new Date().getTime() }) // 更新分类查询缓存 const newCategoryQueryCache = { ...this.data.categoryQueryCache }; newCategoryQueryCache[cacheKey] = newGoodsOnly; this.setData({ categoryQueryCache: newCategoryQueryCache }) // 检查过滤后的非广告商品数量,如果不足6个,则自动触发上拉加载更多 // 对于已发布商品,在非加载更多模式下触发;对于售空商品,在加载更多模式下触发 const nonAdGoodsCount = filteredGoods.filter(item => !item.isAd).length; if (nonAdGoodsCount < 6 && !this.data.loadingMore && !this.data.isLoading) { console.log('刷新后商品数量不足6个,自动触发上拉加载更多'); // 使用setTimeout确保当前任务完成后再触发加载更多 setTimeout(() => { this.loadGoods(true); }, 100); } }, // 插入广告位数据 insertAdSlots: function (goods) { if (!goods || goods.length === 0) return goods const adSlot1 = { id: 'ad_slot_1', name: '广告位1', imageUrls: ['/images/轮播图1.jpg'], mediaItems: [{ url: '/images/轮播图1.jpg', type: 'image' }], price: 0, adType: 'full_card', isAd: true } const adSlot2 = { id: 'ad_slot_2', name: '广告位2', imageUrls: ['/images/轮播图1.jpg'], mediaItems: [{ url: '/images/轮播图1.jpg', type: 'image' }], price: 0, adType: 'half_image', isAd: true } return [adSlot1, adSlot2, ...goods] }, // 广告点击事件处理 onAdClick: function (e) { const adSlot = e.currentTarget.dataset.ad; let imageSrc = e.currentTarget.dataset.src; // 如果没有从data-src获取到,尝试从图片元素直接获取src if (!imageSrc) { imageSrc = e.currentTarget.src; } console.log('广告被点击, 广告位:', adSlot); console.log('广告图片路径:', imageSrc); // 直接预览广告图片(单击触发) const validImageUrls = [imageSrc]; if (validImageUrls.length > 0 && validImageUrls[0]) { this.setData({ previewImageUrls: validImageUrls, previewImageIndex: 0, showImagePreview: true }); console.log('广告图片预览已打开,图片URL:', validImageUrls[0]); } else { console.error('无法获取广告图片路径'); wx.showToast({ title: '图片加载失败', icon: 'none' }); } }, // 加载商品分类列表 loadCategories: function () { API.getProductCategories().then(categories => { if (categories && categories.length > 0) { this.setData({ categories: categories }); } }).catch(err => { console.error('加载分类失败:', err); }); }, // 加载商品数据 - 优化版带缓存,支持状态优先级 loadGoods: function (isLoadMore = false, forceRefresh = false) { // 当正在加载售空商品时,即使hasMoreData为false也继续加载 if (isLoadMore && !this.data.hasMoreData && !this.data.isQueryingSoldOut) { return } console.log('loadGoods - 开始加载商品,isLoadMore:', isLoadMore, 'forceRefresh:', forceRefresh); console.log('loadGoods - 当前搜索关键词:', this.data.searchKeyword); console.log('loadGoods - 当前分类:', this.data.selectedCategory); const currentCategory = this.data.selectedCategory === '全部' ? '' : this.data.selectedCategory; const currentKeyword = this.data.searchKeyword; const cacheKey = `${currentCategory}_${currentKeyword}`; const now = new Date().getTime(); const timestamp = new Date().getTime(); // 如果正在加载sold_out,继续加载sold_out if (isLoadMore && this.data.isQueryingSoldOut) { this.loadSoldOutData(cacheKey, currentKeyword, currentCategory, timestamp, isLoadMore); return; } // 只有非加载更多模式才使用缓存 if (!isLoadMore && !forceRefresh && this.data.categoryQueryCache[cacheKey] && (now - this.data.lastDataTimestamp) < this.data.cacheValidDuration) { // 使用缓存数据 const cachedGoods = this.data.categoryQueryCache[cacheKey]; this.setData({ lastDataTimestamp: now }); this.processCachedGoods(cachedGoods, isLoadMore); return; } // 筛选时不显示骨架屏 if (isLoadMore) { this.setData({ loadingMore: true }) } else if (!forceRefresh) { // 只有非筛选的首次加载才显示骨架屏 this.setData({ isLoading: true, publishedHasMore: true, soldOutPage: 1 }) } const page = isLoadMore ? this.data.page : 1 const pageSize = this.data.pageSize; // 构建API请求参数 const apiParams = { timestamp: timestamp, viewMode: 'shopping', page: page, pageSize: pageSize, keyword: currentKeyword } // 只有非全部分类时才传递category参数 if (currentCategory) { apiParams.category = currentCategory } console.log('loadGoods - API请求参数:', apiParams); // 先只查询published状态的商品 const statusList = ['published']; console.log('loadGoods - 查询状态列表:', statusList); // 取消正在进行的请求 if (this.data.currentRequestTask) { this.data.currentRequestTask.abort(); console.log('已取消旧的API请求'); } // 直接使用API.getProductList,并在请求完成后清除请求任务标记 API.getProductList(statusList, apiParams) .then(res => { wx.hideLoading(); console.log(`===== ${statusList.join(', ')}状态查询结果 =====`); console.log('res.success:', res.success); console.log('res.products:', res.products); console.log('res.products.length:', res.products ? res.products.length : 'undefined'); console.log('page:', page); // 如果有published商品,直接处理 if (res.success && res.products && res.products.length > 0) { console.log('有published商品,处理商品数据'); // 使用返回的商品数量来判断是否还有下一页 const publishedHasMore = res.products.length === pageSize; // 更新缓存(加载更多时追加数据) const updatedCache = { ...this.data.categoryQueryCache }; if (isLoadMore && updatedCache[cacheKey]) { // 追加新数据到缓存 const existingIds = new Set(updatedCache[cacheKey].map(item => item.id)); const newProducts = res.products.filter(item => !existingIds.has(item.id)); updatedCache[cacheKey] = [...updatedCache[cacheKey], ...newProducts]; } else { // 首次加载或刷新时替换缓存 updatedCache[cacheKey] = res.products; } this.setData({ hasMoreData: true, // 保持hasMoreData为true,以便在已发布商品加载完毕后继续加载售空商品 isQueryingSoldOut: !publishedHasMore, // 当已发布商品加载完毕时,切换到加载售空商品 publishedHasMore: publishedHasMore, categoryQueryCache: updatedCache, lastDataTimestamp: now, goodsCache: updatedCache[cacheKey], // 当切换到加载售空商品时,重置售空商品的页码为1 soldOutPage: !publishedHasMore ? 1 : this.data.soldOutPage }); this.processGoodsData(res.products, isLoadMore); return; } // 如果没有published商品,查询sold_out状态 console.log('没有published商品,查询sold_out状态'); console.log('查询参数 - page:', page, 'pageSize:', pageSize, 'keyword:', currentKeyword, 'category:', currentCategory); this.setData({ isQueryingSoldOut: true, soldOutPage: 1, soldOutPageSize: pageSize }); this.loadSoldOutData(cacheKey, currentKeyword, currentCategory, timestamp, isLoadMore); return; }) .catch(err => { console.error('加载商品数据失败:', err); this.setData({ loadingMore: false, isLoading: false, isRefreshing: false }); }) }, // 加载sold_out数据 loadSoldOutData: function (cacheKey, currentKeyword, currentCategory, timestamp, isLoadMore) { const pageSize = this.data.soldOutPageSize || 8; const soldOutPageNum = this.data.soldOutPage || 1; console.log('加载sold_out数据 - page:', soldOutPageNum, 'pageSize:', pageSize); console.log('查询参数 - page:', soldOutPageNum, 'pageSize:', pageSize, 'keyword:', currentKeyword, 'category:', currentCategory); const apiParams = { timestamp: timestamp, viewMode: 'shopping', page: soldOutPageNum, pageSize: pageSize, keyword: currentKeyword } // 只有非全部分类时才传递category参数 if (currentCategory) { apiParams.category = currentCategory } API.getProductList(['sold_out'], apiParams) .then(soldOutRes => { console.log('===== sold_out状态查询结果 ====='); console.log('soldOutRes.success:', soldOutRes.success); console.log('soldOutRes.products:', soldOutRes.products); console.log('soldOutRes.products.length:', soldOutRes.products ? soldOutRes.products.length : 'undefined'); if (soldOutRes.success && soldOutRes.products && soldOutRes.products.length > 0) { // 使用返回的商品数量来判断是否还有下一页 const soldOutHasMore = soldOutRes.products.length === pageSize; // 更新缓存 const updatedCache = { ...this.data.categoryQueryCache }; const existingCache = updatedCache[cacheKey] || []; const existingIds = new Set(existingCache.map(item => item.id)); const uniqueSoldOutProducts = soldOutRes.products.filter(item => !existingIds.has(item.id)); updatedCache[cacheKey] = [...existingCache, ...uniqueSoldOutProducts]; this.processGoodsData(uniqueSoldOutProducts, isLoadMore); this.setData({ hasMoreData: soldOutHasMore, isQueryingSoldOut: soldOutHasMore, categoryQueryCache: updatedCache, lastDataTimestamp: new Date().getTime(), goodsCache: updatedCache[cacheKey], // 直接更新售空商品的页码 soldOutPage: soldOutPageNum + 1 }); console.log('sold_out数据加载完成,总商品数:', updatedCache[cacheKey].length, 'hasMoreData:', soldOutHasMore); } else { console.log('没有找到更多sold_out商品'); this.setData({ isQueryingSoldOut: false, hasMoreData: false, loadingMore: false, isLoading: false }); } }) .catch(err => { console.error('加载sold_out数据失败:', err); this.setData({ isQueryingSoldOut: false, loadingMore: false, isLoading: false, isRefreshing: false }); }); }, // 处理缓存的商品数据 processCachedGoods: function (cachedGoods, isLoadMore) { // 处理商品数据格式并去重 const goodsMap = new Map(); cachedGoods.forEach(product => { const imageUrls = product.imageUrls || product.images || []; const formattedImageUrls = Array.isArray(imageUrls) ? imageUrls : [imageUrls]; // 确保商品ID的一致性 const productId = product.productId || product.id; // 只有当商品ID不存在时才添加,避免重复 if (!goodsMap.has(productId)) { // 计算库存总数 - 支持逗号分隔的数字字符串 const calculateTotalStock = (value) => { if (!value) return 0; if (typeof value === 'string') { // 支持逗号分隔的数字字符串,如 "23,34,24" return value.split(/[,,、]/).map(item => parseInt(item.trim()) || 0).reduce((sum, num) => sum + num, 0); } return parseInt(value) || 0; }; // 优化库存计算 - 尝试多个字段 const minOrder = calculateTotalStock(product.minOrder); const quantity = calculateTotalStock(product.quantity); const stock = calculateTotalStock(product.stock); const inventory = calculateTotalStock(product.inventory); const availableStock = calculateTotalStock(product.availableStock); const totalAvailable = calculateTotalStock(product.totalAvailable); // 优先使用最具体的库存字段 const primaryStock = quantity || minOrder || stock || inventory || availableStock || totalAvailable; const totalStock = primaryStock; // 智能库存显示 - 库存>=10000显示"库存充足",库存=0显示"暂无",其他显示具体数字 let displayStock; if (totalStock >= 10000) { // 库存>=10000时显示"库存充足" displayStock = '库存充足'; } else if (totalStock === 0) { // 库存=0时显示"暂无" displayStock = '暂无'; } else { // 其他情况显示具体数字 displayStock = totalStock; } const processedProduct = { ...product, id: productId, // 统一使用id字段 productId: productId, // 同时保留productId字段 category: product.category || '', fullRegion: product.region || '', region: product.region ? this.extractProvince(product.region) : '', grossWeight: product.grossWeight || product.weight || '', displayGrossWeight: product.grossWeight || product.weight || '', status: product.status, createdAt: product.created_at || product.createTime || null, reservedCount: product.reservedCount || product.selected || 0, reservedCountDisplay: product.reservedCount || product.selected || 0, sales: product.sales || product.reservedCount || Math.floor(Math.random() * 1000) + 100, product_contact: product.product_contact || '', contact_phone: product.contact_phone || '', supplyStatus: product.supplyStatus || '', sourceType: product.sourceType || '', negotiateStatus: '可议价', isReserved: false, isFavorite: false, currentImageIndex: 0, imageUrls: formattedImageUrls, totalStock: displayStock, // 使用优化后的库存显示值 originalTotalStock: totalStock, // 保留原始计算值用于调试 price: product.price !== undefined ? product.price : '' // 确保price字段存在 }; goodsMap.set(productId, processedProduct); } }); // 转换为数组 const processedGoods = Array.from(goodsMap.values()); // 确保商品对象有效 const validGoods = processedGoods.filter(item => { // 确保商品对象有必要的字段 return item && item.id && item.name; }); // 更新收藏状态 this.updateGoodsFavoriteStatus(validGoods, false); // 应用筛选条件 const filteredGoods = this.applyFilters(validGoods, true); const groupedGoods = this.groupGoodsForStaggeredLayout(filteredGoods); this.setData({ goods: validGoods, filteredGoods: filteredGoods, groupedGoods: groupedGoods, loadingMore: false, isLoading: false, isRefreshing: false, // 确保下拉刷新状态被重置 hasMoreData: false // 缓存数据不分页 }); }, // 刷新商品列表 - 强制刷新机制 refreshGoodsList: function () { this.setData({ page: 1, hasMoreData: true, goods: [], filteredGoods: [], loadingMore: false, // 清除所有缓存以获取最新数据 categoryQueryCache: {}, lastDataTimestamp: 0, goodsCache: [] }, () => { console.log('refreshGoodsList:清除缓存并重新加载数据'); this.loadGoods(false, true); // 第二个参数true表示强制刷新 }) }, // 统一字段长度 normalizeFieldLength: function (item) { const normalized = { ...item } // 统一 name 字段长度为 20 字符 if (normalized.name) { normalized.name = normalized.name.length > 20 ? normalized.name.substring(0, 17) + '...' : normalized.name.padEnd(20, ' ') } // 统一 region 字段长度为 15 字符 if (normalized.region) { normalized.region = normalized.region.length > 15 ? normalized.region.substring(0, 12) + '...' : normalized.region.padEnd(15, ' ') } // 统一 grossWeight 字段长度为 10 字符 if (normalized.grossWeight) { normalized.grossWeight = normalized.grossWeight.length > 10 ? normalized.grossWeight.substring(0, 7) + '...' : normalized.grossWeight.padEnd(10, ' ') } return normalized }, // 应用筛选条件 applyFilters: function (goods, shouldSort = true) { let filtered = [...goods] console.log('applyFilters - 开始过滤,原始商品数量:', goods.length, '关键词:', this.data.searchKeyword); // 过滤商品:广告位不受影响,只显示有价格的商品 filtered = filtered.filter(item => { // 广告位不受影响 if (item.isAd) { return true; } // 只显示有价格的商品 return item.price && item.price !== ''; }); if (this.data.selectedCategory !== '全部') { const category = this.data.selectedCategory filtered = filtered.filter(item => item.isAd || (item.category === category)) console.log('applyFilters - 分类过滤后数量:', filtered.length); } if (this.data.searchKeyword) { const keyword = this.data.searchKeyword.toLowerCase() const originalLength = filtered.length; console.log('applyFilters - 搜索关键词:', keyword, '过滤前数量:', originalLength); // 记录每个商品的匹配情况 filtered = filtered.filter(item => { const nameMatch = (item.name || '').toLowerCase().includes(keyword); const productNameMatch = (item.productName || '').toLowerCase().includes(keyword); const specification = (item.specification || item.spec || '').toLowerCase(); const specMatch = specification.includes(keyword); const regionMatch = (item.region || '').toLowerCase().includes(keyword); const grossWeightMatch = (item.grossWeight || '').toLowerCase().includes(keyword); const yolkMatch = (item.yolk || '').toLowerCase().includes(keyword); const match = item.isAd || nameMatch || productNameMatch || specMatch || regionMatch || grossWeightMatch || yolkMatch; // 详细日志,记录每个商品的匹配字段 if (originalLength <= 20 || keyword === '41' || keyword === '43-44') { // 增加特定关键词的日志记录 console.log('商品匹配详情:', { name: item.name, productId: item.productId || item.id, keyword: keyword, name: item.name, productName: item.productName, specification: item.specification, spec: item.spec, formattedSpecification: specification, region: item.region, grossWeight: item.grossWeight, yolk: item.yolk, nameMatch: nameMatch, productNameMatch: productNameMatch, specMatch: specMatch, regionMatch: regionMatch, grossWeightMatch: grossWeightMatch, yolkMatch: yolkMatch, match: match }); } return match; }) console.log('applyFilters - 搜索过滤后数量:', filtered.length); } // 应用高级筛选中的地区筛选 if (this.data.advancedFilters.region !== 'all') { const selectedRegion = this.data.advancedFilters.region filtered = filtered.filter(item => item.isAd || (item.region && item.region.includes(selectedRegion))) } // 同时支持原有的地区筛选(为了向后兼容) else if (this.data.selectedRegion !== '全国') { const selectedRegion = this.data.selectedRegion filtered = filtered.filter(item => item.isAd || (item.region && item.region.includes(selectedRegion))) } // 应用高级筛选中的蛋壳颜色筛选 if (this.data.advancedFilters.shellColor !== 'all') { const selectedShellColor = this.data.advancedFilters.shellColor filtered = filtered.filter(item => item.isAd || (item.shellColor && item.shellColor.includes(selectedShellColor))) } // 应用高级筛选中的蛋黄类型筛选 if (this.data.advancedFilters.yolkType !== 'all') { const selectedYolkType = this.data.advancedFilters.yolkType filtered = filtered.filter(item => item.isAd || (item.yolk && item.yolk.includes(selectedYolkType))) } // 应用高级筛选中的规格筛选 if (this.data.advancedFilters.specification !== 'all') { const selectedSpecification = this.data.advancedFilters.specification filtered = filtered.filter(item => item.isAd || ((item.specification || item.spec) && (item.specification || item.spec).includes(selectedSpecification))) } // 应用高级筛选中的商品名称筛选 if (this.data.advancedFilters.productName !== 'all') { const selectedProductName = this.data.advancedFilters.productName filtered = filtered.filter(item => item.isAd || (item.productName && item.productName.includes(selectedProductName))) } // 去重处理 - 确保返回的商品列表中没有重复的商品 const uniqueGoodsMap = new Map(); filtered.forEach(item => { // 使用id作为唯一标识,如果id不存在则使用productId const uniqueId = item.productId || item.id; if (uniqueId && !uniqueGoodsMap.has(uniqueId)) { uniqueGoodsMap.set(uniqueId, item); } // 对于广告位,使用它们的唯一id else if (item.isAd && !uniqueGoodsMap.has(item.id)) { uniqueGoodsMap.set(item.id, item); } }); filtered = Array.from(uniqueGoodsMap.values()); if (shouldSort) { // First, separate items by status const publishedItems = [] const soldOutItems = [] filtered.forEach(item => { const status = (item.status || '').toLowerCase() if (status === 'published') { publishedItems.push(item) } else if (status === 'sold_out') { soldOutItems.push(item) } }) // Define the sorting function: only by createdAt descending order const sortByCreatedAtDesc = (a, b) => { const createdAtA = new Date(a.createdAt || 0).getTime() const createdAtB = new Date(b.createdAt || 0).getTime() return createdAtB - createdAtA } // Sort each group by createdAt descending publishedItems.sort(sortByCreatedAtDesc) soldOutItems.sort(sortByCreatedAtDesc) // Combine groups: all published first, then all sold_out filtered = [...publishedItems, ...soldOutItems] } // 统一字段长度 filtered = filtered.map(item => this.normalizeFieldLength(item)) return filtered }, // 瀑布流布局 - 淘宝风格左右交替 distributeToColumns: function (goods) { if (!goods || goods.length === 0) { return { leftColumnGoods: [], rightColumnGoods: [] } } const leftColumn = [] const rightColumn = [] for (let i = 0; i < goods.length; i += 2) { const currentRow = Math.floor(i / 2) const isEvenRow = currentRow % 2 === 0 if (i < goods.length) { const item = { ...goods[i], isLong: isEvenRow } leftColumn.push(item) } if (i + 1 < goods.length) { const item = { ...goods[i + 1], isLong: !isEvenRow } rightColumn.push(item) } } return { leftColumnGoods: leftColumn, rightColumnGoods: rightColumn } }, // 分组商品用于交错布局(左长右短,左短右长交替) groupGoodsForStaggeredLayout: function (goods) { if (!goods || goods.length === 0) { return [] } const grouped = [] const len = goods.length for (let i = 0; i < len; i += 2) { const row = [] // 第一个商品:如果是偶数行(index为偶数),则是长商品;如果是奇数行,则是短商品 if (i < len) { row.push({ ...goods[i], isLong: i % 2 === 0 // 偶数索引为长商品 }) } // 第二个商品:与第一个相反 if (i + 1 < len) { row.push({ ...goods[i + 1], isLong: i % 2 !== 0 // 奇数索引为长商品 }) } grouped.push(row) } return grouped }, // 瀑布流布局:将商品分配到左右两列 // 规则:左长右短 -> 左短右长 交替排列 // 偶数行(0,2,4...):左长右短 // 奇数行(1,3,5...):左短右长 distributeToColumns: function (goods) { if (!goods || goods.length === 0) { return { leftColumnGoods: [], rightColumnGoods: [] } } const leftColumn = [] const rightColumn = [] const rowCount = Math.ceil(goods.length / 2) for (let i = 0; i < goods.length; i += 2) { const currentRow = Math.floor(i / 2) const isEvenRow = currentRow % 2 === 0 if (i < goods.length) { leftColumn.push({ ...goods[i], isLong: isEvenRow // 偶数行左边为长,奇数行左边为短 }) } if (i + 1 < goods.length) { rightColumn.push({ ...goods[i + 1], isLong: !isEvenRow // 偶数行右边为短,奇数行右边为长 }) } } return { leftColumnGoods: leftColumn, rightColumnGoods: rightColumn } }, // 搜索输入(带防抖) onSearchInput: function (e) { const keyword = e.detail.value this.setData({ searchKeyword: keyword }) // 清除之前的定时器 if (this.data.searchDebounceTimer) { clearTimeout(this.data.searchDebounceTimer) } // 设置新的定时器,300ms防抖 const timer = setTimeout(() => { this.searchGoods() }, 300) this.setData({ searchDebounceTimer: timer }) }, // 搜索商品 searchGoods: function () { // 重新显示tabBar const app = getApp(); if (app && app.globalData) { app.globalData.showTabBar = true; } console.log('searchGoods - 开始搜索,关键词:', this.data.searchKeyword); console.log('searchGoods - 本地已有商品数量:', this.data.goods.length); // 先对本地已加载的商品进行过滤 const filteredGoods = this.applyFilters(this.data.goods, true); console.log('searchGoods - 本地过滤结果数量:', filteredGoods.length); // 如果本地过滤结果不足,或者没有匹配的商品,则重新加载数据 if (filteredGoods.length < 3 && this.data.searchKeyword) { console.log('searchGoods - 本地过滤结果不足3个,将重新加载数据'); // 调用下拉刷新函数实现自动刷新 this.onRefresh(); } else { // 本地商品足够,直接使用本地过滤结果 console.log('searchGoods:使用本地商品过滤结果,数量:', filteredGoods.length); const groupedGoods = this.groupGoodsForStaggeredLayout(filteredGoods); this.setData({ filteredGoods: filteredGoods, groupedGoods: groupedGoods }); } }, // 切换地区选择器 toggleRegionPicker: function () { this.setData({ showRegionPicker: !this.data.showRegionPicker }) }, // 选择地区(强制刷新机制),添加防抖 selectRegion: function (e) { const region = e.currentTarget.dataset.region // 立即关闭弹窗并设置新的地区 this.setData({ selectedRegion: region, searchKeyword: '', // 清除搜索关键词,筛选框优先级更高 showRegionPicker: false }) // 重新显示tabBar const app = getApp(); if (app && app.globalData) { app.globalData.showTabBar = true; } // 防抖处理:取消之前的定时器 if (this.data.filterDebounceTimer) { clearTimeout(this.data.filterDebounceTimer); } // 设置新的定时器,延迟500ms执行刷新 this.data.filterDebounceTimer = setTimeout(() => { // 调用下拉刷新函数实现自动刷新 this.onRefresh(); }, 500); }, // 阻止事件冒泡 stopPropagation: function () { // 空函数,用于阻止事件冒泡 }, // 选择品种 - 使用下拉刷新机制,添加防抖 selectCategory: function (e) { // 重新显示tabBar const app = getApp(); if (app && app.globalData) { app.globalData.showTabBar = true; } const category = e.currentTarget.dataset.category if (category === this.data.selectedCategory) { return // 如果选择的分类和当前相同,不重复加载 } // 设置新的分类并清除搜索关键词 this.setData({ selectedCategory: category, searchKeyword: '', // 清除搜索关键词,筛选框优先级更高 }); // 如果选择的是"全部"分类,则重置高级筛选条件 if (category === '全部') { this.resetAdvancedFilter(); } // 防抖处理:取消之前的定时器 if (this.data.filterDebounceTimer) { clearTimeout(this.data.filterDebounceTimer); } // 设置新的定时器,延迟500ms执行刷新 this.data.filterDebounceTimer = setTimeout(() => { // 调用下拉刷新函数实现自动刷新 this.onRefresh(); }, 500); }, // 打开高级筛选 openAdvancedFilter: function () { this.setData({ showAdvancedFilter: true }); }, // 关闭高级筛选 closeAdvancedFilter: function () { this.setData({ showAdvancedFilter: false }); }, // 应用高级筛选 applyAdvancedFilter: function () { // 这里可以实现应用筛选条件的逻辑 console.log('应用高级筛选条件:', this.data.advancedFilters); // 关闭侧边栏 this.setData({ showAdvancedFilter: false }); // 刷新商品列表 this.onRefresh(); }, // 重置高级筛选 resetAdvancedFilter: function () { this.setData({ advancedFilters: { shellColor: 'all', yolkType: 'all', specification: 'all', productName: 'all', region: 'all', priceRange: [0, 100], sortBy: 'default' } }); }, // 选择蛋壳颜色并关闭下拉菜单 selectShellColor: function (e) { const shellColor = e.currentTarget.dataset.color; this.setData({ 'advancedFilters.shellColor': shellColor, showShellColorPicker: false }); }, // 选择蛋黄类型并关闭下拉菜单 selectYolkType: function (e) { const yolkType = e.currentTarget.dataset.yolk; this.setData({ 'advancedFilters.yolkType': yolkType, showYolkTypePicker: false }); }, // 选择规格并关闭下拉菜单 selectSpecification: function (e) { const specification = e.currentTarget.dataset.spec; this.setData({ 'advancedFilters.specification': specification, showSpecificationPicker: false }); }, // 选择商品名称并关闭下拉菜单 selectProductName: function (e) { const productName = e.currentTarget.dataset.name; this.setData({ 'advancedFilters.productName': productName, showProductNamePicker: false }); }, // 选择地区并关闭下拉菜单 selectRegion: function (e) { const region = e.currentTarget.dataset.region; this.setData({ 'advancedFilters.region': region, showAdvancedRegionPicker: false }); }, // 选择价格范围 selectPriceRange: function (e) { const priceRange = e.currentTarget.dataset.price; this.setData({ 'advancedFilters.priceRange': priceRange }); }, // 选择排序方式 selectSortBy: function (e) { const sortBy = e.currentTarget.dataset.sort; this.setData({ 'advancedFilters.sortBy': sortBy }); }, // 切换蛋壳颜色下拉菜单 toggleShellColorPicker: function () { this.setData({ showShellColorPicker: !this.data.showShellColorPicker, showYolkTypePicker: false, showSpecificationPicker: false, showProductNamePicker: false, showAdvancedRegionPicker: false }); }, // 切换蛋黄类型下拉菜单 toggleYolkTypePicker: function () { this.setData({ showYolkTypePicker: !this.data.showYolkTypePicker, showShellColorPicker: false, showSpecificationPicker: false, showProductNamePicker: false, showAdvancedRegionPicker: false }); }, // 切换规格下拉菜单 toggleSpecificationPicker: function () { this.setData({ showSpecificationPicker: !this.data.showSpecificationPicker, showShellColorPicker: false, showYolkTypePicker: false, showProductNamePicker: false, showAdvancedRegionPicker: false }); }, // 切换商品名称下拉菜单 toggleProductNamePicker: function () { this.setData({ showProductNamePicker: !this.data.showProductNamePicker, showShellColorPicker: false, showYolkTypePicker: false, showSpecificationPicker: false, showAdvancedRegionPicker: false }); }, // 切换地区下拉菜单 toggleRegionPicker: function () { this.setData({ showAdvancedRegionPicker: !this.data.showAdvancedRegionPicker, showShellColorPicker: false, showYolkTypePicker: false, showSpecificationPicker: false, showProductNamePicker: false }); }, // 查看商品详情 viewGoodsDetail: function (e) { const item = e.currentTarget.dataset.item // 确保productId存在,优先使用id,其次使用productId const productId = String(item.productId || item.id || '') if (!productId) { console.error('商品ID不存在,无法查看详情'); wx.showToast({ title: '商品信息有误', icon: 'none', duration: 2000 }) return; } // 将完整的商品数据传递给详情页,包含联系人信息,与buyer页面保持一致 // 同时传递登录状态信息,让详情页决定是否显示登录弹窗 const needLogin = this.data.needPhoneAuth; wx.navigateTo({ url: `/pages/goods-detail/goods-detail?goodsData=${encodeURIComponent(JSON.stringify(item))}&productId=${productId}&needLogin=${needLogin}` }) }, // 跳转到我要卖蛋页面 navigateToSettlement: function () { wx.switchTab({ url: '/pages/settlement/index' }) }, // 跳转到招商合作页面 navigateToCooperation: function () { this.setData({ sidebarBtnHidden: true }); wx.navigateTo({ url: '/pages/cooperation/index' }) }, // 跳转到货源管理页面 navigateToGoods: function () { this.setData({ sidebarBtnHidden: true }); wx.navigateTo({ url: '/pages/goods/index' }) }, // 预览图片 previewImage: function (e) { // 阻止事件冒泡,避免触发商品点击事件 e.stopPropagation(); // 获取图片信息 const item = e.currentTarget.dataset.item; const index = e.currentTarget.dataset.index; if (!item) { return; } // 确保图片URL存在且为数组 let imageUrls = item.imageUrls || item.images || []; if (!Array.isArray(imageUrls)) { imageUrls = [imageUrls]; } // 过滤掉无效的图片URL const validImageUrls = imageUrls.filter(url => url && typeof url === 'string' && url.trim() !== ''); if (validImageUrls.length === 0) { return; } // 显示图片预览弹窗 this.setData({ previewImageUrls: validImageUrls, previewImageIndex: parseInt(index || 0), showImagePreview: true }); }, // 关闭图片预览 closeImagePreview: function () { this.setData({ showImagePreview: false }); }, // 预览图片切换事件 onPreviewImageChange: function (e) { this.setData({ previewImageIndex: e.detail.current }); }, // 滚动事件处理 - 优化性能 onScroll: function (e) { const { scrollTop } = e.detail; // 清除之前的防抖定时器 if (this.data.scrollDebounceTimer) { clearTimeout(this.data.scrollDebounceTimer) } // 设置防抖,32ms约等于30fps,限制高速滑动时的处理频率 const timer = setTimeout(() => { this.handleScroll(scrollTop) }, 32) this.setData({ scrollDebounceTimer: timer }) }, // 实际的滚动处理逻辑 handleScroll: function (scrollTop) { const threshold = 50; const backToTopThreshold = 300; const lastScrollTop = this.data.lastScrollTop || 0; const isScrollingDown = scrollTop > lastScrollTop; let needUpdate = false; const updates = { lastScrollTop: scrollTop }; // 搜索框始终固定显示,不做隐藏处理 // 侧边栏按钮显示逻辑 // 下滑时隐藏按钮(除非用户未手动隐藏过且在顶部) if (isScrollingDown && scrollTop > threshold && !this.data.sidebarBtnHidden) { updates.sidebarBtnHidden = true; needUpdate = true; wx.setStorageSync('sidebarBtnHidden', true); wx.setStorageSync('userManuallyHidden', true); } // 上滑到顶部时显示按钮 else if (scrollTop <= threshold && this.data.sidebarBtnHidden && !this.data.userManuallyHidden) { updates.sidebarBtnHidden = false; needUpdate = true; wx.setStorageSync('sidebarBtnHidden', false); } // 回到顶部按钮显示逻辑 const shouldShowBackToTop = scrollTop > backToTopThreshold; if (shouldShowBackToTop !== this.data.showBackToTop) { updates.showBackToTop = shouldShowBackToTop; needUpdate = true; } if (needUpdate) { this.setData(updates); } // TabBar显示 const app = getApp(); if (app && app.globalData) { app.globalData.showTabBar = true; } }, // 更新商品的收藏状态 updateGoodsFavoriteStatus: function (goods, isLoadMore) { // 获取用户手机号 let userPhone = ''; try { const users = wx.getStorageSync('users') || {}; const userId = wx.getStorageSync('userId'); // 尝试从users中获取手机号 if (userId && users[userId] && users[userId].phoneNumber) { userPhone = users[userId].phoneNumber; } else { // 尝试从全局用户信息获取 const userInfo = wx.getStorageSync('userInfo'); if (userInfo && userInfo.phoneNumber) { userPhone = userInfo.phoneNumber; } else { // 尝试从直接存储的phoneNumber获取 userPhone = wx.getStorageSync('phoneNumber'); } } } catch (e) { console.error('获取用户手机号失败:', e); } if (!userPhone) { // 用户未登录,无法获取收藏状态 return; } // 调用API获取用户收藏列表 API.getFavorites(userPhone) .then(res => { if (res && res.code === 200) { // 检查API返回的数据结构,确保我们获取到正确的收藏列表 let favoritesList = []; if (Array.isArray(res.data)) { favoritesList = res.data; } else if (res.data && Array.isArray(res.data.favorites)) { favoritesList = res.data.favorites; } else if (res.data && Array.isArray(res.data.data)) { favoritesList = res.data.data; } // 从收藏列表中提取商品ID const favoriteProductIds = favoritesList.map(item => { // 尝试从不同的字段名获取商品ID return String(item.productId || item.id || item.product_id || ''); }).filter(id => id !== ''); // 过滤掉空字符串 // 更新商品的isFavorite状态 const updatedGoods = goods.map(item => ({ ...item, isFavorite: favoriteProductIds.includes(String(item.id || item.productId)) })); // 更新商品列表 let updatedGoodsList = this.data.goods; if (!isLoadMore || this.data.page === 1) { // 第一页或刷新时,直接替换全部商品 updatedGoodsList = updatedGoods; } else { // 加载更多时,追加到现有列表 updatedGoodsList = [...this.data.goods, ...updatedGoods]; } this.setData({ goods: updatedGoodsList }, () => { // 重新应用筛选条件,确保显示的商品收藏状态也更新 const filteredGoods = this.applyFilters(this.data.goods, true); this.setData({ filteredGoods: filteredGoods, }); }); } }) .catch(err => { console.error('获取收藏状态失败:', err); }); }, // 回到顶部 scrollToTop: function () { this.setData({ scrollTop: 0, searchSectionVisible: true, showBackToTop: false }); }, // 上拉加载更多 onReachBottom: function () { if (this.data.hasMoreData && !this.data.loadingMore) { this.loadGoods(true) } }, // 显示一键登录弹窗 showOneKeyLogin() { this.setData({ showAuthModal: false, showOneKeyLoginModal: true }) }, // 关闭未授权提示弹窗 closeAuthModal() { this.setData({ showAuthModal: false }) }, // 关闭一键登录弹窗 closeOneKeyLoginModal() { this.setData({ showOneKeyLoginModal: false }) }, // 分享给朋友/群聊 onShareAppMessage() { return { title: '鸡蛋贸易平台 - 专业的鸡蛋交易小程序', path: '/pages/index/index', imageUrl: '/images/首页分享照片.jpg' } }, // 分享到朋友圈 onShareTimeline() { return { title: '鸡蛋贸易平台 - 专业的鸡蛋交易小程序', query: '', imageUrl: '/images/首页分享照片.jpg' } }, // 处理手机号授权 async onGetPhoneNumber(e) { // 打印详细错误信息,方便调试 console.log('getPhoneNumber响应:', 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') { // 如果是测试模式,跳过真实授权流程 if (this.data.testMode) { await this.simulateLoginForTest() return } wx.showToast({ title: '当前环境无法获取手机号权限', icon: 'none', duration: 3000 }) // 增加关于微信认证要求的说明 console.warn('获取手机号权限失败: 请注意,微信小程序获取手机号功能需要满足以下条件:1. 小程序必须完成微信企业认证;2. 需要在小程序后台配置相应权限;3. 必须使用button组件的open-type="getPhoneNumber"触发。') return } // 检查是否已经登录,避免重复授权 const existingOpenid = wx.getStorageSync('openid') const existingUserId = wx.getStorageSync('userId') const existingUserInfo = wx.getStorageSync('userInfo') if (existingOpenid && existingUserId && existingUserInfo && existingUserInfo.phoneNumber) { // 直接完成身份设置,跳过重复授权 const currentUserType = this.data.pendingUserType || this.data.currentUserType || 'buyer' this.finishSetUserType(currentUserType) return } wx.showLoading({ title: '登录中...', mask: true }) // 引入API服务 const API = require('../../utils/api.js') try { if (e.detail.errMsg === 'getPhoneNumber:ok') { // 用户同意授权,实际处理授权流程 // 同时请求位置授权 wx.authorize({ scope: 'scope.userLocation', success() { // 位置授权成功,获取用户位置 wx.getLocation({ type: 'gcj02', success(res) { const latitude = res.latitude; const longitude = res.longitude; // 存储位置信息到本地 wx.setStorageSync('userLocation', { latitude, longitude }); // 位置获取成功提示 wx.showToast({ title: '位置获取成功', icon: 'success', duration: 1500 }); }, fail() { console.error('登录时获取位置失败'); // 位置获取失败提示 wx.showToast({ title: '位置获取失败', icon: 'none', duration: 1500 }); } }); }, fail() { // 位置授权失败,不影响登录流程 // 位置授权失败提示 wx.showToast({ title: '位置授权已拒绝', icon: 'none', duration: 1500 }); } }); // 1. 先执行微信登录获取code const loginRes = await new Promise((resolve, reject) => { wx.login({ success: resolve, fail: reject }) }) if (!loginRes.code) { throw new Error('获取登录code失败') } // 2. 使用code换取openid const openidRes = await API.getOpenid(loginRes.code) // 改进错误处理逻辑,更宽容地处理服务器返回格式,增加详细日志 let openid = null; let userId = null; if (openidRes && typeof openidRes === 'object') { // 适配服务器返回格式:{success: true, code: 200, message: '获取openid成功', data: {openid, userId}} if (openidRes.data && typeof openidRes.data === 'object') { openid = openidRes.data.openid || openidRes.data.OpenID || null; userId = openidRes.data.userId || null; } else { // 尝试从响应对象中直接提取openid,适配其他可能的格式 openid = openidRes.openid || openidRes.OpenID || null; userId = openidRes.userId || null; } } if (!openid) { console.error('无法从服务器响应中提取openid,完整响应:', JSON.stringify(openidRes)); // 增加更友好的错误信息,指导用户检查服务器配置 throw new Error(`获取openid失败: 服务器返回数据格式可能不符合预期,请检查服务器配置。响应数据为: ${JSON.stringify(openidRes)}`); } // 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) } else if (openidRes && openidRes.userId) { wx.setStorageSync('userId', openidRes.userId) } else { // 生成临时userId const tempUserId = 'user_' + Date.now() wx.setStorageSync('userId', tempUserId) } // 4. 上传手机号加密数据到服务器解密 const phoneData = { ...e.detail, openid: openid } 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 // 5. 获取用户微信名称和头像 let userProfile = null; try { userProfile = await new Promise((resolve, reject) => { wx.getUserProfile({ desc: '用于完善会员资料', success: resolve, fail: reject }); }); } 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 } // 从本地存储获取userId(使用已声明的变量) const storedUserId = wx.getStorageSync('userId') // 优先使用用户之前选择的身份类型,如果没有则尝试获取已存储的或默认为买家 const users = wx.getStorageSync('users') || {} const currentUserType = this.data.pendingUserType || this.data.currentUserType || (users[storedUserId] && users[storedUserId].type ? users[storedUserId].type : 'buyer') console.log('用户身份类型:', currentUserType) // 清除临时存储的身份类型 if (this.data.pendingUserType) { this.setData({ pendingUserType: null }) } // 保存用户信息并等待上传完成 const uploadResult = await this.saveUserInfo(tempUserInfo, currentUserType) console.log('用户信息保存并上传完成') wx.hideLoading() // 根据服务器返回的结果显示不同的提示 if (uploadResult && uploadResult.phoneNumberConflict) { wx.showModal({ title: '登录成功', content: '您的手机号已被其他账号绑定', showCancel: false, confirmText: '我知道了', success(res) { if (res.confirm) { console.log('用户点击了我知道了'); } } }); } // 用户登录成功,但已移除类型选择和跳转功能 } 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) } } }, // 处理用户基本信息授权 handleUserAuth(type) { // 保存当前用户类型 this.setData({ currentUserType: type }) // 先执行微信登录 this.doWechatLogin(type) }, // 测试模式下模拟登录流程 async simulateLoginForTest() { wx.showLoading({ title: '测试模式登录中...', mask: true }) try { // 1. 模拟微信登录,生成测试用的code const mockCode = 'test_code_' + Date.now() // 2. 模拟获取openid和userId const mockOpenid = 'test_openid_' + Date.now() const mockUserId = 'test_user_' + Date.now() // 3. 存储测试数据 wx.setStorageSync('openid', mockOpenid) wx.setStorageSync('userId', mockUserId) // 4. 模拟手机号解密结果 const mockPhoneNumber = null // 5. 创建模拟用户信息 const mockUserInfo = { name: '测试用户', avatarUrl: this.data.avatarUrl, gender: 0, country: '测试国家', province: '测试省份', city: '测试城市', language: 'zh_CN', phoneNumber: mockPhoneNumber } // 6. 获取用户身份类型(优先使用pendingUserType) const userId = wx.getStorageSync('userId') const users = wx.getStorageSync('users') || {} const currentUserType = this.data.pendingUserType || this.data.currentUserType || (users[userId] && users[userId].type ? users[userId].type : 'buyer') console.log('测试模式用户身份类型:', currentUserType) // 7. 清除临时存储的身份类型 if (this.data.pendingUserType) { this.setData({ pendingUserType: null }) } // 8. 保存用户信息并等待上传完成 // 在测试模式下也会上传用户信息到服务器,用于连通性测试 await this.saveUserInfo(mockUserInfo, currentUserType) wx.hideLoading() // 9. 显示成功提示 wx.showToast({ title: '测试模式登录成功', icon: 'success', duration: 2000 }) // 更新登录状态 this.setData({ isLoggedIn: true }) // 测试登录成功,但已移除类型选择和跳转功能 } catch (error) { wx.hideLoading() console.error('测试模式登录过程中发生错误:', error) wx.showToast({ title: '测试模式登录失败', icon: 'none', duration: 2000 }) } }, // 执行微信登录并获取openid async doWechatLogin(type) { // 显示加载提示 wx.showLoading({ title: '登录中...', mask: true }) try { // 调用微信登录接口 const loginRes = await new Promise((resolve, reject) => { wx.login({ success: resolve, fail: reject }) }) if (loginRes.code) { console.log('微信登录成功,code:', loginRes.code) // 保存登录凭证 try { wx.setStorageSync('loginCode', loginRes.code) } catch (e) { console.error('保存登录凭证失败:', e) } // 引入API服务 const API = require('../../utils/api.js') // 发送code和用户类型到服务器换取openid和session_key try { const openidRes = await API.getOpenid(loginRes.code, type) console.log('获取openid响应:', openidRes) // 增强版响应处理逻辑,支持多种返回格式 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); const serverMessage = openidRes && (openidRes.message || openidRes.msg); if (isSuccess && !openid) { console.warn('服务器返回成功状态,但未包含有效的openid:', openidRes); } // 打印获取到的信息,方便调试 console.log('提取到的登录信息:', { openid, userId, sessionKey, serverMessage }); if (openid) { // 存储openid和session_key wx.setStorageSync('openid', openid) if (sessionKey) { wx.setStorageSync('sessionKey', sessionKey) } // 如果有userId,也存储起来 if (userId) { wx.setStorageSync('userId', userId) } console.log('获取openid成功并存储:', openid) // 验证登录状态并获取用户信息 await this.validateLoginAndGetUserInfo(openid) } else { // 即使没有获取到openid,也要继续用户信息授权流程 console.warn('未获取到有效的openid,但继续用户信息授权流程:', openidRes); // 设置一个临时的openid以便继续流程 wx.setStorageSync('openid', 'temp_' + Date.now()) } } catch (error) { console.error('获取openid失败:', error) // 即使获取openid失败,也继续用户信息授权流程 } // 继续用户信息授权流程,等待完成 await this.processUserInfoAuth(type) } else { wx.hideLoading() console.error('微信登录失败:', loginRes) wx.showToast({ title: '登录失败,请重试', icon: 'none', duration: 2000 }) } } catch (err) { wx.hideLoading() console.error('wx.login失败:', err) wx.showToast({ title: '获取登录状态失败', icon: 'none', duration: 2000 }) } }, // 验证登录状态并获取用户信息 async validateLoginAndGetUserInfo(openid) { try { // 引入API服务 const API = require('../../utils/api.js') // 调用服务器验证登录状态 const validateRes = await API.validateUserLogin() if (validateRes.success && validateRes.userInfo) { // 服务器返回了用户信息,同步到本地 const app = getApp() const userInfo = validateRes.userInfo // 更新全局用户信息 app.globalData.userInfo = userInfo // 存储用户信息到本地 wx.setStorageSync('userInfo', userInfo) console.log('验证登录状态成功,用户信息已同步:', userInfo) // 如果手机号存在则清除重新授权标志 if (userInfo.phoneNumber) { // 清除可能存在的重新授权标志 wx.removeStorageSync('needPhoneAuth') console.log('手机号验证通过:', userInfo.phoneNumber) } // 更新登录状态 this.setData({ isLoggedIn: true }) return true } else { console.warn('服务器验证失败,可能是新用户或登录状态无效') return false } } catch (error) { console.error('验证登录状态失败:', error) // 如果验证失败,清除可能存在的无效登录信息 try { wx.removeStorageSync('openid') wx.removeStorageSync('userId') wx.removeStorageSync('userInfo') } catch (e) { console.error('清除无效登录信息失败:', e) } return false } }, // 处理用户信息授权 async processUserInfoAuth(type) { const app = getApp() // 如果已经有用户信息,不需要再进行跳转 if (app.globalData.userInfo) { wx.hideLoading() return } // 优化:首次登录时自动创建临时用户信息并完成登录,不再需要用户填写表单 // 获取已存储的userId或生成新的 let userId = wx.getStorageSync('userId') if (!userId) { userId = 'user_' + Date.now() wx.setStorageSync('userId', userId) } // 创建临时用户信息 const tempUserInfo = { name: '微信用户', avatarUrl: this.data.avatarUrl, gender: 0, country: '', province: '', city: '', language: 'zh_CN' } try { // 保存临时用户信息并完成登录,等待数据上传完成 await this.saveUserInfo(tempUserInfo, type) // 隐藏加载提示 wx.hideLoading() // 数据上传完成,但已移除类型选择和跳转功能 } catch (error) { console.error('处理用户信息授权失败:', error) wx.hideLoading() wx.showToast({ title: '登录失败,请重试', icon: 'none', duration: 2000 }) } }, // 保存用户信息 async saveUserInfo(userInfo, type) { // 确保userId存在 let userId = wx.getStorageSync('userId') if (!userId) { userId = 'user_' + Date.now() wx.setStorageSync('userId', userId) } // 保存用户信息到本地存储 - 修复首次获取问题 let users = wx.getStorageSync('users') // 如果users不存在或不是对象,初始化为空对象 if (!users || typeof users !== 'object') { users = {} } // 初始化用户信息 users[userId] = users[userId] || {} users[userId].info = userInfo users[userId].type = type // 确保存储操作成功 try { wx.setStorageSync('users', users) } catch (e) { console.error('保存用户信息到本地存储失败:', e) } // 保存用户信息到全局变量 const app = getApp() app.globalData.userInfo = userInfo app.globalData.userType = type // 额外保存一份单独的userInfo到本地存储,便于checkPhoneAuthSetting方法检查 try { wx.setStorageSync('userInfo', userInfo) } catch (e) { console.error('保存单独的userInfo失败:', e) } // 上传用户信息到服务器 // 在测试模式下也上传用户信息,用于连通性测试 // 确保测试数据包含服务器所需的所有字段 const completeUserInfo = { ...userInfo, // 确保包含服务器需要的必要字段 name: userInfo.name || '测试用户' } try { const uploadResult = await this.uploadUserInfoToServer(completeUserInfo, userId, type) console.log('用户信息上传到服务器成功') return uploadResult // 返回上传结果 } catch (error) { console.error('用户信息上传到服务器失败:', error) // 显示友好的提示,但不中断流程 wx.showToast({ title: '测试数据上传失败,不影响使用', icon: 'none', duration: 2000 }) // 不再抛出错误,而是返回默认成功结果,确保登录流程继续 return { success: true, message: '本地登录成功,服务器连接失败' } } }, // 处理头像选择 onChooseAvatar(e) { const { avatarUrl } = e.detail this.setData({ avatarUrl }) }, // 处理昵称提交 getUserName(e) { const { name } = e.detail.value const type = this.data.currentUserType if (!name) { wx.showToast({ title: '请输入昵称', icon: 'none', duration: 2000 }) return } // 创建用户信息对象 const userInfo = { name: name, avatarUrl: this.data.avatarUrl, // 其他可能需要的字段 gender: 0, country: '', province: '', city: '', language: 'zh_CN' } // 保存用户信息 this.saveUserInfo(userInfo, type) // 隐藏表单 this.setData({ showUserInfoForm: false }) // 已移除类型选择和跳转功能 }, // 取消用户信息表单 cancelUserInfoForm() { this.setData({ showUserInfoForm: false }) wx.hideLoading() }, // 检查本地缓存并恢复登录状态 checkAndRestoreLoginStatus() { console.log('开始检查并恢复登录状态') const app = getApp() // 从本地存储获取用户信息 const localUserInfo = wx.getStorageSync('userInfo') || {} const userId = wx.getStorageSync('userId') const openid = wx.getStorageSync('openid') console.log('恢复登录状态 - userId:', userId, 'openid:', openid ? '已获取' : '未获取') // 优先使用全局用户信息,如果没有则使用本地存储的用户信息 if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, needPhoneAuth: !app.globalData.userInfo.phoneNumber, isLoggedIn: !!(userId && openid) }) } else { app.globalData.userInfo = localUserInfo this.setData({ userInfo: localUserInfo, needPhoneAuth: !localUserInfo.phoneNumber, isLoggedIn: !!(userId && openid) }) } if (userId && openid) { // 确保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 = user.type this.setData({ currentUserType: currentType }) console.log('恢复登录状态 - 当前本地存储的用户类型:', currentType) // 从服务器获取最新的用户信息,确保身份由数据库决定 this.refreshUserInfoFromServer(openid, userId) } else { console.log('未找到有效的本地登录信息') } }, // 从服务器刷新用户信息并同步身份数据 refreshUserInfoFromServer(openid, userId) { const API = require('../../utils/api.js') API.getUserInfo(openid).then(res => { console.log('从服务器获取用户信息成功:', res) if (res.success && res.data) { const serverUserInfo = res.data // 更新本地用户信息 const app = getApp() const updatedUserInfo = { ...app.globalData.userInfo, ...serverUserInfo } app.globalData.userInfo = updatedUserInfo wx.setStorageSync('userInfo', updatedUserInfo) // 设置用户入驻状态 this.setData({ userInfo: updatedUserInfo, partnerstatus: serverUserInfo.partnerstatus || '' }) // 同步更新用户身份信息(当前身份由数据库决定) if (serverUserInfo.type) { this.syncUserTypeFromServer(userId, serverUserInfo.type) } console.log('用户信息已更新,昵称:', updatedUserInfo.name, '手机号:', updatedUserInfo.phoneNumber, '身份:', serverUserInfo.type) } }).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() const updatedUserInfo = { ...app.globalData.userInfo, ...serverUserInfo } app.globalData.userInfo = updatedUserInfo wx.setStorageSync('userInfo', updatedUserInfo) // 设置用户入驻状态 this.setData({ userInfo: updatedUserInfo, partnerstatus: serverUserInfo.partnerstatus || '' }) // 同步更新用户身份信息(当前身份由数据库决定) if (serverUserInfo.type) { this.syncUserTypeFromServer(userId, serverUserInfo.type) } console.log('用户信息已更新(备选方案):', updatedUserInfo) } }).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] = {} } // 移除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 console.log('用户身份已从服务器同步并保留客服标识:', newUserType) } else { console.log('用户身份与服务器一致,无需更新:', newUserType) } }, // 上传用户信息到服务器 async uploadUserInfoToServer(userInfo, userId, type) { // 引入API服务 const API = require('../../utils/api.js') // 获取openid const openid = wx.getStorageSync('openid') // 构造上传数据(包含openid和session_key) const uploadData = { userId: userId, openid: openid, ...userInfo, type: type, timestamp: Date.now() } // 调用API上传用户信息并返回Promise try { const res = await API.uploadUserInfo(uploadData) console.log('用户信息上传成功:', res) return res } catch (err) { console.error('用户信息上传失败:', err) // 不再抛出错误,而是返回默认成功结果,确保登录流程继续 // 这样即使服务器连接失败,本地登录也能完成 return { success: true, message: '本地登录成功,服务器连接失败' } } }, // 处理手机号授权结果(已重命名为onPhoneNumberResult,此方法已废弃) processPhoneAuthResult: function () { console.warn('processPhoneAuthResult方法已废弃,请使用onPhoneNumberResult方法') }, // 手机号授权处理 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://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. 保存用户信息并等待上传完成 await this.uploadUserInfoToServer(userInfo, userId, currentUserType) console.log('用户信息保存并上传完成') // 更新本地和全局用户信息 app.globalData.userInfo = userInfo wx.setStorageSync('userInfo', userInfo) // 更新页面状态 this.setData({ needPhoneAuth: false, userInfo: userInfo, showOneKeyLoginModal: false, isLoggedIn: true }) 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) } } }, // 上传用户信息到服务器 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' }); } }); }, })