Authored by 毕凯

Merge branch 'feature/cs-quit-queue' into 'master'

Feature/cs quit queue



See merge request !623
@@ -67,11 +67,11 @@ exports.detail = (req, res, next) => { @@ -67,11 +67,11 @@ exports.detail = (req, res, next) => {
67 } 67 }
68 68
69 res.render('question/detail', Object.assign(result, { 69 res.render('question/detail', Object.assign(result, {
70 - title: 'YOHOBUY!潮流大调查', 70 + title: 'YOHO!调研中心',
71 module: '3party', 71 module: '3party',
72 page: 'question-detail', 72 page: 'question-detail',
73 pageHeader: headerModel.setNav({ 73 pageHeader: headerModel.setNav({
74 - navTitle: 'YOHOBUY!潮流大调查' 74 + navTitle: 'YOHO!调研中心'
75 }), 75 }),
76 isApp: req.yoho.isApp, 76 isApp: req.yoho.isApp,
77 localCss: true 77 localCss: true
@@ -117,6 +117,7 @@ router.get('/passport/reg/index', validateCode.load, reg.index); @@ -117,6 +117,7 @@ router.get('/passport/reg/index', validateCode.load, reg.index);
117 router.post('/passport/reg/verifymobile', validateCode.check, reg.sendCodeBusyBoy, reg.verifyMobile); 117 router.post('/passport/reg/verifymobile', validateCode.check, reg.sendCodeBusyBoy, reg.verifyMobile);
118 router.get('/passport/reg/code', reg.guardStep(2), reg.code); 118 router.get('/passport/reg/code', reg.guardStep(2), reg.code);
119 router.post('/passport/reg/sendcode', reg.guardStep(2), reg.sendCodeBusyBoy, reg.sendCode); 119 router.post('/passport/reg/sendcode', reg.guardStep(2), reg.sendCodeBusyBoy, reg.sendCode);
  120 +router.post('/passport/reg/sendcodeagain', reg.guardStep(2), reg.sendCodeBusyBoy, reg.sendCode);
120 router.post('/passport/reg/verifycode', reg.guardStep(2), reg.verifyCode); 121 router.post('/passport/reg/verifycode', reg.guardStep(2), reg.verifyCode);
121 router.get('/passport/reg/password', reg.guardStep(3), reg.password); 122 router.get('/passport/reg/password', reg.guardStep(3), reg.password);
122 router.post('/passport/reg/setpassword', reg.guardStep(3), reg.setPassword); 123 router.post('/passport/reg/setpassword', reg.guardStep(3), reg.setPassword);
@@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
3 <!--im 头部--> 3 <!--im 头部-->
4 <header class="yoho-header chat-header"> 4 <header class="yoho-header chat-header">
5 <a id="js-back" href="{{#if backUrl}}{{backUrl}}{{^}}javascript:history.go(-1);{{/if}}" class="iconfont nav-back">&#xe610;</a> 5 <a id="js-back" href="{{#if backUrl}}{{backUrl}}{{^}}javascript:history.go(-1);{{/if}}" class="iconfont nav-back">&#xe610;</a>
6 - <div class="title">智能小YO</div>  
7 - <div class="header-right"><span data-action="change-human">人工客服</span></div> 6 + <div class="title"><i class="chat-status"></i><span class="js-service-txt">正在连接...</span></div>
  7 + <div class="header-right"></div>
8 </header> 8 </header>
9 <!--网络连接失败--> 9 <!--网络连接失败-->
10 <div class="connection-failed hide"> 10 <div class="connection-failed hide">
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 </div> 16 </div>
17 <div class="fake-img-wrap"> 17 <div class="fake-img-wrap">
18 <img src="#" alt=""> 18 <img src="#" alt="">
19 - </div> 19 + </div>
20 <!--im footer--> 20 <!--im footer-->
21 <footer id="chat-footer"> 21 <footer id="chat-footer">
22 <div id="chat-send-box" class="table"> 22 <div id="chat-send-box" class="table">
@@ -71,4 +71,4 @@ @@ -71,4 +71,4 @@
71 imSocket: "{{imSocket}}", 71 imSocket: "{{imSocket}}",
72 imCs: "{{imCs}}", 72 imCs: "{{imCs}}",
73 }; 73 };
74 -</script>  
  74 +</script>
1 { 1 {
2 "name": "m-yohobuy-node", 2 "name": "m-yohobuy-node",
3 - "version": "5.7.10", 3 + "version": "5.7.11",
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": {
@@ -22,7 +22,7 @@ class ActController extends Controller { @@ -22,7 +22,7 @@ class ActController extends Controller {
22 lazyLoad($('img.lazy')); 22 lazyLoad($('img.lazy'));
23 this.more = new GetMore(); 23 this.more = new GetMore();
24 this.more.on('more', this.doMore.bind(this)); 24 this.more.on('more', this.doMore.bind(this));
25 - this.page = 1; 25 + this.page = 5;
26 this.loading = false; 26 this.loading = false;
27 global.jQuery = $; 27 global.jQuery = $;
28 } 28 }
@@ -11,6 +11,7 @@ import {time} from './time'; @@ -11,6 +11,7 @@ import {time} from './time';
11 import {api} from './store'; 11 import {api} from './store';
12 import {RatingView, LeaveMSGView, OrderListView } from './view'; 12 import {RatingView, LeaveMSGView, OrderListView } from './view';
13 import tip from 'plugin/tip'; 13 import tip from 'plugin/tip';
  14 +import dialog from 'plugin/dialog';
14 15
15 let FastClick = require('yoho-fastclick'); 16 let FastClick = require('yoho-fastclick');
16 17
@@ -112,7 +113,6 @@ let chat = { @@ -112,7 +113,6 @@ let chat = {
112 113
113 const self = this; 114 const self = this;
114 115
115 -  
116 cmEntity.encryptedUid = encryptedUid; 116 cmEntity.encryptedUid = encryptedUid;
117 117
118 self.fetchHistoryMsg().always(function() { 118 self.fetchHistoryMsg().always(function() {
@@ -167,7 +167,7 @@ let chat = { @@ -167,7 +167,7 @@ let chat = {
167 onOpen: $.noop, 167 onOpen: $.noop,
168 sendFailCallback: function() { 168 sendFailCallback: function() {
169 self._sysInfo('<p>连接断开,请尝试<span class="blue">重连</span></p>') 169 self._sysInfo('<p>连接断开,请尝试<span class="blue">重连</span></p>')
170 - .one('click', function() { 170 + .one('touchend', function() {
171 self.connect(); 171 self.connect();
172 }); 172 });
173 }, 173 },
@@ -184,8 +184,49 @@ let chat = { @@ -184,8 +184,49 @@ let chat = {
184 */ 184 */
185 bindEvents: function() { 185 bindEvents: function() {
186 let self = this; 186 let self = this;
  187 + let $dialog;
187 188
188 this.$chat 189 this.$chat
  190 + .on('click.Queue.quit', '[data-trigger=quit-queue]', function() {
  191 + dialog.showDialog({
  192 + dialogText: '确认结束排队吗?',
  193 + hasFooter: {
  194 + leftBtnText: '继续等待',
  195 + rightBtnText: '结束排队'
  196 + }
  197 + }, function() {
  198 + cmEntity.type = socketConf.recType.QUIT_QUEUE;
  199 + socket.send(JSON.stringify(cmEntity));
  200 + dialog.hideDialog();
  201 + });
  202 +
  203 + $dialog = $('.dialog-wrapper .dialog-box');
  204 + $dialog.css({
  205 + background: 'hsla(100, 100%, 100%, 1)'
  206 + });
  207 +
  208 + })
  209 + .on('click.Chat.end', '[data-trigger=end-chat]', function() {
  210 + dialog.showDialog({
  211 + dialogText: '确认结束本次服务吗?',
  212 + hasFooter: {
  213 + leftBtnText: '继续咨询',
  214 + rightBtnText: '结束服务'
  215 + }
  216 + }, function() {
  217 + cmEntity.type = socketConf.recType.USER_END_CHAT;
  218 + socket.send(JSON.stringify(cmEntity));
  219 + dialog.hideDialog();
  220 + });
  221 +
  222 + $dialog = $('.dialog-wrapper .dialog-box');
  223 + $dialog.css({
  224 + background: 'hsla(100, 100%, 100%, 1)'
  225 + });
  226 + })
  227 + .on('click.Chat.end', '[data-action=re-connect]', function() {
  228 + self.connect();
  229 + })
189 .on('click.Rating.toggle', '[data-trigger=rating]', function() { 230 .on('click.Rating.toggle', '[data-trigger=rating]', function() {
190 if (self.canEvalute) { 231 if (self.canEvalute) {
191 self.ratingView.toggle(); 232 self.ratingView.toggle();
@@ -268,12 +309,14 @@ let chat = { @@ -268,12 +309,14 @@ let chat = {
268 conversationId: cmEntity.conversationId, 309 conversationId: cmEntity.conversationId,
269 }); 310 });
270 }).on('rating-success', function(e, data) { 311 }).on('rating-success', function(e, data) {
  312 + const state = (window.socket || {}).readyState;
  313 +
271 self._sysInfo(`您对我们的服务评价为:${data}`); 314 self._sysInfo(`您对我们的服务评价为:${data}`);
272 self.canEvalute = false; 315 self.canEvalute = false;
273 cmEntity.type = socketConf.recType.EVALUTE_SUCCESS; 316 cmEntity.type = socketConf.recType.EVALUTE_SUCCESS;
274 - socket.send(JSON.stringify(cmEntity));  
275 -  
276 - // resizeFooter(); 317 + if (state === WebSocket.OPEN) {
  318 + socket.send(JSON.stringify(cmEntity));
  319 + }
277 }); 320 });
278 321
279 322
@@ -322,12 +365,12 @@ let chat = { @@ -322,12 +365,12 @@ let chat = {
322 disconnect(content) { 365 disconnect(content) {
323 let self = this; 366 let self = this;
324 367
  368 + self.renderHeader('offline');
325 this.canLeaveMSG = true; 369 this.canLeaveMSG = true;
326 -  
327 this.$chat.toggleClass('online', false); 370 this.$chat.toggleClass('online', false);
328 this.toggleMenu(false); 371 this.toggleMenu(false);
329 this._sysInfo(`<p>${content}<span class="blue">连接客服</span></p>`) 372 this._sysInfo(`<p>${content}<span class="blue">连接客服</span></p>`)
330 - .one('click', function() { 373 + .one('touchend', function() {
331 self.connect(); 374 self.connect();
332 }); 375 });
333 }, 376 },
@@ -576,6 +619,7 @@ let chat = { @@ -576,6 +619,7 @@ let chat = {
576 // ------------------------------------------ 619 // ------------------------------------------
577 // 用户进入 620 // 用户进入
578 case allTypes.ENTER: 621 case allTypes.ENTER:
  622 + this.renderHeader('robot');
579 chatMessage.newContent && this._sysInfo(chatMessage.newContent); 623 chatMessage.newContent && this._sysInfo(chatMessage.newContent);
580 break; 624 break;
581 625
@@ -590,6 +634,11 @@ let chat = { @@ -590,6 +634,11 @@ let chat = {
590 this._sysInfo(chatMessage.content); 634 this._sysInfo(chatMessage.content);
591 break; 635 break;
592 636
  637 + case allTypes.QUIT_QUEUE:
  638 + this.renderHeader('robot');
  639 + this._sysInfo(chatMessage.content);
  640 + break;
  641 +
593 // 客服邀请评价 642 // 客服邀请评价
594 case allTypes.EVAL_INVITE: 643 case allTypes.EVAL_INVITE:
595 this._sysInfo('<p data-trigger="rating">请对我们的服务进行<span class="blue">评价</span></p>'); 644 this._sysInfo('<p data-trigger="rating">请对我们的服务进行<span class="blue">评价</span></p>');
@@ -636,7 +685,6 @@ let chat = { @@ -636,7 +685,6 @@ let chat = {
636 */ 685 */
637 _manualState(state, cmEntity) { // eslint-disable-line 686 _manualState(state, cmEntity) { // eslint-disable-line
638 const self = this; 687 const self = this;
639 - const $chatHeader = self.$header;  
640 const $chat = self.$chat; 688 const $chat = self.$chat;
641 const sysInfo = self._sysInfo.bind(this); 689 const sysInfo = self._sysInfo.bind(this);
642 const chatMessage = cmEntity.chatMessage; 690 const chatMessage = cmEntity.chatMessage;
@@ -670,12 +718,13 @@ let chat = { @@ -670,12 +718,13 @@ let chat = {
670 718
671 // state 1: 排队中 719 // state 1: 排队中
672 function inQueue() { 720 function inQueue() {
  721 + self.renderHeader('queue');
673 whetherLeaveMsg(cmEntity); 722 whetherLeaveMsg(cmEntity);
674 } 723 }
675 724
676 // state 2: 人工客服进入 725 // state 2: 人工客服进入
677 function linkSuccess() { 726 function linkSuccess() {
678 - $chatHeader.find('.js-service-txt').text('YOHO客服'); 727 + self.renderHeader('human');
679 728
680 $chat 729 $chat
681 .toggleClass('online', true) 730 .toggleClass('online', true)
@@ -825,7 +874,7 @@ let chat = { @@ -825,7 +874,7 @@ let chat = {
825 }, 874 },
826 875
827 switchService: function(type) { 876 switchService: function(type) {
828 - this.renderHeader(type); 877 + this.renderHeader(`switch-${type}`);
829 878
830 if (type === 'human') { 879 if (type === 'human') {
831 cmEntity.type = socketConf.recType.MANUAL_SERVICE; 880 cmEntity.type = socketConf.recType.MANUAL_SERVICE;
@@ -843,9 +892,25 @@ let chat = { @@ -843,9 +892,25 @@ let chat = {
843 title: '智能小YO', 892 title: '智能小YO',
844 right: '<span data-action="change-human">人工客服</span>' 893 right: '<span data-action="change-human">人工客服</span>'
845 }, 894 },
  895 + queue: {
  896 + title: '<i class="chat-status"></i><span class="js-service-txt">队列中...</span>',
  897 + right: '<span data-trigger="quit-queue">结束排队</span>'
  898 + },
846 human: { 899 human: {
  900 + title: '<i class="chat-status"></i><span class="js-service-txt">YOHO客服</span>',
  901 + right: '<span data-trigger="end-chat">结束服务</span>'
  902 + },
  903 + offline: {
  904 + title: '<i class="chat-status"></i><span class="js-service-txt">YOHO客服</span>',
  905 + right: '<span data-action="re-connect">重新连接</span>'
  906 + },
  907 + 'switch-robot': {
847 title: '<i class="chat-status"></i><span class="js-service-txt">正在连接...</span>', 908 title: '<i class="chat-status"></i><span class="js-service-txt">正在连接...</span>',
848 - right: '<span class="chat-rating-trigger" data-trigger="rating">评价</span>' 909 + right: '<span></span>'
  910 + },
  911 + 'switch-human': {
  912 + title: '<i class="chat-status"></i><span class="js-service-txt">连接人工...</span>',
  913 + right: ''
849 } 914 }
850 }; 915 };
851 916
@@ -62,12 +62,11 @@ function sendMsg(msg) { @@ -62,12 +62,11 @@ function sendMsg(msg) {
62 socket.send(msg); 62 socket.send(msg);
63 } else { 63 } else {
64 sendFailCallback(); 64 sendFailCallback();
65 - console.log('The socket is not open.');  
66 } 65 }
67 } 66 }
68 67
69 module.exports = { 68 module.exports = {
70 init: socketInit, 69 init: socketInit,
71 - send: sendMsg 70 + send: sendMsg,
72 }; 71 };
73 72
@@ -28,10 +28,12 @@ let config = { @@ -28,10 +28,12 @@ let config = {
28 TRANSFER_REQ: 10006, // 收到他人的转移的请求 28 TRANSFER_REQ: 10006, // 收到他人的转移的请求
29 TRANS_REQ_ANSWER: 10007, // 收到他人对自己转移请求的反馈 29 TRANS_REQ_ANSWER: 10007, // 收到他人对自己转移请求的反馈
30 SUC_DISTRIBUTE: 10009, // 客服管理员收到会话分配成功的回执 30 SUC_DISTRIBUTE: 10009, // 客服管理员收到会话分配成功的回执
31 - CS_CHATTING: 5000000, // 客服管理员收到会话分配成功的回执 31 + CS_CHATTING: 5000000, // 客服管理员收到会话分配成功的回执
32 IN_QUNEUE: 777777, // 队列中发送消息后收到的反馈 32 IN_QUNEUE: 777777, // 队列中发送消息后收到的反馈
33 - OFFLINE: 999999999, // 断线  
34 - OP_LEAVE: 999999998 // 对方离开 33 + QUIT_QUEUE: 888881, // 排队中退申请退出队列
  34 + USER_END_CHAT: 888882, // 用户结束会话
  35 + OFFLINE: 999999999, // 断线
  36 + OP_LEAVE: 999999998 // 对方离开
35 }, 37 },
36 38
37 conversationMessage: { 39 conversationMessage: {