Authored by 毕凯

Merge branch 'feature/activity' into 'release/6.2'

Feature/activity



See merge request !980
... ... @@ -41,3 +41,18 @@ exports.sidebar = function(req, res, next) {
});
}).catch(next);
};
exports.bottombar = function(req, res, next) {
model.index({
code: req.params.code
}).then((result) => {
if (!result) {
return next();
}
res.render('feature/bottombar', {
content: result,
layout: false
});
}).catch(next);
};
... ...
... ... @@ -33,6 +33,25 @@ const _getProductBySkns = function(productObj) {
});
};
/**
* 获取店铺组店铺数据
*/
const _getShopGroup = (shopRawData) => {
return api.get('', {
method: 'app.shops.batchGetShops',
shop_ids: shopRawData.defaultShopIds,
order: 'pools_id_asc' // pools_id_desc
}).then(result => {
let renderData = _.get(result, 'data', []);
_.forEach(renderData, shop => {
shop.href = `//m.yohobuy.com/product/shop?domain=${shop.shop_domain}&openby:yohobuy={"action":"go.shop","params":{"shop_id":${shop.shops_id},"shop_template_type":${shop.shop_template_type},"is_red_shop":${shop.is_red_shop}}}`; // eslint-disable-line
});
shopRawData.renderData = renderData;
});
};
module.exports = {
index: function(params) {
return Promise.coroutine(function*() {
... ... @@ -42,6 +61,7 @@ module.exports = {
let data,
sknsArr = [];
let shopGroups = [];
if (params.type === 'preview') { // 开发/预览模式
data = yield api.get('', {
... ... @@ -65,6 +85,8 @@ module.exports = {
if (f.component && f.component[0] &&
f.component[0].type === 'productGroup' && f.component[0].defaultSkns) {
sknsArr.push(_getProductBySkns(f.component[0]));
f.component[0].newStyle = _.get(f, 'component[0].newStyle') === '1';
}
if (f.component && f.component[0] &&
... ... @@ -73,6 +95,17 @@ module.exports = {
maybeLike: '1',
limit: '60'
}, f.component[0].searchCondition || {});
f.component[0].newStyle = _.get(f, 'component[0].newStyle') === '1';
}
// 新增店铺组
if (_.get(f, 'component[0].type') === 'shopGroup') {
shopGroups.push(_getShopGroup(f.component[0]));
}
if (_.get(f, 'type') === 'bottombar') {
f.size = _.size(f.component);
}
_.forEach(f.component, function(component) {
... ... @@ -87,6 +120,10 @@ module.exports = {
yield Promise.all(sknsArr);
}
if (shopGroups.length) {
yield Promise.all(shopGroups);
}
return data;
})();
}
... ...
... ... @@ -10,6 +10,7 @@ let _getProduct = function(o) {
brand_id: o.brand_id,
shop_id: o.shop_id,
shop_template_type: o.shop_template_type,
is_red_shop: o.is_red_shop,
brand_domain: o.brand_domain,
brand_name: o.brand_name,
product_id: o.product_id,
... ...
... ... @@ -102,9 +102,24 @@ const shopFav = (uid, shopIds) => {
});
};
/**
* 根据店铺ID调获取店铺数据
* 图片字段:pic_popular
order 传 pools_id_asc 或者 pools_id_desc
* @param {*} params
*/
const batchGetShops = (params) => {
return api.get('', {
method: 'app.shops.batchGetShops',
shop_ids: params.shop_ids,
order: params.order
});
};
module.exports = {
shopList,
shopNav,
banner,
shopFav
shopFav,
batchGetShops
};
... ...
... ... @@ -252,6 +252,7 @@ router.get('/individuation/coupon', individuation.coupon);
// 活动页模版
router.get('/feature/:code.html', feature.index);
router.get('/featuresidebar/:code.html', feature.sidebar);
router.get('/featurebottombar/:code.html', feature.bottombar);
// 2016 年度账单
router.get('/annual-account', annualAccount.index);
... ...
<div class="bottom-bar">
<div class="bottom-bar-content">
{{#content.floors}}
{{#isEqualOr type '' 'common_floor'}}
<div class="bottom-bar-item">
{{#if param.bgimg}}<img src="{{image2 param.bgimg q=60}}">{{/if}}
{{#component}}
{{#isEqualOr type 'link'}}
{{#isEqualOr url 'closesidebar'}}
<a class="anchor closesidebar" style="{{styleFormat this percent=1}}" href="javascript:void(0);"></a>
{{else}}
<a class="anchor" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}"></a>
{{/isEqualOr}}
{{/isEqualOr}}
{{/component}}
</div>
{{/isEqualOr}}
{{/content.floors}}
</div>
</div>
\ No newline at end of file
... ...
... ... @@ -86,92 +86,25 @@
</div>
{{/isEqualOr}}
{{#isEqualOr type 'shopGroup'}}
{{!-- 店铺组 --}}
{{> feature/shop-group}}
{{/isEqualOr}}
{{#isEqualOr type 'productGroup'}}
{{! 商品池}}
<div class="product-container item{{numOfOneRow}}" {{#if proBgImg}}style="background:url({{image2 proBgImg q=95}}) repeat;background-size:100%;"{{/if}}>
<div class="product-source" condition='{{stringify searchCondition}}' fp="{{getAnalysis ../this @index}}"
{{#unless defaultPros.length}}
{{#if searchCondition.item}}
cloneitem="{{searchCondition.item}}"
{{else}}
cloneitem="{{searchCondition.limit}}"
{{/if}}
{{/unless}}>
<input class="imgwh" type="hidden" value="386x514">
{{#if defaultPros.length}}
{{#defaultPros}}
<div class="feature-product-info {{#if ../searchCondition}}novisible{{/if}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
{{#if ../lefTopImg}}<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=95}}">{{/if}}
{{#if ../rigTopImg}}<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=95}}">{{/if}}
<img class="product-detail-img lazy" data-original="{{image2 productimg q=95}}">
</div>
{{#isEqualOr ../showPrdName '1'}}<p class="product-name">{{productname}}</p>{{/isEqualOr}}
<div class="product-detail-text">
{{#isEqualOr ../showSalePrice '1'}}
<div class="price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}">
<span class="sale-price"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}<span class="market-price">¥{{marketprice}}</span>{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr ../showVipPrice '1'}}
<div class="vipprice"style="{{#if ../vipFontColor}}color:{{../vipFontColor}};{{/if}}{{#if ../vipBgColor}}background:{{../vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
</a>
{{#if ../brandImg}}
<a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
<div class="brand-div">
<span class="brand-name"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>{{brandname}}</span>
</div>
<img class="brand-img" src="{{image2 ../brandImg q=95}}">
</a>
{{/if}}
</div>
{{/defaultPros}}
{{else}}
<div class="feature-product-info novisible">
<a class="first-part product-detail" href=''>
<div class="product-detail-imgbox">
{{#if lefTopImg}}<img class="leftopimg" src="{{image2 lefTopImg q=95}}">{{/if}}
{{#if rigTopImg}}<img class="rigtopimg" src="{{image2 rigTopImg q=95}}">{{/if}}
<img class="product-detail-img" src="">
</div>
{{#isEqualOr showPrdName '1'}}<p class="product-name"></p>{{/isEqualOr}}
<div class="product-detail-text">
{{#isEqualOr showSalePrice '1'}}
<div class="price" style="{{#if salePriceBgColor}}background:{{salePriceBgColor}};{{/if}}">
<span class="sale-price"{{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>
<span class="market-price"></span>
</div>
{{/isEqualOr}}
{{#isEqualOr showVipPrice '1'}}
<div class="vipprice" style="{{#if vipFontColor}}color:{{vipFontColor}};{{/if}}{{#if vipBgColor}}background:{{vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span><span class="vip-price-val"></span>
</div>
{{/isEqualOr}}
</div>
</a>
{{#if brandImg}}
<a class="second-part {{#isEqualOr showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href=''>
<div class="brand-div">
<span class="brand-name" {{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>
</div>
<img class="brand-img" src="{{image2 brandImg q=95}}">
</a>
{{/if}}
</div>
{{/if}}
</div>
</div>
{{#if newStyle}}
{{> feature/product-new-style}}
{{^}}
{{> feature/product-old-style}}
{{/if}}
{{/isEqualOr}}
{{/component}}
</div>
{{/isEqualOr}}
{{#isEqualOr type 'bottombar'}}
{{> feature/bottom-fix}}
{{/isEqualOr}}
{{/content.floors}}
{{/unless}}
</div>
... ...
<div class="bottom-fix" data-size="{{size}}">
{{#if param.bgimg}}
{{#isLazyLoad type @index}}
<img class="lazy" data-original="{{image2 param.bgimg q=95}}">
{{else}}
<img src="{{image2 param.bgimg q=95}}">
{{/isLazyLoad}}
{{/if}}
<div class="show-area" id="bottomShowArea">
{{#component}}
<div class="per-show hide" style="width: {{width}}%;left:{{left}}%" id="bottomShow{{url}}">
</div>
{{/component}}
</div>
<div class="click-area" id="bottomFixClickArea">
{{#component}}
<div class="per-click" style="width: {{width}}%;height:{{height}}%" data-url="{{url}}" id="bottomClick{{url}}">
</div>
{{/component}}
</div>
</div>
... ...
<div class="product-container item{{numOfOneRow}}" {{#if proBgImg}} style="background:url({{image2 proBgImg q=95}}) repeat;background-size:100%;"
{{/if}}>
<div class="product-source" condition='{{stringify searchCondition}}' fp="{{getAnalysis ../this @index}}" {{#unless defaultPros.length}}
{{#if searchCondition.item}} cloneitem="{{searchCondition.item}}" {{else}} cloneitem="{{searchCondition.limit}}" {{/if}}
{{/unless}}>
<input class="imgwh" type="hidden" value="386x514">
{{#if defaultPros.length}}
{{#defaultPros}}
<div class="feature-product-info {{#if ../searchCondition}}novisible{{/if}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
{{#if ../lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=95}}">
{{/if}}
{{#if ../rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=95}}">
{{/if}}
<img class="product-detail-img product-detail-img-new lazy" data-original="{{image2 productimg q=95}}">
</div>
<div class="new-brand-name">
<span class="brand-name" {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>{{brandname}}</span>
</div>
</a>
{{#if ../brandImg}}
<a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
<div class="new-brand-div">
{{#isEqualOr ../showSalePrice '1'}}
<div class="new-price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}">
<span class="sale-price" {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price">¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr ../showVipPrice '1'}}
<div class="vipprice" style="{{#if ../vipFontColor}}color:{{../vipFontColor}};{{/if}}{{#if ../vipBgColor}}background:{{../vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
<img class="brand-img" src="{{image2 ../brandImg q=95}}">
</a>
{{/if}}
</div>
{{/defaultPros}}
{{else}}
<div class="feature-product-info novisible">
<a class="first-part product-detail" href=''>
<div class="product-detail-imgbox">
{{#if lefTopImg}}
<img class="leftopimg" src="{{image2 lefTopImg q=95}}">
{{/if}}
{{#if rigTopImg}}
<img class="rigtopimg" src="{{image2 rigTopImg q=95}}">
{{/if}}
<img class="product-detail-img product-detail-img-new" src="">
<div class="new-brand-name">
<span class="brand-name" {{#if fontColor}} style="color:{{fontColor}};" {{/if}}></span>
</div>
</div>
</a>
{{#if brandImg}}
<a class="second-part {{#isEqualOr showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href=''>
<div class="new-brand-div">
{{#isEqualOr showSalePrice '1'}}
<div class="new-price" style="{{#if salePriceBgColor}}background:{{salePriceBgColor}};{{/if}}">
<span class="sale-price" {{#if fontColor}} style="color:{{fontColor}};" {{/if}}></span>
<span class="market-price"></span>
</div>
{{/isEqualOr}}
{{#isEqualOr showVipPrice '1'}}
<div class="vipprice" style="{{#if vipFontColor}}color:{{vipFontColor}};{{/if}}{{#if vipBgColor}}background:{{vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val"></span>
</div>
{{/isEqualOr}}
</div>
<img class="brand-img" src="{{image2 brandImg q=95}}">
</a>
{{/if}}
</div>
{{/if}}
</div>
</div>
\ No newline at end of file
... ...
<div class="product-container item{{numOfOneRow}}" {{#if proBgImg}} style="background:url({{image2 proBgImg q=95}}) repeat;background-size:100%;"
{{/if}}>
<div class="product-source" condition='{{stringify searchCondition}}' fp="{{getAnalysis ../this @index}}" {{#unless defaultPros.length}}
{{#if searchCondition.item}} cloneitem="{{searchCondition.item}}" {{else}} cloneitem="{{searchCondition.limit}}" {{/if}}
{{/unless}}>
<input class="imgwh" type="hidden" value="386x514">
{{#if defaultPros.length}}
{{#defaultPros}}
<div class="feature-product-info {{#if ../searchCondition}}novisible{{/if}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
{{#if ../lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=95}}">
{{/if}}
{{#if ../rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=95}}">
{{/if}}
<img class="product-detail-img lazy" data-original="{{image2 productimg q=95}}">
</div>
{{#isEqualOr ../showPrdName '1'}}
<p class="product-name">{{productname}}</p>
{{/isEqualOr}}
<div class="product-detail-text">
{{#isEqualOr ../showSalePrice '1'}}
<div class="price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}">
<span class="sale-price" {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price">¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr ../showVipPrice '1'}}
<div class="vipprice" style="{{#if ../vipFontColor}}color:{{../vipFontColor}};{{/if}}{{#if ../vipBgColor}}background:{{../vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
</a>
{{#if ../brandImg}}
<a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
<div class="brand-div">
<span class="brand-name" {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>{{brandname}}</span>
</div>
<img class="brand-img" src="{{image2 ../brandImg q=95}}">
</a>
{{/if}}
</div>
{{/defaultPros}}
{{else}}
<div class="feature-product-info novisible">
<a class="first-part product-detail" href=''>
<div class="product-detail-imgbox">
{{#if lefTopImg}}
<img class="leftopimg" src="{{image2 lefTopImg q=95}}">
{{/if}}
{{#if rigTopImg}}
<img class="rigtopimg" src="{{image2 rigTopImg q=95}}">
{{/if}}
<img class="product-detail-img" src="">
</div>
{{#isEqualOr showPrdName '1'}}
<p class="product-name"></p>
{{/isEqualOr}}
<div class="product-detail-text">
{{#isEqualOr showSalePrice '1'}}
<div class="price" style="{{#if salePriceBgColor}}background:{{salePriceBgColor}};{{/if}}">
<span class="sale-price" {{#if fontColor}} style="color:{{fontColor}};" {{/if}}></span>
<span class="market-price"></span>
</div>
{{/isEqualOr}}
{{#isEqualOr showVipPrice '1'}}
<div class="vipprice" style="{{#if vipFontColor}}color:{{vipFontColor}};{{/if}}{{#if vipBgColor}}background:{{vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val"></span>
</div>
{{/isEqualOr}}
</div>
</a>
{{#if brandImg}}
<a class="second-part {{#isEqualOr showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href=''>
<div class="brand-div">
<span class="brand-name" {{#if fontColor}} style="color:{{fontColor}};" {{/if}}></span>
</div>
<img class="brand-img" src="{{image2 brandImg q=95}}">
</a>
{{/if}}
</div>
{{/if}}
</div>
</div>
\ No newline at end of file
... ...
<div class="shop-container{{#isEqualOr numOfOneRow '2'}} shop-two{{^}} shop-three{{/isEqualOr}}">
{{#renderData}}
{{#isEqualOr ../numOfOneRow '2'}}
<div class="pull-left shop-box">
<div class="shop-img">
<img class="left-icon" src="{{image2 ../lefTopImg q=95}}" alt="">
<img src="{{image2 pic_popular w=187 h=275 q=95}}" alt="">
</div>
<a{{#isEqualOr ../jump2Shop '1'}} href="{{href}}"{{/isEqualOr}} class="shop-bottom-bar" style="background-image: url({{image2 ../brandImg w=290 h=60 q=95}})">
<span class="shop-name">{{shop_name}}</span>
</a>
</div>
{{^}}
<div class="pull-left shop-box">
<div class="shop-img">
<img class="left-icon" src="{{image2 ../lefTopImg q=95}}" alt="">
<img src="{{image2 pic_popular w=187 h=275 q=95}}" alt="">
</div>
<a{{#isEqualOr ../jump2Shop '1'}} href="{{href}}"{{/isEqualOr}} class="shop-bottom-bar" style="background-image: url({{image2 ../brandImg w=290 h=60 q=95}});">
<span class="shop-name">{{shop_name}}</span>
</a>
</div>
{{/isEqualOr}}
{{/renderData}}
</div>
\ No newline at end of file
... ...
... ... @@ -104,7 +104,7 @@ module.exports = {
maxQps: 1200,
maxQps10m: 2500,
geetestJs: '//static.geetest.com/static/tools/gt.js',
jsSdk: '//cdn.yoho.cn/js-sdk/1.2.2/jssdk.js',
jsSdk: '//cdn.yoho.cn/js-sdk/1.2.3/jssdk.js',
redis: {
connect: {
host: '127.0.0.1',
... ...
... ... @@ -49,6 +49,12 @@ function topNavInit() {
if (top > top1) {
cloneNav.fadeIn('slow');
$('.fixnav').each((index, elem) => {
let $elem = $(elem);
$(elem).css('top', $elem.prev().height());
});
} else {
cloneNav.fadeOut('slow');
}
... ... @@ -64,7 +70,9 @@ function ceXuanFuInit() {
return;
}
$('#sidebar').load('//activity.yoho.cn/featuresidebar/' + pageid + '.html', function() {
// //m.yohobuy.com/activity/featuresidebar/
// //activity.yoho.cn/featuresidebar/
$('#sidebar').load('//m.yohobuy.com/activity/featuresidebar/' + pageid + '.html', function() {
$('.sidebar-img').click(function() {
$('.sidebar').show();
});
... ... @@ -82,6 +90,30 @@ function ceXuanFuInit() {
});
}
function diXuanFuInit() {
let $bottomFixClickArea = $('#bottomFixClickArea');
let $bottomPerShow = $('.per-show');
$bottomPerShow.css('bottom', $bottomFixClickArea.height());
$bottomFixClickArea.children().each((index, elem) => {
let pageId = $(elem).data('url');
let $bottomShow = $('#bottomShow' + pageId);
$bottomShow.load('//m.yohobuy.com/activity/featurebottombar/' + pageId + '.html');
$('#bottomClick' + pageId).on('click', () => {
if ($bottomShow.hasClass('hide')) {
$bottomShow.removeClass('hide');
} else {
$bottomShow.addClass('hide');
}
});
});
$('.floor').last().css('margin-bottom', $bottomFixClickArea.height());
}
function videoInit() {
function cancelMove(e) {
e.preventDefault && e.preventDefault();
... ... @@ -242,6 +274,9 @@ $(function() {
// 侧悬浮
ceXuanFuInit();
// 底悬浮
diXuanFuInit();
// 视频相关
videoInit();
... ...
... ... @@ -3,3 +3,5 @@
@import "feature/anchor";
@import "feature/product";
@import "feature/swiper.min";
@import "feature/shop";
@import "feature/bottom";
... ...
.bottom-fix {
position: fixed;
left: 0;
bottom: 0;
z-index: 1;
width: 100%;
img {
display: block;
width: 100%;
height: 100%;
}
.show-area {
position: absolute;
width: 100%;
.per-show {
position: fixed;
}
.hide {
display: none;
}
}
.click-area {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
.per-click {
float: left;
}
}
}
... ...
.product-container {
overflow: hidden;
padding: 0 20px 10px;
... ... @@ -25,6 +23,10 @@
height: 257px;
}
.product-detail-imgbox .product-detail-img-new {
height: 243px;
}
.price,
.vipprice {
line-height: 34px;
... ... @@ -41,6 +43,22 @@
line-height: 23px;
font-size: 18px;
}
.new-price {
> .sale-price {
margin-left: 6px;
font-size: 24px;
font-weight: 700;
color: #fff;
}
> .market-price {
margin-left: 6px;
font-size: 18px;
font-weight: 400;
color: #fff;
}
}
}
.product-source {
... ... @@ -159,12 +177,32 @@
.brand-div {
position: absolute;
top: 8px;
top: -4px;
left: 50%;
width: 100%;
transform: translateX(-50%);
}
.new-brand-div {
position: absolute;
top: -4px;
left: 50%;
width: 100%;
transform: translateX(-50%);
}
.brand-img {
display: block;
margin: 0 auto;
}
}
.new-brand-name {
position: absolute;
bottom: 10px;
left: 0;
right: 0;
.brand-name {
display: -webkit-box;
-webkit-box-orient: vertical;
... ... @@ -173,11 +211,29 @@
line-height: 30px;
overflow: hidden;
font-size: 26px;
color: #444;
}
}
.new-price {
margin-left: 5px;
height: 40px;
line-height: 40px;
color: #fff;
white-space: nowrap;
> .sale-price {
margin-left: 10px;
font-size: 32px;
font-weight: 700;
color: #fff;
}
.brand-img {
display: block;
margin: 0 auto;
> .market-price {
margin-left: 10px;
font-size: 18px;
font-weight: 400;
color: #fff;
}
}
}
... ...
$margin-top: 42px;
$margin-left-2: 20px;
$margin-left-3: 19.75px;
$floor-height-2: 432px;
$floor-height-3: 335px;
$shop-width-2: 285px;
$shop-width-3: 187px;
.shop-container {
width: 100%;
.pull-left {
float: left;
}
.shop-box > a {
display: block;
}
.shop-img {
position: relative;
> .left-icon {
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
}
&.shop-two {
padding-left: $margin-left-2;
height: $floor-height-2;
margin-top: $margin-top;
.shop-box {
width: $shop-width-2;
height: $floor-height-2;
margin-right: $margin-left-2;
.shop-img {
width: $shop-width-2;
height: 372px;
}
.shop-bottom-bar {
width: $shop-width-2;
height: 60px;
line-height: 60px;
color: #fff;
background-size: 100% 100%;
background-repeat: no-repeat;
}
}
}
&.shop-three {
padding-left: $margin-left-3;
height: $floor-height-3;
margin-top: $margin-top;
.shop-box {
width: $shop-width-3;
height: $floor-height-3;
margin-right: $margin-left-3;
.shop-img {
width: $shop-width-3;
height: 275px;
}
.shop-bottom-bar {
width: 187px;
height: 60px;
line-height: 60px;
color: #fff;
background-size: 100% 100%;
background-repeat: no-repeat;
}
}
}
}
... ...
(function ($) {
'use strict';
function __$styleInject(css, returnValue) {
if (typeof document === 'undefined') {
return returnValue;
}
css = css || '';
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
head.appendChild(style);
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
return returnValue;
}
$ = 'default' in $ ? $['default'] : $;
/* eslint-disable */
// Noop
function noop() {}
// Generic callback
function genericCallback(data) {
lastValue = [data];
}
// Call if defined
function callIfDefined(method, object, parameters) {
return method && method.apply && method.apply(object.context || object, parameters);
}
// Give joining character given url
function qMarkOrAmp(url) {
return (/\?/.test(url) ? "&" : "?"
);
}
var STR_ASYNC = "async";
var STR_CHARSET = "charset";
var STR_EMPTY = "";
var STR_ERROR = "error";
var STR_INSERT_BEFORE = "insertBefore";
var STR_JQUERY_JSONP = "_jqjsp";
var STR_ON = "on";
var STR_ON_CLICK = STR_ON + "click";
var STR_ON_ERROR = STR_ON + STR_ERROR;
var STR_ON_LOAD = STR_ON + "load";
var STR_ON_READY_STATE_CHANGE = STR_ON + "readystatechange";
var STR_READY_STATE = "readyState";
var STR_REMOVE_CHILD = "removeChild";
var STR_SCRIPT_TAG = "<script>";
var STR_SUCCESS = "success";
var STR_TIMEOUT = "timeout";
var win = window;
var Deferred = $.Deferred;
var head = $("head")[0] || document.documentElement;
var pageCache = {};
var count = 0;
var lastValue;
var xOptionsDefaults = {
//beforeSend: undefined,
//cache: false,
callback: STR_JQUERY_JSONP,
//callbackParameter: undefined,
//charset: undefined,
//complete: undefined,
//context: undefined,
//data: "",
//dataFilter: undefined,
//error: undefined,
//pageCache: false,
//success: undefined,
//timeout: 0,
//traditional: false,
url: location.href
};
var opera = win.opera;
var oldIE = !!$("<div>").html("<!--[if IE]><i><![endif]-->").find("i").length;
// ###################### MAIN FUNCTION ##
function jsonp(xOptions) {
// Build data with default
xOptions = $.extend({}, xOptionsDefaults, xOptions);
// References to xOptions members (for better minification)
var successCallback = xOptions.success,
errorCallback = xOptions.error,
completeCallback = xOptions.complete,
dataFilter = xOptions.dataFilter,
callbackParameter = xOptions.callbackParameter,
successCallbackName = xOptions.callback,
cacheFlag = xOptions.cache,
pageCacheFlag = xOptions.pageCache,
charset = xOptions.charset,
url = xOptions.url,
data = xOptions.data,
timeout = xOptions.timeout,
pageCached,
// Abort/done flag
done = 0,
// Life-cycle functions
cleanUp = noop,
// Support vars
supportOnload,
supportOnreadystatechange,
// Request execution vars
firstChild,
script,
scriptAfter,
timeoutTimer;
// If we have Deferreds:
// - substitute callbacks
// - promote xOptions to a promise
Deferred && Deferred(function (defer) {
defer.done(successCallback).fail(errorCallback);
successCallback = defer.resolve;
errorCallback = defer.reject;
}).promise(xOptions);
// Create the abort method
xOptions.abort = function () {
!done++ && cleanUp();
};
// Call beforeSend if provided (early abort if false returned)
if (callIfDefined(xOptions.beforeSend, xOptions, [xOptions]) === !1 || done) {
return xOptions;
}
// Control entries
url = url || STR_EMPTY;
data = data ? typeof data == "string" ? data : $.param(data, xOptions.traditional) : STR_EMPTY;
// Build final url
url += data ? qMarkOrAmp(url) + data : STR_EMPTY;
// Add callback parameter if provided as option
callbackParameter && (url += qMarkOrAmp(url) + encodeURIComponent(callbackParameter) + "=?");
// Add anticache parameter if needed
!cacheFlag && !pageCacheFlag && (url += qMarkOrAmp(url) + "_" + new Date().getTime() + "=");
// Replace last ? by callback parameter
url = url.replace(/=\?(&|$)/, "=" + successCallbackName + "$1");
// Success notifier
function notifySuccess(json) {
if (!done++) {
cleanUp();
// Pagecache if needed
pageCacheFlag && (pageCache[url] = { s: [json] });
// Apply the data filter if provided
dataFilter && (json = dataFilter.apply(xOptions, [json]));
// Call success then complete
callIfDefined(successCallback, xOptions, [json, STR_SUCCESS, xOptions]);
callIfDefined(completeCallback, xOptions, [xOptions, STR_SUCCESS]);
}
}
// Error notifier
function notifyError(type) {
if (!done++) {
// Clean up
cleanUp();
// If pure error (not timeout), cache if needed
pageCacheFlag && type != STR_TIMEOUT && (pageCache[url] = type);
// Call error then complete
callIfDefined(errorCallback, xOptions, [xOptions, type]);
callIfDefined(completeCallback, xOptions, [xOptions, type]);
}
}
// Check page cache
if (pageCacheFlag && (pageCached = pageCache[url])) {
pageCached.s ? notifySuccess(pageCached.s[0]) : notifyError(pageCached);
} else {
// Install the generic callback
// (BEWARE: global namespace pollution ahoy)
win[successCallbackName] = genericCallback;
// Create the script tag
script = $(STR_SCRIPT_TAG)[0];
script.id = STR_JQUERY_JSONP + count++;
// Set charset if provided
if (charset) {
script[STR_CHARSET] = charset;
}
opera && opera.version() < 11.60 ?
// onerror is not supported: do not set as async and assume in-order execution.
// Add a trailing script to emulate the event
(scriptAfter = $(STR_SCRIPT_TAG)[0]).text = "document.getElementById('" + script.id + "')." + STR_ON_ERROR + "()" :
// onerror is supported: set the script as async to avoid requests blocking each others
script[STR_ASYNC] = STR_ASYNC;
// Internet Explorer: event/htmlFor trick
if (oldIE) {
script.htmlFor = script.id;
script.event = STR_ON_CLICK;
}
// Attached event handlers
script[STR_ON_LOAD] = script[STR_ON_ERROR] = script[STR_ON_READY_STATE_CHANGE] = function (result) {
// Test readyState if it exists
if (!script[STR_READY_STATE] || !/i/.test(script[STR_READY_STATE])) {
try {
script[STR_ON_CLICK] && script[STR_ON_CLICK]();
} catch (_) {}
result = lastValue;
lastValue = 0;
result ? notifySuccess(result[0]) : notifyError(STR_ERROR);
}
};
// Set source
script.src = url;
// Re-declare cleanUp function
cleanUp = function cleanUp(i) {
timeoutTimer && clearTimeout(timeoutTimer);
script[STR_ON_READY_STATE_CHANGE] = script[STR_ON_LOAD] = script[STR_ON_ERROR] = null;
head[STR_REMOVE_CHILD](script);
scriptAfter && head[STR_REMOVE_CHILD](scriptAfter);
};
// Append main script
head[STR_INSERT_BEFORE](script, firstChild = head.firstChild);
// Append trailing script if needed
scriptAfter && head[STR_INSERT_BEFORE](scriptAfter, firstChild);
// If a timeout is needed, install it
timeoutTimer = timeout > 0 && setTimeout(function () {
notifyError(STR_TIMEOUT);
}, timeout);
}
return xOptions;
}
// ###################### SETUP FUNCTION ##
jsonp.setup = function (xOptions) {
$.extend(xOptionsDefaults, xOptions);
};
// ###################### INSTALL in jQuery ##
$.jsonp = jsonp;
/* eslint-disable */
__$styleInject(".featuretip.tip-wrap{position:fixed;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(0,0,0,.5)}.featuretip .tip{position:fixed;left:50%;top:50%;margin-left:-140px;margin-top:-140px;width:280px;background:#fff;border-top:40px solid #000;text-align:center;line-height:1.25}.featuretip .tip .title{margin:20px auto;font-size:24px;font-weight:700;text-align:center}.featuretip .tip .highlight{font-size:18px}.featuretip .tip .content{font-size:16px;color:#444;text-align:center}.featuretip .tip .button{display:block;margin:20px auto;width:150px;height:30px;font-size:14px;line-height:30px;text-align:center;color:#fff;background:#000;text-decoration:none}", undefined);
__$styleInject(".feature-coin.tip-wrap{position:fixed;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(0,0,0,.5)}.feature-coin .tip{position:fixed;left:50%;top:50%;margin-left:-140px;margin-top:-140px;width:280px;background:#fff;text-align:center;line-height:1.25;background-repeat:no-repeat}.feature-coin .tip .tip-close{position:absolute;right:0;top:0;width:25px;height:25px;line-height:25px;text-align:center;font-size:16px;color:#fff;background:#000;cursor:pointer}.feature-coin .tip .title{margin:21px auto;font-size:22px;font-weight:700;text-align:center}.feature-coin .tip .highlight{font-size:18px}.feature-coin .tip .content{padding:4px;font-size:16px;color:#444;text-align:center;height:48px;overflow:hidden}.feature-coin .bottom-button{text-align:center}.feature-coin .tip .button,.feature-coin .tip .coin{display:inline-block;margin:20px auto;width:116px;height:26px;font-size:14px;line-height:26px;text-align:center;color:#fff;background:#000;text-decoration:none;border:2px solid #000}.feature-coin .tip .coin{color:#000;background:#fff}", undefined);
var isMobile = {
Android: function Android() {
return navigator.userAgent.match(/Android/i) ? true : false;
},
BlackBerry: function BlackBerry() {
return navigator.userAgent.match(/BlackBerry/i) ? true : false;
},
iOS: function iOS() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
},
Windows: function Windows() {
return navigator.userAgent.match(/IEMobile/i) ? true : false;
},
any: function any() {
return isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows();
}
};
var mycurrency = isMobile.any() ? '//m.yohobuy.com/home/mycurrency' : '//www.yohobuy.com/home/currency';
var $tipTmpl = $('<div class="featuretip tip-wrap"><div class="tip"><div class="title"></div><div class="content"></div><a class="button" href="">返回</a></div></div>'); // eslint-disable-line
var $cointipTmpl = $('<div class="feature-coin tip-wrap"><div class="tip"><div class="tip-close">&times;</div><div class="title"></div><div class="content"></div><div class="bottom-button"><a class="button" href="">去逛逛</a><a class="coin" href=\'' + mycurrency + '?openby:yohobuy={"action":"go.mine"}\'>查看有货币</a></div></div></div>'); // eslint-disable-line
var _queryString = function _queryString() {
if (!window._jssdkQS) {
var vars = {},
hash = void 0,
i = void 0,
hashes = window.location.search.slice(1).split('&');
for (i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars[hash[0]] = hash[1];
}
window._jssdkQS = vars;
}
return window._jssdkQS;
};
var _sParamByIframe = function _sParamByIframe() {
var search = window.location.search;
if (search.indexOf('&expires=') === -1) {
search = search ? search + '&' : '?';
search = search + 'expires=' + 7 * 24 * 60 * 60 * 1000;
}
$('<iframe style="display:none;" src="//m.yohobuy.com/activity/wechat/1111' + search + '"></iframe>').prependTo('body');
};
var _bindEvent = function _bindEvent() {
var $body = $('body');
$body.on('click', '.feature-coin .close,.feature-coin .tip-close', function (e) {
$cointipTmpl.fadeOut();
e.preventDefault();
});
$body.on('click', '.feature-coin.tip-wrap', function (e) {
if ('feature-coin tip-wrap' === e.target.className) {
$cointipTmpl.fadeOut();
e.preventDefault();
}
});
$body.on('click', '.featuretip .close', function (e) {
$tipTmpl.fadeOut();
e.preventDefault();
});
$body.on('click', '.featuretip .refresh', function () {
location.reload();
});
$body.on('click', '.featuretip.tip-wrap', function (e) {
if ('featuretip tip-wrap' === e.target.className) {
$tipTmpl.fadeOut();
e.preventDefault();
}
});
};
var utils = {
queryString: _queryString,
init: function init() {
//发送活动页参数
_sParamByIframe();
// 绑定事件
_bindEvent();
},
isApp: function isApp() {
var qs = _queryString();
var isApp = !!qs.app_version || qs.openrefer === 'app' && qs.uid;
return !!isApp;
},
image: function image(url, width, height, mode, quality) {
mode = !isNaN(Number(mode)) ? mode : 2;
url = url || '';
url = url.replace(/{width}/g, width).replace(/{height}/g, height).replace(/{mode}/g, mode);
if (url.indexOf('imageView2') > 0) {
quality = quality || 90;
url += '/q/' + quality;
}
return url.replace('quality/80', 'quality/60').replace('http:', '');
},
sParamByIframe: function sParamByIframe(params) {
$('<iframe style="display:none;" src="//m.yohobuy.com/activity/wechat/1111?' + params + '"></iframe>').prependTo('body');
},
showTip: function showTip(data) {
data = data || {
title: '',
content: '',
close: true
};
$tipTmpl.find('.title').html(data.title);
$tipTmpl.find('.content').html(data.content);
if (data.close) {
$tipTmpl.find('.button').addClass('close');
} else {
$tipTmpl.find('.button').addClass('refresh').html('刷新');
}
$('body').append($tipTmpl);
$tipTmpl.show();
},
showCoinTip: function showCoinTip(data) {
data = data || {
title: '',
content: '',
close: true
};
$cointipTmpl.find('.title').html(data.title);
$cointipTmpl.find('.content').html(data.content);
if (data.close) {
$cointipTmpl.find('.button').addClass('close');
}
if (data.coin) {
$cointipTmpl.find('.coin').css('display', 'inline-block');
} else {
$cointipTmpl.find('.coin').hide();
}
if (data.img) {
$cointipTmpl.find('.tip').css('background-image', 'url(' + data.img + ')');
}
$('body').append($cointipTmpl);
$cointipTmpl.show();
}
};
var _noLoginUrl = function _noLoginUrl() {
var referrer = location.href.split('?')[0];
return '//m.yohobuy.com/signin.html?refer=' + encodeURIComponent(location.href) + '&openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"' + referrer.replace(/\//g, '\\/') + '","param":{"from":"app"}},"requesturl":{"url":"","param":{}},"priority":"N"}}';
};
var user = {
uid: '',
noLoginUrl: _noLoginUrl,
init: function init() {
var _this = this;
return jsonp({
url: '//m.yohobuy.com/passport/login/user?callback=?'
}).then(function (res) {
if (res.code === 200) {
_this.uid = Number(res.data) || 0;
}
if (!_this.uid && utils.isApp()) {
_this.uid = Number(utils.queryString().uid) || 0;
}
return $.Deferred().resolve(_this.uid);
}, function () {
utils.isApp() && (_this.uid = Number(utils.queryString().uid) || 0);
return $.Deferred().resolve(_this.uid);
});
},
auth: function auth() {
if (!this.uid) {
var noLoginUrl = _noLoginUrl();
$('a.auth').attr('href', noLoginUrl);
}
},
favout: function favout(skn) {
if (!skn || !this.uid) {
return;
}
jsonp({
url: '//service.yoho.cn/activity/favorite/addFavorite?productSkn=' + skn + '&uid=' + this.uid + '&callback=?'
}).then(function (res) {
if (res.code === 200) {
utils.showTip({
content: '恭喜您,收藏成功',
close: true
});
} else {
utils.showTip({
content: res.message,
close: true
});
}
}, function () {
utils.showTip({
title: '收藏失败<br>请刷新重新领取',
content: '如多次收藏失败,请联系客服人员<br>带来不便敬请谅解',
close: false
});
});
},
getMktCode: function getMktCode() {
var mkt_code = void 0;
if (this.uid) {
if (Number(this.uid) % 1024 >= 512) {
mkt_code = 100000000000195; // 默认的值
} else {
mkt_code = 100000000000193; // 个性化,动态接口数据
}
} else {
mkt_code = 100000000000197; // 访客接口数据
}
return mkt_code;
}
};
var jsApiList = ['checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone'];
var shareData = {
title: document.title,
link: location.href,
desc: 'YOHO!BUY',
imgUrl: 'http://static.yohobuy.com/m/v1/img/touch/apple-touch-icon-144x144-precomposed-new.png'
};
var _getShareDataById = function _getShareDataById() {
var shareId = utils.queryString().share_id;
if (shareId) {
return jsonp({
url: '//m.yohobuy.com/activity/share?callback=?',
data: {
shareId: shareId
}
}).then(function (res) {
if (res && res.code === 200 && res.data) {
shareData.title = res.data.title;
shareData.link = res.data.link || location.href;
shareData.desc = res.data.content || res.data.title;
shareData.imgUrl = res.data.pic;
}
return $.Deferred().resolve();
}, function () {
return $.Deferred().resolve();
});
} else {
var shareTitle = $('#shareTitle').val();
var shareImg = $('#shareImg').val();
var shareDesc = $('#shareDesc').val();
var shareLink = $('#shareLink').val();
shareData.title = shareTitle ? shareTitle : shareData.title;
shareData.imgUrl = shareImg ? shareImg : shareData.imgUrl;
shareData.desc = shareDesc ? shareDesc : shareData.desc;
shareData.link = shareLink ? shareLink : shareData.link;
return $.Deferred().resolve();
}
};
var share = {
init: function init() {
if (/QQ/i.test(navigator.userAgent)) {
$.ajax({
url: '//qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js',
dataType: 'script',
cache: true,
success: function success() {
_getShareDataById().then(function () {
window.setShareInfo && window.setShareInfo({
title: shareData.title,
summary: shareData.desc,
pic: shareData.imgUrl,
url: shareData.link
});
});
}
});
}
if (/MicroMessenger/i.test(navigator.userAgent)) {
$.ajax({
url: '//res.wx.qq.com/open/js/jweixin-1.1.0.js',
dataType: 'script',
cache: true,
success: function success() {
jsonp({
url: '//m.yohobuy.com/activity/wechat/share?callback=?',
data: {
url: location.href
}
}).then(function (res) {
if (window.wx) {
window.wx.config({
debug: false,
appId: res.appId,
timestamp: res.timestamp,
nonceStr: res.nonceStr,
signature: res.signature,
jsApiList: jsApiList
});
_getShareDataById().then(function () {
window.wx.ready(function () {
window.wx.onMenuShareAppMessage(shareData);
window.wx.onMenuShareTimeline(shareData);
window.wx.onMenuShareQQ(shareData);
window.wx.onMenuShareWeibo(shareData);
window.wx.onMenuShareQZone(shareData);
});
});
}
});
}
});
}
}
};
/**
* 移动端尝试打开 app
*/
var channelMap = {
'baidu.com': 100000000000055,
'so.com': 100000000000049,
'sogou.com': 100000000000053,
'bing.com': 100000000000057,
'm.sm.cn': 100000000000059,
'google.com': 100000000000061
};
var getMktcBySeo = function getMktcBySeo() {
var mktc,
rf = document.referrer;
for (var domain in channelMap) {
if (rf.indexOf(domain) > -1) {
mktc = channelMap[domain];
break;
}
}
return mktc;
};
var getAppPath = function getAppPath() {
var qs = utils.queryString();
var ct = qs.mkt_code || qs.union_type || getMktcBySeo() || '100000000000349';
delete qs.openapp; // 防止重复打开
var shareParams = qs.share_id ? '"share":"/operations/api/v5/webshare/getShare","shareparam":{"share_id":"' + qs.share_id + '"},' : '',
appPath = 'yohobuy://yohobuy.com/goapp?ct=' + ct + '&openby:yohobuy={"action":"go.h5",' + shareParams + '"params":{"islogin":"N","url":"http://feature.yoho.cn' + location.pathname + '","param":' + JSON.stringify(qs) + '}}';
return appPath;
};
var openapp = {
init: function init() {
if (utils.queryString().openapp) {
var u = navigator.userAgent.toLowerCase();
var isiOS = u.indexOf('os') > -1 || u.indexOf('iphone') > -1 || u.indexOf('mac') > -1 || u.indexOf('ipad') > -1;
var appPath = getAppPath();
if (isiOS) {
window.location.href = appPath;
} else {
var ifr = document.createElement('iframe');
ifr.src = appPath;
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
}
}
};
function cookie(name) {
var re = new RegExp(name + '=([^;$]*)', 'i'),
matchPattern = '$1';
return re.test(decodeURIComponent(document.cookie)) ? RegExp[matchPattern] : '';
}
function setCookie(name, value, options) {
var expires = '',
path,
domain,
secure,
date;
if (typeof value !== 'undefined') {
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
if (options.expires && (typeof options.expires === 'number' || options.expires.toUTCString)) {
if (typeof options.expires === 'number') {
date = new Date();
date.setTime(date.getTime() + options.expires * 24 * 60 * 60 * 1000);
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString();
}
path = options.path ? '; path=' + options.path : '';
domain = options.domain ? '; domain=' + options.domain : '';
secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
}
}
var cookies = {
cookie: cookie,
setCookie: setCookie
};
// 1. 优惠券领取
// 2. YOHO币领取
var _getCoin = function _getCoin(data) {
data.app = utils.queryString();
data.app.uid = data.uid;
jsonp({
url: '//m.yohobuy.com/activity/coin/sendCoin?callback=?',
data: data
}).then(function (res) {
if (res.code === 200 && res.data) {
if (res.data.code === 200) {
utils.showCoinTip({
title: '恭喜您,成功领取有货币!',
content: '特殊情况下到账有延时<br>请耐心等待',
close: true,
coin: true,
img: res.data.popupImg
});
} else if (res.data.code === 501) {
utils.showCoinTip({
title: '领取失败',
content: '哎呀,你来的有点早,活动还没开始呢<br/>稍后再来哦',
close: true,
img: res.data.popupImg
});
} else if (res.data.code === 502) {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,活动已结束了,下次要快哟~~',
close: true,
img: res.data.popupImg
});
} else if (res.data.code === 503) {
utils.showCoinTip({
title: '已经领取',
content: '贪心会长胖,你已经领取过了啦~~',
close: true,
img: res.data.popupImg
});
} else if (res.data.code === 504) {
utils.showCoinTip({
title: '领取失败',
content: '哎呀,你来晚了,有货币已经领完了,<br/>下次早点来哦',
close: true,
img: res.data.popupImg
});
} else if (res.data.msg) {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,系统错误,有货君正奋力解决中...请稍后再来',
close: true,
img: res.data.popupImg
});
}
} else if (res.message) {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,系统错误,有货君正奋力解决中...请稍后再来',
close: true,
img: res.data && res.data.popupImg
});
}
}, function () {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,系统错误,有货君正奋力解决中...请稍后再来',
close: true
});
});
};
var _getCoupon = function _getCoupon(data) {
data.app = utils.queryString();
data.app.uid = data.uid;
jsonp({
url: '//m.yohobuy.com/coupon/couponSend?callback=?',
data: data
}).then(function (res) {
if (res.code === 200) {
utils.showTip({
title: '领取成功',
content: '恭喜您,领取成功',
close: true
});
} else if (res.code === 401) {
utils.showTip({
title: '已经领取',
content: '快去分享给更多<br>喜爱<span class="highlight">潮流</span>的小伙伴吧!',
close: true
});
} else if (res.message) {
utils.showTip({
title: '领取失败<br>请刷新重新领取',
content: res.message + '<br>如多次领取失败,请联系客服人员<br>带来不便敬请谅解',
close: false
});
}
}, function () {
utils.showTip({
title: '领取失败<br>请刷新重新领取',
content: '如多次领取失败,请联系客服人员<br>带来不便敬请谅解',
close: false
});
});
};
var _initCoin = function _initCoin(uid) {
if (uid) {
var cointoken = cookies.cookie('yoho-coin-token');
if (cointoken) {
_getCoin({
token: cointoken,
uid: uid
});
cookies.setCookie('yoho-coin-token', '');
}
}
$('body').on('click', '.yoho-coin', function () {
var token = $(this).data('token');
if (user.uid) {
_getCoin({
token: token,
uid: user.uid
});
} else {
cookies.setCookie('yoho-coin-token', token);
if ($('#intimacy-link').length <= 0) {
$('body').append('<a href=\'' + user.noLoginUrl() + '\' style="display:none;" id="intimacy-link"><span class="intimacy-link"></span></a>');
}
$('.intimacy-link').click();
return;
}
});
};
var _initCoupon = function _initCoupon(uid) {
if (uid) {
var conpontoken = cookies.cookie('yoho-conpon-token');
if (conpontoken) {
_getCoupon({
token: conpontoken,
uid: uid
});
cookies.setCookie('yoho-conpon-token', '');
}
}
$('body').on('click', '.yoho-conpon', function () {
var token = $(this).data('token');
if (user.uid) {
_getCoupon({
token: token,
uid: user.uid
});
} else {
cookies.setCookie('yoho-conpon-token', token);
if ($('#intimacy-link').length <= 0) {
$('body').append('<a href=\'' + user.noLoginUrl() + '\' style="display:none;" id="intimacy-link"><span class="intimacy-link"></span></a>');
}
$('.intimacy-link').click();
return;
}
});
};
var promotion = {
init: function init(uid) {
_initCoin(uid); // 初始化有货币
_initCoupon(uid); // 初始化优惠券
}
};
var abTestFlag = false; // ab测试
var _replaceData = function _replaceData(el, cond, data, wh, fp) {
if (!data) {
return;
}
el.find('.brand-name').html(data.brand_name);
el.find('.product-detail').attr('href', '//m.yohobuy.com/product/pro_' + data.product_id + '_' + data.goods_id + '/' + data.cn_alphabet + '.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":' + data.product_skn + '}}');
el.find('.product-detail-img').attr('src', utils.image(data.default_images, wh.w, wh.h, 2, 75));
el.find('.product-name').html(data.product_name);
el.find('.vip-price-val').html('\xA5' + data.vip_price);
el.find('.sale-price').html('\xA5' + data.sales_price);
if (data.sales_price === data.market_price) {
el.find('.market-price').hide();
} else {
el.find('.market-price').html('\xA5' + data.market_price).show();
}
var brandDom = el.find('.product-brand');
if (brandDom) {
if (data.shop_id) {
brandDom.attr('href', '//m.yohobuy.com/product/index/brand?domain=' + data.brand_domain + '&openby:yohobuy={"action":"go.shop","params":{"shop_id":' + data.shop_id + ',"shop_template_type":' + data.shop_template_type + '}}');
} else {
brandDom.attr('href', '//m.yohobuy.com/product/index/brand?domain=' + data.brand_domain + '&openby:yohobuy={"action":"go.brand","params":{"brand_id":' + data.brand_id + '}}');
}
}
// 楼层数据
if (fp) {
if (!fp.I_INDEX) fp.I_INDEX = 0;
fp.I_INDEX++;
el.find('.product-detail').attr('fp', JSON.stringify(fp));
if (brandDom) {
fp.I_INDEX++;
brandDom.attr('fp', JSON.stringify(fp));
}
}
var listDom = el.find('.list-product');
if (listDom) {
var sortStr = '',
gender = cond.gender ? cond.gender : '1,3',
url = '//list.m.yohobuy.com?gender=' + gender;
if (listDom.data('sort')) {
sortStr += ',"sort":' + data.small_sort_id;
url += '&sort=' + data.small_sort_id;
}
if (listDom.data('misort')) {
sortStr += ',"misort":' + data.middle_sort_id;
url += '&misort=' + data.middle_sort_id;
}
if (listDom.data('msort')) {
sortStr += ',"msort":' + data.max_sort_id;
url += '&msort=' + data.max_sort_id;
}
url += '&openby:yohobuy={"action":"go.list","params":{"actiontype":1,"gender":' + gender + sortStr + '}}';
listDom.attr('href', url);
}
el.html(el.html());
return el;
};
var _getProductData = function _getProductData(dataArr) {
if (!dataArr.length) {
return;
}
var data = dataArr.shift();
if (!data || !data.default_images) {
return _getProductData(dataArr);
}
return data;
};
var _jsonp = function _jsonp(el, param, cond) {
var cloneitem = el.attr('cloneitem');
var loading = el.find('.loading');
var goods = el.find('.feature-product-info');
if (!goods.length) {
return;
}
if (cond.abtest) {
// ab测试,访客 和 >=512的uid 显示默认推荐
if (!param.uid || Number(param.uid) % 1024 >= 512) {
if (cloneitem) {
$(goods[0]).remove();
} else {
goods.removeClass('novisible');
loading.hide();
}
return;
}
}
var imgwh = el.find('.imgwh').val() || ''; // 获取图片宽x高
imgwh = imgwh.split('x') || [];
var wh = {
w: imgwh[0] || 300,
h: imgwh[1] || 400
};
// 楼层数据
var fp = el.attr('fp');
fp = fp ? JSON.parse(fp) : '';
jsonp({
url: '//m.yohobuy.com/activity/individuation?callback=?',
data: $.extend({}, param, cond)
}).then(function (res) {
if (!res || !res.length) {
if (cloneitem) {
$(goods[0]).remove();
} else {
goods.removeClass('novisible');
loading.hide();
}
return;
}
if (cloneitem) {
// 可复制item
var cnt = isNaN(Number(cloneitem)) ? res.length : Number(cloneitem);
for (var indx = 0; indx < cnt; indx++) {
var data = _getProductData(res); // 获取商品数据
if (indx === 0) {
var gel = $(goods[0]);
var nel = _replaceData(gel, cond, data, wh, fp);
if (nel) {
nel.removeClass('novisible');
} else {
gel.remove();
}
} else {
var _nel = _replaceData($(goods[0]).clone(), cond, data, wh, fp);
if (_nel) {
_nel.removeClass('novisible');
_nel.appendTo(el);
}
}
}
} else {
goods.each(function (indx, el) {
el = $(el);
_replaceData(el, cond, _getProductData(res), wh, fp);
});
goods.removeClass('novisible');
loading.hide();
}
}, function () {
if (cloneitem) {
$(goods[0]).remove();
} else {
goods.removeClass('novisible');
loading.hide();
}
});
};
var _abTest = function _abTest() {
var mkt_code = user.getMktCode();
// cover覆盖mkt_code
utils.sParamByIframe('cover=1&mkt_code=' + mkt_code + '&expires=' + 7 * 24 * 60 * 60 * 1000);
// 上报曝光事件
var actionUrl = [];
$('a').each(function () {
var href = $(this).attr('href');
if (href && !/^#.*$/.test(href) && !/^javascript.*$/i.test(href)) {
actionUrl.push(href);
}
});
var cnt = 0;
var timer = setInterval(function () {
cnt++;
if (cnt > 3) {
clearInterval(timer);
return;
}
if (window._yas && window._yas.sendAppLogs && window.appBaseLogs) {
clearInterval(timer);
window._yas.sendAppLogs({
appop: 'YB_H5_PAGE_AB_OPEN_L',
param: JSON.stringify({
C_ID: utils.queryString().yh_channel || 1,
PAGE_URL: window.originUrl,
PAGE_NAME: decodeURI(window.qs.title || document.title),
ACTION_URL: actionUrl,
CROWD_CODE: mkt_code + ''
})
}, true);
$('a').click(function () {
var furl = $(this).attr('href');
if (furl && !/^#.*$/.test(furl) && !/^javascript.*$/i.test(furl)) {
window._yas.sendAppLogs({
appop: 'YB_H5_PAGE_AB_FLR_C',
param: JSON.stringify({
C_ID: utils.queryString().yh_channel || 1,
PAGE_URL: window.originUrl,
PAGE_NAME: decodeURI(window.qs.title || document.title),
F_URL: furl,
CROWD_CODE: mkt_code + ''
})
}, true);
}
});
}
}, 1000);
};
var _getProduct = function _getProduct(param) {
$('.product-source').each(function (i, el) {
el = $(el);
var cond = el.attr('condition');
if (!cond) {
return;
}
cond = JSON.parse(cond);
var yh_channel = utils.queryString().yh_channel;
if (cond.abtest) {
abTestFlag = true;
}
if (yh_channel) {
cond.yh_channel = yh_channel;
}
if (i > 3) {
setTimeout(function () {
_jsonp(el, param, cond);
}, 300);
} else {
_jsonp(el, param, cond);
}
});
abTestFlag && _abTest();
};
var individuation = {
init: function init(uid) {
if (!uid && utils.isApp()) {
document.addEventListener('deviceready', function () {
window.yohoInterface.triggerEvent(function (data) {
user.uid = data.uid; // app端 获取uid
// 获取个性话数据
_getProduct({
uid: data.uid,
udid: data.udid
});
}, function () {}, {
method: 'get.analyticAppData'
});
}, false);
} else {
// 获取个性话数据
_getProduct({
uid: uid,
udid: cookies.cookie('_yasvd')
});
}
}
};
// app.js
$(function () {
openapp.init();
user.init().then(function (uid) {
individuation.init(uid); // 个性化推荐
promotion.init(uid); // 促销
user.auth(); // 权限验证
share.init(); // 分享
utils.init();
});
});
var jssdk = {
auth: user.auth,
favout: user.favout,
getMktCode: function getMktCode() {
return user.getMktCode();
},
getUid: function getUid() {
return user.uid;
}
};
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
(function (factory) {
/* eslint-disable */
if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object' && _typeof(module.exports) === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define([], factory);
} else {
window._jssdk = factory();
}
/* eslint-disable */
})(function () {
return jssdk;
});
}(jQuery));
... ...