Browse Source

修复规格状态显示,实现规格下架多选功能,修复售空标签遮挡问题

pull/19/head
Default User 1 month ago
parent
commit
29b33bd247
  1. 214
      pages/goods-update/goods-update.js
  2. 48
      pages/goods-update/goods-update.wxml
  3. 7
      pages/goods-update/goods-update.wxss
  4. 2
      server-example/server-mysql.js

214
pages/goods-update/goods-update.js

@ -380,6 +380,10 @@ Page({
offsetX: 0, // X轴偏移量 offsetX: 0, // X轴偏移量
offsetY: 0, // Y轴偏移量 offsetY: 0, // Y轴偏移量
initialTouch: null, // 初始触摸点 initialTouch: null, // 初始触摸点
// 规格下架相关状态
showSpecUnpublishModal: false, // 控制规格下架弹窗显示
selectedSpecIndices: [], // 选中的规格索引数组,支持多选
isSelected: [] // 每个规格的选中状态数组,true表示选中,false表示未选中
}, },
onLoad: function (options) { onLoad: function (options) {
@ -766,6 +770,8 @@ Page({
region: finalRegion, region: finalRegion,
// 产品日志信息 - 确保是数组格式 // 产品日志信息 - 确保是数组格式
product_log: productLog, product_log: productLog,
// 添加sellerId字段,确保它存在
sellerId: product.sellerId || product.seller_id || product.userId || product.user_id || product.creatorId || product.creator_id || '',
// 复制原始产品对象中的所有字段,确保不丢失任何数据 // 复制原始产品对象中的所有字段,确保不丢失任何数据
...product, ...product,
// 重新设置关键字段,防止被product数据覆盖 // 重新设置关键字段,防止被product数据覆盖
@ -793,7 +799,9 @@ Page({
price: defaultPrice, price: defaultPrice,
costprice: defaultCostprice, costprice: defaultCostprice,
// 确保产品日志字段使用我们处理后的值 - 确保是数组格式 // 确保产品日志字段使用我们处理后的值 - 确保是数组格式
product_log: productLog product_log: productLog,
// 确保sellerId字段存在,放在最后覆盖所有来源的值
sellerId: product.sellerId || product.seller_id || (product.seller ? product.seller.userId : '') || product.userId || product.user_id || product.creatorId || product.creator_id || ''
}; };
console.log('最终formattedGoods.status:', formattedGoods.status); console.log('最终formattedGoods.status:', formattedGoods.status);
@ -1639,17 +1647,10 @@ Page({
// 确认下架(实际执行下架确认的内部方法) // 确认下架(实际执行下架确认的内部方法)
confirmUnpublish: function() { confirmUnpublish: function() {
const goodsDetail = this.data.goodsDetail; // 显示规格选择弹窗,让用户选择要下架的规格
const productId = goodsDetail.productId || goodsDetail.id; this.setData({
showSpecUnpublishModal: true,
wx.showModal({ selectedSpecIndex: -1 // 重置选中索引
title: '确认下架',
content: '确定要下架此商品吗?',
success: (res) => {
if (res.confirm) {
this.unpublishSupply(productId);
}
}
}); });
}, },
@ -1696,6 +1697,195 @@ Page({
}); });
}, },
// 规格下架选择(支持多选)
onSpecUnpublishSelect: function(e) {
const index = e.currentTarget.dataset.index;
let selectedSpecIndices = [...this.data.selectedSpecIndices];
let isSelected = [...this.data.isSelected];
// 确保isSelected数组长度足够
while (isSelected.length <= index) {
isSelected.push(false);
}
// 切换选中状态
const isCurrentlySelected = isSelected[index];
isSelected[index] = !isCurrentlySelected;
// 更新selectedSpecIndices数组
const indexInArray = selectedSpecIndices.indexOf(index);
if (isCurrentlySelected) {
// 已选中,取消选择,从数组中移除
selectedSpecIndices.splice(indexInArray, 1);
} else {
// 未选中,添加选择,添加到数组中
selectedSpecIndices.push(index);
}
this.setData({
selectedSpecIndices: selectedSpecIndices,
isSelected: isSelected
});
},
// 关闭规格下架弹窗
closeSpecUnpublishModal: function() {
this.setData({
showSpecUnpublishModal: false,
selectedSpecIndices: [],
isSelected: []
});
},
// 确认规格下架
confirmSpecUnpublish: function() {
const selectedIndices = this.data.selectedSpecIndices;
if (selectedIndices.length === 0) {
wx.showToast({
title: '请选择要下架的规格',
icon: 'none',
duration: 2000
});
return;
}
const goodsDetail = this.data.goodsDetail;
const productId = goodsDetail.productId || goodsDetail.id;
const weightQuantityData = goodsDetail.weightQuantityData || [];
// 获取当前的spec_status字符串
let currentSpecStatus = goodsDetail.spec_status || '';
let specStatusArray = [];
if (currentSpecStatus) {
specStatusArray = currentSpecStatus.split(/[,,、]/).map(item => item.trim()).filter(item => item);
}
// 确保specStatusArray长度足够
const maxIndex = Math.max(...selectedIndices, weightQuantityData.length - 1);
while (specStatusArray.length <= maxIndex) {
specStatusArray.push('0');
}
// 设置所有选中的规格为售空状态
selectedIndices.forEach(index => {
specStatusArray[index] = '1';
});
// 更新spec_status字符串
const newSpecStatus = specStatusArray.join(',');
// 调用API更新规格状态
wx.showLoading({
title: '处理中...',
mask: true
});
// 添加调试日志
console.log('===== 调试规格更新API调用 =====');
console.log('goodsDetail对象:', JSON.stringify(goodsDetail, null, 2));
console.log('productId:', productId);
console.log('goodsDetail.sellerId:', goodsDetail.sellerId);
console.log('goodsDetail.seller_id:', goodsDetail.seller_id);
console.log('goodsDetail.seller:', JSON.stringify(goodsDetail.seller, null, 2));
console.log('goodsDetail.seller.userId:', goodsDetail.seller ? goodsDetail.seller.userId : 'undefined');
const updateData = {
productId: productId,
sellerId: goodsDetail.sellerId || goodsDetail.seller_id || (goodsDetail.seller ? goodsDetail.seller.userId : ''),
spec_status: newSpecStatus
};
console.log('最终发送的updateData:', JSON.stringify(updateData, null, 2));
API.request('/api/products/edit', 'POST', updateData)
.then(res => {
wx.hideLoading();
console.log('更新规格状态成功:', res);
if (res && (res.code === 200 || res.success === true)) {
wx.showToast({
title: '规格下架成功',
icon: 'success',
duration: 2000
});
// 更新本地数据
const updatedWeightQuantityData = [...weightQuantityData];
// 更新所有选中规格的状态
selectedIndices.forEach(index => {
updatedWeightQuantityData[index].specStatus = '1';
});
// 详细调试日志:检查updatedWeightQuantityData数组的内容
console.log('=== 全部规格下架判断调试 ===');
console.log('更新后的weightQuantityData数组:', JSON.stringify(updatedWeightQuantityData, null, 2));
console.log('数组长度:', updatedWeightQuantityData.length);
// 遍历数组,检查每个规格的specStatus
updatedWeightQuantityData.forEach((item, index) => {
console.log(`${index}个规格: specStatus=${item.specStatus}, 类型=${typeof item.specStatus}`);
});
// 检查是否所有规格都已下架
const allSoldOut = updatedWeightQuantityData.every(item => item.specStatus === '1');
console.log('allSoldOut判断结果:', allSoldOut);
// 更新本地商品状态
this.setData({
'goodsDetail.weightQuantityData': updatedWeightQuantityData,
'goodsDetail.spec_status': newSpecStatus,
'goodsDetail.status': allSoldOut ? 'sold_out' : 'published',
'goodsDetail.label': allSoldOut ? 1 : 0,
showSpecUnpublishModal: false,
selectedSpecIndices: []
});
// 如果所有规格都已下架,调用下架功能接口,确保服务器端更新商品状态
if (allSoldOut) {
console.log('所有规格都已下架,调用下架功能接口更新商品状态');
API.unpublishProduct({ productId: productId })
.then(res => {
console.log('调用下架功能接口成功:', res);
// 再次检查服务器返回后的商品状态
return API.getProductDetail({ productId: productId });
})
.then(detailRes => {
console.log('重新获取商品详情成功:', detailRes);
if (detailRes && detailRes.code === 200 && detailRes.data) {
// 只更新需要的字段,避免丢失本地状态
this.setData({
'goodsDetail.status': detailRes.data.status,
'goodsDetail.label': detailRes.data.label,
'goodsDetail.spec_status': detailRes.data.spec_status
});
}
})
.catch(err => {
console.error('调用下架功能接口失败:', err);
// 接口调用失败不影响本地状态更新,只记录日志
});
} else {
console.log('并非所有规格都已下架,无需调用下架功能接口');
}
} else {
wx.showToast({
title: '更新失败',
icon: 'none',
duration: 2000
});
}
})
.catch(err => {
wx.hideLoading();
console.error('更新规格状态失败:', err);
wx.showToast({
title: '更新失败',
icon: 'none',
duration: 2000
});
});
},
// 编辑输入处理 // 编辑输入处理
onEditInput: function(e) { onEditInput: function(e) {
const field = e.currentTarget.dataset.field; const field = e.currentTarget.dataset.field;

48
pages/goods-update/goods-update.wxml

@ -500,4 +500,52 @@
</scroll-view> </scroll-view>
</view> </view>
</view> </view>
<!-- 规格选择弹窗 - 用于下架单个规格 -->
<view class="custom-select-modal" wx:if="{{showSpecUnpublishModal}}" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); display: flex; justify-content: center; z-index: 9999;" catchtouchmove="true">
<view style="position: fixed; bottom: 0; left: 0; right: 0; background: white; border-radius: 20rpx 20rpx 0 0; max-height: 80vh;">
<!-- 顶部操作栏:取消和确定按钮 -->
<view style="padding: 20rpx; display: flex; justify-content: space-between; align-items: center; border-bottom: 1rpx solid #eee;">
<view bindtap="closeSpecUnpublishModal" style="font-size: 32rpx; color: #333; padding: 10rpx 20rpx;">取消</view>
<view bindtap="confirmSpecUnpublish" style="font-size: 32rpx; color: #07c160; padding: 10rpx 20rpx;">确定</view>
</view>
<view style="padding: 20rpx; font-size: 28rpx; color: #333; text-align: center; border-bottom: 1rpx solid #eee;">
请选择要下架的规格
</view>
<!-- 规格列表 -->
<scroll-view
scroll-y="true"
style="max-height: 60vh; padding: 0; -webkit-overflow-scrolling: touch;"
enable-back-to-top="false"
>
<view
wx:for="{{goodsDetail.weightQuantityData}}"
wx:key="index"
class="spec-item"
bindtap="onSpecUnpublishSelect"
data-index="{{index}}"
style="padding: 32rpx 40rpx; border-bottom: 1rpx solid #f0f0f0; font-size: 32rpx; color: {{item.specStatus == '1' ? '#999999' : '#131413'}}; text-align: left; position: relative; display: flex; justify-content: space-between; align-items: center;"
>
<view class="spec-info" style="flex: 1;">
<view>{{item.weightSpec}}</view>
<view style="font-size: 24rpx; color: #666; margin-top: 8rpx;">
{{item.quantity}} | 售价:{{item.price || '暂无'}}元 | 采购价:{{item.costprice || '暂无'}}元
</view>
</view>
<view style="display: flex; align-items: center;">
<view wx:if="{{item.specStatus == '1'}}" class="sold-out-tag" style="margin-right: 20rpx;">
已售空
</view>
<view wx:if="{{isSelected[index]}}" class="checkbox selected" style="width: 40rpx; height: 40rpx; border: 2rpx solid #07c160; border-radius: 4rpx; display: flex; justify-content: center; align-items: center; margin-right: 20rpx; background-color: #07c160;">
<text style="color: #ffffff; font-size: 24rpx;">✓</text>
</view>
<view wx:else class="checkbox" style="width: 40rpx; height: 40rpx; border: 2rpx solid #d9d9d9; border-radius: 4rpx; display: flex; justify-content: center; align-items: center; margin-right: 20rpx; background-color: #ffffff;">
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view> </view>

7
pages/goods-update/goods-update.wxss

@ -1507,7 +1507,7 @@ video.slider-media .wx-video-volume-icon {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 12rpx; gap: 12rpx;
overflow: hidden; overflow: visible;
} }
.wq-block-row { .wq-block-row {
@ -1535,7 +1535,7 @@ video.slider-media .wx-video-volume-icon {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: visible;
} }
/* 固定宽度块 */ /* 固定宽度块 */
@ -1552,7 +1552,8 @@ video.slider-media .wx-video-volume-icon {
} }
.price-block { .price-block {
flex: 0 0 140rpx; flex: 1 1 auto;
min-width: 140rpx;
} }
.block-text { .block-text {

2
server-example/server-mysql.js

@ -4164,7 +4164,7 @@ app.post('/api/products/detail', async (req, res) => {
// 查询商品详情 - 排除hidden状态商品,直接使用Product表中的reservedCount字段 // 查询商品详情 - 排除hidden状态商品,直接使用Product表中的reservedCount字段
const product = await Product.findOne({ const product = await Product.findOne({
attributes: ['productId', 'productName', 'price', 'quantity', 'grossWeight', 'imageUrls', 'created_at', 'specification', 'yolk', 'sourceType', 'supplyStatus', 'producting', 'product_contact', 'contact_phone', 'region', 'freshness', 'costprice','description', 'frequency', 'product_log', 'spec_status'], attributes: ['productId', 'productName', 'price', 'quantity', 'grossWeight', 'imageUrls', 'created_at', 'specification', 'yolk', 'sourceType', 'supplyStatus', 'producting', 'product_contact', 'contact_phone', 'region', 'freshness', 'costprice','description', 'frequency', 'product_log', 'spec_status', 'status', 'label'],
where: { where: {
productId, productId,
status: { [Sequelize.Op.not]: 'hidden' } status: { [Sequelize.Op.not]: 'hidden' }

Loading…
Cancel
Save