Blame view

public/js/common/chose-panel-new.js 16.9 KB
陈峰 authored
1 2 3 4 5 6 7
/**
 * 购物车选择尺寸、颜色和数量面板
 * @author: feng.chen<feng.chen@yoho.cn>
 * @date: 2017/3/2
 * 示例:
 * let chosePanel = require('chose-panel-new');
 * chosePanel.show({
陈峰 authored
8 9 10
 *      data: {},               // 商品数据
 *      buttonText: '加入购物车', // 自定义底部按钮文字
 *      disableNum: true        // 禁用编辑数量
陈峰 authored
11 12 13 14 15 16 17 18 19
 * }).then((sku) => {
 *      //点击确认按钮回调,返回sku对象,各自业务在此处实现,该组件不做选择后的处理
 *      //...
 * }, () => {
 *      //关闭选择框回调
 * });
 * choselPanel.close(); //关闭选择框
 */
let $ = require('yoho-jquery'),
20 21
    tip = require('plugin/tip'),
    innerScroll = require('plugin/inner-scroll');
陈峰 authored
22
陈峰 authored
23
let panelT = require('common/chose-panel-new.hbs');
陈峰 authored
24 25 26

let $yohoPage = $('.yoho-page'),
    $chosePanel = $('.chose-panel'),
陈峰 authored
27 28 29
    $choseArea,
    $goodNum,
    $btnMinus,
30 31 32 33
    $thumbImg,
    $choseBtnSure,
    $noChoose,
    $chooseInfo;
陈峰 authored
34 35 36

class ChosePanel {
    constructor() {
陈峰 authored
37
        if (!window.cookie) {
38
            require('common');
陈峰 authored
39
        }
40
        this.C_ID = window._ChannelVary[window.cookie('_Channel')];
陈峰 authored
41 42
        this._regEvents();
    }
陈峰 authored
43
    show(opt) {
陈峰 authored
44 45 46 47 48 49 50 51 52 53 54 55 56 57
        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表示不限制购买
陈峰 authored
58 59
            this.skus = this.data.cartInfo.skus || [];
            this.props = this.data.cartInfo.props || [];
郭成尧 authored
60 61
            this.buyNum = this._defaultBuyNum();
            this.minBuyNum = (this.modes.discount && this.data.discountBuy.num) || 1;
62
            this.setting = {
陈峰 authored
63
                disableNum: this.disableNum,
64
                noChoseText: `请选择${this.props.map(prop => prop.name).join('、')}`,
陈峰 authored
65
                buttonText: this.buttonText || this._getButtonText(),
66 67
                buyNum: this.buyNum
            };
陈峰 authored
68 69
        }
陈峰 authored
70
        this._render();
陈峰 authored
71
        return new Promise((resolve, reject) => {
陈峰 authored
72 73
            this._resolve = resolve;
            this._reject = reject;
陈峰 authored
74
        });
陈峰 authored
75 76
    }
    close() {
77
        innerScroll.enableScroll($choseArea);
陈峰 authored
78
        $('.chose-panel').hide();
陈峰 authored
79 80 81 82 83 84 85 86 87 88 89 90 91
    }

    /**
     * 设置商品模式
     */
    _setModes() {
        this.modes = { // 商品特性
            discount: this.data.discountBuy ? true : false, // 量贩
            tickets: this.data.tickets ? true : false, // 门票
            limitCode: this.data.cartInfo.limitProductCode ? true : false, // 限购
            limit: this.data.cartInfo.limit ? true : false, // 限制购买数量
            soonSoldOut: $('.soon-sold-out-tag').length ? true : false, // 即将售罄
            seckill: $('.seckill-time').length ? true : false, // 秒杀
郭成尧 authored
92 93
            disableNum: this.disableNum, // 禁用编辑
            showBuyNow: this.data.showBuyNow // 是否显示双按钮
陈峰 authored
94
        };
陈峰 authored
95 96 97
    }
    _render() {
        let html;
陈峰 authored
98
99
        html = panelT(Object.assign(this.data, this.setting));
陈峰 authored
100 101 102 103 104 105
        if ($chosePanel.length) {
            $chosePanel.replaceWith(html);
        } else {
            $yohoPage.append(html);
        }
106
        this._setVariable();
陈峰 authored
107
        this._initBlockStatus();
陈峰 authored
108 109 110
        innerScroll.disableScroll($choseArea);
    }
    _getButtonText() {
郭成尧 authored
111 112 113 114 115 116
        if (this.modes.showBuyNow) {
            return {
                double: true,
                text: '加入购物车'
            };
        }
陈峰 authored
117
        if (this.modes.tickets || this.modes.limitCode || this.modes.seckill) {
郭成尧 authored
118 119 120 121
            return {
                double: false,
                text: '立即购买'
            };
陈峰 authored
122
        }
郭成尧 authored
123 124 125 126
        return {
            double: false,
            text: '加入购物车'
        };
陈峰 authored
127 128
    }
    _defaultBuyNum() {
郭成尧 authored
129 130
        return (this.modes.discount && this.data.discountBuy.num) ||
            (this.data.cartInfo && this.data.cartInfo.num) || 1;
陈峰 authored
131
    }
陈峰 authored
132 133 134 135 136 137

    /**
     * 初始化属性按钮状态不满足库存的灰色
     */
    _initBlockStatus() {
        // 获取sku列表中库存小于最小购买数量的属性,如果在其他sku中它们没有满足购买数量条件的可以灰色
陈峰 authored
138
        let noStorageSkus = this.skus.filter(sku => sku.storage < this.minBuyNum);
陈峰 authored
139
陈峰 authored
140 141
        $chosePanel.find('.thumb').attr('src', this.data.cartInfo.defaultThumb);
陈峰 authored
142 143 144 145 146
        $('.block').removeClass('zero-stock');
        noStorageSkus.forEach(sku => {
            for (let propType in sku.prop) {
                if (propType) {
                    let prop = sku.prop[propType];
陈峰 authored
147 148
                    let zeroStock = !this.skus.some(_ => _.prop[propType].valId === prop.valId &&
                    _.storage >= this.minBuyNum);
陈峰 authored
149 150 151 152 153 154 155 156 157 158
                    let $block = $(`.block[data-prop-id="${propType}"][data-value-id="${prop.valId}"]`);

                    if (zeroStock) {
                        $block.addClass('zero-stock');
                    } else {
                        $block.removeClass('zero-stock');
                    }
                }
            }
        });
陈峰 authored
159
    }
160
    _setVariable() {
陈峰 authored
161 162
        $chosePanel = $('.chose-panel');
        $choseArea = $('.chose-panel .main .chose-items');
陈峰 authored
163 164 165
        $goodNum = $('#good-num');
        $btnMinus = $('.btn-minus');
        $thumbImg = $('.thumb-img');
166 167 168
        $choseBtnSure = $('#chose-btn-sure');
        $noChoose = $('.not-choose');
        $chooseInfo = $('.choosed-info');
陈峰 authored
169
    }
陈峰 authored
170
    _regEvents() {
陈峰 authored
171
        $yohoPage.on('touchstart', '.chose-panel', (e) => {
陈峰 authored
172 173 174
            return this._closeClick(e);
        });
        $yohoPage.on('touchstart', '.block', (e) => {
175
            this._blockClick(e);
陈峰 authored
176
        });
陈峰 authored
177
        $yohoPage.on('touchstart', '.btn-plus,.btn-minus', (e) => {
178
            this._numClick(e);
陈峰 authored
179
        });
陈峰 authored
180
        $yohoPage.on('touchstart', '.thumb-img .thumb', (e) => {
181
            this._thumbClick(e);
陈峰 authored
182
        });
陈峰 authored
183
        $yohoPage.on('touchstart', '#chose-btn-sure', (e) => {
郭成尧 authored
184 185 186
            return this._choseBtnSureClick(e, false);
        });
        $yohoPage.on('touchstart', '#chose-btn-buynow', (e) => {
郭成尧 authored
187 188
            let sku = this._checkSku(this.buyNum);
李靖 authored
189 190 191 192 193 194 195 196 197 198 199 200
            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);
            }
201
郭成尧 authored
202
            return this._choseBtnSureClick(e, true);
陈峰 authored
203 204
        });
    }
陈峰 authored
205 206 207 208

    /**
     * 点击关闭按钮
     */
陈峰 authored
209 210 211 212 213 214
    _closeClick(e) {
        let $cur = $(e.target);

        if ($cur.closest('.main').length > 0 && !$cur.hasClass('close')) {
            return;
        }
陈峰 authored
215
        this.close();
陈峰 authored
216
        this._reject && this._reject();
陈峰 authored
217
        return false;
陈峰 authored
218
    }
陈峰 authored
219 220 221 222

    /**
     * 点击属性
     */
陈峰 authored
223 224 225 226 227 228 229 230
    _blockClick(e) {
        let $block = $(e.currentTarget);

        if ($block.hasClass('chosed')) {
            $block.removeClass('chosed');
        } else {
            $block.addClass('chosed').siblings().removeClass('chosed');
        }
陈峰 authored
231 232
        this._selectBlock($block);
    }
陈峰 authored
233 234 235 236

    /**
     * 点击数量加减
     */
陈峰 authored
237 238 239
    _numClick(e) {
        let buyNum;
240
        if (this.modes.disableNum) {
陈峰 authored
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
            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');
                }
            }
        }
    }
陈峰 authored
256 257 258 259

    /**
     * 点击缩略图
     */
陈峰 authored
260 261 262 263 264 265 266
    _thumbClick() {
        if ($thumbImg.hasClass('hover')) {
            $thumbImg.removeClass('hover');
        } else {
            $thumbImg.addClass('hover');
        }
    }
陈峰 authored
267 268

    /**
郭成尧 authored
269
     * 点击确定或者立即购买按钮
陈峰 authored
270
     */
郭成尧 authored
271
    _choseBtnSureClick(e, buyNow) {
陈峰 authored
272 273 274
        let selectSku = this._checkSku(this.buyNum);

        if (selectSku) {
陈峰 authored
275 276
            this.close();
            this._resolve && this._resolve({
277
                sku: selectSku,
陈峰 authored
278 279
                skn: this.data.cartInfo.productSkn,
                productId: this.data.cartInfo.productId,
280
                buyNum: this.buyNum,
郭成尧 authored
281 282
                modes: this.modes,
                buyNow: buyNow
283 284
            });
            return false;
陈峰 authored
285 286
        }
    }
陈峰 authored
287 288 289 290

    /**
     * 验证选择sku的购买数量是否通过
     */
陈峰 authored
291
    _checkSku(buyNum) {
292 293 294
        if ($('.block.chosed.zero-stock').length) {
            return false;
        }
陈峰 authored
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
        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;
            }
        }
李靖 authored
320 321 322 323 324
        if (this.modes.tickets && buyNum > selectSku.limitNum) {
            if (selectSku.limitNum) {
                tip.show(`每人只可购买${selectSku.limitNum}张此门票`);
                return false;
            }
陈峰 authored
325
        }
326 327 328 329
        if (this.modes.limit && buyNum > this.maxBuyNum) {
            tip.show('您选择数量大于限购数量~');
            return false;
        }
陈峰 authored
330 331 332 333 334 335
        if (buyNum > selectSku.storage) {
            tip.show('您选择的数量超过了最大库存量~');
            return false;
        }
        return selectSku;
    }
陈峰 authored
336 337 338 339

    /**
     * 选择属性
     */
陈峰 authored
340
    _selectBlock($selectBlock) {
yyq authored
341
        let that = this;
陈峰 authored
342 343 344 345 346
        let propId = $selectBlock.data('prop-id'),
            valueId = $selectBlock.data('value-id');
        let chosed = $($selectBlock).hasClass('chosed');

        if ($('.block.chosed').length === 0) {
陈峰 authored
347
            this._initBlockStatus();
陈峰 authored
348
        } else {
陈峰 authored
349
            // 根据选择的属性值筛选出符合条件的sku列表,然后遍历其他属性如果在sku列表中不存在该属性值,则灰色
陈峰 authored
350 351 352
            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);
陈峰 authored
353 354 355 356 357 358

            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);
yyq authored
359 360 361
                    let fsku = that.skus.filter(sku => sku.prop[propId].valId === valueId &&
                        sku.prop[prop.type].valId === valId);
                    let limitTip = '';
陈峰 authored
362 363 364

                    if (!existsSku) {
                        $block.addClass('zero-stock');
yyq authored
365 366 367
                        if (fsku.length && fsku[0].limitBuyTip) {
                            limitTip = fsku[0].limitBuyTip;
                        }
陈峰 authored
368 369 370
                    } else {
                        $block.removeClass('zero-stock');
                    }
yyq authored
371 372

                    $block.data('limittip', limitTip);
陈峰 authored
373 374 375
                });
            });
        }
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
        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);
            }
        }
陈峰 authored
397
陈峰 authored
398
        this._refreshBlockStatus();
陈峰 authored
399
    }
陈峰 authored
400 401 402 403 404

    /**
     * 选择属性后刷新其他属性的状态
     */
    _refreshBlockStatus() {
陈峰 authored
405
        let selectSku = this._getSelectSku();
yyq authored
406
        let $zeroChose = $('.block.chosed.zero-stock');
陈峰 authored
407 408

        // 设置底部按钮文字
yyq authored
409 410 411 412 413 414 415 416
        if ($zeroChose.length) {
            let tipText = '已售罄';

            if ($zeroChose.data('limittip')) {
                tipText = $zeroChose.data('limittip');
            }

            $choseBtnSure.css('background-color', '#c0c0c0').text(tipText);
陈峰 authored
417
        } else {
郭成尧 authored
418
            $choseBtnSure.css('background-color', '#eb0313').text(this.setting.buttonText.text);
陈峰 authored
419 420 421 422 423 424 425
        }

        // 设置默认购买数量
        this.buyNum = this._defaultBuyNum();
        $goodNum.val(this.buyNum);
        if (this.modes.discount) {
            $btnMinus.addClass('discount-gray');
陈峰 authored
426 427 428 429 430 431
        }

        // 根据颜色属性设置缩略图
        let $colorBlock = $('.block.chosed[data-prop-id="color"]');

        if ($colorBlock.length) {
陈峰 authored
432
            let colorSkus = this.skus.filter(sku => sku.prop.color &&
陈峰 authored
433 434 435 436 437 438
                sku.prop.color.valId === $colorBlock.data('value-id'));

            if (colorSkus.length) {
                let thumb = colorSkus[0].thumb;

                if (!thumb) {
陈峰 authored
439
                    thumb = this.data.cartInfo.defaultThumb;
陈峰 authored
440 441 442 443 444 445 446 447 448 449
                }
                $chosePanel.find('.thumb').attr('src', thumb);
            }
        }

        // 设置选择属性提示
        let valueList = Array.from($('.block.chosed').map((index, ele) => {
            return $(ele).text();
        }));
李靖 authored
450 451
        // if (this.modes.tickets) {
        //     let $chosed = $('.block.chosed');
452
李靖 authored
453 454 455 456
        //     valueList = Array.from($chosed.not('.hide').map((index, ele) => {
        //         return $(ele).text();
        //     }));
        // }
457
陈峰 authored
458
        if (valueList.length) {
459 460 461
            $noChoose.addClass('hide');
            $chooseInfo.removeClass('hide');
            $chooseInfo.text(`已选:${valueList.join('、')}`);
陈峰 authored
462
        } else {
463 464
            $noChoose.removeClass('hide');
            $chooseInfo.addClass('hide');
陈峰 authored
465 466 467 468
        }

        if (selectSku) {
            // 设置left-num文字
李靖 authored
469 470 471
            // let cartInfo = this.data.cartInfo,
            //     numText;
            let numText;
陈峰 authored
472
李靖 authored
473 474 475 476 477 478
            if (selectSku.limitNum) {
                if (selectSku.limitNum) {
                    numText = `限购${selectSku.limitNum}件`;
                } else {
                    numText = '';
                }
陈峰 authored
479 480
            } else if (this.modes.soonSoldOut) {
                numText = '即将售罄';
481
            } else if (selectSku.storage < 4 && selectSku.storage > 0) {
陈峰 authored
482 483 484 485 486
                numText = `剩余${selectSku.storage}件`;
            } else {
                numText = '';
            }
            $chosePanel.find('.left-num').text(numText);
陈峰 authored
487
            $chosePanel.find('.size-info').text(selectSku.sizeInfo).removeClass('hide');
毕凯 authored
488
            $chosePanel.find('.size-rec').text(selectSku.sizeRec || '').removeClass('hide');
陈峰 authored
489
        } else {
490
            $chosePanel.find('.left-num').text('');
陈峰 authored
491
            $chosePanel.find('.size-info').text('').addClass('hide');
毕凯 authored
492
            $chosePanel.find('.size-rec').text('').addClass('hide');
陈峰 authored
493
        }
陈峰 authored
494
    }
陈峰 authored
495 496 497 498

    /**
     * 根据已选择的属性值获得符合条件的sku
     */
陈峰 authored
499
    _getSelectSku() {
陈峰 authored
500
        let selectValues,
陈峰 authored
501 502
            selectSku;
陈峰 authored
503
        if ($('.block.chosed').length !== this.props.length) {
陈峰 authored
504 505 506 507 508 509 510 511 512 513
            return;
        }
        selectValues = Array.from($('.block.chosed').map((index, ele) => {
            let $block = $(ele);

            return {
                propId: $block.data('prop-id'),
                valueId: $block.data('value-id')
            };
        }));
514
        selectSku = this.skus.filter(sku => {
陈峰 authored
515 516 517 518
            return selectValues
                .map(value => {
                    return sku.prop[value.propId].valId === value.valueId;
                })
陈峰 authored
519
                .filter(match => match).length === this.props.length;
陈峰 authored
520
        });
521 522 523 524
        if (selectSku.length >= 1) {
            return selectSku[0];
        }
        return;
陈峰 authored
525
    }
陈峰 authored
526 527
}
陈峰 authored
528
陈峰 authored
529
module.exports = new ChosePanel();