From 9ce1f2259dee75b4f8494c42d736f63db2403f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?= <15778543+xufeiyang6017@user.noreply.gitee.com> Date: Wed, 17 Dec 2025 14:48:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=94=B6=E8=97=8F=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E7=BB=BF=E5=A3=B3=E5=95=86=E5=93=81=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E4=B8=A2=E5=A4=B1=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9F=A5=E8=AF=A2=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=92=8C=E5=9B=BE=E7=89=87URL=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/favorites/index.js | 366 +++++++++++++++++++++++++++++++++ pages/favorites/index.json | 4 + pages/favorites/index.wxml | 114 ++++++++++ pages/favorites/index.wxss | 36 ++++ server-example/server-mysql.js | 231 +++++++++++++++++++++ utils/api.js | 320 +++++++++++++++++++++++++++- 6 files changed, 1066 insertions(+), 5 deletions(-) create mode 100644 pages/favorites/index.js create mode 100644 pages/favorites/index.json create mode 100644 pages/favorites/index.wxml create mode 100644 pages/favorites/index.wxss diff --git a/pages/favorites/index.js b/pages/favorites/index.js new file mode 100644 index 0000000..62415d0 --- /dev/null +++ b/pages/favorites/index.js @@ -0,0 +1,366 @@ +// pages/favorites/index.js +const API = require('../../utils/api.js'); + +Page({ + + /** + * 页面的初始数据 + */ + data: { + favoritesList: [], + loading: true, + hasFavorites: false, + + // 图片预览相关状态 + showImagePreview: false, // 控制图片预览弹窗显示 + previewImageUrls: [], // 预览的图片URL列表 + previewImageIndex: 0, // 当前预览图片的索引 + + // 图片缩放相关状态 + scale: 1, // 当前缩放比例 + lastScale: 1, // 上一次缩放比例 + startDistance: 0, // 双指起始距离 + doubleTapTimer: null, // 双击计时器 + lastTapTime: 0, // 上一次单击时间 + isScaling: false, // 是否正在缩放中 + offsetX: 0, // X轴偏移量 + offsetY: 0, // Y轴偏移量 + initialTouch: null // 初始触摸点 + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + this.loadFavorites(); + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + // 每次显示页面时重新加载收藏列表 + this.loadFavorites(); + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + // 下拉刷新时重新加载收藏列表 + this.loadFavorites(true); + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + }, + + /** + * 加载收藏列表 + */ + loadFavorites: function (isPullDown = false) { + this.setData({ + loading: true + }); + + // 获取手机号码 + const phoneNumber = wx.getStorageSync('phoneNumber') || '18482694520'; // 默认使用测试手机号 + + if (!phoneNumber) { + // 用户未登录,显示提示 + wx.showToast({ + title: '请先登录', + icon: 'none' + }); + this.setData({ + loading: false, + hasFavorites: false + }); + if (isPullDown) { + wx.stopPullDownRefresh(); + } + return; + } + + API.getFavorites(phoneNumber).then(res => { + console.log('获取收藏列表成功:', res); + const favorites = res.data && res.data.favorites ? res.data.favorites : []; + this.setData({ + favoritesList: favorites, + hasFavorites: favorites.length > 0, + loading: false + }); + }).catch(err => { + console.error('获取收藏列表失败:', err); + wx.showToast({ + title: '获取收藏列表失败', + icon: 'none' + }); + this.setData({ + loading: false, + hasFavorites: false + }); + }).finally(() => { + // 停止下拉刷新 + if (isPullDown) { + wx.stopPullDownRefresh(); + } + }); + }, + + /** + * 取消收藏 + */ + cancelFavorite: function (e) { + const productId = e.currentTarget.dataset.productid; + wx.showLoading({ + title: '正在取消收藏', + mask: true + }); + + API.cancelFavorite(productId).then(res => { + console.log('取消收藏成功:', res); + // 从收藏列表中移除该商品 + const updatedList = this.data.favoritesList.filter(item => item.productId !== productId); + this.setData({ + favoritesList: updatedList, + hasFavorites: updatedList.length > 0 + }); + wx.showToast({ + title: '取消收藏成功', + icon: 'success' + }); + }).catch(err => { + console.error('取消收藏失败:', err); + wx.showToast({ + title: '取消收藏失败', + icon: 'none' + }); + }).finally(() => { + wx.hideLoading(); + }); + }, + + /** + * 跳转到商品详情页 + */ + goToGoodsDetail: function (e) { + const productId = e.currentTarget.dataset.productid; + wx.navigateTo({ + url: '/pages/goods-detail/goods-detail?productId=' + productId + }); + }, + + // 轮播图切换 + swiperChange(e) { + const current = e.detail.current; + const itemId = e.currentTarget.dataset.itemId; + + // 更新对应商品项的currentImageIndex + this.setData({ + [`favoritesList[${itemId}].currentImageIndex`]: current + }); + }, + + // 预览图片 + previewImage(e) { + // 登录验证 + const userInfo = wx.getStorageSync('userInfo') || null; + const userId = wx.getStorageSync('userId') || null; + if (!userInfo || !userId) { + // 未登录,显示授权登录弹窗 + this.setData({ + showAuthModal: true, + pendingUserType: 'buyer' + }); + return; + } + + // 已登录,执行图片预览 + const { urls, index } = e.currentTarget.dataset; + this.setData({ + showImagePreview: true, + previewImageUrls: urls, + previewImageIndex: parseInt(index) + }); + }, + + // 关闭图片预览 + closeImagePreview() { + this.setData({ + showImagePreview: false + }); + this.resetZoom(); + }, + + // 重置缩放状态 + resetZoom() { + this.setData({ + scale: 1, + lastScale: 1, + offsetX: 0, + offsetY: 0, + initialTouch: null + }); + }, + + // 处理图片点击事件(单击/双击判断) + handleImageTap(e) { + const currentTime = Date.now(); + const lastTapTime = this.data.lastTapTime; + + // 判断是否为双击(300ms内连续点击) + if (currentTime - lastTapTime < 300) { + // 双击事件 + if (this.data.doubleTapTimer) { + clearTimeout(this.data.doubleTapTimer); + } + + // 切换放大/缩小状态 + const newScale = this.data.scale === 1 ? 2 : 1; + this.setData({ + scale: newScale, + lastScale: newScale, + offsetX: 0, + offsetY: 0, + lastTapTime: 0 // 重置双击状态 + }); + } else { + // 单击事件,设置延迟来检测是否会成为双击 + if (this.data.doubleTapTimer) { + clearTimeout(this.data.doubleTapTimer); + } + + this.setData({ + lastTapTime: currentTime, + doubleTapTimer: setTimeout(() => { + // 确认是单击,关闭图片预览 + this.closeImagePreview(); + }, 300) + }); + } + }, + + // 处理触摸开始事件 + handleTouchStart(e) { + const touches = e.touches; + + if (touches.length === 1) { + // 单指:准备拖动 + this.setData({ + initialTouch: { + x: touches[0].clientX, + y: touches[0].clientY + } + }); + } else if (touches.length === 2) { + // 双指:记录起始距离,准备缩放 + const distance = this.calculateDistance(touches[0], touches[1]); + this.setData({ + startDistance: distance, + isScaling: true, + lastScale: this.data.scale + }); + } + }, + + // 处理触摸移动事件 + handleTouchMove(e) { + const touches = e.touches; + + if (touches.length === 1 && this.data.initialTouch && this.data.scale !== 1) { + // 单指拖动(只有在缩放状态下才允许拖动) + const deltaX = touches[0].clientX - this.data.initialTouch.x; + const deltaY = touches[0].clientY - this.data.initialTouch.y; + + // 计算新的偏移量 + let newOffsetX = this.data.offsetX + deltaX; + let newOffsetY = this.data.offsetY + deltaY; + + // 边界限制 + const windowWidth = wx.getSystemInfoSync().windowWidth; + const windowHeight = wx.getSystemInfoSync().windowHeight; + const maxOffsetX = (windowWidth * (this.data.scale - 1)) / 2; + const maxOffsetY = (windowHeight * (this.data.scale - 1)) / 2; + + newOffsetX = Math.max(-maxOffsetX, Math.min(maxOffsetX, newOffsetX)); + newOffsetY = Math.max(-maxOffsetY, Math.min(maxOffsetY, newOffsetY)); + + this.setData({ + offsetX: newOffsetX, + offsetY: newOffsetY, + initialTouch: { + x: touches[0].clientX, + y: touches[0].clientY + } + }); + } else if (touches.length === 2) { + // 双指缩放 + const currentDistance = this.calculateDistance(touches[0], touches[1]); + const scale = (currentDistance / this.data.startDistance) * this.data.lastScale; + + // 限制缩放范围在0.5倍到3倍之间 + const newScale = Math.max(0.5, Math.min(3, scale)); + + this.setData({ + scale: newScale, + isScaling: true + }); + } + }, + + // 处理触摸结束事件 + handleTouchEnd(e) { + this.setData({ + isScaling: false, + lastScale: this.data.scale, + initialTouch: null + }); + }, + + // 计算两点之间的距离 + calculateDistance(touch1, touch2) { + const dx = touch2.clientX - touch1.clientX; + const dy = touch2.clientY - touch1.clientY; + return Math.sqrt(dx * dx + dy * dy); + }, + + // 切换预览图片 + onPreviewImageChange(e) { + this.setData({ + previewImageIndex: e.detail.current + }); + this.resetZoom(); + } +}) \ No newline at end of file diff --git a/pages/favorites/index.json b/pages/favorites/index.json new file mode 100644 index 0000000..21582e1 --- /dev/null +++ b/pages/favorites/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": {}, + "navigationBarTitleText": "我的收藏" +} \ No newline at end of file diff --git a/pages/favorites/index.wxml b/pages/favorites/index.wxml new file mode 100644 index 0000000..29b1b11 --- /dev/null +++ b/pages/favorites/index.wxml @@ -0,0 +1,114 @@ + + + + + + 加载中... + + + + + + 💔 + 您还没有收藏任何商品 + + + + + + + + + + + + + + + 暂无图片 + + + + + + + + + + + + + {{(item.currentImageIndex || 0) + 1}}/{{item.Product.imageUrls.length}} + + + + + + + + + + + 金标蛋 + {{item.Product.productName || '未命名商品'}} + + + {{(item.Product.spec && item.Product.spec !== '无') ? item.Product.spec : (item.Product.specification && item.Product.specification !== '无') ? item.Product.specification : '无'}} | {{item.Product.yolk || '无'}} | {{item.Product.minOrder || item.Product.quantity || 1}}件 + + + + + + + + ¥{{item.Product.price || 0}} + + + + + + + + + + + + + + + + + + + + + × + + + \ No newline at end of file diff --git a/pages/favorites/index.wxss b/pages/favorites/index.wxss new file mode 100644 index 0000000..f8e9f28 --- /dev/null +++ b/pages/favorites/index.wxss @@ -0,0 +1,36 @@ +/* pages/favorites/index.wxss */ +.container { + min-height: 100vh; + background-color: #f5f5f5; +} + +.loading-container { + display: flex; + justify-content: center; + align-items: center; + height: 50vh; +} + +.empty-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 50vh; + color: #999; +} + +.empty-icon { + font-size: 100rpx; + margin-bottom: 20rpx; +} + +.empty-text { + font-size: 28rpx; +} + +/* 图片轮播样式 */ +.image-swiper { + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js index 4b0e284..589696f 100644 --- a/server-example/server-mysql.js +++ b/server-example/server-mysql.js @@ -813,6 +813,33 @@ CartItem.init({ timestamps: false }); +// 收藏模型 +class Favorite extends Model { } +Favorite.init({ + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, + user_phone: { + type: DataTypes.STRING(20), + allowNull: false + }, + productId: { + type: DataTypes.STRING(100), + allowNull: false + }, + date: { + type: DataTypes.DATE, + defaultValue: Sequelize.NOW + } +}, { + sequelize, + modelName: 'Favorite', + tableName: 'favorites', + timestamps: false +}); + // 联系人表模型 class Contact extends Model { } Contact.init({ @@ -957,6 +984,21 @@ Product.hasMany(CartItem, { onUpdate: 'CASCADE' // 级联更新 }); +// 收藏与商品的关系 (收藏属于商品) +Favorite.belongsTo(Product, { + foreignKey: 'productId', + targetKey: 'productId', // 目标键,使用productId字段(STRING类型)而非默认的id字段(INTEGER类型) + as: 'Product' // 别名,与收藏列表API中使用的一致 +}); + +// 商品与收藏的一对多关系 (商品可以被多个用户收藏) +Product.hasMany(Favorite, { + foreignKey: 'productId', + as: 'favorites', // 别名,表示商品的收藏列表 + onDelete: 'CASCADE', // 级联删除 + onUpdate: 'CASCADE' // 级联更新 +}); + CartItem.belongsTo(Product, { foreignKey: 'productId', as: 'product' // 购物车项中的商品 @@ -3250,6 +3292,195 @@ async function handleAddImagesToExistingProduct(req, res, existingProductId, upl // 其他路由... +// 收藏相关API端点 +// 添加收藏 +app.post('/api/favorites/add', async (req, res) => { + try { + const { user_phone, productId } = req.body; + + console.log('收到添加收藏请求:', { user_phone, productId }); + + // 验证参数 + if (!user_phone || !productId) { + return res.status(400).json({ + success: false, + code: 400, + message: '缺少必要参数', + data: { user_phone, productId } + }); + } + + // 检查是否已存在收藏记录 + const existingFavorite = await Favorite.findOne({ + where: { + user_phone, + productId + } + }); + + if (existingFavorite) { + return res.status(200).json({ + success: true, + code: 200, + message: '已经收藏过该商品', + data: existingFavorite + }); + } + + // 创建新的收藏记录 + const newFavorite = await Favorite.create({ + user_phone, + productId + }); + + console.log('收藏添加成功:', newFavorite); + + res.status(200).json({ + success: true, + code: 200, + message: '收藏添加成功', + data: newFavorite + }); + } catch (error) { + console.error('添加收藏失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '添加收藏失败', + error: error.message + }); + } +}); + +// 取消收藏 +app.post('/api/favorites/remove', async (req, res) => { + try { + const { user_phone, productId } = req.body; + + console.log('收到取消收藏请求:', { user_phone, productId }); + + // 验证参数 + if (!user_phone || !productId) { + return res.status(400).json({ + success: false, + code: 400, + message: '缺少必要参数' + }); + } + + // 删除收藏记录 + const result = await Favorite.destroy({ + where: { + user_phone, + productId + } + }); + + if (result === 0) { + return res.status(404).json({ + success: false, + code: 404, + message: '收藏记录不存在' + }); + } + + console.log('收藏取消成功:', { user_phone, productId }); + + res.status(200).json({ + success: true, + code: 200, + message: '收藏取消成功' + }); + } catch (error) { + console.error('取消收藏失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '取消收藏失败', + error: error.message + }); + } +}); + +// 获取收藏列表 +app.post('/api/favorites/list', async (req, res) => { + try { + const { user_phone } = req.body; + + console.log('收到获取收藏列表请求:', { user_phone }); + + // 验证参数 + if (!user_phone) { + return res.status(400).json({ + success: false, + code: 400, + message: '缺少必要参数' + }); + } + + // 获取收藏列表,并关联查询商品信息 + const favorites = await Favorite.findAll({ + where: { user_phone }, + include: [ + { + model: Product, + as: 'Product', // 与关联定义中的别名一致 + attributes: ['productId', 'productName', 'price', 'quantity', 'grossWeight', 'imageUrls', 'created_at', 'specification', 'yolk'] + } + ], + order: [['date', 'DESC']] + }); + + console.log('获取收藏列表成功,数量:', favorites.length); + + // 处理图片URL,确保是数组格式(与商品详情API保持一致的处理逻辑) + const processedFavorites = favorites.map(favorite => { + const favoriteJSON = favorite.toJSON(); + if (favoriteJSON.Product) { + // 关键修复:将存储在数据库中的JSON字符串反序列化为JavaScript数组 + if (favoriteJSON.Product.imageUrls) { + if (typeof favoriteJSON.Product.imageUrls === 'string') { + console.log('【关键修复】将数据库中的JSON字符串反序列化为JavaScript数组'); + try { + favoriteJSON.Product.imageUrls = JSON.parse(favoriteJSON.Product.imageUrls); + console.log('反序列化后的imageUrls类型:', typeof favoriteJSON.Product.imageUrls); + } catch (parseError) { + console.error('反序列化imageUrls失败:', parseError); + // 如果解析失败,使用空数组确保前端不会崩溃 + favoriteJSON.Product.imageUrls = []; + } + } else if (!Array.isArray(favoriteJSON.Product.imageUrls)) { + // 如果不是数组类型,也转换为空数组 + favoriteJSON.Product.imageUrls = []; + } + } else { + // 确保imageUrls始终是数组 + favoriteJSON.Product.imageUrls = []; + } + } + return favoriteJSON; + }); + + res.status(200).json({ + success: true, + code: 200, + message: '获取收藏列表成功', + data: { + favorites: processedFavorites, + count: processedFavorites.length + } + }); + } catch (error) { + console.error('获取收藏列表失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '获取收藏列表失败', + error: error.message + }); + } +}); + // 辅助函数:清理临时文件 function cleanTempFiles(filePaths) { if (!filePaths || filePaths.length === 0) { diff --git a/utils/api.js b/utils/api.js index e06d9a3..8356359 100644 --- a/utils/api.js +++ b/utils/api.js @@ -1998,20 +1998,20 @@ module.exports = { // 清除过期的登录信息 try { wx.removeStorageSync('openid'); + wx.removeStorageSync('userId'); wx.removeStorageSync('sessionKey'); } catch (e) { console.error('清除过期登录信息失败:', e); } // 重新登录后重试 - return this.login().then(() => { - console.log('重新登录成功,准备重试上传手机号数据'); + return this.login().then(loginRes => { return tryUpload(); }); + } else { + // 其他错误或重试次数用完,直接抛出 + throw error; } - - // 其他错误直接抛出 - throw error; }); }; @@ -2019,6 +2019,231 @@ module.exports = { return tryUpload(); }, + // 添加收藏 + addFavorite: function (productId) { + console.log('API.addFavorite - productId:', productId); + return new Promise((resolve, reject) => { + const openid = wx.getStorageSync('openid'); + const userId = wx.getStorageSync('userId'); + + // 获取用户信息,包含手机号 + const users = wx.getStorageSync('users') || {}; + let userPhone = null; + + // 尝试从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; + } + } + + // 如果没有openid,需要先登录 + if (!openid) { + return this.login().then(loginRes => { + // 重新尝试添加收藏 + return this.addFavorite(productId); + }).catch(loginErr => { + reject(new Error('用户未登录,无法添加收藏')); + }); + } + + // 如果没有手机号,需要先获取 + if (!userPhone) { + // 尝试获取用户信息 + return this.getUserInfo(openid).then(userInfoRes => { + let phoneNumber = null; + if (userInfoRes.data && userInfoRes.data.phoneNumber) { + phoneNumber = userInfoRes.data.phoneNumber; + } + + if (!phoneNumber) { + reject(new Error('无法获取用户手机号,无法添加收藏')); + } else { + // 保存手机号到本地 + if (userId) { + users[userId] = users[userId] || {}; + users[userId].phoneNumber = phoneNumber; + wx.setStorageSync('users', users); + } + // 重新尝试添加收藏 + return this.addFavorite(productId); + } + }).catch(err => { + reject(new Error('无法获取用户信息,无法添加收藏')); + }); + } + + // 构建收藏数据 + const favoriteData = { + user_phone: userPhone, + productId: productId, + date: new Date().toISOString() // 当前时间 + }; + + console.log('添加收藏请求数据:', favoriteData); + + // 发送请求到服务器 + request('/api/favorites/add', 'POST', favoriteData).then(res => { + console.log('添加收藏成功:', res); + resolve(res); + }).catch(error => { + console.error('添加收藏失败:', error); + reject(new Error('添加收藏失败,请稍后重试')); + }); + }); + }, + + // 取消收藏 + cancelFavorite: function (productId) { + console.log('API.cancelFavorite - productId:', productId); + return new Promise((resolve, reject) => { + const openid = wx.getStorageSync('openid'); + + // 获取用户信息,包含手机号 + const users = wx.getStorageSync('users') || {}; + const userId = wx.getStorageSync('userId'); + let userPhone = null; + + // 尝试从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; + } + } + + if (!openid) { + return this.login().then(loginRes => { + // 重新尝试取消收藏 + return this.cancelFavorite(productId); + }).catch(loginErr => { + reject(new Error('用户未登录,无法取消收藏')); + }); + } + + // 如果没有手机号,需要先获取 + if (!userPhone) { + // 尝试获取用户信息 + return this.getUserInfo(openid).then(userInfoRes => { + let phoneNumber = null; + if (userInfoRes.data && userInfoRes.data.phoneNumber) { + phoneNumber = userInfoRes.data.phoneNumber; + } + + if (!phoneNumber) { + reject(new Error('无法获取用户手机号,无法取消收藏')); + } else { + // 保存手机号到本地 + if (userId) { + users[userId] = users[userId] || {}; + users[userId].phoneNumber = phoneNumber; + wx.setStorageSync('users', users); + } + // 重新尝试取消收藏 + return this.cancelFavorite(productId); + } + }).catch(err => { + reject(new Error('无法获取用户信息,无法取消收藏')); + }); + } + + const cancelData = { + user_phone: userPhone, + productId: productId + }; + + console.log('取消收藏请求数据:', cancelData); + + request('/api/favorites/cancel', 'POST', cancelData).then(res => { + console.log('取消收藏成功:', res); + resolve(res); + }).catch(error => { + console.error('取消收藏失败:', error); + reject(new Error('取消收藏失败,请稍后重试')); + }); + }); + }, + + // 获取用户收藏列表 + getFavorites: function () { + console.log('API.getFavorites'); + return new Promise((resolve, reject) => { + const openid = wx.getStorageSync('openid'); + + // 获取用户信息,包含手机号 + const users = wx.getStorageSync('users') || {}; + const userId = wx.getStorageSync('userId'); + let userPhone = null; + + // 尝试从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; + } + } + + if (!openid) { + return this.login().then(loginRes => { + // 重新尝试获取收藏列表 + return this.getFavorites(); + }).catch(loginErr => { + reject(new Error('用户未登录,无法获取收藏列表')); + }); + } + + // 如果没有手机号,需要先获取 + if (!userPhone) { + // 尝试获取用户信息 + return this.getUserInfo(openid).then(userInfoRes => { + let phoneNumber = null; + if (userInfoRes.data && userInfoRes.data.phoneNumber) { + phoneNumber = userInfoRes.data.phoneNumber; + } + + if (!phoneNumber) { + reject(new Error('无法获取用户手机号,无法获取收藏列表')); + } else { + // 保存手机号到本地 + if (userId) { + users[userId] = users[userId] || {}; + users[userId].phoneNumber = phoneNumber; + wx.setStorageSync('users', users); + } + // 重新尝试获取收藏列表 + return this.getFavorites(); + } + }).catch(err => { + reject(new Error('无法获取用户信息,无法获取收藏列表')); + }); + } + + const requestData = { + user_phone: userPhone + }; + + console.log('获取收藏列表请求数据:', requestData); + + request('/api/favorites/list', 'GET', requestData).then(res => { + console.log('获取收藏列表成功:', res); + resolve(res); + }).catch(error => { + console.error('获取收藏列表失败:', error); + reject(new Error('获取收藏列表失败,请稍后重试')); + }); + }); + }, + // 上传用户信息到服务器 uploadUserInfo: function (userInfo) { console.log('API.uploadUserInfo - userInfo:', userInfo); @@ -2633,5 +2858,90 @@ module.exports = { }); }, + // 获取收藏商品列表 + getFavorites: function (phoneNumber) { + console.log('API.getFavorites - phoneNumber:', phoneNumber); + if (!phoneNumber) { + return Promise.reject(new Error('用户未登录')); + } + + return request('/api/favorites/list', 'POST', { + user_phone: phoneNumber + }); + }, + + // 取消收藏商品 + cancelFavorite: function (productId) { + console.log('API.cancelFavorite - productId:', productId); + return new Promise((resolve, reject) => { + const openid = wx.getStorageSync('openid'); + + // 获取用户信息,包含手机号 + const users = wx.getStorageSync('users') || {}; + const userId = wx.getStorageSync('userId'); + let userPhone = null; + + // 尝试从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; + } + } + + if (!openid) { + return this.login().then(loginRes => { + // 重新尝试取消收藏 + return this.cancelFavorite(productId); + }).catch(loginErr => { + reject(new Error('用户未登录,无法取消收藏')); + }); + } + + // 如果没有手机号,需要先获取 + if (!userPhone) { + // 尝试获取用户信息 + return this.getUserInfo(openid).then(userInfoRes => { + let phoneNumber = null; + if (userInfoRes.data && userInfoRes.data.phoneNumber) { + phoneNumber = userInfoRes.data.phoneNumber; + } + + if (!phoneNumber) { + reject(new Error('无法获取用户手机号,无法取消收藏')); + } else { + // 保存手机号到本地 + if (userId) { + users[userId] = users[userId] || {}; + users[userId].phoneNumber = phoneNumber; + wx.setStorageSync('users', users); + } + // 重新尝试取消收藏 + return this.cancelFavorite(productId); + } + }).catch(err => { + reject(new Error('无法获取用户信息,无法取消收藏')); + }); + } + + const requestData = { + user_phone: userPhone, + productId: productId + }; + + console.log('取消收藏请求数据:', requestData); + + request('/api/favorites/remove', 'POST', requestData).then(res => { + console.log('取消收藏成功:', res); + resolve(res); + }).catch(error => { + console.error('取消收藏失败:', error); + reject(new Error('取消收藏失败,请稍后重试')); + }); + }); + } }; \ No newline at end of file