|
|
/**
|
|
|
* 购物车选择尺寸、颜色和数量面板
|
|
|
* @author: feng.chen<feng.chen@yoho.cn>
|
|
|
* @date: 2017/3/2
|
|
|
* 示例:
|
|
|
* let chosePanel = require('chose-panel');
|
|
|
* chosePanel.show({
|
|
|
* data: {}, // 商品数据
|
|
|
* buttonText: '加入购物车', // 自定义底部按钮文字
|
|
|
* disableNum: true // 禁用编辑数量
|
|
|
* }).then((sku) => {
|
|
|
* //点击确认按钮回调,返回sku对象,各自业务在此处实现,该组件不做选择后的处理
|
|
|
* //...
|
|
|
* }, () => {
|
|
|
* //关闭选择框回调
|
|
|
* });
|
|
|
* choselPanel.close(); //关闭选择框
|
|
|
*/
|
|
|
let $ = require('yoho-jquery'),
|
|
|
tip = require('js/plugin/tip'),
|
|
|
innerScroll = require('js/plugin/inner-scroll');
|
|
|
|
|
|
let panelT = require('hbs/activity/group/chose-panel.hbs');
|
|
|
|
|
|
let $yohoPage = $('.yoho-page'),
|
|
|
$chosePanel = $('.chose-panel'),
|
|
|
$choseArea,
|
|
|
$goodNum,
|
|
|
$btnMinus,
|
|
|
$thumbImg,
|
|
|
$choseBtnSure,
|
|
|
$noChoose,
|
|
|
$chooseInfo;
|
|
|
|
|
|
class ChosePanel {
|
|
|
constructor() {
|
|
|
if (!window.cookie) {
|
|
|
require('js/common');
|
|
|
}
|
|
|
this._regEvents();
|
|
|
}
|
|
|
|
|
|
show(opt) {
|
|
|
if (!opt) {
|
|
|
$('.chose-panel').show();
|
|
|
return new Promise((resolve, reject) => {
|
|
|
this._resolve = resolve;
|
|
|
this._reject = reject;
|
|
|
});
|
|
|
}
|
|
|
Object.assign(this, opt);
|
|
|
if (!this.data) {
|
|
|
throw new Error('未赋值');
|
|
|
}
|
|
|
|
|
|
// if (this.data) {
|
|
|
// this._setModes();
|
|
|
// this.maxBuyNum = this.data.cartInfo.limit || 0; // 0表示不限制购买
|
|
|
// this.setting = {
|
|
|
// disableNum: this.disableNum,
|
|
|
// noChoseText: `请选择${this.props.map(prop => prop.name).join('、')}`,
|
|
|
// buttonText: this.buttonText || this._getButtonText(),
|
|
|
// buyNum: this.buyNum
|
|
|
// };
|
|
|
// }
|
|
|
|
|
|
this._render();
|
|
|
return new Promise((resolve, reject) => {
|
|
|
this._resolve = resolve;
|
|
|
this._reject = reject;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
close() {
|
|
|
innerScroll.enableScroll($choseArea);
|
|
|
$('.chose-panel').hide();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 设置商品模式
|
|
|
*/
|
|
|
_setModes() {
|
|
|
this.modes = { // 商品特性
|
|
|
// disableNum: this.disableNum, // 禁用编辑
|
|
|
// showBuyNow: this.data.showBuyNow // 是否显示双按钮
|
|
|
|
|
|
// isSoldOutSoon: false, //是否展示即将售罄
|
|
|
// goodsList: [],
|
|
|
// sizeList: [],
|
|
|
// image: '',
|
|
|
// goodPrice: '',
|
|
|
// price: '',
|
|
|
// buyNumber: 1,
|
|
|
// minusButtonEnable: false,
|
|
|
// plusButtonEnable: true,
|
|
|
// buyButtonEnable: true,
|
|
|
// buy_limit_number: 1
|
|
|
};
|
|
|
}
|
|
|
|
|
|
_render() {
|
|
|
let html;
|
|
|
|
|
|
html = panelT(Object.assign(this.data, this.setting));
|
|
|
if ($chosePanel.length) {
|
|
|
$chosePanel.replaceWith(html);
|
|
|
} else {
|
|
|
$yohoPage.append(html);
|
|
|
}
|
|
|
|
|
|
this._setVariable();
|
|
|
innerScroll.disableScroll($choseArea);
|
|
|
}
|
|
|
|
|
|
_getButtonText() {
|
|
|
if (this.modes.showBuyNow) {
|
|
|
return {
|
|
|
double: true,
|
|
|
text: '加入购物车'
|
|
|
};
|
|
|
}
|
|
|
if (this.modes.tickets || this.modes.limitCode || this.modes.seckill) {
|
|
|
return {
|
|
|
double: false,
|
|
|
text: '立即购买'
|
|
|
};
|
|
|
}
|
|
|
return {
|
|
|
double: false,
|
|
|
text: '加入购物车'
|
|
|
};
|
|
|
}
|
|
|
|
|
|
_defaultBuyNum() {
|
|
|
return (this.modes.discount && this.data.discountBuy.num) ||
|
|
|
(this.data.cartInfo && this.data.cartInfo.num) || 1;
|
|
|
}
|
|
|
|
|
|
_setVariable() {
|
|
|
$chosePanel = $('.chose-panel');
|
|
|
$choseArea = $('.chose-panel .main .chose-items');
|
|
|
$goodNum = $('#good-num');
|
|
|
$btnMinus = $('.btn-minus');
|
|
|
$thumbImg = $('.thumb-img');
|
|
|
$choseBtnSure = $('#chose-btn-sure');
|
|
|
$noChoose = $('.not-choose');
|
|
|
$chooseInfo = $('.choosed-info');
|
|
|
}
|
|
|
|
|
|
_regEvents() {
|
|
|
$yohoPage.on('touchstart', '.chose-panel', (e) => {
|
|
|
return this._closeClick(e);
|
|
|
});
|
|
|
$yohoPage.on('touchstart', '.block', (e) => {
|
|
|
this._blockClick(e);
|
|
|
});
|
|
|
$yohoPage.on('touchstart', '.btn-plus,.btn-minus', (e) => {
|
|
|
this._numClick(e);
|
|
|
});
|
|
|
$yohoPage.on('touchstart', '.thumb-img .thumb', (e) => {
|
|
|
this._thumbClick(e);
|
|
|
});
|
|
|
$yohoPage.on('touchstart', '#chose-btn-sure', (e) => {
|
|
|
return this._choseBtnSureClick(e, false);
|
|
|
});
|
|
|
$yohoPage.on('touchstart', '#chose-btn-buynow', (e) => {
|
|
|
// let sku = this._checkSku(this.buyNum);
|
|
|
|
|
|
// if (window._yas && window._yas.sendCustomInfo) {
|
|
|
// window._yas.sendCustomInfo({
|
|
|
// op: 'YB_GDS_BUYNOW_BTN',
|
|
|
// param: JSON.stringify({
|
|
|
// C_ID: this.C_ID,
|
|
|
// PRD_ID: this.data.cartInfo.productId,
|
|
|
// PRD_NUM: this.buyNum,
|
|
|
// PRD_SKN: this.data.cartInfo.productSkn,
|
|
|
// PRD_SKU: sku && sku.skuId
|
|
|
// })
|
|
|
// }, true);
|
|
|
// }
|
|
|
|
|
|
return this._choseBtnSureClick(e, true);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 点击关闭按钮
|
|
|
*/
|
|
|
_closeClick(e) {
|
|
|
let $cur = $(e.target);
|
|
|
|
|
|
if ($cur.closest('.main').length > 0 && !$cur.hasClass('close')) {
|
|
|
return;
|
|
|
}
|
|
|
this.close();
|
|
|
this._reject && this._reject();
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 点击属性
|
|
|
*/
|
|
|
_blockClick(e) {
|
|
|
let $block = $(e.currentTarget);
|
|
|
|
|
|
if ($block.hasClass('chosed')) {
|
|
|
$block.removeClass('chosed');
|
|
|
} else {
|
|
|
$block.addClass('chosed').siblings().removeClass('chosed');
|
|
|
}
|
|
|
this._selectBlock($block);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 点击数量加减
|
|
|
*/
|
|
|
_numClick(e) {
|
|
|
let buyNum;
|
|
|
|
|
|
if (this.modes.disableNum) {
|
|
|
return;
|
|
|
}
|
|
|
buyNum = $(e.currentTarget).hasClass('btn-minus') ? this.buyNum - 1 : this.buyNum + 1;
|
|
|
if (this._checkSku(buyNum)) {
|
|
|
this.buyNum = buyNum;
|
|
|
$goodNum.val(this.buyNum);
|
|
|
if (this.modes.discount) {
|
|
|
if (buyNum <= this.minBuyNum) {
|
|
|
$('.btn-minus').addClass('discount-gray');
|
|
|
} else {
|
|
|
$('.btn-minus').removeClass('discount-gray');
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 点击缩略图
|
|
|
*/
|
|
|
_thumbClick() {
|
|
|
if ($thumbImg.hasClass('hover')) {
|
|
|
$thumbImg.removeClass('hover');
|
|
|
} else {
|
|
|
$thumbImg.addClass('hover');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 点击确定或者立即购买按钮
|
|
|
*/
|
|
|
_choseBtnSureClick(e, buyNow) {
|
|
|
let selectSku = this._checkSku(this.buyNum);
|
|
|
|
|
|
if (selectSku) {
|
|
|
this.close();
|
|
|
this._resolve && this._resolve({
|
|
|
sku: selectSku,
|
|
|
skn: this.data.cartInfo.productSkn,
|
|
|
productId: this.data.cartInfo.productId,
|
|
|
buyNum: this.buyNum,
|
|
|
modes: this.modes,
|
|
|
buyNow: buyNow
|
|
|
});
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 验证选择sku的购买数量是否通过
|
|
|
*/
|
|
|
_checkSku(buyNum) {
|
|
|
if ($('.block.chosed.zero-stock').length) {
|
|
|
return false;
|
|
|
}
|
|
|
let validSelects = this.props
|
|
|
.filter(prop => !$(`.block[data-prop-id="${prop.type}"]`).hasClass('chosed'))
|
|
|
.map(prop => {
|
|
|
return prop.name;
|
|
|
});
|
|
|
|
|
|
if (validSelects.length) {
|
|
|
tip.show(`请选择${validSelects.join('和')}~`);
|
|
|
return false;
|
|
|
}
|
|
|
let selectSku = this._getSelectSku();
|
|
|
|
|
|
if (!selectSku) {
|
|
|
tip.show('无法选择该属性的商品');
|
|
|
return false;
|
|
|
}
|
|
|
if (buyNum < this.minBuyNum) {
|
|
|
if (this.modes.discount) {
|
|
|
tip.show(`量贩商品,${this.minBuyNum}件起购`);
|
|
|
return false;
|
|
|
} else {
|
|
|
tip.show('您选择的数量不能为零~');
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
if (this.modes.tickets && buyNum > selectSku.limitNum) {
|
|
|
if (selectSku.limitNum) {
|
|
|
tip.show(`每人只可购买${selectSku.limitNum}张此门票`);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
if (this.modes.limit && buyNum > this.maxBuyNum) {
|
|
|
tip.show('您选择数量大于限购数量~');
|
|
|
return false;
|
|
|
}
|
|
|
if (buyNum > selectSku.storage) {
|
|
|
tip.show('您选择的数量超过了最大库存量~');
|
|
|
return false;
|
|
|
}
|
|
|
return selectSku;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 选择属性
|
|
|
*/
|
|
|
_selectBlock($selectBlock) {
|
|
|
let that = this;
|
|
|
let propId = $selectBlock.data('prop-id'),
|
|
|
valueId = $selectBlock.data('value-id');
|
|
|
let chosed = $($selectBlock).hasClass('chosed');
|
|
|
|
|
|
if ($('.block.chosed').length === 0) {
|
|
|
this._initBlockStatus();
|
|
|
} else {
|
|
|
// 根据选择的属性值筛选出符合条件的sku列表,然后遍历其他属性如果在sku列表中不存在该属性值,则灰色
|
|
|
let filterSkus = this.skus.filter(sku => (!chosed || sku.prop[propId].valId === valueId) &&
|
|
|
sku.storage >= this.minBuyNum);
|
|
|
let filterProps = this.props.filter(prop => prop.type !== propId);
|
|
|
|
|
|
filterProps.forEach(prop => {
|
|
|
$(`.block[data-prop-id="${prop.type}"]`).each((i, ele) => {
|
|
|
let $block = $(ele);
|
|
|
let valId = $block.data('value-id');
|
|
|
let existsSku = filterSkus.some(sku => sku.prop[prop.type].valId === valId);
|
|
|
let fsku = that.skus.filter(sku => sku.prop[propId].valId === valueId &&
|
|
|
sku.prop[prop.type].valId === valId);
|
|
|
let limitTip = '';
|
|
|
|
|
|
if (!existsSku) {
|
|
|
$block.addClass('zero-stock');
|
|
|
if (fsku.length && fsku[0].limitBuyTip) {
|
|
|
limitTip = fsku[0].limitBuyTip;
|
|
|
}
|
|
|
} else {
|
|
|
$block.removeClass('zero-stock');
|
|
|
}
|
|
|
|
|
|
$block.data('limittip', limitTip);
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
if (window._yas && window._yas.sendCustomInfo && chosed) {
|
|
|
if (propId === 'color') {
|
|
|
window._yas.sendCustomInfo({
|
|
|
op: 'YB_GDS_COLOR_C',
|
|
|
param: JSON.stringify({
|
|
|
C_ID: this.C_ID,
|
|
|
PRD_ID: this.data.cartInfo.productId,
|
|
|
COLOR: $selectBlock.text()
|
|
|
})
|
|
|
}, true);
|
|
|
} else if (propId === 'size') {
|
|
|
window._yas.sendCustomInfo({
|
|
|
op: 'YB_GDS_SIZE_C',
|
|
|
param: JSON.stringify({
|
|
|
C_ID: this.C_ID,
|
|
|
PRD_ID: this.data.cartInfo.productId,
|
|
|
SIZE: $selectBlock.text()
|
|
|
})
|
|
|
}, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
this._refreshBlockStatus();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 选择属性后刷新其他属性的状态
|
|
|
*/
|
|
|
_refreshBlockStatus() {
|
|
|
let selectSku = this._getSelectSku();
|
|
|
let $zeroChose = $('.block.chosed.zero-stock');
|
|
|
|
|
|
// 设置底部按钮文字
|
|
|
if ($zeroChose.length) {
|
|
|
let tipText = '已售罄';
|
|
|
|
|
|
if ($zeroChose.data('limittip')) {
|
|
|
tipText = $zeroChose.data('limittip');
|
|
|
}
|
|
|
|
|
|
$choseBtnSure.css('background-color', '#c0c0c0').text(tipText);
|
|
|
} else {
|
|
|
$choseBtnSure.css('background-color', '#eb0313').text(this.setting.buttonText.text);
|
|
|
}
|
|
|
|
|
|
// 设置默认购买数量
|
|
|
this.buyNum = this._defaultBuyNum();
|
|
|
$goodNum.val(this.buyNum);
|
|
|
if (this.modes.discount) {
|
|
|
$btnMinus.addClass('discount-gray');
|
|
|
}
|
|
|
|
|
|
// 根据颜色属性设置缩略图
|
|
|
let $colorBlock = $('.block.chosed[data-prop-id="color"]');
|
|
|
|
|
|
if ($colorBlock.length) {
|
|
|
let colorSkus = this.skus.filter(sku => sku.prop.color &&
|
|
|
sku.prop.color.valId === $colorBlock.data('value-id'));
|
|
|
|
|
|
if (colorSkus.length) {
|
|
|
let thumb = colorSkus[0].thumb;
|
|
|
|
|
|
if (!thumb) {
|
|
|
thumb = this.data.cartInfo.defaultThumb;
|
|
|
}
|
|
|
$chosePanel.find('.thumb').attr('src', thumb);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 设置选择属性提示
|
|
|
let valueList = Array.from($('.block.chosed').map((index, ele) => {
|
|
|
return $(ele).text();
|
|
|
}));
|
|
|
|
|
|
if (valueList.length) {
|
|
|
$noChoose.addClass('hide');
|
|
|
$chooseInfo.removeClass('hide');
|
|
|
$chooseInfo.text(`已选:${valueList.join('、')}`);
|
|
|
} else {
|
|
|
$noChoose.removeClass('hide');
|
|
|
$chooseInfo.addClass('hide');
|
|
|
}
|
|
|
|
|
|
if (selectSku) {
|
|
|
let numText;
|
|
|
|
|
|
if (selectSku.limitNum) {
|
|
|
if (selectSku.limitNum) {
|
|
|
numText = `限购${selectSku.limitNum}件`;
|
|
|
} else {
|
|
|
numText = '';
|
|
|
}
|
|
|
} else if (this.modes.soonSoldOut) {
|
|
|
numText = '即将售罄';
|
|
|
} else if (selectSku.storage < 4 && selectSku.storage > 0) {
|
|
|
numText = `剩余${selectSku.storage}件`;
|
|
|
} else {
|
|
|
numText = '';
|
|
|
}
|
|
|
$chosePanel.find('.left-num').text(numText);
|
|
|
$chosePanel.find('.size-info').text(selectSku.sizeInfo).removeClass('hide');
|
|
|
$chosePanel.find('.size-rec').text(selectSku.sizeRec || '').removeClass('hide');
|
|
|
} else {
|
|
|
$chosePanel.find('.left-num').text('');
|
|
|
$chosePanel.find('.size-info').text('').addClass('hide');
|
|
|
$chosePanel.find('.size-rec').text('').addClass('hide');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据已选择的属性值获得符合条件的sku
|
|
|
*/
|
|
|
_getSelectSku() {
|
|
|
let selectValues,
|
|
|
selectSku;
|
|
|
|
|
|
if ($('.block.chosed').length !== this.props.length) {
|
|
|
return;
|
|
|
}
|
|
|
selectValues = Array.from($('.block.chosed').map((index, ele) => {
|
|
|
let $block = $(ele);
|
|
|
|
|
|
return {
|
|
|
propId: $block.data('prop-id'),
|
|
|
valueId: $block.data('value-id')
|
|
|
};
|
|
|
}));
|
|
|
selectSku = this.skus.filter(sku => {
|
|
|
return selectValues
|
|
|
.map(value => {
|
|
|
return sku.prop[value.propId].valId === value.valueId;
|
|
|
})
|
|
|
.filter(match => match).length === this.props.length;
|
|
|
});
|
|
|
if (selectSku.length >= 1) {
|
|
|
return selectSku[0];
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
module.exports = new ChosePanel(); |
...
|
...
|
|