Authored by 徐炜

Merge remote-tracking branch 'origin/feature/customerService' into feature/customerService

... ... @@ -82,6 +82,11 @@ app.use((req, res, next) => {
req.session = {};
}
// 获取客服开关,读cache
global.yoho.cache.get('customerServiceSwitch').then(resule => {
res.locals.customerServiceSwitch = resule || false;
}).catch(next);
next();
});
... ...
/**
* 设置cache controller
* @author: xiaoxiao<xiaoxiao.hao@yoho.cn>
* @date: 2016/12/21
*/
'use strict';
const cache = global.yoho.cache;
const index = (req, res, next) => {
let customerServiceSwitch = req.query.customerServiceSwitch;
if (typeof customerServiceSwitch === 'undefined') {
res.json(false);
return;
}
cache.set('customerServiceSwitch', customerServiceSwitch ? true : false, -1).then(result => {
res.json(result);
}).catch(next);
};
module.exports = {
index
};
... ...
... ... @@ -13,6 +13,7 @@ var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
const rvCtrl = require(`${cRoot}/recent-view`);
const cache = require(`${cRoot}/cache`);
const uploadCtrl = require(`${cRoot}/upload`);
const erp2goods = require(`${cRoot}/erp2goods`);
... ... @@ -22,4 +23,6 @@ router.post('/upload/image', multipartMiddleware, uploadCtrl.uploadImg);
router.get('/erp2goods', erp2goods.find);
router.get('/cache', cache.index); // 设置cache
module.exports = router;
... ...
... ... @@ -27,44 +27,51 @@ const personalController = require(`${cRoot}/qrcode`);
// const FavoriteController = require(`${cRoot}/Favorite`);
// const CouponsController = require(`${cRoot}/coupons`);
const homeNav = [
{
title: '交易管理',
subNav: [
{name: '我的订单', href: '/home/orders', catchs: ['/home/orders', '/home/index']},
{name: '我的收藏', href: '/home/favorite'},
{name: '我的有货币', href: '/home/currency'},
{name: '我的红包', href: '/home/redenvelopes'},
{name: '我的优惠券', href: '/home/coupons'},
{name: '我的VIP', href: '/home/vip'}
]
},
{
title: '服务中心',
subNav: [
{name: '我的退/换货', href: '/home/returns'},
{name: '我的咨询', href: '/home/consult'},
{name: '我的评论', href: '/home/comment'},
/* {name: '我的投诉', href: '/home/complaints'}, */
{name: '我的信息', href: '/home/message', count: 0},
{name: '在线客服', href: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&amp;configID=149091&amp;jid=8732423409', isBlank: true}
]
},
{
title: '个人信息管理',
subNav: [
{name: '编辑个人资料', href: '/home/user'},
{name: '账号安全', href: '/home/account'},
{name: '地址管理', href: '/home/address'},
{name: '兑换礼品卡', href: '/home/gift'}
]
}
];
const getActiveNav = (req)=>{
let mHomeNav = _.cloneDeep(homeNav);
const homeNav = (req, res) => {
return [
{
title: '交易管理',
subNav: [
{name: '我的订单', href: '/home/orders', catchs: ['/home/orders', '/home/index']},
{name: '我的收藏', href: '/home/favorite'},
{name: '我的有货币', href: '/home/currency'},
{name: '我的红包', href: '/home/redenvelopes'},
{name: '我的优惠券', href: '/home/coupons'},
{name: '我的VIP', href: '/home/vip'}
]
},
{
title: '服务中心',
subNav: [
{name: '我的退/换货', href: '/home/returns'},
{name: '我的咨询', href: '/home/consult'},
{name: '我的评论', href: '/home/comment'},
/* {name: '我的投诉', href: '/home/complaints'}, */
{name: '我的信息', href: '/home/message', count: 0},
{
name: '在线客服',
href: res.locals.customerServiceSwitch ?
'/service/client' : 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&amp;configID=149091&amp;jid=8732423409',
isBlank: true
}
]
},
{
title: '个人信息管理',
subNav: [
{name: '编辑个人资料', href: '/home/user'},
{name: '账号安全', href: '/home/account'},
{name: '地址管理', href: '/home/address'},
{name: '兑换礼品卡', href: '/home/gift'}
]
}
];
};
const getActiveNav = (req, res)=>{
let mHomeNav = _.cloneDeep(homeNav(req, res));
return mHomeNav.map((item) => {
item.subNav = item.subNav.map((nav) => {
... ... @@ -94,7 +101,7 @@ const getActiveNav = (req)=>{
const getHomeNav = (req, res, next) => {
res.locals.path = [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}, {name: '个人中心'}];
res.locals.homeNav = getActiveNav(req);
res.locals.homeNav = getActiveNav(req, res);
res.locals.userThumb = '//img10.static.yhbimg.com/headimg/' +
'2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
next();
... ...
... ... @@ -10,6 +10,7 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta content="telephone=no" name="format-detection" />
<meta content="email=no" name="format-detection" />
<meta name="renderer" content="webkit">
{{#if devEnv}}
<link rel="stylesheet" href="//localhost:5002/css/index.css">
{{^}}
... ...
... ... @@ -3,7 +3,7 @@
<img class="code" src="{{csSetting.qrCode}}">
<div class="scan">
<span class="icon"></span>
<span class="tip">扫描二维码<br>现在手机客户端</span>
<span class="tip">扫描二维码<br>下载手机客户端</span>
</div>
</div>
<a href="{{csSetting.pcAdLink}}" target="_blank">
... ...
... ... @@ -15,7 +15,9 @@
<p class="star-text">非常满意</p>
</div>
<div class="detail-reason">
<div class="discontent"></div>
<div class="dis-wrap">
<div class="discontent"></div>
</div>
<textarea class="other-reason" maxlength="50" placeholder="请您输入不满意的其他原因" spellcheck="false"></textarea>
</div>
</div>
... ...
... ... @@ -189,7 +189,7 @@
</div>
<div class="left">
<span class="iconfont rgbf">&#xe602;</span>
<a href="http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&amp;configID=149091&amp;jid=8732423409" target="_blank">
<a href="{{#if customerServiceSwitch}}/service/client{{else}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&amp;configID=149091&amp;jid=8732423409{{/if}}" target="_blank">
<span class="red">便捷</span>
<span class="rgbf">在线客服</span>
</a>
... ...
... ... @@ -51,8 +51,9 @@ var tipTpl = require('hbs/service/tip.hbs'),
var processInfo = {
scrollLoad: false,
manual: false,
promoter: 1, // 评论发起者 1:客户自己 2:客服
savedEval: false // 是否保存过评论
completeClose: false, // 评价完成后关闭
promoter: 1, // 评论发起者 1:客户自己 2:客服
savedEval: false // 是否保存过评论
};
var key,
... ... @@ -412,16 +413,23 @@ function pageInit() {
*/
function handleCusMsg(rec, msgType, message) {
var dom,
image;
image,
mode = 2,
width = 100,
height = 100;
message.newContent = emojiPrefix(message.newContent);
// 用户头像处理
if (!rec.userHead) {
rec.userHead = assetsPrefix + socketConf.defaultUserHead;
} else {
rec.userHead = rec.userHead
.replace(/\{mode\}/, mode)
.replace(/\{width\}/, width)
.replace(/\{height\}/, height);
}
// 图片添加标签
if (msgType === 2) {
message.newContent = '<img class="img-msg" src="' + message.content + '">';
... ... @@ -479,9 +487,9 @@ function pageInit() {
if (msgType === 2) {
message.newContent = '<img class="img-msg" src="' + message.content + '">';
dom = cusTpl({
userHead: rec.userHead,
userName: rec.userName,
dom = csTpl({
csHead: rec.csHead,
csName: rec.csName,
sendTimeShort: rec.sendTimeShort,
newContent: message.newContent
});
... ... @@ -506,9 +514,12 @@ function pageInit() {
/**
* 显示评价弹框
*/
function showEvalModal(isclose) {
function showEvalModal(cptClose) {
var $evalModal = $('#makeEvaluation');
// 评价完成后关闭
processInfo.completeClose = cptClose;
// 没有接入人工
if (!processInfo.manual) {
return;
... ... @@ -545,11 +556,6 @@ function pageInit() {
if (res && res.code === 200) {
// 评价原因
len && discontentHtml(len, data);
if (isclose) {
// 评价完成后,是否关闭窗口
window.close();
}
}
$evalModal.modal('show');
}
... ... @@ -627,10 +633,12 @@ function pageInit() {
break;
case allTypes.OP_LEAVE:
socketChat.clear();
offlineTip(message);
break;
case allTypes.OFFLINE:
socketChat.clear();
offlineTip(message);
break;
... ... @@ -680,10 +688,12 @@ function pageInit() {
onClose: function() {
$iconEval.hide();
$iconMs.hide();
$reconnect = $msgList.find('.list-item')
.last().find('.reconnect');
.last().find('.reconnect');
if (!$reconnect.length) {
socketChat.clear();
offlineTip();
}
},
... ... @@ -693,6 +703,7 @@ function pageInit() {
},
socketClosedCb: function() {
socketChat.clear();
offlineTip();
}
}));
... ... @@ -710,6 +721,10 @@ function pageInit() {
heightBefore,
heightAfter;
var mode = 2,
width = 100,
height = 100;
msgList = msgList.reverse();
len = msgList.length;
... ... @@ -732,6 +747,11 @@ function pageInit() {
case allRTs.CU_SEND:
if (!item.userHead) {
item.userHead = assetsPrefix + socketConf.defaultUserHead;
} else {
item.userHead = item.userHead
.replace(/\{mode\}/, mode)
.replace(/\{width\}/, width)
.replace(/\{height\}/, height);
}
dom += cusTpl({
userHead: item.userHead,
... ... @@ -916,6 +936,11 @@ function pageInit() {
socketConfCM.type = allRTs.EVAL_NOTICE;
socketConfCM.uuid = uuid.v4();
socketChat.send(socketConfCM);
// 完成后关闭
if (processInfo.completeClose) {
window.close();
}
}
},
error: function() {
... ...
... ... @@ -45,10 +45,6 @@ function socketInit(opts) {
console.log('websocket is open');
};
socketIns.onclose = options.onClose || function() {
console.log('websocket is closed');
};
socketIns.onerror = options.onError || function(err) {
console.log(err);
};
... ... @@ -59,6 +55,12 @@ function socketInit(opts) {
if (window.WebSocket) {
setTimeout(function() {
times = 1;
// socket对象存在或者正在链接
if(socket || socket && socket.readyState === WebSocket.CONNECTING) {
return;
}
socket = socketConnect();
connectId = setInterval(function() {
if (socket.readyState !== WebSocket.OPEN) {
... ... @@ -68,11 +70,16 @@ function socketInit(opts) {
times++;
} else {
clearInterval(connectId);
socket = null;
// 连接失败回调
options.connectFailCb();
}
} else {
socket.onclose = options.onClose || function() {
console.log('websocket is closed');
};
clearInterval(connectId);
}
}, 5000);
... ... @@ -89,6 +96,7 @@ function sendMsg(msg) {
if (!window.WebSocket) {
return;
}
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify(msg));
} else {
... ... @@ -99,16 +107,16 @@ function sendMsg(msg) {
/**
* 关闭socket
*/
function closeSocket() {
function clearSocket() {
if (socket) {
socket.close();
socket = null;
}
}
module.exports = {
socket: socket,
init: socketInit,
close: closeSocket,
clear: clearSocket,
send: sendMsg
};
... ...
... ... @@ -37,26 +37,27 @@ var config = {
conversationMessage: {
objectId: '',
sendTime: 0,
sortId: 1, // 预留字段
sortCode: '1', // 预留字段
platId: 2, // YOHO,BLK,MARS
userId: 0, // App 使用
sortId: 1, // 预留字段
sortCode: '1', // 预留字段
platId: 2, // YOHO,BLK,MARS
userId: 0, // App 使用
conversationId: 0, // 对话ID
sessionId: '', // 预留字段临时会话ID
encryptedUid: 0, // 加密ID Web使用
userHead: '', // 用户头像
userName: '', // 用户账号
csId: 0, // 客服 ID
type: 1, // type => [0:没人在线,1:排队,2:接通,3:管理员分配]
userHead: '', // 用户头像
userName: '', // 用户账号
csId: 0, // 客服 ID
type: 1, // type => [0:没人在线,1:排队,2:接通,3:管理员分配]
serviceSortId: 0,
serviceSortCode: '',
customerSettingId: 0, // 预留字段,
roleType: 0, // 0: 用户,1:客服
customerSettingId: 0, // 预留字段,
roleType: 0, // 0: 用户,1:客服
clientType: 1, // 用户终端类别 1、PC、2、H5、3、IOS、4、安卓
chatMessage: {
messageObjectId: '', // 没有用
type: 0, // 消息内容类型: 1:文本 2:图片 3:语音 4: 订单
content: '', // 客户端发送内容
newContent: '' // 处理完过滤过的内容
messageObjectId: '', // 没有用
type: 0, // 消息内容类型: 1:文本 2:图片 3:语音 4: 订单
content: '', // 客户端发送内容
newContent: '' // 处理完过滤过的内容
}
}
};
... ...
... ... @@ -272,6 +272,7 @@ $color-3a3a3a: #3a3a3a;
margin-bottom: 3px;
color: #c5c5c5;
font-size: 12px;
font-family: Helvetica;
}
.msg-bubble {
... ... @@ -281,7 +282,7 @@ $color-3a3a3a: #3a3a3a;
padding: 9px;
color: #ffffff;
line-height: 1.5;
letter-spacing: 2px;
letter-spacing: 1px;
word-break: break-all;
background-color: #3a3a3a;
border-radius: 3px;
... ... @@ -328,6 +329,7 @@ $color-3a3a3a: #3a3a3a;
margin-bottom: 3px;
color: #c5c5c5;
font-size: 12px;
font-family: Helvetica;
text-align: right;
}
... ... @@ -339,7 +341,7 @@ $color-3a3a3a: #3a3a3a;
padding: 9px;
color: #3a3a3a;
line-height: 1.5;
letter-spacing: 2px;
letter-spacing: 1px;
word-break: break-all;
background-color: #ffffff;
border-radius: 3px;
... ... @@ -1067,47 +1069,52 @@ $color-3a3a3a: #3a3a3a;
.detail-reason {
display: none;
.discontent {
.dis-wrap {
margin-left: 8px;
max-height: 155px;
overflow: scroll;
margin-bottom: 30px;
overflow-y: scroll;
overflow-x: hidden;
.dis-row {
font-size: 0;
margin-bottom: 13px;
.discontent {
margin-bottom: 30px;
.type {
position: relative;
display: inline-block;
width: 166px;
height: 40px;
padding: 0 2px;
font-size: 12px;
text-align: center;
line-height: 40px;
border: 1px #999999 solid;
border-radius: 5px;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
.dis-row {
font-size: 0;
margin-bottom: 13px;
&.chosen {
&:after {
position: absolute;
top: 13px;
right: -2px;
content: '';
display: inline-block;
height: 27px;
width: 27px;
background-image: resolve('service/btn-chosen.png');
.type {
position: relative;
display: inline-block;
width: 155px;
height: 40px;
padding: 0 2px;
font-size: 12px;
text-align: center;
line-height: 40px;
border: 1px #999999 solid;
border-radius: 5px;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
&.chosen {
&:after {
position: absolute;
top: 13px;
right: -2px;
content: '';
display: inline-block;
height: 27px;
width: 27px;
background-image: resolve('service/btn-chosen.png');
}
}
}
&:first-child {
margin-right: 15px;
&:first-child {
margin-right: 15px;
}
}
}
}
... ...