mirror of
https://github.com/chatopera/cosin.git
synced 2025-08-01 16:38:02 +08:00
#75 增加chatbot socket.io server
This commit is contained in:
parent
45bf5d6333
commit
546b8e6ddc
@ -705,7 +705,7 @@ public class UKDataContext {
|
|||||||
IM("/im/user"),
|
IM("/im/user"),
|
||||||
AGENT("/im/agent"),
|
AGENT("/im/agent"),
|
||||||
ENTIM("/im/ent"),
|
ENTIM("/im/ent"),
|
||||||
AIIM("/im/ai"),
|
CHATBOT("/im/chatbot"),
|
||||||
CALLCENTER("/callcenter/event"),
|
CALLCENTER("/callcenter/event"),
|
||||||
CALLOUT("/callout/event");
|
CALLOUT("/callout/event");
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ public abstract interface ChatbotRepository extends JpaRepository<Chatbot, Strin
|
|||||||
|
|
||||||
public abstract boolean existsBySnsAccountIdentifierAndOrgi(String snsid, String orgi);
|
public abstract boolean existsBySnsAccountIdentifierAndOrgi(String snsid, String orgi);
|
||||||
|
|
||||||
|
public abstract List<Chatbot> findByIdAndOrgi(String id, String orgi);
|
||||||
|
|
||||||
@Query(value = "select c from Chatbot c where " +
|
@Query(value = "select c from Chatbot c where " +
|
||||||
"(:myorgans is null or c.organ IN :myorgans)")
|
"(:myorgans is null or c.organ IN :myorgans)")
|
||||||
public Page<Chatbot> findByOrgans(@Param("myorgans") List<String> myorgans, Pageable pageRequest);
|
public Page<Chatbot> findByOrgans(@Param("myorgans") List<String> myorgans, Pageable pageRequest);
|
||||||
|
@ -19,7 +19,7 @@ package com.chatopera.cc.webim.util.server;
|
|||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
import com.chatopera.cc.webim.util.server.handler.AiIMEventHandler;
|
import com.chatopera.cc.webim.util.server.handler.ChatbotEventHandler;
|
||||||
import com.chatopera.cc.webim.util.server.handler.EntIMEventHandler;
|
import com.chatopera.cc.webim.util.server.handler.EntIMEventHandler;
|
||||||
import com.chatopera.cc.webim.util.server.handler.IMEventHandler;
|
import com.chatopera.cc.webim.util.server.handler.IMEventHandler;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -38,7 +38,7 @@ public class ServerRunner implements CommandLineRunner {
|
|||||||
private final SocketIONamespace imSocketNameSpace ;
|
private final SocketIONamespace imSocketNameSpace ;
|
||||||
private final SocketIONamespace agentSocketIONameSpace ;
|
private final SocketIONamespace agentSocketIONameSpace ;
|
||||||
private final SocketIONamespace entIMSocketIONameSpace ;
|
private final SocketIONamespace entIMSocketIONameSpace ;
|
||||||
private final SocketIONamespace aiIMSocketIONameSpace ;
|
private final SocketIONamespace chatbotSocketIONameSpace ;
|
||||||
private final SocketIONamespace callCenterSocketIONameSpace ;
|
private final SocketIONamespace callCenterSocketIONameSpace ;
|
||||||
private final SocketIONamespace calloutSocketIONameSpace ;
|
private final SocketIONamespace calloutSocketIONameSpace ;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ public class ServerRunner implements CommandLineRunner {
|
|||||||
imSocketNameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.IM.getNamespace()) ;
|
imSocketNameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.IM.getNamespace()) ;
|
||||||
agentSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.AGENT.getNamespace()) ;
|
agentSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.AGENT.getNamespace()) ;
|
||||||
entIMSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.ENTIM.getNamespace()) ;
|
entIMSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.ENTIM.getNamespace()) ;
|
||||||
aiIMSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.AIIM.getNamespace()) ;
|
chatbotSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.CHATBOT.getNamespace()) ;
|
||||||
|
|
||||||
if(UKDataContext.model.get("sales") != null && UKDataContext.model.get("sales") == true){
|
if(UKDataContext.model.get("sales") != null && UKDataContext.model.get("sales") == true){
|
||||||
calloutSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.CALLOUT.getNamespace());
|
calloutSocketIONameSpace = server.addNamespace(UKDataContext.NameSpaceEnum.CALLOUT.getNamespace());
|
||||||
@ -81,10 +81,10 @@ public class ServerRunner implements CommandLineRunner {
|
|||||||
return entIMSocketIONameSpace;
|
return entIMSocketIONameSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name="aiimNamespace")
|
@Bean(name="chatbotNamespace")
|
||||||
public SocketIONamespace getAiIMSocketIONameSpace(SocketIOServer server){
|
public SocketIONamespace getChatbotSocketIONameSpace(SocketIOServer server){
|
||||||
aiIMSocketIONameSpace.addListeners(new AiIMEventHandler(server));
|
chatbotSocketIONameSpace.addListeners(new ChatbotEventHandler(server));
|
||||||
return aiIMSocketIONameSpace;
|
return chatbotSocketIONameSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name="callCenterNamespace")
|
@Bean(name="callCenterNamespace")
|
||||||
|
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.chatopera.cc.webim.util.server.handler;
|
||||||
|
|
||||||
|
import com.chatopera.cc.core.UKDataContext;
|
||||||
|
import com.chatopera.cc.util.IPTools;
|
||||||
|
import com.chatopera.cc.util.UKTools;
|
||||||
|
import com.chatopera.cc.util.client.NettyClients;
|
||||||
|
import com.chatopera.cc.webim.service.acd.ServiceQuene;
|
||||||
|
import com.chatopera.cc.webim.service.cache.CacheHelper;
|
||||||
|
import com.chatopera.cc.webim.service.repository.ConsultInviteRepository;
|
||||||
|
import com.chatopera.cc.webim.util.MessageUtils;
|
||||||
|
import com.chatopera.cc.webim.util.OnlineUserUtils;
|
||||||
|
import com.chatopera.cc.webim.util.router.OutMessageRouter;
|
||||||
|
import com.chatopera.cc.webim.util.server.message.AgentStatusMessage;
|
||||||
|
import com.chatopera.cc.webim.util.server.message.ChatMessage;
|
||||||
|
import com.chatopera.cc.webim.util.server.message.NewRequestMessage;
|
||||||
|
import com.chatopera.cc.webim.web.model.AgentService;
|
||||||
|
import com.chatopera.cc.webim.web.model.AiUser;
|
||||||
|
import com.chatopera.cc.webim.web.model.CousultInvite;
|
||||||
|
import com.chatopera.cc.webim.web.model.MessageOutContent;
|
||||||
|
import com.corundumstudio.socketio.AckRequest;
|
||||||
|
import com.corundumstudio.socketio.SocketIOClient;
|
||||||
|
import com.corundumstudio.socketio.SocketIOServer;
|
||||||
|
import com.corundumstudio.socketio.annotation.OnConnect;
|
||||||
|
import com.corundumstudio.socketio.annotation.OnDisconnect;
|
||||||
|
import com.corundumstudio.socketio.annotation.OnEvent;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class ChatbotEventHandler
|
||||||
|
{
|
||||||
|
protected SocketIOServer server;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ChatbotEventHandler(SocketIOServer server)
|
||||||
|
{
|
||||||
|
this.server = server ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnConnect
|
||||||
|
public void onConnect(SocketIOClient client)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
String user = client.getHandshakeData().getSingleUrlParam("userid") ;
|
||||||
|
String orgi = client.getHandshakeData().getSingleUrlParam("orgi") ;
|
||||||
|
// String session = client.getHandshakeData().getSingleUrlParam("session") ;
|
||||||
|
String appid = client.getHandshakeData().getSingleUrlParam("appid") ;
|
||||||
|
String aiid = client.getHandshakeData().getSingleUrlParam("aiid") ;
|
||||||
|
// String agent = client.getHandshakeData().getSingleUrlParam("agent") ;
|
||||||
|
// String skill = client.getHandshakeData().getSingleUrlParam("skill") ;
|
||||||
|
|
||||||
|
if(!StringUtils.isBlank(user)){
|
||||||
|
// /**
|
||||||
|
// * 加入到 缓存列表
|
||||||
|
// */
|
||||||
|
NettyClients.getInstance().putIMEventClient(user, client);
|
||||||
|
MessageOutContent outMessage = new MessageOutContent() ;
|
||||||
|
CousultInvite invite = OnlineUserUtils.cousult(appid , orgi, UKDataContext.getContext().getBean(ConsultInviteRepository.class));
|
||||||
|
if(invite!=null && !StringUtils.isBlank(invite.getAisuccesstip())) {
|
||||||
|
outMessage.setMessage(invite.getAisuccesstip());
|
||||||
|
}else{
|
||||||
|
outMessage.setMessage("欢迎使用优客服小E,我来帮您解答问题");
|
||||||
|
}
|
||||||
|
|
||||||
|
outMessage.setMessageType(UKDataContext.MessageTypeEnum.MESSAGE.toString());
|
||||||
|
outMessage.setCalltype(UKDataContext.CallTypeEnum.IN.toString());
|
||||||
|
outMessage.setNickName("AI");
|
||||||
|
outMessage.setCreatetime(UKTools.dateFormate.format(new Date()));
|
||||||
|
|
||||||
|
client.sendEvent(UKDataContext.MessageTypeEnum.STATUS.toString(), outMessage);
|
||||||
|
|
||||||
|
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress() ;
|
||||||
|
String ip = UKTools.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()) ;
|
||||||
|
AiUser aiUser = new AiUser(user, user, System.currentTimeMillis() , orgi,IPTools.getInstance().findGeography(ip)) ;
|
||||||
|
aiUser.setSessionid(UKTools.getContextID(client.getSessionId().toString()));
|
||||||
|
aiUser.setAppid(appid);
|
||||||
|
aiUser.setAiid(aiid);
|
||||||
|
aiUser.setUsername(UKDataContext.GUEST_USER+"_"+UKTools.genIDByKey(aiUser.getId()));
|
||||||
|
aiUser.setChannel(UKDataContext.ChannelTypeEnum.WEBIM.toString());
|
||||||
|
|
||||||
|
AgentService agentService = ServiceQuene.processAiService(aiUser, orgi) ;
|
||||||
|
aiUser.setAgentserviceid(agentService.getId());
|
||||||
|
|
||||||
|
CacheHelper.getOnlineUserCacheBean().put(user, aiUser, UKDataContext.SYSTEM_ORGI);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//添加@OnDisconnect事件,客户端断开连接时调用,刷新客户端信息
|
||||||
|
@OnDisconnect
|
||||||
|
public void onDisconnect(SocketIOClient client) throws Exception
|
||||||
|
{
|
||||||
|
String user = client.getHandshakeData().getSingleUrlParam("userid") ;
|
||||||
|
String orgi = client.getHandshakeData().getSingleUrlParam("orgi") ;
|
||||||
|
if(!StringUtils.isBlank(user)){
|
||||||
|
NettyClients.getInstance().removeIMEventClient(user , UKTools.getContextID(client.getSessionId().toString()));
|
||||||
|
AiUser aiUser = (AiUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi) ;
|
||||||
|
if(aiUser!=null) {
|
||||||
|
ServiceQuene.processAiService(aiUser, orgi) ;
|
||||||
|
CacheHelper.getOnlineUserCacheBean().delete(user,UKDataContext.SYSTEM_ORGI) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
//消息接收入口,网站有新用户接入对话
|
||||||
|
@OnEvent(value = "new")
|
||||||
|
public void onEvent(SocketIOClient client, AckRequest request, NewRequestMessage data)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//消息接收入口,坐席状态更新
|
||||||
|
@OnEvent(value = "agentstatus")
|
||||||
|
public void onEvent(SocketIOClient client, AckRequest request, AgentStatusMessage data)
|
||||||
|
{
|
||||||
|
System.out.println(data.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
//消息接收入口,收发消息,用户向坐席发送消息和 坐席向用户发送消息
|
||||||
|
@OnEvent(value = "message")
|
||||||
|
public void onEvent(SocketIOClient client, AckRequest request, ChatMessage data)
|
||||||
|
{
|
||||||
|
String orgi = client.getHandshakeData().getSingleUrlParam("orgi") ;
|
||||||
|
String aiid = client.getHandshakeData().getSingleUrlParam("aiid") ;
|
||||||
|
String user = client.getHandshakeData().getSingleUrlParam("userid") ;
|
||||||
|
if(data.getType() == null){
|
||||||
|
data.setType("message");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 以下代码主要用于检查 访客端的字数限制
|
||||||
|
*/
|
||||||
|
CousultInvite invite = OnlineUserUtils.cousult(data.getAppid(),data.getOrgi(), UKDataContext.getContext().getBean(ConsultInviteRepository.class));
|
||||||
|
if(invite!=null && invite.getMaxwordsnum() > 0) {
|
||||||
|
if(!StringUtils.isBlank(data.getMessage()) && data.getMessage().length() > invite.getMaxwordsnum()){
|
||||||
|
data.setMessage(data.getMessage().substring(0 , invite.getMaxwordsnum()));
|
||||||
|
}
|
||||||
|
}else if(!StringUtils.isBlank(data.getMessage()) && data.getMessage().length() > 300){
|
||||||
|
data.setMessage(data.getMessage().substring(0 , 300));
|
||||||
|
}
|
||||||
|
data.setSessionid(UKTools.getContextID(client.getSessionId().toString()));
|
||||||
|
/**
|
||||||
|
* 处理表情
|
||||||
|
*/
|
||||||
|
data.setMessage(UKTools.processEmoti(data.getMessage()));
|
||||||
|
data.setTousername(UKDataContext.ChannelTypeEnum.AI.toString());
|
||||||
|
|
||||||
|
data.setAiid(aiid);
|
||||||
|
|
||||||
|
Object cacheData = (AiUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user,orgi) ;
|
||||||
|
if(cacheData!=null && cacheData instanceof AiUser){
|
||||||
|
AiUser aiUser = (AiUser)cacheData ;
|
||||||
|
data.setAgentserviceid(aiUser.getAgentserviceid());
|
||||||
|
data.setChannel(aiUser.getChannel());
|
||||||
|
/**
|
||||||
|
* 一定要设置 ContextID
|
||||||
|
*/
|
||||||
|
data.setContextid(aiUser.getAgentserviceid());
|
||||||
|
}
|
||||||
|
MessageOutContent outMessage = MessageUtils.createAiMessage(data , data.getAppid() , data.getChannel() , UKDataContext.CallTypeEnum.IN.toString() , UKDataContext.AiItemType.USERINPUT.toString() , UKDataContext.MediaTypeEnum.TEXT.toString(), data.getUserid()) ;
|
||||||
|
if(!StringUtils.isBlank(data.getUserid()) && UKDataContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())){
|
||||||
|
if(!StringUtils.isBlank(data.getTouser())){
|
||||||
|
OutMessageRouter router = null ;
|
||||||
|
router = (OutMessageRouter) UKDataContext.getContext().getBean(data.getChannel()) ;
|
||||||
|
if(router!=null){
|
||||||
|
router.handler(data.getTouser(), UKDataContext.MessageTypeEnum.MESSAGE.toString(), data.getAppid(), outMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cacheData!=null && cacheData instanceof AiUser){
|
||||||
|
AiUser aiUser = (AiUser)cacheData ;
|
||||||
|
aiUser.setTime(System.currentTimeMillis());
|
||||||
|
CacheHelper.getOnlineUserCacheBean().put(user, aiUser, UKDataContext.SYSTEM_ORGI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UKTools.ai(data);
|
||||||
|
}
|
||||||
|
}
|
@ -56,6 +56,8 @@ import java.io.IOException;
|
|||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@ -474,32 +476,19 @@ public class IMController extends Handler {
|
|||||||
if (UKDataContext.model.get("chatbot") != null &&
|
if (UKDataContext.model.get("chatbot") != null &&
|
||||||
StringUtils.isNotBlank(invite.getAiid()) &&
|
StringUtils.isNotBlank(invite.getAiid()) &&
|
||||||
invite.isAi() &&
|
invite.isAi() &&
|
||||||
(StringUtils.equals(ai, "true") || (invite.isAifirst() && ai == null))) { //启用 AI , 并且 AI优先 接待
|
invite.isAifirst()) { //启用 AI , 并且 AI优先 接待
|
||||||
DataExchangeInterface dataInterface = (DataExchangeInterface) UKDataContext.getContext().getBean("aiconfig");
|
HashMap<String, String> chatbotConfig = new HashMap<String, String>();
|
||||||
AiConfig aiConfig = (AiConfig) dataInterface.getDataByIdAndOrgi(aiid, invite.getOrgi());
|
chatbotConfig.put("botname", invite.getAiname());
|
||||||
if (aiConfig != null) {
|
chatbotConfig.put("botid", invite.getAiid());
|
||||||
map.addAttribute("aiConfig", aiConfig);
|
chatbotConfig.put("botwelcome", invite.getAimsg());
|
||||||
|
chatbotConfig.put("botfirst", Boolean.toString(invite.isAifirst()));
|
||||||
|
chatbotConfig.put("isai", Boolean.toString(invite.isAi()));
|
||||||
|
if (chatbotConfig != null) {
|
||||||
|
map.addAttribute("chatbotConfig", chatbotConfig);
|
||||||
}
|
}
|
||||||
view = request(super.createRequestPageTempletResponse("/apps/im/ai/index"));
|
view = request(super.createRequestPageTempletResponse("/apps/im/chatbot/index"));
|
||||||
if (CheckMobile.check(request.getHeader("User-Agent")) || !StringUtils.isBlank(mobile)) {
|
if (CheckMobile.check(request.getHeader("User-Agent")) || !StringUtils.isBlank(mobile)) {
|
||||||
view = request(super.createRequestPageTempletResponse("/apps/im/ai/mobile")); //智能机器人 移动端
|
view = request(super.createRequestPageTempletResponse("/apps/im/chatbot/mobile")); //智能机器人 移动端
|
||||||
}
|
|
||||||
if (UKDataContext.model.get("xiaoe") != null) {
|
|
||||||
List<Topic> topicList = OnlineUserUtils.cacheHotTopic((DataExchangeInterface) UKDataContext.getContext().getBean("topic"), super.getUser(request), orgi, aiid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初步按照地区匹配分类筛选
|
|
||||||
*/
|
|
||||||
List<KnowledgeType> topicTypeList = OnlineUserUtils.topicType(orgi, ipdata, OnlineUserUtils.cacheHotTopicType((DataExchangeInterface) UKDataContext.getContext().getBean("topictype"), super.getUser(request), orgi, aiid));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 第二步按照 有 热点主题的 分类做筛选
|
|
||||||
*/
|
|
||||||
map.addAttribute("topicList", OnlineUserUtils.topic(orgi, topicTypeList, topicList));
|
|
||||||
/**
|
|
||||||
* 第三步筛选 分类,如果无热点知识,则不显示分类
|
|
||||||
*/
|
|
||||||
map.addAttribute("topicTypeList", OnlineUserUtils.filterTopicType(topicTypeList, topicList));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CheckMobile.check(request.getHeader("User-Agent")) || !StringUtils.isBlank(mobile)) {
|
if (CheckMobile.check(request.getHeader("User-Agent")) || !StringUtils.isBlank(mobile)) {
|
||||||
|
@ -20,6 +20,7 @@ import com.chatopera.chatbot.ChatbotAPIRuntimeException;
|
|||||||
import org.hibernate.annotations.GenericGenerator;
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
@ -0,0 +1,581 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta http-equiv="Cache-Control" content="no-siteapp" />
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, maximum-scale=1.0, initial-scale=1.0,initial-scale=1.0,user-scalable=no" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<title>在线咨询</title>
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico?t=1489039620156"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/im/css/ukefu.css">
|
||||||
|
<link rel="stylesheet" id="skin" type="text/css" href="/im/css/default/ukefu.css">
|
||||||
|
<!-- kindeditor -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="/im/js/kindeditor/themes/default/default.css">
|
||||||
|
|
||||||
|
<script src="/js/jquery-1.10.2.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/im/js/kindeditor/kindeditor.js"></script>
|
||||||
|
<script type="text/javascript" src="/im/js/kindeditor/lang/zh-CN.js"></script>
|
||||||
|
<script src="/im/js/socket.io.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var editor , words;
|
||||||
|
var newmessage = [] , ring = [];
|
||||||
|
newmessage['mp3'] = '/images/message.mp3';
|
||||||
|
ring['mp3'] = '/images/ring.mp3';
|
||||||
|
KindEditor.ready(function (K) {
|
||||||
|
editor = K.create('textarea[name="content"]', {
|
||||||
|
autoHeightMode: false,
|
||||||
|
width: "100%",
|
||||||
|
resizeType: 0,
|
||||||
|
themeType: 'simple',
|
||||||
|
fontsize: 16,
|
||||||
|
newlineTag : "br" ,
|
||||||
|
uploadJson : "/im/image/upload.html?userid=${userid!''}",
|
||||||
|
allowFileManager : false,
|
||||||
|
allowInsertUpload:false, //增加的参数,上传图片后是否插入到当前区域
|
||||||
|
allowImageRemote:false,
|
||||||
|
filterMode:true,
|
||||||
|
items: ['emoticons', 'cut' , 'image','insertfile'],
|
||||||
|
htmlTags: {img : ['src', 'width', 'height', 'border', 'alt', 'title', 'align', '.width', '.height', '.border'] , br:[]} ,
|
||||||
|
afterChange : function() {
|
||||||
|
var count = this.count() ;
|
||||||
|
var limitNum = <#if inviteData.maxwordsnum gt 0>${inviteData.maxwordsnum}<#else>300</#if>; //设定限制字数
|
||||||
|
var pattern = '还可以输入' + limitNum + '字';
|
||||||
|
var strValue = this.html();
|
||||||
|
if(count > limitNum) {
|
||||||
|
pattern = ('字数超过限制,请适当删除部分内容');
|
||||||
|
//超过字数限制自动截取
|
||||||
|
strValue = strValue.substring(0,limitNum);
|
||||||
|
editor.html(strValue);
|
||||||
|
} else {
|
||||||
|
//计算剩余字数
|
||||||
|
var result = limitNum - this.count();
|
||||||
|
pattern = '还可以输入' + result + '字';
|
||||||
|
if(result < 20){
|
||||||
|
document.getElementById('surplus').style.color = "red" ;
|
||||||
|
}else{
|
||||||
|
document.getElementById('surplus').style.color = "#000000" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(this.count("text") == 0){
|
||||||
|
strValue= "" ;
|
||||||
|
}
|
||||||
|
if(words != this.count("text")){
|
||||||
|
socket.emit('message', {
|
||||||
|
appid : "${appid!''}",
|
||||||
|
userid:"${userid!''}",
|
||||||
|
type:"writing",
|
||||||
|
session:"${sessionid!''}",
|
||||||
|
orgi:"${orgi!''}",
|
||||||
|
message : strValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
words = this.count("text") ;
|
||||||
|
document.getElementById('surplus').innerHTML = count+"/"+limitNum+" , " + pattern; //输入显示
|
||||||
|
////////
|
||||||
|
},
|
||||||
|
afterCreate : function() { //设置编辑器创建后执行的回调函数
|
||||||
|
var self = this;
|
||||||
|
<#if inviteData?? && inviteData.ctrlenter?? && inviteData.ctrlenter == true>
|
||||||
|
//Ctrl+Enter提交表单
|
||||||
|
K.ctrl(document, 13, function() {
|
||||||
|
self.sync();
|
||||||
|
sendMessage();
|
||||||
|
});
|
||||||
|
K.ctrl(self.edit.doc, 13, function() {
|
||||||
|
self.sync();
|
||||||
|
sendMessage();
|
||||||
|
});
|
||||||
|
<#else>
|
||||||
|
var kindEditorIframe = $("iframe").contents().find("body");
|
||||||
|
kindEditorIframe.keydown(function (event) {
|
||||||
|
if(event.keyCode==13 && !event.ctrlKey){
|
||||||
|
self.sync();
|
||||||
|
sendMessage();
|
||||||
|
return false;
|
||||||
|
}else if(event.keyCode==13 && event.ctrlKey){
|
||||||
|
editor.insertHtml('<br/>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//Ctrl+Enter提交表单
|
||||||
|
K.ctrl(document, 13, function() {
|
||||||
|
editor.insertHtml('<br/>');
|
||||||
|
});
|
||||||
|
K.ctrl(self.edit.doc, 13, function() {
|
||||||
|
editor.insertHtml('<br/>');
|
||||||
|
});
|
||||||
|
</#if>
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
KindEditor.options.cssData = "body { font-size: 15px; font-family:'Microsoft Yahei', 'Helvetica', 'Simsun', 'Arial';}";
|
||||||
|
var R3Ajax = {
|
||||||
|
ajax:function(opt){
|
||||||
|
var xhr = this.createXhrObject();
|
||||||
|
xhr.onreadystatechange = function(){
|
||||||
|
if(xhr.readyState!=4) return ;
|
||||||
|
(xhr.status===200 ?
|
||||||
|
opt.success(xhr.responseText,xhr.responseXML):
|
||||||
|
opt.error(xhr.responseText,xhr.status));
|
||||||
|
}
|
||||||
|
xhr.open(opt.type,opt.url,true);
|
||||||
|
if(opt.type!=='post')
|
||||||
|
opt.data=null;
|
||||||
|
else
|
||||||
|
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
|
||||||
|
opt.data = this.parseQuery(opt.data);
|
||||||
|
xhr.send(opt.data);
|
||||||
|
},
|
||||||
|
post:function(url,success,data){
|
||||||
|
var popt = {
|
||||||
|
url:url,
|
||||||
|
type:'post',
|
||||||
|
data:data,
|
||||||
|
success:success,
|
||||||
|
error:function(data){}
|
||||||
|
}
|
||||||
|
this.ajax(popt);
|
||||||
|
},
|
||||||
|
get:function(url,success){
|
||||||
|
var gopt = {
|
||||||
|
url:url,
|
||||||
|
type:'get',
|
||||||
|
success:success,
|
||||||
|
error:function(){}
|
||||||
|
}
|
||||||
|
this.ajax(gopt);
|
||||||
|
},
|
||||||
|
createXhrObject:function(){
|
||||||
|
var methods = [
|
||||||
|
function(){ return new XMLHttpRequest();},
|
||||||
|
function(){ return new ActiveXObject('Msxml2.XMLHTTP');},
|
||||||
|
function(){ return new ActiveXObject('Microsoft.XMLHTTP');}
|
||||||
|
];
|
||||||
|
for(var i=0;len=methods.length,i<len;i++){
|
||||||
|
try{
|
||||||
|
methods[i]();
|
||||||
|
}catch(e){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.createXhrObject = methods[i];
|
||||||
|
return methods[i]();
|
||||||
|
}
|
||||||
|
throw new Error('Could not create an XHR object.');
|
||||||
|
},
|
||||||
|
parseQuery:function(json){
|
||||||
|
if(typeof json == 'object'){
|
||||||
|
var str = '';
|
||||||
|
for(var i in json){
|
||||||
|
str += "&"+i+"="+encodeURIComponent(json[i]);
|
||||||
|
}
|
||||||
|
return str.length==0 ? str : str.substring(1);
|
||||||
|
}else{
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
audioplayer:function(id, file, loop) {
|
||||||
|
var audioplayer = document.getElementById(id);
|
||||||
|
if (audioplayer != null) {
|
||||||
|
document.body.removeChild(audioplayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(file) != 'undefined') {
|
||||||
|
if (navigator.userAgent.indexOf("MSIE") > 0) { // IE
|
||||||
|
var player = document.createElement('bgsound');
|
||||||
|
player.id = id;
|
||||||
|
player.src = file['mp3'];
|
||||||
|
player.setAttribute('autostart', 'true');
|
||||||
|
if (loop) {
|
||||||
|
player.setAttribute('loop', 'infinite');
|
||||||
|
}
|
||||||
|
document.body.appendChild(player);
|
||||||
|
|
||||||
|
} else { // Other FF Chome Safari Opera
|
||||||
|
var player = document.createElement('audio');
|
||||||
|
player.id = id;
|
||||||
|
player.setAttribute('autoplay', 'autoplay');
|
||||||
|
if (loop) {
|
||||||
|
player.setAttribute('loop', 'loop');
|
||||||
|
}
|
||||||
|
document.body.appendChild(player);
|
||||||
|
|
||||||
|
var mp3 = document.createElement('source');
|
||||||
|
mp3.src = file['mp3'];
|
||||||
|
mp3.type = 'audio/mpeg';
|
||||||
|
player.appendChild(mp3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Date.prototype.format = function(fmt) {
|
||||||
|
var o = {
|
||||||
|
"M+" : this.getMonth()+1, //月份
|
||||||
|
"d+" : this.getDate(), //日
|
||||||
|
"h+" : this.getHours(), //小时
|
||||||
|
"m+" : this.getMinutes(), //分
|
||||||
|
"s+" : this.getSeconds(), //秒
|
||||||
|
"q+" : Math.floor((this.getMonth()+3)/3), //季度
|
||||||
|
"S" : this.getMilliseconds() //毫秒
|
||||||
|
};
|
||||||
|
if(/(y+)/.test(fmt)) {
|
||||||
|
fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
|
||||||
|
}
|
||||||
|
for(var k in o) {
|
||||||
|
if(new RegExp("("+ k +")").test(fmt)){
|
||||||
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
var R3Helper = {
|
||||||
|
resize : function(){
|
||||||
|
var height = document.body.offsetHeight ;
|
||||||
|
document.getElementById('above').style.height = (height - 194 - 50)+"px" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function submitForm(form){
|
||||||
|
R3Ajax.post("/im/satis.html?orgi=${orgi!''}" , function(){
|
||||||
|
document.getElementById("diaShade").style.display = "none" ;
|
||||||
|
document.getElementById("dialogWrap").style.display = "none" ;
|
||||||
|
alert("服务评价已提及,请关闭浏览器!");
|
||||||
|
service_end = true;
|
||||||
|
} , "id="+form.id.value+"&satislevel="+document.getElementById("satislevel_input").value +"&satiscomment="+encodeURIComponent(document.getElementById("comment_input").value ));
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
window.onbeforeunload = function(){
|
||||||
|
if(service_end == false){
|
||||||
|
<#if sessionConfig?? && sessionConfig.satisfaction?? && sessionConfig.satisfaction>
|
||||||
|
document.getElementById("diaShade").style.display = "block" ;
|
||||||
|
document.getElementById("dialogWrap").style.display = "block" ;
|
||||||
|
</#if>
|
||||||
|
return "您确定断开对话?" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<!-- kindeditor -->
|
||||||
|
</head>
|
||||||
|
<body style="overflow:hidden;" class="ukefu-point-text">
|
||||||
|
<div class="large ukefu-im-theme <#if type?? && type='text'>ukefu-theme-border-${inviteData.consult_dialog_color!''}</#if>">
|
||||||
|
<div id="containter" class="clearfix">
|
||||||
|
<div id="header" class="theme${inviteData.consult_dialog_color!''}">
|
||||||
|
<img src="<#if inviteData?? && inviteData.consult_dialog_logo??>/res/image.html?id=${inviteData.consult_dialog_logo?url}<#else>/images/logo.png</#if>" style="height:30px;padding:10px;">
|
||||||
|
<div class="ukefu-func-tab">
|
||||||
|
<ul>
|
||||||
|
<#if models?? && models["xiaoe"]?? && models["xiaoe"] == true && inviteData.ai && aiid??>
|
||||||
|
<#if !exchange?? || exchange == "true">
|
||||||
|
<li><a href="/im/index.html?appid=${appid!''}&orgi=${orgi!''}<#if aiid??>&aiid=${aiid}</#if>&ai=true<#if client??>&client=${client!''}</#if><#if type??>&type=text</#if><#if skill??>&skill=${skill!''}</#if><#if agent??>&agent=${agent!''}</#if><#if title??>&title=${title?url}</#if><#if url??>&url=${url?url}</#if><#if traceid??>&traceid=${traceid}</#if>&userid=${userid!''}&sessionid=${sessionid!''}&t=${.now?long}">智能客服</a></li>
|
||||||
|
</#if>
|
||||||
|
<li class="cur"><a href="javascript:void(0)">人工坐席</a></li>
|
||||||
|
<#else>
|
||||||
|
<li class="cur"><a href="javascript:void(0)">人工坐席</a></li>
|
||||||
|
</#if>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content-left">
|
||||||
|
<div class="chat-above" id="above">
|
||||||
|
<#if welcomeAd>
|
||||||
|
<div class="clearfix message welcome">
|
||||||
|
<span id="welcome-message">
|
||||||
|
<#if welcomeAd.adtype =="image">
|
||||||
|
<a href='${welcomeAd.url!''}' title='${welcomeAd.tiptext!''}' target='_blank'><img src='${welcomeAd.imgurl!''}' style='max-width:420px;max-height:178px;margin:0px;vertical-align: middle;'/></a>
|
||||||
|
<#else>
|
||||||
|
<div style='padding:0px 5px 10px 5px;border-bottom:1px solid #dedede;'><a href='${welcomeAd.url!''}' title='${welcomeAd.tiptext!''}' target='_blank' id='point_ad_text'>${(welcomeAd.content!'')?no_esc}</a></div>
|
||||||
|
</#if>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
<div class="clearfix message welcome">
|
||||||
|
<span id="welcome-message">${(inviteData.dialog_message!'欢迎您来咨询!欢迎使用春松客服!如需帮助请联系 info@chatopera.com')?no_esc}</span></div>
|
||||||
|
<#if chatMessageList?? && chatMessageList.content??>
|
||||||
|
<#list chatMessageList.content?reverse as chatMessage>
|
||||||
|
<#if chatMessage.userid?? && userid?? && chatMessage.calltype?? && chatMessage.calltype = "呼入">
|
||||||
|
<div class="clearfix chat-block">
|
||||||
|
<div class="chat-right">
|
||||||
|
<img class="user-img" src="/im/img/user.png" alt="">
|
||||||
|
<div class="chat-message">
|
||||||
|
<label class="time">${chatMessage.createtime!''}</label>
|
||||||
|
<label class="user">${chatMessage.username!''}</label>
|
||||||
|
</div>
|
||||||
|
<div class="chatting-right">
|
||||||
|
<i class="arrow arrow${inviteData.consult_dialog_color!''}"></i>
|
||||||
|
<div class="chat-content theme${inviteData.consult_dialog_color!''}"><#include "/apps/im/media/message.html"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<#else>
|
||||||
|
<div class="clearfix chat-block">
|
||||||
|
<div class="chat-left">
|
||||||
|
<img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt="">
|
||||||
|
<div class="chat-message">
|
||||||
|
<label class="user"><#if chatMessage?? && chatMessage.chatype?? && chatMessage.chatype == 'aireply'>${inviteData.ainame!'小E'}<#else>${chatMessage.username!''}</#if></label>
|
||||||
|
<label class="time">${chatMessage.createtime!''}</label>
|
||||||
|
</div>
|
||||||
|
<div class="chatting-left">
|
||||||
|
<i class="arrow"></i>
|
||||||
|
<div class="chat-content"><#include "/apps/im/media/message.html"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<div class="chat-bottom" id="bottom">
|
||||||
|
<textarea id="message" name="content" style="visibility:hidden;"></textarea>
|
||||||
|
<div class="btn-push clearfix">
|
||||||
|
<div style="float:left;height:34px;line-height:34px;margin: 10px 20px 10px 5px;" id="surplus">0/200</div>
|
||||||
|
<button type="button" class="send-btn active special clearfix" id="sent" onclick="sendMessage()">
|
||||||
|
发送
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content-rig">
|
||||||
|
<div class="content-list" style="padding-top:50px;">
|
||||||
|
<div class="content-head">
|
||||||
|
<p>信息提示</p>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<#if inviteData.dialog_name?? && inviteData.dialog_name != "">
|
||||||
|
<li>
|
||||||
|
<p>名称:${inviteData.dialog_name!''}</p>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<#if inviteData.dialog_address?? && inviteData.dialog_address != "">
|
||||||
|
<li>
|
||||||
|
<p>地址:${inviteData.dialog_address!''}</p>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<#if inviteData.dialog_phone?? && inviteData.dialog_phone != "">
|
||||||
|
<li>
|
||||||
|
<p>电话:${inviteData.dialog_phone!''}</p>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<#if inviteData.dialog_mail?? && inviteData.dialog_mail != "">
|
||||||
|
<li>
|
||||||
|
<p>邮件:${inviteData.dialog_mail!''}</p>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
<#if inviteData.dialog_mail?? && inviteData.dialog_introduction != "">
|
||||||
|
<li>
|
||||||
|
<p style="text-indent:25px;line-height:25px;">${(inviteData.dialog_introduction!'')?no_esc}</p>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="content-pic" style="width:100%;height:192px;">
|
||||||
|
<#if imageAd>
|
||||||
|
<#if imageAd.adtype =="image">
|
||||||
|
<a href='${imageAd.url!''}' title='${imageAd.tiptext!''}' target='_blank'><img src='${imageAd.imgurl!''}' style='max-width:100%;max-height:190px;margin:0px;vertical-align: middle;'/></a>
|
||||||
|
<#else>
|
||||||
|
<div style='padding:0px 5px 10px 5px;border-bottom:1px solid #dedede;'><a href='${imageAd.url!''}' title='${imageAd.tiptext!''}' target='_blank' id='point_ad_text'>${(imageAd.content!'')?no_esc}</a></div>
|
||||||
|
</#if>
|
||||||
|
<#elseif inviteData.dialog_ad??>
|
||||||
|
<img src="/res/image.html?id=${inviteData.dialog_ad!''}" style="height:190px;width:100%;">
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="footer"></div>
|
||||||
|
</div>
|
||||||
|
<#if sessionConfig?? && sessionConfig.satisfaction?? && sessionConfig.satisfaction>
|
||||||
|
<!--调查问卷弹框-->
|
||||||
|
<div class="diaShade" id="diaShade" style="display: none"></div>
|
||||||
|
<div class="dialogWrap" id="dialogWrap" style="display: none">
|
||||||
|
<div class="dialogCon">
|
||||||
|
<form id="commentContent" onSubmit="return submitForm(this)">
|
||||||
|
<input type="hidden" name="id" id="agentserviceid" name="agentserviceid">
|
||||||
|
<h2 class="diaHeader clearfix">
|
||||||
|
<span>评价</span>
|
||||||
|
<hr>
|
||||||
|
</h2>
|
||||||
|
<p class="title">您是否对此次服务满意?</p>
|
||||||
|
<!--评价-->
|
||||||
|
<p style="margin-top:20px;">
|
||||||
|
<span style="float:left;">评价:</span>
|
||||||
|
<span style="position: relative;top: 0px;left: 13px;">
|
||||||
|
<#assign defaultvalue = "">
|
||||||
|
<#if commentList??>
|
||||||
|
<#list commentList as comment>
|
||||||
|
<input type="radio" name="satislevel" value="${comment.code!''}" <#if comment_index == 0>checked="checked"</#if> id="dic_${comment.id!''}" onclick="document.getElementById('satislevel_input').value = this.value">
|
||||||
|
<label for="dic_${comment.id!''}" class="radio">${comment.name!''}</label>
|
||||||
|
<#if defaultvalue == "">
|
||||||
|
<#assign defaultvalue = comment.code>
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
<input type="hidden" id="satislevel_input" name="t" value="${defaultvalue}">
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<!--描述-->
|
||||||
|
<p style="margin-top:20px;">
|
||||||
|
<span style="float:left;">意见:</span>
|
||||||
|
<span style="position: relative;top: 0px;left: 10px;">
|
||||||
|
<input type="hidden" id="comment_input" name="t">
|
||||||
|
<#if commentItemList??>
|
||||||
|
<#list commentItemList as item>
|
||||||
|
<div style="margin-left:55px;margin-bottom:20px;">
|
||||||
|
<input type="radio" name="comment" id="item_${item.id!''}" value="${item.id!''}" onclick="document.getElementById('comment_input').value = this.value">
|
||||||
|
<label for="item_${item.id!''}" class="radio">
|
||||||
|
${item.name!''}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<!--按钮-->
|
||||||
|
<p class="submitBtnWrap">
|
||||||
|
<input type="submit" class="btn submitBtn" id="submitBtn" value="提 交">
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if>
|
||||||
|
<script>
|
||||||
|
var service_end = false ;
|
||||||
|
R3Helper.resize();
|
||||||
|
// 调查问卷
|
||||||
|
var diaShade=document.getElementById('diaShade');
|
||||||
|
var dialogWrap=document.getElementById('dialogWrap');
|
||||||
|
function popup(para) {
|
||||||
|
diaShade.style.display=para;
|
||||||
|
dialogWrap.style.display=para;
|
||||||
|
}
|
||||||
|
<#if !welcomeAd>
|
||||||
|
document.getElementById('above').scrollTop = document.getElementById('above').scrollHeight ; //滚动到 对话内容的 底部
|
||||||
|
</#if>
|
||||||
|
// 参数连接
|
||||||
|
var hostname = location.hostname ;
|
||||||
|
var protocol = window.location.protocol.replace(/:/g,'');
|
||||||
|
var socket = io.connect(protocol + '://'+hostname+':${port}/im/chatbot?userid=${userid!''}&orgi=${orgi!''}&session=${sessionid!''}&appid=${appid!''}&osname=${(osname!'')?url}&browser=${(browser!'')?url}<#if skill??>&skill=${skill}</#if><#if username??>&nickname=${username}</#if><#if agent??>&agent=${agent}</#if><#if title??>&title=${title?url}</#if><#if traceid??>&url=${url?url}</#if><#if traceid??>&traceid=${traceid}</#if>');
|
||||||
|
socket.on('connect',function(){
|
||||||
|
<#if contacts?? && contacts.name??>
|
||||||
|
socket.emit('new', {
|
||||||
|
name : "${contacts.name!''}",
|
||||||
|
phone:"${contacts.phone!''}",
|
||||||
|
email:"${contacts.email}",
|
||||||
|
memo:"${contacts.memo!''}",
|
||||||
|
orgi:"${inviteData.orgi!''}",
|
||||||
|
appid : "${appid!''}"
|
||||||
|
});
|
||||||
|
</#if>
|
||||||
|
})
|
||||||
|
socket.on("agentstatus",function(data){
|
||||||
|
document.getElementById('connect-message').innerHTML=data.message;
|
||||||
|
})
|
||||||
|
socket.on("status",function(data){
|
||||||
|
<#if welcomeAd>
|
||||||
|
output('<span id="connect-message">'+data.message+'</span>' , 'message connect-message' , false);
|
||||||
|
<#else>
|
||||||
|
output('<span id="connect-message">'+data.message+'</span>' , 'message connect-message' , true);
|
||||||
|
</#if>
|
||||||
|
if(data.messageType == "end"){
|
||||||
|
service_end = true ;
|
||||||
|
editor.readonly();
|
||||||
|
<#if sessionConfig?? && sessionConfig.satisfaction?? && sessionConfig.satisfaction>
|
||||||
|
|
||||||
|
document.getElementById("diaShade").style.display = "block" ;
|
||||||
|
document.getElementById("dialogWrap").style.display = "block" ;
|
||||||
|
</#if>
|
||||||
|
}
|
||||||
|
if(document.getElementById("agentserviceid")){
|
||||||
|
document.getElementById("agentserviceid").value = data.agentserviceid ;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
socket.on('message', function(data) {
|
||||||
|
var chat=document.getElementsByClassName('chatting-left').innerText;
|
||||||
|
chat = data.message;
|
||||||
|
if(data.messageType == "image"){
|
||||||
|
chat = "<a href='"+data.message+"_original' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ;
|
||||||
|
}else if(data.messageType == "file"){
|
||||||
|
chat = "<div class='ukefu-message-file'><div class='ukefu-file-icon'><img src='/im/img/file.png'></div><div class='ukefu-file-desc'><a href='"+data.message+"' target='_blank'><div>"+data.filename+"</div><div>"+(data.filesize/1024).toFixed(3)+"Kb</div></a></div></div>" ;
|
||||||
|
}
|
||||||
|
if(data.calltype == "呼入"){
|
||||||
|
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">'+data.createtime+'</label><label class="user">'+data.nickName+'</label> </div><div class="chatting-right"><i class="arrow arrow${inviteData.consult_dialog_color!''}"></i><div class="chat-content theme${inviteData.consult_dialog_color!''}">'+chat+'</div></div>' , "chat-block");
|
||||||
|
}else if(data.calltype == "呼出"){
|
||||||
|
output('<div class="chat-left"> <img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt=""><div class="chat-message"><label class="user">'+data.nickName+'</label><label class="time">'+data.createtime+'</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">'+chat+'</div></div>' , "chat-block");
|
||||||
|
R3Ajax.audioplayer('audioplane', newmessage, false); // 播放
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('disconnect',function() {
|
||||||
|
output('<span id="connect-message">连接坐席失败,在线咨询服务不可用</span>' , 'message connect-message');
|
||||||
|
});
|
||||||
|
function sendDisconnect(){
|
||||||
|
socket.disconnect();
|
||||||
|
}
|
||||||
|
function sendMessage() {
|
||||||
|
editor.sync();
|
||||||
|
var count = editor.count("text");
|
||||||
|
if(count>0 && service_end == false){
|
||||||
|
var message = document.getElementById('message').value;
|
||||||
|
if(message!= ""){
|
||||||
|
socket.emit('message', {
|
||||||
|
appid : "${appid!''}",
|
||||||
|
userid:"${userid!''}",
|
||||||
|
type:"message" ,
|
||||||
|
session:"${sessionid!''}",
|
||||||
|
orgi:"${orgi!''}",
|
||||||
|
message : message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}else if(service_end == true){
|
||||||
|
alert("坐席已断开和您的对话");
|
||||||
|
}
|
||||||
|
editor.html('');
|
||||||
|
}
|
||||||
|
function output(message , clazz , scroll) {
|
||||||
|
if(clazz == "message connect-message"){
|
||||||
|
var messages = document.getElementsByClassName("connect-message") ;
|
||||||
|
for(inx =0 ; inx < messages.length ; ){
|
||||||
|
document.getElementById('above').removeChild(messages[inx]) ;
|
||||||
|
inx++ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var element = ("<div class='clearfix "+clazz+"'>" +" " + message + "</div>");
|
||||||
|
document.getElementById('above').innerHTML= (document.getElementById('above').innerHTML + element);
|
||||||
|
if(scroll == null || scroll == true){
|
||||||
|
document.getElementById('above').scrollTop = document.getElementById('above').scrollHeight ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function update(id , message) {
|
||||||
|
document.getElementById(id).innerHTML= message;
|
||||||
|
}
|
||||||
|
|
||||||
|
var message={
|
||||||
|
// text:data.message,
|
||||||
|
// picture:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// file:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// lang:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// goods:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// POI:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
// 回车事件
|
||||||
|
document.onkeyup=function(e){
|
||||||
|
if(!e) e=window.event;
|
||||||
|
if((e.keyCode||e.which)==13){
|
||||||
|
document.getElementById('sent').click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.onresize = function(){
|
||||||
|
R3Helper.resize();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,431 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Cache-Control" content="no-siteapp" />
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, maximum-scale=1.0, initial-scale=1.0,initial-scale=1.0,user-scalable=no" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<title>智能客服</title>
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico?t=1489039620156"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/im/css/ukefu.css">
|
||||||
|
<link rel="stylesheet" id="skin" type="text/css" href="/im/css/default/ukefu.css">
|
||||||
|
|
||||||
|
<!-- kindeditor -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="/im/js/kindeditor/themes/default/default.css">
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/jquery-1.10.2.min.js"></script>
|
||||||
|
<script src="/js/jquery.form.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/im/js/kindeditor/kindeditor.js"></script>
|
||||||
|
<script type="text/javascript" src="/im/js/kindeditor/lang/zh-CN.js"></script>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
*:not(input,textarea) {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="/im/js/socket.io.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var editor , words , textheight , wordinx = 0 ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本框根据输入内容自适应高度
|
||||||
|
* @param {HTMLElement} 输入框元素
|
||||||
|
* @param {Number} 设置光标与输入框保持的距离(默认0)
|
||||||
|
* @param {Number} 设置最大高度(可选)
|
||||||
|
*/
|
||||||
|
var autoTextarea = function (elem, extra, maxHeight) {
|
||||||
|
extra = extra || 0;
|
||||||
|
var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window,
|
||||||
|
isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera'),
|
||||||
|
addEvent = function (type, callback) {
|
||||||
|
elem.addEventListener ?
|
||||||
|
elem.addEventListener(type, callback, false) :
|
||||||
|
elem.attachEvent('on' + type, callback);
|
||||||
|
},
|
||||||
|
getStyle = elem.currentStyle ? function (name) {
|
||||||
|
var val = elem.currentStyle[name];
|
||||||
|
|
||||||
|
if (name === 'height' && val.search(/px/i) !== 1) {
|
||||||
|
var rect = elem.getBoundingClientRect();
|
||||||
|
return rect.bottom - rect.top -
|
||||||
|
parseFloat(getStyle('paddingTop')) -
|
||||||
|
parseFloat(getStyle('paddingBottom')) + 'px';
|
||||||
|
};
|
||||||
|
|
||||||
|
return val;
|
||||||
|
} : function (name) {
|
||||||
|
return getComputedStyle(elem, null)[name];
|
||||||
|
},
|
||||||
|
minHeight = parseFloat(getStyle('height'));
|
||||||
|
|
||||||
|
|
||||||
|
elem.style.resize = 'none';
|
||||||
|
|
||||||
|
var textchange = function(){
|
||||||
|
changeTextArea(38);
|
||||||
|
}
|
||||||
|
|
||||||
|
var change = function () {
|
||||||
|
changeTextArea(0);
|
||||||
|
wordinx = getPositionForTextArea(document.getElementById('message'));
|
||||||
|
};
|
||||||
|
|
||||||
|
addEvent('propertychange', textchange);
|
||||||
|
addEvent('input', textchange);
|
||||||
|
addEvent('focus', changeTextArea);
|
||||||
|
change();
|
||||||
|
};
|
||||||
|
//多行文本框
|
||||||
|
function getPositionForTextArea(ctrl) {
|
||||||
|
var CaretPos = 0;
|
||||||
|
if (document.selection) { // IE Support
|
||||||
|
ctrl.focus();
|
||||||
|
var Sel = document.selection.createRange();
|
||||||
|
var Sel2 = Sel.duplicate();
|
||||||
|
Sel2.moveToElementText(ctrl);
|
||||||
|
var CaretPos = -1;
|
||||||
|
while (Sel2.inRange(Sel)) {
|
||||||
|
Sel2.moveStart('character');
|
||||||
|
CaretPos++;
|
||||||
|
}
|
||||||
|
} else if (ctrl.selectionStart || ctrl.selectionStart == '0') { // Firefox support
|
||||||
|
CaretPos = ctrl.selectionStart;
|
||||||
|
}
|
||||||
|
return (CaretPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openFaceDialog(){
|
||||||
|
if(document.getElementById("faceindex").style.display == "none"){
|
||||||
|
document.getElementById("faceindex").style.display= "block";
|
||||||
|
document.getElementById("bottom").style.height = $('#message').height()+ 20 + document.getElementById("faceindex").offsetHeight + "px" ;
|
||||||
|
document.getElementById("above").style.height = "calc(100% - "+($('#bottom').height())+"px)"
|
||||||
|
}else{
|
||||||
|
closeFaceDialog(0);
|
||||||
|
}
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeFaceDialog(height){
|
||||||
|
document.getElementById("faceindex").style.display= "none";
|
||||||
|
document.getElementById("bottom").style.height = $('#message').height() + height + "px" ;
|
||||||
|
document.getElementById("above").style.height = "calc(100% - "+($('#message').height())+"px)" ;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeTextArea(height){
|
||||||
|
if(document.getElementById("faceindex").style.display == "none"){
|
||||||
|
$('#bottom').height($('#message').height() + height);
|
||||||
|
document.getElementById("above").style.height = "calc(100% - "+($('#message').height())+"px)"
|
||||||
|
}else{
|
||||||
|
$('#bottom').height($('#message').height() + $('#faceindex').height());
|
||||||
|
document.getElementById("above").style.height = "calc(100% - "+($('#message').height())+"px)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function insertImg(obj){
|
||||||
|
if(wordinx >= 0){
|
||||||
|
var text = $('#message').val();
|
||||||
|
var value = text.substring(0 , wordinx) + "["+obj+"]" + text.substring(wordinx , text.length);
|
||||||
|
$('#message').val(value);
|
||||||
|
wordinx = wordinx + 2 + obj.length ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(document).ready(function(){
|
||||||
|
window.addEventListener('resize', function () {
|
||||||
|
if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
|
||||||
|
window.setTimeout(function () {
|
||||||
|
document.activeElement.scrollIntoViewIfNeeded()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 在输入框获取焦点, 键盘弹起后, 真的是一行代码
|
||||||
|
|
||||||
|
$(document).on('submit.form.data-api','[data-toggle="ajax-form"]', function ( e ) {
|
||||||
|
var formValue = $(e.target) ;
|
||||||
|
$(this).ajaxSubmit({
|
||||||
|
url:formValue.attr("action"),
|
||||||
|
success: function(data){
|
||||||
|
|
||||||
|
},
|
||||||
|
error:function(xhr, type, s){
|
||||||
|
//notification("",false); //结束
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<!-- kindeditor -->
|
||||||
|
</head>
|
||||||
|
<body class="ukefu-im-theme" style="overflow:hidden;height:calc(100%);overflow-y: atuo;/* 或者scroll */-webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */" class="ukefu-point-text">
|
||||||
|
<div id="header" class="theme${inviteData.consult_dialog_color!''}">
|
||||||
|
<img
|
||||||
|
src="<#if inviteData?? && inviteData.consult_dialog_logo??>/res/image.html?id=${inviteData.consult_dialog_logo?url}<#else>/images/logo.png</#if>"
|
||||||
|
style="height:50px;padding:10px;">
|
||||||
|
|
||||||
|
<div class="ukefu-func-tab">
|
||||||
|
<ul>
|
||||||
|
<#if models?? && models["chatbot"]?? && models["chatbot"] == true && inviteData.ai?? && inviteData.ai == true && aiid??>
|
||||||
|
<li><a href="/im/index.html?appid=${appid!''}&orgi=${orgi!''}<#if aiid??>&aiid=${aiid}</#if>&ai=true<#if client??>&client=${client!''}</#if><#if type??>&type=text</#if><#if skill??>&skill=${skill!''}</#if><#if agent??>&agent=${agent!''}</#if>&userid=${userid!''}&sessionid=${sessionid!''}&t=${.now?long}">智能客服</a></li>
|
||||||
|
<li class="cur"><a href="javascript:void(0)">人工坐席</a></li>
|
||||||
|
<#else>
|
||||||
|
<li class="cur"><a href="javascript:void(0)">人工坐席</a></li>
|
||||||
|
</#if>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="cooperation" class="ukefu-cooperation" style="display:none;z-index: 100;background-color: #ffffff;position: fixed;left: 0px;width: 100%;top: 0px;top:0px;height: 100%;">
|
||||||
|
<div class='ukefu-image-canvas' id='ukefu-image-content' style="margin-top:2px;">
|
||||||
|
<img id="ukefu_img_ctx" style="max-width: 100%;max-height: 100%;">
|
||||||
|
</div>
|
||||||
|
<div class='drawBoard' style="position: absolute;left: 0;top: 0;margin-top:2px;z-index: 998;">
|
||||||
|
<canvas id="canvas-borad" class="brushBorad">你的浏览器不支持 canvas 绘图</canvas>
|
||||||
|
</div>
|
||||||
|
<div style="position: absolute;bottom: 10px;width: 100%;text-align: center;z-index:10000">
|
||||||
|
<button id="offcoop-btn" style="border-color:#009688 !important;color:#FFFFFF;display: inline-block;height: 38px;line-height: 38px;padding: 0 18px;background-color: #009688;color: #fff;white-space: nowrap;text-align: center;font-size: 14px;margin-right:10px;border: none;border-radius: 2px;cursor: pointer;opacity: .9;filter: alpha(opacity=90);background-color: #377FED !important;border:1px solid #FFFFFF;" onclick="offCoop();">退出协作</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-above" id="above" style="height:calc(100% - 60px);padding-bottom:100px;">
|
||||||
|
<div class="clearfix message welcome">
|
||||||
|
<span id="welcome-message">${(inviteData.dialog_message!'欢迎您来咨询!欢迎使用春松客服!如需帮助请联系 info@chatopera.com')?no_esc}</span>
|
||||||
|
</div>
|
||||||
|
<#if chatMessageList?? && chatMessageList.content??>
|
||||||
|
<#list chatMessageList.content?reverse as chatMessage>
|
||||||
|
<#if chatMessage.userid?? && userid?? && chatMessage.calltype?? && chatMessage.calltype = "呼入">
|
||||||
|
<div class="clearfix chat-block">
|
||||||
|
<div class="chat-right">
|
||||||
|
<img class="user-img" src="/im/img/user.png" alt="">
|
||||||
|
<div class="chat-message">
|
||||||
|
<label class="time">${chatMessage.createtime!''}</label> <label
|
||||||
|
class="user">${chatMessage.username!''}</label>
|
||||||
|
</div>
|
||||||
|
<div class="chatting-right">
|
||||||
|
<i class="arrow arrow${inviteData.consult_dialog_color!''}"></i>
|
||||||
|
<div
|
||||||
|
class="chat-content theme${inviteData.consult_dialog_color!''}"><#include
|
||||||
|
"/apps/im/media/message.html"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<#else>
|
||||||
|
<div class="clearfix chat-block">
|
||||||
|
<div class="chat-left">
|
||||||
|
<img class="user-img"
|
||||||
|
src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>"
|
||||||
|
alt="">
|
||||||
|
<div class="chat-message">
|
||||||
|
<label class="user">${chatMessage.username!''}</label> <label
|
||||||
|
class="time">${chatMessage.createtime!''}</label>
|
||||||
|
</div>
|
||||||
|
<div class="chatting-left">
|
||||||
|
<i class="arrow"></i>
|
||||||
|
<div class="chat-content"><#include "/apps/im/media/message.html"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</#if> </#list> </#if>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mobile-chat-bottom" id="bottom">
|
||||||
|
<form id="imgForm" action="/im/image/upload.html?userid=${userid!''}&appid=${appid!''}&username=${username!''}&orgi=${orgi!''}" data-toggle="ajax-form"" enctype="multipart/form-data">
|
||||||
|
<a href="javascript:;" class="imgFile" onclick="closeFaceDialog(0)">
|
||||||
|
<img src="/im/img/img.png" class="chat-type" style="width:32px;height:32px;">
|
||||||
|
<input type="file" name="imgFile" id="imgFile" accept="image/*" onChange="$('#imgForm').submit();$(this).val('');">
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
<textarea id="message" name="content" maxlength="<#if inviteData.maxwordsnum gt 0>${inviteData.maxwordsnum}<#else>300</#if>"></textarea>
|
||||||
|
<div class="btn-push clearfix" class="tools">
|
||||||
|
<img id="facedialog" onclick="return openFaceDialog()" src="/im/img/face.png" style="width:32px;height:32px;"></a>
|
||||||
|
<a href="javascript:void(0)" onClick="sendMessage();return false;"><img src="/im/img/send.png" style="width:32px;height:32px;"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="faceindex" style="display:none;height:200px;position: absolute;bottom: 0px;width:100%;overflow-x:auto;">
|
||||||
|
<table class="ke-table" cellpadding="0" cellspacing="0" border="0" style="min-width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<#list 0..4 as row>
|
||||||
|
<tr>
|
||||||
|
<#list 0..20 as col>
|
||||||
|
<td class="ke-cell"><span class="ke-img"><img
|
||||||
|
src="/im/js/kindeditor/plugins/emoticons/images/${row*20 + col}.png"
|
||||||
|
border="0" alt="" onClick="insertImg('${row*20 + col}')"></span></td>
|
||||||
|
</#list>
|
||||||
|
</tr>
|
||||||
|
</#list>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var service_end = false;
|
||||||
|
// 调查问卷
|
||||||
|
var diaShade = document.getElementById('diaShade');
|
||||||
|
var dialogWrap = document.getElementById('dialogWrap');
|
||||||
|
function popup(para) {
|
||||||
|
diaShade.style.display = para;
|
||||||
|
dialogWrap.style.display = para;
|
||||||
|
}
|
||||||
|
document.getElementById('above').scrollTop = document
|
||||||
|
.getElementById('above').scrollHeight; //滚动到 对话内容的 底部
|
||||||
|
// 参数连接
|
||||||
|
// 参数连接
|
||||||
|
var hostname = location.hostname ;
|
||||||
|
var protocol = window.location.protocol.replace(/:/g,'');
|
||||||
|
var socket = io.connect(protocol + '://'+hostname+':${port}/im/chatbot?userid=${userid!''}<#if aiid??>&aiid=${aiid}</#if>&orgi=${orgi!''}&session=${sessionid!''}&appid=${appid!''}&osname=${(osname!'')?url}&browser=${(browser!'')?url}<#if skill??>&skill=${skill}</#if><#if agent??>&agent=${agent}</#if>');
|
||||||
|
socket.on('connect',function(){
|
||||||
|
//service.sendRequestMessage();
|
||||||
|
//output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message');
|
||||||
|
})
|
||||||
|
socket.on("agentstatus",function(data){
|
||||||
|
document.getElementById('connect-message').innerHTML=data.message;
|
||||||
|
})
|
||||||
|
socket.on("status",function(data){
|
||||||
|
output('<span id="connect-message">'+data.message+'</span>' , 'message connect-message');
|
||||||
|
if(data.messageType == "end"){
|
||||||
|
service_end = true ;
|
||||||
|
//editor.readonly();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
socket.on('message', function(data) {
|
||||||
|
var chat=document.getElementsByClassName('chatting-left').innerText;
|
||||||
|
chat = data.message;
|
||||||
|
if(data.messageType == "image"){
|
||||||
|
chat = "<a href='"+data.message+"_original' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ;
|
||||||
|
}else if(data.messageType == "cooperation"){
|
||||||
|
chat = "<a href='javascript:void(0)' onclick='acceptInvite(\""+data.message+"\", \""+data.attachmentid+"\")'>您收到一个协作邀请,点击进入协作</a>" ;
|
||||||
|
}else if(data.messageType == "action"){
|
||||||
|
//检查访客是否在协作页面上,如果在协作页面上,就开始执行重绘,否则不做处理
|
||||||
|
drawCanvasImage(data.attachmentid) ;
|
||||||
|
}
|
||||||
|
if(data.calltype == "呼入"){
|
||||||
|
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">'+data.createtime+'</label><label class="user">'+data.nickName+'</label> </div><div class="chatting-right"><i class="arrow arrow${inviteData.consult_dialog_color!''}"></i><div class="chat-content theme${inviteData.consult_dialog_color!''}">'+chat+'</div></div>' , "chat-block");
|
||||||
|
}else if(data.calltype == "呼出"){
|
||||||
|
output('<div class="chat-left"> <img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt=""><div class="chat-message"><label class="user">'+data.nickName+'</label><label class="time">'+data.createtime+'</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">'+chat+'</div></div>' , "chat-block");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('disconnect',function() {
|
||||||
|
output('<span id="connect-message">连接坐席失败,在线咨询服务不可用</span>' , 'message connect-message');
|
||||||
|
});
|
||||||
|
function sendDisconnect(){
|
||||||
|
socket.disconnect();
|
||||||
|
}
|
||||||
|
function acceptInvite(msgid,fileid){
|
||||||
|
document.getElementById("cooperation").style.display = "block" ;
|
||||||
|
document.getElementById("ukefu_img_ctx").src = "/res/image.html?id=upload/"+fileid ;
|
||||||
|
|
||||||
|
$("#ukefu_img_ctx").load(function() {
|
||||||
|
var height = document.getElementById("ukefu-image-content").offsetHeight;
|
||||||
|
var width = document.getElementById("ukefu-image-content").offsetWidth;
|
||||||
|
var canvas = document.getElementById("canvas-borad") ;
|
||||||
|
if(canvas.getContext){
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
|
||||||
|
drawCanvasImage(fileid) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function drawCanvasImage(fileid){
|
||||||
|
var canvas = document.getElementById("canvas-borad") ;
|
||||||
|
|
||||||
|
if (canvas.getContext && document.getElementById("cooperation").style.display == "block") {
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
//创建新的图片对象
|
||||||
|
var img = new Image();
|
||||||
|
//指定图片的URL
|
||||||
|
img.src = "/res/image.html?id=upload/" + fileid + "_cooperation";
|
||||||
|
//浏览器加载图片完毕后再绘制图片
|
||||||
|
img.onload = function() {
|
||||||
|
ctx.clearRect(0,0,canvas.width,canvas.height);
|
||||||
|
//以Canvas画布上的坐标(10,10)为起始点,绘制图像
|
||||||
|
ctx.drawImage(img, 0, 0 , canvas.width,canvas.height);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function offCoop(){
|
||||||
|
document.getElementById("cooperation").style.display = "none" ;
|
||||||
|
}
|
||||||
|
function sendMessage() {
|
||||||
|
var count = document.getElementById('message').value.length;
|
||||||
|
if (count > 0 && service_end == false) {
|
||||||
|
var message = $("#message").val();
|
||||||
|
sendMessageText(message);
|
||||||
|
$("#message").val("");
|
||||||
|
wordinx = 0;
|
||||||
|
} else if (service_end == true) {
|
||||||
|
alert("服务器已断开和您的对话");
|
||||||
|
}
|
||||||
|
closeFaceDialog(0);
|
||||||
|
}
|
||||||
|
function sendMessageText(message) {
|
||||||
|
if (message != "") {
|
||||||
|
socket.emit('message', {
|
||||||
|
appid : "${appid!''}",
|
||||||
|
userid : "${userid!''}",
|
||||||
|
username : "${username!''}",
|
||||||
|
channel : "webim",
|
||||||
|
type : "message",
|
||||||
|
contextid : "${sessionid!''}",
|
||||||
|
orgi : "${orgi!''}",
|
||||||
|
message : message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function output(message, clazz) {
|
||||||
|
if (clazz == "message connect-message") {
|
||||||
|
var messages = document.getElementsByClassName("connect-message");
|
||||||
|
for (inx = 0; inx < messages.length;) {
|
||||||
|
document.getElementById('above').removeChild(messages[inx]);
|
||||||
|
inx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var element = ("<div class='clearfix "+clazz+"'>" + " " + message + "</div>");
|
||||||
|
document.getElementById('above').innerHTML = (document
|
||||||
|
.getElementById('above').innerHTML + element);
|
||||||
|
document.getElementById('above').scrollTop = document.getElementById('above').scrollHeight ;
|
||||||
|
//$("#welcome-message").html(document.getElementById('above').scrollHeight);
|
||||||
|
}
|
||||||
|
function update(id, message) {
|
||||||
|
document.getElementById(id).innerHTML = message;
|
||||||
|
}
|
||||||
|
autoTextarea(document.getElementById("message"));// 调用
|
||||||
|
$('#message').click(function() {
|
||||||
|
wordinx = getPositionForTextArea(document.getElementById('message'));
|
||||||
|
closeFaceDialog(44);
|
||||||
|
});
|
||||||
|
|
||||||
|
var message = {
|
||||||
|
// text:data.message,
|
||||||
|
// picture:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// file:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// lang:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// goods:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
// POI:function(){
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user