Toggle navigation
Toggle navigation
This project
Loading...
Sign in
fe
/
yohobuywap-node
·
Commits
Go to a project
GitLab
Go to group
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
0
Merge Requests
0
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Plain Diff
Browse Files
Authored by
陈轩
8 years ago
Commit
5f716333a747f8645afd4561b1ee0c4c8297b9bb
2 parents
418bb36a
e79ed6db
Merge branch 'master' into feature/captcha
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
690 additions
and
176 deletions
apps/home/controllers/onlineService.js
apps/home/controllers/orderDetail.js
apps/passport/controllers/bind.js
apps/passport/controllers/reg.js
apps/product/controllers/new-shop.js
apps/product/views/partial/search/list.hbs
apps/service/controllers/chat.js
apps/service/models/chatQa.js
apps/serverAPI/im.js → apps/service/models/im-api.js
apps/service/models/im.js
apps/service/router.js
apps/service/views/action/chat/chat-qa.hbs
apps/service/views/action/chat/index.hbs
apps/service/views/action/chat/qa-search.hbs
apps/service/views/partial/chat/chat-comment.hbs
apps/service/views/partial/chat/leave-msg.hbs
config/common.js
doraemon/middleware/user.js
package.json
public/gulpfile.js
public/hbs/service/chat/msg.hbs
public/hbs/service/chat/orders.hbs
public/js/plugin/filter.js
public/js/product/search/list.js
public/js/service/chat-qa.page.js
public/js/service/chat/index.js
public/js/service/chat/socket-chat.js
public/js/service/chat/socket-config.js
public/js/service/chat/store.js
public/js/service/chat/time.js
public/js/service/chat/view.js
public/scss/service/_chatQaList.css
public/scss/service/chat/_chat.css
public/scss/service/chat/_layout.css
public/scss/service/chat/_message.css
public/scss/service/chat/_rating.css
apps/home/controllers/onlineService.js
View file @
5f71633
...
...
@@ -9,8 +9,12 @@
const
onlineModel
=
require
(
'../models/onlineService'
);
const
headerModel
=
require
(
'../../../doraemon/models/header'
);
// 头部model
const
_
=
require
(
'lodash'
);
const
helpers
=
global
.
yoho
.
helpers
;
const
getOnlineServiceInfo
=
(
req
,
res
,
next
)
=>
{
let
serviceUrl
=
_
.
get
(
req
.
app
.
locals
.
wap
,
'clientService.new'
,
false
)
?
helpers
.
urlFormat
(
'/service/im'
)
:
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
;
onlineModel
.
getOnlineServiceInfo
().
then
((
result
)
=>
{
...
...
@@ -25,7 +29,7 @@ const getOnlineServiceInfo = (req, res, next) => {
title
:
'在线客服'
,
pageFooter
:
true
,
service
:
result
,
serviceUrl
:
'http://chat80.live800.com/live800/chatClient/chatbox.jsp?companyID=493979&configID=123576&jid=9277320930'
serviceUrl
:
serviceUrl
});
}).
catch
(
next
);
};
...
...
apps/home/controllers/orderDetail.js
View file @
5f71633
...
...
@@ -6,15 +6,20 @@
'use strict'
;
const
helpers
=
global
.
yoho
.
helpers
;
const
_
=
require
(
'lodash'
);
const
headerModel
=
require
(
'../../../doraemon/models/header'
);
// 头部model
const
orderDetailModel
=
require
(
'../models/orderDetail'
);
const
orderDetailData
=
(
req
,
res
,
next
)
=>
{
let
uid
=
req
.
user
.
uid
;
let
orderCode
=
req
.
query
.
order_code
;
let
serviceUrl
=
_
.
get
(
req
.
app
.
locals
.
wap
,
'clientService.new'
,
false
)
?
helpers
.
urlFormat
(
'/service/im'
)
:
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
;
orderDetailModel
.
orderDetailData
(
uid
,
orderCode
).
then
(
result
=>
{
result
.
serviceUrl
=
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
;
result
.
serviceUrl
=
serviceUrl
;
res
.
render
(
'orderDetail'
,
{
module
:
'home'
,
page
:
'order-detail'
,
...
...
apps/passport/controllers/bind.js
View file @
5f71633
...
...
@@ -32,6 +32,9 @@ const bind = {
let
openId
=
req
.
query
.
openId
;
let
sourceType
=
req
.
query
.
sourceType
;
let
serviceUrl
=
_
.
get
(
req
.
app
.
locals
.
wap
,
'clientService.new'
,
false
)
?
helpers
.
urlFormat
(
'/service/im'
)
:
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
;
res
.
render
(
'bind/index'
,
{
bindIndex
:
true
,
// js标识
...
...
@@ -44,7 +47,7 @@ const bind = {
openId
:
openId
,
// openId
areaCode
:
'+86'
,
// 默认区号
countrys
:
RegService
.
getAreaData
(),
// 国别码
serviceUrl
:
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
,
// 在线客服
serviceUrl
:
serviceUrl
,
// 在线客服
module
:
'passport'
,
page
:
'bind'
,
title
:
'绑定手机号'
...
...
apps/passport/controllers/reg.js
View file @
5f71633
...
...
@@ -196,6 +196,10 @@ let codeAction = (req, res, next) => {
});
}
let
serviceUrl
=
_
.
get
(
req
.
app
.
locals
.
wap
,
'clientService.new'
,
false
)
?
helpers
.
urlFormat
(
'/service/im'
)
:
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
;
res
.
render
(
'reg/code'
,
{
page
:
'code'
,
title
:
'注册-验证码'
,
...
...
@@ -204,7 +208,7 @@ let codeAction = (req, res, next) => {
areaCode
:
area
,
// 默认的区号
phoneNum
:
mobile
,
// 手机号
token
:
token
,
// 访问令牌
serviceUrl
:
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info='
// 在线客服
serviceUrl
:
serviceUrl
// 在线客服
});
};
...
...
apps/product/controllers/new-shop.js
View file @
5f71633
...
...
@@ -45,14 +45,14 @@ const shop = {
params
.
brand
=
brandId
;
let
searchParam
=
{
let
searchParam
=
Object
.
assign
(
{
isApp
:
req
.
yoho
.
isApp
,
brand
:
brandId
,
type
:
'newest'
,
order
:
'1'
,
page
:
1
,
limit
:
4
};
limit
:
4
,
},
params
);
if
(
req
.
query
.
from
!==
'search'
&&
brandLogo
.
type
===
'2'
&&
brandLogo
.
shopId
)
{
req
.
query
.
shop_id
=
brandLogo
.
shopId
;
...
...
@@ -67,7 +67,7 @@ const shop = {
if
(
brandId
===
0
)
{
params
.
query
=
domain
;
}
if
(
brandShop
.
length
>
0
)
{
if
(
brandShop
.
length
>
0
||
brandLogo
)
{
params
=
_
.
assign
({
brandWay
:
_
.
isEmpty
(
brandShop
)
?
brandLogo
:
brandShop
,
search
:
{
...
...
@@ -97,6 +97,7 @@ const shop = {
});
}
}).
then
((
isBrand
)
=>
{
// console.log(params);
if
(
isBrand
)
{
res
.
render
(
'newshop/brand'
,
{
module
:
'product'
,
...
...
apps/product/views/partial/search/list.hbs
View file @
5f71633
...
...
@@ -139,6 +139,7 @@
{{>
common
/
goods
}}
{{/
@root
.
firstPageGoodsList
}}
</div>
<div
class=
"search-divide"
>
正在加载...
</div>
<div
class=
"default-goods container clearfix"
></div>
<div
class=
"new-goods container clearfix"
></div>
<div
class=
"sale-goods container clearfix"
></div>
...
...
apps/service/controllers/chat.js
View file @
5f71633
'use strict'
;
const
orderModel
=
require
(
'../../home/models/order'
);
const
crypto
=
global
.
yoho
.
crypto
;
const
imApi
=
require
(
'../../serverAPI/im'
);
const
imApi
=
require
(
'../models/im-api'
);
const
userApi
=
require
(
'../../passport/models/auth-helper'
);
const
imModel
=
require
(
'../models/im'
);
const
helpers
=
global
.
yoho
.
helpers
;
const
sign
=
global
.
yoho
.
sign
;
...
...
@@ -20,31 +21,51 @@ exports.appAdapter = (req, res, next) => {
next
();
};
exports
.
page
=
(
req
,
res
)
=>
{
res
.
render
(
'chat/index'
,
{
module
:
'service'
,
page
:
'chat'
,
pageStyle
:
'service-chat'
,
width750
:
true
,
localCss
:
true
,
imServer
:
global
.
yoho
.
config
.
domains
.
imServer
,
imSocket
:
global
.
yoho
.
config
.
domains
.
imSocket
,
userData
:
{
uid
:
req
.
user
.
uid
,
encrypteduid
:
req
.
user
.
ENCRYPTION_UID
||
(
crypto
.
encryption
(
null
,
req
.
user
.
uid
+
''
||
'0'
)),
avatar
:
helpers
.
image
(
req
.
user
.
AVATAR
,
100
,
100
),
uname
:
req
.
user
.
NAME
}
});
exports
.
page
=
(
req
,
res
,
next
)
=>
{
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
query
.
uid
;
}
userApi
.
profile
(
req
.
user
.
uid
)
.
then
(
userinfo
=>
{
userinfo
=
userinfo
.
data
;
res
.
render
(
'chat/index'
,
{
module
:
'service'
,
page
:
'chat'
,
pageStyle
:
'service-chat'
,
width750
:
true
,
localCss
:
true
,
imServer
:
global
.
yoho
.
config
.
domains
.
imServer
,
imSocket
:
global
.
yoho
.
config
.
domains
.
imSocket
,
userData
:
{
uid
:
uid
,
encrypteduid
:
crypto
.
encryption
(
null
,
uid
+
''
),
avatar
:
helpers
.
image
(
userinfo
.
head_ico
,
100
,
100
),
uname
:
userinfo
.
profile_name
}
});
})
.
catch
(
next
);
};
exports
.
getOrders
=
(
req
,
res
,
next
)
=>
{
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
query
.
uid
;
}
orderModel
.
getOrders
({
type
:
req
.
query
.
type
||
1
,
page
:
req
.
query
.
page
||
1
,
gender
:
req
.
query
.
gender
||
'1,3'
,
yh_channel
:
req
.
query
.
channel
||
1
,
uid
:
req
.
user
.
uid
uid
}).
then
(
result
=>
{
res
.
render
(
'chat/chat-order'
,
{
layout
:
false
,
...
...
@@ -59,7 +80,12 @@ exports.getOrders = (req, res, next) => {
*
*/
exports
.
fetchHistory
=
(
req
,
res
)
=>
{
const
uid
=
req
.
user
.
uid
;
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
query
.
uid
;
}
const
endTime
=
req
.
query
.
endTime
;
imApi
.
fetchImHistory
(
uid
,
endTime
).
then
(
result
=>
{
...
...
@@ -69,7 +95,12 @@ exports.fetchHistory = (req, res) => {
exports
.
msghistory
=
(
req
,
res
)
=>
{
const
uid
=
req
.
user
.
uid
;
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
query
.
uid
;
}
imApi
.
fetchImHistory
(
uid
).
then
(
result
=>
{
res
.
json
(
result
);
...
...
@@ -84,7 +115,12 @@ exports.msghistory = (req, res) => {
* content 留言内容
*/
exports
.
saveMSG
=
(
req
,
res
)
=>
{
const
uid
=
req
.
user
.
uid
;
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
body
.
uid
;
}
const
conversationId
=
req
.
body
.
conversationId
;
const
content
=
req
.
body
.
content
;
...
...
@@ -103,26 +139,42 @@ exports.saveMSG = (req, res) => {
* 2. 失败情况
*/
exports
.
fetchOrders
=
(
req
,
res
)
=>
{
const
uid
=
req
.
user
.
uid
;
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
query
.
uid
;
}
imApi
.
fetchOrderList
(
uid
)
.
then
(
result
=>
{
imModel
.
handleOrderList
(
result
.
data
);
imModel
.
handleOrderList
(
result
.
data
,
128
,
170
);
res
.
json
(
result
);
}).
catch
(()
=>
{
return
res
.
json
({
code
:
500
,
data
:
[]
});
});
};
exports
.
saveEvalute
=
(
req
,
res
)
=>
{
const
uid
=
req
.
user
.
uid
;
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
body
.
uid
;
}
const
conversationId
=
req
.
body
.
conversationId
;
const
promoter
=
req
.
body
.
promoter
;
const
stars
=
req
.
body
.
stars
;
const
reasonMsg
=
req
.
body
.
reasonMsg
||
''
;
imApi
.
saveEvalute
(
uid
,
conversationId
,
promoter
,
stars
)
imApi
.
saveEvalute
(
uid
,
conversationId
,
promoter
,
stars
,
reasonMsg
)
.
then
(
result
=>
{
return
res
.
json
(
result
);
}
,
()
=>
{
}
).
catch
(
()
=>
{
return
res
.
json
({
code
:
500
,
message
:
'评价失败'
...
...
@@ -131,3 +183,27 @@ exports.saveEvalute = (req, res) => {
};
exports
.
queryGlobalOrder
=
(
req
,
res
)
=>
{
let
uid
=
req
.
user
.
uid
;
if
(
!
uid
)
{
uid
=
req
.
query
.
uid
;
}
let
emptyOrder
=
{
code
:
200
,
data
:
[],
message
:
'获取失败'
};
imApi
.
queryGlobalOrder
(
uid
)
.
then
(
result
=>
{
imModel
.
handleOrderList
(
result
.
data
,
128
,
170
);
res
.
json
(
result
);
},
()
=>
{
res
.
json
(
emptyOrder
);
});
};
...
...
apps/service/models/chatQa.js
View file @
5f71633
...
...
@@ -59,8 +59,8 @@ const qaDetail = (params) => {
// 根据子id,父id,关键字,匹配问题详情
if
(
params
.
keyword
)
{
// 从搜索列表进入,有关键字
if
(
result
&&
result
[
1
]
&&
result
[
1
].
data
&&
result
[
1
].
data
.
data
)
{
let
keyList
=
result
[
1
].
data
.
data
.
helper_list
;
if
(
result
&&
result
[
1
]
&&
result
[
1
].
data
)
{
let
keyList
=
result
[
1
].
data
.
helper_list
;
_
.
forEach
(
keyList
,
function
(
val
)
{
if
(
val
.
id
==
params
.
sonId
)
{
...
...
apps/serv
erAPI/im
.js → apps/serv
ice/models/im-api
.js
View file @
5f71633
...
...
@@ -4,7 +4,7 @@ const _ = require('lodash');
const
crypto
=
global
.
yoho
.
crypto
;
const
config
=
global
.
yoho
.
config
;
const
Im
API
=
new
global
.
yoho
.
ApiBase
(
config
.
domains
.
imCs
,
{
const
Im
Service
=
new
global
.
yoho
.
ApiBase
(
config
.
domains
.
imCs
,
{
name
:
'im'
,
cache
:
global
.
yoho
.
cache
,
useCache
:
false
...
...
@@ -29,7 +29,7 @@ exports.saveMessage = (uid, conversationId, content) => {
};
return
Im
API
.
post
(
'/api/leavemessage/saveLeavemessage'
,
params
);
return
Im
Service
.
post
(
'/api/leavemessage/saveLeavemessage'
,
params
);
};
...
...
@@ -50,11 +50,11 @@ exports.fetchImHistory = (uid, endTime, pageSize, startTime) => {
encryptedUid
:
encryptedUid
(
uid
)
};
_
.
forEach
({
startTime
,
endTime
},
(
key
,
val
)
=>
{
_
.
forEach
({
startTime
,
endTime
},
(
val
,
key
)
=>
{
val
&&
(
params
[
key
]
=
val
);
});
return
Im
API
.
get
(
'/api/conversationMessage/pageList'
,
params
)
return
Im
Service
.
get
(
'/api/conversationMessage/pageList'
,
params
)
.
then
(
result
=>
{
return
result
;
},
()
=>
{
...
...
@@ -83,7 +83,7 @@ exports.fetchOrderList = (uid, createTimeBegin) => {
val
&&
(
params
[
key
]
=
val
);
});
return
Im
API
.
get
(
'/api/order/queryLastTenOrder'
,
params
);
return
Im
Service
.
get
(
'/api/order/queryLastTenOrder'
,
params
);
};
...
...
@@ -108,14 +108,28 @@ exports.fetchOrderList = (uid, createTimeBegin) => {
| reasonMsg | string | N | 其他原因 |
*/
exports
.
saveEvalute
=
(
uid
,
conversationId
,
promoter
,
stars
)
=>
{
exports
.
saveEvalute
=
(
uid
,
conversationId
,
promoter
,
stars
,
reasonMsg
)
=>
{
let
params
=
{
conversationId
,
uid
,
encryptedUid
:
encryptedUid
(
uid
),
promoter
,
stars
stars
,
reasonMsg
};
return
ImAPI
.
post
(
'/api/evalute/saveEvalute'
,
params
);
return
ImService
.
post
(
'/api/evalute/saveEvalute'
,
params
);
};
/**
* 获取全球购的订单
*/
exports
.
queryGlobalOrder
=
uid
=>
{
let
params
=
{
uId
:
uid
};
return
ImService
.
get
(
'/api/order/queryGlobalOrder'
,
params
);
};
...
...
apps/service/models/im.js
View file @
5f71633
...
...
@@ -9,21 +9,33 @@ const _ = require('lodash');
/**
* function: 处理 订单返回的数据
*/
exports
.
handleOrderList
=
data
=>
{
exports
.
handleOrderList
=
(
data
,
w
,
h
)
=>
{
if
(
_
.
isEmpty
(
data
))
{
return
;
}
function
replaceWH
(
img
)
{
return
img
.
replace
(
/
(\{
width
\}
|
\{
height
\})
/g
,
function
(
$0
)
{
const
dict
=
{
'{width}'
:
w
,
'{height}'
:
h
,
};
return
dict
[
$0
];
});
}
data
.
forEach
(
order
=>
{
order
.
goods
=
order
.
ordersGoodsBoList
.
map
(
good
=>
{
return
{
id
:
good
.
productSku
,
name
:
good
.
productName
,
thumb
:
good
.
imgUrl
,
thumb
:
replaceWH
(
good
.
imgUrl
)
,
color
:
good
.
colorName
,
size
:
good
.
sizeName
,
count
:
good
.
buyNumber
,
price
:
good
.
lastPrice
price
:
good
.
lastPrice
,
tariffPrice
:
good
.
tariffPrice
};
});
order
.
count
=
order
.
ordersGoodsBoList
.
reduce
((
sum
,
good
)
=>
{
...
...
apps/service/router.js
View file @
5f71633
...
...
@@ -16,12 +16,14 @@ const chatQa = require(`${cRoot}/chatQa`); // 问题搜索列表页
// middlware
const
authGuard
=
require
(
'../../doraemon/middleware/auth'
);
const
disableBFCache
=
require
(
'../../doraemon/middleware/disable-BFCache'
);
// Your controller here
router
.
get
(
'/im'
,
chat
.
appAdapter
,
authGuard
,
chat
.
page
);
router
.
get
(
'/im'
,
disableBFCache
,
chat
.
appAdapter
,
authGuard
,
chat
.
page
);
router
.
get
(
'/im/fetchHistory'
,
chat
.
fetchHistory
);
router
.
get
(
'/getOrders'
,
chat
.
getOrders
);
router
.
get
(
'/order-list'
,
chat
.
fetchOrders
);
router
.
get
(
'/im/global-list'
,
chat
.
queryGlobalOrder
);
router
.
get
(
'/im/order-list'
,
chat
.
fetchOrders
);
router
.
post
(
'/leavemsg/save.json'
,
chat
.
saveMSG
);
router
.
post
(
'/im/saveEvalute'
,
chat
.
saveEvalute
);
...
...
apps/service/views/action/chat/chat-qa.hbs
View file @
5f71633
<div
class=
"chat-qa-c"
>
<div
class=
"search-c"
>
<a
href=
"
.
/qaSearch"
>
<a
href=
"
//m.yohobuy.com/service
/qaSearch"
>
<i
class=
"search-icon iconfont"
>

</i>
<input
type=
"text"
placeholder=
"有问题?点我搜搜看吧"
readonly=
"readonly"
/ >
</a>
...
...
@@ -10,7 +10,7 @@
{{#
categorys
}}
<div
class=
"list clearfix open-down"
>
<div
class=
"ico-pic"
>
<img
src=
"
{{
categoryIco
}}
"
/>
<img
src=
"
{{
image
categoryIco
60
60
}}
"
/>
</div>
<div>
<p
class=
"title"
>
{{
categoryName
}}
</p>
...
...
@@ -20,7 +20,7 @@
</div>
<div
class=
"down-item"
>
{{#
contentItems
}}
<a
href=
"
.
/qaDetail?sonId=
{{
id
}}
&parentId=
{{
parentId
}}
"
>
<a
href=
"
//m.yohobuy.com/service
/qaDetail?sonId=
{{
id
}}
&parentId=
{{
parentId
}}
"
>
<p>
{{
caption
}}
</p>
<i
class=
"arr-ico iconfont"
>

</i>
</a>
...
...
@@ -31,7 +31,7 @@
<div
class=
"list-title"
>
常见问题
</div>
<div
class=
"list-group"
>
{{#
faqs
}}
<a
class=
"common-item"
href=
"
.
/qaDetail?sonId=
{{
id
}}
"
>
<a
class=
"common-item"
href=
"
//m.yohobuy.com/service
/qaDetail?sonId=
{{
id
}}
"
>
<p>
{{
caption
}}
</p>
<i
class=
"arr-ico iconfont"
>

</i>
</a>
...
...
apps/service/views/action/chat/index.hbs
View file @
5f71633
<div
class=
"ios-gap"
></div>
<div
id=
"chat-main-wrap"
>
<!--im 头部-->
<header
class=
"yoho-header chat-header"
>
...
...
@@ -23,7 +24,9 @@
<a href="javascript:;" class="input-method input-text"></a>
</span>--}}
<span
class=
"table-cell cell-max"
>
<input
type=
"text"
class=
"input-in text-in"
placeholder=
"发送新消息"
>
<form
action=
""
onsubmit=
"return false"
>
<input
type=
"text"
class=
"input-in text-in"
placeholder=
"发送新消息"
>
</form>
</span>
<span
class=
"table-cell"
>
<a
href=
"javascript:;"
class=
"menu-trigger"
></a>
...
...
@@ -32,20 +35,20 @@
<div
class=
"menu"
>
<div
class=
"icon-wrap camera"
>
<input
type=
"file"
class=
"upload-img"
style=
"position: absolute;right: -3px;top: -3px;
z-index: 999;
"
accept=
"image/*"
>
<input
type=
"file"
class=
"upload-img"
style=
"position: absolute;right: -3px;top: -3px;"
accept=
"image/*"
>
<div
class=
"icon"
></div>
<p
class=
"menu-name"
>
拍照
</p>
</div>
<div
class=
"icon-wrap photo"
>
<input
type=
"file"
name=
"filename"
class=
"upload-img"
style=
"position: absolute;right: -3px;top: -3px;
z-index: 999;
"
accept=
"image/*"
>
<input
type=
"file"
name=
"filename"
class=
"upload-img"
style=
"position: absolute;right: -3px;top: -3px;"
accept=
"image/*"
>
<div
class=
"icon"
></div>
<p
class=
"menu-name"
>
相册
</p>
</div>
<div
class=
"icon-wrap order"
data-trigger=
"order-list"
>
<div
class=
"icon-wrap order"
data-trigger=
"order-list"
data-type=
"order"
>
<div
class=
"icon"
></div>
<p
class=
"menu-name"
>
订单
</p>
</div>
<div
class=
"icon-wrap broad-order"
data-trigger=
"order-list"
data-
param=
"internation
al"
>
<div
class=
"icon-wrap broad-order"
data-trigger=
"order-list"
data-
type=
"glob
al"
>
<div
class=
"icon"
></div>
<p
class=
"menu-name"
>
境外订单
</p>
</div>
...
...
apps/service/views/action/chat/qa-search.hbs
View file @
5f71633
...
...
@@ -8,7 +8,7 @@
</div>
<div
class=
"list-group hot-group"
>
{{#
hotSearch
}}
<a
class=
"common-item"
href=
"
.
/qaDetail?sonId=
{{
id
}}
"
>
<a
class=
"common-item"
href=
"
//m.yohobuy.com/service
/qaDetail?sonId=
{{
id
}}
"
>
<p>
{{
caption
}}
</p>
<i
class=
"arr-ico iconfont"
>

</i>
</a>
...
...
apps/service/views/partial/chat/chat-comment.hbs
View file @
5f71633
<!--评价 主体-->
<div
id=
"chat-comment"
class=
"comment"
>
<div
class=
"comment-inner"
>
<div
class=
"intro"
>
请对我们的服务做出评价
<span
class=
"close
"
>
X
</span></div>
<div
class=
"intro"
>
请对我们的服务做出评价
<span
class=
"close
iconfont"
>
&
#xe623
</span></div>
<div
class=
"stars"
>
<i></i>
<i></i>
...
...
@@ -10,7 +10,7 @@
<i></i>
</div>
<div
class=
"rank"
>
</div>
<textarea
class=
"words-to-say"
placeholder=
"还想吐槽下(选填)"
></textarea>
<textarea
class=
"words-to-say"
maxlength=
"50"
placeholder=
"还想吐槽下(选填)"
></textarea>
<button
class=
"submit"
>
提交
</button>
</div>
</div>
\ No newline at end of file
...
...
apps/service/views/partial/chat/leave-msg.hbs
View file @
5f71633
...
...
@@ -5,7 +5,7 @@
<div
class=
"title"
>
留言
</div>
</header>
<div
class=
"main"
>
<textarea
name=
"leave-text"
class=
"leave-text"
placeholder=
"请输入留言文字,Yoho!客服会以短信形式回复您,谢谢您对Yoho!
有货的支持!"
></textarea>
<textarea
name=
"leave-text"
maxlength=
"120"
class=
"leave-text"
placeholder=
"请输入留言文字,Yoho!Buy有货客服会以短信形式回复您,谢谢您对Yoho!Buy
有货的支持!"
></textarea>
<button
class=
"leave-submit"
>
提交
</button>
</div>
</div>
\ No newline at end of file
...
...
config/common.js
View file @
5f71633
...
...
@@ -28,9 +28,9 @@ module.exports = {
service
:
'http://service.yoho.cn/'
,
liveApi
:
'http://api.live.yoho.cn/'
,
singleApi
:
'http://single.yoho.cn/'
,
imSocket
:
'ws://imsocket.yohobuy.com:10000'
,
imCs
:
'http://imhttp.yohobuy.com/api'
,
imServer
:
'http://imhttp.yohobuy.com/server'
imSocket
:
'wss://imsocket.yohobuy.com:443'
,
imCs
:
'https://imhttp.yohobuy.com/api'
,
imServer
:
'https://imhttp.yohobuy.com/server'
},
subDomains
:
{
host
:
'.m.yohobuy.com'
,
...
...
doraemon/middleware/user.js
View file @
5f71633
...
...
@@ -19,15 +19,6 @@ module.exports = () => {
req
.
user
.
uid
=
cookie
.
getUid
(
req
);
}
// app 特殊读法
if
(
!
req
.
user
.
uid
&&
req
.
yoho
.
isApp
)
{
let
userAgent
=
_
.
get
(
req
.
headers
,
'user-agent'
,
''
);
if
(
userAgent
.
indexOf
(
'YohoBuy'
)
>=
0
)
{
req
.
user
.
uid
=
req
.
cookies
.
_YOHOUID
||
0
;
}
}
next
();
};
};
...
...
package.json
View file @
5f71633
{
"name"
:
"m-yohobuy-node"
,
"version"
:
"5.3.
1
"
,
"version"
:
"5.3.
2
"
,
"private"
:
true
,
"description"
:
"A New Yohobuy Project With Express"
,
"repository"
:
{
...
...
public/gulpfile.js
View file @
5f71633
...
...
@@ -239,6 +239,8 @@ gulp.task('webpack-dev-server', () => {
hot
:
true
,
inline
:
true
,
quiet
:
true
,
clientLogLevel
:
'error'
,
compress
:
true
,
stats
:
{
colors
:
true
},
...
...
public/hbs/service/chat/msg.hbs
View file @
5f71633
{{#
each
.
}}
<div
class=
"msg-wrap
{{
style
from
}}
"
data-uuid=
{{
uuid
}}
>
<img
src=
"
http:
{{
image
avatar
80
80
}}
"
alt=
""
class=
"head-icon"
>
<img
src=
"
{{
image
avatar
80
80
}}
"
alt=
""
class=
"head-icon"
>
<div
class=
"chat-info clearfix"
>
{{#
with
data
}}
{{>
(
lookup
..
'type'
)
}}
...
...
@@ -8,7 +7,6 @@
<i
class=
"msg-status iconfont"
></i>
</div>
</div>
{{/
each
}}
{{!--inline partails--}}
...
...
@@ -35,7 +33,7 @@
{{#
*
inline
'picture'
}}
<div
class=
"msg-content msg-pic"
>
<img
src=
"
{{
content
}}
"
alt=
""
class=
"image chat-image"
>
<img
src=
"
{{
content
}}
?imageView2/0/q/50
"
alt=
""
class=
"image chat-image"
>
</div>
{{/
inline
}}
...
...
public/hbs/service/chat/orders.hbs
View file @
5f71633
...
...
@@ -48,7 +48,9 @@
</section>
<footer
class=
"footer"
>
共
{{
count
}}
件商品 实付
<span
class=
"sum-cost"
>
¥
{{
lastOrderAmount
}}
</span>
{{#
shippingCost
}}
(含运费¥
{{
.
}}
)
{{/
shippingCost
}}
{{#
unless
@root
.
isGlobal
}}
{{#
shippingCost
}}
(含运费¥
{{
.
}}
)
{{/
shippingCost
}}
{{/
unless
}}
</footer>
<div
class=
"send-order clearfix"
>
<button
class=
"send-order-btn"
data-action=
"select"
>
发送订单
</button>
...
...
@@ -60,6 +62,5 @@
<div
class=
"no-orders"
>
<i
class=
"no-orders-pic"
></i>
<p>
您暂时没有订单
</p>
<a
href=
"//m.yohobuy.com/product/new"
>
随便逛逛
</a>
</div>
{{/
each
}}
\ No newline at end of file
...
...
public/js/plugin/filter.js
View file @
5f71633
...
...
@@ -16,7 +16,9 @@ var missStatus; // 是否忽略选中状态
// 隐藏筛选界面
function
hideFilter
()
{
$filter
.
addClass
(
'hide'
);
setTimeout
(
function
()
{
$filter
.
addClass
(
'hide'
);
},
301
);
}
// 显示筛选界面
...
...
public/js/product/search/list.js
View file @
5f71633
...
...
@@ -599,8 +599,13 @@ function search(opt) {
}
else
{
if
(
nav
.
reload
)
{
$container
.
html
(
data
);
num
=
$container
.
find
(
'.good-info'
).
length
;
$
(
'.search-divide'
).
remove
();
$container
.
append
(
'<div class="search-divide">正在加载...</div>'
);
lazyLoad
(
$container
.
find
(
'.lazy'
));
if
(
num
<
12
)
{
$
(
'.search-divide'
).
remove
();
}
RES_QTY
=
$container
.
find
(
'.total'
).
data
(
'id'
);
...
...
@@ -632,6 +637,9 @@ function search(opt) {
$
(
'.search-divide'
).
remove
();
$container
.
append
(
data
);
$container
.
append
(
'<div class="search-divide">正在加载...</div>'
);
if
(
num
<
12
)
{
$
(
'.search-divide'
).
remove
();
}
if
(
$container
.
find
(
'.total'
)[
1
])
{
$container
.
find
(
'.total'
)[
1
].
remove
();
...
...
@@ -1209,3 +1217,7 @@ $('#goods-container').on('click', '.good-info', function() {
},
true
);
}
});
var
fuckNum
=
$
(
'.good-info'
).
length
;
fuckNum
<
12
&&
$
(
'.search-divide'
).
remove
();
...
...
public/js/service/chat-qa.page.js
View file @
5f71633
...
...
@@ -53,7 +53,7 @@ $('.get-qa').on('keyup focus',
$searchGroup
.
show
();
$noResult
.
hide
();
$hotGroup
.
hide
();
var
keyList
=
result
.
data
.
data
.
helper_list
;
var
keyList
=
result
.
data
.
helper_list
;
if
(
keyList
==
''
)
{
$searchGroup
.
empty
();
...
...
public/js/service/chat/index.js
View file @
5f71633
...
...
@@ -10,22 +10,26 @@ import appBridge from 'yoho-app';
import
{
time
}
from
'./time'
;
import
{
api
}
from
'./store'
;
import
{
RatingView
,
LeaveMSGView
,
OrderListView
}
from
'./view'
;
import
tip
from
'plugin/tip'
;
var
socket
=
require
(
'./socket-chat'
),
socketConf
=
require
(
'./socket-config'
);
let
FastClick
=
require
(
'yoho-fastclick'
);
var
cmEntity
=
socketConf
.
conversationMessage
;
FastClick
.
attach
(
document
.
body
)
;
const
chatBox
=
$
(
'#chat-window'
);
window
.
requestAnimFrame
=
(
function
()
{
return
window
.
requestAnimationFrame
||
window
.
webkitRequestAnimationFrame
||
function
(
callback
)
{
window
.
setTimeout
(
callback
,
1000
/
60
);
};
}());
var
qs
=
require
(
'yoho-qs'
);
// 聊天调整footer位置
const
resizeFooter
=
()
=>
{
let
bottom
=
$
(
'#chat-footer'
).
height
();
var
socket
=
require
(
'./socket-chat'
),
socketConf
=
require
(
'./socket-config'
);
chatBox
.
css
(
'bottom'
,
`
$
{
bottom
}
px
`
);
chatBox
[
0
].
scrollTop
=
chatBox
[
0
].
scrollHeight
;
};
var
cmEntity
=
socketConf
.
conversationMessage
;
// 配置
const
msgTypeMap
=
{
...
...
@@ -37,18 +41,41 @@ const msgTypeMap = {
let
userName
=
$
(
'#js-uname'
).
val
();
let
uid
=
cmEntity
.
userId
=
$
(
'#js-uid'
).
val
()
||
0
;
let
encryptedUid
=
cmEntity
.
encryptedUid
=
$
(
'#js-eid'
).
val
()
||
0
;
let
userAvatar
=
cmEntity
.
userHead
=
$
(
'#js-avatar'
).
val
()
||
socketConf
.
defaultUserHead
;
let
userAvatar
=
cmEntity
.
userHead
=
socketConf
.
defaultUserHead
;
let
imgSrc
=
$
(
'#js-avatar'
).
val
();
// 客服配置
let
customerService
=
{
head
:
socketConf
.
defaultUserHead
,
name
:
''
};
function
checkUserAvatarValid
(
src
,
success
)
{
let
imgDOM
=
new
Image
();
imgDOM
.
src
=
src
;
imgDOM
.
style
.
display
=
'none'
;
imgDOM
.
onload
=
function
()
{
success
(
src
);
document
.
body
.
removeChild
(
this
);
};
imgDOM
.
onerror
=
function
()
{
document
.
body
.
removeChild
(
this
);
};
document
.
body
.
appendChild
(
imgDOM
);
}
// window.checkUserAvatarValid = checkUserAvatarValid;
checkUserAvatarValid
(
imgSrc
,
src
=>
{
userAvatar
=
cmEntity
.
userHead
=
src
;
});
let
isAndroid
=
/YohoBuy-android/i
.
test
(
navigator
.
userAgent
);
// 历史消息分页
let
msgHistory
=
{
conversationId
:
''
,
// 会话id
endTime
:
null
,
curCount
:
0
,
totalCount
:
null
...
...
@@ -65,6 +92,8 @@ var chat = {
unFinshMSGs
:
{},
// 没有发送出去消息
$ratingView
:
$
(
'#chat-comment'
),
canEvalute
:
true
,
canManualService
:
true
,
canLeaveMSG
:
false
,
messageT
:
require
(
'service/chat/msg.hbs'
),
...
...
@@ -88,9 +117,6 @@ var chat = {
cmEntity
.
encryptedUid
=
encryptedUid
;
self
.
fetchHistoryMsg
().
always
(
function
()
{
let
chatWinDOM
=
self
.
$chatWin
[
0
];
chatWinDOM
.
scrollTop
=
chatWinDOM
.
scrollHeight
;
self
.
$chatWin
.
append
(
time
(
Date
.
now
()).
show
());
self
.
connect
();
...
...
@@ -137,8 +163,17 @@ var chat = {
// 处理消息
self
.
handleReceiveMSG
(
received
);
},
onClose
:
function
()
{
self
.
_sysInfo
(
'连接已断开'
);
},
onOpen
:
$
.
noop
,
onClose
:
$
.
noop
sendFailCallback
:
function
()
{
self
.
_sysInfo
(
'<p>连接断开,请尝试<span class="blue">重连</span></p>'
)
.
one
(
'click'
,
function
()
{
self
.
connect
();
});
},
};
let
config
=
$
.
extend
(
socketConf
,
actions
);
...
...
@@ -154,18 +189,45 @@ var chat = {
this
.
$chat
.
on
(
'click.Rating.toggle'
,
'[data-trigger=rating]'
,
function
()
{
self
.
canEvalute
&&
self
.
ratingView
.
toggle
();
if
(
self
.
canEvalute
)
{
self
.
ratingView
.
toggle
()
}
else
{
tip
.
show
(
'您已评价,请勿重复评价'
);
}
})
.
on
(
'click.leaveMSG'
,
'[data-trigger=leave-msg]'
,
function
()
{
self
.
leaveMSGView
.
trigger
(
'show.LeaveMSGView'
);
self
.
canLeaveMSG
&&
self
.
leaveMSGView
.
trigger
(
'show.LeaveMSGView'
);
})
.
on
(
'click.orderList'
,
'[data-trigger=order-list]'
,
function
()
{
self
.
orderListView
.
trigger
(
'show.OderListView'
);
let
orderType
=
$
(
this
).
data
(
'type'
)
||
''
;
self
.
orderListView
.
trigger
(
'show.OderListView'
,
[
orderType
]);
})
.
on
(
'click.chat.switchServer'
,
'[data-action=change-human]'
,
function
()
{
self
.
switchService
(
'human'
);
self
.
canManualService
&&
self
.
switchService
(
'human'
);
})
.
on
(
'focus.chat.sendText'
,
'.text-in'
,
function
()
{
self
.
toggleMenu
(
false
);
window
.
requestAnimFrame
(()
=>
{
$
(
'#chat-footer'
)[
0
].
scrollIntoView
();
});
})
.
on
(
'click'
,
'#chat-window'
,
function
()
{
self
.
toggleMenu
(
false
);
})
.
on
(
'focus'
,
'.text-in'
,
function
()
{
self
.
chatWinScrollToBottom
();
return
false
;
})
.
on
(
'keydown.chat.sendText'
,
'.text-in'
,
function
(
event
)
{
event
.
stopPropagation
();
window
.
requestAnimFrame
(()
=>
{
$
(
'#chat-footer'
)[
0
].
scrollIntoView
();
});
if
(
event
.
which
===
13
)
{
let
val
=
$
.
trim
(
event
.
target
.
value
);
...
...
@@ -185,7 +247,6 @@ var chat = {
}
});
this
.
orderListView
.
on
(
'selectOrder.OrderListView'
,
function
(
event
,
data
)
{
let
msg
=
{
...
...
@@ -195,6 +256,7 @@ var chat = {
};
self
.
sendMSG
(
msg
);
self
.
$chatWin
[
0
].
scrollTop
=
self
.
$chatWin
[
0
].
scrollHeight
;
});
this
.
leaveMSGView
...
...
@@ -213,9 +275,12 @@ var chat = {
self
.
canEvalute
=
false
;
cmEntity
.
type
=
socketConf
.
recType
.
EVALUTE_SUCCESS
;
socket
.
send
(
JSON
.
stringify
(
cmEntity
));
resizeFooter
();
//
resizeFooter();
});
window
.
addEventListener
(
'online'
,
function
()
{
self
.
$netTip
.
toggleClass
(
'hide'
,
true
);
self
.
connect
();
...
...
@@ -224,8 +289,21 @@ var chat = {
window
.
addEventListener
(
'offline'
,
function
()
{
self
.
$chat
.
toggleClass
(
'online'
,
false
);
self
.
$netTip
.
toggleClass
(
'hide'
,
false
);
self
.
toggleMenu
(
false
);
// self.disconnect();
});
// app 不支持打开链接
if
(
isAndroid
||
appBridge
.
isApp
)
{
this
.
$chatWin
.
on
(
'click'
,
'.link'
,
function
(
event
)
{
event
.
preventDefault
();
// tip.show('抱歉,暂不支持,长按复制到手机浏览器打开');
return
false
;
});
}
},
/**
...
...
@@ -242,11 +320,14 @@ var chat = {
/**
* 当断开时
*/
disconnect
()
{
disconnect
(
content
)
{
var
self
=
this
;
this
.
canLeaveMSG
=
true
;
this
.
$chat
.
toggleClass
(
'online'
,
false
);
this
.
_sysInfo
(
'<p>会话断开,点击<span class="blue">重连</span></p>'
)
this
.
toggleMenu
(
false
);
this
.
_sysInfo
(
`
<
p
>
$
{
content
}
<
span
class
=
"blue"
>
连接客服
<
/span></
p
>
`
)
.
one
(
'click'
,
function
()
{
self
.
connect
();
});
...
...
@@ -282,8 +363,6 @@ var chat = {
msg
.
uuid
=
uuid
;
cmEntity
.
userHead
=
msg
.
avatar
=
userAvatar
;
cmEntity
.
csHead
=
customerService
.
head
;
cmEntity
.
csName
=
customerService
.
name
;
cmEntity
.
uuid
=
uuid
;
cmEntity
.
type
=
socketConf
.
recType
.
CU_SEND
;
...
...
@@ -291,7 +370,7 @@ var chat = {
case
'order'
:
arr
=
[
'单号:'
,
data
.
orderCode
,
'金额: '
,
'¥'
+
data
.
cost
,
'金额: '
,
data
.
cost
,
'下单时间: '
,
data
.
createTime
,
'状态: '
,
data
.
orderStatus
];
...
...
@@ -300,6 +379,10 @@ var chat = {
cmEntity
.
chatMessage
.
type
=
10
;
cmEntity
.
chatMessage
.
content
=
arr
;
break
;
case
'picture'
:
cmEntity
.
chatMessage
.
type
=
2
;
cmEntity
.
chatMessage
.
content
=
data
.
content
;
break
;
case
'text'
:
default
:
cmEntity
.
chatMessage
.
type
=
1
;
...
...
@@ -345,8 +428,11 @@ var chat = {
$msg
.
trigger
(
'send.sendEvent'
);
});
})
.
on
(
'success.sendEvent'
,
function
()
{
.
on
(
'success.sendEvent'
,
function
(
event
,
rec
)
{
clearTimeout
(
$msg
.
data
(
'timeoutId'
));
if
(
rec
.
type
===
1
)
{
$msg
.
find
(
'.msg-content'
).
html
(
rec
.
chatMessage
.
newContent
);
}
$msg
.
removeClass
(
'send-loading send-fail'
)
.
off
(
'sendEvent'
)
.
removeData
();
...
...
@@ -380,6 +466,9 @@ var chat = {
var
chatMessage
=
cm
.
chatMessage
;
var
allTypes
=
socketConf
.
recType
;
//设置默认用户头像
cm
.
userHead
=
userAvatar
;
switch
(
cm
.
type
)
{
case
allTypes
.
CU_SEND
:
viewData
.
from
=
'customer'
;
...
...
@@ -387,7 +476,7 @@ var chat = {
break
;
case
allTypes
.
CS_SEND
:
viewData
.
from
=
'employee'
;
viewData
.
avatar
=
c
ustomerService
.
head
||
socketConf
.
defaultUser
Head
;
viewData
.
avatar
=
c
m
.
csHead
||
socketConf
.
employe
Head
;
break
;
case
allTypes
.
ROBOT_SEND
:
viewData
.
from
=
'rebot'
;
...
...
@@ -413,7 +502,7 @@ var chat = {
case
1
:
viewData
.
type
=
msgTypeMap
[
1
];
viewData
.
data
=
{
content
:
emojiHanlder
(
chatMessage
.
newContent
)
content
:
emojiHanlder
(
chatMessage
.
newContent
)
||
chatMessage
.
content
};
break
;
...
...
@@ -457,12 +546,15 @@ var chat = {
if
(
this
.
unFinshMSGs
[
uuid
])
{
let
$msg
=
this
.
unFinshMSGs
[
uuid
];
$msg
.
trigger
(
'success.sendEvent'
);
$msg
.
trigger
(
'success.sendEvent'
,
rec
);
}
// var uuid = rec.uuid;
var
viewData
;
this
.
canManualService
=
true
;
this
.
canLeaveMSG
=
false
;
// 服务状态: 离线
if
(
recType
===
allTypes
.
OFFLINE
||
...
...
@@ -490,6 +582,7 @@ var chat = {
case
allTypes
.
CS_CHATTING
:
if
(
chatMessage
.
type
===
5
)
{
// 重复登陆
this
.
canManualService
=
false
;
this
.
_sysInfo
(
chatMessage
.
newContent
);
}
break
;
...
...
@@ -501,6 +594,7 @@ var chat = {
// 客服邀请评价
case
allTypes
.
EVAL_INVITE
:
this
.
_sysInfo
(
'<p data-trigger="rating">请对我们的服务进行<span class="blue">评价</span></p>'
);
this
.
ratingView
.
toggle
(
true
);
break
;
// 客服进入
...
...
@@ -510,7 +604,7 @@ var chat = {
break
;
case
allTypes
.
OP_LEAVE
:
case
allTypes
.
OFFLINE
:
this
.
disconnect
();
this
.
disconnect
(
chatMessage
.
content
);
break
;
case
allTypes
.
TRANSFER
:
break
;
...
...
@@ -546,18 +640,26 @@ var chat = {
const
chatMessage
=
cmEntity
.
chatMessage
;
customerService
.
head
=
cmEntity
.
csHead
;
customerService
.
name
=
cmEntity
.
csName
;
function
noService
()
{
$chatHeader
.
find
(
'.js-service-txt'
).
text
(
'YOHO客服'
);
$chat
.
append
(
time
(
Date
.
now
()).
show
());
}
// state: 0 没有人工客服
function
noEmploye
()
{
$chatHeader
.
find
(
'.js-service-txt'
).
text
(
'YOHO客服'
);
$chat
.
append
(
time
(
Date
.
now
()).
show
());
sysInfo
(
chatMessage
.
content
);
sysInfo
();
}
// state 1: 排队中
function
inQueue
()
{
let
info
=
`
$
{
chatMessage
.
content
}
您可以
<
span
class
=
"blue"
data
-
trigger
=
"leave-msg"
>
留言
<
/span>`
;
// let info = `${chatMessage.content}您可以<span class="blue" data-trigger="leave-msg">留言</span>`;
let
info
=
'您可以选择<span class="blue" data-trigger="leave-msg">留言</span>,客服会以短信形式回复您'
;
self
.
canLeaveMSG
=
true
;
sysInfo
(
info
);
}
...
...
@@ -574,8 +676,11 @@ var chat = {
}
switch
(
state
)
{
case
0
:
noEmploye
();
break
;
case
1
:
inQueue
();
break
;
case
2
:
linkSuccess
();
break
;
case
2
:
case
3
:
linkSuccess
();
break
;
default
:
noService
();
break
;
}
},
...
...
@@ -594,10 +699,6 @@ var chat = {
_drawMSG
:
function
(
viewData
,
cusAction
=
null
)
{
let
chatWin
=
this
.
$chatWin
[
0
];
if
(
!
$
.
isArray
(
viewData
))
{
viewData
=
[
viewData
];
}
// console.log(viewData);
let
$html
=
$
(
this
.
messageT
(
viewData
));
...
...
@@ -663,22 +764,46 @@ var chat = {
let
records
=
result
.
records
||
[];
records
.
reverse
();
// records.reverse();
let
oldFister
=
self
.
$chatWin
.
find
(
'.msg-wrap:first'
)[
0
];
let
grap
=
oldFister
?
oldFister
.
offsetTop
:
0
;
let
$docFragment
=
$
(
document
.
createDocumentFragment
());
records
.
forEach
(
chatMessage
=>
{
records
.
forEach
((
chatMessage
,
index
,
arr
)
=>
{
let
nextChat
=
records
[
index
+
1
];
let
data
=
self
.
buildViewData
(
chatMessage
);
//eslint-disable-line
if
(
data
)
{
arr
.
push
(
data
);
let
conversationId
=
chatMessage
.
conversationId
;
let
timstamp
=
Math
.
ceil
(
chatMessage
.
sendTime
/
1000
);
// 原来是微妙 转换成毫秒
let
$html
=
self
.
_drawMSG
(
data
);
$docFragment
.
prepend
(
$html
);
if
(
index
===
0
&&
!
msgHistory
.
conversationId
)
{
msgHistory
.
conversationId
=
conversationId
;
}
if
(
nextChat
&&
(
nextChat
.
conversationId
!==
msgHistory
.
conversationId
)
)
{
$docFragment
.
prepend
(
time
(
timstamp
).
show
());
msgHistory
.
conversationId
=
nextChat
.
conversationId
;
}
}
});
self
.
_drawMSG
(
arr
,
function
(
$html
)
{
self
.
$historyLoader
.
after
(
$html
);
});
self
.
$historyLoader
.
after
(
$docFragment
);
oldFister
&&
self
.
$chatWin
.
scrollTop
(
oldFister
.
offsetTop
-
grap
);
if
(
records
.
length
)
{
msgHistory
.
endTime
=
records
[
0
].
sendTime
;
msgHistory
.
endTime
=
records
[
records
.
length
-
1
].
sendTime
;
msgHistory
.
curCount
+=
records
.
length
;
}
...
...
@@ -693,7 +818,7 @@ var chat = {
if
(
type
===
'human'
)
{
cmEntity
.
type
=
socketConf
.
recType
.
MANUAL_SERVICE
;
socket
.
send
(
JSON
.
stringify
(
cmEntity
));
this
.
_sysInfo
();
//
this._sysInfo();
}
else
{
// todo;
}
...
...
@@ -722,17 +847,46 @@ var chat = {
.
find
(
'.header-right'
).
html
(
header
.
right
);
return
this
;
},
toggleMenu
:
function
(
willShow
)
{
if
(
willShow
===
void
0
)
{
willShow
=
!
this
.
$chat
.
hasClass
(
'menu-open'
);
}
this
.
$chat
.
toggleClass
(
'menu-open'
,
willShow
);
this
.
chatWinScrollToBottom
();
// let chatWin = this.$chatWin[0];
// let footerH = $('#chat-footer .menu').outerHeight() || 0;
// if (willShow) {
// chatWin.scrollTop += footerH;
// } else {
// chatWin.scrollTop -= footerH;
// }
},
chatWinScrollToBottom
:
function
()
{
let
chatWin
=
chat
.
$chatWin
[
0
];
window
.
requestAnimationFrame
(()
=>
{
chatWin
.
scrollTop
=
chatWin
.
scrollHeight
;
});
}
};
chat
.
init
();
// 触发菜单
$
(
'.menu-trigger'
).
on
(
'click'
,
function
()
{
let
$menu
=
$
(
'.menu'
);
chat
.
toggleMenu
();
// let $menu = $('.menu');
$menu
.
toggle
();
resizeFooter
();
// $menu.toggle();
// resizeFooter();
});
let
$upload
=
$
(
'.upload-img'
);
...
...
@@ -772,8 +926,11 @@ $upload.on('change', function() {
.
done
(
function
(
res
)
{
if
(
res
.
code
===
200
)
{
$elem
.
removeClass
(
'send-loading'
)
.
find
(
'.chat-image'
).
attr
(
'src'
,
res
.
data
.
filePath
);
.
find
(
'.chat-image'
).
attr
(
'src'
,
res
.
data
.
filePath
)
.
on
(
'load'
,
function
()
{
chat
.
chatWinScrollToBottom
();
});
msg
.
data
.
content
=
res
.
data
.
filePath
;
chat
.
sendMSG
(
msg
,
true
);
// only send msg, no draw msg;
}
})
...
...
@@ -783,6 +940,11 @@ $upload.on('change', function() {
.
removeClass
(
'send-loading'
)
.
addClass
(
'send-fail'
)
.
one
(
'click'
,
_action
);
})
.
always
(
function
()
{
input
.
value
=
''
;
chat
.
chatWinScrollToBottom
();
});
};
...
...
@@ -803,16 +965,59 @@ $('#chat-window').on('click', '.chat-image', function() {
});
});
if
(
appBridge
.
isApp
)
{
$
(
'#js-back'
).
on
(
'click'
,
function
(
e
)
{
function
tellAppSuccess
()
{
window
.
setTimeout
(()
=>
{
appBridge
.
invokeMethod
(
'im.page_success'
,
{
url
:
location
.
href
});
},
1000
);
window
.
addEventListener
(
'pageshow'
,
tellAppSuccess
);
}
function
setChannelColor
(
channel
)
{
var
dict
=
{
1
:
'boys'
,
2
:
'girls'
,
3
:
'kids'
,
4
:
'lifestyle'
};
$
(
document
.
body
)
.
removeClass
(
'boys girls kids lifestyle'
)
.
addClass
(
dict
[
channel
]);
}
if
(
appBridge
.
isApp
&&
/YohoBuy-iOS/i
.
test
(
navigator
.
userAgent
))
{
document
.
body
.
classList
.
add
(
'app-ios'
);
}
if
(
isAndroid
)
{
$
(
'#js-back'
).
removeAttr
(
'href'
).
on
(
'click'
,
function
(
e
)
{
e
.
preventDefault
();
window
.
im
.
goBack
();
});
setChannelColor
(
qs
.
yh_channel
);
}
else
if
(
appBridge
.
isApp
)
{
$
(
'#js-back'
).
removeAttr
(
'href'
).
on
(
'click'
,
function
(
e
)
{
e
.
preventDefault
();
appBridge
.
invokeMethod
(
'go.back'
,
{});
});
tellAppSuccess
();
setChannelColor
(
qs
.
yh_channel
);
}
window
.
channelChanged
=
function
(
channel
)
{
setChannelColor
(
channel
);
};
window
.
$
=
$
;
window
.
chat
=
chat
;
window
.
cmEntity
=
cmEntity
;
...
...
public/js/service/chat/socket-chat.js
View file @
5f71633
...
...
@@ -9,6 +9,7 @@ var param,
servers
,
socket
,
server
,
sendFailCallback
,
conversationMessage
;
function
_randomServer
()
{
...
...
@@ -40,6 +41,10 @@ function socketInit(options) {
socket
.
onclose
=
options
.
onClose
||
function
()
{
console
.
log
(
'websocket is closed'
);
};
socket
.
onerror
=
options
.
onError
||
function
()
{
console
.
log
(
'websocket meet error'
);
};
sendFailCallback
=
options
.
sendFailCallback
||
$
.
noop
;
}
else
{
console
.
log
(
'websocket is not support'
);
}
...
...
@@ -57,6 +62,7 @@ function sendMsg(msg) {
console
.
log
(
'websocket send: '
,
JSON
.
parse
(
msg
));
socket
.
send
(
msg
);
}
else
{
sendFailCallback
();
console
.
log
(
'The socket is not open.'
);
}
}
...
...
public/js/service/chat/socket-config.js
View file @
5f71633
...
...
@@ -10,6 +10,7 @@ var config = {
servers
:
[
gDomains
.
imSocket
],
defaultUserHead
:
'//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif'
,
rebotUserHead
:
`
$
{
window
.
STATIC_RESOURCE_PATH
}
/img/
service
/
chat
/
im
-
robot
.
png
`
,
employeHead
:
'//img12.static.yhbimg.com/imserver/2016/11/17/11/02bc3c3de856432175c01d937342a1f2ce.jpg'
,
recType
:
{
ENTER
:
1
,
// 用户进入
LINK_SUCCESS
:
2
,
// 连线人工客服回应
...
...
@@ -45,15 +46,15 @@ var config = {
encryptedUid
:
0
,
userHead
:
'//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif'
,
// 用户头像
userName
:
''
,
// 用户账号
csId
:
0
,
type
:
1
,
csId
:
0
,
// 客服 ID
type
:
1
,
// type => [0:没人在线,1:排队,2:接通,3:管理员分配]
serviceSortId
:
0
,
serviceSortCode
:
''
,
customerSettingId
:
0
,
roleType
:
0
,
chatMessage
:
{
messageObjectId
:
''
,
type
:
0
,
type
:
0
,
// 消息内容类型: 1:文本 2:图片 3:语音 4: 订单
content
:
''
,
newContent
:
''
}
...
...
public/js/service/chat/store.js
View file @
5f71633
...
...
@@ -5,6 +5,8 @@ const socketConf = require('./socket-config');
const
conversation
=
socketConf
.
conversationMessage
;
const
slice
=
Array
.
prototype
.
slice
;
let
uid
=
$
(
'#js-uid'
).
val
();
// EventEmitter
//--------------------------------------------------------
const
EventEmitter
=
function
()
{};
...
...
@@ -53,6 +55,7 @@ let api = {
return
$
.
post
(
'/service/leavemsg/save.json'
,
{
conversationId
:
conversation
.
conversationId
,
content
,
uid
});
},
...
...
@@ -61,8 +64,10 @@ let api = {
* TODO:
* 1. 目前接口不支持分页
*/
fetchOrders
:
function
()
{
return
$
.
get
(
'/service/order-list'
);
fetchOrders
:
function
(
type
)
{
let
url
=
`
/
service
/
im
/
$
{
type
}
-
list
`
;
return
$
.
get
(
url
,
{
uid
});
},
// 获取10条历史记录
...
...
@@ -79,6 +84,7 @@ let api = {
},
saveEvalute
:
function
(
data
)
{
data
.
uid
=
uid
;
return
$
.
post
(
'/service/im/saveEvalute'
,
data
);
}
};
...
...
public/js/service/chat/time.js
View file @
5f71633
...
...
@@ -44,6 +44,10 @@ class Time {
timef
=
this
.
_format
(
this
.
timestamp
,
'yyyy.MM.dd hh:mm'
);
}
return
this
.
render
(
timef
);
}
render
(
timef
)
{
return
`
<
div
class
=
"chat-time"
>
$
{
timef
}
<
/div>`
;
...
...
public/js/service/chat/view.js
View file @
5f71633
...
...
@@ -5,6 +5,7 @@ const loading = require('../../plugin/loading'),
require
(
'../../common'
);
import
{
EventEmitter
,
api
}
from
'./store'
;
import
appBridge
from
'yoho-app'
;
const
LeaveMSGView
=
function
(
elem
)
{
...
...
@@ -12,6 +13,7 @@ const LeaveMSGView = function(elem) {
this
.
$input
=
this
.
$elem
.
find
(
'.leave-text'
);
this
.
$doc
=
$
(
document
);
this
.
bindEvents
();
this
.
isSending
=
false
;
};
LeaveMSGView
.
prototype
=
$
.
extend
({},
EventEmitter
.
prototype
,
{
...
...
@@ -23,10 +25,12 @@ LeaveMSGView.prototype = $.extend({}, EventEmitter.prototype, {
let
self
=
this
;
this
.
$elem
.
on
(
'click'
,
'.chat-page-back'
,
function
()
{
.
on
(
'click'
,
'.chat-page-back'
,
function
(
event
)
{
event
.
stopPropagation
();
self
.
toggleHide
(
true
);
})
.
on
(
'click.LeavseMSG.submit'
,
'.leave-submit'
,
function
()
{
event
.
stopPropagation
();
self
.
submit
();
});
...
...
@@ -40,13 +44,20 @@ LeaveMSGView.prototype = $.extend({}, EventEmitter.prototype, {
toggleHide
(
willHide
)
{
this
.
$elem
.
toggleClass
(
'chat-page-hide'
,
willHide
);
return
this
;
return
false
;
},
/**
* 提交留言的hanlder
*/
submit
()
{
if
(
this
.
isSending
)
{
tip
.
show
(
'正在发送..'
);
return
;
}
this
.
isSending
=
true
;
let
self
=
this
;
let
content
=
$
.
trim
(
this
.
$input
.
val
());
...
...
@@ -57,9 +68,13 @@ LeaveMSGView.prototype = $.extend({}, EventEmitter.prototype, {
api
.
leaveMsg
(
content
)
.
done
(
function
()
{
self
.
trigger
(
'save.LeaveMSGView'
,
'留言成功,'
);
self
.
$input
.
val
(
''
);
})
.
fail
(
function
()
{
self
.
trigger
(
'save.LeaveMSGView'
,
'留言失败'
);
})
.
always
(
function
()
{
self
.
isSending
=
false
;
});
self
.
toggleHide
(
true
);
...
...
@@ -79,6 +94,7 @@ const RatingView = function(elem, socket) {
this
.
rank
=
3
;
this
.
bindEvents
();
this
.
socket
=
socket
;
this
.
isSending
=
false
;
};
RatingView
.
prototype
=
$
.
extend
({},
EventEmitter
.
prototype
,
{
...
...
@@ -88,6 +104,8 @@ RatingView.prototype = $.extend({}, EventEmitter.prototype, {
this
.
elem
.
on
(
'click.RatingView.rating'
,
'.stars i'
,
function
(
event
)
{
event
.
stopPropagation
();
let
starVal
=
$
(
this
).
index
();
self
.
rating
(
starVal
);
...
...
@@ -115,6 +133,12 @@ RatingView.prototype = $.extend({}, EventEmitter.prototype, {
},
post
(
data
)
{
if
(
this
.
isSending
)
{
tip
.
show
(
'正在发送..'
);
return
;
}
this
.
isSending
=
true
;
const
self
=
this
,
elem
=
this
.
elem
;
var
params
=
{
...
...
@@ -138,12 +162,20 @@ RatingView.prototype = $.extend({}, EventEmitter.prototype, {
})
.
fail
(()
=>
{
tip
.
show
(
'评价失败'
);
})
.
always
(()
=>
{
self
.
isSending
=
false
;
});
},
toggle
(
willShow
)
{
if
(
willShow
===
this
.
elem
.
is
(
':visible'
))
{
return
;
}
this
.
elem
.
toggle
(
willShow
);
this
.
rating
(
3
);
this
.
rating
(
4
);
return
false
;
}
});
...
...
@@ -156,8 +188,20 @@ const OrderListView = function(elem) {
this
.
$localOrders
=
this
.
$elem
.
find
(
'[data-tab=local]'
);
this
.
$globalOrders
=
this
.
$elem
.
find
(
'[data-tab=global]'
);
// 分页数据
this
.
state
=
{
global
:
{
curCount
:
0
,
totalCount
:
null
},
order
:
{
curCount
:
0
,
totalCount
:
null
}
};
this
.
bindEvents
();
this
.
fetchOrders
();
//
this.fetchOrders();
};
OrderListView
.
prototype
=
$
.
extend
({},
EventEmitter
.
prototype
,
{
...
...
@@ -165,15 +209,19 @@ OrderListView.prototype = $.extend({}, EventEmitter.prototype, {
const
self
=
this
;
this
.
$elem
.
on
(
'click.OrderListView.back'
,
'.chat-page-back'
,
function
()
{
.
on
(
'click.OrderListView.back'
,
'.chat-page-back'
,
function
(
event
)
{
event
.
stopPropagation
();
self
.
toggleHide
(
true
);
})
.
on
(
'click.OrderListView.select'
,
'[data-action=select]'
,
function
()
{
.
on
(
'click.OrderListView.select'
,
'[data-action=select]'
,
function
(
event
)
{
event
.
stopPropagation
();
self
.
selectOrder
(
$
(
event
.
target
));
});
// 被通知显示,执行显示
this
.
on
(
'show.OderListView'
,
$
.
proxy
(
this
.
toggleHide
,
this
,
false
));
this
.
on
(
'show.OderListView'
,
(
event
,
type
)
=>
{
self
.
toggleHide
(
false
,
type
);
});
},
/**
...
...
@@ -203,25 +251,55 @@ OrderListView.prototype = $.extend({}, EventEmitter.prototype, {
* @param boolean willHide;
* @return this
*/
toggleHide
:
function
(
willHide
)
{
toggleHide
:
function
(
willHide
,
type
)
{
this
.
$elem
.
toggleClass
(
'chat-page-hide'
,
willHide
);
if
(
!
willHide
)
{
let
orderState
=
this
.
state
[
type
];
let
{
totalCount
}
=
orderState
;
totalCount
===
null
&&
this
.
fetchOrderByType
(
type
,
orderState
);
if
(
type
===
'global'
)
{
this
.
$globalOrders
.
show
();
this
.
$localOrders
.
hide
();
}
else
if
(
type
===
'order'
)
{
this
.
$globalOrders
.
hide
();
this
.
$localOrders
.
show
();
}
}
else
{
this
.
$globalOrders
.
hide
();
this
.
$localOrders
.
hide
();
}
return
this
;
},
fetchOrderByType
:
function
(
type
,
orderState
)
{
let
self
=
this
;
let
$order
=
type
===
'global'
?
this
.
$globalOrders
:
this
.
$localOrders
;
let
{
totalCount
}
=
orderState
;
/**
* method: 获取订单
*/
fetchOrders
:
function
()
{
const
self
=
this
;
// TODO: 分页
if
(
totalCount
===
null
)
{
// 还未加载数据
api
.
fetchOrders
(
type
).
done
(
result
=>
{
let
html
=
self
.
orderListT
({
orders
:
result
.
data
,
isApp
:
appBridge
.
isApp
,
isGlobal
:
type
===
'global'
});
return
api
.
fetchOrders
().
done
(
result
=>
{
let
html
=
self
.
orderListT
({
orders
:
result
.
data
});
orderState
.
totalCount
=
result
.
data
.
length
;
orderState
.
curCount
=
result
.
data
.
length
;
self
.
$localOrders
.
append
(
html
);
lazyLoad
(
$
(
'img.lazy'
));
});
$order
.
append
(
html
);
}
);
}
}
});
...
...
public/scss/service/_chatQaList.css
View file @
5f71633
...
...
@@ -104,15 +104,24 @@
}
.gm-ico
{
background-image
:
resolve
(
"service/chat/gm-ico.png"
);
background-image
:
url("/service/chat/gm-ico.png")
;
width
:
60px
;
height
:
60px
;
margin
:
30px
20px
;
}
.advice-ico
{
background-image
:
resolve
(
"service/chat/advice-ico.png"
);
background-image
:
url("/service/chat/advice-ico.png")
;
width
:
60px
;
height
:
60px
;
margin
:
30px
20px
;
}
.tel-ico
{
background-image
:
resolve
(
"service/chat/tel-ico.png"
);
background-image
:
url("/service/chat/tel-ico.png")
;
width
:
60px
;
height
:
60px
;
margin
:
30px
20px
;
}
.arr-ico
{
...
...
@@ -420,15 +429,24 @@
}
.gm-ico
{
background-image
:
resolve
(
"service/chat/gm-ico.png"
);
background-image
:
url("/service/chat/gm-ico.png")
;
width
:
60px
;
height
:
60px
;
margin
:
30px
20px
;
}
.advice-ico
{
background-image
:
resolve
(
"service/chat/advice-ico.png"
);
background-image
:
url("/service/chat/advice-ico.png")
;
width
:
60px
;
height
:
60px
;
margin
:
30px
20px
;
}
.tel-ico
{
background-image
:
resolve
(
"service/chat/tel-ico.png"
);
background-image
:
url("/service/chat/tel-ico.png")
;
width
:
60px
;
height
:
60px
;
margin
:
30px
20px
;
}
.arr-ico
{
...
...
public/scss/service/chat/_chat.css
View file @
5f71633
...
...
@@ -6,7 +6,7 @@
.input-method,
.menu-trigger
{
width
:
6
0px
;
width
:
10
0px
;
height
:
60px
;
background-repeat
:
no-repeat
;
background-size
:
60px
60px
;
...
...
@@ -33,12 +33,15 @@
height
:
70px
;
border
:
1
PX
solid
#e0e0e0
;
border-radius
:
8px
;
padding
:
16px
;
}
.menu-trigger
{
display
:
none
;
margin-left
:
20px
;
padding-left
:
20px
;
padding-right
:
20px
;
background-image
:
resolve
(
"service/chat/menu-trigger.png"
);
background-position
:
center
center
;
}
}
}
...
...
public/scss/service/chat/_layout.css
View file @
5f71633
html
,
body
{
height
:
100%
;
width
:
100%
;
}
.service-chat
{
/* -------------------------------- *\
atom, util
...
...
@@ -68,7 +73,7 @@
i
{
display
:
none
;
background
:
resolve
(
'
img/
service/chat/loading.gif'
)
no-repeat
;
background
:
resolve
(
'service/chat/loading.gif'
)
no-repeat
;
background-size
:
contain
;
width
:
20px
;
height
:
20px
;
...
...
@@ -131,6 +136,8 @@
.chat-rating-trigger
{
display
:
none
;
min-width
:
80px
;
text-align
:
right
;
}
/* 客服在线 */
...
...
@@ -147,4 +154,56 @@
display
:
inline-block
;
}
}
/* menu open*/
.menu-open
{
.menu
{
display
:
block
;
}
#chat-window
{
bottom
:
360px
;
}
#chat-send-box
{
padding-right
:
0
;
}
}
}
body
.app-ios
{
.nav-back
{
text-align
:
left
;
}
#chat-window
,
.connection-failed
,
.chat-page
{
margin-top
:
20
PX
;
}
.ios-gap
{
height
:
20
PX
;
}
}
body
.boys
,
.boys
.chat-header
{
background-color
:
#414141
!important
;
background-image
:
none
;
}
body
.girls
,
.girls
.chat-header
{
background-color
:
#ff88ae
!important
;
background-image
:
none
;
}
body
.kids
,
.kids
.chat-header
{
background-color
:
#7ad9f9
!important
;
background-image
:
none
;
}
body
.lifestyle
,
.lifestyle
.chat-header
{
background-color
:
#4f4138
!important
;
background-image
:
none
;
}
...
...
public/scss/service/chat/_message.css
View file @
5f71633
...
...
@@ -3,7 +3,6 @@
.head-icon
{
height
:
90px
;
width
:
90px
;
background
:
green
;
border-radius
:
50%
;
}
...
...
@@ -137,6 +136,7 @@
}
.msg-content
{
max-width
:
90%
;
margin
:
0
0
0
10px
;
background
:
#646464
;
color
:
#fff
;
...
...
public/scss/service/chat/_rating.css
View file @
5f71633
...
...
@@ -27,6 +27,8 @@
span
{
float
:
right
;
min-width
:
80px
;
text-align
:
right
;
}
}
...
...
@@ -63,6 +65,7 @@
height
:
110px
;
width
:
100%
;
margin
:
50px
0
0
;
padding
:
16px
;
resize
:
none
;
border
:
1px
solid
#e0e0e0
;
border-radius
:
5px
;
...
...
Please
register
or
login
to post a comment