1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-08-01 16:38:02 +08:00

Merge branch 'develop' of github.com:chatopera/cosin into develop

This commit is contained in:
mukaiu 2018-11-03 18:09:09 +08:00
commit 639d6c5d73
96 changed files with 4987 additions and 4083 deletions

View File

@ -34,6 +34,8 @@
## 产品演示 ## 产品演示
* 坐席工作台
[http://cc.chatopera.com/](http://cc.chatopera.com/) [http://cc.chatopera.com/](http://cc.chatopera.com/)
@ -42,6 +44,10 @@
| admin | admin1234 | | admin | admin1234 |
* 网页端访客程序
[http://cc.chatopera.com/testclient.html](http://cc.chatopera.com/testclient.html)
## 功能 ## 功能
* 账号及组织机构管理:按组织、角色分配账号权限 * 账号及组织机构管理:按组织、角色分配账号权限

View File

@ -0,0 +1,2 @@
./app/target/
./logs/

View File

@ -1,6 +1,11 @@
FROM chatopera/java:1.0.0 FROM chatopera/java:1.0.0
MAINTAINER Hai Liang Wang <hain@chatopera.com> MAINTAINER Hai Liang Wang <hain@chatopera.com>
ARG VCS_REF
LABEL org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.vcs-url="https://github.com/chatopera/cosin"
# Set timezone # Set timezone
RUN apt-get update && \ RUN apt-get update && \
apt-get install --no-install-recommends -y tzdata && \ apt-get install --no-install-recommends -y tzdata && \
@ -26,10 +31,11 @@ RUN /bin/bash -c "mkdir -p /{data,logs}"
# build WAR # build WAR
COPY _m2/settings.xml /root/.m2/settings.xml COPY _m2/settings.xml /root/.m2/settings.xml
COPY app /app COPY app /app
COPY config /config
WORKDIR /app WORKDIR /app
RUN mvn clean package && \ RUN mvn clean package && \
rm -rf /opt/apache-tomcat/webapps/ROOT && \ rm -rf /opt/apache-tomcat/webapps/ROOT && \
cp target/contact-center-3.9.0.war /opt/apache-tomcat/webapps/ROOT.war && \ cp target/contact-center-*.war.original /opt/apache-tomcat/webapps/ROOT.war && \
rm -rf /app && \ rm -rf /app && \
rm -rf /root/.m2 rm -rf /root/.m2

View File

@ -136,11 +136,6 @@ under the License.
</server> </server>
--> -->
<server>
<id>chatopera</id>
<username>ada</username>
<password>L1OBFepgSZ</password>
</server>
</servers> </servers>
<mirrors> <mirrors>

View File

@ -13,7 +13,7 @@ PACKAGE_VERSION=1.0.0
# main # main
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return [ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
set -x
cd $appHome cd $appHome
docker build --build-arg VCS_REF=`git rev-parse --short HEAD` --force-rm=true --tag $imagename:$PACKAGE_VERSION .
docker build --force-rm=true --tag $imagename:$PACKAGE_VERSION .
docker tag $imagename:$PACKAGE_VERSION $imagename:develop docker tag $imagename:$PACKAGE_VERSION $imagename:develop

View File

@ -159,9 +159,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.hazelcast</groupId> <groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId> <artifactId>hazelcast-all</artifactId>
<version>3.8</version> <version>3.10.5</version>
<!--$NO-MVN-MAN-VER$--> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.quartz-scheduler</groupId> <groupId>org.quartz-scheduler</groupId>
@ -346,6 +346,14 @@
<attachClasses>true</attachClasses> <attachClasses>true</attachClasses>
<warSourceExcludes>**/WEB-INF</warSourceExcludes> <warSourceExcludes>**/WEB-INF</warSourceExcludes>
<packagingExcludes>**/WEB-INF,**/resources</packagingExcludes> <packagingExcludes>**/WEB-INF,**/resources</packagingExcludes>
<webResources>
<resource>
<directory>../config/sql/</directory>
<includes>
<include>cskefu-MySQL-slim.sql</include>
</includes>
</resource>
</webResources>
</configuration> </configuration>
<version>2.1.1</version> <version>2.1.1</version>
</plugin> </plugin>
@ -360,23 +368,6 @@
</plugins> </plugins>
<defaultGoal>compile</defaultGoal> <defaultGoal>compile</defaultGoal>
</build> </build>
<repositories>
<repository>
<id>SPRING-LIBS-snapshot</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
<repository>
<id>mvn_repository</id>
<name>MVNREPOSITORY</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>SPRING-LIBS-snapshot</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
</distributionManagement>
<developers> <developers>
<developer> <developer>
<id>hain</id> <id>hain</id>
@ -384,7 +375,7 @@
<email>hailiang.hl.wang@gmail.com</email> <email>hailiang.hl.wang@gmail.com</email>
<url>https://github.com/Samurais</url> <url>https://github.com/Samurais</url>
<organization>Chatopera Inc.</organization> <organization>Chatopera Inc.</organization>
<organizationUrl>http://www.chatopera.com</organizationUrl> <organizationUrl>https://www.chatopera.com</organizationUrl>
<roles> <roles>
<role>architect</role> <role>architect</role>
<role>developer</role> <role>developer</role>

View File

@ -17,8 +17,11 @@
package com.chatopera.cc.app; package com.chatopera.cc.app;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.util.mobile.MobileNumberUtils;
import com.chatopera.cc.app.config.StartedEventListener; import com.chatopera.cc.app.config.StartedEventListener;
import com.chatopera.cc.util.Constants;
import com.chatopera.cc.util.SystemEnvHelper;
import com.chatopera.cc.util.mobile.MobileNumberUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -33,6 +36,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.servlet.MultipartConfigElement; import javax.servlet.MultipartConfigElement;
import java.io.IOException; import java.io.IOException;
@ -41,9 +45,8 @@ import java.io.IOException;
@EnableJpaRepositories("com.chatopera.cc.app.persistence.repository") @EnableJpaRepositories("com.chatopera.cc.app.persistence.repository")
@EnableElasticsearchRepositories("com.chatopera.cc.app.persistence.es") @EnableElasticsearchRepositories("com.chatopera.cc.app.persistence.es")
@EnableAsync @EnableAsync
@EnableTransactionManagement
public class Application { public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${web.upload-path}") @Value("${web.upload-path}")
private String uploaddir; private String uploaddir;
@ -51,57 +54,75 @@ public class Application {
@Value("${spring.servlet.multipart.max-file-size}") @Value("${spring.servlet.multipart.max-file-size}")
private String multipartMaxUpload; private String multipartMaxUpload;
@Value("${spring.servlet.multipart.max-request-size}") @Value("${spring.servlet.multipart.max-request-size}")
private String multipartMaxRequest; private String multipartMaxRequest;
static{ /**
MainContext.model.put("contacts", true) ; * 记载模块
MainContext.model.put("sales", true); */
MainContext.model.put("chatbot", true); // 外呼模块
private final static boolean isCalloutModule = SystemEnvHelper.parseModuleFlag("CSKEFU_MODULE_CALLOUT");
// CRM模块
private final static boolean isContactsModule = SystemEnvHelper.parseModuleFlag("CSKEFU_MODULE_CONTACTS");
// 聊天机器人模块
private final static boolean isChatbotModule = SystemEnvHelper.parseModuleFlag("CSKEFU_MODULE_CHATBOT");
static {
// 外呼模块
if (isCalloutModule) {
MainContext.model.put(Constants.CSKEFU_MODULE_CALLOUT, true);
}
// CRM模块
if (isContactsModule) {
MainContext.model.put(Constants.CSKEFU_MODULE_CONTACTS, true);
}
// 聊天机器人模块
if (isChatbotModule) {
MainContext.model.put(Constants.CSKEFU_MODULE_CHATBOT, true);
}
} }
/** /**
* Init local resources * Init local resources
*/ */
protected static void init(){ protected static void init() {
try { try {
logger.info("init mobile number utils ..."); System.out.println("init mobile number utils ...");
MobileNumberUtils.init(); MobileNumberUtils.init();
} catch (IOException e) { } catch (IOException e) {
logger.error("init error ", e); e.printStackTrace();
System.exit(1); System.exit(1);
} }
} }
@Bean @Bean
public MultipartConfigElement multipartConfigElement() { public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory(); MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize(multipartMaxUpload); //KB,MB factory.setMaxFileSize(multipartMaxUpload); //KB,MB
factory.setMaxRequestSize(multipartMaxRequest); factory.setMaxRequestSize(multipartMaxRequest);
factory.setLocation(uploaddir); factory.setLocation(uploaddir);
return factory.createMultipartConfig(); return factory.createMultipartConfig();
} }
@Bean @Bean
public EmbeddedServletContainerCustomizer containerCustomizer() { public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() { return new EmbeddedServletContainerCustomizer() {
@Override @Override
public void customize(ConfigurableEmbeddedServletContainer container) { public void customize(ConfigurableEmbeddedServletContainer container) {
ErrorPage error = new ErrorPage("/error.html"); ErrorPage error = new ErrorPage("/error.html");
container.addErrorPages(error); container.addErrorPages(error);
} }
}; };
} }
public static void main(String[] args) { public static void main(String[] args) {
Application.init(); Application.init();
SpringApplication app = new SpringApplication(Application.class) ; SpringApplication app = new SpringApplication(Application.class);
app.setBannerMode(Banner.Mode.CONSOLE); app.setBannerMode(Banner.Mode.CONSOLE);
app.setAddCommandLineProperties(false); app.setAddCommandLineProperties(false);
app.addListeners(new StartedEventListener()); app.addListeners(new StartedEventListener());
MainContext.setApplicationContext(app.run(args)); MainContext.setApplicationContext(app.run(args));
} }
} }

View File

@ -16,15 +16,15 @@
*/ */
package com.chatopera.cc.app.algorithm; package com.chatopera.cc.app.algorithm;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.router.OutMessageRouter;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.aggregation.filter.AgentStatusBusyOrgiFilter; import com.chatopera.cc.aggregation.filter.AgentStatusBusyOrgiFilter;
import com.chatopera.cc.aggregation.filter.AgentStatusOrgiFilter; import com.chatopera.cc.aggregation.filter.AgentStatusOrgiFilter;
import com.chatopera.cc.aggregation.filter.AgentUserOrgiFilter; import com.chatopera.cc.aggregation.filter.AgentUserOrgiFilter;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.router.OutMessageRouter;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.*; import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.util.WebIMReport; import com.chatopera.cc.util.WebIMReport;
import com.corundumstudio.socketio.SocketIONamespace; import com.corundumstudio.socketio.SocketIONamespace;
@ -72,7 +72,6 @@ public class AutomaticServiceDist {
/** /**
* 载入坐席 ACD策略配置 * 载入坐席 ACD策略配置
* *
* @param orgi
* @return * @return
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -141,9 +140,9 @@ public class AutomaticServiceDist {
int queneUsers = 0; int queneUsers = 0;
PagingPredicate<String, AgentUser> pagingPredicate = null; PagingPredicate<String, AgentUser> pagingPredicate = null;
if (!StringUtils.isBlank(skill)) { if (StringUtils.isNotBlank(skill)) {
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND skill = '" + skill + "' AND orgi = '" + orgi + "'"), 100); pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND skill = '" + skill + "' AND orgi = '" + orgi + "'"), 100);
} else if (!StringUtils.isBlank(agent)) { } else if (StringUtils.isNotBlank(agent)) {
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND agent = '" + agent + "' AND orgi = '" + orgi + "'"), 100); pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND agent = '" + agent + "' AND orgi = '" + orgi + "'"), 100);
} else { } else {
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND orgi = '" + orgi + "'"), 100); pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND orgi = '" + orgi + "'"), 100);
@ -168,7 +167,7 @@ public class AutomaticServiceDist {
public static List<AgentStatus> getAgentStatus(String skill, String orgi) { public static List<AgentStatus> getAgentStatus(String skill, String orgi) {
PagingPredicate<String, AgentStatus> pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate("orgi = '" + orgi + "'"), 100); PagingPredicate<String, AgentStatus> pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate("orgi = '" + orgi + "'"), 100);
if (!StringUtils.isBlank(skill)) { if (StringUtils.isNotBlank(skill)) {
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate("skill = '" + skill + "' AND orgi = '" + orgi + "'"), 100); pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate("skill = '" + skill + "' AND orgi = '" + orgi + "'"), 100);
} }
List<AgentStatus> agentList = new ArrayList<AgentStatus>(); List<AgentStatus> agentList = new ArrayList<AgentStatus>();
@ -186,7 +185,7 @@ public class AutomaticServiceDist {
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentno, orgi); AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentno, orgi);
List<AgentUser> agentStatusList = new ArrayList<AgentUser>(); List<AgentUser> agentStatusList = new ArrayList<AgentUser>();
PagingPredicate<String, AgentUser> pagingPredicate = null; PagingPredicate<String, AgentUser> pagingPredicate = null;
if (agentStatus != null && !StringUtils.isBlank(agentStatus.getSkill())) { if (agentStatus != null && StringUtils.isNotBlank(agentStatus.getSkill())) {
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND ((agent = null AND skill = null) OR (skill = '" + agentStatus.getSkill() + "' AND agent = null) OR agent = '" + agentno + "') AND orgi = '" + orgi + "'"), 10); pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND ((agent = null AND skill = null) OR (skill = '" + agentStatus.getSkill() + "' AND agent = null) OR agent = '" + agentno + "') AND orgi = '" + orgi + "'"), 10);
} else { } else {
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND ((agent = null AND skill = null) OR agent = '" + agentno + "') AND orgi = '" + orgi + "'"), 10); pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND ((agent = null AND skill = null) OR agent = '" + agentno + "') AND orgi = '" + orgi + "'"), 10);
@ -207,15 +206,15 @@ public class AutomaticServiceDist {
outMessage.setNickName(agentStatus.getUsername()); outMessage.setNickName(agentStatus.getUsername());
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date())); outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
if (!StringUtils.isBlank(agentUser.getUserid())) { if (StringUtils.isNotBlank(agentUser.getUserid())) {
OutMessageRouter router = null; OutMessageRouter router = null;
router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()); router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel());
if (router != null) { if (router != null) {
router.handler(agentUser.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), agentUser.getAppid(), outMessage); router.handler(agentUser.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), agentUser.getAppid(), outMessage);
} }
} }
// TODO #111 为坐席分配访客
NettyClients.getInstance().sendAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), agentUser); NettyClients.getInstance().publishAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), agentUser);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@ -269,7 +268,7 @@ public class AutomaticServiceDist {
final boolean isPhone = MainContext.ChannelTypeEnum.PHONE.toString().equals(agentUser.getChannel()); final boolean isPhone = MainContext.ChannelTypeEnum.PHONE.toString().equals(agentUser.getChannel());
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class); AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
AgentService service = null; AgentService service = null;
if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
service = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), agentUser.getOrgi()); service = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), agentUser.getOrgi());
} }
if (service == null) {//当做留言处理 if (service == null) {//当做留言处理
@ -311,7 +310,8 @@ public class AutomaticServiceDist {
NettyClients.getInstance().sendCalloutEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.END.toString(), agentUser); NettyClients.getInstance().sendCalloutEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.END.toString(), agentUser);
} else { } else {
if (agentStatus != null) // WebIM 查看用户状态 if (agentStatus != null) // WebIM 查看用户状态
NettyClients.getInstance().sendAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.END.toString(), agentUser); // TODO #111 结束会话
NettyClients.getInstance().publishAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.END.toString(), agentUser);
OutMessageRouter router = null; OutMessageRouter router = null;
router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()); router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel());
if (router != null) { if (router != null) {
@ -392,7 +392,7 @@ public class AutomaticServiceDist {
public static void recordAgentStatus(String agent, String username, String extno, String skill, boolean admin, String userid, String status, String current, String worktype, String orgi, Date lasttime) { public static void recordAgentStatus(String agent, String username, String extno, String skill, boolean admin, String userid, String status, String current, String worktype, String orgi, Date lasttime) {
WorkMonitorRepository workMonitorRes = MainContext.getContext().getBean(WorkMonitorRepository.class); WorkMonitorRepository workMonitorRes = MainContext.getContext().getBean(WorkMonitorRepository.class);
WorkMonitor workMonitor = new WorkMonitor(); WorkMonitor workMonitor = new WorkMonitor();
if (!StringUtils.isBlank(agent) && !StringUtils.isBlank(status)) { if (StringUtils.isNotBlank(agent) && StringUtils.isNotBlank(status)) {
workMonitor.setAgent(agent); workMonitor.setAgent(agent);
workMonitor.setAgentno(agent); workMonitor.setAgentno(agent);
workMonitor.setStatus(status); workMonitor.setStatus(status);
@ -450,9 +450,9 @@ public class AutomaticServiceDist {
/** /**
* 处理ACD 技能组请求和 坐席请求 * 处理ACD 技能组请求和 坐席请求
*/ */
if (!StringUtils.isBlank(agentUser.getAgent())) { if (StringUtils.isNotBlank(agentUser.getAgent())) {
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND agentno = '" + agentUser.getAgent() + "' AND orgi = '" + orgi + "'"), 1); pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND agentno = '" + agentUser.getAgent() + "' AND orgi = '" + orgi + "'"), 1);
} else if (!StringUtils.isBlank(agentUser.getSkill())) { } else if (StringUtils.isNotBlank(agentUser.getSkill())) {
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND skill = '" + agentUser.getSkill() + "' AND orgi = '" + orgi + "'"), 1); pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND skill = '" + agentUser.getSkill() + "' AND orgi = '" + orgi + "'"), 1);
} else { } else {
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND orgi = '" + orgi + "'"), 1); pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND orgi = '" + orgi + "'"), 1);
@ -500,7 +500,8 @@ public class AutomaticServiceDist {
if (agentStatus != null) { if (agentStatus != null) {
agentService = processAgentService(agentStatus, agentUser, orgi); agentService = processAgentService(agentStatus, agentUser, orgi);
publishMessage(orgi, "invite", "success", agentno); publishMessage(orgi, "invite", "success", agentno);
NettyClients.getInstance().sendAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), agentUser); // TODO #111 为坐席分配邀请的访客
NettyClients.getInstance().publishAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), agentUser);
} else { } else {
agentService = allotAgent(agentUser, orgi); agentService = allotAgent(agentUser, orgi);
} }
@ -528,7 +529,7 @@ public class AutomaticServiceDist {
* @return * @return
* @throws Exception * @throws Exception
*/ */
public static AgentService processChatbotService(final AgentUser agentUser, final String orgi) { public static AgentService processChatbotService(final String botName, final AgentUser agentUser, final String orgi) {
AgentService agentService = new AgentService(); //放入缓存的对象 AgentService agentService = new AgentService(); //放入缓存的对象
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class); AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
Date now = new Date(); Date now = new Date();
@ -548,6 +549,8 @@ public class AutomaticServiceDist {
agentService.setRegion(agentUser.getRegion()); agentService.setRegion(agentUser.getRegion());
agentService.setUsername(agentUser.getUsername()); agentService.setUsername(agentUser.getUsername());
agentService.setChannel(agentUser.getChannel()); agentService.setChannel(agentUser.getChannel());
if (botName != null)
agentService.setAgentusername(botName);
if (StringUtils.isNotBlank(agentUser.getContextid())) { if (StringUtils.isNotBlank(agentUser.getContextid())) {
agentService.setContextid(agentUser.getContextid()); agentService.setContextid(agentUser.getContextid());
@ -579,7 +582,7 @@ public class AutomaticServiceDist {
*/ */
private static AgentService processAgentService(AgentStatus agentStatus, AgentUser agentUser, String orgi, boolean finished) throws Exception { private static AgentService processAgentService(AgentStatus agentStatus, AgentUser agentUser, String orgi, boolean finished) throws Exception {
AgentService agentService = new AgentService(); //放入缓存的对象 AgentService agentService = new AgentService(); //放入缓存的对象
if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
agentService.setId(agentUser.getAgentserviceid()); agentService.setId(agentUser.getAgentserviceid());
} }
agentService.setOrgi(orgi); agentService.setOrgi(orgi);
@ -668,20 +671,20 @@ public class AutomaticServiceDist {
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class); AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
if (!StringUtils.isBlank(agentUser.getName())) { if (StringUtils.isNotBlank(agentUser.getName())) {
agentService.setName(agentUser.getName()); agentService.setName(agentUser.getName());
} }
if (!StringUtils.isBlank(agentUser.getPhone())) { if (StringUtils.isNotBlank(agentUser.getPhone())) {
agentService.setPhone(agentUser.getPhone()); agentService.setPhone(agentUser.getPhone());
} }
if (!StringUtils.isBlank(agentUser.getEmail())) { if (StringUtils.isNotBlank(agentUser.getEmail())) {
agentService.setEmail(agentUser.getEmail()); agentService.setEmail(agentUser.getEmail());
} }
if (!StringUtils.isBlank(agentUser.getResion())) { if (StringUtils.isNotBlank(agentUser.getResion())) {
agentService.setResion(agentUser.getResion()); agentService.setResion(agentUser.getResion());
} }
if (!StringUtils.isBlank(agentUser.getSkill())) { if (StringUtils.isNotBlank(agentUser.getSkill())) {
agentService.setAgentskill(agentUser.getSkill()); agentService.setAgentskill(agentUser.getSkill());
} else if (agentStatus != null) { } else if (agentStatus != null) {
agentService.setAgentskill(agentStatus.getSkill()); agentService.setAgentskill(agentStatus.getSkill());
@ -743,7 +746,7 @@ public class AutomaticServiceDist {
agentUser.getStatus())) { agentUser.getStatus())) {
serviceFinish(agentUser, orgi); serviceFinish(agentUser, orgi);
} }
if (!StringUtils.isBlank(agentUser.getId())) { if (StringUtils.isNotBlank(agentUser.getId())) {
AgentUserRepository agentUserRes = MainContext.getContext().getBean(AgentUserRepository.class); AgentUserRepository agentUserRes = MainContext.getContext().getBean(AgentUserRepository.class);
agentUser = agentUserRes.findByIdAndOrgi(agentUser.getId(), orgi); agentUser = agentUserRes.findByIdAndOrgi(agentUser.getId(), orgi);
if (agentUser != null) { if (agentUser != null) {
@ -766,7 +769,7 @@ public class AutomaticServiceDist {
} }
SessionConfig sessionConfig = initSessionConfig(orgi); SessionConfig sessionConfig = initSessionConfig(orgi);
String successMsg = "坐席分配成功," + queneTip + "为您服务。"; String successMsg = "坐席分配成功," + queneTip + "为您服务。";
if (!StringUtils.isBlank(sessionConfig.getSuccessmsg())) { if (StringUtils.isNotBlank(sessionConfig.getSuccessmsg())) {
successMsg = sessionConfig.getSuccessmsg().replaceAll("\\{agent\\}", queneTip); successMsg = sessionConfig.getSuccessmsg().replaceAll("\\{agent\\}", queneTip);
} }
return successMsg; return successMsg;
@ -779,7 +782,7 @@ public class AutomaticServiceDist {
public static String getServiceFinishMessage(String channel, String orgi) { public static String getServiceFinishMessage(String channel, String orgi) {
SessionConfig sessionConfig = initSessionConfig(orgi); SessionConfig sessionConfig = initSessionConfig(orgi);
String queneTip = "坐席已断开和您的对话"; String queneTip = "坐席已断开和您的对话";
if (!StringUtils.isBlank(sessionConfig.getFinessmsg())) { if (StringUtils.isNotBlank(sessionConfig.getFinessmsg())) {
queneTip = sessionConfig.getFinessmsg(); queneTip = sessionConfig.getFinessmsg();
} }
return queneTip; return queneTip;
@ -795,7 +798,7 @@ public class AutomaticServiceDist {
} }
SessionConfig sessionConfig = initSessionConfig(orgi); SessionConfig sessionConfig = initSessionConfig(orgi);
String noAgentTipMsg = "坐席全忙,已进入等待队列,您也可以在其他时间再来咨询。"; String noAgentTipMsg = "坐席全忙,已进入等待队列,您也可以在其他时间再来咨询。";
if (!StringUtils.isBlank(sessionConfig.getNoagentmsg())) { if (StringUtils.isNotBlank(sessionConfig.getNoagentmsg())) {
noAgentTipMsg = sessionConfig.getNoagentmsg().replaceAll("\\{num\\}", queneTip); noAgentTipMsg = sessionConfig.getNoagentmsg().replaceAll("\\{num\\}", queneTip);
} }
return noAgentTipMsg; return noAgentTipMsg;
@ -809,7 +812,7 @@ public class AutomaticServiceDist {
} }
SessionConfig sessionConfig = initSessionConfig(orgi); SessionConfig sessionConfig = initSessionConfig(orgi);
String agentBusyTipMsg = "正在排队,请稍候,在您之前,还有 " + queneTip + " 位等待用户。"; String agentBusyTipMsg = "正在排队,请稍候,在您之前,还有 " + queneTip + " 位等待用户。";
if (!StringUtils.isBlank(sessionConfig.getAgentbusymsg())) { if (StringUtils.isNotBlank(sessionConfig.getAgentbusymsg())) {
agentBusyTipMsg = sessionConfig.getAgentbusymsg().replaceAll("\\{num\\}", queneTip); agentBusyTipMsg = sessionConfig.getAgentbusymsg().replaceAll("\\{num\\}", queneTip);
} }
return agentBusyTipMsg; return agentBusyTipMsg;

View File

@ -17,6 +17,7 @@
package com.chatopera.cc.app.basic; package com.chatopera.cc.app.basic;
import com.chatopera.cc.util.Constants;
import com.chatopera.cc.util.DateConverter; import com.chatopera.cc.util.DateConverter;
import com.chatopera.cc.app.basic.resource.ActivityResource; import com.chatopera.cc.app.basic.resource.ActivityResource;
import com.chatopera.cc.app.basic.resource.BatchResource; import com.chatopera.cc.app.basic.resource.BatchResource;
@ -409,7 +410,7 @@ public class MainContext {
return this.name; return this.name;
} }
public int getIndex(){ public int getIndex() {
return this.index; return this.index;
} }
} }
@ -986,4 +987,13 @@ public class MainContext {
public static Class<?> getResource(String resource) { public static Class<?> getResource(String resource) {
return uKeFuResourceMap.get(resource); return uKeFuResourceMap.get(resource);
} }
/**
* 是否开启外呼模块
* @return
*/
public static boolean isEnableCalloutModule() {
return model.containsKey(Constants.CSKEFU_MODULE_CALLOUT) && (model.get(Constants.CSKEFU_MODULE_CALLOUT).equals(true));
}
} }

View File

@ -766,14 +766,14 @@ public class MainUtils {
return workintTime; return workintTime;
} }
public static File processImage(File destFile, File imageFile) throws FileNotFoundException, IOException { public static File processImage(final File destFile, final File imageFile) throws FileNotFoundException, IOException {
if (imageFile != null && imageFile.exists()) { if (imageFile != null && imageFile.exists()) {
Thumbnails.of(imageFile).width(460).keepAspectRatio(true).toFile(destFile); Thumbnails.of(imageFile).width(460).keepAspectRatio(true).toFile(destFile);
} }
return destFile; return destFile;
} }
public static File scaleImage(File destFile, File imageFile, float quality) throws FileNotFoundException, IOException { public static File scaleImage(final File destFile, final File imageFile, float quality) throws FileNotFoundException, IOException {
if (imageFile != null && imageFile.exists()) { if (imageFile != null && imageFile.exists()) {
Thumbnails.of(imageFile).scale(1f).outputQuality(quality).toFile(destFile); Thumbnails.of(imageFile).scale(1f).outputQuality(quality).toFile(destFile);
} }
@ -846,45 +846,6 @@ public class MainUtils {
return execute; return execute;
} }
public static void processAttachmentFile(MultipartFile[] files, AttachmentRepository attachementRes, String path, User user, String orgi, WorkOrders workOrders, HttpServletRequest request, String dataid, String modelid) throws IOException {
if (files != null && files.length > 0) {
workOrders.setAnonymous(true);//变更用途为是否有 附件
//保存附件
for (MultipartFile file : files) {
if (file.getSize() > 0) { //文件尺寸 限制 启动 配置中 设置 的最大值其他地方不做限制
String fileid = MainUtils.md5(file.getBytes()); //使用 文件的 MD5作为 ID避免重复上传大文件
if (!StringUtils.isBlank(fileid)) {
AttachmentFile attachmentFile = new AttachmentFile();
attachmentFile.setCreater(user.getId());
attachmentFile.setOrgi(orgi);
attachmentFile.setOrgan(user.getOrgan());
attachmentFile.setDataid(dataid);
attachmentFile.setModelid(modelid);
attachmentFile.setModel(MainContext.ModelType.WORKORDERS.toString());
attachmentFile.setFilelength((int) file.getSize());
if (file.getContentType() != null && file.getContentType().length() > 255) {
attachmentFile.setFiletype(file.getContentType().substring(0, 255));
} else {
attachmentFile.setFiletype(file.getContentType());
}
if (file.getOriginalFilename() != null && file.getOriginalFilename().length() > 255) {
attachmentFile.setTitle(file.getOriginalFilename().substring(0, 255));
} else {
attachmentFile.setTitle(file.getOriginalFilename());
}
if (!StringUtils.isBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) {
attachmentFile.setImage(true);
}
attachmentFile.setFileid(fileid);
attachementRes.save(attachmentFile);
FileUtils.writeByteArrayToFile(new File(path, "app/workorders/" + fileid), file.getBytes());
}
}
}
}
}
/** /**
* 获取系统配置 * 获取系统配置
* *

View File

@ -87,7 +87,7 @@ public class IMServerConfiguration
FileInputStream in = new FileInputStream(sslFile); FileInputStream in = new FileInputStream(sslFile);
sslProperties.load(in); sslProperties.load(in);
in.close(); in.close();
if(!StringUtils.isBlank(sslProperties.getProperty("key-store")) && !StringUtils.isBlank(sslProperties.getProperty("key-store-password"))){ if(StringUtils.isNotBlank(sslProperties.getProperty("key-store")) && StringUtils.isNotBlank(sslProperties.getProperty("key-store-password"))){
config.setKeyStorePassword(MainUtils.decryption(sslProperties.getProperty("key-store-password"))); config.setKeyStorePassword(MainUtils.decryption(sslProperties.getProperty("key-store-password")));
InputStream stream = new FileInputStream(new File(path , "ssl/"+sslProperties.getProperty("key-store"))); InputStream stream = new FileInputStream(new File(path , "ssl/"+sslProperties.getProperty("key-store")));
config.setKeyStore(stream); config.setKeyStore(stream);
@ -96,7 +96,7 @@ public class IMServerConfiguration
// config.setSSLProtocol("https"); // config.setSSLProtocol("https");
int workThreads = !StringUtils.isBlank(threads) && threads.matches("[\\d]{1,6}") ? Integer.parseInt(threads) : 100 ; int workThreads = StringUtils.isNotBlank(threads) && threads.matches("[\\d]{1,6}") ? Integer.parseInt(threads) : 100 ;
config.setWorkerThreads(workThreads); config.setWorkerThreads(workThreads);
// config.setStoreFactory(new HazelcastStoreFactory()); // config.setStoreFactory(new HazelcastStoreFactory());
config.setAuthorizationListener(new AuthorizationListener() { config.setAuthorizationListener(new AuthorizationListener() {

View File

@ -15,8 +15,10 @@
*/ */
package com.chatopera.cc.app.config; package com.chatopera.cc.app.config;
import com.chatopera.cc.util.Constants;
import com.chatopera.cc.app.schedule.CallOutWireTask; import com.chatopera.cc.app.schedule.CallOutWireTask;
import com.chatopera.cc.app.schedule.WebIMAgentDispatcher;
import com.chatopera.cc.app.schedule.WebIMOnlineUserDispatcher;
import com.chatopera.cc.util.Constants;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -38,17 +40,25 @@ public class RedisConfigure {
@Autowired @Autowired
CallOutWireTask callOutWireTask; CallOutWireTask callOutWireTask;
@Autowired
WebIMAgentDispatcher webIMAgentDispatcher;
@Autowired
WebIMOnlineUserDispatcher webIMOnlineUserDispatcher;
@Bean @Bean
RedisMessageListenerContainer redisContainer() { RedisMessageListenerContainer redisContainer() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer(); final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(jedisConnectionFactory); container.setConnectionFactory(jedisConnectionFactory);
container.addMessageListener(messageListener(), pbxEvents()); container.addMessageListener(pbxMessageListener(), pbxEvents());
container.addMessageListener(imAgentDispatchListener(), imAgentEvents());
container.addMessageListener(imOnlineUserDispatchListener(), imOnlineUserEvents());
container.setTaskExecutor(Executors.newFixedThreadPool(50)); container.setTaskExecutor(Executors.newFixedThreadPool(50));
return container; return container;
} }
@Bean @Bean
MessageListenerAdapter messageListener() { MessageListenerAdapter pbxMessageListener() {
return new MessageListenerAdapter(callOutWireTask); return new MessageListenerAdapter(callOutWireTask);
} }
@ -57,4 +67,25 @@ public class RedisConfigure {
return new PatternTopic(Constants.FS_CHANNEL_FS_TO_CC); return new PatternTopic(Constants.FS_CHANNEL_FS_TO_CC);
} }
@Bean
MessageListenerAdapter imAgentDispatchListener() {
return new MessageListenerAdapter(webIMAgentDispatcher);
}
@Bean
PatternTopic imAgentEvents() {
return new PatternTopic(Constants.INSTANT_MESSAGING_WEBIM_AGENT_CHANNEL);
}
@Bean
MessageListenerAdapter imOnlineUserDispatchListener(){
return new MessageListenerAdapter(webIMOnlineUserDispatcher);
}
@Bean
PatternTopic imOnlineUserEvents() {
return new PatternTopic(Constants.INSTANT_MESSAGING_WEBIM_ONLINE_USER_CHANNEL);
}
} }

View File

@ -57,14 +57,18 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
RequestMatcher beans = new AntPathRequestMatcher("/beans/**"); RequestMatcher beans = new AntPathRequestMatcher("/beans/**");
RequestMatcher dump = new AntPathRequestMatcher("/dump/**"); RequestMatcher dump = new AntPathRequestMatcher("/dump/**");
RequestMatcher env = new AntPathRequestMatcher("/env/**"); RequestMatcher env = new AntPathRequestMatcher("/env/**");
RequestMatcher health = new AntPathRequestMatcher("/health/**");
RequestMatcher info = new AntPathRequestMatcher("/info/**"); RequestMatcher info = new AntPathRequestMatcher("/info/**");
RequestMatcher mappings = new AntPathRequestMatcher("/mappings/**"); RequestMatcher mappings = new AntPathRequestMatcher("/mappings/**");
RequestMatcher metrics = new AntPathRequestMatcher("/metrics/**");
RequestMatcher trace = new AntPathRequestMatcher("/trace/**"); RequestMatcher trace = new AntPathRequestMatcher("/trace/**");
RequestMatcher druid = new AntPathRequestMatcher("/druid/**"); RequestMatcher druid = new AntPathRequestMatcher("/druid/**");
return new DelegateRequestMatchingFilter(autconfig , configprops , beans , dump , env , health , info , mappings , metrics , trace, druid); /**
* Bypass actuator api
*/
// RequestMatcher health = new AntPathRequestMatcher("/health/**");
// RequestMatcher metrics = new AntPathRequestMatcher("/metrics/**");
// return new DelegateRequestMatchingFilter(autconfig , configprops , beans , dump , env , health , info , mappings , metrics , trace, druid);
return new DelegateRequestMatchingFilter(autconfig , configprops , beans , dump , env , mappings , trace, druid);
} }
@Bean @Bean

View File

@ -39,7 +39,7 @@ public class ApplicationController extends Handler{
view.addObject("istenantshare",super.isEnabletneant()); view.addObject("istenantshare",super.isEnabletneant());
if(super.isEnabletneant()) { if(super.isEnabletneant()) {
//多租户启用 非超级管理员 一定要选择租户才能进入界面 //多租户启用 非超级管理员 一定要选择租户才能进入界面
if(!user.isSuperuser() && !StringUtils.isBlank(user.getOrgid()) && super.isTenantconsole() && MainContext.SYSTEM_ORGI.equals(user.getOrgi())) { if(!user.isSuperuser() && StringUtils.isNotBlank(user.getOrgid()) && super.isTenantconsole() && MainContext.SYSTEM_ORGI.equals(user.getOrgi())) {
view = request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index")); view = request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
} }
if(StringUtils.isBlank(user.getOrgid())) { if(StringUtils.isBlank(user.getOrgid())) {

View File

@ -16,23 +16,19 @@
*/ */
package com.chatopera.cc.app.handler; package com.chatopera.cc.app.handler;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
import java.text.ParseException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.basic.Viewport; import com.chatopera.cc.app.basic.Viewport;
import com.chatopera.cc.exception.CSKefuException;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.repository.TenantRepository;
import com.chatopera.cc.app.handler.api.rest.QueryParams; import com.chatopera.cc.app.handler.api.rest.QueryParams;
import com.chatopera.cc.app.model.StreamingFile;
import com.chatopera.cc.app.model.SystemConfig;
import com.chatopera.cc.app.model.Tenant; import com.chatopera.cc.app.model.Tenant;
import com.chatopera.cc.app.model.User; import com.chatopera.cc.app.model.User;
import com.chatopera.cc.app.persistence.blob.JpaBlobHelper;
import com.chatopera.cc.app.persistence.repository.StreamingFileRepository;
import com.chatopera.cc.app.persistence.repository.TenantRepository;
import com.chatopera.cc.exception.CSKefuException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
@ -45,9 +41,16 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.app.model.SystemConfig; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.ParseException;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
@Controller @Controller
@ -55,59 +58,67 @@ import com.chatopera.cc.app.model.SystemConfig;
public class Handler { public class Handler {
private static final Logger logger = LoggerFactory.getLogger(Handler.class); private static final Logger logger = LoggerFactory.getLogger(Handler.class);
@Autowired @Autowired
private TenantRepository tenantRes; private TenantRepository tenantRes;
public final static int PAGE_SIZE_BG = 1 ; @Autowired
public final static int PAGE_SIZE_TW = 20 ; private JpaBlobHelper jpaBlobHelper;
public final static int PAGE_SIZE_FV = 50 ;
public final static int PAGE_SIZE_HA = 100 ; @Autowired
private StreamingFileRepository streamingFileRes;
private long starttime = System.currentTimeMillis();
public final static int PAGE_SIZE_BG = 1;
public User getUser(HttpServletRequest request){ public final static int PAGE_SIZE_TW = 20;
User user = (User) request.getSession(true).getAttribute(MainContext.USER_SESSION_NAME) ; public final static int PAGE_SIZE_FV = 50;
if(user==null){ public final static int PAGE_SIZE_HA = 100;
String authorization = request.getHeader("authorization") ;
if(StringUtils.isBlank(authorization) && request.getCookies()!=null){ private long starttime = System.currentTimeMillis();
for(Cookie cookie : request.getCookies()){
if(cookie.getName().equals("authorization")){ public User getUser(HttpServletRequest request) {
authorization = cookie.getValue() ; break ; User user = (User) request.getSession(true).getAttribute(MainContext.USER_SESSION_NAME);
} if (user == null) {
} String authorization = request.getHeader("authorization");
} if (StringUtils.isBlank(authorization) && request.getCookies() != null) {
if(!StringUtils.isBlank(authorization)){ for (Cookie cookie : request.getCookies()) {
user = (User) CacheHelper.getApiUserCacheBean().getCacheObject(authorization, MainContext.SYSTEM_ORGI) ; if (cookie.getName().equals("authorization")) {
} authorization = cookie.getValue();
if(user==null){ break;
user = new User(); }
user.setId(MainUtils.getContextID(request.getSession().getId())) ; }
user.setUsername(MainContext.GUEST_USER+"_"+ MainUtils.genIDByKey(user.getId())) ; }
user.setOrgi(MainContext.SYSTEM_ORGI); if (StringUtils.isNotBlank(authorization)) {
user.setSessionid(user.getId()) ; user = (User) CacheHelper.getApiUserCacheBean().getCacheObject(authorization, MainContext.SYSTEM_ORGI);
} }
}else{ if (user == null) {
user.setSessionid(user.getId()) ; user = new User();
} user.setId(MainUtils.getContextID(request.getSession().getId()));
return user ; user.setUsername(MainContext.GUEST_USER + "_" + MainUtils.genIDByKey(user.getId()));
} user.setOrgi(MainContext.SYSTEM_ORGI);
user.setSessionid(user.getId());
}
} else {
user.setSessionid(user.getId());
}
return user;
}
/** /**
* 构建ElasticSearch基于部门查询的Filter * 构建ElasticSearch基于部门查询的Filter
*
* @param request * @param request
* @param boolQueryBuilder * @param boolQueryBuilder
* @return * @return
* @throws CSKefuException * @throws CSKefuException
*/ */
public boolean esOrganFilter(final HttpServletRequest request, final BoolQueryBuilder boolQueryBuilder) throws CSKefuException { public boolean esOrganFilter(final HttpServletRequest request, final BoolQueryBuilder boolQueryBuilder) throws CSKefuException {
// 组合部门条件 // 组合部门条件
User u = getUser(request); User u = getUser(request);
if( u == null){ if (u == null) {
throw new CSKefuException("[esOrganFilter] 未能获取到登录用户。"); throw new CSKefuException("[esOrganFilter] 未能获取到登录用户。");
} else if(u.isSuperuser()){ } else if (u.isSuperuser()) {
// 超级管理员, 查看任何数据 // 超级管理员, 查看任何数据
return true; return true;
} else if(u.getMyorgans().size() == 0){ } else if (u.getMyorgans().size() == 0) {
// 用户没有被分配到部门返回空数据 // 用户没有被分配到部门返回空数据
return false; return false;
} else { } else {
@ -117,339 +128,367 @@ public class Handler {
return true; return true;
} }
} }
/**
*
* @param queryBuilder
* @param request
*/
public BoolQueryBuilder search(BoolQueryBuilder queryBuilder , ModelMap map, HttpServletRequest request){
queryBuilder.must(termQuery("orgi", this.getOrgi(request))) ;
//搜索框
if(!StringUtils.isBlank(request.getParameter("q"))) {
String q = request.getParameter("q") ;
q = q.replaceAll("(OR|AND|NOT|:|\\(|\\))", "") ;
if(!StringUtils.isBlank(q)){
queryBuilder.must(QueryBuilders.boolQuery().must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND))) ;
map.put("q", q) ;
}
}
//筛选表单
if(!StringUtils.isBlank(request.getParameter("filterid"))) {
queryBuilder.must(termQuery("filterid", request.getParameter("filterid"))) ;
map.put("filterid", request.getParameter("filterid")) ;
}
//批次
if(!StringUtils.isBlank(request.getParameter("batid"))) {
queryBuilder.must(termQuery("batid", request.getParameter("batid"))) ;
map.put("batid", request.getParameter("batid")) ;
}
//活动
if(!StringUtils.isBlank(request.getParameter("actid"))) {
queryBuilder.must(termQuery("actid", request.getParameter("actid"))) ;
map.put("actid", request.getParameter("actid")) ;
}
//业务状态
if(!StringUtils.isBlank(request.getParameter("workstatus"))) {
queryBuilder.must(termQuery("workstatus", request.getParameter("workstatus"))) ;
map.put("workstatus", request.getParameter("workstatus")) ;
}
//拨打状态
if(!StringUtils.isBlank(request.getParameter("callstatus"))) {
queryBuilder.must(termQuery("callstatus", request.getParameter("callstatus"))) ;
map.put("callstatus", request.getParameter("callstatus")) ;
}
//预约状态
if(!StringUtils.isBlank(request.getParameter("apstatus"))) {
queryBuilder.must(termQuery("apstatus", request.getParameter("apstatus"))) ;
map.put("apstatus", request.getParameter("apstatus")) ;
}
RangeQueryBuilder rangeQuery = null ;
//拨打时间区间查询
if(!StringUtils.isBlank(request.getParameter("callbegin")) || !StringUtils.isBlank(request.getParameter("callend"))){
if(!StringUtils.isBlank(request.getParameter("callbegin"))) {
try {
rangeQuery = QueryBuilders.rangeQuery("calltime").from(MainUtils.dateFormate.parse(request.getParameter("callbegin")).getTime()) ;
} catch (ParseException e) {
e.printStackTrace();
}
}
if(!StringUtils.isBlank(request.getParameter("callend")) ) {
try {
if(rangeQuery == null) {
rangeQuery = QueryBuilders.rangeQuery("calltime").to(MainUtils.dateFormate.parse(request.getParameter("callend")).getTime()) ;
}else {
rangeQuery.to(MainUtils.dateFormate.parse(request.getParameter("callend")).getTime()) ;
}
} catch (ParseException e) {
e.printStackTrace();
}
}
map.put("callbegin", request.getParameter("callbegin")) ;
map.put("callend", request.getParameter("callend")) ;
}
//预约时间区间查询
if(!StringUtils.isBlank(request.getParameter("apbegin")) || !StringUtils.isBlank(request.getParameter("apend"))){
if(!StringUtils.isBlank(request.getParameter("apbegin"))) {
try {
rangeQuery = QueryBuilders.rangeQuery("aptime").from(MainUtils.dateFormate.parse(request.getParameter("apbegin")).getTime()) ;
} catch (ParseException e) {
e.printStackTrace();
}
}
if(!StringUtils.isBlank(request.getParameter("apend")) ) {
try {
if(rangeQuery == null) {
rangeQuery = QueryBuilders.rangeQuery("aptime").to(MainUtils.dateFormate.parse(request.getParameter("apend")).getTime()) ;
}else {
rangeQuery.to(MainUtils.dateFormate.parse(request.getParameter("apend")).getTime()) ;
}
} catch (ParseException e) {
e.printStackTrace();
}
}
map.put("apbegin", request.getParameter("apbegin")) ;
map.put("apend", request.getParameter("apend")) ;
}
if(rangeQuery!=null) {
queryBuilder.must(rangeQuery) ;
}
//外呼任务id
if(!StringUtils.isBlank(request.getParameter("taskid"))) {
queryBuilder.must(termQuery("taskid", request.getParameter("taskid"))) ;
map.put("taskid", request.getParameter("taskid")) ;
}
//坐席
if(!StringUtils.isBlank(request.getParameter("owneruser"))) {
queryBuilder.must(termQuery("owneruser", request.getParameter("owneruser"))) ;
map.put("owneruser", request.getParameter("owneruser")) ;
}
//部门
if(!StringUtils.isBlank(request.getParameter("ownerdept"))) {
queryBuilder.must(termQuery("ownerdept", request.getParameter("ownerdept"))) ;
map.put("ownerdept", request.getParameter("ownerdept")) ;
}
//分配状态
if(!StringUtils.isBlank(request.getParameter("status"))) {
queryBuilder.must(termQuery("status", request.getParameter("status"))) ;
map.put("status", request.getParameter("status")) ;
}
return queryBuilder ; /**
} * @param queryBuilder
* @param request
public User getIMUser(HttpServletRequest request , String userid , String nickname){ */
User user = (User) request.getSession(true).getAttribute(MainContext.IM_USER_SESSION_NAME) ; public BoolQueryBuilder search(BoolQueryBuilder queryBuilder, ModelMap map, HttpServletRequest request) {
if(user==null){ queryBuilder.must(termQuery("orgi", this.getOrgi(request)));
user = new User();
if(!StringUtils.isBlank(userid)){
user.setId(userid) ;
}else{
user.setId(MainUtils.getContextID(request.getSession().getId())) ;
}
if(!StringUtils.isBlank(nickname)){
user.setUsername(nickname);
}else{
user.setUsername(MainContext.GUEST_USER+"_"+ MainUtils.genIDByKey(user.getId())) ;
}
user.setSessionid(user.getId()) ;
}else{
user.setSessionid(MainUtils.getContextID(request.getSession().getId())) ;
}
return user ;
}
public void setUser(HttpServletRequest request , User user){
request.getSession(true).removeAttribute(MainContext.USER_SESSION_NAME) ;
request.getSession(true).setAttribute(MainContext.USER_SESSION_NAME , user) ;
}
/** //搜索框
* 创建系统监控的 模板页面 if (StringUtils.isNotBlank(request.getParameter("q"))) {
* @param page String q = request.getParameter("q");
* @return q = q.replaceAll("(OR|AND|NOT|:|\\(|\\))", "");
*/ if (StringUtils.isNotBlank(q)) {
public Viewport createAdminTempletResponse(String page) { queryBuilder.must(QueryBuilders.boolQuery().must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)));
return new Viewport("/admin/include/tpl" , page); map.put("q", q);
} }
/** }
* 创建系统监控的 模板页面
* @param page //筛选表单
* @return if (StringUtils.isNotBlank(request.getParameter("filterid"))) {
*/ queryBuilder.must(termQuery("filterid", request.getParameter("filterid")));
public Viewport createAppsTempletResponse(String page) { map.put("filterid", request.getParameter("filterid"));
return new Viewport("/apps/include/tpl" , page); }
}
//批次
/** if (StringUtils.isNotBlank(request.getParameter("batid"))) {
* 创建系统监控的 模板页面 queryBuilder.must(termQuery("batid", request.getParameter("batid")));
* @param page map.put("batid", request.getParameter("batid"));
* @return }
*/
public Viewport createEntIMTempletResponse(String page) { //活动
return new Viewport("/apps/entim/include/tpl" , page); if (StringUtils.isNotBlank(request.getParameter("actid"))) {
} queryBuilder.must(termQuery("actid", request.getParameter("actid")));
map.put("actid", request.getParameter("actid"));
public Viewport createRequestPageTempletResponse(String page) { }
return new Viewport(page);
} //业务状态
if (StringUtils.isNotBlank(request.getParameter("workstatus"))) {
/** queryBuilder.must(termQuery("workstatus", request.getParameter("workstatus")));
* map.put("workstatus", request.getParameter("workstatus"));
* @param data }
* @return
*/ //拨打状态
public ModelAndView request(Viewport data) { if (StringUtils.isNotBlank(request.getParameter("callstatus"))) {
return new ModelAndView(data.getTemplet()!=null ? data.getTemplet(): data.getPage() , "data", data) ; queryBuilder.must(termQuery("callstatus", request.getParameter("callstatus")));
map.put("callstatus", request.getParameter("callstatus"));
}
//预约状态
if (StringUtils.isNotBlank(request.getParameter("apstatus"))) {
queryBuilder.must(termQuery("apstatus", request.getParameter("apstatus")));
map.put("apstatus", request.getParameter("apstatus"));
}
RangeQueryBuilder rangeQuery = null;
//拨打时间区间查询
if (StringUtils.isNotBlank(request.getParameter("callbegin")) || StringUtils.isNotBlank(request.getParameter("callend"))) {
if (StringUtils.isNotBlank(request.getParameter("callbegin"))) {
try {
rangeQuery = QueryBuilders.rangeQuery("calltime").from(MainUtils.dateFormate.parse(request.getParameter("callbegin")).getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
if (StringUtils.isNotBlank(request.getParameter("callend"))) {
try {
if (rangeQuery == null) {
rangeQuery = QueryBuilders.rangeQuery("calltime").to(MainUtils.dateFormate.parse(request.getParameter("callend")).getTime());
} else {
rangeQuery.to(MainUtils.dateFormate.parse(request.getParameter("callend")).getTime());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
map.put("callbegin", request.getParameter("callbegin"));
map.put("callend", request.getParameter("callend"));
}
//预约时间区间查询
if (StringUtils.isNotBlank(request.getParameter("apbegin")) || StringUtils.isNotBlank(request.getParameter("apend"))) {
if (StringUtils.isNotBlank(request.getParameter("apbegin"))) {
try {
rangeQuery = QueryBuilders.rangeQuery("aptime").from(MainUtils.dateFormate.parse(request.getParameter("apbegin")).getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
if (StringUtils.isNotBlank(request.getParameter("apend"))) {
try {
if (rangeQuery == null) {
rangeQuery = QueryBuilders.rangeQuery("aptime").to(MainUtils.dateFormate.parse(request.getParameter("apend")).getTime());
} else {
rangeQuery.to(MainUtils.dateFormate.parse(request.getParameter("apend")).getTime());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
map.put("apbegin", request.getParameter("apbegin"));
map.put("apend", request.getParameter("apend"));
}
if (rangeQuery != null) {
queryBuilder.must(rangeQuery);
}
//外呼任务id
if (StringUtils.isNotBlank(request.getParameter("taskid"))) {
queryBuilder.must(termQuery("taskid", request.getParameter("taskid")));
map.put("taskid", request.getParameter("taskid"));
}
//坐席
if (StringUtils.isNotBlank(request.getParameter("owneruser"))) {
queryBuilder.must(termQuery("owneruser", request.getParameter("owneruser")));
map.put("owneruser", request.getParameter("owneruser"));
}
//部门
if (StringUtils.isNotBlank(request.getParameter("ownerdept"))) {
queryBuilder.must(termQuery("ownerdept", request.getParameter("ownerdept")));
map.put("ownerdept", request.getParameter("ownerdept"));
}
//分配状态
if (StringUtils.isNotBlank(request.getParameter("status"))) {
queryBuilder.must(termQuery("status", request.getParameter("status")));
map.put("status", request.getParameter("status"));
}
return queryBuilder;
} }
public int getP(HttpServletRequest request) { public User getIMUser(HttpServletRequest request, String userid, String nickname) {
int page = 0; User user = (User) request.getSession(true).getAttribute(MainContext.IM_USER_SESSION_NAME);
String p = request.getParameter("p") ; if (user == null) {
if(!StringUtils.isBlank(p) && p.matches("[\\d]*")){ user = new User();
page = Integer.parseInt(p) ; if (StringUtils.isNotBlank(userid)) {
if(page > 0){ user.setId(userid);
page = page - 1 ; } else {
} user.setId(MainUtils.getContextID(request.getSession().getId()));
} }
return page; if (StringUtils.isNotBlank(nickname)) {
} user.setUsername(nickname);
} else {
public int getPs(HttpServletRequest request) { user.setUsername(MainContext.GUEST_USER + "_" + MainUtils.genIDByKey(user.getId()));
int pagesize = PAGE_SIZE_TW; }
String ps = request.getParameter("ps") ; user.setSessionid(user.getId());
if(!StringUtils.isBlank(ps) && ps.matches("[\\d]*")){ } else {
pagesize = Integer.parseInt(ps) ; user.setSessionid(MainUtils.getContextID(request.getSession().getId()));
} }
return pagesize; return user;
} }
public int getP(QueryParams params) { public void setUser(HttpServletRequest request, User user) {
int page = 0; request.getSession(true).removeAttribute(MainContext.USER_SESSION_NAME);
if(params!=null && !StringUtils.isBlank(params.getP()) && params.getP().matches("[\\d]*")){ request.getSession(true).setAttribute(MainContext.USER_SESSION_NAME, user);
page = Integer.parseInt(params.getP()) ; }
if(page > 0){
page = page - 1 ;
} /**
} * 创建系统监控的 模板页面
return page; *
} * @param page
* @return
public int getPs(QueryParams params) { */
int pagesize = PAGE_SIZE_TW; public Viewport createAdminTempletResponse(String page) {
if(params != null && !StringUtils.isBlank(params.getPs()) && params.getPs().matches("[\\d]*")){ return new Viewport("/admin/include/tpl", page);
pagesize = Integer.parseInt(params.getPs()) ; }
}
return pagesize; /**
} * 创建系统监控的 模板页面
*
* @param page
public int get50Ps(HttpServletRequest request) { * @return
int pagesize = PAGE_SIZE_FV; */
String ps = request.getParameter("ps") ; public Viewport createAppsTempletResponse(String page) {
if(!StringUtils.isBlank(ps) && ps.matches("[\\d]*")){ return new Viewport("/apps/include/tpl", page);
pagesize = Integer.parseInt(ps) ; }
}
return pagesize; /**
} * 创建系统监控的 模板页面
*
public String getOrgi(HttpServletRequest request){ * @param page
return getUser(request).getOrgi(); * @return
} */
/** public Viewport createEntIMTempletResponse(String page) {
* 机构id return new Viewport("/apps/entim/include/tpl", page);
* @param request }
* @return
*/ public Viewport createRequestPageTempletResponse(String page) {
public String getOrgid(HttpServletRequest request){ return new Viewport(page);
User u = getUser(request); }
return u.getOrgid();
} /**
* @param data
public Tenant getTenant(HttpServletRequest request){ * @return
return tenantRes.findById(getOrgi(request)); */
} public ModelAndView request(Viewport data) {
/** return new ModelAndView(data.getTemplet() != null ? data.getTemplet() : data.getPage(), "data", data);
* 根据是否租户共享获取orgi }
* @param request
* @return public int getP(HttpServletRequest request) {
*/ int page = 0;
public String getOrgiByTenantshare(HttpServletRequest request){ String p = request.getParameter("p");
SystemConfig systemConfig = MainUtils.getSystemConfig(); if (StringUtils.isNotBlank(p) && p.matches("[\\d]*")) {
if(systemConfig!=null&&systemConfig.isEnabletneant()&&systemConfig.isTenantshare()) { page = Integer.parseInt(p);
User user = this.getUser(request) ; if (page > 0) {
return user.getOrgid(); page = page - 1;
} }
return getOrgi(request); }
} return page;
}
/**
* 判断是否租户共享 public int getPs(HttpServletRequest request) {
* @return int pagesize = PAGE_SIZE_TW;
*/ String ps = request.getParameter("ps");
public boolean isTenantshare(){ if (StringUtils.isNotBlank(ps) && ps.matches("[\\d]*")) {
SystemConfig systemConfig = MainUtils.getSystemConfig(); pagesize = Integer.parseInt(ps);
if(systemConfig!=null&&systemConfig.isEnabletneant()&&systemConfig.isTenantshare()) { }
return true; return pagesize;
} }
return false;
} public int getP(QueryParams params) {
int page = 0;
/** if (params != null && StringUtils.isNotBlank(params.getP()) && params.getP().matches("[\\d]*")) {
* 判断是否多租户 page = Integer.parseInt(params.getP());
* @return if (page > 0) {
*/ page = page - 1;
public boolean isEnabletneant(){ }
SystemConfig systemConfig = MainUtils.getSystemConfig(); }
if(systemConfig!=null&&systemConfig.isEnabletneant()) { return page;
return true; }
}
return false; public int getPs(QueryParams params) {
} int pagesize = PAGE_SIZE_TW;
/** if (params != null && StringUtils.isNotBlank(params.getPs()) && params.getPs().matches("[\\d]*")) {
* 判断是否多租户 pagesize = Integer.parseInt(params.getPs());
* @return }
*/ return pagesize;
public boolean isTenantconsole(){ }
SystemConfig systemConfig = MainUtils.getSystemConfig();
if(systemConfig!=null&&systemConfig.isEnabletneant()&&systemConfig.isTenantconsole()) {
return true; public int get50Ps(HttpServletRequest request) {
} int pagesize = PAGE_SIZE_FV;
return false; String ps = request.getParameter("ps");
} if (StringUtils.isNotBlank(ps) && ps.matches("[\\d]*")) {
pagesize = Integer.parseInt(ps);
}
return pagesize;
}
public String getOrgi(HttpServletRequest request) {
return getUser(request).getOrgi();
}
/**
* 机构id
*
* @param request
* @return
*/
public String getOrgid(HttpServletRequest request) {
User u = getUser(request);
return u.getOrgid();
}
public Tenant getTenant(HttpServletRequest request) {
return tenantRes.findById(getOrgi(request));
}
/**
* 根据是否租户共享获取orgi
*
* @param request
* @return
*/
public String getOrgiByTenantshare(HttpServletRequest request) {
SystemConfig systemConfig = MainUtils.getSystemConfig();
if (systemConfig != null && systemConfig.isEnabletneant() && systemConfig.isTenantshare()) {
User user = this.getUser(request);
return user.getOrgid();
}
return getOrgi(request);
}
/**
* 判断是否租户共享
*
* @return
*/
public boolean isTenantshare() {
SystemConfig systemConfig = MainUtils.getSystemConfig();
if (systemConfig != null && systemConfig.isEnabletneant() && systemConfig.isTenantshare()) {
return true;
}
return false;
}
/**
* 判断是否多租户
*
* @return
*/
public boolean isEnabletneant() {
SystemConfig systemConfig = MainUtils.getSystemConfig();
if (systemConfig != null && systemConfig.isEnabletneant()) {
return true;
}
return false;
}
/**
* 判断是否多租户
*
* @return
*/
public boolean isTenantconsole() {
SystemConfig systemConfig = MainUtils.getSystemConfig();
if (systemConfig != null && systemConfig.isEnabletneant() && systemConfig.isTenantconsole()) {
return true;
}
return false;
}
public long getStarttime() {
return starttime;
}
public void setStarttime(long starttime) {
this.starttime = starttime;
}
/**
* 使用Blob保存文件
* @param multipart
* @return id
* @throws IOException
*/
public String saveImageFileWithMultipart(MultipartFile multipart) throws IOException {
StreamingFile sf = new StreamingFile();
final String fileid = MainUtils.getUUID();
sf.setId(fileid);
sf.setMime(multipart.getContentType());
sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize()));
sf.setName(multipart.getOriginalFilename());
streamingFileRes.save(sf);
return fileid;
}
public long getStarttime() {
return starttime;
}
public void setStarttime(long starttime) {
this.starttime = starttime;
}
} }

View File

@ -18,13 +18,13 @@ package com.chatopera.cc.app.handler;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.OrganRepository; import com.chatopera.cc.app.persistence.repository.OrganRepository;
import com.chatopera.cc.app.persistence.repository.RoleAuthRepository; import com.chatopera.cc.app.persistence.repository.RoleAuthRepository;
import com.chatopera.cc.app.persistence.repository.UserRepository; import com.chatopera.cc.app.persistence.repository.UserRepository;
import com.chatopera.cc.app.persistence.repository.UserRoleRepository; import com.chatopera.cc.app.persistence.repository.UserRoleRepository;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.util.OnlineUserUtils; import com.chatopera.cc.util.OnlineUserUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -78,10 +78,18 @@ public class LoginController extends Handler {
private void organs(final User user, final String organ) { private void organs(final User user, final String organ) {
if (organ == null) if (organ == null)
return; return;
if (user.inMyorgans(organ))
return;
user.getMyorgans().add(organ); user.getMyorgans().add(organ);
List<Organ> y = organRepository.findByOrgiAndParent(user.getOrgi(), organ); List<Organ> y = organRepository.findByOrgiAndParent(user.getOrgi(), organ);
for (Organ x : y) { for (Organ x : y) {
organs(user, x.getId()); try {
organs(user, x.getId());
} catch (Exception e) {
logger.error("organs", e);
}
} }
} }

View File

@ -16,300 +16,275 @@
*/ */
package com.chatopera.cc.app.handler.admin.channel; package com.chatopera.cc.app.handler.admin.channel;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.handler.Handler; import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.model.CousultInvite; import com.chatopera.cc.app.model.CousultInvite;
import com.chatopera.cc.app.model.Organ; import com.chatopera.cc.app.model.Organ;
import com.chatopera.cc.app.model.OrgiSkillRel; import com.chatopera.cc.app.model.OrgiSkillRel;
import com.chatopera.cc.app.model.User; import com.chatopera.cc.app.model.User;
import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.util.Menu;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.app.persistence.repository.ConsultInviteRepository; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.persistence.repository.OrganRepository; import javax.validation.Valid;
import com.chatopera.cc.app.persistence.repository.OrgiSkillRelRepository; import java.io.IOException;
import com.chatopera.cc.app.persistence.repository.SNSAccountRepository; import java.util.ArrayList;
import com.chatopera.cc.app.persistence.repository.ServiceAiRepository; import java.util.List;
import com.chatopera.cc.app.persistence.repository.UserRepository;
@Controller @Controller
@RequestMapping("/admin/webim") @RequestMapping("/admin/webim")
public class WebIMController extends Handler { public class WebIMController extends Handler {
private final static Logger logger = LoggerFactory.getLogger(WebIMController.class);
@Autowired
private ConsultInviteRepository invite; @Autowired
private ConsultInviteRepository invite;
@Autowired
private OrganRepository organRes ; @Autowired
private OrganRepository organRes;
@Autowired
private UserRepository userRes ; @Autowired
private UserRepository userRes;
@Autowired
private ServiceAiRepository serviceAiRes ; @Autowired
private ServiceAiRepository serviceAiRes;
@Autowired
private OrgiSkillRelRepository orgiSkillRelService; @Autowired
private OrgiSkillRelRepository orgiSkillRelService;
@Value("${web.upload-path}")
@Value("${web.upload-path}")
private String path; private String path;
@Autowired @Autowired
private SNSAccountRepository snsAccountRes; private SNSAccountRepository snsAccountRes;
@RequestMapping("/index") @RequestMapping("/index")
@Menu(type = "app" , subtype = "app" , admin= true) @Menu(type = "app", subtype = "app", admin = true)
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String snsid) { public ModelAndView index(ModelMap map, HttpServletRequest request, @Valid String snsid) {
CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsid, super.getOrgi(request)) ; CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsid, super.getOrgi(request));
if(coultInvite!=null){ logger.info("[index] snsaccount Id {}, AiFirst {}", coultInvite.getSnsaccountid(), coultInvite.isAifirst());
map.addAttribute("inviteData", coultInvite);
map.addAttribute("skillList", getOrgans(request)) ; if (coultInvite != null) {
map.addAttribute("agentList",getUsers(request)) ; map.addAttribute("inviteData", coultInvite);
map.addAttribute("skillList", getOrgans(request));
map.addAttribute("import", request.getServerPort()) ; map.addAttribute("agentList", getUsers(request));
map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(snsid, super.getOrgi(request))) ; map.addAttribute("import", request.getServerPort());
}
return request(super.createAdminTempletResponse("/admin/app/index")); map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(snsid, super.getOrgi(request)));
}
return request(super.createAdminTempletResponse("/admin/webim/index"));
} }
@RequestMapping("/save") @RequestMapping("/save")
@Menu(type = "admin" , subtype = "app" , admin= true) @Menu(type = "admin", subtype = "app", admin = true)
public ModelAndView save(HttpServletRequest request , @Valid CousultInvite inviteData , @RequestParam(value = "webimlogo", required = false) MultipartFile webimlogo,@RequestParam(value = "agentheadimg", required = false) MultipartFile agentheadimg) throws IOException { public ModelAndView save(HttpServletRequest request, @Valid CousultInvite inviteData, @RequestParam(value = "webimlogo", required = false) MultipartFile webimlogo, @RequestParam(value = "agentheadimg", required = false) MultipartFile agentheadimg) throws IOException {
if(!StringUtils.isBlank(inviteData.getSnsaccountid())){ if (StringUtils.isNotBlank(inviteData.getSnsaccountid())) {
CousultInvite tempData = invite.findBySnsaccountidAndOrgi(inviteData.getSnsaccountid() , super.getOrgi(request)) ; CousultInvite tempData = invite.findBySnsaccountidAndOrgi(inviteData.getSnsaccountid(), super.getOrgi(request));
if(tempData!=null){ if (tempData != null) {
tempData.setConsult_vsitorbtn_model(inviteData.getConsult_vsitorbtn_model()); tempData.setConsult_vsitorbtn_model(inviteData.getConsult_vsitorbtn_model());
tempData.setConsult_vsitorbtn_color(inviteData.getConsult_vsitorbtn_color()); tempData.setConsult_vsitorbtn_color(inviteData.getConsult_vsitorbtn_color());
tempData.setConsult_vsitorbtn_position(inviteData.getConsult_vsitorbtn_position()); tempData.setConsult_vsitorbtn_position(inviteData.getConsult_vsitorbtn_position());
tempData.setConsult_vsitorbtn_content(inviteData.getConsult_vsitorbtn_content()); tempData.setConsult_vsitorbtn_content(inviteData.getConsult_vsitorbtn_content());
tempData.setConsult_vsitorbtn_display(inviteData.getConsult_vsitorbtn_display()); tempData.setConsult_vsitorbtn_display(inviteData.getConsult_vsitorbtn_display());
tempData.setConsult_dialog_color(inviteData.getConsult_dialog_color()); tempData.setConsult_dialog_color(inviteData.getConsult_dialog_color());
inviteData = tempData;
inviteData = tempData ; }
} } else {
}else{ inviteData.setSnsaccountid(super.getUser(request).getId());
inviteData.setSnsaccountid(super.getUser(request).getId()); }
} inviteData.setOrgi(super.getOrgi(request));
inviteData.setOrgi(super.getOrgi(request)); // 网页品牌标识
if(webimlogo!=null && webimlogo.getOriginalFilename().lastIndexOf(".") > 0){ if (webimlogo != null && webimlogo.getOriginalFilename().lastIndexOf(".") > 0) {
File logoDir = new File(path , "logo"); inviteData.setConsult_dialog_logo(super.saveImageFileWithMultipart(webimlogo));
if(!logoDir.exists()){ }
logoDir.mkdirs() ;
} // 网页坐席头像
String fileName = "logo/"+inviteData.getId()+webimlogo.getOriginalFilename().substring(webimlogo.getOriginalFilename().lastIndexOf(".")) ; if (agentheadimg != null && agentheadimg.getOriginalFilename().lastIndexOf(".") > 0) {
FileCopyUtils.copy(webimlogo.getBytes(), new File(path , fileName)); inviteData.setConsult_dialog_headimg(super.saveImageFileWithMultipart(agentheadimg));
inviteData.setConsult_dialog_logo(fileName); }
} invite.save(inviteData);
if(agentheadimg!=null && agentheadimg.getOriginalFilename().lastIndexOf(".") > 0){ CacheHelper.getSystemCacheBean().put(inviteData.getSnsaccountid(), inviteData, inviteData.getOrgi());
File headimgDir = new File(path , "headimg"); return request(super.createRequestPageTempletResponse("redirect:/admin/webim/index.html?snsid=" + inviteData.getSnsaccountid()));
if(!headimgDir.exists()){
headimgDir.mkdirs() ;
}
String fileName = "headimg/"+inviteData.getId()+agentheadimg.getOriginalFilename().substring(agentheadimg.getOriginalFilename().lastIndexOf(".")) ;
FileCopyUtils.copy(agentheadimg.getBytes(), new File(path , fileName));
inviteData.setConsult_dialog_headimg(fileName);
}
invite.save(inviteData) ;
CacheHelper.getSystemCacheBean().put(inviteData.getSnsaccountid(), inviteData, inviteData.getOrgi());
return request(super.createRequestPageTempletResponse("redirect:/admin/app/index.html?snsid="+inviteData.getSnsaccountid()));
} }
@RequestMapping("/profile") @RequestMapping("/profile")
@Menu(type = "app" , subtype = "profile" , admin= true) @Menu(type = "app", subtype = "profile", admin = true)
public ModelAndView profile(ModelMap map , HttpServletRequest request , @Valid String snsid) { public ModelAndView profile(ModelMap map, HttpServletRequest request, @Valid String snsid) {
CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsid, super.getOrgi(request)) ; CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsid, super.getOrgi(request));
if(coultInvite!=null){ if (coultInvite != null) {
map.addAttribute("inviteData", coultInvite); map.addAttribute("inviteData", coultInvite);
} }
map.addAttribute("import", request.getServerPort()) ; map.addAttribute("import", request.getServerPort());
map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(snsid, super.getOrgi(request))) ; map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(snsid, super.getOrgi(request)));
map.put("serviceAiList",serviceAiRes.findByOrgi(super.getOrgi(request)) ) ; map.put("serviceAiList", serviceAiRes.findByOrgi(super.getOrgi(request)));
return request(super.createAdminTempletResponse("/admin/app/profile")); return request(super.createAdminTempletResponse("/admin/webim/profile"));
} }
@RequestMapping("/profile/save") @RequestMapping("/profile/save")
@Menu(type = "admin" , subtype = "profile" , admin= true) @Menu(type = "admin", subtype = "profile", admin = true)
public ModelAndView saveprofile(HttpServletRequest request , @Valid CousultInvite inviteData, @RequestParam(value = "dialogad", required = false) MultipartFile dialogad) throws IOException { public ModelAndView saveprofile(HttpServletRequest request, @Valid CousultInvite inviteData, @RequestParam(value = "dialogad", required = false) MultipartFile dialogad) throws IOException {
CousultInvite tempInviteData ; CousultInvite tempInviteData;
if(inviteData!=null && !StringUtils.isBlank(inviteData.getId())){ if (inviteData != null && StringUtils.isNotBlank(inviteData.getId())) {
tempInviteData = invite.findOne(inviteData.getId()) ; tempInviteData = invite.findOne(inviteData.getId());
if(tempInviteData!=null){ if (tempInviteData != null) {
tempInviteData.setDialog_name(inviteData.getDialog_name()); tempInviteData.setDialog_name(inviteData.getDialog_name());
tempInviteData.setDialog_address(inviteData.getDialog_address()); tempInviteData.setDialog_address(inviteData.getDialog_address());
tempInviteData.setDialog_phone(inviteData.getDialog_phone()); tempInviteData.setDialog_phone(inviteData.getDialog_phone());
tempInviteData.setDialog_mail(inviteData.getDialog_mail()); tempInviteData.setDialog_mail(inviteData.getDialog_mail());
tempInviteData.setDialog_introduction(inviteData.getDialog_introduction()); tempInviteData.setDialog_introduction(inviteData.getDialog_introduction());
tempInviteData.setDialog_message(inviteData.getDialog_message()); tempInviteData.setDialog_message(inviteData.getDialog_message());
tempInviteData.setLeavemessage(inviteData.isLeavemessage()) ; tempInviteData.setLeavemessage(inviteData.isLeavemessage());
tempInviteData.setLvmopentype(inviteData.getLvmopentype()); tempInviteData.setLvmopentype(inviteData.getLvmopentype());
tempInviteData.setLvmname(inviteData.isLvmname()); tempInviteData.setLvmname(inviteData.isLvmname());
tempInviteData.setLvmphone(inviteData.isLvmphone()); tempInviteData.setLvmphone(inviteData.isLvmphone());
tempInviteData.setLvmemail(inviteData.isLvmemail()); tempInviteData.setLvmemail(inviteData.isLvmemail());
tempInviteData.setLvmaddress(inviteData.isLvmaddress()); tempInviteData.setLvmaddress(inviteData.isLvmaddress());
tempInviteData.setLvmqq(inviteData.isLvmqq()); tempInviteData.setLvmqq(inviteData.isLvmqq());
tempInviteData.setSkill(inviteData.isSkill()); tempInviteData.setSkill(inviteData.isSkill());
tempInviteData.setConsult_skill_title(inviteData.getConsult_skill_title()); tempInviteData.setConsult_skill_title(inviteData.getConsult_skill_title());
tempInviteData.setConsult_skill_msg(inviteData.getConsult_skill_msg()); tempInviteData.setConsult_skill_msg(inviteData.getConsult_skill_msg());
tempInviteData.setConsult_skill_bottomtitle(inviteData.getConsult_skill_bottomtitle()); tempInviteData.setConsult_skill_bottomtitle(inviteData.getConsult_skill_bottomtitle());
tempInviteData.setConsult_skill_maxagent(inviteData.getConsult_skill_maxagent()); tempInviteData.setConsult_skill_maxagent(inviteData.getConsult_skill_maxagent());
tempInviteData.setConsult_skill_numbers(inviteData.getConsult_skill_numbers()); tempInviteData.setConsult_skill_numbers(inviteData.getConsult_skill_numbers());
tempInviteData.setConsult_skill_agent(inviteData.isConsult_skill_agent()); tempInviteData.setConsult_skill_agent(inviteData.isConsult_skill_agent());
tempInviteData.setOnlyareaskill(inviteData.isOnlyareaskill()); tempInviteData.setOnlyareaskill(inviteData.isOnlyareaskill());
tempInviteData.setAreaskilltipmsg(inviteData.getAreaskilltipmsg()); tempInviteData.setAreaskilltipmsg(inviteData.getAreaskilltipmsg());
tempInviteData.setConsult_info(inviteData.isConsult_info()); tempInviteData.setConsult_info(inviteData.isConsult_info());
tempInviteData.setConsult_info_email(inviteData.isConsult_info_email()); tempInviteData.setConsult_info_email(inviteData.isConsult_info_email());
tempInviteData.setConsult_info_name(inviteData.isConsult_info_name()); tempInviteData.setConsult_info_name(inviteData.isConsult_info_name());
tempInviteData.setConsult_info_phone(inviteData.isConsult_info_phone()); tempInviteData.setConsult_info_phone(inviteData.isConsult_info_phone());
tempInviteData.setConsult_info_resion(inviteData.isConsult_info_resion()); tempInviteData.setConsult_info_resion(inviteData.isConsult_info_resion());
tempInviteData.setConsult_info_message(inviteData.getConsult_info_message()); tempInviteData.setConsult_info_message(inviteData.getConsult_info_message());
tempInviteData.setConsult_info_cookies(inviteData.isConsult_info_cookies()); tempInviteData.setConsult_info_cookies(inviteData.isConsult_info_cookies());
tempInviteData.setRecordhis(inviteData.isRecordhis()); tempInviteData.setRecordhis(inviteData.isRecordhis());
tempInviteData.setTraceuser(inviteData.isTraceuser()); tempInviteData.setTraceuser(inviteData.isTraceuser());
tempInviteData.setAi(inviteData.isAi()); tempInviteData.setAi(inviteData.isAi());
tempInviteData.setAifirst(inviteData.isAifirst()); tempInviteData.setAifirst(inviteData.isAifirst());
tempInviteData.setAimsg(inviteData.getAimsg()); tempInviteData.setAimsg(inviteData.getAimsg());
tempInviteData.setAisuccesstip(inviteData.getAisuccesstip()); tempInviteData.setAisuccesstip(inviteData.getAisuccesstip());
tempInviteData.setAiname(inviteData.getAiname()); tempInviteData.setAiname(inviteData.getAiname());
tempInviteData.setAiid(inviteData.getAiid()); tempInviteData.setAiid(inviteData.getAiid());
tempInviteData.setMaxwordsnum(inviteData.getMaxwordsnum()); tempInviteData.setMaxwordsnum(inviteData.getMaxwordsnum());
tempInviteData.setCtrlenter(inviteData.isCtrlenter()); tempInviteData.setCtrlenter(inviteData.isCtrlenter());
if(dialogad!=null && !StringUtils.isBlank(dialogad.getName()) && dialogad.getBytes()!=null && dialogad.getBytes().length >0){ if (dialogad != null && StringUtils.isNotBlank(dialogad.getName()) && dialogad.getBytes() != null && dialogad.getBytes().length > 0) {
String fileName = "ad/"+inviteData.getId()+dialogad.getOriginalFilename().substring(dialogad.getOriginalFilename().lastIndexOf(".")) ; tempInviteData.setDialog_ad(super.saveImageFileWithMultipart(dialogad));
File file = new File(path , fileName) ; }
if(!file.getParentFile().exists()){ invite.save(tempInviteData);
file.getParentFile().mkdirs(); inviteData = tempInviteData;
} }
FileCopyUtils.copy(dialogad.getBytes(), file); } else {
tempInviteData.setDialog_ad(fileName); invite.save(inviteData);
} }
invite.save(tempInviteData) ; CacheHelper.getSystemCacheBean().put(inviteData.getSnsaccountid(), inviteData, inviteData.getOrgi());
inviteData = tempInviteData ; return request(super.createRequestPageTempletResponse("redirect:/admin/webim/profile.html?snsid=" + inviteData.getSnsaccountid()));
}
}else{
invite.save(inviteData) ;
}
CacheHelper.getSystemCacheBean().put(inviteData.getSnsaccountid(), inviteData, inviteData.getOrgi());
return request(super.createRequestPageTempletResponse("redirect:/admin/app/profile.html?snsid="+inviteData.getSnsaccountid()));
} }
@RequestMapping("/invote") @RequestMapping("/invote")
@Menu(type = "app" , subtype = "invote" , admin= true) @Menu(type = "app", subtype = "invote", admin = true)
public ModelAndView invote(ModelMap map , HttpServletRequest request , @Valid String snsid) { public ModelAndView invote(ModelMap map, HttpServletRequest request, @Valid String snsid) {
CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsid, super.getOrgi(request)) ; CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsid, super.getOrgi(request));
if(coultInvite!=null){ if (coultInvite != null) {
map.addAttribute("inviteData", coultInvite); map.addAttribute("inviteData", coultInvite);
} }
map.addAttribute("import", request.getServerPort()) ; map.addAttribute("import", request.getServerPort());
map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(snsid, super.getOrgi(request))) ; map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(snsid, super.getOrgi(request)));
return request(super.createAdminTempletResponse("/admin/app/invote")); return request(super.createAdminTempletResponse("/admin/webim/invote"));
} }
@RequestMapping("/invote/save") @RequestMapping("/invote/save")
@Menu(type = "admin" , subtype = "profile" , admin= true) @Menu(type = "admin", subtype = "profile", admin = true)
public ModelAndView saveinvote(HttpServletRequest request , @Valid CousultInvite inviteData, @RequestParam(value = "invotebg", required = false) MultipartFile invotebg) throws IOException { public ModelAndView saveinvote(HttpServletRequest request, @Valid CousultInvite inviteData, @RequestParam(value = "invotebg", required = false) MultipartFile invotebg) throws IOException {
CousultInvite tempInviteData ; CousultInvite tempInviteData;
if(inviteData!=null && !StringUtils.isBlank(inviteData.getId())){ if (inviteData != null && StringUtils.isNotBlank(inviteData.getId())) {
tempInviteData = invite.findOne(inviteData.getId()) ; tempInviteData = invite.findOne(inviteData.getId());
if(tempInviteData!=null){ if (tempInviteData != null) {
tempInviteData.setConsult_invite_enable(inviteData.isConsult_invite_enable()); tempInviteData.setConsult_invite_enable(inviteData.isConsult_invite_enable());
tempInviteData.setConsult_invite_content(inviteData.getConsult_invite_content()); tempInviteData.setConsult_invite_content(inviteData.getConsult_invite_content());
tempInviteData.setConsult_invite_accept(inviteData.getConsult_invite_accept()); tempInviteData.setConsult_invite_accept(inviteData.getConsult_invite_accept());
tempInviteData.setConsult_invite_later(inviteData.getConsult_invite_later()); tempInviteData.setConsult_invite_later(inviteData.getConsult_invite_later());
tempInviteData.setConsult_invite_delay(inviteData.getConsult_invite_delay()); tempInviteData.setConsult_invite_delay(inviteData.getConsult_invite_delay());
tempInviteData.setConsult_invite_color(inviteData.getConsult_invite_color()); tempInviteData.setConsult_invite_color(inviteData.getConsult_invite_color());
if(invotebg!=null && !StringUtils.isBlank(invotebg.getName()) && invotebg.getBytes()!=null && invotebg.getBytes().length >0){ if (invotebg != null && StringUtils.isNotBlank(invotebg.getName()) && invotebg.getBytes() != null && invotebg.getBytes().length > 0) {
String fileName = "invote/"+inviteData.getId()+invotebg.getOriginalFilename().substring(invotebg.getOriginalFilename().lastIndexOf(".")) ; tempInviteData.setConsult_invite_bg(super.saveImageFileWithMultipart(invotebg));
File file = new File(path , fileName) ; }
if(!file.getParentFile().exists()){ invite.save(tempInviteData);
file.getParentFile().mkdirs(); inviteData = tempInviteData;
} }
FileCopyUtils.copy(invotebg.getBytes(), file); } else {
tempInviteData.setConsult_invite_bg(fileName); invite.save(inviteData);
} }
invite.save(tempInviteData) ; CacheHelper.getSystemCacheBean().put(inviteData.getSnsaccountid(), inviteData, inviteData.getOrgi());
inviteData = tempInviteData ; return request(super.createRequestPageTempletResponse("redirect:/admin/webim/invote.html?snsid=" + inviteData.getSnsaccountid()));
}
}else{
invite.save(inviteData) ;
}
CacheHelper.getSystemCacheBean().put(inviteData.getSnsaccountid(), inviteData, inviteData.getOrgi());
return request(super.createRequestPageTempletResponse("redirect:/admin/app/invote.html?snsid="+inviteData.getSnsaccountid()));
} }
/** /**
* 获取当前产品下组织信息 * 获取当前产品下组织信息
* @param request *
* @return * @param request
*/ * @return
private List<Organ> getOrgans(HttpServletRequest request){ */
List<Organ> list = null; private List<Organ> getOrgans(HttpServletRequest request) {
if(super.isTenantshare()) { List<Organ> list = null;
List<String> organIdList = new ArrayList<>(); if (super.isTenantshare()) {
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ; List<String> organIdList = new ArrayList<>();
if(!orgiSkillRelList.isEmpty()) { List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request));
for(OrgiSkillRel rel:orgiSkillRelList) { if (!orgiSkillRelList.isEmpty()) {
organIdList.add(rel.getSkillid()); for (OrgiSkillRel rel : orgiSkillRelList) {
} organIdList.add(rel.getSkillid());
} }
list = organRes.findAll(organIdList); }
}else { list = organRes.findAll(organIdList);
list = organRes.findByOrgiAndOrgid(super.getOrgi(request),super.getOrgid(request)) ; } else {
} list = organRes.findByOrgiAndOrgid(super.getOrgi(request), super.getOrgid(request));
return list; }
return list;
} }
/**
* 获取当前产品下人员信息 /**
* @param request * 获取当前产品下人员信息
* @param q *
* @return * @param request
*/ * @return
private List<User> getUsers(HttpServletRequest request){ */
List<User> userList = null; private List<User> getUsers(HttpServletRequest request) {
if(super.isTenantshare()) { List<User> userList = null;
List<String> organIdList = new ArrayList<>(); if (super.isTenantshare()) {
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ; List<String> organIdList = new ArrayList<>();
if(!orgiSkillRelList.isEmpty()) { List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request));
for(OrgiSkillRel rel:orgiSkillRelList) { if (!orgiSkillRelList.isEmpty()) {
organIdList.add(rel.getSkillid()); for (OrgiSkillRel rel : orgiSkillRelList) {
} organIdList.add(rel.getSkillid());
} }
userList=userRes.findByOrganInAndAgentAndDatastatus(organIdList,true,false); }
}else { userList = userRes.findByOrganInAndAgentAndDatastatus(organIdList, true, false);
userList=userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true,false) ; } else {
} userList = userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true, false);
return userList; }
return userList;
} }
} }

View File

@ -16,28 +16,20 @@
*/ */
package com.chatopera.cc.app.handler.admin.config; package com.chatopera.cc.app.handler.admin.config;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.model.Secret;
import com.chatopera.cc.app.model.SysDic;
import com.chatopera.cc.app.model.SystemConfig;
import com.chatopera.cc.app.model.UKeFuDic;
import com.chatopera.cc.app.persistence.repository.SecretRepository; import com.chatopera.cc.app.persistence.repository.SecretRepository;
import com.chatopera.cc.app.persistence.repository.SystemConfigRepository; import com.chatopera.cc.app.persistence.repository.SystemConfigRepository;
import com.chatopera.cc.app.persistence.repository.SystemMessageRepository; import com.chatopera.cc.app.persistence.repository.SystemMessageRepository;
import com.chatopera.cc.app.persistence.repository.TemplateRepository; import com.chatopera.cc.app.persistence.repository.TemplateRepository;
import com.chatopera.cc.app.model.Secret; import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.model.SysDic; import com.corundumstudio.socketio.SocketIOServer;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -50,222 +42,223 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.corundumstudio.socketio.SocketIOServer; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.handler.Handler; import javax.validation.Valid;
import com.chatopera.cc.app.model.SystemConfig; import java.io.File;
import com.chatopera.cc.app.model.UKeFuDic; import java.io.FileOutputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
@Controller @Controller
@RequestMapping("/admin/config") @RequestMapping("/admin/config")
public class SystemConfigController extends Handler{ public class SystemConfigController extends Handler {
@Value("${uk.im.server.port}") @Value("${uk.im.server.port}")
private Integer port; private Integer port;
@Value("${web.upload-path}") @Value("${web.upload-path}")
private String path; private String path;
@Autowired @Autowired
private SocketIOServer server ; private SocketIOServer server;
@Autowired @Autowired
private SystemConfigRepository systemConfigRes ; private SystemConfigRepository systemConfigRes;
@Autowired @Autowired
private SystemMessageRepository systemMessageRes ; private SystemMessageRepository systemMessageRes;
@Autowired @Autowired
private SecretRepository secRes ; private SecretRepository secRes;
@Autowired @Autowired
private TemplateRepository templateRes ; private TemplateRepository templateRes;
@RequestMapping("/index") @RequestMapping("/index")
@Menu(type = "admin" , subtype = "config" , admin = true) @Menu(type = "admin", subtype = "config", admin = true)
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String execute) throws SQLException { public ModelAndView index(ModelMap map, HttpServletRequest request, @Valid String execute) throws SQLException {
map.addAttribute("server", server) ; map.addAttribute("server", server);
if(MainContext.model.get("im")!=null){ if (MainContext.model.get("im") != null) {
map.addAttribute("entim", MainContext.model.get("im")) ; map.addAttribute("entim", MainContext.model.get("im"));
} }
if(request.getSession().getAttribute(MainContext.UKEFU_SYSTEM_INFOACQ)!=null){ if (request.getSession().getAttribute(MainContext.UKEFU_SYSTEM_INFOACQ) != null) {
map.addAttribute("entim", request.getSession().getAttribute(MainContext.UKEFU_SYSTEM_INFOACQ)) ; map.addAttribute("entim", request.getSession().getAttribute(MainContext.UKEFU_SYSTEM_INFOACQ));
} }
map.addAttribute("server", server) ; map.addAttribute("server", server);
map.addAttribute("imServerStatus", MainContext.getIMServerStatus()) ; map.addAttribute("imServerStatus", MainContext.getIMServerStatus());
List<Secret> secretConfig = secRes.findByOrgi(super.getOrgi(request)) ; List<Secret> secretConfig = secRes.findByOrgi(super.getOrgi(request));
if(secretConfig!=null && secretConfig.size() > 0){ if (secretConfig != null && secretConfig.size() > 0) {
map.addAttribute("secret", secretConfig.get(0)) ; map.addAttribute("secret", secretConfig.get(0));
} }
List<SysDic> dicList = UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_DIC) ; List<SysDic> dicList = UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_DIC);
SysDic callCenterDic = null , workOrderDic = null , smsDic = null ; SysDic callCenterDic = null, workOrderDic = null, smsDic = null;
for(SysDic dic : dicList){ for (SysDic dic : dicList) {
if(dic.getCode().equals(MainContext.UKEFU_SYSTEM_CALLCENTER)){ if (dic.getCode().equals(MainContext.UKEFU_SYSTEM_CALLCENTER)) {
callCenterDic = dic ; callCenterDic = dic;
} }
if(dic.getCode().equals(MainContext.UKEFU_SYSTEM_WORKORDEREMAIL)){ if (dic.getCode().equals(MainContext.UKEFU_SYSTEM_WORKORDEREMAIL)) {
workOrderDic = dic ; workOrderDic = dic;
} }
if(dic.getCode().equals(MainContext.UKEFU_SYSTEM_SMSEMAIL)){ if (dic.getCode().equals(MainContext.UKEFU_SYSTEM_SMSEMAIL)) {
smsDic = dic ; smsDic = dic;
} }
} }
if(callCenterDic!=null){ if (callCenterDic != null) {
map.addAttribute("templateList", templateRes.findByTemplettypeAndOrgi(callCenterDic.getId(), super.getOrgi(request))) ; map.addAttribute("templateList", templateRes.findByTemplettypeAndOrgi(callCenterDic.getId(), super.getOrgi(request)));
} }
if(workOrderDic!=null){ if (workOrderDic != null) {
map.addAttribute("workOrderList", templateRes.findByTemplettypeAndOrgi(workOrderDic.getId(), super.getOrgi(request))) ; map.addAttribute("workOrderList", templateRes.findByTemplettypeAndOrgi(workOrderDic.getId(), super.getOrgi(request)));
} }
if(smsDic!=null){ if (smsDic != null) {
map.addAttribute("smsList", templateRes.findByTemplettypeAndOrgi(smsDic.getId(), super.getOrgi(request))) ; map.addAttribute("smsList", templateRes.findByTemplettypeAndOrgi(smsDic.getId(), super.getOrgi(request)));
} }
map.addAttribute("sysMessageList", systemMessageRes.findByMsgtypeAndOrgi(MainContext.SystemMessageType.EMAIL.toString(), super.getOrgi(request))) ; map.addAttribute("sysMessageList", systemMessageRes.findByMsgtypeAndOrgi(MainContext.SystemMessageType.EMAIL.toString(), super.getOrgi(request)));
if(!StringUtils.isBlank(execute) && execute.equals("false")){ if (StringUtils.isNotBlank(execute) && execute.equals("false")) {
map.addAttribute("execute", execute) ; map.addAttribute("execute", execute);
} }
if(!StringUtils.isBlank(request.getParameter("msg"))){ if (StringUtils.isNotBlank(request.getParameter("msg"))) {
map.addAttribute("msg", request.getParameter("msg")) ; map.addAttribute("msg", request.getParameter("msg"));
} }
return request(super.createAdminTempletResponse("/admin/config/index")); return request(super.createAdminTempletResponse("/admin/config/index"));
} }
@RequestMapping("/stopimserver") @RequestMapping("/stopimserver")
@Menu(type = "admin" , subtype = "stopimserver" , access = false , admin = true) @Menu(type = "admin", subtype = "stopimserver", access = false, admin = true)
public ModelAndView stopimserver(ModelMap map , HttpServletRequest request , @Valid String confirm) throws SQLException { public ModelAndView stopimserver(ModelMap map, HttpServletRequest request, @Valid String confirm) throws SQLException {
boolean execute = false ; boolean execute = false;
if(execute = MainUtils.secConfirm(secRes, super.getOrgi(request), confirm)){ if (execute = MainUtils.secConfirm(secRes, super.getOrgi(request), confirm)) {
server.stop(); server.stop();
MainContext.setIMServerStatus(false); MainContext.setIMServerStatus(false);
} }
return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html?execute="+execute)); return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html?execute=" + execute));
} }
@RequestMapping("/startentim") @RequestMapping("/startentim")
@Menu(type = "admin" , subtype = "startentim" , access = false , admin = true) @Menu(type = "admin", subtype = "startentim", access = false, admin = true)
public ModelAndView startentim(ModelMap map , HttpServletRequest request) throws SQLException { public ModelAndView startentim(ModelMap map, HttpServletRequest request) throws SQLException {
MainContext.model.put("im", true) ; MainContext.model.put("im", true);
return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html")); return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html"));
} }
@RequestMapping("/stopentim") @RequestMapping("/stopentim")
@Menu(type = "admin" , subtype = "stopentim" , access = false , admin = true) @Menu(type = "admin", subtype = "stopentim", access = false, admin = true)
public ModelAndView stopentim(ModelMap map , HttpServletRequest request) throws SQLException { public ModelAndView stopentim(ModelMap map, HttpServletRequest request) throws SQLException {
MainContext.model.remove("im") ; MainContext.model.remove("im");
return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html")); return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html"));
} }
/** /**
* 危险操作请谨慎调用 WebLogic/WebSphere/Oracle等中间件服务器禁止调用 * 危险操作请谨慎调用 WebLogic/WebSphere/Oracle等中间件服务器禁止调用
*
* @param map * @param map
* @param request * @param request
* @return * @return
* @throws SQLException * @throws SQLException
*/ */
@RequestMapping("/stop") @RequestMapping("/stop")
@Menu(type = "admin" , subtype = "stop" , access = false , admin = true) @Menu(type = "admin", subtype = "stop", access = false, admin = true)
public ModelAndView stop(ModelMap map , HttpServletRequest request , @Valid String confirm) throws SQLException { public ModelAndView stop(ModelMap map, HttpServletRequest request, @Valid String confirm) throws SQLException {
boolean execute = false ; boolean execute = false;
if(execute = MainUtils.secConfirm(secRes, super.getOrgi(request), confirm)){ if (execute = MainUtils.secConfirm(secRes, super.getOrgi(request), confirm)) {
server.stop(); server.stop();
MainContext.setIMServerStatus(false); MainContext.setIMServerStatus(false);
System.exit(0); System.exit(0);
} }
return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html?execute="+execute)); return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html?execute=" + execute));
} }
@RequestMapping("/save") @RequestMapping("/save")
@Menu(type = "admin" , subtype = "save" , admin = true) @Menu(type = "admin", subtype = "save", admin = true)
public ModelAndView save(ModelMap map , HttpServletRequest request , @Valid SystemConfig config ,BindingResult result , @RequestParam(value = "keyfile", required = false) MultipartFile keyfile , @RequestParam(value = "loginlogo", required = false) MultipartFile loginlogo , @RequestParam(value = "consolelogo", required = false) MultipartFile consolelogo , @RequestParam(value = "favlogo", required = false) MultipartFile favlogo , @Valid Secret secret) throws SQLException, IOException, NoSuchAlgorithmException { public ModelAndView save(ModelMap map, HttpServletRequest request, @Valid SystemConfig config, BindingResult result, @RequestParam(value = "keyfile", required = false) MultipartFile keyfile, @RequestParam(value = "loginlogo", required = false) MultipartFile loginlogo, @RequestParam(value = "consolelogo", required = false) MultipartFile consolelogo, @RequestParam(value = "favlogo", required = false) MultipartFile favlogo, @Valid Secret secret) throws SQLException, IOException, NoSuchAlgorithmException {
/*SystemConfig systemConfig = systemConfigRes.findByOrgi(super.getOrgi(request)) ; /*SystemConfig systemConfig = systemConfigRes.findByOrgi(super.getOrgi(request)) ;
config.setOrgi(super.getOrgi(request));*/ config.setOrgi(super.getOrgi(request));*/
SystemConfig systemConfig = systemConfigRes.findByOrgi(MainContext.SYSTEM_ORGI) ; SystemConfig systemConfig = systemConfigRes.findByOrgi(MainContext.SYSTEM_ORGI);
config.setOrgi(MainContext.SYSTEM_ORGI); config.setOrgi(MainContext.SYSTEM_ORGI);
String msg = "0" ; String msg = "0";
if(StringUtils.isBlank(config.getJkspassword())){ if (StringUtils.isBlank(config.getJkspassword())) {
config.setJkspassword(null); config.setJkspassword(null);
} }
if(systemConfig == null){ if (systemConfig == null) {
config.setCreater(super.getUser(request).getId()); config.setCreater(super.getUser(request).getId());
config.setCreatetime(new Date()); config.setCreatetime(new Date());
systemConfig = config ; systemConfig = config;
}else{ } else {
MainUtils.copyProperties(config,systemConfig); MainUtils.copyProperties(config, systemConfig);
} }
if(config.isEnablessl()){ if (config.isEnablessl()) {
if(keyfile!=null && keyfile.getBytes()!=null && keyfile.getBytes().length > 0 && keyfile.getOriginalFilename()!=null && keyfile.getOriginalFilename().length() > 0){ if (keyfile != null && keyfile.getBytes() != null && keyfile.getBytes().length > 0 && keyfile.getOriginalFilename() != null && keyfile.getOriginalFilename().length() > 0) {
FileUtils.writeByteArrayToFile(new File(path , "ssl/"+keyfile.getOriginalFilename()), keyfile.getBytes()); FileUtils.writeByteArrayToFile(new File(path, "ssl/" + keyfile.getOriginalFilename()), keyfile.getBytes());
systemConfig.setJksfile(keyfile.getOriginalFilename()); systemConfig.setJksfile(keyfile.getOriginalFilename());
File sslFilePath = new File(path , "ssl/https.properties") ; File sslFilePath = new File(path, "ssl/https.properties");
if(!sslFilePath.getParentFile().exists()) { if (!sslFilePath.getParentFile().exists()) {
sslFilePath.getParentFile().mkdirs() ; sslFilePath.getParentFile().mkdirs();
} }
Properties prop = new Properties(); Properties prop = new Properties();
FileOutputStream oFile = new FileOutputStream(sslFilePath);//true表示追加打开 FileOutputStream oFile = new FileOutputStream(sslFilePath);//true表示追加打开
prop.setProperty("key-store-password", MainUtils.encryption(systemConfig.getJkspassword())) ; prop.setProperty("key-store-password", MainUtils.encryption(systemConfig.getJkspassword()));
prop.setProperty("key-store",systemConfig.getJksfile()) ; prop.setProperty("key-store", systemConfig.getJksfile());
prop.store(oFile , "SSL Properties File"); prop.store(oFile, "SSL Properties File");
oFile.close(); oFile.close();
} }
}else if(new File(path , "ssl").exists()){ } else if (new File(path, "ssl").exists()) {
File[] sslFiles = new File(path , "ssl").listFiles() ; File[] sslFiles = new File(path, "ssl").listFiles();
for(File sslFile : sslFiles){ for (File sslFile : sslFiles) {
sslFile.delete(); sslFile.delete();
} }
} }
if(loginlogo!=null && !StringUtils.isBlank(loginlogo.getOriginalFilename()) && loginlogo.getOriginalFilename().lastIndexOf(".") > 0) { if (loginlogo != null && StringUtils.isNotBlank(loginlogo.getOriginalFilename()) && loginlogo.getOriginalFilename().lastIndexOf(".") > 0) {
String logoFileName = "logo/"+ MainUtils.md5(loginlogo.getOriginalFilename())+loginlogo.getOriginalFilename().substring(loginlogo.getOriginalFilename().lastIndexOf(".")) ; systemConfig.setLoginlogo(super.saveImageFileWithMultipart(loginlogo));
FileUtils.writeByteArrayToFile(new File(path ,logoFileName), loginlogo.getBytes()); }
systemConfig.setLoginlogo(logoFileName); if (consolelogo != null && StringUtils.isNotBlank(consolelogo.getOriginalFilename()) && consolelogo.getOriginalFilename().lastIndexOf(".") > 0) {
} systemConfig.setConsolelogo(super.saveImageFileWithMultipart(consolelogo));
if(consolelogo!=null && !StringUtils.isBlank(consolelogo.getOriginalFilename()) && consolelogo.getOriginalFilename().lastIndexOf(".") > 0) { }
String consoleLogoFileName = "logo/"+ MainUtils.md5(consolelogo.getOriginalFilename())+consolelogo.getOriginalFilename().substring(consolelogo.getOriginalFilename().lastIndexOf(".")) ; if (favlogo != null && StringUtils.isNotBlank(favlogo.getOriginalFilename()) && consolelogo.getOriginalFilename().lastIndexOf(".") > 0) {
FileUtils.writeByteArrayToFile(new File(path ,consoleLogoFileName), consolelogo.getBytes()); systemConfig.setFavlogo(super.saveImageFileWithMultipart(favlogo));
systemConfig.setConsolelogo(consoleLogoFileName); }
}
if(favlogo!=null && !StringUtils.isBlank(favlogo.getOriginalFilename()) && consolelogo.getOriginalFilename().lastIndexOf(".") > 0) { if (secret != null && StringUtils.isNotBlank(secret.getPassword())) {
String favLogoFileName = "logo/"+ MainUtils.md5(favlogo.getOriginalFilename())+favlogo.getOriginalFilename().substring(favlogo.getOriginalFilename().lastIndexOf(".")) ; List<Secret> secretConfig = secRes.findByOrgi(super.getOrgi(request));
FileUtils.writeByteArrayToFile(new File(path ,favLogoFileName), favlogo.getBytes()); String repassword = request.getParameter("repassword");
systemConfig.setFavlogo(favLogoFileName); if (StringUtils.isNotBlank(repassword) && repassword.equals(secret.getPassword())) {
} if (secretConfig != null && secretConfig.size() > 0) {
Secret tempSecret = secretConfig.get(0);
if(secret!=null && !StringUtils.isBlank(secret.getPassword())){ String oldpass = request.getParameter("oldpass");
List<Secret> secretConfig = secRes.findByOrgi(super.getOrgi(request)) ; if (StringUtils.isNotBlank(oldpass) && MainUtils.md5(oldpass).equals(tempSecret.getPassword())) {
String repassword = request.getParameter("repassword") ; tempSecret.setPassword(MainUtils.md5(secret.getPassword()));
if(!StringUtils.isBlank(repassword) && repassword.equals(secret.getPassword())){ msg = "1";
if(secretConfig!=null && secretConfig.size() > 0){ tempSecret.setEnable(true);
Secret tempSecret = secretConfig.get(0) ; secRes.save(tempSecret);
String oldpass = request.getParameter("oldpass") ; } else {
if(!StringUtils.isBlank(oldpass) && MainUtils.md5(oldpass).equals(tempSecret.getPassword())){ msg = "3";
tempSecret.setPassword(MainUtils.md5(secret.getPassword())); }
msg = "1" ; } else {
tempSecret.setEnable(true); secret.setOrgi(super.getOrgi(request));
secRes.save(tempSecret) ; secret.setCreater(super.getUser(request).getId());
}else{ secret.setCreatetime(new Date());
msg = "3" ; secret.setPassword(MainUtils.md5(secret.getPassword()));
} secret.setEnable(true);
}else{ msg = "1";
secret.setOrgi(super.getOrgi(request)); secRes.save(secret);
secret.setCreater(super.getUser(request).getId()); }
secret.setCreatetime(new Date()); } else {
secret.setPassword(MainUtils.md5(secret.getPassword())); msg = "2";
secret.setEnable(true); }
msg = "1" ; map.addAttribute("msg", msg);
secRes.save(secret) ; }
} systemConfigRes.save(systemConfig);
}else{
msg = "2" ; CacheHelper.getSystemCacheBean().put("systemConfig", systemConfig, super.getOrgi(request));
} map.addAttribute("imServerStatus", MainContext.getIMServerStatus());
map.addAttribute("msg", msg) ;
} return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html?msg=" + msg));
systemConfigRes.save(systemConfig) ;
CacheHelper.getSystemCacheBean().put("systemConfig", systemConfig , super.getOrgi(request));
map.addAttribute("imServerStatus", MainContext.getIMServerStatus()) ;
return request(super.createRequestPageTempletResponse("redirect:/admin/config/index.html?msg="+msg));
} }
} }

View File

@ -16,20 +16,21 @@
*/ */
package com.chatopera.cc.app.handler.admin.users; package com.chatopera.cc.app.handler.admin.users;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist; import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.repository.UserRoleRepository; import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.model.AgentStatus; import com.chatopera.cc.app.model.AgentStatus;
import com.chatopera.cc.app.model.User;
import com.chatopera.cc.app.model.UserRole;
import com.chatopera.cc.app.persistence.repository.UserRepository;
import com.chatopera.cc.app.persistence.repository.UserRoleRepository;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.util.OnlineUserUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
@ -38,211 +39,225 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.util.Menu; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.basic.MainUtils; import javax.validation.Valid;
import com.chatopera.cc.app.persistence.repository.UserRepository; import java.io.FileNotFoundException;
import com.chatopera.cc.util.OnlineUserUtils; import java.io.IOException;
import com.chatopera.cc.app.handler.Handler; import java.util.Date;
import com.chatopera.cc.app.model.User; import java.util.List;
import com.chatopera.cc.app.model.UserRole;
/** /**
*
* @author 程序猿DD * @author 程序猿DD
* @version 1.0.0 * @version 1.0.0
* @blog http://blog.didispace.com * @blog http://blog.didispace.com
*
*/ */
@Controller @Controller
@RequestMapping("/admin/user") @RequestMapping("/admin/user")
public class UsersController extends Handler{ public class UsersController extends Handler {
private final static Logger logger = LoggerFactory.getLogger(UsersController.class);
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
@Autowired @Autowired
private UserRoleRepository userRoleRes; private UserRoleRepository userRoleRes;
@RequestMapping("/index") @RequestMapping("/index")
@Menu(type = "admin" , subtype = "user") @Menu(type = "admin", subtype = "user")
public ModelAndView index(ModelMap map , HttpServletRequest request) throws FileNotFoundException, IOException { public ModelAndView index(ModelMap map, HttpServletRequest request) throws FileNotFoundException, IOException {
map.addAttribute( map.addAttribute(
"userList", "userList",
userRepository.findByDatastatusAndOrgiAndOrgid( userRepository.findByDatastatusAndOrgiAndOrgid(
false, false,
super.getOrgiByTenantshare(request), super.getOrgiByTenantshare(request),
super.getOrgid(request), super.getOrgid(request),
new PageRequest( new PageRequest(
super.getP(request), super.getP(request),
super.getPs(request), super.getPs(request),
Sort.Direction.ASC, Sort.Direction.ASC,
"createtime" "createtime"
) )
) )
); );
return request(super.createAdminTempletResponse("/admin/user/index")); return request(super.createAdminTempletResponse("/admin/user/index"));
} }
@RequestMapping("/add") @RequestMapping("/add")
@Menu(type = "admin" , subtype = "user") @Menu(type = "admin", subtype = "user")
public ModelAndView add(ModelMap map , HttpServletRequest request) { public ModelAndView add(ModelMap map, HttpServletRequest request) {
return request(super.createRequestPageTempletResponse("/admin/user/add")); return request(super.createRequestPageTempletResponse("/admin/user/add"));
} }
@RequestMapping("/save") @RequestMapping("/save")
@Menu(type = "admin" , subtype = "user") @Menu(type = "admin", subtype = "user")
public ModelAndView save(HttpServletRequest request ,@Valid User user) { public ModelAndView save(HttpServletRequest request, @Valid User user) {
String msg = "" ; String msg = "";
msg = validUser(user); msg = validUser(user);
if(!StringUtils.isBlank(msg)){ if (!StringUtils.isBlank(msg)) {
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg="+msg)); return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=" + msg));
}else{ } else {
if(request.getParameter("admin")!=null){ if (request.getParameter("admin") != null) {
user.setUsertype("0"); user.setUsertype("0");
}else{ } else {
user.setUsertype(null); user.setUsertype(null);
} }
if(!StringUtils.isBlank(user.getPassword())){ if (!StringUtils.isBlank(user.getPassword())) {
user.setPassword(MainUtils.md5(user.getPassword())); user.setPassword(MainUtils.md5(user.getPassword()));
} }
user.setOrgi(super.getOrgiByTenantshare(request)); user.setOrgi(super.getOrgiByTenantshare(request));
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) { if (!StringUtils.isBlank(super.getUser(request).getOrgid())) {
user.setOrgid(super.getUser(request).getOrgid()); user.setOrgid(super.getUser(request).getOrgid());
}else { } else {
user.setOrgid(MainContext.SYSTEM_ORGI); user.setOrgid(MainContext.SYSTEM_ORGI);
} }
userRepository.save(user) ; userRepository.save(user);
OnlineUserUtils.clean(super.getOrgi(request)); OnlineUserUtils.clean(super.getOrgi(request));
} }
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg="+msg)); return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=" + msg));
} }
private String validUser(User user) { private String validUser(User user) {
String msg = ""; String msg = "";
User tempUser = userRepository.findByUsernameAndDatastatus(user.getUsername(),false) ; User tempUser = userRepository.findByUsernameAndDatastatus(user.getUsername(), false);
if(tempUser!=null) { if (tempUser != null) {
msg = "username_exist"; msg = "username_exist";
return msg; return msg;
} }
tempUser = userRepository.findByEmailAndDatastatus(user.getEmail(),false) ; tempUser = userRepository.findByEmailAndDatastatus(user.getEmail(), false);
if(tempUser!=null) { if (tempUser != null) {
msg = "email_exist"; msg = "email_exist";
return msg; return msg;
} }
tempUser = userRepository.findByMobileAndDatastatus(user.getMobile(),false) ; tempUser = userRepository.findByMobileAndDatastatus(user.getMobile(), false);
if(tempUser!=null) { if (tempUser != null) {
msg = "mobile_exist"; msg = "mobile_exist";
return msg; return msg;
} }
List<User> tempUserList = userRepository.findBySipaccountAndDatastatus(user.getSipaccount(),false) ;
if(tempUserList.size()!=0&&user.getSipaccount()!="") { if (!validUserCallcenterParams(user)) {
msg = "sip_account_exist"; msg = "sip_account_exist";
return msg; return msg;
} }
return msg; return msg;
} }
@RequestMapping("/edit") @RequestMapping("/edit")
@Menu(type = "admin" , subtype = "user") @Menu(type = "admin", subtype = "user")
public ModelAndView edit(ModelMap map ,HttpServletRequest request , @Valid String id) { public ModelAndView edit(ModelMap map, HttpServletRequest request, @Valid String id) {
ModelAndView view = request(super.createRequestPageTempletResponse("/admin/user/edit")) ; ModelAndView view = request(super.createRequestPageTempletResponse("/admin/user/edit"));
view.addObject("userData", userRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request))) ; view.addObject("userData", userRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request)));
return view; return view;
} }
@RequestMapping("/update") @RequestMapping("/update")
@Menu(type = "admin" , subtype = "user" , admin = true) @Menu(type = "admin", subtype = "user", admin = true)
public ModelAndView update(HttpServletRequest request ,@Valid User user) { public ModelAndView update(HttpServletRequest request, @Valid User user) {
User tempUser = userRepository.getOne(user.getId()) ; User tempUser = userRepository.getOne(user.getId());
if(tempUser != null){ if (tempUser != null) {
String msg = validUserUpdate(user,tempUser); String msg = validUserUpdate(user, tempUser);
if(!StringUtils.isBlank(msg)){ if (!StringUtils.isBlank(msg)) {
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg="+msg)); return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=" + msg));
} }
tempUser.setUname(user.getUname()); tempUser.setUname(user.getUname());
tempUser.setUsername(user.getUsername()); tempUser.setUsername(user.getUsername());
tempUser.setEmail(user.getEmail()); tempUser.setEmail(user.getEmail());
tempUser.setMobile(user.getMobile()); tempUser.setMobile(user.getMobile());
tempUser.setSipaccount(user.getSipaccount()); tempUser.setSipaccount(user.getSipaccount());
//切换成非坐席 判断是否坐席 以及 是否有对话 //切换成非坐席 判断是否坐席 以及 是否有对话
if(!user.isAgent()) { if (!user.isAgent()) {
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject((super.getUser(request)).getId(), super.getOrgi(request)); AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject((super.getUser(request)).getId(), super.getOrgi(request));
if(!(agentStatus==null && AutomaticServiceDist.getAgentUsers(super.getUser(request).getId(), super.getOrgi(request))==0)) { if (!(agentStatus == null && AutomaticServiceDist.getAgentUsers(super.getUser(request).getId(), super.getOrgi(request)) == 0)) {
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=t1")); return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=t1"));
} }
} }
tempUser.setAgent(user.isAgent()); tempUser.setAgent(user.isAgent());
tempUser.setOrgi(super.getOrgiByTenantshare(request)); tempUser.setOrgi(super.getOrgiByTenantshare(request));
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) { if (!StringUtils.isBlank(super.getUser(request).getOrgid())) {
tempUser.setOrgid(super.getUser(request).getOrgid()); tempUser.setOrgid(super.getUser(request).getOrgid());
}else { } else {
tempUser.setOrgid(MainContext.SYSTEM_ORGI); tempUser.setOrgid(MainContext.SYSTEM_ORGI);
} }
tempUser.setCallcenter(user.isCallcenter()); tempUser.setCallcenter(user.isCallcenter());
if(!StringUtils.isBlank(user.getPassword())){ if (!StringUtils.isBlank(user.getPassword())) {
tempUser.setPassword(MainUtils.md5(user.getPassword())); tempUser.setPassword(MainUtils.md5(user.getPassword()));
} }
if(request.getParameter("admin")!=null){ if (request.getParameter("admin") != null) {
tempUser.setUsertype("0"); tempUser.setUsertype("0");
}else{ } else {
tempUser.setUsertype(null); tempUser.setUsertype(null);
} }
if(tempUser.getCreatetime() == null){ if (tempUser.getCreatetime() == null) {
tempUser.setCreatetime(new Date()); tempUser.setCreatetime(new Date());
} }
tempUser.setUpdatetime(new Date()); tempUser.setUpdatetime(new Date());
userRepository.save(tempUser) ; userRepository.save(tempUser);
OnlineUserUtils.clean(super.getOrgi(request)); OnlineUserUtils.clean(super.getOrgi(request));
} }
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html")); return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html"));
} }
private String validUserUpdate(User user,User oldUser) { private String validUserUpdate(User user, User oldUser) {
String msg = ""; String msg = "";
User tempUser = userRepository.findByUsernameAndDatastatus(user.getUsername(),false) ; User tempUser = userRepository.findByUsernameAndDatastatus(user.getUsername(), false);
if(tempUser!=null&&!user.getUsername().equals(oldUser.getUsername())) { if (tempUser != null && !user.getUsername().equals(oldUser.getUsername())) {
msg = "username_exist"; msg = "username_exist";
return msg; return msg;
} }
tempUser = userRepository.findByEmailAndDatastatus(user.getEmail(),false) ; tempUser = userRepository.findByEmailAndDatastatus(user.getEmail(), false);
if(tempUser!=null&&!user.getEmail().equals(oldUser.getEmail())) { if (tempUser != null && !user.getEmail().equals(oldUser.getEmail())) {
msg = "email_exist"; msg = "email_exist";
return msg; return msg;
} }
tempUser = userRepository.findByMobileAndDatastatus(user.getMobile(),false) ; tempUser = userRepository.findByMobileAndDatastatus(user.getMobile(), false);
if(tempUser!=null&&!user.getMobile().equals(oldUser.getMobile())) { if (tempUser != null && !user.getMobile().equals(oldUser.getMobile())) {
msg = "mobile_exist"; msg = "mobile_exist";
return msg; return msg;
} }
List<User> tempUserList = userRepository.findBySipaccountAndDatastatus(user.getSipaccount(),false) ;
if(tempUserList.size()!=0&&user.getSipaccount()!=""&&!user.getSipaccount().equals(oldUser.getSipaccount())) { if (!validUserCallcenterParams(user)) {
msg = "sip_account_exist"; msg = "sip_account_exist";
return msg; return msg;
} }
return msg;
return msg;
} }
@RequestMapping("/delete") @RequestMapping("/delete")
@Menu(type = "admin" , subtype = "user") @Menu(type = "admin", subtype = "user")
public ModelAndView delete(HttpServletRequest request ,@Valid User user) { public ModelAndView delete(HttpServletRequest request, @Valid User user) {
String msg = "admin_user_delete" ; String msg = "admin_user_delete";
if(user!=null){ if (user != null) {
List<UserRole> userRole = userRoleRes.findByOrgiAndUser(super.getOrgiByTenantshare(request), user) ; List<UserRole> userRole = userRoleRes.findByOrgiAndUser(super.getOrgiByTenantshare(request), user);
userRoleRes.delete(userRole); //删除用户的时候同时删除用户对应的 userRoleRes.delete(userRole); //删除用户的时候同时删除用户对应的
user = userRepository.getOne(user.getId()) ; user = userRepository.getOne(user.getId());
user.setDatastatus(true); user.setDatastatus(true);
userRepository.save(user) ; userRepository.save(user);
OnlineUserUtils.clean(super.getOrgi(request)); OnlineUserUtils.clean(super.getOrgi(request));
}else{ } else {
msg = "admin_user_not_exist" ; msg = "admin_user_not_exist";
} }
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg="+msg)); return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=" + msg));
} }
/**
* 根据是否开启呼叫中心模块检测账号
* @param user
* @return
*/
private boolean validUserCallcenterParams(final User user) {
if (user.isCallcenter() && MainContext.isEnableCalloutModule()) {
List<User> tempUserList = userRepository.findBySipaccountAndDatastatus(user.getSipaccount(), false);
if (tempUserList.size() != 0 && user.getSipaccount() != "") {
return false;
}
}
return true;
}
} }

View File

@ -582,7 +582,7 @@ public class ApiChatbotController extends Handler {
} }
} catch (ChatbotAPIRuntimeException e) { } catch (ChatbotAPIRuntimeException e) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5); resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
resp.addProperty(RestUtils.RESP_KEY_ERROR, "智能问答引擎服务异常" + e.toString()); resp.addProperty(RestUtils.RESP_KEY_ERROR, "智能问答引擎服务异常该机器人【chatbotID】已经存在或服务不能访问到请联系 [info@chatopera.com] 获得支持。");
return resp; return resp;
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4); resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);

View File

@ -16,6 +16,7 @@
package com.chatopera.cc.app.handler.api.rest; package com.chatopera.cc.app.handler.api.rest;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.util.Constants; import com.chatopera.cc.util.Constants;
import com.chatopera.cc.util.Menu; import com.chatopera.cc.util.Menu;
import com.chatopera.cc.exception.CSKefuRestException; import com.chatopera.cc.exception.CSKefuRestException;
@ -154,6 +155,7 @@ public class ApiContactNotesController extends Handler {
} }
ContactNotes cn = new ContactNotes(); ContactNotes cn = new ContactNotes();
cn.setId(MainUtils.getUUID());
cn.setCategory(payload.get("category").getAsString()); cn.setCategory(payload.get("category").getAsString());
cn.setContent(payload.get("content").getAsString()); cn.setContent(payload.get("content").getAsString());
cn.setCreater(payload.get("creater").getAsString()); cn.setCreater(payload.get("creater").getAsString());

View File

@ -292,7 +292,7 @@ public class ContactsController extends Handler {
values.add(MainUtils.transBean2Map(contacts)); values.add(MainUtils.transBean2Map(contacts));
} }
response.setHeader("content-disposition", "attachment;filename=UCKeFu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls"); response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls");
ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream()); ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream());
excelProcess.process(); excelProcess.process();
@ -317,7 +317,7 @@ public class ContactsController extends Handler {
values.add(MainUtils.transBean2Map(contacts)); values.add(MainUtils.transBean2Map(contacts));
} }
response.setHeader("content-disposition", "attachment;filename=UCKeFu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls"); response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls");
ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream()); ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream());
excelProcess.process(); excelProcess.process();
@ -343,7 +343,7 @@ public class ContactsController extends Handler {
values.add(MainUtils.transBean2Map(contacts)); values.add(MainUtils.transBean2Map(contacts));
} }
response.setHeader("content-disposition", "attachment;filename=UCKeFu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls"); response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls");
ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream()); ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream());
excelProcess.process(); excelProcess.process();
@ -430,4 +430,4 @@ public class ContactsController extends Handler {
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/embed/index.html")); return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/embed/index.html"));
} }
} }

View File

@ -17,13 +17,14 @@
package com.chatopera.cc.app.handler.apps.internet; package com.chatopera.cc.app.handler.apps.internet;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.handler.Handler; import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.im.util.RichMediaUtils; import com.chatopera.cc.app.im.util.RichMediaUtils;
import com.chatopera.cc.app.model.*; import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist; import com.chatopera.cc.app.persistence.blob.JpaBlobHelper;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.es.ContactsRepository; import com.chatopera.cc.app.persistence.es.ContactsRepository;
import com.chatopera.cc.app.persistence.repository.*; import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.util.*; import com.chatopera.cc.util.*;
@ -78,6 +79,12 @@ public class IMController extends Handler {
@Value("${web.upload-path}") @Value("${web.upload-path}")
private String path; private String path;
@Autowired
private StreamingFileRepository streamingFileRepository;
@Autowired
private JpaBlobHelper jpaBlobHelper;
@Autowired @Autowired
private ConsultInviteRepository inviteRepository; private ConsultInviteRepository inviteRepository;
@ -707,51 +714,79 @@ public class IMController extends Handler {
@RequestMapping("/image/upload") @RequestMapping("/image/upload")
@Menu(type = "im", subtype = "image", access = true) @Menu(type = "im", subtype = "image", access = true)
public ModelAndView upload(ModelMap map, HttpServletRequest request, @RequestParam(value = "imgFile", required = false) MultipartFile imgFile, @Valid String channel, @Valid String userid, @Valid String username, @Valid String appid, @Valid String orgi, @Valid String paste) throws IOException { public ModelAndView upload(ModelMap map, HttpServletRequest request,
@RequestParam(value = "imgFile", required = false) MultipartFile multipart,
@Valid String channel,
@Valid String userid,
@Valid String username,
@Valid String appid,
@Valid String orgi,
@Valid String paste) throws IOException {
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/upload")); ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/upload"));
UploadStatus upload = null; UploadStatus upload = null;
String fileName = null; String fileName = null;
if (imgFile != null && imgFile.getOriginalFilename().lastIndexOf(".") > 0 && StringUtils.isNotBlank(userid)) { if (multipart != null
&& multipart.getOriginalFilename().lastIndexOf(".") > 0
&& StringUtils.isNotBlank(userid)) {
File uploadDir = new File(path, "upload"); File uploadDir = new File(path, "upload");
if (!uploadDir.exists()) { if (!uploadDir.exists()) {
uploadDir.mkdirs(); uploadDir.mkdirs();
} }
String fileid = MainUtils.md5(imgFile.getBytes());
if (imgFile.getContentType() != null && imgFile.getContentType().indexOf("image") >= 0) {
fileName = "upload/" + fileid + "_original";
File imageFile = new File(path, fileName);
FileCopyUtils.copy(imgFile.getBytes(), imageFile);
String thumbnailsFileName = "upload/" + fileid;
MainUtils.processImage(new File(path, thumbnailsFileName), imageFile);
upload = new UploadStatus("0", "/res/image.html?id=" + thumbnailsFileName); String fileid = MainUtils.getUUID();
String image = "/res/image.html?id=" + thumbnailsFileName; StreamingFile sf = new StreamingFile();
if (request.getServerPort() == 80) { sf.setId(fileid);
image = "/res/image.html?id=" + thumbnailsFileName; sf.setName(multipart.getOriginalFilename());
} else { sf.setMime(multipart.getContentType());
image = "/res/image.html?id=" + thumbnailsFileName; if (multipart.getContentType() != null
} && multipart.getContentType().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) {
if (paste == null) { // 检查文件格式
if (StringUtils.isNotBlank(channel)) { String invalid = StreamingFileUtils.getInstance().validate(Constants.ATTACHMENT_TYPE_IMAGE, multipart.getOriginalFilename());
RichMediaUtils.uploadImageWithChannel(image, fileid, (int) imgFile.getSize(), imgFile.getName(), channel, userid, username, appid, orgi); if (invalid == null) {
} else { fileName = "upload/" + fileid + "_original";
RichMediaUtils.uploadImage(image, fileid, (int) imgFile.getSize(), imgFile.getName(), userid); File imageFile = new File(path, fileName);
FileCopyUtils.copy(multipart.getBytes(), imageFile);
String thumbnailsFileName = "upload/" + fileid;
File thumbnail = new File(path, thumbnailsFileName);
MainUtils.processImage(thumbnail, imageFile);
// 存储数据库
sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize()));
sf.setThumbnail(jpaBlobHelper.createBlobWithFile(thumbnail));
streamingFileRepository.save(sf);
String fileUrl = "/res/image.html?id=" + fileid;
upload = new UploadStatus("0", fileUrl);
if (paste == null) {
if (StringUtils.isNotBlank(channel)) {
RichMediaUtils.uploadImageWithChannel(fileUrl, fileid, (int) multipart.getSize(), multipart.getName(), channel, userid, username, appid, orgi);
} else {
RichMediaUtils.uploadImage(fileUrl, fileid, (int) multipart.getSize(), multipart.getName(), userid);
}
} }
} else {
upload = new UploadStatus(invalid);
} }
} else { } else {
String id = processAttachmentFile(imgFile, request); String invalid = StreamingFileUtils.getInstance().validate(Constants.ATTACHMENT_TYPE_FILE, multipart.getOriginalFilename());
upload = new UploadStatus("0", "/res/file.html?id=" + id); if (invalid == null) {
String file = "/res/file.html?id=" + id; // 存储数据库
if (request.getServerPort() == 80) { sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize()));
file = "/res/file.html?id=" + id; streamingFileRepository.save(sf);
// 存储到本地硬盘
String id = processAttachmentFile(multipart, fileid, request);
upload = new UploadStatus("0", "/res/file.html?id=" + id);
String file = "/res/file.html?id=" + id;
File tempFile = new File(multipart.getOriginalFilename());
if (StringUtils.isNotBlank(channel)) {
RichMediaUtils.uploadFileWithChannel(file, (int) multipart.getSize(), tempFile.getName(), channel, userid, username, appid, orgi, id);
} else {
RichMediaUtils.uploadFile(file, (int) multipart.getSize(), tempFile.getName(), userid, id);
}
} else { } else {
file = "/res/file.html?id=" + id; upload = new UploadStatus(invalid);
}
File tempFile = new File(imgFile.getOriginalFilename());
if (StringUtils.isNotBlank(channel)) {
RichMediaUtils.uploadFileWithChannel(file, (int) imgFile.getSize(), tempFile.getName(), channel, userid, username, appid, orgi, id);
} else {
RichMediaUtils.uploadFile(file, (int) imgFile.getSize(), tempFile.getName(), userid, id);
} }
} }
} else { } else {
@ -761,36 +796,33 @@ public class IMController extends Handler {
return view; return view;
} }
private String processAttachmentFile(MultipartFile file, HttpServletRequest request) throws IOException { private String processAttachmentFile(final MultipartFile file, final String fileid, HttpServletRequest request) throws IOException {
String id = null; String id = null;
if (file.getSize() > 0) { //文件尺寸 限制 启动 配置中 设置 的最大值其他地方不做限制 if (file.getSize() > 0) { //文件尺寸 限制 启动 配置中 设置 的最大值其他地方不做限制
String fileid = MainUtils.md5(file.getBytes()); //使用 文件的 MD5作为 ID避免重复上传大文件 AttachmentFile attachmentFile = new AttachmentFile();
if (StringUtils.isNotBlank(fileid)) { attachmentFile.setCreater(super.getUser(request).getId());
AttachmentFile attachmentFile = new AttachmentFile(); attachmentFile.setOrgi(super.getOrgi(request));
attachmentFile.setCreater(super.getUser(request).getId()); attachmentFile.setOrgan(super.getUser(request).getOrgan());
attachmentFile.setOrgi(super.getOrgi(request)); attachmentFile.setModel(MainContext.ModelType.WEBIM.toString());
attachmentFile.setOrgan(super.getUser(request).getOrgan()); attachmentFile.setFilelength((int) file.getSize());
attachmentFile.setModel(MainContext.ModelType.WEBIM.toString()); if (file.getContentType() != null && file.getContentType().length() > 255) {
attachmentFile.setFilelength((int) file.getSize()); attachmentFile.setFiletype(file.getContentType().substring(0, 255));
if (file.getContentType() != null && file.getContentType().length() > 255) { } else {
attachmentFile.setFiletype(file.getContentType().substring(0, 255)); attachmentFile.setFiletype(file.getContentType());
} else {
attachmentFile.setFiletype(file.getContentType());
}
File uploadFile = new File(file.getOriginalFilename());
if (uploadFile.getName() != null && uploadFile.getName().length() > 255) {
attachmentFile.setTitle(uploadFile.getName().substring(0, 255));
} else {
attachmentFile.setTitle(uploadFile.getName());
}
if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) {
attachmentFile.setImage(true);
}
attachmentFile.setFileid(fileid);
attachementRes.save(attachmentFile);
FileUtils.writeByteArrayToFile(new File(path, "app/app/" + fileid), file.getBytes());
id = attachmentFile.getId();
} }
File uploadFile = new File(file.getOriginalFilename());
if (uploadFile.getName() != null && uploadFile.getName().length() > 255) {
attachmentFile.setTitle(uploadFile.getName().substring(0, 255));
} else {
attachmentFile.setTitle(uploadFile.getName());
}
if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) {
attachmentFile.setImage(true);
}
attachmentFile.setFileid(fileid);
attachementRes.save(attachmentFile);
FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), file.getBytes());
id = attachmentFile.getId();
} }
return id; return id;
} }

View File

@ -419,7 +419,7 @@ public class TopicController extends Handler{
values.add(MainUtils.transBean2Map(topic)) ; values.add(MainUtils.transBean2Map(topic)) ;
} }
response.setHeader("content-disposition", "attachment;filename=UCKeFu-Contacts-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls"); response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls");
if(table!=null){ if(table!=null){
ExcelExporterProcess excelProcess = new ExcelExporterProcess( values, table, response.getOutputStream()) ; ExcelExporterProcess excelProcess = new ExcelExporterProcess( values, table, response.getOutputStream()) ;
excelProcess.process(); excelProcess.process();
@ -469,4 +469,4 @@ public class TopicController extends Handler{
} }
return ; return ;
} }
} }

View File

@ -16,27 +16,17 @@
*/ */
package com.chatopera.cc.app.handler.apps.service; package com.chatopera.cc.app.handler.apps.service;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.util.IP;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist; import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.util.OnlineUserUtils;
import com.chatopera.cc.app.handler.Handler; import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.util.IP;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.util.OnlineUserUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@ -48,400 +38,402 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.app.persistence.repository.AgentServiceRepository; import javax.persistence.criteria.CriteriaBuilder;
import com.chatopera.cc.app.persistence.repository.AgentStatusRepository; import javax.persistence.criteria.CriteriaQuery;
import com.chatopera.cc.app.persistence.repository.AgentUserRepository; import javax.persistence.criteria.Predicate;
import com.chatopera.cc.app.persistence.repository.LeaveMsgRepository; import javax.persistence.criteria.Root;
import com.chatopera.cc.app.persistence.repository.OrganRepository; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.persistence.repository.OrgiSkillRelRepository; import javax.validation.Valid;
import com.chatopera.cc.app.persistence.repository.UserRepository; import java.text.ParseException;
import com.chatopera.cc.app.model.AgentService; import java.util.ArrayList;
import com.chatopera.cc.app.model.AgentStatus; import java.util.Date;
import com.chatopera.cc.app.model.AgentUser; import java.util.List;
import com.chatopera.cc.app.model.AiUser;
import com.chatopera.cc.app.model.LeaveMsg;
import com.chatopera.cc.app.model.Organ;
import com.chatopera.cc.app.model.OrgiSkillRel;
import com.chatopera.cc.app.model.User;
@Controller @Controller
@RequestMapping("/service") @RequestMapping("/service")
public class ChatServiceController extends Handler { public class ChatServiceController extends Handler {
@Autowired @Autowired
private AgentServiceRepository agentServiceRes ; private AgentServiceRepository agentServiceRes;
@Autowired @Autowired
private AgentUserRepository agentUserRes ; private AgentUserRepository agentUserRes;
@Autowired @Autowired
private AgentStatusRepository agentStatusRepository ; private AgentStatusRepository agentStatusRepository;
@Autowired @Autowired
private AgentUserRepository agentUserRepository ; private AgentUserRepository agentUserRepository;
@Autowired @Autowired
private LeaveMsgRepository leaveMsgRes ; private LeaveMsgRepository leaveMsgRes;
@Autowired @Autowired
private OrganRepository organRes ; private OrganRepository organRes;
@Autowired @Autowired
private OrganRepository organ ; private OrganRepository organ;
@Autowired @Autowired
private UserRepository user ; private UserRepository user;
@Autowired @Autowired
private UserRepository userRes ; private UserRepository userRes;
@Autowired @Autowired
private OrgiSkillRelRepository orgiSkillRelService; private OrgiSkillRelRepository orgiSkillRelService;
@RequestMapping("/history/index") @RequestMapping("/history/index")
@Menu(type = "service" , subtype = "history" , admin= true) @Menu(type = "service", subtype = "history", admin = true)
public ModelAndView index(ModelMap map , HttpServletRequest request ,final String username,final String channel ,final String servicetype,final String allocation,final String servicetimetype,final String begin,final String end) { public ModelAndView index(ModelMap map, HttpServletRequest request, final String username, final String channel, final String servicetype, final String allocation, final String servicetimetype, final String begin, final String end) {
Page<AgentService> page = agentServiceRes.findAll(new Specification<AgentService>(){ Page<AgentService> page = agentServiceRes.findAll(new Specification<AgentService>() {
@Override @Override
public Predicate toPredicate(Root<AgentService> root, CriteriaQuery<?> query,CriteriaBuilder cb) { public Predicate toPredicate(Root<AgentService> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> list = new ArrayList<Predicate>(); List<Predicate> list = new ArrayList<Predicate>();
if(!StringUtils.isBlank(username)) { if (!StringUtils.isBlank(username)) {
list.add(cb.equal(root.get("username").as(String.class), username)) ; list.add(cb.equal(root.get("username").as(String.class), username));
} }
if(!StringUtils.isBlank(channel)) { if (!StringUtils.isBlank(channel)) {
list.add(cb.equal(root.get("channel").as(String.class), channel)) ; list.add(cb.equal(root.get("channel").as(String.class), channel));
} }
if(!StringUtils.isBlank(servicetype)&&!StringUtils.isBlank(allocation)) { if (!StringUtils.isBlank(servicetype) && !StringUtils.isBlank(allocation)) {
list.add(cb.equal(root.get(servicetype).as(String.class), allocation)); list.add(cb.equal(root.get(servicetype).as(String.class), allocation));
} }
if(!StringUtils.isBlank(servicetimetype)) { if (!StringUtils.isBlank(servicetimetype)) {
try { try {
if(!StringUtils.isBlank(begin) && begin.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){ if (!StringUtils.isBlank(begin) && begin.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")) {
list.add(cb.greaterThanOrEqualTo(root.get(servicetimetype).as(Date.class), MainUtils.dateFormate.parse(begin))) ; list.add(cb.greaterThanOrEqualTo(root.get(servicetimetype).as(Date.class), MainUtils.dateFormate.parse(begin)));
} }
if(!StringUtils.isBlank(end) && end.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){ if (!StringUtils.isBlank(end) && end.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")) {
list.add(cb.lessThanOrEqualTo(root.get(servicetimetype).as(Date.class), MainUtils.dateFormate.parse(end))) ; list.add(cb.lessThanOrEqualTo(root.get(servicetimetype).as(Date.class), MainUtils.dateFormate.parse(end)));
} }
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
Predicate[] p = new Predicate[list.size()]; Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p)); return cb.and(list.toArray(p));
} }
},new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")) ; }, new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
map.put("agentServiceList", page) ; map.put("agentServiceList", page);
map.put("username", username) ; map.put("username", username);
map.put("channel", channel) ; map.put("channel", channel);
map.put("servicetype", servicetype) ; map.put("servicetype", servicetype);
map.put("servicetimetype", servicetimetype) ; map.put("servicetimetype", servicetimetype);
map.put("allocation", allocation); map.put("allocation", allocation);
map.put("begin", begin) ; map.put("begin", begin);
map.put("end", end) ; map.put("end", end);
map.put("deptlist",organ.findByOrgi(super.getOrgi(request))); map.put("deptlist", organ.findByOrgi(super.getOrgi(request)));
map.put("userlist",user.findByOrgiAndDatastatus(super.getOrgi(request), false)); map.put("userlist", user.findByOrgiAndDatastatus(super.getOrgi(request), false));
return request(super.createAppsTempletResponse("/apps/service/history/index")); return request(super.createAppsTempletResponse("/apps/service/history/index"));
} }
@RequestMapping("/current/index") @RequestMapping("/current/index")
@Menu(type = "service" , subtype = "current" , admin= true) @Menu(type = "service", subtype = "current", admin = true)
public ModelAndView current(ModelMap map , HttpServletRequest request) { public ModelAndView current(ModelMap map, HttpServletRequest request) {
map.put("agentServiceList", agentServiceRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.AgentUserStatusEnum.INSERVICE.toString() ,new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime"))) ; map.put("agentServiceList", agentServiceRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.AgentUserStatusEnum.INSERVICE.toString(), new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime")));
return request(super.createAppsTempletResponse("/apps/service/current/index")); return request(super.createAppsTempletResponse("/apps/service/current/index"));
} }
@RequestMapping("/current/trans") @RequestMapping("/current/trans")
@Menu(type = "service" , subtype = "current" , admin= true) @Menu(type = "service", subtype = "current", admin = true)
public ModelAndView trans(ModelMap map , HttpServletRequest request , @Valid String id) { public ModelAndView trans(ModelMap map, HttpServletRequest request, @Valid String id) {
if(!StringUtils.isBlank(id)){ if (!StringUtils.isBlank(id)) {
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request)) ; AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
List<Organ> skillList = OnlineUserUtils.organ(super.getOrgi(request),true) ; List<Organ> skillList = OnlineUserUtils.organ(super.getOrgi(request), true);
String currentOrgan = super.getUser(request).getOrgan(); String currentOrgan = super.getUser(request).getOrgan();
if(StringUtils.isBlank(currentOrgan)) { if (StringUtils.isBlank(currentOrgan)) {
if(!skillList.isEmpty()) { if (!skillList.isEmpty()) {
currentOrgan = skillList.get(0).getId(); currentOrgan = skillList.get(0).getId();
} }
} }
List<AgentStatus> agentStatusList = AutomaticServiceDist.getAgentStatus(null , super.getOrgi(request)); List<AgentStatus> agentStatusList = AutomaticServiceDist.getAgentStatus(null, super.getOrgi(request));
List<String> usersids = new ArrayList<String>(); List<String> usersids = new ArrayList<String>();
if(!agentStatusList.isEmpty()) { if (!agentStatusList.isEmpty()) {
for(AgentStatus agentStatus:agentStatusList) { for (AgentStatus agentStatus : agentStatusList) {
if(agentStatus!=null){ if (agentStatus != null) {
usersids.add(agentStatus.getAgentno()) ; usersids.add(agentStatus.getAgentno());
} }
} }
} }
List<User> userList = userRes.findAll(usersids); List<User> userList = userRes.findAll(usersids);
for(User user : userList){ for (User user : userList) {
user.setAgentStatus((AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgi(request))); user.setAgentStatus((AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgi(request)));
} }
map.addAttribute("userList", userList) ; map.addAttribute("userList", userList);
map.addAttribute("userid", agentService.getUserid()) ; map.addAttribute("userid", agentService.getUserid());
map.addAttribute("agentserviceid", agentService.getId()) ; map.addAttribute("agentserviceid", agentService.getId());
map.addAttribute("agentuserid", agentService.getAgentuserid()) ; map.addAttribute("agentuserid", agentService.getAgentuserid());
map.addAttribute("agentservice", agentService) ; map.addAttribute("agentservice", agentService);
map.addAttribute("skillList", skillList) ; map.addAttribute("skillList", skillList);
map.addAttribute("currentorgan", currentOrgan) ; map.addAttribute("currentorgan", currentOrgan);
} }
return request(super.createRequestPageTempletResponse("/apps/service/current/transfer")); return request(super.createRequestPageTempletResponse("/apps/service/current/transfer"));
} }
@RequestMapping(value="/transfer/save") @RequestMapping(value = "/transfer/save")
@Menu(type = "apps", subtype = "transfersave") @Menu(type = "apps", subtype = "transfersave")
public ModelAndView transfersave(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String agentno , @Valid String memo){ public ModelAndView transfersave(ModelMap map, HttpServletRequest request, @Valid String id, @Valid String agentno, @Valid String memo) {
if(!StringUtils.isBlank(id)){ if (!StringUtils.isBlank(id)) {
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request)) ; AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(agentService.getUserid(), super.getOrgi(request)) ; AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(agentService.getUserid(), super.getOrgi(request));
if(agentUser != null){ if (agentUser != null) {
agentUser.setAgentno(agentno); agentUser.setAgentno(agentno);
CacheHelper.getAgentUserCacheBean().put(agentService.getUserid() , agentUser , super.getOrgi(request)) ; CacheHelper.getAgentUserCacheBean().put(agentService.getUserid(), agentUser, super.getOrgi(request));
agentUserRepository.save(agentUser) ; agentUserRepository.save(agentUser);
if(MainContext.AgentUserStatusEnum.INSERVICE.toString().equals(agentUser.getStatus())){ //转接 发送消息给 目标坐席 if (MainContext.AgentUserStatusEnum.INSERVICE.toString().equals(agentUser.getStatus())) { //转接 发送消息给 目标坐席
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(super.getUser(request).getId(), super.getOrgi(request)) ; AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(super.getUser(request).getId(), super.getOrgi(request));
if(agentStatus!=null){ if (agentStatus != null) {
AutomaticServiceDist.updateAgentStatus(agentStatus, agentUser, super.getOrgi(request), false); AutomaticServiceDist.updateAgentStatus(agentStatus, agentUser, super.getOrgi(request), false);
} }
AgentStatus transAgentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentno, super.getOrgi(request)) ; AgentStatus transAgentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentno, super.getOrgi(request));
if(transAgentStatus!=null){ if (transAgentStatus != null) {
AutomaticServiceDist.updateAgentStatus(transAgentStatus, agentUser, super.getOrgi(request), true); AutomaticServiceDist.updateAgentStatus(transAgentStatus, agentUser, super.getOrgi(request), true);
agentService.setAgentno(agentno); agentService.setAgentno(agentno);
agentService.setAgentusername(transAgentStatus.getUsername()); agentService.setAgentusername(transAgentStatus.getUsername());
} }
NettyClients.getInstance().sendAgentEventMessage(agentno, MainContext.MessageTypeEnum.NEW.toString(), agentUser); // TODO #111 通知转接消息
} NettyClients.getInstance().publishAgentEventMessage(agentno, MainContext.MessageTypeEnum.NEW.toString(), agentUser);
}else{ }
agentUser = agentUserRepository.findByIdAndOrgi(agentService.getAgentuserid(), super.getOrgi(request)); } else {
if(agentUser!=null){ agentUser = agentUserRepository.findByIdAndOrgi(agentService.getAgentuserid(), super.getOrgi(request));
agentUser.setAgentno(agentno); if (agentUser != null) {
agentUserRepository.save(agentUser) ; agentUser.setAgentno(agentno);
} agentUserRepository.save(agentUser);
} }
}
if(agentService!=null){
agentService.setAgentno(agentno); if (agentService != null) {
if(!StringUtils.isBlank(memo)){ agentService.setAgentno(agentno);
agentService.setTransmemo(memo); if (!StringUtils.isBlank(memo)) {
} agentService.setTransmemo(memo);
agentService.setTrans(true); }
agentService.setTranstime(new Date()); agentService.setTrans(true);
agentServiceRes.save(agentService) ; agentService.setTranstime(new Date());
} agentServiceRes.save(agentService);
} }
}
return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html")) ;
}
@RequestMapping("/current/end")
@Menu(type = "service" , subtype = "current" , admin= true)
public ModelAndView end(ModelMap map , HttpServletRequest request , @Valid String id) throws Exception {
if(!StringUtils.isBlank(id)){
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request)) ;
if(agentService!=null){
User user = super.getUser(request);
AgentUser agentUser = agentUserRepository.findByIdAndOrgi(agentService.getAgentuserid(), super.getOrgi(request));
if(agentUser!=null){
AutomaticServiceDist.deleteAgentUser(agentUser, user.getOrgi());
}
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
agentServiceRes.save(agentService) ;
}
}
return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html")); return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html"));
} }
@RequestMapping("/current/invite") @RequestMapping("/current/end")
@Menu(type = "service" , subtype = "current" , admin= true) @Menu(type = "service", subtype = "current", admin = true)
public ModelAndView currentinvite(ModelMap map , HttpServletRequest request , @Valid String id) throws Exception { public ModelAndView end(ModelMap map, HttpServletRequest request, @Valid String id) throws Exception {
if(!StringUtils.isBlank(id)){ if (!StringUtils.isBlank(id)) {
AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request)) ; AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
if(agentService!=null){ if (agentService != null) {
User user = super.getUser(request); User user = super.getUser(request);
if(StringUtils.isBlank(agentService.getAgentno())) { AgentUser agentUser = agentUserRepository.findByIdAndOrgi(agentService.getAgentuserid(), super.getOrgi(request));
AiUser aiUser = (AiUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(agentService.getSessionid(), agentService.getOrgi()) ; if (agentUser != null) {
IP ipdata = null ; AutomaticServiceDist.deleteAgentUser(agentUser, user.getOrgi());
if(aiUser != null ) { }
ipdata = aiUser.getIpdata() ; agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
OnlineUserUtils.newRequestMessage(aiUser.getUserid() , aiUser.getUsername(), user.getOrgi(), agentService.getSessionid(), agentService.getAppid() , agentService.getIpaddr(), agentService.getOsname() , agentService.getBrowser() , "" , ipdata!=null ? ipdata : null , agentService.getChannel() , user.getOrgan(), user.getId() , null ,null, agentService.getContactsid(), MainContext.ChatInitiatorType.AGENT.toString() , aiUser.getContextid()) ; agentServiceRes.save(agentService);
} }
} }
}
}
return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html")); return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html"));
} }
@RequestMapping("/current/invite")
@RequestMapping("/quene/index") @Menu(type = "service", subtype = "current", admin = true)
@Menu(type = "service" , subtype = "filter" , admin= true) public ModelAndView currentinvite(ModelMap map, HttpServletRequest request, @Valid String id) throws Exception {
public ModelAndView quene(ModelMap map , HttpServletRequest request) { if (!StringUtils.isBlank(id)) {
Page<AgentUser> agentUserList = agentUserRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.AgentUserStatusEnum.INQUENE.toString() ,new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")) ; AgentService agentService = agentServiceRes.findByIdAndOrgi(id, super.getOrgi(request));
List<String> skillList = new ArrayList<String>(); if (agentService != null) {
for(AgentUser agentUser : agentUserList.getContent()){ User user = super.getUser(request);
agentUser.setWaittingtime((int) (System.currentTimeMillis() - agentUser.getCreatetime().getTime())); if (StringUtils.isBlank(agentService.getAgentno())) {
if(!StringUtils.isBlank(agentUser.getSkill())){ AiUser aiUser = (AiUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(agentService.getSessionid(), agentService.getOrgi());
skillList.add(agentUser.getSkill()) ; IP ipdata = null;
} if (aiUser != null) {
} ipdata = aiUser.getIpdata();
if(skillList.size() > 0){ OnlineUserUtils.newRequestMessage(aiUser.getUserid(), aiUser.getUsername(), user.getOrgi(), agentService.getSessionid(), agentService.getAppid(), agentService.getIpaddr(), agentService.getOsname(), agentService.getBrowser(), "", ipdata != null ? ipdata : null, agentService.getChannel(), user.getOrgan(), user.getId(), null, null, agentService.getContactsid(), MainContext.ChatInitiatorType.AGENT.toString(), aiUser.getContextid());
List<Organ> organList = organRes.findAll(skillList) ; }
for(AgentUser agentUser : agentUserList.getContent()){ }
if(!StringUtils.isBlank(agentUser.getSkill())){ }
for(Organ organ : organList){ }
if(agentUser.getSkill().equals(organ.getId())){ return request(super.createRequestPageTempletResponse("redirect:/service/current/index.html"));
agentUser.setSkillname(organ.getName()); }
break ;
}
} @RequestMapping("/quene/index")
} @Menu(type = "service", subtype = "filter", admin = true)
} public ModelAndView quene(ModelMap map, HttpServletRequest request) {
} Page<AgentUser> agentUserList = agentUserRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.AgentUserStatusEnum.INQUENE.toString(), new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
map.put("agentUserList", agentUserList) ; List<String> skillList = new ArrayList<String>();
for (AgentUser agentUser : agentUserList.getContent()) {
agentUser.setWaittingtime((int) (System.currentTimeMillis() - agentUser.getCreatetime().getTime()));
if (!StringUtils.isBlank(agentUser.getSkill())) {
skillList.add(agentUser.getSkill());
}
}
if (skillList.size() > 0) {
List<Organ> organList = organRes.findAll(skillList);
for (AgentUser agentUser : agentUserList.getContent()) {
if (!StringUtils.isBlank(agentUser.getSkill())) {
for (Organ organ : organList) {
if (agentUser.getSkill().equals(organ.getId())) {
agentUser.setSkillname(organ.getName());
break;
}
}
}
}
}
map.put("agentUserList", agentUserList);
return request(super.createAppsTempletResponse("/apps/service/quene/index")); return request(super.createAppsTempletResponse("/apps/service/quene/index"));
} }
@RequestMapping("/quene/clean") @RequestMapping("/quene/clean")
@Menu(type = "service" , subtype = "queneclean" , admin= true) @Menu(type = "service", subtype = "queneclean", admin = true)
public ModelAndView clean(ModelMap map , HttpServletRequest request ,@Valid String id) { public ModelAndView clean(ModelMap map, HttpServletRequest request, @Valid String id) {
AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request)) ; AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request));
if(agentUser!=null && agentUser.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())){ if (agentUser != null && agentUser.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())) {
agentUser.setAgent(null); agentUser.setAgent(null);
agentUser.setSkill(null); agentUser.setSkill(null);
agentUserRes.save(agentUser) ; agentUserRes.save(agentUser);
CacheHelper.getAgentUserCacheBean().put(agentUser.getUserid(), agentUser, super.getOrgi(request)); CacheHelper.getAgentUserCacheBean().put(agentUser.getUserid(), agentUser, super.getOrgi(request));
AutomaticServiceDist.allotAgent(agentUser, super.getOrgi(request)) ; AutomaticServiceDist.allotAgent(agentUser, super.getOrgi(request));
} }
return request(super.createRequestPageTempletResponse("redirect:/service/quene/index.html")); return request(super.createRequestPageTempletResponse("redirect:/service/quene/index.html"));
} }
@RequestMapping("/quene/invite") @RequestMapping("/quene/invite")
@Menu(type = "service" , subtype = "invite" , admin= true) @Menu(type = "service", subtype = "invite", admin = true)
public ModelAndView invite(ModelMap map , HttpServletRequest request ,@Valid String id) throws Exception { public ModelAndView invite(ModelMap map, HttpServletRequest request, @Valid String id) throws Exception {
AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request)) ; AgentUser agentUser = agentUserRes.findByIdAndOrgi(id, super.getOrgi(request));
if(agentUser!=null && agentUser.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())){ if (agentUser != null && agentUser.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())) {
AutomaticServiceDist.allotAgentForInvite(super.getUser(request).getId() , agentUser, super.getOrgi(request)) ; AutomaticServiceDist.allotAgentForInvite(super.getUser(request).getId(), agentUser, super.getOrgi(request));
} }
return request(super.createRequestPageTempletResponse("redirect:/service/quene/index.html")); return request(super.createRequestPageTempletResponse("redirect:/service/quene/index.html"));
} }
@RequestMapping("/agent/index") @RequestMapping("/agent/index")
@Menu(type = "service" , subtype = "onlineagent" , admin= true) @Menu(type = "service", subtype = "onlineagent", admin = true)
public ModelAndView agent(ModelMap map , HttpServletRequest request) { public ModelAndView agent(ModelMap map, HttpServletRequest request) {
List<AgentStatus> agentStatusList = agentStatusRepository.findByOrgi(super.getOrgi(request)) ; List<AgentStatus> agentStatusList = agentStatusRepository.findByOrgi(super.getOrgi(request));
for(int i=0 ; i<agentStatusList.size() ; ){ for (int i = 0; i < agentStatusList.size(); ) {
AgentStatus agentStatus = agentStatusList.get(i) ; AgentStatus agentStatus = agentStatusList.get(i);
if(CacheHelper.getAgentStatusCacheBean().getCacheObject(agentStatus.getAgentno(), super.getOrgi(request))==null) { if (CacheHelper.getAgentStatusCacheBean().getCacheObject(agentStatus.getAgentno(), super.getOrgi(request)) == null) {
agentStatusRepository.delete(agentStatus); agentStatusRepository.delete(agentStatus);
agentStatusList.remove(i) ; agentStatusList.remove(i);
continue ; continue;
}else{ } else {
AgentStatus temp = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentStatus.getAgentno(), super.getOrgi(request)) ; AgentStatus temp = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentStatus.getAgentno(), super.getOrgi(request));
agentStatusList.set(i, temp) ; agentStatusList.set(i, temp);
} }
i++ ; i++;
} }
List<String> skillList = new ArrayList<String>(); List<String> skillList = new ArrayList<String>();
for(AgentStatus agentStatus : agentStatusList){ for (AgentStatus agentStatus : agentStatusList) {
if(!StringUtils.isBlank(agentStatus.getSkill())){ if (!StringUtils.isBlank(agentStatus.getSkill())) {
skillList.add(agentStatus.getSkill()) ; skillList.add(agentStatus.getSkill());
} }
} }
if(skillList.size() > 0){ if (skillList.size() > 0) {
List<Organ> organList = organRes.findAll(skillList) ; List<Organ> organList = organRes.findAll(skillList);
for(AgentStatus agentStatus : agentStatusList){ for (AgentStatus agentStatus : agentStatusList) {
if(!StringUtils.isBlank(agentStatus.getSkill())){ if (!StringUtils.isBlank(agentStatus.getSkill())) {
for(Organ organ : organList){ for (Organ organ : organList) {
if(agentStatus.getSkill().equals(organ.getId())){ if (agentStatus.getSkill().equals(organ.getId())) {
agentStatus.setSkillname(organ.getName()); agentStatus.setSkillname(organ.getName());
break ; break;
} }
} }
} }
} }
} }
map.put("agentStatusList", agentStatusList) ; map.put("agentStatusList", agentStatusList);
return request(super.createAppsTempletResponse("/apps/service/agent/index")); return request(super.createAppsTempletResponse("/apps/service/agent/index"));
} }
@RequestMapping("/agent/offline") @RequestMapping("/agent/offline")
@Menu(type = "service" , subtype = "offline" , admin= true) @Menu(type = "service", subtype = "offline", admin = true)
public ModelAndView offline(ModelMap map , HttpServletRequest request , @Valid String id) { public ModelAndView offline(ModelMap map, HttpServletRequest request, @Valid String id) {
AgentStatus agentStatus = agentStatusRepository.findByIdAndOrgi(id, super.getOrgi(request)); AgentStatus agentStatus = agentStatusRepository.findByIdAndOrgi(id, super.getOrgi(request));
if(agentStatus!=null){ if (agentStatus != null) {
agentStatusRepository.delete(agentStatus); agentStatusRepository.delete(agentStatus);
} }
CacheHelper.getAgentStatusCacheBean().delete(agentStatus.getAgentno(), super.getOrgi(request));; CacheHelper.getAgentStatusCacheBean().delete(agentStatus.getAgentno(), super.getOrgi(request));
AutomaticServiceDist.publishMessage(super.getOrgi(request) , "agent" , "offline" , super.getUser(request).getId()); ;
AutomaticServiceDist.publishMessage(super.getOrgi(request), "agent", "offline", super.getUser(request).getId());
return request(super.createRequestPageTempletResponse("redirect:/service/agent/index.html")); return request(super.createRequestPageTempletResponse("redirect:/service/agent/index.html"));
} }
/**
* 非管理员坐席 /**
* @param map * 非管理员坐席
* @param request *
* @return * @param map
*/ * @param request
@RequestMapping("/user/index") * @return
@Menu(type = "service" , subtype = "userlist" , admin= true) */
public ModelAndView user(ModelMap map , HttpServletRequest request) { @RequestMapping("/user/index")
Page<User> userList = null; @Menu(type = "service", subtype = "userlist", admin = true)
if(super.isTenantshare()) { public ModelAndView user(ModelMap map, HttpServletRequest request) {
List<String> organIdList = new ArrayList<>(); Page<User> userList = null;
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ; if (super.isTenantshare()) {
if(!orgiSkillRelList.isEmpty()) { List<String> organIdList = new ArrayList<>();
for(OrgiSkillRel rel:orgiSkillRelList) { List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request));
organIdList.add(rel.getSkillid()); if (!orgiSkillRelList.isEmpty()) {
} for (OrgiSkillRel rel : orgiSkillRelList) {
} organIdList.add(rel.getSkillid());
userList=userRes.findByOrganInAndAgentAndDatastatus(organIdList,true,false,new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")); }
}else { }
userList=userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true,false, new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")) ; userList = userRes.findByOrganInAndAgentAndDatastatus(organIdList, true, false, new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
} } else {
for(User user : userList.getContent()){ userList = userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true, false, new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
if(CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgi(request))!=null){ }
user.setOnline(true); for (User user : userList.getContent()) {
} if (CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgi(request)) != null) {
} user.setOnline(true);
map.put("userList", userList) ; }
}
map.put("userList", userList);
return request(super.createAppsTempletResponse("/apps/service/user/index")); return request(super.createAppsTempletResponse("/apps/service/user/index"));
} }
/**
* 管理员坐席 /**
* @param map * 管理员坐席
* @param request *
* @return * @param map
*/ * @param request
@RequestMapping("/adminagent/index") * @return
@Menu(type = "service" , subtype = "adminagentlist" , admin= true) */
public ModelAndView adminagent(ModelMap map , HttpServletRequest request) { @RequestMapping("/adminagent/index")
Page<User> userList = userRes.findByOrgidAndAgentAndDatastatusAndUsertype(super.getOrgid(request), true,false,"0", new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")) ; @Menu(type = "service", subtype = "adminagentlist", admin = true)
for(User user : userList.getContent()){ public ModelAndView adminagent(ModelMap map, HttpServletRequest request) {
if(CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgi(request))!=null){ Page<User> userList = userRes.findByOrgidAndAgentAndDatastatusAndUsertype(super.getOrgid(request), true, false, "0", new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
user.setOnline(true); for (User user : userList.getContent()) {
} if (CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgi(request)) != null) {
} user.setOnline(true);
map.put("userList", userList) ; }
}
map.put("userList", userList);
return request(super.createAppsTempletResponse("/apps/service/adminagent/index")); return request(super.createAppsTempletResponse("/apps/service/adminagent/index"));
} }
@RequestMapping("/leavemsg/index")
@Menu(type = "service" , subtype = "leavemsg" , admin= true) @RequestMapping("/leavemsg/index")
public ModelAndView leavemsg(ModelMap map , HttpServletRequest request) { @Menu(type = "service", subtype = "leavemsg", admin = true)
Page<LeaveMsg> leaveMsgList = leaveMsgRes.findByOrgi(super.getOrgi(request),new PageRequest(super.getP(request), super.getPs(request), Direction.DESC , "createtime")) ; public ModelAndView leavemsg(ModelMap map, HttpServletRequest request) {
map.put("leaveMsgList", leaveMsgList) ; Page<LeaveMsg> leaveMsgList = leaveMsgRes.findByOrgi(super.getOrgi(request), new PageRequest(super.getP(request), super.getPs(request), Direction.DESC, "createtime"));
map.put("leaveMsgList", leaveMsgList);
return request(super.createAppsTempletResponse("/apps/service/leavemsg/index")); return request(super.createAppsTempletResponse("/apps/service/leavemsg/index"));
} }
@RequestMapping("/leavemsg/delete") @RequestMapping("/leavemsg/delete")
@Menu(type = "service" , subtype = "leavemsg" , admin= true) @Menu(type = "service", subtype = "leavemsg", admin = true)
public ModelAndView leavemsg(ModelMap map , HttpServletRequest request , @Valid String id) { public ModelAndView leavemsg(ModelMap map, HttpServletRequest request, @Valid String id) {
if(!StringUtils.isBlank(id)){ if (!StringUtils.isBlank(id)) {
leaveMsgRes.delete(id); leaveMsgRes.delete(id);
} }
return request(super.createRequestPageTempletResponse("redirect:/service/leavemsg/index.html")); return request(super.createRequestPageTempletResponse("redirect:/service/leavemsg/index.html"));
} }
} }

View File

@ -16,20 +16,14 @@
*/ */
package com.chatopera.cc.app.handler.apps.service; package com.chatopera.cc.app.handler.apps.service;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.util.Menu; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.es.ContactsRepository; import com.chatopera.cc.app.persistence.es.ContactsRepository;
import com.chatopera.cc.app.persistence.impl.AgentUserService; import com.chatopera.cc.app.persistence.impl.AgentUserService;
import com.chatopera.cc.app.handler.Handler; import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.app.model.AgentServiceSummary; import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.model.AgentUser;
import com.chatopera.cc.app.model.AgentUserContacts;
import com.chatopera.cc.app.model.OnlineUser;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
@ -39,156 +33,147 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.app.basic.MainUtils; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.persistence.repository.AgentServiceRepository; import javax.validation.Valid;
import com.chatopera.cc.app.persistence.repository.AgentUserContactsRepository; import java.util.List;
import com.chatopera.cc.app.persistence.repository.ChatMessageRepository;
import com.chatopera.cc.app.persistence.repository.OnlineUserHisRepository;
import com.chatopera.cc.app.persistence.repository.OnlineUserRepository;
import com.chatopera.cc.app.persistence.repository.ServiceSummaryRepository;
import com.chatopera.cc.app.persistence.repository.TagRelationRepository;
import com.chatopera.cc.app.persistence.repository.TagRepository;
import com.chatopera.cc.app.persistence.repository.UserEventRepository;
import com.chatopera.cc.app.persistence.repository.WeiXinUserRepository;
import com.chatopera.cc.app.model.AgentService;
import com.chatopera.cc.app.model.WeiXinUser;
@Controller @Controller
@RequestMapping("/service") @RequestMapping("/service")
public class OnlineUserController extends Handler { public class OnlineUserController extends Handler {
@Autowired @Autowired
private AgentServiceRepository agentServiceRes ; private AgentServiceRepository agentServiceRes;
@Autowired @Autowired
private AgentUserService agentUserRes ; private AgentUserService agentUserRes;
@Autowired @Autowired
private OnlineUserRepository onlineUserRes; private OnlineUserRepository onlineUserRes;
@Autowired @Autowired
private UserEventRepository userEventRes; private UserEventRepository userEventRes;
@Autowired @Autowired
private ServiceSummaryRepository serviceSummaryRes; private ServiceSummaryRepository serviceSummaryRes;
@Autowired @Autowired
private OnlineUserHisRepository onlineUserHisRes; private OnlineUserHisRepository onlineUserHisRes;
@Autowired @Autowired
private WeiXinUserRepository weiXinUserRes; private WeiXinUserRepository weiXinUserRes;
@Autowired @Autowired
private TagRepository tagRes ; private TagRepository tagRes;
@Autowired @Autowired
private TagRelationRepository tagRelationRes ; private TagRelationRepository tagRelationRes;
@Autowired @Autowired
private ChatMessageRepository chatMessageRepository ; private ChatMessageRepository chatMessageRepository;
@Autowired @Autowired
private ContactsRepository contactsRes ; private ContactsRepository contactsRes;
@Autowired @Autowired
private AgentUserContactsRepository agentUserContactsRes ; private AgentUserContactsRepository agentUserContactsRes;
@RequestMapping("/online/index") @RequestMapping("/online/index")
@Menu(type = "service" , subtype = "online" , admin= true) @Menu(type = "service", subtype = "online", admin = true)
public ModelAndView index(ModelMap map , HttpServletRequest request , String userid , String agentservice , @Valid String channel) { public ModelAndView index(ModelMap map, HttpServletRequest request, String userid, String agentservice, @Valid String channel) {
if(!StringUtils.isBlank(userid)){ if (StringUtils.isNotBlank(userid)) {
map.put("inviteResult", MainUtils.getWebIMInviteResult(onlineUserRes.findByOrgiAndUserid(super.getOrgi(request), userid))) ; map.put("inviteResult", MainUtils.getWebIMInviteResult(onlineUserRes.findByOrgiAndUserid(super.getOrgi(request), userid)));
map.put("tagRelationList", tagRelationRes.findByUserid(userid)) ; map.put("tagRelationList", tagRelationRes.findByUserid(userid));
map.put("onlineUserHistList", onlineUserHisRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ; map.put("onlineUserHistList", onlineUserHisRes.findByUseridAndOrgi(userid, super.getOrgi(request)));
map.put("agentServicesAvg", onlineUserRes.countByUserForAvagTime(super.getOrgi(request), MainContext.AgentUserStatusEnum.END.toString(),userid)) ; map.put("agentServicesAvg", onlineUserRes.countByUserForAvagTime(super.getOrgi(request), MainContext.AgentUserStatusEnum.END.toString(), userid));
List<AgentService> agentServiceList = agentServiceRes.findByUseridAndOrgi(userid, super.getOrgi(request)) ; List<AgentService> agentServiceList = agentServiceRes.findByUseridAndOrgiOrderByLogindateDesc(userid, super.getOrgi(request));
map.put("agentServiceList", agentServiceList) ; map.put("agentServiceList", agentServiceList);
if(agentServiceList.size()>0){ if (agentServiceList.size() > 0) {
map.put("serviceCount", Integer map.put("serviceCount", Integer
.valueOf(this.agentServiceRes .valueOf(this.agentServiceRes
.countByUseridAndOrgiAndStatus(userid, super.getOrgi(request), .countByUseridAndOrgiAndStatus(userid, super.getOrgi(request),
MainContext.AgentUserStatusEnum.END.toString()))); MainContext.AgentUserStatusEnum.END.toString())));
AgentService agentService = agentServiceList.get(0) ; AgentService agentService = agentServiceList.get(0);
if(!StringUtils.isBlank(agentservice)){ if (StringUtils.isNotBlank(agentservice)) {
for(AgentService as : agentServiceList){ for (AgentService as : agentServiceList) {
if(as.getId().equals(agentservice)){ if (as.getId().equals(agentservice)) {
agentService = as ; break ; agentService = as;
} break;
} }
} }
}
if(agentService!=null){
List<AgentServiceSummary> summaries = serviceSummaryRes.findByAgentserviceidAndOrgi(agentService.getId(), super.getOrgi(request)) ; if (agentService != null) {
if(summaries.size() > 0) List<AgentServiceSummary> summaries = serviceSummaryRes.findByAgentserviceidAndOrgi(agentService.getId(), super.getOrgi(request));
map.put("summary" , summaries.get(0)) ; if (summaries.size() > 0)
} map.put("summary", summaries.get(0));
}
List<AgentUserContacts> agentUserContactsList = agentUserContactsRes.findByUseridAndOrgi(userid, super.getOrgi(request)) ;
if(agentUserContactsList.size() > 0){ List<AgentUserContacts> agentUserContactsList = agentUserContactsRes.findByUseridAndOrgi(userid, super.getOrgi(request));
AgentUserContacts agentUserContacts = agentUserContactsList.get(0) ; if (agentUserContactsList.size() > 0) {
map.put("contacts", contactsRes.findOne(agentUserContacts.getContactsid())) ; AgentUserContacts agentUserContacts = agentUserContactsList.get(0);
} map.put("contacts", contactsRes.findOne(agentUserContacts.getContactsid()));
}
map.put("tags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , MainContext.ModelType.USER.toString())) ;
map.put("summaryTags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , MainContext.ModelType.SUMMARY.toString())) ; map.put("tags", tagRes.findByOrgiAndTagtype(super.getOrgi(request), MainContext.ModelType.USER.toString()));
map.put("curAgentService", agentService) ; map.put("summaryTags", tagRes.findByOrgiAndTagtype(super.getOrgi(request), MainContext.ModelType.SUMMARY.toString()));
map.put("curAgentService", agentService);
map.put("agentUserMessageList", chatMessageRepository.findByAgentserviceidAndOrgi(agentService.getId() , super.getOrgi(request), new PageRequest(0, 50, Direction.DESC , "updatetime")));
} map.put("agentUserMessageList", chatMessageRepository.findByAgentserviceidAndOrgi(agentService.getId(), super.getOrgi(request), new PageRequest(0, 50, Direction.DESC, "updatetime")));
}
if(MainContext.ChannelTypeEnum.WEIXIN.toString().equals(channel)){
List<WeiXinUser> weiXinUserList = weiXinUserRes.findByOpenidAndOrgi(userid, super.getOrgi(request)) ; if (MainContext.ChannelTypeEnum.WEIXIN.toString().equals(channel)) {
if(weiXinUserList.size() > 0){ List<WeiXinUser> weiXinUserList = weiXinUserRes.findByOpenidAndOrgi(userid, super.getOrgi(request));
WeiXinUser weiXinUser = weiXinUserList.get(0) ; if (weiXinUserList.size() > 0) {
map.put("weiXinUser",weiXinUser); WeiXinUser weiXinUser = weiXinUserList.get(0);
} map.put("weiXinUser", weiXinUser);
}else if(MainContext.ChannelTypeEnum.WEBIM.toString().equals(channel)){ }
List<OnlineUser> onlineUserList = onlineUserRes.findByUseridAndOrgi(userid, super.getOrgi(request)) ; } else if (MainContext.ChannelTypeEnum.WEBIM.toString().equals(channel)) {
if(onlineUserList.size() >0){ List<OnlineUser> onlineUserList = onlineUserRes.findByUseridAndOrgi(userid, super.getOrgi(request));
map.put("onlineUser", onlineUserList.get(0)) ; if (onlineUserList.size() > 0) {
} map.put("onlineUser", onlineUserList.get(0));
} }
map.put("agentUser", agentUserRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ; }
map.put("curragentuser", agentUserRes.findByUseridAndOrgi(userid, super.getOrgi(request))) ; map.put("agentUser", agentUserRes.findByUseridAndOrgi(userid, super.getOrgi(request)));
} map.put("curragentuser", agentUserRes.findByUseridAndOrgi(userid, super.getOrgi(request)));
}
return request(super.createAppsTempletResponse("/apps/service/online/index")); return request(super.createAppsTempletResponse("/apps/service/online/index"));
} }
@RequestMapping("/online/chatmsg") @RequestMapping("/online/chatmsg")
@Menu(type = "service" , subtype = "chatmsg" , admin= true) @Menu(type = "service", subtype = "chatmsg", admin = true)
public ModelAndView onlinechat(ModelMap map , HttpServletRequest request , String id , String title) { public ModelAndView onlinechat(ModelMap map, HttpServletRequest request, String id, String title) {
AgentService agentService = agentServiceRes.getOne(id) ; AgentService agentService = agentServiceRes.getOne(id);
AgentUser curragentuser = agentUserRes.findByUseridAndOrgi(agentService.getUserid(), super.getOrgi(request)) ; AgentUser curragentuser = agentUserRes.findByUseridAndOrgi(agentService.getUserid(), super.getOrgi(request));
map.put("curAgentService", agentService) ; map.put("curAgentService", agentService);
map.put("curragentuser", curragentuser) ; map.put("curragentuser", curragentuser);
if(!StringUtils.isBlank(title)){ if (StringUtils.isNotBlank(title)) {
map.put("title", title) ; map.put("title", title);
} }
map.put("summaryTags", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , MainContext.ModelType.SUMMARY.toString())) ; map.put("summaryTags", tagRes.findByOrgiAndTagtype(super.getOrgi(request), MainContext.ModelType.SUMMARY.toString()));
if(agentService!=null){ if (agentService != null) {
List<AgentServiceSummary> summaries = serviceSummaryRes.findByAgentserviceidAndOrgi(agentService.getId(), super.getOrgi(request)) ; List<AgentServiceSummary> summaries = serviceSummaryRes.findByAgentserviceidAndOrgi(agentService.getId(), super.getOrgi(request));
if(summaries.size() > 0) if (summaries.size() > 0)
map.put("summary" , summaries.get(0)) ; map.put("summary", summaries.get(0));
} }
map.put("agentUserMessageList", chatMessageRepository.findByAgentserviceidAndOrgi(agentService.getId() , super.getOrgi(request), new PageRequest(0, 50, Direction.DESC , "updatetime"))); map.put("agentUserMessageList", chatMessageRepository.findByAgentserviceidAndOrgi(agentService.getId(), super.getOrgi(request), new PageRequest(0, 50, Direction.DESC, "updatetime")));
return request(super.createRequestPageTempletResponse("/apps/service/online/chatmsg")); return request(super.createRequestPageTempletResponse("/apps/service/online/chatmsg"));
} }
@RequestMapping("/trace") @RequestMapping("/trace")
@Menu(type = "service" , subtype = "trace" , admin= false) @Menu(type = "service", subtype = "trace", admin = false)
public ModelAndView trace(ModelMap map , HttpServletRequest request , @Valid String sessionid) { public ModelAndView trace(ModelMap map, HttpServletRequest request, @Valid String sessionid) {
if(!StringUtils.isBlank(sessionid)){ if (StringUtils.isNotBlank(sessionid)) {
map.addAttribute("traceHisList", userEventRes.findBySessionidAndOrgi(sessionid, super.getOrgi(request), new PageRequest(0, 100))) ; map.addAttribute("traceHisList", userEventRes.findBySessionidAndOrgi(sessionid, super.getOrgi(request), new PageRequest(0, 100)));
} }
return request(super.createRequestPageTempletResponse("/apps/service/online/trace")); return request(super.createRequestPageTempletResponse("/apps/service/online/trace"));
} }
} }

View File

@ -16,26 +16,15 @@
*/ */
package com.chatopera.cc.app.handler.apps.setting; package com.chatopera.cc.app.handler.apps.setting;
import java.io.File; import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.repository.AdTypeRepository; import com.chatopera.cc.app.handler.Handler;
import com.chatopera.cc.app.persistence.repository.SessionConfigRepository; import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.TagRepository; import com.chatopera.cc.app.persistence.blob.JpaBlobHelper;
import com.chatopera.cc.app.persistence.repository.TemplateRepository; import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.app.model.AdType; import com.chatopera.cc.util.Menu;
import com.chatopera.cc.app.model.SysDic;
import com.chatopera.cc.app.model.Tag;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -43,297 +32,289 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.app.persistence.repository.BlackListRepository; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.handler.Handler; import javax.validation.Valid;
import com.chatopera.cc.app.model.BlackEntity; import java.io.IOException;
import com.chatopera.cc.app.model.SessionConfig; import java.util.Date;
import com.chatopera.cc.app.model.UKeFuDic; import java.util.List;
@Controller @Controller
@RequestMapping("/setting") @RequestMapping("/setting")
public class IMAgentController extends Handler{ public class IMAgentController extends Handler {
@Autowired @Autowired
private SessionConfigRepository sessionConfigRes ; private SessionConfigRepository sessionConfigRes;
@Autowired @Autowired
private TagRepository tagRes ; private TagRepository tagRes;
@Autowired @Autowired
private BlackListRepository blackListRes; private BlackListRepository blackListRes;
@Autowired @Autowired
private AdTypeRepository adTypeRes; private AdTypeRepository adTypeRes;
@Autowired @Autowired
private TemplateRepository templateRes ; private TemplateRepository templateRes;
@Value("${web.upload-path}")
@Autowired
private StreamingFileRepository streamingFileRes;
@Autowired
private JpaBlobHelper jpaBlobHelper;
@Value("${web.upload-path}")
private String path; private String path;
@RequestMapping("/agent/index") @RequestMapping("/agent/index")
@Menu(type = "setting" , subtype = "sessionconfig" , admin= false) @Menu(type = "setting", subtype = "sessionconfig", admin = false)
public ModelAndView index(ModelMap map , HttpServletRequest request) { public ModelAndView index(ModelMap map, HttpServletRequest request) {
SessionConfig sessionConfig = sessionConfigRes.findByOrgi(super.getOrgi(request)) ; SessionConfig sessionConfig = sessionConfigRes.findByOrgi(super.getOrgi(request));
if(sessionConfig == null){ if (sessionConfig == null) {
sessionConfig = new SessionConfig() ; sessionConfig = new SessionConfig();
} }
map.put("sessionConfig", sessionConfig) ; map.put("sessionConfig", sessionConfig);
List<SysDic> dicList = UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_DIC) ; List<SysDic> dicList = UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_DIC);
SysDic inputDic = null , outputDic = null ; SysDic inputDic = null, outputDic = null;
for(SysDic dic : dicList){ for (SysDic dic : dicList) {
if(dic.getCode().equals(MainContext.UKEFU_SYSTEM_AI_INPUT)){ if (dic.getCode().equals(MainContext.UKEFU_SYSTEM_AI_INPUT)) {
inputDic = dic ; inputDic = dic;
} }
if(dic.getCode().equals(MainContext.UKEFU_SYSTEM_AI_OUTPUT)){ if (dic.getCode().equals(MainContext.UKEFU_SYSTEM_AI_OUTPUT)) {
outputDic = dic ; outputDic = dic;
} }
} }
if(inputDic!=null){ if (inputDic != null) {
map.addAttribute("innputtemlet", templateRes.findByTemplettypeAndOrgi(inputDic.getId(), super.getOrgi(request))) ; map.addAttribute("innputtemlet", templateRes.findByTemplettypeAndOrgi(inputDic.getId(), super.getOrgi(request)));
} }
if(outputDic!=null){ if (outputDic != null) {
map.addAttribute("outputtemlet", templateRes.findByTemplettypeAndOrgi(outputDic.getId(), super.getOrgi(request))) ; map.addAttribute("outputtemlet", templateRes.findByTemplettypeAndOrgi(outputDic.getId(), super.getOrgi(request)));
} }
return request(super.createAppsTempletResponse("/apps/setting/agent/index")); return request(super.createAppsTempletResponse("/apps/setting/agent/index"));
} }
@RequestMapping("/agent/sessionconfig/save") @RequestMapping("/agent/sessionconfig/save")
@Menu(type = "setting" , subtype = "sessionconfig" , admin= false) @Menu(type = "setting", subtype = "sessionconfig", admin = false)
public ModelAndView sessionconfig(ModelMap map , HttpServletRequest request , @Valid SessionConfig sessionConfig) { public ModelAndView sessionconfig(ModelMap map, HttpServletRequest request, @Valid SessionConfig sessionConfig) {
SessionConfig tempSessionConfig = sessionConfigRes.findByOrgi(super.getOrgi(request)) ; SessionConfig tempSessionConfig = sessionConfigRes.findByOrgi(super.getOrgi(request));
if(tempSessionConfig == null){ if (tempSessionConfig == null) {
tempSessionConfig = sessionConfig; tempSessionConfig = sessionConfig;
tempSessionConfig.setCreater(super.getUser(request).getId()); tempSessionConfig.setCreater(super.getUser(request).getId());
}else{ } else {
MainUtils.copyProperties(sessionConfig, tempSessionConfig); MainUtils.copyProperties(sessionConfig, tempSessionConfig);
} }
tempSessionConfig.setOrgi(super.getOrgi(request)); tempSessionConfig.setOrgi(super.getOrgi(request));
sessionConfigRes.save(tempSessionConfig) ; sessionConfigRes.save(tempSessionConfig);
CacheHelper.getSystemCacheBean().put(MainContext.SYSTEM_CACHE_SESSION_CONFIG+"_"+super.getOrgi(request),tempSessionConfig, super.getOrgi(request)) ; CacheHelper.getSystemCacheBean().put(MainContext.SYSTEM_CACHE_SESSION_CONFIG + "_" + super.getOrgi(request), tempSessionConfig, super.getOrgi(request));
CacheHelper.getSystemCacheBean().delete(MainContext.SYSTEM_CACHE_SESSION_CONFIG_LIST , MainContext.SYSTEM_ORGI) ; CacheHelper.getSystemCacheBean().delete(MainContext.SYSTEM_CACHE_SESSION_CONFIG_LIST, MainContext.SYSTEM_ORGI);
AutomaticServiceDist.initSessionConfigList() ; AutomaticServiceDist.initSessionConfigList();
map.put("sessionConfig", tempSessionConfig) ; map.put("sessionConfig", tempSessionConfig);
return request(super.createRequestPageTempletResponse("redirect:/setting/agent/index.html")); return request(super.createRequestPageTempletResponse("redirect:/setting/agent/index.html"));
} }
@RequestMapping("/blacklist") @RequestMapping("/blacklist")
@Menu(type = "setting" , subtype = "blacklist" , admin= false) @Menu(type = "setting", subtype = "blacklist", admin = false)
public ModelAndView blacklist(ModelMap map , HttpServletRequest request) { public ModelAndView blacklist(ModelMap map, HttpServletRequest request) {
map.put("blackList", blackListRes.findByOrgi(super.getOrgi(request), new PageRequest(super.getP(request), super.getPs(request), Sort.Direction.DESC, "endtime"))) ; map.put("blackList", blackListRes.findByOrgi(super.getOrgi(request), new PageRequest(super.getP(request), super.getPs(request), Sort.Direction.DESC, "endtime")));
map.put("tagTypeList", UKeFuDic.getInstance().getDic("com.dic.tag.type")) ; map.put("tagTypeList", UKeFuDic.getInstance().getDic("com.dic.tag.type"));
return request(super.createAppsTempletResponse("/apps/setting/agent/blacklist")); return request(super.createAppsTempletResponse("/apps/setting/agent/blacklist"));
} }
@RequestMapping("/blacklist/delete") @RequestMapping("/blacklist/delete")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView blacklistdelete(ModelMap map , HttpServletRequest request , @Valid String id) { public ModelAndView blacklistdelete(ModelMap map, HttpServletRequest request, @Valid String id) {
if(!StringUtils.isBlank(id)){ if (!StringUtils.isBlank(id)) {
BlackEntity tempBlackEntity = blackListRes.findByIdAndOrgi(id, super.getOrgi(request)) ; BlackEntity tempBlackEntity = blackListRes.findByIdAndOrgi(id, super.getOrgi(request));
if(tempBlackEntity!=null){ if (tempBlackEntity != null) {
blackListRes.delete(tempBlackEntity); blackListRes.delete(tempBlackEntity);
CacheHelper.getSystemCacheBean().delete(tempBlackEntity.getUserid(), MainContext.SYSTEM_ORGI) ; CacheHelper.getSystemCacheBean().delete(tempBlackEntity.getUserid(), MainContext.SYSTEM_ORGI);
} }
} }
return request(super.createRequestPageTempletResponse("redirect:/setting/blacklist.html")); return request(super.createRequestPageTempletResponse("redirect:/setting/blacklist.html"));
} }
@RequestMapping("/tag") @RequestMapping("/tag")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView tag(ModelMap map , HttpServletRequest request , @Valid String code) { public ModelAndView tag(ModelMap map, HttpServletRequest request, @Valid String code) {
SysDic tagType = null ; SysDic tagType = null;
List<SysDic> tagList = UKeFuDic.getInstance().getDic("com.dic.tag.type") ; List<SysDic> tagList = UKeFuDic.getInstance().getDic("com.dic.tag.type");
if(tagList.size() > 0){ if (tagList.size() > 0) {
if(!StringUtils.isBlank(code)){ if (!StringUtils.isBlank(code)) {
for(SysDic dic : tagList){ for (SysDic dic : tagList) {
if(code.equals(dic.getCode())){ if (code.equals(dic.getCode())) {
tagType = dic ; tagType = dic;
} }
} }
}else{ } else {
tagType = tagList.get(0) ; tagType = tagList.get(0);
} }
map.put("tagType", tagType) ; map.put("tagType", tagType);
} }
if(tagType!=null){ if (tagType != null) {
map.put("tagList", tagRes.findByOrgiAndTagtype(super.getOrgi(request) , tagType.getCode() , new PageRequest(super.getP(request), super.getPs(request)))) ; map.put("tagList", tagRes.findByOrgiAndTagtype(super.getOrgi(request), tagType.getCode(), new PageRequest(super.getP(request), super.getPs(request))));
} }
map.put("tagTypeList", tagList) ; map.put("tagTypeList", tagList);
return request(super.createAppsTempletResponse("/apps/setting/agent/tag")); return request(super.createAppsTempletResponse("/apps/setting/agent/tag"));
} }
@RequestMapping("/tag/add") @RequestMapping("/tag/add")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView tagadd(ModelMap map , HttpServletRequest request , @Valid String tagtype) { public ModelAndView tagadd(ModelMap map, HttpServletRequest request, @Valid String tagtype) {
map.addAttribute("tagtype", tagtype) ; map.addAttribute("tagtype", tagtype);
return request(super.createRequestPageTempletResponse("/apps/setting/agent/tagadd")); return request(super.createRequestPageTempletResponse("/apps/setting/agent/tagadd"));
} }
@RequestMapping("/tag/edit") @RequestMapping("/tag/edit")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView tagedit(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String tagtype) { public ModelAndView tagedit(ModelMap map, HttpServletRequest request, @Valid String id, @Valid String tagtype) {
map.put("tag", tagRes.findOne(id)) ; map.put("tag", tagRes.findOne(id));
map.addAttribute("tagtype", tagtype) ; map.addAttribute("tagtype", tagtype);
return request(super.createRequestPageTempletResponse("/apps/setting/agent/tagedit")); return request(super.createRequestPageTempletResponse("/apps/setting/agent/tagedit"));
} }
@RequestMapping("/tag/update") @RequestMapping("/tag/update")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView tagupdate(ModelMap map , HttpServletRequest request , @Valid Tag tag , @Valid String tagtype) { public ModelAndView tagupdate(ModelMap map, HttpServletRequest request, @Valid Tag tag, @Valid String tagtype) {
Tag temptag = tagRes.findByOrgiAndTag(super.getOrgi(request), tag.getTag()) ; Tag temptag = tagRes.findByOrgiAndTag(super.getOrgi(request), tag.getTag());
if(temptag == null || tag.getId().equals(temptag.getId())){ if (temptag == null || tag.getId().equals(temptag.getId())) {
tag.setOrgi(super.getOrgi(request)); tag.setOrgi(super.getOrgi(request));
tag.setCreater(super.getUser(request).getId()); tag.setCreater(super.getUser(request).getId());
tagRes.save(tag) ; tagRes.save(tag);
} }
return request(super.createRequestPageTempletResponse("redirect:/setting/tag.html?code="+tagtype)); return request(super.createRequestPageTempletResponse("redirect:/setting/tag.html?code=" + tagtype));
} }
@RequestMapping("/tag/save") @RequestMapping("/tag/save")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView tagsave(ModelMap map , HttpServletRequest request , @Valid Tag tag , @Valid String tagtype) { public ModelAndView tagsave(ModelMap map, HttpServletRequest request, @Valid Tag tag, @Valid String tagtype) {
if(tagRes.findByOrgiAndTag(super.getOrgi(request), tag.getTag()) == null){ if (tagRes.findByOrgiAndTag(super.getOrgi(request), tag.getTag()) == null) {
tag.setOrgi(super.getOrgi(request)); tag.setOrgi(super.getOrgi(request));
tag.setCreater(super.getUser(request).getId()); tag.setCreater(super.getUser(request).getId());
tagRes.save(tag) ; tagRes.save(tag);
} }
return request(super.createRequestPageTempletResponse("redirect:/setting/tag.html?code="+tagtype)); return request(super.createRequestPageTempletResponse("redirect:/setting/tag.html?code=" + tagtype));
} }
@RequestMapping("/tag/delete") @RequestMapping("/tag/delete")
@Menu(type = "setting" , subtype = "tag" , admin= false) @Menu(type = "setting", subtype = "tag", admin = false)
public ModelAndView tagdelete(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String tagtype) { public ModelAndView tagdelete(ModelMap map, HttpServletRequest request, @Valid String id, @Valid String tagtype) {
tagRes.delete(id); tagRes.delete(id);
return request(super.createRequestPageTempletResponse("redirect:/setting/tag.html?code="+tagtype)); return request(super.createRequestPageTempletResponse("redirect:/setting/tag.html?code=" + tagtype));
} }
@RequestMapping("/acd") @RequestMapping("/acd")
@Menu(type = "setting" , subtype = "acd" , admin= false) @Menu(type = "setting", subtype = "acd", admin = false)
public ModelAndView acd(ModelMap map , HttpServletRequest request) { public ModelAndView acd(ModelMap map, HttpServletRequest request) {
map.put("tagTypeList", UKeFuDic.getInstance().getDic("com.dic.tag.type")) ; map.put("tagTypeList", UKeFuDic.getInstance().getDic("com.dic.tag.type"));
return request(super.createAppsTempletResponse("/apps/setting/agent/acd")); return request(super.createAppsTempletResponse("/apps/setting/agent/acd"));
} }
@RequestMapping("/adv") @RequestMapping("/adv")
@Menu(type = "setting" , subtype = "adv" , admin= false) @Menu(type = "setting", subtype = "adv", admin = false)
public ModelAndView adv(ModelMap map , HttpServletRequest request , @Valid String adpos) { public ModelAndView adv(ModelMap map, HttpServletRequest request, @Valid String adpos) {
SysDic advType = null ; SysDic advType = null;
List<SysDic> tagList = UKeFuDic.getInstance().getDic("com.dic.adv.type") ; List<SysDic> tagList = UKeFuDic.getInstance().getDic("com.dic.adv.type");
if(tagList.size() > 0){ if (tagList.size() > 0) {
if(!StringUtils.isBlank(adpos)){ if (!StringUtils.isBlank(adpos)) {
for(SysDic dic : tagList){ for (SysDic dic : tagList) {
if(adpos.equals(dic.getId())){ if (adpos.equals(dic.getId())) {
advType = dic ; advType = dic;
} }
} }
}else{ } else {
advType = tagList.get(0) ; advType = tagList.get(0);
} }
map.put("advType", advType) ; map.put("advType", advType);
} }
if(advType!=null){ if (advType != null) {
map.put("adTypeList", adTypeRes.findByAdposAndOrgi(advType.getId() , super.getOrgi(request))) ; map.put("adTypeList", adTypeRes.findByAdposAndOrgi(advType.getId(), super.getOrgi(request)));
} }
map.put("tagTypeList", UKeFuDic.getInstance().getDic("com.dic.tag.type")) ; map.put("tagTypeList", UKeFuDic.getInstance().getDic("com.dic.tag.type"));
map.put("advTypeList", UKeFuDic.getInstance().getDic("com.dic.adv.type")) ; map.put("advTypeList", UKeFuDic.getInstance().getDic("com.dic.adv.type"));
return request(super.createAppsTempletResponse("/apps/setting/agent/adv")); return request(super.createAppsTempletResponse("/apps/setting/agent/adv"));
} }
@RequestMapping("/adv/add") @RequestMapping("/adv/add")
@Menu(type = "setting" , subtype = "adv" , admin= false) @Menu(type = "setting", subtype = "adv", admin = false)
public ModelAndView advadd(ModelMap map , HttpServletRequest request , @Valid String adpos) { public ModelAndView advadd(ModelMap map, HttpServletRequest request, @Valid String adpos) {
map.addAttribute("adpos", adpos) ; map.addAttribute("adpos", adpos);
return request(super.createRequestPageTempletResponse("/apps/setting/agent/adadd")); return request(super.createRequestPageTempletResponse("/apps/setting/agent/adadd"));
} }
@RequestMapping("/adv/save") @RequestMapping("/adv/save")
@Menu(type = "setting" , subtype = "adv" , admin= false) @Menu(type = "setting", subtype = "adv", admin = false)
public ModelAndView advsave(ModelMap map , HttpServletRequest request , @Valid AdType adv , @Valid String advtype , @RequestParam(value = "imgfile", required = false) MultipartFile imgfile) throws IOException { public ModelAndView advsave(ModelMap map, HttpServletRequest request, @Valid AdType adv, @Valid String advtype, @RequestParam(value = "imgfile", required = false) MultipartFile imgfile) throws IOException {
adv.setOrgi(super.getOrgi(request)); adv.setOrgi(super.getOrgi(request));
adv.setCreater(super.getUser(request).getId()); adv.setCreater(super.getUser(request).getId());
if(!StringUtils.isBlank(adv.getContent())){ if (StringUtils.isNotBlank(adv.getContent())) {
adv.setContent(adv.getContent().replaceAll("\"", "'")); adv.setContent(adv.getContent().replaceAll("\"", "'"));
} }
adv.setCreatetime(new Date()); adv.setCreatetime(new Date());
if(imgfile!=null && imgfile.getSize() > 0){ if (imgfile != null && imgfile.getSize() > 0) {
File adDir = new File(path , "adv"); adv.setImgurl("/res/image.html?id=" + super.saveImageFileWithMultipart(imgfile));
if(!adDir.exists()){ }
adDir.mkdirs() ; adTypeRes.save(adv);
}
String fileName = "adv/"+ MainUtils.getUUID()+imgfile.getOriginalFilename().substring(imgfile.getOriginalFilename().lastIndexOf(".")) ; MainUtils.initAdv(super.getOrgi(request));
FileCopyUtils.copy(imgfile.getBytes(), new File(path , fileName));
adv.setImgurl("/res/image.html?id="+java.net.URLEncoder.encode(fileName , "UTF-8")); return request(super.createRequestPageTempletResponse("redirect:/setting/adv.html?adpos=" + adv.getAdpos()));
}
adTypeRes.save(adv) ;
MainUtils.initAdv(super.getOrgi(request));
return request(super.createRequestPageTempletResponse("redirect:/setting/adv.html?adpos="+adv.getAdpos()));
} }
@RequestMapping("/adv/edit") @RequestMapping("/adv/edit")
@Menu(type = "setting" , subtype = "adv" , admin= false) @Menu(type = "setting", subtype = "adv", admin = false)
public ModelAndView advedit(ModelMap map , HttpServletRequest request , @Valid String adpos, @Valid String id) { public ModelAndView advedit(ModelMap map, HttpServletRequest request, @Valid String adpos, @Valid String id) {
map.addAttribute("adpos", adpos) ; map.addAttribute("adpos", adpos);
map.put("ad", adTypeRes.findByIdAndOrgi(id , super.getOrgi(request))) ; map.put("ad", adTypeRes.findByIdAndOrgi(id, super.getOrgi(request)));
return request(super.createRequestPageTempletResponse("/apps/setting/agent/adedit")); return request(super.createRequestPageTempletResponse("/apps/setting/agent/adedit"));
} }
@RequestMapping("/adv/update") @RequestMapping("/adv/update")
@Menu(type = "setting" , subtype = "adv" , admin= false) @Menu(type = "setting", subtype = "adv", admin = false)
public ModelAndView advupdate(ModelMap map , HttpServletRequest request , @Valid AdType ad, @Valid String adpos, @RequestParam(value = "imgfile", required = false) MultipartFile imgfile) throws IOException { public ModelAndView advupdate(ModelMap map, HttpServletRequest request, @Valid AdType ad, @Valid String adpos, @RequestParam(value = "imgfile", required = false) MultipartFile imgfile) throws IOException {
AdType tempad = adTypeRes.findByIdAndOrgi(ad.getId(),super.getOrgi(request)) ; AdType tempad = adTypeRes.findByIdAndOrgi(ad.getId(), super.getOrgi(request));
if(tempad != null){ if (tempad != null) {
ad.setOrgi(super.getOrgi(request)); ad.setOrgi(super.getOrgi(request));
ad.setCreater(tempad.getCreater()); ad.setCreater(tempad.getCreater());
ad.setCreatetime(tempad.getCreatetime()); ad.setCreatetime(tempad.getCreatetime());
if(!StringUtils.isBlank(ad.getContent())){ if (StringUtils.isNotBlank(ad.getContent())) {
ad.setContent(ad.getContent().replaceAll("\"", "'")); ad.setContent(ad.getContent().replaceAll("\"", "'"));
} }
if(imgfile!=null && imgfile.getSize() > 0){ if (imgfile != null && imgfile.getSize() > 0) {
File adDir = new File(path , "adv"); ad.setImgurl("/res/image.html?id=" + super.saveImageFileWithMultipart(imgfile));
if(!adDir.exists()){ } else {
adDir.mkdirs() ; ad.setImgurl(tempad.getImgurl());
} }
String fileName = "adv/"+ MainUtils.getUUID()+imgfile.getOriginalFilename().substring(imgfile.getOriginalFilename().lastIndexOf(".")) ; adTypeRes.save(ad);
FileCopyUtils.copy(imgfile.getBytes(), new File(path , fileName)); MainUtils.initAdv(super.getOrgi(request));
ad.setImgurl("/res/image.html?id="+java.net.URLEncoder.encode(fileName , "UTF-8")); }
}else{ return request(super.createRequestPageTempletResponse("redirect:/setting/adv.html?adpos=" + adpos));
ad.setImgurl(tempad.getImgurl());
}
adTypeRes.save(ad) ;
MainUtils.initAdv(super.getOrgi(request));
}
return request(super.createRequestPageTempletResponse("redirect:/setting/adv.html?adpos="+adpos));
} }
@RequestMapping("/adv/delete") @RequestMapping("/adv/delete")
@Menu(type = "setting" , subtype = "adv" , admin= false) @Menu(type = "setting", subtype = "adv", admin = false)
public ModelAndView advdelete(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String adpos) { public ModelAndView advdelete(ModelMap map, HttpServletRequest request, @Valid String id, @Valid String adpos) {
adTypeRes.delete(id); adTypeRes.delete(id);
MainUtils.initAdv(super.getOrgi(request)); MainUtils.initAdv(super.getOrgi(request));
return request(super.createRequestPageTempletResponse("redirect:/setting/adv.html?adpos="+adpos)); return request(super.createRequestPageTempletResponse("redirect:/setting/adv.html?adpos=" + adpos));
} }
} }

View File

@ -38,7 +38,7 @@ public class TestController extends Handler {
for(int i=0 ; i<500; i++){ for(int i=0 ; i<500; i++){
String user = MainUtils.getUUID(); String user = MainUtils.getUUID();
try { try {
OnlineUserUtils.newRequestMessage(user, "ukewo", "user", "system", "localhost" , "win10", "test" , MainContext.ChannelTypeEnum.WEBIM.toString() , null , null , "admin" , "标题" , "http://www.ukewo.cn" , "12434" , MainContext.ChatInitiatorType.USER.toString()) ; OnlineUserUtils.newRequestMessage(user, "ukewo", "user", "system", "localhost" , "win10", "test" , MainContext.ChannelTypeEnum.WEBIM.toString() , null , null , "admin" , "标题" , "https://www.chatopera.com" , "12434" , MainContext.ChatInitiatorType.USER.toString()) ;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -16,162 +16,171 @@
*/ */
package com.chatopera.cc.app.handler.resource; package com.chatopera.cc.app.handler.resource;
import java.io.File; import com.chatopera.cc.app.basic.MainUtils;
import java.io.IOException; import com.chatopera.cc.app.handler.Handler;
import java.io.InputStream; import com.chatopera.cc.app.model.AttachmentFile;
import java.io.OutputStream; import com.chatopera.cc.app.model.StreamingFile;
import java.net.URL; import com.chatopera.cc.app.model.UploadStatus;
import com.chatopera.cc.app.persistence.blob.JpaBlobHelper;
import javax.servlet.http.HttpServletRequest; import com.chatopera.cc.app.persistence.repository.AttachmentRepository;
import javax.servlet.http.HttpServletResponse; import com.chatopera.cc.app.persistence.repository.StreamingFileRepository;
import javax.validation.Valid; import com.chatopera.cc.util.Menu;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import com.chatopera.cc.util.Menu; import javax.servlet.http.HttpServletRequest;
import com.chatopera.cc.app.basic.MainUtils; import javax.servlet.http.HttpServletResponse;
import com.chatopera.cc.app.persistence.repository.AttachmentRepository; import javax.validation.Valid;
import com.chatopera.cc.app.handler.Handler; import java.io.File;
import com.chatopera.cc.app.model.AttachmentFile; import java.io.IOException;
import com.chatopera.cc.app.model.UploadStatus; import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.sql.SQLException;
@Controller @Controller
@RequestMapping("/res") @RequestMapping("/res")
public class MediaController extends Handler{ public class MediaController extends Handler {
private final static Logger logger = LoggerFactory.getLogger(MediaController.class);
@Value("${web.upload-path}")
@Value("${web.upload-path}")
private String path; private String path;
private String TEMPLATE_DATA_PATH = "WEB-INF/data/templates/"; @Autowired
private StreamingFileRepository streamingFileRes;
@Autowired
private AttachmentRepository attachementRes; @Autowired
private JpaBlobHelper jpaBlobHelper;
private String TEMPLATE_DATA_PATH = "WEB-INF/data/templates/";
@Autowired
private AttachmentRepository attachementRes;
@RequestMapping("/image") @RequestMapping("/image")
@Menu(type = "resouce" , subtype = "image" , access = true) @Menu(type = "resouce", subtype = "image", access = true)
public void index(HttpServletResponse response, @Valid String id) throws IOException { public void index(HttpServletResponse response,
File file = new File(path ,id) ; @Valid String id,
if(!StringUtils.isBlank(id) && !(id.endsWith(".png") || id.endsWith(".jpg"))){ @RequestParam(value = "original", required = false) boolean original,
if(id.endsWith("_original") && !file.exists()){ @RequestParam(value = "cooperation", required = false) boolean cooperation) throws IOException, SQLException {
File orgFile = new File(path , id.substring(0 , id.indexOf("_original"))) ; StreamingFile sf = streamingFileRes.findOne(id);
if(orgFile.exists()){ if (sf != null) {
MainUtils.processImage(file = new File(path , id), orgFile) ; response.setHeader("Content-Type", sf.getMime());
} response.setContentType(sf.getMime());
}else if(!StringUtils.isBlank(id) && file.exists() && !id.endsWith("_original")){ if (cooperation && (sf.getCooperation() != null)) { // 协作文件
File originalFile = new File( path , id+"_original") ; IOUtils.copy(sf.getCooperation().getBinaryStream(), response.getOutputStream());
if(!originalFile.exists()){ } else if (original && sf.getData() != null) { // 源文件
MainUtils.processImage(new File( path , id+"_original"), file) ; IOUtils.copy(sf.getData().getBinaryStream(), response.getOutputStream());
} } else if (sf.getThumbnail() != null) { // 缩略图
}else if(!StringUtils.isBlank(id) && !file.exists() && !id.endsWith("_original")){ IOUtils.copy(sf.getThumbnail().getBinaryStream(), response.getOutputStream());
File destFile = new File(path , id+"_original") ; } else if (sf.getData() != null) {
if(destFile.exists()){ IOUtils.copy(sf.getData().getBinaryStream(), response.getOutputStream());
MainUtils.processImage(new File(path + id), destFile) ; } else {
} logger.warn("[index] can not get streaming file id {}, original {}, cooperation {}", id, original, cooperation);
file = new File(path , id) ; }
} }
}
if(file.exists() && file.isFile()){
response.setHeader("Content-Type","image/png");
response.setContentType("image/png");
response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path ,id)));
}
} }
@RequestMapping("/voice") @RequestMapping("/voice")
@Menu(type = "resouce" , subtype = "voice" , access = true) @Menu(type = "resouce", subtype = "voice", access = true)
public void voice(HttpServletResponse response, @Valid String id) throws IOException { public void voice(HttpServletResponse response, @Valid String id) throws IOException {
File file = new File(path ,id) ; File file = new File(path, id);
if(file.exists() && file.isFile()){ if (file.exists() && file.isFile()) {
response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path ,id))); response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path, id)));
} }
} }
@RequestMapping("/url") @RequestMapping("/url")
@Menu(type = "resouce" , subtype = "image" , access = true) @Menu(type = "resouce", subtype = "image", access = true)
public void url(HttpServletResponse response, @Valid String url) throws IOException { public void url(HttpServletResponse response, @Valid String url) throws IOException {
byte[] data = new byte[1024] ; byte[] data = new byte[1024];
int length = 0 ; int length = 0;
OutputStream out = response.getOutputStream(); OutputStream out = response.getOutputStream();
if(!StringUtils.isBlank(url)){ if (StringUtils.isNotBlank(url)) {
InputStream input = new URL(url).openStream() ; InputStream input = new URL(url).openStream();
while((length = input.read(data) )> 0){ while ((length = input.read(data)) > 0) {
out.write(data, 0, length); out.write(data, 0, length);
} }
input.close(); input.close();
} }
} }
@RequestMapping("/image/upload") @RequestMapping("/image/upload")
@Menu(type = "resouce" , subtype = "imageupload" , access = false) @Menu(type = "resouce", subtype = "imageupload", access = false)
public ModelAndView upload(ModelMap map,HttpServletRequest request , @RequestParam(value = "imgFile", required = false) MultipartFile imgFile) throws IOException { public ModelAndView upload(ModelMap map,
ModelAndView view = request(super.createRequestPageTempletResponse("/public/upload")) ; HttpServletRequest request,
UploadStatus upload = null ; @RequestParam(value = "imgFile", required = false) MultipartFile multipart) throws IOException {
String fileName = null ; ModelAndView view = request(super.createRequestPageTempletResponse("/public/upload"));
if(imgFile!=null && imgFile.getOriginalFilename().lastIndexOf(".") > 0){ UploadStatus notify = null;
File uploadDir = new File(path , "upload"); if (multipart != null && multipart.getOriginalFilename().lastIndexOf(".") > 0) {
if(!uploadDir.exists()){ File uploadDir = new File(path, "upload");
uploadDir.mkdirs() ; if (!uploadDir.exists()) {
} uploadDir.mkdirs();
fileName = "upload/"+ MainUtils.md5(imgFile.getBytes())+imgFile.getOriginalFilename().substring(imgFile.getOriginalFilename().lastIndexOf(".")).toLowerCase() ; }
FileCopyUtils.copy(imgFile.getBytes(), new File(path , fileName)); String fileid = MainUtils.getUUID();
StreamingFile sf = new StreamingFile();
String fileURL = request.getScheme()+"://"+request.getServerName()+"/res/image.html?id="+fileName ; sf.setId(fileid);
if(request.getServerPort() == 80){ sf.setName(multipart.getOriginalFilename());
fileURL = request.getScheme()+"://"+request.getServerName()+"/res/image.html?id="+fileName; sf.setMime(multipart.getContentType());
}else{ sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize()));
fileURL = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/res/image.html?id="+fileName; streamingFileRes.save(sf);
} String fileURL = "/res/image.html?id=" + fileid;
upload = new UploadStatus("0" , fileURL); //图片直接发送给 客户不用返回 notify = new UploadStatus("0", fileURL); //图片直接发送给 客户不用返回
}else{ } else {
upload = new UploadStatus("请选择图片文件"); notify = new UploadStatus("请选择图片文件");
} }
map.addAttribute("upload", upload) ; map.addAttribute("upload", notify);
return view ; return view;
} }
@RequestMapping("/file") @RequestMapping("/file")
@Menu(type = "resouce" , subtype = "file" , access = false) @Menu(type = "resouce", subtype = "file", access = false)
public void file(HttpServletResponse response,HttpServletRequest request, @Valid String id) throws IOException { public void file(HttpServletResponse response, HttpServletRequest request, @Valid String id) throws IOException, SQLException {
if(!StringUtils.isBlank(id)){ if (StringUtils.isNotBlank(id)) {
AttachmentFile attachmentFile = attachementRes.findByIdAndOrgi(id, super.getOrgi(request)) ; AttachmentFile attachmentFile = attachementRes.findByIdAndOrgi(id, super.getOrgi(request));
if(attachmentFile!=null){ if (attachmentFile != null && attachmentFile.getFileid() != null) {
response.setContentType(attachmentFile.getFiletype()); StreamingFile sf = streamingFileRes.findOne(attachmentFile.getFileid());
response.setHeader("Content-Disposition", "attachment;filename="+java.net.URLEncoder.encode(attachmentFile.getTitle(), "UTF-8")); if (sf != null) {
if(!StringUtils.isBlank(attachmentFile.getModel()) && attachmentFile.getModel().equals("app")){ response.setContentType(attachmentFile.getFiletype());
response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path , "app/app/"+attachmentFile.getFileid()))); response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(attachmentFile.getTitle(), "UTF-8"));
}else{ IOUtils.copy(sf.getData().getBinaryStream(), response.getOutputStream());
response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path , "app/workorders/"+attachmentFile.getFileid()))); } else {
} logger.warn("[streaming file] can not get file id {}", attachmentFile.getFileid());
} }
} } else {
logger.warn("[attachment file] can not find attachment file id {}", id);
}
}
} }
@RequestMapping("/template") @RequestMapping("/template")
@Menu(type = "resouce" , subtype = "template" , access = false) @Menu(type = "resouce", subtype = "template", access = false)
public void template(HttpServletResponse response,HttpServletRequest request, @Valid String filename) throws IOException { public void template(HttpServletResponse response, HttpServletRequest request, @Valid String filename) throws IOException {
if(!StringUtils.isBlank(filename)){ if (StringUtils.isNotBlank(filename)) {
InputStream is = MediaController.class.getClassLoader().getResourceAsStream(TEMPLATE_DATA_PATH+filename); InputStream is = MediaController.class.getClassLoader().getResourceAsStream(TEMPLATE_DATA_PATH + filename);
if(is!=null) { if (is != null) {
response.setContentType("text/plain"); response.setContentType("text/plain");
response.setHeader("Content-Disposition", "attachment;filename="+java.net.URLEncoder.encode(filename, "UTF-8")); response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(filename, "UTF-8"));
int length ; int length;
byte[] data = new byte[1024] ; byte[] data = new byte[1024];
while((length = is.read(data)) > 0) { while ((length = is.read(data)) > 0) {
response.getOutputStream().write(data , 0 , length); response.getOutputStream().write(data, 0, length);
} }
is.close(); is.close();
} }
} }
return ; return;
} }
} }

View File

@ -16,110 +16,190 @@
*/ */
package com.chatopera.cc.app.im.client; package com.chatopera.cc.app.im.client;
import java.util.List; import com.chatopera.cc.app.basic.MainContext;
import com.corundumstudio.socketio.SocketIOClient;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.im.util.IMServiceUtils;
import com.chatopera.cc.app.schedule.WebIMAgentDispatcher;
import com.chatopera.cc.app.schedule.WebIMOnlineUserDispatcher;
import com.corundumstudio.socketio.SocketIOClient;
import com.google.gson.JsonObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
public class NettyClients { public class NettyClients {
private final Logger logger = LoggerFactory.getLogger(NettyClient.class); private final Logger logger = LoggerFactory.getLogger(NettyClient.class);
private static NettyClients clients = new NettyClients(); private static NettyClients clients = new NettyClients();
private NettyIMClient imClients = new NettyIMClient();
private NettyAgentClient agentClients = new NettyAgentClient();
private NettyIMClient entIMClients = new NettyIMClient();
private NettyCallCenterClient callCenterClients = new NettyCallCenterClient();
private NettyCalloutClient calloutClients = new NettyCalloutClient();
private NettyChatbotClient chatbotClients = new NettyChatbotClient();
public int size(){
return imClients.size();
}
public static NettyClients getInstance(){
return clients ;
}
public NettyCallCenterClient getCallCenterClients(){
return this.callCenterClients ;
}
public void setImClients(NettyIMClient imClients) { private NettyIMClient imClients = new NettyIMClient();
this.imClients = imClients; private NettyAgentClient agentClients = new NettyAgentClient();
} private NettyIMClient entIMClients = new NettyIMClient();
public void putIMEventClient(String id , SocketIOClient userClient){ private NettyCallCenterClient callCenterClients = new NettyCallCenterClient();
imClients.putClient(id, userClient); private NettyCalloutClient calloutClients = new NettyCalloutClient();
} private NettyChatbotClient chatbotClients = new NettyChatbotClient();
public void closeIMEventClient(String id , String sessionid, String orgi){ public int size() {
List<SocketIOClient> userClients = imClients.getClients(id) ; return imClients.size();
for(SocketIOClient userClient : userClients){ }
if(MainUtils.getContextID(userClient.getSessionId().toString()).equals(sessionid)){
userClient.disconnect(); public static NettyClients getInstance() {
} return clients;
} }
}
public void removeIMEventClient(String id , String sessionid){ public NettyCallCenterClient getCallCenterClients() {
imClients.removeClient(id, sessionid); return this.callCenterClients;
} }
public void sendIMEventMessage(String id , String event , Object data){
List<SocketIOClient> userClients = imClients.getClients(id) ; /**
for(SocketIOClient userClient : userClients){ * 访客连接
userClient.sendEvent(event, data); */
} public void setImClients(NettyIMClient imClients) {
} this.imClients = imClients;
}
public void setAgentClients(NettyAgentClient agentClients) {
this.agentClients = agentClients; public void putIMEventClient(String id, SocketIOClient userClient) {
} imClients.putClient(id, userClient);
public void putAgentEventClient(String id , SocketIOClient agentClient){ }
agentClients.putClient(id, agentClient);
} public void closeIMEventClient(String id, String sessionid, String orgi) {
public void removeAgentEventClient(String id , String sessionid){ List<SocketIOClient> userClients = imClients.getClients(id);
agentClients.removeClient(id, sessionid); for (SocketIOClient userClient : userClients) {
} if (MainUtils.getContextID(userClient.getSessionId().toString()).equals(sessionid)) {
public void sendAgentEventMessage(String id , String event , Object data){ userClient.disconnect();
List<SocketIOClient> agents = agentClients.getClients(id) ; }
for(SocketIOClient agentClient : agents){ }
agentClient.sendEvent(event, data); }
}
} public void removeIMEventClient(String id, String sessionid) {
imClients.removeClient(id, sessionid);
public void setEntImClients(NettyIMClient entIMClients) { }
this.entIMClients = entIMClients;
} public void publishIMEventMessage(final String id, final String event, Serializable data) {
public void putEntIMEventClient(String id , SocketIOClient userClient){ // 检测client是否在这台机器上
entIMClients.putClient(id, userClient); if (!sendIMEventMessage(id, event, data)) {
} try {
public void removeEntIMEventClient(String id , String sessionid){ JsonObject payload = new JsonObject();
entIMClients.removeClient(id, sessionid); payload.addProperty("event", event);
} payload.addProperty("id", id);
public void sendEntIMEventMessage(String id , String event , Object data){ payload.addProperty("data", IMServiceUtils.serialize(data));
List<SocketIOClient> entims = entIMClients.getClients(id) ; MainContext.getContext().getBean(WebIMOnlineUserDispatcher.class).publish(payload);
for(SocketIOClient userClient : entims){ } catch (IOException e) {
userClient.sendEvent(event, data); logger.error("publishIMEventMessage", e);
} }
} }
public int getEntIMClientsNum(String user){ }
return entIMClients.getClients(user)!=null ? entIMClients.getClients(user).size() : 0;
} public boolean sendIMEventMessage(final String id, final String event, Object data) {
List<SocketIOClient> userClients = imClients.getClients(id);
public void sendCallCenterMessage(String id , String event , Object data){ for (SocketIOClient userClient : userClients) {
List<SocketIOClient> ccClients = callCenterClients.getClients(id) ; userClient.sendEvent(event, data);
for(SocketIOClient ccClient : ccClients){ }
ccClient.sendEvent(event, data); return userClients.size() > 0;
} }
}
/**
* 坐席连接
*/
public void setAgentClients(NettyAgentClient agentClients) {
this.agentClients = agentClients;
}
public void putAgentEventClient(String id, SocketIOClient agentClient) {
agentClients.putClient(id, agentClient);
}
public void removeAgentEventClient(String id, String sessionid) {
agentClients.removeClient(id, sessionid);
}
// publish to Redis
public void publishAgentEventMessage(String id, String event, Serializable data) {
// 检测client是否在这台机器上
if (!sendAgentEventMessage(id, event, data)) {
try {
JsonObject payload = new JsonObject();
payload.addProperty("event", event);
payload.addProperty("id", id);
payload.addProperty("data", IMServiceUtils.serialize(data));
MainContext.getContext().getBean(WebIMAgentDispatcher.class).publish(payload);
} catch (IOException e) {
logger.error("publishAgentEventMessage", e);
}
}
}
// 向坐席发送消息
public boolean sendAgentEventMessage(String id, String event, Object data) {
List<SocketIOClient> agents = agentClients.getClients(id);
for (SocketIOClient agentClient : agents) {
agentClient.sendEvent(event, data);
}
return agents.size() > 0;
}
/**
* 企业聊天
*/
public void setEntImClients(NettyIMClient entIMClients) {
this.entIMClients = entIMClients;
}
public void putEntIMEventClient(String id, SocketIOClient userClient) {
entIMClients.putClient(id, userClient);
}
public void removeEntIMEventClient(String id, String sessionid) {
entIMClients.removeClient(id, sessionid);
}
public void sendEntIMEventMessage(String id, String event, Object data) {
List<SocketIOClient> entims = entIMClients.getClients(id);
for (SocketIOClient userClient : entims) {
userClient.sendEvent(event, data);
}
}
public int getEntIMClientsNum(String user) {
return entIMClients.getClients(user) != null ? entIMClients.getClients(user).size() : 0;
}
public void sendCallCenterMessage(String id, String event, Object data) {
List<SocketIOClient> ccClients = callCenterClients.getClients(id);
for (SocketIOClient ccClient : ccClients) {
ccClient.sendEvent(event, data);
}
}
/**
* Callout Event Server Methods.
*/
public void putCalloutEventClient(String id, SocketIOClient client) {
calloutClients.putClient(id, client);
}
public void removeCalloutEventClient(String id, String sessionId) {
calloutClients.removeClient(id, sessionId);
}
public void sendCalloutEventMessage(String id, String event, Object data) {
List<SocketIOClient> _clients = calloutClients.getClients(id);
logger.info("sendCalloutEventMessage get clients size {}", _clients.size());
for (SocketIOClient c : _clients) {
c.sendEvent(event, data);
}
}
/** /**
* Chatbot Event Server Methods. * Chatbot Event Server Methods.
*/ */
public void putChatbotEventClient(String id, SocketIOClient client){ public void putChatbotEventClient(String id, SocketIOClient client) {
chatbotClients.putClient(id, client); chatbotClients.putClient(id, client);
} }
@ -127,29 +207,10 @@ public class NettyClients {
chatbotClients.removeClient(id, sessionId); chatbotClients.removeClient(id, sessionId);
} }
public void sendChatbotEventMessage(String id, String event, Object data){ public void sendChatbotEventMessage(String id, String event, Object data) {
List<SocketIOClient> _clients = chatbotClients.getClients(id); List<SocketIOClient> _clients = chatbotClients.getClients(id);
logger.info("sendChatbotEventMessage get clients size {}", _clients.size()); logger.info("sendChatbotEventMessage get clients size {}", _clients.size());
for(SocketIOClient c: _clients){ for (SocketIOClient c : _clients) {
c.sendEvent(event, data);
}
}
/**
* Callout Event Server Methods.
*/
public void putCalloutEventClient(String id, SocketIOClient client){
calloutClients.putClient(id, client);
}
public void removeCalloutEventClient(String id, String sessionId) {
calloutClients.removeClient(id, sessionId);
}
public void sendCalloutEventMessage(String id, String event, Object data){
List<SocketIOClient> _clients = calloutClients.getClients(id);
logger.info("sendCalloutEventMessage get clients size {}", _clients.size());
for(SocketIOClient c: _clients){
c.sendEvent(event, data); c.sendEvent(event, data);
} }
} }

View File

@ -16,228 +16,212 @@
*/ */
package com.chatopera.cc.app.im.handler; package com.chatopera.cc.app.im.handler;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.List;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist; import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.im.router.OutMessageRouter; import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.message.AgentServiceMessage; import com.chatopera.cc.app.im.message.AgentServiceMessage;
import com.chatopera.cc.app.im.message.AgentStatusMessage; import com.chatopera.cc.app.im.message.AgentStatusMessage;
import com.chatopera.cc.app.im.message.ChatMessage; import com.chatopera.cc.app.im.message.ChatMessage;
import org.apache.commons.lang.StringUtils; import com.chatopera.cc.app.im.router.OutMessageRouter;
import org.springframework.beans.factory.annotation.Autowired; import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.*;
import com.corundumstudio.socketio.AckRequest; import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect; import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent; import com.corundumstudio.socketio.annotation.OnEvent;
import com.chatopera.cc.app.persistence.repository.AgentStatusRepository; import org.apache.commons.lang.StringUtils;
import com.chatopera.cc.app.persistence.repository.AgentUserRepository; import org.springframework.beans.factory.annotation.Autowired;
import com.chatopera.cc.app.persistence.repository.AgentUserTaskRepository;
import com.chatopera.cc.app.persistence.repository.ChatMessageRepository; import java.net.InetSocketAddress;
import com.chatopera.cc.app.persistence.repository.WorkSessionRepository; import java.util.Date;
import com.chatopera.cc.app.model.AgentStatus; import java.util.List;
import com.chatopera.cc.app.model.AgentUser;
import com.chatopera.cc.app.model.AgentUserTask; public class AgentEventHandler {
import com.chatopera.cc.app.model.MessageOutContent; protected SocketIOServer server;
import com.chatopera.cc.app.model.WorkSession;
@Autowired
public class AgentEventHandler public AgentEventHandler(SocketIOServer server) {
{ this.server = server;
protected SocketIOServer server;
@Autowired
public AgentEventHandler(SocketIOServer server)
{
this.server = server ;
}
@OnConnect
public void onConnect(SocketIOClient client)
{
String user = client.getHandshakeData().getSingleUrlParam("userid") ;
String orgi = client.getHandshakeData().getSingleUrlParam("orgi") ;
String session = client.getHandshakeData().getSingleUrlParam("session") ;
String admin = client.getHandshakeData().getSingleUrlParam("admin") ;
if(!StringUtils.isBlank(user) && !StringUtils.isBlank(user)){
client.set("agentno", user);
AgentStatusRepository agentStatusRepository = MainContext.getContext().getBean(AgentStatusRepository.class) ;
List<AgentStatus> agentStatusList = agentStatusRepository.findByAgentnoAndOrgi(user , orgi);
if(agentStatusList.size() > 0){
AgentStatus agentStatus = agentStatusList.get(0) ;
agentStatus.setUpdatetime(new Date());
agentStatusRepository.save(agentStatus);
if(CacheHelper.getAgentStatusCacheBean().getCacheObject(user, orgi)!=null) {
CacheHelper.getAgentStatusCacheBean().put(user, agentStatus , orgi);
}
}
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress() ;
String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()) ;
WorkSessionRepository workSessionRepository = MainContext.getContext().getBean(WorkSessionRepository.class) ;
int count = workSessionRepository.countByAgentAndDatestrAndOrgi(user, MainUtils.simpleDateFormat.format(new Date()), orgi) ;
workSessionRepository.save(MainUtils.createWorkSession(user, MainUtils.getContextID(client.getSessionId().toString()), session, orgi, ip, address.getHostName() , admin , count == 0)) ;
NettyClients.getInstance().putAgentEventClient(user, client);
}
}
//添加@OnDisconnect事件客户端断开连接时调用刷新客户端信息
@OnDisconnect
public void onDisconnect(SocketIOClient client)
{
String user = client.getHandshakeData().getSingleUrlParam("userid") ;
String orgi = client.getHandshakeData().getSingleUrlParam("orgi") ;
String admin = client.getHandshakeData().getSingleUrlParam("admin") ;
if(!StringUtils.isBlank(user)){
AutomaticServiceDist.deleteAgentStatus(user, orgi, !StringUtils.isBlank(admin) && admin.equals("true"));
NettyClients.getInstance().removeAgentEventClient(user , MainUtils.getContextID(client.getSessionId().toString()));
WorkSessionRepository workSessionRepository = MainContext.getContext().getBean(WorkSessionRepository.class) ;
List<WorkSession> workSessionList = workSessionRepository.findByOrgiAndClientid(orgi, MainUtils.getContextID(client.getSessionId().toString())) ;
if(workSessionList.size() > 0) {
WorkSession workSession = workSessionList.get(0) ;
workSession.setEndtime(new Date());
if(workSession.getBegintime()!=null) {
workSession.setDuration((int) (System.currentTimeMillis() - workSession.getBegintime().getTime()));
}else if(workSession.getCreatetime()!=null) {
workSession.setDuration((int) (System.currentTimeMillis() - workSession.getCreatetime().getTime()));
}
if(workSession.isFirsttime()) {
workSession.setFirsttimes(workSession.getDuration());
}
workSessionRepository.save(workSession) ;
}
}
}
//消息接收入口当接收到消息后查找发送目标客户端并且向该客户端发送消息且给自己发送消息
@OnEvent(value = "service")
public void onEvent(SocketIOClient client, AckRequest request, AgentServiceMessage data)
{
}
//消息接收入口当接收到消息后查找发送目标客户端并且向该客户端发送消息且给自己发送消息
@OnEvent(value = "status")
public void onEvent(SocketIOClient client, AckRequest request, AgentStatusMessage data)
{
} }
//消息接收入口当接收到消息后查找发送目标客户端并且向该客户端发送消息且给自己发送消息 @OnConnect
@OnEvent(value = "message") public void onConnect(SocketIOClient client) {
public void onEvent(SocketIOClient client, AckRequest request, ChatMessage data) String user = client.getHandshakeData().getSingleUrlParam("userid");
{ String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
String user = client.getHandshakeData().getSingleUrlParam("userid") ; String session = client.getHandshakeData().getSingleUrlParam("session");
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(data.getTouser(), data.getOrgi()); String admin = client.getHandshakeData().getSingleUrlParam("admin");
MessageOutContent outMessage = new MessageOutContent() ; if (StringUtils.isNotBlank(user) && StringUtils.isNotBlank(user)) {
outMessage.setMessage(data.getMessage()); client.set("agentno", user);
if(MainContext.MediaTypeEnum.COOPERATION.toString().equals(data.getMsgtype())){ AgentStatusRepository agentStatusRepository = MainContext.getContext().getBean(AgentStatusRepository.class);
outMessage.setMessageType(MainContext.MediaTypeEnum.COOPERATION.toString()); List<AgentStatus> agentStatusList = agentStatusRepository.findByAgentnoAndOrgi(user, orgi);
}else{ if (agentStatusList.size() > 0) {
outMessage.setMessageType(MainContext.MediaTypeEnum.TEXT.toString()); AgentStatus agentStatus = agentStatusList.get(0);
} agentStatus.setUpdatetime(new Date());
agentStatusRepository.save(agentStatus);
outMessage.setAttachmentid(data.getAttachmentid()); if (CacheHelper.getAgentStatusCacheBean().getCacheObject(user, orgi) != null) {
CacheHelper.getAgentStatusCacheBean().put(user, agentStatus, orgi);
outMessage.setCalltype(MainContext.CallTypeEnum.OUT.toString()); }
outMessage.setAgentUser(agentUser); }
outMessage.setSnsAccount(null); InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress();
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(data.getUserid(), data.getOrgi()) ; String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString());
if(agentUser == null){
agentUser = MainContext.getContext().getBean(AgentUserRepository.class).findByIdAndOrgi(data.getTouser() , data.getOrgi()) ; WorkSessionRepository workSessionRepository = MainContext.getContext().getBean(WorkSessionRepository.class);
try { int count = workSessionRepository.countByAgentAndDatestrAndOrgi(user, MainUtils.simpleDateFormat.format(new Date()), orgi);
AutomaticServiceDist.serviceFinish(agentUser, data.getOrgi());
} catch (Exception e) { workSessionRepository.save(MainUtils.createWorkSession(user, MainUtils.getContextID(client.getSessionId().toString()), session, orgi, ip, address.getHostName(), admin, count == 0));
e.printStackTrace();
} NettyClients.getInstance().putAgentEventClient(user, client);
} }
}
if(agentUser!=null && user!=null && user.equals(agentUser.getAgentno())){
data.setId(MainUtils.getUUID()); //添加@OnDisconnect事件客户端断开连接时调用刷新客户端信息
data.setContextid(agentUser.getContextid()); @OnDisconnect
public void onDisconnect(SocketIOClient client) {
data.setAgentserviceid(agentUser.getAgentserviceid()); String user = client.getHandshakeData().getSingleUrlParam("userid");
data.setCreater(agentUser.getAgentno()); String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
String admin = client.getHandshakeData().getSingleUrlParam("admin");
if(MainContext.MediaTypeEnum.COOPERATION.toString().equals(data.getMsgtype())){ if (StringUtils.isNotBlank(user)) {
data.setMsgtype(MainContext.MediaTypeEnum.COOPERATION.toString()); AutomaticServiceDist.deleteAgentStatus(user, orgi, StringUtils.isNotBlank(admin) && admin.equals("true"));
}else{ NettyClients.getInstance().removeAgentEventClient(user, MainUtils.getContextID(client.getSessionId().toString()));
data.setMsgtype(MainContext.MediaTypeEnum.TEXT.toString());
} WorkSessionRepository workSessionRepository = MainContext.getContext().getBean(WorkSessionRepository.class);
List<WorkSession> workSessionList = workSessionRepository.findByOrgiAndClientid(orgi, MainUtils.getContextID(client.getSessionId().toString()));
data.setCalltype(MainContext.CallTypeEnum.OUT.toString()); if (workSessionList.size() > 0) {
if(!StringUtils.isBlank(agentUser.getAgentno())){ WorkSession workSession = workSessionList.get(0);
data.setTouser(agentUser.getUserid()); workSession.setEndtime(new Date());
} if (workSession.getBegintime() != null) {
data.setChannel(agentUser.getChannel()); workSession.setDuration((int) (System.currentTimeMillis() - workSession.getBegintime().getTime()));
} else if (workSession.getCreatetime() != null) {
data.setUsession(agentUser.getUserid()); workSession.setDuration((int) (System.currentTimeMillis() - workSession.getCreatetime().getTime()));
}
outMessage.setContextid(agentUser.getContextid()); if (workSession.isFirsttime()) {
outMessage.setFromUser(data.getUserid()); workSession.setFirsttimes(workSession.getDuration());
outMessage.setToUser(data.getTouser()); }
outMessage.setChannelMessage(data); workSessionRepository.save(workSession);
if(agentStatus!=null){ }
data.setUsername(agentStatus.getUsername()); }
outMessage.setNickName(agentStatus.getUsername()); }
}else{
outMessage.setNickName(data.getUsername()); //消息接收入口当接收到消息后查找发送目标客户端并且向该客户端发送消息且给自己发送消息
} @OnEvent(value = "service")
outMessage.setCreatetime(data.getCreatetime()); public void onEvent(SocketIOClient client, AckRequest request, AgentServiceMessage data) {
AgentUserTaskRepository agentUserTaskRes = MainContext.getContext().getBean(AgentUserTaskRepository.class) ; }
AgentUserTask agentUserTask = agentUserTaskRes.getOne(agentUser.getId()) ;
//消息接收入口当接收到消息后查找发送目标客户端并且向该客户端发送消息且给自己发送消息
if(agentUserTask!=null){ @OnEvent(value = "status")
if(agentUserTask.getLastgetmessage() != null && agentUserTask.getLastmessage()!=null){ public void onEvent(SocketIOClient client, AckRequest request, AgentStatusMessage data) {
data.setLastagentmsgtime(agentUserTask.getLastgetmessage());
data.setLastmsgtime(agentUserTask.getLastmessage()); }
data.setAgentreplyinterval((int)((System.currentTimeMillis() - agentUserTask.getLastgetmessage().getTime())/1000)); //坐席上次回复消息的间隔
data.setAgentreplytime((int)((System.currentTimeMillis() - agentUserTask.getLastmessage().getTime())/1000)); //坐席回复消息花费时间 //消息接收入口当接收到消息后查找发送目标客户端并且向该客户端发送消息且给自己发送消息
} @OnEvent(value = "message")
public void onEvent(SocketIOClient client, AckRequest request, ChatMessage data) {
agentUserTask.setAgentreplys(agentUserTask.getAgentreplys()+1); //总咨询记录数量 String user = client.getHandshakeData().getSingleUrlParam("userid");
agentUserTask.setAgentreplyinterval(agentUserTask.getAgentreplyinterval() + data.getAgentreplyinterval()); //总时长 AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(data.getTouser(), data.getOrgi());
if(agentUserTask.getAgentreplys()>0){ MessageOutContent outMessage = new MessageOutContent();
agentUserTask.setAvgreplyinterval(agentUserTask.getAgentreplyinterval() / agentUserTask.getAgentreplys()); outMessage.setMessage(data.getMessage());
} if (MainContext.MediaTypeEnum.COOPERATION.toString().equals(data.getMsgtype())) {
outMessage.setMessageType(MainContext.MediaTypeEnum.COOPERATION.toString());
agentUserTask.setLastgetmessage(new Date()); } else {
outMessage.setMessageType(MainContext.MediaTypeEnum.TEXT.toString());
}
outMessage.setAttachmentid(data.getAttachmentid());
outMessage.setCalltype(MainContext.CallTypeEnum.OUT.toString());
outMessage.setAgentUser(agentUser);
outMessage.setSnsAccount(null);
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(data.getUserid(), data.getOrgi());
if (agentUser == null) {
agentUser = MainContext.getContext().getBean(AgentUserRepository.class).findByIdAndOrgi(data.getTouser(), data.getOrgi());
try {
AutomaticServiceDist.serviceFinish(agentUser, data.getOrgi());
} catch (Exception e) {
e.printStackTrace();
}
}
if (agentUser != null && user != null && user.equals(agentUser.getAgentno())) {
data.setId(MainUtils.getUUID());
data.setContextid(agentUser.getContextid());
data.setAgentserviceid(agentUser.getAgentserviceid());
data.setCreater(agentUser.getAgentno());
if (MainContext.MediaTypeEnum.COOPERATION.toString().equals(data.getMsgtype())) {
data.setMsgtype(MainContext.MediaTypeEnum.COOPERATION.toString());
} else {
data.setMsgtype(MainContext.MediaTypeEnum.TEXT.toString());
}
data.setCalltype(MainContext.CallTypeEnum.OUT.toString());
if (StringUtils.isNotBlank(agentUser.getAgentno())) {
data.setTouser(agentUser.getUserid());
}
data.setChannel(agentUser.getChannel());
data.setUsession(agentUser.getUserid());
outMessage.setContextid(agentUser.getContextid());
outMessage.setFromUser(data.getUserid());
outMessage.setToUser(data.getTouser());
outMessage.setChannelMessage(data);
if (agentStatus != null) {
data.setUsername(agentStatus.getUsername());
outMessage.setNickName(agentStatus.getUsername());
} else {
outMessage.setNickName(data.getUsername());
}
outMessage.setCreatetime(data.getCreatetime());
AgentUserTaskRepository agentUserTaskRes = MainContext.getContext().getBean(AgentUserTaskRepository.class);
AgentUserTask agentUserTask = agentUserTaskRes.getOne(agentUser.getId());
if (agentUserTask != null) {
if (agentUserTask.getLastgetmessage() != null && agentUserTask.getLastmessage() != null) {
data.setLastagentmsgtime(agentUserTask.getLastgetmessage());
data.setLastmsgtime(agentUserTask.getLastmessage());
data.setAgentreplyinterval((int) ((System.currentTimeMillis() - agentUserTask.getLastgetmessage().getTime()) / 1000)); //坐席上次回复消息的间隔
data.setAgentreplytime((int) ((System.currentTimeMillis() - agentUserTask.getLastmessage().getTime()) / 1000)); //坐席回复消息花费时间
}
agentUserTask.setAgentreplys(agentUserTask.getAgentreplys() + 1); //总咨询记录数量
agentUserTask.setAgentreplyinterval(agentUserTask.getAgentreplyinterval() + data.getAgentreplyinterval()); //总时长
if (agentUserTask.getAgentreplys() > 0) {
agentUserTask.setAvgreplyinterval(agentUserTask.getAgentreplyinterval() / agentUserTask.getAgentreplys());
}
agentUserTask.setLastgetmessage(new Date());
// agentUserTask.setReptime(null); // agentUserTask.setReptime(null);
// agentUserTask.setReptimes("0"); // agentUserTask.setReptimes("0");
agentUserTaskRes.save(agentUserTask) ;
}
/**
* 保存消息
*/
MainContext.getContext().getBean(ChatMessageRepository.class).save(data) ;
client.sendEvent(MainContext.MessageTypeEnum.MESSAGE.toString(), data); agentUserTaskRes.save(agentUserTask);
}
if(!StringUtils.isBlank(data.getTouser())){
OutMessageRouter router = null ; /**
router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()) ; * 保存消息
if(router!=null){ */
router.handler(data.getTouser(), MainContext.MessageTypeEnum.MESSAGE.toString(), agentUser.getAppid(), outMessage); MainContext.getContext().getBean(ChatMessageRepository.class).save(data);
}
} client.sendEvent(MainContext.MessageTypeEnum.MESSAGE.toString(), data);
}else if(user!=null && agentUser!=null && !user.equals(agentUser.getAgentno())){
client.sendEvent(MainContext.MessageTypeEnum.END.toString(), agentUser); if (StringUtils.isNotBlank(data.getTouser())) {
} OutMessageRouter router = null;
} router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel());
if (router != null) {
router.handler(data.getTouser(), MainContext.MessageTypeEnum.MESSAGE.toString(), agentUser.getAppid(), outMessage);
}
}
} else if (user != null && agentUser != null && !user.equals(agentUser.getAgentno())) {
client.sendEvent(MainContext.MessageTypeEnum.END.toString(), agentUser);
}
}
} }

View File

@ -51,7 +51,7 @@ public class CalloutEventHandler
String admin = client.getHandshakeData().getSingleUrlParam("admin") ; String admin = client.getHandshakeData().getSingleUrlParam("admin") ;
logger.info("onConnect userid {}, orgi {}.", user, orgi); logger.info("onConnect userid {}, orgi {}.", user, orgi);
if(!StringUtils.isBlank(user) && !StringUtils.isBlank(user)){ if(StringUtils.isNotBlank(user) && StringUtils.isNotBlank(user)){
client.set("agentno", user); client.set("agentno", user);
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress() ; InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress() ;
String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()) ; String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()) ;

View File

@ -24,6 +24,7 @@ import com.chatopera.cc.app.im.message.AgentStatusMessage;
import com.chatopera.cc.app.im.message.ChatMessage; import com.chatopera.cc.app.im.message.ChatMessage;
import com.chatopera.cc.app.im.message.NewRequestMessage; import com.chatopera.cc.app.im.message.NewRequestMessage;
import com.chatopera.cc.app.im.util.ChatbotUtils; import com.chatopera.cc.app.im.util.ChatbotUtils;
import com.chatopera.cc.app.im.util.IMServiceUtils;
import com.chatopera.cc.app.model.*; import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.AgentUserRepository; import com.chatopera.cc.app.persistence.repository.AgentUserRepository;
import com.chatopera.cc.app.persistence.repository.ChatbotRepository; import com.chatopera.cc.app.persistence.repository.ChatbotRepository;
@ -65,6 +66,7 @@ public class ChatbotEventHandler {
@OnConnect @OnConnect
public void onConnect(SocketIOClient client) { public void onConnect(SocketIOClient client) {
try { try {
String user = client.getHandshakeData().getSingleUrlParam("userid"); String user = client.getHandshakeData().getSingleUrlParam("userid");
String nickname = client.getHandshakeData().getSingleUrlParam("nickname"); String nickname = client.getHandshakeData().getSingleUrlParam("nickname");
String orgi = client.getHandshakeData().getSingleUrlParam("orgi"); String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
@ -73,6 +75,7 @@ public class ChatbotEventHandler {
String aiid = client.getHandshakeData().getSingleUrlParam("aiid"); String aiid = client.getHandshakeData().getSingleUrlParam("aiid");
// String agent = client.getHandshakeData().getSingleUrlParam("agent") ; // String agent = client.getHandshakeData().getSingleUrlParam("agent") ;
// String skill = client.getHandshakeData().getSingleUrlParam("skill") ; // String skill = client.getHandshakeData().getSingleUrlParam("skill") ;
logger.info("onConnect userid {}, nickname {}", user, nickname);
Date now = new Date(); Date now = new Date();
if (StringUtils.isNotBlank(user)) { if (StringUtils.isNotBlank(user)) {
@ -80,21 +83,40 @@ public class ChatbotEventHandler {
* 加入到 缓存列表 * 加入到 缓存列表
*/ */
NettyClients.getInstance().putChatbotEventClient(user, client); NettyClients.getInstance().putChatbotEventClient(user, client);
MessageOutContent outMessage = new MessageOutContent();
CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, MainContext.getContext().getBean(ConsultInviteRepository.class)); CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, MainContext.getContext().getBean(ConsultInviteRepository.class));
/**
* 更新坐席服务类型
*/
IMServiceUtils.shiftOpsType(user, orgi, MainContext.OptTypeEnum.CHATBOT);
// send out tip
MessageOutContent tip = new MessageOutContent();
tip.setMessage("您正在使用机器人客服!");
tip.setMessageType(MainContext.MessageTypeEnum.MESSAGE.toString());
tip.setCalltype(MainContext.CallTypeEnum.IN.toString());
tip.setNickName(invite.getAiname());
tip.setCreatetime(MainUtils.dateFormate.format(now));
client.sendEvent(MainContext.MessageTypeEnum.STATUS.toString(), tip);
// send out welcome message
if (invite != null && StringUtils.isNotBlank(invite.getAisuccesstip())) { if (invite != null && StringUtils.isNotBlank(invite.getAisuccesstip())) {
outMessage.setMessage(invite.getAisuccesstip()); ChatMessage welcome = new ChatMessage();
} else { welcome.setCalltype(MainContext.CallTypeEnum.OUT.toString());
outMessage.setMessage("欢迎使用华夏春松机器人客服!"); welcome.setAppid(appid);
welcome.setOrgi(orgi);
welcome.setAiid(aiid);
welcome.setMessage(invite.getAisuccesstip());
welcome.setTouser(user);
welcome.setTousername(nickname);
welcome.setMsgtype(MainContext.MessageTypeEnum.MESSAGE.toString());
welcome.setUserid(user);
welcome.setUsername(invite.getAiname());
welcome.setUpdatetime(System.currentTimeMillis());
client.sendEvent(MainContext.MessageTypeEnum.MESSAGE.toString(), welcome);
} }
outMessage.setMessageType(MainContext.MessageTypeEnum.MESSAGE.toString());
outMessage.setCalltype(MainContext.CallTypeEnum.IN.toString());
outMessage.setNickName(invite.getAiname());
outMessage.setCreatetime(MainUtils.dateFormate.format(now));
client.sendEvent(MainContext.MessageTypeEnum.STATUS.toString(), outMessage);
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress(); InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress();
String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()); String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString());
OnlineUser onlineUser = getOnlineUserRes().findOne(user); OnlineUser onlineUser = getOnlineUserRes().findOne(user);
@ -139,6 +161,7 @@ public class ChatbotEventHandler {
agentUser.setCreatetime(now); agentUser.setCreatetime(now);
agentUser.setUpdatetime(now); agentUser.setUpdatetime(now);
agentUser.setSessionid(session); agentUser.setSessionid(session);
agentUser.setRegion(onlineUser.getRegion());
// 聊天机器人处理的请求 // 聊天机器人处理的请求
agentUser.setOpttype(MainContext.OptTypeEnum.CHATBOT.toString()); agentUser.setOpttype(MainContext.OptTypeEnum.CHATBOT.toString());
@ -146,7 +169,7 @@ public class ChatbotEventHandler {
agentUser.setCity(onlineUser.getCity()); agentUser.setCity(onlineUser.getCity());
agentUser.setProvince(onlineUser.getProvince()); agentUser.setProvince(onlineUser.getProvince());
agentUser.setCountry(onlineUser.getCountry()); agentUser.setCountry(onlineUser.getCountry());
AgentService agentService = AutomaticServiceDist.processChatbotService(agentUser, orgi); AgentService agentService = AutomaticServiceDist.processChatbotService(invite != null ? invite.getAiname() : "机器人客服", agentUser, orgi);
agentUser.setAgentserviceid(agentService.getId()); agentUser.setAgentserviceid(agentService.getId());
// 标记为机器人坐席 // 标记为机器人坐席
@ -172,7 +195,7 @@ public class ChatbotEventHandler {
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user, orgi); AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user, orgi);
OnlineUser onlineUser = (OnlineUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi); OnlineUser onlineUser = (OnlineUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi);
if (agentUser != null) { if (agentUser != null) {
AutomaticServiceDist.processChatbotService(agentUser, orgi); AutomaticServiceDist.processChatbotService(null, agentUser, orgi);
CacheHelper.getAgentUserCacheBean().delete(user, MainContext.SYSTEM_ORGI); CacheHelper.getAgentUserCacheBean().delete(user, MainContext.SYSTEM_ORGI);
CacheHelper.getOnlineUserCacheBean().delete(user, orgi); CacheHelper.getOnlineUserCacheBean().delete(user, orgi);
agentUser.setStatus(MainContext.OnlineUserOperatorStatus.OFFLINE.toString()); agentUser.setStatus(MainContext.OnlineUserOperatorStatus.OFFLINE.toString());

View File

@ -25,6 +25,7 @@ import com.chatopera.cc.app.im.message.AgentStatusMessage;
import com.chatopera.cc.app.im.message.ChatMessage; import com.chatopera.cc.app.im.message.ChatMessage;
import com.chatopera.cc.app.im.message.NewRequestMessage; import com.chatopera.cc.app.im.message.NewRequestMessage;
import com.chatopera.cc.app.im.util.HumanUtils; import com.chatopera.cc.app.im.util.HumanUtils;
import com.chatopera.cc.app.im.util.IMServiceUtils;
import com.chatopera.cc.app.model.*; import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.impl.AgentUserService; import com.chatopera.cc.app.persistence.impl.AgentUserService;
import com.chatopera.cc.app.persistence.repository.AgentServiceRepository; import com.chatopera.cc.app.persistence.repository.AgentServiceRepository;
@ -37,6 +38,8 @@ import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect; import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent; import com.corundumstudio.socketio.annotation.OnEvent;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -45,6 +48,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
public class IMEventHandler { public class IMEventHandler {
private final static Logger logger = LoggerFactory.getLogger(IMEventHandler.class);
protected SocketIOServer server; protected SocketIOServer server;
@Autowired @Autowired
@ -68,19 +72,40 @@ public class IMEventHandler {
String nickname = client.getHandshakeData().getSingleUrlParam("nickname"); String nickname = client.getHandshakeData().getSingleUrlParam("nickname");
if (!StringUtils.isBlank(user)) { if (StringUtils.isNotBlank(user)) {
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress();
String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString());
/**
* 加入到 缓存列表
*/
NettyClients.getInstance().putIMEventClient(user, client);
/**
* 更新坐席服务类型
*/
IMServiceUtils.shiftOpsType(user, orgi, MainContext.OptTypeEnum.HUMAN);
/** /**
* 用户进入到对话连接 排队用户请求 , 如果返回失败表示当前坐席全忙用户进入排队状态当前提示信息 显示 当前排队的队列位置不可进行对话用户发送的消息作为留言处理 * 用户进入到对话连接 排队用户请求 , 如果返回失败表示当前坐席全忙用户进入排队状态当前提示信息 显示 当前排队的队列位置不可进行对话用户发送的消息作为留言处理
*/ */
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress(); NewRequestMessage newRequestMessage = OnlineUserUtils.newRequestMessage(user,
String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()); orgi,
NewRequestMessage newRequestMessage = OnlineUserUtils.newRequestMessage(user, orgi, session, appid, ip, client.getHandshakeData().getSingleUrlParam("osname"), client.getHandshakeData().getSingleUrlParam("browser"), MainContext.ChannelTypeEnum.WEBIM.toString(), skill, agent, nickname, title, url, traceid, MainContext.ChatInitiatorType.USER.toString()); session,
// /** appid,
// * 加入到 缓存列表 ip,
// */ client.getHandshakeData().getSingleUrlParam("osname"),
NettyClients.getInstance().putIMEventClient(user, client); client.getHandshakeData().getSingleUrlParam("browser"),
// MainContext.ChannelTypeEnum.WEBIM.toString(),
if (newRequestMessage != null && !StringUtils.isBlank(newRequestMessage.getMessage())) { skill,
agent,
nickname,
title,
url,
traceid,
MainContext.ChatInitiatorType.USER.toString());
if (newRequestMessage != null && StringUtils.isNotBlank(newRequestMessage.getMessage())) {
MessageOutContent outMessage = new MessageOutContent(); MessageOutContent outMessage = new MessageOutContent();
outMessage.setMessage(newRequestMessage.getMessage()); outMessage.setMessage(newRequestMessage.getMessage());
outMessage.setMessageType(MainContext.MessageTypeEnum.MESSAGE.toString()); outMessage.setMessageType(MainContext.MessageTypeEnum.MESSAGE.toString());
@ -135,20 +160,19 @@ public class IMEventHandler {
agentUser.setName(contacts.getName()); agentUser.setName(contacts.getName());
agentUser.setPhone(contacts.getPhone()); agentUser.setPhone(contacts.getPhone());
agentUser.setEmail(contacts.getEmail()); agentUser.setEmail(contacts.getEmail());
agentUser.setResion(contacts.getMemo());
agentUser.setChatbotops(false); // 非机器人客服 agentUser.setChatbotops(false); // 非机器人客服
agentUser.setOpttype(MainContext.OptTypeEnum.HUMAN.toString());
service.save(agentUser); service.save(agentUser);
CacheHelper.getAgentUserCacheBean().put(agentUser.getUserid(), agentUser, MainContext.SYSTEM_ORGI); CacheHelper.getAgentUserCacheBean().put(agentUser.getUserid(), agentUser, MainContext.SYSTEM_ORGI);
} }
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class); AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
List<AgentService> agentServiceList = agentServiceRes.findByUseridAndOrgi(user, orgi); List<AgentService> agentServiceList = agentServiceRes.findByUseridAndOrgiOrderByLogindateDesc(user, orgi);
if (agentServiceList.size() > 0) { if (agentServiceList.size() > 0) {
AgentService agentService = agentServiceList.get(0); AgentService agentService = agentServiceList.get(0);
agentService.setName(contacts.getName()); agentService.setName(contacts.getName());
agentService.setPhone(contacts.getName()); agentService.setPhone(contacts.getPhone());
agentService.setEmail(contacts.getName()); agentService.setEmail(contacts.getEmail());
agentService.setRegion(contacts.getMemo());
agentServiceRes.save(agentService); agentServiceRes.save(agentService);
} }
} }

View File

@ -24,52 +24,53 @@ import com.chatopera.cc.app.model.AgentService;
import com.chatopera.cc.app.model.MessageDataBean; import com.chatopera.cc.app.model.MessageDataBean;
import com.chatopera.cc.app.model.MessageOutContent; import com.chatopera.cc.app.model.MessageOutContent;
public class MessageRouter extends Router{ public class MessageRouter extends Router {
@Override @Override
public MessageDataBean handler(MessageDataBean inMessage) { public MessageDataBean handler(MessageDataBean inMessage) {
MessageOutContent outMessage = new MessageOutContent() ; MessageOutContent outMessage = new MessageOutContent();
try { try {
outMessage.setOrgi(inMessage.getOrgi()); outMessage.setOrgi(inMessage.getOrgi());
outMessage.setFromUser(inMessage.getToUser()); outMessage.setFromUser(inMessage.getToUser());
outMessage.setToUser(inMessage.getFromUser()); outMessage.setToUser(inMessage.getFromUser());
outMessage.setId(MainUtils.genID()); outMessage.setId(MainUtils.genID());
outMessage.setMessageType(inMessage.getMessageType()); outMessage.setMessageType(inMessage.getMessageType());
outMessage.setUser(inMessage.getUser()); outMessage.setUser(inMessage.getUser());
outMessage.setAgentUser(inMessage.getAgentUser()); outMessage.setAgentUser(inMessage.getAgentUser());
/** /**
* 首先交由 IMR处理 MESSAGE指令 如果当前用户是在 坐席对话列表中 则直接推送给坐席如果不在则执行 IMR * 首先交由 IMR处理 MESSAGE指令 如果当前用户是在 坐席对话列表中 则直接推送给坐席如果不在则执行 IMR
*/ */
if(outMessage.getAgentUser()!=null && outMessage.getAgentUser().getStatus()!=null){ if (outMessage.getAgentUser() != null && outMessage.getAgentUser().getStatus() != null) {
if(outMessage.getAgentUser().getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())){ if (outMessage.getAgentUser().getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())) {
int queneIndex = AutomaticServiceDist.getQueneIndex(inMessage.getAgentUser().getAgent() , inMessage.getOrgi(), inMessage.getAgentUser().getSkill()) ; int queneIndex = AutomaticServiceDist.getQueneIndex(inMessage.getAgentUser().getAgent(), inMessage.getOrgi(), inMessage.getAgentUser().getSkill());
if(MainContext.AgentUserStatusEnum.INQUENE.toString().equals(outMessage.getAgentUser().getStatus())){ if (MainContext.AgentUserStatusEnum.INQUENE.toString().equals(outMessage.getAgentUser().getStatus())) {
outMessage.setMessage(AutomaticServiceDist.getQueneMessage(queneIndex , outMessage.getAgentUser().getChannel(),inMessage.getOrgi())); outMessage.setMessage(AutomaticServiceDist.getQueneMessage(queneIndex, outMessage.getAgentUser().getChannel(), inMessage.getOrgi()));
} }
}else if(outMessage.getAgentUser().getStatus().equals(MainContext.AgentUserStatusEnum.INSERVICE.toString())){ } else if (outMessage.getAgentUser().getStatus().equals(MainContext.AgentUserStatusEnum.INSERVICE.toString())) {
} }
}else if(MainContext.MessageTypeEnum.NEW.toString().equals(inMessage.getMessageType())){ } else if (MainContext.MessageTypeEnum.NEW.toString().equals(inMessage.getMessageType())) {
/** /**
* 找到空闲坐席如果未找到坐席 则将该用户放入到 排队队列 * 找到空闲坐席如果未找到坐席 则将该用户放入到 排队队列
* *
*/ */
AgentService agentService = AutomaticServiceDist.allotAgent(inMessage.getAgentUser(), inMessage.getOrgi()) ; AgentService agentService = AutomaticServiceDist.allotAgent(inMessage.getAgentUser(), inMessage.getOrgi());
if(agentService!=null && MainContext.AgentUserStatusEnum.INSERVICE.toString().equals(agentService.getStatus())){ if (agentService != null && MainContext.AgentUserStatusEnum.INSERVICE.toString().equals(agentService.getStatus())) {
outMessage.setMessage(AutomaticServiceDist.getSuccessMessage(agentService , inMessage.getAgentUser().getChannel(),inMessage.getOrgi())); outMessage.setMessage(AutomaticServiceDist.getSuccessMessage(agentService, inMessage.getAgentUser().getChannel(), inMessage.getOrgi()));
NettyClients.getInstance().sendAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), inMessage.getAgentUser()); // TODO #111 publish to redis
}else{ NettyClients.getInstance().publishAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), inMessage.getAgentUser());
if(agentService.getQueneindex() > 0){ //当前有坐席 } else {
outMessage.setMessage(AutomaticServiceDist.getQueneMessage(agentService.getQueneindex(), inMessage.getAgentUser().getChannel(), inMessage.getOrgi())); if (agentService.getQueneindex() > 0) { //当前有坐席
}else{ outMessage.setMessage(AutomaticServiceDist.getQueneMessage(agentService.getQueneindex(), inMessage.getAgentUser().getChannel(), inMessage.getOrgi()));
outMessage.setMessage(AutomaticServiceDist.getNoAgentMessage(agentService.getQueneindex(), inMessage.getAgentUser().getChannel(), inMessage.getOrgi())); } else {
} outMessage.setMessage(AutomaticServiceDist.getNoAgentMessage(agentService.getQueneindex(), inMessage.getAgentUser().getChannel(), inMessage.getOrgi()));
} }
} }
} catch (Exception e1) { }
e1.printStackTrace(); } catch (Exception e1) {
} e1.printStackTrace();
return outMessage ; }
} return outMessage;
}
} }

View File

@ -32,7 +32,7 @@ public class WebIMOutMessageRouter implements OutMessageRouter{
@Override @Override
public void handler(String touser, String msgtype, String appid, public void handler(String touser, String msgtype, String appid,
MessageOutContent outMessage) { MessageOutContent outMessage) {
NettyClients.getInstance().sendIMEventMessage(touser, msgtype, outMessage); NettyClients.getInstance().publishIMEventMessage(touser, msgtype, outMessage);
} }
} }

View File

@ -137,14 +137,14 @@ public class HumanUtils {
} }
} }
if (StringUtils.isNotBlank(data.getUserid()) && MainContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) { if (StringUtils.isNotBlank(data.getUserid()) && MainContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) {
NettyClients.getInstance().sendIMEventMessage(data.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), outMessage); NettyClients.getInstance().publishIMEventMessage(data.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), outMessage);
if (statusMessage != null) { if (statusMessage != null) {
NettyClients.getInstance().sendIMEventMessage(data.getUserid(), MainContext.MessageTypeEnum.STATUS.toString(), statusMessage); NettyClients.getInstance().publishIMEventMessage(data.getUserid(), MainContext.MessageTypeEnum.STATUS.toString(), statusMessage);
} }
} }
if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentno())) { if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentno())) {
//将消息发送给 坐席 // TODO 将消息发送给 坐席
NettyClients.getInstance().sendAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.MESSAGE.toString(), data); NettyClients.getInstance().publishAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.MESSAGE.toString(), data);
} }
} }
@ -176,7 +176,7 @@ public class HumanUtils {
// outMessage.setCreatetime(data.getCreatetime()); // outMessage.setCreatetime(data.getCreatetime());
// //
// if (!StringUtils.isBlank(data.getUserid()) && MainContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) { // if (!StringUtils.isBlank(data.getUserid()) && MainContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) {
// NettyClients.getInstance().sendIMEventMessage(data.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), outMessage); // NettyClients.getInstance().publishIMEventMessage(data.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), outMessage);
// } // }
// } // }

View File

@ -0,0 +1,68 @@
package com.chatopera.cc.app.im.util;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.model.AgentUser;
import com.chatopera.cc.app.persistence.impl.AgentUserService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Base64;
public class IMServiceUtils {
private final static Logger logger = LoggerFactory.getLogger(IMServiceUtils.class);
public static void shiftOpsType(final String userId, final String orgi, final MainContext.OptTypeEnum opsType){
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(userId, orgi);
AgentUserService service = MainContext.getContext().getBean(
AgentUserService.class);
if (agentUser == null) {
agentUser = service.findByUseridAndOrgi(userId, orgi);
}
if (agentUser != null) {
switch (opsType){
case CHATBOT:
agentUser.setOpttype(MainContext.OptTypeEnum.CHATBOT.toString());
agentUser.setChatbotops(true);
break;
case HUMAN:
agentUser.setOpttype(MainContext.OptTypeEnum.HUMAN.toString());
agentUser.setChatbotops(false);
break;
default:
logger.warn("shiftOpsType unknown type.");
break;
}
service.save(agentUser);
CacheHelper.getAgentUserCacheBean().put(agentUser.getUserid(), agentUser, orgi);
}
}
/**
* Write the object to a Base64 string.
*/
public static String serialize(Serializable o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
/**
* Read the object from Base64 string.
*/
public static Object deserialize(String s) throws IOException,
ClassNotFoundException {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
}
}

View File

@ -103,7 +103,7 @@ public class RichMediaUtils {
data.setTouser(agentUser.getAgentno()); data.setTouser(agentUser.getAgentno());
data.setAppid(agentUser.getAppid()); data.setAppid(agentUser.getAppid());
data.setOrgi(agentUser.getOrgi()); data.setOrgi(agentUser.getOrgi());
if (StringUtils.equals(agentUser.getOpttype(), MainContext.OptTypeEnum.CHATBOT.toString())) { if (agentUser.isChatbotops()) {
// TODO #75 create Chatbot Message // TODO #75 create Chatbot Message
// https://github.com/chatopera/cosin/issues/75 // https://github.com/chatopera/cosin/issues/75
logger.info("[createRichMediaMessageWithChannel] TODO #75 create Chatbot Message"); logger.info("[createRichMediaMessageWithChannel] TODO #75 create Chatbot Message");

View File

@ -37,7 +37,7 @@ public class Chatbot {
private String description; private String description;
private String primaryLanguage; private String primaryLanguage;
private String fallback; private String fallback;
private String welcome; private String welcome; // 问候语
private String baseUrl; // 智能问答引擎服务地址 private String baseUrl; // 智能问答引擎服务地址
private String orgi; // 租户标识 private String orgi; // 租户标识
private String organ; // 组织机构 private String organ; // 组织机构

View File

@ -20,143 +20,180 @@ package com.chatopera.cc.app.model;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
public class MessageInContent implements MessageDataBean{ public class MessageInContent implements MessageDataBean, java.io.Serializable {
public String id ; public String id;
private String nickName; private String nickName;
private String orgi ; private String orgi;
private String message ; private String message;
private String filename ; private String filename;
private int filesize ; private int filesize;
private String messageType; private String messageType;
private String fromUser; private String fromUser;
private String calltype = MainContext.CallTypeEnum.IN.toString() ; private String calltype = MainContext.CallTypeEnum.IN.toString();
private String toUser; private String toUser;
private SNSAccount snsAccount ; private SNSAccount snsAccount;
private AgentUser agentUser ; private AgentUser agentUser;
private Object channelMessage ; private Object channelMessage;
private String agentserviceid ; private String agentserviceid;
private String attachmentid ; private String attachmentid;
private boolean noagent ; private boolean noagent;
private Object user ; private Object user;
private String contextid ; private String contextid;
private String createtime ; private String createtime;
public String getId() { public String getId() {
return id; return id;
} }
public void setId(String id) {
this.id = id; public void setId(String id) {
} this.id = id;
public String getNickName() { }
return nickName;
} public String getNickName() {
public void setNickName(String nickName) { return nickName;
this.nickName = nickName; }
}
public String getOrgi() { public void setNickName(String nickName) {
return orgi; this.nickName = nickName;
} }
public void setOrgi(String orgi) {
this.orgi = orgi; public String getOrgi() {
} return orgi;
public String getMessage() { }
return message;
} public void setOrgi(String orgi) {
public void setMessage(String message) { this.orgi = orgi;
this.message = message; }
}
public String getMessageType() { public String getMessage() {
return messageType; return message;
} }
public void setMessageType(String messageType) {
this.messageType = messageType; public void setMessage(String message) {
} this.message = message;
public String getFromUser() { }
return fromUser;
} public String getMessageType() {
public void setFromUser(String fromUser) { return messageType;
this.fromUser = fromUser; }
}
public String getToUser() { public void setMessageType(String messageType) {
return toUser; this.messageType = messageType;
} }
public void setToUser(String toUser) {
this.toUser = toUser; public String getFromUser() {
} return fromUser;
public SNSAccount getSnsAccount() { }
return snsAccount;
} public void setFromUser(String fromUser) {
public void setSnsAccount(SNSAccount snsAccount) { this.fromUser = fromUser;
this.snsAccount = snsAccount; }
}
public AgentUser getAgentUser() { public String getToUser() {
return agentUser; return toUser;
} }
public void setAgentUser(AgentUser agentUser) {
this.agentUser = agentUser; public void setToUser(String toUser) {
} this.toUser = toUser;
public Object getChannelMessage() { }
return channelMessage;
} public SNSAccount getSnsAccount() {
public void setChannelMessage(Object channelMessage) { return snsAccount;
this.channelMessage = channelMessage; }
}
public Object getUser() { public void setSnsAccount(SNSAccount snsAccount) {
return user; this.snsAccount = snsAccount;
} }
public void setUser(Object user) {
this.user = user; public AgentUser getAgentUser() {
} return agentUser;
public String getContextid() { }
return contextid;
} public void setAgentUser(AgentUser agentUser) {
public void setContextid(String contextid) { this.agentUser = agentUser;
this.contextid = contextid; }
}
public String getCalltype() { public Object getChannelMessage() {
return calltype; return channelMessage;
} }
public void setCalltype(String calltype) {
this.calltype = calltype; public void setChannelMessage(Object channelMessage) {
} this.channelMessage = channelMessage;
public String getCreatetime() { }
return createtime;
} public Object getUser() {
public void setCreatetime(String createtime) { return user;
this.createtime = createtime; }
}
public String getFilename() { public void setUser(Object user) {
return filename; this.user = user;
} }
public void setFilename(String filename) {
this.filename = filename; public String getContextid() {
} return contextid;
public int getFilesize() { }
return filesize;
} public void setContextid(String contextid) {
public void setFilesize(int filesize) { this.contextid = contextid;
this.filesize = filesize; }
}
public String getAgentserviceid() { public String getCalltype() {
return agentserviceid; return calltype;
} }
public void setAgentserviceid(String agentserviceid) {
this.agentserviceid = agentserviceid; public void setCalltype(String calltype) {
} this.calltype = calltype;
public String getAttachmentid() { }
return attachmentid;
} public String getCreatetime() {
public void setAttachmentid(String attachmentid) { return createtime;
this.attachmentid = attachmentid; }
}
public boolean isNoagent() { public void setCreatetime(String createtime) {
return noagent; this.createtime = createtime;
} }
public void setNoagent(boolean noagent) {
this.noagent = noagent; public String getFilename() {
} return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public int getFilesize() {
return filesize;
}
public void setFilesize(int filesize) {
this.filesize = filesize;
}
public String getAgentserviceid() {
return agentserviceid;
}
public void setAgentserviceid(String agentserviceid) {
this.agentserviceid = agentserviceid;
}
public String getAttachmentid() {
return attachmentid;
}
public void setAttachmentid(String attachmentid) {
this.attachmentid = attachmentid;
}
public boolean isNoagent() {
return noagent;
}
public void setNoagent(boolean noagent) {
this.noagent = noagent;
}
} }

View File

@ -0,0 +1,98 @@
/*
* 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.app.model;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Proxy;
import java.sql.Blob;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
@Entity
@Table(name = "cs_stream_file")
@Proxy(lazy = false)
public class StreamingFile implements java.io.Serializable {
private String id;
@NotNull
private String name;
private String mime; // Media Type over HTTP
@NotNull
private Blob data;
private Blob thumbnail; // 图片缩略图
private Blob cooperation; // 图片协作图
@Id
@Column(length = 32)
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "assigned")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@NotNull
public String getName() {
return name;
}
public void setName(@NotNull String name) {
this.name = name;
}
@NotNull
public Blob getData() {
return data;
}
public void setData(@NotNull Blob data) {
this.data = data;
}
public Blob getThumbnail() {
return thumbnail;
}
public void setThumbnail(Blob thumbnail) {
this.thumbnail = thumbnail;
}
public String getMime() {
return mime;
}
public void setMime(String mime) {
this.mime = mime;
}
public Blob getCooperation() {
return cooperation;
}
public void setCooperation(Blob cooperation) {
this.cooperation = cooperation;
}
}

View File

@ -515,6 +515,10 @@ public class User implements java.io.Serializable{
this.ordertype = ordertype; this.ordertype = ordertype;
} }
public boolean inMyorgans(final String organ){
return myorgans.contains(organ);
}
@Transient @Transient
public HashSet<String> getMyorgans() { public HashSet<String> getMyorgans() {
return myorgans; return myorgans;

View File

@ -0,0 +1,55 @@
/*
* 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.app.persistence.blob;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManagerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Blob;
@Component
@Transactional
public class JpaBlobHelper {
private final SessionFactory sessionFactory;
@Autowired
public JpaBlobHelper(EntityManagerFactory factory) {
if (factory.unwrap(SessionFactory.class) == null) {
throw new NullPointerException("factory is not a hibernate factory");
}
this.sessionFactory = factory.unwrap(SessionFactory.class);
}
public Blob createBlob(InputStream content, long size) {
return sessionFactory.getCurrentSession().getLobHelper().createBlob(content, size);
}
public Blob createBlobWithFile(final File file) throws FileNotFoundException {
return createBlob(new FileInputStream(file), file.length());
}
}

View File

@ -31,7 +31,7 @@ public abstract interface AgentServiceRepository
{ {
public abstract AgentService findByIdAndOrgi(String paramString , String orgi); public abstract AgentService findByIdAndOrgi(String paramString , String orgi);
public abstract List<AgentService> findByUseridAndOrgi(String paramString, String orgi); public abstract List<AgentService> findByUseridAndOrgiOrderByLogindateDesc(String paramString, String orgi);
public abstract Page<AgentService> findByOrgi(String orgi, Pageable paramPageable); public abstract Page<AgentService> findByOrgi(String orgi, Pageable paramPageable);

View File

@ -0,0 +1,23 @@
/*
* 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.app.persistence.repository;
import com.chatopera.cc.app.model.StreamingFile;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StreamingFileRepository extends JpaRepository<StreamingFile, String> {
}

View File

@ -91,20 +91,22 @@ public class CallOutPlanTask {
@Scheduled(fixedDelayString = "${cskefu.callout.watch.interval}") // 每分钟执行一次 @Scheduled(fixedDelayString = "${cskefu.callout.watch.interval}") // 每分钟执行一次
public void watch() { public void watch() {
logger.debug("[callout executor] check dialplan job running status ..."); if(MainContext.isEnableCalloutModule()){
// load all jobs logger.debug("[callout executor] check dialplan job running status ...");
List<CallOutDialplan> dps = callOutDialplanRes.findByStatusAndIsarchive(MainContext.CallOutDialplanStatusEnum.RUNNING.toString(), false); // load all jobs
for (CallOutDialplan dp : dps) { List<CallOutDialplan> dps = callOutDialplanRes.findByStatusAndIsarchive(MainContext.CallOutDialplanStatusEnum.RUNNING.toString(), false);
Long size = redisListOps.size(String.format(Constants.FS_DIALPLAN_TARGET, dp.getVoicechannel().getBaseURL(), dp.getId())); for (CallOutDialplan dp : dps) {
if (size > 0) { Long size = redisListOps.size(String.format(Constants.FS_DIALPLAN_TARGET, dp.getVoicechannel().getBaseURL(), dp.getId()));
logger.info("[callout executor] job [{}] is not done yet, remaining [{}]", dp.getName(), size); if (size > 0) {
} else { logger.info("[callout executor] job [{}] is not done yet, remaining [{}]", dp.getName(), size);
dp.setStatus(MainContext.CallOutDialplanStatusEnum.STOPPED.toString()); } else {
dp.setUpdatetime(new Date()); dp.setStatus(MainContext.CallOutDialplanStatusEnum.STOPPED.toString());
callOutDialplanRes.save(dp); dp.setUpdatetime(new Date());
callOutDialplanRes.save(dp);
// 删除状态成员 // 删除状态成员
delHashKey(String.format(Constants.FS_DIALPLAN_STATUS, dp.getVoicechannel().getBaseURL()), dp.getId()); delHashKey(String.format(Constants.FS_DIALPLAN_STATUS, dp.getVoicechannel().getBaseURL()), dp.getId());
}
} }
} }
} }

View File

@ -55,8 +55,6 @@ import java.util.List;
@Component @Component
public class CallOutWireTask implements MessageListener { public class CallOutWireTask implements MessageListener {
private static final Logger logger = LoggerFactory.getLogger(CallOutWireTask.class); private static final Logger logger = LoggerFactory.getLogger(CallOutWireTask.class);
private static final RedisSerializer<String> redisStringSerializer = new StringRedisSerializer();
@Autowired @Autowired
private CallOutDialplanRepository callOutDialplanRes; private CallOutDialplanRepository callOutDialplanRes;

View File

@ -0,0 +1,104 @@
/*
* 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.app.schedule;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.util.IMServiceUtils;
import com.chatopera.cc.util.Constants;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.*;
import java.util.Base64;
/**
* 坐席消息分发
*/
@Component
public class WebIMAgentDispatcher implements MessageListener {
private final static Logger logger = LoggerFactory.getLogger(WebIMAgentDispatcher.class);
private ListOperations<String, String> redisListOps;
private HashOperations<String, String, String> redisHashOps;
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private String redisPort;
@Value("${spring.redis.database}")
private String redisDB;
@Value("${application.node.id}")
private String appNodeId;
/**
* 使用StringRedisTemplate而不是RedisTemplate解决序列化问题
* https://stackoverflow.com/questions/13215024/weird-redis-key-with-spring-data-jedis
*/
@Autowired
private StringRedisTemplate redis;
@PostConstruct
private void init() {
redisListOps = redis.opsForList();
redisHashOps = redis.opsForHash();
}
/**
* Publish Message into Channel with redis PubSub
*
* @param j
*/
public void publish(JsonObject j) {
ChannelTopic ct = new ChannelTopic(String.format(Constants.INSTANT_MESSTRING_WEBIM_AGENT_PATTERN, appNodeId));
j.addProperty("node", appNodeId);
redis.convertAndSend(ct.getTopic(), j.toString());
}
@Override
public void onMessage(Message message, byte[] bytes) {
logger.debug("[instant messaging] onMessage {}", message);
String payload = new String(message.getBody());
JsonParser parser = new JsonParser();
JsonObject j = parser.parse(payload).getAsJsonObject();
logger.debug("[instant messaging] message body {}", j.toString());
try {
NettyClients.getInstance().sendAgentEventMessage(j.get("id").getAsString(),
j.get("event").getAsString(),
IMServiceUtils.deserialize(j.get("data").getAsString()));
} catch (Exception e) {
logger.error("onMessage", e);
}
}
}

View File

@ -0,0 +1,102 @@
/*
* 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.app.schedule;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.util.IMServiceUtils;
import com.chatopera.cc.util.Constants;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.*;
import java.util.Base64;
/**
* 访客消息分发
*/
@Component
public class WebIMOnlineUserDispatcher implements MessageListener {
private final static Logger logger = LoggerFactory.getLogger(WebIMOnlineUserDispatcher.class);
private ListOperations<String, String> redisListOps;
private HashOperations<String, String, String> redisHashOps;
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private String redisPort;
@Value("${spring.redis.database}")
private String redisDB;
@Value("${application.node.id}")
private String appNodeId;
/**
* 使用StringRedisTemplate而不是RedisTemplate解决序列化问题
* https://stackoverflow.com/questions/13215024/weird-redis-key-with-spring-data-jedis
*/
@Autowired
private StringRedisTemplate redis;
@PostConstruct
private void init() {
redisListOps = redis.opsForList();
redisHashOps = redis.opsForHash();
}
/**
* Publish Message into Channel with redis PubSub
*
* @param j
*/
public void publish(JsonObject j) {
ChannelTopic ct = new ChannelTopic(String.format(Constants.INSTANT_MESSTRING_WEBIM_ONLINE_USER_PATTERN, appNodeId));
j.addProperty("node", appNodeId);
redis.convertAndSend(ct.getTopic(), j.toString());
}
@Override
public void onMessage(Message message, byte[] bytes) {
logger.debug("[instant messaging] onMessage {}", message);
String payload = new String(message.getBody());
JsonParser parser = new JsonParser();
JsonObject j = parser.parse(payload).getAsJsonObject();
logger.debug("[instant messaging] message body {}", j.toString());
try {
NettyClients.getInstance().sendIMEventMessage(j.get("id").getAsString(),
j.get("event").getAsString(),
IMServiceUtils.deserialize(j.get("data").getAsString()));
} catch (Exception e) {
logger.error("onMessage", e);
}
}
}

View File

@ -15,25 +15,19 @@
*/ */
package com.chatopera.cc.app.schedule; package com.chatopera.cc.app.schedule;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist; import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.basic.MainUtils; import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.exchange.DataExchangeInterface;
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.impl.CallOutQuene; import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.persistence.repository.AgentUserTaskRepository;
import com.chatopera.cc.app.persistence.repository.JobDetailRepository;
import com.chatopera.cc.app.persistence.repository.OnlineUserRepository;
import com.chatopera.cc.util.OnlineUserUtils;
import com.chatopera.cc.app.im.router.OutMessageRouter;
import com.chatopera.cc.app.im.message.ChatMessage; import com.chatopera.cc.app.im.message.ChatMessage;
import com.chatopera.cc.app.im.router.OutMessageRouter;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.impl.CallOutQuene;
import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.exchange.DataExchangeInterface;
import com.chatopera.cc.util.OnlineUserUtils;
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -43,18 +37,10 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import com.chatopera.cc.app.persistence.repository.ChatMessageRepository; import java.util.ArrayList;
import com.chatopera.cc.app.persistence.repository.ConsultInviteRepository; import java.util.Collection;
import com.chatopera.cc.app.model.AgentStatus; import java.util.Date;
import com.chatopera.cc.app.model.AgentUser; import java.util.List;
import com.chatopera.cc.app.model.AgentUserTask;
import com.chatopera.cc.app.model.AiConfig;
import com.chatopera.cc.app.model.AiUser;
import com.chatopera.cc.app.model.CousultInvite;
import com.chatopera.cc.app.model.JobDetail;
import com.chatopera.cc.app.model.MessageOutContent;
import com.chatopera.cc.app.model.OnlineUser;
import com.chatopera.cc.app.model.SessionConfig;
@Configuration @Configuration
@EnableScheduling @EnableScheduling
@ -72,7 +58,7 @@ public class WebIMTask {
@Autowired @Autowired
private TaskExecutor webimTaskExecutor; private TaskExecutor webimTaskExecutor;
@Scheduled(fixedDelay = 5000) // 每5秒执行一次 @Scheduled(fixedDelay = 5000) // 处理超时消息每5秒执行一次
public void task() { public void task() {
List<SessionConfig> sessionConfigList = AutomaticServiceDist.initSessionConfigList(); List<SessionConfig> sessionConfigList = AutomaticServiceDist.initSessionConfigList();
if (sessionConfigList != null && sessionConfigList.size() > 0 && MainContext.getContext() != null) { if (sessionConfigList != null && sessionConfigList.size() > 0 && MainContext.getContext() != null) {
@ -255,7 +241,7 @@ public class WebIMTask {
private void processMessage(SessionConfig sessionConfig, String message, String servicename, AgentUser agentUser, AgentStatus agentStatus, AgentUserTask task) { private void processMessage(SessionConfig sessionConfig, String message, String servicename, AgentUser agentUser, AgentStatus agentStatus, AgentUserTask task) {
MessageOutContent outMessage = new MessageOutContent(); MessageOutContent outMessage = new MessageOutContent();
if (!StringUtils.isBlank(message)) { if (StringUtils.isNotBlank(message)) {
outMessage.setMessage(message); outMessage.setMessage(message);
outMessage.setMessageType(MainContext.MediaTypeEnum.TEXT.toString()); outMessage.setMessageType(MainContext.MediaTypeEnum.TEXT.toString());
outMessage.setCalltype(MainContext.CallTypeEnum.OUT.toString()); outMessage.setCalltype(MainContext.CallTypeEnum.OUT.toString());
@ -279,7 +265,7 @@ public class WebIMTask {
data.setAgentserviceid(agentUser.getAgentserviceid()); data.setAgentserviceid(agentUser.getAgentserviceid());
data.setCalltype(MainContext.CallTypeEnum.OUT.toString()); data.setCalltype(MainContext.CallTypeEnum.OUT.toString());
if (!StringUtils.isBlank(agentUser.getAgentno())) { if (StringUtils.isNotBlank(agentUser.getAgentno())) {
data.setTouser(agentUser.getUserid()); data.setTouser(agentUser.getUserid());
} }
data.setChannel(agentUser.getChannel()); data.setChannel(agentUser.getChannel());
@ -304,11 +290,12 @@ public class WebIMTask {
*/ */
MainContext.getContext().getBean(ChatMessageRepository.class).save(data); MainContext.getContext().getBean(ChatMessageRepository.class).save(data);
if (agentUser != null && !StringUtils.isBlank(agentUser.getAgentno())) { //同时发送消息给双方 // 同时发送消息给双方
NettyClients.getInstance().sendAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.MESSAGE.toString(), data); if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentno())) {
NettyClients.getInstance().publishAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.MESSAGE.toString(), data);
} }
if (!StringUtils.isBlank(data.getTouser())) { if (StringUtils.isNotBlank(data.getTouser())) {
OutMessageRouter router = null; OutMessageRouter router = null;
router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()); router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel());
if (router != null) { if (router != null) {

View File

@ -17,9 +17,12 @@ package com.chatopera.cc.concurrent.chatbot;
import com.chatopera.cc.concurrent.user.UserDataEvent; import com.chatopera.cc.concurrent.user.UserDataEvent;
import com.lmax.disruptor.RingBuffer; import com.lmax.disruptor.RingBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public class ChatbotEventProducer { public class ChatbotEventProducer {
private final static Logger logger = LoggerFactory.getLogger(ChatbotEventProducer.class);
private final RingBuffer<UserDataEvent> ringBuffer; private final RingBuffer<UserDataEvent> ringBuffer;
public ChatbotEventProducer(RingBuffer<UserDataEvent> ringBuffer) public ChatbotEventProducer(RingBuffer<UserDataEvent> ringBuffer)

View File

@ -16,6 +16,7 @@
package com.chatopera.cc.util; package com.chatopera.cc.util;
import com.chatopera.cc.app.basic.MainContext; import com.chatopera.cc.app.basic.MainContext;
import org.apache.commons.lang.StringUtils;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -30,6 +31,14 @@ public class Constants {
public final static String IM_MESSAGE_TYPE_MESSAGE = "message"; public final static String IM_MESSAGE_TYPE_MESSAGE = "message";
public final static String CHATBOT_EVENT_TYPE_CHAT = "chat"; public final static String CHATBOT_EVENT_TYPE_CHAT = "chat";
/**
* Modules
*/
public final static String CSKEFU_MODULE_CALLOUT = "sales";
public final static String CSKEFU_MODULE_CHATBOT = "chatbot";
public final static String CSKEFU_MODULE_CONTACTS = "contacts";
/** /**
* Formatter * Formatter
*/ */
@ -38,6 +47,21 @@ public class Constants {
public final static SimpleDateFormat DISPLAY_DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public final static SimpleDateFormat DISPLAY_DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public final static DecimalFormat DURATION_MINS_FORMATTER = new DecimalFormat("0.00"); public final static DecimalFormat DURATION_MINS_FORMATTER = new DecimalFormat("0.00");
/**
* Instant Messaging Events
*/
public final static String INSTANT_MESSTRING_WEBIM_AGENT_PATTERN = "im:webim:agent:%s:events";
public final static String INSTANT_MESSAGING_WEBIM_AGENT_CHANNEL = String.format(INSTANT_MESSTRING_WEBIM_AGENT_PATTERN, "*");
public final static String INSTANT_MESSTRING_WEBIM_ONLINE_USER_PATTERN = "im:webim:onlineuser:%s:events";
public final static String INSTANT_MESSAGING_WEBIM_ONLINE_USER_CHANNEL = String.format(INSTANT_MESSTRING_WEBIM_ONLINE_USER_PATTERN, "*");
/**
* Attachment File Type
*/
public final static String ATTACHMENT_TYPE_IMAGE = "image";
public final static String ATTACHMENT_TYPE_FILE = "file";
/** /**
* FreeSwitch Communication * FreeSwitch Communication
*/ */

View File

@ -908,6 +908,7 @@ public class OnlineUserUtils {
if (!StringUtils.isBlank(ip)) { if (!StringUtils.isBlank(ip)) {
ipdata = IPTools.getInstance().findGeography(ip); ipdata = IPTools.getInstance().findGeography(ip);
} }
if (StringUtils.isBlank(nickname)) { if (StringUtils.isBlank(nickname)) {
nickname = "Guest_" + userid; nickname = "Guest_" + userid;
} }

View File

@ -0,0 +1,53 @@
/*
* 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.util;
import java.util.Arrays;
import java.util.HashMap;
public class StreamingFileUtils {
private static StreamingFileUtils singleton = new StreamingFileUtils();
private final HashMap<String, String> extMap = new HashMap<String, String>();
private StreamingFileUtils() {
extMap.put(Constants.ATTACHMENT_TYPE_IMAGE, "gif,jpg,jpeg,png,bmp");
extMap.put(Constants.ATTACHMENT_TYPE_FILE, "pdf,doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2,c66");
extMap.put("flash", "swf,flv");
extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
}
public static StreamingFileUtils getInstance() {
return singleton;
}
/**
* Validate file format
* @param type
* @param filename
* @return
*/
public String validate(final String type, final String filename) {
final String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
if (!Arrays.<String>asList(extMap.get(type).split(",")).contains(ext)) {
return "上传文件扩展名是不允许的扩展名。只允许" + extMap.get(type) + "格式。";
}
return null;
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.util;
import org.apache.commons.lang.StringUtils;
public class SystemEnvHelper {
/**
* 分析是否加载模块在变量为不存在或变量值为true的情况下加载
* 也就是说该变量值不为空或为true时时加载
* @param environmentVariable
* @return
*/
public static boolean parseModuleFlag(final String environmentVariable){
String val = System.getenv(environmentVariable);
return StringUtils.isBlank(val) || StringUtils.equalsIgnoreCase(val, "true");
}
}

View File

@ -15,10 +15,11 @@
# https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/ # https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/
# https://stackoverflow.com/questions/35531661/using-env-variable-in-spring-boots-application-properties # https://stackoverflow.com/questions/35531661/using-env-variable-in-spring-boots-application-properties
# 证书相关信息 # 证书相关信息
license.client.id=bxzq license.client.id=cskefu
application.version=1.0.0 application.version=3.9.0
# 在集群状态下每个Node都有自己唯一的ID
application.node.id=localhost
# security # security
management.security.enabled=false management.security.enabled=false
@ -30,11 +31,6 @@ server.log.path=../logs
server.log.level=INFO server.log.level=INFO
web.upload-path=../data web.upload-path=../data
# multi part
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=50MB
# IM Server # IM Server
uk.im.server.port=8036 uk.im.server.port=8036
uk.im.server.host=localhost uk.im.server.host=localhost
@ -132,7 +128,7 @@ spring.redis.port=6379
# Redis服务器连接密码默认为空 # Redis服务器连接密码默认为空
spring.redis.password= spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制) # 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=20 spring.redis.pool.max-active=-1
# 连接池最大阻塞等待时间(使用负值表示没有限制) # 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1 spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接 # 连接池中的最大空闲连接
@ -152,4 +148,12 @@ cskefu.callout.watch.interval=60000
############################################## ##############################################
storage.minio.url=http://192.168.2.217:9000 storage.minio.url=http://192.168.2.217:9000
storage.minio.access_key=M19Q8YJ8FzLyQtST7r0 storage.minio.access_key=M19Q8YJ8FzLyQtST7r0
storage.minio.secret_key=KHv6qjddHD4HfR1m7fjY7HglSO1WOSzIeTERRUUc storage.minio.secret_key=KHv6qjddHD4HfR1m7fjY7HglSO1WOSzIeTERRUUc
# multi part
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=15MB
spring.servlet.multipart.max-request-size=15MB
# MySQL Blob
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

View File

@ -24,7 +24,7 @@
xmlns="http://www.hazelcast.com/schema/config" xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<group> <group>
<name>CSKeFu_U0C</name> <name>CSKeFu_IMDG</name>
<password>CSKeFu-1234567890</password> <password>CSKeFu-1234567890</password>
</group> </group>
<network> <network>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="zh">
<!-- 本页只用于测试/演示目的 -->
<head>
<!-- META -->
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>春松客服</title>
<!-- 春松客服访客端演示程序 https://github.com/chatopera/cosin/wiki/春松客服访客端演示 -->
<!-- 系统:客服接入:网站列表:创建新网站 网站地址(localhost) -->
<script defer="true" src="/im/104eac.html"></script>
<style>
tr.top td { border-top: thin solid black; }
tr.bottom td { border-bottom: thin solid black; }
tr.row td:first-child { border-left: thin solid black; }
tr.row td:last-child { border-right: thin solid black; }
</style>
</head>
<body>
<h2>春松客服演示客户端</h2>
<h3>设置网站渠道</h3>
以管理员身份 <a href="/" target="_blank">登录</a>,导航【系统-客服接入-网站列表-创建新网站】,按照如下内容设置网站渠道。
<table style="width:100%">
<tr class="top bottom row">
<th>设置</th>
<th></th>
<th>描述</th>
</tr>
<tr class="top bottom row">
<td>网站名称</td>
<td>localhost</td>
<td>任意字符串</td>
</tr>
<tr class="top bottom row">
<td>网站地址</td>
<td>localhost</td>
<td>网站的域名或IP端口选填比如 localhost:8080</td>
</tr>
</table>
然后,刷新本页面,就可以在右下角看到【在线客服】聊天控件,通过<a href="https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%E8%AE%BF%E5%AE%A2%E7%AB%AF%E6%BC%94%E7%A4%BA" target="_blank">详细文档</a>进一步了解在任意网站集成客服控件的方法。
</body>
</html>

View File

@ -32,7 +32,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">欢迎提示语:</label> <label class="layui-form-label">欢迎提示语:</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<textarea id="welcomemsg" style="width:450px;" name="welcomemsg" class="layui-textarea">${extention.welcomemsg!"您好,欢迎致电客服智能IVR演示系统这里是电话机器人演示系统请说要进入的测试流程比如客服系统"}</textarea> <textarea id="welcomemsg" style="width:450px;" name="welcomemsg" class="layui-textarea">${extention.welcomemsg!"您好,欢迎致电春松客服智能IVR演示系统这里是电话机器人演示系统请说要进入的测试流程比如客服系统"}</textarea>
</div> </div>
</div> </div>

View File

@ -32,17 +32,15 @@
<#list snsAccountList.content as snsAccount> <#list snsAccountList.content as snsAccount>
<tr> <tr>
<td> <td>
<a href="/admin/callout/index.html?snsid=${snsAccount.snsid!''}"> ${snsAccount.name!''}
${snsAccount.name!''}
</a>
</td> </td>
<td>${snsAccount.baseURL!''}</td> <td>${snsAccount.baseURL!''}</td>
<td>${snsAccount.createtime?string("yyyy-MM-dd HH:mm:ss")}</td> <td>${snsAccount.createtime?string("yyyy-MM-dd HH:mm:ss")}</td>
<td style="white-space:nowrap;" nowrap="nowrap"> <td style="white-space:nowrap;" nowrap="nowrap">
<a href="/admin/callout/edit.html?id=${snsAccount.id!''}" data-toggle="ajax" data-width="550" data-height="300" data-title="编辑"> <!--<a href="/admin/callout/edit.html?id=${snsAccount.id!''}" data-toggle="ajax" data-width="550" data-height="300" data-title="编辑">-->
<i class="layui-icon">&#xe642;</i> <!--<i class="layui-icon">&#xe642;</i>-->
编辑 <!--编辑-->
</a> <!--</a>-->
<#if !(snsAccount.usertype?? && snsAccount.usertype == "0") && snsAccount.datastatus != true > <#if !(snsAccount.usertype?? && snsAccount.usertype == "0") && snsAccount.datastatus != true >
<a href="/admin/callout/delete.html?id=${snsAccount.id!''}" style="margin-left:10px;" data-toggle="tip" <#if secret?? && secret.enable == true>data-confirm="请输入二次安全验证密码"</#if> title="删除语音需要进行二次密码验证,请确认是否删除?" > <a href="/admin/callout/delete.html?id=${snsAccount.id!''}" style="margin-left:10px;" data-toggle="tip" <#if secret?? && secret.enable == true>data-confirm="请输入二次安全验证密码"</#if> title="删除语音需要进行二次密码验证,请确认是否删除?" >
<i class="layui-icon" style="color:red;">&#x1006;</i> <i class="layui-icon" style="color:red;">&#x1006;</i>

View File

@ -33,14 +33,16 @@
<#list snsAccountList.content as snsAccount> <#list snsAccountList.content as snsAccount>
<tr> <tr>
<td> <td>
<a href="/admin/webim/index.html?snsid=${snsAccount.snsid!''}"> ${snsAccount.name!''}
${snsAccount.name!''}
</a>
</td> </td>
<td>${snsAccount.baseURL!''}</td> <td>${snsAccount.baseURL!''}</td>
<td>${snsAccount.snsid!''}</td> <td>${snsAccount.snsid!''}</td>
<td>${snsAccount.createtime?string("yyyy-MM-dd HH:mm:ss")}</td> <td>${snsAccount.createtime?string("yyyy-MM-dd HH:mm:ss")}</td>
<td style="white-space:nowrap;" nowrap="nowrap"> <td style="white-space:nowrap;" nowrap="nowrap">
<a href="/admin/webim/index.html?snsid=${snsAccount.snsid!''}">
<i class="layui-icon">&#xe632;</i>
接入
</a>
<a href="/admin/im/edit.html?id=${snsAccount.id!''}" data-toggle="ajax" data-width="550" data-height="300" data-title="编辑网站"> <a href="/admin/im/edit.html?id=${snsAccount.id!''}" data-toggle="ajax" data-width="550" data-height="300" data-title="编辑网站">
<i class="layui-icon">&#xe642;</i> <i class="layui-icon">&#xe642;</i>
编辑 编辑

View File

@ -11,11 +11,11 @@
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">1、系统颜色风格选择</div> <div class="ukefu-webim-tl" style="clear:both;">系统颜色风格选择</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
<p>客服系统界面颜色风格</p> <p>春松客服系统界面颜色风格</p>
<p style="color:#888888;font-size:13px;margin-top:10px;">默认的配色是绿色,选择颜色可以在右侧预览风格,点击保存即可生效</p> <p style="color:#888888;font-size:13px;margin-top:10px;">默认的配色是绿色,选择颜色可以在右侧预览风格,点击保存即可生效</p>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
@ -29,8 +29,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">2、请填写服务器的访问地址</div> <div class="ukefu-webim-tl" style="clear:both;">请填写服务器的访问地址</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -39,7 +39,7 @@
</div> </div>
<div class="col-lg-4" style="text-align:right;"> <div class="col-lg-4" style="text-align:right;">
<div class="layui-input-block"> <div class="layui-input-block">
<input type="text" name="iconstr" value="<#if systemConfig.iconstr?? && systemConfig.iconstr!= ''>${systemConfig.iconstr!''}<#else>www.chatopera.com</#if>" autocomplete="off" class="layui-input"> <input type="text" name="iconstr" value="<#if systemConfig.iconstr?? && systemConfig.iconstr!= ''>${systemConfig.iconstr!''}</#if>" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
</div> </div>
@ -47,7 +47,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">3、产品登录界面和后台管理界面标题</div> <div class="ukefu-webim-tl" style="clear:both;">产品登录界面和后台管理界面标题</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -62,7 +62,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">4、登录页欢迎Logo图片</div> <div class="ukefu-webim-tl" style="clear:both;">登录页欢迎Logo图片</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -87,7 +87,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">5、产品后台管理界面Logo图片</div> <div class="ukefu-webim-tl" style="clear:both;">产品后台管理界面Logo图片</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -112,7 +112,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">6、产品标题栏缩略小图</div> <div class="ukefu-webim-tl" style="clear:both;">产品标题栏缩略小图</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -137,7 +137,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">7、重启或停止对话服务</div> <div class="ukefu-webim-tl" style="clear:both;">重启或停止对话服务</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -153,8 +153,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">8、启用EntIM内部IM功能</div> <div class="ukefu-webim-tl" style="clear:both;">启用EntIM内部IM功能</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -165,7 +165,8 @@
<#if entim?? && entim == true> <#if entim?? && entim == true>
<a href="/admin/config/stopentim.html" data-toggle="tip" title="请确认是否关闭EntIM功能" class="layui-btn layui-btn-small layui-btn-danger">关闭EntIM功能</a> <a href="/admin/config/stopentim.html" data-toggle="tip" title="请确认是否关闭EntIM功能" class="layui-btn layui-btn-small layui-btn-danger">关闭EntIM功能</a>
<#else> <#else>
<a href="/admin/config/startentim.html" data-toggle="tip" title="启用EntIM功能" class="layui-btn layui-btn-small">启用EntIM功能</a> <!-- <a href="/admin/config/startentim.html" data-toggle="tip" title="启用EntIM功能" class="layui-btn layui-btn-small">启用EntIM功能</a> -->
<a href="" data-toggle="tip" title="启用EntIM功能" class="layui-btn layui-btn-small">启用EntIM功能</a>
</#if> </#if>
</div> </div>
</div> </div>
@ -173,12 +174,12 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">9、启用权限数据采集功能功能</div> <div class="ukefu-webim-tl" style="clear:both;">启用权限数据采集功能功能</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
<p>启用权限数据采集功能后,会进入数据采集模式,当前状态:<#if infoace?? && infoace == true><small class="ukefu-label theme4">已启用</small><#else><small class="ukefu-label theme4" style="background-color:#FF5722;">已关闭</small></#if></p> <p>启用权限数据采集功能后,会进入数据采集模式,当前状态:<#if infoace?? && infoace == true><small class="ukefu-label theme4">已启用</small><#else><small class="ukefu-label theme4" style="background-color:#FF5722;">已关闭</small></#if></p>
<p style="color:#888888;font-size:13px;margin-top:10px;">启用后,在客服界面上的任何链接点击操作都会触发数据收集功能</p> <p style="color:#888888;font-size:13px;margin-top:10px;">启用后,在春松客服界面上的任何链接点击操作都会触发数据收集功能</p>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<#if infoace?? && infoace == true> <#if infoace?? && infoace == true>
@ -191,8 +192,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">10、停止优客服系统</div> <div class="ukefu-webim-tl" style="clear:both;">停止春松客服系统</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -207,7 +208,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">11、修改微信接收消息的日志级别</div> <div class="ukefu-webim-tl" style="clear:both;">修改微信接收消息的日志级别</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -223,8 +224,8 @@
</div> </div>
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">12、启用服务SSL安全访问</div> <div class="ukefu-webim-tl" style="clear:both;">启用服务SSL安全访问</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -265,8 +266,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">13、启用涉及重要操作的二次验证密码</div> <div class="ukefu-webim-tl" style="clear:both;">启用涉及重要操作的二次验证密码</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -309,7 +310,7 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">14、百度地图的Key代码AK</div> <div class="ukefu-webim-tl" style="clear:both;">百度地图的Key代码AK</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -323,8 +324,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">15、工单系统布局方式</div> <div class="ukefu-webim-tl" style="clear:both;">工单系统布局方式</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -339,7 +340,7 @@
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop">
<div class="ukefu-webim-tl" style="clear:both;">16、启用权限控制</div> <div class="ukefu-webim-tl" style="clear:both;">启用权限控制</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -353,8 +354,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">17、启用语音平台模板配置</div> <div class="ukefu-webim-tl" style="clear:both;">启用语音平台模板配置</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -492,8 +493,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">18、启用工单系统的邮件通知</div> <div class="ukefu-webim-tl" style="clear:both;">启用工单系统的邮件通知</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">
@ -627,8 +628,8 @@
</div> </div>
</div> </div>
<div class="ukefu-webim-prop"> <div class="ukefu-webim-prop" hidden>
<div class="ukefu-webim-tl" style="clear:both;">19、启用多${systemConfig.namealias!'租户'}管理模式</div> <div class="ukefu-webim-tl" style="clear:both;">启用多${systemConfig.namealias!'租户'}管理模式</div>
<div class="box-item"> <div class="box-item">
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-8">

View File

@ -24,9 +24,11 @@
<dd <#if subtype?? && (maintype == 'webim' || subtype == 'im')>class="layui-this"</#if>> <dd <#if subtype?? && (maintype == 'webim' || subtype == 'im')>class="layui-this"</#if>>
<a href="/admin/im/index.html">网站列表</a> <a href="/admin/im/index.html">网站列表</a>
</dd> </dd>
<#if models?? && models["sales"]?? && models["sales"] == true>
<dd <#if subtype?? && (maintype == 'callout' || subtype == 'channel')>class="layui-this"</#if>> <dd <#if subtype?? && (maintype == 'callout' || subtype == 'channel')>class="layui-this"</#if>>
<a href="/admin/callout/index.html">语音渠道</a> <a href="/admin/callout/index.html">语音渠道</a>
</dd> </dd>
</#if>
</dl> </dl>
</li> </li>

View File

@ -9,6 +9,7 @@
</span> </span>
</h1> </h1>
<div class="row" style="padding:5px;"> <div class="row" style="padding:5px;">
<p style="color:red">提示:除管理员外,账号必须在【组织结构】中关联一个部门,必须在【系统角色】中关联一个角色,才可以使用资源。设置后,该账号需重新登系统才能生效。</p>
<div class="col-lg-12"> <div class="col-lg-12">
<table class="layui-table" lay-skin="line"> <table class="layui-table" lay-skin="line">
<colgroup> <colgroup>

View File

@ -30,6 +30,11 @@
<#if inviteData??> <#if inviteData??>
<input type="hidden" name="id" value="${inviteData.id!''}"> <input type="hidden" name="id" value="${inviteData.id!''}">
<input type="hidden" name="snsaccountid" value="${inviteData.snsaccountid!''}"> <input type="hidden" name="snsaccountid" value="${inviteData.snsaccountid!''}">
<input type="hidden" name="ai" value="${inviteData.ai!''}">
<input type="hidden" name="aisuccesstip" value="${inviteData.aisuccesstip!''}">
<input type="hidden" name="aifirst" value="${inviteData.aifirst!''}">
<input type="hidden" name="ainame" value="${inviteData.ainame!''}">
<input type="hidden" name="aiid" value="${inviteData.aiid!''}">
</#if> </#if>
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">

View File

@ -30,6 +30,11 @@
<#if inviteData??> <#if inviteData??>
<input type="hidden" name="id" value="${inviteData.id!''}"> <input type="hidden" name="id" value="${inviteData.id!''}">
<input type="hidden" name="snsaccountid" value="${inviteData.snsaccountid!''}"> <input type="hidden" name="snsaccountid" value="${inviteData.snsaccountid!''}">
<input type="hidden" name="ai" value="${inviteData.ai!''}">
<input type="hidden" name="aisuccesstip" value="${inviteData.aisuccesstip!''}">
<input type="hidden" name="aifirst" value="${inviteData.aifirst!''}">
<input type="hidden" name="ainame" value="${inviteData.ainame!''}">
<input type="hidden" name="aiid" value="${inviteData.aiid!''}">
</#if> </#if>
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">

View File

@ -30,6 +30,11 @@
<#if inviteData??> <#if inviteData??>
<input type="hidden" name="id" value="${inviteData.id!''}"> <input type="hidden" name="id" value="${inviteData.id!''}">
<input type="hidden" name="snsaccountid" value="${inviteData.snsaccountid!''}"> <input type="hidden" name="snsaccountid" value="${inviteData.snsaccountid!''}">
<input type="hidden" name="ai" value="${inviteData.ai!''}">
<input type="hidden" name="aisuccesstip" value="${inviteData.aisuccesstip!''}">
<input type="hidden" name="aifirst" value="${inviteData.aifirst!''}">
<input type="hidden" name="ainame" value="${inviteData.ainame!''}">
<input type="hidden" name="aiid" value="${inviteData.aiid!''}">
</#if> </#if>
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
@ -50,7 +55,7 @@
<p style="color:#888888;font-size:13px;margin-top:10px;">默认显示信息 企业名称</p> <p style="color:#888888;font-size:13px;margin-top:10px;">默认显示信息 企业名称</p>
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<input type="text" name="dialog_name" value="${inviteData.dialog_name!'客服'}" autocomplete="off" class="layui-input" oninput="$('#dialog_name').text($(this).val())" onchange="$('#dialog_name').text($(this).val())"> <input type="text" name="dialog_name" value="${inviteData.dialog_name!'春松客服'}" autocomplete="off" class="layui-input" oninput="$('#dialog_name').text($(this).val())" onchange="$('#dialog_name').text($(this).val())">
</div> </div>
</div> </div>
</div> </div>
@ -205,7 +210,7 @@
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<div class="layui-input-block"> <div class="layui-input-block">
<input type="text" name="consult_skill_title" value="${inviteData.consult_skill_title!'客服'}" autocomplete="off" class="layui-input"> <input type="text" name="consult_skill_title" value="${inviteData.consult_skill_title!'春松客服'}" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
</div> </div>
@ -472,7 +477,7 @@
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<div class="layui-input-block"> <div class="layui-input-block">
<input type="text" name="aisuccesstip" maxlength="100" value="${inviteData.aisuccesstip!'欢迎使用客服小E我来帮您解答问题'}" autocomplete="off" class="layui-input"> <input type="text" name="aisuccesstip" maxlength="100" value="${inviteData.aisuccesstip!'欢迎使用春松客服小E我来帮您解答问题'}" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
</div> </div>
@ -584,16 +589,16 @@
<div class="ukefu-im-profile" style="width:130px;font-size:12px;"> <div class="ukefu-im-profile" style="width:130px;font-size:12px;">
<div class="ukefu-profile-title" style="clear:both;">信息提示</div> <div class="ukefu-profile-title" style="clear:both;">信息提示</div>
<div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;"> <div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;">
名称:<label id="dialog_name">${inviteData.dialog_name!'客服'}</label> 名称:<label id="dialog_name">${inviteData.dialog_name!'春松客服'}</label>
</div> </div>
<div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;"> <div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;">
地址:<label id="dialog_address">${inviteData.dialog_address!'广东深圳'}</label> 地址:<label id="dialog_address">${inviteData.dialog_address!'北京'}</label>
</div> </div>
<div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;"> <div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;">
电话:<label id="dialog_phone">${inviteData.dialog_phone!'0755-xxxxxxxx'}</label> 电话:<label id="dialog_phone">${inviteData.dialog_phone!'185-1935-7507'}</label>
</div> </div>
<div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;"> <div class="box-item" style="padding:5px;white-space: nowrap;text-overflow: ellipsis;">
邮件:<label id="dialog_mail">${inviteData.dialog_mail!'kefu@ukewo.cn'}</label> 邮件:<label id="dialog_mail">${inviteData.dialog_mail!'info@chatopera.com'}</label>
</div> </div>
<div class="box-item" style="padding:5px;text-indent: 25px;line-height:25px;"> <div class="box-item" style="padding:5px;text-indent: 25px;line-height:25px;">
<label id="dialog_introduction">${inviteData.dialog_introduction!'客服公告信息,内容在控制台设置。'}</label> <label id="dialog_introduction">${inviteData.dialog_introduction!'客服公告信息,内容在控制台设置。'}</label>

View File

@ -2,14 +2,16 @@
<li class="ukefu-channel-tip"> <li class="ukefu-channel-tip">
访问渠道:<i class="layui-icon">&#xe63a;</i> 访问渠道:<i class="layui-icon">&#xe63a;</i>
在线客服 在线客服
<#if summary??>
<div class="ukefu-summary">
<a href="/agent/summary.html?userid=${curagentuser.userid!''}&agentserviceid=${curagentuser.agentserviceid!''}&agentuserid=${curagentuser.id}" data-toggle="ajax" data-width="950" data-height="450" title="记录服务小结">
<i class="layui-icon">&#xe618;</i> 已记录服务小结
</a>
</div>
</#if>
</li> </li>
<li class="ukefu-channel-tip">
服务小结: <#if summary??>
<i class="layui-icon">&#xe618;</i>已记录
<#else>
<i class="layui-icon">&#xe64d;</i>未记录
</#if>
</li>
<#if snsAccount??> <#if snsAccount??>
<li class="ukefu-channel-tip"> <li class="ukefu-channel-tip">
接入网站:${snsAccount.name!''}${snsAccount.baseURL!''} 接入网站:${snsAccount.name!''}${snsAccount.baseURL!''}

View File

@ -5,14 +5,16 @@
<li class="ukefu-channel-tip"> <li class="ukefu-channel-tip">
访问渠道:<i class="kfont">&#xe64d;</i> 访问渠道:<i class="kfont">&#xe64d;</i>
微信 微信
<#if summary??>
<div class="ukefu-summary">
<a href="/agent/summary.html?userid=${curagentuser.userid!''}&agentserviceid=${curagentuser.agentserviceid!''}&agentuserid=${curagentuser.id}" data-toggle="ajax" data-width="950" data-height="450" title="记录服务小结">
<i class="layui-icon">&#xe618;</i> 已记录服务小结
</a>
</div>
</#if>
</li> </li>
<li class="ukefu-channel-tip">
服务小结: <#if summary??>
<i class="layui-icon">&#xe618;</i>已记录
<#else>
<i class="layui-icon">&#xe64d;</i>未记录
</#if>
</li>
<#if snsAccount??> <#if snsAccount??>
<li class="ukefu-channel-tip"> <li class="ukefu-channel-tip">
公众号:${snsAccount.name} 公众号:${snsAccount.name}

View File

@ -9,7 +9,7 @@
<#if contacts.gender?? && contacts.gender == '-1'>未知</#if> <#if contacts.gender?? && contacts.gender == '-1'>未知</#if>
</li> </li>
<li> <li>
生日:${contacts.birthday!''} 生日:${contacts.cusbirthday!''}
</li> </li>
<li> <li>
电话:<span class="ukefu-phone-number">${contacts.phone!''}</span> 电话:<span class="ukefu-phone-number">${contacts.phone!''}</span>

View File

@ -8,7 +8,7 @@
<h1 class="site-h1"> <h1 class="site-h1">
<#if curagentuser??>${curagentuser.username!''}${curagentuser.region!''} <#if curagentuser??>${curagentuser.username!''}${curagentuser.region!''}
<div style="float:right;" class="ukefu-service-btn"> <div style="float:right;" class="ukefu-service-btn">
<a href="/agent/summary.html?userid=${curagentuser.userid!''}&agentserviceid=${curagentuser.agentserviceid!''}&agentuserid=${curagentuser.id}" data-toggle="ajax" data-width="950" data-height="450" title="记录服务小结"><button class="layui-btn layui-btn-small"><i class="kfont">&#xe65c;</i> 服务小结</button></a> <a href="/agent/summary.html?userid=${curagentuser.userid!''}&agentserviceid=${curagentuser.agentserviceid!''}&agentuserid=${curagentuser.id}&channel=${curagentuser.channel}" data-toggle="ajax" data-width="950" data-height="450" title="记录服务小结"><button class="layui-btn layui-btn-small"><i class="kfont">&#xe65c;</i> 服务小结</button></a>
<a href="/agent/transfer.html?userid=${curagentuser.userid!''}&agentserviceid=${curagentuser.agentserviceid!''}&agentuserid=${curagentuser.id}" data-toggle="ajax" data-width="950" data-height="550" title="选择转接对象"><button class="layui-btn layui-btn-small"><i class="kfont">&#xe7be;</i> 转接坐席</button></a> <a href="/agent/transfer.html?userid=${curagentuser.userid!''}&agentserviceid=${curagentuser.agentserviceid!''}&agentuserid=${curagentuser.id}" data-toggle="ajax" data-width="950" data-height="550" title="选择转接对象"><button class="layui-btn layui-btn-small"><i class="kfont">&#xe7be;</i> 转接坐席</button></a>
<a href="/agent/end.html?userid=${curagentuser.id!''}" data-toggle="tip" data-title="请确认是否关闭和用户“${curagentuser.username!''}”的对话?"><button class="layui-btn layui-btn-small layui-btn-danger"><i class="kfont">&#xe621;</i> 结束对话</button></a> <a href="/agent/end.html?userid=${curagentuser.id!''}" data-toggle="tip" data-title="请确认是否关闭和用户“${curagentuser.username!''}”的对话?"><button class="layui-btn layui-btn-small layui-btn-danger"><i class="kfont">&#xe621;</i> 结束对话</button></a>
</div> </div>

View File

@ -35,7 +35,7 @@
//创建新的图片对象 //创建新的图片对象
var img = new Image(); var img = new Image();
//指定图片的URL //指定图片的URL
img.src = "/res/image.html?id=upload/${chatMessage.attachmentid!''}_cooperation"; img.src = "/res/image.html?id=${chatMessage.attachmentid!''}&cooperation=true&original=true";
//浏览器加载图片完毕后再绘制图片 //浏览器加载图片完毕后再绘制图片
img.onload = function(){ img.onload = function(){
//以Canvas画布上的坐标(10,10)为起始点,绘制图像 //以Canvas画布上的坐标(10,10)为起始点,绘制图像
@ -49,7 +49,7 @@
<div class='ukefu-preview-image scrawl-main' id="scrawl-main"> <div class='ukefu-preview-image scrawl-main' id="scrawl-main">
<div class='ukefu-image-content hot'> <div class='ukefu-image-content hot'>
<div class='ukefu-image-canvas' id='ukefu-image-content'> <div class='ukefu-image-canvas' id='ukefu-image-content'>
<img id="ukefu_img_ctx" src='${chatMessage.message!''}_original'> <img id="ukefu_img_ctx" src='${chatMessage.message!''}&original=true'>
</div> </div>
<div class='drawBoard'> <div class='drawBoard'>
<canvas id="canvas-borad" class="brushBorad">你的浏览器不支持 canvas 绘图</canvas> <canvas id="canvas-borad" class="brushBorad">你的浏览器不支持 canvas 绘图</canvas>

View File

@ -5,6 +5,7 @@
<input type="hidden" name="userid" value="${userid!''}"> <input type="hidden" name="userid" value="${userid!''}">
<input type="hidden" name="agentserviceid" value="${agentserviceid!''}"> <input type="hidden" name="agentserviceid" value="${agentserviceid!''}">
<input type="hidden" name="agentuserid" value="${agentuserid!''}"> <input type="hidden" name="agentuserid" value="${agentuserid!''}">
<input type="hidden" name="channel" value="${channel!''}">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-inline"> <div class="layui-inline">

View File

@ -43,9 +43,9 @@
<label class="layui-form-label">笔记分类:</label> <label class="layui-form-label">笔记分类:</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<select id="notesCategory" name="notesCategory" lay-filter="category" required lay-verify="required" style="display: inline"> <select id="notesCategory" name="notesCategory" lay-filter="category" required lay-verify="required" style="display: inline">
<option value="webim">网页</option>
<option value="callout">外呼</option> <option value="callout">外呼</option>
<option value="callin">呼入</option> <option value="callin">呼入</option>
<option value="webim">网页</option>
</select> </select>
</div> </div>
</div> </div>
@ -143,7 +143,7 @@
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">生日:</label> <label class="layui-form-label">生日:</label>
<div class="layui-input-inline" style="line-height: 2.5em;"> <div class="layui-input-inline" style="line-height: 2.5em;">
${contacts.birthday!''} ${contacts.cusbirthday!''}
</div> </div>
</div> </div>
</div> </div>

View File

@ -178,7 +178,7 @@
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">生日:</label> <label class="layui-form-label">生日:</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" id="birthday" name="contacts.birthday" autocomplete="off" <input type="text" id="birthday" name="contacts.cusbirthday" autocomplete="off"
class="layui-input"> class="layui-input">
<i class="layui-icon" style="position: absolute;right: 3px;top: 6px;font-size: 25px;">&#xe637;</i> <i class="layui-icon" style="position: absolute;right: 3px;top: 6px;font-size: 25px;">&#xe637;</i>
</div> </div>
@ -284,4 +284,4 @@
} }
}); });
</script> </script>

View File

@ -193,7 +193,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>
@ -233,7 +233,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>
@ -273,7 +273,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>
@ -311,7 +311,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>

View File

@ -94,7 +94,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>
@ -134,7 +134,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>
@ -174,7 +174,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>
@ -212,7 +212,7 @@
[知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效 [知识概况] 45 浏览 15收藏 5评论 2017-10-02 15:40:33前有效
<span> <span>
<i class="kfont">&#xe61e;</i> <i class="kfont">&#xe61e;</i>
<a href="">客服v3.1.0 产品说明书.pdf 等3个附件</a> <a href="">春松客服v3.1.0 产品说明书.pdf 等3个附件</a>
</span> </span>
</div> </div>
</li> </li>

View File

@ -30,9 +30,10 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">智能问答引擎地址</label> <label class="layui-form-label">智能问答引擎地址</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="baseUrl" required lay-verify="required" placeholder="请输入智能问答引擎地址" <input type="text" name="baseUrl" required lay-verify="required" placeholder="联系info@chatopera.com获得智能问答引擎地址"
autocomplete="off" class="layui-input" value="${bot.baseUrl}" <#if id!=null>disabled</#if>> autocomplete="off" class="layui-input" value="${bot.baseUrl}" <#if id!=null>disabled</#if>>
</div> </div>
<label class="layui-form-label"></label>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">名称</label> <label class="layui-form-label">名称</label>
@ -50,6 +51,13 @@
</select> </select>
</div> </div>
</div> </div>
<div class="layui-form-item">
<label class="layui-form-label">问候语</label>
<div class="layui-input-inline">
<input type="text" name="welcome" required lay-verify="required" placeholder="请输入问候语" autocomplete="off"
class="layui-input" value="${bot.welcome}">
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">兜底回复</label> <label class="layui-form-label">兜底回复</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
@ -115,7 +123,7 @@
if (data.rc == 0) { if (data.rc == 0) {
cb(null, data.data); cb(null, data.data);
} else { } else {
cb(data.error); cb(data);
} }
}) })
.fail(function (jqXHR, textStatus) { .fail(function (jqXHR, textStatus) {
@ -128,10 +136,17 @@
var form = layui.form(); var form = layui.form();
form.on('submit(save)', function (data) { form.on('submit(save)', function (data) {
var field = data.field; var field = data.field;
var submitFinish = function (err, bot) { var submitFinish = function (err, bot) {
if (err) { if (err) {
console.error(err); layer.confirm(err.data||err.error, {
btn: ['关闭'],
icon: 2,
title: '提示'
}, function (popup, layero) {
layer.close(popup)
}, function (popup) {
// 取消方法
});
} else { } else {
layer.open({ layer.open({
title: '提示' title: '提示'

View File

@ -68,7 +68,7 @@
if (data.rc == 0) { if (data.rc == 0) {
resolve(data.data); resolve(data.data);
} else { } else {
reject(data.error); reject(data);
} }
}) })
.fail(function (jqXHR, textStatus) { .fail(function (jqXHR, textStatus) {
@ -107,7 +107,18 @@
var isEnabled = $('<td><input type="checkbox" lay-skin="switch" lay-text="开启|关闭" ' + (r.enabled ? 'checked' : '') + '></td>'); var isEnabled = $('<td><input type="checkbox" lay-skin="switch" lay-text="开启|关闭" ' + (r.enabled ? 'checked' : '') + '></td>');
isEnabled.change(function () { isEnabled.change(function () {
change(r.id, $(this).find('input').prop('checked')); change(r.id, $(this).find('input').prop('checked'))
.then(null, function(err){
layer.confirm(err.data||err.error, {
btn: ['关闭'],
icon: 2,
title: '提示'
}, function (index, layero) {
layer.close(index)
}, function (index) {
// 取消方法
});
});
}) })
var rows = [ var rows = [
@ -123,6 +134,16 @@
}) })
$('#bots').html(tds); $('#bots').html(tds);
}, function(err){
layer.confirm(err.data||err.error, {
btn: ['关闭'],
icon: 2,
title: '提示'
}, function (popup, layero) {
layer.close(popup)
}, function (popup) {
// 取消方法
});
}) })
} }
@ -146,7 +167,7 @@
} }
function init() { function init() {
query(1, 10); query(1, 50);
} }
layui.use(['form'], function () { layui.use(['form'], function () {

View File

@ -77,10 +77,10 @@
</div> </div>
<div class="content-bottom"> <div class="content-bottom">
<span id="welcome-message"> <span id="welcome-message">
<p>欢迎使用客服企业IM</p> <p>欢迎使用春松客服企业IM</p>
<p>QQ群<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=637134af30a27220211c843d801ada14700aca69ee8f4acf13f795fe38ea7b94"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="优客服开源项目" title="优客服开源项目"></a></p> <p>QQ群<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=ef3061d99653e2f43619ddcefbf76ac2399196d89fd589501e19ae64423a5a31"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="春松客服开源社区" title="春松客服开源社区"></a></p>
<p>客服企业IM为收费产品</p> <p>春松客服企业IM为收费产品</p>
<p>详情请咨询:<a href="http://www.ukewo.cn" target="_blank" style="color:#32c24d;">客服</a></p> <p>详情请咨询:<a href="https://www.chatopera.com" target="_blank" style="color:#32c24d;">春松客服</a></p>
</span> </span>
</div> </div>
</div> </div>

View File

@ -172,7 +172,7 @@
title: '关于' , title: '关于' ,
btn: '关闭' , btn: '关闭' ,
shade: 0 , shade: 0 ,
content : '<span id="welcome-message"><p>欢迎使用客服企业IM</p><p>QQ群<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=637134af30a27220211c843d801ada14700aca69ee8f4acf13f795fe38ea7b94"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="优客服开源项目" title="优客服开源项目"></a></p><p>客服企业IM为收费产品</p><p>详情请咨询:<a href="http://www.ukewo.cn" target="_blank" style="color:#32c24d;">客服</a></p></span>'}); content : '<span id="welcome-message"><p>欢迎使用春松客服企业IM</p><p>QQ群<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=ef3061d99653e2f43619ddcefbf76ac2399196d89fd589501e19ae64423a5a31"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="春松客服开源社区" title="春松客服开源社区"></a></p><p>春松客服企业IM为收费产品</p><p>详情请咨询:<a href="https://www.chatopera.com" target="_blank" style="color:#32c24d;">春松客服</a></p></span>'});
} }
function search(){ function search(){
layer.open({ layer.open({

View File

@ -37,7 +37,7 @@
allowInsertUpload:false, //增加的参数,上传图片后是否插入到当前区域 allowInsertUpload:false, //增加的参数,上传图片后是否插入到当前区域
allowImageRemote:false, allowImageRemote:false,
filterMode:true, filterMode:true,
items: ['emoticons', 'cut' , 'image','insertfile'], items: ['emoticons', 'cut'],
htmlTags: {img : ['src', 'width', 'height', 'border', 'alt', 'title', 'align', '.width', '.height', '.border'] , br:[]} , htmlTags: {img : ['src', 'width', 'height', 'border', 'alt', 'title', 'align', '.width', '.height', '.border'] , br:[]} ,
afterChange : function() { afterChange : function() {
var count = this.count() ; var count = this.count() ;
@ -269,9 +269,9 @@
<#if !exchange?? || exchange == "true"> <#if !exchange?? || exchange == "true">
<li><a href="/im/index.html?appid=${appid!''}&orgi=${orgi!''}&ai=false<#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> <li><a href="/im/index.html?appid=${appid!''}&orgi=${orgi!''}&ai=false<#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> </#if>
<li class="cur"><a href="javascript:void(0)">智能坐席</a></li> <li class="cur"><a href="javascript:void(0)">智能客服</a></li>
<#else> <#else>
<li class="cur"><a href="javascript:void(0)">智能坐席</a></li> <li class="cur"><a href="javascript:void(0)">智能客服</a></li>
</#if> </#if>
</ul> </ul>
</div> </div>
@ -312,7 +312,7 @@
<div class="chat-left"> <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=""> <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"> <div class="chat-message">
<label class="user"><#if chatMessage?? && chatMessage.chatype?? && chatMessage.chatype == 'aireply'>${inviteData.ainame!'小E'}<#else>${chatMessage.username!''}</#if></label> <label class="user"><#if chatMessage?? && chatMessage.chatype?? && chatMessage.chatype == 'aireply'>${inviteData.ainame!'小'}<#else>${chatMessage.username!''}</#if></label>
<label class="time">${chatMessage.createtime!''}</label> <label class="time">${chatMessage.createtime!''}</label>
</div> </div>
<div class="chatting-left"> <div class="chatting-left">
@ -453,9 +453,9 @@
// 参数连接 // 参数连接
var hostname = location.hostname ; var hostname = location.hostname ;
var protocol = window.location.protocol.replace(/:/g,''); 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><#if aiid??>&aiid=${aiid}</#if>'); var socket = io(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><#if aiid??>&aiid=${aiid}</#if>', {transports: ['websocket', 'polling']});
socket.on('connect',function(){ socket.on('connect',function(){
<#if contacts?? && contacts.name??> <#if contacts?? && contacts.name??>
socket.emit('new', { socket.emit('new', {
name : "${contacts.name!''}", name : "${contacts.name!''}",
phone:"${contacts.phone!''}", phone:"${contacts.phone!''}",
@ -489,16 +489,15 @@
} }
}) })
socket.on('message', function(data) { socket.on('message', function(data) {
console.log("[chatbot io] message ", data);
var chat=document.getElementsByClassName('chatting-left').innerText; var chat=document.getElementsByClassName('chatting-left').innerText;
chat = data.message; chat = data.message;
if(data.messageType == "image"){ if(data.messageType == "image"){
chat = "<a href='"+data.message+"_original' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ; chat = "<a href='"+data.message+"&original=true' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ;
}else if(data.messageType == "file"){ }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>" ; 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 == "呼入"){ 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> </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"); 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.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!''}">'+chat+'</div></div>' , "chat-block");
}else if(data.calltype == "呼出"){ }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.username+'</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"); 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.username+'</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); // 播放 R3Ajax.audioplayer('audioplane', newmessage, false); // 播放

View File

@ -174,12 +174,14 @@
<div class="ukefu-func-tab"> <div class="ukefu-func-tab">
<ul> <ul>
<#if models?? && models["chatbot"]?? && models["chatbot"] == true && inviteData.ai?? && inviteData.ai == true && aiid??> <#if models?? && models["chatbot"]?? && models["chatbot"] == true && inviteData.ai && 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> <#if !exchange?? || exchange == "true">
<li class="cur"><a href="javascript:void(0)">人工坐席</a></li> <li><a href="/im/index.html?appid=${appid!''}&orgi=${orgi!''}&ai=false<#if aiid??>&aiid=${aiid}</#if><#if client??>&client=${client!''}</#if><#if type??>&type=text</#if><#if skill??>&skill=${skill!''}</#if><#if agent??>&agent=${agent!''}</#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> <#else>
<li class="cur"><a href="javascript:void(0)">人工坐席</a></li> <li class="cur"><a href="javascript:void(0)">智能客服</a></li>
</#if> </#if>
</ul> </ul>
</div> </div>
</div> </div>
@ -236,12 +238,12 @@
</div> </div>
<div class="mobile-chat-bottom" id="bottom"> <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"> <!--<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)"> <!--<a href="javascript:;" class="imgFile" onclick="closeFaceDialog(0)">-->
<img src="/im/img/img.png" class="chat-type" style="width:32px;height:32px;"> <!--<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('');"> <!--<input type="file" name="imgFile" id="imgFile" accept="image/*" onChange="$('#imgForm').submit();$(this).val('');">-->
</a> <!--</a>-->
</form> <!--</form>-->
<textarea id="message" name="content" maxlength="<#if inviteData.maxwordsnum gt 0>${inviteData.maxwordsnum}<#else>300</#if>"></textarea> <textarea id="message" name="content" maxlength="<#if inviteData.maxwordsnum gt 0>${inviteData.maxwordsnum}<#else>300</#if>"></textarea>
<div class="btn-push clearfix" class="tools"> <div class="btn-push clearfix" class="tools">
<img id="facedialog" onclick="return openFaceDialog()" src="/im/img/face.png" style="width:32px;height:32px;"></a> <img id="facedialog" onclick="return openFaceDialog()" src="/im/img/face.png" style="width:32px;height:32px;"></a>
@ -281,7 +283,7 @@
// 参数连接 // 参数连接
var hostname = location.hostname ; var hostname = location.hostname ;
var protocol = window.location.protocol.replace(/:/g,''); 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>'); var socket = io(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>', {transports: ['websocket', 'polling']});
socket.on('connect',function(){ socket.on('connect',function(){
//service.sendRequestMessage(); //service.sendRequestMessage();
//output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message'); //output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message');
@ -300,7 +302,7 @@
var chat=document.getElementsByClassName('chatting-left').innerText; var chat=document.getElementsByClassName('chatting-left').innerText;
chat = data.message; chat = data.message;
if(data.messageType == "image"){ if(data.messageType == "image"){
chat = "<a href='"+data.message+"_original' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ; chat = "<a href='"+data.message+"&original=true' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ;
}else if(data.messageType == "cooperation"){ }else if(data.messageType == "cooperation"){
chat = "<a href='javascript:void(0)' onclick='acceptInvite(\""+data.message+"\", \""+data.attachmentid+"\")'>您收到一个协作邀请,点击进入协作</a>" ; chat = "<a href='javascript:void(0)' onclick='acceptInvite(\""+data.message+"\", \""+data.attachmentid+"\")'>您收到一个协作邀请,点击进入协作</a>" ;
}else if(data.messageType == "action"){ }else if(data.messageType == "action"){
@ -308,9 +310,9 @@
drawCanvasImage(data.attachmentid) ; drawCanvasImage(data.attachmentid) ;
} }
if(data.calltype == "呼入"){ 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"); 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.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!''}">'+chat+'</div></div>' , "chat-block");
}else if(data.calltype == "呼出"){ }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"); 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.username+'</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");
} }
}); });
@ -322,7 +324,7 @@
} }
function acceptInvite(msgid,fileid){ function acceptInvite(msgid,fileid){
document.getElementById("cooperation").style.display = "block" ; document.getElementById("cooperation").style.display = "block" ;
document.getElementById("ukefu_img_ctx").src = "/res/image.html?id=upload/"+fileid ; document.getElementById("ukefu_img_ctx").src = "/res/image.html?id="+fileid + "&cooperation=true&original=true";
$("#ukefu_img_ctx").load(function() { $("#ukefu_img_ctx").load(function() {
var height = document.getElementById("ukefu-image-content").offsetHeight; var height = document.getElementById("ukefu-image-content").offsetHeight;
@ -346,7 +348,7 @@
//创建新的图片对象 //创建新的图片对象
var img = new Image(); var img = new Image();
//指定图片的URL //指定图片的URL
img.src = "/res/image.html?id=upload/" + fileid + "_cooperation"; img.src = "/res/image.html?id=" + fileid + "&cooperation=true&original=true";
//浏览器加载图片完毕后再绘制图片 //浏览器加载图片完毕后再绘制图片
img.onload = function() { img.onload = function() {
ctx.clearRect(0,0,canvas.width,canvas.height); ctx.clearRect(0,0,canvas.width,canvas.height);

View File

@ -311,7 +311,7 @@
<div class="chat-left"> <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=""> <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"> <div class="chat-message">
<label class="user"><#if chatMessage?? && chatMessage.chatype?? && chatMessage.chatype == 'aireply'>${inviteData.ainame!'小E'}<#else>${chatMessage.username!''}</#if></label> <label class="user"><#if chatMessage?? && chatMessage.chatype?? && chatMessage.chatype == 'aireply'>${inviteData.ainame!'小'}<#else>${chatMessage.username!''}</#if></label>
<label class="time">${chatMessage.createtime!''}</label> <label class="time">${chatMessage.createtime!''}</label>
</div> </div>
<div class="chatting-left"> <div class="chatting-left">
@ -452,9 +452,10 @@
// 参数连接 // 参数连接
var hostname = location.hostname ; var hostname = location.hostname ;
var protocol = window.location.protocol.replace(/:/g,''); var protocol = window.location.protocol.replace(/:/g,'');
var socket = io.connect(protocol + '://'+hostname+':${port}/im/user?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>'); var socket = io(protocol + '://'+hostname+':${port}/im/user?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>', {transports: ['websocket', 'polling']});
socket.on('connect',function(){ socket.on('connect',function(){
<#if contacts?? && contacts.name??> console.log("on connect ...");
<#if contacts?? && contacts.name??>
socket.emit('new', { socket.emit('new', {
name : "${contacts.name!''}", name : "${contacts.name!''}",
phone:"${contacts.phone!''}", phone:"${contacts.phone!''}",
@ -488,10 +489,11 @@
} }
}) })
socket.on('message', function(data) { socket.on('message', function(data) {
console.log("on message", data);
var chat=document.getElementsByClassName('chatting-left').innerText; var chat=document.getElementsByClassName('chatting-left').innerText;
chat = data.message; chat = data.message;
if(data.messageType == "image"){ if(data.messageType == "image"){
chat = "<a href='"+data.message+"_original' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ; chat = "<a href='"+data.message+"&original=true' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ;
}else if(data.messageType == "file"){ }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>" ; 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>" ;
} }

View File

@ -1,5 +1,5 @@
<#if chatMessage.msgtype?? && chatMessage.msgtype == "image"> <#if chatMessage.msgtype?? && chatMessage.msgtype == "image">
<a href="${(chatMessage.message!'')?no_esc}_original" target="_blank"><img src="${(chatMessage.message!'')?no_esc}" class="ukefu-media-image"></a> <a href="${(chatMessage.message!'')?no_esc}&original=true" target="_blank"><img src="${(chatMessage.message!'')?no_esc}" class="ukefu-media-image"></a>
<#elseif chatMessage.msgtype?? && chatMessage.msgtype == "cooperation"> <#elseif chatMessage.msgtype?? && chatMessage.msgtype == "cooperation">
<a href='javascript:void(0)' onclick='acceptInvite("${chatMessage.message!''}" , "${chatMessage.attachmentid!''}")'>您收到一个协作邀请,点击进入协作</a> <a href='javascript:void(0)' onclick='acceptInvite("${chatMessage.message!''}" , "${chatMessage.attachmentid!''}")'>您收到一个协作邀请,点击进入协作</a>
<#elseif chatMessage.msgtype?? && chatMessage.msgtype == "file"> <#elseif chatMessage.msgtype?? && chatMessage.msgtype == "file">

View File

@ -174,7 +174,7 @@
<div class="ukefu-func-tab"> <div class="ukefu-func-tab">
<ul> <ul>
<#if models?? && models["xiaoe"]?? && models["xiaoe"] == true && inviteData.ai?? && inviteData.ai == true && aiid??> <#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><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> <li class="cur"><a href="javascript:void(0)">人工坐席</a></li>
<#else> <#else>
@ -223,8 +223,8 @@
src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>"
alt=""> alt="">
<div class="chat-message"> <div class="chat-message">
<label class="user">${chatMessage.username!''}</label> <label <label class="user"><#if chatMessage?? && chatMessage.chatype?? && chatMessage.chatype == 'aireply'>${inviteData.ainame!'小松'}<#else>${chatMessage.username!''}</#if></label>
class="time">${chatMessage.createtime!''}</label> <label class="time">${chatMessage.createtime!''}</label>
</div> </div>
<div class="chatting-left"> <div class="chatting-left">
<i class="arrow"></i> <i class="arrow"></i>
@ -281,7 +281,7 @@
// 参数连接 // 参数连接
var hostname = location.hostname ; var hostname = location.hostname ;
var protocol = window.location.protocol.replace(/:/g,''); var protocol = window.location.protocol.replace(/:/g,'');
var socket = io.connect(protocol + '://'+hostname+':${port}/im/user?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>'); var socket = io(protocol + '://'+hostname+':${port}/im/user?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 username??>&nickname=${username}</#if><#if agent??>&agent=${agent}</#if>', {transports: ['websocket', 'polling']});
socket.on('connect',function(){ socket.on('connect',function(){
//service.sendRequestMessage(); //service.sendRequestMessage();
//output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message'); //output('<span id="callOutConnect-message">'+ new Date().format("yyyy-MM-dd hh:mm:ss") + ' 开始沟通' +'</span>' , 'message callOutConnect-message');
@ -300,7 +300,7 @@
var chat=document.getElementsByClassName('chatting-left').innerText; var chat=document.getElementsByClassName('chatting-left').innerText;
chat = data.message; chat = data.message;
if(data.messageType == "image"){ if(data.messageType == "image"){
chat = "<a href='"+data.message+"_original' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ; chat = "<a href='"+data.message+"&original=true' target='_blank'><img src='"+data.message+"' class='ukefu-media-image'/></a>" ;
}else if(data.messageType == "cooperation"){ }else if(data.messageType == "cooperation"){
chat = "<a href='javascript:void(0)' onclick='acceptInvite(\""+data.message+"\", \""+data.attachmentid+"\")'>您收到一个协作邀请,点击进入协作</a>" ; chat = "<a href='javascript:void(0)' onclick='acceptInvite(\""+data.message+"\", \""+data.attachmentid+"\")'>您收到一个协作邀请,点击进入协作</a>" ;
}else if(data.messageType == "action"){ }else if(data.messageType == "action"){
@ -322,7 +322,7 @@
} }
function acceptInvite(msgid,fileid){ function acceptInvite(msgid,fileid){
document.getElementById("cooperation").style.display = "block" ; document.getElementById("cooperation").style.display = "block" ;
document.getElementById("ukefu_img_ctx").src = "/res/image.html?id=upload/"+fileid ; document.getElementById("ukefu_img_ctx").src = "/res/image.html?id="+fileid + "&cooperation=true&original=true";
$("#ukefu_img_ctx").load(function() { $("#ukefu_img_ctx").load(function() {
var height = document.getElementById("ukefu-image-content").offsetHeight; var height = document.getElementById("ukefu-image-content").offsetHeight;
@ -346,7 +346,7 @@
//创建新的图片对象 //创建新的图片对象
var img = new Image(); var img = new Image();
//指定图片的URL //指定图片的URL
img.src = "/res/image.html?id=upload/" + fileid + "_cooperation"; img.src = "/res/image.html?id=" + fileid + "&cooperation=true&original=true";
//浏览器加载图片完毕后再绘制图片 //浏览器加载图片完毕后再绘制图片
img.onload = function() { img.onload = function() {
ctx.clearRect(0,0,canvas.width,canvas.height); ctx.clearRect(0,0,canvas.width,canvas.height);

File diff suppressed because one or more lines are too long

View File

@ -166,7 +166,7 @@
</li> </li>
</#if> </#if>
<#if user?? && user.agent == true> <#if user?? && user.agent == true>
<#if (user?? && user.roleAuthMap["B01"]?? || user.usertype == "0")> <#if (user?? && user.roleAuthMap["A01"]?? || user.usertype == "0")>
<li class="layui-nav-item " style="position: relative;"> <li class="layui-nav-item " style="position: relative;">
<div class="ukefu-last-msg" data-num="0" id="ukefu-last-msg"> <div class="ukefu-last-msg" data-num="0" id="ukefu-last-msg">
<small class="ukefu-msg-tip bg-red" id="msgnum">0</small> <small class="ukefu-msg-tip bg-red" id="msgnum">0</small>
@ -299,15 +299,15 @@
--> -->
<#if models?? && models["xiaoe"]?? && models["xiaoe"] == true> <!--<#if models?? && models["xiaoe"]?? && models["xiaoe"] == true>-->
<#if user?? &&( user.roleAuthMap["A09"]?? || user.usertype == "0") > <!--<#if user?? &&( user.roleAuthMap["A09"]?? || user.usertype == "0") >-->
<dd class="ukefu-left-menu" data-tooltip="智能机器人"> <!--<dd class="ukefu-left-menu" data-tooltip="智能机器人">-->
<a href="javascript:void(0)" data-title="智能机器人" data-href="/apps/xiaoe/index.html" class="iframe_btn" data-id="maincontent" data-type="tabChange"> <!--<a href="javascript:void(0)" data-title="智能机器人" data-href="/apps/xiaoe/index.html" class="iframe_btn" data-id="maincontent" data-type="tabChange">-->
<i class="kfont" style="position: relative;">&#xe63a;</i> <!--<i class="kfont" style="position: relative;">&#xe63a;</i>-->
</a> <!--</a>-->
</dd> <!--</dd>-->
</#if> <!--</#if>-->
</#if> <!--</#if>-->
<#if models?? && models["sales"]?? && models["sales"] == true> <#if models?? && models["sales"]?? && models["sales"] == true>
<#if user?? &&( user.roleAuthMap["A11"]?? || user.usertype == "0") > <#if user?? &&( user.roleAuthMap["A11"]?? || user.usertype == "0") >
<dd class="ukefu-left-menu" data-tooltip="外呼系统"> <dd class="ukefu-left-menu" data-tooltip="外呼系统">
@ -317,11 +317,11 @@
</dd> </dd>
</#if> </#if>
</#if> </#if>
<#if models?? && models["sales"]?? && models["sales"] == true> <#if models?? && models["chatbot"]?? && models["chatbot"] == true>
<#if user?? &&( user.roleAuthMap["A11"]?? || user.usertype == "0") > <#if user?? &&( user.roleAuthMap["A09"]?? || user.usertype == "0") >
<dd class="ukefu-left-menu" data-tooltip="机器人"> <dd class="ukefu-left-menu" data-tooltip="智能机器人">
<a href="javascript:void(0)" data-title="机器人"" data-href="/apps/chatbot/index.html" class="iframe_btn" data-id="maincontent" data-type="tabChange"> <a href="javascript:void(0)" data-title="智能机器人" data-href="/apps/chatbot/index.html" class="iframe_btn" data-id="maincontent" data-type="tabChange">
<i class="kfont" style="position: relative;">&#xe63a;</i> <i class="kfont" style="position: relative;">&#xe63a;</i>
</a> </a>
</dd> </dd>
</#if> </#if>

View File

@ -97,9 +97,8 @@
<th>咨询时间</th> <th>咨询时间</th>
<th>服务时间</th> <th>服务时间</th>
<th>等待时长</th> <th>等待时长</th>
<th>服务时</th> <th>服务时</th>
<th>地域</th> <th>地域</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@ -9,7 +9,7 @@
<#if contacts.gender?? && contacts.gender == '-1'>未知</#if> <#if contacts.gender?? && contacts.gender == '-1'>未知</#if>
</li> </li>
<li> <li>
生日:${contacts.birthday!''} 生日:${contacts.cusbirthday!''}
</li> </li>
<li> <li>
电话:${contacts.phone!''} 电话:${contacts.phone!''}
@ -43,4 +43,4 @@
}); });
</script> </script>
</#if> </#if>
</#if> </#if>

View File

@ -35,7 +35,7 @@
<div class="layui-inline uckefu-inline"> <div class="layui-inline uckefu-inline">
<label class="layui-form-label">生日:</label> <label class="layui-form-label">生日:</label>
<div class="layui-input-inline" style="padding:9px 0;"> <div class="layui-input-inline" style="padding:9px 0;">
${contacts.birthday!''} ${contacts.cusbirthday!''}
</div> </div>
</div> </div>
</div> </div>
@ -202,4 +202,4 @@
var element = layui.element(); var element = layui.element();
element.init(); element.init();
}); });
</script> </script>

View File

@ -35,7 +35,7 @@
<div class="layui-inline uckefu-inline"> <div class="layui-inline uckefu-inline">
<label class="layui-form-label">生日:</label> <label class="layui-form-label">生日:</label>
<div class="layui-input-inline" style="padding:9px 0;"> <div class="layui-input-inline" style="padding:9px 0;">
${contacts.birthday!''} ${contacts.cusbirthday!''}
</div> </div>
</div> </div>
</div> </div>
@ -202,4 +202,4 @@
var element = layui.element(); var element = layui.element();
element.init(); element.init();
}); });
</script> </script>

View File

@ -21,9 +21,9 @@
layui.use('layer', function(){ layui.use('layer', function(){
var layer = layui.layer; var layer = layui.layer;
<#if msg?? && msg == '0'> <#if msg?? && msg == '0'>
layer.alert('手机或密码错误,请重新填写', {icon: 2}); layer.alert('用户名或密码错误,请重新填写', {icon: 2});
<#elseif msg?? && msg == '1'> <#elseif msg?? && msg == '1'>
layer.alert('用户注册成功,请使用手机和密码登陆', {icon: 1}); layer.alert('用户注册成功,请通过用户名和密码登陆', {icon: 1});
</#if> </#if>
}); });
layui.use('form', function(){ layui.use('form', function(){
@ -49,7 +49,7 @@
<!-- <input name="username" id="username" autofocus required lay-verify="required" <!-- <input name="username" id="username" autofocus required lay-verify="required"
class="form-control required" value="" placeholder="用户名/邮件/手机号"> --> class="form-control required" value="" placeholder="用户名/邮件/手机号"> -->
<input name="username" id="username" autofocus required lay-verify="required" <input name="username" id="username" autofocus required lay-verify="required"
class="form-control required" value="" placeholder="登录账号"> class="form-control required" value="" placeholder="用户名">
</div> </div>
<div class="form-group has-feedback" style="margin-bottom:10px;"> <div class="form-group has-feedback" style="margin-bottom:10px;">
<span class="kfont form-control-feedback">&#xe618;</span> <span class="kfont form-control-feedback">&#xe618;</span>

View File

@ -437,6 +437,19 @@ CREATE TABLE `cs_callout_targets` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='外呼计划目标客户'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='外呼计划目标客户';
-- ----------------------------
-- Table structure for cs_stream_file
-- ----------------------------
DROP TABLE IF EXISTS `cs_stream_file`;
CREATE TABLE `cs_stream_file` (
`id` varchar(32) NOT NULL COMMENT '文件ID',
`name` varchar(300) NOT NULL COMMENT '文件名称',
`data` mediumblob NOT NULL COMMENT '原始文件',
`thumbnail` mediumblob COMMENT '缩略图',
`mime` varchar(200) DEFAULT NULL COMMENT '文件类型 Content Type',
`cooperation` mediumblob COMMENT '协作文件',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT '文件';
-- ---------------------------- -- ----------------------------
-- Table structure for uk_ad_position -- Table structure for uk_ad_position
@ -457,7 +470,7 @@ CREATE TABLE `uk_ad_position` (
`AREA` text COMMENT '分类描述', `AREA` text COMMENT '分类描述',
`IMGURL` varchar(255) DEFAULT NULL COMMENT '图片URL', `IMGURL` varchar(255) DEFAULT NULL COMMENT '图片URL',
`TIPTEXT` varchar(100) DEFAULT NULL COMMENT '提示文本', `TIPTEXT` varchar(100) DEFAULT NULL COMMENT '提示文本',
`URL` varchar(255) DEFAULT NULL COMMENT '路径', `URL` text DEFAULT NULL COMMENT '路径',
`CONTENT` text COMMENT '内容', `CONTENT` text COMMENT '内容',
`WEIGHT` int(11) DEFAULT NULL COMMENT '权重', `WEIGHT` int(11) DEFAULT NULL COMMENT '权重',
`ADTYPE` varchar(50) DEFAULT NULL COMMENT '广告类型', `ADTYPE` varchar(50) DEFAULT NULL COMMENT '广告类型',
@ -498,7 +511,7 @@ CREATE TABLE `uk_agentservice` (
`lastmessage` datetime DEFAULT NULL COMMENT '最后一条消息时间', `lastmessage` datetime DEFAULT NULL COMMENT '最后一条消息时间',
`waittingtimestart` datetime DEFAULT NULL COMMENT '进入排队时间', `waittingtimestart` datetime DEFAULT NULL COMMENT '进入排队时间',
`lastgetmessage` datetime DEFAULT NULL COMMENT '坐席最后一条消息时间', `lastgetmessage` datetime DEFAULT NULL COMMENT '坐席最后一条消息时间',
`lastmsg` varchar(100) DEFAULT '' COMMENT '最后一条消息内容', `lastmsg` text COMMENT '最后一条消息内容',
`agentskill` varchar(100) DEFAULT '' COMMENT '技能组', `agentskill` varchar(100) DEFAULT '' COMMENT '技能组',
`create_time` datetime DEFAULT NULL COMMENT '创建时间', `create_time` datetime DEFAULT NULL COMMENT '创建时间',
`creater` varchar(255) DEFAULT NULL COMMENT '创建人', `creater` varchar(255) DEFAULT NULL COMMENT '创建人',
@ -637,7 +650,7 @@ CREATE TABLE `uk_agentuser` (
`lastmessage` datetime DEFAULT NULL COMMENT '最后一条消息时间', `lastmessage` datetime DEFAULT NULL COMMENT '最后一条消息时间',
`waittingtimestart` datetime DEFAULT NULL COMMENT '进入队列时间', `waittingtimestart` datetime DEFAULT NULL COMMENT '进入队列时间',
`lastgetmessage` datetime DEFAULT NULL COMMENT '最后一条消息时间', `lastgetmessage` datetime DEFAULT NULL COMMENT '最后一条消息时间',
`lastmsg` varchar(100) DEFAULT '' COMMENT '最后一条消息', `lastmsg` text COMMENT '最后一条消息',
`agentskill` varchar(100) DEFAULT '' COMMENT '技能组', `agentskill` varchar(100) DEFAULT '' COMMENT '技能组',
`create_time` datetime DEFAULT NULL COMMENT '创建时间', `create_time` datetime DEFAULT NULL COMMENT '创建时间',
`creater` varchar(255) DEFAULT NULL COMMENT '创建人', `creater` varchar(255) DEFAULT NULL COMMENT '创建人',
@ -676,7 +689,7 @@ CREATE TABLE `uk_agentuser` (
`avgreplytime` int(11) DEFAULT '0' COMMENT '平均回复时长', `avgreplytime` int(11) DEFAULT '0' COMMENT '平均回复时长',
`sessionid` varchar(32) DEFAULT NULL COMMENT '会话ID', `sessionid` varchar(32) DEFAULT NULL COMMENT '会话ID',
`title` varchar(255) DEFAULT NULL COMMENT '标题', `title` varchar(255) DEFAULT NULL COMMENT '标题',
`url` varchar(255) DEFAULT NULL COMMENT 'URL', `url` text DEFAULT NULL COMMENT 'URL',
`traceid` varchar(32) DEFAULT NULL COMMENT '跟踪ID', `traceid` varchar(32) DEFAULT NULL COMMENT '跟踪ID',
`agenttimeout` int(11) DEFAULT '0' COMMENT '坐席超时时长', `agenttimeout` int(11) DEFAULT '0' COMMENT '坐席超时时长',
`agenttimeouttimes` int(11) DEFAULT '0' COMMENT '坐席超时次数', `agenttimeouttimes` int(11) DEFAULT '0' COMMENT '坐席超时次数',
@ -781,7 +794,7 @@ CREATE TABLE `uk_attachment_file` (
`organ` varchar(32) DEFAULT NULL COMMENT '组织机构ID', `organ` varchar(32) DEFAULT NULL COMMENT '组织机构ID',
`datastatus` tinyint(4) DEFAULT NULL COMMENT '数据状态(逻辑删除)', `datastatus` tinyint(4) DEFAULT NULL COMMENT '数据状态(逻辑删除)',
`title` varchar(255) DEFAULT NULL COMMENT '标题', `title` varchar(255) DEFAULT NULL COMMENT '标题',
`url` varchar(255) CHARACTER SET utf32 DEFAULT NULL COMMENT '地址', `url` text CHARACTER SET utf32 DEFAULT NULL COMMENT '地址',
`updatetime` datetime DEFAULT NULL COMMENT '更新时间', `updatetime` datetime DEFAULT NULL COMMENT '更新时间',
`filelength` int(11) DEFAULT NULL COMMENT '文件长度', `filelength` int(11) DEFAULT NULL COMMENT '文件长度',
`filetype` varchar(255) DEFAULT NULL COMMENT '文件类型', `filetype` varchar(255) DEFAULT NULL COMMENT '文件类型',
@ -1610,7 +1623,7 @@ CREATE TABLE `cs_contact_notes` (
`createtime` datetime NOT NULL COMMENT '创建时间', `createtime` datetime NOT NULL COMMENT '创建时间',
`updatetime` datetime NOT NULL COMMENT '更新时间', `updatetime` datetime NOT NULL COMMENT '更新时间',
`category` varchar(200) DEFAULT NULL COMMENT '内容类型', `category` varchar(200) DEFAULT NULL COMMENT '内容类型',
`content` varchar(1000) DEFAULT NULL COMMENT '内容', `content` text COMMENT '内容',
`creater` varchar(32) DEFAULT NULL COMMENT '创建人', `creater` varchar(32) DEFAULT NULL COMMENT '创建人',
`datastatus` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除', `datastatus` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已删除',
`agentuser` varchar(32) DEFAULT NULL COMMENT '在线访客记录ID', `agentuser` varchar(32) DEFAULT NULL COMMENT '在线访客记录ID',
@ -2112,7 +2125,7 @@ CREATE TABLE `uk_inviterecord` (
`responsetime` int(11) DEFAULT NULL COMMENT '响应时间', `responsetime` int(11) DEFAULT NULL COMMENT '响应时间',
`appid` varchar(32) DEFAULT NULL COMMENT 'SNSID', `appid` varchar(32) DEFAULT NULL COMMENT 'SNSID',
`title` varchar(255) DEFAULT NULL COMMENT '标题', `title` varchar(255) DEFAULT NULL COMMENT '标题',
`url` varchar(255) DEFAULT NULL COMMENT '地址', `url` text DEFAULT NULL COMMENT '地址',
`traceid` varchar(32) DEFAULT NULL COMMENT '跟踪ID', `traceid` varchar(32) DEFAULT NULL COMMENT '跟踪ID',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='邀请记录表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='邀请记录表';
@ -2481,7 +2494,7 @@ CREATE TABLE `uk_onlineuser` (
`keyword` varchar(100) DEFAULT NULL COMMENT '搜索引擎关键词', `keyword` varchar(100) DEFAULT NULL COMMENT '搜索引擎关键词',
`source` varchar(50) DEFAULT NULL COMMENT '来源', `source` varchar(50) DEFAULT NULL COMMENT '来源',
`title` varchar(255) DEFAULT NULL COMMENT '标题', `title` varchar(255) DEFAULT NULL COMMENT '标题',
`url` varchar(255) DEFAULT NULL COMMENT '来源URL', `url` text DEFAULT NULL COMMENT '来源URL',
`useragent` text COMMENT 'UA', `useragent` text COMMENT 'UA',
`invitetimes` int(11) DEFAULT NULL COMMENT '要求次数', `invitetimes` int(11) DEFAULT NULL COMMENT '要求次数',
`invitestatus` varchar(10) DEFAULT NULL COMMENT '邀请状态', `invitestatus` varchar(10) DEFAULT NULL COMMENT '邀请状态',
@ -2541,7 +2554,7 @@ CREATE TABLE `uk_onlineuser_his` (
`keyword` varchar(100) DEFAULT NULL COMMENT '搜索引擎关键词', `keyword` varchar(100) DEFAULT NULL COMMENT '搜索引擎关键词',
`source` varchar(50) DEFAULT NULL COMMENT '来源', `source` varchar(50) DEFAULT NULL COMMENT '来源',
`title` varchar(255) DEFAULT NULL COMMENT '标题', `title` varchar(255) DEFAULT NULL COMMENT '标题',
`url` varchar(255) DEFAULT NULL COMMENT '来源URL', `url` text DEFAULT NULL COMMENT '来源URL',
`useragent` text COMMENT 'UA', `useragent` text COMMENT 'UA',
`invitetimes` int(11) DEFAULT NULL COMMENT '要求次数', `invitetimes` int(11) DEFAULT NULL COMMENT '要求次数',
`invitestatus` varchar(10) DEFAULT NULL COMMENT '邀请状态', `invitestatus` varchar(10) DEFAULT NULL COMMENT '邀请状态',
@ -2914,7 +2927,7 @@ CREATE TABLE `uk_recentuser` (
`name` varchar(100) DEFAULT NULL COMMENT '名称', `name` varchar(100) DEFAULT NULL COMMENT '名称',
`orgi` varchar(100) DEFAULT NULL COMMENT '租户ID', `orgi` varchar(100) DEFAULT NULL COMMENT '租户ID',
`user_id` varchar(32) DEFAULT NULL COMMENT '用户ID', `user_id` varchar(32) DEFAULT NULL COMMENT '用户ID',
`lastmsg` varchar(100) DEFAULT NULL COMMENT '最后一条消息', `lastmsg` text COMMENT '最后一条消息',
`newmsg` int(11) DEFAULT NULL COMMENT '未读消息数量', `newmsg` int(11) DEFAULT NULL COMMENT '未读消息数量',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='公共已读消息'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='公共已读消息';
@ -3475,7 +3488,7 @@ CREATE TABLE `uk_sysdic` (
`DICID` varchar(32) DEFAULT NULL COMMENT '目录ID', `DICID` varchar(32) DEFAULT NULL COMMENT '目录ID',
`DEFAULTVALUE` tinyint(4) DEFAULT NULL COMMENT '默认值', `DEFAULTVALUE` tinyint(4) DEFAULT NULL COMMENT '默认值',
`DISCODE` tinyint(4) DEFAULT NULL COMMENT '编码', `DISCODE` tinyint(4) DEFAULT NULL COMMENT '编码',
`URL` varchar(255) DEFAULT NULL COMMENT '系统权限资源的URL', `URL` text DEFAULT NULL COMMENT '系统权限资源的URL',
`MODULE` varchar(32) DEFAULT NULL COMMENT '权限资源所属模块', `MODULE` varchar(32) DEFAULT NULL COMMENT '权限资源所属模块',
`MLEVEL` varchar(32) DEFAULT NULL COMMENT '菜单级别(一级/二级)', `MLEVEL` varchar(32) DEFAULT NULL COMMENT '菜单级别(一级/二级)',
`RULES` varchar(100) DEFAULT NULL, `RULES` varchar(100) DEFAULT NULL,
@ -7130,9 +7143,7 @@ INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce8b990057e', '在线坐
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce8e6a2057f', '全部坐席', 'pub', 'A08_A04_A02', NULL, 'auth', '402881ef612b1f5b01612cdd1e930570', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:41:56', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/service/user/index.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce8e6a2057f', '全部坐席', 'pub', 'A08_A04_A02', NULL, 'auth', '402881ef612b1f5b01612cdd1e930570', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:41:56', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/service/user/index.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce964ae0580', '智能机器人', 'pub', 'A09_A01', NULL, 'auth', '402881ef612b1f5b01612cc602450546', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:42:28', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, 'javascript:;', 'webim', '2', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce964ae0580', '智能机器人', 'pub', 'A09_A01', NULL, 'auth', '402881ef612b1f5b01612cc602450546', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:42:28', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, 'javascript:;', 'webim', '2', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce996f80581', '语料库配置', 'pub', 'A09_A02', NULL, 'auth', '402881ef612b1f5b01612cc602450546', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:42:41', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, 'javascript:;', 'webim', '2', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce996f80581', '语料库配置', 'pub', 'A09_A02', NULL, 'auth', '402881ef612b1f5b01612cc602450546', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:42:41', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, 'javascript:;', 'webim', '2', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce9d8150582', '机器人选项', 'pub', 'A09_A01_A01', NULL, 'auth', '402881ef612b1f5b01612ce964ae0580', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:42:58', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/index.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ce9d8150582', '机器人管理', 'pub', 'A09_A01_A01', NULL, 'auth', '402881ef612b1f5b01612ce964ae0580', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:42:58', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/index.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cea04810583', '对话测试', 'pub', 'A09_A01_A02', NULL, 'auth', '402881ef612b1f5b01612ce964ae0580', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:43:09', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/chat.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cea430f0584', '用户提问历史', 'pub', 'A09_A01_A03', NULL, 'auth', '402881ef612b1f5b01612ce964ae0580', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:43:25', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/history.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ceaff050587', '对话场景', 'pub', 'A09_A02_A03', NULL, 'auth', '402881ef612b1f5b01612ce996f80581', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:44:13', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/scene.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ceaff050587', '对话场景', 'pub', 'A09_A02_A03', NULL, 'auth', '402881ef612b1f5b01612ce996f80581', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:44:13', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/scene.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ced9d5f0588', '知识维护', 'pub', 'A09_A02_A01', NULL, 'auth', '402881ef612b1f5b01612ce996f80581', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:47:05', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/knowledge.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ced9d5f0588', '知识维护', 'pub', 'A09_A02_A01', NULL, 'auth', '402881ef612b1f5b01612ce996f80581', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:47:05', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/knowledge.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cedca5e0589', '词库配置', 'pub', 'A09_A02_A02', NULL, 'auth', '402881ef612b1f5b01612ce996f80581', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:47:16', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/words.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cedca5e0589', '词库配置', 'pub', 'A09_A02_A02', NULL, 'auth', '402881ef612b1f5b01612ce996f80581', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:47:16', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/xiaoe/words.html', 'webim', '3', NULL, 'left');
@ -7146,7 +7157,6 @@ INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cefb4120590', '语音留
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ceffa060591', '漏话列表', 'pub', 'A10_A01_A06', NULL, 'auth', '402881ef612b1f5b01612cee4fbb058a', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:49:40', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/callcenter/misscall/index.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612ceffa060591', '漏话列表', 'pub', 'A10_A01_A06', NULL, 'auth', '402881ef612b1f5b01612cee4fbb058a', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:49:40', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/callcenter/misscall/index.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf03d740592', '在线坐席', 'pub', 'A10_A02_A01', NULL, 'auth', '402881ef612b1f5b01612cee80ed058b', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:49:57', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/callcenter/online/index.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf03d740592', '在线坐席', 'pub', 'A10_A02_A01', NULL, 'auth', '402881ef612b1f5b01612cee80ed058b', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:49:57', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/callcenter/online/index.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf065f40593', '全部坐席', 'pub', 'A10_A02_A02', NULL, 'auth', '402881ef612b1f5b01612cee80ed058b', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:50:07', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/callcenter/agents/index.html', 'webim', '3', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf065f40593', '全部坐席', 'pub', 'A10_A02_A02', NULL, 'auth', '402881ef612b1f5b01612cee80ed058b', NULL, NULL, '&#x756e646566696e6564;', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:50:07', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/apps/callcenter/agents/index.html', 'webim', '3', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf11a140594', '坐席工作台', 'pub', 'B01', NULL, 'auth', '402888815d2fe37f015d2fe75cc80002', NULL, NULL, '', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:50:53', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/agent/index.html', 'webim', '1', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf147810595', '系统管理', 'pub', 'B02', NULL, 'auth', '402888815d2fe37f015d2fe75cc80002', NULL, NULL, '<i class=\"layui-icon\" style=\"position: relative;\">&#xe631;</i>', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:51:05', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/admin/content.html', 'webim', '1', NULL, 'left'); INSERT INTO `uk_sysdic` VALUES ('402881ef612b1f5b01612cf147810595', '系统管理', 'pub', 'B02', NULL, 'auth', '402888815d2fe37f015d2fe75cc80002', NULL, NULL, '<i class=\"layui-icon\" style=\"position: relative;\">&#xe631;</i>', NULL, NULL, '297e8c7b455798280145579c73e501c1', '2018-01-25 18:51:05', NULL, 0, 0, '402888815d2fe37f015d2fe75cc80002', 0, 0, '/admin/content.html', 'webim', '1', NULL, 'left');
INSERT INTO `uk_sysdic` VALUES ('402881fb61e49a9a0161e4a8a1260392', '过滤器类型', 'pub', 'com.dic.filter.modeltype', NULL, 'data', '0', '', NULL, NULL, NULL, NULL, '4028cac3614cd2f901614cf8be1f0324', '2018-03-02 11:01:52', NULL, 1, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL); INSERT INTO `uk_sysdic` VALUES ('402881fb61e49a9a0161e4a8a1260392', '过滤器类型', 'pub', 'com.dic.filter.modeltype', NULL, 'data', '0', '', NULL, NULL, NULL, NULL, '4028cac3614cd2f901614cf8be1f0324', '2018-03-02 11:01:52', NULL, 1, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `uk_sysdic` VALUES ('402881fb61e49a9a0161e4a925a20393', '过滤器取值方式', 'pub', 'com.dic.filter.convalue', NULL, 'data', '0', '', NULL, NULL, NULL, NULL, '4028cac3614cd2f901614cf8be1f0324', '2018-03-02 11:02:25', NULL, 1, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL); INSERT INTO `uk_sysdic` VALUES ('402881fb61e49a9a0161e4a925a20393', '过滤器取值方式', 'pub', 'com.dic.filter.convalue', NULL, 'data', '0', '', NULL, NULL, NULL, NULL, '4028cac3614cd2f901614cf8be1f0324', '2018-03-02 11:02:25', NULL, 1, 0, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL);
@ -7752,7 +7762,7 @@ CREATE TABLE `uk_system_message` (
`SECLEV` varchar(50) DEFAULT NULL COMMENT '启用SSL', `SECLEV` varchar(50) DEFAULT NULL COMMENT '启用SSL',
`SSLPORT` varchar(50) DEFAULT NULL COMMENT 'SSL端口', `SSLPORT` varchar(50) DEFAULT NULL COMMENT 'SSL端口',
`ORGI` varchar(32) DEFAULT NULL COMMENT '租户ID', `ORGI` varchar(32) DEFAULT NULL COMMENT '租户ID',
`URL` varchar(255) DEFAULT NULL COMMENT 'URL', `URL` text DEFAULT NULL COMMENT 'URL',
`smstype` varchar(32) DEFAULT NULL COMMENT '短信类型', `smstype` varchar(32) DEFAULT NULL COMMENT '短信类型',
`APPKEY` varchar(200) DEFAULT NULL COMMENT 'APPKEY', `APPKEY` varchar(200) DEFAULT NULL COMMENT 'APPKEY',
`APPSEC` varchar(200) DEFAULT NULL COMMENT 'APPSEC', `APPSEC` varchar(200) DEFAULT NULL COMMENT 'APPSEC',
@ -7837,7 +7847,7 @@ CREATE TABLE `uk_systemconfig` (
-- Records of uk_systemconfig -- Records of uk_systemconfig
-- ---------------------------- -- ----------------------------
BEGIN; BEGIN;
INSERT INTO `uk_systemconfig` VALUES ('2c93809364e0a6d00164ef6722270582', NULL, '春松客服-全渠道智能客服', NULL, 'cskefu', NULL, NULL, NULL, NULL, 'www.chatopera.com', NULL, NULL, '4028cac3614cd2f901614cf8be1f0324', '2018-07-31 08:14:30', NULL, NULL, NULL, NULL, NULL, '01', 'info', 0, NULL, NULL, '', 0, 0, '', '', '', '', '', '', NULL, 0, 0, 0, 0, '', '', NULL, NULL, '', '', NULL, 0, 0, NULL, NULL, NULL, 0, '', NULL, 0, 0, '租户', 0, 0, NULL, NULL, NULL); INSERT INTO `uk_systemconfig` VALUES ('2c93809364e0a6d00164ef6722270582', NULL, '春松客服-全渠道智能客服', NULL, 'cskefu', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '4028cac3614cd2f901614cf8be1f0324', '2018-07-31 08:14:30', NULL, NULL, NULL, NULL, NULL, '01', 'info', 0, NULL, NULL, '', 0, 0, '', '', '', '', '', '', NULL, 0, 0, 0, 0, '', '', NULL, NULL, '', '', NULL, 0, 0, NULL, NULL, NULL, 0, '', NULL, 0, 0, '租户', 0, 0, NULL, NULL, NULL);
COMMIT; COMMIT;
-- ---------------------------- -- ----------------------------
@ -8179,7 +8189,7 @@ CREATE TABLE `uk_userevent` (
`city` varchar(32) DEFAULT NULL COMMENT '城市', `city` varchar(32) DEFAULT NULL COMMENT '城市',
`isp` varchar(32) DEFAULT NULL COMMENT '运营商', `isp` varchar(32) DEFAULT NULL COMMENT '运营商',
`province` varchar(32) DEFAULT NULL COMMENT '省份', `province` varchar(32) DEFAULT NULL COMMENT '省份',
`url` varchar(255) DEFAULT NULL COMMENT '接入URL', `url` text DEFAULT NULL COMMENT '接入URL',
`sessionid` varchar(32) DEFAULT NULL COMMENT '会话ID', `sessionid` varchar(32) DEFAULT NULL COMMENT '会话ID',
`param` text COMMENT '请求参数', `param` text COMMENT '请求参数',
`times` int(11) DEFAULT NULL COMMENT '访问次数', `times` int(11) DEFAULT NULL COMMENT '访问次数',