first
This commit is contained in:
777
node_modules/vant/es/sku/Sku.js
generated
vendored
Normal file
777
node_modules/vant/es/sku/Sku.js
generated
vendored
Normal file
@ -0,0 +1,777 @@
|
||||
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, isEmpty } 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.filter(function (i) {
|
||||
return i.is_necessary !== false;
|
||||
}).some(function (i) {
|
||||
return (_this.selectedProp[i.k_id] || []).length === 0;
|
||||
});
|
||||
},
|
||||
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 (selectedProp[item.k_id]) {
|
||||
_this3.selectedProp[item.k_id] = selectedProp[item.k_id];
|
||||
}
|
||||
});
|
||||
|
||||
if (isEmpty(this.selectedProp)) {
|
||||
this.propList.forEach(function (item) {
|
||||
var _item$v;
|
||||
|
||||
// 没有加价的属性,默认选中第一个
|
||||
if ((item == null ? void 0 : (_item$v = item.v) == null ? void 0 : _item$v.length) > 0) {
|
||||
var v = item.v,
|
||||
k_id = item.k_id;
|
||||
var isHasConfigPrice = v.some(function (i) {
|
||||
return +i.price !== 0;
|
||||
}); // 没有加价属性
|
||||
|
||||
if (!isHasConfigPrice) {
|
||||
// 找到第一个不被禁用的属性
|
||||
// 历史如果没有 text_status 字段的,就相当于沿用直接原来的逻辑取第一个属性
|
||||
var firstEnableProp = v.find(function (prop) {
|
||||
return prop.text_status !== 0;
|
||||
});
|
||||
|
||||
if (firstEnableProp) {
|
||||
_this3.selectedProp[k_id] = [firstEnableProp.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,
|
||||
"disabled": skuValue.text_status === 0
|
||||
}
|
||||
});
|
||||
})]);
|
||||
})]);
|
||||
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]);
|
||||
}
|
||||
});
|
49
node_modules/vant/es/sku/components/SkuActions.js
generated
vendored
Normal file
49
node_modules/vant/es/sku/components/SkuActions.js
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
import _mergeJSXProps from "@vue/babel-helper-vue-jsx-merge-props";
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { inherit } from '../../utils/functional'; // Components
|
||||
|
||||
import Button from '../../button'; // Types
|
||||
|
||||
var _createNamespace = createNamespace('sku-actions'),
|
||||
createComponent = _createNamespace[0],
|
||||
bem = _createNamespace[1],
|
||||
t = _createNamespace[2];
|
||||
|
||||
function SkuActions(h, props, slots, ctx) {
|
||||
var createEmitter = function createEmitter(name) {
|
||||
return function () {
|
||||
props.skuEventBus.$emit(name);
|
||||
};
|
||||
};
|
||||
|
||||
return h("div", _mergeJSXProps([{
|
||||
"class": bem()
|
||||
}, inherit(ctx)]), [props.showAddCartBtn && h(Button, {
|
||||
"attrs": {
|
||||
"size": "large",
|
||||
"type": "warning",
|
||||
"text": props.addCartText || t('addCart')
|
||||
},
|
||||
"on": {
|
||||
"click": createEmitter('sku:addCart')
|
||||
}
|
||||
}), h(Button, {
|
||||
"attrs": {
|
||||
"size": "large",
|
||||
"type": "danger",
|
||||
"text": props.buyText || t('buy')
|
||||
},
|
||||
"on": {
|
||||
"click": createEmitter('sku:buy')
|
||||
}
|
||||
})]);
|
||||
}
|
||||
|
||||
SkuActions.props = {
|
||||
buyText: String,
|
||||
addCartText: String,
|
||||
skuEventBus: Object,
|
||||
showAddCartBtn: Boolean
|
||||
};
|
||||
export default createComponent(SkuActions);
|
114
node_modules/vant/es/sku/components/SkuDateTimeField.js
generated
vendored
Normal file
114
node_modules/vant/es/sku/components/SkuDateTimeField.js
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { stringToDate, dateToString } from '../utils/time-helper'; // Components
|
||||
|
||||
import Popup from '../../popup';
|
||||
import DateTimePicker from '../../datetime-picker';
|
||||
import Field from '../../field';
|
||||
var namespace = createNamespace('sku-datetime-field');
|
||||
var createComponent = namespace[0];
|
||||
var t = namespace[2];
|
||||
export default createComponent({
|
||||
props: {
|
||||
value: String,
|
||||
label: String,
|
||||
required: Boolean,
|
||||
placeholder: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'date'
|
||||
}
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
showDatePicker: false,
|
||||
currentDate: this.type === 'time' ? '' : new Date(),
|
||||
minDate: new Date(new Date().getFullYear() - 60, 0, 1)
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: function value(val) {
|
||||
switch (this.type) {
|
||||
case 'time':
|
||||
this.currentDate = val;
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
this.currentDate = stringToDate(val) || new Date();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title: function title() {
|
||||
return t("title." + this.type);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick: function onClick() {
|
||||
this.showDatePicker = true;
|
||||
},
|
||||
onConfirm: function onConfirm(val) {
|
||||
var data = val;
|
||||
|
||||
if (this.type !== 'time') {
|
||||
data = dateToString(val, this.type);
|
||||
}
|
||||
|
||||
this.$emit('input', data);
|
||||
this.showDatePicker = false;
|
||||
},
|
||||
onCancel: function onCancel() {
|
||||
this.showDatePicker = false;
|
||||
},
|
||||
formatter: function formatter(type, val) {
|
||||
var word = t("format." + type);
|
||||
return "" + val + word;
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var _this = this;
|
||||
|
||||
var h = arguments[0];
|
||||
return h(Field, {
|
||||
"attrs": {
|
||||
"readonly": true,
|
||||
"is-link": true,
|
||||
"center": true,
|
||||
"value": this.value,
|
||||
"label": this.label,
|
||||
"required": this.required,
|
||||
"placeholder": this.placeholder
|
||||
},
|
||||
"on": {
|
||||
"click": this.onClick
|
||||
}
|
||||
}, [h(Popup, {
|
||||
"attrs": {
|
||||
"round": true,
|
||||
"position": "bottom",
|
||||
"getContainer": "body"
|
||||
},
|
||||
"slot": "extra",
|
||||
"model": {
|
||||
value: _this.showDatePicker,
|
||||
callback: function callback($$v) {
|
||||
_this.showDatePicker = $$v;
|
||||
}
|
||||
}
|
||||
}, [h(DateTimePicker, {
|
||||
"attrs": {
|
||||
"type": this.type,
|
||||
"title": this.title,
|
||||
"value": this.currentDate,
|
||||
"minDate": this.minDate,
|
||||
"formatter": this.formatter
|
||||
},
|
||||
"on": {
|
||||
"cancel": this.onCancel,
|
||||
"confirm": this.onConfirm
|
||||
}
|
||||
})])]);
|
||||
}
|
||||
});
|
78
node_modules/vant/es/sku/components/SkuHeader.js
generated
vendored
Normal file
78
node_modules/vant/es/sku/components/SkuHeader.js
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
import _mergeJSXProps from "@vue/babel-helper-vue-jsx-merge-props";
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { inherit } from '../../utils/functional';
|
||||
import { BORDER_BOTTOM } from '../../utils/constant'; // Components
|
||||
|
||||
import Image from '../../image'; // Types
|
||||
|
||||
var _createNamespace = createNamespace('sku-header'),
|
||||
createComponent = _createNamespace[0],
|
||||
bem = _createNamespace[1];
|
||||
|
||||
function getSkuImgValue(sku, selectedSku) {
|
||||
var imgValue;
|
||||
sku.tree.some(function (item) {
|
||||
var id = selectedSku[item.k_s];
|
||||
|
||||
if (id && item.v) {
|
||||
var matchedSku = item.v.filter(function (skuValue) {
|
||||
return skuValue.id === id;
|
||||
})[0] || {};
|
||||
var img = matchedSku.previewImgUrl || matchedSku.imgUrl || matchedSku.img_url;
|
||||
|
||||
if (img) {
|
||||
imgValue = _extends({}, matchedSku, {
|
||||
ks: item.k_s,
|
||||
imgUrl: img
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
return imgValue;
|
||||
}
|
||||
|
||||
function SkuHeader(h, props, slots, ctx) {
|
||||
var _slots$skuHeaderIma;
|
||||
|
||||
var sku = props.sku,
|
||||
goods = props.goods,
|
||||
skuEventBus = props.skuEventBus,
|
||||
selectedSku = props.selectedSku,
|
||||
_props$showHeaderImag = props.showHeaderImage,
|
||||
showHeaderImage = _props$showHeaderImag === void 0 ? true : _props$showHeaderImag;
|
||||
var selectedValue = getSkuImgValue(sku, selectedSku);
|
||||
var imgUrl = selectedValue ? selectedValue.imgUrl : goods.picture;
|
||||
|
||||
var previewImage = function previewImage() {
|
||||
skuEventBus.$emit('sku:previewImage', selectedValue);
|
||||
};
|
||||
|
||||
return h("div", _mergeJSXProps([{
|
||||
"class": [bem(), BORDER_BOTTOM]
|
||||
}, inherit(ctx)]), [showHeaderImage && h(Image, {
|
||||
"attrs": {
|
||||
"fit": "cover",
|
||||
"src": imgUrl
|
||||
},
|
||||
"class": bem('img-wrap'),
|
||||
"on": {
|
||||
"click": previewImage
|
||||
}
|
||||
}, [(_slots$skuHeaderIma = slots['sku-header-image-extra']) == null ? void 0 : _slots$skuHeaderIma.call(slots)]), h("div", {
|
||||
"class": bem('goods-info')
|
||||
}, [slots.default == null ? void 0 : slots.default()])]);
|
||||
}
|
||||
|
||||
SkuHeader.props = {
|
||||
sku: Object,
|
||||
goods: Object,
|
||||
skuEventBus: Object,
|
||||
selectedSku: Object,
|
||||
showHeaderImage: Boolean
|
||||
};
|
||||
export default createComponent(SkuHeader);
|
16
node_modules/vant/es/sku/components/SkuHeaderItem.js
generated
vendored
Normal file
16
node_modules/vant/es/sku/components/SkuHeaderItem.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import _mergeJSXProps from "@vue/babel-helper-vue-jsx-merge-props";
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { inherit } from '../../utils/functional'; // Types
|
||||
|
||||
var _createNamespace = createNamespace('sku-header-item'),
|
||||
createComponent = _createNamespace[0],
|
||||
bem = _createNamespace[1];
|
||||
|
||||
function SkuHeader(h, props, slots, ctx) {
|
||||
return h("div", _mergeJSXProps([{
|
||||
"class": bem()
|
||||
}, inherit(ctx)]), [slots.default && slots.default()]);
|
||||
}
|
||||
|
||||
export default createComponent(SkuHeader);
|
94
node_modules/vant/es/sku/components/SkuImgUploader.js
generated
vendored
Normal file
94
node_modules/vant/es/sku/components/SkuImgUploader.js
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils'; // Components
|
||||
|
||||
import Uploader from '../../uploader';
|
||||
var namespace = createNamespace('sku-img-uploader');
|
||||
var createComponent = namespace[0];
|
||||
var t = namespace[2];
|
||||
export default createComponent({
|
||||
props: {
|
||||
value: String,
|
||||
uploadImg: Function,
|
||||
customUpload: Function,
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 6
|
||||
}
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
fileList: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value: function value(val) {
|
||||
if (val) {
|
||||
this.fileList = [{
|
||||
url: val,
|
||||
isImage: true
|
||||
}];
|
||||
} else {
|
||||
this.fileList = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
afterReadFile: function afterReadFile(file) {
|
||||
var _this = this;
|
||||
|
||||
file.status = 'uploading';
|
||||
file.message = t('uploading');
|
||||
this.uploadImg(file.file, file.content).then(function (img) {
|
||||
file.status = 'done';
|
||||
|
||||
_this.$emit('input', img);
|
||||
}).catch(function () {
|
||||
file.status = 'failed';
|
||||
file.message = t('fail');
|
||||
});
|
||||
},
|
||||
onOversize: function onOversize() {
|
||||
this.$toast(t('oversize', this.maxSize));
|
||||
},
|
||||
onDelete: function onDelete() {
|
||||
this.$emit('input', '');
|
||||
},
|
||||
onClickUpload: function onClickUpload() {
|
||||
var _this2 = this;
|
||||
|
||||
if (this.customUpload) {
|
||||
this.customUpload().then(function (url) {
|
||||
_this2.fileList.push({
|
||||
url: url
|
||||
});
|
||||
|
||||
_this2.$emit('input', url);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var _this3 = this;
|
||||
|
||||
var h = arguments[0];
|
||||
return h(Uploader, {
|
||||
"attrs": {
|
||||
"maxCount": 1,
|
||||
"readonly": !!this.customUpload,
|
||||
"maxSize": this.maxSize * 1024 * 1024,
|
||||
"afterRead": this.afterReadFile
|
||||
},
|
||||
"on": {
|
||||
"oversize": this.onOversize,
|
||||
"delete": this.onDelete,
|
||||
"click-upload": this.onClickUpload
|
||||
},
|
||||
"model": {
|
||||
value: _this3.fileList,
|
||||
callback: function callback($$v) {
|
||||
_this3.fileList = $$v;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
220
node_modules/vant/es/sku/components/SkuMessages.js
generated
vendored
Normal file
220
node_modules/vant/es/sku/components/SkuMessages.js
generated
vendored
Normal file
@ -0,0 +1,220 @@
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { isEmail } from '../../utils/validate/email';
|
||||
import { isNumeric } from '../../utils/validate/number'; // Components
|
||||
|
||||
import Cell from '../../cell';
|
||||
import Field from '../../field';
|
||||
import SkuImgUploader from './SkuImgUploader';
|
||||
import SkuDateTimeField from './SkuDateTimeField';
|
||||
|
||||
var _createNamespace = createNamespace('sku-messages'),
|
||||
createComponent = _createNamespace[0],
|
||||
bem = _createNamespace[1],
|
||||
t = _createNamespace[2];
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
messageConfig: Object,
|
||||
goodsId: [Number, String],
|
||||
messages: {
|
||||
type: Array,
|
||||
default: function _default() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
messageValues: this.resetMessageValues(this.messages)
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
messages: function messages(val) {
|
||||
this.messageValues = this.resetMessageValues(val);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetMessageValues: function resetMessageValues(messages) {
|
||||
var messageConfig = this.messageConfig;
|
||||
var _messageConfig$initia = messageConfig.initialMessages,
|
||||
initialMessages = _messageConfig$initia === void 0 ? {} : _messageConfig$initia;
|
||||
return (messages || []).map(function (message) {
|
||||
return {
|
||||
value: initialMessages[message.name] || ''
|
||||
};
|
||||
});
|
||||
},
|
||||
getType: function getType(message) {
|
||||
if (+message.multiple === 1) {
|
||||
return 'textarea';
|
||||
}
|
||||
|
||||
if (message.type === 'id_no') {
|
||||
return 'text';
|
||||
}
|
||||
|
||||
return message.datetime > 0 ? 'datetime' : message.type;
|
||||
},
|
||||
getMessages: function getMessages() {
|
||||
var messages = {};
|
||||
this.messageValues.forEach(function (item, index) {
|
||||
messages["message_" + index] = item.value;
|
||||
});
|
||||
return messages;
|
||||
},
|
||||
getCartMessages: function getCartMessages() {
|
||||
var _this = this;
|
||||
|
||||
var messages = {};
|
||||
this.messageValues.forEach(function (item, index) {
|
||||
var message = _this.messages[index];
|
||||
messages[message.name] = item.value;
|
||||
});
|
||||
return messages;
|
||||
},
|
||||
getPlaceholder: function getPlaceholder(message) {
|
||||
var type = +message.multiple === 1 ? 'textarea' : message.type;
|
||||
var map = this.messageConfig.placeholderMap || {};
|
||||
return message.placeholder || map[type] || t("placeholder." + type);
|
||||
},
|
||||
validateMessages: function validateMessages() {
|
||||
var values = this.messageValues;
|
||||
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = values[i].value;
|
||||
var message = this.messages[i];
|
||||
|
||||
if (value === '') {
|
||||
// 必填字段的校验
|
||||
if (String(message.required) === '1') {
|
||||
var textType = t(message.type === 'image' ? 'upload' : 'fill');
|
||||
return textType + message.name;
|
||||
}
|
||||
} else {
|
||||
if (message.type === 'tel' && !isNumeric(value)) {
|
||||
return t('invalid.tel');
|
||||
}
|
||||
|
||||
if (message.type === 'mobile' && !/^\d{6,20}$/.test(value)) {
|
||||
return t('invalid.mobile');
|
||||
}
|
||||
|
||||
if (message.type === 'email' && !isEmail(value)) {
|
||||
return t('invalid.email');
|
||||
}
|
||||
|
||||
if (message.type === 'id_no' && (value.length < 15 || value.length > 18)) {
|
||||
return t('invalid.id_no');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The phone number copied from IOS mobile phone address book
|
||||
* will add spaces and invisible Unicode characters
|
||||
* which cannot pass the /^\d+$/ verification
|
||||
* so keep numbers and dots
|
||||
*/
|
||||
getFormatter: function getFormatter(message) {
|
||||
return function formatter(value) {
|
||||
if (message.type === 'mobile' || message.type === 'tel') {
|
||||
return value.replace(/[^\d.]/g, '');
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
},
|
||||
getExtraDesc: function getExtraDesc(message) {
|
||||
var h = this.$createElement;
|
||||
var extraDesc = message.extraDesc;
|
||||
|
||||
if (extraDesc) {
|
||||
return h("div", {
|
||||
"class": bem('extra-message')
|
||||
}, [extraDesc]);
|
||||
}
|
||||
},
|
||||
genMessage: function genMessage(message, index) {
|
||||
var _this2 = this;
|
||||
|
||||
var h = this.$createElement;
|
||||
|
||||
if (message.type === 'image') {
|
||||
return h(Cell, {
|
||||
"key": this.goodsId + "-" + index,
|
||||
"attrs": {
|
||||
"title": message.name,
|
||||
"required": String(message.required) === '1',
|
||||
"valueClass": bem('image-cell-value')
|
||||
},
|
||||
"class": bem('image-cell')
|
||||
}, [h(SkuImgUploader, {
|
||||
"attrs": {
|
||||
"maxSize": this.messageConfig.uploadMaxSize,
|
||||
"uploadImg": this.messageConfig.uploadImg,
|
||||
"customUpload": this.messageConfig.customUpload
|
||||
},
|
||||
"model": {
|
||||
value: _this2.messageValues[index].value,
|
||||
callback: function callback($$v) {
|
||||
_this2.$set(_this2.messageValues[index], "value", $$v);
|
||||
}
|
||||
}
|
||||
}), h("div", {
|
||||
"class": bem('image-cell-label')
|
||||
}, [t('imageLabel')])]);
|
||||
} // 时间和日期使用的vant选择器
|
||||
|
||||
|
||||
var isDateOrTime = ['date', 'time'].indexOf(message.type) > -1;
|
||||
|
||||
if (isDateOrTime) {
|
||||
return h(SkuDateTimeField, {
|
||||
"attrs": {
|
||||
"label": message.name,
|
||||
"required": String(message.required) === '1',
|
||||
"placeholder": this.getPlaceholder(message),
|
||||
"type": this.getType(message)
|
||||
},
|
||||
"key": this.goodsId + "-" + index,
|
||||
"model": {
|
||||
value: _this2.messageValues[index].value,
|
||||
callback: function callback($$v) {
|
||||
_this2.$set(_this2.messageValues[index], "value", $$v);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return h("div", {
|
||||
"class": bem('cell-block')
|
||||
}, [h(Field, {
|
||||
"attrs": {
|
||||
"maxlength": "200",
|
||||
"center": !message.multiple,
|
||||
"label": message.name,
|
||||
"required": String(message.required) === '1',
|
||||
"placeholder": this.getPlaceholder(message),
|
||||
"type": this.getType(message),
|
||||
"formatter": this.getFormatter(message),
|
||||
"border": false
|
||||
},
|
||||
"key": this.goodsId + "-" + index,
|
||||
"model": {
|
||||
value: _this2.messageValues[index].value,
|
||||
callback: function callback($$v) {
|
||||
_this2.$set(_this2.messageValues[index], "value", $$v);
|
||||
}
|
||||
}
|
||||
}), this.getExtraDesc(message)]);
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var h = arguments[0];
|
||||
return h("div", {
|
||||
"class": bem()
|
||||
}, [this.messages.map(this.genMessage)]);
|
||||
}
|
||||
});
|
117
node_modules/vant/es/sku/components/SkuRow.js
generated
vendored
Normal file
117
node_modules/vant/es/sku/components/SkuRow.js
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
// Utils
|
||||
import { createNamespace } from '../../utils';
|
||||
import { BORDER_BOTTOM } from '../../utils/constant'; // Mixins
|
||||
|
||||
import { ParentMixin } from '../../mixins/relation';
|
||||
import { BindEventMixin } from '../../mixins/bind-event';
|
||||
|
||||
var _createNamespace = createNamespace('sku-row'),
|
||||
createComponent = _createNamespace[0],
|
||||
bem = _createNamespace[1],
|
||||
t = _createNamespace[2];
|
||||
|
||||
export { bem };
|
||||
export default createComponent({
|
||||
mixins: [ParentMixin('vanSkuRows'), BindEventMixin(function (bind) {
|
||||
if (this.scrollable && this.$refs.scroller) {
|
||||
bind(this.$refs.scroller, 'scroll', this.onScroll);
|
||||
}
|
||||
})],
|
||||
props: {
|
||||
skuRow: Object
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
progress: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
scrollable: function scrollable() {
|
||||
return this.skuRow.largeImageMode && this.skuRow.v.length > 6;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onScroll: function onScroll() {
|
||||
var _this$$refs = this.$refs,
|
||||
scroller = _this$$refs.scroller,
|
||||
row = _this$$refs.row;
|
||||
var distance = row.offsetWidth - scroller.offsetWidth;
|
||||
this.progress = scroller.scrollLeft / distance;
|
||||
},
|
||||
genTitle: function genTitle() {
|
||||
var h = this.$createElement;
|
||||
return h("div", {
|
||||
"class": bem('title')
|
||||
}, [this.skuRow.k, this.skuRow.is_multiple && h("span", {
|
||||
"class": bem('title-multiple')
|
||||
}, ["\uFF08", t('multiple'), "\uFF09"])]);
|
||||
},
|
||||
genIndicator: function genIndicator() {
|
||||
var h = this.$createElement;
|
||||
|
||||
if (this.scrollable) {
|
||||
var style = {
|
||||
transform: "translate3d(" + this.progress * 20 + "px, 0, 0)"
|
||||
};
|
||||
return h("div", {
|
||||
"class": bem('indicator-wrapper')
|
||||
}, [h("div", {
|
||||
"class": bem('indicator')
|
||||
}, [h("div", {
|
||||
"class": bem('indicator-slider'),
|
||||
"style": style
|
||||
})])]);
|
||||
}
|
||||
},
|
||||
genContent: function genContent() {
|
||||
var h = this.$createElement;
|
||||
var nodes = this.slots();
|
||||
|
||||
if (this.skuRow.largeImageMode) {
|
||||
var top = [];
|
||||
var bottom = [];
|
||||
nodes.forEach(function (node, index) {
|
||||
var group = Math.floor(index / 3) % 2 === 0 ? top : bottom;
|
||||
group.push(node);
|
||||
});
|
||||
return h("div", {
|
||||
"class": bem('scroller'),
|
||||
"ref": "scroller"
|
||||
}, [h("div", {
|
||||
"class": bem('row'),
|
||||
"ref": "row"
|
||||
}, [top]), bottom.length ? h("div", {
|
||||
"class": bem('row')
|
||||
}, [bottom]) : null]);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
},
|
||||
centerItem: function centerItem(selectSkuId) {
|
||||
if (!this.skuRow.largeImageMode || !selectSkuId) {
|
||||
return;
|
||||
}
|
||||
|
||||
var _this$children = this.children,
|
||||
children = _this$children === void 0 ? [] : _this$children;
|
||||
var _this$$refs2 = this.$refs,
|
||||
scroller = _this$$refs2.scroller,
|
||||
row = _this$$refs2.row;
|
||||
var child = children.find(function (it) {
|
||||
return +it.skuValue.id === +selectSkuId;
|
||||
});
|
||||
|
||||
if (scroller && row && child && child.$el) {
|
||||
var target = child.$el;
|
||||
var to = target.offsetLeft - (scroller.offsetWidth - target.offsetWidth) / 2;
|
||||
scroller.scrollLeft = to;
|
||||
}
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var h = arguments[0];
|
||||
return h("div", {
|
||||
"class": [bem(), BORDER_BOTTOM]
|
||||
}, [this.genTitle(), this.genContent(), this.genIndicator()]);
|
||||
}
|
||||
});
|
102
node_modules/vant/es/sku/components/SkuRowItem.js
generated
vendored
Normal file
102
node_modules/vant/es/sku/components/SkuRowItem.js
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
import { bem } from './SkuRow';
|
||||
import { createNamespace } from '../../utils';
|
||||
import { isSkuChoosable } from '../utils/sku-helper';
|
||||
import { ChildrenMixin } from '../../mixins/relation';
|
||||
import Icon from '../../icon';
|
||||
import Image from '../../image';
|
||||
|
||||
var _createNamespace = createNamespace('sku-row-item'),
|
||||
createComponent = _createNamespace[0];
|
||||
|
||||
export default createComponent({
|
||||
mixins: [ChildrenMixin('vanSkuRows')],
|
||||
props: {
|
||||
lazyLoad: Boolean,
|
||||
skuValue: Object,
|
||||
skuKeyStr: String,
|
||||
skuEventBus: Object,
|
||||
selectedSku: Object,
|
||||
largeImageMode: Boolean,
|
||||
disableSoldoutSku: Boolean,
|
||||
skuList: {
|
||||
type: Array,
|
||||
default: function _default() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imgUrl: function imgUrl() {
|
||||
var url = this.skuValue.imgUrl || this.skuValue.img_url;
|
||||
return this.largeImageMode ? url || 'https://img01.yzcdn.cn/upload_files/2020/06/24/FmKWDg0bN9rMcTp9ne8MXiQWGtLn.png' : url;
|
||||
},
|
||||
choosable: function choosable() {
|
||||
if (!this.disableSoldoutSku) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isSkuChoosable(this.skuList, this.selectedSku, {
|
||||
key: this.skuKeyStr,
|
||||
valueId: this.skuValue.id
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelect: function onSelect() {
|
||||
if (this.choosable) {
|
||||
this.skuEventBus.$emit('sku:select', _extends({}, this.skuValue, {
|
||||
skuKeyStr: this.skuKeyStr
|
||||
}));
|
||||
}
|
||||
},
|
||||
onPreviewImg: function onPreviewImg(event) {
|
||||
event.stopPropagation();
|
||||
var skuValue = this.skuValue,
|
||||
skuKeyStr = this.skuKeyStr;
|
||||
this.skuEventBus.$emit('sku:previewImage', _extends({}, skuValue, {
|
||||
ks: skuKeyStr,
|
||||
imgUrl: skuValue.imgUrl || skuValue.img_url
|
||||
}));
|
||||
},
|
||||
genImage: function genImage(classPrefix) {
|
||||
var h = this.$createElement;
|
||||
|
||||
if (this.imgUrl) {
|
||||
return h(Image, {
|
||||
"attrs": {
|
||||
"fit": "cover",
|
||||
"src": this.imgUrl,
|
||||
"lazyLoad": this.lazyLoad
|
||||
},
|
||||
"class": classPrefix + "-img"
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var h = arguments[0];
|
||||
var choosed = this.skuValue.id === this.selectedSku[this.skuKeyStr];
|
||||
var classPrefix = this.largeImageMode ? bem('image-item') : bem('item');
|
||||
return h("span", {
|
||||
"class": [classPrefix, choosed ? classPrefix + "--active" : '', !this.choosable ? classPrefix + "--disabled" : ''],
|
||||
"on": {
|
||||
"click": this.onSelect
|
||||
}
|
||||
}, [this.genImage(classPrefix), h("div", {
|
||||
"class": classPrefix + "-name"
|
||||
}, [this.largeImageMode ? h("span", {
|
||||
"class": {
|
||||
'van-multi-ellipsis--l2': this.largeImageMode
|
||||
}
|
||||
}, [this.skuValue.name]) : this.skuValue.name]), this.largeImageMode && h(Icon, {
|
||||
"attrs": {
|
||||
"name": "enlarge"
|
||||
},
|
||||
"class": classPrefix + "-img-icon",
|
||||
"on": {
|
||||
"click": this.onPreviewImg
|
||||
}
|
||||
})]);
|
||||
}
|
||||
});
|
53
node_modules/vant/es/sku/components/SkuRowPropItem.js
generated
vendored
Normal file
53
node_modules/vant/es/sku/components/SkuRowPropItem.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
import { createNamespace } from '../../utils';
|
||||
|
||||
var _createNamespace = createNamespace('sku-row-prop-item'),
|
||||
createComponent = _createNamespace[0];
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
skuValue: Object,
|
||||
skuKeyStr: String,
|
||||
skuEventBus: Object,
|
||||
selectedProp: Object,
|
||||
multiple: Boolean,
|
||||
disabled: Boolean
|
||||
},
|
||||
computed: {
|
||||
choosed: function choosed() {
|
||||
var selectedProp = this.selectedProp,
|
||||
skuKeyStr = this.skuKeyStr,
|
||||
skuValue = this.skuValue;
|
||||
|
||||
if (selectedProp && selectedProp[skuKeyStr]) {
|
||||
return selectedProp[skuKeyStr].indexOf(skuValue.id) > -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelect: function onSelect() {
|
||||
if (this.disabled) return;
|
||||
this.skuEventBus.$emit('sku:propSelect', _extends({}, this.skuValue, {
|
||||
skuKeyStr: this.skuKeyStr,
|
||||
multiple: this.multiple
|
||||
}));
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var h = arguments[0];
|
||||
return h("span", {
|
||||
"class": ['van-sku-row__item', {
|
||||
'van-sku-row__item--active': this.choosed
|
||||
}, {
|
||||
'van-sku-row__item--disabled': this.disabled
|
||||
}],
|
||||
"on": {
|
||||
"click": this.onSelect
|
||||
}
|
||||
}, [h("span", {
|
||||
"class": "van-sku-row__item-name"
|
||||
}, [this.skuValue.name])]);
|
||||
}
|
||||
});
|
180
node_modules/vant/es/sku/components/SkuStepper.js
generated
vendored
Normal file
180
node_modules/vant/es/sku/components/SkuStepper.js
generated
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
import { createNamespace } from '../../utils';
|
||||
import { LIMIT_TYPE } from '../constants';
|
||||
import Stepper from '../../stepper';
|
||||
var namespace = createNamespace('sku-stepper');
|
||||
var createComponent = namespace[0];
|
||||
var t = namespace[2];
|
||||
var QUOTA_LIMIT = LIMIT_TYPE.QUOTA_LIMIT,
|
||||
STOCK_LIMIT = LIMIT_TYPE.STOCK_LIMIT;
|
||||
export default createComponent({
|
||||
props: {
|
||||
stock: Number,
|
||||
skuEventBus: Object,
|
||||
skuStockNum: Number,
|
||||
selectedNum: Number,
|
||||
stepperTitle: String,
|
||||
disableStepperInput: Boolean,
|
||||
customStepperConfig: Object,
|
||||
hideQuotaText: Boolean,
|
||||
quota: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
quotaUsed: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
startSaleNum: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
currentNum: this.selectedNum,
|
||||
// 购买限制类型: 限购/库存
|
||||
limitType: STOCK_LIMIT
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
currentNum: function currentNum(num) {
|
||||
var intValue = parseInt(num, 10);
|
||||
|
||||
if (intValue >= this.stepperMinLimit && intValue <= this.stepperLimit) {
|
||||
this.skuEventBus.$emit('sku:numChange', intValue);
|
||||
}
|
||||
},
|
||||
stepperLimit: function stepperLimit(limit) {
|
||||
if (limit < this.currentNum && this.stepperMinLimit <= limit) {
|
||||
this.currentNum = limit;
|
||||
}
|
||||
|
||||
this.checkState(this.stepperMinLimit, limit);
|
||||
},
|
||||
stepperMinLimit: function stepperMinLimit(start) {
|
||||
if (start > this.currentNum || start > this.stepperLimit) {
|
||||
this.currentNum = start;
|
||||
}
|
||||
|
||||
this.checkState(start, this.stepperLimit);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
stepperLimit: function stepperLimit() {
|
||||
var quotaLimit = this.quota - this.quotaUsed;
|
||||
var limit; // 无限购时直接取库存,有限购时取限购数和库存数中小的那个
|
||||
|
||||
if (this.quota > 0 && quotaLimit <= this.stock) {
|
||||
// 修正负的limit
|
||||
limit = quotaLimit < 0 ? 0 : quotaLimit;
|
||||
this.limitType = QUOTA_LIMIT;
|
||||
} else {
|
||||
limit = this.stock;
|
||||
this.limitType = STOCK_LIMIT;
|
||||
}
|
||||
|
||||
return limit;
|
||||
},
|
||||
stepperMinLimit: function stepperMinLimit() {
|
||||
return this.startSaleNum < 1 ? 1 : this.startSaleNum;
|
||||
},
|
||||
quotaText: function quotaText() {
|
||||
var _this$customStepperCo = this.customStepperConfig,
|
||||
quotaText = _this$customStepperCo.quotaText,
|
||||
hideQuotaText = _this$customStepperCo.hideQuotaText;
|
||||
if (hideQuotaText) return '';
|
||||
var text = '';
|
||||
|
||||
if (quotaText) {
|
||||
text = quotaText;
|
||||
} else {
|
||||
var textArr = [];
|
||||
|
||||
if (this.startSaleNum > 1) {
|
||||
textArr.push(t('quotaStart', this.startSaleNum));
|
||||
}
|
||||
|
||||
if (this.quota > 0) {
|
||||
textArr.push(t('quotaLimit', this.quota));
|
||||
}
|
||||
|
||||
text = textArr.join(t('comma'));
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
},
|
||||
created: function created() {
|
||||
this.checkState(this.stepperMinLimit, this.stepperLimit);
|
||||
},
|
||||
methods: {
|
||||
setCurrentNum: function setCurrentNum(num) {
|
||||
this.currentNum = num;
|
||||
this.checkState(this.stepperMinLimit, this.stepperLimit);
|
||||
},
|
||||
onOverLimit: function onOverLimit(action) {
|
||||
this.skuEventBus.$emit('sku:overLimit', {
|
||||
action: action,
|
||||
limitType: this.limitType,
|
||||
quota: this.quota,
|
||||
quotaUsed: this.quotaUsed,
|
||||
startSaleNum: this.startSaleNum
|
||||
});
|
||||
},
|
||||
onChange: function onChange(currentValue) {
|
||||
var intValue = parseInt(currentValue, 10);
|
||||
var handleStepperChange = this.customStepperConfig.handleStepperChange;
|
||||
handleStepperChange && handleStepperChange(intValue);
|
||||
this.$emit('change', intValue);
|
||||
},
|
||||
checkState: function checkState(min, max) {
|
||||
// 如果选择小于起售,则强制变为起售
|
||||
if (this.currentNum < min || min > max) {
|
||||
this.currentNum = min;
|
||||
} else if (this.currentNum > max) {
|
||||
// 当前选择数量大于最大可选时,需要重置已选数量
|
||||
this.currentNum = max;
|
||||
}
|
||||
|
||||
this.skuEventBus.$emit('sku:stepperState', {
|
||||
valid: min <= max,
|
||||
min: min,
|
||||
max: max,
|
||||
limitType: this.limitType,
|
||||
quota: this.quota,
|
||||
quotaUsed: this.quotaUsed,
|
||||
startSaleNum: this.startSaleNum
|
||||
});
|
||||
}
|
||||
},
|
||||
render: function render() {
|
||||
var _this = this;
|
||||
|
||||
var h = arguments[0];
|
||||
return h("div", {
|
||||
"class": "van-sku-stepper-stock"
|
||||
}, [h("div", {
|
||||
"class": "van-sku__stepper-title"
|
||||
}, [this.stepperTitle || t('num')]), h(Stepper, {
|
||||
"attrs": {
|
||||
"integer": true,
|
||||
"min": this.stepperMinLimit,
|
||||
"max": this.stepperLimit,
|
||||
"disableInput": this.disableStepperInput
|
||||
},
|
||||
"class": "van-sku__stepper",
|
||||
"on": {
|
||||
"overlimit": this.onOverLimit,
|
||||
"change": this.onChange
|
||||
},
|
||||
"model": {
|
||||
value: _this.currentNum,
|
||||
callback: function callback($$v) {
|
||||
_this.currentNum = $$v;
|
||||
}
|
||||
}
|
||||
}), !this.hideQuotaText && this.quotaText && h("span", {
|
||||
"class": "van-sku__stepper-quota"
|
||||
}, ["(", this.quotaText, ")"])]);
|
||||
}
|
||||
});
|
9
node_modules/vant/es/sku/constants.js
generated
vendored
Normal file
9
node_modules/vant/es/sku/constants.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export var LIMIT_TYPE = {
|
||||
QUOTA_LIMIT: 0,
|
||||
STOCK_LIMIT: 1
|
||||
};
|
||||
export var UNSELECTED_SKU_VALUE_ID = '';
|
||||
export default {
|
||||
LIMIT_TYPE: LIMIT_TYPE,
|
||||
UNSELECTED_SKU_VALUE_ID: UNSELECTED_SKU_VALUE_ID
|
||||
};
|
1
node_modules/vant/es/sku/index.css
generated
vendored
Normal file
1
node_modules/vant/es/sku/index.css
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
27
node_modules/vant/es/sku/index.js
generated
vendored
Normal file
27
node_modules/vant/es/sku/index.js
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Utils
|
||||
import lang from './lang';
|
||||
import constants from './constants';
|
||||
import skuHelper from './utils/sku-helper'; // Components
|
||||
|
||||
import Sku from './Sku';
|
||||
import Locale from '../locale';
|
||||
import SkuActions from './components/SkuActions';
|
||||
import SkuHeader from './components/SkuHeader';
|
||||
import SkuHeaderItem from './components/SkuHeaderItem';
|
||||
import SkuMessages from './components/SkuMessages';
|
||||
import SkuStepper from './components/SkuStepper';
|
||||
import SkuRow from './components/SkuRow';
|
||||
import SkuRowItem from './components/SkuRowItem';
|
||||
import SkuRowPropItem from './components/SkuRowPropItem';
|
||||
Locale.add(lang);
|
||||
Sku.SkuActions = SkuActions;
|
||||
Sku.SkuHeader = SkuHeader;
|
||||
Sku.SkuHeaderItem = SkuHeaderItem;
|
||||
Sku.SkuMessages = SkuMessages;
|
||||
Sku.SkuStepper = SkuStepper;
|
||||
Sku.SkuRow = SkuRow;
|
||||
Sku.SkuRowItem = SkuRowItem;
|
||||
Sku.SkuRowPropItem = SkuRowPropItem;
|
||||
Sku.skuHelper = skuHelper;
|
||||
Sku.skuConstants = constants;
|
||||
export default Sku;
|
399
node_modules/vant/es/sku/index.less
generated
vendored
Normal file
399
node_modules/vant/es/sku/index.less
generated
vendored
Normal file
@ -0,0 +1,399 @@
|
||||
@import '../style/var';
|
||||
@import '../style/mixins/clearfix';
|
||||
@import '../style/mixins/hairline';
|
||||
|
||||
.van-sku {
|
||||
&-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
min-height: 50%;
|
||||
max-height: 80%;
|
||||
overflow-y: visible;
|
||||
font-size: @font-size-md;
|
||||
background: @white;
|
||||
}
|
||||
|
||||
&-body {
|
||||
flex: 1 1 auto;
|
||||
min-height: 44px;
|
||||
overflow-y: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
margin: 0 @padding-md;
|
||||
|
||||
&__img-wrap {
|
||||
flex-shrink: 0;
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
margin: @padding-sm @padding-sm @padding-sm 0;
|
||||
overflow: hidden;
|
||||
border-radius: @border-radius-md;
|
||||
}
|
||||
|
||||
&__goods-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding: @padding-sm 20px @padding-sm 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-header-item {
|
||||
margin-top: @padding-xs;
|
||||
color: @gray-6;
|
||||
font-size: @font-size-sm;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
&__price-symbol {
|
||||
font-size: @font-size-lg;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
&__price-num {
|
||||
font-weight: @font-weight-bold;
|
||||
font-size: 22px;
|
||||
vertical-align: bottom;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
&__goods-price {
|
||||
// for price align
|
||||
margin-left: -2px;
|
||||
color: @red;
|
||||
}
|
||||
|
||||
&__price-tag {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: @padding-xs;
|
||||
padding: 0 5px;
|
||||
overflow: hidden;
|
||||
color: @red;
|
||||
font-size: @font-size-sm;
|
||||
line-height: 16px;
|
||||
border-radius: 8px;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: currentColor;
|
||||
opacity: 0.1;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
&-group-container {
|
||||
padding-top: @padding-sm;
|
||||
|
||||
&--hide-soldout {
|
||||
.van-sku-row__item--disabled {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sku row */
|
||||
&-row {
|
||||
margin: 0 @padding-md @padding-sm;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__item,
|
||||
&__image-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: @text-color;
|
||||
border-radius: @border-radius-md;
|
||||
cursor: pointer;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: @sku-item-background-color;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&--active {
|
||||
color: @red;
|
||||
|
||||
&::before {
|
||||
background: currentColor;
|
||||
opacity: 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 40px;
|
||||
margin: 0 @padding-sm @padding-sm 0;
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
|
||||
&-img {
|
||||
z-index: 1;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 4px 4px;
|
||||
object-fit: cover;
|
||||
border-radius: @border-radius-sm;
|
||||
}
|
||||
|
||||
&-name {
|
||||
z-index: 1;
|
||||
padding: @padding-xs;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
color: @gray-5;
|
||||
background: @active-color;
|
||||
cursor: not-allowed;
|
||||
|
||||
.van-sku-row__item-img {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__image {
|
||||
margin-right: 0;
|
||||
|
||||
&-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 110px;
|
||||
margin: 0 4px 4px 0;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&-img {
|
||||
width: 100%;
|
||||
height: 110px;
|
||||
|
||||
&-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 3;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: #fff;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
border-bottom-left-radius: @border-radius-md;
|
||||
}
|
||||
}
|
||||
|
||||
&-name {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
height: 40px;
|
||||
padding: @padding-base;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
|
||||
span {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
&--active {
|
||||
border-color: currentColor;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
color: @gray-5;
|
||||
cursor: not-allowed;
|
||||
|
||||
&::before {
|
||||
z-index: 2;
|
||||
background: @active-color;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
padding-bottom: @padding-sm;
|
||||
}
|
||||
|
||||
&__title-multiple {
|
||||
color: @gray-6;
|
||||
}
|
||||
|
||||
&__scroller {
|
||||
margin: 0 -@padding-md;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__row {
|
||||
display: inline-flex;
|
||||
margin-bottom: 4px;
|
||||
padding: 0 @padding-md;
|
||||
}
|
||||
|
||||
&__indicator {
|
||||
width: 40px;
|
||||
height: 4px;
|
||||
background: @gray-3;
|
||||
border-radius: 2px;
|
||||
|
||||
&-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
&-slider {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background-color: @red;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-stepper-stock {
|
||||
padding: @padding-sm @padding-md;
|
||||
overflow: hidden;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
&__stepper {
|
||||
float: right;
|
||||
padding-left: @padding-base;
|
||||
|
||||
&-title {
|
||||
float: left;
|
||||
}
|
||||
|
||||
&-quota {
|
||||
float: right;
|
||||
color: @red;
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
}
|
||||
|
||||
&__stock {
|
||||
display: inline-block;
|
||||
margin-right: @padding-xs;
|
||||
color: @gray-6;
|
||||
font-size: @font-size-sm;
|
||||
|
||||
&-num--highlight {
|
||||
color: @red;
|
||||
}
|
||||
}
|
||||
|
||||
&-messages {
|
||||
padding-bottom: @padding-xl;
|
||||
|
||||
&__image-cell {
|
||||
.van-cell__title {
|
||||
max-width: @field-label-width;
|
||||
margin-right: @field-label-margin-right;
|
||||
color: @field-label-color;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.van-cell__value {
|
||||
overflow: visible;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&-label {
|
||||
color: @cell-label-color;
|
||||
font-size: @cell-label-font-size;
|
||||
line-height: @cell-label-line-height;
|
||||
}
|
||||
}
|
||||
|
||||
&__cell-block {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
.hairline-bottom(@cell-border-color, @padding-md, @padding-md);
|
||||
}
|
||||
|
||||
&:last-child::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__extra-message {
|
||||
margin-top: -2px;
|
||||
padding: 0 16px 12px;
|
||||
color: @cell-label-color;
|
||||
font-size: @cell-label-font-size;
|
||||
line-height: @cell-label-line-height;
|
||||
}
|
||||
}
|
||||
|
||||
&-actions {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
padding: @padding-xs @padding-md;
|
||||
|
||||
.van-button {
|
||||
height: 40px;
|
||||
font-weight: @font-weight-bold;
|
||||
font-size: @font-size-md;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
||||
&:first-of-type {
|
||||
border-top-left-radius: 20px;
|
||||
border-bottom-left-radius: 20px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
border-top-right-radius: 20px;
|
||||
border-bottom-right-radius: 20px;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
background: @gradient-orange;
|
||||
}
|
||||
|
||||
&--danger {
|
||||
background: @gradient-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
86
node_modules/vant/es/sku/lang.js
generated
vendored
Normal file
86
node_modules/vant/es/sku/lang.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Sku only provide zh-CN lang by default
|
||||
*/
|
||||
export default {
|
||||
'zh-CN': {
|
||||
vanSku: {
|
||||
select: '请选择',
|
||||
selected: '已选',
|
||||
selectSku: '请先选择商品规格',
|
||||
soldout: '库存不足',
|
||||
originPrice: '原价',
|
||||
minusTip: '至少选择一件',
|
||||
minusStartTip: function minusStartTip(start) {
|
||||
return start + "\u4EF6\u8D77\u552E";
|
||||
},
|
||||
unavailable: '商品已经无法购买啦',
|
||||
stock: '剩余',
|
||||
stockUnit: '件',
|
||||
quotaTip: function quotaTip(quota) {
|
||||
return "\u6BCF\u4EBA\u9650\u8D2D" + quota + "\u4EF6";
|
||||
},
|
||||
quotaUsedTip: function quotaUsedTip(quota, count) {
|
||||
return "\u6BCF\u4EBA\u9650\u8D2D" + quota + "\u4EF6\uFF0C\u4F60\u5DF2\u8D2D\u4E70" + count + "\u4EF6";
|
||||
}
|
||||
},
|
||||
vanSkuActions: {
|
||||
buy: '立即购买',
|
||||
addCart: '加入购物车'
|
||||
},
|
||||
vanSkuImgUploader: {
|
||||
oversize: function oversize(maxSize) {
|
||||
return "\u6700\u5927\u53EF\u4E0A\u4F20\u56FE\u7247\u4E3A" + maxSize + "MB\uFF0C\u8BF7\u5C1D\u8BD5\u538B\u7F29\u56FE\u7247\u5C3A\u5BF8";
|
||||
},
|
||||
fail: '上传失败',
|
||||
uploading: '上传中...'
|
||||
},
|
||||
vanSkuStepper: {
|
||||
quotaLimit: function quotaLimit(quota) {
|
||||
return "\u9650\u8D2D" + quota + "\u4EF6";
|
||||
},
|
||||
quotaStart: function quotaStart(start) {
|
||||
return start + "\u4EF6\u8D77\u552E";
|
||||
},
|
||||
comma: ',',
|
||||
num: '购买数量'
|
||||
},
|
||||
vanSkuMessages: {
|
||||
fill: '请填写',
|
||||
upload: '请上传',
|
||||
imageLabel: '仅限一张',
|
||||
invalid: {
|
||||
tel: '请填写正确的数字格式留言',
|
||||
mobile: '手机号长度为6-20位数字',
|
||||
email: '请填写正确的邮箱',
|
||||
id_no: '请填写正确的身份证号码'
|
||||
},
|
||||
placeholder: {
|
||||
id_no: '请填写身份证号',
|
||||
text: '请填写留言',
|
||||
tel: '请填写数字',
|
||||
email: '请填写邮箱',
|
||||
date: '请选择日期',
|
||||
time: '请选择时间',
|
||||
textarea: '请填写留言',
|
||||
mobile: '请填写手机号'
|
||||
}
|
||||
},
|
||||
vanSkuRow: {
|
||||
multiple: '可多选'
|
||||
},
|
||||
vanSkuDatetimeField: {
|
||||
title: {
|
||||
date: '选择年月日',
|
||||
time: '选择时间',
|
||||
datetime: '选择日期时间'
|
||||
},
|
||||
format: {
|
||||
year: '年',
|
||||
month: '月',
|
||||
day: '日',
|
||||
hour: '时',
|
||||
minute: '分'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
18
node_modules/vant/es/sku/style/index.js
generated
vendored
Normal file
18
node_modules/vant/es/sku/style/index.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
import '../../style/base.css';
|
||||
import '../../overlay/index.css';
|
||||
import '../../info/index.css';
|
||||
import '../../icon/index.css';
|
||||
import '../../image/index.css';
|
||||
import '../../cell/index.css';
|
||||
import '../../field/index.css';
|
||||
import '../../popup/index.css';
|
||||
import '../../loading/index.css';
|
||||
import '../../button/index.css';
|
||||
import '../../toast/index.css';
|
||||
import '../../picker/index.css';
|
||||
import '../../swipe/index.css';
|
||||
import '../../swipe-item/index.css';
|
||||
import '../../image-preview/index.css';
|
||||
import '../../uploader/index.css';
|
||||
import '../../stepper/index.css';
|
||||
import '../index.css';
|
18
node_modules/vant/es/sku/style/less.js
generated
vendored
Normal file
18
node_modules/vant/es/sku/style/less.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
import '../../style/base.less';
|
||||
import '../../overlay/index.less';
|
||||
import '../../info/index.less';
|
||||
import '../../icon/index.less';
|
||||
import '../../image/index.less';
|
||||
import '../../cell/index.less';
|
||||
import '../../field/index.less';
|
||||
import '../../popup/index.less';
|
||||
import '../../loading/index.less';
|
||||
import '../../button/index.less';
|
||||
import '../../toast/index.less';
|
||||
import '../../picker/index.less';
|
||||
import '../../swipe/index.less';
|
||||
import '../../swipe-item/index.less';
|
||||
import '../../image-preview/index.less';
|
||||
import '../../uploader/index.less';
|
||||
import '../../stepper/index.less';
|
||||
import '../index.less';
|
148
node_modules/vant/es/sku/utils/sku-helper.js
generated
vendored
Normal file
148
node_modules/vant/es/sku/utils/sku-helper.js
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
import { UNSELECTED_SKU_VALUE_ID } from '../constants';
|
||||
/*
|
||||
normalize sku tree
|
||||
|
||||
[
|
||||
{
|
||||
count: 2,
|
||||
k: "品种", // 规格名称 skuKeyName
|
||||
k_id: "1200", // skuKeyId
|
||||
k_s: "s1" // skuKeyStr
|
||||
v: [ // skuValues
|
||||
{ // skuValue
|
||||
id: "1201", // skuValueId
|
||||
name: "萌" // 具体的规格值 skuValueName
|
||||
}, {
|
||||
id: "973",
|
||||
name: "帅"
|
||||
}
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
|
||||
v
|
||||
{
|
||||
s1: [{
|
||||
id: "1201",
|
||||
name: "萌"
|
||||
}, {
|
||||
id: "973",
|
||||
name: "帅"
|
||||
}],
|
||||
...
|
||||
}
|
||||
*/
|
||||
|
||||
export var normalizeSkuTree = function normalizeSkuTree(skuTree) {
|
||||
var normalizedTree = {};
|
||||
skuTree.forEach(function (treeItem) {
|
||||
normalizedTree[treeItem.k_s] = treeItem.v;
|
||||
});
|
||||
return normalizedTree;
|
||||
};
|
||||
export var normalizePropList = function normalizePropList(propList) {
|
||||
var normalizedProp = {};
|
||||
propList.forEach(function (item) {
|
||||
var itemObj = {};
|
||||
item.v.forEach(function (it) {
|
||||
itemObj[it.id] = it;
|
||||
});
|
||||
normalizedProp[item.k_id] = itemObj;
|
||||
});
|
||||
return normalizedProp;
|
||||
}; // 判断是否所有的sku都已经选中
|
||||
|
||||
export var isAllSelected = function isAllSelected(skuTree, selectedSku) {
|
||||
// 筛选selectedSku对象中key值不为空的值
|
||||
var selected = Object.keys(selectedSku).filter(function (skuKeyStr) {
|
||||
return selectedSku[skuKeyStr] !== UNSELECTED_SKU_VALUE_ID;
|
||||
});
|
||||
return skuTree.length === selected.length;
|
||||
}; // 根据已选择的 sku 获取 skuComb
|
||||
|
||||
export var getSkuComb = function getSkuComb(skuList, selectedSku) {
|
||||
var skuComb = skuList.filter(function (item) {
|
||||
return Object.keys(selectedSku).every(function (skuKeyStr) {
|
||||
return String(item[skuKeyStr]) === String(selectedSku[skuKeyStr]);
|
||||
});
|
||||
});
|
||||
return skuComb[0];
|
||||
}; // 获取已选择的sku名称
|
||||
|
||||
export var getSelectedSkuValues = function getSelectedSkuValues(skuTree, selectedSku) {
|
||||
var normalizedTree = normalizeSkuTree(skuTree);
|
||||
return Object.keys(selectedSku).reduce(function (selectedValues, skuKeyStr) {
|
||||
var skuValues = normalizedTree[skuKeyStr] || [];
|
||||
var skuValueId = selectedSku[skuKeyStr];
|
||||
|
||||
if (skuValueId !== UNSELECTED_SKU_VALUE_ID && skuValues.length > 0) {
|
||||
var skuValue = skuValues.filter(function (value) {
|
||||
return value.id === skuValueId;
|
||||
})[0];
|
||||
skuValue && selectedValues.push(skuValue);
|
||||
}
|
||||
|
||||
return selectedValues;
|
||||
}, []);
|
||||
}; // 判断sku是否可选
|
||||
|
||||
export var isSkuChoosable = function isSkuChoosable(skuList, selectedSku, skuToChoose) {
|
||||
var _extends2;
|
||||
|
||||
var key = skuToChoose.key,
|
||||
valueId = skuToChoose.valueId; // 先假设sku已选中,拼入已选中sku对象中
|
||||
|
||||
var matchedSku = _extends({}, selectedSku, (_extends2 = {}, _extends2[key] = valueId, _extends2)); // 再判断剩余sku是否全部不可选,若不可选则当前sku不可选中
|
||||
|
||||
|
||||
var skusToCheck = Object.keys(matchedSku).filter(function (skuKey) {
|
||||
return matchedSku[skuKey] !== UNSELECTED_SKU_VALUE_ID;
|
||||
});
|
||||
var filteredSku = skuList.filter(function (sku) {
|
||||
return skusToCheck.every(function (skuKey) {
|
||||
return String(matchedSku[skuKey]) === String(sku[skuKey]);
|
||||
});
|
||||
});
|
||||
var stock = filteredSku.reduce(function (total, sku) {
|
||||
total += sku.stock_num;
|
||||
return total;
|
||||
}, 0);
|
||||
return stock > 0;
|
||||
};
|
||||
export var getSelectedPropValues = function getSelectedPropValues(propList, selectedProp) {
|
||||
var normalizeProp = normalizePropList(propList);
|
||||
return Object.keys(selectedProp).reduce(function (acc, cur) {
|
||||
selectedProp[cur].forEach(function (it) {
|
||||
acc.push(_extends({}, normalizeProp[cur][it]));
|
||||
});
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
export var getSelectedProperties = function getSelectedProperties(propList, selectedProp) {
|
||||
var list = [];
|
||||
(propList || []).forEach(function (prop) {
|
||||
if (selectedProp[prop.k_id] && selectedProp[prop.k_id].length > 0) {
|
||||
var v = [];
|
||||
prop.v.forEach(function (it) {
|
||||
if (selectedProp[prop.k_id].indexOf(it.id) > -1) {
|
||||
v.push(_extends({}, it));
|
||||
}
|
||||
});
|
||||
list.push(_extends({}, prop, {
|
||||
v: v
|
||||
}));
|
||||
}
|
||||
});
|
||||
return list;
|
||||
};
|
||||
export default {
|
||||
normalizeSkuTree: normalizeSkuTree,
|
||||
getSkuComb: getSkuComb,
|
||||
getSelectedSkuValues: getSelectedSkuValues,
|
||||
isAllSelected: isAllSelected,
|
||||
isSkuChoosable: isSkuChoosable,
|
||||
getSelectedPropValues: getSelectedPropValues,
|
||||
getSelectedProperties: getSelectedProperties
|
||||
};
|
34
node_modules/vant/es/sku/utils/time-helper.js
generated
vendored
Normal file
34
node_modules/vant/es/sku/utils/time-helper.js
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
import { padZero } from '../../utils/format/string'; // 字符串转 Date
|
||||
// 只处理 YYYY-MM-DD 或者 YYYY-MM-DD HH:MM 格式
|
||||
|
||||
export function stringToDate(timeString) {
|
||||
if (!timeString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Date(timeString.replace(/-/g, '/'));
|
||||
} // Date 转字符串
|
||||
// type: date or datetime
|
||||
|
||||
export function dateToString(date, type) {
|
||||
if (type === void 0) {
|
||||
type = 'date';
|
||||
}
|
||||
|
||||
if (!date) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var year = date.getFullYear();
|
||||
var month = date.getMonth() + 1;
|
||||
var day = date.getDate();
|
||||
var timeString = year + "-" + padZero(month) + "-" + padZero(day);
|
||||
|
||||
if (type === 'datetime') {
|
||||
var hours = date.getHours();
|
||||
var minute = date.getMinutes();
|
||||
timeString += " " + padZero(hours) + ":" + padZero(minute);
|
||||
}
|
||||
|
||||
return timeString;
|
||||
}
|
Reference in New Issue
Block a user