Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
libai
/
guodong
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f08f72e3
authored
Mar 10, 2021
by
libai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
测试
parent
e92de3bf
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1368 additions
and
1 deletions
gzh/customer/guodong.html
gzh/customer/index.html
gzh/customer/naicha.html
gzh/customer/guodong.html
0 → 100644
View file @
f08f72e3
<!doctype html>
<html>
<head>
<meta
charset=
"utf-8"
>
<title>
客服聊天
</title>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
>
<meta
name=
"format-detection"
content=
"telephone=no"
>
<meta
name=
"apple-mobile-web-app-capable"
content=
"yes"
>
<meta
name=
"apple-mobile-web-app-status-bar-style"
content=
"black"
>
<script
src=
"http://libs.baidu.com/jquery/2.0.0/jquery.min.js"
></script>
<style>
html
,
body
{
width
:
100%
;
height
:
100%
;
margin
:
0
;
padding
:
0
;
}
input
[
type
=
"button"
],
button
{
-webkit-appearance
:
none
;
}
a
{
color
:
#428bca
;
text-decoration
:
none
;
}
.cs-box
{
width
:
100%
;
height
:
100%
;
margin
:
0
;
padding
:
0
;
display
:
flex
;
flex-direction
:
column
;
position
:
relative
;
overflow
:
hidden
;
}
.cs-box
h4
{
text-align
:
center
;
height
:
30px
;
line-height
:
30px
;
width
:
100%
;
background
:
#229ffd
;
color
:
rgb
(
255
,
255
,
255
);
margin
:
0
;
}
.cs-chat
{
overflow-y
:
auto
;
padding
:
10px
;
height
:
380px
;
word-wrap
:
break-word
;
background-color
:
#f3f5f7
;
flex
:
1
1
auto
;
}
.cs-submit
{
width
:
100%
;
background-color
:
gainsboro
;
flex
:
0
0
auto
;
display
:
flex
;
justify-content
:
space-around
;
padding
:
0.266667rem
;
position
:
relative
;
}
.txt
{
display
:
flex
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
border
:
1px
solid
#d7d7d7
;
border-radius
:
0.16rem
;
overflow
:
hidden
;
position
:
relative
;
background
:
#fcfafa
;
width
:
80%
;
}
.btn
{
display
:
flex
;
position
:
relative
;
}
.txt
.content
{
outline
:
none
;
border
:
none
;
background
:
none
;
width
:
95%
;
min-height
:
0.9rem
;
padding
:
0.266667rem
0
0.133333rem
0
;
line-height
:
0.9rem
;
white-space
:
pre-wrap
;
overflow-x
:
hidden
;
overflow-y
:
scroll
;
font-size
:
18px
;
resize
:
none
;
color
:
#353535
;
display
:
inline-block
;
}
.btn
input
{
padding
:
0.25rem
1rem
;
border-radius
:
5px
;
box-sizing
:
border-box
;
background-color
:
#428bca
;
color
:
#fff
;
text-align
:
center
;
vertical-align
:
middle
;
border
:
1px
solid
transparent
;
font-weight
:
500
;
margin-right
:
8px
;
outline
:
none
;
}
.txt
.uploadimg
{
width
:
2rem
;
height
:
1.9rem
;
margin
:
0.1rem
;
border-radius
:
10%
;
background
:
url(img/img.png)
no-repeat
;
background-size
:
contain
;
text-align
:
center
;
box-sizing
:
border-box
;
border
:
1px
solid
transparent
;
display
:
inline-block
;
background-color
:
#eee
;
}
.txt
.uploadimg
input
{
opacity
:
0
;
width
:
100%
;
height
:
100%
;
}
.chat-box
{
position
:
relative
;
width
:
100%
;
margin
:
5px
0
;
}
.info
{
display
:
inline-block
;
width
:
2.2rem
;
height
:
2.2rem
;
line-height
:
2.2rem
;
overflow
:
hidden
;
vertical-align
:
top
;
font-size
:
13px
;
background-color
:
#229ffd
;
border-radius
:
50%
;
text-align
:
center
;
color
:
#fff
;
padding
:
0.1rem
;
margin-right
:
6px
;
}
.chat-text
{
display
:
inline-block
;
vertical-align
:
top
;
position
:
relative
;
padding
:
0.4rem
0.3rem
;
max-width
:
80%
;
white-space
:
pre-wrap
;
border
:
1px
solid
#DEDEDE
;
background-color
:
#fff
;
border-radius
:
4px
;
box-sizing
:
border-box
;
color
:
#252525
;
}
.service
{
text-align
:
left
;
}
.custom
{
text-align
:
right
;
}
.custom
.chat-text
{
margin-right
:
6px
;
background-color
:
#A5DE37
;
color
:
#fff
;
}
.service-text
:before
{
content
:
''
;
position
:
absolute
;
top
:
50%
;
left
:
-4px
;
width
:
5px
;
height
:
5px
;
background
:
#fff
;
border-top
:
1px
solid
#DEDEDE
;
border-left
:
1px
solid
#DEDEDE
;
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
}
#custom
.chat-text
:after
{
content
:
''
;
position
:
absolute
;
top
:
50%
;
right
:
-10px
;
width
:
0
;
height
:
0
;
border-top
:
6px
solid
transparent
;
border-bottom
:
6px
solid
transparent
;
border-left
:
10px
solid
#A5DE37
;
-webkit-transform
:
translate
(
0
,
-50%
);
transform
:
translate
(
0
,
-50%
);
}
.copyright
{
width
:
100%
;
height
:
1rem
;
line-height
:
1rem
;
background-color
:
gainsboro
;
flex
:
0
0
auto
;
display
:
flex
;
position
:
relative
;
text-align
:
center
;
font-size
:
10px
;
color
:
#353535
;
}
.system
{
text-align
:
center
;
color
:
gray
;
font-size
:
13px
;
margin
:
10px
0
;
}
.funbtn
{
text-align
:
center
;
width
:
50%
;
height
:
1.5rem
;
line-height
:
1.5rem
;
font-size
:
15px
;
margin-left
:
25%
;
text-decoration
:
underline
;
color
:
#229ffd
;
}
.tips
{
position
:
absolute
;
width
:
100%
;
height
:
1.5rem
;
line-height
:
1.5rem
;
top
:
-1.5rem
;
left
:
0
;
font-size
:
12px
;
padding-left
:
0.4rem
;
}
.warn
{
background
:
rgba
(
254
,
174
,
27
,
0.8
);
color
:
#fff
;
}
.error
{
background
:
rgba
(
255
,
67
,
81
,
0.8
);
color
:
#fff
;
}
.normal
{
background
:
rgba
(
27
,
154
,
247
,
0.8
);
color
:
#fff
;
}
.des
{
background
:
rgb
(
81
,
206
,
255
);
color
:
#fff
;
}
</style>
</head>
<body>
<div
class=
"cs-box"
>
<h4>
客服聊天
<span
id=
"state"
></span></h4>
<div
id=
"cs-chat"
class=
"cs-chat"
>
<div
class=
"chat-box service"
id=
"help"
>
<div
class=
"info des"
>
系统
</div>
<span
class=
"chat-text service-text"
>
您好,有什么需要帮助的吗?
</span>
</div>
</div>
<div
class=
"cs-submit"
>
<div
class=
"txt"
>
<textarea
id=
"content"
class=
"content"
placeholder=
"请输入您的问题"
></textarea>
<div
class=
"uploadimg"
>
<input
accept=
"image/*"
type=
"file"
id=
"img"
onchange=
"uploadimg()"
/>
</div>
</div>
<div
class=
"btn"
>
<input
type=
"button"
value=
"发送"
id=
"send"
/>
</div>
<div
class=
"tips"
id=
"tips"
hidden=
"hidden"
></div>
</div>
<div
class=
"copyright"
>
</div>
<input
type=
"text"
hidden=
"hidden"
id=
"guestid"
>
</div>
<script>
var
server
=
"http://liveauth.ishuaji.cn"
;
var
cdn
=
"https://app.ixiulive.com/"
;
var
ws
;
var
checkTimer
;
var
sendtime
=
0
;
var
map
=
new
Map
();
$
(
function
(){
btninit
();
params
();
});
function
params
(){
// var url = window.location.search;
map
.
set
(
'ua'
,
window
.
navigator
.
userAgent
.
toLowerCase
());
map
.
set
(
'pkg'
,
'wechat'
);
map
.
set
(
'cid'
,
'wechat'
);
map
.
set
(
'gzh'
,
'guodong'
);
// if (url.indexOf("?") != -1) {
// var p = url.substr(1);
// keys = p.split("&");
// for (i = 0; i
<
keys
.
length
;
i
++
)
{
// map.set(keys[i].split("=")[0],keys[i].split("=")[1]);
// if("guestid"===keys[i].split("=")[0]){
// setCookie('cs-guestid',keys[i].split("=")[1],3);
// }
// }
// }
}
function
btninit
(){
$
(
"#send"
).
click
(
function
(){
sendmsg
();
});
$
(
"#img"
).
click
(
function
(){
var
guestid
=
$
(
"#guestid"
).
val
();
if
(
null
==
guestid
||
guestid
==
''
){
//连接客服
system
(
'正在转接客服,请稍等'
);
connect
(
false
);
}
});
}
function
sendmsg
(){
var
content
=
$
(
"#content"
).
val
();
if
(
null
==
content
||
content
==
''
){
tips
(
"不可以发送空消息"
,
"error"
,
5000
);
return
;
}
if
(
content
.
length
>
120
){
tips
(
"内容超过最大限制"
,
"warn"
,
5000
);
return
;
}
var
guestid
=
$
(
"#guestid"
).
val
();
if
(
null
==
guestid
||
guestid
==
''
){
//连接客服
system
(
'正在转接客服,请稍等'
);
connect
(
true
);
}
else
{
send
(
content
,
2001
)
}
}
function
connect
(
send
){
var
guestid
=
getCookie
(
'cs-guestid'
);
$
.
ajax
({
url
:
server
+
"/guest/service"
,
data
:{
guestid
:
guestid
},
dataType
:
"json"
,
type
:
"POST"
,
success
:
function
(
data
){
if
(
data
.
code
==
1
){
guestid
=
data
.
guestid
;
$
(
"#guestid"
).
val
(
guestid
);
setCookie
(
'cs-guestid'
,
guestid
,
3
)
var
list
=
data
.
history
;
if
(
list
!=
null
&&
list
.
length
>
0
&&
sendtime
==
0
){
$
(
"#help"
).
remove
();
$
.
each
(
list
,
function
(
i
,
msg
){
historybulid
(
msg
.
mtype
,
msg
.
content
,
msg
.
fid
,
msg
.
mid
);
if
(
i
==
list
.
length
-
1
){
system
(
'---上次聊到这里('
+
msg
.
sendtime
+
')---'
);
$
(
"#cs-chat"
).
append
(
'
<
div
class
=
"system"
>---------------<
/div>'
)
;
}
});
}
if
(
data
.
more
){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"funbtn"
onclick
=
"more()"
>
更早的聊天记录
<
/div>'
)
;
}
WebSocketStart
(
guestid
,
send
);
}
else
{
system
(
"连接失败("
+
data
.
code
+
")"
);
}
},
error
:
function
(){
system
(
"网络异常"
);
}
});
}
function
more
(){
var
guestid
=
$
(
"#guestid"
).
val
();
var
index
=
$
(
"#cs-chat"
).
children
(
".chat-box"
).
eq
(
0
).
attr
(
"data-mid"
);
$
.
ajax
({
url
:
server
+
"/guest/chathistory"
,
data
:{
guestid
:
guestid
,
index
:
index
},
dataType
:
"json"
,
type
:
"POST"
,
success
:
function
(
data
){
if
(
data
.
code
==
1
){
$
(
"#cs-chat"
).
find
(
".funbtn"
).
remove
();
var
list
=
data
.
history
;
if
(
list
.
length
>
0
){
$
.
each
(
list
,
function
(
i
,
msg
){
historybulid
(
msg
.
mtype
,
msg
.
content
,
msg
.
fid
,
msg
.
mid
);
if
(
i
==
list
.
length
-
1
){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"funbtn"
onclick
=
"more()"
>
更早的聊天记录
<
/div>'
)
;
}
if
(
i
==
0
){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
'+msg.sendtime+'
<
/div>'
)
;
}
});
}
else
{
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
哦豁,没有了
<
/div>'
)
;
}
}
else
{
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
获取失败
(
'+data.code+'
)
<
/div>'
)
;
}
},
error
:
function
(){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
服务出错
<
/div>'
)
;
}
});
}
function
system
(
msg
){
var
sysmsg
=
'
<
div
class
=
"system"
>
'+msg+'
<
/div>'
;
var
cname
=
$
(
"#cs-chat"
).
children
(
"div:last-child"
).
attr
(
"class"
);
if
(
cname
==
'system'
){
$
(
"#cs-chat"
).
children
(
"div:last-child"
).
text
(
msg
);
}
else
{
var
chat
=
$
(
"#cs-chat"
);
chat
.
append
(
sysmsg
);
var
offset
=
chat
[
0
].
scrollHeight
-
chat
[
0
].
clientHeight
;
if
(
offset
-
chat
[
0
].
scrollTop
<
(
chat
[
0
].
clientHeight
/
2
)){
chat
.
animate
({
scrollTop
:
chat
.
scrollHeight
},
500
);
}
else
{
tips
(
"有新的系统消息"
,
"normal"
,
3000
);
}
}
}
function
state
(
msg
){
$
(
"#state"
).
text
(
"("
+
msg
+
")"
);
}
function
tips
(
msg
,
type
,
time
){
if
(
time
>
0
){
$
(
"#tips"
).
removeClass
(
"error warn normal"
).
addClass
(
type
).
text
(
msg
).
show
().
delay
(
time
).
hide
(
300
);
}
else
{
$
(
"#tips"
).
removeClass
(
"error warn normal"
).
addClass
(
type
).
text
(
msg
).
show
();
}
}
function
removetips
(){
$
(
"#tips"
).
hide
();
}
function
msgbulid
(
type
,
msg
,
kf
,
fid
){
var
content
=
""
;
var
size
=
200
;
if
(
fid
>
0
){
if
(
fid
==
1
){
content
+=
'
<
div
class
=
"chat-box service"
><
div
class
=
"info des"
>
'+kf+'
<
/div><span class="chat-text service-text">'
;
}
else
{
content
+=
'
<
div
class
=
"chat-box service"
><
div
class
=
"info"
>
'+kf+'
<
/div><span class="chat-text service-text">'
;
}
}
else
{
content
+=
'
<
div
class
=
"chat-box custom"
><
span
class
=
"chat-text "
>
';
}
if(type==1){
content+=msg+'
<
/span></
div
>
';
}else{
if(fid>0){
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
p_95
';
}else{
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
l_
'+size+'
,
m_mfit
';
}
content+='
<
img
width
=
"200px"
src
=
"'+cdn+msg+'"
><
/span></
div
>
'
;
}
var
chat
=
$
(
"#cs-chat"
);
chat
.
append
(
content
);
var
offset
=
chat
[
0
].
scrollHeight
-
chat
[
0
].
clientHeight
;
if
(
offset
-
chat
[
0
].
scrollTop
<
(
chat
[
0
].
clientHeight
/
2
)){
chat
.
animate
({
scrollTop
:
chat
.
scrollHeight
},
1000
);
}
else
{
if
(
fid
>
0
){
tips
(
"收到一条新消息"
,
"normal"
,
3000
);
}
}
if
(
type
==
2
){
system
(
'长按图片即可放大或保存到手机查看'
);
}
}
function
historybulid
(
type
,
msg
,
fid
,
mid
){
var
content
=
""
;
var
size
=
200
;
if
(
fid
>
0
){
content
+=
'
<
div
class
=
"chat-box service"
data
-
mid
=
"'+mid+'"
><
div
class
=
"info des"
>
客服
<
/div><span class="chat-text service-text">'
;
}
else
{
content
+=
'
<
div
class
=
"chat-box custom"
data
-
mid
=
"'+mid+'"
><
span
class
=
"chat-text "
>
';
}
if(type==1){
content+=msg+'
<
/span></
div
>
';
}else{
if(fid>0){
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
p_95
';
}else{
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
l_
'+size+'
,
m_mfit
';
}
content+='
<
img
width
=
"200px"
src
=
"'+cdn+msg+'"
><
/span></
div
>
';
}
$("#cs-chat").prepend(content);
}
function WebSocketStart(guestid,send) {
state("连接中");
if(ws!=null&&ws.readyState == WebSocket.OPEN){
system("The socket is opening,please close first!");
return;
}
if ("WebSocket" in window)
{
// 打开一个 web socket
var url="ws://118.178.112.116:21901/ws?guestid="+guestid+"&type=5";
try {
ws = new WebSocket(url);
}catch(err){
console.error("WebSocket connect error:", err);
system("连接失败");
}
ws.onopen = function()
{
state("连接成功");
system("客服已接入");
if(send){
sendmsg();
}
checkTimer=setInterval("check()",60000);
};
ws.onmessage = function (evt)
{
var msg=JSON.parse(evt.data);
if(msg.uid!='
0
'
){
msgbulid
(
msg
.
mtype
,
msg
.
content
,
msg
.
kfName
,
msg
.
fid
);
sendtime
=
new
Date
().
getTime
();
}
};
ws
.
onclose
=
function
(
event
)
{
state
(
"连接断开"
);
console
.
error
(
"WebSocket close observed:"
,
event
);
};
ws
.
onerror
=
function
(
event
)
{
// 关闭 websocket
state
(
"连接错误"
);
msgbulid
(
1
,
"会话意外断开,发送消息即可联系客服"
,
"系统"
,
1
);
console
.
error
(
"WebSocket error observed:"
,
event
);
};
}
else
{
// 浏览器不支持 WebSocket
state
(
"不支持"
);
}
}
function
check
(){
if
(
sendtime
>
0
){
var
min
=
3
;
var
cut
=
2
;
var
time
=
new
Date
().
getTime
()
-
sendtime
;
if
(
time
>
1000
*
60
*
min
&&
time
<
1000
*
60
*
min
+
1
){
var
index
=
$
(
".chat-box"
).
last
().
attr
(
"class"
).
indexOf
(
"service"
);
if
(
index
>-
1
){
msgbulid
(
1
,
"客服还没有等到您的回复,系统将在"
+
cut
+
"分钟后关闭会话"
,
"系统"
,
1
);
}
}
if
(
new
Date
().
getTime
()
-
sendtime
>
1000
*
60
*
(
min
+
cut
)){
var
index
=
$
(
".chat-box"
).
last
().
attr
(
"class"
).
indexOf
(
"service"
);
if
(
index
>-
1
){
msgbulid
(
1
,
"因您长时间未回复,本次会话已经中止,如果还有问题需要咨询,请直接发送消息"
,
"系统"
,
1
);
checkTimer
=
null
;
sendtime
=-
1
;
$
(
"#guestid"
).
val
(
''
);
ws
.
close
();
}
}
}
}
function
send
(
message
,
cid
)
{
if
(
!
window
.
WebSocket
)
{
return
;
}
if
(
ws
.
readyState
==
WebSocket
.
OPEN
)
{
var
guestid
=
$
(
"#guestid"
).
val
();
map
.
set
(
"guestid"
,
guestid
);
var
msg
=
new
WsMsg
(
cid
,
message
,
JSON
.
stringify
(
mapToObj
(
map
)));
ws
.
send
(
JSON
.
stringify
(
msg
));
if
(
cid
==
2001
){
msgbulid
(
1
,
message
,
''
,
0
)
}
else
{
msgbulid
(
2
,
message
,
''
,
0
)
}
$
(
"#content"
).
val
(
''
);
sendtime
=
new
Date
().
getTime
();
}
else
{
tips
(
"连接已断开"
,
"error"
,
3000
);
state
(
"连接断开"
);
}
}
function
mapToObj
(
strMap
){
let
obj
=
Object
.
create
(
null
);
for
(
let
[
k
,
v
]
of
strMap
)
{
obj
[
k
]
=
v
;
}
return
obj
;
}
function
WsMsg
(
cid
,
content
,
extend
)
{
this
.
time
=
new
Date
().
getTime
();
this
.
msgid
=
Math
.
random
().
toString
(
36
).
slice
(
-
8
);
this
.
cid
=
cid
;
this
.
content
=
content
;
this
.
extend
=
extend
;
this
.
toUid
=
2000
;
}
function
uploadimg
(){
var
file
=
$
(
"#img"
)[
0
].
files
;
if
(
file
.
length
<
1
){
return
;
}
if
(
file
.
length
>
1
){
tips
(
"每次只可选择一个图片"
,
"error"
,
3000
);
return
;
}
if
(
file
[
0
].
size
>
10485760
){
tips
(
"超过限制,最大支持10M的图片"
,
"error"
,
5000
);
return
;
}
var
guestid
=
$
(
"#guestid"
).
val
();
var
formdata
=
new
FormData
();
formdata
.
append
(
"img"
,
file
[
0
]);
formdata
.
append
(
"guestid"
,
guestid
);
var
url
=
server
+
"/guest/upload/img"
;
var
xhr
=
new
XMLHttpRequest
();
xhr
.
upload
.
addEventListener
(
"progress"
,
uploadProgress
,
false
);
xhr
.
open
(
"post"
,
url
,
true
);
xhr
.
onload
=
function
()
{
var
result
=
xhr
.
responseText
;
var
json
=
eval
(
"("
+
result
+
")"
);
switch
(
json
.
code
)
{
case
1
:
// var path=cdn+;
send
(
json
.
imgkey
,
2002
);
$
(
"#img"
).
val
(
''
);
break
;
default
:
system
(
json
.
msg
);
$
(
"#img"
).
val
(
''
);
break
;
}
};
xhr
.
send
(
formdata
);
}
function
uploadProgress
(
evt
)
{
if
(
evt
.
lengthComputable
)
{
var
percentComplete
=
Math
.
round
(
evt
.
loaded
*
100
/
evt
.
total
);
tips
(
"上传中("
+
percentComplete
+
"%)"
,
"normal"
);
if
(
percentComplete
==
100
){
tips
(
"上传完成"
,
"normal"
,
3000
);
}
}
else
{
tips
(
"上传失败"
,
"error"
,
3000
);
}
}
function
setCookie
(
cname
,
cvalue
,
exdays
)
{
var
d
=
new
Date
();
d
.
setTime
(
d
.
getTime
()
+
(
exdays
*
24
*
60
*
60
*
1000
));
var
expires
=
"expires="
+
d
.
toUTCString
();
document
.
cookie
=
cname
+
"="
+
cvalue
+
"; "
+
expires
;
}
function
getCookie
(
cname
)
{
var
name
=
cname
+
"="
;
var
ca
=
document
.
cookie
.
split
(
';'
);
for
(
var
i
=
0
;
i
<
ca
.
length
;
i
++
)
{
var
c
=
ca
[
i
];
while
(
c
.
charAt
(
0
)
==
' '
)
c
=
c
.
substring
(
1
);
if
(
c
.
indexOf
(
name
)
!=
-
1
)
return
c
.
substring
(
name
.
length
,
c
.
length
);
}
return
""
;
}
function
clearCookie
(
name
)
{
setCookie
(
name
,
""
,
-
1
);
}
</script>
</body>
</html>
\ No newline at end of file
gzh/customer/index.html
View file @
f08f72e3
...
@@ -287,7 +287,10 @@
...
@@ -287,7 +287,10 @@
});
});
function
params
(){
function
params
(){
var
url
=
window
.
location
.
search
;
var
url
=
window
.
location
.
search
;
// map.set('ua',window.navigator.userAgent.toLowerCase());
map
.
set
(
'ua'
,
window
.
navigator
.
userAgent
.
toLowerCase
());
// map.set('pkg','wechat');
// map.set('cid','wechat');
// map.set('gzh','naicha');
if
(
url
.
indexOf
(
"?"
)
!=
-
1
)
{
if
(
url
.
indexOf
(
"?"
)
!=
-
1
)
{
var
p
=
url
.
substr
(
1
);
var
p
=
url
.
substr
(
1
);
keys
=
p
.
split
(
"&"
);
keys
=
p
.
split
(
"&"
);
...
...
gzh/customer/naicha.html
0 → 100644
View file @
f08f72e3
<!doctype html>
<html>
<head>
<meta
charset=
"utf-8"
>
<title>
客服聊天
</title>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
>
<meta
name=
"format-detection"
content=
"telephone=no"
>
<meta
name=
"apple-mobile-web-app-capable"
content=
"yes"
>
<meta
name=
"apple-mobile-web-app-status-bar-style"
content=
"black"
>
<script
src=
"http://libs.baidu.com/jquery/2.0.0/jquery.min.js"
></script>
<style>
html
,
body
{
width
:
100%
;
height
:
100%
;
margin
:
0
;
padding
:
0
;
}
input
[
type
=
"button"
],
button
{
-webkit-appearance
:
none
;
}
a
{
color
:
#428bca
;
text-decoration
:
none
;
}
.cs-box
{
width
:
100%
;
height
:
100%
;
margin
:
0
;
padding
:
0
;
display
:
flex
;
flex-direction
:
column
;
position
:
relative
;
overflow
:
hidden
;
}
.cs-box
h4
{
text-align
:
center
;
height
:
30px
;
line-height
:
30px
;
width
:
100%
;
background
:
#229ffd
;
color
:
rgb
(
255
,
255
,
255
);
margin
:
0
;
}
.cs-chat
{
overflow-y
:
auto
;
padding
:
10px
;
height
:
380px
;
word-wrap
:
break-word
;
background-color
:
#f3f5f7
;
flex
:
1
1
auto
;
}
.cs-submit
{
width
:
100%
;
background-color
:
gainsboro
;
flex
:
0
0
auto
;
display
:
flex
;
justify-content
:
space-around
;
padding
:
0.266667rem
;
position
:
relative
;
}
.txt
{
display
:
flex
;
-webkit-box-sizing
:
border-box
;
box-sizing
:
border-box
;
border
:
1px
solid
#d7d7d7
;
border-radius
:
0.16rem
;
overflow
:
hidden
;
position
:
relative
;
background
:
#fcfafa
;
width
:
80%
;
}
.btn
{
display
:
flex
;
position
:
relative
;
}
.txt
.content
{
outline
:
none
;
border
:
none
;
background
:
none
;
width
:
95%
;
min-height
:
0.9rem
;
padding
:
0.266667rem
0
0.133333rem
0
;
line-height
:
0.9rem
;
white-space
:
pre-wrap
;
overflow-x
:
hidden
;
overflow-y
:
scroll
;
font-size
:
18px
;
resize
:
none
;
color
:
#353535
;
display
:
inline-block
;
}
.btn
input
{
padding
:
0.25rem
1rem
;
border-radius
:
5px
;
box-sizing
:
border-box
;
background-color
:
#428bca
;
color
:
#fff
;
text-align
:
center
;
vertical-align
:
middle
;
border
:
1px
solid
transparent
;
font-weight
:
500
;
margin-right
:
8px
;
outline
:
none
;
}
.txt
.uploadimg
{
width
:
2rem
;
height
:
1.9rem
;
margin
:
0.1rem
;
border-radius
:
10%
;
background
:
url(img/img.png)
no-repeat
;
background-size
:
contain
;
text-align
:
center
;
box-sizing
:
border-box
;
border
:
1px
solid
transparent
;
display
:
inline-block
;
background-color
:
#eee
;
}
.txt
.uploadimg
input
{
opacity
:
0
;
width
:
100%
;
height
:
100%
;
}
.chat-box
{
position
:
relative
;
width
:
100%
;
margin
:
5px
0
;
}
.info
{
display
:
inline-block
;
width
:
2.2rem
;
height
:
2.2rem
;
line-height
:
2.2rem
;
overflow
:
hidden
;
vertical-align
:
top
;
font-size
:
13px
;
background-color
:
#229ffd
;
border-radius
:
50%
;
text-align
:
center
;
color
:
#fff
;
padding
:
0.1rem
;
margin-right
:
6px
;
}
.chat-text
{
display
:
inline-block
;
vertical-align
:
top
;
position
:
relative
;
padding
:
0.4rem
0.3rem
;
max-width
:
80%
;
white-space
:
pre-wrap
;
border
:
1px
solid
#DEDEDE
;
background-color
:
#fff
;
border-radius
:
4px
;
box-sizing
:
border-box
;
color
:
#252525
;
}
.service
{
text-align
:
left
;
}
.custom
{
text-align
:
right
;
}
.custom
.chat-text
{
margin-right
:
6px
;
background-color
:
#A5DE37
;
color
:
#fff
;
}
.service-text
:before
{
content
:
''
;
position
:
absolute
;
top
:
50%
;
left
:
-4px
;
width
:
5px
;
height
:
5px
;
background
:
#fff
;
border-top
:
1px
solid
#DEDEDE
;
border-left
:
1px
solid
#DEDEDE
;
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
}
#custom
.chat-text
:after
{
content
:
''
;
position
:
absolute
;
top
:
50%
;
right
:
-10px
;
width
:
0
;
height
:
0
;
border-top
:
6px
solid
transparent
;
border-bottom
:
6px
solid
transparent
;
border-left
:
10px
solid
#A5DE37
;
-webkit-transform
:
translate
(
0
,
-50%
);
transform
:
translate
(
0
,
-50%
);
}
.copyright
{
width
:
100%
;
height
:
1rem
;
line-height
:
1rem
;
background-color
:
gainsboro
;
flex
:
0
0
auto
;
display
:
flex
;
position
:
relative
;
text-align
:
center
;
font-size
:
10px
;
color
:
#353535
;
}
.system
{
text-align
:
center
;
color
:
gray
;
font-size
:
13px
;
margin
:
10px
0
;
}
.funbtn
{
text-align
:
center
;
width
:
50%
;
height
:
1.5rem
;
line-height
:
1.5rem
;
font-size
:
15px
;
margin-left
:
25%
;
text-decoration
:
underline
;
color
:
#229ffd
;
}
.tips
{
position
:
absolute
;
width
:
100%
;
height
:
1.5rem
;
line-height
:
1.5rem
;
top
:
-1.5rem
;
left
:
0
;
font-size
:
12px
;
padding-left
:
0.4rem
;
}
.warn
{
background
:
rgba
(
254
,
174
,
27
,
0.8
);
color
:
#fff
;
}
.error
{
background
:
rgba
(
255
,
67
,
81
,
0.8
);
color
:
#fff
;
}
.normal
{
background
:
rgba
(
27
,
154
,
247
,
0.8
);
color
:
#fff
;
}
.des
{
background
:
rgb
(
81
,
206
,
255
);
color
:
#fff
;
}
</style>
</head>
<body>
<div
class=
"cs-box"
>
<h4>
客服聊天
<span
id=
"state"
></span></h4>
<div
id=
"cs-chat"
class=
"cs-chat"
>
<div
class=
"chat-box service"
id=
"help"
>
<div
class=
"info des"
>
系统
</div>
<span
class=
"chat-text service-text"
>
您好,有什么需要帮助的吗?
</span>
</div>
</div>
<div
class=
"cs-submit"
>
<div
class=
"txt"
>
<textarea
id=
"content"
class=
"content"
placeholder=
"请输入您的问题"
></textarea>
<div
class=
"uploadimg"
>
<input
accept=
"image/*"
type=
"file"
id=
"img"
onchange=
"uploadimg()"
/>
</div>
</div>
<div
class=
"btn"
>
<input
type=
"button"
value=
"发送"
id=
"send"
/>
</div>
<div
class=
"tips"
id=
"tips"
hidden=
"hidden"
></div>
</div>
<div
class=
"copyright"
>
</div>
<input
type=
"text"
hidden=
"hidden"
id=
"guestid"
>
</div>
<script>
var
server
=
"http://liveauth.ishuaji.cn"
;
var
cdn
=
"https://app.ixiulive.com/"
;
var
ws
;
var
checkTimer
;
var
sendtime
=
0
;
var
map
=
new
Map
();
$
(
function
(){
btninit
();
params
();
});
function
params
(){
// var url = window.location.search;
map
.
set
(
'ua'
,
window
.
navigator
.
userAgent
.
toLowerCase
());
map
.
set
(
'pkg'
,
'wechat'
);
map
.
set
(
'cid'
,
'wechat'
);
map
.
set
(
'gzh'
,
'naicha'
);
// if (url.indexOf("?") != -1) {
// var p = url.substr(1);
// keys = p.split("&");
// for (i = 0; i
<
keys
.
length
;
i
++
)
{
// map.set(keys[i].split("=")[0],keys[i].split("=")[1]);
// if("guestid"===keys[i].split("=")[0]){
// setCookie('cs-guestid',keys[i].split("=")[1],3);
// }
// }
// }
}
function
btninit
(){
$
(
"#send"
).
click
(
function
(){
sendmsg
();
});
$
(
"#img"
).
click
(
function
(){
var
guestid
=
$
(
"#guestid"
).
val
();
if
(
null
==
guestid
||
guestid
==
''
){
//连接客服
system
(
'正在转接客服,请稍等'
);
connect
(
false
);
}
});
}
function
sendmsg
(){
var
content
=
$
(
"#content"
).
val
();
if
(
null
==
content
||
content
==
''
){
tips
(
"不可以发送空消息"
,
"error"
,
5000
);
return
;
}
if
(
content
.
length
>
120
){
tips
(
"内容超过最大限制"
,
"warn"
,
5000
);
return
;
}
var
guestid
=
$
(
"#guestid"
).
val
();
if
(
null
==
guestid
||
guestid
==
''
){
//连接客服
system
(
'正在转接客服,请稍等'
);
connect
(
true
);
}
else
{
send
(
content
,
2001
)
}
}
function
connect
(
send
){
var
guestid
=
getCookie
(
'cs-guestid'
);
$
.
ajax
({
url
:
server
+
"/guest/service"
,
data
:{
guestid
:
guestid
},
dataType
:
"json"
,
type
:
"POST"
,
success
:
function
(
data
){
if
(
data
.
code
==
1
){
guestid
=
data
.
guestid
;
$
(
"#guestid"
).
val
(
guestid
);
setCookie
(
'cs-guestid'
,
guestid
,
3
)
var
list
=
data
.
history
;
if
(
list
!=
null
&&
list
.
length
>
0
&&
sendtime
==
0
){
$
(
"#help"
).
remove
();
$
.
each
(
list
,
function
(
i
,
msg
){
historybulid
(
msg
.
mtype
,
msg
.
content
,
msg
.
fid
,
msg
.
mid
);
if
(
i
==
list
.
length
-
1
){
system
(
'---上次聊到这里('
+
msg
.
sendtime
+
')---'
);
$
(
"#cs-chat"
).
append
(
'
<
div
class
=
"system"
>---------------<
/div>'
)
;
}
});
}
if
(
data
.
more
){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"funbtn"
onclick
=
"more()"
>
更早的聊天记录
<
/div>'
)
;
}
WebSocketStart
(
guestid
,
send
);
}
else
{
system
(
"连接失败("
+
data
.
code
+
")"
);
}
},
error
:
function
(){
system
(
"网络异常"
);
}
});
}
function
more
(){
var
guestid
=
$
(
"#guestid"
).
val
();
var
index
=
$
(
"#cs-chat"
).
children
(
".chat-box"
).
eq
(
0
).
attr
(
"data-mid"
);
$
.
ajax
({
url
:
server
+
"/guest/chathistory"
,
data
:{
guestid
:
guestid
,
index
:
index
},
dataType
:
"json"
,
type
:
"POST"
,
success
:
function
(
data
){
if
(
data
.
code
==
1
){
$
(
"#cs-chat"
).
find
(
".funbtn"
).
remove
();
var
list
=
data
.
history
;
if
(
list
.
length
>
0
){
$
.
each
(
list
,
function
(
i
,
msg
){
historybulid
(
msg
.
mtype
,
msg
.
content
,
msg
.
fid
,
msg
.
mid
);
if
(
i
==
list
.
length
-
1
){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"funbtn"
onclick
=
"more()"
>
更早的聊天记录
<
/div>'
)
;
}
if
(
i
==
0
){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
'+msg.sendtime+'
<
/div>'
)
;
}
});
}
else
{
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
哦豁,没有了
<
/div>'
)
;
}
}
else
{
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
获取失败
(
'+data.code+'
)
<
/div>'
)
;
}
},
error
:
function
(){
$
(
"#cs-chat"
).
prepend
(
'
<
div
class
=
"system"
>
服务出错
<
/div>'
)
;
}
});
}
function
system
(
msg
){
var
sysmsg
=
'
<
div
class
=
"system"
>
'+msg+'
<
/div>'
;
var
cname
=
$
(
"#cs-chat"
).
children
(
"div:last-child"
).
attr
(
"class"
);
if
(
cname
==
'system'
){
$
(
"#cs-chat"
).
children
(
"div:last-child"
).
text
(
msg
);
}
else
{
var
chat
=
$
(
"#cs-chat"
);
chat
.
append
(
sysmsg
);
var
offset
=
chat
[
0
].
scrollHeight
-
chat
[
0
].
clientHeight
;
if
(
offset
-
chat
[
0
].
scrollTop
<
(
chat
[
0
].
clientHeight
/
2
)){
chat
.
animate
({
scrollTop
:
chat
.
scrollHeight
},
500
);
}
else
{
tips
(
"有新的系统消息"
,
"normal"
,
3000
);
}
}
}
function
state
(
msg
){
$
(
"#state"
).
text
(
"("
+
msg
+
")"
);
}
function
tips
(
msg
,
type
,
time
){
if
(
time
>
0
){
$
(
"#tips"
).
removeClass
(
"error warn normal"
).
addClass
(
type
).
text
(
msg
).
show
().
delay
(
time
).
hide
(
300
);
}
else
{
$
(
"#tips"
).
removeClass
(
"error warn normal"
).
addClass
(
type
).
text
(
msg
).
show
();
}
}
function
removetips
(){
$
(
"#tips"
).
hide
();
}
function
msgbulid
(
type
,
msg
,
kf
,
fid
){
var
content
=
""
;
var
size
=
200
;
if
(
fid
>
0
){
if
(
fid
==
1
){
content
+=
'
<
div
class
=
"chat-box service"
><
div
class
=
"info des"
>
'+kf+'
<
/div><span class="chat-text service-text">'
;
}
else
{
content
+=
'
<
div
class
=
"chat-box service"
><
div
class
=
"info"
>
'+kf+'
<
/div><span class="chat-text service-text">'
;
}
}
else
{
content
+=
'
<
div
class
=
"chat-box custom"
><
span
class
=
"chat-text "
>
';
}
if(type==1){
content+=msg+'
<
/span></
div
>
';
}else{
if(fid>0){
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
p_95
';
}else{
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
l_
'+size+'
,
m_mfit
';
}
content+='
<
img
width
=
"200px"
src
=
"'+cdn+msg+'"
><
/span></
div
>
'
;
}
var
chat
=
$
(
"#cs-chat"
);
chat
.
append
(
content
);
var
offset
=
chat
[
0
].
scrollHeight
-
chat
[
0
].
clientHeight
;
if
(
offset
-
chat
[
0
].
scrollTop
<
(
chat
[
0
].
clientHeight
/
2
)){
chat
.
animate
({
scrollTop
:
chat
.
scrollHeight
},
1000
);
}
else
{
if
(
fid
>
0
){
tips
(
"收到一条新消息"
,
"normal"
,
3000
);
}
}
if
(
type
==
2
){
system
(
'长按图片即可放大或保存到手机查看'
);
}
}
function
historybulid
(
type
,
msg
,
fid
,
mid
){
var
content
=
""
;
var
size
=
200
;
if
(
fid
>
0
){
content
+=
'
<
div
class
=
"chat-box service"
data
-
mid
=
"'+mid+'"
><
div
class
=
"info des"
>
客服
<
/div><span class="chat-text service-text">'
;
}
else
{
content
+=
'
<
div
class
=
"chat-box custom"
data
-
mid
=
"'+mid+'"
><
span
class
=
"chat-text "
>
';
}
if(type==1){
content+=msg+'
<
/span></
div
>
';
}else{
if(fid>0){
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
p_95
';
}else{
msg+='
?
x
-
oss
-
process
=
image
/
resize
,
l_
'+size+'
,
m_mfit
';
}
content+='
<
img
width
=
"200px"
src
=
"'+cdn+msg+'"
><
/span></
div
>
';
}
$("#cs-chat").prepend(content);
}
function WebSocketStart(guestid,send) {
state("连接中");
if(ws!=null&&ws.readyState == WebSocket.OPEN){
system("The socket is opening,please close first!");
return;
}
if ("WebSocket" in window)
{
// 打开一个 web socket
var url="ws://118.178.112.116:21901/ws?guestid="+guestid+"&type=5";
try {
ws = new WebSocket(url);
}catch(err){
console.error("WebSocket connect error:", err);
system("连接失败");
}
ws.onopen = function()
{
state("连接成功");
system("客服已接入");
if(send){
sendmsg();
}
checkTimer=setInterval("check()",60000);
};
ws.onmessage = function (evt)
{
var msg=JSON.parse(evt.data);
if(msg.uid!='
0
'
){
msgbulid
(
msg
.
mtype
,
msg
.
content
,
msg
.
kfName
,
msg
.
fid
);
sendtime
=
new
Date
().
getTime
();
}
};
ws
.
onclose
=
function
(
event
)
{
state
(
"连接断开"
);
console
.
error
(
"WebSocket close observed:"
,
event
);
};
ws
.
onerror
=
function
(
event
)
{
// 关闭 websocket
state
(
"连接错误"
);
msgbulid
(
1
,
"会话意外断开,发送消息即可联系客服"
,
"系统"
,
1
);
console
.
error
(
"WebSocket error observed:"
,
event
);
};
}
else
{
// 浏览器不支持 WebSocket
state
(
"不支持"
);
}
}
function
check
(){
if
(
sendtime
>
0
){
var
min
=
3
;
var
cut
=
2
;
var
time
=
new
Date
().
getTime
()
-
sendtime
;
if
(
time
>
1000
*
60
*
min
&&
time
<
1000
*
60
*
min
+
1
){
var
index
=
$
(
".chat-box"
).
last
().
attr
(
"class"
).
indexOf
(
"service"
);
if
(
index
>-
1
){
msgbulid
(
1
,
"客服还没有等到您的回复,系统将在"
+
cut
+
"分钟后关闭会话"
,
"系统"
,
1
);
}
}
if
(
new
Date
().
getTime
()
-
sendtime
>
1000
*
60
*
(
min
+
cut
)){
var
index
=
$
(
".chat-box"
).
last
().
attr
(
"class"
).
indexOf
(
"service"
);
if
(
index
>-
1
){
msgbulid
(
1
,
"因您长时间未回复,本次会话已经中止,如果还有问题需要咨询,请直接发送消息"
,
"系统"
,
1
);
checkTimer
=
null
;
sendtime
=-
1
;
$
(
"#guestid"
).
val
(
''
);
ws
.
close
();
}
}
}
}
function
send
(
message
,
cid
)
{
if
(
!
window
.
WebSocket
)
{
return
;
}
if
(
ws
.
readyState
==
WebSocket
.
OPEN
)
{
var
guestid
=
$
(
"#guestid"
).
val
();
map
.
set
(
"guestid"
,
guestid
);
var
msg
=
new
WsMsg
(
cid
,
message
,
JSON
.
stringify
(
mapToObj
(
map
)));
ws
.
send
(
JSON
.
stringify
(
msg
));
if
(
cid
==
2001
){
msgbulid
(
1
,
message
,
''
,
0
)
}
else
{
msgbulid
(
2
,
message
,
''
,
0
)
}
$
(
"#content"
).
val
(
''
);
sendtime
=
new
Date
().
getTime
();
}
else
{
tips
(
"连接已断开"
,
"error"
,
3000
);
state
(
"连接断开"
);
}
}
function
mapToObj
(
strMap
){
let
obj
=
Object
.
create
(
null
);
for
(
let
[
k
,
v
]
of
strMap
)
{
obj
[
k
]
=
v
;
}
return
obj
;
}
function
WsMsg
(
cid
,
content
,
extend
)
{
this
.
time
=
new
Date
().
getTime
();
this
.
msgid
=
Math
.
random
().
toString
(
36
).
slice
(
-
8
);
this
.
cid
=
cid
;
this
.
content
=
content
;
this
.
extend
=
extend
;
this
.
toUid
=
2000
;
}
function
uploadimg
(){
var
file
=
$
(
"#img"
)[
0
].
files
;
if
(
file
.
length
<
1
){
return
;
}
if
(
file
.
length
>
1
){
tips
(
"每次只可选择一个图片"
,
"error"
,
3000
);
return
;
}
if
(
file
[
0
].
size
>
10485760
){
tips
(
"超过限制,最大支持10M的图片"
,
"error"
,
5000
);
return
;
}
var
guestid
=
$
(
"#guestid"
).
val
();
var
formdata
=
new
FormData
();
formdata
.
append
(
"img"
,
file
[
0
]);
formdata
.
append
(
"guestid"
,
guestid
);
var
url
=
server
+
"/guest/upload/img"
;
var
xhr
=
new
XMLHttpRequest
();
xhr
.
upload
.
addEventListener
(
"progress"
,
uploadProgress
,
false
);
xhr
.
open
(
"post"
,
url
,
true
);
xhr
.
onload
=
function
()
{
var
result
=
xhr
.
responseText
;
var
json
=
eval
(
"("
+
result
+
")"
);
switch
(
json
.
code
)
{
case
1
:
// var path=cdn+;
send
(
json
.
imgkey
,
2002
);
$
(
"#img"
).
val
(
''
);
break
;
default
:
system
(
json
.
msg
);
$
(
"#img"
).
val
(
''
);
break
;
}
};
xhr
.
send
(
formdata
);
}
function
uploadProgress
(
evt
)
{
if
(
evt
.
lengthComputable
)
{
var
percentComplete
=
Math
.
round
(
evt
.
loaded
*
100
/
evt
.
total
);
tips
(
"上传中("
+
percentComplete
+
"%)"
,
"normal"
);
if
(
percentComplete
==
100
){
tips
(
"上传完成"
,
"normal"
,
3000
);
}
}
else
{
tips
(
"上传失败"
,
"error"
,
3000
);
}
}
function
setCookie
(
cname
,
cvalue
,
exdays
)
{
var
d
=
new
Date
();
d
.
setTime
(
d
.
getTime
()
+
(
exdays
*
24
*
60
*
60
*
1000
));
var
expires
=
"expires="
+
d
.
toUTCString
();
document
.
cookie
=
cname
+
"="
+
cvalue
+
"; "
+
expires
;
}
function
getCookie
(
cname
)
{
var
name
=
cname
+
"="
;
var
ca
=
document
.
cookie
.
split
(
';'
);
for
(
var
i
=
0
;
i
<
ca
.
length
;
i
++
)
{
var
c
=
ca
[
i
];
while
(
c
.
charAt
(
0
)
==
' '
)
c
=
c
.
substring
(
1
);
if
(
c
.
indexOf
(
name
)
!=
-
1
)
return
c
.
substring
(
name
.
length
,
c
.
length
);
}
return
""
;
}
function
clearCookie
(
name
)
{
setCookie
(
name
,
""
,
-
1
);
}
</script>
</body>
</html>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment