You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1945 lines
64 KiB

3 months ago
// 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({
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;
}
// 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.nickName ? product.seller.nickName : '未知卖家',
status: product.status || 'published',
imageUrls: product.imageUrls || [],
reservedCount: reservedCount,
createdAt: product.created_at || product.createTime || null,
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.nickName ? 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
});
},
// 搜索输入处理
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
}
// ✅ 修改:实时过滤当前已加载的商品(前端搜索)
// 注意:这是在前端对已加载数据进行搜索,如果要搜索全部数据需要后端支持
const filtered = goods.filter(item =>
(item.name && item.name.toLowerCase().includes(searchKeyword.toLowerCase())) ||
(item.spec && item.spec.toLowerCase().includes(searchKeyword.toLowerCase())) ||
(item.yolk && item.yolk.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
});
}
// ✅ 修改:在当前已加载商品中搜索(前端搜索)
const filtered = goods.filter(item =>
(item.name && item.name.toLowerCase().includes(searchKeyword.toLowerCase())) ||
(item.spec && item.spec.toLowerCase().includes(searchKeyword.toLowerCase())) ||
(item.yolk && item.yolk.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 { urls, index } = e.currentTarget.dataset
this.setData({
showImagePreview: true,
previewImageUrls: urls,
previewImageIndex: parseInt(index)
})
},
// 预览图片
previewImage(e) {
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,
nickname: 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 { nickname } = e.detail.value;
if (!nickname || nickname.trim() === '') {
wx.showToast({
title: '昵称不能为空',
icon: 'none'
});
return;
}
const userInfo = {
nickname: nickname.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;
this.setData({
currentGoodsDetail: goodsItem,
showGoodsDetail: true
});
// 隐藏底部导航栏 - 通过更新全局数据
const app = getApp();
if (app && app.globalData) {
app.globalData.showTabBar = false;
}
// 同时尝试直接更新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);
}
);
},
// 关闭商品详情
closeGoodsDetail: function () {
this.setData({
showGoodsDetail: false,
currentGoodsDetail: {}
});
// 显示底部导航栏 - 通过更新全局数据
const app = getApp();
if (app && app.globalData) {
app.globalData.showTabBar = true;
}
// 同时尝试直接更新tabBar的选中状态
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
const tabBar = this.getTabBar();
if (tabBar.setData) {
tabBar.setData({ show: true });
}
}
},
// 在详情弹窗中点击"我想要"按钮
onClickWantInDetail: function (e) {
const goodsId = e.currentTarget.dataset.id;
// 先关闭详情弹窗
this.closeGoodsDetail();
// 然后调用原来的"我想要"方法
this.onClickWant({ currentTarget: { dataset: { id: goodsId } } });
},
// 获取手机号并登录
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,
nickname: 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,
nickname: '微信用户',
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'
});
}
});
}
}
});
}
}
});