Authored by 郭成尧

invoice-page

@@ -6,6 +6,7 @@ const cartModel = require('../models/cart'); @@ -6,6 +6,7 @@ const cartModel = require('../models/cart');
6 const headerModel = require('../../../doraemon/models/header'); 6 const headerModel = require('../../../doraemon/models/header');
7 const userModel = require('../../serverAPI/user'); 7 const userModel = require('../../serverAPI/user');
8 const addressModel = require('../../serverAPI/user/address'); 8 const addressModel = require('../../serverAPI/user/address');
  9 +const orderModel = require('../models/order');
9 10
10 11
11 exports.orderEnsure = (req, res, next) => { 12 exports.orderEnsure = (req, res, next) => {
@@ -45,51 +46,46 @@ exports.orderEnsure = (req, res, next) => { @@ -45,51 +46,46 @@ exports.orderEnsure = (req, res, next) => {
45 let userProfile = userModel.queryProfile(uid); 46 let userProfile = userModel.queryProfile(uid);
46 let address = addressModel.addressData(uid); 47 let address = addressModel.addressData(uid);
47 48
48 - return Promise.all([order, userProfile, address])  
49 - .then(  
50 - result => {  
51 - order = result[0];  
52 - userProfile = result[1];  
53 - address = result[2];  
54 -  
55 - if (order.cartUrl) { // TODO? 普通或者预售商品为空时, BUT WHEN AJAX?  
56 - return res.redirect(order.cartUrl);  
57 - }  
58 -  
59 - if (req.xhr) {  
60 - return res.json(order);  
61 - }  
62 -  
63 - // 获取用户完整手机号  
64 - let mobile = _.get(userProfile, 'data.mobile', '');  
65 - let orderAddress = _.get(order, 'address', []);  
66 - let addressList = _.get(address, 'data', []);  
67 -  
68 - orderAddress.length && addressList.forEach(address => { //eslint-disable-line  
69 - if (address.address_id === orderAddress.address_id) {  
70 - mobile = address.mobile;  
71 - }  
72 - });  
73 -  
74 - let viewData = {  
75 - orderEnsurePage: true,  
76 - isOrdinaryCart: cartType !== 'advance',  
77 - orderEnsure: order,  
78 - userMobile: mobile  
79 - };  
80 -  
81 - viewData.pageHeader = headerData;  
82 - viewData.pageFooter = true;  
83 - viewData.module = 'cart';  
84 - viewData.page = 'order-ensure';  
85 - viewData.width750 = true;  
86 - viewData.title = '确认订单';  
87 -  
88 - res.render('order-ensure', viewData); 49 + return Promise.all([order, userProfile, address]).then(result => {
  50 + order = result[0];
  51 + userProfile = result[1];
  52 + address = result[2];
  53 +
  54 + if (order.cartUrl) { // TODO? 普通或者预售商品为空时, BUT WHEN AJAX?
  55 + return res.redirect(order.cartUrl);
  56 + }
  57 +
  58 + if (req.xhr) {
  59 + return res.json(order);
  60 + }
  61 +
  62 + // 获取用户完整手机号
  63 + let mobile = _.get(userProfile, 'data.mobile', '');
  64 + let orderAddress = _.get(order, 'address', []);
  65 + let addressList = _.get(address, 'data', []);
  66 +
  67 + orderAddress.length && addressList.forEach(address => { //eslint-disable-line
  68 + if (address.address_id === orderAddress.address_id) {
  69 + mobile = address.mobile;
89 } 70 }
90 - )  
91 - .catch(next); 71 + });
92 72
  73 + let viewData = {
  74 + orderEnsurePage: true,
  75 + isOrdinaryCart: cartType !== 'advance',
  76 + orderEnsure: order,
  77 + userMobile: mobile
  78 + };
  79 +
  80 + viewData.pageHeader = headerData;
  81 + viewData.pageFooter = true;
  82 + viewData.module = 'cart';
  83 + viewData.page = 'order-ensure';
  84 + viewData.width750 = true;
  85 + viewData.title = '确认订单';
  86 +
  87 + res.render('order-ensure', viewData);
  88 + }).catch(next);
93 }; 89 };
94 90
95 /** 91 /**
@@ -149,40 +145,42 @@ exports.couponSearch = (req, res, next) => { @@ -149,40 +145,42 @@ exports.couponSearch = (req, res, next) => {
149 })(); 145 })();
150 }; 146 };
151 147
  148 +/**
  149 + * 选择地址
  150 + */
152 exports.selectAddress = (req, res, next) => { 151 exports.selectAddress = (req, res, next) => {
153 let uid = req.user.uid; 152 let uid = req.user.uid;
154 153
155 - return addressModel.addressData(uid)  
156 - .then(address => {  
157 - let moreUrl = req.get('Referer') || '/cart/index/new/orderEnsure'; // 取跳过来的url 154 + return addressModel.addressData(uid).then(address => {
  155 + let moreUrl = req.get('Referer') || '/cart/index/new/orderEnsure'; // 取跳过来的url
158 156
159 - address = address.data; 157 + address = address.data;
160 158
161 - // 购物车订单进来,秒杀进来  
162 - if (  
163 - moreUrl.indexOf('/cart/index/new/orderEnsure') !== -1 ||  
164 - moreUrl.indexOf('/cart/index/seckill') !== -1  
165 - ) {  
166 - req.session.addressMore = moreUrl; // TODO: 注意cookie-session  
167 - } 159 + // 购物车订单进来,秒杀进来
  160 + if (
  161 + moreUrl.indexOf('/cart/index/new/orderEnsure') !== -1 ||
  162 + moreUrl.indexOf('/cart/index/seckill') !== -1
  163 + ) {
  164 + req.session.addressMore = moreUrl; // TODO: 注意cookie-session
  165 + }
168 166
169 - moreUrl = req.session.addressMore; 167 + moreUrl = req.session.addressMore;
170 168
171 - let headerData = headerModel.setNav({  
172 - navTitle: '选择地址',  
173 - navBtn: false,  
174 - backUrl: moreUrl  
175 - }); 169 + let headerData = headerModel.setNav({
  170 + navTitle: '选择地址',
  171 + navBtn: false,
  172 + backUrl: moreUrl
  173 + });
176 174
177 - res.render('select-address', {  
178 - module: 'cart',  
179 - page: 'select-address',  
180 - pageHeader: headerData,  
181 - pageFooter: true,  
182 - moreUrl,  
183 - address  
184 - }); 175 + res.render('select-address', {
  176 + module: 'cart',
  177 + page: 'select-address',
  178 + pageHeader: headerData,
  179 + pageFooter: true,
  180 + moreUrl,
  181 + address
185 }); 182 });
  183 + }).catch(next);
186 }; 184 };
187 185
188 /** 186 /**
@@ -190,14 +188,23 @@ exports.selectAddress = (req, res, next) => { @@ -190,14 +188,23 @@ exports.selectAddress = (req, res, next) => {
190 */ 188 */
191 exports.invoiceInfo = (req, res, next) => { 189 exports.invoiceInfo = (req, res, next) => {
192 let uid = req.user.uid; 190 let uid = req.user.uid;
  191 + let cookieData = req.cookies['order-info'];
  192 + let orderInfo = JSON.parse(cookieData);
193 193
194 - let orderInfo = req.cookies.orderInfo;  
195 -  
196 - try {  
197 - orderInfo = JSON.parse(orderInfo);  
198 - } catch (e) {  
199 - orderInfo = {};  
200 - }  
201 - 194 + co(function* () {
  195 + let userData = yield userModel.queryProfile(uid);
  196 + let mobile = _.get(userData, 'data.mobile', '');
  197 + let addresslist = yield userModel.addressTextData(uid);
  198 + let returnData = orderModel.processInvoiceData(orderInfo, mobile, addresslist);
  199 + let headerData = headerModel.setNav({
  200 + navTitle: '发票信息',
  201 + navBtn: false
  202 + });
202 203
  204 + res.render('select-invoice', _.assign(returnData, {
  205 + pageHeader: headerData,
  206 + module: 'cart',
  207 + page: 'select-invoice'
  208 + })).catch(next);
  209 + })();
203 }; 210 };
  1 +'use strict';
  2 +
  3 +const _ = require('lodash');
  4 +const crypto = global.yoho.crypto;
  5 +
  6 +const processInvoiceData = (orderInfo, mobile, addresslist) => {
  7 + let invoices_title = '';
  8 + let invoiceType = '7';
  9 + let invoices_type = '2';
  10 + let invoice_Top = '个人';
  11 +
  12 + // 用户手机号处理
  13 + if (orderInfo.receiverMobile && orderInfo.isModifyTel) {
  14 + mobile = orderInfo.receiverMobile;
  15 + } else {
  16 + _.forEach(addresslist, addressValue => {
  17 + if (addressValue.address_id === crypto.encryption('', orderInfo.addressId)) {
  18 + mobile = addressValue.mobile;
  19 + }
  20 + });
  21 + }
  22 +
  23 + // 发票信息处理
  24 + if (orderInfo.invoiceType && orderInfo.invoiceTitle) {
  25 + invoices_title = orderInfo.invoiceText;
  26 + invoiceType = orderInfo.invoiceType;
  27 + invoices_type = orderInfo.invoicesType * 1;
  28 + invoice_Top = orderInfo.invoiceTitle;
  29 + }
  30 +
  31 + return {
  32 + invoiceNotice: '发票须知',
  33 + phone: mobile ? mobile : '', // TODO 字符串替换 ****
  34 + completeTel: mobile,
  35 + isCompany: invoice_Top !== '单位',
  36 + companyName: invoices_title,
  37 + isPaper: invoices_type === 1,
  38 + invoicesType: [
  39 + {
  40 + id: '2',
  41 + type: '电子发票',
  42 + choosed: !invoices_type || invoices_type === 2,
  43 + },
  44 + {
  45 + id: '1',
  46 + type: '纸质发票',
  47 + choosed: invoices_type === 1
  48 + }
  49 + ],
  50 + invoiceTitle: [
  51 + {
  52 + type: '个人',
  53 + choosed: invoice_Top === '个人'
  54 + },
  55 + {
  56 + type: '单位',
  57 + choosed: invoice_Top === '单位'
  58 + }
  59 + ],
  60 + content: [
  61 + {
  62 + choosed: !invoiceType || invoiceType === 7,
  63 + id: 7,
  64 + text: '服装'
  65 + },
  66 + {
  67 + choosed: invoiceType === 9,
  68 + id: 9,
  69 + text: '配件'
  70 + },
  71 + {
  72 + choosed: invoiceType === 11,
  73 + id: 11,
  74 + text: '日用品'
  75 + },
  76 + {
  77 + choosed: invoiceType === 3,
  78 + id: 3,
  79 + text: '办公用品'
  80 + },
  81 + {
  82 + choosed: invoiceType === 6,
  83 + id: 6,
  84 + text: '体育用品'
  85 + },
  86 + {
  87 + choosed: invoiceType === 10,
  88 + id: 10,
  89 + text: '数码产品'
  90 + },
  91 + ]
  92 + };
  93 +
  94 +};
  95 +
  96 +module.exports = {
  97 + processInvoiceData
  98 +};
@@ -132,7 +132,7 @@ @@ -132,7 +132,7 @@
132 <input type="hidden" class="user-mobile" value="{{userMobile}}" /> 132 <input type="hidden" class="user-mobile" value="{{userMobile}}" />
133 <span class="title">发票</span> 133 <span class="title">发票</span>
134 <span class="iconfont checkbox {{#if needInvoice}}icon-cb-radio{{else}}icon-radio{{/if}}"></span> 134 <span class="iconfont checkbox {{#if needInvoice}}icon-cb-radio{{else}}icon-radio{{/if}}"></span>
135 - <a id="invoice" class="invoice-info" href="/cart/index/invoiceInfo"> 135 + <a id="invoice" class="invoice-info" href="/cart/index/new/invoiceInfo">
136 <span class="title">发票信息</span> 136 <span class="title">发票信息</span>
137 <span class="invoice-type"><i class="iconfont">&#xe614;</i></span> 137 <span class="invoice-type"><i class="iconfont">&#xe614;</i></span>
138 </a> 138 </a>
  1 +<div class="invoice-info-page yoho-page">
  2 + <ul class="invoice-form">
  3 + <li>
  4 + <span class="title">发票类型:</span>
  5 + <div class="invoice-type">
  6 + {{#invoicesType}}
  7 + <span {{#if choosed}}class="on"{{/if}} data-id="{{id}}">{{type}}</span>
  8 + {{/invoicesType}}
  9 + </div>
  10 + </li>
  11 + <li>
  12 + <span class="title">发票抬头:</span>
  13 + <div class="invoice-top">
  14 + {{#invoiceTitle}}
  15 + <span {{#if choosed}}class="on"{{/if}}><i class="iconfont choose {{#if choosed}}icon-cb-radio{{else}}icon-radio{{/if}}"></i>{{type}}</span>
  16 + {{/invoiceTitle}}
  17 + </div>
  18 + </li>
  19 + <li {{#isPaper}}style="display: none;"{{/isPaper}} class="tel-area">
  20 + <span class="title"><i class="txt-point">*</i>发票人手机:</span>
  21 + <span class="phone">
  22 + <input type="hidden" class="copy-tel" value="{{completeTel}}">
  23 + <input type="text" name="tel" data-tel="{{completeTel}}" class="tel {{#phone}}istel{{/phone}}" value="{{phone}}" placeholder="可通过手机号在发票服务平台查询">
  24 + </span>
  25 + </li>
  26 +
  27 + <li class="company-area" {{#isCompany}}style="display: none;"{{/isCompany}}><input type="text" name="company" class="company" value="{{companyName}}" placeholder="填写单位名称" maxlength="30"></li>
  28 + </ul>
  29 +
  30 + <ul class="invoice-cont">
  31 + <li class="cont-title">
  32 + <span>发票内容:</span>
  33 + <span class="choose-cont" data-id=""></span>
  34 + </li>
  35 + {{#each content}}
  36 + <li><span class="iconfont choose {{#if choosed}}icon-cb-radio{{else}}icon-radio{{/if}}" data-id="{{id}}"></span>{{text}}</li>
  37 + {{/each}}
  38 + </ul>
  39 +
  40 + <div class="btn-area"><span class="confirm-btn">确认</span></div>
  41 +
  42 + <div class="invoice-notice">
  43 + <div class="mask-bg"></div>
  44 + <div class="notice-area">
  45 + <div class="notice-cont">
  46 + <h2>发票须知</h2>
  47 + <p>1、发票金额不含优惠券/有货币/红包/优惠码/运费,只包含商品实付金额</p>
  48 + <p>2、电子发票:是税局认可的有效收付款凭证,其法律效力、基本用途及使用规定同纸质发票,如需纸质发票可自行下载打印</p>
  49 + </div>
  50 + <div class="think-ok">我知道了</div>
  51 + </div>
  52 + </div>
  53 +
  54 + <input type="hidden" class="edit-flag" value="false" />
  55 + <input type="hidden" class="address-more" value="{{addressMore}}" />
  56 +</div>
@@ -21,3 +21,10 @@ exports.queryProfile = (uid) => { @@ -21,3 +21,10 @@ exports.queryProfile = (uid) => {
21 21
22 return api.get('', params, options); 22 return api.get('', params, options);
23 }; 23 };
  24 +
  25 +exports.addressTextData = (uid) => {
  26 + return api.get('', {
  27 + method: 'app.address.get',
  28 + uid: uid
  29 + });
  30 +};
  1 +/**
  2 + * 发票信息
  3 + * @author: wsl<shuiling.wang@yoho.cn>
  4 + * @date: 2016/6/14
  5 + */
  6 +
  7 +var $ = require('yoho-jquery'),
  8 + tip = require('../plugin/tip'),
  9 + dialog = require('../plugin/dialog'),
  10 + order = require('./order-info');
  11 +
  12 +var $invoiceNotice = $('.invoice-notice'),
  13 + $companyArea = $('.company-area'),
  14 + $editFlag = $('.edit-flag'),
  15 + $chooseCont = $('.choose-cont'),
  16 + $invoiceType = $('.invoice-type'),
  17 + $tel = $('.tel'),
  18 + $company = $('.company'),
  19 + $telArea = $('.tel-area'),
  20 + orderInfo = order.orderInfo,
  21 + $chooseContLi = $('.invoice-cont').find('.icon-cb-radio').parent(),
  22 + $copyTel = $('.copy-tel'),
  23 + isModifyTel = false;
  24 +
  25 +var myreg = /^(((13[0-9]{1})|(14[0-9]{1})|(15[0-9]{1})|(17[0-9]{1})|(18[0-9]{1}))+\d{8})$/,
  26 + linkUrl = $('.address-more').val() || '/cart/index/orderEnsure?cartType=ordinary';
  27 +
  28 +var C_ID = window._ChannelVary[window.cookie('_Channel')] || 1;
  29 +
  30 +require('../common');
  31 +
  32 +if (window.getUid() !== orderInfo('uid')) {
  33 + order.init();
  34 + window.location.reload();
  35 +}
  36 +
  37 +// 单选效果
  38 +function chooseAction(pDom, dom) {
  39 + if (dom.hasClass('icon-cb-radio')) {
  40 + return;
  41 + } else {
  42 + pDom.find('.choose').removeClass('icon-cb-radio icon-radio').addClass('icon-radio');
  43 + dom.removeClass('icon-radio').addClass('icon-cb-radio');
  44 + dom.parent().addClass('on');
  45 + dom.parent().siblings().removeClass('on');
  46 + $editFlag.val('true');
  47 + }
  48 +}
  49 +
  50 +// 确认表单事件
  51 +function confirmAction() {
  52 + var type = $invoiceType.find('.on').data('id'),
  53 + title = $('.invoice-top').find('.on').text(),
  54 + tel = $tel.attr('data-tel'),
  55 + company = $company.val(),
  56 + cont = $chooseCont.data('id');
  57 +
  58 + if ($editFlag.val() === 'true') {
  59 + if (type === 2 && !myreg.test($tel.attr('data-tel'))) {
  60 + tip.show('请输入正确手机号');
  61 + $tel.focus();
  62 + return false;
  63 + } else if (title === '单位' && company.length === 0) {
  64 + tip.show('请填写发票抬头');
  65 + $company.focus();
  66 + return false;
  67 + } else if (title === '单位' && company.length > 30) {
  68 + tip.show('发票抬头不得超过30个汉字');
  69 + $company.focus();
  70 + return false;
  71 + } else {
  72 + dialog.showDialog({
  73 + dialogText: '确认保存修改内容?',
  74 + hasFooter: {
  75 + leftBtnText: '取消',
  76 + rightBtnText: '确定'
  77 + }
  78 + }, function() {
  79 + orderInfo('invoiceText', (title === '单位' ? company : ''));
  80 + orderInfo('invoiceType', cont);
  81 + orderInfo('receiverMobile', tel);
  82 + orderInfo('invoicesType', type);
  83 + orderInfo('invoiceTitle', title);
  84 +
  85 + if (isModifyTel && $copyTel !== tel) {
  86 + orderInfo('isModifyTel', true);
  87 + } else {
  88 + orderInfo('isModifyTel', false);
  89 + }
  90 +
  91 + dialog.showDialog({
  92 + dialogText: '保存成功',
  93 + autoHide: true,
  94 + fast: true
  95 + });
  96 + window.location.href = linkUrl;
  97 + }, function() {
  98 + window.location.href = linkUrl;
  99 + });
  100 + }
  101 + } else {
  102 + window.location.href = linkUrl;
  103 + }
  104 +}
  105 +
  106 +$chooseCont.html($chooseContLi.text()).attr('data-id', $chooseContLi.find('span').data('id'));
  107 +
  108 +// 发票抬头、发票内容选择
  109 +$('.invoice-top span, .invoice-cont li').not('.invoice-cont .cont-title').on('touchstart', function() {
  110 + chooseAction($(this).parent(), $(this).find('.choose'));
  111 +
  112 + if ($(this).parent().hasClass('invoice-cont')) {
  113 + $chooseCont.html($(this).text()).attr('data-id', $(this).find('span').data('id'));
  114 + }
  115 +
  116 + if ($(this).text() === '单位') {
  117 + $companyArea.slideDown();
  118 + }
  119 +
  120 + if ($(this).text() === '个人') {
  121 + $companyArea.slideUp();
  122 + }
  123 +});
  124 +
  125 +// 发票类型选择
  126 +$('.invoice-type span').on('touchstart', function() {
  127 + if ($(this).hasClass('on')) {
  128 + return;
  129 + } else {
  130 + $(this).addClass('on').siblings().removeClass('on');
  131 + $editFlag.val('true');
  132 +
  133 + // 纸质发票不显示手机号
  134 + if ($(this).index() === 1) {
  135 + $telArea.slideUp();
  136 + } else {
  137 + $telArea.slideDown();
  138 + }
  139 + }
  140 +});
  141 +
  142 +// 发票须知
  143 +$('.invoice-btn').on('touchstart', function() {
  144 + $invoiceNotice.fadeIn();
  145 + return false;
  146 +});
  147 +
  148 +// 关闭发票须知弹框
  149 +$('.think-ok, .mask-bg').on('touchstart', function() {
  150 + $invoiceNotice.fadeOut();
  151 +});
  152 +
  153 +// 电话清空
  154 +$('.istel').one('input', function() {
  155 + $(this).val('').removeClass('istel');
  156 +});
  157 +
  158 +$tel.on('input', function() {
  159 + $(this).attr('data-tel', $(this).val());
  160 + $editFlag.val('true');
  161 + isModifyTel = true;
  162 +});
  163 +
  164 +$company.on('input', function() {
  165 + $editFlag.val('true');
  166 +});
  167 +
  168 +// 确认及返回事件
  169 +$('.confirm-btn, .nav-back').on('touchstart', function(e) {
  170 +
  171 + setTimeout(function() {
  172 + if (window._yas && window._yas.sendCustomInfo) {
  173 + window._yas.sendCustomInfo({
  174 + op: 'YB_SC_INVOICE_INFO_SAVE',
  175 + param: JSON.stringify({
  176 + C_ID: C_ID,
  177 + INVOICE_TYPE: $invoiceType.find('.on').data('id'),
  178 + INVOICE_TITLE: $('.invoice-top').find('.on').text(),
  179 + INVOICE_CONTENT: $chooseCont.data('id')
  180 + })
  181 + }, true);
  182 + }
  183 + }, 200);
  184 +
  185 + e.preventDefault();
  186 + confirmAction();
  187 +});
  188 +
  189 +// initData();
@@ -590,7 +590,7 @@ @@ -590,7 +590,7 @@
590 590
591 span { 591 span {
592 display: inline-block; 592 display: inline-block;
593 - width: 130px; 593 + width: 160px;
594 } 594 }
595 } 595 }
596 596