import _extends from "@babel/runtime/helpers/esm/extends"; import Vue from 'vue'; import Popup from '../popup'; import Toast from '../toast'; import ImagePreview from '../image-preview'; import SkuHeader from './components/SkuHeader'; import SkuHeaderItem from './components/SkuHeaderItem'; import SkuRow from './components/SkuRow'; import SkuRowItem from './components/SkuRowItem'; import SkuRowPropItem from './components/SkuRowPropItem'; import SkuStepper from './components/SkuStepper'; import SkuMessages from './components/SkuMessages'; import SkuActions from './components/SkuActions'; import { createNamespace } from '../utils'; import { isAllSelected, isSkuChoosable, getSkuComb, getSelectedSkuValues, getSelectedPropValues, getSelectedProperties } from './utils/sku-helper'; import { LIMIT_TYPE, UNSELECTED_SKU_VALUE_ID } from './constants'; var namespace = createNamespace('sku'); var createComponent = namespace[0], bem = namespace[1], t = namespace[2]; var QUOTA_LIMIT = LIMIT_TYPE.QUOTA_LIMIT; export default createComponent({ props: { sku: Object, goods: Object, value: Boolean, buyText: String, goodsId: [Number, String], priceTag: String, lazyLoad: Boolean, hideStock: Boolean, properties: Array, addCartText: String, stepperTitle: String, getContainer: [String, Function], hideQuotaText: Boolean, hideSelectedText: Boolean, resetStepperOnHide: Boolean, customSkuValidator: Function, disableStepperInput: Boolean, resetSelectedSkuOnHide: Boolean, quota: { type: Number, default: 0 }, quotaUsed: { type: Number, default: 0 }, startSaleNum: { type: Number, default: 1 }, initialSku: { type: Object, default: function _default() { return {}; } }, stockThreshold: { type: Number, default: 50 }, showSoldoutSku: { type: Boolean, default: true }, showAddCartBtn: { type: Boolean, default: true }, disableSoldoutSku: { type: Boolean, default: true }, customStepperConfig: { type: Object, default: function _default() { return {}; } }, showHeaderImage: { type: Boolean, default: true }, previewOnClickImage: { type: Boolean, default: true }, safeAreaInsetBottom: { type: Boolean, default: true }, closeOnClickOverlay: { type: Boolean, default: true }, bodyOffsetTop: { type: Number, default: 200 }, messageConfig: { type: Object, default: function _default() { return { initialMessages: {}, placeholderMap: {}, uploadImg: function uploadImg() { return Promise.resolve(); }, uploadMaxSize: 5 }; } } }, data: function data() { return { selectedSku: {}, selectedProp: {}, selectedNum: 1, show: this.value }; }, watch: { show: function show(val) { this.$emit('input', val); if (!val) { this.$emit('sku-close', { selectedSkuValues: this.selectedSkuValues, selectedNum: this.selectedNum, selectedSkuComb: this.selectedSkuComb }); if (this.resetStepperOnHide) { this.resetStepper(); } if (this.resetSelectedSkuOnHide) { this.resetSelectedSku(); } } }, value: function value(val) { this.show = val; }, skuTree: 'resetSelectedSku', initialSku: function initialSku() { this.resetStepper(); this.resetSelectedSku(); } }, computed: { skuGroupClass: function skuGroupClass() { return ['van-sku-group-container', { 'van-sku-group-container--hide-soldout': !this.showSoldoutSku }]; }, bodyStyle: function bodyStyle() { if (this.$isServer) { return; } var maxHeight = window.innerHeight - this.bodyOffsetTop; return { maxHeight: maxHeight + 'px' }; }, isSkuCombSelected: function isSkuCombSelected() { var _this = this; // SKU 未选完 if (this.hasSku && !isAllSelected(this.skuTree, this.selectedSku)) { return false; } // 属性未全选 return !this.propList.some(function (it) { return (_this.selectedProp[it.k_id] || []).length < 1; }); }, isSkuEmpty: function isSkuEmpty() { return Object.keys(this.sku).length === 0; }, hasSku: function hasSku() { return !this.sku.none_sku; }, hasSkuOrAttr: function hasSkuOrAttr() { return this.hasSku || this.propList.length > 0; }, selectedSkuComb: function selectedSkuComb() { var skuComb = null; if (this.isSkuCombSelected) { if (this.hasSku) { skuComb = getSkuComb(this.skuList, this.selectedSku); } else { skuComb = { id: this.sku.collection_id, price: Math.round(this.sku.price * 100), stock_num: this.sku.stock_num }; } if (skuComb) { skuComb.properties = getSelectedProperties(this.propList, this.selectedProp); skuComb.property_price = this.selectedPropValues.reduce(function (acc, cur) { return acc + (cur.price || 0); }, 0); } } return skuComb; }, selectedSkuValues: function selectedSkuValues() { return getSelectedSkuValues(this.skuTree, this.selectedSku); }, selectedPropValues: function selectedPropValues() { return getSelectedPropValues(this.propList, this.selectedProp); }, price: function price() { if (this.selectedSkuComb) { return ((this.selectedSkuComb.price + this.selectedSkuComb.property_price) / 100).toFixed(2); } // sku.price是一个格式化好的价格区间 return this.sku.price; }, originPrice: function originPrice() { if (this.selectedSkuComb && this.selectedSkuComb.origin_price) { return ((this.selectedSkuComb.origin_price + this.selectedSkuComb.property_price) / 100).toFixed(2); } return this.sku.origin_price; }, skuTree: function skuTree() { return this.sku.tree || []; }, skuList: function skuList() { return this.sku.list || []; }, propList: function propList() { return this.properties || []; }, imageList: function imageList() { var imageList = [this.goods.picture]; if (this.skuTree.length > 0) { this.skuTree.forEach(function (treeItem) { if (!treeItem.v) { return; } treeItem.v.forEach(function (vItem) { var imgUrl = vItem.previewImgUrl || vItem.imgUrl || vItem.img_url; if (imgUrl && imageList.indexOf(imgUrl) === -1) { imageList.push(imgUrl); } }); }); } return imageList; }, stock: function stock() { var stockNum = this.customStepperConfig.stockNum; if (stockNum !== undefined) { return stockNum; } if (this.selectedSkuComb) { return this.selectedSkuComb.stock_num; } return this.sku.stock_num; }, stockText: function stockText() { var h = this.$createElement; var stockFormatter = this.customStepperConfig.stockFormatter; if (stockFormatter) { return stockFormatter(this.stock); } return [t('stock') + " ", h("span", { "class": bem('stock-num', { highlight: this.stock < this.stockThreshold }) }, [this.stock]), " " + t('stockUnit')]; }, selectedText: function selectedText() { var _this2 = this; if (this.selectedSkuComb) { var values = this.selectedSkuValues.concat(this.selectedPropValues); return t('selected') + " " + values.map(function (item) { return item.name; }).join(' '); } var unselectedSku = this.skuTree.filter(function (item) { return _this2.selectedSku[item.k_s] === UNSELECTED_SKU_VALUE_ID; }).map(function (item) { return item.k; }); var unselectedProp = this.propList.filter(function (item) { return (_this2.selectedProp[item.k_id] || []).length < 1; }).map(function (item) { return item.k; }); return t('select') + " " + unselectedSku.concat(unselectedProp).join(' '); } }, created: function created() { var skuEventBus = new Vue(); this.skuEventBus = skuEventBus; skuEventBus.$on('sku:select', this.onSelect); skuEventBus.$on('sku:propSelect', this.onPropSelect); skuEventBus.$on('sku:numChange', this.onNumChange); skuEventBus.$on('sku:previewImage', this.onPreviewImage); skuEventBus.$on('sku:overLimit', this.onOverLimit); skuEventBus.$on('sku:stepperState', this.onStepperState); skuEventBus.$on('sku:addCart', this.onAddCart); skuEventBus.$on('sku:buy', this.onBuy); this.resetStepper(); this.resetSelectedSku(); // 组件初始化后的钩子,抛出skuEventBus this.$emit('after-sku-create', skuEventBus); }, methods: { resetStepper: function resetStepper() { var skuStepper = this.$refs.skuStepper; var selectedNum = this.initialSku.selectedNum; var num = selectedNum != null ? selectedNum : this.startSaleNum; // 用来缓存不合法的情况 this.stepperError = null; if (skuStepper) { skuStepper.setCurrentNum(num); } else { // 当首次加载(skuStepper 为空)时,传入数量如果不合法,可能会存在问题 this.selectedNum = num; } }, // @exposed-api resetSelectedSku: function resetSelectedSku() { var _this3 = this; this.selectedSku = {}; // 重置 selectedSku this.skuTree.forEach(function (item) { _this3.selectedSku[item.k_s] = UNSELECTED_SKU_VALUE_ID; }); this.skuTree.forEach(function (item) { var key = item.k_s; // 规格值只有1个时,优先判断 var valueId = item.v.length === 1 ? item.v[0].id : _this3.initialSku[key]; if (valueId && isSkuChoosable(_this3.skuList, _this3.selectedSku, { key: key, valueId: valueId })) { _this3.selectedSku[key] = valueId; } }); var skuValues = this.selectedSkuValues; if (skuValues.length > 0) { this.$nextTick(function () { _this3.$emit('sku-selected', { skuValue: skuValues[skuValues.length - 1], selectedSku: _this3.selectedSku, selectedSkuComb: _this3.selectedSkuComb }); }); } // 重置商品属性 this.selectedProp = {}; var _this$initialSku$sele = this.initialSku.selectedProp, selectedProp = _this$initialSku$sele === void 0 ? {} : _this$initialSku$sele; // 只有一个属性值时,默认选中,且选中外部传入信息 this.propList.forEach(function (item) { if (item.v && item.v.length === 1) { _this3.selectedProp[item.k_id] = [item.v[0].id]; } else if (selectedProp[item.k_id]) { _this3.selectedProp[item.k_id] = selectedProp[item.k_id]; } }); var propValues = this.selectedPropValues; if (propValues.length > 0) { this.$emit('sku-prop-selected', { propValue: propValues[propValues.length - 1], selectedProp: this.selectedProp, selectedSkuComb: this.selectedSkuComb }); } // 抛出重置事件 this.$emit('sku-reset', { selectedSku: this.selectedSku, selectedProp: this.selectedProp, selectedSkuComb: this.selectedSkuComb }); this.centerInitialSku(); }, getSkuMessages: function getSkuMessages() { return this.$refs.skuMessages ? this.$refs.skuMessages.getMessages() : {}; }, getSkuCartMessages: function getSkuCartMessages() { return this.$refs.skuMessages ? this.$refs.skuMessages.getCartMessages() : {}; }, validateSkuMessages: function validateSkuMessages() { return this.$refs.skuMessages ? this.$refs.skuMessages.validateMessages() : ''; }, validateSku: function validateSku() { if (this.selectedNum === 0) { return t('unavailable'); } if (this.isSkuCombSelected) { return this.validateSkuMessages(); } // 自定义sku校验 if (this.customSkuValidator) { var err = this.customSkuValidator(this); if (err) return err; } return t('selectSku'); }, onSelect: function onSelect(skuValue) { var _extends2, _extends3; // 点击已选中的sku时则取消选中 this.selectedSku = this.selectedSku[skuValue.skuKeyStr] === skuValue.id ? _extends({}, this.selectedSku, (_extends2 = {}, _extends2[skuValue.skuKeyStr] = UNSELECTED_SKU_VALUE_ID, _extends2)) : _extends({}, this.selectedSku, (_extends3 = {}, _extends3[skuValue.skuKeyStr] = skuValue.id, _extends3)); this.$emit('sku-selected', { skuValue: skuValue, selectedSku: this.selectedSku, selectedSkuComb: this.selectedSkuComb }); }, onPropSelect: function onPropSelect(propValue) { var _extends4; var arr = this.selectedProp[propValue.skuKeyStr] || []; var pos = arr.indexOf(propValue.id); if (pos > -1) { arr.splice(pos, 1); } else if (propValue.multiple) { arr.push(propValue.id); } else { arr.splice(0, 1, propValue.id); } this.selectedProp = _extends({}, this.selectedProp, (_extends4 = {}, _extends4[propValue.skuKeyStr] = arr, _extends4)); this.$emit('sku-prop-selected', { propValue: propValue, selectedProp: this.selectedProp, selectedSkuComb: this.selectedSkuComb }); }, onNumChange: function onNumChange(num) { this.selectedNum = num; }, onPreviewImage: function onPreviewImage(selectedValue) { var _this4 = this; var imageList = this.imageList; var index = 0; var indexImage = imageList[0]; if (selectedValue && selectedValue.imgUrl) { this.imageList.some(function (image, pos) { if (image === selectedValue.imgUrl) { index = pos; return true; } return false; }); indexImage = selectedValue.imgUrl; } var params = _extends({}, selectedValue, { index: index, imageList: this.imageList, indexImage: indexImage }); this.$emit('open-preview', params); if (!this.previewOnClickImage) { return; } ImagePreview({ images: this.imageList, startPosition: index, onClose: function onClose() { _this4.$emit('close-preview', params); } }); }, onOverLimit: function onOverLimit(data) { var action = data.action, limitType = data.limitType, quota = data.quota, quotaUsed = data.quotaUsed; var handleOverLimit = this.customStepperConfig.handleOverLimit; if (handleOverLimit) { handleOverLimit(data); return; } if (action === 'minus') { if (this.startSaleNum > 1) { Toast(t('minusStartTip', this.startSaleNum)); } else { Toast(t('minusTip')); } } else if (action === 'plus') { if (limitType === QUOTA_LIMIT) { if (quotaUsed > 0) { Toast(t('quotaUsedTip', quota, quotaUsed)); } else { Toast(t('quotaTip', quota)); } } else { Toast(t('soldout')); } } }, onStepperState: function onStepperState(data) { this.stepperError = data.valid ? null : _extends({}, data, { action: 'plus' }); }, onAddCart: function onAddCart() { this.onBuyOrAddCart('add-cart'); }, onBuy: function onBuy() { this.onBuyOrAddCart('buy-clicked'); }, onBuyOrAddCart: function onBuyOrAddCart(type) { // sku 不符合购买条件 if (this.stepperError) { return this.onOverLimit(this.stepperError); } var error = this.validateSku(); if (error) { Toast(error); } else { this.$emit(type, this.getSkuData()); } }, // @exposed-api getSkuData: function getSkuData() { return { goodsId: this.goodsId, messages: this.getSkuMessages(), selectedNum: this.selectedNum, cartMessages: this.getSkuCartMessages(), selectedSkuComb: this.selectedSkuComb }; }, // 当 popup 完全打开后执行 onOpened: function onOpened() { this.centerInitialSku(); }, centerInitialSku: function centerInitialSku() { var _this5 = this; (this.$refs.skuRows || []).forEach(function (it) { var _ref = it.skuRow || {}, k_s = _ref.k_s; it.centerItem(_this5.initialSku[k_s]); }); } }, render: function render() { var _this6 = this; var h = arguments[0]; if (this.isSkuEmpty) { return; } var sku = this.sku, skuList = this.skuList, goods = this.goods, price = this.price, lazyLoad = this.lazyLoad, originPrice = this.originPrice, skuEventBus = this.skuEventBus, selectedSku = this.selectedSku, selectedProp = this.selectedProp, selectedNum = this.selectedNum, stepperTitle = this.stepperTitle, selectedSkuComb = this.selectedSkuComb, showHeaderImage = this.showHeaderImage, disableSoldoutSku = this.disableSoldoutSku; var slotsProps = { price: price, originPrice: originPrice, selectedNum: selectedNum, skuEventBus: skuEventBus, selectedSku: selectedSku, selectedSkuComb: selectedSkuComb }; var slots = function slots(name) { return _this6.slots(name, slotsProps); }; var Header = slots('sku-header') || h(SkuHeader, { "attrs": { "sku": sku, "goods": goods, "skuEventBus": skuEventBus, "selectedSku": selectedSku, "showHeaderImage": showHeaderImage } }, [h("template", { "slot": "sku-header-image-extra" }, [slots('sku-header-image-extra')]), slots('sku-header-price') || h("div", { "class": "van-sku__goods-price" }, [h("span", { "class": "van-sku__price-symbol" }, ["\uFFE5"]), h("span", { "class": "van-sku__price-num" }, [price]), this.priceTag && h("span", { "class": "van-sku__price-tag" }, [this.priceTag])]), slots('sku-header-origin-price') || originPrice && h(SkuHeaderItem, [t('originPrice'), " \uFFE5", originPrice]), !this.hideStock && h(SkuHeaderItem, [h("span", { "class": "van-sku__stock" }, [this.stockText])]), this.hasSkuOrAttr && !this.hideSelectedText && h(SkuHeaderItem, [this.selectedText]), slots('sku-header-extra')]); var Group = slots('sku-group') || this.hasSkuOrAttr && h("div", { "class": this.skuGroupClass }, [this.skuTree.map(function (skuTreeItem) { return h(SkuRow, { "attrs": { "skuRow": skuTreeItem }, "ref": "skuRows", "refInFor": true }, [skuTreeItem.v.map(function (skuValue) { return h(SkuRowItem, { "attrs": { "skuList": skuList, "lazyLoad": lazyLoad, "skuValue": skuValue, "skuKeyStr": skuTreeItem.k_s, "selectedSku": selectedSku, "skuEventBus": skuEventBus, "disableSoldoutSku": disableSoldoutSku, "largeImageMode": skuTreeItem.largeImageMode } }); })]); }), this.propList.map(function (skuTreeItem) { return h(SkuRow, { "attrs": { "skuRow": skuTreeItem } }, [skuTreeItem.v.map(function (skuValue) { return h(SkuRowPropItem, { "attrs": { "skuValue": skuValue, "skuKeyStr": skuTreeItem.k_id + '', "selectedProp": selectedProp, "skuEventBus": skuEventBus, "multiple": skuTreeItem.is_multiple } }); })]); })]); var Stepper = slots('sku-stepper') || h(SkuStepper, { "ref": "skuStepper", "attrs": { "stock": this.stock, "quota": this.quota, "quotaUsed": this.quotaUsed, "startSaleNum": this.startSaleNum, "skuEventBus": skuEventBus, "selectedNum": selectedNum, "stepperTitle": stepperTitle, "skuStockNum": sku.stock_num, "disableStepperInput": this.disableStepperInput, "customStepperConfig": this.customStepperConfig, "hideQuotaText": this.hideQuotaText }, "on": { "change": function change(event) { _this6.$emit('stepper-change', event); } } }); var Messages = slots('sku-messages') || h(SkuMessages, { "ref": "skuMessages", "attrs": { "goodsId": this.goodsId, "messageConfig": this.messageConfig, "messages": sku.messages } }); var Actions = slots('sku-actions') || h(SkuActions, { "attrs": { "buyText": this.buyText, "skuEventBus": skuEventBus, "addCartText": this.addCartText, "showAddCartBtn": this.showAddCartBtn } }); return h(Popup, { "attrs": { "round": true, "closeable": true, "position": "bottom", "getContainer": this.getContainer, "closeOnClickOverlay": this.closeOnClickOverlay, "safeAreaInsetBottom": this.safeAreaInsetBottom }, "class": "van-sku-container", "on": { "opened": this.onOpened }, "model": { value: _this6.show, callback: function callback($$v) { _this6.show = $$v; } } }, [Header, h("div", { "class": "van-sku-body", "style": this.bodyStyle }, [slots('sku-body-top'), Group, slots('extra-sku-group'), Stepper, Messages]), slots('sku-actions-top'), Actions]); } });