Authored by 周少峰

Merge branch 'release/6.1' into gray

Conflicts:
	apps/passport/models/login-service.js
	config/common.js
Showing 44 changed files with 2969 additions and 118 deletions
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 6
7 'use strict'; 7 'use strict';
8 8
  9 +const _ = require('lodash');
9 const crypto = global.yoho.crypto; 10 const crypto = global.yoho.crypto;
10 const logger = global.yoho.logger; 11 const logger = global.yoho.logger;
11 12
@@ -58,6 +59,17 @@ const convertCoupons = (req, res, next) => { @@ -58,6 +59,17 @@ const convertCoupons = (req, res, next) => {
58 }).catch(next); 59 }).catch(next);
59 }; 60 };
60 61
  62 +// 获取礼品卡列表
  63 +const getGiftCards = (req, res, next) => {
  64 + req.ctx(oeModel).getGiftCards(req.user.uid).then(data => {
  65 + if (data.data) {
  66 + data.data.userMobile = req.user.mobile;
  67 + }
  68 +
  69 + res.send(data);
  70 + }).catch(next);
  71 +};
  72 +
61 // 订单金额计算 73 // 订单金额计算
62 const compute = (req, res, next) => { 74 const compute = (req, res, next) => {
63 let params = req.body; 75 let params = req.body;
@@ -72,9 +84,39 @@ const compute = (req, res, next) => { @@ -72,9 +84,39 @@ const compute = (req, res, next) => {
72 res.send(data); 84 res.send(data);
73 }).catch(next); 85 }).catch(next);
74 } 86 }
  87 +};
75 88
  89 +// 发送虚拟资产使用校验短信(目前仅有礼品卡 --- giftCard)
  90 +const sendCheckSms = (req, res, next) => {
  91 + let params = req.body;
76 92
  93 + if (params.giftCard) {
  94 + return req.ctx(oeModel).sendGiftCardCkeckSms(req.user.uid, req.yoho.udid).then(result => {
  95 + res.json(result);
  96 + }).catch(next);
  97 + }
77 98
  99 + return next();
  100 +};
  101 +
  102 +// 订单提交前置校验
  103 +const submitCheck = (req, res, next) => {
  104 + let checkCode = req.body.checkCode;
  105 +
  106 + // 带礼品卡号和短信验证码,则校验短信验证码,否则删除使用礼品卡
  107 + if (req.body.giftCard && checkCode) {
  108 + return req.ctx(oeModel).checkGiftCardSmsCode(req.user.uid, checkCode, req.yoho.udid).then(result => {
  109 + if (result.code === 200) {
  110 + return next();
  111 + }
  112 +
  113 + res.json(result);
  114 + }).catch(next);
  115 + } else {
  116 + _.unset(req.body, 'giftCard');
  117 + }
  118 +
  119 + return next();
78 }; 120 };
79 121
80 // 提交订单 122 // 提交订单
@@ -150,7 +192,16 @@ const submit = (req, res, next) => { @@ -150,7 +192,16 @@ const submit = (req, res, next) => {
150 userAgent: userAgent 192 userAgent: userAgent
151 }); 193 });
152 194
153 - params.udid = req.cookies._yasvd || 'yoho_pc'; 195 + params.udid = req.yoho.udid;
  196 +
  197 + // 5.8.1 发票优化需求
  198 + // 只接受电子发票(1 纸质 2 电子),发票内容为明细(id 12:明细)
  199 + if (params.invoicesType) {
  200 + Object.assign(params, {
  201 + invoicesType: 2,
  202 + invoicesContent: 12
  203 + });
  204 + }
154 205
155 if (params.sku) { // 快捷结算 206 if (params.sku) { // 快捷结算
156 req.ctx(easypayModel).easypayOrderSubmit(uid, 'ordinary', params, remoteIp).then(result => { 207 req.ctx(easypayModel).easypayOrderSubmit(uid, 'ordinary', params, remoteIp).then(result => {
@@ -173,6 +224,9 @@ module.exports = { @@ -173,6 +224,9 @@ module.exports = {
173 index, 224 index,
174 getCoupons, 225 getCoupons,
175 convertCoupons, 226 convertCoupons,
  227 + getGiftCards,
176 compute, 228 compute,
  229 + sendCheckSms,
  230 + submitCheck,
177 submit 231 submit
178 }; 232 };
@@ -39,10 +39,11 @@ const ticketEnsure = (req, res, next) => { @@ -39,10 +39,11 @@ const ticketEnsure = (req, res, next) => {
39 39
40 const ticketSubmit = (req, res, next) => { 40 const ticketSubmit = (req, res, next) => {
41 let uid = req.user.uid; 41 let uid = req.user.uid;
42 - let sku = req.body.sku || 0;  
43 - let count = req.body.count || 0;  
44 - let mobile = req.body.mobile || 0;  
45 - let yohoCoin = req.body.coin || 0; 42 + let params = req.body;
  43 + let sku = params.sku || 0;
  44 + let count = params.count || 0;
  45 + let mobile = params.mobile || 0;
  46 + let yohoCoin = params.coin || 0;
46 47
47 if (!sku || !count || !mobile) { 48 if (!sku || !count || !mobile) {
48 return res.json({ 49 return res.json({
@@ -51,7 +52,9 @@ const ticketSubmit = (req, res, next) => { @@ -51,7 +52,9 @@ const ticketSubmit = (req, res, next) => {
51 }); 52 });
52 } 53 }
53 54
54 - req.ctx(ticketService).submitTicket(uid, sku, count, mobile, yohoCoin).then(result => { 55 + params.udid = req.yoho.udid;
  56 +
  57 + req.ctx(ticketService).submitTicket(uid, sku, count, mobile, yohoCoin, params).then(result => {
55 return res.json(result); 58 return res.json(result);
56 }).catch(next); 59 }).catch(next);
57 }; 60 };
@@ -62,7 +65,7 @@ const ticketCompute = (req, res, next) => { @@ -62,7 +65,7 @@ const ticketCompute = (req, res, next) => {
62 let buyNumber = req.body.count || 0; 65 let buyNumber = req.body.count || 0;
63 let yohoCoin = req.body.coin || 0; 66 let yohoCoin = req.body.coin || 0;
64 67
65 - req.ctx(ticketService).addTicket(uid, sku, buyNumber, yohoCoin).then(result => { 68 + req.ctx(ticketService).addTicket(uid, sku, buyNumber, yohoCoin, req.body).then(result => {
66 if (_.isEmpty(result)) { 69 if (_.isEmpty(result)) {
67 return res.json({ 70 return res.json({
68 code: 401, 71 code: 401,
1 /** 1 /**
2 - * address api 2 + * easypay api
3 * @author: yyq<yanqing.yang@yoho.cn> 3 * @author: yyq<yanqing.yang@yoho.cn>
4 * @date: 2016/11/04 4 * @date: 2016/11/04
5 */ 5 */
@@ -68,6 +68,12 @@ module.exports = class extends global.yoho.BaseModel { @@ -68,6 +68,12 @@ module.exports = class extends global.yoho.BaseModel {
68 }); 68 });
69 } 69 }
70 70
  71 + if (other.giftCard) {
  72 + Object.assign(param, {
  73 + gift_card_code: other.giftCard
  74 + });
  75 + }
  76 +
71 if (other.promotionCode) { 77 if (other.promotionCode) {
72 Object.assign(param, { 78 Object.assign(param, {
73 promotion_code: other.promotionCode 79 promotion_code: other.promotionCode
@@ -153,6 +159,20 @@ module.exports = class extends global.yoho.BaseModel { @@ -153,6 +159,20 @@ module.exports = class extends global.yoho.BaseModel {
153 }); 159 });
154 } 160 }
155 161
  162 + // 礼品卡
  163 + if (other.giftCard) {
  164 + Object.assign(param, {
  165 + gift_card_code: other.giftCard
  166 + });
  167 + }
  168 +
  169 + // 优惠码
  170 + if (other.promotionCode) {
  171 + Object.assign(param, {
  172 + promotion_code: other.promotionCode
  173 + });
  174 + }
  175 +
156 // 优惠券码 176 // 优惠券码
157 if (other.couponCode) { 177 if (other.couponCode) {
158 Object.assign(param, { 178 Object.assign(param, {
@@ -70,6 +70,17 @@ module.exports = class extends global.yoho.BaseModel { @@ -70,6 +70,17 @@ module.exports = class extends global.yoho.BaseModel {
70 } 70 }
71 71
72 /** 72 /**
  73 + * 获取用户可用礼品卡信息API
  74 + * @param uid [number] uid
  75 + */
  76 + getGiftCardAsync(uid) {
  77 + return this.get({data: {
  78 + method: 'app.Shopping.listGiftCard',
  79 + uid: uid
  80 + }});
  81 + }
  82 +
  83 + /**
73 * 订单计算API 84 * 订单计算API
74 * @param uid [number] uid 85 * @param uid [number] uid
75 * @param cartType [string] 购物车类型,ordinary表示普通, advance表示预售 86 * @param cartType [string] 购物车类型,ordinary表示普通, advance表示预售
@@ -103,6 +114,12 @@ module.exports = class extends global.yoho.BaseModel { @@ -103,6 +114,12 @@ module.exports = class extends global.yoho.BaseModel {
103 }); 114 });
104 } 115 }
105 116
  117 + if (other.giftCard) {
  118 + Object.assign(param, {
  119 + gift_card_code: other.giftCard
  120 + });
  121 + }
  122 +
106 if (other.couponCode) { 123 if (other.couponCode) {
107 Object.assign(param, { 124 Object.assign(param, {
108 coupon_code: other.couponCode 125 coupon_code: other.couponCode
@@ -118,6 +135,31 @@ module.exports = class extends global.yoho.BaseModel { @@ -118,6 +135,31 @@ module.exports = class extends global.yoho.BaseModel {
118 } 135 }
119 136
120 /** 137 /**
  138 + * 发送礼品卡使用校验短信API
  139 + * @param uid [number] uid
  140 + */
  141 + sendGiftCardCkeckSmsAsync(uid, udid) {
  142 + return this.get({data: {
  143 + method: 'app.giftcard.sendSms',
  144 + uid: uid,
  145 + udid: udid
  146 + }});
  147 + }
  148 +
  149 + /**
  150 + * 校验礼品卡使用短信验证码API
  151 + * @param code [number] code
  152 + */
  153 + checkGiftCardSmsCodeAsync(uid, code, udid) {
  154 + return this.get({data: {
  155 + method: 'app.giftcard.validRegCode',
  156 + uid: uid,
  157 + code: code,
  158 + udid: udid
  159 + }});
  160 + }
  161 +
  162 + /**
121 * 订单提交API 163 * 订单提交API
122 * @param uid [number] uid 164 * @param uid [number] uid
123 * @param cartType [String] 购物车类型,ordinary表示普通, advance表示预售 165 * @param cartType [String] 购物车类型,ordinary表示普通, advance表示预售
@@ -176,6 +218,13 @@ module.exports = class extends global.yoho.BaseModel { @@ -176,6 +218,13 @@ module.exports = class extends global.yoho.BaseModel {
176 }); 218 });
177 } 219 }
178 220
  221 + // 礼品卡
  222 + if (other.giftCard) {
  223 + Object.assign(param, {
  224 + gift_card_code: other.giftCard
  225 + });
  226 + }
  227 +
179 // 备注 228 // 备注
180 if (other.remark) { 229 if (other.remark) {
181 Object.assign(param, { 230 Object.assign(param, {
@@ -221,4 +270,3 @@ module.exports = class extends global.yoho.BaseModel { @@ -221,4 +270,3 @@ module.exports = class extends global.yoho.BaseModel {
221 }}); 270 }});
222 } 271 }
223 }; 272 };
224 -  
@@ -83,21 +83,35 @@ module.exports = class extends global.yoho.BaseModel { @@ -83,21 +83,35 @@ module.exports = class extends global.yoho.BaseModel {
83 }); 83 });
84 } 84 }
85 85
  86 + // 获取礼品卡列表
  87 + getGiftCards(uid) {
  88 + return new EnsureApi(this.ctx).getGiftCardAsync(uid).then(result => {
  89 + if (!_.isEmpty(_.get(result, 'data.usable_giftCards', []))) {
  90 + _.map(result.data.usable_giftCards, value => {
  91 + return Object.assign(value, {price: _.replace(value.remainAmount, /[^(0-9.)]/ig, '')});
  92 + });
  93 + }
  94 +
  95 + return result;
  96 + });
  97 + }
  98 +
  99 + // 发送礼品卡使用校验短信
  100 + sendGiftCardCkeckSms(uid, udid) {
  101 + return new EnsureApi(this.ctx).sendGiftCardCkeckSmsAsync(uid, udid);
  102 + }
  103 +
  104 + // 校验礼品卡使用短信验证码
  105 + checkGiftCardSmsCode(uid, code, udid) {
  106 + return new EnsureApi(this.ctx).checkGiftCardSmsCodeAsync(uid, code, udid);
  107 + }
  108 +
86 // 订单提交 109 // 订单提交
87 submit(uid, cartType, p, remoteIp) { 110 submit(uid, cartType, p, remoteIp) {
88 if (p.addressId) { 111 if (p.addressId) {
89 p.addressId = crypto.decrypt('', `${p.addressId}`); 112 p.addressId = crypto.decrypt('', `${p.addressId}`);
90 } 113 }
91 114
92 - // 5.8.1 发票优化需求  
93 - // 只接受电子发票(1 纸质 2 电子),发票内容为明细(id 12:明细)  
94 - if (p.invoicesType) {  
95 - Object.assign(p, {  
96 - invoicesType: 2,  
97 - invoicesContent: 12  
98 - });  
99 - }  
100 -  
101 return new EnsureApi(this.ctx).orderSubmitAsync(uid, cartType, p.addressId, p.deliveryTime, 115 return new EnsureApi(this.ctx).orderSubmitAsync(uid, cartType, p.addressId, p.deliveryTime,
102 p.deliveryWay, p.paymentType, p.paymentId, p.printPrice, p, remoteIp).then(result => { 116 p.deliveryWay, p.paymentType, p.paymentId, p.printPrice, p, remoteIp).then(result => {
103 if (result.code === 200) { 117 if (result.code === 200) {
@@ -15,7 +15,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -15,7 +15,7 @@ module.exports = class extends global.yoho.BaseModel {
15 * @param mobile 手机号码 15 * @param mobile 手机号码
16 * @param yohoCoin 有货币 16 * @param yohoCoin 有货币
17 */ 17 */
18 - submit(uid, sku, count, mobile, yohoCoin) { 18 + submit(uid, sku, count, mobile, yohoCoin, other = {}) {
19 let params = { 19 let params = {
20 method: 'app.shopping.submitTicket', 20 method: 'app.shopping.submitTicket',
21 uid, 21 uid,
@@ -28,6 +28,18 @@ module.exports = class extends global.yoho.BaseModel { @@ -28,6 +28,18 @@ module.exports = class extends global.yoho.BaseModel {
28 params.use_yoho_coin = yohoCoin / 100; 28 params.use_yoho_coin = yohoCoin / 100;
29 } 29 }
30 30
  31 + if (other.giftCard) {
  32 + Object.assign(params, {
  33 + gift_card_code: other.giftCard
  34 + });
  35 + }
  36 +
  37 + if (other.udid) {
  38 + Object.assign(params, {
  39 + udid: other.udid
  40 + });
  41 + }
  42 +
31 return this.get({data: params}); 43 return this.get({data: params});
32 } 44 }
33 45
@@ -38,7 +50,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -38,7 +50,7 @@ module.exports = class extends global.yoho.BaseModel {
38 * @param count 购买数量 1-4 50 * @param count 购买数量 1-4
39 * @param yohoCoin 有货币 51 * @param yohoCoin 有货币
40 */ 52 */
41 - add(uid, sku, count, yohoCoin) { 53 + add(uid, sku, count, yohoCoin, other = {}) {
42 let params = { 54 let params = {
43 method: 'app.shopping.ticket', 55 method: 'app.shopping.ticket',
44 uid, 56 uid,
@@ -50,6 +62,12 @@ module.exports = class extends global.yoho.BaseModel { @@ -50,6 +62,12 @@ module.exports = class extends global.yoho.BaseModel {
50 params.use_yoho_coin = yohoCoin / 100; 62 params.use_yoho_coin = yohoCoin / 100;
51 } 63 }
52 64
  65 + if (other.giftCard) {
  66 + Object.assign(params, {
  67 + gift_card_code: other.giftCard
  68 + });
  69 + }
  70 +
53 return this.get({data: params}); 71 return this.get({data: params});
54 } 72 }
55 }; 73 };
@@ -24,8 +24,8 @@ module.exports = class extends global.yoho.BaseModel { @@ -24,8 +24,8 @@ module.exports = class extends global.yoho.BaseModel {
24 return _.get(info, 'data.shopping_cart_data.last_order_amount', 0); 24 return _.get(info, 'data.shopping_cart_data.last_order_amount', 0);
25 } 25 }
26 26
27 - addTicket(uid, sku, count, yohoCoin) {  
28 - return new TicketApi(this.ctx).add(uid, sku, count, yohoCoin).then(ticketInfo => { 27 + addTicket(uid, sku, count, yohoCoin, other) {
  28 + return new TicketApi(this.ctx).add(uid, sku, count, yohoCoin, other).then(ticketInfo => {
29 let result = {}; 29 let result = {};
30 30
31 if (_.isEmpty(ticketInfo)) { 31 if (_.isEmpty(ticketInfo)) {
@@ -54,8 +54,8 @@ module.exports = class extends global.yoho.BaseModel { @@ -54,8 +54,8 @@ module.exports = class extends global.yoho.BaseModel {
54 }); 54 });
55 } 55 }
56 56
57 - submitTicket(uid, sku, count, mobile, yohoCoin) {  
58 - return new TicketApi(this.ctx).submit(uid, sku, count, mobile, yohoCoin).then(result => { 57 + submitTicket(uid, sku, count, mobile, yohoCoin, other) {
  58 + return new TicketApi(this.ctx).submit(uid, sku, count, mobile, yohoCoin, other).then(result => {
59 if (_.isEmpty(result)) { 59 if (_.isEmpty(result)) {
60 return { 60 return {
61 code: 500, 61 code: 500,
@@ -30,16 +30,18 @@ router.post('/address/setdefault', address.setDefault); // 设置默认地址 @@ -30,16 +30,18 @@ router.post('/address/setdefault', address.setDefault); // 设置默认地址
30 30
31 router.get('/ensure', auth, ensure.index); // 限购商品快捷结算页 31 router.get('/ensure', auth, ensure.index); // 限购商品快捷结算页
32 router.get('/ensure/coupons', auth, ensure.getCoupons); // 结算优惠券列表 32 router.get('/ensure/coupons', auth, ensure.getCoupons); // 结算优惠券列表
  33 +router.get('/ensure/giftcards', auth, ensure.getGiftCards); // 结算礼品卡列表
33 router.get('/ensure/couponcode', auth, ensure.convertCoupons); // 优惠码兑换券 34 router.get('/ensure/couponcode', auth, ensure.convertCoupons); // 优惠码兑换券
34 router.post('/ensure/compute', auth, ensure.compute); // 价格重新计算 35 router.post('/ensure/compute', auth, ensure.compute); // 价格重新计算
35 -router.post('/ensure/submit', auth, ensure.submit); // 价格重新计算 36 +router.post('/ensure/submit', auth, ensure.submitCheck, ensure.submit); // 订单提交
  37 +router.post('/property/checksms', ensure.sendCheckSms); // 虚拟资产使用校验
36 38
37 router.get('/easypay', auth, easypay.index); // 限购商品快捷结算页 39 router.get('/easypay', auth, easypay.index); // 限购商品快捷结算页
38 router.post('/easypay/compute', auth, easypay.compute); // 价格重新计算 40 router.post('/easypay/compute', auth, easypay.compute); // 价格重新计算
39 router.post('/easypay/submit', auth, easypay.submit); // 限购商品订单提交 41 router.post('/easypay/submit', auth, easypay.submit); // 限购商品订单提交
40 42
41 router.get('/ticketEnsure', auth, ticket.ticketEnsure); 43 router.get('/ticketEnsure', auth, ticket.ticketEnsure);
42 -router.post('/ticketSubmit', auth, ticket.ticketSubmit); 44 +router.post('/ticketSubmit', auth, ensure.submitCheck, ticket.ticketSubmit);
43 router.post('/ticketCompute', auth, ticket.ticketCompute); 45 router.post('/ticketCompute', auth, ticket.ticketCompute);
44 46
45 router.get('/cart', cart.cart); 47 router.get('/cart', cart.cart);
@@ -100,7 +100,7 @@ @@ -100,7 +100,7 @@
100 {{/each}} 100 {{/each}}
101 </ul> 101 </ul>
102 </div> 102 </div>
103 - <p class="package-shipping">运费:¥{{shopping_cost}}元(原价{{shopping_orig_cost}}元,优惠{{shopping_cut_cost}}元)</p> 103 + <p class="package-shipping"></p>
104 </div> 104 </div>
105 {{/each}} 105 {{/each}}
106 </div> 106 </div>
@@ -251,6 +251,27 @@ @@ -251,6 +251,27 @@
251 </div> 251 </div>
252 </dd> 252 </dd>
253 {{/if}} 253 {{/if}}
  254 +
  255 + <dt id="use-gift-card" class="hide"><span class="locker-switch"></span>使用礼品卡<span class="can-use-tip"></span></dt>
  256 + <dd class="gift-card-box hide">
  257 + <table>
  258 + <thead>
  259 + <tr>
  260 + <th width="260">卡号</th>
  261 + <th>面值</th>
  262 + <th>卡内余额</th>
  263 + <th width="230">有效期</th>
  264 + <th width="86">选择</th>
  265 + </tr>
  266 + </thead>
  267 + <tbody>
  268 + <tr>
  269 + <td colspan="5">暂无礼品卡</td>
  270 + </tr>
  271 + </tbody>
  272 + </table>
  273 + </dd>
  274 +
254 <dt><span class="locker-switch"></span>添加备注信息</dt> 275 <dt><span class="locker-switch"></span>添加备注信息</dt>
255 <dd id="remark-box" class="remark-box"> 276 <dd id="remark-box" class="remark-box">
256 <div class="note-text-box"> 277 <div class="note-text-box">
@@ -284,7 +305,7 @@ @@ -284,7 +305,7 @@
284 </div> 305 </div>
285 306
286 <div class="sum-wrap"> 307 <div class="sum-wrap">
287 - 应付金额:<span id="order-price" class="price">¥ {{round last_order_amount 2}}</span> 308 + 应付金额:<span id="order-price" class="price" data-price="{{last_order_amount}}">¥ {{round last_order_amount 2}}</span>
288 <button id="order-submit">提交订单</button> 309 <button id="order-submit">提交订单</button>
289 </div> 310 </div>
290 {{/ shoppingCartData}} 311 {{/ shoppingCartData}}
@@ -100,10 +100,30 @@ @@ -100,10 +100,30 @@
100 </dd> 100 </dd>
101 101
102 </dl> 102 </dl>
  103 +
  104 + <dt id="use-gift-card" class="hide"><span class="locker-switch"></span>使用礼品卡<span class="can-use-tip"></span></dt>
  105 + <dd class="gift-card-box hide">
  106 + <table>
  107 + <thead>
  108 + <tr>
  109 + <th width="260">卡号</th>
  110 + <th>面值</th>
  111 + <th>卡内余额</th>
  112 + <th width="230">有效期</th>
  113 + <th width="86">选择</th>
  114 + </tr>
  115 + </thead>
  116 + <tbody>
  117 + <tr>
  118 + <td colspan="5">暂无礼品卡</td>
  119 + </tr>
  120 + </tbody>
  121 + </table>
  122 + </dd>
103 </div> 123 </div>
104 124
105 <div class="sum-wrap"> 125 <div class="sum-wrap">
106 - 应付金额:<span id="order-price" class="price">¥ {{round last_order_amount 2}}</span> 126 + 应付金额:<span id="order-price" class="price" data-price="{{last_order_amount}}">¥ {{round last_order_amount 2}}</span>
107 <button id="order-submit" data-url="{{productUrl}}">提交订单</button> 127 <button id="order-submit" data-url="{{productUrl}}">提交订单</button>
108 </div> 128 </div>
109 129
@@ -106,7 +106,7 @@ @@ -106,7 +106,7 @@
106 <li class="invoice-personal-name invoice-row personal-row"> 106 <li class="invoice-personal-name invoice-row personal-row">
107 <span class="row-title"></span> 107 <span class="row-title"></span>
108 <div class="row-content"> 108 <div class="row-content">
109 - <input id="personal-name" class="personal-name" type="text" placeholder="个人( 可修改 )"> 109 + <input id="personal-name" class="personal-name" type="text" placeholder="个人( 可修改 )" maxlength="100">
110 </div> 110 </div>
111 </li> 111 </li>
112 <li class="invoice-title-name invoice-row company-row hide"> 112 <li class="invoice-title-name invoice-row company-row hide">
@@ -115,7 +115,7 @@ @@ -115,7 +115,7 @@
115 单&nbsp;位&nbsp;名&nbsp;称: 115 单&nbsp;位&nbsp;名&nbsp;称:
116 </span> 116 </span>
117 <div class="row-content"> 117 <div class="row-content">
118 - <input id="company-name" class="company-name" type="text" placeholder="请填写单位名称"> 118 + <input id="company-name" class="company-name" type="text" placeholder="请填写单位名称" maxlength="100">
119 <span class="input-tip company-name-tip red hide"> 119 <span class="input-tip company-name-tip red hide">
120 <span class="iconfont">&#xe629;</span> 120 <span class="iconfont">&#xe629;</span>
121 <em>请填写发票抬头</em> 121 <em>请填写发票抬头</em>
  1 +'use strict';
  2 +
  3 +const ordersService = require('../models/orders-service');
  4 +const invoiceModel = require('../models/invoice');
  5 +
  6 +const index = (req, res, next) => {
  7 + let page = parseInt(req.query.page, 10) || 1;
  8 + let limit = parseInt(req.query.limit, 10) || 10;
  9 +
  10 + return req.ctx(ordersService).index(req.user.uid, page, limit, 8).then(result => {
  11 + res.render('invoice', {
  12 + meOrders: result
  13 + });
  14 + }).catch(next);
  15 +};
  16 +
  17 +const detail = (req, res, next) => {
  18 + return req.ctx(invoiceModel).getInvoiceDetail(req.query.orderCode, req.user.uid).then(result => {
  19 + res.send(result);
  20 + }).catch(next);
  21 +};
  22 +
  23 +const supply = (req, res, next) => {
  24 + let params = req.body;
  25 +
  26 + // 5.8.1 发票优化需求
  27 + // 只接受电子发票(1 纸质 2 电子),发票内容为明细(id 12:明细)
  28 + Object.assign(params, {
  29 + invoicesType: 2,
  30 + contentId: 12
  31 + });
  32 +
  33 + return req.ctx(invoiceModel).submitInvoiceSupply(params, req.user.uid).then(result => {
  34 + res.send(result);
  35 + }).catch(next);
  36 +};
  37 +
  38 +module.exports = {
  39 + index,
  40 + detail,
  41 + supply
  42 +};
  1 +/**
  2 + * 个人中心---我的礼品卡
  3 + * @author xiaoxiao <xiaoxiao.hao@yoho.cn>
  4 + * @date: 2017/9/1
  5 + */
  6 +'use strict';
  7 +
  8 +const meGiftService = require('../models/me-gift-service');
  9 +
  10 +/**
  11 + * 礼品卡列表
  12 + */
  13 +exports.index = (req, res, next) => {
  14 + let uid = req.user.uid;
  15 + let responseData = {
  16 + module: 'home',
  17 + page: 'me-gift'
  18 + };
  19 +
  20 + req.ctx(meGiftService).getList(req.query, uid).then(result => {
  21 + responseData.meGiftPage = true;
  22 + Object.assign(responseData, result);
  23 + res.render('home/gift/me-gift', responseData);
  24 + }).catch(next);
  25 +};
  26 +
  27 +/**
  28 + * 消费明细
  29 + */
  30 +exports.detail = (req, res, next) => {
  31 + let uid = req.user.uid;
  32 + let responseData = {
  33 + module: 'home',
  34 + page: 'me-gift',
  35 + layout: false
  36 + };
  37 +
  38 + return req.ctx(meGiftService).consumeList(req.query, uid).then(result => {
  39 + Object.assign(responseData, result);
  40 + return res.render('home/gift/me-detail', responseData);
  41 + }).catch(next);
  42 +};
  43 +
  44 +/**
  45 + * 激活礼品卡
  46 + */
  47 +exports.activateGift = (req, res, next) => {
  48 + let uid = req.user.uid;
  49 +
  50 + req.ctx(meGiftService).activateGift(req.body, uid).then(result => {
  51 + res.json(result);
  52 + }).catch(next);
  53 +};
  54 +
  55 +/**
  56 + * 发送邮箱验证码
  57 + */
  58 +exports.sendEmailCode = (req, res, next) => {
  59 + let uid = req.user.uid;
  60 +
  61 + req.ctx(meGiftService).sendEmailCode(req.body, uid).then(result => {
  62 + res.json(result);
  63 + }).catch(next);
  64 +};
  65 +
  66 +/**
  67 + * 验证邮箱验证码
  68 + */
  69 +exports.verifyEmail = (req, res, next) => {
  70 + let uid = req.user.uid;
  71 +
  72 + req.ctx(meGiftService).verifyEmail(req.body, uid).then(result => {
  73 + res.json(result);
  74 + }).catch(next);
  75 +};
  76 +
  77 +/**
  78 + * 发验证码
  79 + */
  80 +exports.smsBind = (req, res, next) => {
  81 + req.ctx(meGiftService).smsBind(req.body).then(result => {
  82 + res.json(result);
  83 + }).catch(next);
  84 +};
  85 +
  86 +/**
  87 + * 修改绑定的手机号
  88 + */
  89 +exports.changeMobile = (req, res, next) => {
  90 + let uid = req.user.uid;
  91 +
  92 + req.ctx(meGiftService).changeMobile(req.body, uid).then(result => {
  93 + res.json(result);
  94 + }).catch(next);
  95 +};
@@ -72,7 +72,7 @@ const modifyAddress = (req, res, next) => { @@ -72,7 +72,7 @@ const modifyAddress = (req, res, next) => {
72 return ''; 72 return '';
73 } 73 }
74 }()); 74 }());
75 - let udid = req.cookies._yasvd || 'yoho_pc'; 75 + let udid = req.yoho.udid;
76 76
77 if (!orderId || !userName || !areaCode || !address) { 77 if (!orderId || !userName || !areaCode || !address) {
78 return res.json({ 78 return res.json({
@@ -27,6 +27,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -27,6 +27,7 @@ module.exports = class extends global.yoho.BaseModel {
27 {name: '我的红包', href: '/home/redenvelopes'}, 27 {name: '我的红包', href: '/home/redenvelopes'},
28 {name: '我的优惠券', href: '/home/coupons'}, 28 {name: '我的优惠券', href: '/home/coupons'},
29 {name: '我的邀请好友', href: '/home/spread'}, 29 {name: '我的邀请好友', href: '/home/spread'},
  30 + {name: '我的礼品卡', href: '/home/megift'},
30 {name: '我的VIP', href: '/home/vip'} 31 {name: '我的VIP', href: '/home/vip'}
31 ] 32 ]
32 }, 33 },
@@ -34,6 +35,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -34,6 +35,7 @@ module.exports = class extends global.yoho.BaseModel {
34 title: '服务中心', 35 title: '服务中心',
35 subNav: [ 36 subNav: [
36 {name: '我的退/换货', href: '/home/returns'}, 37 {name: '我的退/换货', href: '/home/returns'},
  38 + {name: '我的发票', href: '/home/invoice'},
37 {name: '我的咨询', href: '/home/consult'}, 39 {name: '我的咨询', href: '/home/consult'},
38 {name: '我的评论', href: '/home/comment'}, 40 {name: '我的评论', href: '/home/comment'},
39 41
@@ -70,7 +72,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -70,7 +72,7 @@ module.exports = class extends global.yoho.BaseModel {
70 '/home/account/modifymobile' 72 '/home/account/modifymobile'
71 ]}, 73 ]},
72 {name: '地址管理', href: '/home/address'}, 74 {name: '地址管理', href: '/home/address'},
73 - {name: '兑换礼品卡', href: '/home/gift'} 75 + // {name: '兑换礼品卡', href: '/home/gift'} // @韩施超-产品让注释的
74 ] 76 ]
75 } 77 }
76 ]; 78 ];
  1 +/**
  2 + * 我的消息model
  3 + * @author: yyq<yanqing.yang@yoho.cn>
  4 + * @date: 2016/8/29
  5 + */
  6 +'use strict';
  7 +
  8 +const _ = require('lodash');
  9 +
  10 +module.exports = class extends global.yoho.BaseModel {
  11 + constructor(ctx) {
  12 + super(ctx);
  13 + }
  14 +
  15 + getInvoiceDetail(orderCode, uid) {
  16 + return this.get({data: {
  17 + method: 'app.invoice.detail',
  18 + uid: uid,
  19 + order_code: orderCode
  20 + }}).then(result => {
  21 + if (result.code === 200) {
  22 + _.unset(result, 'data.uid');
  23 + _.set(result, 'data.invoicesType', _.get(result, 'data.invoices_type') === 2 ? '电子发票' : '纸质发票');
  24 + }
  25 +
  26 + return result;
  27 + });
  28 + }
  29 +
  30 + submitInvoiceSupply(info, uid) {
  31 + let param = {
  32 + order_code: info.orderCode,
  33 + invoices_type: info.invoicesType,
  34 + invoices_title: info.titleName,
  35 + invoice_content: info.contentId,
  36 + receiverMobile: info.receiver,
  37 + buyerTaxNumber: info.taxNumber,
  38 + invoice_payable_type: info.taxNumber ? 2 : 1
  39 + };
  40 +
  41 + return this.get({data: Object.assign(param, {
  42 + method: 'app.invoice.supply',
  43 + uid: uid
  44 + })}).then(result => {
  45 + _.unset(result, 'data.uid');
  46 +
  47 + return result;
  48 + });
  49 + }
  50 +};
  1 +'use strict';
  2 +
  3 +module.exports = class extends global.yoho.BaseModel {
  4 + constructor(ctx) {
  5 + super(ctx);
  6 + }
  7 +
  8 + /**
  9 + * [获取礼品卡列表]
  10 + * @param {[type]} uid [用户id]
  11 + * @param {[type]} status [1-可使用,2-已冻结,3-已过期,4-已用完]
  12 + * @return {[type]} [{}]
  13 + */
  14 + getList(uid, status, page, limit) {
  15 + let options = {
  16 + method: 'app.giftcard.pagelist',
  17 + uid: uid,
  18 + status: status,
  19 + page: page,
  20 + limit: limit || 10
  21 + };
  22 +
  23 + return this.get({data: options});
  24 + }
  25 +
  26 + /**
  27 + * [获取礼品卡消费记录]
  28 + * @param {[type]} cardCode [礼品卡号]
  29 + * @param {[type]} uid [用户id]
  30 + * @param {[type]} page [当前页]
  31 + * @param {[type]} limit [页大小]
  32 + * @return {[type]} [{}]
  33 + */
  34 + consumeList(params, uid) {
  35 + let options = {
  36 + method: 'app.giftcard.consumelist',
  37 + cardCode: params.cardCode,
  38 + uid: uid,
  39 + page: params.page,
  40 + limit: params.limit || 10
  41 + };
  42 +
  43 + if (params.type) {
  44 + options.type = params.type;
  45 + }
  46 +
  47 + return this.get({data: options});
  48 + }
  49 +
  50 + /**
  51 + * [发送邮箱验证码]
  52 + * @param {[type]} email [邮箱]
  53 + * @param {[type]} uid [用户id]
  54 + * @return {[type]} [{}]
  55 + */
  56 + sendEmailCode(email, uid) {
  57 + let options = {
  58 + method: 'app.giftcard.emailcode',
  59 + email: email,
  60 + uid: uid
  61 + };
  62 +
  63 + return this.get({data: options});
  64 + }
  65 +
  66 + /**
  67 + * [验证邮箱验证码]
  68 + * @param {[type]} code [邮箱验证码]
  69 + * @param {[type]} uid [用户id]
  70 + * @return {[type]} [{}]
  71 + */
  72 + verifyEmail(code, uid) {
  73 + let options = {
  74 + method: 'app.giftcard.verifyemail',
  75 + uid: uid,
  76 + code: code
  77 + };
  78 +
  79 + return this.get({data: options});
  80 + }
  81 +
  82 + /**
  83 + * [激活礼品卡]
  84 + * @param {[type]} uid [用户id]
  85 + * @param {[type]} cardCode [礼品卡卡号]
  86 + * @param {[type]} cardPwd [礼品卡卡密]
  87 + * @return {[type]} [{}]
  88 + */
  89 + activateGift(uid, cardCode, cardPwd) {
  90 + let options = {
  91 + method: 'app.giftcard.activate',
  92 + uid: uid,
  93 + cardCode: cardCode,
  94 + cardPwd: cardPwd
  95 + };
  96 +
  97 + return this.get({data: options});
  98 + }
  99 +
  100 + /**
  101 + * [检查是否绑定手机号]
  102 + * @param {[type]} area [区号]
  103 + * @param {[type]} mobile [手机号]
  104 + * @return {[type]} [{}]
  105 + */
  106 + checkIsCanBind(area, mobile) {
  107 + let options = {
  108 + method: 'app.passport.checkIsCanBind',
  109 + area: area,
  110 + mobile: mobile
  111 + };
  112 +
  113 + return this.get({data: options});
  114 + }
  115 +
  116 + /**
  117 + * [发验证码]
  118 + * @param {[type]} area [区号]
  119 + * @param {[type]} mobile [手机号]
  120 + * @return {[type]} [{}]
  121 + */
  122 + smsbind(area, mobile) {
  123 + let options = {
  124 + method: 'app.passport.smsbind',
  125 + area: area,
  126 + mobile: mobile
  127 + };
  128 +
  129 + return this.get({data: options});
  130 + }
  131 +
  132 + /**
  133 + * [修改绑定的手机号]
  134 + * @param {[type]} area [区号]
  135 + * @param {[type]} mobile [手机号]
  136 + * @param {[type]} code [验证码]
  137 + * @param {[type]} uid [用户id]
  138 + * @return {[type]} [{}]
  139 + */
  140 + changeMobile(area, mobile, code, uid) {
  141 + let options = {
  142 + method: 'app.passport.changeMobile',
  143 + area: area,
  144 + mobile: mobile,
  145 + code: code,
  146 + uid: uid
  147 + };
  148 +
  149 + return this.get({data: options});
  150 + }
  151 +
  152 + /**
  153 + * [获取用户信息]
  154 + * @param {[type]} uid [用户id]
  155 + * @return {[type]} [{}]
  156 + */
  157 + getProfile(uid) {
  158 + let options = {
  159 + uid: uid,
  160 + method: 'app.passport.profile'
  161 + };
  162 +
  163 + return this.get({data: options});
  164 + }
  165 +};
  1 +/**
  2 + * 我的礼品卡列表
  3 + * @author xiaoxiao <xiaoxiao.hao@yoho.cn>
  4 + * @date: 2017/9/1
  5 + */
  6 +'use strict';
  7 +const Promise = require('bluebird');
  8 +const _ = require('lodash');
  9 +const helpers = global.yoho.helpers;
  10 +const MeGiftAPi = require('./me-gift-api');
  11 +const setPager = require(`${global.utils}/pager`).setPager;
  12 +const crypto = global.yoho.crypto;
  13 +
  14 +module.exports = class extends global.yoho.BaseModel {
  15 + constructor(ctx) {
  16 + super(ctx);
  17 + this.meGiftAPi = new MeGiftAPi(this.ctx);
  18 + }
  19 +
  20 + headTab(params) {
  21 + let type = params.type;
  22 + let tabs = [{
  23 + name: '使用中',
  24 + url: helpers.urlFormat('/home/megift'),
  25 + active: false
  26 + }, {
  27 + name: '已过期',
  28 + url: helpers.urlFormat('/home/megift', {type: 1}),
  29 + active: false
  30 + }, {
  31 + name: '已用完',
  32 + url: helpers.urlFormat('/home/megift', {type: 2}),
  33 + active: false
  34 + }, {
  35 + name: '已冻结',
  36 + url: helpers.urlFormat('/home/megift', {type: 3}),
  37 + active: false
  38 + }, {
  39 + name: '添加礼品卡',
  40 + class: 'add-gift',
  41 + active: false
  42 + }];
  43 +
  44 + tabs[type].active = true;
  45 + return tabs;
  46 + }
  47 +
  48 + // 礼品卡列表-status=[1-可使用,2-已冻结,3-已过期,4-已用完]
  49 + getList(params, uid) {
  50 + let status = 1;
  51 +
  52 + params.type = Number(params.type > -1 && params.type < 4 ? params.type : 0);
  53 + params.page = Number(params.page) || 1;
  54 +
  55 + switch (params.type) {
  56 + case 1: status = 3; break;
  57 + case 2: status = 4; break;
  58 + case 3: status = 2; break;
  59 + default: status = 1;
  60 + }
  61 +
  62 + return Promise.all([
  63 + this.meGiftAPi.getList(uid, status, params.page),
  64 + this.verifyBinMobile(uid)
  65 + ]).then(rlist => {
  66 + let giftData = {};
  67 +
  68 + giftData.data = _.get(rlist[0], 'data.giftCardInfoBOList', []);
  69 + giftData.pager = Object.assign({
  70 + count: _.get(rlist[0], 'data.total', 0),
  71 + curPage: params.page,
  72 + totalPages: _.get(rlist[0], 'data.pageSize', 0)
  73 + }, setPager(_.get(rlist[0], 'data.pageSize', 0), params));
  74 +
  75 + return {
  76 + giftData: giftData,
  77 + userInfo: rlist[1],
  78 + tabs: this.headTab(params)
  79 + };
  80 + });
  81 + }
  82 +
  83 + // 获取礼品卡消费记录
  84 + consumeList(params, uid) {
  85 + let types = ['类型', '消费', '退款'];
  86 +
  87 + params.page = Number(params.page) || 1;
  88 + params.type = Number(params.type) || 0;
  89 +
  90 + return this.meGiftAPi.consumeList(params, uid).then(rlist => {
  91 + let giftData = {};
  92 +
  93 + giftData.data = _.get(rlist, 'data', {});
  94 + giftData.pager = Object.assign({
  95 + count: _.get(rlist, 'data.total', 0),
  96 + curPage: params.page,
  97 + totalPages: _.get(rlist, 'data.pageSize', 0)
  98 + }, setPager(_.get(rlist, 'data.pageSize', 0), params));
  99 + _.set(giftData, 'data.types', types[params.type] || types[0]);
  100 +
  101 + return giftData;
  102 + });
  103 + }
  104 +
  105 + // 验证手机是否绑定
  106 + verifyBinMobile() {
  107 + let userInfo = {
  108 + isBinMobile: Number(!!_.get(this.ctx, 'req.user.mobile', false))
  109 + };
  110 +
  111 + return Promise.resolve(userInfo);
  112 + }
  113 +
  114 + // 发送邮箱验证码
  115 + sendEmailCode(params, uid) {
  116 + return this.meGiftAPi.sendEmailCode(params.email, uid);
  117 + }
  118 +
  119 + // 验证邮箱验证码
  120 + verifyEmail(params, uid) {
  121 + return this.meGiftAPi.verifyEmail(params.code, uid);
  122 + }
  123 +
  124 + // 发验手机证码
  125 + smsBind(params) {
  126 + return this.meGiftAPi.checkIsCanBind(params.area, params.mobile).then(res => {
  127 + if (_.get(res, 'data.isCanBind') === 'N') {
  128 + return {
  129 + code: 401,
  130 + message: '<p>绑定失败,该手机号已被绑定</p><p>请更换手机号</p>'
  131 + };
  132 + }
  133 + return this.meGiftAPi.smsbind(params.area, params.mobile);
  134 + });
  135 + }
  136 +
  137 + // 修改绑定的手机号
  138 + changeMobile(params, uid) {
  139 + return this.meGiftAPi.changeMobile(params.area, params.mobile, params.code, uid).then(res => {
  140 + if (res.code === 200) {
  141 + _.set(this.ctx, 'req.session.USER_MOBILE', params.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'));
  142 + }
  143 + return res;
  144 + });
  145 + }
  146 +
  147 + // 激活礼品卡
  148 + activateGift(params, uid) {
  149 + return this.meGiftAPi.activateGift(uid, params.cardCode, crypto.encryption('yoho9646yoho9646', params.cardPwd));
  150 + }
  151 +};
@@ -4,7 +4,7 @@ const api = global.yoho.API; @@ -4,7 +4,7 @@ const api = global.yoho.API;
4 4
5 exports.getUserSuccessfulOrders = (uid)=>{ 5 exports.getUserSuccessfulOrders = (uid)=>{
6 return api.get('', { 6 return api.get('', {
7 - method: 'app.SpaceOrders.get', 7 + method: 'app.SpaceOrders.list',
8 uid: uid, 8 uid: uid,
9 type: 5, 9 type: 5,
10 page: 1, 10 page: 1,
@@ -18,7 +18,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -18,7 +18,7 @@ module.exports = class extends global.yoho.BaseModel {
18 */ 18 */
19 getUserOrders(uid, page, limit, type) { 19 getUserOrders(uid, page, limit, type) {
20 let options = { 20 let options = {
21 - method: 'app.SpaceOrders.get', 21 + method: 'app.SpaceOrders.list',
22 uid: uid, 22 uid: uid,
23 type: type, 23 type: type,
24 page: page, 24 page: page,
@@ -26,7 +26,8 @@ module.exports = class extends global.yoho.BaseModel { @@ -26,7 +26,8 @@ module.exports = class extends global.yoho.BaseModel {
26 this.ORDER_EMPTY_DESC = { 26 this.ORDER_EMPTY_DESC = {
27 1: '您还没有任何订单', 27 1: '您还没有任何订单',
28 5: '您目前还没有成功的订单', 28 5: '您目前还没有成功的订单',
29 - 7: '您还没有任何取消的订单' 29 + 7: '您还没有任何取消的订单',
  30 + 8: '您还没有相关订单'
30 }; 31 };
31 32
32 this.TABS = [ 33 this.TABS = [
@@ -368,6 +369,33 @@ module.exports = class extends global.yoho.BaseModel { @@ -368,6 +369,33 @@ module.exports = class extends global.yoho.BaseModel {
368 newOrder.payType = _.get(order, 'payment_type'); 369 newOrder.payType = _.get(order, 'payment_type');
369 newOrder.title = _.get(order, 'order_title'); 370 newOrder.title = _.get(order, 'order_title');
370 371
  372 + // 补开发票订单
  373 + if (type === 8) {
  374 + let iop = _.get(order, 'links', []);
  375 + let issueType = +_.get(order, 'invoice.issueType');
  376 +
  377 + newOrder.invoiceType = '';
  378 + newOrder.issueType = issueType === 2;
  379 + newOrder.invoiceOperation = _.zipObject(iop, iop);
  380 +
  381 + if (!newOrder.invoiceOperation || (!newOrder.invoiceOperation.invoiceDetail &&
  382 + !newOrder.invoiceOperation.supplyInvoice)) {
  383 + _.set(newOrder, 'invoiceOperation.invoiceSupplying', issueType === 1);
  384 + }
  385 +
  386 + if (+order.refund_status === 1 || +order.exchange_status === 1) {
  387 + Object.assign(newOrder, {
  388 + invoiceOperation: {unsupportSupply: true},
  389 + unsupportSupplyTip: +order.refund_status === 1 ?
  390 + '订单商品已申请退货,暂无发票信息' : '换货订单暂不支持补开发票'
  391 + });
  392 + }
  393 +
  394 + if (newOrder.issueType) {
  395 + newOrder.invoiceType = _.get(order, 'invoice.type', 0) === 2 ? '电子发票' : '纸质发票';
  396 + }
  397 + }
  398 +
371 if (order.is_cancel === 'Y' || order.status === 6) { 399 if (order.is_cancel === 'Y' || order.status === 6) {
372 newOrder.canDelete = true; // 删除订单 400 newOrder.canDelete = true; // 删除订单
373 } 401 }
@@ -46,6 +46,9 @@ const ordersController = require(`${cRoot}/orders`); @@ -46,6 +46,9 @@ const ordersController = require(`${cRoot}/orders`);
46 const AddressController = require(`${cRoot}/address`); 46 const AddressController = require(`${cRoot}/address`);
47 47
48 const giftController = require(`${cRoot}/gift`); 48 const giftController = require(`${cRoot}/gift`);
  49 +const invoiceController = require(`${cRoot}/invoice`);
  50 +
  51 +const meGiftController = require(`${cRoot}/me-gift`);
49 52
50 53
51 // 首页 54 // 首页
@@ -268,7 +271,22 @@ router.get('/gift', tabsMiddleware.getCommonHeader, captcha.tryGeetest, giftCont @@ -268,7 +271,22 @@ router.get('/gift', tabsMiddleware.getCommonHeader, captcha.tryGeetest, giftCont
268 271
269 router.post('/gift/exchange', giftController.exchange); 272 router.post('/gift/exchange', giftController.exchange);
270 273
  274 +// 我的发票
  275 +router.get('/invoice', tabsMiddleware.getCommonHeader, invoiceController.index);
  276 +router.get('/invoice/detail', invoiceController.detail);
  277 +router.post('/invoice/supply', invoiceController.supply);
  278 +
271 // 是否新客(仅操作cookie) 279 // 是否新客(仅操作cookie)
272 router.get('/newuser', newUserController.check); 280 router.get('/newuser', newUserController.check);
273 281
  282 +// 我的礼品卡
  283 +router.get('/megift', tabsMiddleware.getCommonHeader, meGiftController.index);
  284 +router.post('/megift/sendEmailCode', meGiftController.sendEmailCode);// 发送邮箱验证码
  285 +router.post('/megift/verifyEmail', meGiftController.verifyEmail);// 验证邮箱验证码
  286 +// 检查是否绑定手机号、发验证码
  287 +router.post('/megift/smsBind', meGiftController.smsBind);
  288 +router.post('/megift/changeMobile', meGiftController.changeMobile);// 修改绑定手机
  289 +router.post('/megift/activateGift', meGiftController.activateGift);// 激活礼品卡
  290 +router.get('/megift/detail', meGiftController.detail);// 消费明细
  291 +
274 module.exports = router; 292 module.exports = router;
  1 +{{# data}}
  2 + <table class="info-gift-header" data-card-code={{cardCode}}>
  3 + <tr>
  4 + <td class="text-left">卡号:{{cardCode}}</td>
  5 + <td>状态:{{statusStr}}</td>
  6 + <td class="text-right validity-time">有效期:{{dateStr}}{{#if willExpire}}{{willExpire}}{{/if}}</td>
  7 + </tr>
  8 + <tr>
  9 + <td class="text-left">面值:{{round amount 2}} </td>
  10 + <td colspan="2">余额:{{round remainAmount 2}}</td>
  11 + </tr>
  12 + </table>
  13 + <div class="me-gift-info-table">
  14 + <div class="me-gift-header">
  15 + <div>时间</div>
  16 + <div>订单编号</div>
  17 + <div>
  18 + <span class="gift-filter">
  19 + <em class="gift-type">{{types}}</em>
  20 + <ul class="ul-list">
  21 + <li data-cc="1">消费</li>
  22 + <li data-cc="2">退款</li>
  23 + </ul>
  24 + </span>
  25 + </div>
  26 + <div>金额(元)</div>
  27 + </div>
  28 + {{#if giftCardConsumeInfoBOList}}
  29 + {{# giftCardConsumeInfoBOList}}
  30 + <div class="me-gift-tr">
  31 + <div>{{dateFormat 'YYYY-MM-DD HH:mm:ss' createTime}}</div>
  32 + <div>{{orderCode}}</div>
  33 + {{#isEqual type 1}}
  34 + <div class="consume">消费</div>
  35 + <div class="consume">-{{round ../changeAmount 2}}</div>
  36 + {{/isEqual}}
  37 + {{#isEqual type 2}}
  38 + <div class="refund">退款</div>
  39 + <div class="refund">+{{round ../changeAmount 2}}</div>
  40 + {{/isEqual}}
  41 + {{#isEqual type 3}}
  42 + <div class="refund">退款</div>
  43 + <div class="refund">+{{round ../changeAmount 2}}</div>
  44 + {{/isEqual}}
  45 + </div>
  46 + {{/giftCardConsumeInfoBOList}}
  47 + {{^}}
  48 + <div class="cart-list-empty"></div>
  49 + {{/if}}
  50 + </div>
  51 +{{/data}}
  52 + {{> pager}}
  1 +<div class="me-gift-page me-page yoho-page clearfix">
  2 + {{> path}}
  3 + {{> navigation}}
  4 + <div class="me-main">
  5 + <div class="me-gift block">
  6 + <div class="title">
  7 + <h2>礼品卡</h2>
  8 + </div>
  9 +
  10 + <div class="me-content" data-is-bin-mobile={{userInfo.isBinMobile}} data-email={{userInfo.email}}>
  11 + {{> tabs}}
  12 + <div class="me-gift-table">
  13 + <div class="me-gift-header">
  14 + <div class="card-number">卡号</div>
  15 + <div class="card-price">卡片面值(元)</div>
  16 + <div class="card-balance">卡片余额(元)</div>
  17 + <div class="activate-time">激活时间</div>
  18 + <div class="invalid-time">失效时间</div>
  19 + <div class="cart-operation">操作</div>
  20 + </div>
  21 + {{#if giftData.data}}
  22 + {{#giftData.data}}
  23 + <div class="me-gift-tr" data-card-code={{cardCode}}>
  24 + <div>{{cardCode}}</div>
  25 + <div>{{amount}}</div>
  26 + <div>{{remainAmount}}</div>
  27 + <div>{{dateFormat 'YYYY-MM-DD' activateTime}}</div>
  28 + <div>{{dateFormat 'YYYY-MM-DD' endTime}}</div>
  29 + <div class="info-list">消费明细</div>
  30 + </div>
  31 + {{/giftData.data}}
  32 + {{^}}
  33 + <div class="cart-list-empty"></div>
  34 + {{/if}}
  35 + </div>
  36 + </div>
  37 +
  38 + {{#giftData}}
  39 + {{> pager}}
  40 + {{/giftData}}
  41 + </div>
  42 + </div>
  43 +</div>
  44 +
  45 +{{!-- 验证邮箱模板 --}}
  46 +<script id="verify-email-tpl" type="text/html">
  47 + <div class="title">验证邮箱</div>
  48 + <div class="gift-group">您的账户还未绑定手机,绑定手机前需要验证您的邮箱</div>
  49 + <div class="gift-group">短信验证码已发送至您的邮箱“{{userInfo.email}}</div>
  50 + <div class="gift-group verify-input">
  51 + <input type="text" placeholder="短信验证码" class="left email-code" />
  52 + <span class="left email-btn">获取短信验证码</span>
  53 + </div>
  54 +</script>
  55 +
  56 +{{!-- 绑定手机模板 --}}
  57 +<script id="verify-mobile-tpl" type="text/html">
  58 + <div class="title">绑定手机号</div>
  59 + <div class="verify-input">
  60 + <div class="gift-group">
  61 + <span class="mobile-area left">
  62 + <em>+86</em>
  63 + <i class="iconfont">&#xe60b;</i>
  64 + <ul class="ul-list mobile-area-list">
  65 + <li data-cc="+86">中国 +86</li>
  66 + <li data-cc="+853">中国澳门 +853</li>
  67 + <li data-cc="+886">中国台湾 +886</li>
  68 + <li data-cc="+852">中国香港 +852</li>
  69 + <li data-cc="+1">美国 +1</li>
  70 + <li data-cc="+61">澳大利亚 +61</li>
  71 + <li data-cc="+82">韩国 +82</li>
  72 + <li data-cc="+1">加拿大 +1</li>
  73 + <li data-cc="+60">马来西亚 +60</li>
  74 + <li data-cc="+81">日本 +81</li>
  75 + <li data-cc="+65">新加坡 +65</li>
  76 + <li data-cc="+44">英国 +44</li>
  77 + </ul>
  78 + </span>
  79 + <input type="text" placeholder="请输入手机号" class="right mobile" />
  80 + </div>
  81 + <div class="gift-group bind-mobile-input">
  82 + <input type="text" placeholder="短信验证码" class="left mobile-code" />
  83 + <span class="right mobile-btn">获取短信验证码</span>
  84 + </div>
  85 + </div>
  86 +</script>
  87 +
  88 +{{!-- 激活礼品卡模板 --}}
  89 +<script id="activate-gift-tpl" type="text/html">
  90 + <div class="title">激活礼品卡</div>
  91 + <div class="verify-input activate-center">
  92 + <div class="gift-group"><input type="text" placeholder="请输入礼品卡卡号" class="card-code" /></div>
  93 + <div class="gift-group activate-input-last"><input type="text" placeholder="请输入礼品卡卡密" class="card-pwd" /></div>
  94 + </div>
  95 +</script>
  96 +
  97 +{{!-- 消费明细 --}}
  98 +<script id="detail-gift-tpl" type="text/html">
  99 +<div class="detail-gift-list">
  100 + <div class="info-title">消费明细</div>
  101 + <div class="verify-input detail-gift-content">
  102 + </div>
  103 +</div>
  104 +</script>
  1 +<div class="orders-me-page invoice-me-page me-page yoho-page clearfix">
  2 + {{> path}}
  3 + {{> navigation}}
  4 +
  5 + {{# meOrders}}
  6 + <div class="me-main">
  7 + <div class="orders block">
  8 + <h2 class="title">我的发票</h2>
  9 +
  10 + <div id="me-invoice-orders" class="me-orders">
  11 + <p class="order-table-header table-header clearfix">
  12 + <span class="info">商品信息</span>
  13 + <span class="price">单价(元)</span>
  14 + <span class="count">数量</span>
  15 + <span class="pay">发票类型</span>
  16 + <span class="order-status">状态</span>
  17 + <span class="operation">操作</span>
  18 + </p>
  19 +
  20 + {{#if orders.empty}}
  21 + <p class="empty-tip">您还没有相关订单<br><span>未开票的订单可以在这里补开发票</span></p>
  22 + {{^}}
  23 + {{# orders.list}}
  24 + <div class="order" data-id="{{orderNum}}" data-time="{{time}}" data-paytype="{{payType}}">
  25 + <p class="order-title">
  26 + {{title}}
  27 + <span class="order-time">下单时间:{{orderTime}}</span>
  28 + {{#if unsupportSupplyTip}}
  29 + <span class="right unsupport-tip"><i class="iconfont">&#xe6c9;</i>{{unsupportSupplyTip}}</span>
  30 + {{/if}}
  31 + </p>
  32 + <div class="order-wrap">
  33 + <ul>
  34 + {{# goods}}
  35 + <li>
  36 + <div class="info clearfix">
  37 + <a class="thumb-wrap" href="{{href}}" target="_blank">
  38 + <img class="thumb" src="{{thumb}}">
  39 + {{> home/orders/order-goods-tags}}
  40 + </a>
  41 + <div class="text-info">
  42 + {{#if refundStatus}}
  43 + <a href="{{goRefundUrl}}"><span class="had-refund">已退换</span></a>
  44 + {{/if}}
  45 + <a class="name" href="{{href}}" target="_blank">{{name}}</a>
  46 + <span class="color-size">
  47 + {{#if virtualGood}}
  48 + {{#if color}}
  49 + 日期:{{color}}&nbsp;&nbsp;
  50 + {{/if}}
  51 + {{#if size}}
  52 + 区域:{{size}}
  53 + {{/if}}
  54 + {{else}}
  55 + {{#if color}}
  56 + <b title="{{color}}">颜色:{{color}}&nbsp;&nbsp;</b>
  57 + {{/if}}
  58 +
  59 + {{#if size}}
  60 + 尺码:{{size}}
  61 + {{/if}}
  62 +
  63 + {{#if arrivalDate}}
  64 + <i class="arrival-date">上市期:{{arrivalDate}}</i>
  65 + {{/if}}
  66 + {{/if}}
  67 + </span>
  68 + </div>
  69 + </div>
  70 + <div class="price">
  71 + <p>{{price}}</p>
  72 + {{#if linePrice}}
  73 + <p class="line-through">{{linePrice}}</p>
  74 + {{/if}}
  75 + {{#isVipPrice}}
  76 + <p class="tip-message">(VIP)</p>
  77 + {{/isVipPrice}}
  78 + {{#isStuPrice}}
  79 + <p class="tip-message">(学生价)</p>
  80 + {{/isStuPrice}}
  81 + {{#if free}}
  82 + <span class="free-icon">免单</span>
  83 + {{/if}}
  84 + </div>
  85 + <div class="count">{{count}}</div>
  86 + </li>
  87 + {{/ goods}}
  88 + </ul>
  89 +
  90 + <div class="pay">
  91 + <span class="pay-tip">{{invoiceType}}</span>
  92 +
  93 + </div>
  94 + <div class="order-status">
  95 + <span class="no-pay">{{#if issueType}}已开票{{^}}未开票{{/if}}</span>
  96 + </div>
  97 + <div class="operation">
  98 + {{# invoiceOperation}}
  99 + {{#if invoiceDetail}}
  100 + <span class="op-item view-invoice" data-id="{{../orderNum}}">查看发票</span>
  101 + {{/if}}
  102 +
  103 + {{#if invoiceSupplying}}
  104 + <span class="op-item" data-id="{{../orderNum}}">开票中</span>
  105 + {{/if}}
  106 +
  107 + {{#if supplyInvoice}}
  108 + <span class="op-item supply-invoice" data-id="{{../orderNum}}">申请补开</span>
  109 + {{/if}}
  110 +
  111 + {{#if unsupportSupply}}
  112 + <span class="op-item" data-id="{{../orderNum}}">不支持补开</span>
  113 + {{/if}}
  114 + {{/ invoiceOperation}}
  115 + </div>
  116 + </div>
  117 + </div>
  118 + {{/ orders.list}}
  119 + {{/if}}
  120 + </div>
  121 +
  122 + {{> pager}}
  123 + </div>
  124 + </div>
  125 + {{/ meOrders}}
  126 +</div>
  127 +
  128 +<div id="invoice-hide-dg" class="hide">
  129 + <p class="invoice-header">补开发票</p>
  130 + <div class="invoice-content el-content">
  131 + <p class="invoice-type-text">
  132 + <span class="row-title">&nbsp;&nbsp;&nbsp;型:</span>
  133 + 电子发票
  134 + </p>
  135 +
  136 + <p class="el-tip">
  137 + ※ 电子发票是税务局认可的有效凭证,其法律效力、基本用途及使用规定同纸质发票,如需纸质发票可自行下载打印。<br>
  138 + <a href="/help/detail?id=33&contId=139" target="_blank">查看发票须知</a>
  139 + </p>
  140 +
  141 + <ul>
  142 + <li class="invoice-title invoice-row">
  143 + <span class="row-title">
  144 + <em>*</em>
  145 +&nbsp;&nbsp;&nbsp;头:
  146 + </span>
  147 + <div class="row-content">
  148 + <span class="radio-wrap">
  149 + <label class="rbt-1 radio-btn on" data-id="1"></label> 个人
  150 + </span>
  151 + <span class="radio-wrap">
  152 + <label class="rbt-2 radio-btn" data-id="2"></label> 单位
  153 + </span>
  154 + </div>
  155 + </li>
  156 + <li class="invoice-personal-name invoice-row personal-row">
  157 + <span class="row-title"></span>
  158 + <div class="row-content">
  159 + <input id="personal-name" class="personal-name" type="text" placeholder="个人( 可修改 )" maxlength="100">
  160 + </div>
  161 + </li>
  162 + <li class="invoice-title-name invoice-row company-row hide">
  163 + <span class="row-title">
  164 + <em>*</em>
  165 +&nbsp;&nbsp;&nbsp;称:
  166 + </span>
  167 + <div class="row-content">
  168 + <input id="company-name" class="company-name" type="text" placeholder="请填写单位名称" maxlength="100">
  169 + <span class="input-tip company-name-tip red hide">
  170 + <span class="iconfont">&#xe629;</span>
  171 + <em>请填写发票抬头</em>
  172 + </span>
  173 + </div>
  174 + </li>
  175 + <li class="invoice-tax-num invoice-row company-row hide">
  176 + <span class="row-title">
  177 + <em>*</em>
  178 +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号:
  179 + </span>
  180 + <div class="row-content">
  181 + <input id="company-tax-num" class="company-tax-num" type="text" placeholder="请输入正确的纳税人识别号">
  182 + <span class="input-tip company-tax-tip red hide">
  183 + <span class="iconfont">&#xe629;</span>
  184 + <em>请填写纳税人识别号</em>
  185 + </span>
  186 + </div>
  187 + </li>
  188 + <li class="receiver invoice-row">
  189 + <span class="row-title">
  190 + <em>*</em>
  191 +&nbsp;&nbsp;&nbsp;码:
  192 + </span>
  193 + <div class="row-content">
  194 + <input id="receiver-phone" class="receiver-phone" type="text" placeholder="可通过手机号码在发票服务平台查询">
  195 + <span class="input-tip receiver-tip red hide">
  196 + <span class="iconfont">&#xe629;</span>
  197 + <em></em>
  198 + </span>
  199 + </div>
  200 + </li>
  201 + </ul>
  202 + </div>
  203 +</div>
1 <ul class="tabs clearfix"> 1 <ul class="tabs clearfix">
2 {{# tabs}} 2 {{# tabs}}
3 - <li {{#if active}}class="active"{{/if}}>  
4 - <a href="{{url}}">{{name}}</a> 3 + <li class="{{#if active}}active{{/if}}{{#if class}} {{class}}{{/if}}">
  4 + <a href="{{#if url}}{{url}}{{^}}javascript:;{{/if}}">{{name}}</a>
5 </li> 5 </li>
6 {{/ tabs}} 6 {{/ tabs}}
7 </ul> 7 </ul>
@@ -125,6 +125,7 @@ module.exports = class extends global.yoho.BaseModel { @@ -125,6 +125,7 @@ module.exports = class extends global.yoho.BaseModel {
125 125
126 req.session.TOKEN_ = publicToken; 126 req.session.TOKEN_ = publicToken;
127 req.session.LOGIN_UID_ = uid; 127 req.session.LOGIN_UID_ = uid;
  128 + req.session.USER_MOBILE = data.mobile;
128 129
129 res.cookie('_TOKEN', publicToken, { 130 res.cookie('_TOKEN', publicToken, {
130 domain: config.cookieDomain, 131 domain: config.cookieDomain,
@@ -19,15 +19,15 @@ module.exports = { @@ -19,15 +19,15 @@ module.exports = {
19 // test3 19 // test3
20 singleApi: 'http://api-test3.yohops.com:9999/', 20 singleApi: 'http://api-test3.yohops.com:9999/',
21 api: 'http://api-test3.yohops.com:9999/', 21 api: 'http://api-test3.yohops.com:9999/',
22 - service: 'http://service-test3.yohops.com:9999/',  
23 - serviceNotify: 'http://service-test3.yohops.com:9999/', 22 + service: 'http://api-test3.yohops.com:9999/',
  23 + serviceNotify: 'http://api-test3.yohops.com:9999/',
24 global: 'http://global-test-soa.yohops.com:9999/', 24 global: 'http://global-test-soa.yohops.com:9999/',
25 platformApi: 'http://192.168.102.48:8088/', 25 platformApi: 'http://192.168.102.48:8088/',
26 26
27 // test2 27 // test2
28 // singleApi: 'http://api-test2.yohops.com:9999/', 28 // singleApi: 'http://api-test2.yohops.com:9999/',
29 // api: 'http://api-test2.yohops.com:9999/', 29 // api: 'http://api-test2.yohops.com:9999/',
30 - // service: 'http://service-test2.yohops.com:9999/', 30 + // service: 'http://api-test2.yohops.com:9999/',
31 // serviceNotify: 'http://service-test2.yohops.com:9999/', 31 // serviceNotify: 'http://service-test2.yohops.com:9999/',
32 // global: 'http://global-test-soa.yohops.com:9999/', 32 // global: 'http://global-test-soa.yohops.com:9999/',
33 // platformApi: 'http://192.168.102.48:8088/', 33 // platformApi: 'http://192.168.102.48:8088/',
@@ -35,23 +35,23 @@ module.exports = { @@ -35,23 +35,23 @@ module.exports = {
35 // prod 35 // prod
36 // singleApi: 'http://single.yoho.cn/', 36 // singleApi: 'http://single.yoho.cn/',
37 // api: 'http://api.yoho.cn/', 37 // api: 'http://api.yoho.cn/',
38 - // service: 'http://service.yoho.cn/', 38 + // service: 'http://api.yoho.cn/',
39 // serviceNotify: 'http://service.yoho.cn/', 39 // serviceNotify: 'http://service.yoho.cn/',
40 // global: 'http://api-global.yohobuy.com/', 40 // global: 'http://api-global.yohobuy.com/',
41 // platformApi: 'http://172.16.6.210:8088/', 41 // platformApi: 'http://172.16.6.210:8088/',
42 42
43 // gray 43 // gray
44 - singleApi: 'http://single.gray.yohops.com/',  
45 - api: 'http://api.gray.yohops.com/',  
46 - service: 'http://service.gray.yohops.com/',  
47 - platformApi: 'http://172.16.6.210:8088/', 44 + // singleApi: 'http://single.gray.yohops.com/',
  45 + // api: 'http://api.gray.yohops.com/',
  46 + // service: 'http://api.gray.yohops.com/',
  47 + // platformApi: 'http://172.16.6.210:8088/',
48 48
49 // dev 49 // dev
50 // api: 'http://dev-api.yohops.com:9999/', 50 // api: 'http://dev-api.yohops.com:9999/',
51 - // service: 'http://dev-service.yohops.com:9999/', 51 + // service: 'http://dev-api.yohops.com:9999/',
52 // serviceNotify: 'http://dev-service.yohops.com:9999/', 52 // serviceNotify: 'http://dev-service.yohops.com:9999/',
53 // singleApi: 'http://dev-api.yohops.com:9999/', 53 // singleApi: 'http://dev-api.yohops.com:9999/',
54 - // platformApi: 'http://192.168.102.48:8088/',, 54 + // platformApi: 'http://192.168.102.48:8088/',
55 55
56 imSocket: 'ws://socket.yohobuy.com:10240', 56 imSocket: 'ws://socket.yohobuy.com:10240',
57 imCs: 'http://im.yohobuy.com/api', 57 imCs: 'http://im.yohobuy.com/api',
@@ -171,10 +171,10 @@ if (isProduction) { @@ -171,10 +171,10 @@ if (isProduction) {
171 domains: { 171 domains: {
172 singleApi: 'http://single.yoho.cn/', 172 singleApi: 'http://single.yoho.cn/',
173 api: 'http://api.yoho.yohoops.org/', 173 api: 'http://api.yoho.yohoops.org/',
174 - service: 'http://service.yoho.yohoops.org/', 174 + service: 'http://api.yoho.yohoops.org/',
175 search: 'http://search.yohoops.org/yohosearch/', 175 search: 'http://search.yohoops.org/yohosearch/',
176 global: 'http://api-global.yohobuy.com/', 176 global: 'http://api-global.yohobuy.com/',
177 - serviceNotify: 'http://service.yoho.cn/', 177 + serviceNotify: 'http://api.yoho.yohoops.org/',
178 imSocket: 'wss://imsocket.yohobuy.com:443', 178 imSocket: 'wss://imsocket.yohobuy.com:443',
179 imCs: 'https://imhttp.yohobuy.com/api', 179 imCs: 'https://imhttp.yohobuy.com/api',
180 platformApi: 'http://api.platform.yohoops.org', 180 platformApi: 'http://api.platform.yohoops.org',
@@ -223,10 +223,10 @@ if (isProduction) { @@ -223,10 +223,10 @@ if (isProduction) {
223 domains: { 223 domains: {
224 singleApi: process.env.TEST_API || 'http://192.168.102.31:8092/brower', 224 singleApi: process.env.TEST_API || 'http://192.168.102.31:8092/brower',
225 api: process.env.TEST_API || 'http://testapi.yoho.cn:28078/', 225 api: process.env.TEST_API || 'http://testapi.yoho.cn:28078/',
226 - service: process.env.TEST_SERVICE || 'http://testservice.yoho.cn:28077/', 226 + service: process.env.TEST_API || 'http://testapi.yoho.cn:28078/',
227 global: process.env.TEST_GOLBAL || 'http://global-test-soa.yohops.com:9999/', 227 global: process.env.TEST_GOLBAL || 'http://global-test-soa.yohops.com:9999/',
228 search: process.env.TEST_SEARCH || 'http://192.168.102.216:8080/yohosearch/', 228 search: process.env.TEST_SEARCH || 'http://192.168.102.216:8080/yohosearch/',
229 - serviceNotify: process.env.TEST_SERVICE || 'http://testservice.yoho.cn:28077/', 229 + serviceNotify: process.env.TEST_API || 'http://testapi.yoho.cn:28078/',
230 imSocket: 'ws://socket.yohobuy.com:10240', 230 imSocket: 'ws://socket.yohobuy.com:10240',
231 imCs: 'http://im.yohobuy.com/api' 231 imCs: 'http://im.yohobuy.com/api'
232 }, 232 },
@@ -76,7 +76,7 @@ module.exports = () => { @@ -76,7 +76,7 @@ module.exports = () => {
76 76
77 // uuid 77 // uuid
78 yoho.udid = (function() { 78 yoho.udid = (function() {
79 - let udid = req.cookies.udid; 79 + let udid = req.cookies._yasvd || req.cookies.udid;
80 80
81 if (!udid) { 81 if (!udid) {
82 udid = md5(yoho.clientIp); 82 udid = md5(yoho.clientIp);
@@ -33,6 +33,7 @@ module.exports = () => { @@ -33,6 +33,7 @@ module.exports = () => {
33 req.user.name = getName(userInfo); // 0 33 req.user.name = getName(userInfo); // 0
34 req.user.vip = getVip(userInfo); // 2 34 req.user.vip = getVip(userInfo); // 2
35 req.user.token = getToken(userInfo); // 3 35 req.user.token = getToken(userInfo); // 3
  36 + req.user.mobile = req.session.USER_MOBILE;
36 req.user.isStudent = req.cookies.isStudent || 0; 37 req.user.isStudent = req.cookies.isStudent || 0;
37 38
38 req.user.uid = { 39 req.user.uid = {
1 { 1 {
2 "name": "yohobuy-node", 2 "name": "yohobuy-node",
3 - "version": "6.0.20", 3 + "version": "6.0.21",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {
  1 +{{# usable_giftCards}}
  2 + <tr>
  3 + <td>{{cardCode}}</td>
  4 + <td>{{amount}}</td>
  5 + <td>{{remainAmount}}</td>
  6 + <td>{{dateStr}}</td>
  7 + <td><span class="gift-card-radio" data-id="{{cardCode}}" data-price="{{price}}"></span></td>
  8 + </tr>
  9 +{{/ usable_giftCards}}
  1 +<h2 class="title">发票详情</h2>
  2 +<p class="order-info">订单号:{{order_code}}</p>
  3 +<table>
  4 + <tr>
  5 + <td width="80"><span class="lt">发票类型</span></td>
  6 + <td>{{invoicesType}}</td>
  7 + </tr>
  8 + <tr>
  9 + <td><span class="lt">发票内容</span></td>
  10 + <td>{{invoice_content}}</td>
  11 + </tr>
  12 + <tr>
  13 + <td><span class="lt">发票抬头</span></td>
  14 + <td>{{title}}</td>
  15 + </tr>
  16 + {{#if buyerTaxNumber}}
  17 + <tr>
  18 + <td><span class="lt">税号</span></td>
  19 + <td>{{buyerTaxNumber}}</td>
  20 + </tr>
  21 + {{/if}}
  22 + <tr>
  23 + <td colspan=2 class="line"></td>
  24 + </tr>
  25 + <tr>
  26 + <td><span class="lt">收票人姓名</span></td>
  27 + <td>{{userName}}</td>
  28 + </tr>
  29 + <tr>
  30 + <td><span class="lt">收票人手机</span></td>
  31 + <td>{{receiverMobile}}</td>
  32 + </tr>
  33 +</table>
  34 +{{#if showInvoice}}
  35 + <p>
  36 + <a href="{{pdfUrl}}" class="download-btn">下载电子发票</a>
  37 + </p>
  38 +{{/if}}
@@ -22,12 +22,16 @@ var payWay, @@ -22,12 +22,16 @@ var payWay,
22 multiPackage, 22 multiPackage,
23 coupon, 23 coupon,
24 yohoCoin, 24 yohoCoin,
  25 + giftCard,
25 refund; 26 refund;
26 27
  28 +var lastOrderPrice = $orderPrice.data('price');
  29 +
27 var address = require('./order/address'), 30 var address = require('./order/address'),
28 invoice = require('./order/invoice'), 31 invoice = require('./order/invoice'),
29 esaypayInfo = require('./order/easypay'); 32 esaypayInfo = require('./order/easypay');
30 33
  34 +var giftCardTpl = require('hbs/cart/ensure-gift-card-list.hbs');
31 var coinTpl = Hbs.compile($('#yoho-coin-tpl').html()); 35 var coinTpl = Hbs.compile($('#yoho-coin-tpl').html());
32 var promotionTpl = Hbs.compile($('#promotion-list-tpl').html()); 36 var promotionTpl = Hbs.compile($('#promotion-list-tpl').html());
33 37
@@ -97,6 +101,11 @@ function compute(coin, cb) { @@ -97,6 +101,11 @@ function compute(coin, cb) {
97 reqData.redEnvelopes = order.redEnvelopes; 101 reqData.redEnvelopes = order.redEnvelopes;
98 } 102 }
99 103
  104 + // 礼品卡
  105 + if (order.giftCard) {
  106 + reqData.giftCard = order.giftCard;
  107 + }
  108 +
100 if (esaypayInfo) { 109 if (esaypayInfo) {
101 if (order.sku) { 110 if (order.sku) {
102 reqData.sku = order.sku; 111 reqData.sku = order.sku;
@@ -135,11 +144,15 @@ function compute(coin, cb) { @@ -135,11 +144,15 @@ function compute(coin, cb) {
135 yohoCoin.$el.html(coinTpl(res)); 144 yohoCoin.$el.html(coinTpl(res));
136 145
137 // update last order amount 146 // update last order amount
  147 + lastOrderPrice = res.last_order_amount;
138 $orderPrice.html('¥ ' + res.last_order_amount); 148 $orderPrice.html('¥ ' + res.last_order_amount);
139 149
140 // update promotion formula list 150 // update promotion formula list
141 $balanceDetail.html(promotionTpl(res)); 151 $balanceDetail.html(promotionTpl(res));
142 152
  153 + // update giftCard use status
  154 + giftCard.setUseStatus(lastOrderPrice);
  155 +
143 } 156 }
144 157
145 // callback 158 // callback
@@ -674,6 +687,93 @@ yohoCoin = { @@ -674,6 +687,93 @@ yohoCoin = {
674 } 687 }
675 }; 688 };
676 689
  690 +// 礼品卡
  691 +giftCard = {
  692 + $el: $('#use-gift-card'),
  693 + init: function() {
  694 + if (!this.$el.length) {
  695 + return;
  696 + }
  697 +
  698 + this.$giftCardWrap = this.$el.next();
  699 +
  700 + this.getList();
  701 + this.eventBind();
  702 + },
  703 + getList: function() {
  704 + var that = this;
  705 +
  706 + $.ajax({
  707 + type: 'GET',
  708 + url: '/cart/ensure/giftcards'
  709 + }).then(function(data) {
  710 + if (data.code === 200) {
  711 + if (data.data && data.data.usable_giftCards && data.data.usable_giftCards.length) {
  712 + that.$el.removeClass('hide').next().removeClass('hide');
  713 + $('.can-use-tip', that.$el).text('(' + data.data.usable_giftCards.length + '张可用)');
  714 + }
  715 +
  716 + if (data.data.usable_giftCards.length) {
  717 + $('tbody', that.$giftCardWrap).html(giftCardTpl(data.data));
  718 +
  719 + that.$radios = $('.gift-card-radio', that.$giftCardWrap);
  720 + }
  721 +
  722 + that.checkContent = '<h2>安全验证</h2>' +
  723 + '<p class="tip-info">您正在使用礼品卡支付,为了保证您的账户安全,需要进行安全验证。</p>' +
  724 + '<p class="receiver-info">验证码已发送至' + (data.data.userMobile || '您绑定的') + '手机号</p>' +
  725 + '<p><input type="text" placeholder="短信验证码" maxlength="8"><span class="send-sms">获取验证码</span></p>';
  726 + }
  727 + });
  728 + },
  729 + eventBind: function() {
  730 + var that = this;
  731 +
  732 + this.$giftCardWrap.on('click', '.gift-card-radio', function() {
  733 + var $this = $(this);
  734 +
  735 + if ($this.hasClass('disabled')) {
  736 + return;
  737 + }
  738 +
  739 + if ($this.hasClass('on')) {
  740 + // 取消使用礼品卡,设置其他礼品卡可用
  741 + that.setUseStatus(2);
  742 + } else if (+$this.data('price') >= lastOrderPrice * 1) { // 已选礼品卡总价大于订单总价,设置其他礼品卡不可选
  743 + that.setUseStatus();
  744 + }
  745 +
  746 + $this.toggleClass('on');
  747 + that.changeCardUse();
  748 + });
  749 + },
  750 + changeCardUse: function() {
  751 + var codes = [];
  752 +
  753 + if (!this.$radios) {
  754 + return;
  755 + }
  756 +
  757 + this.$radios.filter('.on').each(function() {
  758 + codes.push($(this).data('id'));
  759 + });
  760 +
  761 + order.giftCard = codes.join(',');
  762 + compute(order.coin);
  763 + },
  764 + setUseStatus: function(price) {
  765 + if (!this.$radios) {
  766 + return;
  767 + }
  768 +
  769 + if (price && price * 1 > 0) {
  770 + this.$radios.filter('.disable').removeClass('disable');
  771 + } else {
  772 + this.$radios.not('.on').addClass('disable');
  773 + }
  774 + }
  775 +};
  776 +
677 // 退换货提示 777 // 退换货提示
678 refund = { 778 refund = {
679 $el: $('.special-tip'), 779 $el: $('.special-tip'),
@@ -691,8 +791,6 @@ refund = { @@ -691,8 +791,6 @@ refund = {
691 } 791 }
692 }; 792 };
693 793
694 -  
695 -  
696 $('.locker-switch').click(function() { 794 $('.locker-switch').click(function() {
697 var $this = $(this), 795 var $this = $(this),
698 $par = $this.parent(); 796 $par = $this.parent();
@@ -740,58 +838,19 @@ $('.locker-switch').click(function() { @@ -740,58 +838,19 @@ $('.locker-switch').click(function() {
740 }); 838 });
741 }()); 839 }());
742 840
743 -$('#remark-box').on('keyup', '.note-text', function() {  
744 - var $this = $(this);  
745 - var val = $.trim($this.val());  
746 -  
747 - if (val) {  
748 - $this.addClass('has-text');  
749 -  
750 - if (val.length > 100) {  
751 - val = val.substring(0, 99);  
752 - $this.val(val);  
753 - }  
754 -  
755 - order.remark = val;  
756 - } else {  
757 - $this.removeClass('has-text');  
758 - }  
759 -}).on('click', '.radio-btn', function() {  
760 - var $this = $(this);  
761 -  
762 - if ($this.hasClass('on')) {  
763 - return;  
764 - }  
765 -  
766 - if ($this.hasClass('unprint')) {  
767 - order.printPrice = 'N';  
768 - } else {  
769 - order.printPrice = 'Y';  
770 - }  
771 -  
772 - $this.siblings('.on').removeClass('on');  
773 - $this.addClass('on');  
774 -});  
775 -  
776 -$('#order-submit').click(function() {  
777 - var invoiceInfo = invoice.getInvoice();  
778 -  
779 - order.addressId = address.getAddress();  
780 -  
781 - // 发票信息  
782 - if (invoiceInfo) {  
783 - $.extend(order, invoiceInfo);  
784 - }  
785 -  
786 - // 订单参数校验  
787 - if (!validateOrderInfo(order)) {  
788 - return;  
789 - } 841 +function sendCkeckSms() {
  842 + return $.ajax({
  843 + type: 'POST',
  844 + url: '/cart/property/checksms',
  845 + data: {giftCard: order.giftCard}
  846 + });
  847 +}
790 848
  849 +function submitOrder(reqData) {
791 $.ajax({ 850 $.ajax({
792 type: 'POST', 851 type: 'POST',
793 url: '/cart/ensure/submit', 852 url: '/cart/ensure/submit',
794 - data: order 853 + data: reqData
795 }).then(function(data) { 854 }).then(function(data) {
796 var rdata, subTip, newUser, 855 var rdata, subTip, newUser,
797 tongJi = { 856 tongJi = {
@@ -800,6 +859,7 @@ $('#order-submit').click(function() { @@ -800,6 +859,7 @@ $('#order-submit').click(function() {
800 sku: [], 859 sku: [],
801 py: [] 860 py: []
802 }; 861 };
  862 + var errAlert;
803 863
804 if (data.code === 200) { 864 if (data.code === 200) {
805 rdata = data.data; 865 rdata = data.data;
@@ -877,9 +937,131 @@ $('#order-submit').click(function() { @@ -877,9 +937,131 @@ $('#order-submit').click(function() {
877 location.href = rdata.url; 937 location.href = rdata.url;
878 } 938 }
879 } else if (data.message) { 939 } else if (data.message) {
880 - new dialog.Alert(data.message).show(); 940 + errAlert = new dialog.Alert(data.message);
  941 + errAlert.$el.addClass('ensure-alert');
  942 + errAlert.show();
881 } 943 }
882 }); 944 });
  945 +}
  946 +
  947 +$('#remark-box').on('keyup', '.note-text', function() {
  948 + var $this = $(this);
  949 + var val = $.trim($this.val());
  950 +
  951 + if (val) {
  952 + $this.addClass('has-text');
  953 +
  954 + if (val.length > 100) {
  955 + val = val.substring(0, 99);
  956 + $this.val(val);
  957 + }
  958 +
  959 + order.remark = val;
  960 + } else {
  961 + $this.removeClass('has-text');
  962 + }
  963 +}).on('click', '.radio-btn', function() {
  964 + var $this = $(this);
  965 +
  966 + if ($this.hasClass('on')) {
  967 + return;
  968 + }
  969 +
  970 + if ($this.hasClass('unprint')) {
  971 + order.printPrice = 'N';
  972 + } else {
  973 + order.printPrice = 'Y';
  974 + }
  975 +
  976 + $this.siblings('.on').removeClass('on');
  977 + $this.addClass('on');
  978 +});
  979 +
  980 +$('#order-submit').click(function() {
  981 + var invoiceInfo = invoice.getInvoice();
  982 + var checkDg;
  983 +
  984 + order.addressId = address.getAddress();
  985 +
  986 + // 发票信息
  987 + if (invoiceInfo) {
  988 + $.extend(order, invoiceInfo);
  989 + }
  990 +
  991 + // 订单参数校验
  992 + if (!validateOrderInfo(order)) {
  993 + return;
  994 + }
  995 +
  996 + // 使用礼品卡时候进行短信校验
  997 + if (order.giftCard) {
  998 + checkDg = new dialog.Dialog({
  999 + content: giftCard.checkContent || '',
  1000 + className: 'gift-card-check-dialog',
  1001 + btns: [{
  1002 + id: 'check-cancel',
  1003 + btnClass: ['check-cancel'],
  1004 + name: '取消',
  1005 + cb: function() {
  1006 + checkDg.close();
  1007 + }
  1008 + }, {
  1009 + id: 'check-sure',
  1010 + btnClass: ['check-sure'],
  1011 + name: '确定',
  1012 + cb: function() {
  1013 + order.checkCode = $('input', checkDg.$el).val();
  1014 +
  1015 + if (order.checkCode) {
  1016 + submitOrder(order);
  1017 + checkDg.close();
  1018 + }
  1019 + }
  1020 + }]
  1021 + });
  1022 +
  1023 + checkDg.$sendBtn = $('.send-sms', checkDg.$el);
  1024 + checkDg.sendSms = function() {
  1025 + var that = this;
  1026 +
  1027 + if (!this.$sendBtn || this.seconds > 0) {
  1028 + return;
  1029 + }
  1030 +
  1031 + sendCkeckSms(); // 发送验证码
  1032 +
  1033 + if (!this.seconds || this.seconds < 1) {
  1034 + this.seconds = 59;
  1035 + }
  1036 +
  1037 + this.timer && clearInterval(this.timer);
  1038 +
  1039 + this.$sendBtn.text('重新获取(' + (this.seconds--) + ')').addClass('timer');
  1040 +
  1041 + this.timer = setInterval(function() {
  1042 + if (that.seconds > 0) {
  1043 + that.$sendBtn.text('重新获取(' + (that.seconds--) + ')').addClass('timer');
  1044 + } else {
  1045 + that.$sendBtn.text('重新获取').removeClass('timer');
  1046 + clearInterval(that.timer);
  1047 + }
  1048 + }, 1000);
  1049 +
  1050 + return this;
  1051 + };
  1052 +
  1053 + checkDg.$sendBtn.click(function() {
  1054 + checkDg.sendSms();
  1055 + });
  1056 +
  1057 + checkDg.sendSms().show();
  1058 +
  1059 + return;
  1060 + } else {
  1061 + order.checkCode && delete order.checkCode;
  1062 + }
  1063 +
  1064 + submitOrder(order);
883 }); 1065 });
884 1066
885 payWay.init(); 1067 payWay.init();
@@ -887,6 +1069,7 @@ deliveryWay.init(); @@ -887,6 +1069,7 @@ deliveryWay.init();
887 multiPackage.init(); 1069 multiPackage.init();
888 coupon.init(); 1070 coupon.init();
889 yohoCoin.init(); 1071 yohoCoin.init();
  1072 +giftCard.init();
890 refund.init(); 1073 refund.init();
891 1074
892 // 获取用户是否新客(品众统计)写cookie 1075 // 获取用户是否新客(品众统计)写cookie
@@ -11,9 +11,14 @@ var yas = require('../common/data-yas'), @@ -11,9 +11,14 @@ var yas = require('../common/data-yas'),
11 var $orderPrice = $('#order-price'); 11 var $orderPrice = $('#order-price');
12 var order = {}; 12 var order = {};
13 13
14 -var yohoCoin; 14 +var yohoCoin,
  15 + giftCard;
  16 +
  17 +var lastOrderPrice = $orderPrice.data('price');
15 var submitting = false; 18 var submitting = false;
16 19
  20 +var giftCardTpl = require('hbs/cart/ensure-gift-card-list.hbs');
  21 +
17 require('../common'); 22 require('../common');
18 require('../simple-header'); 23 require('../simple-header');
19 24
@@ -85,7 +90,11 @@ function compute(coin) { @@ -85,7 +90,11 @@ function compute(coin) {
85 order.coin = result.data.usedCoinNum; 90 order.coin = result.data.usedCoinNum;
86 yohoCoin.maxCoin = result.data.canUseCoinNum; 91 yohoCoin.maxCoin = result.data.canUseCoinNum;
87 92
88 - $orderPrice.html('¥ ' + result.data.last_order_amount); 93 + lastOrderPrice = result.data.last_order_amount;
  94 +
  95 + $orderPrice.html('¥ ' + lastOrderPrice);
  96 +
  97 + giftCard.setUseStatus(lastOrderPrice);
89 } 98 }
90 }); 99 });
91 } 100 }
@@ -133,44 +142,213 @@ yohoCoin = { @@ -133,44 +142,213 @@ yohoCoin = {
133 } 142 }
134 }; 143 };
135 144
136 -$('.locker-switch').click(function() {  
137 - var $this = $(this),  
138 - $par = $this.parent(); 145 +// 礼品卡
  146 +giftCard = {
  147 + $el: $('#use-gift-card'),
  148 + init: function() {
  149 + if (!this.$el.length) {
  150 + return;
  151 + }
139 152
140 - $par.toggleClass('open');  
141 -}); 153 + this.$giftCardWrap = this.$el.next();
142 154
  155 + this.getList();
  156 + this.eventBind();
  157 + },
  158 + getList: function() {
  159 + var that = this;
143 160
144 -$('#order-submit').on('click', function() { 161 + $.ajax({
  162 + type: 'GET',
  163 + url: '/cart/ensure/giftcards'
  164 + }).then(function(data) {
  165 + if (data.code === 200) {
  166 + if (data.data && data.data.usable_giftCards && data.data.usable_giftCards.length) {
  167 + that.$el.removeClass('hide').next().removeClass('hide');
  168 + $('.can-use-tip', that.$el).text('(' + data.data.usable_giftCards.length + '张可用)');
  169 + }
  170 +
  171 + if (data.data.usable_giftCards.length) {
  172 + $('tbody', that.$giftCardWrap).html(giftCardTpl(data.data));
  173 +
  174 + that.$radios = $('.gift-card-radio', that.$giftCardWrap);
  175 + }
  176 +
  177 + that.checkContent = '<h2>安全验证</h2>' +
  178 + '<p class="tip-info">您正在使用礼品卡支付,为了保证您的账户安全,需要进行安全验证。</p>' +
  179 + '<p class="receiver-info">验证码已发送至' + (data.data.userMobile || '您绑定的') + '手机号</p>' +
  180 + '<p><input type="text" placeholder="短信验证码" maxlength="8"><span class="send-sms">获取验证码</span></p>';
  181 + }
  182 + });
  183 + },
  184 + eventBind: function() {
  185 + var that = this;
  186 +
  187 + this.$giftCardWrap.on('click', '.gift-card-radio', function() {
145 var $this = $(this); 188 var $this = $(this);
146 189
147 - if (submitting) { 190 + if ($this.hasClass('disabled')) {
148 return; 191 return;
149 } 192 }
150 193
151 - order = handleOrderInfo(order); 194 + if ($this.hasClass('on')) {
  195 + // 取消使用礼品卡,设置其他礼品卡可用
  196 + that.setUseStatus(2);
  197 + } else if (+$this.data('price') >= lastOrderPrice * 1) { // 已选礼品卡总价大于订单总价,设置其他礼品卡不可选
  198 + that.setUseStatus();
  199 + }
152 200
153 - if (!validateUserInfo(order)) { 201 + $this.toggleClass('on');
  202 + that.changeCardUse();
  203 + });
  204 + },
  205 + changeCardUse: function() {
  206 + var codes = [];
  207 +
  208 + if (!this.$radios) {
154 return; 209 return;
155 } 210 }
156 211
  212 + this.$radios.filter('.on').each(function() {
  213 + codes.push($(this).data('id'));
  214 + });
  215 +
  216 + order.giftCard = codes.join(',');
  217 + compute(order.coin);
  218 + },
  219 + setUseStatus: function(price) {
  220 + if (!this.$radios) {
  221 + return;
  222 + }
  223 +
  224 + if (price && price * 1 > 0) {
  225 + this.$radios.filter('.disable').removeClass('disable');
  226 + } else {
  227 + this.$radios.not('.on').addClass('disable');
  228 + }
  229 + }
  230 +};
  231 +
  232 +function submitOrder(reqData, url) {
157 submitting = true; 233 submitting = true;
158 $.ajax({ 234 $.ajax({
159 type: 'POST', 235 type: 'POST',
160 url: '/cart/ticketSubmit', 236 url: '/cart/ticketSubmit',
161 - data: order 237 + data: reqData
162 }).then(function(data) { 238 }).then(function(data) {
163 if (data.code === 200) { 239 if (data.code === 200) {
164 window.location.href = data.data.refer; 240 window.location.href = data.data.refer;
165 } else if (data.code === 500) { 241 } else if (data.code === 500) {
166 - errorInfo(data.message, $this.data('url')); 242 + errorInfo(data.message, url);
  243 + } else {
  244 + new dialog.Alert(data.message || '网络异常~').show();
167 } 245 }
168 }).always(function() { 246 }).always(function() {
169 submitting = false; 247 submitting = false;
170 }); 248 });
  249 +}
  250 +
  251 +function sendCkeckSms() {
  252 + return $.ajax({
  253 + type: 'POST',
  254 + url: '/cart/property/checksms',
  255 + data: {giftCard: order.giftCard}
  256 + });
  257 +}
  258 +
  259 +$('.locker-switch').click(function() {
  260 + var $this = $(this),
  261 + $par = $this.parent();
  262 +
  263 + $par.toggleClass('open');
  264 +});
  265 +
  266 +$('#order-submit').on('click', function() {
  267 + var errUrl = $(this).data('url'),
  268 + checkDg;
  269 +
  270 + if (submitting) {
  271 + return;
  272 + }
  273 +
  274 + order = handleOrderInfo(order);
  275 +
  276 + if (!validateUserInfo(order)) {
  277 + return;
  278 + }
  279 +
  280 + // 使用礼品卡时候进行短信校验
  281 + if (order.giftCard) {
  282 + checkDg = new dialog.Dialog({
  283 + content: giftCard.checkContent || '',
  284 + className: 'gift-card-check-dialog',
  285 + btns: [{
  286 + id: 'check-cancel',
  287 + btnClass: ['check-cancel'],
  288 + name: '取消',
  289 + cb: function() {
  290 + checkDg.close();
  291 + }
  292 + }, {
  293 + id: 'check-sure',
  294 + btnClass: ['check-sure'],
  295 + name: '确定',
  296 + cb: function() {
  297 + order.checkCode = $('input', checkDg.$el).val();
  298 +
  299 + if (order.checkCode) {
  300 + submitOrder(order, errUrl);
  301 + checkDg.close();
  302 + }
  303 + }
  304 + }]
  305 + });
  306 +
  307 + checkDg.$sendBtn = $('.send-sms', checkDg.$el);
  308 + checkDg.sendSms = function() {
  309 + var that = this;
  310 +
  311 + if (!this.$sendBtn || this.seconds > 0) {
  312 + return;
  313 + }
  314 +
  315 + sendCkeckSms(); // 发送验证码
  316 +
  317 + if (!this.seconds || this.seconds < 1) {
  318 + this.seconds = 59;
  319 + }
  320 +
  321 + this.timer && clearInterval(this.timer);
  322 +
  323 + this.$sendBtn.text('重新获取(' + (this.seconds--) + ')').addClass('timer');
  324 +
  325 + this.timer = setInterval(function() {
  326 + if (that.seconds > 0) {
  327 + that.$sendBtn.text('重新获取(' + (that.seconds--) + ')').addClass('timer');
  328 + } else {
  329 + that.$sendBtn.text('重新获取').removeClass('timer');
  330 + clearInterval(that.timer);
  331 + }
  332 + }, 1000);
  333 +
  334 + return this;
  335 + };
  336 +
  337 + checkDg.$sendBtn.click(function() {
  338 + checkDg.sendSms();
  339 + });
  340 +
  341 + checkDg.sendSms().show();
  342 +
  343 + return;
  344 + }
  345 +
  346 + order.checkCode && delete order.checkCode;
  347 + submitOrder(order, errUrl);
171 }); 348 });
172 349
173 yohoCoin.init(); 350 yohoCoin.init();
  351 +giftCard.init();
174 352
175 // 获取用户是否新客(品众统计)写cookie 353 // 获取用户是否新客(品众统计)写cookie
176 $.ajax({type: 'GET', url: '/home/newuser'}); 354 $.ajax({type: 'GET', url: '/home/newuser'});
  1 +/**
  2 + * 我的发票
  3 + * @author: yyq<yanqing.yang@yoho.cn>
  4 + * @date: 201/2/17
  5 + */
  6 +
  7 +var $ = require('yoho-jquery');
  8 +var dialog = require('../common/dialog');
  9 +
  10 +var Dialog = dialog.Dialog,
  11 + Alert = dialog.Alert;
  12 +
  13 +var $hideDg = $('#invoice-hide-dg');
  14 +
  15 +var detailTpl = require('hbs/home/invoice/detail.hbs');
  16 +var invoiceTpl = $hideDg.html();
  17 +
  18 +var defaultReceiver;
  19 +
  20 +require('../common');
  21 +
  22 +$hideDg.remove();
  23 +
  24 +function bindSupplyDialogEvent($el) {
  25 + var $titleWrap = $('.invoice-title', $el),
  26 + $personalRow = $('.personal-row', $el),
  27 + $companyRow = $('.company-row', $el);
  28 +
  29 + $titleWrap.on('click', '.radio-btn', function() {
  30 + var $this = $(this),
  31 + id = $this.data('id');
  32 +
  33 + if ($this.hasClass('on')) {
  34 + return;
  35 + }
  36 +
  37 + if (id * 1 === 2) {
  38 + $companyRow.removeClass('hide');
  39 + $personalRow.addClass('hide');
  40 + } else {
  41 + $companyRow.addClass('hide');
  42 + $personalRow.removeClass('hide');
  43 + }
  44 +
  45 + $titleWrap.find('.on').removeClass('on');
  46 + $this.addClass('on');
  47 + });
  48 +}
  49 +
  50 +function packInvoiceInfo($el) {
  51 + var resData = { // 5.8.1需求,只支持电子发票(type: 2),发票内容只能开明细(id:12)
  52 + invocesType: 2,
  53 + contentId: 12,
  54 + contentName: '明细'
  55 + },
  56 + receiver = $('#receiver-phone', $el).val();
  57 +
  58 + resData.titleId = $('.invoice-title .on', $el).data('id') || 1;
  59 +
  60 + if (resData.titleId * 1 === 1) {
  61 + resData.titleName = $.trim($('#personal-name', $el).val()) || '个人';
  62 + } else {
  63 + resData.titleName = $.trim($('#company-name', $el).val());
  64 + resData.taxNumber = $.trim($('#company-tax-num', $el).val());
  65 + }
  66 +
  67 + if (receiver) {
  68 + resData.receiver = receiver;
  69 + }
  70 +
  71 + return resData;
  72 +}
  73 +
  74 +function validateInvoice($el, info) {
  75 + var pass = true;
  76 + var $receiverTip;
  77 +
  78 + // 发票抬头
  79 + if (!info.titleName) {
  80 + pass = false;
  81 + $('.company-name-tip', $el).removeClass('hide');
  82 + } else {
  83 + $('.company-name-tip', $el).addClass('hide');
  84 + }
  85 +
  86 + if (info.titleId === 2) {
  87 + if (!info.taxNumber) {
  88 + pass = false;
  89 + $('.company-tax-tip', $el).removeClass('hide');
  90 + } else {
  91 + $('.company-tax-tip', $el).addClass('hide');
  92 + }
  93 + }
  94 +
  95 + // 收票人手机号
  96 + if (info.invocesType * 1 === 2) {
  97 + $receiverTip = $('.receiver-tip', $el);
  98 +
  99 + if (!info.receiver) {
  100 + $receiverTip.removeClass('hide').find('em').html('请填写手机号码');
  101 + pass = false;
  102 + } else if (defaultReceiver && info.receiver === defaultReceiver.hide) {
  103 + $receiverTip.addClass('hide');
  104 + } else if (!/^[0-9]{11}$/.test(info.receiver)) {
  105 + $receiverTip.removeClass('hide').find('em').html('请输入正确手机号');
  106 + pass = false;
  107 + } else {
  108 + $receiverTip.addClass('hide');
  109 + }
  110 + }
  111 +
  112 + return pass;
  113 +}
  114 +
  115 +function viewInvoice(code) {
  116 + if (!code) {
  117 + return;
  118 + }
  119 +
  120 + $.ajax({
  121 + url: '/home/invoice/detail',
  122 + type: 'GET',
  123 + data: {orderCode: code}
  124 + }).done(function(res) {
  125 + if (res.code !== 200) {
  126 + return;
  127 + }
  128 +
  129 + new Dialog({
  130 + className: 'invoice-me-page invoice-detail-dialog',
  131 + content: detailTpl(res.data)
  132 + }).show();
  133 + });
  134 +}
  135 +
  136 +function supplyInvoice(info, cb) {
  137 + $.ajax({
  138 + url: '/home/invoice/supply',
  139 + type: 'POST',
  140 + data: info
  141 + }).done(function(res) {
  142 + var _dg, _btn;
  143 +
  144 + cb && cb(res); // eslint-disable-line
  145 +
  146 + if (res.code === 200) {
  147 + if (res.data.issueType === 2) {
  148 + _btn = {
  149 + name: '查看发票',
  150 + cb: function() {
  151 + viewInvoice(res.data.order_code);
  152 + }
  153 + };
  154 + } else {
  155 + _btn = {name: '我知道了'};
  156 + }
  157 +
  158 + _dg = new Dialog({
  159 + className: 'invoice-me-page supply-success-dialog',
  160 + content: '<h2>提交成功</h2><p>您的服务申请已提交,您可以在我的发票中下载电子发票</p>',
  161 + btns: [{
  162 + id: 'close-dg',
  163 + name: _btn.name,
  164 + btnClass: ['close-dg'],
  165 + cb: function() {
  166 + _dg.close();
  167 + _btn.cb && _btn.cb();
  168 + }
  169 + }]
  170 + }).show();
  171 + }
  172 + });
  173 +}
  174 +
  175 +$('#me-invoice-orders').on('click', '.supply-invoice', function() {
  176 + var $this = $(this);
  177 + var dg = new Dialog({
  178 + className: 'invoice-me-page invoice-supply-dialog',
  179 + content: invoiceTpl,
  180 + btns: [{
  181 + id: 'sure-apply',
  182 + name: '提交',
  183 + btnClass: ['sure-apply'],
  184 + cb: function() {
  185 + var info = packInvoiceInfo(dg.$el);
  186 + var errAlert;
  187 +
  188 + if (!validateInvoice(dg.$el, info)) {
  189 + return;
  190 + }
  191 +
  192 + info.orderCode = $this.data('id');
  193 + supplyInvoice(info, function(data) {
  194 + if (data.code !== 200) {
  195 + dg.$el.hide();
  196 + errAlert = new Alert(data.message).show();
  197 + errAlert.$el.on('click', '.close', function() {
  198 + dg.$el.show();
  199 + }).on('click', '.alert-sure', function() {
  200 + dg.$el.show();
  201 + });
  202 + return;
  203 + }
  204 +
  205 + dg.close();
  206 +
  207 + if (+data.issueType === 2) {
  208 + $this.removeClass('supply-invoice').addClass('view-invoice').text('查看发票');
  209 + } else {
  210 + $this.removeClass('supply-invoice').text('开票中');
  211 + }
  212 + });
  213 + }
  214 + }, {
  215 + id: 'cancel-apply',
  216 + name: '取消',
  217 + btnClass: ['cancel-apply'],
  218 + cb: function() {
  219 + dg.close();
  220 + }
  221 + }]
  222 + }).show();
  223 +
  224 + // 事件绑定
  225 + bindSupplyDialogEvent(dg.$el);
  226 +}).on('click', '.view-invoice', function() {
  227 + viewInvoice($(this).data('id'));
  228 +});
  1 +var $ = require('yoho-jquery'),
  2 + Hbs = require('yoho-handlebars'),
  3 + dialog = require('../common/dialog');
  4 +var meGift;
  5 +
  6 +require('yoho-jquery-placeholder');
  7 +require('../common');
  8 +
  9 +meGift = {
  10 + isFlag: false, // 防止用户频繁点击
  11 + // 验证邮箱模板
  12 + emailTpl: Hbs.compile($('#verify-email-tpl').html()),
  13 +
  14 + // 绑定手机模板
  15 + mobileTpl: Hbs.compile($('#verify-mobile-tpl').html()),
  16 +
  17 + // 激活礼品卡模板
  18 + giftTpl: Hbs.compile($('#activate-gift-tpl').html()),
  19 +
  20 + // 消费明细模板
  21 + detailGiftTpl: Hbs.compile($('#detail-gift-tpl').html()),
  22 +
  23 + // 添加礼品卡按钮
  24 + $addGift: $('.add-gift'),
  25 +
  26 + // 是否绑定手机
  27 + isBinMobile: +$('.me-content').data('is-bin-mobile'),
  28 +
  29 + // 用户邮箱
  30 + userEmail: $('.me-content').data('email'),
  31 +
  32 + init: function() {
  33 + var that = this;
  34 +
  35 + // 添加礼品卡
  36 + this.$addGift.click(function() {
  37 + if (that.isBinMobile) {
  38 + that.activateGift();
  39 + } else {
  40 + that.getMobileCode();
  41 + }
  42 + });
  43 +
  44 + // 显示手机区号或类型下拉列表
  45 + $('body').on('click', '.mobile-area,.gift-filter', function() {
  46 + $(this).find('.ul-list').toggle();
  47 + });
  48 +
  49 + // 选择手机区号
  50 + $('body').on('click', '.mobile-area-list', function(event) {
  51 + var $li = $(event.target).closest('li');
  52 +
  53 + $('.mobile-area').find('em').text($li.data('cc'));
  54 + });
  55 +
  56 + // 消费明细
  57 + $('.me-gift-table').on('click', '.info-list', function() {
  58 +
  59 + new dialog.Dialog({
  60 + content: that.detailGiftTpl({}),
  61 + className: 'me-page me-gift-page me-gift-confirm'
  62 + }).show();
  63 +
  64 + that.infoList('?' + $.param({
  65 + cardCode: $(this).closest('.me-gift-tr').data('card-code')
  66 + }));
  67 + });
  68 +
  69 + // 消费明细-选择类型筛选
  70 + $('body').on('click', '.gift-filter ul', function(event) {
  71 + var $li = $(event.target).closest('li');
  72 +
  73 + $('.gift-filter').find('em').text($li.text());
  74 + that.infoList('?' + $.param({
  75 + cardCode: $('.info-gift-header').data('card-code'),
  76 + type: $li.data('cc')
  77 + }));
  78 + });
  79 +
  80 + // 消费明细翻页
  81 + $('body').on('click', '.detail-gift-content .pager a', function() {
  82 + if ($(this).hasClass('cur')) {
  83 + return false;
  84 + }
  85 +
  86 + that.infoList($(this).attr('href'));
  87 + return false;
  88 + });
  89 + },
  90 +
  91 + postAjax: function(url, data, verifyData) {
  92 + var deferred = $.Deferred(); // eslint-disable-line
  93 + var that = this;
  94 + var x;
  95 +
  96 + if (that.isFlag) {
  97 + return deferred.resolve({
  98 + code: 401,
  99 + message: '数据请求中...'
  100 + });
  101 + }
  102 +
  103 + if (verifyData) {
  104 + for (x in verifyData) {
  105 + if (!data[x]) {
  106 + that.meAlert(verifyData[x], false);
  107 + return deferred.resolve({
  108 + code: 401,
  109 + message: verifyData[x]
  110 + });
  111 + }
  112 + }
  113 + }
  114 +
  115 + that.isFlag = true;
  116 +
  117 + return $.ajax({
  118 + url: url,
  119 + type: 'post',
  120 + data: data
  121 + }).then(function(res) {
  122 + if (res.code !== 200) {
  123 + that.meAlert(res.message, false);
  124 + }
  125 +
  126 + that.isFlag = false;
  127 + return res;
  128 + }, function() {
  129 + that.isFlag = false;
  130 + });
  131 + },
  132 +
  133 + intTimer: function($dom) {
  134 + var intTime = 60;
  135 + var intval = setInterval(function() {
  136 +
  137 + if (intTime-- <= 0) {
  138 + clearInterval(intval);
  139 + $dom.removeClass('int-timer').html('获取短信验证码');
  140 + return false;
  141 + }
  142 +
  143 + $dom.html(intTime + 's');
  144 + }, 1000);
  145 +
  146 + $dom.addClass('int-timer');
  147 + $dom.html(intTime + 's');
  148 + },
  149 +
  150 + // 获取邮箱验证码
  151 + getEmailCode: function() {
  152 + var that = this;
  153 +
  154 + this.postAjax('/home/megift/sendEmailCode', {
  155 + email: this.userEmail
  156 + }, {}).then(function(res) {
  157 + if (res.code === 200) {
  158 + that.intTimer($('.email-btn'));
  159 + }
  160 + });
  161 + },
  162 +
  163 + // 效验邮箱验证码
  164 + verifyEmailCode: function() {
  165 + var that = this;
  166 + var dg = new dialog.Dialog({
  167 + closeIcon: false,
  168 + content: that.emailTpl({}),
  169 + className: 'me-gift-confirm',
  170 + btns: [{
  171 + id: 'confirm-email-btn',
  172 + name: '绑定手机号',
  173 + btnClass: ['alert-sure'],
  174 + cb: function() {
  175 + var emailCode = $('.email-code').val();
  176 + var verifyData = {code: '验证码不能为空'};
  177 +
  178 + that.postAjax('/home/megift/verifyEmail', {
  179 + email: that.userEmail,
  180 + code: emailCode
  181 + }, verifyData).then(function(res) {
  182 + if (res.code === 200) {
  183 + dg.close();
  184 + that.getMobileCode();
  185 + }
  186 + });
  187 + }
  188 + }]
  189 + }).show();
  190 +
  191 + setTimeout(function() {
  192 + $('[placeholder]', dg.$el).placeholder(); // ie8 兼容 placeholder
  193 + }, 10);
  194 +
  195 + // 发送邮箱验证码
  196 + $('.me-gift-confirm').find('.email-btn').unbind('click').bind('click', function() {
  197 + if (!$(this).hasClass('int-timer')) {
  198 + that.getEmailCode();
  199 + }
  200 + });
  201 + },
  202 +
  203 + // 获取手机验证码
  204 + getMobileCode: function() {
  205 + var that = this;
  206 + var dg = new dialog.Dialog({
  207 + closeIcon: false,
  208 + content: that.mobileTpl({}),
  209 + className: 'me-gift-confirm',
  210 + btns: [{
  211 + id: 'confirm-mobile-cancel',
  212 + name: '取消',
  213 + btnClass: ['confirm-cancel'],
  214 + cb: function() {
  215 + dg.close();
  216 + }
  217 + }, {
  218 + id: 'confirm-mobile-sure',
  219 + name: '激活',
  220 + btnClass: ['confirm-sure'],
  221 + cb: function() {
  222 + var verifyData = {
  223 + area: '请选择手机区号',
  224 + mobile: '手机号不能为空',
  225 + code: '手机验证码不能为空'
  226 + };
  227 +
  228 + that.postAjax('/home/megift/changeMobile', {
  229 + area: ($('.mobile-area').find('em').text() || '').replace(/^\+/, ''),
  230 + mobile: $('input.mobile').val(),
  231 + code: $('input.mobile-code').val()
  232 + }, verifyData).then(function(res) {
  233 + if (res.code === 200) {
  234 + that.isBinMobile = 1;
  235 + dg.close();
  236 + that.activateGift();
  237 + }
  238 + });
  239 + }
  240 + }]
  241 + }).show();
  242 +
  243 + setTimeout(function() {
  244 + $('[placeholder]', dg.$el).placeholder(); // ie8 兼容 placeholder
  245 + }, 10);
  246 +
  247 + // 发送邮箱验证码
  248 + $('.me-gift-confirm').find('.mobile-btn').unbind('click').bind('click', function() {
  249 + if (!$(this).hasClass('int-timer')) {
  250 + that.smsBind();
  251 + }
  252 + });
  253 + },
  254 +
  255 + // 发送手机验证码
  256 + smsBind: function() {
  257 + var that = this;
  258 + var area = ($('.mobile-area').find('em').text() || '').replace(/^\+/, '');
  259 + var mobile = $('input.mobile').val();
  260 + var verifyData = {
  261 + area: '请选择手机区号',
  262 + mobile: '手机号不能为空'
  263 + };
  264 +
  265 + this.postAjax('/home/megift/smsBind', {
  266 + area: area,
  267 + mobile: mobile
  268 + }, verifyData).then(function(res) {
  269 + if (res.code === 200) {
  270 + that.intTimer($('.mobile-btn'));
  271 + }
  272 + });
  273 + },
  274 +
  275 + // 激活礼品卡
  276 + activateGift: function() {
  277 + var that = this;
  278 + var dg = new dialog.Dialog({
  279 + closeIcon: false,
  280 + content: that.giftTpl({}),
  281 + className: 'me-gift-confirm',
  282 + btns: [{
  283 + id: 'confirm-gift-cancel',
  284 + name: '取消',
  285 + btnClass: ['confirm-cancel'],
  286 + cb: function() {
  287 + dg.close();
  288 + }
  289 + }, {
  290 + id: 'confirm-gift-sure',
  291 + name: '激活',
  292 + btnClass: ['confirm-sure'],
  293 + cb: function() {
  294 + var $confirm = $('.me-gift-confirm');
  295 + var verifyData = {
  296 + cardCode: '礼品卡卡号不能为空',
  297 + cardPwd: '礼品卡卡密不能为空'
  298 + };
  299 +
  300 + that.postAjax('/home/meGift/activateGift', {
  301 + cardCode: $confirm.find('.card-code').val(),
  302 + cardPwd: $confirm.find('.card-pwd').val()
  303 + }, verifyData).then(function(res) {
  304 + if (res.code === 200) {
  305 + dg.close();
  306 + that.meAlert('<p>您的礼品卡激活成功</p>', false, function() {
  307 + location.reload();
  308 + });
  309 + }
  310 + });
  311 + }
  312 + }]
  313 + }).show();
  314 +
  315 + setTimeout(function() {
  316 + $('[placeholder]', dg.$el).placeholder(); // ie8 兼容 placeholder
  317 + }, 10);
  318 + },
  319 +
  320 + // 消费明细
  321 + infoList: function(url) {
  322 + url = url || '';
  323 + $.get('/home/megift/detail' + url).then(function(res) {
  324 + if (!res) {
  325 + return false;
  326 + }
  327 + $('.detail-gift-content').html(res);
  328 + });
  329 + },
  330 +
  331 + // 我的弹框
  332 + meAlert: function(content, mask, callback) {
  333 + var dg;
  334 + var meAlertDialog = $('.me-gift-confirm');
  335 +
  336 + meAlertDialog.addClass('hide');
  337 +
  338 + dg = new dialog.Dialog({
  339 + closeIcon: false,
  340 + content: content,
  341 + className: 'me-gift-alert',
  342 + mask: !!mask,
  343 + btns: [{
  344 + name: '我知道了',
  345 + id: 'alert-gift-cancel',
  346 + btnClass: ['alert-sure'],
  347 + cb: function() {
  348 + dg.close();
  349 + meAlertDialog.removeClass('hide');
  350 + callback && callback();
  351 + }
  352 + }]
  353 + }).show();
  354 + }
  355 +};
  356 +
  357 +$(function() {
  358 + meGift.init();
  359 +});
@@ -1244,6 +1244,43 @@ @@ -1244,6 +1244,43 @@
1244 } 1244 }
1245 } 1245 }
1246 1246
  1247 + .gift-card-box {
  1248 + > table {
  1249 + width: 100%;
  1250 + text-align: center;
  1251 + border: 1px solid #e8e8e8;
  1252 + }
  1253 +
  1254 + th,
  1255 + td {
  1256 + background-color: #f0f0f0;
  1257 + line-height: 30px;
  1258 + text-align: center;
  1259 + }
  1260 +
  1261 + td {
  1262 + padding: 20px 0;
  1263 + background-color: #fff;
  1264 + border-top: 1px solid #e8e8e8;
  1265 + }
  1266 +
  1267 + .gift-card-radio {
  1268 + display: inline-block;
  1269 + width: 15px;
  1270 + height: 15px;
  1271 + margin-right: 6px;
  1272 + background-image: url(/cart/radio-off.png);
  1273 + vertical-align: middle;
  1274 + position: relative;
  1275 + top: -1px;
  1276 + cursor: pointer;
  1277 +
  1278 + &.on {
  1279 + background-image: url(/cart/radio-check.png);
  1280 + }
  1281 + }
  1282 + }
  1283 +
1247 .remark-box { 1284 .remark-box {
1248 padding: 30px 20px 0; 1285 padding: 30px 20px 0;
1249 background-color: #f0f0f0; 1286 background-color: #f0f0f0;
@@ -1835,3 +1872,75 @@ @@ -1835,3 +1872,75 @@
1835 padding: 0 6px; 1872 padding: 0 6px;
1836 } 1873 }
1837 } 1874 }
  1875 +
  1876 +.gift-card-check-dialog {
  1877 + font-size: 14px;
  1878 +
  1879 + .close {
  1880 + display: none;
  1881 + }
  1882 +
  1883 + .content {
  1884 + width: 352px;
  1885 + padding: 0 30px;
  1886 +
  1887 + h2 {
  1888 + font-size: 18px;
  1889 + margin-bottom: 26px;
  1890 + }
  1891 +
  1892 + > p {
  1893 + line-height: 2;
  1894 + }
  1895 +
  1896 + input {
  1897 + width: 160px;
  1898 + height: 30px;
  1899 + padding-left: 10px;
  1900 + box-sizing: border-box;
  1901 + }
  1902 +
  1903 + .send-sms {
  1904 + width: 120px;
  1905 + height: 30px;
  1906 + color: #fff;
  1907 + margin-left: 20px;
  1908 + background-color: #494949;
  1909 + display: inline-block;
  1910 + cursor: pointer;
  1911 + }
  1912 +
  1913 + .send-sms.timer {
  1914 + background-color: #b0b0b0;
  1915 + cursor: default;
  1916 + }
  1917 + }
  1918 +
  1919 + .tip-info {
  1920 + text-align: left;
  1921 + }
  1922 +
  1923 + .receiver-info {
  1924 + padding: 24px 0 30px;
  1925 + }
  1926 +
  1927 + .btns {
  1928 + padding-top: 30px;
  1929 +
  1930 + .btn {
  1931 + min-width: 100px;
  1932 + padding: 0;
  1933 + }
  1934 +
  1935 + .check-sure {
  1936 + background-color: #000;
  1937 + color: #fff;
  1938 + margin-left: 96px;
  1939 + }
  1940 + }
  1941 +}
  1942 +
  1943 +.alert-dialog.ensure-alert > .content {
  1944 + padding-bottom: 0;
  1945 + padding-top: 60px;
  1946 +}
@@ -22,3 +22,5 @@ @@ -22,3 +22,5 @@
22 @import "../variables"; 22 @import "../variables";
23 @import "returns-detail"; 23 @import "returns-detail";
24 @import "returns-save"; 24 @import "returns-save";
  25 +@import "me-gift";
  26 +@import "invoice";
  1 +.invoice-me-page {
  2 + .orders > .title {
  3 + font-size: 16px;
  4 + font-weight: bold;
  5 + padding-left: 10px;
  6 + background: #e3e3e3;
  7 + margin-bottom: 10px;
  8 + }
  9 +
  10 + .order-title {
  11 + overflow: hidden;
  12 +
  13 + .unsupport-tip {
  14 + color: #999;
  15 +
  16 + .iconfont {
  17 + font-size: 14px;
  18 + margin: 0 4px;
  19 + }
  20 + }
  21 + }
  22 +
  23 + .operation {
  24 + > .op-item {
  25 + color: #999;
  26 + cursor: default;
  27 + }
  28 +
  29 + > .view-invoice {
  30 + color: #468fa2;
  31 + cursor: pointer;
  32 + }
  33 +
  34 + > .supply-invoice {
  35 + display: inline-block;
  36 + box-sizing: border-box;
  37 + width: 68px;
  38 + height: 18px;
  39 + border-radius: 5px;
  40 + text-align: center;
  41 + color: #000;
  42 + border: 1px solid #000;
  43 + cursor: pointer;
  44 + }
  45 + }
  46 +
  47 + .empty-tip {
  48 + font-size: 16px;
  49 + line-height: 1.5;
  50 + padding: 10px 0 300px;
  51 +
  52 + &:before {
  53 + content: "";
  54 + display: block;
  55 + width: 70px;
  56 + height: 90px;
  57 + background: resolve("home/empty-content.jpg");
  58 + margin: 30px auto;
  59 + }
  60 +
  61 + > span {
  62 + font-size: 14px;
  63 + color: #ccc;
  64 + }
  65 + }
  66 +
  67 + &.invoice-detail-dialog {
  68 + background: #fff;
  69 +
  70 + > .close {
  71 + position: absolute;
  72 + top: 10px;
  73 + right: 12px;
  74 + cursor: pointer;
  75 +
  76 + .iconfont {
  77 + font-size: 32px;
  78 + }
  79 + }
  80 +
  81 + .content {
  82 + width: 450px;
  83 + text-align: left;
  84 + font-size: 14px;
  85 + color: #666;
  86 + line-height: 1.6;
  87 + padding-bottom: 10px;
  88 + }
  89 +
  90 + .title {
  91 + font-size: 16px;
  92 + color: #222;
  93 + padding-bottom: 14px;
  94 + border-bottom: 1px solid #ccc;
  95 + }
  96 +
  97 + .order-info {
  98 + line-height: 50px;
  99 + color: #555;
  100 + }
  101 +
  102 + table {
  103 + width: 100%;
  104 + margin-bottom: 20px;
  105 +
  106 + td {
  107 + padding: 6px 20px;
  108 + border: 1px solid #e3e4e5;
  109 + }
  110 +
  111 + .lt {
  112 + text-align: justify;
  113 + text-align-last: justify;
  114 + display: block;
  115 + color: #555;
  116 +
  117 + &:after {
  118 + content: "";
  119 + display: block;
  120 + overflow: hidden;
  121 + width: 100%;
  122 + height: 0;
  123 + }
  124 + }
  125 +
  126 + .line {
  127 + background-color: #eff0f1;
  128 + }
  129 + }
  130 +
  131 + .download-btn {
  132 + display: block;
  133 + width: 130px;
  134 + line-height: 30px;
  135 + color: #fff;
  136 + background-color: #444;
  137 + text-align: center;
  138 + margin: auto;
  139 + margin-top: 10px;
  140 + }
  141 + }
  142 +
  143 + &.invoice-supply-dialog {
  144 + $red: #d0021b;
  145 +
  146 + width: 690px;
  147 + padding: 20px 58px;
  148 + font-size: 14px;
  149 + color: #444;
  150 + background-color: #fff;
  151 + box-sizing: border-box;
  152 +
  153 + > .close {
  154 + position: absolute;
  155 + top: 10px;
  156 + right: 12px;
  157 + cursor: pointer;
  158 +
  159 + .iconfont {
  160 + font-size: 32px;
  161 + }
  162 + }
  163 +
  164 + .radio-btn {
  165 + &:before {
  166 + content: "";
  167 + width: 15px;
  168 + height: 15px;
  169 + margin-right: 4px;
  170 + background-image: url(/cart/radio-off.png);
  171 + display: inline-block;
  172 + vertical-align: middle;
  173 + position: relative;
  174 + top: -2px;
  175 + cursor: pointer;
  176 + }
  177 +
  178 + &.on:before {
  179 + content: ".";
  180 + background-image: url(/cart/radio-on.png);
  181 + text-indent: -9999px;
  182 + }
  183 + }
  184 +
  185 + > .content {
  186 + text-align: left;
  187 + }
  188 +
  189 + .invoice-header {
  190 + font-size: 14px;
  191 + padding: 24px 0 20px;
  192 + border-bottom: 1px solid #e8e8e8;
  193 + }
  194 +
  195 + .invoice-content {
  196 + font-weight: 300;
  197 + }
  198 +
  199 + .row-title {
  200 + font-weight: normal;
  201 + }
  202 +
  203 + .el-tip {
  204 + background-color: #f5f5f5;
  205 + padding: 14px;
  206 + line-height: 1.5;
  207 +
  208 + > a {
  209 + display: inline-block;
  210 + padding-top: 12px;
  211 + font-weight: 500;
  212 + }
  213 + }
  214 +
  215 + .invoice-type-text {
  216 + line-height: 20px;
  217 + padding: 20px 10px;
  218 +
  219 + .row-title {
  220 + margin-right: 10px;
  221 + }
  222 + }
  223 +
  224 + .invoice-row {
  225 + padding-top: 16px;
  226 + padding-left: 92px;
  227 + overflow: hidden;
  228 +
  229 + .row-content {
  230 + width: 110%;
  231 + }
  232 +
  233 + .row-title {
  234 + line-height: 30px;
  235 + position: absolute;
  236 + margin-left: -92px;
  237 +
  238 + > em {
  239 + color: $red;
  240 + margin-right: 3px;
  241 + position: relative;
  242 + top: 2px;
  243 + }
  244 + }
  245 +
  246 + .radio-wrap {
  247 + width: 92px;
  248 + display: inline-block;
  249 + padding: 8px 0;
  250 + }
  251 +
  252 + input {
  253 + width: 220px;
  254 + height: 30px;
  255 + padding: 0 10px;
  256 + background: #f5f5f5;
  257 + border: 1px solid #e0e0e0;
  258 + }
  259 +
  260 + .red {
  261 + color: $red;
  262 + }
  263 + }
  264 +
  265 + .btns {
  266 + padding-top: 28px;
  267 + padding-bottom: 10px;
  268 +
  269 + .btn {
  270 + width: 140px;
  271 + height: 40px;
  272 + line-height: 38px;
  273 + box-sizing: border-box;
  274 + }
  275 +
  276 + .sure-apply {
  277 + background-color: #000;
  278 + color: #fff;
  279 + font-weight: 300;
  280 + margin-right: 30px;
  281 + }
  282 + }
  283 + }
  284 +
  285 + &.supply-success-dialog {
  286 + background-color: #fff;
  287 + font-size: 14px;
  288 +
  289 + .content {
  290 + width: 300px;
  291 + padding: 0 30px 40px;
  292 + line-height: 2;
  293 + color: #444;
  294 +
  295 + h2 {
  296 + font-size: 18px;
  297 + margin-bottom: 26px;
  298 + }
  299 + }
  300 + }
  301 +}
  1 +.me-gift-page {
  2 + .me-gift .me-content {
  3 + min-height: 370px;
  4 + }
  5 +
  6 + .tabs li.add-gift {
  7 + margin-top: -5px;
  8 + background-image: none;
  9 + background-color: #000;
  10 + float: right;
  11 +
  12 + a {
  13 + color: #fff;
  14 + }
  15 + }
  16 +
  17 + .me-gift-table,
  18 + .me-gift-info-table {
  19 + display: table;
  20 + width: 775px;
  21 + text-align: center;
  22 + border: 1px solid #e6e6e6;
  23 + margin: 0 10px 30px;
  24 +
  25 + .me-gift-header {
  26 + display: table-row;
  27 + background-color: #efefef;
  28 +
  29 + div {
  30 + height: 30px;
  31 + display: table-cell;
  32 + vertical-align: middle;
  33 + font-size: 13px;
  34 + width: 120px;
  35 +
  36 + &:first-child {
  37 + width: 174px;
  38 + }
  39 + }
  40 + }
  41 +
  42 + .me-gift-tr {
  43 + display: table-row;
  44 +
  45 + &:first-child div {
  46 + border-top: none;
  47 + }
  48 +
  49 + div {
  50 + display: table-cell;
  51 + height: 50px;
  52 + vertical-align: middle;
  53 + font-size: 13px;
  54 + border-top: 1px solid #e6e6e6;
  55 + }
  56 +
  57 + div.info-list {
  58 + color: #4a90e2;
  59 + cursor: pointer;
  60 + }
  61 + }
  62 + }
  63 +
  64 + .me-gift-info-table {
  65 + margin-bottom: 0;
  66 + }
  67 +
  68 + .me-gift-info-table .me-gift-tr div {
  69 + width: auto;
  70 + height: 40px;
  71 + }
  72 +
  73 + .cart-list-empty {
  74 + background: resolve("home/gift.png") no-repeat center;
  75 + background-size: 110px 132px;
  76 + width: 775px;
  77 + height: 300px;
  78 + display: table-caption;
  79 + caption-side: bottom;
  80 + border: 1px solid #e6e6e6;
  81 + border-top: none;
  82 + }
  83 +
  84 + .refund {
  85 + color: #86bf4a;
  86 + }
  87 +
  88 + .consume {
  89 + color: #d0021b;
  90 + }
  91 +
  92 + div.content {
  93 + padding: 0 !important;
  94 + }
  95 +}
  96 +
  97 +.me-gift-alert {
  98 + width: 350px;
  99 +
  100 + .content {
  101 + color: #444;
  102 + padding: 62px 0;
  103 + font-size: 18px;
  104 +
  105 + p {
  106 + margin-top: 10px;
  107 + }
  108 + }
  109 +
  110 + .btns {
  111 + margin-bottom: 10px;
  112 + }
  113 +
  114 + .btn {
  115 + width: 160px;
  116 + height: 30px;
  117 + line-height: 30px;
  118 + }
  119 +}
  120 +
  121 +.me-gift-confirm {
  122 + color: #444;
  123 +
  124 + .title,
  125 + .info-title {
  126 + font-size: 18px;
  127 + padding-bottom: 25px;
  128 + margin: 0 20px;
  129 + }
  130 +
  131 + .info-title {
  132 + border-bottom: 1px solid #e6e6e6;
  133 + }
  134 +
  135 + .gift-group {
  136 + margin-top: 10px;
  137 + overflow: hidden;
  138 + }
  139 +
  140 + .left {
  141 + float: left;
  142 + }
  143 +
  144 + .right {
  145 + float: right;
  146 + }
  147 +
  148 + .verify-input {
  149 + font-size: 14px;
  150 +
  151 + input {
  152 + height: 30px;
  153 + line-height: 30px;
  154 + padding: 0 5px;
  155 + font-size: 14px;
  156 + color: #444;
  157 + border: 1px solid #e6e6e6;
  158 + outline: none;
  159 + box-sizing: border-box;
  160 + }
  161 +
  162 + .email-btn,
  163 + .mobile-btn {
  164 + border: 1px solid #e6e6e6;
  165 + font-size: 13px;
  166 + background-color: #444;
  167 + color: #fff;
  168 + height: 30px;
  169 + cursor: pointer;
  170 + width: 110px;
  171 + line-height: 30px;
  172 + }
  173 +
  174 + .email-code {
  175 + margin-left: 35px;
  176 + }
  177 +
  178 + .email-btn {
  179 + margin-left: 20px;
  180 + }
  181 +
  182 + .int-timer {
  183 + background-color: #b0b0b0 !important;
  184 + }
  185 + }
  186 +
  187 + input.mobile {
  188 + width: 260px;
  189 + border-left: none;
  190 + }
  191 +
  192 + .mobile-area {
  193 + width: 70px;
  194 + line-height: 26px;
  195 + height: 30px;
  196 + text-align: center;
  197 + border: 1px solid #e6e6e6;
  198 + outline: none;
  199 + box-sizing: border-box;
  200 + border-right: none;
  201 + background-color: #fff;
  202 + cursor: pointer;
  203 + }
  204 +
  205 + .ul-list {
  206 + position: absolute;
  207 + width: 130px;
  208 + margin-left: -25px;
  209 + background-color: #fff;
  210 + margin-top: -3px;
  211 + border: 1px solid #e6e6e6;
  212 + display: none;
  213 + cursor: pointer;
  214 + z-index: 1;
  215 +
  216 + li {
  217 + border-bottom: 1px solid #e6e6e6;
  218 + height: 30px;
  219 + line-height: 30px;
  220 +
  221 + &:hover {
  222 + color: #4a90e2;
  223 + }
  224 + }
  225 + }
  226 +
  227 + input.mobile-code {
  228 + width: 200px;
  229 + }
  230 +
  231 + .card-code,
  232 + .card-pwd {
  233 + width: 330px;
  234 + }
  235 +
  236 + .border-top-info {
  237 + border-top: 1px solid #e6e6e6;
  238 + }
  239 +
  240 + .info-gift-header {
  241 + width: 777px;
  242 + text-align: center;
  243 + margin: 25px 10px 15px;
  244 + font-size: 14px;
  245 +
  246 + .text-left {
  247 + text-align: left;
  248 + }
  249 +
  250 + .text-right {
  251 + text-align: right;
  252 + }
  253 +
  254 + td {
  255 + height: 25px;
  256 + }
  257 +
  258 + .validity-time {
  259 + width: 330px;
  260 + }
  261 + }
  262 +
  263 + .gift-type {
  264 + background: resolve("home/gift-filter.png") no-repeat center;
  265 + background-size: 69px 21px;
  266 + width: 69px;
  267 + height: 21px;
  268 + line-height: 21px;
  269 + display: inline-block;
  270 + cursor: pointer;
  271 + }
  272 +
  273 + .gift-filter .ul-list {
  274 + width: 69px;
  275 + margin-left: 52px;
  276 + margin-top: 0;
  277 + }
  278 +
  279 + .img-check-main .img-check-tip {
  280 + top: 115px;
  281 + }
  282 +
  283 + .detail-gift-list {
  284 + width: 797px;
  285 + min-height: 500px;
  286 +
  287 + .me-pager {
  288 + width: 755px;
  289 + margin: 0 10px;
  290 + border: 1px solid #e6e6e6;
  291 + border-top: none;
  292 + }
  293 + }
  294 +
  295 + div.content {
  296 + padding: 10px 30px;
  297 + }
  298 +
  299 + .btns {
  300 + margin-bottom: 10px;
  301 + }
  302 +
  303 + .btn {
  304 + min-width: 100px;
  305 + height: 30px;
  306 + line-height: 30px;
  307 + }
  308 +
  309 + .confirm-sure {
  310 + margin-left: 65px;
  311 + }
  312 +
  313 + .alert-sure {
  314 + width: 160px;
  315 + }
  316 +
  317 + .activate-input-last {
  318 + margin-top: 30px;
  319 + }
  320 +
  321 + .activate-center {
  322 + padding-bottom: 30px;
  323 + }
  324 +
  325 + .bind-mobile-input {
  326 + margin: 30px 0 50px;
  327 + }
  328 +}
  329 +
  330 +.me-gift-confirm.me-page {
  331 + width: auto !important;
  332 +}