|
|
|
|
// pages/buyer/index.js
|
|
|
|
|
const API = require('../../utils/api.js')
|
|
|
|
|
console.log('API对象内容:', API)
|
|
|
|
|
console.log('API方法列表:', Object.keys(API))
|
|
|
|
|
|
|
|
|
|
// 格式化毛重显示的辅助函数
|
|
|
|
|
function formatGrossWeight(grossWeight, weight) {
|
|
|
|
|
// 添加详细的日志记录,帮助诊断问题
|
|
|
|
|
console.log('===== formatGrossWeight 函数调用 =====');
|
|
|
|
|
console.log('输入参数:');
|
|
|
|
|
console.log('- grossWeight:', grossWeight, '(类型:', typeof grossWeight, ')');
|
|
|
|
|
console.log('- weight:', weight, '(类型:', typeof weight, ')');
|
|
|
|
|
|
|
|
|
|
// 1. 优先使用grossWeight,只要它不是null、不是undefined、不是空字符串
|
|
|
|
|
if (grossWeight !== null && grossWeight !== undefined && grossWeight !== '') {
|
|
|
|
|
console.log('使用grossWeight参数');
|
|
|
|
|
// 保持原始字符串类型,不再强制转换为数字
|
|
|
|
|
console.log('返回结果:', grossWeight);
|
|
|
|
|
return grossWeight;
|
|
|
|
|
}
|
|
|
|
|
// 如果grossWeight无效,尝试使用weight字段
|
|
|
|
|
if (weight !== null && weight !== undefined && weight !== '') {
|
|
|
|
|
console.log('使用weight参数');
|
|
|
|
|
// 保持原始字符串类型
|
|
|
|
|
console.log('返回结果:', weight);
|
|
|
|
|
return weight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 新增逻辑:如果grossWeight和weight都无效,返回空字符串以支持文字输入
|
|
|
|
|
console.log('两个参数都无效,返回空字符串');
|
|
|
|
|
return ""; // 返回空字符串以支持文字输入
|
|
|
|
|
}
|
|
|
|
|
Page({
|
|
|
|
|
// 分享给朋友/群聊
|
|
|
|
|
onShareAppMessage() {
|
|
|
|
|
return {
|
|
|
|
|
title: '发现优质鸡蛋货源,快来看看吧!',
|
|
|
|
|
path: '/pages/buyer/index',
|
|
|
|
|
imageUrl: '/images/你有好蛋.png'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 分享到朋友圈
|
|
|
|
|
onShareTimeline() {
|
|
|
|
|
return {
|
|
|
|
|
title: '发现优质鸡蛋货源,快来看看吧!',
|
|
|
|
|
query: '',
|
|
|
|
|
imageUrl: '/images/你有好蛋.png'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
data: {
|
|
|
|
|
goods: [],
|
|
|
|
|
searchKeyword: '',
|
|
|
|
|
filteredGoods: [],
|
|
|
|
|
selectedCategory: '全部', // 默认显示全部商品
|
|
|
|
|
showCustomToast: false, // 控制自定义弹窗显示
|
|
|
|
|
toastAnimation: {}, // 存储动画对象
|
|
|
|
|
|
|
|
|
|
// 图片预览相关状态
|
|
|
|
|
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, // 初始触摸点
|
|
|
|
|
|
|
|
|
|
// 用于强制刷新的键
|
|
|
|
|
goodsListKey: Date.now(),
|
|
|
|
|
forceUpdateTime: Date.now(),
|
|
|
|
|
|
|
|
|
|
// 已预约商品ID列表
|
|
|
|
|
reservedGoodsIds: [],
|
|
|
|
|
|
|
|
|
|
// 分页相关状态
|
|
|
|
|
page: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
loadingMore: false,
|
|
|
|
|
totalGoods: 0,
|
|
|
|
|
totalPages: 1,
|
|
|
|
|
|
|
|
|
|
// 授权登录相关状态
|
|
|
|
|
showAuthModal: false, // 控制未授权提示弹窗显示
|
|
|
|
|
showOneKeyLoginModal: false, // 控制一键登录弹窗显示
|
|
|
|
|
pendingUserType: 'buyer', // 记录用户即将选择的身份类型
|
|
|
|
|
avatarUrl: '/images/default-avatar.png', // 默认头像
|
|
|
|
|
showUserInfoForm: false, // 控制用户信息填写表单显示
|
|
|
|
|
currentGoodsId: null, // 记录当前点击的商品ID
|
|
|
|
|
|
|
|
|
|
// 商品详情相关状态
|
|
|
|
|
showGoodsDetail: false, // 控制商品详情弹窗显示
|
|
|
|
|
currentGoodsDetail: {} // 当前显示的商品详情
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
onLoad() {
|
|
|
|
|
console.log('买家页面加载完成')
|
|
|
|
|
// 从本地存储加载已预约商品ID列表
|
|
|
|
|
const reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || []
|
|
|
|
|
this.setData({
|
|
|
|
|
reservedGoodsIds
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:使用新的分页方式加载数据
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
goods: [],
|
|
|
|
|
filteredGoods: [],
|
|
|
|
|
loadingMore: false
|
|
|
|
|
}, () => {
|
|
|
|
|
this.loadGoods().then(() => {
|
|
|
|
|
console.log('onLoad加载商品数据完成');
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('onLoad加载商品数据失败:', err);
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 点击"我想要"按钮
|
|
|
|
|
onClickWant: function (e) {
|
|
|
|
|
const goodsId = e.currentTarget.dataset.id;
|
|
|
|
|
console.log('用户点击了"我想要"按钮,商品ID:', goodsId, '类型:', typeof goodsId);
|
|
|
|
|
|
|
|
|
|
// 保存当前商品ID
|
|
|
|
|
this.setData({
|
|
|
|
|
currentGoodsId: goodsId
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 检查用户登录状态
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
const userInfo = wx.getStorageSync('userInfo');
|
|
|
|
|
const userId = wx.getStorageSync('userId');
|
|
|
|
|
|
|
|
|
|
console.log('检查用户授权状态 - openid:', !!openid, 'userInfo:', !!userInfo, 'userId:', !!userId);
|
|
|
|
|
|
|
|
|
|
if (!openid || !userId || !userInfo) {
|
|
|
|
|
console.log('用户未登录,显示一键登录弹窗');
|
|
|
|
|
// 显示一键登录弹窗,让用户确认是否要登录
|
|
|
|
|
this.showOneKeyLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击"我想要"后,将用户类型设置为buyer
|
|
|
|
|
const API = require('../../utils/api.js');
|
|
|
|
|
API.updateUserType('buyer');
|
|
|
|
|
|
|
|
|
|
// 1. 前置验证
|
|
|
|
|
if (!goodsId) {
|
|
|
|
|
console.error('商品ID为空,无法预约');
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '商品信息不完整',
|
|
|
|
|
icon: 'error',
|
|
|
|
|
duration: 2000
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 确保商品ID是字符串格式
|
|
|
|
|
const goodsIdStr = String(goodsId);
|
|
|
|
|
if (!goodsIdStr || goodsIdStr === 'undefined' || goodsIdStr === 'null') {
|
|
|
|
|
console.error('无效的商品ID:', goodsIdStr);
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '商品信息不完整',
|
|
|
|
|
icon: 'error',
|
|
|
|
|
duration: 2000
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 查找商品信息
|
|
|
|
|
const goodsItem = this.findGoodsItemById(goodsIdStr);
|
|
|
|
|
if (!goodsItem) {
|
|
|
|
|
console.error('未找到对应商品信息,ID:', goodsIdStr);
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '商品信息已更新,请刷新页面',
|
|
|
|
|
icon: 'error',
|
|
|
|
|
duration: 2000
|
|
|
|
|
});
|
|
|
|
|
// 主动刷新页面数据
|
|
|
|
|
this.refreshGoodsList();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('找到商品信息:', goodsItem)
|
|
|
|
|
|
|
|
|
|
// 检查商品是否已预约
|
|
|
|
|
if (goodsItem.isReserved) {
|
|
|
|
|
console.log('商品已预约,无需重复操作');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建完整的product对象,包含所有必要字段
|
|
|
|
|
const product = {
|
|
|
|
|
productId: String(goodsItem.productId || goodsItem.id), // 确保为字符串
|
|
|
|
|
id: String(goodsItem.productId || goodsItem.id), // 同时设置id字段,与productId保持一致
|
|
|
|
|
productName: goodsItem.name || goodsItem.productName || '未命名商品',
|
|
|
|
|
name: goodsItem.name || goodsItem.productName || '未命名商品',
|
|
|
|
|
quantity: goodsItem.minOrder || 1, // 使用商品的最小订单数量作为实际件数,如果没有则默认为1
|
|
|
|
|
price: goodsItem.price || '', // 确保价格有默认值,使用空字符串支持字符串类型
|
|
|
|
|
specification: goodsItem.spec || goodsItem.specification || '',
|
|
|
|
|
grossWeight: goodsItem.grossWeight !== null && goodsItem.grossWeight !== undefined ? goodsItem.grossWeight : (goodsItem.weight || ''), // 使用空字符串支持字符串类型
|
|
|
|
|
yolk: goodsItem.yolk || '',
|
|
|
|
|
testMode: false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('找到的完整商品信息:', goodsItem)
|
|
|
|
|
|
|
|
|
|
wx.showLoading({ title: '正在预约...' })
|
|
|
|
|
|
|
|
|
|
// 调用API增加预约人数
|
|
|
|
|
console.log('准备调用API.addToCart,传递完整的product对象');
|
|
|
|
|
API.addToCart(product)
|
|
|
|
|
.then(res => {
|
|
|
|
|
wx.hideLoading()
|
|
|
|
|
console.log('增加预约人数成功:', res)
|
|
|
|
|
console.log('API.addToCart返回的数据结构:', JSON.stringify(res))
|
|
|
|
|
|
|
|
|
|
// 增强的成功检测逻辑:即使服务器没有明确返回success:true,也尝试更新UI
|
|
|
|
|
const isSuccess = res && (res.success || res.code === 200 || res.status === 'success');
|
|
|
|
|
if (isSuccess) {
|
|
|
|
|
// 更新已预约商品ID列表
|
|
|
|
|
this.updateReservedGoodsList(goodsItem)
|
|
|
|
|
|
|
|
|
|
// 直接更新当前商品的状态,避免整页刷新带来的延迟感
|
|
|
|
|
// 1. 找到当前商品在列表中的索引 - 增强版,处理多种ID格式
|
|
|
|
|
const goodsIndex = this.data.filteredGoods.findIndex(item =>
|
|
|
|
|
String(item.id) === goodsIdStr || String(item.productId) === goodsIdStr
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (goodsIndex !== -1) {
|
|
|
|
|
// 2. 更新商品的isReserved状态为true
|
|
|
|
|
const updateData = {};
|
|
|
|
|
updateData[`filteredGoods[${goodsIndex}].isReserved`] = true;
|
|
|
|
|
|
|
|
|
|
// 3. 更新预约人数(如果API返回了最新的预约人数)
|
|
|
|
|
// 优先使用服务器返回的selected字段,保持与商品列表加载时的逻辑一致
|
|
|
|
|
const newReservedCount = res.selected !== undefined ? res.selected :
|
|
|
|
|
(res.reservedCount !== undefined ? res.reservedCount :
|
|
|
|
|
(res.reservationCount || (this.data.filteredGoods[goodsIndex].reservationCount + 1)));
|
|
|
|
|
|
|
|
|
|
// 同时更新selected、reservedCount和reservationCount字段,确保数据一致性
|
|
|
|
|
updateData[`filteredGoods[${goodsIndex}].selected`] = newReservedCount;
|
|
|
|
|
updateData[`filteredGoods[${goodsIndex}].reservedCount`] = newReservedCount;
|
|
|
|
|
updateData[`filteredGoods[${goodsIndex}].reservationCount`] = newReservedCount;
|
|
|
|
|
|
|
|
|
|
// 4. 应用更新并验证
|
|
|
|
|
console.log('准备更新商品状态:', updateData);
|
|
|
|
|
this.setData(updateData, () => {
|
|
|
|
|
console.log('商品状态更新成功');
|
|
|
|
|
console.log('更新后商品状态:', this.data.filteredGoods[goodsIndex].isReserved);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.warn('未找到对应商品索引,无法即时更新UI状态');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 优化:点击"我想要"后,不立即刷新商品列表,而是使用本地更新的值
|
|
|
|
|
// 这样可以避免服务器数据未及时同步导致预约人数回退
|
|
|
|
|
// 仅在用户主动刷新页面或下次进入页面时才从服务器获取最新数据
|
|
|
|
|
|
|
|
|
|
// 记录成功的预约行为
|
|
|
|
|
this.recordBehavior('want_success', 'goods', goodsId)
|
|
|
|
|
|
|
|
|
|
// 显示"稍后会有专员联系"的弹窗
|
|
|
|
|
this.showContactToast()
|
|
|
|
|
} else {
|
|
|
|
|
// 失败时可以考虑添加日志,但不显示弹窗
|
|
|
|
|
console.error('预约失败:', res.message);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
wx.hideLoading()
|
|
|
|
|
console.error('增加预约人数失败:', err);
|
|
|
|
|
|
|
|
|
|
// 增强的错误详情日志,包含新增的错误属性
|
|
|
|
|
console.error('错误详情:', {
|
|
|
|
|
message: err.message,
|
|
|
|
|
stack: err.stack,
|
|
|
|
|
isForeignKeyError: err.isForeignKeyError,
|
|
|
|
|
productId: err.productId, // 增强的错误信息
|
|
|
|
|
timestamp: err.timestamp, // 增强的错误信息
|
|
|
|
|
originalError: err.originalError, // 增强的错误信息
|
|
|
|
|
statusCode: err.statusCode,
|
|
|
|
|
needRelogin: err.needRelogin
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 检查是否需要重新登录
|
|
|
|
|
if (err.needRelogin || err.message.includes('重新登录')) {
|
|
|
|
|
console.warn('检测到需要重新登录');
|
|
|
|
|
wx.showModal({
|
|
|
|
|
title: '登录状态失效',
|
|
|
|
|
content: '您的登录已过期,请重新授权登录',
|
|
|
|
|
showCancel: false,
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
// 清除本地存储的用户信息
|
|
|
|
|
wx.removeStorageSync('openid');
|
|
|
|
|
wx.removeStorageSync('userId');
|
|
|
|
|
// 跳转到登录页面
|
|
|
|
|
wx.navigateTo({ url: '/pages/login/index' });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return; // 结束后续处理
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 对于需要处理的特殊情况,仍然在后台默默处理
|
|
|
|
|
if (err.isForeignKeyError) {
|
|
|
|
|
console.log('检测到外键约束错误,自动刷新商品列表', { productId: err.productId });
|
|
|
|
|
|
|
|
|
|
// 先尝试在本地更新商品状态为预约中,提供即时反馈
|
|
|
|
|
const goodsItem = this.findGoodsItemById(String(goodsId));
|
|
|
|
|
if (goodsItem) {
|
|
|
|
|
const goodsIndex = this.data.filteredGoods.findIndex(item =>
|
|
|
|
|
String(item.id) === String(goodsId) || String(item.productId) === String(goodsId)
|
|
|
|
|
);
|
|
|
|
|
if (goodsIndex !== -1) {
|
|
|
|
|
const updateData = {};
|
|
|
|
|
updateData[`filteredGoods[${goodsIndex}].isReserved`] = true;
|
|
|
|
|
if (this.data.filteredGoods[goodsIndex].reservationCount !== undefined) {
|
|
|
|
|
updateData[`filteredGoods[${goodsIndex}].reservationCount`] =
|
|
|
|
|
this.data.filteredGoods[goodsIndex].reservationCount + 1;
|
|
|
|
|
}
|
|
|
|
|
console.log('临时更新商品状态,等待刷新确认:', updateData);
|
|
|
|
|
this.setData(updateData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 后台静默刷新商品列表
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.refreshGoodsList();
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
else if (err.message.includes('刷新')) {
|
|
|
|
|
console.log('需要刷新商品列表');
|
|
|
|
|
// 后台静默刷新商品列表
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.refreshGoodsList();
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
// 其他错误情况下可以显示一个简单的提示
|
|
|
|
|
else {
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '操作失败,请稍后重试',
|
|
|
|
|
icon: 'none',
|
|
|
|
|
duration: 2000
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 记录用户行为
|
|
|
|
|
this.recordBehavior('want_intent', 'goods', goodsId)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 根据ID查找商品信息的辅助方法 - 增强版,支持多种ID格式和来源
|
|
|
|
|
findGoodsItemById: function (goodsIdStr) {
|
|
|
|
|
// 1. 首先从页面数据中查找
|
|
|
|
|
console.log('尝试从页面数据中查找商品,ID:', goodsIdStr);
|
|
|
|
|
let goodsItem = this.data.goods.find(item =>
|
|
|
|
|
String(item.id) === goodsIdStr ||
|
|
|
|
|
String(item.productId) === goodsIdStr
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 2. 如果页面数据中找不到,从本地存储中查找
|
|
|
|
|
if (!goodsItem) {
|
|
|
|
|
console.log('页面数据中未找到商品,尝试从本地存储中查找');
|
|
|
|
|
const localGoods = wx.getStorageSync('goods') || [];
|
|
|
|
|
goodsItem = localGoods.find(item =>
|
|
|
|
|
String(item.id) === goodsIdStr ||
|
|
|
|
|
String(item.productId) === goodsIdStr
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 如果仍未找到,尝试从最新加载的缓存中查找
|
|
|
|
|
if (!goodsItem) {
|
|
|
|
|
console.log('本地存储中未找到商品,尝试从原始数据中查找');
|
|
|
|
|
// 可以添加更多的查找策略,例如临时缓存等
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return goodsItem;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 更新已预约商品列表的辅助方法
|
|
|
|
|
updateReservedGoodsList: function (goodsItem) {
|
|
|
|
|
// 添加到已预约商品ID列表
|
|
|
|
|
const { reservedGoodsIds } = this.data
|
|
|
|
|
// 确保商品ID为字符串类型,避免类型不匹配问题
|
|
|
|
|
const actualGoodsId = String(goodsItem.productId || goodsItem.id)
|
|
|
|
|
|
|
|
|
|
// 检查是否已存在,同样进行类型转换确保匹配
|
|
|
|
|
const isAlreadyReserved = reservedGoodsIds.some(id => String(id) === actualGoodsId)
|
|
|
|
|
|
|
|
|
|
if (!isAlreadyReserved) {
|
|
|
|
|
const newReservedGoodsIds = [...reservedGoodsIds, actualGoodsId]
|
|
|
|
|
this.setData({
|
|
|
|
|
reservedGoodsIds: newReservedGoodsIds
|
|
|
|
|
})
|
|
|
|
|
// 保存到本地存储
|
|
|
|
|
wx.setStorageSync('reservedGoodsIds', newReservedGoodsIds)
|
|
|
|
|
console.log('已更新预约列表:', newReservedGoodsIds)
|
|
|
|
|
} else {
|
|
|
|
|
console.log('商品已在预约列表中')
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 刷新商品列表
|
|
|
|
|
refreshGoodsList() {
|
|
|
|
|
console.log('刷新商品列表 - 重置分页状态并重新加载')
|
|
|
|
|
|
|
|
|
|
// 重置分页状态
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
loadingMore: false, // ✅ 添加这行
|
|
|
|
|
goods: [],
|
|
|
|
|
filteredGoods: []
|
|
|
|
|
}, () => {
|
|
|
|
|
// 调用loadGoods函数重新加载第一页数据
|
|
|
|
|
this.loadGoods().then(() => {
|
|
|
|
|
console.log('刷新商品列表完成');
|
|
|
|
|
// 调用调试函数检查创建时间字段
|
|
|
|
|
this.debugCreatedAtFields();
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('刷新商品列表失败:', err);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
onShow() {
|
|
|
|
|
console.log('页面显示,开始重新加载数据 - 使用分页加载')
|
|
|
|
|
|
|
|
|
|
// 确保用户身份被设置为买家
|
|
|
|
|
const userId = wx.getStorageSync('userId');
|
|
|
|
|
if (userId) {
|
|
|
|
|
// 更新用户类型
|
|
|
|
|
let users = wx.getStorageSync('users');
|
|
|
|
|
if (typeof users !== 'object' || users === null) {
|
|
|
|
|
users = {};
|
|
|
|
|
}
|
|
|
|
|
if (!users[userId]) {
|
|
|
|
|
users[userId] = {};
|
|
|
|
|
}
|
|
|
|
|
users[userId].type = 'buyer';
|
|
|
|
|
wx.setStorageSync('users', users);
|
|
|
|
|
|
|
|
|
|
// 更新标签
|
|
|
|
|
let tags = wx.getStorageSync('tags');
|
|
|
|
|
if (typeof tags !== 'object' || tags === null) {
|
|
|
|
|
tags = {};
|
|
|
|
|
}
|
|
|
|
|
tags[userId] = tags[userId] || [];
|
|
|
|
|
tags[userId] = tags[userId].filter(tag => !tag.startsWith('身份:'));
|
|
|
|
|
tags[userId].push(`身份:buyer`);
|
|
|
|
|
wx.setStorageSync('tags', tags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:重置分页状态并清空数据
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
goods: [],
|
|
|
|
|
filteredGoods: [],
|
|
|
|
|
loadingMore: false
|
|
|
|
|
}, () => {
|
|
|
|
|
// 调用loadGoods函数加载第一页数据
|
|
|
|
|
this.loadGoods().then((result) => {
|
|
|
|
|
console.log('onShow加载商品数据完成');
|
|
|
|
|
// 记录浏览行为
|
|
|
|
|
this.recordBehavior('browse', 'goods');
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('onShow加载商品数据失败:', err);
|
|
|
|
|
// ✅ 修改:错误处理 - 使用本地数据作为后备,但也要支持分页
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
this.recordBehavior('browse', 'goods');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 更新自定义tabBar状态
|
|
|
|
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
|
|
|
|
this.getTabBar().setData({
|
|
|
|
|
selected: 1
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 更新全局tab状态
|
|
|
|
|
const app = getApp();
|
|
|
|
|
app.updateCurrentTab('buyer');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 带分页的本地存储回退函数
|
|
|
|
|
fallbackToLocalStorageWithPagination() {
|
|
|
|
|
const localGoods = wx.getStorageSync('goods') || [];
|
|
|
|
|
const reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || [];
|
|
|
|
|
|
|
|
|
|
const { page, pageSize } = this.data;
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:对本地数据进行分页处理
|
|
|
|
|
const startIndex = (page - 1) * pageSize;
|
|
|
|
|
const endIndex = startIndex + pageSize;
|
|
|
|
|
const pagedLocalGoods = localGoods.slice(startIndex, endIndex);
|
|
|
|
|
|
|
|
|
|
console.log('本地存储分页信息:', {
|
|
|
|
|
当前页码: page,
|
|
|
|
|
每页大小: pageSize,
|
|
|
|
|
起始索引: startIndex,
|
|
|
|
|
结束索引: endIndex,
|
|
|
|
|
分页后商品数量: pagedLocalGoods.length,
|
|
|
|
|
本地总商品数量: localGoods.length
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 为本地商品添加是否已预约的标志和格式化毛重
|
|
|
|
|
const goodsWithReservedStatus = pagedLocalGoods.map(item => {
|
|
|
|
|
// 增强的预约人数计算逻辑
|
|
|
|
|
const selectedValue = item.selected;
|
|
|
|
|
const reservedCountValue = item.reservedCount;
|
|
|
|
|
const reservationCountValue = item.reservationCount;
|
|
|
|
|
|
|
|
|
|
const finalReservationCount = selectedValue !== undefined && selectedValue !== null ? selectedValue :
|
|
|
|
|
(reservedCountValue !== undefined && reservedCountValue !== null ? reservedCountValue :
|
|
|
|
|
(reservationCountValue || 0));
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
|
|
|
|
displayGrossWeight: formatGrossWeight(item.grossWeight, item.weight),
|
|
|
|
|
isReserved: reservedGoodsIds.some(id =>
|
|
|
|
|
String(id) === String(item.id) ||
|
|
|
|
|
String(id) === String(item.productId)
|
|
|
|
|
),
|
|
|
|
|
reservedCount: finalReservationCount,
|
|
|
|
|
currentImageIndex: item.currentImageIndex || 0
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:判断是否还有更多本地数据
|
|
|
|
|
const hasMoreLocalData = endIndex < localGoods.length;
|
|
|
|
|
const nextPage = page + 1;
|
|
|
|
|
|
|
|
|
|
console.log('本地数据分页状态:', {
|
|
|
|
|
是否有更多数据: hasMoreLocalData,
|
|
|
|
|
下一页码: nextPage,
|
|
|
|
|
本地数据总数: localGoods.length
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 更新页面状态
|
|
|
|
|
this.setData({
|
|
|
|
|
goods: goodsWithReservedStatus,
|
|
|
|
|
filteredGoods: goodsWithReservedStatus,
|
|
|
|
|
reservedGoodsIds: reservedGoodsIds,
|
|
|
|
|
page: nextPage, // 更新页码
|
|
|
|
|
hasMoreData: hasMoreLocalData, // 根据本地数据判断是否还有更多
|
|
|
|
|
loadingMore: false
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 下拉刷新处理函数
|
|
|
|
|
onPullDownRefresh() {
|
|
|
|
|
console.log('触发下拉刷新,重置分页状态并重新加载商品数据');
|
|
|
|
|
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
|
|
|
|
|
// 检查openid是否存在,但不再显示登录提示
|
|
|
|
|
if (!openid) {
|
|
|
|
|
console.warn('openid不存在,使用本地数据或空列表');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:重置分页状态
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
loadingMore: false,
|
|
|
|
|
goods: [],
|
|
|
|
|
filteredGoods: []
|
|
|
|
|
}, () => {
|
|
|
|
|
// 无论是否有openid,都尝试加载商品数据
|
|
|
|
|
this.loadGoods().then((result) => {
|
|
|
|
|
console.log('下拉刷新加载商品数据完成');
|
|
|
|
|
// 加载完成后停止下拉刷新动画
|
|
|
|
|
wx.stopPullDownRefresh();
|
|
|
|
|
console.log('===== 下拉刷新动画停止 ======');
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('下拉刷新加载商品失败:', err);
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:错误处理 - 使用带分页的本地数据回退
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
|
|
|
|
|
// 不显示提示,只记录日志
|
|
|
|
|
console.log('已使用缓存数据');
|
|
|
|
|
|
|
|
|
|
// 出错时也要停止下拉刷新动画
|
|
|
|
|
wx.stopPullDownRefresh();
|
|
|
|
|
console.log('===== 下拉刷新动画停止 ======');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 加载货源数据(为了兼容性添加的函数)
|
|
|
|
|
loadSupplies() {
|
|
|
|
|
console.log('调用loadSupplies函数 - 重定向到onPullDownRefresh')
|
|
|
|
|
this.onPullDownRefresh();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 从服务器加载货源数据(为了兼容性添加的函数)
|
|
|
|
|
loadSuppliesFromServer() {
|
|
|
|
|
console.log('调用loadSuppliesFromServer函数 - 重定向到API.getProductList')
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
console.log('loadSuppliesFromServer - openid:', openid);
|
|
|
|
|
|
|
|
|
|
// 不再因为没有openid而阻止加载数据,允许未登录用户查看商品
|
|
|
|
|
if (!openid) {
|
|
|
|
|
console.warn('openid不存在,将尝试加载公开商品数据');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || [];
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:添加分页参数
|
|
|
|
|
const { pageSize } = this.data;
|
|
|
|
|
API.getProductList('published', {
|
|
|
|
|
viewMode: 'shopping',
|
|
|
|
|
page: 1, // 第一页
|
|
|
|
|
pageSize: pageSize // 使用配置的页面大小
|
|
|
|
|
})
|
|
|
|
|
.then(res => {
|
|
|
|
|
console.log('loadSuppliesFromServer - 获取商品列表成功:', res);
|
|
|
|
|
if (res.success && res.products) {
|
|
|
|
|
// 将服务器返回的商品数据转换为需要的格式
|
|
|
|
|
const goods = res.products.map(product => {
|
|
|
|
|
// 处理grossWeight为null或无效的情况
|
|
|
|
|
const grossWeightValue = product.grossWeight !== null && product.grossWeight !== undefined ? product.grossWeight : '';
|
|
|
|
|
|
|
|
|
|
// 计算预约人数,增强逻辑确保能正确处理各种情况
|
|
|
|
|
let reservedCount = 0;
|
|
|
|
|
if (product.selected !== undefined && product.selected !== null) {
|
|
|
|
|
reservedCount = product.selected;
|
|
|
|
|
} else if (product.reservedCount !== undefined && product.reservedCount !== null) {
|
|
|
|
|
reservedCount = product.reservedCount;
|
|
|
|
|
} else if (product.reservationCount !== undefined && product.reservationCount !== null) {
|
|
|
|
|
reservedCount = product.reservationCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: String(product.id), // 确保ID为字符串类型
|
|
|
|
|
productId: String(product.productId || product.id), // 添加productId字段并确保为字符串类型
|
|
|
|
|
name: product.productName, // 品种
|
|
|
|
|
productName: product.productName, // 确保包含productName字段
|
|
|
|
|
price: product.price,
|
|
|
|
|
minOrder: product.quantity,
|
|
|
|
|
yolk: product.yolk,
|
|
|
|
|
spec: product.specification,
|
|
|
|
|
region: product.region || '', // 【新增】添加地区字段
|
|
|
|
|
grossWeight: grossWeightValue, // 确保不为null
|
|
|
|
|
displayGrossWeight: formatGrossWeight(grossWeightValue, product.weight),
|
|
|
|
|
seller: product.seller && (product.seller.name || product.seller.nickName) ? (product.seller.name || product.seller.nickName) : '未知卖家',
|
|
|
|
|
status: product.status || 'published',
|
|
|
|
|
imageUrls: product.imageUrls || [],
|
|
|
|
|
reservedCount: reservedCount,
|
|
|
|
|
createdAt: product.created_at || product.createTime || null,
|
|
|
|
|
product_contact: product.product_contact || '',
|
|
|
|
|
contact_phone: product.contact_phone || '',
|
|
|
|
|
isReserved: reservedGoodsIds.some(id =>
|
|
|
|
|
String(id) === String(product.id) ||
|
|
|
|
|
String(id) === String(product.productId)
|
|
|
|
|
),
|
|
|
|
|
currentImageIndex: 0
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 过滤掉hidden状态的商品
|
|
|
|
|
const filteredGoods = goods.filter(item => {
|
|
|
|
|
const itemStatus = (item.status || '').toLowerCase();
|
|
|
|
|
return itemStatus !== 'hidden';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('loadSuppliesFromServer过滤后商品数量:', filteredGoods.length, '原始商品数量:', goods.length);
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:保存到本地存储(分页数据)
|
|
|
|
|
wx.setStorageSync('goods', filteredGoods);
|
|
|
|
|
wx.setStorageSync('goodsTimestamp', Date.now());
|
|
|
|
|
|
|
|
|
|
// 更新页面数据
|
|
|
|
|
this.setData({
|
|
|
|
|
goods: filteredGoods,
|
|
|
|
|
filteredGoods: filteredGoods,
|
|
|
|
|
forceUpdateTime: Date.now(),
|
|
|
|
|
goodsListKey: Date.now(),
|
|
|
|
|
reservedGoodsIds: reservedGoodsIds,
|
|
|
|
|
// ✅ 修改:更新分页状态
|
|
|
|
|
page: 2, // 加载第一页后,下一页是第2页
|
|
|
|
|
hasMoreData: res.totalPages > 1, // 根据总页数判断是否有更多数据
|
|
|
|
|
totalGoods: res.total || 0,
|
|
|
|
|
totalPages: res.totalPages || 1
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 记录浏览行为
|
|
|
|
|
this.recordBehavior('browse', 'goods');
|
|
|
|
|
|
|
|
|
|
resolve({ success: true, products: filteredGoods });
|
|
|
|
|
} else {
|
|
|
|
|
console.error('获取商品列表失败:', res);
|
|
|
|
|
// 如果获取失败,使用本地缓存的数据
|
|
|
|
|
this.fallbackToLocalStorage();
|
|
|
|
|
resolve({ success: false });
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.error('获取商品列表失败:', err);
|
|
|
|
|
// 错误处理:使用本地数据
|
|
|
|
|
this.fallbackToLocalStorage();
|
|
|
|
|
reject(err);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 加载商品列表 - 修复分页重复问题
|
|
|
|
|
loadGoods(isLoadMore = false) {
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
console.log('loadGoods - openid:', openid);
|
|
|
|
|
|
|
|
|
|
// 不再因为没有openid而返回空列表,允许未登录用户查看商品
|
|
|
|
|
if (!openid) {
|
|
|
|
|
console.warn('openid不存在,将尝试加载公开商品数据或本地缓存');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果是加载更多且已经没有更多数据,则直接返回
|
|
|
|
|
if (isLoadMore && !this.data.hasMoreData) {
|
|
|
|
|
console.log('没有更多数据可加载');
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果是加载更多且正在加载中,则直接返回
|
|
|
|
|
if (isLoadMore && this.data.loadingMore) {
|
|
|
|
|
console.log('正在加载中,请稍后再试');
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 修复:确定当前请求的页码和页面大小
|
|
|
|
|
let currentPage;
|
|
|
|
|
let currentPageSize = this.data.pageSize; // 使用配置的页面大小
|
|
|
|
|
|
|
|
|
|
if (isLoadMore) {
|
|
|
|
|
// 加载更多时使用当前页码
|
|
|
|
|
currentPage = this.data.page;
|
|
|
|
|
} else {
|
|
|
|
|
// 刷新或首次加载时重置为第1页
|
|
|
|
|
currentPage = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('分页请求参数:', {
|
|
|
|
|
当前页码: currentPage,
|
|
|
|
|
每页大小: currentPageSize,
|
|
|
|
|
加载更多: isLoadMore
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 设置加载中状态
|
|
|
|
|
if (isLoadMore) {
|
|
|
|
|
this.setData({
|
|
|
|
|
loadingMore: true
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 记录请求开始时间,用于性能监控
|
|
|
|
|
const requestStartTime = Date.now();
|
|
|
|
|
|
|
|
|
|
// 添加时间戳参数防止请求缓存
|
|
|
|
|
const timestamp = new Date().getTime();
|
|
|
|
|
|
|
|
|
|
// 添加参数检查
|
|
|
|
|
if (!API || typeof API.getProductList !== 'function') {
|
|
|
|
|
console.error('API.getProductList 方法不存在');
|
|
|
|
|
// 如果API不可用,尝试使用本地缓存数据
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
return Promise.reject(new Error('API不可用'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('准备调用API.getProductList,无论是否登录都尝试获取公开商品');
|
|
|
|
|
return API.getProductList('published', {
|
|
|
|
|
timestamp: timestamp,
|
|
|
|
|
viewMode: 'shopping',
|
|
|
|
|
page: currentPage,
|
|
|
|
|
pageSize: currentPageSize,
|
|
|
|
|
// 增加搜索关键词参数
|
|
|
|
|
keyword: this.data.searchKeyword,
|
|
|
|
|
category: this.data.selectedCategory === '全部' ? '' : this.data.selectedCategory
|
|
|
|
|
})
|
|
|
|
|
.then(res => {
|
|
|
|
|
// 记录请求结束时间和耗时
|
|
|
|
|
const requestEndTime = Date.now();
|
|
|
|
|
console.log(`API请求耗时: ${requestEndTime - requestStartTime}ms`);
|
|
|
|
|
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
console.log('从服务器获取商品列表成功:', res)
|
|
|
|
|
|
|
|
|
|
if (res.success && res.products) {
|
|
|
|
|
console.log(`从服务器获取到 ${res.products.length} 个商品`);
|
|
|
|
|
|
|
|
|
|
// ✅ 修复:使用实际返回的商品数量进行计算
|
|
|
|
|
const pagedProducts = res.products;
|
|
|
|
|
const totalGoods = res.total || 0;
|
|
|
|
|
const totalPages = res.totalPages || Math.ceil(totalGoods / currentPageSize);
|
|
|
|
|
|
|
|
|
|
console.log('分页信息:', {
|
|
|
|
|
请求页码: currentPage,
|
|
|
|
|
请求每页大小: currentPageSize,
|
|
|
|
|
实际返回商品数量: pagedProducts.length,
|
|
|
|
|
总商品数量: totalGoods,
|
|
|
|
|
计算总页数: totalPages,
|
|
|
|
|
服务器返回总页数: res.totalPages
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ✅ 修复:如果返回的商品数量为0,说明没有更多数据
|
|
|
|
|
if (pagedProducts.length === 0) {
|
|
|
|
|
console.log('服务器返回空数据,没有更多商品');
|
|
|
|
|
this.setData({
|
|
|
|
|
hasMoreData: false,
|
|
|
|
|
loadingMore: false
|
|
|
|
|
});
|
|
|
|
|
return { success: true, hasMoreData: false };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从本地存储获取已预约商品ID列表
|
|
|
|
|
const reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || []
|
|
|
|
|
|
|
|
|
|
// 将服务器返回的商品数据转换为本地需要的格式
|
|
|
|
|
const newGoods = pagedProducts.map(product => {
|
|
|
|
|
// 处理grossWeight为null或无效的情况,返回空字符串以支持文字输入
|
|
|
|
|
const grossWeightValue = product.grossWeight !== null && product.grossWeight !== undefined ? product.grossWeight : '';
|
|
|
|
|
|
|
|
|
|
// 确保商品ID的一致性
|
|
|
|
|
const productIdStr = String(product.productId || product.id);
|
|
|
|
|
|
|
|
|
|
// 增强的预约人数计算逻辑
|
|
|
|
|
const selectedValue = product.selected;
|
|
|
|
|
const reservedCountValue = product.reservedCount;
|
|
|
|
|
const reservationCountValue = product.reservationCount;
|
|
|
|
|
|
|
|
|
|
const finalReservationCount = selectedValue !== undefined && selectedValue !== null ? selectedValue :
|
|
|
|
|
(reservedCountValue !== undefined && reservedCountValue !== null ? reservedCountValue :
|
|
|
|
|
(reservationCountValue || 0));
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: productIdStr,
|
|
|
|
|
productId: productIdStr,
|
|
|
|
|
name: product.productName,
|
|
|
|
|
price: product.price,
|
|
|
|
|
minOrder: product.quantity,
|
|
|
|
|
yolk: product.yolk,
|
|
|
|
|
spec: product.specification,
|
|
|
|
|
region: product.region || '', // 【新增】添加地区字段
|
|
|
|
|
grossWeight: grossWeightValue,
|
|
|
|
|
displayGrossWeight: formatGrossWeight(grossWeightValue, product.weight),
|
|
|
|
|
seller: product.seller && (product.seller.name || product.seller.nickName) ? (product.seller.name || product.seller.nickName) : '未知卖家',
|
|
|
|
|
status: product.status || 'published',
|
|
|
|
|
imageUrls: product.imageUrls || [],
|
|
|
|
|
createdAt: product.created_at || product.createTime || null,
|
|
|
|
|
reservedCount: finalReservationCount,
|
|
|
|
|
product_contact: product.product_contact || '', // 【新增】添加联系人字段
|
|
|
|
|
contact_phone: product.contact_phone || '', // 【新增】添加联系人电话字段
|
|
|
|
|
debugInfo: {
|
|
|
|
|
originalSelected: selectedValue,
|
|
|
|
|
originalReservedCount: reservedCountValue,
|
|
|
|
|
originalReservationCount: reservationCountValue
|
|
|
|
|
},
|
|
|
|
|
isReserved: reservedGoodsIds.some(id =>
|
|
|
|
|
String(id) === productIdStr ||
|
|
|
|
|
String(id) === String(product.id)
|
|
|
|
|
),
|
|
|
|
|
currentImageIndex: 0
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 过滤掉hidden状态的商品
|
|
|
|
|
const filteredNewGoods = newGoods.filter(item => {
|
|
|
|
|
const itemStatus = (item.status || '').toLowerCase();
|
|
|
|
|
return itemStatus !== 'hidden';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('过滤后商品数量:', filteredNewGoods.length, '原始商品数量:', newGoods.length);
|
|
|
|
|
|
|
|
|
|
// ✅ 修复:数据处理逻辑 - 根据是否是加载更多决定数据合并方式
|
|
|
|
|
let updatedGoods = [];
|
|
|
|
|
let updatedFilteredGoods = [];
|
|
|
|
|
|
|
|
|
|
if (isLoadMore) {
|
|
|
|
|
// 加载更多:合并数据,但要去重
|
|
|
|
|
const existingIds = new Set(this.data.goods.map(item => item.id));
|
|
|
|
|
const uniqueNewGoods = filteredNewGoods.filter(item => !existingIds.has(item.id));
|
|
|
|
|
|
|
|
|
|
updatedGoods = [...this.data.goods, ...uniqueNewGoods];
|
|
|
|
|
updatedFilteredGoods = [...this.data.filteredGoods, ...uniqueNewGoods];
|
|
|
|
|
|
|
|
|
|
console.log('去重信息:', {
|
|
|
|
|
新数据数量: filteredNewGoods.length,
|
|
|
|
|
去重后数量: uniqueNewGoods.length,
|
|
|
|
|
重复数量: filteredNewGoods.length - uniqueNewGoods.length
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// 刷新:替换数据
|
|
|
|
|
updatedGoods = filteredNewGoods;
|
|
|
|
|
updatedFilteredGoods = filteredNewGoods;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 修复:准确判断是否还有更多数据
|
|
|
|
|
const hasMoreData = currentPage < totalPages && filteredNewGoods.length > 0;
|
|
|
|
|
const nextPage = currentPage + 1;
|
|
|
|
|
|
|
|
|
|
console.log('分页状态:', {
|
|
|
|
|
当前页商品数: filteredNewGoods.length,
|
|
|
|
|
更新后总数: updatedGoods.length,
|
|
|
|
|
总商品数: totalGoods,
|
|
|
|
|
当前页码: currentPage,
|
|
|
|
|
下一页码: nextPage,
|
|
|
|
|
总页数: totalPages,
|
|
|
|
|
是否有更多数据: hasMoreData
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 更新页面状态
|
|
|
|
|
this.setData({
|
|
|
|
|
goods: updatedGoods,
|
|
|
|
|
filteredGoods: updatedFilteredGoods,
|
|
|
|
|
reservedGoodsIds: reservedGoodsIds,
|
|
|
|
|
page: nextPage, // 更新为下一页
|
|
|
|
|
hasMoreData: hasMoreData,
|
|
|
|
|
loadingMore: false,
|
|
|
|
|
totalGoods: totalGoods,
|
|
|
|
|
totalPages: totalPages
|
|
|
|
|
}, () => {
|
|
|
|
|
console.log('页面数据更新完成');
|
|
|
|
|
|
|
|
|
|
// 调用调试函数检查创建时间字段
|
|
|
|
|
this.debugCreatedAtFields();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 记录浏览行为
|
|
|
|
|
this.recordBehavior('browse', 'goods')
|
|
|
|
|
|
|
|
|
|
return { success: true, hasMoreData };
|
|
|
|
|
} else {
|
|
|
|
|
console.error('获取商品列表失败:', res);
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
this.setData({
|
|
|
|
|
loadingMore: false
|
|
|
|
|
});
|
|
|
|
|
// 如果获取失败,使用本地缓存的数据
|
|
|
|
|
this.fallbackToLocalStorage();
|
|
|
|
|
return { success: false };
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.error('获取商品列表失败:', err)
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
this.setData({
|
|
|
|
|
loadingMore: false
|
|
|
|
|
});
|
|
|
|
|
// 错误处理:使用本地数据
|
|
|
|
|
this.fallbackToLocalStorage();
|
|
|
|
|
return Promise.reject(err);
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 上拉加载更多
|
|
|
|
|
onReachBottom() {
|
|
|
|
|
console.log('触发上拉加载更多,当前页码:', this.data.page, '是否有更多数据:', this.data.hasMoreData);
|
|
|
|
|
|
|
|
|
|
if (this.data.hasMoreData && !this.data.loadingMore) {
|
|
|
|
|
this.loadGoods(true).then(result => {
|
|
|
|
|
if (result && result.success) {
|
|
|
|
|
console.log('上拉加载更多成功');
|
|
|
|
|
}
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('上拉加载更多失败:', err);
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '加载失败,请重试',
|
|
|
|
|
icon: 'none',
|
|
|
|
|
duration: 1500
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.log('没有更多数据或正在加载中');
|
|
|
|
|
if (!this.data.hasMoreData) {
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '没有更多商品了',
|
|
|
|
|
icon: 'none',
|
|
|
|
|
duration: 1500
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 预加载下一页数据 - 优化版本
|
|
|
|
|
preloadNextPage() {
|
|
|
|
|
// 当滚动到距离底部一定距离时,预加载下一页数据
|
|
|
|
|
const { hasMoreData, loadingMore } = this.data;
|
|
|
|
|
if (!hasMoreData || loadingMore) return;
|
|
|
|
|
|
|
|
|
|
console.log('预加载下一页数据');
|
|
|
|
|
// 添加延时,避免频繁触发预加载
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
// 再次检查状态,确保没有被其他操作更改
|
|
|
|
|
if (!this.data.loadingMore && this.data.hasMoreData) {
|
|
|
|
|
this.loadGoods(true);
|
|
|
|
|
}
|
|
|
|
|
}, 1000); // 增加延迟时间到1秒,减少重复加载
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 监听滚动事件,实现预加载
|
|
|
|
|
onScroll(e) {
|
|
|
|
|
const { scrollHeight, scrollTop, clientHeight } = e.detail;
|
|
|
|
|
const threshold = 800; // 增加阈值到800rpx,提前触发预加载
|
|
|
|
|
|
|
|
|
|
// 计算当前滚动位置距离底部的距离
|
|
|
|
|
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
|
|
|
|
|
|
|
|
|
|
// 当距离底部小于阈值且有更多数据时,触发预加载
|
|
|
|
|
if (distanceToBottom < threshold && this.data.hasMoreData && !this.data.loadingMore) {
|
|
|
|
|
this.preloadNextPage();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 回退到本地存储数据 - 修改为支持分页
|
|
|
|
|
fallbackToLocalStorage() {
|
|
|
|
|
const localGoods = wx.getStorageSync('goods') || [];
|
|
|
|
|
const reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || [];
|
|
|
|
|
|
|
|
|
|
const { page, pageSize } = this.data;
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:对本地数据进行分页处理
|
|
|
|
|
const startIndex = (page - 1) * pageSize;
|
|
|
|
|
const endIndex = startIndex + pageSize;
|
|
|
|
|
const pagedLocalGoods = localGoods.slice(startIndex, endIndex);
|
|
|
|
|
|
|
|
|
|
console.log('本地存储回退分页信息:', {
|
|
|
|
|
当前页码: page,
|
|
|
|
|
每页大小: pageSize,
|
|
|
|
|
分页后商品数量: pagedLocalGoods.length,
|
|
|
|
|
本地总商品数量: localGoods.length
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 为本地商品添加是否已预约的标志和格式化毛重
|
|
|
|
|
const goodsWithReservedStatus = pagedLocalGoods.map(item => {
|
|
|
|
|
const selectedValue = item.selected;
|
|
|
|
|
const reservedCountValue = item.reservedCount;
|
|
|
|
|
const reservationCountValue = item.reservationCount;
|
|
|
|
|
|
|
|
|
|
const finalReservationCount = selectedValue !== undefined && selectedValue !== null ? selectedValue :
|
|
|
|
|
(reservedCountValue !== undefined && reservedCountValue !== null ? reservedCountValue :
|
|
|
|
|
(reservationCountValue || 0));
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
|
|
|
|
displayGrossWeight: formatGrossWeight(item.grossWeight, item.weight),
|
|
|
|
|
isReserved: reservedGoodsIds.some(id =>
|
|
|
|
|
String(id) === String(item.id) ||
|
|
|
|
|
String(id) === String(item.productId)
|
|
|
|
|
),
|
|
|
|
|
reservedCount: finalReservationCount,
|
|
|
|
|
currentImageIndex: item.currentImageIndex || 0,
|
|
|
|
|
createdAt: item.createdAt || item.created_at || item.createTime || null
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 过滤掉hidden状态的商品
|
|
|
|
|
const filteredGoods = goodsWithReservedStatus.filter(item => {
|
|
|
|
|
const itemStatus = (item.status || '').toLowerCase();
|
|
|
|
|
return itemStatus !== 'hidden';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:判断是否还有更多本地数据
|
|
|
|
|
const hasMoreLocalData = endIndex < localGoods.length;
|
|
|
|
|
|
|
|
|
|
console.log('本地存储回退时分页商品数量:', filteredGoods.length, '本地总商品数量:', localGoods.length);
|
|
|
|
|
|
|
|
|
|
// 更新页面状态
|
|
|
|
|
this.setData({
|
|
|
|
|
goods: filteredGoods,
|
|
|
|
|
filteredGoods: filteredGoods,
|
|
|
|
|
forceUpdateTime: Date.now(),
|
|
|
|
|
// ✅ 修改:回退时也更新分页状态
|
|
|
|
|
hasMoreData: hasMoreLocalData
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 清除搜索
|
|
|
|
|
clearSearch() {
|
|
|
|
|
this.setData({
|
|
|
|
|
searchKeyword: '',
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
selectedCategory: '全部'
|
|
|
|
|
}, () => {
|
|
|
|
|
// 重新加载第一页数据
|
|
|
|
|
this.loadGoods().then(() => {
|
|
|
|
|
console.log('清除搜索后数据加载完成');
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('清除搜索后数据加载失败:', err);
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 搜索输入处理
|
|
|
|
|
onSearchInput(e) {
|
|
|
|
|
const searchKeyword = e.detail.value
|
|
|
|
|
this.setData({
|
|
|
|
|
searchKeyword: searchKeyword
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const { goods } = this.data
|
|
|
|
|
|
|
|
|
|
// 如果搜索词为空,重置分页并重新加载所有数据
|
|
|
|
|
if (!searchKeyword.trim()) {
|
|
|
|
|
console.log('搜索词为空,重置分页状态并重新加载数据');
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
selectedCategory: '全部'
|
|
|
|
|
}, () => {
|
|
|
|
|
// 重新加载第一页数据
|
|
|
|
|
this.loadGoods().then(() => {
|
|
|
|
|
console.log('重置搜索后数据加载完成');
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('重置搜索后数据加载失败:', err);
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:只搜索商品名称字段(对应数据库product表的productName字段)
|
|
|
|
|
const filtered = goods.filter(item =>
|
|
|
|
|
item.name && item.name.toLowerCase().includes(searchKeyword.toLowerCase())
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
this.setData({
|
|
|
|
|
filteredGoods: filtered
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 搜索商品
|
|
|
|
|
searchGoods() {
|
|
|
|
|
const { searchKeyword, goods, totalGoods } = this.data
|
|
|
|
|
|
|
|
|
|
// 如果搜索词为空,重置分页并重新加载
|
|
|
|
|
if (!searchKeyword.trim()) {
|
|
|
|
|
console.log('搜索词为空,重置分页状态并重新加载数据');
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
selectedCategory: '全部'
|
|
|
|
|
}, () => {
|
|
|
|
|
this.loadGoods().then(() => {
|
|
|
|
|
console.log('搜索重置后数据加载完成');
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
console.error('搜索重置后数据加载失败:', err);
|
|
|
|
|
this.fallbackToLocalStorageWithPagination();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 添加:搜索范围提示
|
|
|
|
|
if (goods.length < totalGoods) {
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: `正在${goods.length}个已加载商品中搜索`,
|
|
|
|
|
icon: 'none',
|
|
|
|
|
duration: 1500
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:只搜索商品名称字段(对应数据库product表的productName字段)
|
|
|
|
|
const filtered = goods.filter(item =>
|
|
|
|
|
item.name && item.name.toLowerCase().includes(searchKeyword.toLowerCase())
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
this.setData({
|
|
|
|
|
filteredGoods: filtered
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 调试商品数据中的创建时间字段
|
|
|
|
|
debugCreatedAtFields() {
|
|
|
|
|
console.log('=== 商品数据创建时间调试 ===');
|
|
|
|
|
if (this.data.goods && this.data.goods.length > 0) {
|
|
|
|
|
const firstGoods = this.data.goods.slice(0, 3); // 只检查前3个商品
|
|
|
|
|
firstGoods.forEach((item, index) => {
|
|
|
|
|
console.log(`商品${index + 1}:`);
|
|
|
|
|
console.log(' 原始数据:', JSON.stringify(item, null, 2));
|
|
|
|
|
console.log(' createdAt:', item.createdAt);
|
|
|
|
|
console.log(' created_at:', item.created_at);
|
|
|
|
|
console.log(' createTime:', item.createTime);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 清除本地缓存并重新加载数据
|
|
|
|
|
clearCacheAndReload() {
|
|
|
|
|
console.log('清除本地缓存并重新加载数据...');
|
|
|
|
|
wx.removeStorageSync('goods');
|
|
|
|
|
wx.removeStorageSync('reservedGoodsIds');
|
|
|
|
|
|
|
|
|
|
// ✅ 修改:重置分页状态后重新加载
|
|
|
|
|
this.setData({
|
|
|
|
|
page: 1,
|
|
|
|
|
hasMoreData: true,
|
|
|
|
|
goods: [],
|
|
|
|
|
filteredGoods: [],
|
|
|
|
|
loadingMore: false
|
|
|
|
|
}, () => {
|
|
|
|
|
this.loadGoods();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 切换图片
|
|
|
|
|
swiperChange(e) {
|
|
|
|
|
const current = e.detail.current
|
|
|
|
|
const itemId = e.currentTarget.dataset.itemId
|
|
|
|
|
|
|
|
|
|
// 更新对应商品项的currentImageIndex
|
|
|
|
|
this.setData({
|
|
|
|
|
[`filteredGoods[${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)
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 预览图片
|
|
|
|
|
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()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 显示联系提示弹窗
|
|
|
|
|
showContactToast() {
|
|
|
|
|
this.setData({
|
|
|
|
|
showCustomToast: true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 3秒后自动隐藏
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.setData({
|
|
|
|
|
showCustomToast: false
|
|
|
|
|
})
|
|
|
|
|
}, 800)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 微信登录
|
|
|
|
|
doWechatLogin: function (userType) {
|
|
|
|
|
console.log('开始微信登录,用户类型:', userType);
|
|
|
|
|
|
|
|
|
|
// 显示加载提示
|
|
|
|
|
wx.showLoading({
|
|
|
|
|
title: '登录中...',
|
|
|
|
|
mask: true
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 调用微信登录接口
|
|
|
|
|
wx.login({
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.code) {
|
|
|
|
|
console.log('获取登录code成功:', res.code);
|
|
|
|
|
// 保存登录code到本地
|
|
|
|
|
wx.setStorageSync('loginCode', res.code);
|
|
|
|
|
|
|
|
|
|
// 获取openid和session_key
|
|
|
|
|
this.getOpenid(res.code, userType);
|
|
|
|
|
} else {
|
|
|
|
|
console.error('登录失败:', res.errMsg);
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '登录失败,请重试',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
console.error('调用login接口失败:', err);
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '网络错误,请重试',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 获取openid
|
|
|
|
|
getOpenid: function (code, userType) {
|
|
|
|
|
console.log('获取openid,用户类型:', userType);
|
|
|
|
|
|
|
|
|
|
API.getOpenid(code)
|
|
|
|
|
.then(res => {
|
|
|
|
|
console.log('获取openid成功:', res);
|
|
|
|
|
|
|
|
|
|
if (res.success) {
|
|
|
|
|
// 保存openid到本地
|
|
|
|
|
wx.setStorageSync('openid', res.data.openid);
|
|
|
|
|
wx.setStorageSync('session_key', res.data.session_key);
|
|
|
|
|
|
|
|
|
|
// 验证登录状态并获取用户信息
|
|
|
|
|
this.validateLoginAndGetUserInfo(userType);
|
|
|
|
|
} else {
|
|
|
|
|
console.error('获取openid失败:', res.message);
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '登录失败,请重试',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.error('获取openid异常:', err);
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '网络错误,请重试',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 验证登录状态并获取用户信息
|
|
|
|
|
validateLoginAndGetUserInfo: function (userType) {
|
|
|
|
|
console.log('验证登录状态,用户类型:', userType);
|
|
|
|
|
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
|
|
|
|
|
if (!openid) {
|
|
|
|
|
console.error('openid不存在');
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
API.getUserInfo(openid)
|
|
|
|
|
.then(res => {
|
|
|
|
|
console.log('获取用户信息结果:', res);
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
if (res.success) {
|
|
|
|
|
// 检查用户是否已存在
|
|
|
|
|
if (res.data && res.data.id) {
|
|
|
|
|
// 用户已存在,保存用户信息
|
|
|
|
|
const userInfo = {
|
|
|
|
|
userId: res.data.id,
|
|
|
|
|
openid: openid,
|
|
|
|
|
name: res.data.name || res.data.nickname || '',
|
|
|
|
|
avatarUrl: res.data.avatar || '',
|
|
|
|
|
type: res.data.type
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存用户信息到本地
|
|
|
|
|
wx.setStorageSync('userInfo', userInfo);
|
|
|
|
|
wx.setStorageSync('userId', res.data.id);
|
|
|
|
|
|
|
|
|
|
// 显示成功提示
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '登录成功',
|
|
|
|
|
icon: 'success'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 登录成功后,重新执行"我想要"操作
|
|
|
|
|
this.handleLoginSuccess();
|
|
|
|
|
} else {
|
|
|
|
|
// 用户不存在,需要获取用户信息授权
|
|
|
|
|
this.processUserInfoAuth(userType);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 获取用户信息失败,可能是新用户
|
|
|
|
|
console.log('用户可能是新用户,开始授权流程');
|
|
|
|
|
this.processUserInfoAuth(userType);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.error('验证登录状态异常:', err);
|
|
|
|
|
wx.hideLoading();
|
|
|
|
|
// 发生异常,尝试获取用户信息授权
|
|
|
|
|
this.processUserInfoAuth(userType);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 处理用户信息授权
|
|
|
|
|
processUserInfoAuth: function (userType) {
|
|
|
|
|
console.log('处理用户信息授权,用户类型:', userType);
|
|
|
|
|
|
|
|
|
|
// 存储待设置的用户类型
|
|
|
|
|
this.setData({
|
|
|
|
|
pendingUserType: userType,
|
|
|
|
|
showAuthModal: true
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 处理登录成功
|
|
|
|
|
handleLoginSuccess: function () {
|
|
|
|
|
console.log('登录成功,检查是否有待执行的操作');
|
|
|
|
|
|
|
|
|
|
// 登录成功后,重新执行"我想要"操作
|
|
|
|
|
if (this.data.currentGoodsId) {
|
|
|
|
|
console.log('有未完成的操作,执行预约');
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
const goodsItem = this.findGoodsItemById(String(this.data.currentGoodsId));
|
|
|
|
|
if (goodsItem) {
|
|
|
|
|
// 重新调用onClickWant,但这次用户已登录
|
|
|
|
|
this.onClickWant({ currentTarget: { dataset: { id: this.data.currentGoodsId } } });
|
|
|
|
|
}
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 记录用户行为
|
|
|
|
|
// 显示一键登录弹窗
|
|
|
|
|
showOneKeyLogin: function () {
|
|
|
|
|
console.log('显示一键登录弹窗');
|
|
|
|
|
this.setData({
|
|
|
|
|
showAuthModal: false,
|
|
|
|
|
showOneKeyLoginModal: true
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 关闭授权弹窗
|
|
|
|
|
closeAuthModal: function () {
|
|
|
|
|
console.log('关闭授权弹窗');
|
|
|
|
|
this.setData({
|
|
|
|
|
showAuthModal: false
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 关闭一键登录弹窗
|
|
|
|
|
closeOneKeyLoginModal: function () {
|
|
|
|
|
console.log('关闭一键登录弹窗');
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 选择头像
|
|
|
|
|
onChooseAvatar: function (e) {
|
|
|
|
|
console.log('选择头像:', e);
|
|
|
|
|
const { avatarUrl } = e.detail;
|
|
|
|
|
this.setData({
|
|
|
|
|
avatarUrl
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 获取用户名
|
|
|
|
|
getUserName: function (e) {
|
|
|
|
|
console.log('获取用户名:', e);
|
|
|
|
|
const { name } = e.detail.value;
|
|
|
|
|
|
|
|
|
|
if (!name || name.trim() === '') {
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '昵称不能为空',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const userInfo = {
|
|
|
|
|
name: name.trim(),
|
|
|
|
|
avatarUrl: this.data.avatarUrl
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.saveUserInfo(userInfo, this.data.pendingUserType);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 取消用户信息表单
|
|
|
|
|
cancelUserInfoForm: function () {
|
|
|
|
|
console.log('取消用户信息表单');
|
|
|
|
|
this.setData({
|
|
|
|
|
showUserInfoForm: false
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 跳转到商品详情页面
|
|
|
|
|
showGoodsDetail: function (e) {
|
|
|
|
|
// 检查用户是否登录
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
const userId = wx.getStorageSync('userId');
|
|
|
|
|
|
|
|
|
|
if (!openid || !userId) {
|
|
|
|
|
console.log('用户未登录,显示登录提示和弹窗');
|
|
|
|
|
// 提示登录后才可查看详情
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '登录后才可查看详情',
|
|
|
|
|
icon: 'none',
|
|
|
|
|
duration: 1500
|
|
|
|
|
});
|
|
|
|
|
// 显示登录弹窗
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.showOneKeyLogin();
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goodsItem = e.currentTarget.dataset.item;
|
|
|
|
|
// 跳转到商品详情页面,并传递商品数据,使用encodeURIComponent编码JSON字符串
|
|
|
|
|
wx.navigateTo({
|
|
|
|
|
url: '/pages/goods-detail/goods-detail?goodsData=' + encodeURIComponent(JSON.stringify(goodsItem))
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 同时尝试直接更新tabBar的选中状态
|
|
|
|
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
|
|
|
|
const tabBar = this.getTabBar();
|
|
|
|
|
if (tabBar.setData) {
|
|
|
|
|
tabBar.setData({ show: false });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 调用后端API执行商品联系人更新
|
|
|
|
|
console.log('开始调用API.updateProductContacts()');
|
|
|
|
|
API.updateProductContacts().then(function(res) {
|
|
|
|
|
console.log('商品联系人更新成功:', res);
|
|
|
|
|
}).catch(function(err) {
|
|
|
|
|
console.error('商品联系人更新失败:', err);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取手机号并登录
|
|
|
|
|
onGetPhoneNumber: function (e) {
|
|
|
|
|
console.log('获取手机号:', e);
|
|
|
|
|
|
|
|
|
|
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
|
|
|
|
console.log('用户拒绝授权手机号');
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const encryptedData = e.detail.encryptedData;
|
|
|
|
|
const iv = e.detail.iv;
|
|
|
|
|
|
|
|
|
|
// 调用API进行登录
|
|
|
|
|
API.login(encryptedData, iv)
|
|
|
|
|
.then(res => {
|
|
|
|
|
console.log('登录成功:', res);
|
|
|
|
|
|
|
|
|
|
if (res.success) {
|
|
|
|
|
// 保存登录信息
|
|
|
|
|
wx.setStorageSync('openid', res.data.openid);
|
|
|
|
|
wx.setStorageSync('userId', res.data.userId);
|
|
|
|
|
wx.setStorageSync('sessionKey', res.data.sessionKey || '');
|
|
|
|
|
|
|
|
|
|
// 登录成功后立即获取用户微信名称
|
|
|
|
|
wx.getUserProfile({
|
|
|
|
|
desc: '用于完善会员资料',
|
|
|
|
|
success: (userProfile) => {
|
|
|
|
|
console.log('获取用户信息成功:', userProfile);
|
|
|
|
|
|
|
|
|
|
// 构建用户信息
|
|
|
|
|
const userInfo = {
|
|
|
|
|
openid: res.data.openid,
|
|
|
|
|
userId: res.data.userId,
|
|
|
|
|
name: userProfile.userInfo.name || userProfile.userInfo.nickName,
|
|
|
|
|
avatarUrl: userProfile.userInfo.avatarUrl,
|
|
|
|
|
type: this.data.pendingUserType
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存用户信息到本地存储
|
|
|
|
|
wx.setStorageSync('userInfo', userInfo);
|
|
|
|
|
|
|
|
|
|
// 上传用户信息到服务器
|
|
|
|
|
API.uploadUserInfo(userInfo)
|
|
|
|
|
.then(uploadRes => {
|
|
|
|
|
console.log('用户信息上传成功:', uploadRes);
|
|
|
|
|
|
|
|
|
|
// 关闭登录弹窗
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 登录成功后,重新执行"我想要"操作
|
|
|
|
|
this.handleLoginSuccess();
|
|
|
|
|
})
|
|
|
|
|
.catch(uploadErr => {
|
|
|
|
|
console.error('用户信息上传失败:', uploadErr);
|
|
|
|
|
|
|
|
|
|
// 即使上传失败,也关闭登录弹窗
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 登录成功后,重新执行"我想要"操作
|
|
|
|
|
this.handleLoginSuccess();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
fail: (profileErr) => {
|
|
|
|
|
console.error('获取用户信息失败:', profileErr);
|
|
|
|
|
|
|
|
|
|
// 即使获取用户信息失败,也构建基本用户信息对象
|
|
|
|
|
const userInfo = {
|
|
|
|
|
openid: res.data.openid,
|
|
|
|
|
userId: res.data.userId,
|
|
|
|
|
name: '微信用户',
|
|
|
|
|
avatarUrl: '/images/default-avatar.png',
|
|
|
|
|
type: this.data.pendingUserType
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存用户信息到本地存储
|
|
|
|
|
wx.setStorageSync('userInfo', userInfo);
|
|
|
|
|
|
|
|
|
|
// 关闭登录弹窗
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 登录成功后,重新执行"我想要"操作
|
|
|
|
|
this.handleLoginSuccess();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '登录失败,请重试',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.error('登录失败:', err);
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '网络错误,请重试',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
this.setData({
|
|
|
|
|
showOneKeyLoginModal: false
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 保存用户信息
|
|
|
|
|
saveUserInfo: function (userInfo, type) {
|
|
|
|
|
console.log('保存用户信息:', userInfo, '类型:', type);
|
|
|
|
|
|
|
|
|
|
const openid = wx.getStorageSync('openid');
|
|
|
|
|
const userId = wx.getStorageSync('userId');
|
|
|
|
|
|
|
|
|
|
if (!openid || !userId) {
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '登录信息已过期,请重新登录',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userInfo.userId = userId;
|
|
|
|
|
userInfo.openid = openid;
|
|
|
|
|
userInfo.type = type;
|
|
|
|
|
|
|
|
|
|
// 保存到本地存储
|
|
|
|
|
wx.setStorageSync('userInfo', userInfo);
|
|
|
|
|
|
|
|
|
|
// 上传到服务器
|
|
|
|
|
this.uploadUserInfoToServer(userInfo, userId, type);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 上传用户信息到服务器
|
|
|
|
|
uploadUserInfoToServer: function (userInfo, userId, type) {
|
|
|
|
|
console.log('上传用户信息到服务器:', userInfo);
|
|
|
|
|
|
|
|
|
|
API.saveUserInfo(userInfo, type)
|
|
|
|
|
.then(res => {
|
|
|
|
|
console.log('上传用户信息成功:', res);
|
|
|
|
|
|
|
|
|
|
this.setData({
|
|
|
|
|
showUserInfoForm: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 登录成功后,重新执行"我想要"操作
|
|
|
|
|
if (this.data.currentGoodsId) {
|
|
|
|
|
// 模拟点击"我想要"按钮,使用新的商品ID
|
|
|
|
|
const goodsItem = this.findGoodsItemById(String(this.data.currentGoodsId));
|
|
|
|
|
if (goodsItem) {
|
|
|
|
|
// 重新调用onClickWant,但这次用户已登录
|
|
|
|
|
this.onClickWant({ currentTarget: { dataset: { id: this.data.currentGoodsId } } });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.error('上传用户信息失败:', err);
|
|
|
|
|
|
|
|
|
|
// 即使上传失败,也标记为已登录
|
|
|
|
|
this.setData({
|
|
|
|
|
showUserInfoForm: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 尝试执行"我想要"操作
|
|
|
|
|
if (this.data.currentGoodsId) {
|
|
|
|
|
const goodsItem = this.findGoodsItemById(String(this.data.currentGoodsId));
|
|
|
|
|
if (goodsItem) {
|
|
|
|
|
// 重新调用onClickWant,但这次用户已登录
|
|
|
|
|
this.onClickWant({ currentTarget: { dataset: { id: this.data.currentGoodsId } } });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
recordBehavior(behaviorType, targetType, targetId) {
|
|
|
|
|
try {
|
|
|
|
|
console.log(`记录行为: ${behaviorType}, ${targetType}, ${targetId || '无ID'}`)
|
|
|
|
|
|
|
|
|
|
// 可以在这里添加更复杂的行为记录逻辑,如发送到服务器等
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('记录行为失败:', error)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 格式化时间为北京时间(UTC+8)并转换为 年-月-日-时:分 格式
|
|
|
|
|
formatTimeToBeijing: function (timeValue) {
|
|
|
|
|
if (!timeValue) {
|
|
|
|
|
return '未知';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 创建Date对象
|
|
|
|
|
const date = new Date(timeValue);
|
|
|
|
|
|
|
|
|
|
// 检查日期是否有效
|
|
|
|
|
if (isNaN(date.getTime())) {
|
|
|
|
|
return '未知';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 使用Date对象的方法直接获取UTC时间,然后加8小时计算北京时间
|
|
|
|
|
const utcYear = date.getUTCFullYear();
|
|
|
|
|
const utcMonth = date.getUTCMonth();
|
|
|
|
|
const utcDate = date.getUTCDate();
|
|
|
|
|
const utcHours = date.getUTCHours() + 8; // 直接加8小时
|
|
|
|
|
|
|
|
|
|
// 创建北京时间Date对象
|
|
|
|
|
const beijingTime = new Date(Date.UTC(utcYear, utcMonth, utcDate, utcHours, date.getUTCMinutes()));
|
|
|
|
|
|
|
|
|
|
// 格式化时间,使用连字符分隔
|
|
|
|
|
const year = beijingTime.getFullYear();
|
|
|
|
|
const month = (beijingTime.getMonth() + 1).toString().padStart(2, '0');
|
|
|
|
|
const day = beijingTime.getDate().toString().padStart(2, '0');
|
|
|
|
|
const hours = beijingTime.getHours().toString().padStart(2, '0');
|
|
|
|
|
const minutes = beijingTime.getMinutes().toString().padStart(2, '0');
|
|
|
|
|
|
|
|
|
|
// 返回格式:年-月-日-时:分
|
|
|
|
|
return `${year}-${month}-${day}-${hours}:${minutes}`;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('北京时间格式化错误:', error);
|
|
|
|
|
return '未知';
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 拨打电话功能
|
|
|
|
|
makePhoneCall(e) {
|
|
|
|
|
const phoneNumber = e.currentTarget.dataset.phone;
|
|
|
|
|
if (phoneNumber) {
|
|
|
|
|
wx.showModal({
|
|
|
|
|
title: '联系人电话',
|
|
|
|
|
content: phoneNumber,
|
|
|
|
|
showCancel: true,
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
confirmText: '拨打',
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
wx.makePhoneCall({
|
|
|
|
|
phoneNumber: phoneNumber,
|
|
|
|
|
success: () => {
|
|
|
|
|
console.log('拨打电话成功');
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
console.error('拨打电话失败', err);
|
|
|
|
|
wx.showToast({
|
|
|
|
|
title: '拨打电话失败',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|