/* eslint-disable no-param-reassign */ /* eslint-disable no-nested-ternary */ import Toast from 'tdesign-miniprogram/toast/index'; Component({ options: { multipleSlots: true, addGlobalClass: true, }, properties: { src: { type: String, }, title: String, show: { type: Boolean, value: false, }, limitBuyInfo: { type: String, value: '', }, isStock: { type: Boolean, value: true, }, limitMaxCount: { type: Number, value: 999, }, limitMinCount: { type: Number, value: 1, }, skuList: { type: Array, value: [], observer(skuList) { if (skuList && skuList.length > 0) { if (this.initStatus) { this.initData(); } } }, }, specList: { type: Array, value: [], observer(specList) { if (specList && specList.length > 0) { this.initData(); } }, }, outOperateStatus: { type: Boolean, value: false, }, hasAuth: { type: Boolean, value: false, }, count: { type: Number, value: 1, observer(count) { this.setData({ buyNum: count, }); }, }, }, initStatus: false, selectedSku: {}, selectSpecObj: {}, data: { buyNum: 1, isAllSelectedSku: false, }, methods: { initData() { const { skuList } = this.properties; const { specList } = this.properties; // 为每个规格值计算库存信息 specList.forEach((item) => { if (item.specValueList.length > 0) { item.specValueList.forEach((subItem) => { const obj = this.checkSkuStockQuantity(subItem, skuList, item); subItem.hasStockObj = obj; // 初始化未选中状态 subItem.isSelected = false; }); } }); // 默认选择策略:优先选择第一个有库存的SKU组合,其次选择第一个SKU const getQty = (sku) => { return Number((sku.stockInfo && sku.stockInfo.stockQuantity) ?? sku.stock ?? sku.quantity ?? 0) || 0; }; const defaultSku = (skuList || []).find((s) => getQty(s) > 0) || (skuList || [])[0]; // 构建 selectedSku 映射,并在 specList 中标记选中项 const selectedSkuMap = {}; if (defaultSku && Array.isArray(defaultSku.specInfo)) { defaultSku.specInfo.forEach((spec) => { const specId = spec.specId; const specValueId = spec.specValueId; const specTitle = spec.specTitle; const specValue = spec.specValue; // 在对应的规格组内标记选中项 specList.forEach((group) => { const sameGroup = String(group.specId) === String(specId) || (!!specTitle && group.title === specTitle); if (sameGroup && Array.isArray(group.specValueList)) { group.specValueList.forEach((sv) => { const matchById = specValueId != null && String(sv.specValueId) === String(specValueId); const matchByText = specValue != null && sv.specValue != null && sv.specValue === specValue; sv.isSelected = matchById || matchByText; }); // 记录所选项的ID(优先使用ID) const chosen = group.specValueList.find((sv) => sv.isSelected); if (chosen) { selectedSkuMap[group.specId] = chosen.specValueId; } } }); }); } else { // 当没有SKU或SKU缺少specInfo时,退化为每组选择第一个有库存的规格值 specList.forEach((group) => { const firstAvailable = (group.specValueList || []).find((sv) => sv.hasStockObj?.hasStock) || (group.specValueList || [])[0]; if (firstAvailable) { group.specValueList.forEach((sv) => { sv.isSelected = sv === firstAvailable; }); selectedSkuMap[group.specId] = firstAvailable.specValueId; } }); } // 更新组件状态 const isAllSelectedSku = specList.every((spec) => !!selectedSkuMap[spec.specId]); this.selectedSku = selectedSkuMap; this.selectSpecObj = {}; this.setData({ specList, isAllSelectedSku, }); // 通知父页面已完成默认选择,便于价格与图片联动 this.triggerEvent('change', { selectedSku: this.selectedSku, isAllSelectedSku, }); this.initStatus = true; }, // 兼容两种数据结构: // 1) sku.specInfo 使用 { specId, specValueId } // 2) sku.specInfo 使用 { specTitle, specValue } // 同时 specList.subItem 具备 { specValueId, specValue } checkSkuStockQuantity(specValueItem, skuList, specGroupItem) { let hasStock = false; let stockQuantity = 0; skuList.forEach((sku) => { if (sku.specInfo) { sku.specInfo.forEach((spec) => { // 统一以字符串比较,避免类型不一致导致匹配失败 const matchById = spec.specValueId != null && specValueItem.specValueId != null && String(spec.specValueId) === String(specValueItem.specValueId); const sameGroupByTitle = spec.specTitle && specGroupItem && specGroupItem.title && spec.specTitle === specGroupItem.title; const matchByText = spec.specValue != null && specValueItem.specValue != null && spec.specValue === specValueItem.specValue && (sameGroupByTitle || true); // 若无 title 也放行文本匹配 if (matchById || matchByText) { // 兼容多种库存字段来源,优先 stockInfo.stockQuantity const qty = Number( (sku.stockInfo && sku.stockInfo.stockQuantity) ?? sku.stock ?? sku.quantity ?? 0 ) || 0; stockQuantity += qty; if (qty > 0) { hasStock = true; } } }); } }); return { hasStock, stockQuantity, }; }, toChooseItem(e) { const { specid, id, val } = e.currentTarget.dataset; // 放开点击,避免因错误的 hasStock 计算而阻断选择 const { specList } = this.data; const { skuList } = this.properties; specList.forEach((spec) => { if (String(spec.specId) === String(specid)) { spec.specValueList.forEach((specValue) => { if (String(specValue.specValueId) === String(id)) { specValue.isSelected = !specValue.isSelected; } else { specValue.isSelected = false; } }); } }); this.selectSpecObj[specid] = { specId: specid, specValueId: id, specValue: val, }; this.selectedSku[specid] = id; const isAllSelectedSku = this.isAllSelectedSku(); this.setData({ specList, isAllSelectedSku, }); // 与父页面绑定的事件名保持一致:父页面使用 bind:change="chooseSpecItem" this.triggerEvent('change', { selectedSku: this.selectedSku, isAllSelectedSku, }); }, isAllSelectedSku() { const { specList } = this.properties; let isAllSelectedSku = true; specList.forEach((spec) => { if (!this.selectedSku[spec.specId]) { isAllSelectedSku = false; } }); return isAllSelectedSku; }, getSelectedSkuId() { const { skuList } = this.properties; const { selectedSku } = this; let selectedSkuId = ''; skuList.forEach((sku) => { let isMatch = true; if (sku.specInfo) { sku.specInfo.forEach((spec) => { // 统一字符串比较避免类型不一致导致匹配失败 if (String(selectedSku[spec.specId]) !== String(spec.specValueId)) { isMatch = false; } }); } if (isMatch) { selectedSkuId = sku.skuId; } }); return selectedSkuId; }, handlePopupHide() { // 触发与父页面绑定一致的事件名,确保可以关闭弹窗 this.triggerEvent('closeSpecsPopup'); }, specsConfirm() { const { isAllSelectedSku } = this.data; if (!isAllSelectedSku) { Toast({ context: this, selector: '#t-toast', message: '请选择完整的商品规格', theme: 'warning', direction: 'column', }); return; } this.triggerEvent('specsConfirm', { selectedSku: this.selectedSku, buyNum: this.data.buyNum, }); }, addCart() { const { isAllSelectedSku } = this.data; if (!isAllSelectedSku) { Toast({ context: this, selector: '#t-toast', message: '请选择完整的商品规格', theme: 'warning', direction: 'column', }); return; } this.triggerEvent('addCart', { selectedSku: this.selectedSku, buyNum: this.data.buyNum, }); }, buyNow() { const { isAllSelectedSku } = this.data; if (!isAllSelectedSku) { Toast({ context: this, selector: '#t-toast', message: '请选择完整的商品规格', theme: 'warning', direction: 'column', }); return; } this.triggerEvent('buyNow', { selectedSku: this.selectedSku, buyNum: this.data.buyNum, }); }, setBuyNum(e) { const { value } = e.detail; this.setData({ buyNum: value, }); }, changeNum(e) { const { buyNum } = e.detail; this.setData({ buyNum, }); }, handleBuyNumChange(e) { const { value } = e.detail; this.setData({ buyNum: value, }); // 触发父组件的 changeNum 事件,通知价格更新 this.triggerEvent('changeNum', { buyNum: value, }); }, }, });