合并master 解决冲突
Showing
95 changed files
with
2278 additions
and
566 deletions
Too many changes to show.
To preserve performance only 95 of 95+ files are displayed.
@@ -109,6 +109,7 @@ const getPlatForm = (req) => { | @@ -109,6 +109,7 @@ const getPlatForm = (req) => { | ||
109 | if (yoho.app_version) { | 109 | if (yoho.app_version) { |
110 | yoho.app_version = _.toString(yoho.app_version); | 110 | yoho.app_version = _.toString(yoho.app_version); |
111 | arrs = yoho.app_version.split('.'); | 111 | arrs = yoho.app_version.split('.'); |
112 | + | ||
112 | // if (arrs.length > 2) { | 113 | // if (arrs.length > 2) { |
113 | // if (arrs[0] && +arrs[0] < 4) { | 114 | // if (arrs[0] && +arrs[0] < 4) { |
114 | // isNewVersion = false; | 115 | // isNewVersion = false; |
@@ -250,11 +250,15 @@ const _getContent = (data, isApp) => { | @@ -250,11 +250,15 @@ const _getContent = (data, isApp) => { | ||
250 | if (fun === 'getCoupon' && data[i].data.length && _.has(data[i - 1], 'template_name') && data[i - 1].template_name === 'text') { | 250 | if (fun === 'getCoupon' && data[i].data.length && _.has(data[i - 1], 'template_name') && data[i - 1].template_name === 'text') { |
251 | data[i].data[0].floorTitle = data[i - 1].data; | 251 | data[i].data[0].floorTitle = data[i - 1].data; |
252 | } | 252 | } |
253 | + | ||
253 | build = processFun[fun](data[i].data, isApp); | 254 | build = processFun[fun](data[i].data, isApp); |
254 | if (!build) { | 255 | if (!build) { |
255 | continue; | 256 | continue; |
256 | } | 257 | } |
257 | - result.push(build); | 258 | + result.push(_.assign({ |
259 | + templateName: data[i].templateName || data[i].template_name, | ||
260 | + templateId: data[i].templateId || data[i].template_id | ||
261 | + }, build)); | ||
258 | } | 262 | } |
259 | build = []; | 263 | build = []; |
260 | return result; | 264 | return result; |
1 | <div class="coupon-area-page yoho-page"> | 1 | <div class="coupon-area-page yoho-page"> |
2 | {{# content}} | 2 | {{# content}} |
3 | {{#if isSingleImage}} | 3 | {{#if isSingleImage}} |
4 | - <a href="{{url}}"><img src="{{image src 0 0}}" class="just-img"/></a> | 4 | + <div data-id="{{templateId}}" data-floor-name="{{templateName}}" class="floor"> |
5 | + <a href="{{url}}"><img src="{{image src 0 0}}" class="just-img"/></a> | ||
6 | + </div> | ||
5 | {{/if}} | 7 | {{/if}} |
6 | {{#if isCarouselBanner}} | 8 | {{#if isCarouselBanner}} |
7 | - {{> resources/banner-top}} | 9 | + <div data-id="{{templateId}}" data-floor-name="{{templateName}}" class="floor-focus"> |
10 | + {{> resources/banner-top}} | ||
11 | + </div> | ||
8 | {{/if}} | 12 | {{/if}} |
9 | {{#if isFocus}} | 13 | {{#if isFocus}} |
10 | - {{> resources/banner-top}} | 14 | + <div data-id="{{templateId}}" data-floor-name="{{templateName}}" class="floor-focus"> |
15 | + {{> resources/banner-top}} | ||
16 | + </div> | ||
11 | {{/if}} | 17 | {{/if}} |
12 | {{#if isCoupon}} | 18 | {{#if isCoupon}} |
13 | - <div class="coupon-floor" coupon-id="{{couponID}}"> | ||
14 | - {{#if showFloorTitle}} | ||
15 | - <div class="floor-title"> | ||
16 | - {{floorTitle}} | ||
17 | - </div> | ||
18 | - {{/if}} | ||
19 | - <div class="floor-main" id="{{couponID}}" style="background-image: url({{image.src}});"> | ||
20 | - <a href="{{image.url}}" class="main-left"></a> | ||
21 | - <div class="main-right-receive"> | ||
22 | - <span class="on-receive"></span> | 19 | + <div data-id="{{templateId}}" data-floor-name="{{templateName}}" class="floor"> |
20 | + <div class="coupon-floor" coupon-id="{{couponID}}"> | ||
21 | + {{#if showFloorTitle}} | ||
22 | + <div class="floor-title"> | ||
23 | + {{floorTitle}} | ||
24 | + </div> | ||
25 | + {{/if}} | ||
26 | + <div class="floor-main" id="{{couponID}}" style="background-image: url({{image.src}});"> | ||
27 | + <a href="{{image.url}}" class="main-left"></a> | ||
28 | + <div class="main-right-receive"> | ||
29 | + <span class="on-receive"></span> | ||
30 | + </div> | ||
31 | + <a href="{{image.url}}" class="main-right-use hidden"> | ||
32 | + <span class="received"></span> | ||
33 | + </a> | ||
34 | + <a href="{{image.url}}" class="main-right-go hidden"> | ||
35 | + <span class="zero"></span> | ||
36 | + </a> | ||
23 | </div> | 37 | </div> |
24 | - <a href="{{image.url}}" class="main-right-use hidden"> | ||
25 | - <span class="received"></span> | ||
26 | - </a> | ||
27 | - <a href="{{image.url}}" class="main-right-go hidden"> | ||
28 | - <span class="zero"></span> | ||
29 | - </a> | ||
30 | </div> | 38 | </div> |
31 | </div> | 39 | </div> |
32 | {{/if}} | 40 | {{/if}} |
@@ -50,6 +58,7 @@ | @@ -50,6 +58,7 @@ | ||
50 | <input id="appurl" type="hidden" value="{{appUrl}}"> | 58 | <input id="appurl" type="hidden" value="{{appUrl}}"> |
51 | <input id="wapurl" type="hidden" value="{{wapUrl}}"> | 59 | <input id="wapurl" type="hidden" value="{{wapUrl}}"> |
52 | {{/ noLoginUrl}} | 60 | {{/ noLoginUrl}} |
61 | + {{> common/suspend-home}} | ||
53 | </div> | 62 | </div> |
54 | <div class="floor-mask"></div> | 63 | <div class="floor-mask"></div> |
55 | <div class="floor-message"> | 64 | <div class="floor-message"> |
@@ -2,6 +2,11 @@ | @@ -2,6 +2,11 @@ | ||
2 | <div class="ma-header"> | 2 | <div class="ma-header"> |
3 | <div>{{headerTip}}</div> | 3 | <div>{{headerTip}}</div> |
4 | </div> | 4 | </div> |
5 | + {{# download}} | ||
6 | + <a href="{{url}}" class="down"> | ||
7 | + <img src="{{img}}" alt="{{alt}}" /> | ||
8 | + </a> | ||
9 | + {{/ download}} | ||
5 | <div class="tab"> | 10 | <div class="tab"> |
6 | <div class="swiper-container"> | 11 | <div class="swiper-container"> |
7 | <div class="swiper-wrapper"> | 12 | <div class="swiper-wrapper"> |
@@ -42,9 +47,4 @@ | @@ -42,9 +47,4 @@ | ||
42 | <p>{{title}}</p> | 47 | <p>{{title}}</p> |
43 | </div> | 48 | </div> |
44 | {{/ newsList}} | 49 | {{/ newsList}} |
45 | - {{# download}} | ||
46 | - <a href="{{url}}" class="down"> | ||
47 | - <img src="{{img}}" alt="{{alt}}" /> | ||
48 | - </a> | ||
49 | - {{/ download}} | ||
50 | </div> | 50 | </div> |
@@ -115,6 +115,9 @@ | @@ -115,6 +115,9 @@ | ||
115 | {{# isLimited}} | 115 | {{# isLimited}} |
116 | <p class="good-tag limit-tag">限量</p> | 116 | <p class="good-tag limit-tag">限量</p> |
117 | {{/ isLimited}} | 117 | {{/ isLimited}} |
118 | + {{# isPresell}} | ||
119 | + <p class="good-tag is-presell">预售</p> | ||
120 | + {{/ isPresell}} | ||
118 | {{/ tags}} | 121 | {{/ tags}} |
119 | </div> | 122 | </div> |
120 | <div class="good-detail-img"> | 123 | <div class="good-detail-img"> |
@@ -44,6 +44,9 @@ | @@ -44,6 +44,9 @@ | ||
44 | {{# isLimited}} | 44 | {{# isLimited}} |
45 | <p class="good-tag limit-tag">限量</p> | 45 | <p class="good-tag limit-tag">限量</p> |
46 | {{/ isLimited}} | 46 | {{/ isLimited}} |
47 | + {{# isPresell}} | ||
48 | + <p class="good-tag is-presell">预售</p> | ||
49 | + {{/ isPresell}} | ||
47 | {{/ tags}} | 50 | {{/ tags}} |
48 | </div> | 51 | </div> |
49 | <div class="good-detail-img"> | 52 | <div class="good-detail-img"> |
apps/cart/controllers/pay.js
0 → 100644
1 | +/** | ||
2 | + * 支付成功页 | ||
3 | + * @author: jing.li<jing.li@yoho.cn> | ||
4 | + * @date: 2016/10/25 | ||
5 | + */ | ||
6 | + | ||
7 | +'use strict'; | ||
8 | + | ||
9 | +const mRoot = '../models'; | ||
10 | +const payModel = require(`${mRoot}/pay`); | ||
11 | +const headerModel = require('../../../doraemon/models/header'); // 头部model | ||
12 | + | ||
13 | +// 货到付款 | ||
14 | +const payCod = (req, res, next) => { | ||
15 | + let headerData = headerModel.setNav({ | ||
16 | + navTitle: '支付完成' | ||
17 | + }); | ||
18 | + | ||
19 | + let responseData = { | ||
20 | + pageHeader: headerData, | ||
21 | + module: 'cart', | ||
22 | + page: 'pay', | ||
23 | + title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停' | ||
24 | + }; | ||
25 | + | ||
26 | + let param = { | ||
27 | + uid: req.user.uid, | ||
28 | + udid: req.sessionID || require('md5')(req.ip) || 'yoho', | ||
29 | + orderCode: req.query.order_code, | ||
30 | + contentCode: '05afedf76886d732573f10f7451a1703' | ||
31 | + }; | ||
32 | + | ||
33 | + // 如果没有uid,跳转到首页 | ||
34 | + if (!param.uid) { | ||
35 | + res.redirect('/'); | ||
36 | + return; | ||
37 | + } | ||
38 | + | ||
39 | + payModel.getPayCod(param).then(result => { | ||
40 | + if (result.match === true) { | ||
41 | + res.render('pay/pay-cod', Object.assign(responseData, result)); | ||
42 | + } else { | ||
43 | + res.redirect('/'); | ||
44 | + } | ||
45 | + | ||
46 | + }).catch(next); | ||
47 | +}; | ||
48 | + | ||
49 | +// 支付宝支付 | ||
50 | +const payAli = (req, res, next) => { | ||
51 | + let headerData = headerModel.setNav({ | ||
52 | + navTitle: '支付完成' | ||
53 | + }); | ||
54 | + | ||
55 | + let responseData = { | ||
56 | + pageHeader: headerData, | ||
57 | + module: 'cart', | ||
58 | + page: 'pay', | ||
59 | + title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停' | ||
60 | + }; | ||
61 | + | ||
62 | + let param = { | ||
63 | + uid: req.user.uid, | ||
64 | + udid: req.sessionID || require('md5')(req.ip) || 'yoho', | ||
65 | + orderCode: req.query.out_trade_no, | ||
66 | + contentCode: '05afedf76886d732573f10f7451a1703' | ||
67 | + }; | ||
68 | + | ||
69 | + // 如果没有uid,跳转到首页 | ||
70 | + if (!param.uid) { | ||
71 | + res.redirect('/'); | ||
72 | + return; | ||
73 | + } | ||
74 | + | ||
75 | + payModel.getPayAli(param).then(result => { | ||
76 | + if (result.match === true) { | ||
77 | + res.render('pay/pay-ali', Object.assign(responseData, result)); | ||
78 | + } else { | ||
79 | + res.redirect('/'); | ||
80 | + } | ||
81 | + | ||
82 | + }).catch(next); | ||
83 | +}; | ||
84 | + | ||
85 | +module.exports = { | ||
86 | + payCod, | ||
87 | + payAli | ||
88 | +}; |
1 | /** | 1 | /** |
2 | +<<<<<<< HEAD | ||
2 | * sub app cart | 3 | * sub app cart |
3 | * @author: xuan.chen@yoho.cn<xuan.chen@yoho.cn> | 4 | * @author: xuan.chen@yoho.cn<xuan.chen@yoho.cn> |
4 | * @date: 2016/09/26 | 5 | * @date: 2016/09/26 |
6 | +======= | ||
7 | + * sub app guang | ||
8 | + * @author: Bi Kai<kai.bi@yoho.cn> | ||
9 | + * @date: 2016/05/09 | ||
10 | +>>>>>>> feature/payment | ||
5 | */ | 11 | */ |
6 | 12 | ||
7 | var express = require('express'), | 13 | var express = require('express'), |
apps/cart/models/pay.js
0 → 100644
1 | +/** | ||
2 | + * 支付成功页 | ||
3 | + * @author: jing.li<jing.li@yoho.cn> | ||
4 | + * @date: 2016/10/25 | ||
5 | + */ | ||
6 | + | ||
7 | +'use strict'; | ||
8 | + | ||
9 | +const api = global.yoho.API; | ||
10 | +const serviceAPI = global.yoho.ServiceAPI; | ||
11 | +const utils = '../../../utils'; | ||
12 | +const productProcess = require(`${utils}/product-process`); | ||
13 | + | ||
14 | +// 资源位 | ||
15 | +const _getBanner = (param) => { | ||
16 | + return serviceAPI.get('operations/api/v5/resource/get', { | ||
17 | + content_code: param.contentCode | ||
18 | + }, { | ||
19 | + code: 200 | ||
20 | + }).then((result) => { | ||
21 | + | ||
22 | + result = result.data; | ||
23 | + | ||
24 | + return result; | ||
25 | + }); | ||
26 | +}; | ||
27 | + | ||
28 | +// 购买此商品的用户也购买了 | ||
29 | +const _getOthersBuy2 = (param) => { | ||
30 | + return api.get('', { | ||
31 | + method: 'app.recommend.purchased', | ||
32 | + productSkn: param.skn, | ||
33 | + udid: param.uid, | ||
34 | + rec_pos: '100005', | ||
35 | + limit: 2 | ||
36 | + }, { | ||
37 | + code: 200 | ||
38 | + }).then((result) => { | ||
39 | + | ||
40 | + if (result && result.data && result.data.product_list) { | ||
41 | + return productProcess.processProductList(result.data.product_list); | ||
42 | + } | ||
43 | + | ||
44 | + }); | ||
45 | +}; | ||
46 | + | ||
47 | +// 订单信息 | ||
48 | +const _getOtherDetail = (param) => { | ||
49 | + return api.get('', { | ||
50 | + method: 'app.SpaceOrders.detail', | ||
51 | + uid: param.uid, | ||
52 | + order_code: param.orderCode | ||
53 | + }, { | ||
54 | + code: 200 | ||
55 | + }).then((result) => { | ||
56 | + | ||
57 | + return result; | ||
58 | + | ||
59 | + }); | ||
60 | +}; | ||
61 | + | ||
62 | +// 购买此商品的用户也购买了,要先从订单详情获取商品skn | ||
63 | +const _getOthersBuy = (param) => { | ||
64 | + return api.all([ | ||
65 | + _getOtherDetail(param) | ||
66 | + ]).then((result) => { | ||
67 | + | ||
68 | + let goodSkn = ''; | ||
69 | + | ||
70 | + if (result && result[0] && result[0].data && result[0].data.order_goods) { | ||
71 | + goodSkn = result[0].data.order_goods[0].product_skn; | ||
72 | + } | ||
73 | + | ||
74 | + return _getOthersBuy2(Object.assign(param, {skn: goodSkn})); | ||
75 | + | ||
76 | + }).then((result) => { | ||
77 | + | ||
78 | + return result; | ||
79 | + }); | ||
80 | +}; | ||
81 | + | ||
82 | +// 货到付款 | ||
83 | +const getPayCod = (param) => { | ||
84 | + return api.all([ | ||
85 | + _getBanner(param), | ||
86 | + _getOthersBuy(param), | ||
87 | + _getOtherDetail(param) | ||
88 | + ]).then((result) => { | ||
89 | + | ||
90 | + let resu = { | ||
91 | + match: true, | ||
92 | + banner: [], | ||
93 | + othersBuy: [] | ||
94 | + }; | ||
95 | + | ||
96 | + if (result && result[0]) { | ||
97 | + resu.banner = result[0]; | ||
98 | + } | ||
99 | + | ||
100 | + if (result && result[1]) { | ||
101 | + resu.othersBuy = result[1]; | ||
102 | + } | ||
103 | + | ||
104 | + if (result && result[2] && result[2].data && result[2].data.payment_amount) { | ||
105 | + resu.payment = result[2].data.payment_amount; | ||
106 | + } else { | ||
107 | + resu.match = false; | ||
108 | + } | ||
109 | + | ||
110 | + resu.orderCode = param.orderCode; | ||
111 | + | ||
112 | + resu.orderUrl = '/home/orders/detail?order_code=' + param.orderCode; | ||
113 | + | ||
114 | + return resu; | ||
115 | + }); | ||
116 | +}; | ||
117 | + | ||
118 | +// 支付宝支付 | ||
119 | +const getPayAli = (param) => { | ||
120 | + return api.all([ | ||
121 | + _getBanner(param), | ||
122 | + _getOthersBuy(param), | ||
123 | + _getOtherDetail(param) | ||
124 | + ]).then((result) => { | ||
125 | + | ||
126 | + let resu = { | ||
127 | + match: true, | ||
128 | + banner: [], | ||
129 | + othersBuy: [] | ||
130 | + }; | ||
131 | + | ||
132 | + if (result && result[0]) { | ||
133 | + resu.banner = result[0]; | ||
134 | + } | ||
135 | + | ||
136 | + if (result && result[1]) { | ||
137 | + resu.othersBuy = result[1]; | ||
138 | + } | ||
139 | + | ||
140 | + if (result && result[2] && result[2].data && result[2].data.payment_amount) { | ||
141 | + resu.payment = result[2].data.payment_amount; | ||
142 | + } else { | ||
143 | + resu.match = false; | ||
144 | + } | ||
145 | + | ||
146 | + resu.orderCode = param.orderCode; | ||
147 | + | ||
148 | + resu.orderUrl = '/home/orders/detail?order_code=' + param.orderCode; | ||
149 | + | ||
150 | + return resu; | ||
151 | + }); | ||
152 | +}; | ||
153 | + | ||
154 | +module.exports = { | ||
155 | + getPayCod, | ||
156 | + getPayAli | ||
157 | +}; |
@@ -39,7 +39,13 @@ exports.compute = options => { | @@ -39,7 +39,13 @@ exports.compute = options => { | ||
39 | method: 'app.Seckill.compute', | 39 | method: 'app.Seckill.compute', |
40 | }, options); | 40 | }, options); |
41 | 41 | ||
42 | - return API.post(url, queryData); | 42 | + return API.post(url, queryData).then(result => { |
43 | + // TODO 数据处理 | ||
44 | + if (result.code === 200 && result.data) { | ||
45 | + result.data.yohoCoinCompute = paymentProcess.yohoCoinCompute(result.data); | ||
46 | + } | ||
47 | + return result; | ||
48 | + }); | ||
43 | }; | 49 | }; |
44 | 50 | ||
45 | 51 |
@@ -12,6 +12,7 @@ const authMW = require('../../doraemon/middleware/auth'); | @@ -12,6 +12,7 @@ const authMW = require('../../doraemon/middleware/auth'); | ||
12 | 12 | ||
13 | const seckill = require(cRoot + '/seckill'); | 13 | const seckill = require(cRoot + '/seckill'); |
14 | const countController = require(`${cRoot}/count`); | 14 | const countController = require(`${cRoot}/count`); |
15 | +const payController = require(`${cRoot}/pay`); | ||
15 | 16 | ||
16 | // Your controller here | 17 | // Your controller here |
17 | router.all('/index/seckill/', authMW); | 18 | router.all('/index/seckill/', authMW); |
@@ -21,5 +22,7 @@ router.post('/index/seckill/compute', seckill.compute); | @@ -21,5 +22,7 @@ router.post('/index/seckill/compute', seckill.compute); | ||
21 | router.post('/index/seckill/submit', seckill.submit); | 22 | router.post('/index/seckill/submit', seckill.submit); |
22 | 23 | ||
23 | router.get('/index/count', countController.cartCount); | 24 | router.get('/index/count', countController.cartCount); |
25 | +router.get('/paySuccess/payCod', payController.payCod);// 支付成功,货到付款 | ||
26 | +router.get('/shopping/pay/aliwapreturn', payController.payAli);// 支付成功,支付宝付款 | ||
24 | 27 | ||
25 | module.exports = router; | 28 | module.exports = router; |
@@ -66,11 +66,12 @@ | @@ -66,11 +66,12 @@ | ||
66 | <i class="iconfont hide up"></i> | 66 | <i class="iconfont hide up"></i> |
67 | </h3> | 67 | </h3> |
68 | <ul> | 68 | <ul> |
69 | + <li class="dispatch-time-info">快递公司会尽力按您选择的送货时间配送,如遇特殊情况(天气、环境等)无法按您要求时间配送,还请您谅解。</li> | ||
69 | {{#each dispatchTime}} | 70 | {{#each dispatchTime}} |
70 | - <li {{#if isSelected}}class="chosed"{{/if}} data-id="{{id}}"> | ||
71 | - <span>{{name}}</span> | ||
72 | - <i class="right iconfont radio {{#if isSelected}}icon-cb-radio{{else}}icon-radio{{/if}}" ></i> | ||
73 | - </li> | 71 | + <li {{#if isSelected}}class="chosed"{{/if}} data-id="{{id}}"> |
72 | + <span>{{name}}</span> | ||
73 | + <i class="right iconfont radio {{#if isSelected}}icon-cb-radio{{else}}icon-radio{{/if}}" ></i> | ||
74 | + </li> | ||
74 | {{/each}} | 75 | {{/each}} |
75 | </ul> | 76 | </ul> |
76 | </div> | 77 | </div> |
@@ -111,28 +112,18 @@ | @@ -111,28 +112,18 @@ | ||
111 | </a> | 112 | </a> |
112 | </li> | 113 | </li> |
113 | {{/if}} | 114 | {{/if}} |
114 | - <li class="coin" data-yoho-coin="{{yohoCoin}}"> | 115 | + <li class="coin" data-yoho-coin="{{yohoCoinCompute.yohoCoin}}" data-yoho-coin-click={{yohoCoinCompute.yohoCoinClick}}> |
115 | <span class="title">有货币</span> | 116 | <span class="title">有货币</span> |
116 | - | ||
117 | - {{#if yohoCoin}} | ||
118 | - <span class="desc used {{#unless useYohoCoin}}hide{{/unless}}">已抵¥{{useYohoCoin}}</span> | ||
119 | - <span class="desc can-use {{#if useYohoCoin}}hide{{/if}}">可抵¥{{yohoCoin}}</span> | ||
120 | - | ||
121 | - {{#if useYohoCoin}} | ||
122 | - <span class="coin-check"> | ||
123 | - <!-- <em>- ¥ {{useYohoCoin}}</em> --> | ||
124 | - <i class="iconfont checkbox icon-cb-radio"></i> | ||
125 | - </span> | 117 | + <span class="desc msg">{{yohoCoinCompute.yohoCoinMsg}}</span> |
118 | + <span class="yoho-coin-help">?</span> | ||
119 | + {{#if yohoCoinCompute.useYohoCoin}} | ||
120 | + <span class="coin-check"> | ||
121 | + <i class="iconfont checkbox icon-cb-radio"></i> | ||
122 | + </span> | ||
126 | {{else}} | 123 | {{else}} |
127 | - <span class="coin-check"> | ||
128 | - <!-- <em style="display: none;">- ¥ {{useYohoCoin}}</em> --> | ||
129 | - <i class="iconfont checkbox icon-radio"></i> | ||
130 | - </span> | ||
131 | - {{/if}} | ||
132 | - {{^}} | ||
133 | - <span class="not-used coin-check"> | ||
134 | - 无有货币可用 | ||
135 | - </span> | 124 | + <span class="coin-check"> |
125 | + <i class="iconfont checkbox icon-radio"></i> | ||
126 | + </span> | ||
136 | {{/if}} | 127 | {{/if}} |
137 | </li> | 128 | </li> |
138 | 129 | ||
@@ -190,6 +181,18 @@ | @@ -190,6 +181,18 @@ | ||
190 | <a href="javascript:;">提交订单</a> | 181 | <a href="javascript:;">提交订单</a> |
191 | </div> | 182 | </div> |
192 | 183 | ||
184 | + <div class="yoho-coin-help-dialog-bg hide"></div> | ||
185 | + <div class="yoho-coin-help-dialog hide"> | ||
186 | + <div class="yoho-coin-title">有货币使用条件:</div> | ||
187 | + <div class="yoho-coin-content"> | ||
188 | + <p>1.订单金额大于20元(含)</p> | ||
189 | + <p>2.有货币数量大于{{yohoCoinCompute.yoho_coin_pay_rule.num_limit}}个(含)</p> | ||
190 | + <p>3.有货币支付不得超过每笔订单应付金额的{{yohoCoinCompute.yoho_coin_pay_rule.max_pay_rate_desc}}</p> | ||
191 | + <p>备注:使用有货币数量为{{yohoCoinCompute.yoho_coin_pay_rule.num_limit}}的整数倍,100有货币抵1元。</p> | ||
192 | + </div> | ||
193 | + <div class="yoho-coin-footer">知道了</div> | ||
194 | + </div> | ||
195 | + | ||
193 | <input type="hidden" id="product-sku" name="product-sku" value="{{sku}}"> | 196 | <input type="hidden" id="product-sku" name="product-sku" value="{{sku}}"> |
194 | {{#with seckill}} | 197 | {{#with seckill}} |
195 | <input type="hidden" id="activity-id" name="activity-id" value="{{activityId}}"> | 198 | <input type="hidden" id="activity-id" name="activity-id" value="{{activityId}}"> |
apps/cart/views/action/pay/pay-ali.hbs
0 → 100644
1 | +<div class="pay-success"> | ||
2 | + <div class="top-tip"> | ||
3 | + <div class="img-c"></div> | ||
4 | + <p class="ok-tip">恭喜您,付款成功!</p> | ||
5 | + </div> | ||
6 | + <div class="info-table-c"> | ||
7 | + <table class="info-table"> | ||
8 | + <tr> | ||
9 | + <td>订单编号</td> | ||
10 | + <td>{{orderCode}}</td> | ||
11 | + </tr> | ||
12 | + <tr> | ||
13 | + <td>付款金额</td> | ||
14 | + <td>¥{{payment}}</td> | ||
15 | + </tr> | ||
16 | + <tr> | ||
17 | + <td>付款方式</td> | ||
18 | + <td>支付宝</td> | ||
19 | + </tr> | ||
20 | + </table> | ||
21 | + </div> | ||
22 | + <div class="btn-c"> | ||
23 | + <a href="/">随便逛逛</a> | ||
24 | + <a href="{{orderUrl}}">查看订单</a> | ||
25 | + </div> | ||
26 | + {{# banner}} | ||
27 | + {{#data}} | ||
28 | + <a href="{{url}}" class="ad-pic" alt="{{alt}}"> | ||
29 | + <img src="{{image src 640 200}}" /> | ||
30 | + </a> | ||
31 | + {{/data}} | ||
32 | + {{/banner}} | ||
33 | + <div class="others-buy clearfix"> | ||
34 | + <p>购买此商品的用户也购买了</p> | ||
35 | + {{# othersBuy}} | ||
36 | + {{> common/goods}} | ||
37 | + {{/ othersBuy}} | ||
38 | + </div> | ||
39 | + {{> home/maybe-like}} | ||
40 | +</div> | ||
41 | + |
apps/cart/views/action/pay/pay-cod.hbs
0 → 100644
1 | +<div class="pay-success"> | ||
2 | + <div class="top-tip"> | ||
3 | + <div class="img-c"></div> | ||
4 | + <p class="ok-tip">订单提交成功</p> | ||
5 | + <p class="left-tip">您需要在收货时向售货员支付¥{{payment}}</p> | ||
6 | + </div> | ||
7 | + <div class="info-table-c"> | ||
8 | + <table class="info-table"> | ||
9 | + <tr> | ||
10 | + <td>订单编号</td> | ||
11 | + <td>{{orderCode}}</td> | ||
12 | + </tr> | ||
13 | + <tr> | ||
14 | + <td>付款金额</td> | ||
15 | + <td>¥{{payment}}</td> | ||
16 | + </tr> | ||
17 | + <tr> | ||
18 | + <td>付款方式</td> | ||
19 | + <td>货到付款</td> | ||
20 | + </tr> | ||
21 | + </table> | ||
22 | + </div> | ||
23 | + <div class="btn-c"> | ||
24 | + <a href="/">随便逛逛</a> | ||
25 | + <a href="{{orderUrl}}">查看订单</a> | ||
26 | + </div> | ||
27 | + {{# banner}} | ||
28 | + {{#data}} | ||
29 | + <a href="{{url}}" class="ad-pic" alt="{{alt}}"> | ||
30 | + <img src="{{image src 640 200}}" /> | ||
31 | + </a> | ||
32 | + {{/data}} | ||
33 | + {{/banner}} | ||
34 | + <div class="others-buy clearfix"> | ||
35 | + <p>购买此商品的用户也购买了</p> | ||
36 | + {{# othersBuy}} | ||
37 | + {{> common/goods}} | ||
38 | + {{/ othersBuy}} | ||
39 | + </div> | ||
40 | + {{> home/maybe-like}} | ||
41 | +</div> | ||
42 | + |
@@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
7 | 'use strict'; | 7 | 'use strict'; |
8 | 8 | ||
9 | const headerModel = require('../../../doraemon/models/header'); // 头部model | 9 | const headerModel = require('../../../doraemon/models/header'); // 头部model |
10 | +const footerModel = require('../../../doraemon/models/footer_tab'); // 底部tab | ||
10 | const indexModel = require('../models/brand'); | 11 | const indexModel = require('../models/brand'); |
11 | 12 | ||
12 | /** | 13 | /** |
@@ -16,17 +17,11 @@ const indexModel = require('../models/brand'); | @@ -16,17 +17,11 @@ const indexModel = require('../models/brand'); | ||
16 | * @param int channel 1表示男生频道, 2表示女生频道, 3表示潮童频道, 4表示创意生活频道 | 17 | * @param int channel 1表示男生频道, 2表示女生频道, 3表示潮童频道, 4表示创意生活频道 |
17 | */ | 18 | */ |
18 | let index = (req, res, next) => { | 19 | let index = (req, res, next) => { |
19 | - | ||
20 | - let headerData = headerModel.setNav({ | ||
21 | - navTitle: '品牌一览' | ||
22 | - }); | ||
23 | - | ||
24 | let responseData = { | 20 | let responseData = { |
25 | - pageHeader: headerData, | ||
26 | module: 'channel', | 21 | module: 'channel', |
27 | page: 'brand', | 22 | page: 'brand', |
28 | title: '品牌一览 | Yoho!Buy有货 | 潮流购物逛不停', | 23 | title: '品牌一览 | Yoho!Buy有货 | 潮流购物逛不停', |
29 | - //pageFooter: true | 24 | + showFooterTab: footerModel.getUrlData('category') |
30 | }; | 25 | }; |
31 | 26 | ||
32 | let param = { | 27 | let param = { |
@@ -59,6 +54,7 @@ let search = (req, res, next) => { | @@ -59,6 +54,7 @@ let search = (req, res, next) => { | ||
59 | pageHeader: headerData, | 54 | pageHeader: headerData, |
60 | module: 'channel', | 55 | module: 'channel', |
61 | page: 'brand', | 56 | page: 'brand', |
57 | + isWechat: req.yoho.isWechat, | ||
62 | title: '品牌一览 | Yoho!Buy有货 | 潮流购物逛不停', | 58 | title: '品牌一览 | Yoho!Buy有货 | 潮流购物逛不停', |
63 | pageFooter: true | 59 | pageFooter: true |
64 | }; | 60 | }; |
@@ -89,7 +85,10 @@ let addBrandSearch = (req, res, next) => { | @@ -89,7 +85,10 @@ let addBrandSearch = (req, res, next) => { | ||
89 | 85 | ||
90 | let records = timestamp + '_' + brandName; | 86 | let records = timestamp + '_' + brandName; |
91 | 87 | ||
92 | - let param = {uid, records}; | 88 | + let param = { |
89 | + uid, | ||
90 | + records | ||
91 | + }; | ||
93 | 92 | ||
94 | indexModel.addSearchHistory(param).then((result) => { | 93 | indexModel.addSearchHistory(param).then((result) => { |
95 | res.json(result); | 94 | res.json(result); |
@@ -124,11 +123,19 @@ let searchAsync = (req, res, next) => { | @@ -124,11 +123,19 @@ let searchAsync = (req, res, next) => { | ||
124 | } | 123 | } |
125 | 124 | ||
126 | if (!uid) { | 125 | if (!uid) { |
127 | - return res.json({code: 200, data: {}}); | 126 | + return res.json({ |
127 | + code: 200, | ||
128 | + data: {} | ||
129 | + }); | ||
128 | } | 130 | } |
129 | 131 | ||
130 | return indexModel.branchSearchHistoryAsync(uid).then((result) => { | 132 | return indexModel.branchSearchHistoryAsync(uid).then((result) => { |
131 | - return res.json({code: 200, data: { history: result }}); | 133 | + return res.json({ |
134 | + code: 200, | ||
135 | + data: { | ||
136 | + history: result | ||
137 | + } | ||
138 | + }); | ||
132 | }); | 139 | }); |
133 | }; | 140 | }; |
134 | 141 |
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | */ | 3 | */ |
4 | 'use strict'; | 4 | 'use strict'; |
5 | const cateModel = require('../models/cate'); | 5 | const cateModel = require('../models/cate'); |
6 | -const headerModel = require('../../../doraemon/models/header'); | 6 | +const footerModel = require('../../../doraemon/models/footer_tab'); // 底部tab |
7 | const helpers = global.yoho.helpers; | 7 | const helpers = global.yoho.helpers; |
8 | 8 | ||
9 | let index = (req, res, next) => { | 9 | let index = (req, res, next) => { |
@@ -12,15 +12,13 @@ let index = (req, res, next) => { | @@ -12,15 +12,13 @@ let index = (req, res, next) => { | ||
12 | module: 'channel', | 12 | module: 'channel', |
13 | page: 'cate', | 13 | page: 'cate', |
14 | title: '商品分类', | 14 | title: '商品分类', |
15 | - pageHeader: headerModel.setNav({ | ||
16 | - navTitle: '商品分类' | ||
17 | - }), | ||
18 | pageFooter: false, | 15 | pageFooter: false, |
19 | category: { | 16 | category: { |
20 | nav: result.nav, | 17 | nav: result.nav, |
21 | list: result.list, | 18 | list: result.list, |
22 | searchUrl: helpers.urlFormat('/search', null, 'search') | 19 | searchUrl: helpers.urlFormat('/search', null, 'search') |
23 | - } | 20 | + }, |
21 | + showFooterTab: footerModel.getUrlData('category') | ||
24 | }); | 22 | }); |
25 | }).catch(next); | 23 | }).catch(next); |
26 | }; | 24 | }; |
@@ -6,6 +6,8 @@ | @@ -6,6 +6,8 @@ | ||
6 | 'use strict'; | 6 | 'use strict'; |
7 | const _ = require('lodash'); | 7 | const _ = require('lodash'); |
8 | const channelModel = require('../models/channel'); | 8 | const channelModel = require('../models/channel'); |
9 | +const homeModel = require('../../home/models/index'); | ||
10 | +const footerModel = require('../../../doraemon/models/footer_tab'); // 底部tab | ||
9 | 11 | ||
10 | const helpers = global.yoho.helpers; | 12 | const helpers = global.yoho.helpers; |
11 | 13 | ||
@@ -16,13 +18,7 @@ let _renderData = { | @@ -16,13 +18,7 @@ let _renderData = { | ||
16 | searchUrl: helpers.urlFormat('/search', null, 'search') | 18 | searchUrl: helpers.urlFormat('/search', null, 'search') |
17 | }, | 19 | }, |
18 | maybeLike: true, | 20 | maybeLike: true, |
19 | - showFooterTab: { | ||
20 | - indexUrl: helpers.urlFormat('/?go=1'), // 首页 | ||
21 | - categoryUrl: helpers.urlFormat('/cate'), // 分类 | ||
22 | - guangUrl: helpers.urlFormat('', null, 'guang'), // 逛首页 | ||
23 | - shoppingCartUrl: helpers.urlFormat('/cart/index/index'), // 购物车 | ||
24 | - mineUrl: helpers.urlFormat('/home') // 个人中心 | ||
25 | - }, | 21 | + showFooterTab: footerModel.getUrlData('home'), |
26 | pageFooter: true | 22 | pageFooter: true |
27 | }; | 23 | }; |
28 | 24 | ||
@@ -38,6 +34,8 @@ let _channelPage = (req, res, data) => { | @@ -38,6 +34,8 @@ let _channelPage = (req, res, data) => { | ||
38 | gender: data.gender, | 34 | gender: data.gender, |
39 | uid: _.toString(req.user.uid) | 35 | uid: _.toString(req.user.uid) |
40 | }).then(result => { | 36 | }).then(result => { |
37 | + _renderData.homeHeader.defaultTerms = result.defaultTerms; | ||
38 | + | ||
41 | if (!result.content.length || !result.sideNav.length) { | 39 | if (!result.content.length || !result.sideNav.length) { |
42 | res.set('Cache-Control', 'no-cache'); | 40 | res.set('Cache-Control', 'no-cache'); |
43 | } | 41 | } |
@@ -102,7 +100,7 @@ let switchChannel = (req, res, next) => { | @@ -102,7 +100,7 @@ let switchChannel = (req, res, next) => { | ||
102 | let boys = (req, res, next) => { | 100 | let boys = (req, res, next) => { |
103 | _channelPage(req, res, { | 101 | _channelPage(req, res, { |
104 | gender: 'boys', | 102 | gender: 'boys', |
105 | - title: '男生首页', | 103 | + title: '男生 | Yoho!Buy有货 | 潮流购物逛不停', |
106 | boysHomePage: true | 104 | boysHomePage: true |
107 | }).catch(next); // TODO 我们在路由处理的最上层的方法处理catch | 105 | }).catch(next); // TODO 我们在路由处理的最上层的方法处理catch |
108 | }; | 106 | }; |
@@ -113,7 +111,7 @@ let boys = (req, res, next) => { | @@ -113,7 +111,7 @@ let boys = (req, res, next) => { | ||
113 | let girls = (req, res, next) => { | 111 | let girls = (req, res, next) => { |
114 | _channelPage(req, res, { | 112 | _channelPage(req, res, { |
115 | gender: 'girls', | 113 | gender: 'girls', |
116 | - title: '女生首页', | 114 | + title: '女生 | Yoho!Buy有货 | 潮流购物逛不停', |
117 | girlsHomePage: true | 115 | girlsHomePage: true |
118 | }).catch(next); | 116 | }).catch(next); |
119 | }; | 117 | }; |
@@ -125,7 +123,7 @@ let girls = (req, res, next) => { | @@ -125,7 +123,7 @@ let girls = (req, res, next) => { | ||
125 | let kids = (req, res, next) => { | 123 | let kids = (req, res, next) => { |
126 | _channelPage(req, res, { | 124 | _channelPage(req, res, { |
127 | gender: 'kids', | 125 | gender: 'kids', |
128 | - title: '潮童首页', | 126 | + title: '潮童 | Yoho!Buy有货 | 潮流购物逛不停', |
129 | kidsHomePage: true | 127 | kidsHomePage: true |
130 | }).catch(next); | 128 | }).catch(next); |
131 | }; | 129 | }; |
@@ -136,7 +134,7 @@ let kids = (req, res, next) => { | @@ -136,7 +134,7 @@ let kids = (req, res, next) => { | ||
136 | let lifestyle = (req, res, next) => { | 134 | let lifestyle = (req, res, next) => { |
137 | _channelPage(req, res, { | 135 | _channelPage(req, res, { |
138 | gender: 'lifestyle', | 136 | gender: 'lifestyle', |
139 | - title: '创意生活首页', | 137 | + title: '创意生活 | Yoho!Buy有货 | 潮流购物逛不停', |
140 | lifestyleHomePage: true | 138 | lifestyleHomePage: true |
141 | }).catch(next); | 139 | }).catch(next); |
142 | }; | 140 | }; |
@@ -155,6 +153,47 @@ let bottomBanner = (req, res, next) => { | @@ -155,6 +153,47 @@ let bottomBanner = (req, res, next) => { | ||
155 | }).catch(next); | 153 | }).catch(next); |
156 | }; | 154 | }; |
157 | 155 | ||
156 | +/** | ||
157 | + * 店铺推荐收藏状态人数 | ||
158 | + */ | ||
159 | +let shopRecom = (req, res, next) => { | ||
160 | + channelModel.shopRecom({ | ||
161 | + shopIds: req.body.shopIds || '', | ||
162 | + uid: req.user.uid || 0, | ||
163 | + }).then(result => { | ||
164 | + res.send(result); | ||
165 | + }).catch(next); | ||
166 | +} | ||
167 | + | ||
168 | +/** | ||
169 | + * 获取用户vip信息 | ||
170 | + */ | ||
171 | +let userVip = (req, res, next) => { | ||
172 | + let uid = req.user.uid; | ||
173 | + | ||
174 | + if (!uid) { | ||
175 | + res.json({ | ||
176 | + code: 555, | ||
177 | + msg: '未登录' | ||
178 | + }); | ||
179 | + } else { | ||
180 | + homeModel.getGradeGrade(uid, req.query.channel || 1).then(result => { | ||
181 | + if (result.code === 200) { | ||
182 | + res.json({ | ||
183 | + code: 200, | ||
184 | + current_vip_level: result.data.current_vip_level, | ||
185 | + }); | ||
186 | + } else { | ||
187 | + res.json({ | ||
188 | + code: 500, | ||
189 | + msg: '出错了', | ||
190 | + }) | ||
191 | + } | ||
192 | + }); | ||
193 | + } | ||
194 | + | ||
195 | +} | ||
196 | + | ||
158 | module.exports = { | 197 | module.exports = { |
159 | switchChannel, | 198 | switchChannel, |
160 | index, | 199 | index, |
@@ -162,5 +201,7 @@ module.exports = { | @@ -162,5 +201,7 @@ module.exports = { | ||
162 | girls, | 201 | girls, |
163 | kids, | 202 | kids, |
164 | lifestyle, | 203 | lifestyle, |
165 | - bottomBanner | ||
166 | -}; | 204 | + bottomBanner, |
205 | + shopRecom, | ||
206 | + userVip, | ||
207 | +}; |
@@ -121,8 +121,6 @@ const getBrandByChannel = (channel) => { | @@ -121,8 +121,6 @@ const getBrandByChannel = (channel) => { | ||
121 | searchUrl: helpers.urlFormat('/brands/search', null), | 121 | searchUrl: helpers.urlFormat('/brands/search', null), |
122 | brandPage: true, | 122 | brandPage: true, |
123 | 123 | ||
124 | - // pageFooter: true, | ||
125 | - showDownloadApp: true, | ||
126 | brandType: '全部品牌', | 124 | brandType: '全部品牌', |
127 | secondBrandType: '新入驻品牌', | 125 | secondBrandType: '新入驻品牌', |
128 | thirdBrandType: '热门品牌', | 126 | thirdBrandType: '热门品牌', |
@@ -184,7 +182,9 @@ const getBrandByChannel = (channel) => { | @@ -184,7 +182,9 @@ const getBrandByChannel = (channel) => { | ||
184 | 182 | ||
185 | let obj = {}; | 183 | let obj = {}; |
186 | 184 | ||
187 | - obj = Object.assign(obj, {title: key}); | 185 | + obj = Object.assign(obj, { |
186 | + title: key | ||
187 | + }); | ||
188 | 188 | ||
189 | let list = []; | 189 | let list = []; |
190 | 190 | ||
@@ -199,7 +199,9 @@ const getBrandByChannel = (channel) => { | @@ -199,7 +199,9 @@ const getBrandByChannel = (channel) => { | ||
199 | 199 | ||
200 | }); | 200 | }); |
201 | 201 | ||
202 | - obj = Object.assign(obj, {list}); | 202 | + obj = Object.assign(obj, { |
203 | + list | ||
204 | + }); | ||
203 | 205 | ||
204 | resu.channel.brandList.push(obj); | 206 | resu.channel.brandList.push(obj); |
205 | 207 | ||
@@ -224,7 +226,9 @@ const getBrandByChannel = (channel) => { | @@ -224,7 +226,9 @@ const getBrandByChannel = (channel) => { | ||
224 | img: helpers.image(newList[key].brand_ico, 186, 115), | 226 | img: helpers.image(newList[key].brand_ico, 186, 115), |
225 | }); | 227 | }); |
226 | 228 | ||
227 | - obj = Object.assign(obj, {list}); | 229 | + obj = Object.assign(obj, { |
230 | + list | ||
231 | + }); | ||
228 | 232 | ||
229 | resu.channel.newBrandWall.push(obj); | 233 | resu.channel.newBrandWall.push(obj); |
230 | 234 | ||
@@ -249,7 +253,9 @@ const getBrandByChannel = (channel) => { | @@ -249,7 +253,9 @@ const getBrandByChannel = (channel) => { | ||
249 | img: helpers.image(hotList[key].brand_ico, 186, 115), | 253 | img: helpers.image(hotList[key].brand_ico, 186, 115), |
250 | }); | 254 | }); |
251 | 255 | ||
252 | - obj = Object.assign(obj, {list}); | 256 | + obj = Object.assign(obj, { |
257 | + list | ||
258 | + }); | ||
253 | 259 | ||
254 | resu.channel.recommandBrandWall.push(obj); | 260 | resu.channel.recommandBrandWall.push(obj); |
255 | 261 | ||
@@ -314,7 +320,9 @@ const addSearchHistory = (param) => { | @@ -314,7 +320,9 @@ const addSearchHistory = (param) => { | ||
314 | uid: param.uid, | 320 | uid: param.uid, |
315 | records: param.records | 321 | records: param.records |
316 | 322 | ||
317 | - }, { code: 200 }); | 323 | + }, { |
324 | + code: 200 | ||
325 | + }); | ||
318 | }; | 326 | }; |
319 | 327 | ||
320 | /** | 328 | /** |
@@ -457,7 +465,6 @@ const branchSearch = (params) => { | @@ -457,7 +465,6 @@ const branchSearch = (params) => { | ||
457 | 465 | ||
458 | let resu = { | 466 | let resu = { |
459 | brandPage: true, | 467 | brandPage: true, |
460 | - showDownloadApp: true, | ||
461 | pageFooter: true, | 468 | pageFooter: true, |
462 | hot: [], | 469 | hot: [], |
463 | history: [], | 470 | history: [], |
@@ -504,7 +511,9 @@ const branchSearch = (params) => { | @@ -504,7 +511,9 @@ const branchSearch = (params) => { | ||
504 | 511 | ||
505 | let obj = {}; | 512 | let obj = {}; |
506 | 513 | ||
507 | - obj = Object.assign(obj, {name: hotList[key].brandName}); | 514 | + obj = Object.assign(obj, { |
515 | + name: hotList[key].brandName | ||
516 | + }); | ||
508 | 517 | ||
509 | resu.hot.push(obj); | 518 | resu.hot.push(obj); |
510 | 519 | ||
@@ -550,7 +559,9 @@ const delBrandSearchHistory = (param) => { | @@ -550,7 +559,9 @@ const delBrandSearchHistory = (param) => { | ||
550 | method: 'app.search.clearHotBrandRecords', | 559 | method: 'app.search.clearHotBrandRecords', |
551 | uid: param.uid | 560 | uid: param.uid |
552 | 561 | ||
553 | - }, { code: 200 }).then(result => { | 562 | + }, { |
563 | + code: 200 | ||
564 | + }).then(result => { | ||
554 | 565 | ||
555 | return result; | 566 | return result; |
556 | 567 | ||
@@ -561,7 +572,9 @@ const delBrandSearchHistory = (param) => { | @@ -561,7 +572,9 @@ const delBrandSearchHistory = (param) => { | ||
561 | * [异步获取用户最近搜索词] | 572 | * [异步获取用户最近搜索词] |
562 | */ | 573 | */ |
563 | const branchSearchHistoryAsync = (uid) => { | 574 | const branchSearchHistoryAsync = (uid) => { |
564 | - return branchSearchHistory({uid}).then((result) => { | 575 | + return branchSearchHistory({ |
576 | + uid | ||
577 | + }).then((result) => { | ||
565 | let hisList = result.data; | 578 | let hisList = result.data; |
566 | 579 | ||
567 | let obj = []; | 580 | let obj = []; |
@@ -8,6 +8,7 @@ const utils = '../../../utils'; | @@ -8,6 +8,7 @@ const utils = '../../../utils'; | ||
8 | const contentCodeConfig = require('../../../config/content-code'); | 8 | const contentCodeConfig = require('../../../config/content-code'); |
9 | const _ = require('lodash'); | 9 | const _ = require('lodash'); |
10 | const api = global.yoho.ServiceAPI; | 10 | const api = global.yoho.ServiceAPI; |
11 | +const API = global.yoho.API; | ||
11 | const logger = global.yoho.logger; | 12 | const logger = global.yoho.logger; |
12 | const resourcesProcess = require(`${utils}/resources-process`); | 13 | const resourcesProcess = require(`${utils}/resources-process`); |
13 | 14 | ||
@@ -37,25 +38,23 @@ const bottomBannerCode = contentCodeConfig.bottom; | @@ -37,25 +38,23 @@ const bottomBannerCode = contentCodeConfig.bottom; | ||
37 | * 频道选择页 默认数据 | 38 | * 频道选择页 默认数据 |
38 | * @type {Object} | 39 | * @type {Object} |
39 | */ | 40 | */ |
40 | -const channelList = [ | ||
41 | - { | ||
42 | - href: '/boys', | ||
43 | - title: '男生', | ||
44 | - entitle: 'BOYS' | ||
45 | - }, { | ||
46 | - href: '/girls', | ||
47 | - title: '女生', | ||
48 | - entitle: 'GIRLS' | ||
49 | - }, { | ||
50 | - href: '/kids', | ||
51 | - title: '潮童', | ||
52 | - entitle: 'KIDS' | ||
53 | - }, { | ||
54 | - href: '/lifestyle', | ||
55 | - title: '创意生活', | ||
56 | - entitle: 'LIFESTYLE' | ||
57 | - } | ||
58 | -]; | 41 | +const channelList = [{ |
42 | + href: '/boys', | ||
43 | + title: '男生', | ||
44 | + entitle: 'BOYS' | ||
45 | +}, { | ||
46 | + href: '/girls', | ||
47 | + title: '女生', | ||
48 | + entitle: 'GIRLS' | ||
49 | +}, { | ||
50 | + href: '/kids', | ||
51 | + title: '潮童', | ||
52 | + entitle: 'KIDS' | ||
53 | +}, { | ||
54 | + href: '/lifestyle', | ||
55 | + title: '创意生活', | ||
56 | + entitle: 'LIFESTYLE' | ||
57 | +}]; | ||
59 | 58 | ||
60 | /** | 59 | /** |
61 | * 获取二级菜单顶部颜色 | 60 | * 获取二级菜单顶部颜色 |
@@ -136,8 +135,8 @@ const _getChannelResource = (params) => { | @@ -136,8 +135,8 @@ const _getChannelResource = (params) => { | ||
136 | if (result && result.code === 200 && result.data && result.data.list) { | 135 | if (result && result.code === 200 && result.data && result.data.list) { |
137 | for (let item of result.data.list) { | 136 | for (let item of result.data.list) { |
138 | item.template_name === 'single_image' && | 137 | item.template_name === 'single_image' && |
139 | - item.data.length === 1 && | ||
140 | - (item.singleOne = true); | 138 | + item.data.length === 1 && |
139 | + (item.singleOne = true); | ||
141 | } | 140 | } |
142 | return resourcesProcess(result.data.list); | 141 | return resourcesProcess(result.data.list); |
143 | } else { | 142 | } else { |
@@ -168,6 +167,24 @@ const _getLeftNav = (choosed) => { | @@ -168,6 +167,24 @@ const _getLeftNav = (choosed) => { | ||
168 | }; | 167 | }; |
169 | 168 | ||
170 | /** | 169 | /** |
170 | + * 获取热门搜索 | ||
171 | + **/ | ||
172 | +const _getSearchIndex = () => { | ||
173 | + return API.get('', { | ||
174 | + method: 'app.search.getTerms' | ||
175 | + }, { | ||
176 | + cache: true | ||
177 | + }).then((result) => { | ||
178 | + if (result && result.code === 200) { | ||
179 | + return result.data; | ||
180 | + } else { | ||
181 | + logger.error('Hot Search return code is not 200'); | ||
182 | + return {}; | ||
183 | + } | ||
184 | + }); | ||
185 | +}; | ||
186 | + | ||
187 | +/** | ||
171 | * 获取频道选择页数据 | 188 | * 获取频道选择页数据 |
172 | * @return {[type]} | 189 | * @return {[type]} |
173 | */ | 190 | */ |
@@ -252,10 +269,10 @@ let getChannelData = (params) => { | @@ -252,10 +269,10 @@ let getChannelData = (params) => { | ||
252 | var channelData = {}; | 269 | var channelData = {}; |
253 | let navGender = _.cloneDeep(params.gender); | 270 | let navGender = _.cloneDeep(params.gender); |
254 | 271 | ||
255 | - return Promise.all([_getChannelResource(params), _getLeftNav(navGender)]).then((data) => { | 272 | + return Promise.all([_getChannelResource(params), _getLeftNav(navGender), _getSearchIndex()]).then((data) => { |
256 | channelData.content = data[0] || []; // 资源位数据 | 273 | channelData.content = data[0] || []; // 资源位数据 |
257 | channelData.sideNav = data[1] || []; // 侧边栏数据 | 274 | channelData.sideNav = data[1] || []; // 侧边栏数据 |
258 | - | 275 | + channelData.defaultTerms = (data[2] && data[2].defaultTerms && data[2].defaultTerms.length !== 0) ? data[2].defaultTerms[0].content : '搜索商品、品牌'; |
259 | return channelData; | 276 | return channelData; |
260 | }); | 277 | }); |
261 | }; | 278 | }; |
@@ -282,8 +299,20 @@ let getBottomBannerData = (gender) => { | @@ -282,8 +299,20 @@ let getBottomBannerData = (gender) => { | ||
282 | }); | 299 | }); |
283 | }; | 300 | }; |
284 | 301 | ||
302 | +/** | ||
303 | + * 获取店铺推荐收藏和人数 | ||
304 | + */ | ||
305 | +let shopRecom = (params) => { | ||
306 | + return API.get('', { | ||
307 | + method: 'app.shops.floorNewInfo', | ||
308 | + shop_ids: params.shopIds, | ||
309 | + uid: params.uid, | ||
310 | + }); | ||
311 | +}; | ||
312 | + | ||
285 | module.exports = { | 313 | module.exports = { |
286 | getChannelData, | 314 | getChannelData, |
287 | getChannelSwitchData, | 315 | getChannelSwitchData, |
288 | - getBottomBannerData | 316 | + getBottomBannerData, |
317 | + shopRecom, | ||
289 | }; | 318 | }; |
@@ -29,4 +29,7 @@ router.post('/brands/searchAsync', brandController.searchAsync); // 品牌搜索 | @@ -29,4 +29,7 @@ router.post('/brands/searchAsync', brandController.searchAsync); // 品牌搜索 | ||
29 | router.post('/brands/addBrandSearch', brandController.addBrandSearch); // 添加品牌搜索记录 | 29 | router.post('/brands/addBrandSearch', brandController.addBrandSearch); // 添加品牌搜索记录 |
30 | router.get('/brands/delBrandHistory', brandController.delBrandHistory); // 删除品牌搜索记录 | 30 | router.get('/brands/delBrandHistory', brandController.delBrandHistory); // 删除品牌搜索记录 |
31 | 31 | ||
32 | +// 5.2新楼层功能 | ||
33 | +router.post('/channel/shopRecom', channel.shopRecom); // 店铺推荐收藏状态 | ||
34 | +router.post('/channel/userVip', channel.userVip) | ||
32 | module.exports = router; | 35 | module.exports = router; |
1 | <div class="brand-page brand-search-page yoho-page"> | 1 | <div class="brand-page brand-search-page yoho-page"> |
2 | - <div class="newbrand-search"> | 2 | + <div class="newbrand-search {{#if isWechat}} wechat {{/if}}"> |
3 | <form class="search-box clearfix"> | 3 | <form class="search-box clearfix"> |
4 | <input type="text" class="search-input" id="keyword" placeholder="查找品牌"> | 4 | <input type="text" class="search-input" id="keyword" placeholder="查找品牌"> |
5 | <i class="search-icon iconfont"></i> | 5 | <i class="search-icon iconfont"></i> |
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | </div> | 9 | </div> |
10 | </form> | 10 | </form> |
11 | </div> | 11 | </div> |
12 | - <div class="search-result"> | 12 | + <div class="search-result {{#if isWechat}} wechat {{/if}}"> |
13 | </div> | 13 | </div> |
14 | </div> | 14 | </div> |
15 | 15 |
@@ -14,7 +14,9 @@ | @@ -14,7 +14,9 @@ | ||
14 | {{/announcement}} --}} | 14 | {{/announcement}} --}} |
15 | {{! 中间banner}} | 15 | {{! 中间banner}} |
16 | {{#if singleImage}} | 16 | {{#if singleImage}} |
17 | + <div data-id="{{template_id}}"> | ||
17 | {{> resources/banner}} | 18 | {{> resources/banner}} |
19 | + </div> | ||
18 | {{/if}} | 20 | {{/if}} |
19 | {{! 两个小图}} | 21 | {{! 两个小图}} |
20 | {{#if smallPic}} | 22 | {{#if smallPic}} |
@@ -53,7 +55,7 @@ | @@ -53,7 +55,7 @@ | ||
53 | {{> resources/plus-star}} | 55 | {{> resources/plus-star}} |
54 | {{/if}} | 56 | {{/if}} |
55 | {{! 新人专享}} | 57 | {{! 新人专享}} |
56 | - {{#if newUserFloor}} | 58 | + {{#if oldNewUserFloor}} |
57 | {{> resources/fresh-only}} | 59 | {{> resources/fresh-only}} |
58 | {{/if}} | 60 | {{/if}} |
59 | {{! 秒杀}} | 61 | {{! 秒杀}} |
@@ -72,4 +74,32 @@ | @@ -72,4 +74,32 @@ | ||
72 | {{#if sixLinesFloor}} | 74 | {{#if sixLinesFloor}} |
73 | {{> resources/six-lines-floor}} | 75 | {{> resources/six-lines-floor}} |
74 | {{/if}} | 76 | {{/if}} |
77 | + {{! vip专属}} | ||
78 | + {{#if vipUse}} | ||
79 | + {{> resources/vip-only}} | ||
80 | + {{/if}} | ||
81 | + {{! 店铺推荐}} | ||
82 | + {{#if shopRecommend}} | ||
83 | + {{> resources/shop-recommand}} | ||
84 | + {{/if}} | ||
85 | + {{! 新新人专享}} | ||
86 | + {{#if newUserFloor}} | ||
87 | + {{> resources/new-user-floor}} | ||
88 | + {{/if}} | ||
89 | + {{! 人气单品}} | ||
90 | + {{#if popularSingleProduct}} | ||
91 | + {{> resources/hot-single}} | ||
92 | + {{/if}} | ||
93 | + {{! SALE}} | ||
94 | + {{#if sale1T1L4R}} | ||
95 | + {{> resources/sale-floor}} | ||
96 | + {{/if}} | ||
97 | + {{! 新品首发楼层}} | ||
98 | + {{#if newProductFloor}} | ||
99 | + {{> resources/new-first}} | ||
100 | + {{/if}} | ||
101 | + {{! 分隔楼层}} | ||
102 | + {{#if divideImage}} | ||
103 | + {{> resources/divide-image}} | ||
104 | + {{/if}} | ||
75 | {{/content}} | 105 | {{/content}} |
1 | -<div class="home-header clearfix" {{# bgColor}}style="background-color:{{.}};background-image:none"{{/ bgColor}}> | ||
2 | - <span class="nav-btn iconfont"></span> | ||
3 | - <span class="logo"></span> | ||
4 | - <span class="search-btn iconfont"><a href="{{searchUrl}}"></a></span> | 1 | +<div id="home-header" class="home-header clearfix" {{# bgColor}}style="background-color:{{.}};background-image:none"{{/ bgColor}}> |
2 | + <div id="browser-header"> | ||
3 | + <span class="nav-btn iconfont"></span> | ||
4 | + <span class="logo"></span> | ||
5 | + <span class="search-btn iconfont"><a href="{{searchUrl}}"></a></span> | ||
6 | + </div> | ||
7 | + <div id="wechat-header" class="hide"> | ||
8 | + <span class="nav-btn iconfont"></span> | ||
9 | + <div class="search-input"> | ||
10 | + <a href="{{searchUrl}}"> | ||
11 | + <i class="search-icon iconfont"></i> | ||
12 | + <p>{{defaultTerms}}</p> | ||
13 | + </a> | ||
14 | + </div> | ||
15 | + </div> | ||
16 | + <script type="text/javascript"> | ||
17 | + var isWechat = /micromessenger/i.test(navigator.userAgent || ''); | ||
18 | + if (isWechat) { | ||
19 | + document.getElementById('browser-header').classList.add('hide'); | ||
20 | + document.getElementById('wechat-header').classList.remove('hide'); | ||
21 | + document.getElementById('home-header').classList.add('iswechat'); | ||
22 | + } | ||
23 | + </script> | ||
5 | </div> | 24 | </div> |
@@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
8 | const mRoot = '../models'; | 8 | const mRoot = '../models'; |
9 | const indexModel = require(`${mRoot}/index`); | 9 | const indexModel = require(`${mRoot}/index`); |
10 | const headerModel = require('../../../doraemon/models/header'); // 头部model | 10 | const headerModel = require('../../../doraemon/models/header'); // 头部model |
11 | +const footerModel = require('../../../doraemon/models/footer_tab'); // 底部tab | ||
11 | const guangProcess = require(`${global.utils}/guang-process`); | 12 | const guangProcess = require(`${global.utils}/guang-process`); |
12 | const stringProcess = require(`${global.utils}/string-process`); | 13 | const stringProcess = require(`${global.utils}/string-process`); |
13 | const Promise = require('bluebird'); | 14 | const Promise = require('bluebird'); |
@@ -50,7 +51,7 @@ const editor = (req, res, next) => { | @@ -50,7 +51,7 @@ const editor = (req, res, next) => { | ||
50 | articleData.colparam = { | 51 | articleData.colparam = { |
51 | urlpath: req.path, | 52 | urlpath: req.path, |
52 | param: `?id=${id}` | 53 | param: `?id=${id}` |
53 | - } | 54 | + }; |
54 | 55 | ||
55 | build.push(guangProcess.formatArticle(articleData, true, isApp, false, uid)); | 56 | build.push(guangProcess.formatArticle(articleData, true, isApp, false, uid)); |
56 | }); | 57 | }); |
@@ -151,25 +152,17 @@ const pageData = (req, res, next) => { | @@ -151,25 +152,17 @@ const pageData = (req, res, next) => { | ||
151 | * @param next | 152 | * @param next |
152 | */ | 153 | */ |
153 | const index = (req, res, next) => { | 154 | const index = (req, res, next) => { |
154 | - let headerData = headerModel.setNav({ | ||
155 | - navTitle: '逛' | ||
156 | - }); | ||
157 | - | ||
158 | let responseData = { | 155 | let responseData = { |
159 | - pageHeader: headerData, | ||
160 | module: 'guang', | 156 | module: 'guang', |
161 | page: 'index', | 157 | page: 'index', |
162 | title: '逛 | Yoho!Buy有货 | 潮流购物逛不停', | 158 | title: '逛 | Yoho!Buy有货 | 潮流购物逛不停', |
163 | - pageFooter: true | 159 | + showFooterTab: footerModel.getUrlData('guang') |
164 | }; | 160 | }; |
165 | 161 | ||
166 | let param = { | 162 | let param = { |
167 | uid: req.user.uid || req.query.uid, | 163 | uid: req.user.uid || req.query.uid, |
168 | - | ||
169 | udid: req.user.udid, | 164 | udid: req.user.udid, |
170 | - | ||
171 | type: req.query.type || '0', | 165 | type: req.query.type || '0', |
172 | - | ||
173 | gender: req.query.gender || '1,3' | 166 | gender: req.query.gender || '1,3' |
174 | }; | 167 | }; |
175 | 168 | ||
@@ -278,4 +271,4 @@ module.exports = { | @@ -278,4 +271,4 @@ module.exports = { | ||
278 | tag, | 271 | tag, |
279 | listDynamicData, | 272 | listDynamicData, |
280 | detailDynamicData | 273 | detailDynamicData |
281 | -}; | ||
274 | +}; |
@@ -7,6 +7,9 @@ | @@ -7,6 +7,9 @@ | ||
7 | 7 | ||
8 | const mRoot = '../models'; | 8 | const mRoot = '../models'; |
9 | const rssModel = require(`${mRoot}/rss`); | 9 | const rssModel = require(`${mRoot}/rss`); |
10 | +const Feed = require('feed'); | ||
11 | +const _ = require('lodash'); | ||
12 | +const moment = require('moment'); | ||
10 | const helpers = global.yoho.helpers; | 13 | const helpers = global.yoho.helpers; |
11 | 14 | ||
12 | /** | 15 | /** |
@@ -15,18 +18,61 @@ const helpers = global.yoho.helpers; | @@ -15,18 +18,61 @@ const helpers = global.yoho.helpers; | ||
15 | const index = (req, res, next) => { | 18 | const index = (req, res, next) => { |
16 | let gender = req.query.gender || '1,2,3', | 19 | let gender = req.query.gender || '1,2,3', |
17 | items = []; | 20 | items = []; |
18 | - | 21 | + return rssModel.getRssArticle(gender).then((result) => { |
22 | + if (!result) { | ||
23 | + return next(); | ||
24 | + } | ||
25 | + res.setHeader('Content-Type', 'text/xml; charset=utf-8'); | ||
26 | + var feed = new Feed({ | ||
27 | + id: 'http://yohobuy.com', | ||
28 | + title: '有货逛', | ||
29 | + description: 'Yoho!Buy有货 | 年轻人潮流购物中心', | ||
30 | + link: 'http://yohobuy.com', | ||
31 | + copyright: '2015 yoho.inc', | ||
32 | + generator: 'http://m.yohobuy.com', | ||
33 | + updated: new Date(), | ||
34 | + }) | ||
35 | + _.forEach(result, item => { | ||
36 | + item.url = item.url.indexOf('http') >= 0 ? item.url : 'http://'+item.url | ||
37 | + feed.addItem({ | ||
38 | + title: item.title, | ||
39 | + link: `${item.url}&ref=rss`, | ||
40 | + description: item.intro, | ||
41 | + author: [{ | ||
42 | + name: (item.author && item.author.name) || ' ' | ||
43 | + }], | ||
44 | + date: new Date(item.publishTimeLong && parseFloat(item.publishTimeLong) || moment(item.publishTime, "MM月DD日 HH:mm")) | ||
45 | + }); | ||
46 | + }); | ||
47 | + if (req.params[0] && req.params[0] === '/atom') { | ||
48 | + return res.send(feed.render('atom-1.0')); | ||
49 | + } | ||
50 | + return res.send(feed.render('rss-2.0')) | ||
51 | + }); | ||
52 | +}; | ||
53 | +const rss = (req, res, next, gmt) => { | ||
54 | + let gender = req.query.gender || '1,2,3', | ||
55 | + items = []; | ||
19 | res.setHeader('Content-Type', 'text/xml; charset=utf-8'); | 56 | res.setHeader('Content-Type', 'text/xml; charset=utf-8'); |
20 | return rssModel.getRssArticle(gender).then((result) => { | 57 | return rssModel.getRssArticle(gender).then((result) => { |
58 | + if (!result) { | ||
59 | + return next(); | ||
60 | + } | ||
61 | + _.forEach(result, item => { | ||
62 | + item.url = item.url.indexOf('http') >= 0 ? item.url : 'http://'+item.url; | ||
63 | + let time = new Date(item.publishTimeLong && parseFloat(item.publishTimeLong) || moment(item.publishTime, "MM月DD日 HH:mm")); | ||
64 | + let format = gmt ? 'ddd, MM MMM YYYY hh:mm:ss +0800' : 'YYYY-MM-DD hh:mm:ss +0800'; | ||
65 | + | ||
66 | + item.publishTime = moment(time).format(format); | ||
67 | + }); | ||
21 | return res.render('rss/index', { | 68 | return res.render('rss/index', { |
22 | layout: false, | 69 | layout: false, |
23 | - time: (new Date()).toUTCString(), | ||
24 | items: result | 70 | items: result |
25 | }); | 71 | }); |
26 | }); | 72 | }); |
27 | }; | 73 | }; |
28 | 74 | ||
29 | - | ||
30 | module.exports = { | 75 | module.exports = { |
31 | - index | ||
32 | -}; | 76 | + index, |
77 | + rss | ||
78 | +}; |
@@ -41,9 +41,11 @@ const getRssArticle = (gender) => { | @@ -41,9 +41,11 @@ const getRssArticle = (gender) => { | ||
41 | let artListFunc = (i, len, resolve) => { | 41 | let artListFunc = (i, len, resolve) => { |
42 | if (i < len) { | 42 | if (i < len) { |
43 | let value = article.data.list.artList[i]; | 43 | let value = article.data.list.artList[i]; |
44 | + | ||
44 | if (typeof value.id !== 'undefined') { | 45 | if (typeof value.id !== 'undefined') { |
45 | build = guangProcess.formatArticle(value, false, false, true); | 46 | build = guangProcess.formatArticle(value, false, false, true); |
46 | - build.author.name = (build.author && build.author.name) || ''; | 47 | + build.author = build.author || {}; |
48 | + build.author.name = (build.author && build.author.name) || '' | ||
47 | return _genIntro(value.id).then((intro) => { | 49 | return _genIntro(value.id).then((intro) => { |
48 | build.intro = intro; | 50 | build.intro = intro; |
49 | result.push(build); | 51 | result.push(build); |
@@ -91,6 +93,7 @@ const _genIntro = (id) => { | @@ -91,6 +93,7 @@ const _genIntro = (id) => { | ||
91 | }); | 93 | }); |
92 | 94 | ||
93 | }; | 95 | }; |
96 | + | ||
94 | module.exports = { | 97 | module.exports = { |
95 | getRssArticle | 98 | getRssArticle |
96 | -}; | 99 | +}; |
@@ -54,7 +54,9 @@ router.get('/plustar', plustar.getListData); // 国际优选列表页 | @@ -54,7 +54,9 @@ router.get('/plustar', plustar.getListData); // 国际优选列表页 | ||
54 | router.get('/plustar/brandinfo', plustar.getDetailData); // 国际优选详情页 | 54 | router.get('/plustar/brandinfo', plustar.getDetailData); // 国际优选详情页 |
55 | router.post('/plustar/brandinfoAsync', plustar.getDetailDataAsync); // 国际优选详情页异步数据 | 55 | router.post('/plustar/brandinfoAsync', plustar.getDetailDataAsync); // 国际优选详情页异步数据 |
56 | 56 | ||
57 | -router.get('/rss', rss.index); // 订阅资讯 | 57 | +router.get('/rss/new', (req, res, next) => rss.rss(req, res, next, '')); // 订阅资讯 |
58 | +router.get('/rss/new-gmt', (req, res, next) => rss.rss(req, res, next, 'gmt')); // 订阅资讯 | ||
59 | +router.get(/^\/rss(\/\w+)?(\/\w+)?/, rss.index); // 订阅资讯 | ||
58 | 60 | ||
59 | router.get('/info/listData', index.listDynamicData); | 61 | router.get('/info/listData', index.listDynamicData); |
60 | router.get('/info/detailData', index.detailDynamicData); | 62 | router.get('/info/detailData', index.detailDynamicData); |
@@ -15,5 +15,5 @@ | @@ -15,5 +15,5 @@ | ||
15 | <div class="plusstar-resources"> | 15 | <div class="plusstar-resources"> |
16 | <!--资源位数据模板--> | 16 | <!--资源位数据模板--> |
17 | </div><!--/plusstar-resources--> | 17 | </div><!--/plusstar-resources--> |
18 | - | 18 | + {{> common/suspend-home}} |
19 | </div><!--/plusstar-page--> | 19 | </div><!--/plusstar-page--> |
1 | -<?xml version="1.0" encoding="UTF-8"?> | ||
2 | -<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> | ||
3 | - <channel> | ||
4 | - <title>有货逛</title> | ||
5 | - <link>http://yohobuy.com</link> | ||
6 | - <generator>http://m.yohobuy.com</generator> | ||
7 | - <description>Yoho!Buy有货 | 年轻人潮流购物中心</description> | ||
8 | - <atom:link href="http://guang.m.yohobuy.com/rss" rel="self"></atom:link> | ||
9 | - <atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/> | ||
10 | - <language>zh-cn</language> | ||
11 | - <copyright>2015 yoho.inc</copyright> | ||
12 | - <lastBuildDate>{{time}}</lastBuildDate> | ||
13 | - <ttl>50</ttl> | ||
14 | - {{# items}} | ||
15 | - <item> | ||
16 | - <title><![CDATA[{{title}}]]></title> | ||
17 | - <link> | ||
18 | - <![CDATA[{{{url}}}&ref=rss]]> | ||
19 | - </link> | ||
20 | - <description> | ||
21 | - <![CDATA[{{{intro}}}]]> | ||
22 | - </description> | ||
23 | - <pubDate>{{publishTime}}</pubDate> | ||
24 | - <author> | ||
25 | - <![CDATA[{{author.name}}]]> | ||
26 | - </author> | ||
27 | - <guid> | ||
28 | - <![CDATA[{{{url}}}&ref=rss]]> | ||
29 | - </guid> | ||
30 | - <source>有货</source> | ||
31 | - </item> | ||
32 | - {{/items}} | ||
33 | - </channel> | 1 | +<?xml version='1.0' encoding='utf-8'?> |
2 | +<rss version='2.0'> | ||
3 | + <channel> | ||
4 | + <language>zh-cn</language> | ||
5 | + <title><![CDATA[有货逛]]></title> | ||
6 | + <link><![CDATA[http://yohobuy.com]]></link> | ||
7 | + <description><![CDATA[Yoho!Buy有货 | 年轻人潮流购物中心]]></description> | ||
8 | + <generator><![CDATA[yohobuy.com]]></generator> | ||
9 | + <image> | ||
10 | + <title><![CDATA[有货逛]]></title> | ||
11 | + <url><![CDATA[https://cdn.yoho.cn/m-yohobuy-node/assets/img/channel/yohologo.png?v1588b112f08]]></url> | ||
12 | + <link><![CDATA[http://yohobuy.com]]></link> | ||
13 | + <width><![CDATA[ 295 ]]></width> | ||
14 | + <height><![CDATA[ 60 ]]></height> | ||
15 | + <description><![CDATA[yohobuy.com]]></description> | ||
16 | + </image> | ||
17 | + {{# items}} | ||
18 | + <item> | ||
19 | + <title><![CDATA[{{title}}]]></title> | ||
20 | + <link><![CDATA[{{{url}}}&ref=rss]]></link> | ||
21 | + <description><![CDATA[{{{intro}}}]]></description> | ||
22 | + <pubDate><![CDATA[{{publishTime}}]]></pubDate> | ||
23 | + <source><![CDATA[有货逛]]></source> | ||
24 | + <author>有货</author> | ||
25 | + </item> | ||
26 | + {{/items}} | ||
27 | + | ||
28 | + </channel> | ||
34 | </rss> | 29 | </rss> |
@@ -18,6 +18,9 @@ | @@ -18,6 +18,9 @@ | ||
18 | {{# is_limited}} | 18 | {{# is_limited}} |
19 | <p class="good-tag limit-tag">限量</p> | 19 | <p class="good-tag limit-tag">限量</p> |
20 | {{/ is_limited}} | 20 | {{/ is_limited}} |
21 | + {{# is_presell}} | ||
22 | + <p class="good-tag is-presell">预售</p> | ||
23 | + {{/ is_presell}} | ||
21 | {{/ tags}} | 24 | {{/ tags}} |
22 | </div> | 25 | </div> |
23 | <div class="good-detail-img"> | 26 | <div class="good-detail-img"> |
@@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
7 | 'use strict'; | 7 | 'use strict'; |
8 | 8 | ||
9 | const headerModel = require('../../../doraemon/models/header'); // 头部model | 9 | const headerModel = require('../../../doraemon/models/header'); // 头部model |
10 | +const footerModel = require('../../../doraemon/models/footer_tab'); // 底部tab | ||
10 | const indexModel = require('../models/index'); | 11 | const indexModel = require('../models/index'); |
11 | 12 | ||
12 | /** | 13 | /** |
@@ -22,23 +23,18 @@ exports.index = (req, res, next) => { | @@ -22,23 +23,18 @@ exports.index = (req, res, next) => { | ||
22 | udid: require('md5')(req.ip) | 23 | udid: require('md5')(req.ip) |
23 | }; | 24 | }; |
24 | 25 | ||
25 | - let headerData = headerModel.setNav({ | ||
26 | - navTitle: '个人中心', | ||
27 | - backUrl: '//m.yohobuy.com/?go=1' | ||
28 | - }); | ||
29 | - | ||
30 | indexModel.index(params).then(result => { | 26 | indexModel.index(params).then(result => { |
31 | if (result) { | 27 | if (result) { |
32 | res.render('home', Object.assign(result, { | 28 | res.render('home', Object.assign(result, { |
33 | isLogin: params.uid ? true : false, | 29 | isLogin: params.uid ? true : false, |
34 | module: 'home', | 30 | module: 'home', |
35 | page: 'index', | 31 | page: 'index', |
36 | - title: 'Yoho!Buy 有货', | ||
37 | - pageHeader: headerData, | 32 | + title: '个人中心 | Yoho!Buy有货 | 潮流购物逛不停', |
38 | pageFooter: true, | 33 | pageFooter: true, |
39 | pageChannel: { | 34 | pageChannel: { |
40 | boys: true | 35 | boys: true |
41 | - } | 36 | + }, |
37 | + showFooterTab: footerModel.getUrlData('mine') | ||
42 | })); | 38 | })); |
43 | } | 39 | } |
44 | }).catch(next); | 40 | }).catch(next); |
@@ -206,4 +202,3 @@ exports.preferential = (req, res, next) => { | @@ -206,4 +202,3 @@ exports.preferential = (req, res, next) => { | ||
206 | }).catch(next); | 202 | }).catch(next); |
207 | 203 | ||
208 | }; | 204 | }; |
209 | - |
@@ -15,67 +15,21 @@ const _serverCrash = (res, params) => { | @@ -15,67 +15,21 @@ const _serverCrash = (res, params) => { | ||
15 | res.render('installment/server-crash', params); | 15 | res.render('installment/server-crash', params); |
16 | }; | 16 | }; |
17 | 17 | ||
18 | -// 判断是否已经获取到了开通的状态值 | ||
19 | -const _reviewStatus = (res, req, uid, status) => { | ||
20 | - let jumpUrl = helpers.appUrlFormat('/product/new', 'go.new'); | ||
21 | - | ||
22 | - if (status === '1') { | ||
23 | - return { | ||
24 | - review: { | ||
25 | - url: jumpUrl | ||
26 | - } | ||
27 | - }; | ||
28 | - } else if (status === '2') { | ||
29 | - return Promise.all([installmentModel.getSearchIntallment({ | ||
30 | - page: 1 | ||
31 | - }), installmentModel.getQueryCreditInfo(uid)]).then((result) => { //eslint-disable-line | ||
32 | - return { | ||
33 | - success: { | ||
34 | - price: result[1].currCreditLimit, | ||
35 | - installmentOnly: { | ||
36 | - title: { | ||
37 | - title: '分期专享', | ||
38 | - more_url: helpers.appUrlFormat(req.originalUrl, 'go.instalmentlist', { | ||
39 | - title: '分期专享' | ||
40 | - }) | ||
41 | - }, | ||
42 | - goods: result[0] | ||
43 | - }, | ||
44 | - url: helpers.appUrlFormat(req.originalUrl, 'go.instalmentlist', { | ||
45 | - title: '分期专享' | ||
46 | - }) | ||
47 | - } | ||
48 | - }; | ||
49 | - }).catch(() => { | ||
50 | - _serverCrash(res, { | ||
51 | - url: req.originalUrl, | ||
52 | - title: '分期专享' | ||
53 | - }); | ||
54 | - }); | 18 | +const _banksInit = () => { |
19 | + const banks = ['农业银行', '中国银行', '工商银行', '建设银行', '光大银行', '兴业银行', '邮储银行', '民生银行', '中信银行', '广发银行']; | ||
55 | 20 | ||
56 | - } else if (status === '3') { | ||
57 | - return { | ||
58 | - error: true, | ||
59 | - failReason: '姓名、身份证、银行卡不匹配' | ||
60 | - }; | ||
61 | - } else if (status === '4') { | ||
62 | - return { | ||
63 | - cancel: { | ||
64 | - url: jumpUrl | ||
65 | - } | ||
66 | - }; | ||
67 | - } else if (status === '5') { | ||
68 | - return { | ||
69 | - error: true, | ||
70 | - failReason: '您的授信未通过,在有货更多的消费,增加信用度,会大大提升审核通过率奥。' | ||
71 | - }; | 21 | + if (new Date() >= new Date('2016-10-18 00:00:00')) { |
22 | + // 2016年10月12日至17日 平安银行业务暂停(平安银行期间不支持服务) | ||
23 | + banks.push('平安银行'); | ||
72 | } | 24 | } |
25 | + | ||
26 | + return banks; | ||
73 | }; | 27 | }; |
74 | 28 | ||
75 | // 还款列表公共处理块 | 29 | // 还款列表公共处理块 |
76 | const _repaymentList = (req, res, opt, params) => { | 30 | const _repaymentList = (req, res, opt, params) => { |
77 | params = _.assign({ | 31 | params = _.assign({ |
78 | - uid: req.cookies.installmentUid || 1 | 32 | + uid: req.cookies.installmentUid |
79 | }, params); | 33 | }, params); |
80 | 34 | ||
81 | installmentModel.getQueryAmtList(params).then((result) => { | 35 | installmentModel.getQueryAmtList(params).then((result) => { |
@@ -96,12 +50,14 @@ const _repaymentList = (req, res, opt, params) => { | @@ -96,12 +50,14 @@ const _repaymentList = (req, res, opt, params) => { | ||
96 | // 开通分期首页 | 50 | // 开通分期首页 |
97 | const index = (req, res) => { | 51 | const index = (req, res) => { |
98 | let uid = req.query.uid; | 52 | let uid = req.query.uid; |
53 | + Promise.all([ | ||
54 | + installmentModel.getStauts(uid), | ||
55 | + installmentModel.getSearchIntallment({ | ||
56 | + page: 1 | ||
57 | + }) | ||
58 | + ]).then((result) => { | ||
99 | 59 | ||
100 | - Promise.all([installmentModel.getStauts(uid), installmentModel.getSearchIntallment({ | ||
101 | - page: 1 | ||
102 | - })]).then((result) => { | ||
103 | - | ||
104 | - // status:0 未申请 1审核中 2已开通 3 审核未通过 | 60 | + // openStatus:0 未申请 1审核中 2已开通 3 审核未通过 |
105 | let openStatus = result[0]; | 61 | let openStatus = result[0]; |
106 | let installmentOnly = { | 62 | let installmentOnly = { |
107 | title: { | 63 | title: { |
@@ -114,22 +70,32 @@ const index = (req, res) => { | @@ -114,22 +70,32 @@ const index = (req, res) => { | ||
114 | }; | 70 | }; |
115 | 71 | ||
116 | if (openStatus === '0') { | 72 | if (openStatus === '0') { |
117 | - return installmentModel.getResources().then(data => { | ||
118 | - if (data[0] && data[0].data[0]) { | ||
119 | - data[0].data[0].url = 'javascript:void(0)'; //eslint-disable-line | ||
120 | - } | 73 | + return Promise.all([installmentModel.getResources('openN'), installmentModel.getNotices()]).then(data => { |
74 | + _.forEach(data[0], (item) => { | ||
75 | + if (item.singleOne) { | ||
76 | + item.data[0].url = 'javascript:void(0)'; //eslint-disable-line | ||
77 | + } | ||
78 | + }); | ||
121 | 79 | ||
122 | return { | 80 | return { |
123 | - bannerTop: data, | 81 | + content: data[0], |
82 | + notice: data[1], | ||
124 | notOpen: true, | 83 | notOpen: true, |
125 | installmentOnly: installmentOnly | 84 | installmentOnly: installmentOnly |
126 | }; | 85 | }; |
127 | }); | 86 | }); |
128 | } else if (openStatus === '2') { | 87 | } else if (openStatus === '2') { |
129 | - return Promise.all([installmentModel.getQueryCreditInfo(uid), installmentModel.getQueryAmtInfo(uid)]).then((data) => { //eslint-disable-line | 88 | + return Promise.all([ |
89 | + installmentModel.getQueryCreditInfo(uid), | ||
90 | + installmentModel.getQueryAmtInfo(uid), | ||
91 | + installmentModel.getResources('openY'), | ||
92 | + installmentModel.getNotices() | ||
93 | + ]).then((data) => { | ||
130 | let params = _.assign({ | 94 | let params = _.assign({ |
131 | isOverdue: false, | 95 | isOverdue: false, |
132 | - installmentOnly: installmentOnly | 96 | + installmentOnly: installmentOnly, |
97 | + content: data[2], | ||
98 | + notice: data[3] | ||
133 | }, data[0], data[1]); | 99 | }, data[0], data[1]); |
134 | 100 | ||
135 | // status: 1 正常 2 逾期 3 不可用 4 未开通 | 101 | // status: 1 正常 2 逾期 3 不可用 4 未开通 |
@@ -144,8 +110,14 @@ const index = (req, res) => { | @@ -144,8 +110,14 @@ const index = (req, res) => { | ||
144 | }); | 110 | }); |
145 | } else if (openStatus === '1' || openStatus === '3' || openStatus === '4' || openStatus === '5') { | 111 | } else if (openStatus === '1' || openStatus === '3' || openStatus === '4' || openStatus === '5') { |
146 | res.redirect('/home/installment/review?status=' + openStatus); | 112 | res.redirect('/home/installment/review?status=' + openStatus); |
113 | + | ||
114 | + return false; | ||
147 | } | 115 | } |
148 | }).then((result) => { | 116 | }).then((result) => { |
117 | + if (!result) { | ||
118 | + return; | ||
119 | + } | ||
120 | + | ||
149 | res.render('installment/open-index', _.assign({ | 121 | res.render('installment/open-index', _.assign({ |
150 | module: 'home', | 122 | module: 'home', |
151 | page: 'installment', | 123 | page: 'installment', |
@@ -194,13 +166,67 @@ const review = (req, res) => { | @@ -194,13 +166,67 @@ const review = (req, res) => { | ||
194 | page: 'installment', | 166 | page: 'installment', |
195 | title: '有货分期' | 167 | title: '有货分期' |
196 | }; | 168 | }; |
169 | + let templete = 'installment/open-result'; | ||
170 | + let jumpUrl = helpers.appUrlFormat('/product/new', 'go.new'); | ||
171 | + let params = {}; | ||
172 | + | ||
173 | + if (openStatus === '2') { | ||
174 | + Promise.all([ | ||
175 | + installmentModel.getSearchIntallment({ | ||
176 | + page: 1 | ||
177 | + }), | ||
178 | + installmentModel.getQueryCreditInfo(uid), | ||
179 | + installmentModel.getResources('advertisement') | ||
180 | + ]).then((result) => { | ||
181 | + res.render(templete, _.assign({ | ||
182 | + success: { | ||
183 | + price: result[1].currCreditLimit, | ||
184 | + installmentOnly: { | ||
185 | + title: { | ||
186 | + title: '分期专享', | ||
187 | + more_url: helpers.appUrlFormat(req.originalUrl, 'go.instalmentlist', { | ||
188 | + title: '分期专享' | ||
189 | + }) | ||
190 | + }, | ||
191 | + goods: result[0] | ||
192 | + }, | ||
193 | + advertisement: result[2][0].data[0], | ||
194 | + url: helpers.appUrlFormat(req.originalUrl, 'go.instalmentlist', { | ||
195 | + title: '分期专享' | ||
196 | + }) | ||
197 | + } | ||
198 | + }, data)); | ||
199 | + }).catch(() => { | ||
200 | + _serverCrash(res, { | ||
201 | + url: req.originalUrl | ||
202 | + }); | ||
203 | + }); | ||
197 | 204 | ||
198 | - if (openStatus !== '2') { | ||
199 | - res.render('installment/open-result', _.assign(data, _reviewStatus(res, req, uid, openStatus))); | ||
200 | } else { | 205 | } else { |
201 | - _reviewStatus(res, req, uid, openStatus).then((params) => { | ||
202 | - res.render('installment/open-result', _.assign(data, params)); | ||
203 | - }); | 206 | + if (openStatus === '1') { |
207 | + params = { | ||
208 | + review: { | ||
209 | + url: jumpUrl | ||
210 | + } | ||
211 | + }; | ||
212 | + } else if (openStatus === '3') { | ||
213 | + params = { | ||
214 | + error: true, | ||
215 | + failReason: req.query.failReason || '姓名、身份证、银行卡不匹配' | ||
216 | + }; | ||
217 | + } else if (openStatus === '4') { | ||
218 | + params = { | ||
219 | + cancel: { | ||
220 | + url: jumpUrl | ||
221 | + } | ||
222 | + }; | ||
223 | + } else if (openStatus === '5') { | ||
224 | + params = { | ||
225 | + error: true, | ||
226 | + failReason: '您的授信未通过,在有货更多的消费,增加信用度,会大大提升审核通过率奥。' | ||
227 | + }; | ||
228 | + } | ||
229 | + res.render(templete, _.assign(params, data)); | ||
204 | } | 230 | } |
205 | }; | 231 | }; |
206 | 232 | ||
@@ -258,7 +284,7 @@ const repayRecordPage = (req, res) => { | @@ -258,7 +284,7 @@ const repayRecordPage = (req, res) => { | ||
258 | // ajax 请求还款记录 | 284 | // ajax 请求还款记录 |
259 | const getRepayRecord = (req, res) => { | 285 | const getRepayRecord = (req, res) => { |
260 | let params = _.assign({ | 286 | let params = _.assign({ |
261 | - uid: req.cookies.installmentUid || 1, | 287 | + uid: req.cookies.installmentUid, |
262 | pageNo: req.query.page || 1 | 288 | pageNo: req.query.page || 1 |
263 | }); | 289 | }); |
264 | 290 | ||
@@ -281,23 +307,38 @@ const getRepayRecord = (req, res) => { | @@ -281,23 +307,38 @@ const getRepayRecord = (req, res) => { | ||
281 | 307 | ||
282 | // 账号管理 | 308 | // 账号管理 |
283 | const account = (req, res) => { | 309 | const account = (req, res) => { |
310 | + var url = req.yoho.isApp || req.cookies.appVersion ? '/home/installment/account' : '/home/installment/bank-card'; | ||
311 | + if (req.cookies.appVersion) { | ||
312 | + var versions = req.cookies.appVersion.split('.'); | ||
313 | + if (versions.length >= 2) { | ||
314 | + if (versions[0] < 5 || (parseInt(versions[0], 10)===5 && versions[1] <= 1)) { | ||
315 | + | ||
316 | + } else { | ||
317 | + url = helpers.appUrlFormat(url, 'go.instalmentMyCard') | ||
318 | + } | ||
319 | + } | ||
320 | + } | ||
284 | res.render('installment/account', { | 321 | res.render('installment/account', { |
285 | module: 'home', | 322 | module: 'home', |
286 | page: 'account', | 323 | page: 'account', |
287 | title: '账号管理', | 324 | title: '账号管理', |
288 | isInstallmentPage: true, | 325 | isInstallmentPage: true, |
289 | - posId: 7 | 326 | + posId: 7, |
327 | + url: url | ||
290 | }); | 328 | }); |
291 | }; | 329 | }; |
292 | 330 | ||
293 | // 添加新银行卡 | 331 | // 添加新银行卡 |
294 | const bindCard = (req, res) => { | 332 | const bindCard = (req, res) => { |
333 | + const banks = _banksInit(); | ||
334 | + | ||
295 | res.render('installment/bind-card', { | 335 | res.render('installment/bind-card', { |
296 | module: 'home', | 336 | module: 'home', |
297 | page: 'bind-card', | 337 | page: 'bind-card', |
298 | - title: '使用新卡还款', | 338 | + title: req.query.title || '使用新卡还款', |
299 | bindCard: { | 339 | bindCard: { |
300 | - userName: req.query.name | 340 | + userName: req.query.name, |
341 | + banks: banks.join('、') | ||
301 | }, | 342 | }, |
302 | isInstallmentPage: true | 343 | isInstallmentPage: true |
303 | }); | 344 | }); |
@@ -320,12 +361,7 @@ const postAccount = (req, res) => { | @@ -320,12 +361,7 @@ const postAccount = (req, res) => { | ||
320 | }; | 361 | }; |
321 | 362 | ||
322 | const startingService = (req, res) => { | 363 | const startingService = (req, res) => { |
323 | - const banks = ['农业银行', '中国银行', '工商银行', '建设银行', '光大银行', '兴业银行', '邮储银行', '民生银行', '中信银行', '广发银行']; | ||
324 | - | ||
325 | - if (new Date() >= new Date('2016-10-18 00:00:00')) { | ||
326 | - // 2016年10月12日至17日 平安银行业务暂停(平安银行期间不支持服务) | ||
327 | - banks.push('平安银行'); | ||
328 | - } | 364 | + const banks = _banksInit(); |
329 | 365 | ||
330 | res.render('installment/starting-service', { | 366 | res.render('installment/starting-service', { |
331 | module: 'home', | 367 | module: 'home', |
@@ -354,7 +390,7 @@ function getRealIP(req) { | @@ -354,7 +390,7 @@ function getRealIP(req) { | ||
354 | const activateService = (req, res) => { | 390 | const activateService = (req, res) => { |
355 | 391 | ||
356 | installmentModel.activateService({ | 392 | installmentModel.activateService({ |
357 | - uid: req.cookies.installmentUid || 532892, | 393 | + uid: req.cookies.installmentUid, |
358 | userName: req.body.userName, | 394 | userName: req.body.userName, |
359 | identityCardNo: req.body.identityCardNo, | 395 | identityCardNo: req.body.identityCardNo, |
360 | cardNo: req.body.cardNo, | 396 | cardNo: req.body.cardNo, |
@@ -378,7 +414,7 @@ const activateService = (req, res) => { | @@ -378,7 +414,7 @@ const activateService = (req, res) => { | ||
378 | const getBankInfo = (req, res) => { | 414 | const getBankInfo = (req, res) => { |
379 | installmentModel.getBankInfo({ | 415 | installmentModel.getBankInfo({ |
380 | cardNo: req.query.cardNo, | 416 | cardNo: req.query.cardNo, |
381 | - uid: req.cookies.installmentUid || 512579468 // TODO: fix uid | 417 | + uid: req.cookies.installmentUid |
382 | }).then((result)=> { | 418 | }).then((result)=> { |
383 | res.json(result); | 419 | res.json(result); |
384 | }).catch(() => { | 420 | }).catch(() => { |
@@ -411,7 +447,7 @@ const orderIndex = (req, res) => { | @@ -411,7 +447,7 @@ const orderIndex = (req, res) => { | ||
411 | 447 | ||
412 | const orderList = (req, res) => { | 448 | const orderList = (req, res) => { |
413 | const params = { | 449 | const params = { |
414 | - uid: req.cookies.installmentUid || 8041876, // TODO: fix me | 450 | + uid: req.cookies.installmentUid, |
415 | type: req.query.type || 1, | 451 | type: req.query.type || 1, |
416 | page: req.query.page || 1, | 452 | page: req.query.page || 1, |
417 | limit: req.query.limit || 10 | 453 | limit: req.query.limit || 10 |
@@ -447,7 +483,7 @@ const orderList = (req, res) => { | @@ -447,7 +483,7 @@ const orderList = (req, res) => { | ||
447 | 483 | ||
448 | const orderDetail = (req, res) => { | 484 | const orderDetail = (req, res) => { |
449 | const params = { | 485 | const params = { |
450 | - uid: req.cookies.installmentUid || 8041876, // TODO: fix me | 486 | + uid: req.cookies.installmentUid, |
451 | orderCode: req.params.id | 487 | orderCode: req.params.id |
452 | }; | 488 | }; |
453 | 489 | ||
@@ -490,7 +526,9 @@ const orderDetail = (req, res) => { | @@ -490,7 +526,9 @@ const orderDetail = (req, res) => { | ||
490 | navBtn: false, | 526 | navBtn: false, |
491 | currAmtCount: 0, | 527 | currAmtCount: 0, |
492 | currFeeCount: 0, | 528 | currFeeCount: 0, |
493 | - isCurrFee: true, | 529 | + isInstallmentPage: true, |
530 | + isCurrFee: true | ||
531 | + }, { | ||
494 | helpers: { | 532 | helpers: { |
495 | isPaymentComplete: function(status, options) { | 533 | isPaymentComplete: function(status, options) { |
496 | if (status === 2 || status === 4 || status === 5) { // 已结清/已取消 | 534 | if (status === 2 || status === 4 || status === 5) { // 已结清/已取消 |
@@ -539,7 +577,7 @@ const orderDetail = (req, res) => { | @@ -539,7 +577,7 @@ const orderDetail = (req, res) => { | ||
539 | // 还款详情 | 577 | // 还款详情 |
540 | const repayDetail = (req, res) => { | 578 | const repayDetail = (req, res) => { |
541 | let params = { | 579 | let params = { |
542 | - uid: req.cookies.installmentUid || 512579468, | 580 | + uid: req.cookies.installmentUid, |
543 | rePayNo: req.query.id || '', | 581 | rePayNo: req.query.id || '', |
544 | pageNo: 1 | 582 | pageNo: 1 |
545 | }; | 583 | }; |
@@ -601,13 +639,16 @@ const serverCrash = (req, res) => { | @@ -601,13 +639,16 @@ const serverCrash = (req, res) => { | ||
601 | 639 | ||
602 | // 银行卡列表 | 640 | // 银行卡列表 |
603 | const bankCard = (req, res) => { | 641 | const bankCard = (req, res) => { |
604 | - let uid = req.cookies.installmentUid || 512579468; | 642 | + let uid = req.cookies.installmentUid; |
605 | 643 | ||
606 | installmentModel.getBankCards(uid).then((result) => { | 644 | installmentModel.getBankCards(uid).then((result) => { |
607 | res.render('installment/bank-card', { | 645 | res.render('installment/bank-card', { |
646 | + module: 'home', | ||
647 | + page: 'bank-card', | ||
608 | title: '我的银行卡', | 648 | title: '我的银行卡', |
609 | isInstallmentPage: true, | 649 | isInstallmentPage: true, |
610 | - accountList: result | 650 | + accountList: result, |
651 | + userName: result[0].userName | ||
611 | }); | 652 | }); |
612 | }).catch(() => { | 653 | }).catch(() => { |
613 | _serverCrash(res, { | 654 | _serverCrash(res, { |
@@ -617,6 +658,62 @@ const bankCard = (req, res) => { | @@ -617,6 +658,62 @@ const bankCard = (req, res) => { | ||
617 | }); | 658 | }); |
618 | }; | 659 | }; |
619 | 660 | ||
661 | +// 银行卡详情 | ||
662 | +const cardDetail = (req, res) => { | ||
663 | + let uid = req.cookies.installmentUid; | ||
664 | + let cardIdNo = req.query.cardIdNo; | ||
665 | + | ||
666 | + installmentModel.getCardDetail(uid, cardIdNo).then((result) => { | ||
667 | + res.render('installment/card-detail', { | ||
668 | + module: 'home', | ||
669 | + page: 'card-detail', | ||
670 | + title: '银行卡详情', | ||
671 | + isInstallmentPage: true, | ||
672 | + width750: true, | ||
673 | + cardDetail: result | ||
674 | + }); | ||
675 | + }).catch(() => { | ||
676 | + _serverCrash(res, { | ||
677 | + url: req.originalUrl, | ||
678 | + title: '银行卡详情' | ||
679 | + }); | ||
680 | + }); | ||
681 | +}; | ||
682 | + | ||
683 | +// 删除绑定 | ||
684 | +const delBankCard = (req, res) => { | ||
685 | + let params = { | ||
686 | + uid: req.cookies.installmentUid, | ||
687 | + cardIdNo: req.query.cardIdNo | ||
688 | + }; | ||
689 | + | ||
690 | + installmentModel.delBankCard(params).then((result) => { | ||
691 | + res.json(result); | ||
692 | + }).catch(() => { | ||
693 | + _serverCrash(res, { | ||
694 | + url: req.originalUrl, | ||
695 | + title: '银行卡详情' | ||
696 | + }); | ||
697 | + }); | ||
698 | +}; | ||
699 | + | ||
700 | +// 切换银行卡绑定 | ||
701 | +const setMasterCard = (req, res) => { | ||
702 | + let params = { | ||
703 | + uid: req.cookies.installmentUid, | ||
704 | + cardIdNo: req.query.cardIdNo | ||
705 | + }; | ||
706 | + | ||
707 | + installmentModel.setMasterCard(params).then((result) => { | ||
708 | + res.json(result); | ||
709 | + }).catch(() => { | ||
710 | + _serverCrash(res, { | ||
711 | + url: req.originalUrl, | ||
712 | + title: '银行卡详情' | ||
713 | + }); | ||
714 | + }); | ||
715 | +}; | ||
716 | + | ||
620 | module.exports = { | 717 | module.exports = { |
621 | index, | 718 | index, |
622 | review, | 719 | review, |
@@ -643,5 +740,8 @@ module.exports = { | @@ -643,5 +740,8 @@ module.exports = { | ||
643 | bindCard, | 740 | bindCard, |
644 | serverCrash, | 741 | serverCrash, |
645 | bankCard, | 742 | bankCard, |
646 | - postAccount | 743 | + postAccount, |
744 | + cardDetail, | ||
745 | + delBankCard, | ||
746 | + setMasterCard | ||
647 | }; | 747 | }; |
@@ -4,13 +4,19 @@ const model = require('../models/myqrcode'), | @@ -4,13 +4,19 @@ const model = require('../models/myqrcode'), | ||
4 | headerModel = require('../../../doraemon/models/header'); // 头部model | 4 | headerModel = require('../../../doraemon/models/header'); // 头部model |
5 | 5 | ||
6 | exports.index = (req, res, next) => { | 6 | exports.index = (req, res, next) => { |
7 | - let params = req.query; | 7 | + let params = req.query, |
8 | + esc = false, | ||
9 | + appversion = req.query.app_version; | ||
10 | + | ||
11 | + if (Number(appversion.substr(0, 1) < 5) || (Number(appversion.substr(0, 1)) === 5 && Number(appversion.substr(2, 1)) < 2)) { | ||
12 | + esc = true; | ||
13 | + } | ||
8 | 14 | ||
9 | model.getQr({ | 15 | model.getQr({ |
10 | token: params.token, | 16 | token: params.token, |
11 | }).then(result => { | 17 | }).then(result => { |
12 | params.token = result; | 18 | params.token = result; |
13 | - params.uname = decodeURIComponent(params.uname); | 19 | + params.uname = esc ? decodeURIComponent(params.uname) : decodeURIComponent(params.uname.replace(/\%/g, escape('%'))); |
14 | params.icon = params.icon || 'https://img11.static.yhbimg.com/yhb-img01/2016/07/05/13/017ec560b82c132ab2fdb22f7cf6f42b83.png?imageView/2/w/{width}/h/{height}'; | 20 | params.icon = params.icon || 'https://img11.static.yhbimg.com/yhb-img01/2016/07/05/13/017ec560b82c132ab2fdb22f7cf6f42b83.png?imageView/2/w/{width}/h/{height}'; |
15 | res.render('myqrcode', { | 21 | res.render('myqrcode', { |
16 | title: '查看二维码', | 22 | title: '查看二维码', |
@@ -14,15 +14,13 @@ const orderDetailData = (req, res, next) => { | @@ -14,15 +14,13 @@ const orderDetailData = (req, res, next) => { | ||
14 | let orderCode = req.query.order_code; | 14 | let orderCode = req.query.order_code; |
15 | 15 | ||
16 | orderDetailModel.orderDetailData(uid, orderCode).then(result => { | 16 | orderDetailModel.orderDetailData(uid, orderCode).then(result => { |
17 | - | 17 | + result.serviceUrl = 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='; |
18 | res.render('orderDetail', { | 18 | res.render('orderDetail', { |
19 | module: 'home', | 19 | module: 'home', |
20 | page: 'order-detail', | 20 | page: 'order-detail', |
21 | pageHeader: headerModel.setNav({ | 21 | pageHeader: headerModel.setNav({ |
22 | navTitle: '订单详情', | 22 | navTitle: '订单详情', |
23 | - navBtn: false, | ||
24 | - orderDetail: true, | ||
25 | - serviceUrl: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=', | 23 | + navBtn: false |
26 | }), | 24 | }), |
27 | title: '订单详情', | 25 | title: '订单详情', |
28 | pageFooter: true, | 26 | pageFooter: true, |
@@ -11,11 +11,11 @@ const headerModel = require('../../../doraemon/models/header'); // 头部model | @@ -11,11 +11,11 @@ const headerModel = require('../../../doraemon/models/header'); // 头部model | ||
11 | const _ = require('lodash'); | 11 | const _ = require('lodash'); |
12 | 12 | ||
13 | const suggestData = (req, res, next) => { | 13 | const suggestData = (req, res, next) => { |
14 | + let uid = req.user.uid; | ||
14 | let udid = req.sessionID || 'yoho'; | 15 | let udid = req.sessionID || 'yoho'; |
15 | let page = req.query.page || 1; | 16 | let page = req.query.page || 1; |
16 | let limit = 10; | 17 | let limit = 10; |
17 | - | ||
18 | - suggestModel.suggestData(udid, page, limit).then((result) => { | 18 | + suggestModel.suggestData(uid, udid, page, limit).then((result) => { |
19 | 19 | ||
20 | res.render('suggest', { | 20 | res.render('suggest', { |
21 | module: 'home', | 21 | module: 'home', |
@@ -84,7 +84,9 @@ const _getAddressData = (params) => { | @@ -84,7 +84,9 @@ const _getAddressData = (params) => { | ||
84 | return api.get('', { | 84 | return api.get('', { |
85 | method: 'app.address.gethidden', | 85 | method: 'app.address.gethidden', |
86 | uid: params.uid | 86 | uid: params.uid |
87 | - }, {code: 200}); | 87 | + }, { |
88 | + code: 200 | ||
89 | + }); | ||
88 | } else { | 90 | } else { |
89 | return false; | 91 | return false; |
90 | } | 92 | } |
@@ -98,7 +100,6 @@ const _getAddressData = (params) => { | @@ -98,7 +100,6 @@ const _getAddressData = (params) => { | ||
98 | const index = (params) => { | 100 | const index = (params) => { |
99 | let finalResult = { | 101 | let finalResult = { |
100 | myIndexPage: true, | 102 | myIndexPage: true, |
101 | - showDownloadApp: true, | ||
102 | navHome: true, | 103 | navHome: true, |
103 | pageFooter: true, | 104 | pageFooter: true, |
104 | refundExchangeNum: 0, | 105 | refundExchangeNum: 0, |
@@ -452,5 +453,6 @@ module.exports = { | @@ -452,5 +453,6 @@ module.exports = { | ||
452 | recordContent, | 453 | recordContent, |
453 | delRecord, | 454 | delRecord, |
454 | getGrade, | 455 | getGrade, |
455 | - getPreferential | 456 | + getPreferential, |
457 | + getGradeGrade, | ||
456 | }; | 458 | }; |
@@ -13,6 +13,11 @@ const api = global.yoho.API; | @@ -13,6 +13,11 @@ const api = global.yoho.API; | ||
13 | const serviceAPI = global.yoho.ServiceAPI; | 13 | const serviceAPI = global.yoho.ServiceAPI; |
14 | const logger = global.yoho.logger; | 14 | const logger = global.yoho.logger; |
15 | const API_TIMEOUT = 10000; | 15 | const API_TIMEOUT = 10000; |
16 | +const codeContent = { | ||
17 | + openN: '0876085ff46bed27f1a1eb6ee8b68987', | ||
18 | + openY: 'c233ad4ca91fef45ed7d0b26d9953e61', | ||
19 | + advertisement: 'f3fe0793a7d59479542a14b15359c47d' | ||
20 | +}; | ||
16 | 21 | ||
17 | // 处理还款列表数据 | 22 | // 处理还款列表数据 |
18 | const _processAmtList = (listData, queryDays) => { | 23 | const _processAmtList = (listData, queryDays) => { |
@@ -145,19 +150,7 @@ const _processBankCards = (list) => { | @@ -145,19 +150,7 @@ const _processBankCards = (list) => { | ||
145 | list = list || []; | 150 | list = list || []; |
146 | 151 | ||
147 | _.forEach(list, (data) => { | 152 | _.forEach(list, (data) => { |
148 | - // let newCardNo = data.cardNo.split(''); | ||
149 | - // let cardNo = newCardNo.length; | ||
150 | - // data.cardNo = ''; | ||
151 | - // | ||
152 | - // | ||
153 | - // for (let i = 1; i < cardNo; i++) { | ||
154 | - // if (i < (cardNo - 4)) { | ||
155 | - // data.cardNo += '*'; | ||
156 | - // } else { | ||
157 | - // data.cardNo += newCardNo[i - 1]; | ||
158 | - // } | ||
159 | - // } | ||
160 | - | 153 | + data.url = '/home/installment/card-detail?cardIdNo=' + data.cardIdNo; |
161 | 154 | ||
162 | // 正则替换卡号,保留后4位 | 155 | // 正则替换卡号,保留后4位 |
163 | data.cardNo = data.cardNo.replace(/(\d+)(\d{4})$/, function(a, b, c) { | 156 | data.cardNo = data.cardNo.replace(/(\d+)(\d{4})$/, function(a, b, c) { |
@@ -169,13 +162,24 @@ const _processBankCards = (list) => { | @@ -169,13 +162,24 @@ const _processBankCards = (list) => { | ||
169 | return list; | 162 | return list; |
170 | }; | 163 | }; |
171 | 164 | ||
165 | +// 银行卡详情数据处理 | ||
166 | +const _processCardDetail = (list) => { | ||
167 | + list = list || {}; | ||
168 | + | ||
169 | + list.isMaster = list.masterType === '1' ? true : false; | ||
170 | + list.cardNo = list.cardNo ? list.cardNo.replace(/\*/g, '') : list.cardNo; | ||
171 | + | ||
172 | + return list; | ||
173 | +}; | ||
174 | + | ||
172 | /** | 175 | /** |
173 | * 获取资源位数据 | 176 | * 获取资源位数据 |
174 | * @return {[array]} | 177 | * @return {[array]} |
175 | */ | 178 | */ |
176 | -const getResources = () => { | 179 | +const getResources = (code) => { |
177 | return serviceAPI.get('/operations/api/v5/resource/get', { | 180 | return serviceAPI.get('/operations/api/v5/resource/get', { |
178 | - content_code: '0876085ff46bed27f1a1eb6ee8b68987' | 181 | + content_code: codeContent[code], |
182 | + platform: 'iphone' | ||
179 | }, { | 183 | }, { |
180 | cache: true | 184 | cache: true |
181 | }).then((result) => { | 185 | }).then((result) => { |
@@ -481,6 +485,63 @@ const postAccount = (params) => { | @@ -481,6 +485,63 @@ const postAccount = (params) => { | ||
481 | }); | 485 | }); |
482 | }; | 486 | }; |
483 | 487 | ||
488 | +// 获取银行卡详情 | ||
489 | +const getCardDetail = (uid, cardIdNo) => { | ||
490 | + return api.get('', { | ||
491 | + method: 'user.instalment.getBankCardDetail', | ||
492 | + uid: uid, | ||
493 | + cardIdNo: cardIdNo | ||
494 | + }, { | ||
495 | + timeout: API_TIMEOUT | ||
496 | + }).then((result) => { | ||
497 | + if (result && result.code === 200) { | ||
498 | + return _processCardDetail(result.data); | ||
499 | + } else { | ||
500 | + logger.error('get getBankCards data return code is not 200'); | ||
501 | + return Promise.reject(result); | ||
502 | + } | ||
503 | + }); | ||
504 | +}; | ||
505 | + | ||
506 | +// 解除银行卡绑定 | ||
507 | +const delBankCard = (params) => { | ||
508 | + return api.get('', _.assign({ | ||
509 | + method: 'user.instalment.unbindCard' | ||
510 | + }, params)).then((res) => { | ||
511 | + return res; | ||
512 | + }); | ||
513 | +}; | ||
514 | + | ||
515 | +// 切换银行卡主卡 | ||
516 | +const setMasterCard = (params) => { | ||
517 | + return api.get('', _.assign({ | ||
518 | + method: 'user.instalment.toggleCard' | ||
519 | + }, params)).then((res) => { | ||
520 | + return res; | ||
521 | + }); | ||
522 | +}; | ||
523 | + | ||
524 | +// 公告 | ||
525 | +const getNotices = () => { | ||
526 | + return api.get('', { | ||
527 | + method: 'app.resources.getNotices', | ||
528 | + position: 8, | ||
529 | + client_type: 'iphone' | ||
530 | + }, { | ||
531 | + cache: true | ||
532 | + }).then((res) => { | ||
533 | + if (res && res.code === 200) { | ||
534 | + if (res.data && res.data.list.length < 1) { | ||
535 | + return false; | ||
536 | + } else { | ||
537 | + return res.data; | ||
538 | + } | ||
539 | + } else { | ||
540 | + return false; | ||
541 | + } | ||
542 | + }); | ||
543 | +}; | ||
544 | + | ||
484 | module.exports = { | 545 | module.exports = { |
485 | getStauts, | 546 | getStauts, |
486 | getQueryCreditInfo, | 547 | getQueryCreditInfo, |
@@ -497,5 +558,12 @@ module.exports = { | @@ -497,5 +558,12 @@ module.exports = { | ||
497 | getInstallmentOrderDetail, | 558 | getInstallmentOrderDetail, |
498 | totalAmount, | 559 | totalAmount, |
499 | checkVerifyCode, | 560 | checkVerifyCode, |
500 | - postAccount | 561 | + postAccount, |
562 | + getCardDetail, | ||
563 | + delBankCard, | ||
564 | + setMasterCard, | ||
565 | + getNotices | ||
501 | }; | 566 | }; |
567 | + | ||
568 | + | ||
569 | + |
@@ -9,8 +9,8 @@ exports.getQr = (params) => { | @@ -9,8 +9,8 @@ exports.getQr = (params) => { | ||
9 | 9 | ||
10 | try { | 10 | try { |
11 | uid = crypto.decrypt(PASSWORD, decodeURIComponent(params.token)); | 11 | uid = crypto.decrypt(PASSWORD, decodeURIComponent(params.token)); |
12 | + uid = parseInt(uid, 10) | ||
12 | } catch (e) { | 13 | } catch (e) { |
13 | - console.error(e); | ||
14 | uid = params.token; | 14 | uid = params.token; |
15 | } | 15 | } |
16 | 16 |
@@ -11,14 +11,13 @@ const serviceAPI = global.yoho.ServiceAPI; | @@ -11,14 +11,13 @@ const serviceAPI = global.yoho.ServiceAPI; | ||
11 | const camelCase = global.yoho.camelCase; | 11 | const camelCase = global.yoho.camelCase; |
12 | const _ = require('lodash'); | 12 | const _ = require('lodash'); |
13 | 13 | ||
14 | -const suggestData = (udid, page, limit) => { | 14 | +const suggestData = (uid, udid, page, limit) => { |
15 | 15 | ||
16 | return serviceAPI.get('suggest/api/v1/suggest/getList', { | 16 | return serviceAPI.get('suggest/api/v1/suggest/getList', { |
17 | udid: udid, | 17 | udid: udid, |
18 | page: page, | 18 | page: page, |
19 | limit: limit | 19 | limit: limit |
20 | }).then((result) => { | 20 | }).then((result) => { |
21 | - | ||
22 | if (result && result.code === 200 && result.data) { | 21 | if (result && result.code === 200 && result.data) { |
23 | _.forEach(result.data.list, function(data) { | 22 | _.forEach(result.data.list, function(data) { |
24 | 23 | ||
@@ -36,7 +35,6 @@ const suggestData = (udid, page, limit) => { | @@ -36,7 +35,6 @@ const suggestData = (udid, page, limit) => { | ||
36 | }; | 35 | }; |
37 | 36 | ||
38 | const upAndDown = (uid, udid, reliable, suggestId) => { | 37 | const upAndDown = (uid, udid, reliable, suggestId) => { |
39 | - | ||
40 | return serviceAPI.get('suggest/api/v1/suggest/is_reliable', { | 38 | return serviceAPI.get('suggest/api/v1/suggest/is_reliable', { |
41 | uid: uid, | 39 | uid: uid, |
42 | udid: udid, | 40 | udid: udid, |
@@ -131,6 +131,9 @@ router.get('/installment/agreement', installment.agreement);// æœåŠ¡åè®®é™æ€ | @@ -131,6 +131,9 @@ router.get('/installment/agreement', installment.agreement);// æœåŠ¡åè®®é™æ€ | ||
131 | 131 | ||
132 | router.get('/installment/server-crash', installment.serverCrash); // 服务器崩溃 | 132 | router.get('/installment/server-crash', installment.serverCrash); // 服务器崩溃 |
133 | router.get('/installment/bank-card', installment.bankCard); // 银行卡列表 | 133 | router.get('/installment/bank-card', installment.bankCard); // 银行卡列表 |
134 | +router.get('/installment/card-detail', installment.cardDetail); // 银行卡详情 | ||
135 | +router.get('/installment/delBankCard', installment.delBankCard); // 删除绑定 | ||
136 | +router.get('/installment/setMasterCard', installment.setMasterCard); // 切换主卡 | ||
134 | 137 | ||
135 | router.get('/recommend-for-you/userCenter', recommendForYou.userCenter);// 为你优选 | 138 | router.get('/recommend-for-you/userCenter', recommendForYou.userCenter);// 为你优选 |
136 | 139 |
@@ -130,8 +130,7 @@ | @@ -130,8 +130,7 @@ | ||
130 | {{#unless @root.wap.ucenter.removePrefer}} | 130 | {{#unless @root.wap.ucenter.removePrefer}} |
131 | {{> common/recommend-for-you}} | 131 | {{> common/recommend-for-you}} |
132 | {{/unless}} | 132 | {{/unless}} |
133 | - {{> common/suspend-cart}} | ||
134 | </div> | 133 | </div> |
135 | 134 | ||
136 | -{{> download-app}} | 135 | +{{> footer-tab}} |
137 | 136 |
1 | <div class="account-page" data-pos-id="{{posId}}"> | 1 | <div class="account-page" data-pos-id="{{posId}}"> |
2 | <ul class="account-list"> | 2 | <ul class="account-list"> |
3 | - <li><a href="/home/installment/bank-card">我的银行卡:<div class="list-right"><span class="iconfont"></span></div></a></li> | 3 | + <li><a href="{{url}}">我的银行卡:<div class="list-right"><span class="iconfont"></span></div></a></li> |
4 | </ul> | 4 | </ul> |
5 | </div> | 5 | </div> |
1 | <div class="bank-card-page"> | 1 | <div class="bank-card-page"> |
2 | - <ul class="bank-card-list"> | 2 | + <div class="bank-card-list" data-user="{{userName}}"> |
3 | {{#accountList}} | 3 | {{#accountList}} |
4 | - <li class="card-bg-{{lowerCase bankCode}}"><span>{{cardNo}}</span></li> | 4 | + <a class="card-bg-{{lowerCase bankCode}} card-nav" href="{{url}}"><span>{{cardNo}}</span></a> |
5 | {{/accountList}} | 5 | {{/accountList}} |
6 | - </ul> | 6 | + </div> |
7 | </div> | 7 | </div> |
@@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
8 | <li> | 8 | <li> |
9 | <label>银行卡</label> | 9 | <label>银行卡</label> |
10 | <input id="cardNo" name="cardNo" type="tel" placeholder="请输入本人银行卡号" size="26" maxlength="23"> | 10 | <input id="cardNo" name="cardNo" type="tel" placeholder="请输入本人银行卡号" size="26" maxlength="23"> |
11 | + <span class="iconfont notice"></span> | ||
11 | </li> | 12 | </li> |
12 | <li id="bank-desc" style="display: none;"> | 13 | <li id="bank-desc" style="display: none;"> |
13 | <div class="bank-info"> | 14 | <div class="bank-info"> |
@@ -20,8 +21,19 @@ | @@ -20,8 +21,19 @@ | ||
20 | <input type="number" placeholder="请输入银行预留手机号" id="mobile" name="mobile" pattern="\d*" maxlength="11"> | 21 | <input type="number" placeholder="请输入银行预留手机号" id="mobile" name="mobile" pattern="\d*" maxlength="11"> |
21 | </li> | 22 | </li> |
22 | </ul> | 23 | </ul> |
23 | - <a href="" class="open-btn disabled">下一步</a> | 24 | + <div class="open-btn disabled">下一步</div> |
24 | <a href="" class="jumpResult"> </a> | 25 | <a href="" class="jumpResult"> </a> |
26 | + | ||
27 | + <div class="installment-overdue-notice"> | ||
28 | + <div class="mask-bg"></div> | ||
29 | + <div class="notice-area"> | ||
30 | + <div class="notice-cont"> | ||
31 | + <h2>支持银行</h2> | ||
32 | + <p>{{banks}}</p> | ||
33 | + </div> | ||
34 | + <div class="think-ok">我知道了</div> | ||
35 | + </div> | ||
36 | + </div> | ||
25 | {{/bindCard}} | 37 | {{/bindCard}} |
26 | 38 | ||
27 | <div class="success"> | 39 | <div class="success"> |
1 | +<div class="card-detail-page yoho-page"> | ||
2 | + {{#cardDetail}} | ||
3 | + <div class="card-detail" data-card-id="{{cardIdNo}}"> | ||
4 | + <div class="card-icon card-icon-{{lowerCase bankCode}}"></div> | ||
5 | + <div class="card-right"> | ||
6 | + <p class="bank-name">{{bankName}}</p> | ||
7 | + <p class="card-no">储蓄卡 | 尾号{{cardNo}}</p> | ||
8 | + </div> | ||
9 | + </div> | ||
10 | + <ul class="card-info"> | ||
11 | + <li><span class="txt-label">持卡人</span><span class="info-right card-user">{{userName}}</span></li> | ||
12 | + <li><span class="txt-label">预留手机号</span><span class="info-right card-mobile">{{mobile}}</span></li> | ||
13 | + <li> | ||
14 | + <span class="txt-label">分期银行</span> | ||
15 | + <span class="info-right card-bank"> | ||
16 | + {{#if isMaster}} | ||
17 | + 主卡,用于支付验证和还款验证。 | ||
18 | + {{else}} | ||
19 | + 副卡,仅用于还款验证。 | ||
20 | + {{/if}} | ||
21 | + </span> | ||
22 | + </li> | ||
23 | + </ul> | ||
24 | + <div class="tip-cont"> | ||
25 | + {{#if isMaster}} | ||
26 | + <p>如果您更换银行预留手机号,请先新增其他还款银行卡,并将新增银行卡切换为主卡。然后解除绑定此卡,重新绑定即可。</p> | ||
27 | + {{else}} | ||
28 | + <p>如果您更换银行预留手机号,请先将银行卡解除绑定,再次重新绑定即可。</p> | ||
29 | + | ||
30 | + <div class="card-btn"> | ||
31 | + <span class="relieve-btn">解除绑定</span> | ||
32 | + <span class="change-btn">切换为主卡</span> | ||
33 | + </div> | ||
34 | + {{/if}} | ||
35 | + </div> | ||
36 | + {{/cardDetail}} | ||
37 | +</div> |
@@ -140,7 +140,7 @@ | @@ -140,7 +140,7 @@ | ||
140 | <div class='help-group'> | 140 | <div class='help-group'> |
141 | <h2>五、服务支持</h2> | 141 | <h2>五、服务支持</h2> |
142 | <p> | 142 | <p> |
143 | - 如您在使用有货分期过程中遇到还款及资金安全方面问题您可联系信而富客服为,您进行相关处理和解答,联系电话:400-688-8692(工作日9:00-18:00),如您无法联系信而富客服您可联系有货客服,我们将在3个工作日内给您回复,感谢您的理解与支持! | 143 | + 如您在使用有货分期过程中遇到还款及资金安全方面问题,您可联系信而富客服为您进行相关处理和解答,联系电话:400-688-8692(工作日9:00-18:00),如您无法联系信而富客服您可联系有货客服,我们将在3个工作日内给您回复,感谢您的理解与支持! |
144 | </p> | 144 | </p> |
145 | </div> | 145 | </div> |
146 | </div> | 146 | </div> |
1 | <div class="installment-page installment-bg yoho-page"> | 1 | <div class="installment-page installment-bg yoho-page"> |
2 | - {{#if notOpen}} | ||
3 | - <input type="hidden" value="false" class="is-open"> | ||
4 | - {{# bannerTop}} | ||
5 | - {{> resources/banner-top}} | ||
6 | - {{/ bannerTop}} | ||
7 | - <div class="open-index"> | ||
8 | - <ul class="open-info"> | ||
9 | - <li> | ||
10 | - <span class="open-icon-1"></span> | ||
11 | - <span>先消费<br>后还款</span> | ||
12 | - </li> | ||
13 | - <li> | ||
14 | - <span class="open-icon-2"></span> | ||
15 | - <span>30天免息<br>灵活分期</span> | ||
16 | - </li> | ||
17 | - <li> | ||
18 | - <span class="open-icon-3"></span> | ||
19 | - <span>指定商品<br>立享优惠</span> | ||
20 | - </li> | ||
21 | - </ul> | 2 | + <div class="loading-tip">下拉刷新</div> |
3 | + <div class="installment-main"> | ||
4 | + <div class="main-content"> | ||
5 | + {{#if notOpen}} | ||
6 | + <input type="hidden" value="false" class="is-open"> | ||
7 | + {{# content}} | ||
8 | + {{#if singleImage}} | ||
9 | + {{> resources/banner}} | ||
10 | + {{/if}} | ||
11 | + {{/ content}} | ||
12 | + {{#notice}} | ||
13 | + {{> installment/installment-notice}} | ||
14 | + {{/notice}} | ||
15 | + <div class="open-index"> | ||
16 | + <ul class="open-info"> | ||
17 | + <li> | ||
18 | + <span class="open-icon-1"></span> | ||
19 | + <span>先消费<br>后还款</span> | ||
20 | + </li> | ||
21 | + <li> | ||
22 | + <span class="open-icon-2"></span> | ||
23 | + <span>30天免息<br>灵活分期</span> | ||
24 | + </li> | ||
25 | + <li> | ||
26 | + <span class="open-icon-3"></span> | ||
27 | + <span>指定商品<br>立享优惠</span> | ||
28 | + </li> | ||
29 | + </ul> | ||
22 | 30 | ||
23 | - <a href="/home/installment/starting-service" class="open-btn">立即开通</a> | ||
24 | - </div> | 31 | + <a href="/home/installment/starting-service" class="open-btn">立即开通</a> |
32 | + </div> | ||
25 | 33 | ||
26 | - {{# installmentOnly}} | ||
27 | - {{> installment/installment-only}} | ||
28 | - {{/ installmentOnly}} | ||
29 | - {{else}} | ||
30 | - <input type="hidden" value="true" class="is-open"> | ||
31 | - <div class="detail-tab"> | ||
32 | - <span class="on is-repay">待还款金额</span> | ||
33 | - <span class="is-usable">可用额度</span> | ||
34 | - </div> | ||
35 | - <div class="repay installment-cont"> | ||
36 | - <div class="repay-area detail-bg"> | ||
37 | - <p class="detail-txt1">近7日待还款</p> | ||
38 | - <p class="detail-txt1">¥<span class="detail-txt2">{{dayAmt}}</span></p> | ||
39 | - {{#if isOverdue}} | ||
40 | - <p class="detail-txt3">您有¥{{overAmt}}已逾期,点击<a href="/home/installment/repay/overdue" class="nav-bit" data-id="1">查看详情</a></p> | ||
41 | - {{/if}} | ||
42 | - <a href="/home/installment/repay/7daylist" class="see-btn nav-bit" data-id="2">明细</a> | ||
43 | - </div> | ||
44 | - <ul class="group-list"> | ||
45 | - <li><a href="/home/installment/repay/month" class="nav-bit" data-id="3">本月待还金额:<div class="list-right"><span class="list-r-txt">¥{{monthAmt}}</span><span class="iconfont"> </span></div></a></li> | ||
46 | - <li><a href="/home/installment/repay/total" class="nav-bit" data-id="4">待还总金额:<div class="list-right"><span class="list-r-txt">¥{{totalAmt}}</span><span class="iconfont"> </span></div></a></li> | ||
47 | - <li><a href="/home/installment/repay/record" class="nav-bit" data-id="5">还款记录:<div class="list-right iconfont"></div></a></li> | ||
48 | - <li><a href="/home/installment/order" class="nav-bit" data-id="6">分期订单:<div class="list-right iconfont"></div></a></li> | ||
49 | - </ul> | 34 | + {{# installmentOnly}} |
35 | + {{> installment/installment-only}} | ||
36 | + {{/ installmentOnly}} | ||
37 | + {{else}} | ||
38 | + <input type="hidden" value="true" class="is-open"> | ||
39 | + <div class="detail-tab"> | ||
40 | + <span class="on is-repay">待还款金额</span> | ||
41 | + <span class="is-usable">可用额度</span> | ||
42 | + </div> | ||
43 | + <div class="repay installment-cont"> | ||
44 | + <div class="repay-area detail-bg"> | ||
45 | + <p class="detail-txt1">近7日待还款</p> | ||
46 | + <p class="detail-txt1">¥<span class="detail-txt2">{{dayAmt}}</span></p> | ||
47 | + {{#if isOverdue}} | ||
48 | + <p class="detail-txt3">您有¥{{overAmt}}已逾期,点击<a href="/home/installment/repay/overdue" class="nav-bit" data-id="1">查看详情</a></p> | ||
49 | + {{/if}} | ||
50 | + <a href="/home/installment/repay/7daylist" class="see-btn nav-bit" data-id="2">明细</a> | ||
51 | + </div> | ||
52 | + {{#notice}} | ||
53 | + {{> installment/installment-notice}} | ||
54 | + {{/notice}} | ||
55 | + <ul class="group-list"> | ||
56 | + <li><a href="/home/installment/repay/month" class="nav-bit" data-id="3">本月待还金额:<div class="list-right"><span class="list-r-txt">¥{{monthAmt}}</span><span class="iconfont"> </span></div></a></li> | ||
57 | + <li><a href="/home/installment/repay/total" class="nav-bit" data-id="4">待还总金额:<div class="list-right"><span class="list-r-txt">¥{{totalAmt}}</span><span class="iconfont"> </span></div></a></li> | ||
58 | + <li><a href="/home/installment/repay/record" class="nav-bit" data-id="5">还款记录:<div class="list-right iconfont"></div></a></li> | ||
59 | + <li><a href="/home/installment/order" class="nav-bit" data-id="6">分期订单:<div class="list-right iconfont"></div></a></li> | ||
60 | + </ul> | ||
50 | 61 | ||
51 | - <ul class="group-list"> | ||
52 | - <li><a href="/home/installment/account" class="nav-bit" data-id="7">账户管理:<span class="list-right iconfont"></span></a></li> | ||
53 | - </ul> | ||
54 | - </div> | ||
55 | - <div class="usable installment-cont"> | ||
56 | - <div class="usable-area detail-bg"> | ||
57 | - {{#replayStatus}}<div class="replay-status">{{.}}</div>{{/replayStatus}} | ||
58 | - <p class="detail-txt1">可用额度</p> | ||
59 | - <p class="detail-txt1">¥<span class="detail-txt2">{{currCreditLimit}}</span></p> | ||
60 | - <p class="detail-txt1">总额度:¥{{initCreditLimit}}</p> | ||
61 | - <a href="/home/installment/agreement" class="terms">服务条款</a> | ||
62 | - </div> | ||
63 | - {{# installmentOnly}} | ||
64 | - {{> installment/installment-only}} | ||
65 | - {{/ installmentOnly}} | 62 | + <ul class="group-list"> |
63 | + <li><a href="/home/installment/account" class="nav-bit" data-id="7">账户管理:<span class="list-right iconfont"></span></a></li> | ||
64 | + </ul> | ||
65 | + {{# content}} | ||
66 | + {{#if singleImage}} | ||
67 | + {{> installment/installment-banner}} | ||
68 | + {{/if}} | ||
69 | + {{/ content}} | ||
70 | + </div> | ||
71 | + <div class="usable installment-cont"> | ||
72 | + <div class="usable-area detail-bg"> | ||
73 | + {{#replayStatus}}<div class="replay-status">{{.}}</div>{{/replayStatus}} | ||
74 | + <p class="detail-txt1">可用额度</p> | ||
75 | + <p class="detail-txt1">¥<span class="detail-txt2">{{currCreditLimit}}</span></p> | ||
76 | + <p class="detail-txt1">总额度:¥{{initCreditLimit}}</p> | ||
77 | + <a href="/home/installment/agreement" class="terms">服务条款</a> | ||
78 | + </div> | ||
79 | + {{# installmentOnly}} | ||
80 | + {{> installment/installment-only}} | ||
81 | + {{/ installmentOnly}} | ||
82 | + </div> | ||
83 | + {{/if}} | ||
66 | </div> | 84 | </div> |
67 | - {{/if}} | 85 | + </div> |
68 | </div> | 86 | </div> |
@@ -17,6 +17,15 @@ | @@ -17,6 +17,15 @@ | ||
17 | {{# installmentOnly}} | 17 | {{# installmentOnly}} |
18 | {{> installment/installment-only}} | 18 | {{> installment/installment-only}} |
19 | {{/ installmentOnly}} | 19 | {{/ installmentOnly}} |
20 | + {{# advertisement}} | ||
21 | + <div class="advertisement-area"> | ||
22 | + <div class="mask-bg"></div> | ||
23 | + <a class="advertisement-box" href="{{url}}"> | ||
24 | + <i class="close-box"></i> | ||
25 | + <div style="background-image: url('{{image src 540 550}}');" class="advertisement-img"></div> | ||
26 | + </a> | ||
27 | + </div> | ||
28 | + {{/ advertisement}} | ||
20 | {{/ success}} | 29 | {{/ success}} |
21 | {{# error}} | 30 | {{# error}} |
22 | <div class="error"> | 31 | <div class="error"> |
@@ -11,13 +11,12 @@ | @@ -11,13 +11,12 @@ | ||
11 | <div class="date-box">{{../create_time}}</div> | 11 | <div class="date-box">{{../create_time}}</div> |
12 | </div> | 12 | </div> |
13 | {{/order_goods}} | 13 | {{/order_goods}} |
14 | + <div class="right-box"> | ||
15 | + <div class="amount">¥{{amount}}</div> | ||
16 | + <div class="status">{{install_status}}</div> | ||
17 | + </div> | ||
18 | + <div class="clearfix"></div> | ||
14 | </a> | 19 | </a> |
15 | - | ||
16 | - <div class="right-box"> | ||
17 | - <div class="amount">¥{{amount}}</div> | ||
18 | - <div class="status">{{install_status}}</div> | ||
19 | - </div> | ||
20 | - <div class="clearfix"></div> | ||
21 | </li> | 20 | </li> |
22 | {{/each}} | 21 | {{/each}} |
23 | {{/if}} | 22 | {{/if}} |
1 | <div class="repayment-list-page installment-order-page yoho-page" data-pos-id="{{posId}}"> | 1 | <div class="repayment-list-page installment-order-page yoho-page" data-pos-id="{{posId}}"> |
2 | - {{> resources/banner-top}} | ||
3 | <ul class="header-tab"> | 2 | <ul class="header-tab"> |
4 | <li class="active"> | 3 | <li class="active"> |
5 | <a href="/home/installment/order.html?type=1" data-type="1">全部</a> | 4 | <a href="/home/installment/order.html?type=1" data-type="1">全部</a> |
1 | <div class="installment-starting-service-page yoho-page"> | 1 | <div class="installment-starting-service-page yoho-page"> |
2 | - {{> resources/banner-top}} | 2 | + {{!-- {{> resources/banner-top}} --}} |
3 | <div class="exclamation"> | 3 | <div class="exclamation"> |
4 | 基本信息的有效性决定您能否激活有货分期,以及最终可获得的额度! | 4 | 基本信息的有效性决定您能否激活有货分期,以及最终可获得的额度! |
5 | </div> | 5 | </div> |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | <div class="field"> | 15 | <div class="field"> |
16 | <label for="identityCardNo">身份证号:</label> | 16 | <label for="identityCardNo">身份证号:</label> |
17 | 17 | ||
18 | - <input id="identityCardNo" name="identityCardNo" type="text" placeholder="请填写身份证号" maxlength="18"/> | 18 | + <input id="identityCardNo" name="identityCardNo" type="tel" placeholder="请填写身份证号" maxlength="18"/> |
19 | <div class="clearfix"></div> | 19 | <div class="clearfix"></div> |
20 | </div> | 20 | </div> |
21 | 21 | ||
@@ -55,10 +55,11 @@ | @@ -55,10 +55,11 @@ | ||
55 | <div class="agreements"> | 55 | <div class="agreements"> |
56 | <input id="accept-agreements" name="agreements" type="checkbox" class="installment-check-btn" checked/> | 56 | <input id="accept-agreements" name="agreements" type="checkbox" class="installment-check-btn" checked/> |
57 | <label for="accept-agreements"> | 57 | <label for="accept-agreements"> |
58 | - <div class="text-label">免费开通,详情请见 | ||
59 | - <a id="agreements" href="" data-href="/home/installment/agreement">《有货分期-信而富用户服务协议&借款服务协议》</a> | ||
60 | - </div> | 58 | + |
61 | </label> | 59 | </label> |
60 | + <div class="text-label">免费开通,详情请见 | ||
61 | + <a id="agreements" href="" data-href="/home/installment/agreement">《有货分期-信而富用户服务协议&借款服务协议》</a> | ||
62 | + </div> | ||
62 | <div class="clearfix"></div> | 63 | <div class="clearfix"></div> |
63 | </div> | 64 | </div> |
64 | 65 |
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | <ul id="order-nav" class="order-nav clearfix"> | 3 | <ul id="order-nav" class="order-nav clearfix"> |
4 | {{#each navs}} | 4 | {{#each navs}} |
5 | <li class="tap-hightlight {{#if active}}active{{/if}}" data-type="{{typeId}}"> | 5 | <li class="tap-hightlight {{#if active}}active{{/if}}" data-type="{{typeId}}"> |
6 | - <a href="{{url}}">{{name}}</a> | 6 | + <a class="nav-tap" data-url="{{url}}">{{name}}</a> |
7 | </li> | 7 | </li> |
8 | {{/each}} | 8 | {{/each}} |
9 | </ul> | 9 | </ul> |
@@ -37,6 +37,7 @@ | @@ -37,6 +37,7 @@ | ||
37 | <span >订单状态:{{statusStr}}</span> | 37 | <span >订单状态:{{statusStr}}</span> |
38 | <span>下单时间:<b class="createTime">{{createTime}}</b></span> | 38 | <span>下单时间:<b class="createTime">{{createTime}}</b></span> |
39 | </p> | 39 | </p> |
40 | + <a href="{{serviceUrl}}" target="_blank" class="iconfont icon-right"></a> | ||
40 | </div> | 41 | </div> |
41 | {{#if logisticsUrl}} | 42 | {{#if logisticsUrl}} |
42 | <a class="logistics sub" href="{{logisticsUrl}}"> | 43 | <a class="logistics sub" href="{{logisticsUrl}}"> |
1 | +<div class="banner-center banner-center-swiper"> | ||
2 | + {{#if singleOne}} | ||
3 | + {{#data}} | ||
4 | + <div class="banner-list"> | ||
5 | + <a href="{{url}}"> | ||
6 | + <img src="{{image src 640 210}}" alt=""> | ||
7 | + </a> | ||
8 | + </div> | ||
9 | + {{/data}} | ||
10 | + {{else}} | ||
11 | + <ul class="banner-list swiper-wrapper clearfix"> | ||
12 | + {{#data}} | ||
13 | + <li class="swiper-slide"> | ||
14 | + <a href="{{url}}"> | ||
15 | + <img src="{{image src 640 210}}" alt=""> | ||
16 | + </a> | ||
17 | + </li> | ||
18 | + {{/data}} | ||
19 | + </ul> | ||
20 | + {{/if}} | ||
21 | + <div class="swiper-pagination"> | ||
22 | + <div class="pagination-inner"> | ||
23 | + </div> | ||
24 | + </div> | ||
25 | +</div> |
1 | +<div class="notice-wrap clearfix"> | ||
2 | + <div class="notice" data-time="{{time}}"> | ||
3 | + <span class="notice-icon"></span> | ||
4 | + <div class="swiper-wrapper"> | ||
5 | + {{#list}} | ||
6 | + <a class="notice-item swiper-slide swiper-no-swiping item-{{@index}}" href="{{url}}"> | ||
7 | + {{title}} | ||
8 | + </a> | ||
9 | + {{/list}} | ||
10 | + </div> | ||
11 | + </div> | ||
12 | +</div> |
apps/passport/controllers/app-agreement.js
0 → 100644
1 | +/** | ||
2 | + * 服务条款 | ||
3 | + * @author: zxr<xiaoru.zhang@yoho.cn> | ||
4 | + * @date: 2016/10/25 | ||
5 | + */ | ||
6 | +'use strict'; | ||
7 | +const headerModel = require('../../../doraemon/models/header'); // 头部model | ||
8 | + | ||
9 | +const privacy = (req, res) => { | ||
10 | + | ||
11 | + res.render('agreement/privacy', { | ||
12 | + title: '隐私条款', | ||
13 | + width750: true | ||
14 | + }); | ||
15 | +}; | ||
16 | + | ||
17 | +const newpower = (req, res) => { | ||
18 | + let parameter = {}; | ||
19 | + | ||
20 | + res.render('agreement/newpower', { | ||
21 | + title: '关于新力传媒', | ||
22 | + width750: true | ||
23 | + }); | ||
24 | +}; | ||
25 | + | ||
26 | +const aboutYoho = (req, res) => { | ||
27 | + | ||
28 | + res.render('agreement/yohobuy', { | ||
29 | + title: '关于YOHO!BUY有货', | ||
30 | + width750: true | ||
31 | + }); | ||
32 | +}; | ||
33 | + | ||
34 | +const agreement = (req, res) => { | ||
35 | + let parameter = {}; | ||
36 | + let isApp = req.query.app_version || req.query.client_type || false; | ||
37 | + | ||
38 | + if (req.yoho.isApp) { | ||
39 | + parameter = { | ||
40 | + appVersion: '1' | ||
41 | + }; | ||
42 | + } else { | ||
43 | + parameter = { | ||
44 | + pageHeader: headerModel.setNav({ | ||
45 | + navTitle: 'YOHO!BUY有货app服务条款' | ||
46 | + }), | ||
47 | + }; | ||
48 | + } | ||
49 | + | ||
50 | + res.render('agreement/agreement', Object.assign({ | ||
51 | + module: 'passport', | ||
52 | + page: 'agreement', | ||
53 | + title: 'YOHO!BUY有货app服务条款', | ||
54 | + width750: true | ||
55 | + }, parameter)); | ||
56 | +}; | ||
57 | + | ||
58 | +module.exports = { | ||
59 | + privacy, | ||
60 | + newpower, | ||
61 | + aboutYoho, | ||
62 | + agreement | ||
63 | +}; |
@@ -10,6 +10,7 @@ const _ = require('lodash'); | @@ -10,6 +10,7 @@ const _ = require('lodash'); | ||
10 | const helpers = global.yoho.helpers; | 10 | const helpers = global.yoho.helpers; |
11 | 11 | ||
12 | const service = require('../models/back-service'); | 12 | const service = require('../models/back-service'); |
13 | +const captchaService = require('../models/captcha-service'); | ||
13 | 14 | ||
14 | const SIGN_IN = helpers.urlFormat('/passport/login'); | 15 | const SIGN_IN = helpers.urlFormat('/passport/login'); |
15 | 16 | ||
@@ -150,18 +151,93 @@ const indexMobilePage = (req, res, next) => { | @@ -150,18 +151,93 @@ const indexMobilePage = (req, res, next) => { | ||
150 | isPassportPage: true, | 151 | isPassportPage: true, |
151 | backMobile: true, | 152 | backMobile: true, |
152 | countrys: result.data, | 153 | countrys: result.data, |
153 | - areaCode: '+86' | 154 | + areaCode: '+86', |
155 | + verifySrc: helpers.urlFormat('/passport/back/generatecodeimg.png', {t: Date.now()}) | ||
154 | })); | 156 | })); |
155 | }) | 157 | }) |
156 | .catch(next); | 158 | .catch(next); |
157 | }; | 159 | }; |
158 | 160 | ||
159 | /** | 161 | /** |
162 | + * 生成验证码 | ||
163 | + * @param req | ||
164 | + * @param res | ||
165 | + */ | ||
166 | +const generateCodeImg = (req, res) => { | ||
167 | + let verifyCodeImg = captchaService.generateCaptcha(109, 50, 4); | ||
168 | + | ||
169 | + if (verifyCodeImg) { | ||
170 | + | ||
171 | + if (req.session.backupCaptch) { | ||
172 | + req.session.backupCaptch.code = verifyCodeImg.text; | ||
173 | + req.session.backupCaptch.verifyResult = false; | ||
174 | + } else { | ||
175 | + req.session.backupCaptch = { | ||
176 | + code: verifyCodeImg.text, | ||
177 | + verifyResult: false | ||
178 | + }; | ||
179 | + } | ||
180 | + | ||
181 | + res.set('Cache-Control', 'no-cache').send(verifyCodeImg.image); | ||
182 | + } | ||
183 | +}; | ||
184 | + | ||
185 | +/** | ||
160 | * 发送手机验证码 | 186 | * 发送手机验证码 |
161 | */ | 187 | */ |
162 | const sendCodeToMobileAPI = (req, res, next) => { | 188 | const sendCodeToMobileAPI = (req, res, next) => { |
189 | + let verifyCode = req.body.verifyCode || ''; | ||
163 | let phoneNum = req.body.phoneNum || ''; | 190 | let phoneNum = req.body.phoneNum || ''; |
164 | let areaCode = req.body.areaCode || '86'; | 191 | let areaCode = req.body.areaCode || '86'; |
192 | + | ||
193 | + /* 如果设置了冻结时间,验证 */ | ||
194 | + if (_.has(req.session, 'backupCaptch.timeout')) { | ||
195 | + let untilTime = (parseInt(req.session.backupCaptch.timeout, 10) - | ||
196 | + parseInt(Date.now(), 10)) / 1000 / 60; | ||
197 | + | ||
198 | + if (parseInt(Date.now(), 10) < parseInt(req.session.backupCaptch.timeout, 10)) { | ||
199 | + return res.json({ | ||
200 | + code: 401, | ||
201 | + message: '请' + (parseInt(untilTime, 10) + 1) + '分钟后尝试!' | ||
202 | + }); | ||
203 | + } | ||
204 | + } | ||
205 | + | ||
206 | + /* 如果设置了验证次数,验证是否合法,验证次数减 1;没有,设置验证次数 */ | ||
207 | + if (_.has(req.session, 'backupCaptch.useTime')) { | ||
208 | + if (parseInt(req.session.backupCaptch.useTime, 10) <= 0) { | ||
209 | + | ||
210 | + /* 如果超过验证次数,冻结 5 分钟,更新验证次数 */ | ||
211 | + req.session.backupCaptch.timeout = Date.now() + 5 * 60 * 1000; | ||
212 | + req.session.backupCaptch.useTime = 5; | ||
213 | + return res.json({ | ||
214 | + code: 401, | ||
215 | + message: '请5分钟后尝试!' | ||
216 | + }); | ||
217 | + } | ||
218 | + req.session.backupCaptch.useTime = req.session.backupCaptch.useTime - 1; | ||
219 | + } else { | ||
220 | + req.session.backupCaptch.useTime = 5; | ||
221 | + } | ||
222 | + | ||
223 | + if (verifyCode) { | ||
224 | + if (verifyCode.toString() === _.get(req, 'session.backupCaptch.code', '').toString()) { | ||
225 | + req.session.backupCaptch.verifyResult = true; | ||
226 | + } else { | ||
227 | + return res.json({ | ||
228 | + code: 400, | ||
229 | + message: '验证码输入错误' | ||
230 | + }); | ||
231 | + } | ||
232 | + } else if (!req.session.backupCaptch.verifyResult) { | ||
233 | + | ||
234 | + return res.json({ | ||
235 | + code: 409, | ||
236 | + message: '非法请求!', | ||
237 | + refer: helpers.urlFormat('/') | ||
238 | + }); | ||
239 | + } | ||
240 | + | ||
165 | let ERR = { | 241 | let ERR = { |
166 | code: 400, | 242 | code: 400, |
167 | message: '输入手机号码出错' | 243 | message: '输入手机号码出错' |
@@ -198,6 +274,11 @@ const verifyCodeByMobilePage = (req, res) => { | @@ -198,6 +274,11 @@ const verifyCodeByMobilePage = (req, res) => { | ||
198 | let phoneNum = req.query.phoneNum || ''; | 274 | let phoneNum = req.query.phoneNum || ''; |
199 | let areaCode = req.query.areaCode || '86'; | 275 | let areaCode = req.query.areaCode || '86'; |
200 | 276 | ||
277 | + /* 用户直接进入第二个页面的情况 */ | ||
278 | + if (!_.get(req, 'session.backupCaptch.verifyResult')) { | ||
279 | + return res.redirect(helpers.urlFormat('/')); | ||
280 | + } | ||
281 | + | ||
201 | res.render('back/mobile-code', Object.assign({ | 282 | res.render('back/mobile-code', Object.assign({ |
202 | module: 'passport', | 283 | module: 'passport', |
203 | page: 'back-code', | 284 | page: 'back-code', |
@@ -208,8 +289,8 @@ const verifyCodeByMobilePage = (req, res) => { | @@ -208,8 +289,8 @@ const verifyCodeByMobilePage = (req, res) => { | ||
208 | isPassportPage: true, | 289 | isPassportPage: true, |
209 | backCode: true, | 290 | backCode: true, |
210 | areaCode: areaCode, | 291 | areaCode: areaCode, |
211 | - phoneNum: phoneNum | ||
212 | - | 292 | + phoneNum: phoneNum, |
293 | + verifySrc: helpers.urlFormat('/passport/back/generatecodeimg.png', {t: Date.now()}) | ||
213 | })); | 294 | })); |
214 | }; | 295 | }; |
215 | 296 | ||
@@ -309,5 +390,6 @@ module.exports = { | @@ -309,5 +390,6 @@ module.exports = { | ||
309 | verifyCodeByMobilePage, | 390 | verifyCodeByMobilePage, |
310 | verifyCodeByMobileAPI, | 391 | verifyCodeByMobileAPI, |
311 | setNewPasswordByMobilePage, | 392 | setNewPasswordByMobilePage, |
312 | - setNewPasswordByMobileAPI | 393 | + setNewPasswordByMobileAPI, |
394 | + generateCodeImg | ||
313 | }; | 395 | }; |
@@ -13,8 +13,50 @@ const sign = global.yoho.sign; | @@ -13,8 +13,50 @@ const sign = global.yoho.sign; | ||
13 | const cookie = global.yoho.cookie; | 13 | const cookie = global.yoho.cookie; |
14 | const RegService = require('../models/reg-service'); | 14 | const RegService = require('../models/reg-service'); |
15 | const AuthHelper = require('../models/auth-helper'); | 15 | const AuthHelper = require('../models/auth-helper'); |
16 | +const captchaService = require('../models/captcha-service'); | ||
17 | + | ||
18 | +/* | ||
19 | + session 结构 | ||
20 | + phoneReg: { | ||
21 | + step //当前步骤 | ||
22 | + captcha // step1 的校验码 | ||
23 | + count: 5 // 默认可以重发5次, 当count: 0, 冻结30min,之后解冻 | ||
24 | + expire // 解冻时间 | ||
25 | + } | ||
26 | +*/ | ||
27 | + | ||
28 | +/** | ||
29 | + * 步骤校验 | ||
30 | + * step: 预期步骤 | ||
31 | + */ | ||
32 | +let guardStep = function(step) { | ||
33 | + return (req, res, next) => { | ||
34 | + let curStep = _.get(req.session, 'phoneReg.step'); | ||
35 | + | ||
36 | + if (curStep !== step) { | ||
37 | + if (req.xhr) { | ||
38 | + return res.json({ | ||
39 | + code: 400, | ||
40 | + refer: '/reg.html', | ||
41 | + message: '页面失效' | ||
42 | + }); | ||
43 | + } else { | ||
44 | + return res.redirect('/reg.html'); | ||
45 | + } | ||
46 | + } | ||
16 | 47 | ||
48 | + return next(); | ||
49 | + }; | ||
50 | +}; | ||
51 | + | ||
52 | +/** | ||
53 | + * Step1: 输入手机号码 + 验证码 | ||
54 | + */ | ||
17 | let index = (req, res) => { | 55 | let index = (req, res) => { |
56 | + if (req.user.uid) { | ||
57 | + return res.redirect(req.get('refer') || '/'); | ||
58 | + } | ||
59 | + | ||
18 | // 设置注册有效时间30分钟, 防机器刷 | 60 | // 设置注册有效时间30分钟, 防机器刷 |
19 | // req.session.REG_EXPIRE = Date.now() + 1800000; | 61 | // req.session.REG_EXPIRE = Date.now() + 1800000; |
20 | let refer = req.query.refer; | 62 | let refer = req.query.refer; |
@@ -23,17 +65,27 @@ let index = (req, res) => { | @@ -23,17 +65,27 @@ let index = (req, res) => { | ||
23 | domain: 'yohobuy.com' | 65 | domain: 'yohobuy.com' |
24 | }); | 66 | }); |
25 | 67 | ||
68 | + // session init | ||
69 | + _.set(req.session, 'phoneReg.step', 1); | ||
70 | + | ||
71 | + if (req.session.phoneReg.count == null) { // eslint-disable-line | ||
72 | + req.session.phoneReg.count = 5; | ||
73 | + } | ||
74 | + | ||
26 | res.render('reg/index', { | 75 | res.render('reg/index', { |
27 | module: 'passport', | 76 | module: 'passport', |
28 | page: 'reg', | 77 | page: 'reg', |
29 | title: '注册', | 78 | title: '注册', |
30 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line | 79 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line |
80 | + captchaUrl: helpers.urlFormat('/passport/reg/captcha.png', {t: Date.now()}), | ||
31 | headerText: '注册', // 头部信息 | 81 | headerText: '注册', // 头部信息 |
32 | isPassportPage: true, // 模板中模块标识 | 82 | isPassportPage: true, // 模板中模块标识 |
33 | areaCode: '+86', // 默认的区号 | 83 | areaCode: '+86', // 默认的区号 |
34 | countrys: RegService.getAreaData() // 地区信息列表 | 84 | countrys: RegService.getAreaData() // 地区信息列表 |
35 | }); | 85 | }); |
36 | }; | 86 | }; |
87 | + | ||
88 | + | ||
37 | let verifyMobile = (req, res, next) => { | 89 | let verifyMobile = (req, res, next) => { |
38 | let data = { | 90 | let data = { |
39 | code: 400, | 91 | code: 400, |
@@ -43,6 +95,28 @@ let verifyMobile = (req, res, next) => { | @@ -43,6 +95,28 @@ let verifyMobile = (req, res, next) => { | ||
43 | 95 | ||
44 | let mobile = +req.body.phoneNum; | 96 | let mobile = +req.body.phoneNum; |
45 | let area = +(req.body.areaCode || 86); | 97 | let area = +(req.body.areaCode || 86); |
98 | + let captcha = (req.body.captcha || '').trim(); | ||
99 | + let diffCaptcha = _.get(req.session, 'phoneReg.captcha'); | ||
100 | + | ||
101 | + // error case: 没有验证码 | ||
102 | + if (!diffCaptcha) { | ||
103 | + return res.json({ | ||
104 | + code: 400, | ||
105 | + message: '请求失败', | ||
106 | + refreshCaptcha: true | ||
107 | + }); | ||
108 | + } | ||
109 | + | ||
110 | + delete req.session.phoneReg.captcha; // captcha 一次性 | ||
111 | + | ||
112 | + // error case: 验证码不匹配 | ||
113 | + if (captcha !== diffCaptcha) { | ||
114 | + return res.json({ | ||
115 | + code: 400, | ||
116 | + message: '校验码不正确', | ||
117 | + refreshCaptcha: true | ||
118 | + }); | ||
119 | + } | ||
46 | 120 | ||
47 | // 判断参数是否合法 | 121 | // 判断参数是否合法 |
48 | if (!_.isNumber(mobile) || !_.isNumber(area)) { | 122 | if (!_.isNumber(mobile) || !_.isNumber(area)) { |
@@ -58,6 +132,7 @@ let verifyMobile = (req, res, next) => { | @@ -58,6 +132,7 @@ let verifyMobile = (req, res, next) => { | ||
58 | // return res.json(data); | 132 | // return res.json(data); |
59 | // } | 133 | // } |
60 | 134 | ||
135 | + | ||
61 | // 向手机发送注册验证码 | 136 | // 向手机发送注册验证码 |
62 | RegService.sendCodeToMobile(area, mobile).then((result) => { | 137 | RegService.sendCodeToMobile(area, mobile).then((result) => { |
63 | if (!result.code) { | 138 | if (!result.code) { |
@@ -68,6 +143,14 @@ let verifyMobile = (req, res, next) => { | @@ -68,6 +143,14 @@ let verifyMobile = (req, res, next) => { | ||
68 | if (result.code === 200) { | 143 | if (result.code === 200) { |
69 | let token = sign.makeToken(mobile); | 144 | let token = sign.makeToken(mobile); |
70 | 145 | ||
146 | + _.set(req.session, 'phoneReg.step', 2); // go step 2 | ||
147 | + --req.session.phoneReg.count; | ||
148 | + | ||
149 | + // count is 0, will freeze; | ||
150 | + if (!req.session.phoneReg.count) { | ||
151 | + _.set(req.session, 'phoneReg.expire', Date.now() + 5 * 60 * 1000); | ||
152 | + } | ||
153 | + | ||
71 | result.data = helpers.urlFormat('/passport/reg/code', { | 154 | result.data = helpers.urlFormat('/passport/reg/code', { |
72 | token: token, | 155 | token: token, |
73 | phoneNum: mobile, | 156 | phoneNum: mobile, |
@@ -78,6 +161,11 @@ let verifyMobile = (req, res, next) => { | @@ -78,6 +161,11 @@ let verifyMobile = (req, res, next) => { | ||
78 | return res.json(result); | 161 | return res.json(result); |
79 | }).catch(next); | 162 | }).catch(next); |
80 | }; | 163 | }; |
164 | + | ||
165 | + | ||
166 | +/** | ||
167 | + * Step2: 校验 手机验证码 | ||
168 | + */ | ||
81 | let codeAction = (req, res, next) => { | 169 | let codeAction = (req, res, next) => { |
82 | let token = req.query.token; | 170 | let token = req.query.token; |
83 | let mobile = +req.query.phoneNum; | 171 | let mobile = +req.query.phoneNum; |
@@ -94,7 +182,7 @@ let codeAction = (req, res, next) => { | @@ -94,7 +182,7 @@ let codeAction = (req, res, next) => { | ||
94 | res.render('reg/code', { | 182 | res.render('reg/code', { |
95 | page: 'code', | 183 | page: 'code', |
96 | title: '注册-验证码', | 184 | title: '注册-验证码', |
97 | - backUrl: '/?go=1', // eslint-disable-line | 185 | + backUrl: '/?go=1', // eslint-disable-line |
98 | headerText: '注册', // 头部信息 | 186 | headerText: '注册', // 头部信息 |
99 | isPassportPage: true, // 模板中模块标识 | 187 | isPassportPage: true, // 模板中模块标识 |
100 | areaCode: area, // 默认的区号 | 188 | areaCode: area, // 默认的区号 |
@@ -103,6 +191,36 @@ let codeAction = (req, res, next) => { | @@ -103,6 +191,36 @@ let codeAction = (req, res, next) => { | ||
103 | serviceUrl: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=' // 在线客服 | 191 | serviceUrl: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=' // 在线客服 |
104 | }); | 192 | }); |
105 | }; | 193 | }; |
194 | + | ||
195 | +let sendCodeBusyBoy = (req, res, next) => { | ||
196 | + let count = _.get(req.session, 'phoneReg.count'); | ||
197 | + let expire = _.get(req.session, 'phoneReg.expire'); | ||
198 | + | ||
199 | + if (count) { | ||
200 | + return next(); | ||
201 | + } else { | ||
202 | + | ||
203 | + /* | ||
204 | + 如果 count === 0 | ||
205 | + 1. 没过解冻期 | ||
206 | + 2. 过了解冻期, count reset to 5 | ||
207 | + */ | ||
208 | + let now = Date.now(); | ||
209 | + | ||
210 | + if (now > expire) { | ||
211 | + _.set(req.session, 'phoneReg.count', 5); | ||
212 | + return next(); | ||
213 | + | ||
214 | + } else { | ||
215 | + return res.json({ | ||
216 | + code: 400, | ||
217 | + message: '发送次数太多, 5分钟稍后再试' | ||
218 | + }); | ||
219 | + } | ||
220 | + | ||
221 | + } | ||
222 | +}; | ||
223 | + | ||
106 | let sendCode = (req, res, next) => { | 224 | let sendCode = (req, res, next) => { |
107 | let data = { | 225 | let data = { |
108 | code: 400, | 226 | code: 400, |
@@ -129,9 +247,22 @@ let sendCode = (req, res, next) => { | @@ -129,9 +247,22 @@ let sendCode = (req, res, next) => { | ||
129 | 247 | ||
130 | // 向手机发送注册验证码 | 248 | // 向手机发送注册验证码 |
131 | RegService.sendCodeToMobile(area, mobile).then((result) => { | 249 | RegService.sendCodeToMobile(area, mobile).then((result) => { |
132 | - return result.code ? res.json(result) : res.json(data); | 250 | + let code = _.get(result, 'code'); |
251 | + | ||
252 | + if (code) { | ||
253 | + --req.session.phoneReg.count; | ||
254 | + | ||
255 | + // count is 0, will freeze; | ||
256 | + if (!req.session.phoneReg.count) { | ||
257 | + _.set(req.session, 'phoneReg.expire', Date.now() + 5 * 60 * 1000); | ||
258 | + } | ||
259 | + return res.json(result); | ||
260 | + } else { | ||
261 | + return res.json(data); | ||
262 | + } | ||
133 | }).catch(next); | 263 | }).catch(next); |
134 | }; | 264 | }; |
265 | + | ||
135 | let verifyCode = (req, res, next) => { | 266 | let verifyCode = (req, res, next) => { |
136 | let data = { | 267 | let data = { |
137 | code: 400, | 268 | code: 400, |
@@ -143,7 +274,7 @@ let verifyCode = (req, res, next) => { | @@ -143,7 +274,7 @@ let verifyCode = (req, res, next) => { | ||
143 | let area = +(req.body.areaCode || 86); | 274 | let area = +(req.body.areaCode || 86); |
144 | let code = +req.body.code; | 275 | let code = +req.body.code; |
145 | 276 | ||
146 | - /* 判断参数是否合法 */ | 277 | + /* 判断参数是否合法 */ |
147 | if (!_.isNumber(mobile) || !_.isNumber(area) || !_.isNumber(code)) { | 278 | if (!_.isNumber(mobile) || !_.isNumber(area) || !_.isNumber(code)) { |
148 | data.message = '手机号错误'; | 279 | data.message = '手机号错误'; |
149 | return res.json(data); | 280 | return res.json(data); |
@@ -163,46 +294,58 @@ let verifyCode = (req, res, next) => { | @@ -163,46 +294,58 @@ let verifyCode = (req, res, next) => { | ||
163 | return res.json(data); | 294 | return res.json(data); |
164 | } | 295 | } |
165 | 296 | ||
166 | - // 返回跳转到设置密码的链接 | ||
167 | - if (result.code === 200) { | ||
168 | - let token = sign.makeToken(mobile); | ||
169 | - | ||
170 | - result.data = helpers.urlFormat('/passport/reg/password', { | ||
171 | - token: token, | ||
172 | - phoneNum: mobile, | ||
173 | - areaCode: area | ||
174 | - }); | ||
175 | - } else if (result.code === 404) { | ||
176 | - result.message = '验证码错误'; // 统一验证提示 | 297 | + let resultCode = _.get(result, 'code'); |
298 | + let token = sign.makeToken(mobile); | ||
299 | + | ||
300 | + switch (resultCode) { | ||
301 | + case 200: | ||
302 | + _.set(req.session, 'phoneReg.step', 3); // go step 3 | ||
303 | + result.data = helpers.urlFormat('/passport/reg/password', { | ||
304 | + token: token, | ||
305 | + phoneNum: mobile, | ||
306 | + areaCode: area, | ||
307 | + smsCode: code | ||
308 | + }); | ||
309 | + break; | ||
310 | + case 404: | ||
311 | + default: | ||
312 | + result = data; | ||
177 | } | 313 | } |
178 | 314 | ||
179 | return res.json(result); | 315 | return res.json(result); |
180 | }).catch(next); | 316 | }).catch(next); |
181 | }; | 317 | }; |
318 | + | ||
319 | +/** | ||
320 | + * Step3: set Password | ||
321 | + */ | ||
182 | let passwordAction = (req, res, next) => { | 322 | let passwordAction = (req, res, next) => { |
183 | let token = req.query.token; | 323 | let token = req.query.token; |
184 | let mobile = +req.query.phoneNum; | 324 | let mobile = +req.query.phoneNum; |
185 | let area = +(req.query.areaCode || 86); | 325 | let area = +(req.query.areaCode || 86); |
326 | + let smsCode = +req.query.smsCode; | ||
186 | 327 | ||
187 | // 判断是否允许访问, 不允许则跳转到错误页面 | 328 | // 判断是否允许访问, 不允许则跳转到错误页面 |
188 | - if (!_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !sign.verifyToken(mobile, token)) { | 329 | + if (!smsCode || !_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !sign.verifyToken(mobile, token)) { |
189 | return next({ | 330 | return next({ |
190 | code: 403, | 331 | code: 403, |
191 | - message: 'error token or mobile' | 332 | + message: 'error token, mobile or verifyCode' |
192 | }); | 333 | }); |
193 | } | 334 | } |
194 | 335 | ||
195 | res.render('reg/password', { | 336 | res.render('reg/password', { |
196 | page: 'password', | 337 | page: 'password', |
197 | title: '注册-设置密码', | 338 | title: '注册-设置密码', |
198 | - backUrl: '/?go=1', // eslint-disable-line | 339 | + backUrl: '/?go=1', // eslint-disable-line |
199 | headerText: '注册', // 头部信息 | 340 | headerText: '注册', // 头部信息 |
200 | isPassportPage: true, // 模板中模块标识 | 341 | isPassportPage: true, // 模板中模块标识 |
201 | areaCode: area, // 默认的区号 | 342 | areaCode: area, // 默认的区号 |
202 | phoneNum: mobile, // 手机号 | 343 | phoneNum: mobile, // 手机号 |
203 | - token: token // 访问令牌 | 344 | + token: token, // 访问令牌 |
345 | + smsCode: smsCode // 手机验证码 | ||
204 | }); | 346 | }); |
205 | }; | 347 | }; |
348 | + | ||
206 | let setPassword = (req, res, next) => { | 349 | let setPassword = (req, res, next) => { |
207 | let data = { | 350 | let data = { |
208 | code: 400, | 351 | code: 400, |
@@ -214,9 +357,10 @@ let setPassword = (req, res, next) => { | @@ -214,9 +357,10 @@ let setPassword = (req, res, next) => { | ||
214 | let area = +(req.body.areaCode || 86); | 357 | let area = +(req.body.areaCode || 86); |
215 | let password = req.body.password; | 358 | let password = req.body.password; |
216 | let token = req.body.token; | 359 | let token = req.body.token; |
360 | + let smsCode = +req.body.smsCode; | ||
217 | 361 | ||
218 | // 判断参数是否合法 | 362 | // 判断参数是否合法 |
219 | - if (!_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) { | 363 | + if (!smsCode || !_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) { |
220 | data.message = '请求参数不合法'; | 364 | data.message = '请求参数不合法'; |
221 | return res.json(data); | 365 | return res.json(data); |
222 | } | 366 | } |
@@ -228,7 +372,7 @@ let setPassword = (req, res, next) => { | @@ -228,7 +372,7 @@ let setPassword = (req, res, next) => { | ||
228 | } | 372 | } |
229 | 373 | ||
230 | // 判断密码是否符合规则 | 374 | // 判断密码是否符合规则 |
231 | - if (!helpers.verifyPassword(password)) { | 375 | + if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/.test(password)) { |
232 | return res.json(data); | 376 | return res.json(data); |
233 | } | 377 | } |
234 | 378 | ||
@@ -236,7 +380,7 @@ let setPassword = (req, res, next) => { | @@ -236,7 +380,7 @@ let setPassword = (req, res, next) => { | ||
236 | let shoppingKey = cookie.getShoppingKey(req); | 380 | let shoppingKey = cookie.getShoppingKey(req); |
237 | 381 | ||
238 | // 验证注册的标识码是否有效 | 382 | // 验证注册的标识码是否有效 |
239 | - RegService.regMobileAes(area, mobile, password, shoppingKey).then((result) => { | 383 | + RegService.regMobileAes(area, mobile, password, shoppingKey, smsCode).then((result) => { |
240 | if (!result.code || result.code !== 200) { | 384 | if (!result.code || result.code !== 200) { |
241 | return Promise.reject(result); | 385 | return Promise.reject(result); |
242 | } | 386 | } |
@@ -258,6 +402,8 @@ let setPassword = (req, res, next) => { | @@ -258,6 +402,8 @@ let setPassword = (req, res, next) => { | ||
258 | refer = '/home'; | 402 | refer = '/home'; |
259 | } | 403 | } |
260 | 404 | ||
405 | + delete req.session.phoneNum; | ||
406 | + | ||
261 | return res.json({ | 407 | return res.json({ |
262 | code: 200, | 408 | code: 200, |
263 | message: '注册成功', | 409 | message: '注册成功', |
@@ -269,12 +415,29 @@ let setPassword = (req, res, next) => { | @@ -269,12 +415,29 @@ let setPassword = (req, res, next) => { | ||
269 | }).catch(next); | 415 | }).catch(next); |
270 | }; | 416 | }; |
271 | 417 | ||
418 | +/** | ||
419 | + * 生成 校验码 | ||
420 | + */ | ||
421 | +const genCaptcha = (req, res) => { | ||
422 | + let captcha = captchaService.generateCaptcha(90, 52, 4); | ||
423 | + | ||
424 | + _.set(req.session, 'phoneReg.captcha', captcha.text); | ||
425 | + | ||
426 | + res.type('png') | ||
427 | + .set('Cache-Control', 'no-cache') | ||
428 | + .status(200) | ||
429 | + .send(captcha.image); | ||
430 | +}; | ||
431 | + | ||
272 | module.exports = { | 432 | module.exports = { |
433 | + guardStep, | ||
434 | + sendCodeBusyBoy, | ||
273 | index, | 435 | index, |
274 | verifyMobile, | 436 | verifyMobile, |
275 | code: codeAction, | 437 | code: codeAction, |
276 | sendCode, | 438 | sendCode, |
277 | verifyCode, | 439 | verifyCode, |
278 | password: passwordAction, | 440 | password: passwordAction, |
279 | - setPassword | 441 | + setPassword, |
442 | + genCaptcha | ||
280 | }; | 443 | }; |
1 | /* eslint no-unused-vars: ["error", { "args": "none" }] */ | 1 | /* eslint no-unused-vars: ["error", { "args": "none" }] */ |
2 | 'use strict'; | 2 | 'use strict'; |
3 | +const _ = require('lodash'); | ||
3 | const helpers = global.yoho.helpers; | 4 | const helpers = global.yoho.helpers; |
4 | const cookie = global.yoho.cookie; | 5 | const cookie = global.yoho.cookie; |
5 | const RegService = require('../models/reg-service'); | 6 | const RegService = require('../models/reg-service'); |
6 | const PhoneService = require('../models/phone-service'); | 7 | const PhoneService = require('../models/phone-service'); |
7 | const AuthHelper = require('../models/auth-helper'); | 8 | const AuthHelper = require('../models/auth-helper'); |
9 | +const captchaService = require('../models/captcha-service'); | ||
8 | 10 | ||
9 | // constrant | 11 | // constrant |
10 | const CODE_REQUIRED = '请输入校验码'; | 12 | const CODE_REQUIRED = '请输入校验码'; |
@@ -23,7 +25,7 @@ exports.beforeIn = (req, res, next) => { | @@ -23,7 +25,7 @@ exports.beforeIn = (req, res, next) => { | ||
23 | }); | 25 | }); |
24 | 26 | ||
25 | if (!req.xhr && req.user.uid) { | 27 | if (!req.xhr && req.user.uid) { |
26 | - return res.redirect(req.cookies.refer); | 28 | + return res.redirect(req.cookies.refer || '/'); |
27 | } | 29 | } |
28 | 30 | ||
29 | next(); | 31 | next(); |
@@ -31,6 +33,12 @@ exports.beforeIn = (req, res, next) => { | @@ -31,6 +33,12 @@ exports.beforeIn = (req, res, next) => { | ||
31 | 33 | ||
32 | // 短信登录 第一步: 展现页面 | 34 | // 短信登录 第一步: 展现页面 |
33 | const _step1 = (req, res, next) => { | 35 | const _step1 = (req, res, next) => { |
36 | + _.set(req.session, 'smsLogin.step', 1); | ||
37 | + | ||
38 | + if (req.session.smsLogin.count == null) { // eslint-disable-line | ||
39 | + req.session.smsLogin.count = 5; | ||
40 | + } | ||
41 | + | ||
34 | let template = 'sms/login'; | 42 | let template = 'sms/login'; |
35 | let viewData = { | 43 | let viewData = { |
36 | module: 'passport', | 44 | module: 'passport', |
@@ -38,6 +46,7 @@ const _step1 = (req, res, next) => { | @@ -38,6 +46,7 @@ const _step1 = (req, res, next) => { | ||
38 | title: '手机短信登录', | 46 | title: '手机短信登录', |
39 | isPassportPage: true, | 47 | isPassportPage: true, |
40 | headerText: '手机号码快捷登录', | 48 | headerText: '手机号码快捷登录', |
49 | + captchaUrl: helpers.urlFormat('/passport/sms_login/captcha.png', {t: Date.now()}), | ||
41 | areaCode: '+86', // 默认的区号 | 50 | areaCode: '+86', // 默认的区号 |
42 | countrys: RegService.getAreaData() // 地区信息列表 | 51 | countrys: RegService.getAreaData() // 地区信息列表 |
43 | }; | 52 | }; |
@@ -58,7 +67,7 @@ const _step2 = (req, res, next) => { | @@ -58,7 +67,7 @@ const _step2 = (req, res, next) => { | ||
58 | title: '手机短信登录', | 67 | title: '手机短信登录', |
59 | isPassportPage: true, | 68 | isPassportPage: true, |
60 | headerText: '手机号码快捷登录', | 69 | headerText: '手机号码快捷登录', |
61 | - canResend: interval < Date.now(), | 70 | + countdown: Math.ceil((interval - Date.now()) / 1000), |
62 | mobile, | 71 | mobile, |
63 | area | 72 | area |
64 | }; | 73 | }; |
@@ -83,7 +92,7 @@ const _step3 = (req, res, next) => { | @@ -83,7 +92,7 @@ const _step3 = (req, res, next) => { | ||
83 | // 短信 登录 | 92 | // 短信 登录 |
84 | exports.loginPage = (req, res, next) => { | 93 | exports.loginPage = (req, res, next) => { |
85 | let step = Number(req.query.step) || 1; | 94 | let step = Number(req.query.step) || 1; |
86 | - let smsLoginStep = req.session.smsLoginStep || 1; | 95 | + let smsLoginStep = _.get(req.session, 'smsLogin.step', 1); |
87 | 96 | ||
88 | if (step === 2 && smsLoginStep !== 2) { | 97 | if (step === 2 && smsLoginStep !== 2) { |
89 | return res.redirect(req.path); | 98 | return res.redirect(req.path); |
@@ -109,23 +118,63 @@ exports.loginPage = (req, res, next) => { | @@ -109,23 +118,63 @@ exports.loginPage = (req, res, next) => { | ||
109 | exports.tokenBefore = (req, res, next) => { | 118 | exports.tokenBefore = (req, res, next) => { |
110 | let area = req.query.area = (req.query.area || '').trim(); | 119 | let area = req.query.area = (req.query.area || '').trim(); |
111 | let mobile = req.query.mobile = (req.query.mobile || '').trim(); | 120 | let mobile = req.query.mobile = (req.query.mobile || '').trim(); |
121 | + let step = _.get(req.session, 'smsLogin.step'); | ||
122 | + let count = _.get(req.session, 'smsLogin.count'); | ||
123 | + let interval = _.get(req.session, 'smsLogin.interval'); | ||
124 | + let captcha1 = _.get(req.session, 'smsLogin.captcha'); | ||
125 | + let captcha2 = (req.query.captcha || '').trim(); | ||
126 | + | ||
112 | 127 | ||
113 | if (!req.xhr) { | 128 | if (!req.xhr) { |
114 | return next(404); | 129 | return next(404); |
115 | } | 130 | } |
116 | 131 | ||
117 | - if (req.session.smsLogin && req.session.smsLogin.interval > Date.now()) { | 132 | + if ([area, mobile].some(val => val === '')) { |
118 | return res.json({ | 133 | return res.json({ |
119 | - code: 429, | ||
120 | - message: TOO_MANY | 134 | + code: 401, |
135 | + message: '手机号 必填' | ||
121 | }); | 136 | }); |
122 | } | 137 | } |
123 | 138 | ||
139 | + delete req.session.smsLogin.captcha; // 图形验证码 一次性 | ||
124 | 140 | ||
125 | - if ([area, mobile].some(val => val === '')) { | 141 | + // step1 要 校验图形验证码 |
142 | + if (step === 1) { | ||
143 | + if (!captcha2) { | ||
144 | + return res.json({ | ||
145 | + code: 400, | ||
146 | + message: '请填写验证码' | ||
147 | + }); | ||
148 | + } | ||
149 | + | ||
150 | + if (captcha1 !== captcha2) { | ||
151 | + return res.json({ | ||
152 | + code: 400, | ||
153 | + message: VERIFY_ERROR | ||
154 | + }); | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + let now = Date.now(); | ||
159 | + | ||
160 | + // 重发次数用完了, 回冻结5min | ||
161 | + // 1. 过了冻结期, count 重设为 5次 | ||
162 | + // 2. 没过冻结期, end | ||
163 | + // 没有用完, 判断是否请求太频繁 | ||
164 | + if (!count) { | ||
165 | + if (interval > now) { | ||
166 | + return res.json({ | ||
167 | + code: 400, | ||
168 | + message: TOO_MANY, | ||
169 | + during: Math.ceil((interval - now) / 1000) | ||
170 | + }); | ||
171 | + } else { | ||
172 | + _.set(req.session, 'smsLogin.count', 5); | ||
173 | + } | ||
174 | + } else if (interval > now) { | ||
126 | return res.json({ | 175 | return res.json({ |
127 | - code: 401, | ||
128 | - message: '请求参数,无法处理' | 176 | + code: 429, |
177 | + message: TOO_MANY | ||
129 | }); | 178 | }); |
130 | } | 179 | } |
131 | 180 | ||
@@ -139,12 +188,18 @@ exports.token = (req, res, next) => { | @@ -139,12 +188,18 @@ exports.token = (req, res, next) => { | ||
139 | 188 | ||
140 | PhoneService.sendSMS(mobile, area, 1).then(result => { | 189 | PhoneService.sendSMS(mobile, area, 1).then(result => { |
141 | if (result.code === 200) { | 190 | if (result.code === 200) { |
142 | - req.session.smsLogin = { | ||
143 | - interval: Date.now() + 60 * 1000, // 重发验证码 间隔: 60s | ||
144 | - area, | ||
145 | - mobile | ||
146 | - }; | ||
147 | - req.session.smsLoginStep = 2; // 进入短信登录 step2 | 191 | + |
192 | + _.set(req.session, 'smsLogin.step', 2); | ||
193 | + _.set(req.session, 'smsLogin.area', area); | ||
194 | + _.set(req.session, 'smsLogin.mobile', mobile); | ||
195 | + | ||
196 | + --req.session.smsLogin.count; | ||
197 | + | ||
198 | + if (!req.session.smsLogin.count) { | ||
199 | + _.set(req.session, 'smsLogin.interval', Date.now() + 5 * 60 * 1000); | ||
200 | + } else { | ||
201 | + _.set(req.session, 'smsLogin.interval', Date.now() + 60 * 1000); | ||
202 | + } | ||
148 | 203 | ||
149 | result.redirect = '/passport/sms_login?step=2'; | 204 | result.redirect = '/passport/sms_login?step=2'; |
150 | res.json(result); | 205 | res.json(result); |
@@ -157,8 +212,9 @@ exports.token = (req, res, next) => { | @@ -157,8 +212,9 @@ exports.token = (req, res, next) => { | ||
157 | 212 | ||
158 | exports.checkBefore = (req, res, next) => { | 213 | exports.checkBefore = (req, res, next) => { |
159 | let code = req.query.code = (req.query.code || '').trim(); | 214 | let code = req.query.code = (req.query.code || '').trim(); |
215 | + let step = _.get(req.session, 'smsLogin.step'); | ||
160 | 216 | ||
161 | - if (!req.xhr && req.session.smsLoginStep !== 2) { | 217 | + if (!req.xhr && step !== 2) { |
162 | return next(404); | 218 | return next(404); |
163 | } | 219 | } |
164 | 220 | ||
@@ -214,11 +270,13 @@ exports.check = (req, res, next) => { | @@ -214,11 +270,13 @@ exports.check = (req, res, next) => { | ||
214 | // 手机号码 没注册 | 270 | // 手机号码 没注册 |
215 | if (r1.data.is_register !== 'Y') { | 271 | if (r1.data.is_register !== 'Y') { |
216 | redirect = '/passport/sms_login?step=3'; | 272 | redirect = '/passport/sms_login?step=3'; |
217 | - req.session.smsLoginStep = 3; | 273 | + _.set(req.session, 'smsLogin.step', 3); |
218 | 274 | ||
219 | res.json({ | 275 | res.json({ |
220 | code: 200, | 276 | code: 200, |
221 | - redirect | 277 | + redirect, |
278 | + newer: true, | ||
279 | + registerCode: r1.data.code | ||
222 | }); | 280 | }); |
223 | 281 | ||
224 | return; | 282 | return; |
@@ -246,7 +304,6 @@ exports.check = (req, res, next) => { | @@ -246,7 +304,6 @@ exports.check = (req, res, next) => { | ||
246 | }); | 304 | }); |
247 | 305 | ||
248 | delete req.session.smsLogin; | 306 | delete req.session.smsLogin; |
249 | - delete req.session.smsLoginStep; | ||
250 | }) | 307 | }) |
251 | .catch(error => { | 308 | .catch(error => { |
252 | res.json(error); | 309 | res.json(error); |
@@ -258,7 +315,9 @@ exports.check = (req, res, next) => { | @@ -258,7 +315,9 @@ exports.check = (req, res, next) => { | ||
258 | 315 | ||
259 | // AJAX 短信登录 设置密码 in step3 | 316 | // AJAX 短信登录 设置密码 in step3 |
260 | exports.password = (req, res, next) => { | 317 | exports.password = (req, res, next) => { |
261 | - if (req.session.smsLoginStep !== 3) { | 318 | + let step = _.get(req.session, 'smsLogin.step'); |
319 | + | ||
320 | + if (step !== 3) { | ||
262 | return next(); | 321 | return next(); |
263 | } | 322 | } |
264 | 323 | ||
@@ -268,10 +327,10 @@ exports.password = (req, res, next) => { | @@ -268,10 +327,10 @@ exports.password = (req, res, next) => { | ||
268 | message: BAD_PASSWORD | 327 | message: BAD_PASSWORD |
269 | }; | 328 | }; |
270 | 329 | ||
271 | - let smsLogin = req.session.smsLogin || {}; | ||
272 | - let mobile = smsLogin.mobile; | ||
273 | - let area = smsLogin.area; | 330 | + let mobile = _.get(req.session, 'smsLogin.mobile'); |
331 | + let area = _.get(req.session, 'smsLogin.area'); | ||
274 | let password = (req.body.password || '').trim(); | 332 | let password = (req.body.password || '').trim(); |
333 | + let registerCode = +req.body.registerCode || 0; | ||
275 | 334 | ||
276 | if (!password) { | 335 | if (!password) { |
277 | data.message = PASSWORD_REQUIRED; | 336 | data.message = PASSWORD_REQUIRED; |
@@ -283,7 +342,7 @@ exports.password = (req, res, next) => { | @@ -283,7 +342,7 @@ exports.password = (req, res, next) => { | ||
283 | return res.json(data); | 342 | return res.json(data); |
284 | } | 343 | } |
285 | 344 | ||
286 | - if (!helpers.verifyPassword(password)) { | 345 | + if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/.test(password)) { |
287 | return res.json(data); | 346 | return res.json(data); |
288 | } | 347 | } |
289 | 348 | ||
@@ -291,7 +350,7 @@ exports.password = (req, res, next) => { | @@ -291,7 +350,7 @@ exports.password = (req, res, next) => { | ||
291 | let shoppingKey = cookie.getShoppingKey(req); | 350 | let shoppingKey = cookie.getShoppingKey(req); |
292 | 351 | ||
293 | 352 | ||
294 | - RegService.regMobileAes(area, mobile, password, shoppingKey).then(result => { | 353 | + RegService.regMobileAes(area, mobile, password, shoppingKey, registerCode).then(result => { |
295 | if (!result.code || result.code !== 200) { | 354 | if (!result.code || result.code !== 200) { |
296 | return Promise.reject(result); | 355 | return Promise.reject(result); |
297 | } | 356 | } |
@@ -304,11 +363,23 @@ exports.password = (req, res, next) => { | @@ -304,11 +363,23 @@ exports.password = (req, res, next) => { | ||
304 | res.json({ | 363 | res.json({ |
305 | code: 200, | 364 | code: 200, |
306 | message: LOGIN_SUCCSS, | 365 | message: LOGIN_SUCCSS, |
307 | - redirect: req.cookies.refer | 366 | + redirect: req.cookies.refer || '/' |
308 | }); | 367 | }); |
309 | delete req.session.smsLogin; | 368 | delete req.session.smsLogin; |
310 | - delete req.session.smsLoginStep; | ||
311 | }).catch(next); | 369 | }).catch(next); |
370 | +}; | ||
371 | + | ||
372 | + | ||
373 | +/** | ||
374 | + * 生成 校验码 | ||
375 | + */ | ||
376 | +exports.genCaptcha = (req, res) => { | ||
377 | + let captcha = captchaService.generateCaptcha(90, 52, 4); | ||
312 | 378 | ||
379 | + _.set(req.session, 'smsLogin.captcha', captcha.text); | ||
313 | 380 | ||
381 | + res.type('png') | ||
382 | + .set('Cache-Control', 'no-cache') | ||
383 | + .status(200) | ||
384 | + .send(captcha.image); | ||
314 | }; | 385 | }; |
apps/passport/models/captcha-service.js
0 → 100644
1 | +/** | ||
2 | + * Created by TaoHuang on 2016/7/1. | ||
3 | + */ | ||
4 | + | ||
5 | +'use strict'; | ||
6 | + | ||
7 | +const _ = require('lodash'); | ||
8 | +const Captchapng = require('captchapng'); | ||
9 | + | ||
10 | +exports.generateCaptcha = (width, height, length) => { | ||
11 | + let min = Math.pow(10, (length - 1 || 1)); | ||
12 | + let max = Math.pow(10, (length - 1 || 1)) * 9; | ||
13 | + let token = '' + _.random(min, max); | ||
14 | + | ||
15 | + let png = new Captchapng(width, height, token);// | ||
16 | + | ||
17 | + png.color(0, 0, 0, 0); // First color: background (red, green, blue, alpha) | ||
18 | + png.color(80, 80, 80, 255); // Second color: paint (red, green, blue, alpha) | ||
19 | + | ||
20 | + return { | ||
21 | + image: new Buffer(png.getBase64(), 'base64'), | ||
22 | + text: token | ||
23 | + }; | ||
24 | +}; |
@@ -96,12 +96,13 @@ const RegService = { | @@ -96,12 +96,13 @@ const RegService = { | ||
96 | 96 | ||
97 | return api.post('', params); | 97 | return api.post('', params); |
98 | }, | 98 | }, |
99 | - regMobileAes(area, mobile, password, shoppingKey) { | 99 | + regMobileAes(area, mobile, password, shoppingKey, smsCode) { |
100 | let params = { | 100 | let params = { |
101 | method: 'app.passport.registerAES', | 101 | method: 'app.passport.registerAES', |
102 | area: area, | 102 | area: area, |
103 | profile: mobile, | 103 | profile: mobile, |
104 | - password: aes.aesPwd(password) | 104 | + password: aes.aesPwd(password), |
105 | + verifyCode: smsCode | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | if (shoppingKey) { | 108 | if (shoppingKey) { |
@@ -12,15 +12,18 @@ const login = require(cRoot + '/login'); | @@ -12,15 +12,18 @@ const login = require(cRoot + '/login'); | ||
12 | const back = require(cRoot + '/back'); | 12 | const back = require(cRoot + '/back'); |
13 | const bind = require(cRoot + '/bind'); | 13 | const bind = require(cRoot + '/bind'); |
14 | const reg = require(cRoot + '/reg'); | 14 | const reg = require(cRoot + '/reg'); |
15 | + | ||
16 | +const disableBFCahce = require('../../doraemon/middleware/disable-BFCache'); | ||
17 | + | ||
15 | const smsLogin = require(cRoot + '/sms'); | 18 | const smsLogin = require(cRoot + '/sms'); |
16 | const update = require(cRoot + '/update'); | 19 | const update = require(cRoot + '/update'); |
17 | - | 20 | +const agreement = require(cRoot + '/app-agreement'); |
18 | 21 | ||
19 | const router = express.Router(); // eslint-disable-line | 22 | const router = express.Router(); // eslint-disable-line |
20 | 23 | ||
21 | // 兼容老的路由 | 24 | // 兼容老的路由 |
22 | router.get('/signin.html', login.common.beforeLogin, login.local.loginPage); | 25 | router.get('/signin.html', login.common.beforeLogin, login.local.loginPage); |
23 | -router.get('/reg.html', reg.index); | 26 | +router.get('/reg.html', disableBFCahce, reg.index); |
24 | router.get('/login.html', login.common.beforeLogin, login.local.international); | 27 | router.get('/login.html', login.common.beforeLogin, login.local.international); |
25 | router.get('/phoneback.html', back.indexMobilePage); | 28 | router.get('/phoneback.html', back.indexMobilePage); |
26 | router.get('/emailback.html', back.indexEmailPage); | 29 | router.get('/emailback.html', back.indexEmailPage); |
@@ -36,15 +39,16 @@ router.get('/passport/international', login.common.beforeLogin, login.local.inte | @@ -36,15 +39,16 @@ router.get('/passport/international', login.common.beforeLogin, login.local.inte | ||
36 | router.post('/passport/login/auth', login.local.login); | 39 | router.post('/passport/login/auth', login.local.login); |
37 | 40 | ||
38 | // SMS 短信 | 41 | // SMS 短信 |
39 | -// router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn); | ||
40 | -// router.get('/passport/sms_login', smsLogin.loginPage); | ||
41 | -// router.get('/passport/sms_login/token.json', | ||
42 | -// smsLogin.tokenBefore, | ||
43 | -// smsLogin.token); // only ajax; | ||
44 | -// router.get('/passport/sms_login/check.json', | ||
45 | -// smsLogin.checkBefore, | ||
46 | -// smsLogin.check); // only ajax | ||
47 | -// router.post('/passport/sms_login/password.json', smsLogin.password); | 42 | +router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn); |
43 | +router.get('/passport/sms_login', smsLogin.loginPage); | ||
44 | +router.get('/passport/sms_login/token.json', | ||
45 | + smsLogin.tokenBefore, | ||
46 | + smsLogin.token); // only ajax; | ||
47 | +router.get('/passport/sms_login/check.json', | ||
48 | + smsLogin.checkBefore, | ||
49 | + smsLogin.check); // only ajax | ||
50 | +router.post('/passport/sms_login/password.json', smsLogin.password); | ||
51 | +router.get('/passport/sms_login/captcha.png', smsLogin.genCaptcha); | ||
48 | 52 | ||
49 | // 微信登录 | 53 | // 微信登录 |
50 | router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login); | 54 | router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login); |
@@ -83,13 +87,15 @@ router.post('/passport/bind/changeMobile', bind.changeMobile); | @@ -83,13 +87,15 @@ router.post('/passport/bind/changeMobile', bind.changeMobile); | ||
83 | /** | 87 | /** |
84 | * 注册 | 88 | * 注册 |
85 | */ | 89 | */ |
90 | +router.use('/passport/reg/*', disableBFCahce); | ||
86 | router.get('/passport/reg/index', reg.index); | 91 | router.get('/passport/reg/index', reg.index); |
87 | -router.post('/passport/reg/verifymobile', reg.verifyMobile); | ||
88 | -router.get('/passport/reg/code', reg.code); | ||
89 | -router.post('/passport/reg/sendcode', reg.sendCode); | ||
90 | -router.post('/passport/reg/verifycode', reg.verifyCode); | ||
91 | -router.get('/passport/reg/password', reg.password); | ||
92 | -router.post('/passport/reg/setpassword', reg.setPassword); | 92 | +router.get('/passport/reg/captcha.png', reg.genCaptcha); |
93 | +router.post('/passport/reg/verifymobile', reg.sendCodeBusyBoy, reg.verifyMobile); | ||
94 | +router.get('/passport/reg/code', reg.guardStep(2), reg.code); | ||
95 | +router.post('/passport/reg/sendcode', reg.guardStep(2), reg.sendCodeBusyBoy, reg.sendCode); | ||
96 | +router.post('/passport/reg/verifycode', reg.guardStep(2), reg.verifyCode); | ||
97 | +router.get('/passport/reg/password', reg.guardStep(3), reg.password); | ||
98 | +router.post('/passport/reg/setpassword', reg.guardStep(3), reg.setPassword); | ||
93 | 99 | ||
94 | /** | 100 | /** |
95 | * 密码找回 | 101 | * 密码找回 |
@@ -101,6 +107,7 @@ router.get('/passport/back/success', back.backSuccessByEmailPage);// 邮箱找 | @@ -101,6 +107,7 @@ router.get('/passport/back/success', back.backSuccessByEmailPage);// 邮箱找 | ||
101 | 107 | ||
102 | router.get('/passport/back/mobile', back.indexMobilePage);// 输入手机号找回密码页面 | 108 | router.get('/passport/back/mobile', back.indexMobilePage);// 输入手机号找回密码页面 |
103 | router.get('/passport/back/mobilecode', back.verifyCodeByMobilePage);// 输入手机验证码页面 | 109 | router.get('/passport/back/mobilecode', back.verifyCodeByMobilePage);// 输入手机验证码页面 |
110 | +router.get('/passport/back/generatecodeimg.png', back.generateCodeImg);// 生成图片验证码 | ||
104 | router.post('/passport/back/sendcode', back.sendCodeToMobileAPI);// 发送手机验证码 | 111 | router.post('/passport/back/sendcode', back.sendCodeToMobileAPI);// 发送手机验证码 |
105 | router.post('/passport/back/verifycode', back.verifyCodeByMobileAPI);// 校验手机验证码 | 112 | router.post('/passport/back/verifycode', back.verifyCodeByMobileAPI);// 校验手机验证码 |
106 | 113 | ||
@@ -113,4 +120,10 @@ router.post('/passport/back/passwordbymobile', back.setNewPasswordByMobileAPI);/ | @@ -113,4 +120,10 @@ router.post('/passport/back/passwordbymobile', back.setNewPasswordByMobileAPI);/ | ||
113 | */ | 120 | */ |
114 | router.get('/passport/update', update.index); | 121 | router.get('/passport/update', update.index); |
115 | 122 | ||
123 | +// 服务条款 | ||
124 | +router.get('/passport/privacy', agreement.privacy);// 隐私条款 | ||
125 | +router.get('/passport/newpower', agreement.newpower);// 新力传媒 | ||
126 | +router.get('/passport/yohobuy', agreement.aboutYoho);// 关于有货 | ||
127 | +router.get('/passport/agreement', agreement.agreement);// 服务条款 | ||
128 | + | ||
116 | module.exports = router; | 129 | module.exports = router; |
1 | +<div class="agreement-page yoho-page"> | ||
2 | + <h3>服务条款</h3> | ||
3 | + <p><strong>重要须知:有货(江苏)商贸服务有限公司(下称“YOHO!BUY”)在此特别提醒您仔细阅读</strong>(未成年人应在其法定监护人的陪同下阅读)本《YOHO!BUY用户服务协议》(下称“本协议”)中的各个条款,包括但不限于免除或者限制YOHO!BUY责任的条款、对用户权利进行限制的条款以及约定争议解决方式、司法管辖的条款。您有权选择同意或者不同意本协议。<br> | ||
4 | + </p> | ||
5 | + <p><strong>您如果通过登录YOHO!BUY网站(http://www.yohobuy.com/)用户注册页面或者YOHO!BUY提供的其他用户注册渠道注册用户账号,即视为您完全同意本协议,愿意接受本协议所有及任何条款的约束。</strong></p><br> | ||
6 | + <p><strong>1.名词解释</strong></p><br> | ||
7 | + <p>除您与YOHO!BUY另有约定外,本协议及其补充协议当中的下列名词均采用如下解释:</p> | ||
8 | + <p><strong>1.1 YOHO!BUY网站用户协议:</strong>即本协议,指您与YOHO!BUY当下订立的旨在约定您登录、使用本网站,以及通过本网站下达订单、购买商品、支付货款、收取商品等整个网购过程中,您与YOHO!BUY之间的权利、义务的书面合同。</p><br> | ||
9 | + <p><strong>1.2 YOHO!BUY网站:</strong>即本网站,指YOHO!BUY享有全部著作权的、提供给您及其他用户登录和使用的一个专注潮流的网站,网址为http://www.yohobuy.com/。</p><br> | ||
10 | + <p><strong>1.3 商品:</strong>是YOHO!BUY通过本网站向您推荐并进行销售的具体商品的统称。</p><br> | ||
11 | + <p><strong>1.4 品牌供应商:</strong>与YOHO!BUY签订协议,组织商业活动并通过本网站销售商品和服务的公司,包括品牌供应商或者其授权的经销商。</p><br> | ||
12 | + <p><strong>1.5 购物车:</strong>是模拟线下实体商店提供给顾客放置商品的“购物车”的一个概念,指本网站向您展示您已经下达订单、准备购买但尚未支付相应的购买价款的商品信息的网页区域,又称“虚拟购物车”。</p><br> | ||
13 | + <p><strong>1.6 订单:</strong>指由本网站结帐程序生成的记录会员通过本网站所购买的商品的名称、品牌、价款、折扣等交易信息的表格。这份文件将被用作所有可能发生的与会员购买有关的询问、请求和争议的参考。</p><br> | ||
14 | + <p><strong>1.7 发货单:</strong>指YOHO!BUY或者其品牌供应商、授权的经销商附录在会员所订购的商品的包裹上的、供会员签收的商品销售凭证,发货单一般会简要地说明了对应包裹的每一件商品的名称和数量,如发生退换货必须寄回。</p><br> | ||
15 | + <p><strong>1.8 收货地址:</strong>指您或者其他用户通过本网站购买商品所要求的送货地址,如果没有特别说明,即为会员填写的订单上所记载的送货地址。</p><br> | ||
16 | + <p><strong>1.9 用户账号:</strong>指您通过登录本网站或者YOHO!BUY提供其他的用户账号注册渠道,注册获得并可据以登录本网站的账号。</p><br> | ||
17 | + <p><strong>1.10 恶意评论:</strong>是指个人或组织对本网站、YOHO!BUY和/或本网站对外销售的商品没有兴趣,却组织人力或者采用计算机程序模拟正常用户在本网站上大规模发表用户评论,特别发表对本网站、YOHO!BUY和/或本网站销售的商品负面的评论乃至违反国家有关法律法规的评论。</p><br> | ||
18 | + <p><strong>2.合同目的</strong></p><br> | ||
19 | + <p>本协议旨在约定您在登录、使用本网站,通过本网站购买商品的过程中,您与YOHO!BUY双方分别作为本协议的一方合同当事人所享有的权利和所负有的义务。<br><br> | ||
20 | + <p><strong>3.用户账号</strong></p><br> | ||
21 | + <p>3.1 您可以通过登录本网站的用户账号注册页面注册用户账号并设置相应的登录密码,一经注册成功,您即可以凭借用户账号及登录密码登录及使用本网站。就目前而言,上述用户账号既可能是您的移动电话号码,也可能是您的个人邮箱账号。</p><br> | ||
22 | + <p>3.2 您成功注册用户账号后,如果需要使用该用户账号从本网站购买商品的,至少还应当填写一个收货人、收货地址和手机号码。除此之外,您还可以按照本网站相关页面的说明填写该用户账号项下的用户姓名、性别、生日、移动电话、固定电话、联系地址、QQ、邮编、购物习惯、着装习惯、喜爱品牌等个人信息,上述个人信息仅作为完善您的用户账号资料之用,是否填写并不影响您从本网站购买商品。</p><br> | ||
23 | + <p><strong>3.3 每个手机号码、每个收货地址仅对应一个会员账户。 包含但不限于以下行为,视为虚假注册:</p><br> | ||
24 | + <p>(1)以同一手机号码注册多个账户;</p><br> | ||
25 | + <p>(2)多个账户使用同一收货地址或同一IP地址;</p><br> | ||
26 | + <p>YOHO!BUY有权取消虚假注册账户在YOHO!BUY上消费的权利。</strong></p><br> | ||
27 | + <p>3.4您务必妥善保管您的用户账号、登录密码、支付密码(如有)及您在其项下填写的所有个人信息,不得将其赠与、转让、借用或者以其他的方式提供给第三方。否则,由此给您(或YOHO!BUY、任何第三方)造成的一切损失,概由您自行承担(或者负责赔偿),包括但不限于:</p> | ||
28 | + <p>(1)您无法凭借该用户账号登录、使用本网站及/或从本网站购买商品;</p><br> | ||
29 | + <p>(2)您的该用户账号及其项下的YOHO币(有货币)、优惠券等未经您允许而被第三方盗用。</p><br> | ||
30 | + <p>3.5为了防止您及其他用户的用户账号及其项下的个人信息泄露或者被他人窃取,YOHO!BUY可能会随时采取计算机病毒查杀技术、计算机加密技术等措施进行保护。对此,您完全同意并接受,但这并不能免除本协议第3.3条所述的、您对用户账号及其项下的个人信息所负有的妥善保管义务。</p><br> | ||
31 | + <p>3.6 您如果遗忘了密码或者密码被他人修改,您可以按照YOHO!BUY公布的账号及密码找回规则,通过YOHO!BUY提供的账号及密码找回系统程序进行找回,或者在第一时间联系YOHO!BUY的客服人员协助找回,但YOHO!BUY不保证一定可以找回。</p><br> | ||
32 | + <p><strong>3.7 您充分理解并完全同意:YOHO!BUY是一家面向消费者的专注潮流的网站,YOHO!BUY根据您的用户账号下的商品购买记录及其他相关信息,如果发现您此前通过本网站或者YOHO!BUY提供的其他网购渠道购买的商品大多数并非用于个人消费或者使用用途的,对于您的这个用户账号的商品购买需求,YOHO!BUY有权不予接受;您如果已经下达订单,YOHO!BUY有权不予接受订单;YOHO!BUY如果已经接受订单的,有权单方面解除并不予发货。而且,YOHO!BUY视情况还有权冻结您的这个用户账号,使之无法通过本网站以及YOHO!BUY提供的其他网购渠道下达订单、购买商品。</strong></p><br> | ||
33 | + <p><strong>3.8 作为一个YOHO!BUY的会员,您可以邀请任何一个您的家庭成员、朋友、同事加入本站。这样您就成为他们的邀请人。然而,假如您希望扩大邀请至您家庭成员、朋友、同事等直系圈子以外的人,或者您希望把您的网站链接到本网站,您必须获取YOHO!BUY的预先许可。 在未取得YOHO!BUY事先的书面许可情况下,任何会员通过任何方式组织任何类型的大规模邀请计划,导致不符合前述条款的,将被禁止使用本网站,并且他的个人帐户将被取消。为了防止任何发动自己成为会员的企图,最多两个不同的会员可以使用同一个住所地址。</strong></p><br> | ||
34 | + <p><strong>3.9您充分理解并同意:YOHO!BUY有权使用您的注册信息、用户名、密码等信息,登录进入用户的注册账户,进行证据保全,包括但不限于公证、见证等。</strong></p><br> | ||
35 | + <p><strong>4.商品描述与营销信息</strong></p><br> | ||
36 | + <p><strong>4.1 商品描述:除非YOHO!BUY或者本网站另有说明,本网站出售的商品均为正宗的商品。YOHO!BUY直接与品牌供应商及其授权的经销商合作开展各项营销活动,相关商品信息均由品牌供应商及/或其授权的经销商提供,YOHO!BUY尽可能根据所接收到的商品信息准确、详尽地描述每一件商品。然而,由于品牌供应商及/或其授权的经销商所提供的商品不一定是准确、完整、可靠、有效和没有错误的,因此YOHO!BUY不能保证本网站所有商品的描述和其他相关内容是准确、完整、可靠、有效和没有错误的。</strong></p><br> | ||
37 | + <p>4.2 营销信息:您一经注册用户账号,即视为您同意YOHO!BUY及/或其关联公司通过短信或者电子邮件的方式向您注册时填写的手机号码或者电子邮箱发送相应的商品广告信息、促销优惠等营销信息;您如果不同意发送,您可以通过相应的退订功能进行退订。</p><br> | ||
38 | + <p><strong>5.商品价格</strong></p><br> | ||
39 | + <p>本网站上显示的所有价格都是以人民币为计价单位,不包括运费。结帐之前运费会自动计算包含在订单总价之内。在商品详情页面里您可以找到所有的相关信息,支付价格为下订单时的有效价格。<br></p><br> | ||
40 | + <p><strong>6.订单</strong></p><br> | ||
41 | + <p>6.1 YOHO!BUY保留对单个商品的总出售数量进行限制、对单个订单的商品购买数量及同一IP地址对同类商品购买数量进行限制的权利。</p><br> | ||
42 | + <p>6.2 根据您填写的订单信息,系统将会生成一份包含您的订单的所有必要信息的电子订单表格。在结帐的过程中,您将被邀请复查订购商品的信息、付款方式以及这些商品的运输方式和费用。依据这些信息生成的最终订单表格被认为是该次交易的有效证据,这份文件被认为是所有的发货、问题、退货和争议事项的参考,所以您必须非常仔细地复查这些信息并纠正一切可能的错误。点击“完成”意味着您认可订单表格中包含的所有信息都是正确和完整的。</p><br> | ||
43 | + <p>6.3 如果您填写的收货人与用户本人不一致的,收货人的行为和意思表示视为您的行为和意思表示,您应对收货人的行为及意思表示的法律后果承担连带责任。</p><br> | ||
44 | + <p><strong>7.取消订单</strong></p><br> | ||
45 | + <p>7.1 订单内商品的颜色、尺码、数量下单后无法修改。如您需修改订单收货地址,请在下单后两小时内自助网上修改或联系YOHO!BUY客服修改,我们将协助您联系快递进行修改,但不保证修改成功。</p><br> | ||
46 | + <p>7.2 您也可以选择取消订单或联系YOHO!BUY客服取消,对反复的取消行为,我们可能会调查其原因,也可能会成为我们可能拒绝向您提供服务、冻结或关闭您的个人帐户的原因。</p><br> | ||
47 | + <p><strong>8.合同成立</strong></p><br> | ||
48 | + <p>您充分理解并认可:除法律另有强制性规定外,YOHO!BUY网站上销售方展示的商品和价格等信息仅仅是交易信息的发布,您下单时须填写您希望购买的商品数量、价款及支付方式、收货人、联系方式、收货地址等内容;系统生成的订单信息是计算机信息系统根据您填写的内容自动生成的数据,仅是您向销售方发出的交易诉求;销售方收到您的订单信息后,只有在销售方将您在订单中订购的商品从仓库实际直接向您发出时( 以商品出库为标志),方视为您与销售方之间就实际直接向您发出的商品建立了交易关系;如果您在一份订单里订购了多种商品并且销售方只给您发出了部分商品时,您与销售方之间仅就实际直接向您发出的商品建立了交易关系;只有在销售方实际直接向您发出了订单中订购的其他商品时,您和销售方之间就订单中该其他已实际直接向您发出的商品才成立交易关系。</p><br> | ||
49 | + <p><strong>9.商品缺货</strong></p><br> | ||
50 | + <p>YOHO!BUY接收到您的订单以后,YOHO!BUY发现所订购的商品全部或部分缺货。在这种情况下,YOHO!BUY会就缺货的商品详细情况与您联系后处理退款。如果您在收到此类通知15天之内没有取消订单,YOHO!BUY将把有货的商品送达或者在没有一件订购的商品有货的情况下取消该订单。在任何情况下,由于商品的缺货对您或第三方带来的任何损失,YOHO!BUY不负任何责任。</p><br> | ||
51 | + <p><strong>10.配送服务</strong></p><br> | ||
52 | + <p>10.1您所订购的商品有两种配送方式:(1)由YOHO!BUY选择具有运输服务资质的公司为您提供运输代理服务;(2)由品牌供应商选择具有提供运输服务资质的公司为您提供运输代理服务。上述任一配送方式下,您确认并同意一旦YOHO!BUY或者品牌供应商向运输代理服务公司交付你订购的商品,意味着您与提供运输代理服务公司签订了运输代理协议,形成了运输代理合同法律关系; 相关商品灭失及毁损风险自商品交付至运输代理服务公司起转移给您。</p><br> | ||
53 | + <p>10.2您理解并同意:因以下原因造成订单延迟或无法配送等,YOHO!BUY不承担延迟配送的责任:</p><br> | ||
54 | + <p>(1)您提供的信息错误,地址不详细等原因导致;</p><br> | ||
55 | + <p>(2)货物送达后无人签收,导致无法配送或延迟配送的;</p><br> | ||
56 | + <p>(3)情势变更等因素导致;</p><br> | ||
57 | + <p>(4)不可抗力因素导致,如自然灾害、战争、暴乱等情况</p><br> | ||
58 | + <p><strong>11.交货</strong></p><br> | ||
59 | + <p>11.1 您所订购的商品将被送至订单表格上注明的收货地址。无论什么原因商品不能送达到送货地址的,YOHO!BUY将会尽快跟您取得联系。假如从我们第一次试图跟您联系之日7天内您没有提供答复,YOHO!BUY有权取消该订单。</p><br> | ||
60 | + <p>11.2 在您收到订购商品的同时,请您书面签收证明您收到了完好状态的商品。如果包装出现破损,请拒收。</p><br> | ||
61 | + <p>11.3 如果送货单中的商品列表与您的订单表格中所记录的不同,或者您收到的商品与发货单中的商品列表不符,您可以按照YOHO!BUY对外公布且正在实施的退货政策及退货程序,将相应的商品退回YOHO!BUY或者YOHO!BUY指定的第三方。而且,您务必于收到所订购的商品之日起48小时内,联系YOHO!BUY在线客服或致电400-8899-646将上述情况告知YOHO!BUY;否则,YOHO!BUY有权不予退换货。</p><br> | ||
62 | + <p><strong>12.付款及所有权</p><br> | ||
63 | + <p>YOHO!BUY通过本网站对外销售的商品,如果在YOHO!BUY将商品交付第三方承运人运输之时: | ||
64 | + (1)您已经支付商品的全额的购买价款的,则其所有权于YOHO!BUY将其交付第三方承运人之时转移至您的名下;</p><br> | ||
65 | + <p>(2)您尚未支付商品的全额的购买价款的,则其所有权于您支付全额的购买价款之时转移至您的名下。</p><br> | ||
66 | + <p>在商品所有权按照前款约定转移至您的名下之前,商品所有权由YOHO!BUY、品牌供应商或其授权的经销商所有。</strong></p><br> | ||
67 | + <p><strong>13.退回订单</strong></p><br> | ||
68 | + <p>13.1 如果您对您通过本网站所订购的商品不满意,您可以退回所有或部分商品。对于YOHO!BUY已经收取到的被退回的商品的价款,YOHO!BUY将扣除退货运费后将相应的余额返还给您。您在下达的订单中如果使用了优惠券等其他优惠,YOHO!BUY亦将会按照相应的活动规则进行返还。</p><br> | ||
69 | + <p>13.2 您如果需要退货的,务必于收到商品之日起7天内主动联系YOHO!BUY客服,将您需要退货的需求告知YOHO!BUY。而且,您务必于收到商品之日起7天内,按照不影响商品正常使用及再次销售的原则,将您需要退货的商品及其包装、赠品、发货单、税务发票(如有)等送货时一并交付给您的物品和资料,全部完好无损地退回YOHO!BUY或该商品的品牌供应商。否则,YOHO!BUY有权不予退货。除有相反的证据外,退货的日期以YOHO!BUY或者该商品的品牌供应商收到的包裹上显示的寄出邮戳所显示的日期为准。对于某些商品,如YOHO!BUY在商品详情页面及有关退货政策中已提示该类商品不予以退货的,您的下达订单行为将被视为您已同意接受YOHO!BUY对此类商品不予退货的安排。</p><br> | ||
70 | + <p>13.3 YOHO!BUY有权拒绝不符合YOHO!BUY对外公布实施的退货政策(参阅http://www.yohobuy.com/help/)所规定的条件的所有退货。仅当YOHO!BUY确认以上规定的这些条款得到了适时的遵从后,YOHO!BUY才会启动返还货款金额的程序。YOHO!BUY收到退货后7天内,所有的退款均遵循YOHO!BUY退换货政策操作。</p><br> | ||
71 | + <p>13.4 如果您的退货与上述退货规定不符,您将没有资格得到任何退款。不过,您仍有资格自行支付费用(包括运费)以便接收已经退回到YOHO!BUY的商品。如果您不想接收已经退回到YOHO!BUY的商品,YOHO!BUY有权保有这些商品并保留已经收到的金额。</p><br> | ||
72 | + <p><strong>14.商品保证</strong></p><br> | ||
73 | + <p>本网站所展示的商品完全符合中华人民共和国的相关法律法规的规定。YOHO!BUY保证本网站所售的商品均为正品。如果您对在本网站所购买的商品品牌存在怀疑,只需要在收到商品的90天内,凭工商部门的有效鉴定报告联系YOHO!BUY索取等同该商品售价的全额赔偿。</p><br> | ||
74 | + <p><strong>15.知识产权</strong></p><br> | ||
75 | + <p>15.1 YOHO!BUY对本网站的内容享有全部知识产权,包括但不限于:编码、商标、服务标志、商号、图形、美术品、照片、肖像、文字内容、音频片断、按钮图标已及计算机软件、标识、数码下载、数据汇编都是YOHO!BUY或其内容提供者的财产,受到中华人民共和国版权相关法律法规的保护。您对其仅享有本协议约定范围内的临时的、可撤销的非专有使用权。</p><br> | ||
76 | + <p>15.2 您仅在符合本网站使用目的的前提下被许可浏览和使用本网站,即以个人名义浏览信息和购买供个人使用商品的目的。其他方式的使用都是被严格禁止的,包括但不限于以下方式:复制、修改、销售、传送、再版、删除、添加、展览、记入或演示本网站的内容或以其他方式部分地或整体地非法使用本网站的内容,但经YOHO!BUY允许将本网站当中的资讯转发至微信朋友圈等第三方媒体的除外。</p><br> | ||
77 | + <p><strong>16.用户守则</strong><p><br> | ||
78 | + <p>16.1 本网站与其他在线使用的互联网网站一样,您如果需要进行下载、安装、运行、登录或者使用,您至少必须自备一部可供上网的智能移动终端,并确保其能够通过互联网与本网站服务器软件进行实时的信息(即电子数据)交互,相应的上网流量费等相关费用由您自行承担。除非另有说明,YOHO!BUY存储在其服务器上的数据是YOHO!BUY和其会员之间交易的唯一有效证据。</p><br> | ||
79 | + <p>16.2 本网站目前属于免费使用的网站,YOHO!BUY有权对本网站进行升级及更新,自行设置收费的软件功能、费率标准、收费对象及/或收费时段。您如果不同意YOHO!BUY设置的软件功能、费率标准、收费对象及/或收费时段的,则应当立即停止使用本网站;您如果继续使用的,则视为您接受YOHO!BUY的上述设置,您应当遵照履行并向YOHO!BUY支付相应的费用。</p><br> | ||
80 | + <p>16.3 您不得进行任何侵犯本网站知识产权的行为,或者进行其他的有损于YOHO!BUY或其他用户合法权益的行为,包括但不限于:</p><br> | ||
81 | + <p>(1)删除或修改本网站上的版权信息;</p><br> | ||
82 | + <p>(2)修改、复制和/或发行本网站;</p><br> | ||
83 | + <p>(3)在本网站当中内置各种插件程序或者其他的第三方程序;</p><br> | ||
84 | + <p>(4)进行编译、反编译、反向工程或者以其他方式破解本网站的行为;</p><br> | ||
85 | + <p>(5)使用本网站外挂和/或利用本网站当中的BUG来获得不正当的利益;</p><br> | ||
86 | + <p>(6)利用劫持域名服务器等技术非法侵入、破坏本网站的服务器软件系统,或者修改、增加、删除、窃取、截留、替换本网站的客户端和/或服务器软件系统中的数据,或者非法挤占本网站的服务器空间,或者实施其他的使之超负荷运行的行为;</p><br> | ||
87 | + <p>(7)假冒YOHO!BUY或签约商家在本网站当中发布任何诈骗或虚假信息;</p><br> | ||
88 | + <p>(8)利用本网站故意传播恶意程序或计算机病毒。</p><br> | ||
89 | + <p>16.4 您充分理解到:YOHO!BUY可能会不定期地通过发布软件升级包或软件补丁、在线升级等方式对本网站进行更新。更新的过程中,YOHO!BUY可能通过互联网调取、收集您的PC端终端上的关于本网站的客户端软件版本信息、数据及其他有关资料,并自动进行替换、修改、删除和/或补充。此种行为是网站更新所必须的一种操作或步骤,您如果不同意YOHO!BUY进行此种操作,请您不要进行更新;您更新的行为即视为您同意YOHO!BUY进行此种操作。</p><br> | ||
90 | + <p>16.5 您有权在本网站当中发表评论,转发或者回复其他用户的评论,但您应确保评论真实、客观且不会侵犯任何第三方的著作权、肖像权、名誉权、隐私权等合法权利。而且,您不得借助本网站用户评论功能发布任何广告。</p><br> | ||
91 | + <p>16.6 您应当遵守国家有关法律法规,不得在本网站当中发表、转发或者传播含有下列内容的信息:</p><br> | ||
92 | + <p>(1)反对宪法所确定的基本原则的;</p><br> | ||
93 | + <p>(2)危害国家安全、泄露国家秘密、颠覆国家政权、破坏国家统一的;</p><br> | ||
94 | + <p>(3)损害国家荣誉和利益的;</p><br> | ||
95 | + <p>(4)煽动民族仇恨、民族歧视,破坏民族团结的;</p><br> | ||
96 | + <p>(5)破坏国家宗教政策,宣扬邪教和封建迷信的;</p><br> | ||
97 | + <p>(6)散布谣言,扰乱社会秩序,破坏社会稳定的;</p><br> | ||
98 | + <p>(7)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;</p><br> | ||
99 | + <p>(8)侮辱或者诽谤他人,侵害他人合法权益的;</p><br> | ||
100 | + <p>(9)含有法律、行政法规禁止的其他内容的。</p><br> | ||
101 | + <p>16.7您充分理解并同意:YOHO!BUY保有删除站内各类不符合法律政策或不真实的信息内容而无需通知您的权利。</p><br> | ||
102 | + <p>16.8 个人账户是YOHO!BUY授权您使用YOHO!BUY网站用户管理系统的唯一凭证。YOHO!BUY所提供的优惠券、积分、YOHO币(有货币)、折扣、推送等服务和优惠均通过用户管理系统发放,并且仅提供给获得授权的用户个人使用。您同意在符合法律法规及本条款规定的情况下使用个人帐户,YOHO!BUY有可能在某些情况(例如:您违反本条款和/或其它公开规则,或者您严重违背社会公德、提供虚假注册身份信息或者有其他违反法律禁止性规定的行为或损害YOHO!BUY利益的不正当行为等)下暂时冻结、永久冻结、修改、删除您的个人账户或者采取其他处理措施。特别地,您了解并同意,YOHO!BUY用户管理系统中个人帐户、积分、YOHO币(有货币)、优惠券等互联网产品及服务所有权归属YOHO!BUY,会员在满足YOHO!BUY公布的规则的前提下有权使用上述产品及服务。非经YOHO!BUY同意,您不得将YOHO!BUY各项产品及服务用于商业用途(例如:销售YOHO!BUY个人帐户、销售个人帐户下积分、YOHO币(有货币)、优惠券等)。在使用YOHO!BUY服务过程中,如果您或您的个人帐户刻意规避YOHO!BUY管理措施,或存在涉嫌欺诈、商业牟利、不恰当或不诚实地使用服务或者其他违反本条款和/或其他公开规则的行为(包括但不限于使用作弊软件获取积分及/或优惠券及/或YOHO币(有货币)、贩卖个人帐号、积分及/或优惠券及/或YOHO币(有货币)、盗号、协助盗号、非用于个人或家庭的合理消费等),YOHO!BUY有权拒绝为您继续提供服务,永久冻结您的个人帐户,并根据具体情况并有权对该等个人帐号中因上述手段而产生、获得的一切虚拟产品予以清零。</p><br> | ||
103 | + <p>16.9您理解并同意,如因您违反相关法律与本协议之规定,使YOHO!BUY遭受任何损失,或受到任何第三方索赔,或受到任何行政管理部门的处罚,您应当赔偿YOHO!BUY因此遭受的损失和(或)相关费用,包括但不限于合理的律师费用。</p><br> | ||
104 | + <p><strong>17.免责声明</strong><p><br> | ||
105 | + <p><strong>17.1 关于本网站的免责声明</strong></p><br> | ||
106 | + <p>17.1.1 本网站与其他的在线使用的互联网网站一样,也会受到各种不良信息、网络安全和网络故障问题的困扰,包括但不限于:</p><br> | ||
107 | + <p>(1)其他用户可能会发布诈骗或虚假信息,或者发表有谩骂、诅咒、诋毁、攻击内容的,或者含有淫秽、色情、下流、反动、煽动民族仇恨等让人反感、厌恶的内容的非法言论;</p><br> | ||
108 | + <p>(2)其他用户可能会发布一些侵犯您或者其他第三方知识产权、肖像权、姓名权、名誉权、隐私权和/或其他合法权益的图片、照片、文字等资料;</p><br> | ||
109 | + <p>(3)面临着诸如黑客攻击、计算机病毒困扰、系统崩溃、网络掉线、网速缓慢、程序漏洞等问题的困扰和威胁。</p><br> | ||
110 | + <p><strong>17.1.2 您充分理解到:本协议第17.1.1条所述的各种不良信息、网络安全和网络故障问题,并不是YOHO!BUY或者本网站所导致的问题,由此可能会造成您感到反感、恶心、呕吐等精神损害,或者给您造成其他的损失,概由您自行承担,YOHO!BUY无须向您承担任何责任。</strong></p><br> | ||
111 | + <p>17.1.3 您完全同意:除法律法规规定或者您与YOHO!BUY约定须提前通知的以外,YOHO!BUY有权单方面地中止或者终止本网站所提供的服务而无须提前通知您。该等中止、终止,可能是因为YOHO!BUY解散、注销、合并、分立,也可能是因为YOHO!BUY将本网站或其运营权转让给了第三方,还可能是因为国家法律、法规、政策及国家机关的命令或者其他的诸如地震、火灾、海啸、台风、罢工、战争等不可抗力事件,还可能是因为您违反本协议第16.3条和/或第16.5条所约定的用户守则。</p><br> | ||
112 | + <p><strong>17.2 关于商品销售的免责声明</p><br> | ||
113 | + <p>17.2.1 由于用不同手机终端设备观看时网页显示的差异,YOHO!BUY上促销的商品在图像和颜色方面可能跟真实的物品不尽一致。因此,所有显示的图片、视频和其他商品显示方法仅限于图示目的,在任何情况下不认为是合同的组成部分。假如供出售的商品跟网站上的描述不同,对您唯一的补救措施是根据本协议在没有使用的情况下退回该商品。</p><br> | ||
114 | + <p>17.2.2 YOHO!BUY保留根据市场价格波动随时修改上线商品价格的权利而无须事先通知。在由于系统错误、排版错误或供应商提供价格信息错误的情况下以不正确的价格列出来的商品,YOHO!BUY有拒绝或取消任何对以不正确的价格列出来的商品所下订单的权利。</p><br> | ||
115 | + <p>17.2.3 由于合理的或不可避免的送货延迟对您或第三方带来的任何损失,YOHO!BUY不负任何责任。在这种情况下,YOHO!BUY将尽快地把任何可预知的延迟情况通知您,并在此时请您选择是否取消订单。</p><br> | ||
116 | + <p>17.2.4 YOHO!BUY上面陈列的货物完全符合中华人民共和国的相关法律法规的规定。YOHO!BUY直接与品牌供应商或者他们授权的经销商合作,他们保证其商品是正宗的。您在YOHO!BUY上找到的商品描述均由品牌供应商或者他们授权的经销商提供,仅由他们对其真实性负责。除非另有明确书面说明,YOHO!BUY不对本站上的信息、产品、服务作任何形式的,明示的或默示的担保(法律明确规定的除外)。您应该系统性地参照货物描述找出他们的特征,对于任何种类的直接或间接的、实质或非实质的由于商品的使用造成的损失,YOHO!BUY概不负责。</strong></p><br> | ||
117 | + <p><strong>18.个人信息保护</strong></p><br> | ||
118 | + <p>18.1 YOHO!BUY可能通过本网站在您自愿选择服务或提供信息的情况下收集您的个人信息(简称“个人信息”),例如您的姓名、邮件地址、电话号码及其他身份信息等。我们有可能会保留一些用户的使用习惯信息,用于更好地了解和服务于用户。这些数据将有利于我们开发出更符合用户需求的功能、信息和服务。 </p><br> | ||
119 | + <p>18.2 YOHO!BUY通过本网站可能会收集一些特定的关于您所使用的机器的技术信息,可能会包括:IP地址、操作系统版本、浏览器版本、显示器分辨率、推荐网站等。这些信息将用于提供更好的用户使用体验,提供更方便的服务。 </p><br> | ||
120 | + <p><strong>18.3 YOHO!BUY非常重视保护您的YOHO!BUY账号及密码、电话号码、地理位置、智能移动终端品牌及型号等个人信息,未经您同意,YOHO!BUY不会将其披露给无关的第三方,更不会将其公之于众,但因下列原因而披露给第三方的除外: </p><br> | ||
121 | + <p>(1)基于国家法律法规的规定而对外披露; </p><br> | ||
122 | + <p>(2)应国家司法机关及其他有关机关基于法定程序的要求而披露; </p><br> | ||
123 | + <p>(3)为保护YOHO!BUY或您的合法权益而披露; </p><br> | ||
124 | + <p>(4)在紧急情况,为保护其他用户及第三方人身安全而披露; </p><br> | ||
125 | + <p>(5)经您本人同意或应您的要求而披露。 </p><br> | ||
126 | + <p>18.4 YOHO!BUY将使用各种安全技术和程序防止您及其他用户个人信息的丢失、不当使用、未经授权阅览或披露。但您充分理解到:由于技术的限制以及可能存在的各种恶意手段,在互联网行业,即便竭尽所能加强安全措施,也不可能始终保证信息百分之百的安全。</strong> </p><br> | ||
127 | + <p><strong>19.其他约定</strong></p><br> | ||
128 | + <p>19.1 YOHO!BUY保留随时地、不事先通知地、不需要任何理由地、单方面地修订本协议的权利。本协议一经修订,YOHO!BUY将会用修订后的协议版本完全替代修订前的协议版本,并通过适当的方式向所有用户公布。您应当及时关注和了解本协议的修订情况,如果您不同意修订后协议版本,请您立即停止使用本网站,否则即视同您同意并完全接受修订后的协议版本。</p><br> | ||
129 | + <p><strong>19.2 YOHO!BUY有可能以消费者告知书、买家须知、温馨提示等形式,向您说明您在使用本网站购买商品时应当履行的本协议所约定的义务之外的其他义务,您亦应当仔细阅读并全面履行。上述说明如果与本协议相互冲突或者矛盾的,以上述约定为准;上述约定未涉及的内容,仍适用本协议。</p><br> | ||
130 | + <p>19.3 YOHO!BUY将本协议内置于本网站的注册环节,您在注册的过程中即可查阅、了解本协议,并通过勾选“我已阅读并接受YOHO!BUY用户服务协议”表示您完全同意并接受本协议之约束,或者通过取消勾选“我已阅读并接受YOHO!BUY用户服务协议”表示您不同意本协议。</strong></p><br> | ||
131 | + <p>19.4 本协议各条款是可分的,所约定的任何条款如果部分或者全部无效,不影响该条款其他部分及本协议其他条款的法律效力。</p><br> | ||
132 | + <p>19.5 本协议各条款的标题只是为了方便用户阅读而起到提示、醒目的作用,对本协议的解释及适用没有任何指引作用。</p><br> | ||
133 | + <p>19.6 YOHO!BUY基于本协议及其补充协议的有效弃权必须是书面的,并且该弃权不能产生连带的相同或者类似的弃权。</p><br> | ||
134 | + <p><strong>19.7 您通过本网站购买非商品的服务产品的,您与YOHO!BUY之间的权利义务亦参照本协议的相关约定。</strong></p><br> | ||
135 | + <p>19.8 您与YOHO!BUY均应当严格履行本协议及其补充协议所约定的各项义务,如发生争议或者纠纷,双方可以友好协商解决;协商不成的,任何一方均可提请YOHO!BUY住所所在地人民法院诉讼解决。</p><br> | ||
136 | + <p>19.9 本网站的客户服务电话为:400-8899-646,您如对本协议条款有任何疑问或者需要帮助,可以通过上述电话与YOHO!BUY联系。</p><br> | ||
137 | + <p>19.10 本协议及其补充协议签订地为江苏省南京市建邺区,均受中华人民共和国法律、法规管辖,YOHO!BUY保留最终解释权。</p><br> | ||
138 | + | ||
139 | + <div class="select-btn"> | ||
140 | + <span><i class="iconfont pitch select"></i>我已阅读并同意遵守YOHO!BUY有货app服务条款</span> | ||
141 | + <div class="submit-btn" href="">确 定</div> | ||
142 | + </div> | ||
143 | + | ||
144 | + <input type="hidden" name="app_version" value="{{appVersion}}"> | ||
145 | +</div> |
1 | +<div class="newpower-page yoho-page"> | ||
2 | + <div class="banner"></div> | ||
3 | + | ||
4 | + <p> | ||
5 | + <span>一、公司概况:</span><br> | ||
6 | + 南京新与力文化传播有限公司(简称新力传媒)——中国潮流文化生态圈的创造者和引领者。10年以来,YOHO!致力于中国潮流产业的发展,从一本《YOHO!潮流志》开始,延伸到网络社区、电子商务等等领域,成为中国最权威和最具影响力的潮流“营、销”平台。我们通过媒体+零售线上线下一体化布局,为中国数以亿计的潮流消费者提供潮流讯息、产品及服务,并传播积极健康、全球化的潮流生活方式,更为中国的年轻一代消费者带来了来自全球的潮流生活方式。公司总部位于南京建邺区国家广告产业园,并在北京、上海、广州、香港、东京设立了分(子)公司。公司已获得鼎晖投资、新加坡淡马锡祥峰基金、软银赛富基金、达晨创投、华人文化等数轮投资。公司致力于将“YOHO!”打造成为中国年轻人最喜爱和最值得信赖的品牌,引领中国潮流文化产业的发展。 <br><br> | ||
7 | + | ||
8 | + <span>二、公司主要项目:</span><br> | ||
9 | + 1、平面杂志及电子平台<br> | ||
10 | + 《YOHO!潮流志》、《YOHO!GIRL》为YOHO!旗下在国内潮流领域影响力的杂志媒体。《YOHO!潮流志》2005 年10月创刊。他是国内第一本完全原创版权的,提供潮流和 lifestyle 资讯,属于年轻人的潮流时尚半月刊,通过正规发行渠道(报刊亭、连锁商超等)发行至全国各大中城市,深受全国年轻人的喜爱。设计给国内年轻女性的中高端时装月刊《YOHO!GIRL》,2013年3月正式创刊,在香港、大陆以及日本东京茑屋地区同步发行。以大量独家资讯加上独特的编采手法,改变读者的阅读习惯,扩阔大家在时装、美容、设计、生活、次文化等各方面的视野。深入结构品牌背后的哲学和时装趋势,带领各读者一探最新时尚。<br><br> | ||
11 | + | ||
12 | + 作为中国影响力最大、权威性最高、发行量最广的潮流杂志电子平台, “Yoho!Now”于 iOS 和 Android平台触亮全球潮流资讯,“Yoho!Now”7*24h 无休供应时装、运动、设计、科技、美容、家居、趣闻等严选潮流营养,并于每周发布特别线上专题,与读者Play and Learn。《YOHO!潮流志》和《YOHO!GIRL》亦于各自App內每周上架新鲜线上周刊,打包纸质版内容精华,汇通YOHO!潮流矩阵。 <br><br> | ||
13 | + | ||
14 | + 2、关于“Yoho!Buy有货” <br> | ||
15 | + “Yoho!Buy有货”(www.yohobuy.com)——年轻人潮流购物中心,同样秉承YOHO!“年轻是种态度”的口号,Yoho!Buy有货专注于中国潮流趋势和受众的需要,凭借专业的买手团队和对中国潮流趋势敏锐的嗅觉,积极开拓符合中国年轻人喜爱的品牌和商品。销售包括国际知名、日韩港台流行、明星设计师、内地原创等等超过1000 个潮流品牌商品,满足18-35岁年轻群体的时尚个性化述求,涵盖男女服装、鞋帽、配件、童装及创意生活用品等。Yoho!Buy有货所销售的品牌均与品牌直接签订销售协议,保持货品与国际国内实体店铺同步,通过独家定制、限定发售、明星合作品牌等,并结合“逛”内容频道及社区互动引导消费。Yoho!Buy有货已成为中国年轻态群体最喜爱的潮流购物平台。<br><br> | ||
16 | + | ||
17 | + 3、关于“mars - 新鲜好去处”<br> | ||
18 | + “mars - 新鲜好去处”是一款由YOHO!出品的潮流生活应用,立志为百万年轻人打造最酷的“城市探索”线上枢纽。连续两周被 Apple 评选为App Store“最佳新应用”,并获得 2016 年“一月最佳 App”、“最佳生活 App”等推荐。mars深入探索全球热点城市潮流坐标,现已上线北京、上海、成都、台北、香港、东京、首尔、纽约、洛杉矶等城市,未来还将陆续上线更多城市。集优质潮流攻略、专属玩乐线路、每日热点话题等功能,邀集世界各地时髦生活方式达人与所有用户分享好去处,让潮流随时、随地、随享。我们的目标就是带你去那些“如果你不用 mars 可能一辈子都不知道”的潮流好去处。<br><br> | ||
19 | + </p> | ||
20 | +</div> |
1 | +<div class="privacy-page yoho-page"> | ||
2 | + <h3>隐私条款</h3> | ||
3 | + <p>欢迎访问YOHO!BUY有货APP!我们以本隐私申明声明对访问者隐私保护的许诺。</p><br> | ||
4 | + | ||
5 | + <p> | ||
6 | + <span>YOHO!BUY有货的信息收集与使用</span><br> | ||
7 | + | ||
8 | + YOHO!BUY有货APP收集用户提交的个人识别信息(下称“个人识别信息”), 一旦注册,YOHO!BUY 有货APP用户即可以建立由一页或多页网页组成的含有用户信息的用户档案。我们将收集用户发布在其用户档案中的数据,包括但不限于: 会员信息,联系信息,购物&着装习惯和喜爱品牌(合称为“用户档案信息”),我们使用这些信息来获得用户的统计资料。我们将会用这些统计数据来给我们的用户分类,以便有针对性地向我们的用户提供新的服务。我们会通过您的邮件地址来通知您这些新的服务。<br><br> | ||
9 | + | ||
10 | + 我们同样从用户处收集其他非个人识别信息(下称“非个人识别信息”),包括IP地址、集合的用户数据和浏览器类型。该等数据会被用来管理YOHO!BUY 有货APP,跟踪使用记录,改进YOHO!BUY 有货APP的服务。该等非个人识别信息通常被用于下列目的:研究和分析站点的使用情况,订制您浏览的广告和内容,满足您对服务的要求,以及改进我们的服务。出于安全和监管的目的,用户的IP地址将会被记录。<br><br> | ||
11 | + | ||
12 | + 我们或其商业伙伴可能在YOHO!BUY 有货APP上不时地进行促销或者抽奖。用户可能会被要求提供个人识别信息,包括姓名,电子邮件地址或家庭住址。因进行促销或者抽奖而收集个人识别信息时,您将清楚地被告知个人识别信息的收集方以及适用的隐私政策。<br><br> | ||
13 | + | ||
14 | + <span>YOHO!BUY 有货APP收集信息的共享与披露</span><br> | ||
15 | + | ||
16 | + 除本隐私政策另有规定,我们不会在未经您同意的情况下在YOHO!BUY 有货APP及其母公司、子公司或者关联公司(为本隐私政策之目的,包括遵守本隐私政策的技术提供者)之外泄露您的个人识别信息或者用户档案信息,除非我们认为这种披露是有必要的:(1)为遵守法律的要求或者回应我们收到的传票、搜查令或者其他法律程序,而不论该等回应是否为适用法律所要求的;(2)为回应主管政府部门的要求;(3)为了保护公众和服务用户的安全;或者(4)为了维护我们的法律权利和利益。<br><br> | ||
17 | + | ||
18 | + 当我们出售YOHO!BUY 有货APP或其全部资产时,我们保留向其继任者转让个人识别信息和用户档案信息的权利。 | ||
19 | + 我们也可以向某些您明确同意接收其信息的广告合作伙伴转让您的个人识别信息和用户档案信息。因此进行个人识别信息的收集时,您将清楚地被告知适用的隐私政策。<br><br> | ||
20 | + | ||
21 | + <span>用户名和密码</span><br> | ||
22 | + YOHO!BUY 有货APP用户账号通过用户创设的密码确保其安全性。您应当对您密码的保密负全部责任。请不要和他人分享此信息。如果您泄漏了密码,您可能丢失了您的个人识别信息,并且有可能导致对您不利的司法行为。如果您和他人共享一台电脑,您应该在离开YOHO!BUY 有货APP时退出系统以保证您的信息不被后来使用该电脑者获取。 | ||
23 | + 因此不管任何原因使您的密码安全受到危及,您应该立即通过我们的客服热线:400-889-9646和我们取得联系 。<br><br> | ||
24 | + | ||
25 | + <span>您的交易行为</span><br> | ||
26 | + 我们跟踪IP地址仅仅只是为了安全的必要。如果我们没有发现任何安全问题,我们会及时删除我们收集到的IP地址。我们还跟踪全天的页面访问数据。全天页面访问数据被用来反映网站的流量,我们可以为未来的发展制定计划(例如,增加服务器)。<br><br> | ||
27 | + | ||
28 | + <span>邮件 / 短信 / 会刊服务</span><br> | ||
29 | + 我们保留通过邮件、短信、邮寄会刊的形式,对本网站注册、购物用户发送订单信息、促销活动等告知服务的权利。如果您在YOHO!BUY 有货APP注册、购物,表明您已默示同意接受此项服务。如果您不想接收来自我们的邮件、短信或会刊,您可以向我们的客服提出退阅申请,并注明您的E-mail地址、手机号或相关地址信息,我们会在收到申请后为您办理退阅。<br><br> | ||
30 | + | ||
31 | + <span>Cookies 的使用</span><br> | ||
32 | + 我们使用cookies来储存用户的喜好和记录活动信息以确保用户不会重复收到同样的广告和定制的时事通讯、广告以及基于浏览器类型和用户档案信息的网页内容。我们不会把在cookies中保存的信息与您在我们网站上提交的任何个人识别信息相连接。您可以通过设置您的浏览器以接受或者拒绝全部或部分的cookies,或要求在cookies被设置时通知您。由于每个浏览器是不同的,请查看浏览器的“帮助”菜单来了解如何更改您的cookies选择参数。但是,您应允许来自YOHO!BUY 有货APP的cookies以使您可以使用网站的更多的功能。<br><br> | ||
33 | + | ||
34 | + <span>外部链接</span><br> | ||
35 | + YOHO!BUY 有货APP包含其他网站的链接。但我们不对其他网站上的隐私政策和/或其执行承担责任。当链接到其他网站时,用户应该阅读该网站贴示的隐私政策。我们的隐私政策仅适用于自YOHO!BUY 有货APP收集的信息。<br><br> | ||
36 | + | ||
37 | + <span>第三方广告</span><br> | ||
38 | + 我们可能会通过与第三方合作向用户提供服务。因此,我们可能向该第三方提供您通过YOHO!BUY 有货APP提交给我们的个人识别信息和用户档案信息;但该第三方应同意承担与我们相同的责任以保护用户的隐私。另外,在不会披露用户的个人识别信息和用户档案信息的前提下,我们可以对集合的用户个人识别信息和用户档案进行分析和商业性使用。<br><br> | ||
39 | + | ||
40 | + <span>安全</span><br> | ||
41 | + 我们会采取合理措施保护存储在我们数据库中的用户个人识别信息和用户档案信息,并且对那些需要履行其工作职责的雇员,比如我们的客户服务人员和技术人员,获取用户个人识别信息和用户档案信息进行限制。请注意,我们无法保证用户个人识别信息和用户档案信息的安全性。未授权的登陆或使用、硬件或软件的故障、以及其他因素均可能在任何时候危及用户个人识别信息的安全性。<br><br> | ||
42 | + | ||
43 | + <span>隐私政策的变更</span><br> | ||
44 | + 我们可能对本隐私政策不时进行修改。如果我们进行任何修改,我们将在YOHO!BUY 有货APP主页上发布为期30天的通知以使用户知道被修改内容的类型以及指示用户审阅更新的隐私政策。如果您在对本隐私政策任何细微修改发布后继续使用网站,则表示您同意遵守任何该等修改。<br><br> | ||
45 | + | ||
46 | + <span>联系我们</span><br> | ||
47 | + 如果您就本隐私政策有任何疑问,请与我们客服联系客服热线:400-889-9646。<br><br> | ||
48 | + </p> | ||
49 | +</div> |
1 | +<div class="about-yohobuy-page yohobuy-page"> | ||
2 | + <div class="banner"></div> | ||
3 | + | ||
4 | + <p> | ||
5 | + {{!-- <span>关于“Yoho!Buy 有货”</span><br> --}} | ||
6 | + “Yoho!Buy 有货”( www.yohobuy.com )——年轻人潮流购物中心,同样秉承YOHO!“年轻是种态度”的口号,Yoho!Buy有货专注于中国潮流趋势和受众的需要,凭借专业的买手团队和对中国潮流趋势敏锐的嗅觉,积极开拓符合中国年轻人喜爱的品牌和商品。销售包括国际知名、日韩港台流行、明星设计师、内地原创等等超过1000 个潮流品牌商品,满足18-35岁年轻群体的时尚个性化述求,涵盖男女服装、鞋帽、配件、童装及创意生活用品等。Yoho!Buy有货所销售的品牌均与品牌直接签订销售协议,保持货品与国际国内实体店铺同步,通过独家定制、限定发售、明星合作品牌等,并结合“逛”内容频道及社区互动引导消费。Yoho!Buy有货已成为中国年轻态群体最喜爱的潮流购物平台。 | ||
7 | + </p> | ||
8 | + | ||
9 | + <div class="about-bottom"></div> | ||
10 | +</div> |
@@ -6,6 +6,12 @@ | @@ -6,6 +6,12 @@ | ||
6 | <span id="area-code" class="area-code">{{areaCode}}</span> | 6 | <span id="area-code" class="area-code">{{areaCode}}</span> |
7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> | 7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> |
8 | </div> | 8 | </div> |
9 | + <div class="passport-captcha row"> | ||
10 | + <div class="passport-captcha-img"><img id="verify-code-img" src="{{verifySrc}}" alt="verify code"></div> | ||
11 | + <div class="passport-captcha-input"> | ||
12 | + <input id="verify-code" type="text" placeholder="验证码"> | ||
13 | + </div> | ||
14 | + </div> | ||
9 | <span id="btn-next" class="btn btn-next disable row">下一步</span> | 15 | <span id="btn-next" class="btn btn-next disable row">下一步</span> |
10 | </div> | 16 | </div> |
11 | </div> | 17 | </div> |
1 | <div class="back-new-password-page passport-page yoho-page"> | 1 | <div class="back-new-password-page passport-page yoho-page"> |
2 | {{> passport/header}} | 2 | {{> passport/header}} |
3 | <div class="content"> | 3 | <div class="content"> |
4 | - <div class="input-container row has-eye"> | ||
5 | - <input id="pwd" class="input pwd" type="text" placeholder="请输入新密码" autocomplete="off" maxlength="20"> | 4 | + <div class="row js-password"> |
5 | + <div class="input-container has-eye"> | ||
6 | + <input id="pwd" class="input pwd" type="text" placeholder="请输入新密码" autocomplete="off" maxlength="20"> | ||
7 | + </div> | ||
8 | + <div class="pwd-lint"> | ||
9 | + <i class="iconfont icon-tip"></i> | ||
10 | + <span class="pwd-lint-txt">由字母、数字组合,不能包含特殊字符</span> | ||
11 | + </div> | ||
6 | </div> | 12 | </div> |
7 | <span id="btn-ok" class="btn btn-ok disable">完成</span> | 13 | <span id="btn-ok" class="btn btn-ok disable">完成</span> |
8 | </div> | 14 | </div> |
@@ -10,8 +10,14 @@ | @@ -10,8 +10,14 @@ | ||
10 | 您以后还可以使手机号+密码的形式登录有货哦! | 10 | 您以后还可以使手机号+密码的形式登录有货哦! |
11 | </div> | 11 | </div> |
12 | {{/if}} | 12 | {{/if}} |
13 | - <div class="input-container row has-eye"> | ||
14 | - <input id="pwd" class="input pwd" type="text" placeholder="请输入密码" autocomplete="off" maxlength="20"> | 13 | + <div class="row"> |
14 | + <div class="input-container row has-eye"> | ||
15 | + <input id="pwd" class="input pwd" type="text" placeholder="请输入密码" autocomplete="off" maxlength="20"> | ||
16 | + </div> | ||
17 | + <div class="pwd-lint"> | ||
18 | + <i class="iconfont icon-tip"></i> | ||
19 | + <span class="pwd-lint-txt">由字母、数字组合,不能包含特殊字符</span> | ||
20 | + </div> | ||
15 | </div> | 21 | </div> |
16 | <span id="btn-sure" class="btn btn-sure disable row">确定</span> | 22 | <span id="btn-sure" class="btn btn-sure disable row">确定</span> |
17 | </div> | 23 | </div> |
@@ -6,7 +6,17 @@ | @@ -6,7 +6,17 @@ | ||
6 | <span id="area-code" class="area-code">{{areaCode}}</span> | 6 | <span id="area-code" class="area-code">{{areaCode}}</span> |
7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> | 7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> |
8 | </div> | 8 | </div> |
9 | + <!-- 验证码: start--> | ||
10 | + <div class="passport-captcha row"> | ||
11 | + <div class="passport-captcha-img"> | ||
12 | + <img class="passport-captcha-png" src="{{captchaUrl}}"> | ||
13 | + </div> | ||
14 | + <div class="passport-captcha-input"> | ||
15 | + <input id="js-captcha" type="text" placeholder="验证码"> | ||
16 | + </div> | ||
17 | + </div> | ||
18 | + <!-- 验证码: end--> | ||
9 | <span id="btn-next" class="btn btn-next disable row">下一步</span> | 19 | <span id="btn-next" class="btn btn-next disable row">下一步</span> |
10 | <p class="register-tip">Yoho!Family账号可登录Yoho!Buy有货、Yoho!Now、mars及SHOW</p> | 20 | <p class="register-tip">Yoho!Family账号可登录Yoho!Buy有货、Yoho!Now、mars及SHOW</p> |
11 | </div> | 21 | </div> |
12 | -</div> | 22 | +</div> |
1 | <div class="reg-password-page passport-page yoho-page"> | 1 | <div class="reg-password-page passport-page yoho-page"> |
2 | {{> passport/header}} | 2 | {{> passport/header}} |
3 | <div class="content"> | 3 | <div class="content"> |
4 | - <div class="input-container row has-eye"> | ||
5 | - <input id="pwd" class="input pwd" type="text" placeholder="请输入密码" autocomplete="off" maxlength="20"> | 4 | + <div class="row js-password"> |
5 | + <div class="input-container has-eye"> | ||
6 | + <input id="pwd" class="input pwd" type="text" placeholder="6-20位的密码" autocomplete="off" maxlength="20"> | ||
7 | + </div> | ||
8 | + <div class="pwd-lint"> | ||
9 | + <i class="iconfont icon-tip"></i> | ||
10 | + <span class="pwd-lint-txt">由字母、数字组合,不能包含特殊字符</span> | ||
11 | + </div> | ||
6 | </div> | 12 | </div> |
7 | - <span id="btn-sure" class="btn btn-sure disable row">确定</span> | 13 | + <span id="btn-sure" class="btn btn-sure disable row">注册</span> |
14 | + <div class="app-agreement"><span></span><i class="iconfont pitch select"></i><a class="agreement-detail">我已阅读并同意遵守YOHO!BUY有货服务条款</a></div> | ||
8 | </div> | 15 | </div> |
9 | <input id="phone-num" type="hidden" value="{{phoneNum}}"> | 16 | <input id="phone-num" type="hidden" value="{{phoneNum}}"> |
10 | <input id="area-code" type="hidden" value="{{areaCode}}"> | 17 | <input id="area-code" type="hidden" value="{{areaCode}}"> |
11 | <input id="token" type="hidden" value="{{token}}"> | 18 | <input id="token" type="hidden" value="{{token}}"> |
19 | + <input id="sms-code" type="hidden" value="{{smsCode}}"> | ||
20 | +</div> | ||
21 | + | ||
22 | +<div class="prompt"> | ||
23 | + <span class="word">是否已阅读并同意遵守YOHO!BUY<br>有货服务条款</span> | ||
24 | + <div class="choose"> | ||
25 | + <span class="ensure">是</span> | ||
26 | + <span class="deny">否</span> | ||
27 | + | ||
28 | + </div> | ||
12 | </div> | 29 | </div> |
@@ -15,5 +15,5 @@ | @@ -15,5 +15,5 @@ | ||
15 | <input type="hidden" name="area" id="area" value="{{area}}"> | 15 | <input type="hidden" name="area" id="area" value="{{area}}"> |
16 | </div> | 16 | </div> |
17 | <script> | 17 | <script> |
18 | - var canResend = {{canResend}}; | 18 | + var countdown = {{countdown}}; |
19 | </script> | 19 | </script> |
@@ -7,6 +7,12 @@ | @@ -7,6 +7,12 @@ | ||
7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> | 7 | <input id="phone-num" class="input phone-num" type="text" placeholder="手机号"> |
8 | <button class="clear-input" type="button"></button> | 8 | <button class="clear-input" type="button"></button> |
9 | </div> | 9 | </div> |
10 | + <div class="passport-captcha row"> | ||
11 | + <div class="passport-captcha-img"><img src="{{captchaUrl}}" alt=""></div> | ||
12 | + <div class="passport-captcha-input"> | ||
13 | + <input id="js-captcha" type="text" placeholder="验证码"> | ||
14 | + </div> | ||
15 | + </div> | ||
10 | <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button> | 16 | <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button> |
11 | </div> | 17 | </div> |
12 | </div> | 18 | </div> |
@@ -2,9 +2,17 @@ | @@ -2,9 +2,17 @@ | ||
2 | {{> passport/header}} | 2 | {{> passport/header}} |
3 | <div class="content"> | 3 | <div class="content"> |
4 | <p class="sms-login-msg small">你以后还可以使用手机号码 + 密码的形式登录有货哦!</p> | 4 | <p class="sms-login-msg small">你以后还可以使用手机号码 + 密码的形式登录有货哦!</p> |
5 | - <div class="input-container row has-eye"> | ||
6 | - <input id="pwd" class="pwd input" type="text" placeholder="密码"> | ||
7 | - <div class="eye" id="eye"></div> | 5 | + <div class="row js-password"> |
6 | + <div class="input-container row has-eye"> | ||
7 | + <input id="pwd" class="pwd input" type="text" placeholder="6-20位的密码"> | ||
8 | + <div class="eye" id="eye"></div> | ||
9 | + </div> | ||
10 | + <div class="pwd-lint"> | ||
11 | + <i class="iconfont icon-tip"></i> | ||
12 | + <span class="pwd-lint-txt">由字母、数字组合,不能包含特殊字符</span> | ||
13 | + </div> | ||
14 | + </div> | ||
15 | + <div> | ||
8 | </div> | 16 | </div> |
9 | <span id="btn-next" class="btn btn-next disable row">确定</span> | 17 | <span id="btn-next" class="btn btn-next disable row">确定</span> |
10 | </div> | 18 | </div> |
@@ -12,6 +12,7 @@ const detailModel = require(`${mRoot}/detail`); // 商品详情 model | @@ -12,6 +12,7 @@ const detailModel = require(`${mRoot}/detail`); // 商品详情 model | ||
12 | const introModel = require(`${mRoot}/intro`); // 商品尺码信息 model | 12 | const introModel = require(`${mRoot}/intro`); // 商品尺码信息 model |
13 | const preferenceModel = require(`${mRoot}/preference`); // 商品偏好 model | 13 | const preferenceModel = require(`${mRoot}/preference`); // 商品偏好 model |
14 | const detailRelated = require(`${mRoot}/consult-comment`); // 商品评论咨询 model | 14 | const detailRelated = require(`${mRoot}/consult-comment`); // 商品评论咨询 model |
15 | +const couponModel = require(`${mRoot}/coupon`); // 商品 优惠券 modal | ||
15 | const _ = require('lodash'); | 16 | const _ = require('lodash'); |
16 | 17 | ||
17 | const helpers = global.yoho.helpers; | 18 | const helpers = global.yoho.helpers; |
@@ -138,12 +139,9 @@ exports.intro = (req, res, next) => { | @@ -138,12 +139,9 @@ exports.intro = (req, res, next) => { | ||
138 | exports.preference = (req, res, next) => { | 139 | exports.preference = (req, res, next) => { |
139 | preferenceModel({ | 140 | preferenceModel({ |
140 | productskn: req.query.productSkn, | 141 | productskn: req.query.productSkn, |
141 | - yhchannel: req.yoho.channel, | ||
142 | - brandId: req.query.brandId | 142 | + limit: '20' // 后期值需要修改的话得手动改 |
143 | }).then((result) => { | 143 | }).then((result) => { |
144 | - res.render('detail/preference', Object.assign({ | ||
145 | - layout: false | ||
146 | - }, result)); | 144 | + res.send(result); |
147 | }).catch(next); | 145 | }).catch(next); |
148 | }; | 146 | }; |
149 | 147 | ||
@@ -160,6 +158,9 @@ exports.comments = (req, res, next) => { | @@ -160,6 +158,9 @@ exports.comments = (req, res, next) => { | ||
160 | }); | 158 | }); |
161 | 159 | ||
162 | detailRelated.comments(req.query).then((result) => { | 160 | detailRelated.comments(req.query).then((result) => { |
161 | + if (result.navTitle) { | ||
162 | + headerData.navTitle = result.navTitle; | ||
163 | + } | ||
163 | res.render('detail/comments', Object.assign({ | 164 | res.render('detail/comments', Object.assign({ |
164 | title: '购买评价', | 165 | title: '购买评价', |
165 | pageHeader: headerData, | 166 | pageHeader: headerData, |
@@ -175,12 +176,15 @@ exports.consults = (req, res, next) => { | @@ -175,12 +176,15 @@ exports.consults = (req, res, next) => { | ||
175 | if (!req.query.product_id) { | 176 | if (!req.query.product_id) { |
176 | return next(); | 177 | return next(); |
177 | } | 178 | } |
178 | - | 179 | + let uid = req.user.uid || 0; |
179 | let headerData = headerModel.setNav({ | 180 | let headerData = headerModel.setNav({ |
180 | navTitle: '购买咨询' | 181 | navTitle: '购买咨询' |
181 | }); | 182 | }); |
182 | 183 | ||
183 | - detailRelated.consults(req.query).then((result) => { | 184 | + detailRelated.consults(req.query, uid).then((result) => { |
185 | + if (result.navTitle) { | ||
186 | + headerData.navTitle = result.navTitle; | ||
187 | + } | ||
184 | res.render('detail/consults', Object.assign({ | 188 | res.render('detail/consults', Object.assign({ |
185 | title: '购买咨询', | 189 | title: '购买咨询', |
186 | pageHeader: headerData, | 190 | pageHeader: headerData, |
@@ -247,13 +251,12 @@ exports.consultsubmit = (req, res, next) => { | @@ -247,13 +251,12 @@ exports.consultsubmit = (req, res, next) => { | ||
247 | data: '' | 251 | data: '' |
248 | }; | 252 | }; |
249 | 253 | ||
250 | - // 判断参数是否存在 | 254 | + // 判断参数是否存在 |
251 | if (!req.body.product_id || !req.body.content) { | 255 | if (!req.body.product_id || !req.body.content) { |
252 | return res.json(data); | 256 | return res.json(data); |
253 | } | 257 | } |
254 | 258 | ||
255 | - detailRelated.addConsult(req.user.uid, req.body.product_id, req.body.content).then((result) => { | ||
256 | - | 259 | + return detailRelated.addConsult(req.user.uid, req.body.product_id, req.body.content).then((result) => { |
257 | if (result) { | 260 | if (result) { |
258 | Object.assign(data, result); | 261 | Object.assign(data, result); |
259 | } | 262 | } |
@@ -344,7 +347,7 @@ exports.index = (req, res, next) => { | @@ -344,7 +347,7 @@ exports.index = (req, res, next) => { | ||
344 | * @param {[type]} res [description] | 347 | * @param {[type]} res [description] |
345 | * @return {[type]} [description] | 348 | * @return {[type]} [description] |
346 | */ | 349 | */ |
347 | -exports.indexData = (req, res, next)=> { | 350 | +exports.indexData = (req, res, next) => { |
348 | if (!req.xhr) { | 351 | if (!req.xhr) { |
349 | return next(); | 352 | return next(); |
350 | } | 353 | } |
@@ -361,10 +364,59 @@ exports.indexData = (req, res, next)=> { | @@ -361,10 +364,59 @@ exports.indexData = (req, res, next)=> { | ||
361 | ua: req.get('user-agent') || '' | 364 | ua: req.get('user-agent') || '' |
362 | }, req.__User__)).then((result) => { | 365 | }, req.__User__)).then((result) => { |
363 | if (_.isEmpty(result)) { | 366 | if (_.isEmpty(result)) { |
364 | - return res.json({code: 400, message: '数据错误'}); | 367 | + return res.json({ |
368 | + code: 400, | ||
369 | + message: '数据错误' | ||
370 | + }); | ||
365 | } | 371 | } |
366 | result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false; | 372 | result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false; |
367 | return res.json(result); | 373 | return res.json(result); |
368 | }).catch(next); | 374 | }).catch(next); |
369 | 375 | ||
370 | }; | 376 | }; |
377 | + | ||
378 | + | ||
379 | +/** | ||
380 | + * [查询商品 品牌券] | ||
381 | + */ | ||
382 | +exports.brandCoupon = (req, res) => { | ||
383 | + const uid = req.user.uid; | ||
384 | + const skn = +req.query.skn; | ||
385 | + const brandId = +req.query.brandId; | ||
386 | + | ||
387 | + if (!(skn && brandId)) { | ||
388 | + return res.json([]); | ||
389 | + } | ||
390 | + | ||
391 | + couponModel.queryProdPageCoupons(uid, skn, brandId) | ||
392 | + .then( | ||
393 | + result => { | ||
394 | + return result.data || []; | ||
395 | + }, () => { | ||
396 | + return []; | ||
397 | + }) | ||
398 | + .then(coupons => { | ||
399 | + return res.json(coupons); | ||
400 | + }); | ||
401 | +}; | ||
402 | + | ||
403 | +/** | ||
404 | + * [获取商品 品牌券] | ||
405 | + */ | ||
406 | +exports.getCoupon = (req, res, next) => { | ||
407 | + const uid = req.user.uid; | ||
408 | + const couponId = +req.body.couponId; | ||
409 | + | ||
410 | + if (!couponId) { | ||
411 | + return res.json({ | ||
412 | + code: 400, | ||
413 | + message: '优惠券不存在' | ||
414 | + }); | ||
415 | + } | ||
416 | + | ||
417 | + return couponModel.getCoupon(uid, couponId) | ||
418 | + .then(data => { | ||
419 | + return res.json(data); | ||
420 | + }) | ||
421 | + .catch(next); | ||
422 | +}; |
@@ -38,13 +38,16 @@ const _getUidFromUserAgent = (req) => { | @@ -38,13 +38,16 @@ const _getUidFromUserAgent = (req) => { | ||
38 | */ | 38 | */ |
39 | const _baseShop = (req, res, shopInfo, shopId) => { | 39 | const _baseShop = (req, res, shopInfo, shopId) => { |
40 | 40 | ||
41 | - listModel.getBaseShopData(req.query, shopInfo).then(result => { | 41 | + listModel.getBaseShopData(Object.assign(req.query, { |
42 | + channel: req.yoho.channel | ||
43 | + }), shopInfo).then(result => { | ||
42 | if (result && result.baseShopHome && result.baseShopHome.banner) { | 44 | if (result && result.baseShopHome && result.baseShopHome.banner) { |
43 | if (result.baseShopHome.banner.indexOf('?') < 0) { | 45 | if (result.baseShopHome.banner.indexOf('?') < 0) { |
44 | result.baseShopHome.banner += '?imageMogr2/auto-orient/strip/thumbnail/x150/crop/640x150'; | 46 | result.baseShopHome.banner += '?imageMogr2/auto-orient/strip/thumbnail/x150/crop/640x150'; |
45 | } | 47 | } |
46 | } | 48 | } |
47 | - res.render('search/goods-list', { | 49 | + |
50 | + res.render('search/goods-list', Object.assign({ | ||
48 | module: 'product', | 51 | module: 'product', |
49 | page: 'search-list', | 52 | page: 'search-list', |
50 | pageHeader: headerModel.setNav({ | 53 | pageHeader: headerModel.setNav({ |
@@ -53,12 +56,9 @@ const _baseShop = (req, res, shopInfo, shopId) => { | @@ -53,12 +56,9 @@ const _baseShop = (req, res, shopInfo, shopId) => { | ||
53 | goodList: result, | 56 | goodList: result, |
54 | showDownloadApp: true, | 57 | showDownloadApp: true, |
55 | pageFooter: true, | 58 | pageFooter: true, |
56 | - title: shopInfo.shop_name + '|' + shopInfo.shop_name + '潮流服装服饰-Yoho!Buy有货', | ||
57 | - keywords: shopInfo.shop_name + ',' + shopInfo.shop_name + '服装服饰,' + shopInfo.shop_name + '潮流服装服饰', | ||
58 | - description: shopInfo.shop_name + '|Yoho!Buy有货' + shopInfo.shop_name + '潮流服饰官方授权店!100%品牌正品保证,支持货到付款。', | ||
59 | shopId: shopId, | 59 | shopId: shopId, |
60 | shopPage: true | 60 | shopPage: true |
61 | - }); | 61 | + }, result.seoResult)); |
62 | }); | 62 | }); |
63 | 63 | ||
64 | }; | 64 | }; |
@@ -142,19 +142,16 @@ const _shop = (req, res, shopId) => { | @@ -142,19 +142,16 @@ const _shop = (req, res, shopId) => { | ||
142 | // 有领券功能,不缓存 | 142 | // 有领券功能,不缓存 |
143 | res.set('Cache-Control', 'no-cache'); | 143 | res.set('Cache-Control', 'no-cache'); |
144 | 144 | ||
145 | - res.render('shop/index', { | 145 | + res.render('shop/index', Object.assign({ |
146 | module: 'product', | 146 | module: 'product', |
147 | page: 'shop', | 147 | page: 'shop', |
148 | shopIndex: result, | 148 | shopIndex: result, |
149 | shopHeadHide: true, | 149 | shopHeadHide: true, |
150 | gender: req.query.gender, | 150 | gender: req.query.gender, |
151 | channel: req.query.channel, | 151 | channel: req.query.channel, |
152 | - title: result.seoTitle + '|' + result.seoTitle + '潮流服装服饰-Yoho!Buy有货', | ||
153 | - keywords: result.seoTitle + ',' + result.seoTitle + '服装服饰,' + result.seoTitle + '潮流服装服饰', | ||
154 | - description: result.seoTitle + '|Yoho!Buy有货' + result.seoTitle + '潮流服饰官方授权店!100%品牌正品保证,支持货到付款。', | ||
155 | shopId: shopId, | 152 | shopId: shopId, |
156 | shopPage: true | 153 | shopPage: true |
157 | - }); | 154 | + }, result.seoResult)); |
158 | 155 | ||
159 | }); | 156 | }); |
160 | } | 157 | } |
@@ -222,7 +219,8 @@ const category = (req, res) => { | @@ -222,7 +219,8 @@ const category = (req, res) => { | ||
222 | }), | 219 | }), |
223 | goodList: params, | 220 | goodList: params, |
224 | showDownloadApp: true, | 221 | showDownloadApp: true, |
225 | - pageFooter: true | 222 | + pageFooter: true, |
223 | + category: true | ||
226 | }); | 224 | }); |
227 | }; | 225 | }; |
228 | 226 | ||
@@ -272,11 +270,13 @@ const brand = (req, res, next) => { | @@ -272,11 +270,13 @@ const brand = (req, res, next) => { | ||
272 | if (req.query.from !== 'search' && brandLogo.type === '2' && brandLogo.shopId) { | 270 | if (req.query.from !== 'search' && brandLogo.type === '2' && brandLogo.shopId) { |
273 | _shop(req, res, brandLogo.shopId); | 271 | _shop(req, res, brandLogo.shopId); |
274 | } else { // 获取品牌店铺信息 | 272 | } else { // 获取品牌店铺信息 |
275 | - listModel.getBrandShops(brandId).then(brandShop => { | 273 | + listModel.getBrandShops(brandId, req).then(brandShop => { |
276 | if (brandId === 0) { | 274 | if (brandId === 0) { |
277 | params.query = domain; | 275 | params.query = domain; |
278 | } | 276 | } |
279 | 277 | ||
278 | + params.seoResult = brandShop.seoResult; | ||
279 | + | ||
280 | // 从搜索页过来的,显示搜索框, 和进入品牌引导信息 或者品牌关联多店铺 | 280 | // 从搜索页过来的,显示搜索框, 和进入品牌引导信息 或者品牌关联多店铺 |
281 | if (req.query.from === 'search' || brandShop.length > 0) { | 281 | if (req.query.from === 'search' || brandShop.length > 0) { |
282 | params = _.assign({ | 282 | params = _.assign({ |
@@ -286,7 +286,7 @@ const brand = (req, res, next) => { | @@ -286,7 +286,7 @@ const brand = (req, res, next) => { | ||
286 | url: helpers.urlFormat('', null, 'search') | 286 | url: helpers.urlFormat('', null, 'search') |
287 | } | 287 | } |
288 | }, params); | 288 | }, params); |
289 | - } else if (brandId !== 0) { // 品牌一览过来的展示品牌介绍和LOGO | 289 | + } else if (brandId && brandId !== 0 && brandId !== '' && brandId !== 'undefined') { // 品牌一览过来的展示品牌介绍和LOGO |
290 | return Promise.all([listModel.getBrandIntro(brandId, uid), listModel.getBrandBanner(brandId)]).then((resData) => { //eslint-disable-line | 290 | return Promise.all([listModel.getBrandIntro(brandId, uid), listModel.getBrandBanner(brandId)]).then((resData) => { //eslint-disable-line |
291 | title = resData[0].title; | 291 | title = resData[0].title; |
292 | delete resData[0].title; | 292 | delete resData[0].title; |
@@ -303,7 +303,7 @@ const brand = (req, res, next) => { | @@ -303,7 +303,7 @@ const brand = (req, res, next) => { | ||
303 | res.set('Cache-Control', 'no-cache'); | 303 | res.set('Cache-Control', 'no-cache'); |
304 | } | 304 | } |
305 | 305 | ||
306 | - res.render('search/goods-list', { | 306 | + res.render('search/goods-list', Object.assign({ |
307 | module: 'product', | 307 | module: 'product', |
308 | page: 'search-list', | 308 | page: 'search-list', |
309 | pageHeader: headerModel.setNav({ | 309 | pageHeader: headerModel.setNav({ |
@@ -312,12 +312,9 @@ const brand = (req, res, next) => { | @@ -312,12 +312,9 @@ const brand = (req, res, next) => { | ||
312 | goodList: params, | 312 | goodList: params, |
313 | showDownloadApp: true, | 313 | showDownloadApp: true, |
314 | pageFooter: true, | 314 | pageFooter: true, |
315 | - title: title + '|' + title + '潮流服装服饰-Yoho!Buy有货', | ||
316 | - keywords: title + ',' + title + '服装服饰,' + title + '潮流服装服饰', | ||
317 | - description: title + '|Yoho!Buy有货' + title + '潮流服饰官方授权店!100%品牌正品保证,支持货到付款。', | ||
318 | domain: req.query.domain, | 315 | domain: req.query.domain, |
319 | shopPage: true | 316 | shopPage: true |
320 | - }); | 317 | + }, params.seoResult)); |
321 | }); | 318 | }); |
322 | } | 319 | } |
323 | }).catch(next); | 320 | }).catch(next); |
@@ -356,7 +353,7 @@ const shopIntro = (req, res, next) => { | @@ -356,7 +353,7 @@ const shopIntro = (req, res, next) => { | ||
356 | let appVersion = req.body.appVersion || false; | 353 | let appVersion = req.body.appVersion || false; |
357 | let params = {}; | 354 | let params = {}; |
358 | 355 | ||
359 | - if (shopId) { | 356 | + if (parseInt(shopId, 10)) { |
360 | listModel.getShopIntro(shopId).then(result => { | 357 | listModel.getShopIntro(shopId).then(result => { |
361 | if (appVersion) { | 358 | if (appVersion) { |
362 | params = { | 359 | params = { |
@@ -480,20 +477,14 @@ const userCoupon = (req, res, next) => { | @@ -480,20 +477,14 @@ const userCoupon = (req, res, next) => { | ||
480 | res.setHeader('Access-Control-Allow-Origin', allowOrigin); | 477 | res.setHeader('Access-Control-Allow-Origin', allowOrigin); |
481 | res.setHeader('Access-Control-Allow-Credentials', 'true'); | 478 | res.setHeader('Access-Control-Allow-Credentials', 'true'); |
482 | 479 | ||
483 | - if (!req.query.couponID) { | 480 | + if (!req.body.couponID) { |
484 | return; | 481 | return; |
485 | } | 482 | } |
486 | 483 | ||
487 | - let cryptCouponId = crypto.decrypt('', req.query.couponID); | ||
488 | - let uid = req.user.uid; | ||
489 | - | ||
490 | - if (req.yoho.isApp !== 'false') { | ||
491 | - uid = req.query.uid ? crypto.decrypt('', req.query.uid) : req.cookies.appUid; | ||
492 | - | ||
493 | - if (!uid || uid === 'undefined') { | ||
494 | - uid = _getUidFromUserAgent(req); | ||
495 | - } | ||
496 | - } | 484 | + let cryptCouponId = crypto.decrypt('', req.body.couponID); |
485 | + let uid = req.body.uid || req.user.uid; | ||
486 | + let isApp = req.body.app_version || req.body.appVersion || false; | ||
487 | + let data = {}; | ||
497 | 488 | ||
498 | cryptCouponId = parseInt(cryptCouponId, 10); | 489 | cryptCouponId = parseInt(cryptCouponId, 10); |
499 | uid = parseInt(uid, 10); | 490 | uid = parseInt(uid, 10); |
@@ -507,32 +498,83 @@ const userCoupon = (req, res, next) => { | @@ -507,32 +498,83 @@ const userCoupon = (req, res, next) => { | ||
507 | return; | 498 | return; |
508 | }).catch(next); | 499 | }).catch(next); |
509 | } else { | 500 | } else { |
501 | + data.code = 4401;// 401错误已经被接口占用 | ||
510 | let refer = req.get('referer'); | 502 | let refer = req.get('referer'); |
503 | + let toUrl = helpers.urlFormat('/signin.html', {refer: refer}); | ||
511 | 504 | ||
512 | - if (req.yoho.isApp !== 'false') { | ||
513 | - let toUrl = refer + '&openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"' + | ||
514 | - refer + | 505 | + if (isApp) { |
506 | + toUrl += '&openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"' + refer + | ||
515 | '","param":{}},"requesturl":{"param":{"method":"app.promotion.getCoupon","couponId":"' + | 507 | '","param":{}},"requesturl":{"param":{"method":"app.promotion.getCoupon","couponId":"' + |
516 | - cryptCouponId + | ||
517 | - '"},"url":"' + | ||
518 | - _.get(global, 'yoho.API.ApiUrl', '') + | ||
519 | - '"},"priority":"Y"}}'; | ||
520 | - | ||
521 | - res.json({ | ||
522 | - code: 4401, | ||
523 | - url: toUrl | ||
524 | - }); | 508 | + cryptCouponId + '"},"url":"' + _.get(global, 'yoho.API.ApiUrl', '') + '"},"priority":"Y"}}'; |
509 | + } | ||
525 | 510 | ||
526 | - } else { | ||
527 | - res.json({ | ||
528 | - code: 4401, | ||
529 | - url: helpers.urlFormat('/signin.html', {refer: refer}) | ||
530 | - }); | 511 | + data.url = toUrl; |
512 | + res.json(data); | ||
513 | + } | ||
514 | +}; | ||
515 | + | ||
516 | +/** | ||
517 | + * 获取店铺优惠券列表 | ||
518 | + * @param req | ||
519 | + * @param res | ||
520 | + * @param next | ||
521 | + */ | ||
522 | +const getShopCouponsList = (req, res, next) => { | ||
523 | + let allowOrigin = _.get(req, 'headers.origin', null) ? | ||
524 | + req.headers.origin : req.protocol + '://' + req.headers.host; | ||
525 | + | ||
526 | + res.setHeader('Access-Control-Allow-Origin', allowOrigin); | ||
527 | + res.setHeader('Access-Control-Allow-Credentials', 'true'); | ||
528 | + | ||
529 | + let uid = req.query.uid || req.user.uid; | ||
530 | + let shopId = parseInt(req.query.shopId, 10); | ||
531 | + let param = {}; | ||
532 | + | ||
533 | + if (shopId) { | ||
534 | + if (uid) { | ||
535 | + param.uid = uid; | ||
531 | } | 536 | } |
532 | 537 | ||
538 | + param.shop_id = shopId; | ||
533 | 539 | ||
540 | + listModel.shopCouponsList(param).then(result => { | ||
541 | + res.json(result); | ||
542 | + }).catch(next); | ||
543 | + } else { | ||
544 | + res.json([]); | ||
534 | } | 545 | } |
546 | +}; | ||
547 | + | ||
548 | +/** | ||
549 | + * 获取品牌优惠券列表 | ||
550 | + * @param req | ||
551 | + * @param res | ||
552 | + * @param next | ||
553 | + */ | ||
554 | +const getBrandCouponsList = (req, res, next) => { | ||
555 | + let allowOrigin = _.get(req, 'headers.origin', null) ? | ||
556 | + req.headers.origin : req.protocol + '://' + req.headers.host; | ||
557 | + | ||
558 | + res.setHeader('Access-Control-Allow-Origin', allowOrigin); | ||
559 | + res.setHeader('Access-Control-Allow-Credentials', 'true'); | ||
560 | + | ||
561 | + let uid = req.query.uid || req.user.uid; | ||
562 | + let brandId = parseInt(req.query.brandId, 10); | ||
563 | + let param = {}; | ||
535 | 564 | ||
565 | + if (brandId) { | ||
566 | + if (uid) { | ||
567 | + param.uid = uid; | ||
568 | + } | ||
569 | + | ||
570 | + param.brand_id = brandId; | ||
571 | + | ||
572 | + listModel.brandCouponsList(param).then(result => { | ||
573 | + res.json(result); | ||
574 | + }).catch(next); | ||
575 | + } else { | ||
576 | + res.json([]); | ||
577 | + } | ||
536 | }; | 578 | }; |
537 | 579 | ||
538 | module.exports = { | 580 | module.exports = { |
@@ -545,5 +587,7 @@ module.exports = { | @@ -545,5 +587,7 @@ module.exports = { | ||
545 | shopFav, | 587 | shopFav, |
546 | baseShopFav, | 588 | baseShopFav, |
547 | shopCategory, | 589 | shopCategory, |
548 | - userCoupon | 590 | + userCoupon, |
591 | + getShopCouponsList, | ||
592 | + getBrandCouponsList | ||
549 | }; | 593 | }; |
@@ -13,6 +13,24 @@ const newModel = require(`${mRoot}/new`); | @@ -13,6 +13,24 @@ const newModel = require(`${mRoot}/new`); | ||
13 | const _ = require('lodash'); | 13 | const _ = require('lodash'); |
14 | const helpers = global.yoho.helpers; | 14 | const helpers = global.yoho.helpers; |
15 | 15 | ||
16 | +// 新品到着(blk) | ||
17 | +const blkNewGoods = (req, res) => { | ||
18 | + let params = Object.assign({ | ||
19 | + isblknew: true | ||
20 | + }, req.query); | ||
21 | + | ||
22 | + res.render('search/goods-list', { | ||
23 | + module: 'product', | ||
24 | + page: 'search-list', | ||
25 | + pageHeader: headerModel.setNav({ | ||
26 | + navTitle: req.query.title || req.query.sort_name || '新品抢先看' | ||
27 | + }), | ||
28 | + goodList: params, | ||
29 | + showDownloadApp: true, | ||
30 | + pageFooter: true | ||
31 | + }); | ||
32 | +}; | ||
33 | + | ||
16 | // 新品到着 | 34 | // 新品到着 |
17 | const newGoods = (req, res, next) => { | 35 | const newGoods = (req, res, next) => { |
18 | let channel = req.cookies._Channel; | 36 | let channel = req.cookies._Channel; |
@@ -45,10 +63,15 @@ const selectNewSale = (req, res, next) => { | @@ -45,10 +63,15 @@ const selectNewSale = (req, res, next) => { | ||
45 | let params = _.assign({}, req.query); | 63 | let params = _.assign({}, req.query); |
46 | 64 | ||
47 | newModel.getSearchData(params).then((result) => { | 65 | newModel.getSearchData(params).then((result) => { |
48 | - res.render('search/page', { | ||
49 | - layout: false, | ||
50 | - new: result | ||
51 | - }); | 66 | + if (result.list.length > 0) { |
67 | + res.render('search/page', { | ||
68 | + layout: false, | ||
69 | + new: result.list, | ||
70 | + total: result.total | ||
71 | + }); | ||
72 | + } else { | ||
73 | + res.json(result); | ||
74 | + } | ||
52 | }).catch(next); | 75 | }).catch(next); |
53 | }; | 76 | }; |
54 | 77 | ||
@@ -72,6 +95,7 @@ let filter = (req, res, next) => { | @@ -72,6 +95,7 @@ let filter = (req, res, next) => { | ||
72 | 95 | ||
73 | 96 | ||
74 | module.exports = { | 97 | module.exports = { |
98 | + blkNewGoods, | ||
75 | newGoods, | 99 | newGoods, |
76 | selectNewSale, | 100 | selectNewSale, |
77 | filter | 101 | filter |
@@ -25,7 +25,7 @@ const willStartActivity = { | @@ -25,7 +25,7 @@ const willStartActivity = { | ||
25 | // 奥莱首页控制器 | 25 | // 奥莱首页控制器 |
26 | exports.index = (req, res, next) => { | 26 | exports.index = (req, res, next) => { |
27 | let headerData = headerModel.setNav({ | 27 | let headerData = headerModel.setNav({ |
28 | - navTitle: 'OUTLET', | 28 | + navTitle: '奥莱', |
29 | navBtn: false | 29 | navBtn: false |
30 | }); | 30 | }); |
31 | 31 | ||
@@ -35,7 +35,8 @@ exports.index = (req, res, next) => { | @@ -35,7 +35,8 @@ exports.index = (req, res, next) => { | ||
35 | 35 | ||
36 | outletModel.getContent(categoryId, yhChannel, contentcode).then(result => { | 36 | outletModel.getContent(categoryId, yhChannel, contentcode).then(result => { |
37 | res.render('outlet', Object.assign({ | 37 | res.render('outlet', Object.assign({ |
38 | - pageHeader: headerData | 38 | + pageHeader: headerData, |
39 | + title: '奥莱 | Yoho!Buy有货 | 潮流购物逛不停', | ||
39 | }, result)); | 40 | }, result)); |
40 | }).catch(next); | 41 | }).catch(next); |
41 | }; | 42 | }; |
@@ -66,7 +67,7 @@ exports.activityTime = (req, res, next) => { | @@ -66,7 +67,7 @@ exports.activityTime = (req, res, next) => { | ||
66 | // 奥莱活动频道列表页 | 67 | // 奥莱活动频道列表页 |
67 | exports.activityList = (req, res, next) => { | 68 | exports.activityList = (req, res, next) => { |
68 | let headerData = headerModel.setNav({ | 69 | let headerData = headerModel.setNav({ |
69 | - navTitle: 'OUTLET', | 70 | + navTitle: '奥莱', |
70 | navBtn: false | 71 | navBtn: false |
71 | }); | 72 | }); |
72 | 73 |
@@ -35,7 +35,7 @@ exports.cart = (req, res, next) => { | @@ -35,7 +35,7 @@ exports.cart = (req, res, next) => { | ||
35 | yhChannel = req.query.yh_channel || '1', | 35 | yhChannel = req.query.yh_channel || '1', |
36 | limit = 30; | 36 | limit = 30; |
37 | if (_.get(req, 'app.locals.wap.cart.removePrefer', false)) { | 37 | if (_.get(req, 'app.locals.wap.cart.removePrefer', false)) { |
38 | - return res.send(''); | 38 | + return res.send(''); |
39 | } | 39 | } |
40 | recommendForYouModel.getPreference({ | 40 | recommendForYouModel.getPreference({ |
41 | yh_channel: yhChannel, | 41 | yh_channel: yhChannel, |
@@ -55,5 +55,5 @@ exports.cart = (req, res, next) => { | @@ -55,5 +55,5 @@ exports.cart = (req, res, next) => { | ||
55 | page: 'recommend' | 55 | page: 'recommend' |
56 | }); | 56 | }); |
57 | }).catch(next); | 57 | }).catch(next); |
58 | - | 58 | + |
59 | }; | 59 | }; |
@@ -184,10 +184,16 @@ const search = (req, res, next) => { | @@ -184,10 +184,16 @@ const search = (req, res, next) => { | ||
184 | 184 | ||
185 | params.isApp = req.yoho.isApp; | 185 | params.isApp = req.yoho.isApp; |
186 | searchModel.getSearchData(params).then((result) => { | 186 | searchModel.getSearchData(params).then((result) => { |
187 | - res.render('search/page', { | ||
188 | - layout: false, | ||
189 | - new: result | ||
190 | - }); | 187 | + if (result.list && result.list.length > 0) { |
188 | + res.render('search/page', { | ||
189 | + layout: false, | ||
190 | + new: result.list, | ||
191 | + total: result.total | ||
192 | + }); | ||
193 | + } else { | ||
194 | + res.json(result); | ||
195 | + } | ||
196 | + | ||
191 | }).catch(next); | 197 | }).catch(next); |
192 | }; | 198 | }; |
193 | 199 |
@@ -64,12 +64,13 @@ const _formatConsultsList = (data) => { | @@ -64,12 +64,13 @@ const _formatConsultsList = (data) => { | ||
64 | * @limit {[number]} 每页咨询数量 | 64 | * @limit {[number]} 每页咨询数量 |
65 | * @return {[object]} | 65 | * @return {[object]} |
66 | */ | 66 | */ |
67 | -const getConsults = (id, page, limit) => { | 67 | +const getConsults = (id, page, limit, uid) => { |
68 | let params = { | 68 | let params = { |
69 | method: 'app.consult.li', | 69 | method: 'app.consult.li', |
70 | product_id: id, | 70 | product_id: id, |
71 | page: page ? page : 1, | 71 | page: page ? page : 1, |
72 | - limit: limit ? limit : 300 | 72 | + limit: limit ? limit : 300, |
73 | + uid | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | return api.get('', params, { | 76 | return api.get('', params, { |
@@ -146,7 +147,7 @@ let comments = (params) => { | @@ -146,7 +147,7 @@ let comments = (params) => { | ||
146 | 147 | ||
147 | if (result.comments && result.comments.length) { | 148 | if (result.comments && result.comments.length) { |
148 | if (result.commentsNum) { | 149 | if (result.commentsNum) { |
149 | - _.set(data, 'pageHeader.navTitle', `购买评价(${result.commentsNum})`); | 150 | + _.set(data, 'navTitle', `购买评价(${result.commentsNum})`); |
150 | } | 151 | } |
151 | data.comments = result.comments; | 152 | data.comments = result.comments; |
152 | } | 153 | } |
@@ -160,10 +161,10 @@ let comments = (params) => { | @@ -160,10 +161,10 @@ let comments = (params) => { | ||
160 | * @params {[object]} 查询参数 | 161 | * @params {[object]} 查询参数 |
161 | * @return {[object]} | 162 | * @return {[object]} |
162 | */ | 163 | */ |
163 | -let consults = (params) => { | 164 | +let consults = (params, uid) => { |
164 | return api.all([ | 165 | return api.all([ |
165 | _getCommonConsult(), | 166 | _getCommonConsult(), |
166 | - getConsults(params.product_id, 1, 60) | 167 | + getConsults(params.product_id, 1, 60, uid) |
167 | ]).then(result => { | 168 | ]).then(result => { |
168 | let data = { | 169 | let data = { |
169 | link: `/product/detail/consultform?product_id=${params.product_id}` | 170 | link: `/product/detail/consultform?product_id=${params.product_id}` |
@@ -173,7 +174,7 @@ let consults = (params) => { | @@ -173,7 +174,7 @@ let consults = (params) => { | ||
173 | 174 | ||
174 | if (result[1].list && result[1].list.length) { | 175 | if (result[1].list && result[1].list.length) { |
175 | if (result[1].total) { | 176 | if (result[1].total) { |
176 | - _.set(data, 'pageHeader.navTitle', `购买咨询(${result[1].total})`); | 177 | + _.set(data, 'navTitle', `购买咨询(${result[1].total})`); |
177 | } | 178 | } |
178 | data.consults = result[1].list; | 179 | data.consults = result[1].list; |
179 | } | 180 | } |
@@ -217,9 +218,9 @@ let addConsult = (uid, productId, content) => { | @@ -217,9 +218,9 @@ let addConsult = (uid, productId, content) => { | ||
217 | 218 | ||
218 | module.exports = { | 219 | module.exports = { |
219 | getCommentInfo, // 商品详情相关,获取评价,来自晒单 | 220 | getCommentInfo, // 商品详情相关,获取评价,来自晒单 |
220 | - comments, // 商品详情相关-购买评价 | ||
221 | - consults, // 商品详情相关-购买咨询 | ||
222 | - addConsult, // 商品详情相关-添加咨询 | 221 | + comments, // 商品详情相关-购买评价 |
222 | + consults, // 商品详情相关-购买咨询 | ||
223 | + addConsult, // 商品详情相关-添加咨询 | ||
223 | upvoteConsult, // 咨询点赞 | 224 | upvoteConsult, // 咨询点赞 |
224 | getConsults // 获取咨询 | 225 | getConsults // 获取咨询 |
225 | }; | 226 | }; |
apps/product/models/coupon.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +const api = global.yoho.API; | ||
4 | + | ||
5 | +/** | ||
6 | + * [查询商品详情页优惠券] | ||
7 | + * doc: http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/促销/product_detail_page_coupon.md | ||
8 | + */ | ||
9 | +exports.queryProdPageCoupons = (uid, skn, brandId) => { | ||
10 | + const param = { | ||
11 | + method: 'app.coupons.queryProdPageCoupons', | ||
12 | + uid, | ||
13 | + skn, | ||
14 | + brandId | ||
15 | + }; | ||
16 | + | ||
17 | + return api.get('', param, {cache: true}); | ||
18 | +}; | ||
19 | + | ||
20 | +/** | ||
21 | + * [用户领券] | ||
22 | + * doc: http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/促销/promotion.md | ||
23 | + */ | ||
24 | +exports.getCoupon = (uid, couponId) => { | ||
25 | + const param = { | ||
26 | + method: 'app.promotion.getCoupon', | ||
27 | + uid, | ||
28 | + couponId | ||
29 | + }; | ||
30 | + | ||
31 | + return api.post('', param); | ||
32 | +}; |
@@ -1251,8 +1251,10 @@ const _detailDataPkg = (origin, ua) => { | @@ -1251,8 +1251,10 @@ const _detailDataPkg = (origin, ua) => { | ||
1251 | 1251 | ||
1252 | dest.preferenceUrl = `/product/detail/preference${extra}`; | 1252 | dest.preferenceUrl = `/product/detail/preference${extra}`; |
1253 | } | 1253 | } |
1254 | + dest.brandId = origin.brand_id || 0; | ||
1254 | 1255 | ||
1255 | dest.productSkn = origin.product_skn; | 1256 | dest.productSkn = origin.product_skn; |
1257 | + dest.isLimitBuy = Number(origin.isLimitBuy); // 1 限购商品, 0 非限购商品 | ||
1256 | 1258 | ||
1257 | // 商品信息 | 1259 | // 商品信息 |
1258 | if (origin.goods_list.length) { | 1260 | if (origin.goods_list.length) { |
@@ -1267,7 +1269,7 @@ const _detailDataPkg = (origin, ua) => { | @@ -1267,7 +1269,7 @@ const _detailDataPkg = (origin, ua) => { | ||
1267 | // colorStorageNum = 0; | 1269 | // colorStorageNum = 0; |
1268 | // pagecache重构 | 1270 | // pagecache重构 |
1269 | _.forEach(origin.goods_list, function(value) { | 1271 | _.forEach(origin.goods_list, function(value) { |
1270 | - //未上架也显示 | 1272 | + // 未上架也显示 |
1271 | // if (value.status === 0 && !origin.isLimitBuy) { | 1273 | // if (value.status === 0 && !origin.isLimitBuy) { |
1272 | // return; | 1274 | // return; |
1273 | // } | 1275 | // } |
@@ -1468,7 +1470,15 @@ const _detailDataPkg = (origin, ua) => { | @@ -1468,7 +1470,15 @@ const _detailDataPkg = (origin, ua) => { | ||
1468 | dest.introUrl = '/product/detail/intro/' + origin.product_skn; | 1470 | dest.introUrl = '/product/detail/intro/' + origin.product_skn; |
1469 | dest.id = origin.product_id; | 1471 | dest.id = origin.product_id; |
1470 | dest.goodsId = origin.goods_id; | 1472 | dest.goodsId = origin.goods_id; |
1473 | + dest.isDepositAdvance = origin.is_deposit_advance === 'Y'; // 是否定金预售 | ||
1474 | + dest.isSeckill = origin.is_secKill === 'Y'; // 是否秒杀 | ||
1475 | + dest.isLimitBuy = origin.isLimitBuy; // 是否 限购 | ||
1476 | + dest.isPresale = Boolean(origin.expect_arrival_time); // 是否普通预售 | ||
1471 | 1477 | ||
1478 | + // 自定义 属性 | ||
1479 | + dest.showCoupon = !( | ||
1480 | + dest.isDepositAdvance || dest.isSeckill || dest.isLimitBuy || dest.isPresale | ||
1481 | + ); // 商品有限购、秒杀、定金预售、普通预售 不显示领券 | ||
1472 | 1482 | ||
1473 | 1483 | ||
1474 | return dest; | 1484 | return dest; |
@@ -1520,7 +1530,7 @@ let getProductAsyncData = (data) => { | @@ -1520,7 +1530,7 @@ let getProductAsyncData = (data) => { | ||
1520 | finalResult.isStudent = data.isStudent; | 1530 | finalResult.isStudent = data.isStudent; |
1521 | return finalResult; | 1531 | return finalResult; |
1522 | }); | 1532 | }); |
1523 | - | 1533 | + |
1524 | }); | 1534 | }); |
1525 | 1535 | ||
1526 | }); | 1536 | }); |
@@ -1584,7 +1594,8 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | @@ -1584,7 +1594,8 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | ||
1584 | } | 1594 | } |
1585 | 1595 | ||
1586 | if (origin.is_secKill) { | 1596 | if (origin.is_secKill) { |
1587 | - dest.isDepositAdvance = origin.is_deposit_advance;// 判断定金预售字段 | 1597 | + dest.isDepositAdvance = origin.isDeposit_advance;// A定金预售字段 = origin.is_deposit_advance === 'Y'; // 是否定金预售 |
1598 | + dest.isPresale = Boolean(origin.expect_arrival_time) | ||
1588 | } | 1599 | } |
1589 | 1600 | ||
1590 | // 商品返回 YOHO 币 | 1601 | // 商品返回 YOHO 币 |
@@ -1624,7 +1635,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | @@ -1624,7 +1635,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | ||
1624 | colorStorageNum = 0; | 1635 | colorStorageNum = 0; |
1625 | 1636 | ||
1626 | _.forEach(origin.goods_list, function(value) { | 1637 | _.forEach(origin.goods_list, function(value) { |
1627 | - //未上架也显示 | 1638 | + // 未上架也显示 |
1628 | // if (value.status === 0) { | 1639 | // if (value.status === 0) { |
1629 | // return; | 1640 | // return; |
1630 | // } | 1641 | // } |
@@ -1743,6 +1754,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | @@ -1743,6 +1754,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | ||
1743 | } | 1754 | } |
1744 | let soldOut = (origin.storage_sum === 0) || (totalStorageNum === 0); // status | 1755 | let soldOut = (origin.storage_sum === 0) || (totalStorageNum === 0); // status |
1745 | let notForSale = origin.attribute === 2; | 1756 | let notForSale = origin.attribute === 2; |
1757 | + let preSale = (origin.status === 0 && origin.advance_shelve_time > 0); | ||
1746 | 1758 | ||
1747 | // 悬浮的购物车信息 | 1759 | // 悬浮的购物车信息 |
1748 | dest.cartInfo = { | 1760 | dest.cartInfo = { |
@@ -1752,7 +1764,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | @@ -1752,7 +1764,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | ||
1752 | }; | 1764 | }; |
1753 | 1765 | ||
1754 | // 显示加入购物车链接 | 1766 | // 显示加入购物车链接 |
1755 | - if (!soldOut && !notForSale || origin.isLimitBuy) { | 1767 | + if (!soldOut && !notForSale && !preSale || origin.isLimitBuy) { |
1756 | _.orderBy(colorGroup); | 1768 | _.orderBy(colorGroup); |
1757 | Object.assign(dest.cartInfo, { | 1769 | Object.assign(dest.cartInfo, { |
1758 | productId: origin.product_id, | 1770 | productId: origin.product_id, |
@@ -1807,12 +1819,15 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | @@ -1807,12 +1819,15 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => { | ||
1807 | origin.goods_id + '.html'); | 1819 | origin.goods_id + '.html'); |
1808 | return callback(); | 1820 | return callback(); |
1809 | } | 1821 | } |
1810 | - } else if (notForSale) { | 1822 | + } else if (notForSale && !preSale) { |
1811 | dest.cartInfo.notForSale = true; | 1823 | dest.cartInfo.notForSale = true; |
1812 | return callback(); | 1824 | return callback(); |
1813 | - } else if (soldOut) { | 1825 | + } else if (soldOut && !preSale) { |
1814 | dest.cartInfo.soldOut = true; | 1826 | dest.cartInfo.soldOut = true; |
1815 | return callback(); | 1827 | return callback(); |
1828 | + } else if (preSale) { | ||
1829 | + dest.cartInfo.preSale = true; | ||
1830 | + return callback(); | ||
1816 | } | 1831 | } |
1817 | 1832 | ||
1818 | // 是否收藏 使用单独收藏接口获取 | 1833 | // 是否收藏 使用单独收藏接口获取 |
-
Please register or login to post a comment