|
|
|
|
// 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();
|
|
|
|
|
|
|
|
|
|
// 添加收藏状态变化事件监听
|
|
|
|
|
const app = getApp();
|
|
|
|
|
this.favoriteChangedHandler = (data) => {
|
|
|
|
|
console.log('收藏页面收到收藏状态变化通知:', data);
|
|
|
|
|
// 重新加载收藏列表以更新状态
|
|
|
|
|
this.loadFavorites();
|
|
|
|
|
};
|
|
|
|
|
app.eventBus.on('favoriteChanged', this.favoriteChangedHandler);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生命周期函数--监听页面初次渲染完成
|
|
|
|
|
*/
|
|
|
|
|
onReady() {
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生命周期函数--监听页面显示
|
|
|
|
|
*/
|
|
|
|
|
onShow() {
|
|
|
|
|
// 每次显示页面时重新加载收藏列表
|
|
|
|
|
this.loadFavorites();
|
|
|
|
|
|
|
|
|
|
// 更新自定义tabBar状态
|
|
|
|
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
|
|
|
|
this.getTabBar().setData({
|
|
|
|
|
selected: 3
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 更新全局tab状态
|
|
|
|
|
const app = getApp();
|
|
|
|
|
if (app.updateCurrentTab) {
|
|
|
|
|
app.updateCurrentTab('favorites');
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生命周期函数--监听页面隐藏
|
|
|
|
|
*/
|
|
|
|
|
onHide() {
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生命周期函数--监听页面卸载
|
|
|
|
|
*/
|
|
|
|
|
onUnload() {
|
|
|
|
|
// 移除事件监听
|
|
|
|
|
const app = getApp();
|
|
|
|
|
if (this.favoriteChangedHandler) {
|
|
|
|
|
app.eventBus.off('favoriteChanged', this.favoriteChangedHandler);
|
|
|
|
|
console.log('收藏页面移除收藏状态变化事件监听');
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 页面相关事件处理函数--监听用户下拉动作
|
|
|
|
|
*/
|
|
|
|
|
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'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 触发全局事件,通知其他页面收藏状态已更改
|
|
|
|
|
const app = getApp();
|
|
|
|
|
app.eventBus.emit('favoriteChanged', {
|
|
|
|
|
productId: productId,
|
|
|
|
|
isFavorite: false
|
|
|
|
|
});
|
|
|
|
|
}).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();
|
|
|
|
|
}
|
|
|
|
|
})
|