Authored by 周少峰

Merge branch 'master' into feature/seoUrl302

... ... @@ -33,7 +33,7 @@ exports.index = (req, res, next) => {
exports.getCouponStatus = (req, res, next) => {
couponModel.getCouponStatus({
uid: req.user.uid,
contentCode: req.query.contentCode
contentCode: req.query.contentCode || contentCode
}).then(result => {
res.json(result);
}).catch(next);
... ...
... ... @@ -6,10 +6,10 @@
'use strict';
const _ = require('lodash');
const pinyin = require('pinyin-converter');
const crypto = global.yoho.crypto;
const pinyin = require('../models/province-pinyin');
const addressApi = require('../models/address-api');
const worldSort = 'abcdefghijklmnopqrstuvwxyz';
... ... @@ -20,14 +20,11 @@ const getAreaListData = (id) => {
if (id * 1 === 0 && list.length) {
_.forEach(list, value => {
value.initial = _.get(pinyin(value.caption, {
style: pinyin.STYLE_FIRST_LETTER
}), '[0][0]', 'w');
value.initial = pinyin[value.caption] || 'z';
value.pySort = _.indexOf(worldSort, value.initial);
});
result.data = list;
}
return result;
});
};
... ...
... ... @@ -619,8 +619,10 @@ const formatCart = (cartDataRet, uid, shoppingKey, cartDelList) => {
}
// promotionInfos, gifts, priceGifts 放一起展示
let hasGifts = _.get(result, 'ordinaryCart.gifts') && _.get(result, 'ordinaryCart.gifts').length;
let hasPrices = _.get(result, 'ordinaryCart.priceGifts') && _.get(result, 'ordinaryCart.priceGifts').length;
let hasGifts = _.get(result, 'ordinaryCart.giftsPromotionInfos') &&
_.get(result, 'ordinaryCart.giftsPromotionInfos').length;
let hasPrices = _.get(result, 'ordinaryCart.priceGiftsPromotionInfos') &&
_.get(result, 'ordinaryCart.priceGiftsPromotionInfos').length;
let hasPromo = _.get(result, 'ordinaryCart.promotionInfos') && _.get(result, 'ordinaryCart.promotionInfos').length;
let orderAmount = (parseFloat(_.get(advStat, 'orderAmount', 0)) +
parseFloat(_.get(ordStat, 'orderAmount', 0))).toFixed(2);
... ...
module.exports = {
'北京市': 'b',
'天津市': 't',
'河北省': 'h',
'山西省': 's',
'内蒙古自治区': 'n',
'辽宁省': 'l',
'吉林省': 'j',
'黑龙江省': 'h',
'上海市': 's',
'江苏省': 'j',
'浙江省': 'z',
'安徽省': 'a',
'福建省': 'f',
'江西省': 'j',
'山东省': 's',
'河南省': 'h',
'湖北省': 'h',
'湖南省': 'h',
'广东省': 'g',
'广西壮族自治区': 'g',
'海南省': 'h',
'重庆市': 'c',
'四川省': 's',
'贵州省': 'g',
'云南省': 'y',
'西藏自治区': 'x',
'陕西省': 's',
'甘肃省': 'g',
'青海省': 'q',
'宁夏回族自治区': 'n',
'新疆维吾尔自治区': 'x'
};
... ...
... ... @@ -64,7 +64,7 @@ const homeNav = (req) => {
{name: '我的信息', href: '/home/message', count: 0},
{
name: '在线客服',
href: _.get(req.app.locals.pc, 'clientService.new', false) ? 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409' : '/service/client',
href: _.get(req.app.locals.pc, 'clientService.new', false) ? 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409' : '/service/client',
isBlank: true
}
]
... ...
... ... @@ -50,12 +50,6 @@ passport.use('local', new LocalStrategy({
return done({message: '登录参数错误'}, null);
}
let verifyCode = req.body.captcha;
if (verifyCode && verifyCode !== req.session.captcha) {
return done({message: '验证码不正确或验证码过期', needCaptcha: true}, null);
}
let shoppingKey = cookie.getShoppingKey(req);
let account = req.body.account;
... ...
... ... @@ -35,7 +35,16 @@ router.post('/passport/login/qrcode/refresh', login.local.qrcode.refresh);
router.post('/passport/login/qrcode/check', login.local.qrcode.check); // 验证二维码的状态
router.get('/passport/login', login.common.beforeLogin, login.local.loginPage);
router.post('/passport/login/auth', login.local.login);
router.post('/passport/login/auth',
(req, res, next) => {
if (req.body.loginType === 'password') {
return captcha.requiredAPI(req, res, next);
} else {
return next();
}
},
login.local.login
);
router.get('/passport/logout', login.local.logout);
// 微信登录
... ...
... ... @@ -55,7 +55,7 @@
</span>
</li>
<li class="clearfix captcha-wrap hide">
<li class="clearfix captcha-wrap">
</li>
<li class="relative clearfix sms-login hide">
... ...
... ... @@ -6,7 +6,7 @@
<span class="title">留言</span>
</div>
<div class="cus-body">
<textarea maxlength="120" placeholder="请输入留言信息" spellcheck="false"></textarea>
<textarea maxlength="500" placeholder="请输入留言信息" spellcheck="false"></textarea>
<i class="leave-msg-tip hide">留言内容不能为空</i>
</div>
<div class="cus-footer">
... ...
... ... @@ -19,7 +19,7 @@
<div class="edit-left">
<div class="util">
<span class="icon emoji">表情</span>
<span class="icon">图片<label for="sendImg"></label></span>
<span class="icon image">图片<label for="sendImg"></label></span>
<span class="icon evaluate">评价</span>
<span class="icon manual-service">人工客服</span>
</div>
... ...
... ... @@ -36,8 +36,7 @@ module.exports = {
// service: 'http://dev-service.yohops.com:9999/',
imSocket: 'ws://socket.yohobuy.com:10240',
imCs: 'http://im.yohobuy.com/api',
imServer: 'http://im.yohobuy.com/server'
imCs: 'http://im.yohobuy.com/api'
},
subDomains: {
host: '.yohobuy.com',
... ... @@ -130,8 +129,7 @@ if (isProduction) {
service: 'http://service.yoho.yohoops.org/',
search: 'http://search.yohoops.org/yohosearch/',
imSocket: 'ws://imsocket.yohobuy.com:10000',
imCs: 'https://imhttp.yohobuy.com/api',
imServer: 'https://imhttp.yohobuy.com/server'
imCs: 'https://imhttp.yohobuy.com/api'
},
memcache: {
master: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
... ... @@ -160,8 +158,7 @@ if (isProduction) {
service: process.env.TEST_SERVICE || 'http://testservice.yoho.cn:28077/',
search: process.env.TEST_SEARCH || 'http://192.168.102.216:8080/yohosearch/',
imSocket: 'ws://socket.yohobuy.com:10240',
imCs: 'http://im.yohobuy.com/api',
imServer: 'http://im.yohobuy.com/server'
imCs: 'http://im.yohobuy.com/api'
},
useOneapm: true,
useCache: true,
... ...
... ... @@ -28,44 +28,45 @@ const channelMap = {
const sortMap = {
boys: [
{misort: 16, viewNum: 5}, // 卫衣
{misort: 21, viewNum: 5}, // 夹克
{misort: 44, viewNum: 5}, // 休闲运动鞋
{misort: 22, viewNum: 5}, // 大衣/风衣
{misort: 12, viewNum: 5}, // 衬衫
{misort: 11, viewNum: 5}, // T恤
{misort: 16, viewNum: 5}, // 卫衣
{misort: 21, viewNum: 5}, // 大衣/风衣
{misort: 44, viewNum: 5}, // 休闲/运动鞋
{misort: 26, viewNum: 5}, // 休闲裤
{misort: 27, viewNum: 5}, // 牛仔裤
{misort: 48, viewNum: 5}, // 时装鞋
{misort: 20, viewNum: 5}, // 棉衣
{misort: 257, viewNum: 5}, // 毛衣/针织
{misort: 172, viewNum: 5}, // 皮衣
{misort: 45, viewNum: 5}, // 靴子
{misort: 226, viewNum: 5}, // 防风外套
{misort: 18, viewNum: 5}, // 羽绒服
{misort: 13, viewNum: 5}, // POLO
{misort: 28, viewNum: 5}, // 短裤
{misort: 49, viewNum: 5}, // 双肩包
{misort: 60, viewNum: 5}, // 帽子
{misort: 59, viewNum: 5}, // 手表
{misort: 66, viewNum: 5}, // 配饰
{misort: 50, viewNum: 5}, // 手拎包/单肩包
{misort: 65, viewNum: 5}, // 首饰
{misort: 309, viewNum: 5}, // 内裤
{misort: 259, viewNum: 5} // 美妆
{misort: 237, viewNum: 5}, // 钱包/卡包/手包/钥匙包
{misort: 61, viewNum: 5} // 太阳镜/眼镜
],
girls: [
{misort: 31, viewNum: 4}, // 连衣裙
{misort: 11, viewNum: 4}, // T恤
{misort: 32, viewNum: 4}, // 半身裙
{misort: 16, viewNum: 4}, // 卫衣
{misort: 257, viewNum: 4}, // 毛衣/针织
{misort: 21, viewNum: 4}, // 夹克
{misort: 12, viewNum: 4}, // 衬衫
{misort: 44, viewNum: 4}, // 休闲/运动鞋
{misort: 22, viewNum: 4}, // 大衣/风衣
{misort: 31, viewNum: 4}, // 连衣裙
{misort: 48, viewNum: 4}, // 时装鞋
{misort: 257, viewNum: 4}, // 毛衣/针织
{misort: 172, viewNum: 4}, // 皮衣
{misort: 226, viewNum: 4}, // 防风外套
{misort: 20, viewNum: 4}, // 棉服
{misort: 26, viewNum: 4}, // 休闲裤
{misort: 27, viewNum: 4}, // 牛仔裤
{misort: 18, viewNum: 4}, // 羽绒服
{misort: 12, viewNum: 4}, // 衬衫
{misort: 28, viewNum: 4}, // 短裤
{misort: 48, viewNum: 4}, // 时装鞋
{misort: 49, viewNum: 4}, // 双肩包
{misort: 50, viewNum: 4}, // 手拎包/单肩包
{misort: 39, viewNum: 4}, // 袜子
{misort: 60, viewNum: 4}, // 帽子
{misort: 61, viewNum: 4}, // 太阳镜/眼镜
{misort: 65, viewNum: 4}, // 首饰
... ... @@ -76,21 +77,25 @@ const sortMap = {
kids: [
{misort: 396, viewNum: 4}, // 卫衣
{misort: 368, viewNum: 4}, // 休闲/运动鞋
{misort: 369, viewNum: 4}, // 休闲裤
{misort: 366, viewNum: 4}, // T恤
{misort: 404, viewNum: 4}, // 夹克
{misort: 400, viewNum: 4}, // 毛衣/针织
{misort: 369, viewNum: 4}, // 休闲裤
{misort: 371, viewNum: 4}, // 连衣裙
{misort: 367, viewNum: 4}, // 衬衫
{misort: 462, viewNum: 4}, // 靴子
{misort: 406, viewNum: 4}, // 大衣/风衣
{misort: 390, viewNum: 4}, // 运动裤
{misort: 368, viewNum: 4}, // 休闲/运动鞋
{misort: 423, viewNum: 4}, // 棉衣
{misort: 392, viewNum: 4}, // 双肩包
{misort: 402, viewNum: 4}, // 马甲
{misort: 470, viewNum: 4}, // 连体裤
{misort: 448, viewNum: 4}, // 玩具娱乐
{misort: 382, viewNum: 4}, // 凉鞋/凉拖
{misort: 388, viewNum: 4}, // 牛仔裤
{misort: 417, viewNum: 4}, // 套装
{misort: 408, viewNum: 4}, // 袜子
{misort: 367, viewNum: 4}, // 衬衫
{misort: 371, viewNum: 4}, // 连衣裙
{misort: 429, viewNum: 4}, // 太阳镜/眼镜
{misort: 414, viewNum: 4} // 帽子
{misort: 470, viewNum: 4}, // 连体裤
{misort: 372, viewNum: 4}, // 短裤
{misort: 370, viewNum: 4}, // 半身裙
{misort: 460, viewNum: 4} // 时装鞋
],
lifestyle: [
... ...
... ... @@ -29,8 +29,6 @@ module.exports = (limiter, policy) => {
const key = `pc:limiter:${limiter.remoteIp}`;
let isNew = true;
res.on('render', function() {
let route = req.route ? req.route.path : '';
let appPath = req.app.mountpath;
... ... @@ -46,15 +44,14 @@ module.exports = (limiter, policy) => {
pageIncr = 5;
}
if (pageIncr > 0 && !isNew) {
cache.incrAsync(key, pageIncr);
if (pageIncr > 0) {
cache.incr(key, pageIncr, (err) => {});
}
});
return cache.getAsync(key).then((result) => {
logger.debug('qps limiter: ' + key + '@' + result + ' max: ' + MAX_QPS);
if (result && _.isNumber(result)) {
isNew = false;
if (result === -1) {
return Promise.resolve(true);
}
... ...
... ... @@ -189,7 +189,7 @@
</div>
<div class="left">
<span class="iconfont rgbf">&#xe602;</span>
<a href="{{#if @root.pc.clientService.new}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&amp;configID=149091&amp;jid=8732423409{{else}}/service/client{{/if}}" target="_blank">
<a href="{{#if @root.pc.clientService.new}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409{{else}}/service/client{{/if}}" target="_blank">
<span class="red">便捷</span>
<span class="rgbf">在线客服</span>
</a>
... ...
{
"name": "yohobuy-node",
"version": "5.4.14",
"version": "5.4.18",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -56,7 +56,6 @@
"passport-sina": "^0.1.0",
"passport-strategy": "1.x.x",
"passport-weixin": "^0.1.0",
"pinyin-converter": "^2.8.1",
"request-ip": "^1.2.2",
"request-promise": "^3.0.0",
"serve-favicon": "^2.3.0",
... ...
... ... @@ -173,10 +173,6 @@ function getCouponStatus() {
data[hash[0]] = hash[1];
}
if (!data.contentCode) {
return;
}
$.ajax({
type: 'GET',
url: '/coupon/couponstatus',
... ...
... ... @@ -103,7 +103,7 @@ ColorPanelAction = {
},
selectColor: function() {
var $this = $(this);
var index = $this.index($this.parent().find('.dt'));
var index = $this.parent().find('.dt').index($this);
var $srows = $this.closest('.goods-info').find('.choose-size .size-row');
var $bigImgs = $this.closest('.goods-choose-box').find('.goods-info-bigImg .bigImg');
... ...
... ... @@ -55,7 +55,7 @@ var $accountInput1 = $('#account1'),
// 图像验证码
$captchaImgWrapper = $('.captcha-wrap'),
captchaImg = new Captcha('.captcha-wrap').init(),
$showCaptchaImg = false,
$showCaptchaImg = true,
getCaptchaImgVal = function() {
return captchaImg.getResults();
},
... ... @@ -250,6 +250,8 @@ var tpl = function(text) {
].join('');
};
require('../../common/promise');
// 切换登录方式
accountChangeEvent.add(function(type) {
currentLogin = AccountLoginData[type];
... ... @@ -278,7 +280,10 @@ accountChangeEvent.add(function(type) {
if (type === AccountLoginData.PasswordLogin.name) {
if ($showCaptchaImg) {
$captchaImgWrapper.removeClass('hide');
captchaImg.refresh();
$.sleep(500).then(function() {
captchaImg.refresh();
});
}
}
... ... @@ -648,7 +653,9 @@ function validateSmsCaptchaImg() {
}
function refreshSmsCaptchaImg() {
smsCaptchaImg.refresh();
$.sleep(1000).then(function() {
smsCaptchaImg.refresh();
});
}
/** ************************************************************************/
... ... @@ -848,7 +855,7 @@ function loginAsync() {
areaCode: getAreaCodeVal(),
account: currentLogin.getAccountVal(),
password: currentLogin.creditableToken(),
captcha: currentLogin.type() === 'password' ? getCaptchaImgVal() : '',
verifyCode: currentLogin.type() === 'password' ? getCaptchaImgVal() : '',
isRemember: getRememberMeVal(),
loginType: currentLogin.type()
}
... ...
... ... @@ -576,6 +576,8 @@ exports.init = function(page) {
};
}
var isRegRequesting = false; // eslint-disable-line
// ajax表单提交
$registerBtn.click(function() {
var url;
... ... @@ -590,6 +592,12 @@ exports.init = function(page) {
return;
} else {
if (isRegRequesting) {
return;
}
isRegRequesting = true;
// ajax提交
$.ajax({
type: 'POST',
... ... @@ -636,6 +644,8 @@ exports.init = function(page) {
alert(data.message); //eslint-disable-line
}
}).always(function() {
isRegRequesting = false;
});
}
});
... ...
/**
* 浏览器相关功能扩展
* @author: liqi <qi.li@yoho.cn>
* @date: 2016/11/26
*/
var $ = require('yoho-jquery');
var state;
var isHidden;
var changeEvent;
/**
* 获取光标位置
*/
function _getCursorPosition() {
var sel,
pos = 0,
selLength,
el = $(this).get(0);
if ('selectionStart' in el) {
pos = el.selectionStart;
} else if ('selection' in document) {
sel = document.selection.createRange();
selLength = document.selection.createRange().text.length;
el.focus();
sel.moveStart('character', -el.value.length);
pos = sel.text.length - selLength;
}
return pos;
}
/**
* 判断当前tab页是否可见
*/
function tabIsHidden() {
if (typeof document.hidden !== 'undefined') {
changeEvent = 'visibilitychange';
state = 'visibilityState';
} else if (typeof document.mozHidden !== 'undefined') {
changeEvent = 'mozvisibilitychange';
state = 'mozVisibilityState';
} else if (typeof document.msHidden !== 'undefined') {
changeEvent = 'msvisibilitychange';
state = 'msVisibilityState';
} else if (typeof document.webkitHidden !== 'undefined') {
changeEvent = 'webkitvisibilitychange';
state = 'webkitVisibilityState';
}
return document[state] === 'hidden';
}
/**
* 判断当前tab页可见
* @param callback 可见回调
*/
function tabVisible(callback) {
isHidden = tabIsHidden();
document.addEventListener(changeEvent, function() {
if (!isHidden) {
if (callback) {
return callback();
}
}
}, false);
}
/**
* 设置光标位置
* @param el 元素
* @param pos 位置
*/
function setCursor(el, pos) {
var range;
if (el.setSelectionRange) {
// chrome and firefox support
el.setSelectionRange(pos, pos);
el.focus();
} else if (el.createTextRange) {
// IE support
range = el.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
/**
* 回车发送
* 回车 & CTRL 换行
* @param e 事件
* @param fn 回车事件
*/
function ctrlEnter(e, send) {
var code = e.keyCode,
tag = $(e.target),
val = tag.val(),
pos = tag.getCursorPosition(),
start = val.substring(0, pos),
end = val.substring(pos),
newVal = [start, '\n', end].join(''),
ctrlLike = e.ctrlKey || e.metaKey;
if (code !== 13) {
return;
}
if (!ctrlLike) {
e.preventDefault();
send(e);
} else {
tag.val(newVal);
setCursor(tag[0], pos + 1);
}
}
// 获取光标位置
// jquery.fn.extend
$.fn.extend({
getCursorPosition: _getCursorPosition
});
module.exports = {
ctrlEnter: ctrlEnter,
setCursor: setCursor,
tabVisible: tabVisible,
tabIsHidden: tabIsHidden
};
... ...
... ... @@ -10,7 +10,8 @@
var $ = require('yoho-jquery'),
uuid = require('uuid'),
emojiMap = require('./emoji-map'),
tab = require('./tab-hidden'),
editArea = require('./edit-area'),
broswer = require('./broswer'),
socketChat = require('./socket-chat'),
socketConf = require('./socket-config');
... ... @@ -76,35 +77,11 @@ encryptedUid = $encryptedUid.val();
assetsPrefix = $assetsPrefix.val();
socketConfCM = socketConf.conversationMessage;
socketConfCM.encryptedUid = encryptedUid;
// 原始配置信息用于重新连线
originConf = JSON.parse(JSON.stringify(socketConf));
// 页面初始化
function pageInit() {
// 原始配置信息用于重新连线
originConf = JSON.parse(JSON.stringify(socketConf));
/**
* 设置光标位置
* @param el
* @param pos
*/
function setCurPos(el, pos) {
var range;
if (el.setSelectionRange) {
// chrome and firefox support
el.setSelectionRange(pos, pos);
el.focus();
} else if (el.createTextRange) {
// IE support
range = el.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
/**
* 添加新的消息
*/
... ... @@ -152,7 +129,7 @@ function pageInit() {
textDom = area[0];
pos = cursorPosition ? cursorPosition : newVal.length;
setCurPos(textDom, pos);
broswer.setCursor(textDom, pos);
}
/**
... ... @@ -234,33 +211,6 @@ function pageInit() {
}
/**
* enter提交
* enter+ctrl换行
*/
function msgEnterAction(e) {
var code = e.keyCode,
tag = $(e.target),
val = tag.val(),
pos = tag.getCursorPosition(),
start = val.substring(0, pos),
end = val.substring(pos),
newVal = [start, '\n', end].join(''),
ctrlLike = e.ctrlKey || e.metaKey;
if (code !== 13) {
return;
}
if (!ctrlLike) {
e.preventDefault();
sendMessage(e);
} else {
tag.val(newVal);
setCurPos(tag[0], pos + 1);
}
}
/**
* 常见问题
*/
function toggleAnswer(e) {
... ... @@ -307,8 +257,6 @@ function pageInit() {
* @param message 消息对象
*/
function enterSuccess(message) {
var $ms = $('.icon.manual-service');
// 删除重新连线
$msgList.find('.reconnect').parents('.push-tip').remove();
... ... @@ -316,7 +264,9 @@ function pageInit() {
systemTip(message.content);
// 显示人工客服
$ms.show();
editArea.setIcons({
'manual-service': true
});
}
/**
... ... @@ -333,9 +283,7 @@ function pageInit() {
ADMIN_MANUAL_SERVICE = 3;
var dom,
tipText,
$iconEval = $('.icon.evaluate'),
$iconMs = $('.icon.manual-service');
tipText;
switch (msgType) {
... ... @@ -355,7 +303,9 @@ function pageInit() {
});
// 隐藏人工
$iconMs.hide();
editArea.setIcons({
'manual-service': false
});
break;
case MANUAL_SERVICE: // 2是接入人工成功
... ... @@ -368,8 +318,12 @@ function pageInit() {
processInfo.manual = true;
// 显示评价&隐藏人工
$iconEval.show();
$iconMs.hide();
editArea.setIcons({
emoji: true,
image: true,
evaluate: true,
'manual-service': false
});
break;
case ADMIN_MANUAL_SERVICE: // 3是管理员分配客服成功
... ... @@ -382,8 +336,12 @@ function pageInit() {
processInfo.manual = true;
// 显示评价&隐藏人工
$iconEval.show();
$iconMs.hide();
editArea.setIcons({
emoji: true,
image: true,
evaluate: true,
'manual-service': false
});
break;
default:
... ... @@ -394,6 +352,14 @@ function pageInit() {
msgAppend(dom);
}
/**
* 人工接入队列中
* @param message 内部消息对象
*/
function inQueue(message) {
systemTip(message.content);
}
/**
* 返回表情路径处理
* @param text 文本
... ... @@ -570,7 +536,7 @@ function pageInit() {
recType = rec.type,
message = rec.chatMessage,
msgType = message ? message.type : -1,
isHidden = tab.tabIsHidden(),
isHidden = broswer.tabIsHidden(),
allTypes = socketConf.recType;
// 删除上个定时器
... ... @@ -596,6 +562,10 @@ function pageInit() {
linkSuccess(msgType, message);
break;
case allTypes.IN_QUNEUE:
inQueue(message);
break;
case allTypes.CU_SEND:
handleCusMsg(rec, msgType, message);
break;
... ... @@ -632,11 +602,19 @@ function pageInit() {
case allTypes.OP_LEAVE:
socketChat.clear();
editArea.setIcons({
emoji: false,
image: false
});
offlineTip(message);
break;
case allTypes.OFFLINE:
socketChat.clear();
editArea.setIcons({
emoji: false,
image: false
});
offlineTip(message);
break;
... ... @@ -654,8 +632,6 @@ function pageInit() {
*/
function connectSocket() {
var $reconnect,
$iconEval = $('.icon.evaluate'),
$iconMs = $('.icon.manual-service'),
$connectFail = $('.connect-fail'),
// 获取上次会话id
... ... @@ -680,13 +656,19 @@ function pageInit() {
},
onOpen: function() {
$iconMs.hide();
$iconEval.hide();
editArea.setIcons({
evaluate: false,
'manual-service': false
});
},
onClose: function() {
$iconEval.hide();
$iconMs.hide();
editArea.setIcons({
emoji: false,
image: false,
evaluate: false,
'manual-service': false
});
$reconnect = $msgList.find('.list-item')
.last().find('.reconnect');
... ... @@ -843,7 +825,7 @@ function pageInit() {
}());
// tab页title重置
tab.tabVisible(function() {
broswer.tabVisible(function() {
document.title = docTitle;
clearInterval(titleInterval);
});
... ... @@ -952,28 +934,10 @@ function pageInit() {
height: '100%'
});
// 获取鼠标位置
$.fn.getCursorPosition = function() {
var sel,
pos = 0,
selLength,
el = $(this).get(0);
if ('selectionStart' in el) {
pos = el.selectionStart;
} else if ('selection' in document) {
sel = document.selection.createRange();
selLength = document.selection.createRange().text.length;
el.focus();
sel.moveStart('character', -el.value.length);
pos = sel.text.length - selLength;
}
return pos;
};
// enter提交 ctrl+enter换行
$msgArea.on('keydown', msgEnterAction);
$msgArea.on('keydown', function(e) {
broswer.ctrlEnter(e, sendMessage);
});
// 常见问题
$('.qa-list .q').on('click', toggleAnswer);
... ... @@ -996,7 +960,7 @@ function pageInit() {
dataType: 'json',
acceptFileTypes: /(\.|\/)(bmp|gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5M
url: configDomains.imServer + '/fileManage/uploadFile',
url: configDomains.imCs + '/fileManage/uploadFile',
progressall: function(e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
... ...
/**
* 倒计时 mm:ss
*
* @author: liqi <qi.li@yoho.cn>
* @date: 2016/11/11
*/
/**
* 格式化
* @param total 总的分钟数
* @param el 倒计时显示元素
* @returns {string}
*/
function _secsFormat(total, el) {
var mins = Math.floor(total / 60);
var secs = total - mins * 60;
mins < 10 && (mins = '0' + mins);
secs < 10 && (secs = '0' + secs);
el && el.html(mins + ':' + secs);
if (!el) {
return mins + ':' + secs;
}
}
function countdown(mins, el) {
var interval,
secs = mins * 60;
interval = setInterval(function() {
_secsFormat(--secs, el);
secs === 0 && clearInterval(interval);
}, 1000);
_secsFormat(secs, el);
}
module.exports = countdown;
/**
* 消息编辑区
* @author: liqi <qi.li@yoho.cn>
* @date: 2016/11/26
*/
var $ = require('yoho-jquery');
module.exports = {
/**
* 消息编辑区图标显示
* true: 显示 false: 隐藏
*/
setIcons: function(opt) {
var $util = $('.msg-edit .util');
$.each(opt, function(key, val) {
var $el = $util.find('.' + key);
if (!$el.length || !val && val !== false) {
return;
}
val === true && $el.show();
val === false && $el.hide();
});
}
};
... ...
... ... @@ -29,9 +29,10 @@ var config = {
SUC_DISTRIBUTE: 10009, // 客服管理员收到会话分配成功的回执
CS_LOGOUT: 10011, // 客服注销
END_WORK: 444444, // 成功保存工单
IN_QUNEUE: 777777, // 队列中发送消息后收到的反馈)
CS_CHATTING: 5000000, // 客服管理员收到会话分配成功的回执
OP_LEAVE: 999999998, // 对方断开
OFFLINE: 999999999 // 断线
OFFLINE: 999999999 // 断线
},
conversationMessage: {
... ...
/**
* 判断当前tab页是否可见
*
* @author: liqi <qi.li@yoho.cn>
* @date: 2016/11/26
*/
var state;
var isHidden;
var changeEvent;
function tabIsHidden() {
if (typeof document.hidden !== 'undefined') {
changeEvent = 'visibilitychange';
state = 'visibilityState';
} else if (typeof document.mozHidden !== 'undefined') {
changeEvent = 'mozvisibilitychange';
state = 'mozVisibilityState';
} else if (typeof document.msHidden !== 'undefined') {
changeEvent = 'msvisibilitychange';
state = 'msVisibilityState';
} else if (typeof document.webkitHidden !== 'undefined') {
changeEvent = 'webkitvisibilitychange';
state = 'webkitVisibilityState';
}
return document[state] === 'hidden';
}
function tabVisible(callback) {
isHidden = tabIsHidden();
document.addEventListener(changeEvent, function() {
if (!isHidden) {
if (callback) {
return callback();
}
}
}, false);
}
module.exports = {
tabVisible: tabVisible,
tabIsHidden: tabIsHidden
};
... ... @@ -196,8 +196,8 @@ $color-3a3a3a: #3a3a3a;
.main-body {
padding: 12px 17px;
height: 474px;
max-height: 474px;
height: 408px;
max-height: 408px;
overflow-y: auto;
.msg-list {
... ... @@ -270,7 +270,7 @@ $color-3a3a3a: #3a3a3a;
.time {
display: block;
margin-bottom: 3px;
color: #c5c5c5;
color: #666;
font-size: 12px;
font-family: Helvetica;
}
... ... @@ -327,7 +327,7 @@ $color-3a3a3a: #3a3a3a;
.time {
display: block;
margin-bottom: 3px;
color: #c5c5c5;
color: #666;
font-size: 12px;
font-family: Helvetica;
text-align: right;
... ... @@ -426,7 +426,7 @@ $color-3a3a3a: #3a3a3a;
.msg-edit {
position: relative;
height: 85px;
height: 150px;
width: 100%;
border-top: 1px #e0e0e0 solid;
border-bottom-left-radius: 3px;
... ... @@ -434,7 +434,7 @@ $color-3a3a3a: #3a3a3a;
background-color: #ffffff;
.edit-left {
height: 85px;
height: 150px;
padding: 6px 17px;
margin-right: 60px;
... ... @@ -449,6 +449,8 @@ $color-3a3a3a: #3a3a3a;
line-height: 13px;
cursor: pointer;
&.emoji,
&.image,
&.evaluate,
&.manual-service {
display: none;
... ... @@ -531,7 +533,7 @@ $color-3a3a3a: #3a3a3a;
color: #ffffff;
font-size: 12px;
text-align: center;
line-height: 85px;
line-height: 150px;
background-color: #3a3a3a;
border-bottom-right-radius: 3px;
cursor: pointer;
... ...