Authored by biao

update for cancel order, show btns on detail page, and fix some bugs

... ... @@ -37,6 +37,7 @@ const detail = (req, res) => {
orderModel.getOrderDetail(uid, code).then(result => {
res.render('index', {
isMe: true,
page: 'order-detail',
content: Object.assign({
nav: mcHandler.getMeCrumb(),
navigation: mcHandler.getSideMenu('订单详情'),
... ... @@ -103,6 +104,12 @@ const getExpressInfo = (req, res) => {
});
};
const getCancelOrderReason = (req, res) => {
orderModel.getCancelOrderReason().then(result => {
res.json(result);
});
};
module.exports = {
index: index,
detail: detail,
... ... @@ -110,5 +117,6 @@ module.exports = {
getOrderTotal: getOrderTotal,
cancelOrder: cancelOrder,
deleteOrder: deleteOrder,
getExpressInfo: getExpressInfo
getExpressInfo: getExpressInfo,
getCancelOrderReason: getCancelOrderReason
};
... ...
... ... @@ -8,63 +8,110 @@ const _ = require('lodash');
const pageSize = 10;
// 订单列表类型对应的导航下标
const typeActiveIndexMap = {
1: 0,
2: 1,
3: 2
};
const btnMap = {
all: [
{
name: '立即付款',
classStr: 'btn red pay-btn mr'
},
{
name: '修改订单',
classStr: 'btn white edit-btn mr'
},
{
name: '取消订单',
classStr: 'btn white cancel-btn'
}
],
edit: [
{
name: '修改订单',
classStr: 'btn white edit-btn'
}
],
complete: [
{
name: '确认收货',
classStr: 'btn complete-btn'
}
]
};
// 订单状态
const statusMap = {
0: {
value: 0,
valueStr: '待付款',
step: 1
step: 1,
btns: btnMap.all
},
1: {
value: 1,
valueStr: '已付款',
step: 1
valueStr: '备货中',
step: 1,
btns: btnMap.edit
},
2: {
value: 1,
valueStr: '备货中',
step: 1
step: 1,
btns: btnMap.edit
},
3: {
value: 1,
valueStr: '配货中',
step: 1
valueStr: '备货中',
step: 1,
btns: btnMap.edit
},
4: {
value: 2,
valueStr: '已发货',
step: 2
step: 2,
showGetBtn: true,
btns: btnMap.complete
},
5: {
value: 2,
valueStr: '运输中',
step: 3
valueStr: '待收货',
step: 3,
showGetBtn: true,
btns: btnMap.complete
},
6: {
value: 3,
valueStr: '已完成',
step: 4
valueStr: '交易完成',
step: 4,
showEditor: true
}
};
// 订单类型为手机的订单
const isMobileOrder = {
3: true,
4: true,
6: true
};
// 根据订单状态获取当前步骤
const _getStepByOrderStatus = (st) => {
let steps = [
{
stepStr: '1.提交订单'
} ,
},
{
stepStr: '2.商品出库'
} ,
},
{
stepStr: '3.等待收货'
} ,
},
{
stepStr: '4.交易完成'
}
... ... @@ -75,11 +122,13 @@ const _getStepByOrderStatus = (st) => {
steps[i].isActive = true;
}
// 最后一个激活步骤需要特殊处理样式
steps[curStep - 1].isLastActive = true;
return steps;
}
};
// 转换时间戳
const _convertUnixTime = (src) => {
return moment.unix(src).format('YYYY-MM-DD hh:mm:ss');
};
... ... @@ -104,6 +153,15 @@ const cancelOrder = (uid, code) => {
});
};
const getCancelOrderReason = () => {
return api.get('', {
method: 'app.SpaceOrders.closeReasons'
}, {
cache: true
});
};
const getExpressInfo = (uid, code) => {
return api.get('', {
method: 'app.express.get',
... ... @@ -159,19 +217,22 @@ const _getUserOrder = (uid, type, page) => {
// 具体订单类型见 http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/%E8%AE%A2%E5%8D%95/order.md
// 判断是否是手机订单,3, 4, 6对应 iOS, Android, H5
item.showMobile = ot === 3 || ot === 4 || ot === 6;
item.showMobile = isMobileOrder[ot];
// 判断是否展示编辑选项
item.showEditOption = st === 6;
item.showEditOption = statusMap[st].showEditor;
// 判断是否是待收货状态
item.showGetBtn = st === 4 || st === 5;
item.showGetBtn = statusMap[st].showGetBtn;
item.showBuyBtn = item.isCancel === 'Y';
if (item.statusStr === '已付款') {
item.statusStr = '备货中';
if (item.isCancel === 'Y') {
item.showBuyBtn = true;
item.statusStr = '已取消';
} else {
item.statusStr = statusMap[st].valueStr;
}
});
return {
... ... @@ -182,6 +243,40 @@ const _getUserOrder = (uid, type, page) => {
});
};
const _convertAddress = (addressList, createTime) => {
let addrList = [];
addressList.forEach(addr => {
let address = {
time: '',
city: '',
action: ''
};
address.time = addr.acceptTime;
addr = addr.acceptAddress.split(' ');
if (addr.length > 1 && /市/.test(addr[0])) {
address.city = addr[0].replace('市', '');
addr.splice(0, 1);
address.action = addr.join('');
} else {
address.action = addr.join('');
}
addrList.push(address);
});
// 增加一个默认初始状态
addrList.push({
time: createTime,
action: '您的订单已提交,等待付款'
});
return _.reverse(addrList);
};
const getOrderData = (uid, type, page) => {
const navBar = {
tabs: [
... ... @@ -234,34 +329,6 @@ const getOrderData = (uid, type, page) => {
});
};
const _convertAddress = addressList => {
let addrList = [];
addressList.forEach(addr => {
let address = {
time: '',
city: '',
action: ''
};
address.time = addr.acceptTime;
addr = addr.acceptAddress.split(' ');
if (addr.length > 1 && /市/.test(addr[0])) {
address.city = addr[0].replace('市', '');
addr.splice(0, 1);
address.action = addr.join('');
} else {
address.action = addr.join('');
}
addrList.push(address);
});
return _.reverse(addrList);
};
const getOrderDetail = (uid, code) => {
return api.all([_getDetail(uid, code), getExpressInfo(uid, code)]).then(result => {
let detail = result[0] && camelCase(result[0].data);
... ... @@ -280,10 +347,12 @@ const getOrderDetail = (uid, code) => {
if (detail.isCancel !== 'Y') {
detail.steps = _getStepByOrderStatus(detail.status);
detail.btns = statusMap[detail.status].btns;
}
detail.expressInfo = express;
detail.expressInfo.addressList = _convertAddress(express.expressDetail);
detail.expressInfo.addressList = _convertAddress(express.expressDetail, detail.createTime);
return {
orderDetail: Object.assign(basicData, detail)
... ... @@ -296,6 +365,7 @@ module.exports = {
getOrderData: getOrderData,
getOrderDetail: getOrderDetail,
cancelOrder: cancelOrder,
getCancelOrderReason: getCancelOrderReason,
deleteOrder: deleteOrder,
getExpressInfo: getExpressInfo
};
... ...
... ... @@ -20,6 +20,7 @@ router.get('/getOrderList', order.getOrderList);
router.get('/getOrderTotal', order.getOrderTotal);
router.get('/deleteOrder', order.deleteOrder);
router.get('/cancelOrder', order.cancelOrder);
router.get('/getCancelOrderReason', order.getCancelOrderReason);
router.get('/getExpressInfo', order.getExpressInfo);
// 个人中心首页/收货地址
... ...
... ... @@ -5,7 +5,7 @@
<li class="first">商品信息</li>
<li>价格</li>
<li>数量</li>
<li></li>
<li></li>
</ul>
<div class="table-body">
{{> order/goods-box}}
... ...
{{# expressInfo}}
<div class="order-express info-box">
<h4 class="status-title">订单跟踪</h4>
{{#if expressNumber}}
<div class="express-basic">
<p>物流公司:{{caption}}</p>
<p>运单号:{{expressNumber}}</p>
</div>
{{/if}}
<div class="express-detail">
<div class="table">
<ul class="header">
... ...
<div class="order-status">
<div class="order-status order" data-code="{{orderCode}}">
<div class="basic">
<p>订单号:{{orderCode}}</p>
<p>订单状态:{{statusStr}}</p>
<div class="edit-btns">
<span class="btn black">确认收货</span>
<ul>
{{# btns}}
<li>
<span class="{{classStr}}">{{name}}</span>
</li>
{{/ btns}}
</ul>
</div>
</div>
... ...
var cancelOrder = require('./order/cancel-order');
function reload() {
location.href = location.href;
}
$('.cancel-btn').on('click', function() {
var $this = $(this);
var code = $this.closest('.order').data('code');
cancelOrder.start(code, reload);
});
... ...
... ... @@ -9,6 +9,8 @@ var _dialog = dialog.Dialog;
var expressTpl = require('../../tpl/me/express.hbs');
var cancelOrder = require('./order/cancel-order');
// 更新表格
var tableOperation = {
$header: $('.table.column-category'),
... ... @@ -86,8 +88,6 @@ var typeMap = {
// 个人中心共用代码加载
require('./me');
// 添加.check方法
require('../plugins/check');
// 获取订单列表
function getOrderList(type, page) {
... ... @@ -217,35 +217,7 @@ function deleteOrder(code, $el) {
});
}
// 取消订单
function cancelOrder(code, $el) {
$.ajax({
url: 'cancelOrder',
data: {
orderCode: code
}
}).done(function() {
var tip = new _dialog({
className: 'order-dialog',
content: '<h1>订单修改</h1>' +
'<span>您已成功取消了该订单</span>',
closeCb: updateTableContent.bind(null, $el.closest('.order')),
btns: [
{
id: 'cancel-complete',
btnClass: ['confirm'],
name: '确定',
cb: function() {
tip.close(updateTableContent.bind(null, $el.closest('.order')));
}
}
]
}).show();
}).fail(function(err) {
console.log(err);
});
}
// 取消订单
function getExpressInfo(code, $el) {
... ... @@ -274,9 +246,11 @@ function getExpressInfo(code, $el) {
// tab切换处理
// searchBar相关处理暂时不上线
$('.tabs li').on('click', function() {
var $this = $(this);
var $searchBar = $('.search-bar');
// var $searchBar = $('.search-bar');
var type = typeMap[$this.data('type')];
... ... @@ -288,11 +262,11 @@ $('.tabs li').on('click', function() {
$this.find('.badge').text('');
// 搜索栏只在全部订单tab下才显示
if (type !== 1) {
$searchBar.addClass('vhide');
} else {
$searchBar.removeClass('vhide');
}
// if (type !== 1) {
// $searchBar.addClass('vhide');
// } else {
// $searchBar.removeClass('vhide');
// }
getOrderList(type, page);
}
... ... @@ -336,79 +310,11 @@ function bindCancelEvent() {
var $this = $(this);
var code = $this.closest('.order').data('code');
var tip = new _dialog({
className: 'order-dialog cancel-dialog',
content: '<h1>取消订单</h1>' +
'<span class="tip">您取消订单的原因是:</span>' +
'<div class="reason">' +
'<div class="row">' +
'<p><span class="iconfont raido checked">&#xe603;</span>支付不成功</p>' +
'<p><span class="iconfont raido">&#xe604;</span>现在不想购买</p>' +
'</div>' +
'<div class="row">' +
'<p><span class="iconfont raido">&#xe604;</span>订单架构有问题</p>' +
'<p><span class="iconfont raido">&#xe604;</span>修改订单信息</p>' +
'</div>' +
'<div class="row">' +
'<p><span class="iconfont raido">&#xe604;</span>错误或重复下单</p>' +
'<p><span class="iconfont raido">&#xe604;</span>忘记使用优惠券或YOHO币</p>' +
'</div>' +
'<div class="row">' +
'<p><span class="iconfont raido">&#xe604;</span>等待发货时间过长</p>' +
'<p><span class="iconfont raido">&#xe604;</span>商品价格较贵</p>' +
'</div>' +
'<div class="row">' +
'<p><span class="iconfont raido">&#xe604;</span>运费较高</p>' +
'</div>' +
'<div class="row other">' +
'<p><span class="iconfont raido">&#xe604;</span>其他原因</p>' +
'<input type="text" disabled placeholder="50个字以内"/>' +
'</div>' +
'</div>' +
'<span class="tip">温馨提示:</span>' +
'<p class="tip-item"><span class="asterisk">*</span>订单成功取消后无法恢复</p>' +
'<p class="tip-item"><span class="asterisk">*</span>该订单已付金额将原路返回</p>' +
'<p class="tip-item"><span class="asterisk">*</span>取消订单后,存在促销关系的子订单及优惠可能会一并取消</p>',
btns: [
{
id: 'cancel-confirm',
btnClass: ['confirm'],
name: '确定并取消订单',
cb: function() {
cancelOrder(code, $this.closest('.order'));
tip.close();
}
},
{
id: 'cancel-stop',
btnClass: ['cancel-btn'],
name: '暂不取消',
cb: function() {
tip.close();
}
}
]
}).show();
$('.cancel-dialog .reason p').check({
type: 'radio',
group: 'reason',
onChange: function(ele, checked) {
var $ele = $(ele);
var $input = $('.cancel-dialog .reason input');
if (checked && $ele.parent('.other').length) {
$input.prop('disabled', false);
$input.focus();
} else {
$input.val('');
$input.prop('disabled', true);
}
}
});
cancelOrder.start(code, updateTableContent.bind(null, $this.closest('.order')));
});
}
function bindExpressEvent() {
$('.express').on('click', function() {
var $this = $(this);
... ...
var dialog = require('../../plugins/dialog');
var _dialog = dialog.Dialog;
// 添加.check方法
require('../../plugins/check');
// 将一维数组转化成子数组长度为l的二维数组
function getDimensions(arr, l) {
var a = arr.slice(0, arr.length);
var newArr = [];
var subArr = [];
do {
subArr = a.splice(0, l);
newArr.push(subArr);
} while (subArr.length >= l);
return newArr;
}
function getTpl(data) {
var cancelOrderTpl = require('../../../tpl/me/cancel-order.hbs');
return cancelOrderTpl(data);
}
// 取消订单
function cancelOrder(code, onCancel) {
$.ajax({
url: '/me/cancelOrder',
data: {
orderCode: code
}
}).done(function() {
var tip = new _dialog({
className: 'order-dialog',
content: '<h1>订单修改</h1>' +
'<span>您已成功取消了该订单</span>',
closeCb: onCancel,
btns: [
{
id: 'cancel-complete',
btnClass: ['confirm'],
name: '确定',
cb: function() {
tip.close(onCancel);
}
}
]
}).show();
}).fail(function(err) {
console.log(err);
});
}
function showDiaglog(tpl, code, onCancel) {
var tip = new _dialog({
className: 'order-dialog cancel-dialog',
content: tpl,
keep: true,
btns: [
{
id: 'cancel-confirm',
btnClass: ['confirm'],
name: '确定并取消订单',
cb: function() {
cancelOrder(code, onCancel);
tip.close();
}
},
{
id: 'cancel-stop',
btnClass: ['cancel-btn'],
name: '暂不取消',
cb: function() {
tip.close();
}
}
]
}).show();
$('.cancel-dialog .reason p').check({
type: 'radio',
group: 'reason',
onChange: function(ele, checked) {
var $ele = $(ele);
var $input = $('.cancel-dialog .reason input');
if (checked && $ele.parent('.other').length) {
$input.prop('disabled', false);
$input.focus();
} else {
$input.val('');
$input.prop('disabled', true);
}
}
});
}
// 获取取消订单的理由
function getCancelReason(code, onCancel) {
$.ajax({
url: '/me/getCancelOrderReason'
}).done(function(result) {
var tpl;
var data;
var reasons = [];
if (result.code) {
data = getDimensions(result.data, 2);
data.forEach(function(d, idx) {
if (idx === 0) {
d[0].checked = true;
}
reasons.push({
subReasons: d
});
});
tpl = getTpl({
reasons: reasons
});
showDiaglog(tpl, code, onCancel);
}
}) .fail(function(err) {
console.log(err);
});
}
function start(code, onCancel) {
getCancelReason(code, onCancel);
}
module.exports = {
start: start
};
... ...
... ... @@ -21,6 +21,18 @@
right: 0;
top: 50%;
margin-top: -13px;
.btn {
cursor: pointer;
}
.mr {
margin-right: $space;
}
li {
float: left;
}
}
}
... ...
... ... @@ -26,6 +26,8 @@
}
&.cancel-dialog {
min-width: 490px;
* {
text-align: left;
color: #1b1b1b;
... ... @@ -79,7 +81,7 @@
}
p {
width: 50%;
width: 49%;
display: inline-block;
box-sizing: border-box;
font-size: 14px;
... ...
<h1>取消订单</h1>
<span class="tip">您取消订单的原因是:</span>
<div class="reason">
{{# reasons}}
<div class="row">
{{# subReasons}}
<p data-value="{{id}}">
<span class="iconfont raido {{#if checked}}checked{{/if}}">{{#if checked}}&#xe603;{{^}}&#xe604;{{/if}}</span>
{{reason}}
</p>
{{/ subReasons}}
</div>
{{/ reasons}}
</div>
<span class="tip">温馨提示:</span>
<p class="tip-item">
<span class="asterisk">*</span>订单成功取消后无法恢复
</p>
<p class="tip-item">
<span class="asterisk">*</span>该订单已付金额将原路返回
</p>
<p class="tip-item">
<span class="asterisk">*</span>取消订单后,存在促销关系的子订单及优惠可能会一并取消
</p>
... ...
... ... @@ -11,7 +11,11 @@
<p>{{accept_address}}</p>
</div>
{{/ sub_express_deatil}}
{{# sub_express_deatil}}
{{#if @first}}
<div class="tip">
<p>以上为最新跟踪信息<a href='order/detail?code={{order_code}}'>查看全部</a></p>
</div>
{{/if}}
{{/ sub_express_deatil}}
</div>
... ...