UNPKG

lulouis-vant

Version:

Lightweight Mobile UI Components built on Vue

460 lines (428 loc) 13.5 kB
import _extends from "@babel/runtime/helpers/esm/extends"; /* eslint-disable camelcase */ import Vue from 'vue'; import Popup from '../popup'; import Toast from '../toast'; import ImagePreview from '../image-preview'; import SkuHeader from './components/SkuHeader'; import SkuRow from './components/SkuRow'; import SkuRowItem from './components/SkuRowItem'; import SkuStepper from './components/SkuStepper'; import SkuMessages from './components/SkuMessages'; import SkuActions from './components/SkuActions'; import { isAllSelected, isSkuChoosable, getSkuComb, getSelectedSkuValues } from './utils/skuHelper'; import { LIMIT_TYPE, UNSELECTED_SKU_VALUE_ID } from './constants'; import create from '../utils/create'; var QUOTA_LIMIT = LIMIT_TYPE.QUOTA_LIMIT; export default create({ render: function render() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return !_vm.isSkuEmpty ? _c('popup', { staticClass: "van-sku-container", attrs: { "position": "bottom", "close-on-click-overlay": _vm.closeOnClickOverlay, "get-container": _vm.getContainer }, model: { value: _vm.show, callback: function callback($$v) { _vm.show = $$v; }, expression: "show" } }, [_vm._t("sku-header", [_c('sku-header', { attrs: { "sku-event-bus": _vm.skuEventBus, "selected-sku": _vm.selectedSku, "goods": _vm.goods, "sku": _vm.sku } }, [_vm._t("sku-header-price", [_c('div', { staticClass: "van-sku__goods-price" }, [_c('span', { staticClass: "van-sku__price-symbol" }, [_vm._v("¥")]), _c('span', { staticClass: "van-sku__price-num", domProps: { "textContent": _vm._s(_vm.price) } })])], { price: _vm.price, selectedSkuComb: _vm.selectedSkuComb })], 2)], { skuEventBus: _vm.skuEventBus, selectedSku: _vm.selectedSku, selectedSkuComb: _vm.selectedSkuComb }), _c('div', { staticClass: "van-sku-body", style: _vm.bodyStyle }, [_vm._t("sku-body-top", null, { selectedSku: _vm.selectedSku, skuEventBus: _vm.skuEventBus }), _vm._t("sku-group", [_vm.hasSku ? _c('div', { class: _vm.skuGroupClass }, _vm._l(_vm.skuTree, function (skuTreeItem, index) { return _c('sku-row', { key: index, attrs: { "sku-row": skuTreeItem } }, _vm._l(skuTreeItem.v, function (skuValue, valueIndex) { return _c('sku-row-item', { key: valueIndex, attrs: { "sku-key-str": skuTreeItem.k_s, "sku-value": skuValue, "sku-event-bus": _vm.skuEventBus, "selected-sku": _vm.selectedSku, "sku-list": _vm.sku.list } }); }), 1); }), 1) : _vm._e()], { selectedSku: _vm.selectedSku, skuEventBus: _vm.skuEventBus }), _vm._t("extra-sku-group", null, { skuEventBus: _vm.skuEventBus }), _vm._t("sku-stepper", [_c('sku-stepper', { ref: "skuStepper", attrs: { "sku-event-bus": _vm.skuEventBus, "selected-sku": _vm.selectedSku, "selected-sku-comb": _vm.selectedSkuComb, "selected-num": _vm.selectedNum, "stepper-title": _vm.stepperTitle, "sku-stock-num": _vm.sku.stock_num, "hide-quota-text": _vm.hideQuotaText, "quota": _vm.quota, "quota-used": _vm.quotaUsed, "disable-stepper-input": _vm.disableStepperInput, "hide-stock": _vm.hideStock, "custom-stepper-config": _vm.customStepperConfig }, on: { "change": function change($event) { _vm.$emit('stepper-change', $event); } } })], { skuEventBus: _vm.skuEventBus, selectedSku: _vm.selectedSku, selectedSkuComb: _vm.selectedSkuComb, selectedNum: _vm.selectedNum }), _vm._t("sku-messages", [_c('sku-messages', { ref: "skuMessages", attrs: { "goods-id": _vm.goodsId, "message-config": _vm.messageConfig, "messages": _vm.sku.messages } })])], 2), _vm._t("sku-actions", [_c('sku-actions', { attrs: { "sku-event-bus": _vm.skuEventBus, "buy-text": _vm.buyText, "show-add-cart-btn": _vm.showAddCartBtn } })], { skuEventBus: _vm.skuEventBus })], 2) : _vm._e(); }, name: 'sku', components: { Popup: Popup, SkuHeader: SkuHeader, SkuRow: SkuRow, SkuRowItem: SkuRowItem, SkuStepper: SkuStepper, SkuMessages: SkuMessages, SkuActions: SkuActions }, props: { sku: Object, goods: Object, quota: Number, value: Boolean, buyText: String, quotaUsed: Number, goodsId: [Number, String], hideStock: Boolean, hideQuotaText: Boolean, stepperTitle: String, getContainer: Function, resetStepperOnHide: Boolean, resetSelectedSkuOnHide: Boolean, disableStepperInput: Boolean, closeOnClickOverlay: Boolean, initialSku: { type: Object, default: function _default() { return {}; } }, showSoldoutSku: { type: Boolean, default: true }, showAddCartBtn: { type: Boolean, default: true }, bodyOffsetTop: { type: Number, default: 200 }, messageConfig: { type: Object, default: function _default() { return { placeholderMap: {}, uploadImg: function uploadImg() { return Promise.resolve(); }, uploadMaxSize: 5 }; } }, customStepperConfig: { type: Object, default: function _default() { return {}; } }, customSkuValidator: Function }, data: function data() { return { selectedSku: {}, selectedNum: 1, show: this.value }; }, watch: { show: function show(val) { this.$emit('input', val); if (!val) { var selectedSkuValues = getSelectedSkuValues(this.sku.tree, this.selectedSku); this.$emit('sku-close', { selectedSkuValues: selectedSkuValues, selectedNum: this.selectedNum, selectedSkuComb: this.selectedSkuComb }); if (this.resetStepperOnHide) { this.$refs.skuStepper && this.$refs.skuStepper.setCurrentNum(1); } if (this.resetSelectedSkuOnHide) { this.resetSelectedSku(this.skuTree); } } }, value: function value(val) { this.show = val; }, skuTree: function skuTree(val) { this.resetSelectedSku(val); } }, computed: { skuGroupClass: function skuGroupClass() { return ['van-sku-group-container', 'van-hairline--bottom', { 'van-sku-group-container--hide-soldout': !this.showSoldoutSku }]; }, bodyStyle: function bodyStyle() { if (this.$isServer) { return; } // header高度82px, sku actions高度50px,如果改动了样式自己传下bodyOffsetTop调整下 var maxHeight = window.innerHeight - this.bodyOffsetTop; return { maxHeight: maxHeight + 'px' }; }, isSkuCombSelected: function isSkuCombSelected() { return isAllSelected(this.sku.tree, this.selectedSku); }, isSkuEmpty: function isSkuEmpty() { return Object.keys(this.sku).length === 0; }, hasSku: function hasSku() { return !this.sku.none_sku; }, selectedSkuComb: function selectedSkuComb() { if (!this.hasSku) { return { id: this.sku.collection_id, price: Math.round(this.sku.price * 100), stock_num: this.sku.stock_num }; } if (this.isSkuCombSelected) { return getSkuComb(this.sku.list, this.selectedSku); } return null; }, price: function price() { if (this.selectedSkuComb) { return (this.selectedSkuComb.price / 100).toFixed(2); } // sku.price是一个格式化好的价格区间 return this.sku.price; }, skuTree: function skuTree() { return this.sku.tree || []; }, imageList: function imageList() { var imageList = [this.goods.picture]; if (this.skuTree.length > 0) { var treeItem = this.skuTree.filter(function (item) { return item.k_s === 's1'; })[0] || {}; if (!treeItem.v) { return; } treeItem.v.forEach(function (vItem) { var img = vItem.imgUrl || vItem.img_url; if (img) { imageList.push(img); } }); } return imageList; } }, created: function created() { var skuEventBus = new Vue(); this.skuEventBus = skuEventBus; skuEventBus.$on('sku:close', this.onClose); skuEventBus.$on('sku:select', this.onSelect); skuEventBus.$on('sku:numChange', this.onNumChange); skuEventBus.$on('sku:previewImage', this.onPreviewImage); skuEventBus.$on('sku:overLimit', this.onOverLimit); skuEventBus.$on('sku:addCart', this.onAddCart); skuEventBus.$on('sku:buy', this.onBuy); this.resetSelectedSku(this.skuTree); // 组件初始化后的钩子,抛出skuEventBus this.$emit('after-sku-create', skuEventBus); }, methods: { resetSelectedSku: function resetSelectedSku(skuTree) { var _this = this; this.selectedSku = {}; // 重置selectedSku skuTree.forEach(function (item) { _this.selectedSku[item.k_s] = _this.initialSku[item.k_s] || UNSELECTED_SKU_VALUE_ID; }); // 只有一个sku规格值时默认选中 skuTree.forEach(function (item) { var key = item.k_s; var valueId = item.v[0].id; if (item.v.length === 1 && isSkuChoosable(_this.sku.list, _this.selectedSku, { key: key, valueId: valueId })) { _this.selectedSku[key] = valueId; } }); }, 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 '商品已经无法购买啦'; } if (this.isSkuCombSelected) { return this.validateSkuMessages(); } // 自定义sku校验 if (this.customSkuValidator) { var err = this.customSkuValidator(this); if (err) return err; } return '请先选择商品规格'; }, onClose: function onClose() { this.show = false; }, 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 }); }, onNumChange: function onNumChange(num) { this.selectedNum = num; }, onPreviewImage: function onPreviewImage(indexImage) { var _this2 = this; var index = this.imageList.findIndex(function (image) { return image === indexImage; }); var cbParams = { index: index, imageList: this.imageList, indexImage: indexImage }; this.$emit('preview-on', cbParams); ImagePreview({ images: this.imageList, startPosition: index, onClose: function onClose() { _this2.$emit('preview-close', cbParams); } }); }, 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') { Toast('至少选择一件'); } else if (action === 'plus') { if (limitType === QUOTA_LIMIT) { var msg = "\u9650\u8D2D" + quota + "\u4EF6"; if (quotaUsed > 0) msg += "\uFF0C" + ("\u4F60\u5DF2\u8D2D\u4E70" + quotaUsed + "\u4EF6"); Toast(msg); } else { Toast('库存不足'); } } }, onAddCart: function onAddCart() { this.onBuyOrAddCart('add-cart'); }, onBuy: function onBuy() { this.onBuyOrAddCart('buy-clicked'); }, onBuyOrAddCart: function onBuyOrAddCart(type) { var error = this.validateSku(); if (error) { Toast(error); } else { this.$emit(type, this.getSkuData()); } }, getSkuData: function getSkuData() { return { goodsId: this.goodsId, selectedNum: this.selectedNum, selectedSkuComb: this.selectedSkuComb, messages: this.getSkuMessages(), cartMessages: this.getSkuCartMessages() }; } } });