mirror of
https://github.com/chatopera/cosin.git
synced 2025-07-24 08:31:45 +08:00
close #442 optimize the ACD
This commit is contained in:
parent
799add4fc4
commit
0a073e9e2e
@ -22,9 +22,11 @@ import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.SNSAccount;
|
||||
import com.chatopera.cc.model.SessionConfig;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.SNSAccountRepository;
|
||||
import com.chatopera.cc.persistence.repository.SessionConfigRepository;
|
||||
import com.chatopera.cc.util.HashMapUtils;
|
||||
import com.chatopera.cc.util.WebIMReport;
|
||||
@ -58,6 +60,9 @@ public class ACDPolicyService {
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private SNSAccountRepository snsAccountRes;
|
||||
|
||||
/**
|
||||
* 载入坐席 ACD策略配置
|
||||
*
|
||||
@ -229,25 +234,28 @@ public class ACDPolicyService {
|
||||
*
|
||||
* TODO 指定技能组无用户,停止分配
|
||||
*/
|
||||
|
||||
SNSAccount snsAccount = snsAccountRes.findBySnsidAndOrgi(agentUser.getAppid(), orgi);
|
||||
|
||||
// 对于该租户的所有客服
|
||||
// for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
// if ((!entry.getValue().isBusy()) && (entry.getValue().getUsers() < sessionConfig.getMaxuser())) {
|
||||
// agentStatuses.add(entry.getValue());
|
||||
// logger.info(
|
||||
// "[filterOutAvailableAgentStatus] <Redundance> find ready agent {}, agentname {}, status {}, service {}/{}, skills {}",
|
||||
// entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
// entry.getValue().getUsers(),
|
||||
// entry.getValue().getMaxusers(),
|
||||
// HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
// } else {
|
||||
// logger.info(
|
||||
// "[filterOutAvailableAgentStatus] <Redundance> skip ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
// entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
// entry.getValue().getUsers(),
|
||||
// entry.getValue().getMaxusers(),
|
||||
// HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
// }
|
||||
// }
|
||||
for (final Map.Entry<String, AgentStatus> entry : map.entrySet()) {
|
||||
if ((!entry.getValue().isBusy()) && (entry.getValue().getUsers() < sessionConfig.getMaxuser()) && entry.getValue().getSkills().containsKey(snsAccount.getOrgan())) {
|
||||
agentStatuses.add(entry.getValue());
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Redundance> find ready agent {}, agentname {}, status {}, service {}/{}, skills {}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
} else {
|
||||
logger.info(
|
||||
"[filterOutAvailableAgentStatus] <Redundance> skip ready agent {}, name {}, status {}, service {}/{}, skills {}",
|
||||
entry.getValue().getAgentno(), entry.getValue().getUsername(), entry.getValue().getStatus(),
|
||||
entry.getValue().getUsers(),
|
||||
entry.getValue().getMaxusers(),
|
||||
HashMapUtils.concatKeys(entry.getValue().getSkills(), "|"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("[filterOutAvailableAgentStatus] agent status list size: {}", agentStatuses.size());
|
||||
|
@ -19,6 +19,7 @@ package com.chatopera.cc.acd.middleware.visitor;
|
||||
import com.chatopera.cc.acd.ACDPolicyService;
|
||||
import com.chatopera.cc.acd.ACDWorkMonitor;
|
||||
import com.chatopera.cc.acd.basic.ACDComposeContext;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.model.AgentReport;
|
||||
import com.chatopera.cc.model.SessionConfig;
|
||||
@ -66,8 +67,12 @@ public class ACDVisSessionCfgMw implements Middleware<ACDComposeContext> {
|
||||
ctx.setMessage(sessionConfig.getNotinwhmsg());
|
||||
} else if (report.getAgents() == 0) {
|
||||
// 没有就绪的坐席
|
||||
logger.info("[apply] find no agents, redirect to leave a message.");
|
||||
ctx.setNoagent(true);
|
||||
if (ctx.getChannel().equals(MainContext.ChannelType.MESSENGER.toString())) {
|
||||
next.apply();
|
||||
} else {
|
||||
logger.info("[apply] find no agents, redirect to leave a message.");
|
||||
ctx.setNoagent(true);
|
||||
}
|
||||
} else {
|
||||
logger.info("[apply] find agents size {}, allocate agent in next.", report.getAgents());
|
||||
// 具备工作中的就绪坐席,进入筛选坐席
|
||||
|
@ -48,6 +48,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
@ -107,6 +108,7 @@ public class Handler {
|
||||
|
||||
/**
|
||||
* 获得登录账号的当前导航的组织机构
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@ -122,7 +124,19 @@ public class Handler {
|
||||
Organ organ = (Organ) request.getSession(true).getAttribute(Constants.ORGAN_SESSION_NAME);
|
||||
if (organ == null) {
|
||||
if (organs.size() > 0) {
|
||||
organ = organs.get(0);
|
||||
ArrayList<String> organTree = new ArrayList();
|
||||
organs.stream().forEach(o -> {
|
||||
if (organTree.stream().filter(p -> StringUtils.equals(o.getParent(), p)).findFirst().isPresent()) {
|
||||
int index = organTree.indexOf(o.getParent());
|
||||
organTree.add(index + 1, o.getId());
|
||||
} else {
|
||||
organTree.add(0, o.getId());
|
||||
}
|
||||
});
|
||||
|
||||
organ = organs.stream().filter(o ->
|
||||
StringUtils.equals(o.getId(), organTree.get(0))
|
||||
).findFirst().orElse(organs.get(0));
|
||||
request.getSession(true).setAttribute(Constants.ORGAN_SESSION_NAME, organ);
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ public class AgentAuditController extends Handler {
|
||||
|
||||
if (StringUtils.isBlank(skill) && StringUtils.isBlank(agentno)) {
|
||||
if (organs.size() > 0) {
|
||||
agentUsers = agentUserRes.findByOrgiAndStatusAndSkillInAndAgentnoIsNot(
|
||||
agentUsers = agentUserRes.findByOrgiAndStatusAndSkillInAndAgentnoIsNotAndChatbotopsIsFalse(
|
||||
orgi, MainContext.AgentUserStatusEnum.INSERVICE.toString(), organs.keySet(), logined.getId(), defaultSort);
|
||||
}
|
||||
} else if (StringUtils.isNotBlank(skill) && StringUtils.isNotBlank(agentno)) {
|
||||
|
@ -40,6 +40,7 @@ public class FbOTN implements Serializable {
|
||||
private Date createtime;
|
||||
private Date updatetime;
|
||||
private Date sendtime;
|
||||
private Integer melinkNum;
|
||||
private Integer subNum;
|
||||
|
||||
private FbMessenger fbMessenger;
|
||||
@ -152,6 +153,14 @@ public class FbOTN implements Serializable {
|
||||
this.subNum = subNum;
|
||||
}
|
||||
|
||||
public Integer getMelinkNum() {
|
||||
return melinkNum;
|
||||
}
|
||||
|
||||
public void setMelinkNum(Integer melinkNum) {
|
||||
this.melinkNum = melinkNum;
|
||||
}
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "pageId", referencedColumnName = "pageId", insertable = false, updatable = false)
|
||||
@NotFound(action = NotFoundAction.IGNORE)
|
||||
|
@ -62,7 +62,7 @@ public interface AgentUserRepository extends JpaRepository<AgentUser, String> {
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillAndAgentnoIsNot(final String orgi, final String status, final String skill, final String agentno, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillInAndAgentnoIsNot(final String orgi, final String status, final Collection<String> skill, final String agentno, final Sort sort);
|
||||
List<AgentUser> findByOrgiAndStatusAndSkillInAndAgentnoIsNotAndChatbotopsIsFalse(final String orgi, final String status, final Collection<String> skill, final String agentno, final Sort sort);
|
||||
|
||||
List<AgentUser> findByOrgiAndStatusAndAgentno(final String orgi, final String status, final String agentno, final Sort defaultSort);
|
||||
|
||||
|
@ -41,4 +41,9 @@ public interface FbOTNRepository extends JpaRepository<FbOTN, String> {
|
||||
@Modifying
|
||||
@Query(nativeQuery = true, value = "update cs_fb_otn set sub_num = sub_num +1 where id = ?1")
|
||||
void incOneSubNumById(final String id);
|
||||
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query(nativeQuery = true, value = "update cs_fb_otn set melink_num = melink_num +1 where id = ?1")
|
||||
void incOneMelinkNumById(final String id);
|
||||
}
|
||||
|
@ -48,12 +48,14 @@
|
||||
uploadText.hide();
|
||||
json.url = data.url;
|
||||
jsonInput.val(JSON.stringify(json));
|
||||
jsonInput.trigger("change");
|
||||
img.css('height', '130px');
|
||||
});
|
||||
});
|
||||
textInput.bind("input propertychange", function (event) {
|
||||
json.content = textInput.val();
|
||||
jsonInput.val(JSON.stringify(json));
|
||||
jsonInput.trigger("change");
|
||||
});
|
||||
select.change(function () {
|
||||
if (select.val() == 'image') {
|
||||
@ -66,8 +68,10 @@
|
||||
json.type = 'text'
|
||||
}
|
||||
jsonInput.val(JSON.stringify(json));
|
||||
jsonInput.trigger("change");
|
||||
})
|
||||
jsonInput.val(JSON.stringify(json));
|
||||
jsonInput.trigger("change");
|
||||
$this.append(jsonInput)
|
||||
$this.append(select)
|
||||
$this.append(box)
|
||||
|
@ -682,10 +682,10 @@ script.
|
||||
});
|
||||
|
||||
$('#quickReplyAgentBox').on('click', '.chooseAnswer', function () {
|
||||
editor.html($(this).data('title'))
|
||||
editor.html($(this).data('title') + "")
|
||||
});
|
||||
|
||||
$('#quickReplyBox').on('click', '.chooseAnswer', function () {
|
||||
editor.html($(this).data('title'))
|
||||
editor.html($(this).data('title') + "")
|
||||
});
|
||||
|
||||
|
@ -685,10 +685,10 @@ script.
|
||||
});
|
||||
|
||||
$('#quickReplyAgentBox').on('click', '.chooseAnswer', function () {
|
||||
editor.html($(this).data('title'))
|
||||
editor.html($(this).data('title') + "")
|
||||
});
|
||||
|
||||
$('#quickReplyBox').on('click', '.chooseAnswer', function () {
|
||||
editor.html($(this).data('title'))
|
||||
editor.html($(this).data('title') + "")
|
||||
});
|
||||
|
||||
|
@ -681,10 +681,10 @@ script.
|
||||
|
||||
});
|
||||
$('#ccaQuickReplyAgentBox').on('click', '.chooseAnswer', function () {
|
||||
editor.html($(this).data('title'))
|
||||
editor.html($(this).data('title') + "")
|
||||
});
|
||||
|
||||
$('#ccaQuickReplyBox').on('click', '.chooseAnswer', function () {
|
||||
editor.html($(this).data('title'))
|
||||
editor.html($(this).data('title') + "")
|
||||
});
|
||||
|
||||
|
@ -311,7 +311,7 @@ html
|
||||
.ukefu-func-tab
|
||||
ul
|
||||
if models.contains("chatbot") && inviteData.ai && aiid
|
||||
if !exchange || exchange == "true"
|
||||
if exchange || exchange == "true"
|
||||
li
|
||||
a(href="/im/index.html?appid=" + appid + "&orgi=" + orgi + (aiid ? "&aiid=" + aiid : "") + "&ai=false" + (client ? "&client=" + client : '') + (type ? "&type=text" : "") + (skill ? "&skill=" + skill : '') + (agent ? "&agent=" + agent : '') + (title ? "&title=" + title : '') + (url ? "&url=" + url : '') + (traceid ? "&traceid=" + traceid : '') + "&userid=" + userid + "&sessionid=" + sessionid + "&t=" + pugHelper.currentTimeMillis()) 人工坐席
|
||||
li.cur
|
||||
|
@ -213,7 +213,7 @@ html
|
||||
.ukefu-func-tab
|
||||
ul
|
||||
if models.contains("chatbot") && inviteData.ai && inviteData.ai == true && aiid
|
||||
if !exchange || exchange == "true"
|
||||
if exchange || exchange == "true"
|
||||
li
|
||||
a(href="/im/index.html?appid=" + appid + "&orgi=" + orgi + (aiid ? '&aiid=' + aiid : '') + "&ai=false" + (client ? '&client=' + client : '') + (type ? '&type=' + type : '') + (skill ? '&skill=' + skill : '') + (agent ? '&agent=' + agent : '') + "&userid=" + userid + "&sessionid=" + sessionid + "&t=" + pugHelper.currentTimeMillis()) 人工客服
|
||||
li.cur
|
||||
|
@ -54,7 +54,6 @@ else if inviteData.consult_invite_color == "6"
|
||||
#ukefu-point-theme.ukefu-theme-color.theme1(class="ukefu-point-theme" + (inviteData.consult_vsitorbtn_model ? inviteData.consult_vsitorbtn_model : '1'), style=style + theme)
|
||||
#ukefu-im-point-text.ukefu-im-point-text(style='cursor: pointer;' + text + ';line-height: 23px;font-size: 15px;text-align: center;margin: 0 auto;')
|
||||
i(style="width:24px;height:24px;display: inline-block;font: normal normal normal 14px/1 FontAwesome;font-size: inherit;text-rendering: auto;-webkit-font-smoothing: antialiased;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAB60lEQVRIS7WV4TVsQRCEqyJABkSACBABLwJE8IjAigARIAMieCsCREAGjwja+eb03TO7O9ddrPm1Z29PV3dXdY31y8eL5I+ILUmbktYz/lXSs+2nofu9ABFBsjNJB5JWJT3MJNuR9CbpTtK5bUDnThMgIkaZnKSXtkkydyIC8BNJgI1sn88GzQFExI2kXUlHtsdDI+B7RBDPvUfbf+o7UwCZnHnv2qb9hU9EMEYKAuS4uzgByHapYqtvnkNoyRvE030Zaw0AScz7cijRZ9+Tv33b2xOAlOGjpLWvjmYWLEf1X9I2Mi4dRMRRtgVZ5WTgtaRX26cVmUj3lMtVzEPdeUTARVFfB4AsIbYG4Pe/0qbdxXERSaL7UapnKiYLIW5MTG8HGYjG6aAQlqNE+1RXVBYRUzH5H0SzF5MO2NqXJXHQ5dpAjbWKQL2jrSWo6MA2+zQlU2bOKOBi0MRaRVRq3OtcYHaT2YFDSQR8CSSTQ/itbXgpp+VFgCDbi5Z59ej+L6RKuqqTNwEqvWMbK2li97XxpSXwPhRTlPSOq7Zc99MHJxeQdt+6HcklYhdICmfonWKaZwgAh8RC8HmSXUjCjtcXtZQhAKrHGqiQUTynpTRfr1YLQwBomcq7HekdxbdG9JOF65XpMpLWOT4AygTtGd0Q7EsAAAAASUVORK5CYII=);")
|
||||
br
|
||||
| #{inviteData.consult_vsitorbtn_content ? inviteData.consult_vsitorbtn_content : '在线客服'}
|
||||
if inviteData.skill == true && inviteData.consult_skill_fixed == false
|
||||
#ichatContent.ichat-content.ichat-float-left(style='width:152px;display: block;font-size:14px;' + theme + ';box-shadow: 0 0 10px #DDDDDD;border: 1px solid #DDDDDD;overflow: hidden;text-align: left;')
|
||||
@ -72,12 +71,17 @@ else if inviteData.consult_invite_color == "6"
|
||||
else
|
||||
img(src=baseUrl + '/images/title.jpg', style='width:140px;margin:0 5px;vertical-align: middle;')
|
||||
div(style="padding:10px 5px;text-align:center;color:#555;")= inviteData.skill == true && inviteData.consult_skill_fixed == false && inviteData.consult_skill_msg ? inviteData.consult_skill_msg : ''
|
||||
|
||||
if skillGroups
|
||||
for skill in skillGroups
|
||||
- var skillNum = 0
|
||||
for agent in agentList
|
||||
- skillNum = skillNum + 1
|
||||
| #{skillNum}
|
||||
if agent.skills[skill.id]
|
||||
- skillNum = skillNum + 1
|
||||
|
||||
div(style='padding:5px;color:#555;border:1px solid #dddddd;background-color:#efefef;')
|
||||
a(href=baseUrl + '/im/text/' + appid + '.html?skill=' + skill.id + '&orgi=' + orgi, onclick='return openAgentChatDialog(this.href)', style='color: #777; text-decoration: none;') #{skill.name}(#{skillNum})
|
||||
|
||||
if inviteData.consult_skill_agent && inviteData.consult_skill_agent == true
|
||||
ul(class="ichat-list-ul", style="border: 0 none;list-style: none outside none;margin: 0;padding: 0;width: 150px;")
|
||||
if agentList
|
||||
|
@ -794,6 +794,7 @@ CREATE TABLE `cs_fb_otn` (
|
||||
`updatetime` DATETIME NOT NULL,
|
||||
`sendtime` DATETIME NULL DEFAULT NULL,
|
||||
`sub_num` INT(11) NOT NULL,
|
||||
`melink_num` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='FB OTN';
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
USE `cosinee`;
|
||||
-- -----------------
|
||||
-- prepare variables
|
||||
-- -----------------
|
||||
|
||||
SET @dbname = DATABASE ( );
|
||||
SET @tablename = "cs_fb_otn";
|
||||
SET @columnname = "melink_num";
|
||||
|
||||
SET @preparedStatement = (
|
||||
SELECT
|
||||
IF
|
||||
(
|
||||
(
|
||||
SELECT
|
||||
COUNT( * )
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
( table_name = @tablename )
|
||||
AND ( table_schema = @dbname )
|
||||
AND ( column_name = @columnname )
|
||||
) > 0,
|
||||
"SELECT 1",
|
||||
CONCAT( "ALTER TABLE ", @tablename, " ADD ", @columnname, " INT(11) DEFAULT 0 COMMENT 'Melink 点击数';" )
|
||||
)
|
||||
);
|
||||
PREPARE alterIfNotExists
|
||||
FROM
|
||||
@preparedStatement;
|
||||
EXECUTE alterIfNotExists;
|
||||
DEALLOCATE PREPARE alterIfNotExists;
|
@ -55,12 +55,10 @@
|
||||
</dependency>
|
||||
|
||||
<!-- pugjs, template engine surpass freemarker https://pugjs.org/ -->
|
||||
<!-- hosted with Chatopera Nexus -->
|
||||
<!-- https://gitlab.chatopera.com/cskefu/spring-pug4j -->
|
||||
<dependency>
|
||||
<groupId>de.neuland-bfi</groupId>
|
||||
<artifactId>spring-pug4j</artifactId>
|
||||
<version>2.0.0-alpha-4-SNAPSHOT</version>
|
||||
<version>2.0.0-alpha-2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -497,6 +497,7 @@ public class ApiChatbotController extends Handler {
|
||||
} else if (c.getChannel().equals(Constants.CHANNEL_TYPE_MESSENGER)) {
|
||||
FbMessenger fbMessenger = fbMessengerRepository.findOneByPageId(c.getSnsAccountIdentifier());
|
||||
fbMessenger.setAiid(null);
|
||||
fbMessenger.setAi(false);
|
||||
fbMessengerRepository.save(fbMessenger);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user