Files
ai_dianshang/miniprogram/pages/cart/components/specs-popup/index.js
2025-11-17 14:11:46 +08:00

274 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { fetchGood } from '../../../../services/good/fetchGood';
import Toast from 'tdesign-miniprogram/toast/index';
Component({
options: {
addGlobalClass: true,
multipleSlots: true, // 在组件定义时的选项中启用多slot支持
},
properties: {
show: {
type: Boolean,
value: false,
observer(newVal) {
if (newVal && this.data.spuId) {
this.loadProductDetail();
}
},
},
spuId: {
type: String,
value: '',
},
skuId: {
type: String,
value: '',
},
value: {
type: String,
value: '',
},
title: {
type: String,
observer(newVal) {
this.setData({ 'goods.title': newVal });
},
},
price: {
type: String,
value: '',
observer(newVal) {
this.setData({ 'goods.price': newVal });
},
},
thumb: {
type: String,
value: '',
observer(newVal) {
this.setData({ 'goods.thumb': newVal });
},
},
thumbMode: {
type: String,
value: 'aspectFit',
},
zIndex: {
type: Number,
value: 99,
},
},
data: {
goods: {
title: '',
thumb: '',
price: '',
hideKey: {
originPrice: true,
tags: true,
specs: true,
num: true,
},
},
specList: [],
skuList: [],
selectedSku: {},
isAllSelectedSku: false,
selectSkuSellsPrice: 0,
currentPrice: '',
buyNum: 1,
loading: false,
},
methods: {
async loadProductDetail() {
const { spuId, skuId } = this.data;
if (!spuId) return;
this.setData({ loading: true });
try {
const detail = await fetchGood(spuId);
const { specList = [], skuList = [], minSalePrice } = detail;
// 处理SKU数据
const skuArray = skuList.map((sku) => ({
...sku,
specInfo: sku.specInfo || [],
quantity: Number(
(sku.stockInfo && sku.stockInfo.stockQuantity) || sku.stock || sku.quantity || 0
),
price: Number((sku.priceInfo && sku.priceInfo[0] && sku.priceInfo[0].price) || sku.price || 0),
skuId: sku.skuId || sku.id,
}));
// 初始化规格选择默认选中当前SKU
this.initSpecSelection(specList, skuArray, skuId);
this.setData({
specList,
skuList: skuArray,
selectSkuSellsPrice: minSalePrice,
currentPrice: minSalePrice,
loading: false,
});
} catch (error) {
console.error('加载商品详情失败:', error);
Toast({
context: this,
selector: '#t-toast',
message: '加载失败,请重试',
theme: 'error',
});
this.setData({ loading: false });
}
},
initSpecSelection(specList, skuArray, currentSkuId) {
const selectedSku = {};
// 查找当前SKU
const currentSku = skuArray.find(sku => String(sku.skuId) === String(currentSkuId));
console.log('[初始化规格] 当前SKU ID:', currentSkuId);
console.log('[初始化规格] 匹配的SKU:', currentSku);
if (currentSku && Array.isArray(currentSku.specInfo)) {
// 标记当前SKU的规格为选中
currentSku.specInfo.forEach((spec) => {
const specId = spec.specId;
const specValueId = spec.specValueId;
specList.forEach((group) => {
if (String(group.specId) === String(specId)) {
group.specValueList.forEach((sv) => {
sv.isSelected = String(sv.specValueId) === String(specValueId);
});
selectedSku[group.specId] = specValueId;
}
});
});
}
const isAllSelectedSku = specList.every((spec) => !!selectedSku[spec.specId]);
// 更新价格
const initPrice = currentSku ? currentSku.price : (skuArray[0] ? skuArray[0].price : 0);
console.log('[初始化规格] 初始价格:', initPrice);
this.setData({
selectedSku,
isAllSelectedSku,
selectSkuSellsPrice: initPrice,
currentPrice: initPrice,
'goods.price': initPrice,
});
},
toChooseItem(e) {
const { specid, id } = e.currentTarget.dataset;
const { specList, skuList } = this.data;
// 更新选中状态
specList.forEach((spec) => {
if (String(spec.specId) === String(specid)) {
spec.specValueList.forEach((specValue) => {
specValue.isSelected = String(specValue.specValueId) === String(id);
});
}
});
// 更新selectedSku
const selectedSku = { ...this.data.selectedSku };
selectedSku[specid] = id;
const isAllSelectedSku = specList.every((spec) => !!selectedSku[spec.specId]);
this.setData({
specList,
selectedSku,
isAllSelectedSku,
});
// 查找SKU并更新价格
if (isAllSelectedSku) {
const matchedSku = this.findMatchedSku(selectedSku, skuList);
if (matchedSku) {
console.log('[SKU选择] 匹配SKU:', matchedSku);
console.log('[SKU选择] SKU价格:', matchedSku.price);
this.setData({
selectSkuSellsPrice: matchedSku.price,
currentPrice: matchedSku.price,
'goods.price': matchedSku.price,
});
} else {
console.warn('[SKU选择] 未找到匹配SKU');
}
}
},
findMatchedSku(selectedSku, skuList) {
return skuList.find((sku) => {
if (!sku.specInfo || sku.specInfo.length === 0) return false;
return sku.specInfo.every((spec) => {
const specId = String(spec.specId);
const specValueId = String(spec.specValueId);
const selectedSpecValueId = String(selectedSku[specId] || '');
return selectedSpecValueId === specValueId;
});
});
},
onClose() {
this.triggerEvent('close');
},
onConfirm() {
const { isAllSelectedSku, selectedSku, skuList, spuId, buyNum } = this.data;
if (!isAllSelectedSku) {
Toast({
context: this,
selector: '#t-toast',
message: '请选择完整的商品规格',
theme: 'warning',
});
return;
}
// 查找匹配SKU
const matchedSku = this.findMatchedSku(selectedSku, skuList);
if (!matchedSku) {
Toast({
context: this,
selector: '#t-toast',
message: '该规格不存在',
theme: 'error',
});
return;
}
// 触发confirm事件传递数量
this.triggerEvent('confirm', {
spuId,
skuId: matchedSku.skuId,
price: matchedSku.price,
quantity: buyNum,
});
},
handleBuyNumChange(e) {
const { value } = e.detail;
this.setData({
buyNum: value,
});
},
onCloseOver() {
this.triggerEvent('closeover');
},
},
});