Authored by 郭成尧

Merge branch 'feature/featureTemplate2' into 'master'

Feature/feature template2



See merge request !448
@@ -9,7 +9,7 @@ exports.index = function(req, res, next) { @@ -9,7 +9,7 @@ exports.index = function(req, res, next) {
9 if (!result) { 9 if (!result) {
10 return next(); 10 return next();
11 } 11 }
12 - res.render('feature', { 12 + res.render('feature/index', {
13 module: 'activity', 13 module: 'activity',
14 page: 'feature', 14 page: 'feature',
15 title: result.name || 'Yoho!Buy有货', 15 title: result.name || 'Yoho!Buy有货',
@@ -18,3 +18,17 @@ exports.index = function(req, res, next) { @@ -18,3 +18,17 @@ exports.index = function(req, res, next) {
18 }); 18 });
19 }).catch(next); 19 }).catch(next);
20 }; 20 };
  21 +
  22 +exports.sidebar = function(req, res, next) {
  23 + model.index({
  24 + code: req.params.code
  25 + }).then((result) => {
  26 + if (!result) {
  27 + return next();
  28 + }
  29 + res.render('feature/sidebar', {
  30 + content: result,
  31 + layout: false
  32 + });
  33 + }).catch(next);
  34 +}
@@ -16,6 +16,7 @@ const _getProductBySkns = function(productObj) { @@ -16,6 +16,7 @@ const _getProductBySkns = function(productObj) {
16 producturl: `//m.yohobuy.com/product/pro_${val.product_id}_${goods_id}/${val.cn_alphabet}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":${val.product_skn}}}`, // eslint-disable-line 16 producturl: `//m.yohobuy.com/product/pro_${val.product_id}_${goods_id}/${val.cn_alphabet}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":${val.product_skn}}}`, // eslint-disable-line
17 productimg: helpers.image(val.default_images, 213, 284, 2, 60).replace('quality/80', 'quality/60'), 17 productimg: helpers.image(val.default_images, 213, 284, 2, 60).replace('quality/80', 'quality/60'),
18 productname: val.product_name, 18 productname: val.product_name,
  19 + vipprice: val.vip_price,
19 saleprice: val.sales_price, 20 saleprice: val.sales_price,
20 marketprice: val.sales_price === val.market_price ? '' : val.market_price, 21 marketprice: val.sales_price === val.market_price ? '' : val.market_price,
21 brandname: val.brand_name 22 brandname: val.brand_name
@@ -15,6 +15,7 @@ let _getProduct = function(o) { @@ -15,6 +15,7 @@ let _getProduct = function(o) {
15 product_id: o.product_id, 15 product_id: o.product_id,
16 product_name: o.product_name, 16 product_name: o.product_name,
17 product_skn: o.product_skn, 17 product_skn: o.product_skn,
  18 + vip_price: o.vip_price,
18 market_price: o.market_price, 19 market_price: o.market_price,
19 sales_price: o.sales_price, 20 sales_price: o.sales_price,
20 cn_alphabet: o.cn_alphabet, 21 cn_alphabet: o.cn_alphabet,
@@ -229,6 +229,7 @@ router.get('/individuation', individuation.productLst); @@ -229,6 +229,7 @@ router.get('/individuation', individuation.productLst);
229 229
230 // 活动页模版 230 // 活动页模版
231 router.get('/feature/:code.html', feature.index); 231 router.get('/feature/:code.html', feature.index);
  232 +router.get('/featuresidebar/:code.html', feature.sidebar);
232 233
233 // 2016 年度账单 234 // 2016 年度账单
234 router.get('/annual-account', annualAccount.index); 235 router.get('/annual-account', annualAccount.index);
1 <div class="feature-page yoho-page"> 1 <div class="feature-page yoho-page">
2 - {{#content.webShare}}  
3 - <input id="shareLink" type="hidden" value="{{url}}">  
4 - <input id="shareDesc" type="hidden" value="{{content}}">  
5 - <input id="shareImg" type="hidden" value="{{pic}}">  
6 - <input id="shareTitle" type="hidden" value="{{title}}">  
7 - {{/content.webShare}}  
8 - {{#content.floors}}  
9 - {{#isEqualOr type 'sidebar'}}  
10 - {{! 侧悬浮}}  
11 - <div class="cexuanfu" id="load_cxf"></div>  
12 - {{/isEqualOr}}  
13 - {{#isEqualOr type '' 'common_floor' 'fix'}}  
14 - {{! 普通楼层 顶悬浮}}  
15 - <div {{#if param.anchorname}}id="{{param.anchorname}}"{{/if}} {{#if id}}data-id="{{id}}"{{/if}} class="floor {{type}}"  
16 - style="{{#if param.bgcolor}}background-color:{{param.bgcolor}}{{/if}}">  
17 - {{#if param.bgimg}}  
18 - <img src="{{image2 param.bgimg q=60}}">  
19 - {{/if}}  
20 - {{#component}}  
21 - {{#isEqualOr type 'link'}}  
22 - {{! 普通组件}}  
23 - <a class="anchor" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>  
24 - {{/isEqualOr}} 2 + {{#unless content.visiable}}
  3 + <div class="over">
  4 + <p>此活动已结束</p>
  5 + <p>稍后自动跳转更多其他精彩活动...</p>
  6 + </div>
  7 + {{else}}
  8 + {{#content.webShare}}
  9 + <input id="shareLink" type="hidden" value="{{url}}">
  10 + <input id="shareDesc" type="hidden" value="{{content}}">
  11 + <input id="shareImg" type="hidden" value="{{pic}}">
  12 + <input id="shareTitle" type="hidden" value="{{title}}">
  13 + {{/content.webShare}}
  14 + {{#content.floors}}
  15 + {{#isEqualOr type 'sidebar'}}
  16 + {{! 侧悬浮}}
  17 + <div id="sidebar" pageid="{{param.sidebarPageId}}"></div>
  18 + {{/isEqualOr}}
  19 + {{#isEqualOr type '' 'common_floor' 'fix'}}
  20 + {{! 普通楼层 顶悬浮}}
  21 + <div {{#if param.anchorname}}id="{{param.anchorname}}"{{/if}} {{#if param.tabname}}tabname="{{param.tabname}}"{{/if}} {{#if id}}data-id="{{id}}"{{/if}} class="floor {{type}}"
  22 + style="{{#if param.bgcolor}}background-color:{{param.bgcolor}}{{/if}}">
  23 + {{#if param.bgimg}}
  24 + {{#isLazyLoad type @index}}
  25 + <img class="lazy" data-original="{{image2 param.bgimg q=60}}">
  26 + {{else}}
  27 + <img src="{{image2 param.bgimg q=60}}">
  28 + {{/isLazyLoad}}
  29 + {{/if}}
  30 + {{#component}}
  31 + {{#isEqualOr type 'link'}}
  32 + {{! 普通组件}}
  33 + <a class="anchor {{#if modalImg}}modalimg{{/if}}" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
  34 + {{#if modalImg}}
  35 + <div class="modal">
  36 + <span class="modal-close"></span>
  37 + <img class="modal-img lazy" data-original="{{image2 modalImg q=60}}">
  38 + </div>
  39 + {{/if}}
  40 + {{/isEqualOr}}
25 41
26 - {{#isEqualOr type 'coupon'}}  
27 - {{! 优惠券}}  
28 - <a class="anchor yoho-conpon" style="{{styleFormat this percent=1}}" data-token="{{token}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>  
29 - {{/isEqualOr}} 42 + {{#isEqualOr type 'coupon'}}
  43 + {{! 优惠券}}
  44 + <a class="anchor yoho-conpon" style="{{styleFormat this percent=1}}" data-token="{{token}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
  45 + {{/isEqualOr}}
30 46
31 - {{#isEqualOr type 'yohoCoin'}}  
32 - {{! 有货币}}  
33 - <a class="anchor yoho-coin" style="{{styleFormat this percent=1}}" data-token="{{token}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>  
34 - {{/isEqualOr}} 47 + {{#isEqualOr type 'yohoCoin'}}
  48 + {{! 有货币}}
  49 + <a class="anchor yoho-coin" style="{{styleFormat this percent=1}}" data-token="{{token}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
  50 + {{/isEqualOr}}
35 51
36 - {{#isEqualOr type 'video'}}  
37 - {{! 视频}}  
38 - <a class="anchor video-bg" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>  
39 - <div class="video-android-close hide"></div>  
40 - <div class="video-android-bg hide"></div>  
41 - <video class="video" controls loop preload="meta" name="media">  
42 - <source src="{{videoSrc}}">  
43 - </video>  
44 - {{/isEqualOr}} 52 + {{#isEqualOr type 'video'}}
  53 + {{! 视频}}
  54 + <a class="anchor video-bg" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
  55 + <div class="video-android-close hide"></div>
  56 + <div class="video-android-bg hide"></div>
  57 + <video class="video" controls loop preload="meta" name="media">
  58 + <source src="{{videoSrc}}">
  59 + </video>
  60 + {{/isEqualOr}}
45 61
46 - {{#isEqualOr type 'marquee' 'swiper'}}  
47 - {{! 轮播/滑动}}  
48 - <div class="swiper-container {{type}}" data-loop="{{loop}}" {{#if spaceBetween}}data-spacebetween="{{spaceBetween}}"{{/if}} {{#if autoplay}}data-autoplay="{{autoplay}}"{{/if}}>  
49 - <div class="swiper-wrapper">  
50 - {{#list}}  
51 - <div class="swiper-slide" style="{{styleFormat this percent=1}}">  
52 - <img src="{{image2 src q=60}}">  
53 - <a class="anchor" href="{{#if link}}{{link}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../../this @index}}"></a>  
54 - </div>  
55 - {{/list}}  
56 - </div>  
57 - {{#isEqualOr type 'marquee'}}  
58 - <div class="swiper-pagination"></div>  
59 - {{/isEqualOr}}  
60 - </div>  
61 - {{/isEqualOr}} 62 + {{#isEqualOr type 'marquee' 'swiper'}}
  63 + {{! 轮播/滑动}}
  64 + <div class="swiper-container {{type}}" data-loop="{{loop}}" {{#if spaceBetween}}data-spacebetween="{{spaceBetween}}"{{/if}} {{#if autoplay}}data-autoplay="{{autoplay}}"{{/if}}>
  65 + <div class="swiper-wrapper">
  66 + {{#list}}
  67 + <div class="swiper-slide" style="{{styleFormat this percent=1}}">
  68 + <img src="{{image2 src q=60}}">
  69 + <a class="anchor" href="{{#if link}}{{link}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../../this @index}}"></a>
  70 + </div>
  71 + {{/list}}
  72 + </div>
  73 + {{#isEqualOr type 'marquee'}}
  74 + <div class="swiper-pagination"></div>
  75 + {{/isEqualOr}}
  76 + </div>
  77 + {{/isEqualOr}}
62 78
63 - {{#isEqualOr type 'tab'}}  
64 - {{! tab}}  
65 - <div class="tab-container">  
66 - {{#repeat count}}  
67 - <a class="anchor {{#if @first}}active{{/if}}" style="{{tabStyle @index ../count}}"></a>  
68 - {{/repeat}}  
69 - </div>  
70 - {{/isEqualOr}}  
71 -  
72 - {{#isEqualOr type 'productGroup'}}  
73 - {{! 商品池}}  
74 - <div class="product-container item{{numOfOneRow}}" {{#if proBgImg}}style="background:url({{image2 proBgImg q=60}})repeat;"{{/if}}>  
75 - <div class="product-source" {{#unless defaultPros.length}} {{#if searchCondition }}cloneitem="{{searchCondition.limit}}"{{/if}}{{/unless}} condition='{{stringify searchCondition}}' fp="{{getAnalysis ../this @index}}">  
76 - <input class="imgwh" type="hidden" value="193x257">  
77 - {{#if defaultPros.length}}  
78 - {{#defaultPros}}  
79 - <div class="feature-product-info {{#if ../condition}}novisible{{/if}}">  
80 - <a class="first-part product-detail" href='{{producturl}}'>  
81 - <div class="product-detail-imgbox">  
82 - {{#if ../lefTopImg}}<img class="leftopimg" src="{{image2 ../lefTopImg q=60}}">{{/if}}  
83 - {{#if ../rigTopImg}}<img class="rigtopimg" src="{{image2 ../rigTopImg q=60}}">{{/if}}  
84 - <img class="product-detail-img" src="{{image2 productimg q=60}}">  
85 - </div>  
86 - {{#isEqualOr ../showPrdName '1'}}<p class="product-name">{{productname}}</p>{{/isEqualOr}}  
87 - <div class="product-detail-text">  
88 - <div class="price">  
89 - <span class="sale-price"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>¥{{saleprice}}</span>  
90 - {{#if marketprice}}<span class="market-price">¥{{marketprice}}</span>{{/if}}  
91 - </div>  
92 - </div>  
93 - </a>  
94 - {{#if ../brandImg}}  
95 - <a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>  
96 - <div class="brand-div">  
97 - <span class="brand-name"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>{{brandname}}</span>  
98 - </div>  
99 - <img class="brand-img" src="{{image2 ../brandImg q=60}}">  
100 - </a>  
101 - {{/if}}  
102 - </div>  
103 - {{/defaultPros}}  
104 - {{else}}  
105 - <div class="feature-product-info novisible">  
106 - <a class="first-part product-detail" href=''>  
107 - <div class="product-detail-imgbox">  
108 - {{#if lefTopImg}}<img class="leftopimg" src="{{image2 lefTopImg q=60}}">{{/if}}  
109 - {{#if rigTopImg}}<img class="rigtopimg" src="{{image2 rigTopImg q=60}}">{{/if}}  
110 - <img class="product-detail-img" src="">  
111 - </div>  
112 - {{#isEqualOr showPrdName '1'}}<p class="product-name"></p>{{/isEqualOr}}  
113 - <div class="product-detail-text">  
114 - <div class="price">  
115 - <span class="sale-price"{{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>  
116 - <span class="market-price"></span>  
117 - </div>  
118 - </div>  
119 - </a>  
120 - {{#if brandImg}}  
121 - <a class="second-part {{#isEqualOr showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href=''>  
122 - <div class="brand-div">  
123 - <span class="brand-name" {{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>  
124 - </div>  
125 - <img class="brand-img" src="{{image2 brandImg q=60}}">  
126 - </a>  
127 - {{/if}}  
128 - </div>  
129 - {{/if}}  
130 - </div>  
131 - </div>  
132 - {{/isEqualOr}}  
133 - {{/component}}  
134 - </div>  
135 - {{/isEqualOr}}  
136 - {{/content.floors}} 79 + {{#isEqualOr type 'tab'}}
  80 + {{! tab}}
  81 + <div class="tab-container">
  82 + {{#repeat count}}
  83 + <a class="anchor {{#if @first}}active{{/if}}" tab={{tabName @index ../tabnames}} style="{{tabStyle @index ../count}}"></a>
  84 + {{/repeat}}
  85 + </div>
  86 + {{/isEqualOr}}
  87 +
  88 + {{#isEqualOr type 'productGroup'}}
  89 + {{! 商品池}}
  90 + <div class="product-container item{{numOfOneRow}}" {{#if proBgImg}}style="background:url({{image2 proBgImg q=60}})repeat;"{{/if}}>
  91 + <div class="product-source" condition='{{stringify searchCondition}}' fp="{{getAnalysis ../this @index}}"
  92 + {{#unless defaultPros.length}}
  93 + {{#if searchCondition.item}}
  94 + cloneitem="{{searchCondition.item}}"
  95 + {{else}}
  96 + cloneitem="{{searchCondition.limit}}"
  97 + {{/if}}
  98 + {{/unless}}>
  99 + <input class="imgwh" type="hidden" value="193x257">
  100 + {{#if defaultPros.length}}
  101 + {{#defaultPros}}
  102 + <div class="feature-product-info {{#if ../searchCondition}}novisible{{/if}}">
  103 + <a class="first-part product-detail" href='{{producturl}}'>
  104 + <div class="product-detail-imgbox">
  105 + {{#if ../lefTopImg}}<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=60}}">{{/if}}
  106 + {{#if ../rigTopImg}}<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=60}}">{{/if}}
  107 + <img class="product-detail-img lazy" data-original="{{image2 productimg q=60}}">
  108 + </div>
  109 + {{#isEqualOr ../showPrdName '1'}}<p class="product-name">{{productname}}</p>{{/isEqualOr}}
  110 + <div class="product-detail-text">
  111 + {{#isEqualOr ../showSalePrice '1'}}
  112 + <div class="price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}">
  113 + <span class="sale-price"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>¥{{saleprice}}</span>
  114 + {{#if marketprice}}<span class="market-price">¥{{marketprice}}</span>{{/if}}
  115 + </div>
  116 + {{/isEqualOr}}
  117 + {{#isEqualOr ../showVipPrice '1'}}
  118 + <div class="vipprice"style="{{#if ../vipFontColor}}color:{{../vipFontColor}};{{/if}}{{#if ../vipBgColor}}background:{{../vipBgColor}};{{/if}}">
  119 + <span class="vip-price-text">VIP价</span>
  120 + <span class="vip-price-val">¥{{vipprice}}</span>
  121 + </div>
  122 + {{/isEqualOr}}
  123 + </div>
  124 + </a>
  125 + {{#if ../brandImg}}
  126 + <a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
  127 + <div class="brand-div">
  128 + <span class="brand-name"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>{{brandname}}</span>
  129 + </div>
  130 + <img class="brand-img lazy" data-original="{{image2 ../brandImg q=60}}">
  131 + </a>
  132 + {{/if}}
  133 + </div>
  134 + {{/defaultPros}}
  135 + {{else}}
  136 + <div class="feature-product-info novisible">
  137 + <a class="first-part product-detail" href=''>
  138 + <div class="product-detail-imgbox">
  139 + {{#if lefTopImg}}<img class="leftopimg" src="{{image2 lefTopImg q=60}}">{{/if}}
  140 + {{#if rigTopImg}}<img class="rigtopimg" src="{{image2 rigTopImg q=60}}">{{/if}}
  141 + <img class="product-detail-img" src="">
  142 + </div>
  143 + {{#isEqualOr showPrdName '1'}}<p class="product-name"></p>{{/isEqualOr}}
  144 + <div class="product-detail-text">
  145 + {{#isEqualOr showSalePrice '1'}}
  146 + <div class="price" style="{{#if salePriceBgColor}}background:{{salePriceBgColor}};{{/if}}">
  147 + <span class="sale-price"{{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>
  148 + <span class="market-price"></span>
  149 + </div>
  150 + {{/isEqualOr}}
  151 + {{#isEqualOr showVipPrice '1'}}
  152 + <div class="vipprice" style="{{#if vipFontColor}}color:{{vipFontColor}};{{/if}}{{#if vipBgColor}}background:{{vipBgColor}};{{/if}}">
  153 + <span class="vip-price-text">VIP价</span><span class="vip-price-val"></span>
  154 + </div>
  155 + {{/isEqualOr}}
  156 + </div>
  157 + </a>
  158 + {{#if brandImg}}
  159 + <a class="second-part {{#isEqualOr showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href=''>
  160 + <div class="brand-div">
  161 + <span class="brand-name" {{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>
  162 + </div>
  163 + <img class="brand-img" src="{{image2 brandImg q=60}}">
  164 + </a>
  165 + {{/if}}
  166 + </div>
  167 + {{/if}}
  168 + </div>
  169 + </div>
  170 + {{/isEqualOr}}
  171 + {{/component}}
  172 + </div>
  173 + {{/isEqualOr}}
  174 + {{/content.floors}}
  175 + {{/unless}}
137 </div> 176 </div>
  1 +{{#if content.thumbnail}}
  2 +<img class="sidebar-img" src="{{image2 content.thumbnail q=60}}">
  3 +{{/if}}
  4 +<div class="sidebar">
  5 + <div class="sidebar-content">
  6 + {{#content.floors}}
  7 + {{#isEqualOr type '' 'common_floor'}}
  8 + <div class="sidebar-item">
  9 + {{#if param.bgimg}}<img src="{{image2 param.bgimg q=60}}">{{/if}}
  10 + {{#component}}
  11 + {{#isEqualOr type 'link'}}
  12 + {{#isEqualOr url 'closesidebar'}}
  13 + <a class="anchor closesidebar" style="{{styleFormat this percent=1}}" href="javascript:void(0);"></a>
  14 + {{else}}
  15 + <a class="anchor" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}"></a>
  16 + {{/isEqualOr}}
  17 + {{/isEqualOr}}
  18 + {{/component}}
  19 + </div>
  20 + {{/isEqualOr}}
  21 + {{/content.floors}}
  22 + </div>
  23 +</div>
@@ -8,9 +8,9 @@ const qpsLimiter = require('./rules/qps-limit'); @@ -8,9 +8,9 @@ const qpsLimiter = require('./rules/qps-limit');
8 const captchaPolicy = require('./policies/captcha'); 8 const captchaPolicy = require('./policies/captcha');
9 9
10 const IP_WHITE_LIST = [ 10 const IP_WHITE_LIST = [
11 -  
12 - // '106.38.38.146',  
13 - // '218.94.75.58' 11 + '106.38.38.146',
  12 + '218.94.75.58',
  13 + '218.94.75.50'
14 ]; 14 ];
15 15
16 const limiter = (rule, policy, context) => { 16 const limiter = (rule, policy, context) => {
@@ -18,14 +18,18 @@ const limiter = (rule, policy, context) => { @@ -18,14 +18,18 @@ const limiter = (rule, policy, context) => {
18 }; 18 };
19 19
20 module.exports = (req, res, next) => { 20 module.exports = (req, res, next) => {
21 - let remoteIp = req.get('X-Forwarded-For') || req.connection.remoteAddress;  
22 -  
23 - logger.debug('request remote ip: ', remoteIp); 21 + let remoteIp = req.get('X-Forwarded-For') || req.get('X-Real-IP') || '';
24 22
25 if (remoteIp.indexOf(',') > 0) { 23 if (remoteIp.indexOf(',') > 0) {
26 let arr = remoteIp.split(','); 24 let arr = remoteIp.split(',');
27 25
28 - remoteIp = arr[0]; 26 + remoteIp = arr[arr.length - 1];
  27 + }
  28 +
  29 + remoteIp = _.trim(remoteIp);
  30 +
  31 + if (_.startsWith(remoteIp, '10.66.')) {
  32 + remoteIp = req.get('X-Real-IP');
29 } 33 }
30 34
31 const excluded = _.includes(IP_WHITE_LIST, remoteIp); 35 const excluded = _.includes(IP_WHITE_LIST, remoteIp);
@@ -22,6 +22,10 @@ module.exports = (req, res, next) => { @@ -22,6 +22,10 @@ module.exports = (req, res, next) => {
22 return next(); 22 return next();
23 } 23 }
24 24
  25 + if (res.statusCode == 403) {
  26 + return res.end();
  27 + }
  28 +
25 if (req.xhr) { 29 if (req.xhr) {
26 return res.json({ 30 return res.json({
27 code: 400, 31 code: 400,
@@ -101,7 +101,7 @@ @@ -101,7 +101,7 @@
101 <script type="text/javascript" src="{{src}}"></script> 101 <script type="text/javascript" src="{{src}}"></script>
102 {{/loadJs}} 102 {{/loadJs}}
103 {{#isFeature}} 103 {{#isFeature}}
104 - <script type="text/javascript" src="//cdn.yoho.cn/js-sdk/1.2.0/jssdk.js"></script> 104 + <script type="text/javascript" src="//cdn.yoho.cn/js-sdk/1.2.2/jssdk.js"></script>
105 {{/isFeature}} 105 {{/isFeature}}
106 {{#unless devEnv}} 106 {{#unless devEnv}}
107 {{> analysis}} 107 {{> analysis}}
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 a.async = 1; 12 a.async = 1;
13 a.src = j; 13 a.src = j;
14 m.parentNode.insertBefore(a, m); 14 m.parentNode.insertBefore(a, m);
15 - }(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.3.7/yas.js', '_yas')); 15 + }(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.3.8/yas.js', '_yas'));
16 16
17 var _hmt = _hmt || []; 17 var _hmt = _hmt || [];
18 18
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 uid = uid === 0 ? '' : uid; 56 uid = uid === 0 ? '' : uid;
57 window._ozuid = uid; // 暴露ozuid 57 window._ozuid = uid; // 暴露ozuid
58 if (window._yas) { 58 if (window._yas) {
59 - window._yas(1 * new Date(), '2.3.7', 'yohobuy_m', uid, '', ''); 59 + window._yas(1 * new Date(), '2.3.8', 'yohobuy_m', uid, '', '');
60 } 60 }
61 61
62 setTimeout(function() { 62 setTimeout(function() {
1 { 1 {
2 "name": "m-yohobuy-node", 2 "name": "m-yohobuy-node",
3 - "version": "5.5.10", 3 + "version": "5.5.11",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {
1 -let $ = require('yoho-jquery');  
2 -let Swiper = require('yoho-swiper'); 1 +var $ = require('yoho-jquery');
  2 +var lazyLoad = require('yoho-jquery-lazyload');
  3 +var Swiper = require('yoho-swiper');
  4 +var yoho = require('../yoho-app');
3 5
4 global.jQuery = $; 6 global.jQuery = $;
5 7
6 let isAndroid = /(Android)/i.test(navigator.userAgent); 8 let isAndroid = /(Android)/i.test(navigator.userAgent);
7 let isWechat = /micromessenger/i.test(navigator.userAgent); 9 let isWechat = /micromessenger/i.test(navigator.userAgent);
8 10
  11 +lazyLoad($('img.lazy'));
  12 +
9 function swiperInit() { 13 function swiperInit() {
10 $('.swiper-container').each(function() { 14 $('.swiper-container').each(function() {
11 let opt = { 15 let opt = {
@@ -52,19 +56,27 @@ function topNavInit() { @@ -52,19 +56,27 @@ function topNavInit() {
52 } 56 }
53 57
54 function ceXuanFuInit() { 58 function ceXuanFuInit() {
55 - $('#load_cxf').load('http://feature.yoho.cn/public/cexuanfu/cexuanfu.html', function() {  
56 - $('#cxf').click(function() {  
57 - if ($(this).hasClass('isclick')) {  
58 - $('.cxfall').hide();  
59 - $(this).removeClass('iscxf');  
60 - } else {  
61 - $('.cxfall').show();  
62 - $(this).addClass('iscxf'); 59 + var cxf = $('#sidebar');
  60 + var pageid = cxf.attr('pageid');
  61 +
  62 + if (!pageid) {
  63 + return;
  64 + }
  65 +
  66 + $('#sidebar').load('//activity.yoho.cn/featuresidebar/' + pageid + '.html', function() {
  67 + $('.sidebar-img').click(function() {
  68 + $('.sidebar').show();
  69 + });
  70 + $('.sidebar').click(function(e) {
  71 + var $cur = $(e.target);
  72 +
  73 + if (!$cur.closest('.sidebar-content').length) {
  74 + $(this).hide();
63 } 75 }
64 }); 76 });
65 - $('.cxfallbg').click(function() {  
66 - $(this).parent().hide();  
67 - $('#cxf').removeClass('iscxf'); 77 +
  78 + $('.closesidebar').click(function() {
  79 + $('.sidebar').hide();
68 }); 80 });
69 }); 81 });
70 } 82 }
@@ -99,31 +111,65 @@ function videoInit() { @@ -99,31 +111,65 @@ function videoInit() {
99 } 111 }
100 112
101 function tabInit() { 113 function tabInit() {
102 - let tabContainer = $('.tab-container');  
103 - let nextDom = tabContainer.parent().nextAll();  
104 - let tab = tabContainer.find('a.anchor'); 114 + $('.tab-container').each(function() {
  115 + var tab = $(this).find('a.anchor');
  116 + var tabname = (tab.attr('tab') || '').split('_')[0] + '_';
  117 +
  118 + tab.on('click', function() {
  119 + tab.removeClass('active');
  120 + $(this).addClass('active');
  121 +
  122 + let index = $(this).index() + 1;
  123 +
  124 + for (let i = 1; i <= tab.length; i++) {
  125 + if (index === i) {
  126 + $('div[tabname="' + tabname + i + '"]').show();
  127 + } else {
  128 + $('div[tabname="' + tabname + i + '"]').hide();
  129 + }
  130 + }
  131 + });
105 132
106 - tab.on('click', function() {  
107 - tab.removeClass('active');  
108 - $(this).addClass('active'); 133 + for (let i = 2; i <= tab.length; i++) {
  134 + $('div[tabname="' + tabname + i + '"]').hide();
  135 + }
  136 + });
  137 +}
109 138
110 - let index = $(this).index(); 139 +function modalInit() {
  140 + $('a.modalimg').on('click', function() {
  141 + $($(this).next('.modal')[0]).show();
  142 + });
111 143
112 - for (let i = 0; i < tab.length; i++) {  
113 - if (index === i) {  
114 - $(nextDom[i]).show();  
115 - } else {  
116 - $(nextDom[i]).hide();  
117 - }  
118 - } 144 + $('.modal-close').on('click', function() {
  145 + $($(this).parent().get(0)).hide();
  146 + return false;
119 }); 147 });
120 148
121 - for (let i = 1; i < tab.length; i++) {  
122 - $(nextDom[i]).hide();  
123 - } 149 + $('.modal').on('click', function(e) {
  150 + if (e.target.tagName === 'IMG') {
  151 + return false;
  152 + } else {
  153 + $(this).hide();
  154 + return false;
  155 + }
  156 + });
124 } 157 }
125 158
  159 +
  160 +
126 $(function() { 161 $(function() {
  162 + if ($('.over').length) {
  163 + // 过期/删除 状态的 活动
  164 + setTimeout(function() {
  165 + yoho.goHome();
  166 + }, 3000);
  167 + return false;
  168 + }
  169 +
  170 + // tab
  171 + tabInit();
  172 +
127 // 微信中点击之后,返回跳到指定位置 173 // 微信中点击之后,返回跳到指定位置
128 let totalH, scH; 174 let totalH, scH;
129 let top = localStorage.changtu1; 175 let top = localStorage.changtu1;
@@ -149,6 +195,6 @@ $(function() { @@ -149,6 +195,6 @@ $(function() {
149 // 视频相关 195 // 视频相关
150 videoInit(); 196 videoInit();
151 197
152 - // tab  
153 - tabInit(); 198 + // 模态框
  199 + modalInit();
154 }); 200 });
@@ -102,12 +102,11 @@ yoho = { @@ -102,12 +102,11 @@ yoho = {
102 i; 102 i;
103 103
104 url = (url || '').split('?'); 104 url = (url || '').split('?');
105 - hashs = url[1].split('&'); 105 + hashs = (url[1] || '').split('&');
106 106
107 if (hashs && hashs.length) { 107 if (hashs && hashs.length) {
108 for (i = 0; i < hashs.length; i++) { 108 for (i = 0; i < hashs.length; i++) {
109 hash = hashs[i].split('='); 109 hash = hashs[i].split('=');
110 - console.log(hashs[i]);  
111 query[hash[0]] = hash[1]; 110 query[hash[0]] = hash[1];
112 } 111 }
113 } 112 }
@@ -174,6 +173,19 @@ yoho = { @@ -174,6 +173,19 @@ yoho = {
174 $appLink.attr('href', url); 173 $appLink.attr('href', url);
175 $appLink[0].click(); 174 $appLink[0].click();
176 return false; 175 return false;
  176 + },
  177 +
  178 + goHome: function() {
  179 + var url = '//m.yohobuy.com/';
  180 +
  181 + if (yoho.isApp) {
  182 + url = url + '?openby:yohobuy=' + JSON.stringify({
  183 + action: 'go.home'
  184 + });
  185 + }
  186 + $appLink.attr('href', url);
  187 + $appLink[0].click();
  188 + return false;
177 } 189 }
178 }; 190 };
179 191
@@ -150,3 +150,157 @@ body { @@ -150,3 +150,157 @@ body {
150 height: 100%; 150 height: 100%;
151 } 151 }
152 } 152 }
  153 +
  154 +.video {
  155 + position: fixed;
  156 + top: -100%;
  157 + width: 100%;
  158 + height: 360px;
  159 + z-index: 3;
  160 +
  161 + &.android {
  162 + top: 30%;
  163 + z-index: 1002;
  164 + }
  165 +}
  166 +
  167 +.video-android-bg {
  168 + position: fixed;
  169 + top: 0;
  170 + left: 0;
  171 + right: 0;
  172 + bottom: 0;
  173 + width: 100%;
  174 + height: 100%;
  175 + z-index: 1001;
  176 + background: #000;
  177 + opacity: 0.7;
  178 +}
  179 +
  180 +.video-android-close {
  181 + position: fixed;
  182 + top: 26.2%;
  183 + right: 10px;
  184 + width: 35px;
  185 + height: 35px;
  186 + z-index: 1003;
  187 + background-image: resolve("activity/close.png");
  188 + background-size: cover;
  189 +}
  190 +
  191 +.feature-page .modal {
  192 + position: fixed;
  193 + width: 100%;
  194 + height: 100%;
  195 + top: 0;
  196 + left: 0;
  197 + margin: 0 auto;
  198 + z-index: 1001;
  199 + background: rgba(0, 0, 0, 0.5);
  200 + display: none;
  201 +}
  202 +
  203 +.feature-page .modal .modal-close {
  204 + position: absolute;
  205 + display: inline-block;
  206 + top: 20%;
  207 + right: 5%;
  208 + width: 45px;
  209 + height: 45px;
  210 + overflow: hidden;
  211 + border-radius: 50px;
  212 + background: black;
  213 + opacity: 0.5;
  214 + z-index: 100;
  215 +}
  216 +
  217 +.feature-page .modal .modal-close:before,
  218 +.feature-page .modal .modal-close:after {
  219 + content: "";
  220 + position: absolute;
  221 + width: 80%;
  222 + top: 50%;
  223 + left: 10%;
  224 + height: 6px;
  225 + margin-top: -3px;
  226 + border-radius: 5px;
  227 + background: #fff;
  228 +}
  229 +
  230 +.feature-page .modal .modal-close:before {
  231 + transform: rotate(45deg);
  232 +}
  233 +
  234 +.feature-page .modal .modal-close:after {
  235 + transform: rotate(-45deg);
  236 +}
  237 +
  238 +.feature-page .modal .modal-img {
  239 + position: absolute;
  240 + height: auto;
  241 + top: 20%;
  242 + left: 50%;
  243 + width: 90%;
  244 + transform: translateX(-50%);
  245 +}
  246 +
  247 +.feature-page .sidebar {
  248 + position: fixed;
  249 + width: 100%;
  250 + height: 100%;
  251 + top: 0;
  252 + left: 0;
  253 + margin: 0 auto;
  254 + display: none;
  255 + background: rgba(0, 0, 0, 0.5);
  256 + z-index: 1000;
  257 +}
  258 +
  259 +.feature-page .sidebar-content {
  260 + position: fixed;
  261 + display: block;
  262 + top: 50%;
  263 + right: 0;
  264 + width: 242px;
  265 + margin-top: -407px;
  266 + z-index: 1001;
  267 +}
  268 +
  269 +.feature-page .sidebar-item {
  270 + position: relative;
  271 +
  272 + img {
  273 + display: block;
  274 + width: 100%;
  275 + }
  276 +
  277 + a {
  278 + position: absolute;
  279 + }
  280 +}
  281 +
  282 +.feature-page .sidebar-img {
  283 + position: fixed;
  284 + display: block;
  285 + top: 50%;
  286 + right: 0;
  287 + width: 140px;
  288 + height: 150px;
  289 + margin-top: -75px;
  290 + z-index: 999;
  291 +}
  292 +
  293 +.feature-page .over {
  294 + position: fixed;
  295 + top: 50%;
  296 + left: 50%;
  297 + width: 100%;
  298 + transform: translate(-50%, -50%);
  299 + text-align: center;
  300 + font-size: 28px;
  301 + color: #000;
  302 +
  303 + p {
  304 + margin-bottom: 20px;
  305 + }
  306 +}
1 -.video {  
2 - position: fixed;  
3 - top: -100%;  
4 - width: 100%;  
5 - height: 360px;  
6 - z-index: 3;  
7 -  
8 - &.android {  
9 - top: 30%;  
10 - z-index: 1002;  
11 - }  
12 -}  
13 1
14 -.video-android-bg {  
15 - position: fixed;  
16 - top: 0;  
17 - left: 0;  
18 - right: 0;  
19 - bottom: 0;  
20 - width: 100%;  
21 - height: 100%;  
22 - z-index: 1001;  
23 - background: #000;  
24 - opacity: 0.7;  
25 -}  
26 -  
27 -.video-android-close {  
28 - position: fixed;  
29 - top: 26.2%;  
30 - right: 10px;  
31 - width: 35px;  
32 - height: 35px;  
33 - z-index: 1003;  
34 - background-image: resolve("activity/close.png");  
35 - background-size: cover;  
36 -}  
37 2
38 .product-container { 3 .product-container {
39 overflow: hidden; 4 overflow: hidden;
@@ -56,12 +21,14 @@ @@ -56,12 +21,14 @@
56 height: 257px; 21 height: 257px;
57 } 22 }
58 23
59 - .price { 24 + .price,
  25 + .vipprice {
60 line-height: 34px; 26 line-height: 34px;
61 height: 34px; 27 height: 34px;
62 } 28 }
63 29
64 - .sale-price { 30 + .sale-price,
  31 + .vipprice {
65 font-size: 26px; 32 font-size: 26px;
66 } 33 }
67 } 34 }
@@ -132,7 +99,7 @@ @@ -132,7 +99,7 @@
132 position: absolute; 99 position: absolute;
133 left: 0; 100 left: 0;
134 top: 0; 101 top: 0;
135 - width: 40%; 102 + width: 100%;
136 height: auto; 103 height: auto;
137 z-index: 1; 104 z-index: 1;
138 } 105 }
@@ -141,11 +108,25 @@ @@ -141,11 +108,25 @@
141 position: absolute; 108 position: absolute;
142 right: 0; 109 right: 0;
143 top: 0; 110 top: 0;
144 - width: 40%; 111 + width: 100%;
145 height: auto; 112 height: auto;
146 z-index: 1; 113 z-index: 1;
147 } 114 }
148 115
  116 + .vipprice {
  117 + line-height: 40px;
  118 + height: 40px;
  119 + white-space: nowrap;
  120 + text-align: center;
  121 + font-size: 26px;
  122 + color: #000;
  123 + }
  124 +
  125 + .vip-price-text {
  126 + margin-right: 10px;
  127 + font-weight: 500;
  128 + }
  129 +
149 .price { 130 .price {
150 font-size: 18px; 131 font-size: 18px;
151 line-height: 40px; 132 line-height: 40px;
@@ -35,6 +35,13 @@ module.exports = { @@ -35,6 +35,13 @@ module.exports = {
35 } 35 }
36 return JSON.stringify(fp); 36 return JSON.stringify(fp);
37 }, 37 },
  38 + isLazyLoad: function(type, index, opt) {
  39 + if (type !== 'fix' && index > 8) { // 活动页中 不是浮动层及8张图后面的采用懒加载
  40 + return opt.fn(this); // eslint-disable-line
  41 + } else {
  42 + return opt.inverse(this); // eslint-disable-line
  43 + }
  44 + },
38 styleFormat: function(styleObj, opts) { 45 styleFormat: function(styleObj, opts) {
39 let style = ''; 46 let style = '';
40 47
@@ -50,6 +57,11 @@ module.exports = { @@ -50,6 +57,11 @@ module.exports = {
50 } 57 }
51 return style; 58 return style;
52 }, 59 },
  60 + tabName: function(index, tabnames) {
  61 + var names = tabnames.split(',');
  62 +
  63 + return names[index];
  64 + },
53 tabStyle: function(index, count) { 65 tabStyle: function(index, count) {
54 let width = (100 / Number(count)).toFixed(2); 66 let width = (100 / Number(count)).toFixed(2);
55 let style = 'height:100%;width:' + width + '%;'; 67 let style = 'height:100%;width:' + width + '%;';