Authored by 陈轩

save

... ... @@ -50,3 +50,21 @@ exports.fetchImHistory = (uid, pageSize, startTime, endTime) => {
return ImAPI.get('/api/conversationMessage/pageList', params);
};
/**
* 获取用户订单, 默认最近10笔
* @param {int} uid 用户uid
* @param {init} createTimeBegin 开始时间
*/
exports.fetchOrderList = (uid, createTimeBegin) => {
let params = {
uid,
encryptedUid: encryptedUid(uid)
};
_.forEach({createTimeBegin}, (key, val) => {
val && (params[key] = val)
});
return ImAPI.get('/api/cs/queryUserLastTenOrdersNgoodsInfo', params);
};
... ...
... ... @@ -4,6 +4,7 @@ const orderModel = require('../../home/models/order');
const crypto = global.yoho.crypto;
const indexModel = require('../../home/models/index');
const imApi = require('../../serverAPI/im');
const imModel = require('../models/im');
exports.page = (req, res, next) => {
res.render('chat/index', {
... ... @@ -49,6 +50,13 @@ exports.msghistory = (req, res, next) => {
});
};
/**
* Request: 发表留言
* type: POST
* params:
* conversationId 会话id
* content 留言内容
*/
exports.saveMSG = (req, res, next) => {
const uid = req.user.uid;
const conversationId = req.body.conversationId;
... ... @@ -59,3 +67,22 @@ exports.saveMSG = (req, res, next) => {
res.json(result);
});
};
/**
* Request: 获取订单
* type: GET
*
* TODO:
* 1. 分页, 目前接口不支持
* 2. 失败情况
*/
exports.fetchOrders = (req, res, next) => {
const uid = req.user.uid;
imApi.fetchOrderList(uid)
.then(result => {
imModel.handleOrderList(result.data);
res.json(result);
});
};
... ...
'use strict';
/**
* im 接口数据的 处理
*/
/**
* function: 处理 订单返回的数据
*/
exports.handleOrderList = data => {
if (!data.length) {
return;
}
data.forEach(order => {
order.goods = order.ordersGoodsBoList.map(good => {
return {
id: good.productSku,
name: good.productName,
thumb: good.imgUrl,
color: good.colorName,
size: good.sizeName,
count: good.buyNumber,
price: good.lastPrice
};
});
order.count = order.ordersGoodsBoList.reduce((sum, good) => {
return sum + good.buyNumber;
}, 0);
});
};
... ...
... ... @@ -18,6 +18,7 @@ router.get('/im', chat.page);
router.get('/getOrders', chat.getOrders);
router.get('/userinfo', chat.userinfo);
router.get('/msghistory', chat.msghistory);
router.get('/order-list', chat.fetchOrders);
router.post('/leavemsg/save.json', chat.saveMSG);
router.get('/chatQaList', chatQa.qaList); // 问题搜索列表页
... ...
... ... @@ -42,11 +42,11 @@
<div class="icon"></div>
<p class="menu-name">相册</p>
</div>
<div class="icon-wrap order" id="js-order-list">
<div class="icon-wrap order" data-trigger="order-list">
<div class="icon"></div>
<p class="menu-name">订单</p>
</div>
<div class="icon-wrap broad-order">
<div class="icon-wrap broad-order" data-trigger="order-list" data-param="international">
<div class="icon"></div>
<p class="menu-name">境外订单</p>
</div>
... ... @@ -55,16 +55,7 @@
</div>
{{> chat-comment}}
{{> leave-msg}}
{{> order-list}}
{{!--订单--}}
<div id="order-list" class="chat-page chat-page-hide">
<header class="yoho-header chat-header">
<a href="javascript:void 0;" class="iconfont nav-back">&#xe610;</a>
<div class="title">选择订单</div>
</header>
<div class="main"></div>
</div>
{{> chat/leave-msg}}
{{> chat/order-list}}
<input type="hidden" id="encrypteduid" value="{{encrypteduid}}">
\ No newline at end of file
... ...
... ... @@ -7,5 +7,5 @@
<div class="main">
<textarea name="leave-text" class="leave-text" placeholder="请输入留言文字,Yoho!客服会以短信形式回复您,谢谢您对Yoho!有货的支持!"></textarea>
<button class="leave-submit">提交</button>
<div>
</div>
</div>
\ No newline at end of file
... ...
{{!--订单--}}
<div id="order-list" class="chat-page chat-page-hide">
<header class="yoho-header chat-header">
<a href="javascript:void 0;" class="iconfont chat-page-back nav-back">&#xe610;</a>
<div class="title">选择订单</div>
</header>
<div class="main">
<div data-tab="local"><!-- 订单 --></div>
<div data-tab="global"><!-- 海外订单 --></div>
</div>
</div>
... ...
<div id="order-list-wrap">
<!--im 头部-->
<header id="chat-header" class="yoho-header">
<a href="#" class="iconfont nav-back order-back">&#xe610;</a>
<div class="header-status">
<span class="service-name">订单列表</span>
</div>
</header>
<div id="order-container" class="order-container">
<div class="orders"></div>
</div>
</div>
\ No newline at end of file
<div class="msg-wrap {{style}}">
<img src="{{avatar}}" alt="" class="head-icon">
<div class="chat-info">
{{#data}}
{{> (lookup .. 'type')}}
{{/data}}
{{!--订单--}}
{{!--{{# order}}
{{/ order}}--}}
{{!--文字类型--}}
{{!--{{# text}}
{{/ text}}--}}
{{!--图片类型--}}
{{!--{{# picture}}
{{/ picture}}--}}
{{!--语音--}}
{{!--{{# voice}}
{{/ voice}}--}}
</div>
</div>
{{!--inline partails--}}
{{#*inline 'order'}}
<div class="chat-order">
<img src="{{thumb}}">
<div>
<span class="label">订单号: </span><span>{{orderCode}}</span><br>
<span class="label">金额: </span><span class="red">{{cost}}</span><br>
<span class="label">下单时间: </span><span>{{createTime}}</span><br>
<span class="label">订单状态</span><span>{{orderStatus}}</span><br>
</div>
</div>
{{/inline}}
{{#*inline 'text'}}
<div class="chat-txt">
TODO
</div>
{{/inline}}
{{#*inline 'picture'}}
<div class="chat-pic">
TODO
</div>
{{/inline}}
{{#*inline 'voice'}}
<div class="chat-voice">
TODO
</div>
{{/inline}}
{{#*inline 'system'}}
<div class="">
</div>
{{/inline}}
\ No newline at end of file
... ...
<div class="chat-txt chat-txt-order">
<img src="{{thumb}}">
<div>
<span class="label">订单号: </span><span>{{orderCode}}</span><br>
<span class="label">金额: </span><span class="red">{{cost}}</span><br>
<span class="label">下单时间: </span><span>{{createTime}}</span><br>
<span class="label">订单状态</span><span>{{orderStatus}}</span><br>
</div>
</div>
\ No newline at end of file
... ...
{{#each orders}}
<div class="order-page">
<div class="order" data-id="{{orderCode}}" data-href="{{detailUrl}}">
<header class="header">
订单编号:{{orderCode}}
<span class="order-status">{{orderStatusDesc}}</span>
</header>
<section class="order-goods">
{{# goods}}
{{> order/good}}
{{/ goods}}
</section>
<footer class="footer">
{{count}}件商品 实付<span class="sum-cost">¥{{sumCost}}</span>
{{#shippingCost}}(含运费¥{{.}}){{/shippingCost}}
</footer>
<div class="send-order clearfix">
<button class="send-order-btn">发送订单</button>
</div>
</div>
<input class="js-create-time" type="hidden" name="human-time" value="{{time}}">
</div>
{{/each}}
\ No newline at end of file
... ...
... ... @@ -5,10 +5,21 @@
'use strict';
import { time } from './time';
import { tip } from './tip';
import { Customer, Employee} from './role';
import { RatingView, LeaveMSGView, OrderListView } from './view';
import {
time
} from './time';
import {
tip
} from './tip';
import {
Customer,
Employee
} from './role';
import {
RatingView,
LeaveMSGView,
OrderListView
} from './view';
require('../../home/jquery.upload');
var saveImage = require('../../home/save-image');
... ... @@ -37,14 +48,18 @@ const resizeFooter = () => {
var chat = {
$chat: null,
$chatWin: null,
messageT: require('service/chat/msg.hbs'),
// 初始化websocket
init: function() {
this.$chat = $('#chat-main-wrap');
this.$chatWin = this.$chat.find('#chat-window');
// TODO: chat view 与 LeaveMSGView, OrderListView的通信 解耦
this.leaveMSGView = new LeaveMSGView('#leave-msg');
this.orderListView = new OrderListView();
this.orderListView = new OrderListView('#order-list');
const self = this;
... ... @@ -64,8 +79,8 @@ var chat = {
var received = JSON.parse(e.data);
console.log(received);
cmEntity.conversationId = received.newConversationId > 0 ?
received.newConversationId :
received.conversationId;
received.newConversationId :
received.conversationId;
self.getMessage(received);
}
... ... @@ -84,13 +99,73 @@ var chat = {
.on('click.leaveMSG', '[data-trigger=leave-msg]', function() {
self.leaveMSGView.trigger('show.LeaveMSGView');
})
.on('click.orderList', '#js-order-list', function() {
.on('click.orderList', '[data-trigger=order-list]', function() {
self.orderListView.trigger('show.OderListView');
});
this.orderListView
.on('selectOrder.OrderListView', function(event, data) {
let msg = {
type: 'order',
data
};
self.sendMSG(msg);
});
// TODO
},
/**
* method: 在聊天窗口上, 画出信息
* @param object msg
* {
* from: str //来源 ["customer", "robot", "employee", "system"]
* type: str //消息类型 see swtich msg.type
* data: object //消息数据
* }
*
* 测试数据:
chat.sendMSG({
type: 'order',
data: {
imgSrc: '123123123123',
orderCode: '123123123123',
cost: '123123123123',
createTime: '123123123123',
orderStatus: '123123123123'
}
})
*
*/
sendMSG: function(msg) {
this._drawMSG(msg);
switch (msg.type) {
case 'order': // 订单消息
break;
case 'pic': // 图片消息
break;
case 'voice': // 语音消息
break;
default: // 文字消息
break;
}
},
/**
* 订单消息
* @param object viewData 订单消息模版数据
*/
_drawMSG: function(viewData) {
let chatWin = this.$chatWin[0];
let html = this.messageT(viewData);
this.$chatWin.append(html);
chatWin.scrollTop = chatWin.scrollHeight; },
// 获取10条历史记录
fetchHistoryMsg: function(cb) {
const self = this;
... ... @@ -134,9 +209,9 @@ var chat = {
this.handleCusMsg(rec, msgType, message);
break;
// case allTypes.BREAK_TIME:
// breakCountdown(message);
// break;
// case allTypes.BREAK_TIME:
// breakCountdown(message);
// break;
case allTypes.ROBOT_SEND:
rec.csName = rec.csName || '客服机器人';
... ... @@ -150,16 +225,16 @@ var chat = {
this.handleCsMsg(rec, msgType, message);
break;
// case allTypes.EVAL_INVITE:
// // 客服发起
// processInfo.promoter = 2;
// showEvalModal();
// break;
// case allTypes.EVAL_INVITE:
// // 客服发起
// processInfo.promoter = 2;
// showEvalModal();
// break;
// case allTypes.CS_CHATTING:
// // 正在人工会话
// csChatting(message);
// break;
// case allTypes.CS_CHATTING:
// // 正在人工会话
// csChatting(message);
// break;
case allTypes.OFFLINE:
append(time(Date.now()).show());
... ... @@ -301,4 +376,5 @@ $('#chat-window').on('click', '.chat-image', function() {
});
window.$ = $;
\ No newline at end of file
window.$ = $;
window.chat = chat;
... ...
... ... @@ -50,6 +50,15 @@ let api = {
conversationId: conversation.conversationId,
content,
});
},
/**
* 获取订单
* TODO:
* 1. 目前接口不支持分页
*/
fetchOrders: function() {
return $.get('/service/order-list');
}
};
... ...
... ... @@ -2,7 +2,7 @@ const loading = require('../../plugin/loading'),
lazyLoad = require('yoho-jquery-lazyload');
require('../../common');
import {EventEmitter, bus} from './store';
import {EventEmitter, bus, api} from './store';
const LeaveMSGView = function(elem) {
... ... @@ -12,7 +12,7 @@ const LeaveMSGView = function(elem) {
this.bindEvents();
};
LeaveMSGView.prototype = $.extend(EventEmitter.prototype, {
LeaveMSGView.prototype = $.extend({}, EventEmitter.prototype, {
/**
* 绑定事件
* 1. 提交按钮事件
... ... @@ -22,7 +22,7 @@ LeaveMSGView.prototype = $.extend(EventEmitter.prototype, {
this.$elem
.on('click', '.chat-page-back', function() {
self.toggleView(true);
self.toggleHide(true);
})
.on('click.LeavseMSG.submit', '.leave-submit', function() {
self.submit();
... ... @@ -103,87 +103,81 @@ class RatingView {
}
}
/*
订单列表view
*/
class OrderListView {
constructor() {
this.bindEvent();
this.order = {
page: 0,
end: false
};
this.$curContainer = $('#order-container').children('.orders:not(.hide)');
this.getOrder(this);
}
const OrderListView = function(elem) {
this.$elem = $(elem);
this.orderListT = require('service/chat/orders.hbs');
this.$localOrders = this.$elem.find('[data-tab=local]');
this.$globalOrders = this.$elem.find('[data-tab=global]');
this.bindEvents();
this.fetchOrders();
};
bindEvent() {
// 订单
$('body').on('touchstart', '.menu .order', function() {
$('#chat-main-wrap').hide();
$('#order-list-wrap').show();
OrderListView.prototype = $.extend({}, EventEmitter.prototype, {
bindEvents: function() {
const self = this;
this.$elem
.on('click.OrderListView.back', '.chat-page-back', function() {
self.toggleHide(true);
})
.on('click.OrderListView.select', '[data-action=select]', function() {
$('.order-back').on('click', function() {
$('#order-list-wrap').hide();
$('#chat-main-wrap').show();
});
});
}
getOrder(self, cb, option) {
var opt = {
type: 1,
page: self.order.page + 1
// 被通知显示,执行显示
this.on('show.OderListView', $.proxy(this.toggleHide, this, false));
},
/**
* method: 选择订单,然后关闭
*/
selectOrder: function() {
let $order = $(event.target).closest('.order-page');
// 订单数据
let data = {
imgSrc: $order.find('.thumb').attr('src'),
orderCode: $order.find('[data-id]'),
cost: $order.find('.sum-cost').text(),
createTime: $order.find('.js-create-time').val(),
orderStatus: $order.find('.order-status').text()
};
var show = option && !option.noLoadingMask;
if (this.inAjax) {
return;
}
this.inAjax = true;
show && loading.showLoadingMask();
$.ajax({
type: 'GET',
url: '/service/getOrders',
data: opt,
success: function(data) {
var num;
if (data) {
self.order.page = opt.page;
if (opt.page === 1) {
self.$curContainer.html(data);
lazyLoad(self.$curContainer.find('.lazy'), {
try_again_css: 'order-failure'
});
} else {
num = self.$curContainer.children('.order').length;
self.$curContainer.append(data);
// lazyload
lazyLoad(self.$curContainer.children('.order:gt(' + (num - 1) + ')').find('.lazy'), {
try_again_css: 'order-failure'
});
}
window.rePosFooter(); // 重新计算底部位置
} else {
if (opt.page > 1) {
return;
}
self.$curContainer.html('<div class="no-order"><div class="icon"></div><span>你还没有订单!</span><a class="walk-way" href="//m.yohobuy.com/product/new">随便逛逛</a></div>');
self.order.end = true;
}
// 通知chat,订单列表已选择订单
this.trigger('selectOrder.OrderListView', [data]);
// 关闭
this.toggleHide(true);
},
this.inAjax = false;
show && loading.hideLoadingMask();
}
/**
* method: show/hide 订单列表
* @param boolean willHide;
* @return this
*/
toggleHide: function(willHide) {
this.$elem.toggleClass('chat-page-hide', willHide);
return this;
},
/**
* method: 获取订单
*/
fetchOrders: function() {
const self = this;
return api.fetchOrders().done(result => {
let html = self.orderListT({orders: result.data});
self.$localOrders.append(html);
});
}
}
});
OrderListView.prototype.constructer = OrderListView;
export {RatingView, LeaveMSGView, OrderListView};
export {RatingView, LeaveMSGView, OrderListView};
\ No newline at end of file
... ...
... ... @@ -91,6 +91,18 @@
z-index: 100;
background-color: #f0f0f0;
transition: .3s;
.main {
position: absolute;
width: 100%;
top: 105px;
bottom: 0;
overflow: auto;
}
.main::-webkit-scrollbar {
width: 0;
}
}
.chat-page-hide {
... ...
... ... @@ -10,11 +10,11 @@
}
.send-order-btn {
display: inline-block;
float: right;
height: 60px;
width: 145px;
line-height: 60px;
padding: 0;
text-align: center;
font-size: 28px;
color: #fff;
... ...
... ... @@ -57,6 +57,9 @@ module.exports = {
query: {
helperDirs: [
path.join(__dirname, '/js/common/helpers')
],
partialDirs: [
path.join(__dirname, '../doraemon/views/partial')
]
}
}]
... ...