diff --git a/contact-center/app/src/main/java/com/cskefu/cc/acd/middleware/visitor/ACDVisBodyParserMw.java b/contact-center/app/src/main/java/com/cskefu/cc/acd/middleware/visitor/ACDVisBodyParserMw.java index 7da261a2..9aae742a 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/acd/middleware/visitor/ACDVisBodyParserMw.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/acd/middleware/visitor/ACDVisBodyParserMw.java @@ -1,14 +1,14 @@ -/* - * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. - * , Licensed under the Chunsong Public +/* + * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. + * , Licensed under the Chunsong Public * License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html * 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. - * Copyright (C) 2019-2022 Chatopera Inc, , - * Licensed under the Apache License, Version 2.0, + * Copyright (C) 2019-2022 Chatopera Inc, , + * Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 */ @@ -22,12 +22,14 @@ import com.cskefu.cc.cache.Cache; import com.cskefu.cc.model.AgentUser; import com.cskefu.cc.model.AgentUserContacts; import com.cskefu.cc.model.Contacts; +import com.cskefu.cc.model.ExecuteResult; import com.cskefu.cc.persistence.repository.ContactsRepository; import com.cskefu.cc.persistence.repository.AgentUserContactsRepository; import com.cskefu.cc.proxy.AgentStatusProxy; import com.cskefu.cc.proxy.AgentUserProxy; import com.chatopera.compose4j.Functional; import com.chatopera.compose4j.Middleware; +import com.cskefu.cc.proxy.LicenseProxy; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,6 +64,9 @@ public class ACDVisBodyParserMw implements Middleware { @Autowired private ACDMessageHelper acdMessageHelper; + @Autowired + private LicenseProxy licenseProxy; + /** * 设置AgentUser基本信息 * @@ -87,6 +92,16 @@ public class ACDVisBodyParserMw implements Middleware { ctx.getOnlineUserId(), ctx.getOnlineUserNickname(), ctx.getAppid()); + + // 执行计费逻辑 + ExecuteResult writeDownResult = licenseProxy.writeDownAgentUserUsageInStore(p); + + if (writeDownResult.getRc() != ExecuteResult.RC_SUCC) { + // 配额操作失败,提示座席 + p.setLicenseVerifiedPass(false); + p.setLicenseBillingMsg(writeDownResult.getMsg()); + } + logger.info("[apply] create new agent user id {}", p.getId()); return p; }); diff --git a/contact-center/app/src/main/java/com/cskefu/cc/aspect/AgentUserAspect.java b/contact-center/app/src/main/java/com/cskefu/cc/aspect/AgentUserAspect.java index e342ff09..8b5f57e5 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/aspect/AgentUserAspect.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/aspect/AgentUserAspect.java @@ -1,14 +1,14 @@ -/* - * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. - * , Licensed under the Chunsong Public +/* + * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. + * , Licensed under the Chunsong Public * License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html * 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. - * Copyright (C) 2019-2022 Chatopera Inc, , - * Licensed under the Apache License, Version 2.0, + * Copyright (C) 2019-2022 Chatopera Inc, , + * Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 */ @@ -18,14 +18,17 @@ import com.cskefu.cc.basic.MainContext; import com.cskefu.cc.cache.Cache; import com.cskefu.cc.cache.RedisCommand; import com.cskefu.cc.cache.RedisKey; +import com.cskefu.cc.exception.BillingResourceException; import com.cskefu.cc.model.AgentUser; import com.cskefu.cc.proxy.AgentAuditProxy; +import com.cskefu.cc.proxy.LicenseProxy; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -51,6 +54,31 @@ public class AgentUserAspect { @Autowired private AgentAuditProxy agentAuditProxy; + @Autowired + private LicenseProxy licenseProxy; + + @Before("execution(* com.cskefu.cc.persistence.repository.AgentUserRepository.save(..))") + public void beforeSave(final JoinPoint joinPoint) { + final AgentUser agentUser = (AgentUser) joinPoint.getArgs()[0]; + + if (StringUtils.isBlank(agentUser.getId())) { + logger.info("[beforeSave] agentUser id is blank"); + + if (StringUtils.isNotBlank(agentUser.getOpttype()) && StringUtils.equals(MainContext.OptType.CHATBOT.toString(), agentUser.getOpttype())) { + // 机器人座席支持的对话,跳过计数 + agentUser.setLicenseVerifiedPass(true); + return; + } + + // 计数加一 + try { + licenseProxy.increResourceUsageInMetaKv(MainContext.BillingResource.AGENGUSER, 1); + } catch (BillingResourceException e) { + logger.error("[beforeSave] error", e.toString()); + } + } + } + @After("execution(* com.cskefu.cc.persistence.repository.AgentUserRepository.save(..))") public void save(final JoinPoint joinPoint) { final AgentUser agentUser = (AgentUser) joinPoint.getArgs()[0]; diff --git a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentAuditController.java b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentAuditController.java index e781cf0b..86c7e958 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentAuditController.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentAuditController.java @@ -71,9 +71,6 @@ public class AgentAuditController extends Handler { @Autowired private UserRepository userRes; - @Autowired - private AgentUserRepository agentUserRepository; - @Autowired private ChatMessageRepository chatMessageRepository; @@ -245,7 +242,7 @@ public class AgentAuditController extends Handler { view.addObject( "agentUserList", agentUserRes.findByStatusAndAgentnoIsNot( MainContext.AgentUserStatusEnum.INSERVICE.toString(), logined.getId(), defaultSort)); - List agentUserList = agentUserRepository.findByUserid(userid); + List agentUserList = agentUserRes.findByUserid(userid); view.addObject( "curagentuser", agentUserList != null && agentUserList.size() > 0 ? agentUserList.get(0) : null); @@ -266,7 +263,7 @@ public class AgentAuditController extends Handler { } ModelAndView view = request(super.createView(mainagentuser)); final User logined = super.getUser(request); - AgentUser agentUser = agentUserRepository.findById(id).orElse(null); + AgentUser agentUser = agentUserRes.findById(id).orElse(null); if (agentUser != null) { view.addObject("curagentuser", agentUser); diff --git a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentController.java b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentController.java index 7beb6194..5011d63d 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentController.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/AgentController.java @@ -1,1255 +1,1264 @@ /* - * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. - * , Licensed under the Chunsong Public + * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. + * , Licensed under the Chunsong Public * License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html * 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. - * Copyright (C) 2018-Jun. 2023 Chatopera Inc, , Licensed under the Apache License, Version 2.0, + * Copyright (C) 2018-Jun. 2023 Chatopera Inc, , Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 - * Copyright (C) 2017 优客服-多渠道客服系统, Licensed under the Apache License, Version 2.0, + * Copyright (C) 2017 优客服-多渠道客服系统, Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 */ - package com.cskefu.cc.controller.apps; - - import com.alibaba.fastjson.JSONObject; - import com.cskefu.cc.acd.ACDAgentService; - import com.cskefu.cc.acd.ACDWorkMonitor; - import com.cskefu.cc.activemq.BrokerPublisher; - import com.cskefu.cc.basic.Constants; - import com.cskefu.cc.basic.MainContext; - import com.cskefu.cc.basic.MainUtils; - import com.cskefu.cc.cache.Cache; - import com.cskefu.cc.controller.Handler; - import com.cskefu.cc.util.restapi.RestUtils; - import com.cskefu.cc.exception.CSKefuException; - import com.cskefu.cc.model.*; - import com.cskefu.cc.peer.PeerSyncIM; - import com.cskefu.cc.persistence.blob.JpaBlobHelper; - import com.cskefu.cc.persistence.interfaces.DataExchangeInterface; - import com.cskefu.cc.persistence.repository.*; - import com.cskefu.cc.proxy.*; - import com.cskefu.cc.socketio.message.ChatMessage; - import com.cskefu.cc.socketio.message.Message; - import com.cskefu.cc.util.Menu; - import com.cskefu.cc.util.PinYinTools; - import com.cskefu.cc.util.PropertiesEventUtil; - import org.apache.commons.lang3.StringUtils; - 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.context.annotation.Lazy; - import org.springframework.data.domain.Page; - import org.springframework.data.domain.PageRequest; - import org.springframework.data.domain.Sort; - import org.springframework.data.domain.Sort.Direction; - import org.springframework.http.HttpHeaders; - import org.springframework.http.HttpStatus; - import org.springframework.http.ResponseEntity; - import org.springframework.stereotype.Controller; - import org.springframework.ui.ModelMap; - import org.springframework.util.FileCopyUtils; - import org.springframework.web.bind.annotation.RequestMapping; - import org.springframework.web.bind.annotation.RequestParam; - import org.springframework.web.bind.annotation.ResponseBody; - import org.springframework.web.multipart.MultipartFile; - import org.springframework.web.servlet.ModelAndView; - - import jakarta.servlet.http.HttpServletRequest; - import jakarta.servlet.http.HttpServletResponse; - import jakarta.validation.Valid; - import java.io.File; - import java.io.IOException; - import java.text.ParseException; - import java.text.SimpleDateFormat; - import java.util.ArrayList; - import java.util.Date; - import java.util.List; - import java.util.Map; - - @Controller - @RequestMapping("/agent") - public class AgentController extends Handler { - - static final Logger logger = LoggerFactory.getLogger(AgentController.class); - - @Autowired - private ACDWorkMonitor acdWorkMonitor; - - @Autowired - private ACDAgentService acdAgentService; - - @Autowired - private ContactsRepository contactsRes; - - @Autowired - private PropertiesEventRepository propertiesEventRes; - - @Autowired - private AgentUserRepository agentUserRes; - - @Autowired - private AgentStatusRepository agentStatusRes; - - @Autowired - private AgentServiceRepository agentServiceRes; - - @Autowired - private PassportWebIMUserRepository onlineUserRes; - - @Autowired - private WeiXinUserRepository weiXinUserRes; - - @Autowired - private ServiceSummaryRepository serviceSummaryRes; - - @Autowired - private ChatMessageRepository chatMessageRes; - - @Autowired - private AgentProxy agentProxy; - - @Autowired - private TagRepository tagRes; - - @Autowired - private TagRelationRepository tagRelationRes; - - @Autowired - private AgentUserTaskRepository agentUserTaskRes; - - @Autowired - private UserRepository userRes; - - @Autowired - private StatusEventRepository statusEventRes; - - @Autowired - private AgentUserProxy agentUserProxy; - - @Autowired - private PbxHostRepository pbxHostRes; - - @Autowired - private AgentUserContactsRepository agentUserContactsRes; - - @Autowired - private StreamingFileRepository streamingFileRes; - - @Autowired - private JpaBlobHelper jpaBlobHelper; - - @Autowired - private BlackEntityProxy blackEntityProxy; - - @Autowired - private Cache cache; - - @Autowired - private AgentServiceProxy agentServiceProxy; - - @Value("${web.upload-path}") - private String webUploadPath; - - @Autowired - @Lazy - private PeerSyncIM peerSyncIM; - - @Autowired - private BrokerPublisher brokerPublisher; - - @Autowired - private AgentStatusProxy agentStatusProxy; - - @Autowired - private UserProxy userProxy; - - @Autowired - private OrganProxy organProxy; - - @Autowired - private OrganRepository organRes; - - @Autowired - private ChatbotRepository chatbotRes; - - /** - * 坐席从联系人列表进入坐席工作台和该联系人聊天 - * - * @param map - * @param request - * @param response - * @param sort - * @param channels 可立即触达的渠道 - * @param contactid - * @return - * @throws IOException - * @throws TemplateException - */ - @RequestMapping("/proactive") - @Menu(type = "apps", subtype = "agent") - public ModelAndView proactive( - ModelMap map, - HttpServletRequest request, - HttpServletResponse response, - @Valid String sort, - @Valid String channels, - @RequestParam(name = "contactid", required = false) String contactid) throws IOException, CSKefuException { - - if (StringUtils.isBlank(contactid)) { - logger.info("[chat] empty contactid, fast return error page."); - return request(super.createView("/public/error")); - } - - logger.info( - "[chat] contactid {}, channels {}", contactid, - channels); - - final User logined = super.getUser(request); - AgentUser agentUser = agentUserProxy.figureAgentUserBeforeChatWithContactInfo(channels, contactid, logined); - - if (agentUser != null) { - logger.info( - "[chat] resolved agentUser, figure view model data as index page, agentUserId {}, onlineUser Id {}, agentno {}, channel {}", - agentUser.getId(), agentUser.getUserid(), agentUser.getAgentno(), agentUser.getChanneltype()); - } else { - logger.info("[chat] can not resolve agentUser !!!"); - } - - // TODO 在agentUser没有得到的情况下,传回的前端信息增加提示,提示放在modelview中 - - // 处理原聊天数据 - ModelAndView view = request(super.createView("/apps/agent/index")); - agentUserProxy.buildIndexViewWithModels(view, map, request, response, sort, logined, agentUser); - return view; - } - - - /** - * 打开坐席工作台 - * - * @param map - * @param request - * @param response - * @param sort - * @return - * @throws IOException - * @throws TemplateException - */ - @RequestMapping("/index") - @Menu(type = "apps", subtype = "agent") - public ModelAndView index( - ModelMap map, - HttpServletRequest request, - HttpServletResponse response, - @Valid String sort) throws IOException { - final User logined = super.getUser(request); - ModelAndView view = request(super.createView("/apps/agent/index")); - agentUserProxy.buildIndexViewWithModels(view, map, request, response, sort, logined, null); - return view; - } - - @RequestMapping("/agentusers") - @Menu(type = "apps", subtype = "agent") - public ModelAndView agentusers(HttpServletRequest request, String userid) { - ModelAndView view = request(super.createView("/apps/agent/agentusers")); - User logined = super.getUser(request); - view.addObject( - "agentUserList", agentUserRes.findByAgentno(logined.getId(), - Sort.by(Direction.DESC, "status"))); - List agentUserList = agentUserRes.findByUserid(userid); - view.addObject( - "curagentuser", agentUserList != null && agentUserList.size() > 0 ? agentUserList.get(0) : null); - - return view; - } - - @RequestMapping("/agentuserpage") - @Menu(type = "apps", subtype = "agent") - public ModelAndView agentuserpage( - ModelMap map, - HttpServletRequest request, - String id, - Integer page, - Integer current) throws IOException { - String mainagentuserconter = "/apps/agent/mainagentuserconter"; - ModelAndView view = request(super.createView(mainagentuserconter)); - AgentUser agentUser = agentUserRes.findById(id).orElse(null); - if (agentUser != null) { - view.addObject("curagentuser", agentUser); - view.addObject( - "agentUserMessageList", this.chatMessageRes.findByusession(agentUser.getUserid(), current)); - } - return view; - } - - @RequestMapping("/agentuserLabel") - @Menu(type = "apps", subtype = "agent") - public ModelAndView agentuserLabel( - ModelMap map, - HttpServletRequest request, - String iconid) throws IOException { - String mainagentuserconter = "/apps/agent/mainagentuserconter"; - ModelAndView view = request(super.createView(mainagentuserconter)); - ChatMessage labelid = this.chatMessageRes.findById(iconid).orElse(null); - if (labelid != null) { - if (labelid.isIslabel() == false) { - labelid.setIslabel(true); - } else { - labelid.setIslabel(false); - } - chatMessageRes.save(labelid); - } - return view; - } - - @RequestMapping("/agentusersearch") - @Menu(type = "apps", subtype = "agent") - public ModelAndView agentusersearch( - ModelMap map, - HttpServletRequest request, - String id, - String search, - String condition - ) throws IOException { - String mainagentuserconter = "/apps/agent/mainagentusersearch"; - ModelAndView view = request(super.createView(mainagentuserconter)); - AgentUser agentUser = agentUserRes.findById(id).orElse(null); - - if (agentUser != null) { - Page agentUserMessageList = null; - if (condition.equals("label")) { - agentUserMessageList = this.chatMessageRes.findByislabel( - agentUser.getUserid(), search, PageRequest.of(0, 9999, Direction.DESC, "updatetime")); - } else { - agentUserMessageList = this.chatMessageRes.findByUsessionAndMessageContaining( - agentUser.getUserid(), search, PageRequest.of(0, 9999, Direction.DESC, "updatetime")); - } - view.addObject("agentUserMessageList", agentUserMessageList); - } - return view; - } - - - @RequestMapping("/agentusersearchdetails") - @Menu(type = "apps", subtype = "agent") - public ModelAndView agentusersearchdetails( - ModelMap map, - HttpServletRequest request, - String id, - String createtime, - String thisid) throws IOException, ParseException { - String mainagentuserconter = "/apps/agent/mainagentuserconter"; - ModelAndView view = request(super.createView(mainagentuserconter)); - AgentUser agentUser = agentUserRes.findById(id).orElse(null); - if (agentUser != null) { - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Date date = formatter.parse(createtime); - view.addObject("agentusersearchdetails", thisid); - view.addObject( - "agentUserMessageList", this.chatMessageRes.findByCreatetime(agentUser.getUserid(), date)); - view.addObject( - "agentUserMessageListnum", this.chatMessageRes.countByUsessionAndCreatetimeGreaterThanEqual( - agentUser.getUserid(), date)); - } - return (view); - } - - @RequestMapping("/agentuser") - @Menu(type = "apps", subtype = "agent") - public ModelAndView agentuser( - ModelMap map, - HttpServletRequest request, - String id, - String channel) throws IOException { - // set default Value as WEBIM - String mainagentuser = "/apps/agent/mainagentuser"; - switch (MainContext.ChannelType.toValue(channel)) { - case MESSENGER: - mainagentuser = "/apps/agent/mainagentuser_messenger"; - break; - case PHONE: - mainagentuser = "/apps/agent/mainagentuser_callout"; - break; - case SKYPE: - mainagentuser = "/apps/agent/mainagentuser_skype"; - break; - } - - ModelAndView view = request(super.createView(mainagentuser)); - final User logined = super.getUser(request); - AgentUser agentUser = agentUserRes.findById(id).orElse(null); - - if (agentUser != null) { - view.addObject("curagentuser", agentUser); - - Chatbot c = chatbotRes.findBySnsAccountIdentifier(agentUser.getAppid()); - if (c != null) { - view.addObject("aisuggest", c.isAisuggest()); - } - - view.addObject("inviteData", OnlineUserProxy.consult(agentUser.getAppid())); - AgentUserTask agentUserTask = agentUserTaskRes.findById(id).orElse(null); - agentUserTask.setTokenum(0); - agentUserTaskRes.save(agentUserTask); - - if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { - List summarizes = this.serviceSummaryRes.findByAgentserviceid( - agentUser.getAgentserviceid()); - if (summarizes.size() > 0) { - view.addObject("summary", summarizes.get(0)); - } - } - - view.addObject( - "agentUserMessageList", - this.chatMessageRes.findByUsession(agentUser.getUserid(), - PageRequest.of(0, 20, Direction.DESC, - "updatetime"))); - AgentService agentService = null; - if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { - agentService = this.agentServiceRes.findById(agentUser.getAgentserviceid()).orElse(null); - view.addObject("curAgentService", agentService); - if (agentService != null) { - /** - * 获取关联数据 - */ - agentServiceProxy.processRelaData(logined.getId(), agentService, map); - } - } - if (MainContext.ChannelType.WEIXIN.toString().equals(agentUser.getChanneltype())) { - List passportWechatUserList = weiXinUserRes.findByOpenid(agentUser.getUserid()); - if (passportWechatUserList.size() > 0) { - PassportWechatUser passportWechatUser = passportWechatUserList.get(0); - view.addObject("weiXinUser", passportWechatUser); - } - } else if (MainContext.ChannelType.WEBIM.toString().equals(agentUser.getChanneltype())) { - PassportWebIMUser passportWebIMUser = onlineUserRes.findById(agentUser.getUserid()).orElse(null); - if (passportWebIMUser != null) { - if (passportWebIMUser.getLogintime() != null) { - if (MainContext.OnlineUserStatusEnum.OFFLINE.toString().equals(passportWebIMUser.getStatus())) { - passportWebIMUser.setBetweentime( - (int) (passportWebIMUser.getUpdatetime().getTime() - passportWebIMUser.getLogintime().getTime())); - } else { - passportWebIMUser.setBetweentime( - (int) (System.currentTimeMillis() - passportWebIMUser.getLogintime().getTime())); - } - } - view.addObject("onlineUser", passportWebIMUser); - } - } else if (MainContext.ChannelType.PHONE.toString().equals(agentUser.getChanneltype())) { - if (agentService != null && StringUtils.isNotBlank(agentService.getOwner())) { - StatusEvent statusEvent = this.statusEventRes.findById(agentService.getOwner()).orElse(null); - if (statusEvent != null) { - if (StringUtils.isNotBlank(statusEvent.getHostid())) { - view.addObject("pbxHost", pbxHostRes.findById(statusEvent.getHostid()).orElse(null)); - } - view.addObject("statusEvent", statusEvent); - } - } - } - - view.addObject("serviceCount", this.agentServiceRes - .countByUseridAndStatus(agentUser - .getUserid(), - MainContext.AgentUserStatusEnum.END - .toString())); - view.addObject("tagRelationList", tagRelationRes.findByUserid(agentUser.getUserid())); - } - - AgentService service = agentServiceRes.findById(agentUser.getAgentserviceid()).orElse(null); - if (service != null) { - view.addObject("tags", tagRes.findByTagtypeAndSkill(MainContext.ModelType.USER.toString(), service.getSkill())); - } - return view; - } - - @RequestMapping("/workorders/list") - @Menu(type = "apps", subtype = "workorderslist") - public ModelAndView workorderslist(HttpServletRequest request, String contactsid, ModelMap map) { - if (MainContext.hasModule(Constants.CSKEFU_MODULE_WORKORDERS) && StringUtils.isNotBlank(contactsid)) { - DataExchangeInterface dataExchange = (DataExchangeInterface) MainContext.getContext().getBean( - "workorders"); - if (dataExchange != null) { - map.addAttribute( - "workOrdersList", - dataExchange.getListDataById(contactsid, super.getUser(request).getId())); - } - map.addAttribute("contactsid", contactsid); - } - return request(super.createView("/apps/agent/workorders")); - } - - /** - * 设置为就绪,置闲 - * - * @param request - * @return - */ - @RequestMapping(value = "/ready") - @Menu(type = "apps", subtype = "agent") - public ModelAndView ready(HttpServletRequest request) { - final User logined = super.getUser(request); - final AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( - logined.getId(), logined.getSkills()); - - // 缓存就绪状态 - agentProxy.ready(logined, agentStatus, false); - - // 为该坐席分配访客 - acdAgentService.assignVisitors(agentStatus.getAgentno()); - acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(), - agentStatus.getUsername(), - agentStatus.getAgentno(), - logined.isAdmin(), // 0代表admin - agentStatus.getAgentno(), - MainContext.AgentStatusEnum.NOTREADY.toString(), - MainContext.AgentStatusEnum.READY.toString(), - MainContext.AgentWorkType.MEIDIACHAT.toString(), - null); - - return request(super.createView("/public/success")); - } - - /** - * 将一个已经就绪的坐席设置为未就绪的状态 - * 这个接口并不会重新分配坐席的现在的服务中的访客给其它坐席 - * - * @param request - * @return - */ - @RequestMapping(value = "/notready") - @Menu(type = "apps", subtype = "agent") - public ModelAndView notready(HttpServletRequest request) { - final User logined = super.getUser(request); - logger.info("[notready] set user {} as not ready", logined.getId()); - AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( - logined.getId(), logined.getSkills()); - - agentStatus.setBusy(false); - agentStatus.setUpdatetime(new Date()); - agentStatus.setStatus(MainContext.AgentStatusEnum.NOTREADY.toString()); - cache.putAgentStatus(agentStatus); - agentStatusRes.save(agentStatus); - - agentStatusProxy.broadcastAgentsStatus("agent", "notready", agentStatus.getAgentno()); - - acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(), - agentStatus.getUsername(), - agentStatus.getAgentno(), - logined.isAdmin(), // 0代表admin - agentStatus.getAgentno(), - MainContext.AgentStatusEnum.READY.toString(), - MainContext.AgentStatusEnum.NOTREADY.toString(), - MainContext.AgentWorkType.MEIDIACHAT.toString(), - null); - - return request(super.createView("/public/success")); - } - - /** - * 设置状态:就绪,置忙 - * - * @param request - * @return - */ - @RequestMapping(value = "/busy") - @Menu(type = "apps", subtype = "agent") - public ModelAndView busy(HttpServletRequest request) { - final User logined = super.getUser(request); - logger.info("[busy] set user {} as busy", logined.getId()); - AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( - logined.getId(), logined.getSkills()); - - agentStatus.setBusy(true); - acdWorkMonitor.recordAgentStatus( - agentStatus.getAgentno(), - agentStatus.getUsername(), - agentStatus.getAgentno(), - super.getUser(request).isAdmin(), - agentStatus.getAgentno(), - MainContext.AgentStatusEnum.NOTBUSY.toString(), - MainContext.AgentStatusEnum.BUSY.toString(), - MainContext.AgentWorkType.MEIDIACHAT.toString(), - agentStatus.getUpdatetime()); - agentStatus.setUpdatetime(new Date()); - cache.putAgentStatus(agentStatus); - agentStatusRes.save(agentStatus); - - agentStatusProxy.broadcastAgentsStatus("agent", "busy", logined.getId()); - - return request(super.createView("/public/success")); - } - - /** - * 设置状态:就绪,置闲 - * - * @param request - * @return - */ - @RequestMapping(value = "/notbusy") - @Menu(type = "apps", subtype = "agent") - public ModelAndView notbusy(HttpServletRequest request) { - final User logined = super.getUser(request); - // 组织结构和权限数据 - logger.info("[notbusy] set user {} as not busy", logined.getId()); - - AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( - logined.getId(), logined.getSkills()); - - // 设置为就绪,置闲 - agentStatus.setBusy(false); - agentStatus.setUpdatetime(new Date()); - agentStatus.setStatus(MainContext.AgentStatusEnum.READY.toString()); - - // 更新工作记录 - acdWorkMonitor.recordAgentStatus( - agentStatus.getAgentno(), - agentStatus.getUsername(), - agentStatus.getAgentno(), - super.getUser(request).isAdmin(), - agentStatus.getAgentno(), - MainContext.AgentStatusEnum.BUSY.toString(), - MainContext.AgentStatusEnum.NOTBUSY.toString(), - MainContext.AgentWorkType.MEIDIACHAT.toString(), - agentStatus.getUpdatetime()); - - // 更新数据库和缓存 - cache.putAgentStatus(agentStatus); - agentStatusRes.save(agentStatus); - - // 重新分配访客给坐席 - acdAgentService.assignVisitors(agentStatus.getAgentno()); - - return request(super.createView("/public/success")); - } - - @RequestMapping(value = "/clean") - @Menu(type = "apps", subtype = "clean") - public ModelAndView clean(HttpServletRequest request) throws Exception { - List agentUserList = agentUserRes.findByAgentnoAndStatus( - super.getUser(request).getId(), MainContext.AgentUserStatusEnum.END.toString()); - List agentServiceList = new ArrayList<>(); - for (AgentUser agentUser : agentUserList) { - if (agentUser != null && super.getUser(request).getId().equals(agentUser.getAgentno())) { - acdAgentService.finishAgentUser(agentUser); - AgentService agentService = agentServiceRes.findById(agentUser.getAgentserviceid()).orElse(null); - if (agentService != null) { - agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString()); - agentServiceList.add(agentService); - } - } - } - agentServiceRes.saveAll(agentServiceList); - return request(super - .createView("redirect:/agent/index.html")); - } - - - /** - * 结束对话 - * 如果当前对话属于登录用户或登录用户为超级用户,则可以结束这个对话 - * - * @param request - * @param id - * @return - * @throws Exception - */ - @RequestMapping({"/end"}) - @Menu(type = "apps", subtype = "agent") - public ModelAndView end(HttpServletRequest request, @Valid String id) { - logger.info("[end] end id {}", id); - final User logined = super.getUser(request); - - final AgentUser agentUser = agentUserRes.findById(id).orElse(null); - - if (agentUser != null) { - if ((StringUtils.equals( - logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) { - // 删除访客-坐席关联关系,包括缓存 - try { - acdAgentService.finishAgentUser(agentUser); - } catch (CSKefuException e) { - // 未能删除成功 - logger.error("[end]", e); - } - } else { - logger.info("[end] Permission not fulfill."); - } - } - - return request(super - .createView("redirect:/agent/index.html")); - } - - @RequestMapping({"/readmsg"}) - @Menu(type = "apps", subtype = "agent") - public ModelAndView readmsg(HttpServletRequest request, @Valid String userid) { - - AgentUserTask agentUserTask = agentUserTaskRes.findById(userid).orElse(null); - agentUserTask.setTokenum(0); - agentUserTaskRes.save(agentUserTask); - return request(super.createView("/public/success")); - } - - @RequestMapping({"/blacklist/add"}) - @Menu(type = "apps", subtype = "blacklist") - public ModelAndView blacklistadd(ModelMap map, HttpServletRequest request, @Valid String agentuserid, @Valid String agentserviceid, @Valid String userid) - throws Exception { - map.addAttribute("agentuserid", agentuserid); - map.addAttribute("agentserviceid", agentserviceid); - map.addAttribute("userid", userid); - map.addAttribute("agentUser", agentUserRes.findById(userid).orElse(null)); - return request(super.createView("/apps/agent/blacklistadd")); - } - - @RequestMapping({"/blacklist/save"}) - @Menu(type = "apps", subtype = "blacklist") - public ModelAndView blacklist( - HttpServletRequest request, - @Valid String agentuserid, - @Valid String agentserviceid, - @Valid String userid, - @Valid BlackEntity blackEntity) - throws Exception { - logger.info("[blacklist] userid {}", userid); - final User logined = super.getUser(request); - - if (StringUtils.isBlank(userid)) { - throw new CSKefuException("Invalid userid"); - } - /** - * 添加黑名单 - * 一定时间后触发函数 - */ - JSONObject payload = new JSONObject(); - - int timeSeconds = blackEntity.getControltime() * 3600; - payload.put("userId", userid); - ModelAndView view = end(request, agentuserid); - - // 更新或创建黑名单 - blackEntityProxy.updateOrCreateBlackEntity(blackEntity, logined, userid, agentserviceid, agentuserid); - - // 创建定时任务 取消拉黑 - brokerPublisher.send( - Constants.WEBIM_SOCKETIO_ONLINE_USER_BLACKLIST, payload.toJSONString(), false, timeSeconds); - - return view; - } - - @RequestMapping("/tagrelation") - @Menu(type = "apps", subtype = "tagrelation") - public ModelAndView tagrelation(ModelMap map, HttpServletRequest request, @Valid String userid, @Valid String tagid, @Valid String dataid) { - TagRelation tagRelation = tagRelationRes.findByUseridAndTagid(userid, tagid); - if (tagRelation == null) { - tagRelation = new TagRelation(); - tagRelation.setUserid(userid); - tagRelation.setTagid(tagid); - tagRelation.setDataid(dataid); - tagRelationRes.save(tagRelation); - } else { - tagRelationRes.delete(tagRelation); - } - return request(super.createView("/public/success")); - } - - /** - * 坐席聊天时发送图片和文件 - * - * @param map - * @param request - * @param multipart - * @param id - * @param paste 是否是粘贴到chatbox的图片事件,此时发送者还没有执行发送 - * @return - * @throws IOException - */ - @RequestMapping("/image/upload") - @Menu(type = "im", subtype = "image") - public ResponseEntity upload( - ModelMap map, - HttpServletRequest request, - @RequestParam(value = "imgFile", required = false) MultipartFile multipart, - @Valid String id, - @Valid boolean paste) throws IOException { - logger.info("[upload] image file, agentUser id {}, paste {}", id, paste); - final User logined = super.getUser(request); - - JSONObject result = new JSONObject(); - HttpHeaders headers = RestUtils.header(); - final AgentUser agentUser = agentUserRes.findById(id).orElse(null); - - if (multipart != null && multipart.getOriginalFilename().lastIndexOf(".") > 0) { - try { - StreamingFile sf = agentProxy.saveFileIntoMySQLBlob(logined, multipart); - // 发送通知 - if (!paste) { - agentProxy.sendFileMessageByAgent(logined, agentUser, multipart, sf); - } - result.put("error", 0); - result.put("url", sf.getFileUrl()); - } catch (CSKefuException e) { - result.put("error", 1); - result.put("message", "请选择文件"); - } - } else { - result.put("error", 1); - result.put("message", "请选择图片文件"); - } - return new ResponseEntity<>(result.toString(), headers, HttpStatus.OK); - } - - @RequestMapping("/message/image") - @Menu(type = "resouce", subtype = "image", access = true) - public ModelAndView messageimage(HttpServletResponse response, ModelMap map, @Valid String id, @Valid String t) throws IOException { - ChatMessage message = chatMessageRes.findById(id).orElse(null); - map.addAttribute("chatMessage", message); - map.addAttribute("agentUser", cache.findOneAgentUserByUserId(message.getUserid())); +package com.cskefu.cc.controller.apps; + +import com.alibaba.fastjson.JSONObject; +import com.cskefu.cc.acd.ACDAgentService; +import com.cskefu.cc.acd.ACDWorkMonitor; +import com.cskefu.cc.activemq.BrokerPublisher; +import com.cskefu.cc.basic.Constants; +import com.cskefu.cc.basic.MainContext; +import com.cskefu.cc.basic.MainUtils; +import com.cskefu.cc.cache.Cache; +import com.cskefu.cc.controller.Handler; +import com.cskefu.cc.util.restapi.RestUtils; +import com.cskefu.cc.exception.CSKefuException; +import com.cskefu.cc.model.*; +import com.cskefu.cc.peer.PeerSyncIM; +import com.cskefu.cc.persistence.blob.JpaBlobHelper; +import com.cskefu.cc.persistence.interfaces.DataExchangeInterface; +import com.cskefu.cc.persistence.repository.*; +import com.cskefu.cc.proxy.*; +import com.cskefu.cc.socketio.message.ChatMessage; +import com.cskefu.cc.socketio.message.Message; +import com.cskefu.cc.util.Menu; +import com.cskefu.cc.util.PinYinTools; +import com.cskefu.cc.util.PropertiesEventUtil; +import org.apache.commons.lang3.StringUtils; +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.context.annotation.Lazy; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.ModelAndView; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; + +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Controller +@RequestMapping("/agent") +public class AgentController extends Handler { + + static final Logger logger = LoggerFactory.getLogger(AgentController.class); + + @Autowired + private ACDWorkMonitor acdWorkMonitor; + + @Autowired + private ACDAgentService acdAgentService; + + @Autowired + private ContactsRepository contactsRes; + + @Autowired + private PropertiesEventRepository propertiesEventRes; + + @Autowired + private AgentUserRepository agentUserRes; + + @Autowired + private AgentStatusRepository agentStatusRes; + + @Autowired + private AgentServiceRepository agentServiceRes; + + @Autowired + private PassportWebIMUserRepository onlineUserRes; + + @Autowired + private WeiXinUserRepository weiXinUserRes; + + @Autowired + private ServiceSummaryRepository serviceSummaryRes; + + @Autowired + private ChatMessageRepository chatMessageRes; + + @Autowired + private AgentProxy agentProxy; + + @Autowired + private TagRepository tagRes; + + @Autowired + private TagRelationRepository tagRelationRes; + + @Autowired + private AgentUserTaskRepository agentUserTaskRes; + + @Autowired + private UserRepository userRes; + + @Autowired + private StatusEventRepository statusEventRes; + + @Autowired + private AgentUserProxy agentUserProxy; + + @Autowired + private PbxHostRepository pbxHostRes; + + @Autowired + private AgentUserContactsRepository agentUserContactsRes; + + @Autowired + private StreamingFileRepository streamingFileRes; + + @Autowired + private JpaBlobHelper jpaBlobHelper; + + @Autowired + private BlackEntityProxy blackEntityProxy; + + @Autowired + private Cache cache; + + @Autowired + private AgentServiceProxy agentServiceProxy; + + @Value("${web.upload-path}") + private String webUploadPath; + + @Autowired + @Lazy + private PeerSyncIM peerSyncIM; + + @Autowired + private BrokerPublisher brokerPublisher; + + @Autowired + private AgentStatusProxy agentStatusProxy; + + @Autowired + private UserProxy userProxy; + + @Autowired + private OrganProxy organProxy; + + @Autowired + private OrganRepository organRes; + + @Autowired + private ChatbotRepository chatbotRes; + + /** + * 坐席从联系人列表进入坐席工作台和该联系人聊天 + * + * @param map + * @param request + * @param response + * @param sort + * @param channels 可立即触达的渠道 + * @param contactid + * @return + * @throws IOException + * @throws TemplateException + */ + @RequestMapping("/proactive") + @Menu(type = "apps", subtype = "agent") + public ModelAndView proactive( + ModelMap map, + HttpServletRequest request, + HttpServletResponse response, + @Valid String sort, + @Valid String channels, + @RequestParam(name = "contactid", required = false) String contactid) throws IOException, CSKefuException { + + if (StringUtils.isBlank(contactid)) { + logger.info("[chat] empty contactid, fast return error page."); + return request(super.createView("/public/error")); + } + + logger.info( + "[chat] contactid {}, channels {}", contactid, + channels); + + final User logined = super.getUser(request); + AgentUser agentUser = agentUserProxy.figureAgentUserBeforeChatWithContactInfo(channels, contactid, logined); + + if (agentUser != null) { + logger.info( + "[chat] resolved agentUser, figure view model data as index page, agentUserId {}, onlineUser Id {}, agentno {}, channel {}", + agentUser.getId(), agentUser.getUserid(), agentUser.getAgentno(), agentUser.getChanneltype()); + } else { + logger.info("[chat] can not resolve agentUser !!!"); + } + + // TODO 在agentUser没有得到的情况下,传回的前端信息增加提示,提示放在modelview中 + + // 处理原聊天数据 + ModelAndView view = request(super.createView("/apps/agent/index")); + agentUserProxy.buildIndexViewWithModels(view, map, request, response, sort, logined, agentUser); + return view; + } + + + /** + * 打开坐席工作台 + * + * @param map + * @param request + * @param response + * @param sort + * @return + * @throws IOException + * @throws TemplateException + */ + @RequestMapping("/index") + @Menu(type = "apps", subtype = "agent") + public ModelAndView index( + ModelMap map, + HttpServletRequest request, + HttpServletResponse response, + @Valid String sort, + boolean licenseVerifiedPass, + String licenseBillingMsg) throws IOException { + logger.info("[index] licenseVerifiedPass {}, licenseBillingMsg {}", licenseVerifiedPass, licenseBillingMsg); + final User logined = super.getUser(request); + ModelAndView view = request(super.createView("/apps/agent/index")); + agentUserProxy.buildIndexViewWithModels(view, map, request, response, sort, logined, null); + return view; + } + + @RequestMapping("/agentusers") + @Menu(type = "apps", subtype = "agent") + public ModelAndView agentusers(HttpServletRequest request, + String userid, + boolean licenseVerifiedPass, + String licenseBillingMsg) { + logger.info("[agentusers] userid {}, licenseVerifiedPass {}, licenseBillingMsg {}", userid, licenseVerifiedPass, licenseBillingMsg); + ModelAndView view = request(super.createView("/apps/agent/agentusers")); + User logined = super.getUser(request); + view.addObject( + "agentUserList", agentUserRes.findByAgentno(logined.getId(), + Sort.by(Direction.DESC, "status"))); + List agentUserList = agentUserRes.findByUserid(userid); + view.addObject( + "curagentuser", agentUserList != null && agentUserList.size() > 0 ? agentUserList.get(0) : null); + view.addObject("licenseVerifiedPass", licenseVerifiedPass); + view.addObject("licenseBillingMsg", licenseBillingMsg); + return view; + } + + @RequestMapping("/agentuserpage") + @Menu(type = "apps", subtype = "agent") + public ModelAndView agentuserpage( + ModelMap map, + HttpServletRequest request, + String id, + Integer page, + Integer current) throws IOException { + String mainagentuserconter = "/apps/agent/mainagentuserconter"; + ModelAndView view = request(super.createView(mainagentuserconter)); + AgentUser agentUser = agentUserRes.findById(id).orElse(null); + if (agentUser != null) { + view.addObject("curagentuser", agentUser); + view.addObject( + "agentUserMessageList", this.chatMessageRes.findByusession(agentUser.getUserid(), current)); + } + return view; + } + + @RequestMapping("/agentuserLabel") + @Menu(type = "apps", subtype = "agent") + public ModelAndView agentuserLabel( + ModelMap map, + HttpServletRequest request, + String iconid) throws IOException { + String mainagentuserconter = "/apps/agent/mainagentuserconter"; + ModelAndView view = request(super.createView(mainagentuserconter)); + ChatMessage labelid = this.chatMessageRes.findById(iconid).orElse(null); + if (labelid != null) { + if (labelid.isIslabel() == false) { + labelid.setIslabel(true); + } else { + labelid.setIslabel(false); + } + chatMessageRes.save(labelid); + } + return view; + } + + @RequestMapping("/agentusersearch") + @Menu(type = "apps", subtype = "agent") + public ModelAndView agentusersearch( + ModelMap map, + HttpServletRequest request, + String id, + String search, + String condition + ) throws IOException { + String mainagentuserconter = "/apps/agent/mainagentusersearch"; + ModelAndView view = request(super.createView(mainagentuserconter)); + AgentUser agentUser = agentUserRes.findById(id).orElse(null); + + if (agentUser != null) { + Page agentUserMessageList = null; + if (condition.equals("label")) { + agentUserMessageList = this.chatMessageRes.findByislabel( + agentUser.getUserid(), search, PageRequest.of(0, 9999, Direction.DESC, "updatetime")); + } else { + agentUserMessageList = this.chatMessageRes.findByUsessionAndMessageContaining( + agentUser.getUserid(), search, PageRequest.of(0, 9999, Direction.DESC, "updatetime")); + } + view.addObject("agentUserMessageList", agentUserMessageList); + } + return view; + } + + + @RequestMapping("/agentusersearchdetails") + @Menu(type = "apps", subtype = "agent") + public ModelAndView agentusersearchdetails( + ModelMap map, + HttpServletRequest request, + String id, + String createtime, + String thisid) throws IOException, ParseException { + String mainagentuserconter = "/apps/agent/mainagentuserconter"; + ModelAndView view = request(super.createView(mainagentuserconter)); + AgentUser agentUser = agentUserRes.findById(id).orElse(null); + if (agentUser != null) { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = formatter.parse(createtime); + view.addObject("agentusersearchdetails", thisid); + view.addObject( + "agentUserMessageList", this.chatMessageRes.findByCreatetime(agentUser.getUserid(), date)); + view.addObject( + "agentUserMessageListnum", this.chatMessageRes.countByUsessionAndCreatetimeGreaterThanEqual( + agentUser.getUserid(), date)); + } + return (view); + } + + @RequestMapping("/agentuser") + @Menu(type = "apps", subtype = "agent") + public ModelAndView agentuser( + ModelMap map, + HttpServletRequest request, + String id, + String channel) throws IOException { + // set default Value as WEBIM + String mainagentuser = "/apps/agent/mainagentuser"; + switch (MainContext.ChannelType.toValue(channel)) { + case MESSENGER: + mainagentuser = "/apps/agent/mainagentuser_messenger"; + break; + case PHONE: + mainagentuser = "/apps/agent/mainagentuser_callout"; + break; + case SKYPE: + mainagentuser = "/apps/agent/mainagentuser_skype"; + break; + } + + ModelAndView view = request(super.createView(mainagentuser)); + final User logined = super.getUser(request); + AgentUser agentUser = agentUserRes.findById(id).orElse(null); + + if (agentUser != null) { + view.addObject("curagentuser", agentUser); + + Chatbot c = chatbotRes.findBySnsAccountIdentifier(agentUser.getAppid()); + if (c != null) { + view.addObject("aisuggest", c.isAisuggest()); + } + + view.addObject("inviteData", OnlineUserProxy.consult(agentUser.getAppid())); + AgentUserTask agentUserTask = agentUserTaskRes.findById(id).orElse(null); + agentUserTask.setTokenum(0); + agentUserTaskRes.save(agentUserTask); + + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { + List summarizes = this.serviceSummaryRes.findByAgentserviceid( + agentUser.getAgentserviceid()); + if (summarizes.size() > 0) { + view.addObject("summary", summarizes.get(0)); + } + } + + view.addObject( + "agentUserMessageList", + this.chatMessageRes.findByUsession(agentUser.getUserid(), + PageRequest.of(0, 20, Direction.DESC, + "updatetime"))); + AgentService agentService = null; + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { + agentService = this.agentServiceRes.findById(agentUser.getAgentserviceid()).orElse(null); + view.addObject("curAgentService", agentService); + if (agentService != null) { + /** + * 获取关联数据 + */ + agentServiceProxy.processRelaData(logined.getId(), agentService, map); + } + } + if (MainContext.ChannelType.WEIXIN.toString().equals(agentUser.getChanneltype())) { + List passportWechatUserList = weiXinUserRes.findByOpenid(agentUser.getUserid()); + if (passportWechatUserList.size() > 0) { + PassportWechatUser passportWechatUser = passportWechatUserList.get(0); + view.addObject("weiXinUser", passportWechatUser); + } + } else if (MainContext.ChannelType.WEBIM.toString().equals(agentUser.getChanneltype())) { + PassportWebIMUser passportWebIMUser = onlineUserRes.findById(agentUser.getUserid()).orElse(null); + if (passportWebIMUser != null) { + if (passportWebIMUser.getLogintime() != null) { + if (MainContext.OnlineUserStatusEnum.OFFLINE.toString().equals(passportWebIMUser.getStatus())) { + passportWebIMUser.setBetweentime( + (int) (passportWebIMUser.getUpdatetime().getTime() - passportWebIMUser.getLogintime().getTime())); + } else { + passportWebIMUser.setBetweentime( + (int) (System.currentTimeMillis() - passportWebIMUser.getLogintime().getTime())); + } + } + view.addObject("onlineUser", passportWebIMUser); + } + } else if (MainContext.ChannelType.PHONE.toString().equals(agentUser.getChanneltype())) { + if (agentService != null && StringUtils.isNotBlank(agentService.getOwner())) { + StatusEvent statusEvent = this.statusEventRes.findById(agentService.getOwner()).orElse(null); + if (statusEvent != null) { + if (StringUtils.isNotBlank(statusEvent.getHostid())) { + view.addObject("pbxHost", pbxHostRes.findById(statusEvent.getHostid()).orElse(null)); + } + view.addObject("statusEvent", statusEvent); + } + } + } + + view.addObject("serviceCount", this.agentServiceRes + .countByUseridAndStatus(agentUser + .getUserid(), + MainContext.AgentUserStatusEnum.END + .toString())); + view.addObject("tagRelationList", tagRelationRes.findByUserid(agentUser.getUserid())); + } + + AgentService service = agentServiceRes.findById(agentUser.getAgentserviceid()).orElse(null); + if (service != null) { + view.addObject("tags", tagRes.findByTagtypeAndSkill(MainContext.ModelType.USER.toString(), service.getSkill())); + } + return view; + } + + @RequestMapping("/workorders/list") + @Menu(type = "apps", subtype = "workorderslist") + public ModelAndView workorderslist(HttpServletRequest request, String contactsid, ModelMap map) { + if (MainContext.hasModule(Constants.CSKEFU_MODULE_WORKORDERS) && StringUtils.isNotBlank(contactsid)) { + DataExchangeInterface dataExchange = (DataExchangeInterface) MainContext.getContext().getBean( + "workorders"); + if (dataExchange != null) { + map.addAttribute( + "workOrdersList", + dataExchange.getListDataById(contactsid, super.getUser(request).getId())); + } + map.addAttribute("contactsid", contactsid); + } + return request(super.createView("/apps/agent/workorders")); + } + + /** + * 设置为就绪,置闲 + * + * @param request + * @return + */ + @RequestMapping(value = "/ready") + @Menu(type = "apps", subtype = "agent") + public ModelAndView ready(HttpServletRequest request) { + final User logined = super.getUser(request); + final AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( + logined.getId(), logined.getSkills()); + + // 缓存就绪状态 + agentProxy.ready(logined, agentStatus, false); + + // 为该坐席分配访客 + acdAgentService.assignVisitors(agentStatus.getAgentno()); + acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(), + agentStatus.getUsername(), + agentStatus.getAgentno(), + logined.isAdmin(), // 0代表admin + agentStatus.getAgentno(), + MainContext.AgentStatusEnum.NOTREADY.toString(), + MainContext.AgentStatusEnum.READY.toString(), + MainContext.AgentWorkType.MEIDIACHAT.toString(), + null); + + return request(super.createView("/public/success")); + } + + /** + * 将一个已经就绪的坐席设置为未就绪的状态 + * 这个接口并不会重新分配坐席的现在的服务中的访客给其它坐席 + * + * @param request + * @return + */ + @RequestMapping(value = "/notready") + @Menu(type = "apps", subtype = "agent") + public ModelAndView notready(HttpServletRequest request) { + final User logined = super.getUser(request); + logger.info("[notready] set user {} as not ready", logined.getId()); + AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( + logined.getId(), logined.getSkills()); + + agentStatus.setBusy(false); + agentStatus.setUpdatetime(new Date()); + agentStatus.setStatus(MainContext.AgentStatusEnum.NOTREADY.toString()); + cache.putAgentStatus(agentStatus); + agentStatusRes.save(agentStatus); + + agentStatusProxy.broadcastAgentsStatus("agent", "notready", agentStatus.getAgentno()); + + acdWorkMonitor.recordAgentStatus(agentStatus.getAgentno(), + agentStatus.getUsername(), + agentStatus.getAgentno(), + logined.isAdmin(), // 0代表admin + agentStatus.getAgentno(), + MainContext.AgentStatusEnum.READY.toString(), + MainContext.AgentStatusEnum.NOTREADY.toString(), + MainContext.AgentWorkType.MEIDIACHAT.toString(), + null); + + return request(super.createView("/public/success")); + } + + /** + * 设置状态:就绪,置忙 + * + * @param request + * @return + */ + @RequestMapping(value = "/busy") + @Menu(type = "apps", subtype = "agent") + public ModelAndView busy(HttpServletRequest request) { + final User logined = super.getUser(request); + logger.info("[busy] set user {} as busy", logined.getId()); + AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( + logined.getId(), logined.getSkills()); + + agentStatus.setBusy(true); + acdWorkMonitor.recordAgentStatus( + agentStatus.getAgentno(), + agentStatus.getUsername(), + agentStatus.getAgentno(), + super.getUser(request).isAdmin(), + agentStatus.getAgentno(), + MainContext.AgentStatusEnum.NOTBUSY.toString(), + MainContext.AgentStatusEnum.BUSY.toString(), + MainContext.AgentWorkType.MEIDIACHAT.toString(), + agentStatus.getUpdatetime()); + agentStatus.setUpdatetime(new Date()); + cache.putAgentStatus(agentStatus); + agentStatusRes.save(agentStatus); + + agentStatusProxy.broadcastAgentsStatus("agent", "busy", logined.getId()); + + return request(super.createView("/public/success")); + } + + /** + * 设置状态:就绪,置闲 + * + * @param request + * @return + */ + @RequestMapping(value = "/notbusy") + @Menu(type = "apps", subtype = "agent") + public ModelAndView notbusy(HttpServletRequest request) { + final User logined = super.getUser(request); + // 组织结构和权限数据 + logger.info("[notbusy] set user {} as not busy", logined.getId()); + + AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentno( + logined.getId(), logined.getSkills()); + + // 设置为就绪,置闲 + agentStatus.setBusy(false); + agentStatus.setUpdatetime(new Date()); + agentStatus.setStatus(MainContext.AgentStatusEnum.READY.toString()); + + // 更新工作记录 + acdWorkMonitor.recordAgentStatus( + agentStatus.getAgentno(), + agentStatus.getUsername(), + agentStatus.getAgentno(), + super.getUser(request).isAdmin(), + agentStatus.getAgentno(), + MainContext.AgentStatusEnum.BUSY.toString(), + MainContext.AgentStatusEnum.NOTBUSY.toString(), + MainContext.AgentWorkType.MEIDIACHAT.toString(), + agentStatus.getUpdatetime()); + + // 更新数据库和缓存 + cache.putAgentStatus(agentStatus); + agentStatusRes.save(agentStatus); + + // 重新分配访客给坐席 + acdAgentService.assignVisitors(agentStatus.getAgentno()); + + return request(super.createView("/public/success")); + } + + @RequestMapping(value = "/clean") + @Menu(type = "apps", subtype = "clean") + public ModelAndView clean(HttpServletRequest request) throws Exception { + List agentUserList = agentUserRes.findByAgentnoAndStatus( + super.getUser(request).getId(), MainContext.AgentUserStatusEnum.END.toString()); + List agentServiceList = new ArrayList<>(); + for (AgentUser agentUser : agentUserList) { + if (agentUser != null && super.getUser(request).getId().equals(agentUser.getAgentno())) { + acdAgentService.finishAgentUser(agentUser); + AgentService agentService = agentServiceRes.findById(agentUser.getAgentserviceid()).orElse(null); + if (agentService != null) { + agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString()); + agentServiceList.add(agentService); + } + } + } + agentServiceRes.saveAll(agentServiceList); + return request(super + .createView("redirect:/agent/index.html")); + } + + + /** + * 结束对话 + * 如果当前对话属于登录用户或登录用户为超级用户,则可以结束这个对话 + * + * @param request + * @param id + * @return + * @throws Exception + */ + @RequestMapping({"/end"}) + @Menu(type = "apps", subtype = "agent") + public ModelAndView end(HttpServletRequest request, @Valid String id) { + logger.info("[end] end id {}", id); + final User logined = super.getUser(request); + + final AgentUser agentUser = agentUserRes.findById(id).orElse(null); + + if (agentUser != null) { + if ((StringUtils.equals( + logined.getId(), agentUser.getAgentno()) || logined.isAdmin())) { + // 删除访客-坐席关联关系,包括缓存 + try { + acdAgentService.finishAgentUser(agentUser); + } catch (CSKefuException e) { + // 未能删除成功 + logger.error("[end]", e); + } + } else { + logger.info("[end] Permission not fulfill."); + } + } + + return request(super + .createView("redirect:/agent/index.html")); + } + + @RequestMapping({"/readmsg"}) + @Menu(type = "apps", subtype = "agent") + public ModelAndView readmsg(HttpServletRequest request, @Valid String userid) { + + AgentUserTask agentUserTask = agentUserTaskRes.findById(userid).orElse(null); + agentUserTask.setTokenum(0); + agentUserTaskRes.save(agentUserTask); + return request(super.createView("/public/success")); + } + + @RequestMapping({"/blacklist/add"}) + @Menu(type = "apps", subtype = "blacklist") + public ModelAndView blacklistadd(ModelMap map, HttpServletRequest request, @Valid String agentuserid, @Valid String agentserviceid, @Valid String userid) + throws Exception { + map.addAttribute("agentuserid", agentuserid); + map.addAttribute("agentserviceid", agentserviceid); + map.addAttribute("userid", userid); + map.addAttribute("agentUser", agentUserRes.findById(userid).orElse(null)); + return request(super.createView("/apps/agent/blacklistadd")); + } + + @RequestMapping({"/blacklist/save"}) + @Menu(type = "apps", subtype = "blacklist") + public ModelAndView blacklist( + HttpServletRequest request, + @Valid String agentuserid, + @Valid String agentserviceid, + @Valid String userid, + @Valid BlackEntity blackEntity) + throws Exception { + logger.info("[blacklist] userid {}", userid); + final User logined = super.getUser(request); + + if (StringUtils.isBlank(userid)) { + throw new CSKefuException("Invalid userid"); + } + /** + * 添加黑名单 + * 一定时间后触发函数 + */ + JSONObject payload = new JSONObject(); + + int timeSeconds = blackEntity.getControltime() * 3600; + payload.put("userId", userid); + ModelAndView view = end(request, agentuserid); + + // 更新或创建黑名单 + blackEntityProxy.updateOrCreateBlackEntity(blackEntity, logined, userid, agentserviceid, agentuserid); + + // 创建定时任务 取消拉黑 + brokerPublisher.send( + Constants.WEBIM_SOCKETIO_ONLINE_USER_BLACKLIST, payload.toJSONString(), false, timeSeconds); + + return view; + } + + @RequestMapping("/tagrelation") + @Menu(type = "apps", subtype = "tagrelation") + public ModelAndView tagrelation(ModelMap map, HttpServletRequest request, @Valid String userid, @Valid String tagid, @Valid String dataid) { + TagRelation tagRelation = tagRelationRes.findByUseridAndTagid(userid, tagid); + if (tagRelation == null) { + tagRelation = new TagRelation(); + tagRelation.setUserid(userid); + tagRelation.setTagid(tagid); + tagRelation.setDataid(dataid); + tagRelationRes.save(tagRelation); + } else { + tagRelationRes.delete(tagRelation); + } + return request(super.createView("/public/success")); + } + + /** + * 坐席聊天时发送图片和文件 + * + * @param map + * @param request + * @param multipart + * @param id + * @param paste 是否是粘贴到chatbox的图片事件,此时发送者还没有执行发送 + * @return + * @throws IOException + */ + @RequestMapping("/image/upload") + @Menu(type = "im", subtype = "image") + public ResponseEntity upload( + ModelMap map, + HttpServletRequest request, + @RequestParam(value = "imgFile", required = false) MultipartFile multipart, + @Valid String id, + @Valid boolean paste) throws IOException { + logger.info("[upload] image file, agentUser id {}, paste {}", id, paste); + final User logined = super.getUser(request); + + JSONObject result = new JSONObject(); + HttpHeaders headers = RestUtils.header(); + final AgentUser agentUser = agentUserRes.findById(id).orElse(null); + + if (multipart != null && multipart.getOriginalFilename().lastIndexOf(".") > 0) { + try { + StreamingFile sf = agentProxy.saveFileIntoMySQLBlob(logined, multipart); + // 发送通知 + if (!paste) { + agentProxy.sendFileMessageByAgent(logined, agentUser, multipart, sf); + } + result.put("error", 0); + result.put("url", sf.getFileUrl()); + } catch (CSKefuException e) { + result.put("error", 1); + result.put("message", "请选择文件"); + } + } else { + result.put("error", 1); + result.put("message", "请选择图片文件"); + } + return new ResponseEntity<>(result.toString(), headers, HttpStatus.OK); + } + + @RequestMapping("/message/image") + @Menu(type = "resouce", subtype = "image", access = true) + public ModelAndView messageimage(HttpServletResponse response, ModelMap map, @Valid String id, @Valid String t) throws IOException { + ChatMessage message = chatMessageRes.findById(id).orElse(null); + map.addAttribute("chatMessage", message); + map.addAttribute("agentUser", cache.findOneAgentUserByUserId(message.getUserid())); /*if(StringUtils.isNotBlank(t)){ map.addAttribute("t", t) ; }*/ - map.addAttribute("t", true); - return request(super.createView("/apps/agent/media/messageimage")); - } + map.addAttribute("t", true); + return request(super.createView("/apps/agent/media/messageimage")); + } - @RequestMapping("/message/image/upload") - @Menu(type = "im", subtype = "image") - public ModelAndView messageimage( - ModelMap map, - HttpServletRequest request, - @RequestParam(value = "image", required = false) MultipartFile image, - @Valid String id, - @Valid String userid, - @Valid String fileid) throws IOException { - logger.info("[messageimage] userid {}, chat message id {}, fileid {}", userid, id, fileid); - if (image != null && StringUtils.isNotBlank(fileid)) { - File tempFile = File.createTempFile(fileid, ".png"); - try { - // 创建临时图片文件 - if (!tempFile.getParentFile().exists()) { - tempFile.getParentFile().mkdirs(); - } - // 写入临时文件 - FileCopyUtils.copy(image.getBytes(), tempFile); - ChatMessage chatMessage = chatMessageRes.findById(id).orElse(null); - chatMessage.setCooperation(true); - chatMessageRes.save(chatMessage); + @RequestMapping("/message/image/upload") + @Menu(type = "im", subtype = "image") + public ModelAndView messageimage( + ModelMap map, + HttpServletRequest request, + @RequestParam(value = "image", required = false) MultipartFile image, + @Valid String id, + @Valid String userid, + @Valid String fileid) throws IOException { + logger.info("[messageimage] userid {}, chat message id {}, fileid {}", userid, id, fileid); + if (image != null && StringUtils.isNotBlank(fileid)) { + File tempFile = File.createTempFile(fileid, ".png"); + try { + // 创建临时图片文件 + if (!tempFile.getParentFile().exists()) { + tempFile.getParentFile().mkdirs(); + } + // 写入临时文件 + FileCopyUtils.copy(image.getBytes(), tempFile); + ChatMessage chatMessage = chatMessageRes.findById(id).orElse(null); + chatMessage.setCooperation(true); + chatMessageRes.save(chatMessage); - // 写入协作文件 - String fileName = "upload/" + fileid + "_cooperation"; - File imageFile = new File(webUploadPath, fileName); - MainUtils.scaleImage(imageFile, tempFile, 0.1F); + // 写入协作文件 + String fileName = "upload/" + fileid + "_cooperation"; + File imageFile = new File(webUploadPath, fileName); + MainUtils.scaleImage(imageFile, tempFile, 0.1F); - // 保存到数据库 - StreamingFile sf = streamingFileRes.findById(fileid).orElse(null); - if (sf != null) { - sf.setCooperation(jpaBlobHelper.createBlobWithFile(imageFile)); - streamingFileRes.save(sf); - } + // 保存到数据库 + StreamingFile sf = streamingFileRes.findById(fileid).orElse(null); + if (sf != null) { + sf.setCooperation(jpaBlobHelper.createBlobWithFile(imageFile)); + streamingFileRes.save(sf); + } - cache.findOneAgentUserByUserId( - chatMessage.getUserid()).ifPresent(p -> { - Message outMessage = new Message(); - outMessage.setMessage("/res/image.html?id=" + fileid + "&cooperation=true"); - outMessage.setFilename(imageFile.getName()); - outMessage.setAttachmentid(chatMessage.getAttachmentid()); - outMessage.setFilesize((int) imageFile.length()); - outMessage.setMessageType(MainContext.MediaType.ACTION.toString()); - outMessage.setCalltype(MainContext.CallType.INVITE.toString()); - outMessage.setCreatetime(Constants.DISPLAY_DATE_FORMATTER.format(new Date())); - outMessage.setAgentUser(p); + cache.findOneAgentUserByUserId( + chatMessage.getUserid()).ifPresent(p -> { + Message outMessage = new Message(); + outMessage.setMessage("/res/image.html?id=" + fileid + "&cooperation=true"); + outMessage.setFilename(imageFile.getName()); + outMessage.setAttachmentid(chatMessage.getAttachmentid()); + outMessage.setFilesize((int) imageFile.length()); + outMessage.setMessageType(MainContext.MediaType.ACTION.toString()); + outMessage.setCalltype(MainContext.CallType.INVITE.toString()); + outMessage.setCreatetime(Constants.DISPLAY_DATE_FORMATTER.format(new Date())); + outMessage.setAgentUser(p); - peerSyncIM.send( - MainContext.ReceiverType.VISITOR, - MainContext.ChannelType.toValue(p.getChanneltype()), - p.getAppid(), - MainContext.MessageType.MESSAGE, - p.getUserid(), - outMessage, - true); - }); - } finally { - if (tempFile.exists()) { - tempFile.delete(); - } - } - } - return request(super.createView("/public/success")); - } + peerSyncIM.send( + MainContext.ReceiverType.VISITOR, + MainContext.ChannelType.toValue(p.getChanneltype()), + p.getAppid(), + MainContext.MessageType.MESSAGE, + p.getUserid(), + outMessage, + true); + }); + } finally { + if (tempFile.exists()) { + tempFile.delete(); + } + } + } + return request(super.createView("/public/success")); + } - /** - * 坐席会话关联联系人 - * - * @param map - * @param request - * @param contactsid 联系人ID - * @param userid 访客ID - * @param agentserviceid 坐席服务ID - * @param agentuserid 坐席ID - * @return - */ - @RequestMapping(value = "/contacts") - @Menu(type = "apps", subtype = "contacts") - public ModelAndView contacts( - ModelMap map, - final HttpServletRequest request, - @Valid String contactsid, - @Valid String userid, - @Valid String agentserviceid, - @Valid String agentuserid) throws CSKefuException { - logger.info( - "[contacts] contactsid {}, userid {}, agentserviceid {}, agentuserid {}", contactsid, userid, - agentserviceid, agentuserid); + /** + * 坐席会话关联联系人 + * + * @param map + * @param request + * @param contactsid 联系人ID + * @param userid 访客ID + * @param agentserviceid 坐席服务ID + * @param agentuserid 坐席ID + * @return + */ + @RequestMapping(value = "/contacts") + @Menu(type = "apps", subtype = "contacts") + public ModelAndView contacts( + ModelMap map, + final HttpServletRequest request, + @Valid String contactsid, + @Valid String userid, + @Valid String agentserviceid, + @Valid String agentuserid) throws CSKefuException { + logger.info( + "[contacts] contactsid {}, userid {}, agentserviceid {}, agentuserid {}", contactsid, userid, + agentserviceid, agentuserid); - final User logined = super.getUser(request); + final User logined = super.getUser(request); - if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(contactsid)) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(contactsid)) { - /** - * 获得联系人 - */ - Contacts contacts = contactsRes.findById(contactsid).orElse(null); - if (contacts != null) { - map.addAttribute("contacts", contacts); - } + /** + * 获得联系人 + */ + Contacts contacts = contactsRes.findById(contactsid).orElse(null); + if (contacts != null) { + map.addAttribute("contacts", contacts); + } - /** - * 在关联联系人后,更新AgentUser的显示的名字 - */ - AgentUser agentUser = agentUserRes.findById(agentuserid).orElse(null); - if (agentUser != null) { - agentUser.setUsername(contacts.getName()); - agentUser.setNickname(contacts.getName()); - agentUserRes.save(agentUser); - } + /** + * 在关联联系人后,更新AgentUser的显示的名字 + */ + AgentUser agentUser = agentUserRes.findById(agentuserid).orElse(null); + if (agentUser != null) { + agentUser.setUsername(contacts.getName()); + agentUser.setNickname(contacts.getName()); + agentUserRes.save(agentUser); + } - /** - * 更新OnlineUser - */ - PassportWebIMUser passportWebIMUser = onlineUserRes.findOneByUserid(userid); - if (passportWebIMUser != null) { - passportWebIMUser.setContactsid(contactsid); - passportWebIMUser.setUsername(contacts.getName()); - passportWebIMUser.setUpdateuser(logined.getUname()); - onlineUserRes.save(passportWebIMUser); - } + /** + * 更新OnlineUser + */ + PassportWebIMUser passportWebIMUser = onlineUserRes.findOneByUserid(userid); + if (passportWebIMUser != null) { + passportWebIMUser.setContactsid(contactsid); + passportWebIMUser.setUsername(contacts.getName()); + passportWebIMUser.setUpdateuser(logined.getUname()); + onlineUserRes.save(passportWebIMUser); + } - AgentService agentService = agentServiceRes.findById(agentserviceid).orElse(null); - if (agentService != null) { - agentService.setContactsid(contactsid); - agentService.setUsername(contacts.getName()); - agentServiceRes.save(agentService); + AgentService agentService = agentServiceRes.findById(agentserviceid).orElse(null); + if (agentService != null) { + agentService.setContactsid(contactsid); + agentService.setUsername(contacts.getName()); + agentServiceRes.save(agentService); - AgentUserContacts agentUserContacts = agentUserContactsRes.findOneByUserid( - userid).orElseGet(() -> { - AgentUserContacts p = new AgentUserContacts(); + AgentUserContacts agentUserContacts = agentUserContactsRes.findOneByUserid( + userid).orElseGet(() -> { + AgentUserContacts p = new AgentUserContacts(); - p.setUserid(userid); - p.setCreater(super.getUser(request).getId()); - p.setCreatetime(new Date()); - return p; - }); + p.setUserid(userid); + p.setCreater(super.getUser(request).getId()); + p.setCreatetime(new Date()); + return p; + }); - agentUserContacts.setContactsid(contactsid); - agentUserContacts.setAppid(agentService.getAppid()); - agentUserContacts.setChanneltype(agentService.getChanneltype()); + agentUserContacts.setContactsid(contactsid); + agentUserContacts.setAppid(agentService.getAppid()); + agentUserContacts.setChanneltype(agentService.getChanneltype()); - agentUserContactsRes.save(agentUserContacts); - } - } - return request(super.createView("/apps/agent/contacts")); - } + agentUserContactsRes.save(agentUserContacts); + } + } + return request(super.createView("/apps/agent/contacts")); + } - @RequestMapping(value = "/clean/associated") - @Menu(type = "apps", subtype = "cleanassociated") - public ModelAndView cleanAssociated(ModelMap map, HttpServletRequest request, final @RequestParam String currentAgentUserContactsId) { - String contactsid = null; - if (StringUtils.isNotEmpty(currentAgentUserContactsId)) { - AgentUserContacts agentUserContacts = agentUserContactsRes.findById(currentAgentUserContactsId).orElse(null); - if (agentUserContacts != null) { - agentUserContactsRes.delete(agentUserContacts); - } - } + @RequestMapping(value = "/clean/associated") + @Menu(type = "apps", subtype = "cleanassociated") + public ModelAndView cleanAssociated(ModelMap map, HttpServletRequest request, final @RequestParam String currentAgentUserContactsId) { + String contactsid = null; + if (StringUtils.isNotEmpty(currentAgentUserContactsId)) { + AgentUserContacts agentUserContacts = agentUserContactsRes.findById(currentAgentUserContactsId).orElse(null); + if (agentUserContacts != null) { + agentUserContactsRes.delete(agentUserContacts); + } + } - return request(super.createView("/apps/agent/contacts")); - } + return request(super.createView("/apps/agent/contacts")); + } - @ResponseBody - @RequestMapping(value = "/evaluation") - @Menu(type = "apps", subtype = "evaluation") - public String evaluation(HttpServletRequest request, @Valid String agentuserid) { - AgentUser agentUser = agentUserRes.findById(agentuserid).orElse(null); + @ResponseBody + @RequestMapping(value = "/evaluation") + @Menu(type = "apps", subtype = "evaluation") + public String evaluation(HttpServletRequest request, @Valid String agentuserid) { + AgentUser agentUser = agentUserRes.findById(agentuserid).orElse(null); - Message outMessage = new Message(); - outMessage.setChannelMessage(agentUser); - outMessage.setAgentUser(agentUser); + Message outMessage = new Message(); + outMessage.setChannelMessage(agentUser); + outMessage.setAgentUser(agentUser); - peerSyncIM.send( - MainContext.ReceiverType.VISITOR, - MainContext.ChannelType.toValue(agentUser.getChanneltype()), - agentUser.getAppid(), - MainContext.MessageType.SATISFACTION, - agentUser.getUserid(), - outMessage, - true); + peerSyncIM.send( + MainContext.ReceiverType.VISITOR, + MainContext.ChannelType.toValue(agentUser.getChanneltype()), + agentUser.getAppid(), + MainContext.MessageType.SATISFACTION, + agentUser.getUserid(), + outMessage, + true); - return "ok"; - } + return "ok"; + } - @RequestMapping(value = "/summary") - @Menu(type = "apps", subtype = "summary") - public ModelAndView summary( - ModelMap map, - HttpServletRequest request, - @Valid String userid, - @Valid String agentserviceid, - @Valid String agentuserid, - @Valid String channel) { - if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { - AgentUser agentUser = this.agentUserRes.findById(agentuserid).orElse(null); - if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentserviceid())) { - List summaries = this.serviceSummaryRes.findByAgentserviceid( - agentUser.getAgentserviceid()); - if (summaries.size() > 0) { - map.addAttribute("summary", summaries.get(0)); - } - } - Organ currentOrgan = super.getOrgan(request); - if(null!=currentOrgan){ - map.addAttribute( - "tags", tagRes.findByTagtypeAndSkill( - MainContext.ModelType.CCSUMMARY.toString(), currentOrgan.getParent())); - } - - - map.addAttribute("userid", userid); - map.addAttribute("agentserviceid", agentserviceid); - map.addAttribute("agentuserid", agentuserid); - map.addAttribute("channel", channel); - } - return request(super.createView("/apps/agent/summary")); - } - - @RequestMapping(value = "/summary/save") - @Menu(type = "apps", subtype = "summarysave") - public ModelAndView summarysave( - ModelMap map, - HttpServletRequest request, - @Valid AgentServiceSummary summary, - @Valid String contactsid, - @Valid String userid, - @Valid String agentserviceid, - @Valid String agentuserid, - @Valid String channel) { - if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { - summary.setCreater(super.getUser(request).getId()); - summary.setCreatetime(new Date()); - AgentService service = agentServiceRes.findById(agentserviceid).orElse(null); - summary.setAgent(service.getAgentno()); - summary.setAgentno(service.getAgentno()); - summary.setSkill(service.getSkill()); - summary.setUsername(service.getUsername()); - summary.setAgentusername(service.getAgentusername()); - summary.setChannel(service.getChanneltype()); - summary.setContactsid(contactsid); - summary.setLogindate(service.getLogindate()); - summary.setContactsid(service.getContactsid()); - summary.setEmail(service.getEmail()); - summary.setPhonenumber(service.getPhone()); - serviceSummaryRes.save(summary); - } - - return request(super.createView( - "redirect:/agent/agentuser.html?id=" + agentuserid + "&channel=" + channel)); - } - - /** - * 坐席转接窗口 - * - * @param map - * @param request - * @param userid - * @param agentserviceid - * @param agentuserid - * @return - */ - @RequestMapping(value = "/transfer") - @Menu(type = "apps", subtype = "transfer") - public ModelAndView transfer( - ModelMap map, - final HttpServletRequest request, - final @Valid String userid, - final @Valid String agentserviceid, - final @Valid String agentuserid) { - logger.info("[transfer] userId {}, agentUser {}", userid, agentuserid); - final User logined = super.getUser(request); - - Organ targetOrgan = super.getOrgan(request); - Map ownOrgans = organProxy.findAllOrganByParent(targetOrgan); - - if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { - // 列出所有技能组 - List skillGroups = organRes.findByIdInAndSkill(ownOrgans.keySet(), true); - - // 选择当前用户的默认技能组 - AgentService agentService = agentServiceRes.findById(agentserviceid).orElse(null); - - String currentOrgan = agentService.getSkill(); - - if (StringUtils.isBlank(currentOrgan)) { - if (!skillGroups.isEmpty()) { - currentOrgan = skillGroups.get(0).getId(); - } - } - logger.info("[transfer] set current organ as {}", currentOrgan); - // 列出所有在线的坐席,排除本身 - List userids = new ArrayList<>(); - final Map agentStatusMap = cache.findAllReadyAgentStatus(); - - for (final String o : agentStatusMap.keySet()) { - if (!StringUtils.equals(o, logined.getId())) { - userids.add(o); - } - } - - logger.info("[transfer] get all userids except mine, {}", StringUtils.join(userids, "\t")); - - final List userList = userRes.findAllById(userids); - for (final User o : userList) { - o.setAgentStatus(agentStatusMap.get(o.getId())); - // find user's skills - userProxy.attachOrgansPropertiesForUser(o); - } - - map.addAttribute("userList", userList); - map.addAttribute("userid", userid); - map.addAttribute("agentserviceid", agentserviceid); - map.addAttribute("agentuserid", agentuserid); - map.addAttribute("skillGroups", skillGroups); - map.addAttribute("agentno", agentService.getAgentno()); - map.addAttribute("agentservice", this.agentServiceRes.findById(agentserviceid).orElse(null)); - map.addAttribute("currentorgan", currentOrgan); - } - - return request(super.createView("/apps/agent/transfer")); - } - - /** - * 查找一个组织机构中的在线坐席 - * - * @param map - * @param request - * @param organ - * @return - */ - @RequestMapping(value = "/transfer/agent") - @Menu(type = "apps", subtype = "transferagent") - public ModelAndView transferagent( - ModelMap map, - HttpServletRequest request, - @Valid String organ, - @Valid String agentid) { - final User logined = super.getUser(request); - if (StringUtils.isNotBlank(organ)) { - List userids = new ArrayList<>(); - - final Map agentStatusMap = cache.findAllReadyAgentStatus(); - - for (final String o : agentStatusMap.keySet()) { - if (!StringUtils.equals(o, agentid)) { - userids.add(o); - } - } - - final List userList = userRes.findAllById(userids); - for (final User o : userList) { - o.setAgentStatus(agentStatusMap.get(o.getId())); - // find user's skills - userProxy.attachOrgansPropertiesForUser(o); - } - map.addAttribute("userList", userList); - map.addAttribute("currentorgan", organ); - } - return request(super.createView("/apps/agent/transferagentlist")); - } + @RequestMapping(value = "/summary") + @Menu(type = "apps", subtype = "summary") + public ModelAndView summary( + ModelMap map, + HttpServletRequest request, + @Valid String userid, + @Valid String agentserviceid, + @Valid String agentuserid, + @Valid String channel) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { + AgentUser agentUser = this.agentUserRes.findById(agentuserid).orElse(null); + if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentserviceid())) { + List summaries = this.serviceSummaryRes.findByAgentserviceid( + agentUser.getAgentserviceid()); + if (summaries.size() > 0) { + map.addAttribute("summary", summaries.get(0)); + } + } + Organ currentOrgan = super.getOrgan(request); + if (null != currentOrgan) { + map.addAttribute( + "tags", tagRes.findByTagtypeAndSkill( + MainContext.ModelType.CCSUMMARY.toString(), currentOrgan.getParent())); + } - @RequestMapping("/calloutcontact/add") - @Menu(type = "apps", subtype = "calloutcontact", admin = true) - public ModelAndView add(ModelMap map, HttpServletRequest request, @Valid String ckind) { - map.addAttribute("ckind", ckind); - return request(super.createView("/apps/agent/calloutcontact/add")); - } + map.addAttribute("userid", userid); + map.addAttribute("agentserviceid", agentserviceid); + map.addAttribute("agentuserid", agentuserid); + map.addAttribute("channel", channel); + } + return request(super.createView("/apps/agent/summary")); + } - @RequestMapping(value = "/calloutcontact/save") - @Menu(type = "apps", subtype = "calloutcontact") - public ModelAndView calloutcontactsave( - ModelMap map, - HttpServletRequest request, - @RequestParam(value = "agentuser") String agentuser, - @Valid Contacts contacts) throws CSKefuException { - logger.info("[agent ctrl] calloutcontactsave agentuser [{}]", agentuser); - AgentUser au = agentUserRes.findById(agentuser).orElse(null); - if (au == null) { - throw new CSKefuException("不存在该服务记录"); - } + @RequestMapping(value = "/summary/save") + @Menu(type = "apps", subtype = "summarysave") + public ModelAndView summarysave( + ModelMap map, + HttpServletRequest request, + @Valid AgentServiceSummary summary, + @Valid String contactsid, + @Valid String userid, + @Valid String agentserviceid, + @Valid String agentuserid, + @Valid String channel) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { + summary.setCreater(super.getUser(request).getId()); + summary.setCreatetime(new Date()); + AgentService service = agentServiceRes.findById(agentserviceid).orElse(null); + summary.setAgent(service.getAgentno()); + summary.setAgentno(service.getAgentno()); + summary.setSkill(service.getSkill()); + summary.setUsername(service.getUsername()); + summary.setAgentusername(service.getAgentusername()); + summary.setChannel(service.getChanneltype()); + summary.setContactsid(contactsid); + summary.setLogindate(service.getLogindate()); + summary.setContactsid(service.getContactsid()); + summary.setEmail(service.getEmail()); + summary.setPhonenumber(service.getPhone()); + serviceSummaryRes.save(summary); + } - User logined = super.getUser(request); - contacts.setId(MainUtils.getUUID()); - contacts.setCreater(logined.getId()); - contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName())); - if (StringUtils.isBlank(contacts.getCusbirthday())) { - contacts.setCusbirthday(null); - } - contactsRes.save(contacts); + return request(super.createView( + "redirect:/agent/agentuser.html?id=" + agentuserid + "&channel=" + channel)); + } - AgentUserContacts auc = new AgentUserContacts(); - auc.setId(MainUtils.getUUID()); - auc.setUsername(au.getUsername()); - auc.setUserid(au.getUserid()); - auc.setContactsid(contacts.getId()); - auc.setChanneltype(au.getChanneltype()); - auc.setCreatetime(new Date()); - auc.setAppid(au.getAppid()); - auc.setCreater(logined.getId()); - agentUserContactsRes.save(auc); - return request(super.createView("redirect:/agent/index.html")); - } + /** + * 坐席转接窗口 + * + * @param map + * @param request + * @param userid + * @param agentserviceid + * @param agentuserid + * @return + */ + @RequestMapping(value = "/transfer") + @Menu(type = "apps", subtype = "transfer") + public ModelAndView transfer( + ModelMap map, + final HttpServletRequest request, + final @Valid String userid, + final @Valid String agentserviceid, + final @Valid String agentuserid) { + logger.info("[transfer] userId {}, agentUser {}", userid, agentuserid); + final User logined = super.getUser(request); - @RequestMapping("/calloutcontact/update") - @Menu(type = "apps", subtype = "calloutcontact") - public ModelAndView update(HttpServletRequest request, @Valid Contacts contacts) { - Contacts data = contactsRes.findById(contacts.getId()).orElse(null); - if (data != null) { - List events = PropertiesEventUtil.processPropertiesModify( - request, contacts, data, "id", "creater", "createtime", "updatetime"); //记录 数据变更 历史 - if (events.size() > 0) { - String modifyid = MainUtils.getUUID(); - Date modifytime = new Date(); - for (PropertiesEvent event : events) { - event.setDataid(contacts.getId()); - event.setCreater(super.getUser(request).getId()); - event.setModifyid(modifyid); - event.setCreatetime(modifytime); - propertiesEventRes.save(event); - } - } + Organ targetOrgan = super.getOrgan(request); + Map ownOrgans = organProxy.findAllOrganByParent(targetOrgan); - contacts.setCreater(data.getCreater()); - contacts.setCreatetime(data.getCreatetime()); - contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName())); - if (StringUtils.isBlank(contacts.getCusbirthday())) { - contacts.setCusbirthday(null); - } - contactsRes.save(contacts); - } + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { + // 列出所有技能组 + List skillGroups = organRes.findByIdInAndSkill(ownOrgans.keySet(), true); - return request(super.createView("redirect:/agent/index.html")); - } - } + // 选择当前用户的默认技能组 + AgentService agentService = agentServiceRes.findById(agentserviceid).orElse(null); + + String currentOrgan = agentService.getSkill(); + + if (StringUtils.isBlank(currentOrgan)) { + if (!skillGroups.isEmpty()) { + currentOrgan = skillGroups.get(0).getId(); + } + } + logger.info("[transfer] set current organ as {}", currentOrgan); + // 列出所有在线的坐席,排除本身 + List userids = new ArrayList<>(); + final Map agentStatusMap = cache.findAllReadyAgentStatus(); + + for (final String o : agentStatusMap.keySet()) { + if (!StringUtils.equals(o, logined.getId())) { + userids.add(o); + } + } + + logger.info("[transfer] get all userids except mine, {}", StringUtils.join(userids, "\t")); + + final List userList = userRes.findAllById(userids); + for (final User o : userList) { + o.setAgentStatus(agentStatusMap.get(o.getId())); + // find user's skills + userProxy.attachOrgansPropertiesForUser(o); + } + + map.addAttribute("userList", userList); + map.addAttribute("userid", userid); + map.addAttribute("agentserviceid", agentserviceid); + map.addAttribute("agentuserid", agentuserid); + map.addAttribute("skillGroups", skillGroups); + map.addAttribute("agentno", agentService.getAgentno()); + map.addAttribute("agentservice", this.agentServiceRes.findById(agentserviceid).orElse(null)); + map.addAttribute("currentorgan", currentOrgan); + } + + return request(super.createView("/apps/agent/transfer")); + } + + /** + * 查找一个组织机构中的在线坐席 + * + * @param map + * @param request + * @param organ + * @return + */ + @RequestMapping(value = "/transfer/agent") + @Menu(type = "apps", subtype = "transferagent") + public ModelAndView transferagent( + ModelMap map, + HttpServletRequest request, + @Valid String organ, + @Valid String agentid) { + final User logined = super.getUser(request); + if (StringUtils.isNotBlank(organ)) { + List userids = new ArrayList<>(); + + final Map agentStatusMap = cache.findAllReadyAgentStatus(); + + for (final String o : agentStatusMap.keySet()) { + if (!StringUtils.equals(o, agentid)) { + userids.add(o); + } + } + + final List userList = userRes.findAllById(userids); + for (final User o : userList) { + o.setAgentStatus(agentStatusMap.get(o.getId())); + // find user's skills + userProxy.attachOrgansPropertiesForUser(o); + } + map.addAttribute("userList", userList); + map.addAttribute("currentorgan", organ); + } + return request(super.createView("/apps/agent/transferagentlist")); + } + + + @RequestMapping("/calloutcontact/add") + @Menu(type = "apps", subtype = "calloutcontact", admin = true) + public ModelAndView add(ModelMap map, HttpServletRequest request, @Valid String ckind) { + map.addAttribute("ckind", ckind); + return request(super.createView("/apps/agent/calloutcontact/add")); + } + + @RequestMapping(value = "/calloutcontact/save") + @Menu(type = "apps", subtype = "calloutcontact") + public ModelAndView calloutcontactsave( + ModelMap map, + HttpServletRequest request, + @RequestParam(value = "agentuser") String agentuser, + @Valid Contacts contacts) throws CSKefuException { + logger.info("[agent ctrl] calloutcontactsave agentuser [{}]", agentuser); + AgentUser au = agentUserRes.findById(agentuser).orElse(null); + if (au == null) { + throw new CSKefuException("不存在该服务记录"); + } + + User logined = super.getUser(request); + contacts.setId(MainUtils.getUUID()); + contacts.setCreater(logined.getId()); + contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName())); + if (StringUtils.isBlank(contacts.getCusbirthday())) { + contacts.setCusbirthday(null); + } + contactsRes.save(contacts); + + AgentUserContacts auc = new AgentUserContacts(); + auc.setId(MainUtils.getUUID()); + auc.setUsername(au.getUsername()); + auc.setUserid(au.getUserid()); + auc.setContactsid(contacts.getId()); + auc.setChanneltype(au.getChanneltype()); + auc.setCreatetime(new Date()); + auc.setAppid(au.getAppid()); + auc.setCreater(logined.getId()); + agentUserContactsRes.save(auc); + return request(super.createView("redirect:/agent/index.html")); + } + + @RequestMapping("/calloutcontact/update") + @Menu(type = "apps", subtype = "calloutcontact") + public ModelAndView update(HttpServletRequest request, @Valid Contacts contacts) { + Contacts data = contactsRes.findById(contacts.getId()).orElse(null); + if (data != null) { + List events = PropertiesEventUtil.processPropertiesModify( + request, contacts, data, "id", "creater", "createtime", "updatetime"); //记录 数据变更 历史 + if (events.size() > 0) { + String modifyid = MainUtils.getUUID(); + Date modifytime = new Date(); + for (PropertiesEvent event : events) { + event.setDataid(contacts.getId()); + event.setCreater(super.getUser(request).getId()); + event.setModifyid(modifyid); + event.setCreatetime(modifytime); + propertiesEventRes.save(event); + } + } + + contacts.setCreater(data.getCreater()); + contacts.setCreatetime(data.getCreatetime()); + contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName())); + if (StringUtils.isBlank(contacts.getCusbirthday())) { + contacts.setCusbirthday(null); + } + contactsRes.save(contacts); + } + + return request(super.createView("redirect:/agent/index.html")); + } +} diff --git a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/IMController.java b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/IMController.java index e6afc0a4..9ea62a55 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/IMController.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/IMController.java @@ -117,7 +117,7 @@ public class IMController extends Handler { private LeaveMsgRepository leaveMsgRes; @Autowired - private AgentUserRepository agentUserRepository; + private AgentUserRepository agentUserRes; @Autowired private AttachmentRepository attachementRes; @@ -822,7 +822,7 @@ public class IMController extends Handler { Contacts contacts1 = contactsRes.findOneByWluidAndWlsidAndWlcidAndDatastatus( uid, sid, cid, false); if (contacts1 != null) { - agentUserRepository.findOneByUserid(userid).ifPresent(p -> { + agentUserRes.findOneByUserid(userid).ifPresent(p -> { // 关联AgentService的联系人 if (StringUtils.isNotBlank(p.getAgentserviceid())) { AgentService agentService = agentServiceRepository.findById(p.getAgentserviceid()).orElse(null); diff --git a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/service/ChatServiceController.java b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/service/ChatServiceController.java index f8b3d030..86bbdf66 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/service/ChatServiceController.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/controller/apps/service/ChatServiceController.java @@ -77,9 +77,6 @@ public class ChatServiceController extends Handler { @Autowired private AgentStatusRepository agentStatusRepository; - @Autowired - private AgentUserRepository agentUserRepository; - @Autowired private LeaveMsgRepository leaveMsgRes; @@ -233,7 +230,7 @@ public class ChatServiceController extends Handler { if (agentUser != null) { agentUser.setAgentno(agentno); agentUser.setAgentname(targetAgent.getUname()); - agentUserRepository.save(agentUser); + agentUserRes.save(agentUser); if (MainContext.AgentUserStatusEnum.INSERVICE.toString().equals( agentUser.getStatus())) { // 转接 , 发送消息给 目标坐席 @@ -288,11 +285,11 @@ public class ChatServiceController extends Handler { } } } else { - agentUser = agentUserRepository.findById(agentService.getAgentuserid()).orElse(null); + agentUser = agentUserRes.findById(agentService.getAgentuserid()).orElse(null); if (agentUser != null) { agentUser.setAgentno(agentno); agentUser.setAgentname(targetAgent.getUname()); - agentUserRepository.save(agentUser); + agentUserRes.save(agentUser); } } @@ -317,7 +314,7 @@ public class ChatServiceController extends Handler { AgentService agentService = agentServiceRes.findById(id).orElse(null); if (agentService != null) { User user = super.getUser(request); - AgentUser agentUser = agentUserRepository.findById(agentService.getAgentuserid()).orElse(null); + AgentUser agentUser = agentUserRes.findById(agentService.getAgentuserid()).orElse(null); if (agentUser != null) { acdAgentService.finishAgentUser(agentUser); } diff --git a/contact-center/app/src/main/java/com/cskefu/cc/model/AgentUser.java b/contact-center/app/src/main/java/com/cskefu/cc/model/AgentUser.java index c30ad35e..07371d25 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/model/AgentUser.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/model/AgentUser.java @@ -1,15 +1,15 @@ /* - * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. - * , Licensed under the Chunsong Public + * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. + * , Licensed under the Chunsong Public * License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html * 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. - * Copyright (C) 2018- Jun. 2023 Chatopera Inc, , Licensed under the Apache License, Version 2.0, + * Copyright (C) 2018- Jun. 2023 Chatopera Inc, , Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 - * Copyright (C) 2017 优客服-多渠道客服系统, Licensed under the Apache License, Version 2.0, + * Copyright (C) 2017 优客服-多渠道客服系统, Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 */ package com.cskefu.cc.model; @@ -19,6 +19,7 @@ import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Proxy; import jakarta.persistence.*; + import java.io.Serializable; import java.util.Date; @@ -105,6 +106,7 @@ public class AgentUser implements Serializable, Comparable { @Transient private boolean tip = false; + @Transient private boolean agentTip = false; @@ -119,11 +121,25 @@ public class AgentUser implements Serializable, Comparable { @Transient private boolean fromhis = false; + @Transient private boolean online = false; + @Transient private boolean disconnect = false; + /** + * 证书验证通过 + */ + @Transient + private boolean licenseVerifiedPass = true; + + /** + * 证书验证提示信息 + */ + @Transient + private String licenseBillingMsg; + public AgentUser() { } @@ -617,4 +633,22 @@ public class AgentUser implements Serializable, Comparable { public void setAgentname(String agentname) { this.agentname = agentname; } + + @Transient + public boolean isLicenseVerifiedPass() { + return licenseVerifiedPass; + } + + public void setLicenseVerifiedPass(boolean licenseVerifiedPass) { + this.licenseVerifiedPass = licenseVerifiedPass; + } + + @Transient + public String getLicenseBillingMsg() { + return licenseBillingMsg; + } + + public void setLicenseBillingMsg(String licenseBillingMsg) { + this.licenseBillingMsg = licenseBillingMsg; + } } diff --git a/contact-center/app/src/main/java/com/cskefu/cc/proxy/AgentUserProxy.java b/contact-center/app/src/main/java/com/cskefu/cc/proxy/AgentUserProxy.java index 58df9ddb..589e6d9d 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/proxy/AgentUserProxy.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/proxy/AgentUserProxy.java @@ -1,14 +1,14 @@ -/* - * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. - * , Licensed under the Chunsong Public +/* + * Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd. + * , Licensed under the Chunsong Public * License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html * 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. - * Copyright (C) 2019-2022 Chatopera Inc, , - * Licensed under the Apache License, Version 2.0, + * Copyright (C) 2019-2022 Chatopera Inc, , + * Licensed under the Apache License, Version 2.0, * http://www.apache.org/licenses/LICENSE-2.0 */ package com.cskefu.cc.proxy; @@ -34,6 +34,7 @@ import org.springframework.web.servlet.ModelAndView; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import java.io.IOException; import java.util.*; @@ -96,6 +97,8 @@ public class AgentUserProxy { @Lazy private PeerSyncIM peerSyncIM; + @Autowired + private LicenseProxy licenseProxy; /** * 与联系人主动聊天前查找获取AgentUser diff --git a/contact-center/app/src/main/java/com/cskefu/cc/proxy/LicenseProxy.java b/contact-center/app/src/main/java/com/cskefu/cc/proxy/LicenseProxy.java index 6241c442..1b2a54fd 100644 --- a/contact-center/app/src/main/java/com/cskefu/cc/proxy/LicenseProxy.java +++ b/contact-center/app/src/main/java/com/cskefu/cc/proxy/LicenseProxy.java @@ -19,6 +19,7 @@ import com.cskefu.cc.basic.Constants; import com.cskefu.cc.basic.MainContext; import com.cskefu.cc.basic.MainUtils; import com.cskefu.cc.exception.*; +import com.cskefu.cc.model.AgentUser; import com.cskefu.cc.model.ExecuteResult; import com.cskefu.cc.model.MetaKv; import com.cskefu.cc.persistence.repository.MetaKvRepository; @@ -511,5 +512,33 @@ public class LicenseProxy { } } + /** + * 访客会话执行计费 + * + * @param agentUser + * @return + */ + public ExecuteResult writeDownAgentUserUsageInStore(final AgentUser agentUser) { + // 检查是否还在体验阶段 + ExecuteResult er = new ExecuteResult(); + int alreadyUsed = getResourceUsageInMetaKv(MainContext.BillingResource.AGENGUSER); + if (alreadyUsed <= 100) { + // 可以免费创建 100 个访客会话 + er.setRc(ExecuteResult.RC_SUCC); + return er; + } + try { + writeDownResourceUsageInStore(MainContext.BillingResource.AGENGUSER, 1); + er.setRc(ExecuteResult.RC_SUCC); + } catch (BillingQuotaException e) { + er.setRc(ExecuteResult.RC_ERR1); + er.setMsg(e.getMessage()); + } catch (BillingResourceException e) { + er.setRc(ExecuteResult.RC_ERR2); + er.setMsg(e.getMessage()); + } + + return er; + } } diff --git a/contact-center/app/src/main/resources/static/js/CSKeFu_IM.v1.js b/contact-center/app/src/main/resources/static/js/CSKeFu_IM.v1.js index 24b22cca..e369db7c 100644 --- a/contact-center/app/src/main/resources/static/js/CSKeFu_IM.v1.js +++ b/contact-center/app/src/main/resources/static/js/CSKeFu_IM.v1.js @@ -11,196 +11,203 @@ * Licensed under the Apache License, Version 2.0 * http://www.apache.org/licenses/LICENSE-2.0 */ -var title = "春松客服-开源客服系统" ; -var socket , newuser = [] , newmessage = [] , ring = []; -newuser['mp3'] = '/images/new.mp3'; +var title = "春松客服-开源客服系统"; +var socket, newuser = [], newmessage = [], ring = []; +newuser['mp3'] = '/images/new.mp3'; newmessage['mp3'] = '/images/message.mp3'; ring['mp3'] = '/images/ring.mp3'; -$(document).ready(function(){ - var protocol = window.location.protocol.replace(/:/g,''); - socket = io(protocol+'://'+hostname+':'+port+"/im/agent?userid="+userid+"&session="+session+"&admin="+adminuser , {transports: ['websocket'], upgrade: false}); - socket.on('connect',function() { - console.log("[IM] 连接初始化成功"); - //请求服务端记录 当前用户在线事件 - }).on('disconnect',function() { - console.log("[IM] 连接已断开"); - //请求服务端记录,当前用户离线 +$(document).ready(function () { + var protocol = window.location.protocol.replace(/:/g, ''); + socket = io(protocol + '://' + hostname + ':' + port + "/im/agent?userid=" + userid + "&session=" + session + "&admin=" + adminuser, { + transports: ['websocket'], + upgrade: false + }); + socket.on('connect', function () { + console.log("[IM] 连接初始化成功"); + //请求服务端记录 当前用户在线事件 + }).on('disconnect', function () { + console.log("[IM] 连接已断开"); + //请求服务端记录,当前用户离线 }); - - socket.on('chatevent', function(data) { - // console.log(data.messageType + " ..... message:"+data.message); - }).on('task', function(data) { - - }).on('new', function(data) { - if($('#customerChatAudit').length > 0){ - if(customerChatAudit.$('#agentuser_' + data.userid).length > 0 && customerChatAudit.$("#chat_users li").length>1){ - customerChatAudit.$('#agentuser_' + data.userid).remove(); - customerChatAudit.$("#chat_users li:first-child a").click(); - }else{ - customerChatAudit.$('#ccaIndex').html("
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - "
还没有任何对话
\n" + - "
\n" + - "
\n" + - "
\n" + - "
"); - } - } - if($('#multiMediaDialogWin').length > 0 && multiMediaDialogWin != null && multiMediaDialogWin.$ &&multiMediaDialogWin.$('#agentusers').length > 0){ - multiMediaDialogWin.Proxy.newAgentUserService(data,"agent"); - }else{ - //来电弹屏 - $('#agentdesktop').attr('data-href' , '/agent/index.html?userid='+data.userid).click(); - WebIM.audioplayer('audioplane', newuser, false); // 播放 - } - }).on('status', function(data) { - $.post('/lazyAgentStatus').success(function(html){ - $('#agents_status').html(html); - }); - // $('#agents_status').html("服务中的人数:"+data.users+"人,当前排队人数:"+data.inquene+"人,在线坐席数:"+data.agents+"人,坐席忙:"+data.busy+"人"); - }).on('message', function(data) { - if($('#multiMediaDialogWin').length > 0 && multiMediaDialogWin != null && multiMediaDialogWin.$ && multiMediaDialogWin.$('#agentusers').length > 0){ - multiMediaDialogWin.Proxy.newAgentUserMessage(data,"agent"); - if(data.type == 'message'){ - WebIM.audioplayer('audioplane', newmessage, false); // 播放 - if(multiMediaDialogWin.isAisuggest && multiMediaDialogWin.isAisuggest == "true"){ - multiMediaDialogWin.Proxy.quickReply(data,"agent"); - } - } - }else{ - //来电弹屏 - $('#agentdesktop').attr('data-href' , '/agent/index.html?userid='+data.userid).click(); - } - }).on('workorder', function(data) { - }).on('transout', function(data){ - // TODO 坐席会话被转接出去 - if($('#multiMediaDialogWin').length > 0){ - if(multiMediaDialogWin.document.getElementById('agentusers') != null){ - multiMediaDialogWin.Proxy.transoutAgentUserService(data); - } - } - layer.msg("您与"+data.username+"的会话已被转接给"+data.agentname,{time:1500}) + socket.on('chatevent', function (data) { + // console.log(data.messageType + " ..... message:"+data.message); + }).on('task', function (data) { + }).on('new', function (data) { + console.log("new data ...", data); + if ($('#customerChatAudit').length > 0) { + if (customerChatAudit.$('#agentuser_' + data.userid).length > 0 && customerChatAudit.$("#chat_users li").length > 1) { + customerChatAudit.$('#agentuser_' + data.userid).remove(); + customerChatAudit.$("#chat_users li:first-child a").click(); + } else { + customerChatAudit.$('#ccaIndex').html("
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + "
还没有任何对话
\n" + + "
\n" + + "
\n" + + "
\n" + + "
"); + } + } - }).on('audit_message', function(data){ - // 会话监控:消息 - if($('#customerChatAudit').length > 0 && customerChatAudit != null && customerChatAudit.$ && customerChatAudit.$('#agentuserscca').length > 0){ - customerChatAudit.Proxy.newAgentUserMessage(data,"cca"); - if(data.type == 'message'){ - WebIM.audioplayer('audioplane', newmessage, false); // 播放 - if(customerChatAudit.isCcaAisuggest && customerChatAudit.isCcaAisuggest == "true"){ - customerChatAudit.Proxy.quickReply(data,"cca"); - } - } - } - }).on('audit_new', function(data){ - // 会话监控:新建 - if(skills.indexOf(data.skill)>-1 && $('#customerChatAudit').length > 0 && customerChatAudit != null && customerChatAudit.$){ - customerChatAudit.Proxy.newAgentUserService(data,"cca"); - if(data.type == 'message'){ - WebIM.audioplayer('audioplane', newmessage, false); // 播放 - } - } - }).on('audit_end', function(data){ - // 会话监控:结束 - if($('#customerChatAudit').length > 0){ - if(customerChatAudit.document.getElementById('agentuserscca') != null){ - customerChatAudit.Proxy.endAgentUserService(data); - } - } - }).on('end', function(data) { - console.warn(111111, data) - if($('#multiMediaDialogWin').length > 0){ - if(multiMediaDialogWin.document.getElementById('agentusers') != null){ - multiMediaDialogWin.Proxy.endAgentUserService(data); - } - }else{ - //来电弹屏 - $('#agentdesktop').attr('data-href', '/agent/index.html?userid='+data.userid).click(); - } - }).on('leave', function(data){ - top.layer.msg('当前会话已经过期,稍后将自动登出!',{icon: 1, time: 2000}); - setTimeout(function(){ - // 执行登出 - window.location.href = "/logout.html?code=2"; - }, 2000); - }); - /****每分钟执行一次,与服务器交互,保持会话****/ - setInterval(function(){ - WebIM.ping(); - } , 60000); + if ($('#multiMediaDialogWin').length > 0 && + multiMediaDialogWin != null && + multiMediaDialogWin.$ && + multiMediaDialogWin.$('#agentusers').length > 0) { + multiMediaDialogWin.Proxy.newAgentUserService(data, "agent"); + } else { + //来电弹屏 + $('#agentdesktop').attr('data-href', '/agent/index.html?userid=' + data.userid + '&licenseVerifiedPass=' + data.licenseVerifiedPass + '&licenseBillingMsg=' + data.licenseBillingMsg).click(); + WebIM.audioplayer('audioplane', newuser, false); // 播放 + } + }).on('status', function (data) { + $.post('/lazyAgentStatus').success(function (html) { + $('#agents_status').html(html); + }); + // $('#agents_status').html("服务中的人数:"+data.users+"人,当前排队人数:"+data.inquene+"人,在线坐席数:"+data.agents+"人,坐席忙:"+data.busy+"人"); + }).on('message', function (data) { + if ($('#multiMediaDialogWin').length > 0 && multiMediaDialogWin != null && multiMediaDialogWin.$ && multiMediaDialogWin.$('#agentusers').length > 0) { + multiMediaDialogWin.Proxy.newAgentUserMessage(data, "agent"); + if (data.type == 'message') { + WebIM.audioplayer('audioplane', newmessage, false); // 播放 + if (multiMediaDialogWin.isAisuggest && multiMediaDialogWin.isAisuggest == "true") { + multiMediaDialogWin.Proxy.quickReply(data, "agent"); + } + } + } else { + //来电弹屏 + $('#agentdesktop').attr('data-href', '/agent/index.html?userid=' + data.userid).click(); + } + }).on('workorder', function (data) { + + }).on('transout', function (data) { + // TODO 坐席会话被转接出去 + if ($('#multiMediaDialogWin').length > 0) { + if (multiMediaDialogWin.document.getElementById('agentusers') != null) { + multiMediaDialogWin.Proxy.transoutAgentUserService(data); + } + } + layer.msg("您与" + data.username + "的会话已被转接给" + data.agentname, {time: 1500}) + + }).on('audit_message', function (data) { + // 会话监控:消息 + if ($('#customerChatAudit').length > 0 && customerChatAudit != null && customerChatAudit.$ && customerChatAudit.$('#agentuserscca').length > 0) { + customerChatAudit.Proxy.newAgentUserMessage(data, "cca"); + if (data.type == 'message') { + WebIM.audioplayer('audioplane', newmessage, false); // 播放 + if (customerChatAudit.isCcaAisuggest && customerChatAudit.isCcaAisuggest == "true") { + customerChatAudit.Proxy.quickReply(data, "cca"); + } + } + } + }).on('audit_new', function (data) { + // 会话监控:新建 + if (skills.indexOf(data.skill) > -1 && $('#customerChatAudit').length > 0 && customerChatAudit != null && customerChatAudit.$) { + customerChatAudit.Proxy.newAgentUserService(data, "cca"); + if (data.type == 'message') { + WebIM.audioplayer('audioplane', newmessage, false); // 播放 + } + } + }).on('audit_end', function (data) { + // 会话监控:结束 + if ($('#customerChatAudit').length > 0) { + if (customerChatAudit.document.getElementById('agentuserscca') != null) { + customerChatAudit.Proxy.endAgentUserService(data); + } + } + }).on('end', function (data) { + console.warn(111111, data) + if ($('#multiMediaDialogWin').length > 0) { + if (multiMediaDialogWin.document.getElementById('agentusers') != null) { + multiMediaDialogWin.Proxy.endAgentUserService(data); + } + } else { + //来电弹屏 + $('#agentdesktop').attr('data-href', '/agent/index.html?userid=' + data.userid).click(); + } + }).on('leave', function (data) { + top.layer.msg('当前会话已经过期,稍后将自动登出!', {icon: 1, time: 2000}); + setTimeout(function () { + // 执行登出 + window.location.href = "/logout.html?code=2"; + }, 2000); + }); + /****每分钟执行一次,与服务器交互,保持会话****/ + setInterval(function () { + WebIM.ping(); + }, 60000); }); var WebIM = { - sendMessage:function(message , userid , appid , session , touser , agentstatus, agentuserid){ - WebIM.sendTypeMessage(message, userid, appid, session, touser, agentstatus, null , null,agentuserid) ; - }, - sendTypeMessage:function(message , userid , appid , session , touser , agentstatus , msgtype , attachmentid,agentuserid){ - socket.emit('message', { - appid : appid , - userid:userid, - sign:session, - touser:touser, - session: session, - username:agentstatus, - nickname:agentstatus, - message : message, - msgtype:msgtype, - attachmentid:attachmentid, - agentuser:agentuserid + sendMessage: function (message, userid, appid, session, touser, agentstatus, agentuserid) { + WebIM.sendTypeMessage(message, userid, appid, session, touser, agentstatus, null, null, agentuserid); + }, + sendTypeMessage: function (message, userid, appid, session, touser, agentstatus, msgtype, attachmentid, agentuserid) { + socket.emit('message', { + appid: appid, + userid: userid, + sign: session, + touser: touser, + session: session, + username: agentstatus, + nickname: agentstatus, + message: message, + msgtype: msgtype, + attachmentid: attachmentid, + agentuser: agentuserid }); - }, - // 发送会话监控干预消息 - sendIntervention: function(supervisorid, agentuserid, session, msgtype, content, extra){ - socket.emit('intervention', { - supervisorid: supervisorid, // 坐席监控人员ID,必须 - agentuserid: agentuserid, // 坐席访客会话ID,必须 - msgtype: msgtype, // 干预消息类型, 必须 - content: content, // 干预消息内容, 必须 - session: session, // 登录会话ID - extra: extra // 其它可选属性, 可选 - }); - }, - ping : function(){ - loadURL("/message/ping.html"); - console.log("[IM] heartbeat:" + new Date().getTime()); - }, - audioplayer:function(id, file, loop) { - var audioplayer = document.getElementById(id); - if (audioplayer != null) { - document.body.removeChild(audioplayer); - } + }, + // 发送会话监控干预消息 + sendIntervention: function (supervisorid, agentuserid, session, msgtype, content, extra) { + socket.emit('intervention', { + supervisorid: supervisorid, // 坐席监控人员ID,必须 + agentuserid: agentuserid, // 坐席访客会话ID,必须 + msgtype: msgtype, // 干预消息类型, 必须 + content: content, // 干预消息内容, 必须 + session: session, // 登录会话ID + extra: extra // 其它可选属性, 可选 + }); + }, + ping: function () { + loadURL("/message/ping.html"); + console.log("[IM] heartbeat:" + new Date().getTime()); + }, + audioplayer: function (id, file, loop) { + var audioplayer = document.getElementById(id); + if (audioplayer != null) { + document.body.removeChild(audioplayer); + } - if (typeof(file) != 'undefined') { - if (navigator.userAgent.indexOf("MSIE") > 0) { // IE - var player = document.createElement('bgsound'); - player.id = id; - player.src = file['mp3']; - player.setAttribute('autostart', 'true'); - if (loop) { - player.setAttribute('loop', 'infinite'); - } - document.body.appendChild(player); + if (typeof (file) != 'undefined') { + if (navigator.userAgent.indexOf("MSIE") > 0) { // IE + var player = document.createElement('bgsound'); + player.id = id; + player.src = file['mp3']; + player.setAttribute('autostart', 'true'); + if (loop) { + player.setAttribute('loop', 'infinite'); + } + document.body.appendChild(player); - } else { // Other FF Chome Safari Opera - var player = document.createElement('audio'); - player.id = id; - player.setAttribute('autoplay', 'autoplay'); - if (loop) { - player.setAttribute('loop', 'loop'); - } - document.body.appendChild(player); + } else { // Other FF Chome Safari Opera + var player = document.createElement('audio'); + player.id = id; + player.setAttribute('autoplay', 'autoplay'); + if (loop) { + player.setAttribute('loop', 'loop'); + } + document.body.appendChild(player); - var mp3 = document.createElement('source'); - mp3.src = file['mp3']; - mp3.type = 'audio/mpeg'; - player.appendChild(mp3); - } - } - } + var mp3 = document.createElement('source'); + mp3.src = file['mp3']; + mp3.type = 'audio/mpeg'; + player.appendChild(mp3); + } + } + } } diff --git a/contact-center/app/src/main/resources/static/js/cskefu.js b/contact-center/app/src/main/resources/static/js/cskefu.js index a0f17e02..0c01fc96 100644 --- a/contact-center/app/src/main/resources/static/js/cskefu.js +++ b/contact-center/app/src/main/resources/static/js/cskefu.js @@ -343,22 +343,23 @@ function newMessageScorllBottom(type, msgType) { var Proxy = { newAgentUserService: function (data, type) { + console.log("newAgentUserService data type", data, type) if ($('#tip_message_' + data.userid).length > 0) { var channel = data.channeltype if (channel) { if (channel === 'phone') { $('#tip_icon_phone_' + data.userid).attr("src", "/images/phone-ico.png"); } else { - $('#tip_icon_' +channel+ '_' + data.userid).removeClass('ukefu-channel-icon-end').addClass("ukefu-channel-icon"); + $('#tip_icon_' + channel + '_' + data.userid).removeClass('ukefu-channel-icon-end').addClass("ukefu-channel-icon"); } } $('#tip_message_' + data.userid).removeClass('bg-gray').addClass("bg-green").text('在线'); } else { if ($('.chat-list-item.active').length > 0) { var id = $('.chat-list-item.active').data('id'); - type == "agent" ? loadURL('/agent/agentusers.html?newuser=true&userid=' + id, '#agentusers') : loadURL('/apps/cca/agentusers.html?newuser=true&userid=' + id, '#agentuserscca'); + type == "agent" ? loadURL('/agent/agentusers.html?newuser=true&userid=' + id + '&licenseVerifiedPass=' + data.licenseVerifiedPass + '&licenseBillingMsg=' + data.licenseBillingMsg, '#agentusers') : loadURL('/apps/cca/agentusers.html?newuser=true&userid=' + id + "&licenseVerifiedPass=" + data.licenseVerifiedPass + "&licenseBillingMsg=" + data.licenseBillingMsg, '#agentuserscca'); } else { - type == "agent" ? location.href = "/agent/index.html?newuser=true" : location.href = "/apps/cca/index.html?newuser=true"; + type == "agent" ? location.href = "/agent/index.html?newuser=true&licenseVerifiedPass=" + data.licenseVerifiedPass + "&licenseBillingMsg=" + data.licenseBillingMsg : location.href = "/apps/cca/index.html?newuser=true&licenseVerifiedPass=" + data.licenseVerifiedPass + "&licenseBillingMsg=" + data.licenseBillingMsg; } } if (data.userid == cursession) { @@ -485,7 +486,7 @@ var Proxy = { if (channel === 'phone') { $('#tip_icon_phone_' + data.userid).attr("src", "/images/cde-ico-gray.png"); } else { - $('#tip_icon_'+ channel +'_' + data.userid).removeClass("ukefu-channel-icon").addClass('ukefu-channel-icon-end'); + $('#tip_icon_' + channel + '_' + data.userid).removeClass("ukefu-channel-icon").addClass('ukefu-channel-icon-end'); } } $('#tip_message_' + data.userid).removeClass("bg-green").addClass('bg-gray').text('离开'); @@ -504,7 +505,11 @@ var Proxy = { } }, tipMsgForm: function (href) { - top.layer.prompt({formType: 2, title: '请输入拉黑原因', area: ['300px', '50px']}, function (value, index, elem) { + top.layer.prompt({ + formType: 2, + title: '请输入拉黑原因', + area: ['300px', '50px'] + }, function (value, index, elem) { location.href = href + "&description=" + encodeURIComponent(value); top.layer.close(index); }); diff --git a/contact-center/app/src/main/resources/templates/apps/agent/agentusers.pug b/contact-center/app/src/main/resources/templates/apps/agent/agentusers.pug index a4aee649..d1868ff8 100644 --- a/contact-center/app/src/main/resources/templates/apps/agent/agentusers.pug +++ b/contact-center/app/src/main/resources/templates/apps/agent/agentusers.pug @@ -80,3 +80,11 @@ .last-msg small.ukefu-badge.bg-red(id="last_msg_" + agentuser.userid,style="#{(agentuser.tokenum == 0 || (curagentuser && curagentuser.id == agentuser.id)) ? 'display:none' : ''}") | #{agentuser.tokenum ? agentuser.tokenum : 0} +script(language="javascript"). + $(document).ready(function () { + var licenseVerifiedPass = #{licenseVerifiedPass}; + var licenseBillingMsg = '#{licenseBillingMsg}'; + if (licenseBillingMsg) { + handleGeneralCodeInQueryPathOrApiResp(licenseBillingMsg); + } + }); \ No newline at end of file