Authored by baoss

Merge branch 'feature/group-buy' of git.yoho.cn:fe/yohobuywap-node into feature/group-buy

... ... @@ -150,6 +150,10 @@ function goodsDetail(req, res, next) {
finalResult.activityGroupDetailList = result.activityGroupDetailList;
finalResult.activityIdDetail = result.activityIdDetail;
finalResult.shopInfo = result.shopInfo;
finalResult.support = result.support;
finalResult.floor = result.floor;
finalResult.storage_sum = result.storage_sum;
return res.render('group/goodsDetail', {
page: 'group-goodsDetail',
nodownload: true,
... ...
... ... @@ -216,7 +216,7 @@ class GroupApi extends global.yoho.BaseModel {
shop_id: data.shop_id,
};
this.get({data: param})
return this.get({data: param})
.then(res =>{
let shopList = res.data;
... ... @@ -225,15 +225,9 @@ class GroupApi extends global.yoho.BaseModel {
shopInfo.brand_ico = shopInfo.brand_ico.replace(/{width}/g, 120)
.replace(/{height}/g, 60).replace('{mode}', 2);
return {
shopInfo,
shopList
};
return shopInfo;
} else {
return {
shopInfo: {},
shopList: []
};
return null;
}
});
}
... ... @@ -270,6 +264,28 @@ class GroupApi extends global.yoho.BaseModel {
console.log(error);
});
}
getSupport(obj) {
let param = {
method: 'app.product.supportService',
product_skn: obj.productSkn,
coupon_limit_status: 0
};
return this.get({data: param})
.then(function(data) {
let free = [{
flag: 1,
title: '免邮',
desc: '免邮'
}];
return free.concat(data.data);
})
.catch(function(error) {
console.log(error);
});
}
}
module.exports = GroupApi;
... ...
... ... @@ -209,8 +209,13 @@ class GroupService extends global.yoho.BaseModel {
async goodsDetail(params) {
let result = await this.api.getProductData(params);
result.shopInfo = await this.api.getShopInfo({brand_id: result.brand_id, shop_id: result.shop_id});
result.activityIdDetail = await this.api.getCollageProductInfo(params);
result.activityGroupDetailList = await this.api.fetchActivityGroups(params);
result.support = await this.api.getSupport(params);
result.floor = await this.api._getResourceCode({
contentCode: '3c3a94fd6c6e19508b6921acd7f6cbad'
});
for (let item of result.activityGroupDetailList) {
item.formatLeftTime = this.formatDate(item.leftTime);
}
... ...
... ... @@ -43,136 +43,142 @@
{{/if}}
</div>
</div>
<div class="goods-join">
<div class="title">选择下面小伙伴,快速加入</div>
{{#each activityGroupDetailList}}
<div class="content">
<img class="avatar" src="{{image2 founderHeadUrl q=60 w=60 h=60}}"/>
<span class="nick-name">{{founderNickName}}</span>
<div class="middle">
<div class="top" >
<span class="text">还差</span>
<span class="text" style='color:red'>{{lackNum}}</span>
<span class="text">人成功</span>
{{#if activityGroupDetailList}}
<div class="goods-join">
<div class="title">选择下面小伙伴,快速加入</div>
{{#each activityGroupDetailList}}
<div class="content">
<img class="avatar" src="{{image2 founderHeadUrl q=60 w=60 h=60}}"/>
<span class="nick-name">{{founderNickName}}</span>
<div class="middle">
<div class="top">
<span class="text">还差</span>
<span class="text" style='color:red'>{{lackNum}}</span>
<span class="text">人成功</span>
</div>
<div class="text">剩余<span class="left-time"
data-value="{{leftTime}}">{{formatLeftTime}}</span></div>
</div>
<div class="text">剩余<span class="left-time" data-value="{{leftTime}}">{{formatLeftTime}}</span></div>
</div>
<div class='ibutton'>
立即参团
<div class='ibutton'>
立即参团
</div>
</div>
</div>
{{/each}}
</div>
{{#if periodOfMarket}}
<div class="period-of-market">
<h1>上市期:</h1>
<h1 >{{periodOfMarket}}</h1>
{{/each}}
</div>
{{/if}}
<div class="price-date data-bind">
<div class="student-price">
<i class="student-name">学生价</i><span class="student-value"></span>
{{#if shopInfo}}
<div class="shop-info" data-id="{{shopInfo.shop_id}}">
<img class="shop-icon" src="{{shopInfo.brand_ico}}"/>
<span class="shop-name">{{shopInfo.brand_name}}</span>
<span class="shop-detail">进入店铺</span>
</div>
</div>
{{!-- {{#if studentCoinNum}}
<div class="price-date">
<div class="student-price">
<i class="student-name">返</i> 学生返币{{ studentCoinNum}}个
</div>
</div>
{{else}}
{{#commodityReturn}}
<div class="price-date">
<div class="student-price">
<i class="student-name">返</i> 返{{studentCoinNum}}个YOHO币
</div>
</div>
{{/commodityReturn}}
{{/if}} --}}
<ul class="vip-level data-bind clearfix">
<li class="icons-item">
<span class="vip-img">
</span>
<span class="vip-price"></span>
</li>
</ul>
{{/if}}
{{! 品牌优惠券}}
<div class="brand-coupon hide">
<i class="iconfont font-right pull-right">&#xe614;</i>
<i class="iconfont font-quan">&#xe902;</i><span>领取优惠券</span>
<div class="rule-detail" bindtap="detailsRegularTap">
<span class="cell-name-text">拼团规则说明</span>
<img src="//img10.static.yhbimg.com/yhb-img01/2019/02/20/14/0141f133c49d96725870ce82328fd2c143.png" class="m-icon"/>
</div>
<div class="goods-discount data-bind" id="goodsDiscount">
<h1 class="first-item short-text tap-hightlight"><span class="icon-down iconfont dropdown">&#xe609;</span></h1>
<div class="discount-folder">
<h1 class="folder-item tap-hightlight"></h1>
<div class="rule-detail-cell">
<div class="tree">
<img src='//img11.static.yhbimg.com/yhb-img01/2019/02/20/14/01f2ab50d7c23882f75a1ff7b790418593.png'/>
</div>
<div class="tree-tip-view">
<span class="tree-tip">{{activityIdDetail.activityDescription}}</span>
</div>
</div>
{{# feedbacks}}
<div class="feedback-list ">
{{#if commentsNum}}
{{> detail/feedback-tab}}
{{else}}
{{#if consultsNum}}
{{> detail/feedback-tab}}
{{else}}
<div class="nodata tap-hightlight" id="goto-consult">
<span>暂无商品评价和咨询</span>
<a href="{{consultsUrl}}" class="go-consult">我要咨询<span class="iconfont">&#xe604;</span></a>
</div>
{{/if}}
{{#if support}}
<div class="support-service">
{{#each support}}
<div class="support-service-item">
{{#if flag}}
<img src="//img11.static.yhbimg.com/yhb-img01/2019/02/20/15/010f1dcec3c258c0b302e082397f3f8488.png" class="support-service-image"/>
{{else}}
<img src="//img11.static.yhbimg.com/yhb-img01/2019/02/20/15/01f4a1c2bd1eed2bdf32ddbcfdee9acfd9.png" class="support-service-image"/>
{{/if}}
<span class="support-service-title">{{title}}</span>
</div>
{{/ feedbacks}}
{{# enterStore}}
<div id="enter-store" class="enter-store page-block tap-hightlight">
<a class="store-logo" href="{{url}}" style="">
<img class="lazy" data-original="{{image2 img w=47 h=47 q=60}}" alt="{{storeName}}">
</a>
<a class="store-name" href="{{url}}">{{storeName}}</a>
<a class="store-link" href="{{url}}">进入店铺<span class="iconfont">&#xe604;</span></a>
</div>
{{/ enterStore}}
{{# bundleData}}
{{> detail/bundle}}
{{/ bundleData}}
{{# discountBuy}}
<input type="hidden" id="discount-buy" value="{{num}}">
<input type="hidden" id="promotion-phrase" value="{{promotionPhrase}}">
{{/ discountBuy}}
{{/each}}
</div>
{{/if}}
<div class="floors">
{{#each floor}}
{{#ifcond template_name "==" 'focus'}}
{{> group/resources/focus}}
{{/ifcond}}
{{#ifcond template_name "==" 'newSingleImage'}}
{{> group/resources/new-single-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'twoPicture'}}
{{> group/resources/two-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'image_list'}}
{{> group/resources/four-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'splitJointImg'}}
{{> group/resources/split-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'collageBuyPrdList'}}
{{> group/resources/collage-buy-prd-list}}
{{/ifcond}}
{{/each}}
</div>
<div id="productDesc" {{#if limit}}class="limit"{{/if}}> </div>
{{> detail/recommend-for-you}}
<div class="chose-panel"></div>
<div class="cart-bar data-bind">
{{#unless @root.wap.common.removeCartCount}}
<input type="hidden" id="remove-cart-count" value="1">
{{/unless}}
<a href="" class="num-incart iconfont"><span class="num-tag hide"></span>&#xe62c;</a>
<a id="addtoCart" href="javascript:;" class="addto-cart add-to-cart-url data-bind"></a>
<a id="soldOut" href="javascript:;" class="sold-out data-bind">已售罄</a>
<a id="notForSale" href="javascript:;" class="sold-out data-bind">非卖品</a>
<a id="limitNotForSale" href="javascript:;" class="sold-out limit data-bind">即将发售</a>
<a id="preSale" href="javascript:;" class="sold-out limit data-bind">即将开售</a>
<a href="javascript:;" id="addtoCart" class="addto-cart can-buy-limit data-bind">立即购买</a>
<a id="noLimitCode" href="javascript:;" class="sold-out limit data-bind">立即购买</a>
<input type="hidden" id="limitCodeUrl" name="limitCodeUrl" value="">
<input type="hidden" id="limitProductPay" name="limitProductPay" value="">
<input type="hidden" id="limitProductCode" class="data-bind" name="limitProductCode" value="">
<div class="bottom">
<div class="count-down">
{{#if storage_sum}}
<div data-current="{{activityIdDetail.currentTime}}"
data-begin="{{activityIdDetail.beginTime}}"
data-end="{{activityIdDetail.endTime}}"
class="comp-count-dow-by-now">
<span id="label"></span>
<span class="number" id="days"></span>
<span class="number" id="hours"></span>
<span class="number" id="minutes"></span>
<span class="number" id="seconds"></span>
</div>
{{/if}}
</div>
<div class='shoppint-cart-icon'>
<img src="//img10.static.yhbimg.com/yhb-img01/2019/02/21/01/016b3f1cbc1b946fa0acbb1523f6386435.png"
class="shoppint-cart-icon-image"/>
</div>
{{#if isShowPop}}
<div class='old-customer-tips'>
<img style='width:100%;height:100%' src='/static/images/group/PT_tip@3x.png'/>
</div>
{{/if}}
{{#if storage_sum }}
<button class='shoppint-cart-add'
bindtap="selfBuy" style='border-radius: 0;'>
{{#if groupNo}}
<span class="bottom-title">{{activityIdDetail.formatCollagePrice}}</span>
<span class="bottom-title">自己开团</span>
{{else}}
<span class="bottom-title">{{realPrice}}</span>
<span class="bottom-title">单人购买</span>
{{/if}}
</button>
<a href="javascript:;" id="likeBtn" class="favorite iconfont ">&#xe605;</a>
<button class="buynow join-group-btn"
bindtap="buyAction">
<span class="bottom-title">{{activityIdDetail.formatCollagePrice}}</span>
{{#if groupNo}}
<span class="bottom-title">确认参团{{#if activityIdDetail.joinLimit '==1'}},仅限新人{{/if}}</span>
{{else}}
<div class="bottom-title">{{activityIdDetail.peopleNum}}人成团</div>
{{/if}}
</button>
{{else}}
<div class='soldOut disable'>
<span class="bottom-title mainText">已售罄</span>
<span class="bottom-title subText">还有机会</span>
</div>
{{/if}}
</div>
{{#if introUrl}}
<input id="introUrl" type="hidden" value="{{introUrl}}">
{{/if}}
... ...
... ... @@ -26,8 +26,7 @@
<span class="name">颜色</span>
<ul class="size-row clearfix">
{{#each goodsList}}
<li class="block{{#if chosed}} chosed{{/if}}" data-prop-id="{{../type}}"
data-value-id="{{id}}">{{color_name}}</li>
<li class="block{{#if chosed}} chosed{{/if}}" data-goods-id="{{goods_id}}">{{factory_goods_name}}</li>
{{/each}}
</ul>
</div>
... ... @@ -35,8 +34,7 @@
<span class="name">尺码</span>
<ul class="size-row clearfix">
{{#each sizeList}}
<li class="block{{#if chosed}} chosed{{/if}}" data-prop-id="{{../type}}"
data-value-id="{{id}}">{{size_name}}</li>
<li class="block{{#if chosed}} chosed{{/if}}" data-sku="{{product_sku}}">{{size_name}}</li>
{{/each}}
</ul>
</div>
... ...
... ... @@ -24,6 +24,28 @@ function hiddenTips($ele) {
}
}
function add0(m) {
return m < 10 ? '0' + m : m;
}
function formatDate(shijianchuo) {
// 秒数
let second = Math.floor(shijianchuo);
// 小时位
let hr = Math.floor(second / 3600);
// 分钟位
let min = Math.floor((second - hr * 3600) / 60);
// 秒位
let sec = (second - hr * 3600 - min * 60);
return add0(hr) + ':' + add0(min) + ':' + add0(sec);
}
let timer;
class Detail extends Page {
constructor() {
super();
... ... @@ -36,6 +58,7 @@ class Detail extends Page {
this.getIntro();
this.goSwiper();
this.toTop();
this.startTimer();
}
getIntro() {
... ... @@ -145,6 +168,29 @@ class Detail extends Page {
}
});
}
startTimer() {
let list = [];
let activityGroupDetailList = document.querySelectorAll('.left-time');
for (let item of activityGroupDetailList) {
list.push(item.getAttribute('data-value'));
}
timer = setInterval(function() {
for (let i = 0; i < activityGroupDetailList.length; i++) {
list[i] = Number(list[i]) - 1;
if (list[i]) {
activityGroupDetailList[i].innerText = formatDate(list[i]);
} else {
clearInterval(timer);
window.reload();
}
}
}, 1000);
}
stopTimer() {
clearInterval(timer);
}
}
$(() => {
new Detail();
... ...
... ... @@ -62,28 +62,6 @@ class ChosePanel {
$('.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;
... ... @@ -95,33 +73,43 @@ class ChosePanel {
}
this._setVariable();
this._initBlockStatus();
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;
}
/**
* 初始化属性按钮状态不满足库存的灰色
*/
_initBlockStatus() {
// 获取sku列表中库存小于最小购买数量的属性,如果在其他sku中它们没有满足购买数量条件的可以灰色
let noStorageSkus = this.skus.filter(sku => sku.storage < this.minBuyNum);
$chosePanel.find('.thumb').attr('src', this.data.cartInfo.defaultThumb);
$('.block').removeClass('zero-stock');
noStorageSkus.forEach(sku => {
for (let propType in sku.prop) {
if (propType) {
let prop = sku.prop[propType];
let zeroStock = !this.skus.some(_ => _.prop[propType].valId === prop.valId &&
_.storage >= this.minBuyNum);
let $block = $(`.block[data-prop-id="${propType}"][data-value-id="${prop.valId}"]`);
if (zeroStock) {
$block.addClass('zero-stock');
} else {
$block.removeClass('zero-stock');
}
}
}
});
}
_setVariable() {
$chosePanel = $('.chose-panel');
$choseArea = $('.chose-panel .main .chose-items');
... ... @@ -150,21 +138,6 @@ class ChosePanel {
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);
});
}
... ... @@ -232,23 +205,29 @@ class ChosePanel {
}
/**
* 点击确定或者立即购买按钮
* 点击确定
*/
_choseBtnSureClick(e, buyNow) {
let selectSku = this._checkSku(this.buyNum);
_choseBtnSureClick() {
// let selectSku = this._checkSku(this.buyNum);
//
// if (selectSku) {
// this.close();
// this._resolve && this._resolve({
// sku: selectSku,
// buyNum: this.buyNum,
// buyNow: buyNow
// });
// return false;
// }
// todo mock
this.close();
this._resolve && this._resolve({
sku: {skuId: 693031},
buyNum: 1,
buyNow: true
});
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;
}
}
/**
... ... @@ -274,21 +253,6 @@ class ChosePanel {
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;
... ... @@ -339,29 +303,8 @@ class ChosePanel {
});
});
}
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();
// this._refreshBlockStatus();
}
/**
... ...
... ... @@ -85,4 +85,246 @@
}
}
}
.shop-info {
height: 120px;
background-color: #fff;
margin-top: 14px;
.shop-icon {
height: 80px;
width: 150px;
margin-top: 20px;
margin-left: 30px;
display: inline-block;
}
.shop-name {
display: inline-block;
font-family: SanFranciscoText-Regular, sans-serif;
font-size: 32px;
color: #4a4a4a;
letter-spacing: 0;
line-height: 120px;
vertical-align: top;
margin-left: 18px;
}
.shop-detail {
float: right;
margin-top: 30px;
margin-right: 40px;
display: inline-block;
height: 60px;
border-radius: 60px;
border: 1px solid #4a4a4a;
font-family: PingFang-SC-Medium, sans-serif;
font-size: 26px;
color: #444;
letter-spacing: 0;
font-weight: 500;
padding: 0 28px;
line-height: 57px;
box-sizing: border-box;
}
}
.rule-detail {
width: 100%;
height: 76px;
align-items: center;
display: flex;
justify-content: space-between;
background-color: white;
margin-top: 14px;
.cell-name-text {
width: 50%;
color: #444;
font-size: 28px;
margin-left: 30px;
text-align: left;
}
.m-icon {
width: 15px;
height: 26px;
margin-right: 30px;
display: inline-block;
overflow: hidden;
}
}
.rule-detail-cell {
background-color: white;
width: 100%;
height: 250px;
align-items: center;
display: flex;
flex-direction: column;
border-top: 1px solid #e0e0e0;
.tree {
width: 100%;
height: 170px;
align-items: center;
justify-content: center;
display: flex;
flex-direction: row;
img {
width: 520px;
}
}
.tree-tip-view {
width: 100%;
height: 80px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
color: #b0b0b0;
font-size: 20px;
}
}
.support-service {
background: #fff;
margin-top: 14px;
margin-bottom: 14px;
flex-direction: row;
display: flex;
padding: 20px;
}
.support-service-item {
display: flex;
align-items: center;
flex-direction: row;
padding-left: 15px;
}
.support-service-image {
width: 30px;
height: 30px;
display: inline-block;
overflow: hidden;
}
.support-service-title {
color: #444;
font-size: 26px;
padding-left: 5px;
}
.floors {
margin-bottom: 14px;
}
.bottom {
display: flex;
position: fixed;
flex-direction: row;
width: 100%;
height: 100px;
bottom: 0;
background-color: #fff;
border-top: 1px solid rgb(242, 242, 242);
z-index: 1000;
.count-down {
position: absolute;
top: -88px;
left: 0;
right: 0;
height: 88px;
.comp-count-dow-by-now {
height: 88px;
line-height: 88px;
color: #fff;
font-size: 24px;
text-align: center;
background-color: rgba(34, 34, 34, 0.8);
}
.number {
display: inline-block;
font-size: 40px;
vertical-align: bottom;
}
}
.shoppint-cart-icon {
position: relative;
width: 160px;
background-color: #fff;
vertical-align: center;
justify-content: center;
text-align: center;
}
.shoppint-cart-icon-image {
display: inline;
position: absolute;
width: 50px;
height: 50px;
align-items: center;
z-index: 10;
margin-top: 30px;
margin-left: -30px;
}
.badge {
position: absolute;
right: 15px;
width: 15px;
height: 15px;
line-height: 15px;
background: #f00;
color: #fff;
border-radius: 50%;
text-align: center;
font-size: 8px;
margin-top: 15px;
}
.shoppint-cart-add {
flex: 1;
border-radius: 0;
background-color: #444;
vertical-align: center;
justify-content: center;
flex-direction: column;
display: flex;
text-align: center;
}
.bottom-title {
display: flex;
color: white;
font-size: 30px;
width: 100%;
text-align: center;
align-items: center;
justify-content: center;
border-radius: 0;
}
.join-group-btn {
background-color: #d0021b;
border-radius: 0;
}
.buynow {
flex: 1;
vertical-align: center;
justify-content: center;
background-color: #d0021b;
flex-direction: column;
display: flex;
text-align: center;
}
}
}
... ...