Authored by htoooth

Merge branch 'feature/yohood' into release/5.9

/**
* 立即购买controller
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/9/23
*/
'use strict';
const headerModel = require('../../../doraemon/models/simple-header');
const ticketService = require('../models/ticket-service');
const _ = require('lodash');
const stepper = [
{ name: '填写订单', focus: true },
{ name: '付款,完成购买' }
];
const ticketEnsure = (req, res, next) => {
let uid = req.user.uid;
let sku = req.body.productSku || 0;
let buyNumber = req.body.buyNumber || 0;
ticketService.addTicket(uid, sku, buyNumber).then(result => {
let header = headerModel.setSimpleHeaderData() || {};
result.stepper = stepper;
res.render('ticket-ensure', {
title: '填写订单 | ' + (res.locals.title || ''),
page: 'ticket',
content: result,
simpleHeader: header,
pageClass: 'order-easypay-page'
});
}).catch(next);
};
const ticketSubmit = (req, res, next) => {
let uid = req.user.uid;
let sku = req.body.sku || 0;
let count = req.body.count || 0;
let mobile = req.body.mobile || 0;
let yohoCoin = req.body.yohoCoin || 0;
if (!sku || !count || !mobile) {
return res.json({
code: 410,
message: '参数错误'
});
}
ticketService.submitTicket(uid, sku, count, mobile, yohoCoin).then(result => {
return res.json(result);
}).catch(next);
};
const ticketCompute = (req, res, next) => {
let uid = req.user.uid;
let sku = req.body.sku || 0;
let buyNumber = req.body.count || 0;
let yohoCoin = req.body.coin || 0;
ticketService.addTicket(uid, sku, buyNumber, yohoCoin).then(result => {
if (_.isEmpty(result)) {
return res.json({
code: 401,
message: '不成功'
});
}
return res.json({
code: 200,
data: result
});
}).catch(next);
};
module.exports = {
ticketSubmit,
ticketEnsure,
ticketCompute
};
... ...
/**
* Created by TaoHuang on 2017/6/22.
*/
const api = global.yoho.API;
/**
* 电子票下单
* @param uid 用户id
* @param sku 商品sku
* @param count 购买数量 1-4
* @param mobile 手机号码
* @param yohoCoin 有货币
*/
function submit(uid, sku, count, mobile, yohoCoin) {
let params = {
method: 'app.shopping.submitTicket',
uid,
product_sku: sku,
buy_number: count,
mobile: mobile
};
if (yohoCoin) {
params.use_yoho_coin = yohoCoin / 100;
}
return api.get('', params);
}
/**
* 电子票添加和查询
* @param uid 用户 id
* @param sku 商品sku
* @param count 购买数量 1-4
* @param yohoCoin 有货币
*/
function add(uid, sku, count, yohoCoin) {
let params = {
method: 'app.shopping.ticket',
uid,
product_sku: sku,
buy_number: count
};
if (yohoCoin) {
params.use_yoho_coin = yohoCoin / 100;
}
return api.get('', params);
}
module.exports = {
submit,
add
};
... ...
/**
* Created by TaoHuang on 2017/6/22.
*/
const api = require('./ticket-api');
const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const _handleUseYhoCoin = require('./order-ensure-handle').handleUseYohoCoin;
function _handleGoodsList(list) {
return list.map((i) => {
i.linkToGoods = helpers.getUrlBySkc(i.product_skn);
i.productPrice = i.sales_price;
return i;
});
}
function _handleAmount(info) {
return _.get(info, 'data.shopping_cart_data.last_order_amount', 0);
}
const addTicket = co(function * (uid, sku, count, yohoCoin) {
let ticketInfo = yield api.add(uid, sku, count, yohoCoin);
let result = {};
if (ticketInfo.code !== 200) {
return result;
}
result.goodsList = _handleGoodsList(_.get(ticketInfo, 'data.goods_list', []));
result.last_order_amount = _handleAmount(ticketInfo);
Object.assign(result, _handleUseYhoCoin(_.get(ticketInfo, 'data.shopping_cart_data', {})));
return result;
});
const submitTicket = co(function * (uid, sku, count, mobile, yohoCoin) {
let result = yield api.submit(uid, sku, count, mobile, yohoCoin);
if (result.code !== 200) {
return {
code: 410,
message: '提交失败'
};
}
return {
code: 200,
message: '提交成功',
data: {
refer: helpers.urlFormat('/shopping/newpay', {
ordercode: result.data.order_code
})
}
};
});
module.exports = {
addTicket,
submitTicket
};
... ...
... ... @@ -15,6 +15,7 @@ const cart = require(`${cRoot}/cart`);
const address = require(`${cRoot}/address`);
const easypay = require(`${cRoot}/easypay`);
const ensure = require(`${cRoot}/order-ensure`);
const ticket = require(`${cRoot}/ticket`);
router.get('/index/getProductInfo', cart.getProductInfo);
router.post('/cart/detailAdd', cart.cartAddIndex); // 加入购物车 商品详情页
... ... @@ -36,6 +37,10 @@ router.get('/easypay', auth, easypay.index); // 限购商品快捷结算页
router.post('/easypay/compute', auth, easypay.compute); // 价格重新计算
router.post('/easypay/submit', auth, easypay.submit); // 限购商品订单提交
router.post('/ticketEnsure', auth, ticket.ticketEnsure);
router.post('/ticketSubmit', auth, ticket.ticketSubmit);
router.post('/ticketCompute', auth, ticket.ticketCompute);
router.get('/cart', cart.cart);
router.post('/cart/select', cart.selectProduct);
router.post('/cart/modifyNum', cart.modifyProductNum);
... ...
<div class="order-ensure2016 yoho-page {{pageClass}}">
{{# content}}
<div class="order-ensure-title">
{{> shopping-step}}
</div>
<div class="address-wrap">
<div class="block-title">请填写并核对以下信息</div>
<div class="ticket-selection">
<div class="title">支付及发劵时间:</div>
<ul class="modity-pay-info">
<li>付款方式:<span>在线支付</span></li>
<li>发劵时间:<span>自动发货 - 在您支付成功后,系统将立即为您发放二维码,您可以在您的订单中查看。</span></li>
<li>手机号:
<span class="show-ticket-mobile hide">
<span class="ticket-mobile"></span><span class="ticket-modify-btn">[修改]</span>
</span>
<span class="set-ticket-mobile">
<input type="text" value="" class="ticket-mobile-input"/>
<span class="ticket-mobile-tip">请填写正确手机号以便于接收票条信息</span>
</span>
</li>
</ul>
</div>
</div>
<div class="goods-wrap">
<div class="block-title">订单商品信息</div>
<table class="goods-table">
<thead>
<tr>
<th width="3%"></th>
<th class="aline-left" width="46%">商品信息</th>
<th>颜色/尺码</th>
<th width="18%">单价</th>
<th width="6%">数量</th>
<th width="3%"></th>
</tr>
</thead>
<tbody>
{{#each goodsList}}
<tr class="goods-item" data-skn="{{product_skn}}" data-sku="{{product_sku}}"
data-price="{{last_price}}" data-num="{{buy_number}}">
<td{{#if @first}} class="border-top"{{/if}}></td>
<td class="border-top aline-left">
<a class="image" href="{{linkToGoods}}">
<img src="{{image2 goods_images w=64 h=85}}" class="thumb">
<p class="name">
{{product_name}}
</p>
</a>
</td>
<td class="border-top color-size">
颜色:<span class="color">{{color_name}}</span>
尺码:<span class="size">{{size_name}}</span>
</td>
<td class="border-top price">
<p class="red">¥ {{round productPrice 2}}</p>
</td>
<td class="border-top">× {{buy_number}}</td>
<td{{#if @first}} class="border-top"{{/if}}></td>
</tr>
{{/each}}
</tbody>
</table>
</div>
<div class="extra-wrap ticket-wrapper">
<dl>
<dt><span class="locker-switch"></span>使用有货币</dt>
<dd id="yoho-coin-box" class="yoho-coin-box" data-coin="{{usedCoinNum}}"
data-max={{canUseCoinNum}} data-total="{{total_yoho_coin_num}}">
<div class="outer-view">
<p class="coin-err-tip">{{coinErrorTip}}</p>
<p>有货币满<span class="red">{{yoho_coin_pay_rule.num_limit}}</span>个即可使用,每次使用有货币为<span
class="red">{{yoho_coin_pay_rule.num_limit}}</span>的整数倍</p>
<i class="help-icon"></i>
<div class="coin-tip-help">
<p>有货币使用提示:</p>
<p>
1.订单金额大于20元(含20元)<br>
2.有货币数量大于{{yoho_coin_pay_rule.num_limit}}个(含{{yoho_coin_pay_rule.num_limit}}个) <br>
3.有货币支付上限为每笔订单应付金额的{{yoho_coin_pay_rule.max_pay_rate_desc}}
</p>
<p class="rs-text">备注:使用有货币数量为{{yoho_coin_pay_rule.num_limit}}的整数倍,100有货币抵1元</p>
</div>
</div>
<div class="coin-main-view">
<p>本次使用有货币<span class="red">{{canUseCoinNum}}</span>个,抵扣 <span class="red">¥{{yoho_coin}}</span>
</p>
<p class="grey fw300">您当前共有有货币 <span class="red">{{total_yoho_coin_num}}</span> 个,可用 <span
class="red">{{canUseCoinNum}}</span></p>
<label class="coin-cancel-btn fw300">取消使用</label>
<label class="coin-use-btn">确定</label>
</div>
</dd>
</dl>
</div>
<div class="sum-wrap">
应付金额:<span id="order-price" class="price">¥ {{round last_order_amount 2}}</span>
<button id="order-submit">提交订单</button>
</div>
{{/ content}}
</div>
... ...
... ... @@ -6,7 +6,7 @@
'use strict';
const QRcodeModel = require('../models/qrcode');
const QRcodeModel = require('../models/qrcode-api');
const helpers = global.yoho.helpers;
exports.QRcode = (req, res, next) => {
... ...
... ... @@ -76,7 +76,7 @@ const ORDER_OP_ALL = [
type: 'lookQrcode',
name: '查看二维码',
qrcode: true,
hrefFun: it => helpers.urlFormat('/home/orders/detail', {orderCode: it})
hrefFun: it => helpers.urlFormat('/home/qrcode', {orderCode: it})
},
{
type: 'afterService',
... ... @@ -404,7 +404,8 @@ const getOrders = (uid, page, limit, type, isPage)=> {
newGood.refundStatus = refundNum > 0;// 只要发生一件退换,退换过的标记
newGood.goRefundUrl = helpers.urlFormat('/home/returns');
newGood.arrivalDate = good.expect_arrival_time;
let goodsTagName = _getGoodsTag(order.attribute, good.goods_type);
let goodsTagName = _getGoodsTag(+order.attribute, good.goods_type);
if (goodsTagName) {
newGood[goodsTagName] = true;
... ... @@ -525,7 +526,7 @@ const _getVirtualPro = (isCancel, status, createTime) => {
process.middleStatus[1].cur = true;
} else if (status === 6) {
process.percent = '100%';
process.middleStatus[3].cur = true;
process.middleStatus[2].cur = true;
}
}
... ... @@ -707,7 +708,7 @@ const _getOrderDetail = co(function * (uid, orderId) {
detail.progress = statusInfo.cancel ? false : (function() {
// 未取消订单,进度
if (orderDetail.attribute === 3) {
if (+orderDetail.attribute === 3) {
return _getVirtualPro(orderDetail.is_cancel, +orderDetail.status, orderDetail.create_time);
} else {
if (isOfflineBySelf(orderDetail)) {
... ... @@ -735,7 +736,7 @@ const _getOrderDetail = co(function * (uid, orderId) {
detail.traceOrder.courierNumbe = expressInfo.courierNumbe;
// 虚拟商品
if (orderDetail.attribute === 3) {
if (+orderDetail.attribute === 3) {
detail.virtualGoods = true;
detail.virtualPayMode = {
payMode: ChannelConfig.payType[orderDetail.payment_type],
... ... @@ -797,7 +798,7 @@ const _getOrderDetail = co(function * (uid, orderId) {
num: good.buy_number,
sum: good.goods_amount,
sku: good.product_sku,
[_getGoodsTag(good.attribute, good.goods_type)]: true
[_getGoodsTag(+good.attribute, good.goods_type)]: true
};
// 划线的价格
... ... @@ -847,6 +848,7 @@ const _getOrderDetail = co(function * (uid, orderId) {
detail.operation = _getOrderDetailOp(orderDetail.order_code, +orderDetail.payment, +orderDetail.status,
orderDetail.is_cancel, orderDetail.payment_status, orderDetail.payment_type,
+orderDetail.order_type, +orderDetail.attribute, +orderDetail.refund_status);
detail.packageTitle = orderDetail.package_title;
detail.packages = _getPackageInfo(orderDetail);
... ...
... ... @@ -38,7 +38,6 @@
<div class='clearfix'></div>
</div>
</div>
<a class='btn-qcode' href='#'>打印二维码</a>
</div>
{{/qrcodeData}}
<div class='subtitle'>
... ... @@ -50,26 +49,11 @@
如何使用二维码
</p>
<p class='tro'>
1、点击【打印二维码】按钮打印,入场时出示二维码电子票检验入场;
2、每个二维码只能使用一次,请保管好您的序列号,不要随意泄露给其他
人。
1、入场时出示二维码电子票检验入场。
</p>
</div>
<div class="main-info">
<p class="p1">
如何获取二维码
</p>
<p class='tro'>
1、您可以点击【打印二维码】将票面打印,请在打印时将版面设置成横向打
印;
2、如果您的电脑未连接打印机,请点击【打印二维码】后,将弹出的票面图
片截图并保存,然后另行打印。
</p>
</div>
<div class="main-info">
<p class='gray'>
1、请保持票面干净完整,入场时只需要出示打印票面进行检验即可入场,每个
二维码只可使用一次,请您妥善保管。2、如果您的电脑未连接打印机,请点击【打印二维码后】,将弹出的票面图片截图并保存,然后另行打印。
<p class="tro">
2、每个二维码只能使用一次,请保管好您的序列号,不要随意泄露给其他人。
</p>
</div>
</div>
... ...
... ... @@ -166,6 +166,7 @@
</a>
<div class="logistics hide"> </div>
{{/if}}
{{/ operation}}
</div>
</div>
... ...
... ... @@ -37,9 +37,6 @@ const BUNDLE_PRODUCE = 2; // 量贩
const BUNDLE_PACKAGE = 1; // 套餐
const tdk = require('../../../utils/getTDK');
// 展览票
const YOHOOD_TICKET = 51335912;
const _getProductAdditionInfoAsync = (data) => {
return co(function * () {
let productId = _.get(data, 'product_id', 0);
... ... @@ -1383,12 +1380,13 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
};
}
// 电子票
result.isTicket = propOrigin('product_skn') === YOHOOD_TICKET;
// 虚拟商品目前只有电子票
result.isTicket = virtualGoods;
if (virtualGoods && result.isTicket) {
// 虚拟商品
result.buyNow = true; // 是否立即购买
result.buyNowBase = helpers.urlFormat('/ticket', null, 'shopping');
result.buyNowBase = helpers.urlFormat('/cart/ticketEnsure');
if (result.salePrice) {
result.advancePrice = result.salePrice; // 先行价格
delete result.salePrice;
... ...
... ... @@ -131,7 +131,7 @@
{{#if virtualGoods}}
{{!-- 电子门票按钮 --}}
{{#if isVirtualBtn}}
<form name="ticket-form" action="//www.yohobuy.com/cart/index/ticketEnsure" method="POST"
<form name="ticket-form" action="{{buyNowBase}}" method="POST"
class="hide"></form>
<span id="buy-ticket" class="buy-ticket buy-now item-buy{{#if dis}} dis{{/if}}">立即购买</span>
{{/if}}
... ...
... ... @@ -10,11 +10,11 @@
</ul>
</div>
<div class="chose-size row clearfix {{#if isTicket}} hide {{/if}}">
<div class="chose-size row clearfix {{#unless isTicket}} hide {{/unless}}">
<input type="hidden" name="isTicket" value="{{isTicket}}"/>
<span class="title pull-left">
选区域:
</span>
<span class="title pull-left">
选区域:
</span>
<div id="sizes" class="size-wrapper pull-left">
{{#each colors}}
... ... @@ -25,9 +25,9 @@
{{/each}}
<span class="size-warn warn-tip hide">
<i class="iconfont">&#xe62c;</i>
请选择区域
</span>
<i class="iconfont">&#xe62c;</i>
请选择区域
</span>
</ul>
{{/each}}
</div>
... ...
... ... @@ -24,13 +24,21 @@ module.exports = {
// global: 'http://global-test-soa.yohops.com:9999/',
// platformApi: 'http://192.168.102.48:8088/',
// test2
singleApi: 'http://api-test2.yohops.com:9999/',
api: 'http://api-test2.yohops.com:9999/',
service: 'http://service-test2.yohops.com:9999/',
serviceNotify: 'http://service-test2.yohops.com:9999/',
global: 'http://global-test-soa.yohops.com:9999/',
platformApi: 'http://192.168.102.48:8088/',
// prod
singleApi: 'http://single.yoho.cn/',
api: 'http://api.yoho.cn/',
service: 'http://service.yoho.cn/',
serviceNotify: 'http://service.yoho.cn/',
global: 'http://api-global.yohobuy.com/',
platformApi: 'http://172.16.6.210:8088/',
// singleApi: 'http://single.yoho.cn/',
// api: 'http://api.yoho.cn/',
// service: 'http://service.yoho.cn/',
// serviceNotify: 'http://service.yoho.cn/',
// global: 'http://api-global.yohobuy.com/',
// platformApi: 'http://172.16.6.210:8088/',
// gray
// singleApi: 'http://single.gray.yohops.com/',
... ... @@ -220,8 +228,7 @@ if (isProduction) {
search: process.env.TEST_SEARCH || 'http://192.168.102.216:8080/yohosearch/',
serviceNotify: process.env.TEST_SERVICE || 'http://testservice.yoho.cn:28077/',
imSocket: 'ws://socket.yohobuy.com:10240',
imCs: 'http://im.yohobuy.com/api',
platformApi: 'http://192.168.102.48:8088/'
imCs: 'http://im.yohobuy.com/api'
},
useOneapm: true,
useCache: true,
... ...
/**
* Created by TaoHuang on 2017/6/22.
*/
var $ = require('jquery');
var yas = require('../common/data-yas'),
dialog = require('../common/dialog');
var $orderPrice = $('#order-price');
var order = {};
var yohoCoin;
var submitting = false;
require('../common');
require('../simple-header');
function validateUserInfo(info) {
var errTip = '';
if (!info.mobile) {
errTip = '您还没有填写手机号';
}
if (errTip) {
new dialog.Alert((errTip)).show();
return false;
}
return true;
}
function handleOrderInfo(info) {
var $goods = $('.goods-item');
info.sku = $goods.data('sku');
info.count = $goods.data('num');
info.mobile = $('.ticket-mobile-input').val();
return info;
}
function compute(coin) {
var req;
order = handleOrderInfo(order);
req = $.extend({}, order, {
coin: coin || 0
});
$.ajax({
type: 'POST',
url: '/cart/ticketcompute',
data: req
}).then((result) => {
if (result.code === 200) {
order.coin = result.data.usedCoinNum;
yohoCoin.maxCoin = result.data.canUseCoinNum;
$orderPrice.html('¥ ' + result.data.last_order_amount);
}
});
}
// 有货币
yohoCoin = {
$el: $('#yoho-coin-box'),
init: function() {
var data;
if (!this.$el.length) {
return;
}
data = this.$el.data();
if (data) {
order.coin = data.coin || 0;
this.maxCoin = data.max;
this.totalCoin = data.total;
}
this.eventBind();
},
eventBind: function() {
var that = this;
this.$el.on('click', '.coin-use-btn', function() {
if (order.coin * 1 !== this.maxCoin * 1) {
compute(that.maxCoin);
}
that.close();
}).on('click', '.coin-cancel-btn', function() {
if (order.coin * 1 !== 0) {
order.coin = 0;
compute();
}
that.close();
});
},
close: function() {
this.$el.prev().children('.locker-switch').trigger('click');
}
};
$('.locker-switch').click(function() {
var $this = $(this),
$par = $this.parent();
$par.toggleClass('open');
});
$('#order-submit').on('click', function() {
if (submitting) {
return;
}
order = handleOrderInfo(order);
if (!validateUserInfo(order)) {
return;
}
submitting = true;
$.ajax({
type: 'POST',
url: '/cart/ticketSubmit',
data: order
}).then(function(data) {
if (data.code === 200) {
window.location.href = data.data.refer;
}
}).always(function() {
submitting = false;
});
});
yohoCoin.init();
// 获取用户是否新客(品众统计)写cookie
$.ajax({type: 'GET', url: '/home/newuser'});
// 订单确认页默认埋点
yas.givePoint('YB_SC_ORDER_ENSURE');
... ...
... ... @@ -3,9 +3,6 @@ var Slide = require('../plugins/yohoui/YH.slide');
var $item = $('li', '.qrctxt');
var len = $item.length, slide;
var src = /url\("([^'"]*)"\)/g.exec($('.print-qrcode').css('background'))[1];
$('.print-qrcode').find('img').attr('src', src);
require('../common');
... ...
... ... @@ -212,7 +212,7 @@ bindEvent.add(function() {
var $descColor = $('#desc-color');
var thumbsLoaded = {};
var isTicket = $('input[name="isTicket"]').length > 0 && $('input[name="isTicket"]').val() === 'true';
var isTicket = $('input[name="isTicket"]').length > 0;
var brandDomain = $('.home').attr('href');
... ... @@ -598,21 +598,25 @@ bindEvent.add(function() {
$sizes.not('.hide').addClass('hide').children('li').removeClass('focus');
$sizes.eq(index).removeClass('hide');
// 是否展览
// 是否
if (isTicket) {
$sizes.eq(index).children('li').trigger('click');
$('.chose-size').addClass('hide');
}
// 隐藏 仅剩 X 件 提示
$('.few-sold').addClass('hide');
}
// 没有选中尺码
maxStock = +$('.size:not(.hide) li.focus').data('num');
// 选中尺码
if ($('.size:not(.hide) li.focus').length === 1) {
maxStock = +$('.size:not(.hide) li.focus').data('num');
} else {
// 没有选中
maxStock = -1;
}
// 如果库存数量为 0,表示已售罄
if (!maxStock) {
maxStock = -1;
$enableNotifyYou.addClass('hide'); // 没有
// 初始化color-size显示或隐藏
... ... @@ -935,31 +939,13 @@ bindEvent.add(function() {
sku = $('.size:not(.hide) li.focus').data('sku');
buyNumber = getNum();
$.ajax({
type: 'POST',
url: '/cart/index/setTicket',
data: {
productSku: sku,
buyNumber: buyNumber
}
}).then(function(data) {
var $ticketForm,
myAlert;
if (data.code * 1 === 200) {
$ticketForm = $('form[name="ticket-form"]');
$ticketForm.html(
'<input name="productSku" value="' + sku + '" />' +
'<input name="buyNumber" value="' + buyNumber + '" />'
);
$ticketForm.submit();
} else if (data.code * 1 === 401) {
document.location.href = data.message;
} else {
myAlert = new Alert(data.message);
myAlert.show();
}
});
var $ticketForm = $('form[name="ticket-form"]'); // eslint-disable-line
$ticketForm.html(
'<input name="productSku" value="' + sku + '" />' +
'<input name="buyNumber" value="' + buyNumber + '" />'
);
$ticketForm.submit();
});
// 立即购买
... ...
... ... @@ -827,6 +827,44 @@
}
}
.ticket-wrapper {
border-bottom-color: #e8e8e8;
border-top-color: #fff;
}
.ticket-selection {
font-size: 15px;
line-height: 1.5;
.title {
line-height: 40px;
font-size: 16px;
padding-left: 25px;
font-weight: bold;
margin-top: 10px;
}
.modity-pay-info {
li {
padding-left: 30px;
margin-bottom: 15px;
.ticket-mobile-input {
width: 208px;
border: 1px solid #b0b0b0;
padding: 5px;
margin-right: 10px;
font-size: 14px;
}
.ticket-mobile-tip {
color: #da0045;
margin-left: 15px;
}
}
}
}
.use-coupons {
.tip-box {
width: 60%;
... ...