IMChatLoginServiceProcessor.java 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. package com.cn.service;
  2. import com.alibaba.fastjson.JSONObject;
  3. import org.jim.common.ImAio;
  4. import org.jim.common.ImConfig;
  5. import org.jim.common.cache.redis.RedissonTemplate;
  6. import org.jim.common.message.MessageHelper;
  7. import org.jim.common.utils.JsonKit;
  8. import org.jim.server.command.CommandManager;
  9. import org.jim.server.model.*;
  10. import nl.basjes.shaded.org.springframework.util.CollectionUtils;
  11. import org.jim.server.enums.*;
  12. import org.apache.commons.lang3.StringUtils;
  13. import org.jim.common.ImConst;
  14. import org.jim.common.ImStatus;
  15. import org.jim.common.cache.redis.JedisTemplate;
  16. import org.jim.common.packets.*;
  17. import org.jim.server.command.handler.processor.login.LoginCmdProcessor;
  18. import org.jim.server.util.SnowflakeIdUtils;
  19. import org.redisson.api.RLock;
  20. import org.redisson.api.RedissonClient;
  21. import org.slf4j.Logger;
  22. import org.slf4j.LoggerFactory;
  23. import org.tio.core.ChannelContext;
  24. import org.tio.utils.lock.SetWithLock;
  25. import java.util.*;
  26. import java.util.concurrent.TimeUnit;
  27. import java.util.stream.Collectors;
  28. /**
  29. * @author Darren
  30. * @date 2020/2/2 11:03
  31. */
  32. public class IMChatLoginServiceProcessor implements LoginCmdProcessor {
  33. private static Logger logger = LoggerFactory.getLogger(IMChatLoginServiceProcessor.class);
  34. private static JedisTemplate jedisTemplate = null;
  35. protected static ImConfig imConfig = null;
  36. private static RedissonClient redisson = null;
  37. private static final String GROUP_PROPERTY = " * ";
  38. private static final String CURRENT_SYSTEM_ALL_USER_ID = "CURRENT_SYSTEM_ALL_USER_ID";
  39. private final String LOGIN = "LOGIN";
  40. static {
  41. try {
  42. imConfig = CommandManager.getImConfig();
  43. jedisTemplate = JedisTemplate.me();
  44. redisson = RedissonTemplate.me().getRedissonClient();
  45. } catch (Exception e) {
  46. logger.info("IMChatLoginServiceProcessor 初始化失败!");
  47. e.printStackTrace();
  48. }
  49. }
  50. /**
  51. * doLogin方法注意:J-IM登陆命令是根据user是否为空判断是否登陆成功,
  52. * 当登陆失败时设置user属性需要为空,相反登陆成功user属性是必须非空的;
  53. * @param loginReqBody
  54. * @param channelContext
  55. * @return
  56. */
  57. @Override
  58. public LoginRespBody doLogin(LoginReqBody loginReqBody, ChannelContext channelContext) {
  59. logger.info("执行登录处理器doLogin()方法...");
  60. RLock rLock = redisson.getLock(LOGIN);
  61. LoginRespBody loginRespBody;
  62. boolean res = false;
  63. try {
  64. res = rLock.tryLock(500, 5000, TimeUnit.MILLISECONDS);
  65. if (res) {
  66. //获取token
  67. String token = loginReqBody.getToken();
  68. User user = null;
  69. if(StringUtils.isNotBlank(token)){
  70. user = this.getUser(token);
  71. }
  72. if(user == null){
  73. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10008);
  74. }else{
  75. Boolean noOnlineService = user.getExtras().getBoolean("noOnlineService");
  76. if(noOnlineService != null && noOnlineService){
  77. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10022,user);
  78. }else{
  79. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10007,user);
  80. String userJson = JsonKit.toJSONString(user);
  81. Map<String,String> users = jedisTemplate.hashGetAll(CURRENT_SYSTEM_ALL_USER_ID);
  82. if(!CollectionUtils.isEmpty(users)){
  83. boolean flag = true;
  84. for(Map.Entry<String,String> entry : users.entrySet()){
  85. if(entry.getKey() == user.getId() ){
  86. flag = false;
  87. }
  88. }
  89. if(flag){
  90. //存储所有登录的用户 的 userId
  91. jedisTemplate.hashSet(CURRENT_SYSTEM_ALL_USER_ID, user.getId(), userJson);
  92. }
  93. }else{
  94. jedisTemplate.hashSet(CURRENT_SYSTEM_ALL_USER_ID, user.getId(), userJson);
  95. }
  96. }
  97. }
  98. }else{
  99. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10028);
  100. }
  101. } catch (InterruptedException e) {
  102. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10029);
  103. e.printStackTrace();
  104. } finally {
  105. if (res) {
  106. rLock.unlock();
  107. }
  108. }
  109. return loginRespBody;
  110. }
  111. /**
  112. * 通过token 获取用户信息
  113. * @param token
  114. * @return {@link {@link User}}
  115. * @author Darren
  116. * @date 2020/2/5 15:34
  117. */
  118. public User getUser(String token) {
  119. User user = null;
  120. String[] tokenArray = token.split(ImConst.SEPARATOR);
  121. if(tokenArray.length == 2){
  122. //判断访问类型
  123. String visitType = tokenArray[0];
  124. Map<String, String> map = jedisTemplate.hashGetAll(token);
  125. if( !CollectionUtils.isEmpty(map) ){
  126. if( VisitTypeEnum.SERVICEACCOUNT.getKey().equals(visitType) ){
  127. user = this.createServiceAccountUser(map);
  128. this.disposeServiceAccountData(user);
  129. }
  130. if( VisitTypeEnum.CUSTOMER.getKey().equals(visitType) ){
  131. //当前访问人为客户
  132. user = this.createCustomerData(map);
  133. }
  134. if( VisitTypeEnum.VISITOR.getKey().equals(visitType) ){
  135. //当前访问人为游客
  136. user = this.createVisitorData(map);
  137. //修改游客在线状态
  138. Boolean noOnlineService = user.getExtras().getBoolean("noOnlineService");
  139. if(!noOnlineService){
  140. VisitorDepartmentMiddle.dao.findById(user.getId()).set("online",0).update();
  141. }
  142. }
  143. }
  144. }
  145. return user;
  146. }
  147. /** ============================================= <游客> 处理 start================================================== */
  148. /**
  149. * 创建 游客 user 数据
  150. * @param map
  151. * @return {@link {@link User}}
  152. * @author Darren
  153. * @date 2020/2/5 15:30
  154. */
  155. private User createVisitorData(Map<String, String> map) {
  156. User user = new User();
  157. user.setId(map.get("visitorDepartmentId"));
  158. String headImg = map.get("headImg") == null ? null : map.get("headImg").replace("\"","");
  159. user.setAvatar(headImg);
  160. String nickname = map.get("nickname") == null ? null : map.get("nickname").replace("\"","");
  161. user.setNick(nickname);
  162. Map<String, Object> visitorMap = new HashMap<>();
  163. visitorMap.put("visitorId",map.get("id"));
  164. visitorMap.put("companyId",map.get("companyId"));
  165. visitorMap.put("departmentId",map.get("departmentId"));
  166. visitorMap.put("phone",map.get("phone") == null ? null : map.get("phone").replace("\"",""));
  167. user.setExtras(new JSONObject(visitorMap));
  168. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  169. user.setVisitType(VisitTypeEnum.VISITOR.getKey());
  170. user.setGroups(this.initVisitorGroups(user));
  171. return user;
  172. }
  173. /**
  174. * 初始化游客 群组数据
  175. * @param user
  176. * @return {@link {@link List< Group>}}
  177. * @author Darren
  178. * @date 2020/2/5 15:26
  179. */
  180. private List<Group> initVisitorGroups(User user) {
  181. List<Group> groups = disposeVisitorGroupData(user);
  182. Boolean noOnlineService = user.getExtras().getBoolean("noOnlineService");
  183. if(!noOnlineService){
  184. this.createConversation(groups.get(0),user);
  185. }
  186. return groups;
  187. }
  188. /**
  189. * 处理游客群组数据
  190. * 自动分配原则,根据上次服务状态,优先分配上次服务客服,
  191. * 若上次服务客服不在线或不存在上次服务客服状况,
  192. * 则优先根据当前在线客服服务人数最少的客服进行分配,和服务上限无关;
  193. * @param user
  194. * @return {@link {@link List< Group>}}
  195. * @author Darren
  196. * @date 2020/2/5 15:25
  197. */
  198. private List<Group> disposeVisitorGroupData(User user){
  199. List<Group> groups = new ArrayList<>();
  200. //获取 当前平台下 部门下 所有的在线的客服
  201. String serviceAccountContainerKey
  202. = user.getExtras().getString("companyId") + ImConst.SEPARATOR
  203. + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
  204. + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
  205. //value组成 : Map<String ( serviceAccountRoleDepartmentId ), String (当前连接客户人数)>
  206. Map<String, String> serviceAccountContainer = jedisTemplate.hashGetAll(serviceAccountContainerKey);
  207. StringBuilder sql1 = new StringBuilder();
  208. sql1.append(" select ")
  209. .append(GROUP_PROPERTY)
  210. .append(" from sw_group where 1 = 1 ")
  211. .append(" and company_id = " + user.getExtras().getString("companyId"))
  212. .append(" and department_id = " + user.getExtras().getString("departmentId"))
  213. .append(" and consumer_id = " + user.getId())
  214. .append(" order by create_time desc");
  215. //判断 游客在平台下部门下 是否有群组 且判断 游客对应的客服 是否在线
  216. ChatGroup chatGroup1 = ChatGroup.dao.findFirst(sql1.toString());
  217. boolean isOnline = false;
  218. if( null != chatGroup1 ){
  219. String accountRoleDepartmentId = chatGroup1.getStr("service_account_role_department_middle_id");
  220. //游客对应客服存在 且 在线; isOnline=true;
  221. isOnline = serviceAccountContainer.containsKey(accountRoleDepartmentId);
  222. }
  223. user.getExtras().put("noOnlineService",false);
  224. if(!isOnline){
  225. // 从当前在线的客服中 获取 连接客户数最少的 客服
  226. Map.Entry<String, String> minReceptionNumServiceAccount = this.getServiceAccountMinReceptionNum(serviceAccountContainer);
  227. if( null != minReceptionNumServiceAccount ){
  228. //当前平台下部门下 存在客服
  229. user.getExtras().put("serviceAccountRoleDepartmentId",minReceptionNumServiceAccount.getKey());
  230. String sql2 = this.createSelectGroupSql(user);
  231. ChatGroup chatGroup2 = ChatGroup.dao.findFirst(sql2);
  232. if( null != chatGroup2){
  233. chatGroup2
  234. // 更改 sw_group 表中 group_state 字段为在线 (群组离线状态 1: 离线 0: 在线)
  235. .set("group_state",GroupStateEnum.ON_LINE.getKey())
  236. // 更改 sw_group 表中 consumer_type 字段为在线 (客户/游客 离线状态 1:离线 0:在线)
  237. .set("consumer_type",ConsumerTypeEnum.ON_LINE.getKey())
  238. // 更改 sw_group 表中 service_account_type 字段为 在线 (客服离线状态 1: 离线 0: 在线)
  239. .set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  240. // 更改 sw_group 表中 message_state 字段为 非留言 (群组留言状态 1:留言 0:非留言)
  241. .set("message_state",MessageStateEnum.NO.getKey())
  242. .update();
  243. //之前 客服 和 客户/游客 之间 有群组
  244. Group group = disposeChatGroupToGroup(chatGroup2);
  245. groups.add(group);
  246. }else{
  247. //创建群组
  248. Group group = this.createGroup(user);
  249. //把 Group 转成 Map 用于 jfianl框架的 添加使用
  250. Map<String, Object> groupAttrs = groupToMap(group);
  251. groupAttrs.put("group_state", GroupStateEnum.ON_LINE.getKey());
  252. groupAttrs.put("consumer_type", ConsumerTypeEnum.ON_LINE.getKey());
  253. //客服是否是离线状态 1: 是 0: 否
  254. groupAttrs.put("service_account_type", ServiceAccountOfflineTypeEnum.ON_LINE.getKey());
  255. //群组留言状态 1:留言 0:非留言
  256. groupAttrs.put("message_state", MessageStateEnum.NO.getKey());
  257. //jfianl框架的 保存
  258. ChatGroup.dao._setAttrs(groupAttrs).save();
  259. groups.add(group);
  260. }
  261. //更改 客服正在 服务的 客户/游客 数量
  262. int num = Integer.valueOf(minReceptionNumServiceAccount.getValue());
  263. jedisTemplate.hashSet(serviceAccountContainerKey,minReceptionNumServiceAccount.getKey(),String.valueOf(++num));
  264. }else{
  265. //当前平台下部门下 没有在线客服
  266. user.getExtras().put("noOnlineService",true);
  267. }
  268. }else{
  269. Group group = disposeChatGroupToGroup(chatGroup1);
  270. groups.add(group);
  271. chatGroup1
  272. // 更改 sw_group 表中 group_state 字段为在线 (群组离线状态 1: 离线 0: 在线)
  273. .set("group_state",GroupStateEnum.ON_LINE.getKey())
  274. // 更改 sw_group 表中 consumer_type 字段为在线 (客户/游客 离线状态 1:离线 0:在线)
  275. .set("consumer_type",ConsumerTypeEnum.ON_LINE.getKey())
  276. // 更改 sw_group 表中 service_account_type 字段为 在线 (客服离线状态 1: 离线 0: 在线)
  277. .set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  278. // 更改 sw_group 表中 message_state 字段为 非留言 (群组留言状态 1:留言 0:非留言)
  279. .set("message_state",MessageStateEnum.NO.getKey())
  280. .update();
  281. }
  282. return groups;
  283. }
  284. /** ============================================= <游客> 处理 end================================================== */
  285. /** ============================================= <客户> 处理 start================================================== */
  286. /**
  287. * 创建 客户 user 数据
  288. * @param map
  289. * @return {@link {@link User}}
  290. * @author Darren
  291. * @date 2020/2/4 10:07
  292. */
  293. private User createCustomerData(Map<String, String> map) {
  294. User user = new User();
  295. user.setId(map.get("customerDepartmentId"));
  296. String headImg = map.get("headImg") == null ? null : map.get("headImg").replace("\"","");
  297. user.setAvatar(headImg);
  298. String nickname = map.get("nickname") == null ? null : map.get("nickname").replace("\"","");
  299. user.setNick(nickname);
  300. Map<String, Object> customerMap = new HashMap<>();
  301. customerMap.put("isBlack",map.get("isBlack"));
  302. customerMap.put("isClaim",map.get("isClaim"));
  303. customerMap.put("customerId",map.get("id"));
  304. customerMap.put("companyId",map.get("companyId"));
  305. customerMap.put("departmentId",map.get("departmentId"));
  306. customerMap.put("serviceAccountId",map.get("serviceAccountId"));
  307. customerMap.put("phone",map.get("phone") == null ? null : map.get("phone").replace("\"",""));
  308. customerMap.put("serviceAccountRoleDepartmentId",map.get("serviceAccountRoleDepartmentId"));
  309. user.setExtras(new JSONObject(customerMap));
  310. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  311. user.setVisitType(VisitTypeEnum.CUSTOMER.getKey());
  312. user.setGroups(this.initCustomerGroups(user));
  313. return user;
  314. }
  315. /**
  316. * 绑定客户群组 一个客户在一个平台下在一个部门下 只会有一个群组
  317. * @param user
  318. * @return {@link {@link List< Group>}}
  319. * @author Darren
  320. * @date 2020/2/4 11:05
  321. */
  322. private List<Group> initCustomerGroups(User user) {
  323. //获取 当前平台下 部门下 在线的 客服
  324. String serviceAccountContainerKey
  325. = user.getExtras().getString("companyId") + ImConst.SEPARATOR
  326. + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
  327. + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
  328. //是否创建 会话
  329. user.getExtras().put("isCreateConversation",true);
  330. List<Group> groups = new ArrayList<>();
  331. // isClaim: 是否认领 1:是 0:否; isBlack: 是否加入黑名单 1:是 0:否;
  332. if(
  333. CustomerClaimTypeEnum.YES.getKey().equals(user.getExtras().getString("isClaim")) &&
  334. BlackListStateEnum.NO.getKey().equals(user.getExtras().getString("isBlack"))
  335. ){
  336. //被认领 并且 没有加入黑名单
  337. String receptionNum
  338. = jedisTemplate.hashGet(
  339. serviceAccountContainerKey
  340. , user.getExtras().getString("serviceAccountRoleDepartmentId")
  341. );
  342. String sql = this.createSelectGroupSql(user);
  343. ChatGroup chatGroup = ChatGroup.dao.findFirst(sql);
  344. if( null != chatGroup){
  345. //判断 (之前群组 是否是留言群组 ) >>> 现在 处理的是 客户登录的处理逻辑
  346. if(
  347. MessageStateEnum.YES.getKey() == chatGroup.getInt("message_state")
  348. ){
  349. // 群组 是留言群组 则不重新创建会话
  350. user.getExtras().put("isCreateConversation",false);
  351. }
  352. chatGroup
  353. // 更改 sw_group 表中 group_state 字段为在线 (群组离线状态 1: 离线 0: 在线)
  354. .set("group_state",GroupStateEnum.ON_LINE.getKey())
  355. // 更改 sw_group 表中 consumer_type 字段为在线 (客户/游客 离线状态 1:离线 0:在线)
  356. .set("consumer_type",ConsumerTypeEnum.ON_LINE.getKey())
  357. .update();
  358. //判断当前 认领这个 客户 的客服 是否在线
  359. if( StringUtils.isNotBlank(receptionNum) ){
  360. //在线
  361. chatGroup
  362. // 更改 sw_group 表中 service_account_type 字段为 在线 (客服离线状态 1: 离线 0: 在线)
  363. .set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  364. // 更改 sw_group 表中 message_state 字段为 非留言 (群组留言状态 1:留言 0:非留言)
  365. .set("message_state",MessageStateEnum.NO.getKey())
  366. .update();
  367. //更改客服的服务数量
  368. Integer num = Integer.valueOf(receptionNum);
  369. jedisTemplate.hashSet(serviceAccountContainerKey,user.getExtras().getString("serviceAccountRoleDepartmentId"),String.valueOf(++num));
  370. }else{
  371. //离线
  372. chatGroup
  373. // 更改 sw_group 表中 service_account_type 字段为 离线 (客服离线状态 1: 离线 0: 在线)
  374. .set("service_account_type",ServiceAccountOfflineTypeEnum.OFF_LINE.getKey())
  375. // 更改 sw_group 表中 message_state 字段为 留言 (群组留言状态 1:留言 0:非留言)
  376. .set("message_state",MessageStateEnum.YES.getKey())
  377. .update();
  378. }
  379. //之前 客服 和 客户 之间 有群组
  380. Group group = this.disposeChatGroupToGroup(chatGroup);
  381. groups.add(group);
  382. }else{
  383. // 创建新的群组
  384. Group group = this.createGroup(user);
  385. //把 Group 转成 Map 用于 jfianl框架的 添加使用
  386. Map<String, Object> groupAttrs = this.groupToMap(group);
  387. groupAttrs.put("group_state", GroupStateEnum.ON_LINE.getKey());
  388. groupAttrs.put("consumer_type", ConsumerTypeEnum.ON_LINE.getKey());
  389. //判断当前 认领这个 客户 的客服 是否在线
  390. if( StringUtils.isNotBlank(receptionNum) ){
  391. //在线
  392. //更改客服的服务数量
  393. Integer num = Integer.valueOf(receptionNum);
  394. jedisTemplate.hashSet(serviceAccountContainerKey,user.getExtras().getString("serviceAccountRoleDepartmentId"),String.valueOf(++num));
  395. //客服是否是离线状态 1: 是 0: 否
  396. groupAttrs.put("service_account_type", ServiceAccountOfflineTypeEnum.ON_LINE.getKey());
  397. //群组留言状态 1:留言 0:非留言
  398. groupAttrs.put("message_state", MessageStateEnum.NO.getKey());
  399. }else{
  400. //离线
  401. //客服是否是离线状态 1: 是 0: 否
  402. groupAttrs.put("service_account_type", ServiceAccountOfflineTypeEnum.OFF_LINE.getKey());
  403. //群组留言状态 1:留言 0:非留言
  404. groupAttrs.put("message_state", MessageStateEnum.YES.getKey());
  405. }
  406. //jfianl框架的 保存
  407. ChatGroup.dao._setAttrs(groupAttrs).save();
  408. groups.add(group);
  409. }
  410. }else{
  411. //按照游客 方式 处理 找到 在线客服 连接数 最少的
  412. groups.addAll(this.disposeVisitorGroupData(user));
  413. }
  414. if( user.getExtras().getBoolean("isCreateConversation")){
  415. Boolean noOnlineService = user.getExtras().getBoolean("noOnlineService");
  416. if(!noOnlineService){
  417. this.createConversation(groups.get(0),user);
  418. }
  419. }
  420. return groups;
  421. }
  422. /**
  423. * 创建 sw_conversation 数据
  424. * @param group
  425. * @param user
  426. * @return {@link }
  427. * @author Darren
  428. * @date 2020/2/6 10:16
  429. */
  430. private void createConversation(Group group,User user) {
  431. Map<String, Object> attrs = new HashMap<>();
  432. Long conversationId = SnowflakeIdUtils.getInstance().nextId();
  433. attrs.put("id", conversationId );
  434. //会话状态 0:游客会话 1:客户会话 群组类型 0:游客-客服 类型 1:客户-客服 类型
  435. attrs.put("state", group.getGroupType());
  436. attrs.put("consumer_id",group.getConsumerId());
  437. if(VisitTypeEnum.CUSTOMER.getKey().equals(user.getVisitType())){
  438. attrs.put("user_id", Long.valueOf(user.getExtras().getString("customerId")));
  439. }
  440. if(VisitTypeEnum.VISITOR.getKey().equals(user.getVisitType())){
  441. attrs.put("user_id", Long.valueOf(user.getExtras().getString("visitorId")));
  442. }
  443. attrs.put("user_nickname", user.getNick());
  444. attrs.put("user_phone", user.getExtras().getString("phone"));
  445. attrs.put("company_id", Long.valueOf(group.getCompanyId()));
  446. attrs.put("department_id", Long.valueOf(group.getDepartmentId()));
  447. ServiceAccountRoleDepartmentMiddle pojo
  448. = ServiceAccountRoleDepartmentMiddle.dao.findById(group.getServiceAccountRoleDepartmentId());
  449. attrs.put("service_account_id", pojo.getLong("service_account_id"));
  450. attrs.put("service_account_role_department_middle_id",group.getServiceAccountRoleDepartmentId());
  451. Conversation.dao._setAttrs(attrs).save();
  452. // 添加 sw_group_conversation_middle 数据
  453. GroupConversationMiddle.dao
  454. .set("id",SnowflakeIdUtils.getInstance().nextId())
  455. .set("group_id",group.getGroup_id())
  456. .set("conversation_id",conversationId)
  457. .save();
  458. }
  459. /**
  460. * 构建查询分组sql
  461. * @param user
  462. * @return {@link {@link String}}
  463. * @author Darren
  464. * @date 2020/2/4 20:45
  465. */
  466. private String createSelectGroupSql(User user){
  467. StringBuilder sql = new StringBuilder();
  468. sql.append(" select ")
  469. .append(GROUP_PROPERTY)
  470. .append(" from sw_group where 1 = 1 ")
  471. .append(" and company_id = " + user.getExtras().getString("companyId"))
  472. .append(" and department_id = " + user.getExtras().getString("departmentId"))
  473. .append(
  474. " and service_account_role_department_middle_id = "
  475. + user.getExtras().getString("serviceAccountRoleDepartmentId")
  476. )
  477. .append(" and consumer_id = " + user.getId())
  478. .append(" order by create_time desc");
  479. return sql.toString();
  480. }
  481. /**
  482. * 获取容器中 接待数量最少的 客服
  483. * @param serviceAccountContainer
  484. * @return {@link {@link Map.Entry< String, String>}}
  485. * @author Darren
  486. * @date 2020/2/5 10:34
  487. */
  488. private Map.Entry<String,String> getServiceAccountMinReceptionNum( Map<String, String> serviceAccountContainer ){
  489. if(!CollectionUtils.isEmpty(serviceAccountContainer)){
  490. List<Map.Entry<String, String>> entries = serviceAccountContainer.entrySet().stream().collect(Collectors.toList());
  491. entries.sort( (o1,o2) -> (Integer.valueOf(o1.getValue()) - Integer.valueOf(o2.getValue())) );
  492. return entries.get(0);
  493. }
  494. return null;
  495. }
  496. /**
  497. * 把 Group 转成 Map 用于 jfianl框架的 添加使用
  498. * @param group
  499. * @return {@link {@link Map< String, Object>}}
  500. * @author Darren
  501. * @date 2020/2/4 20:30
  502. */
  503. private Map<String, Object> groupToMap(Group group){
  504. Map<String, Object> attrs = new HashMap<>();
  505. attrs.put("group_id", group.getGroup_id());
  506. attrs.put("name", group.getName());
  507. attrs.put("avatar", group.getAvatar());
  508. attrs.put("service_account_role_department_middle_id", group.getServiceAccountRoleDepartmentId());
  509. attrs.put("consumer_id", group.getConsumerId());
  510. attrs.put("group_type", group.getGroupType());
  511. attrs.put("company_id", group.getCompanyId());
  512. attrs.put("department_id", group.getDepartmentId());
  513. return attrs;
  514. }
  515. /**
  516. * 创建群组
  517. * @param user
  518. * @return {@link {@link Group}}
  519. * @author Darren
  520. * @date 2020/2/4 20:28
  521. */
  522. private Group createGroup(User user){
  523. //创建新的群组
  524. Group group = new Group();
  525. group.setGroup_id(String.valueOf(SnowflakeIdUtils.getInstance().nextId()));
  526. //群组名称 采用客户名称
  527. group.setName(user.getNick());
  528. group.setAvatar(user.getAvatar());
  529. group.setServiceAccountRoleDepartmentId(user.getExtras().getString("serviceAccountRoleDepartmentId"));
  530. group.setConsumerId(user.getId());
  531. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  532. if(VisitTypeEnum.CUSTOMER.getKey().equals(user.getVisitType())){
  533. group.setGroupType(GroupTypeEnum.CUSTOMER.getKey());
  534. }
  535. if(VisitTypeEnum.VISITOR.getKey().equals(user.getVisitType())){
  536. group.setGroupType(GroupTypeEnum.VISITOR.getKey());
  537. }
  538. group.setCompanyId(user.getExtras().getString("companyId"));
  539. group.setDepartmentId(user.getExtras().getString("departmentId"));
  540. return group;
  541. }
  542. /** ============================================= <客户> 处理 end================================================== */
  543. /** ============================================= 客服处理 start================================================== */
  544. /**
  545. * 创建 客服 user 数据
  546. * @param map
  547. * @return {@link {@link User}}
  548. * @author Darren
  549. * @date 2020/2/3 19:59
  550. */
  551. private User createServiceAccountUser(Map<String, String> map){
  552. User user = new User();
  553. //当前访问人为客服
  554. user.setId(map.get("serviceAccountRoleDepartmentId"));
  555. //用户头像
  556. String headImg = map.get("headImg") == null ? null : map.get("headImg").replace("\"", "");
  557. user.setAvatar(headImg);
  558. //user nick
  559. String nickname = map.get("nickname") == null ? null : map.get("nickname").replace("\"", "");
  560. user.setNick(nickname);
  561. //扩展预留字段;
  562. Map<String, Object> serviceAccountMap = new HashMap<>();
  563. serviceAccountMap.put("companyId", map.get("companyId"));
  564. serviceAccountMap.put("isDefault", map.get("isDefault"));
  565. serviceAccountMap.put("departmentId", map.get("departmentId"));
  566. serviceAccountMap.put("hasViewAllServiceAccount", map.get("hasViewAllServiceAccount"));
  567. serviceAccountMap.put("serviceAccountId", map.get("id"));
  568. serviceAccountMap.put("intoChat", map.get("intoChat"));
  569. if(Boolean.valueOf(map.get("intoChat"))){
  570. String type = map.get("type").replace("\"","");
  571. if(VisitTypeEnum.CUSTOMER.getKey().equals(type)){
  572. serviceAccountMap.put("customerDepartmentId", map.get("customerDepartmentId"));
  573. String customerNickname = map.get("customerNickname") == null ? null : map.get("customerNickname").replace("\"", "");
  574. serviceAccountMap.put("customerNickname", customerNickname);
  575. String customerHeadImg = map.get("customerHeadImg") == null ? null : map.get("customerHeadImg").replace("\"", "");
  576. serviceAccountMap.put("customerHeadImg", customerHeadImg);
  577. String customerPhone = map.get("customerPhone") == null ? null : map.get("customerPhone").replace("\"", "");
  578. serviceAccountMap.put("customerPhone", customerPhone);
  579. serviceAccountMap.put("customerId", map.get("customerId"));
  580. serviceAccountMap.put("type", type);
  581. }
  582. if(VisitTypeEnum.VISITOR.getKey().equals(type)){
  583. serviceAccountMap.put("visitorDepartmentId", map.get("visitorDepartmentId"));
  584. String visitorNickname = map.get("visitorNickname") == null ? null : map.get("visitorNickname").replace("\"", "");
  585. serviceAccountMap.put("visitorNickname", visitorNickname);
  586. String visitorHeadImg = map.get("visitorHeadImg") == null ? null : map.get("visitorHeadImg").replace("\"", "");
  587. serviceAccountMap.put("visitorHeadImg", visitorHeadImg);
  588. String visitorPhone = map.get("visitorPhone") == null ? null : map.get("visitorPhone").replace("\"", "");
  589. serviceAccountMap.put("visitorPhone", visitorPhone);
  590. serviceAccountMap.put("visitorId", map.get("visitorId"));
  591. String groupId = map.get("groupId") == null ? null : map.get("groupId").replace("\"", "");
  592. serviceAccountMap.put("groupId", groupId);
  593. serviceAccountMap.put("type", type);
  594. }
  595. }
  596. user.setExtras(new JSONObject(serviceAccountMap));
  597. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  598. user.setVisitType(VisitTypeEnum.SERVICEACCOUNT.getKey());
  599. user.setGroups(this.initServiceAccountGroups(user));
  600. user.setViewAllGroups(this.initViewAllServiceAccountGroup(user));
  601. user.setIntoChatGroups(this.initIntoChatGroups(user));
  602. return user;
  603. }
  604. /**
  605. * 初始化 由客服主动发起聊天的群组
  606. * @param user
  607. * @return {@link {@link List< Group>}}
  608. * @author Darren
  609. * @date 2020/2/17 9:43
  610. */
  611. private List<Group> initIntoChatGroups(User user) {
  612. List<Group> groups = new ArrayList<>();
  613. //是否创建 会话
  614. user.getExtras().put("isCreateConversation",true);
  615. String type = user.getExtras().getString("type");
  616. if( user.getExtras().getBoolean("intoChat") ){
  617. if(VisitTypeEnum.CUSTOMER.getKey().equals(type)){
  618. groups.add(this.disposeCustomerIntoChatGroupData(user));
  619. }else{
  620. groups.add(this.disposeVisitorIntoChatGroupData(user));
  621. }
  622. if( user.getExtras().getBoolean("isCreateConversation")){
  623. this.createIntoChatConversation(groups.get(0),user);
  624. }
  625. }
  626. return groups;
  627. }
  628. /**
  629. * 处理客服 向游客 发起聊天
  630. * @param user
  631. * @return {@link {@link Group}}
  632. * @author Darren
  633. * @date 2020/2/18 15:04
  634. */
  635. private Group disposeVisitorIntoChatGroupData(User user){
  636. // 群组 是留言群组 或 群组为在线状态 则不重新创建会话
  637. user.getExtras().put("isCreateConversation",false);
  638. ChatGroup chatGroup = ChatGroup.dao.findById(user.getExtras().get("groupId"));
  639. chatGroup
  640. // 更改 sw_group 表中 service_account_type 字段为 在线 (客服离线状态 1: 离线 0: 在线)
  641. .set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  642. .update();
  643. return disposeChatGroupToGroup(chatGroup);
  644. }
  645. /**
  646. * 处理客服 向客户 发起聊天
  647. * @param user
  648. * @return {@link {@link Group}}
  649. * @author Darren
  650. * @date 2020/2/18 15:04
  651. */
  652. private Group disposeCustomerIntoChatGroupData(User user) {
  653. String customerDepartmentId = user.getExtras().getString("customerDepartmentId");
  654. StringBuilder sql = new StringBuilder();
  655. sql.append(" select ")
  656. .append(GROUP_PROPERTY)
  657. .append(" from sw_group where group_type = 1 ")
  658. .append(" and company_id = " + user.getExtras().getString("companyId"))
  659. .append(" and department_id = " + user.getExtras().getString("departmentId"))
  660. .append(
  661. " and service_account_role_department_middle_id = " + user.getId()
  662. )
  663. .append(" and consumer_id = " + customerDepartmentId )
  664. .append(" order by create_time desc");
  665. ChatGroup chatGroup = ChatGroup.dao.findFirst(sql.toString());
  666. //customer 是否在线 如果不在线就是 留言群组
  667. boolean isOnline = isOnline(customerDepartmentId);
  668. if(null != chatGroup){
  669. //说明 当前存在 群组
  670. if(
  671. MessageStateEnum.YES.getKey() == chatGroup.getInt("message_state") ||
  672. GroupStateEnum.ON_LINE.getKey() == chatGroup.getInt("group_state")
  673. ){
  674. // 群组 是留言群组 或 群组为在线状态 则不重新创建会话
  675. user.getExtras().put("isCreateConversation",false);
  676. }
  677. chatGroup
  678. // 更改 sw_group 表中 service_account_type 字段为 在线 (客服离线状态 1: 离线 0: 在线)
  679. .set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  680. .update();
  681. if(isOnline){
  682. chatGroup
  683. // 更改 sw_group 表中 group_state 字段为在线 (群组离线状态 1: 离线 0: 在线)
  684. .set("group_state",GroupStateEnum.ON_LINE.getKey())
  685. // 更改 sw_group 表中 consumer_type 字段为在线 (客户/游客 离线状态 1:离线 0:在线)
  686. .set("consumer_type",ConsumerTypeEnum.ON_LINE.getKey())
  687. // 更改 sw_group 表中 message_state 字段为 非留言 (群组留言状态 1:留言 0:非留言)
  688. .set("message_state",MessageStateEnum.NO.getKey())
  689. .update();
  690. }else{
  691. chatGroup
  692. // 更改 sw_group 表中 group_state 字段为在线 (群组离线状态 1: 离线 0: 在线)
  693. .set("group_state",GroupStateEnum.OFF_LINE.getKey())
  694. // 更改 sw_group 表中 consumer_type 字段为在线 (客户/游客 离线状态 1:离线 0:在线)
  695. .set("consumer_type",ConsumerTypeEnum.OFF_LINE.getKey())
  696. // 更改 sw_group 表中 message_state 字段为 非留言 (群组留言状态 1:留言 0:非留言)
  697. .set("message_state",MessageStateEnum.YES.getKey())
  698. .update();
  699. }
  700. return disposeChatGroupToGroup(chatGroup);
  701. }else{
  702. //创建新的群组
  703. Group group = this.createIntoChatGroup(user);
  704. Map<String, Object> groupAttrs = this.groupToMap(group);
  705. groupAttrs.put("service_account_type", ServiceAccountOfflineTypeEnum.ON_LINE.getKey());
  706. if(isOnline){
  707. groupAttrs.put("group_state", GroupStateEnum.ON_LINE.getKey());
  708. groupAttrs.put("consumer_type", ConsumerTypeEnum.ON_LINE.getKey());
  709. groupAttrs.put("message_state", MessageStateEnum.NO.getKey());
  710. }else{
  711. groupAttrs.put("group_state", GroupStateEnum.OFF_LINE.getKey());
  712. groupAttrs.put("consumer_type", ConsumerTypeEnum.OFF_LINE.getKey());
  713. groupAttrs.put("message_state", MessageStateEnum.YES.getKey());
  714. }
  715. //jfianl框架的 保存
  716. ChatGroup.dao._setAttrs(groupAttrs).save();
  717. return group;
  718. }
  719. }
  720. /**
  721. * 创建客服邀请客户进入聊天的会话
  722. * @param group
  723. * @param user
  724. * @return {@link }
  725. * @author Darren
  726. * @date 2020/2/17 14:55
  727. */
  728. private void createIntoChatConversation(Group group, User user){
  729. Map<String, Object> attrs = new HashMap<>();
  730. Long conversationId = SnowflakeIdUtils.getInstance().nextId();
  731. attrs.put("id", conversationId );
  732. //会话状态 0:游客会话 1:客户会话 群组类型 0:游客-客服 类型 1:客户-客服 类型
  733. attrs.put("state", group.getGroupType());
  734. attrs.put("consumer_id", group.getConsumerId());
  735. attrs.put("user_id", user.getExtras().getString("customerId"));
  736. attrs.put("user_nickname", user.getExtras().getString("customerNickname"));
  737. attrs.put("user_phone", user.getExtras().getString("customerPhone"));
  738. attrs.put("company_id", Long.valueOf(group.getCompanyId()));
  739. attrs.put("department_id", Long.valueOf(group.getDepartmentId()));
  740. ServiceAccountRoleDepartmentMiddle pojo
  741. = ServiceAccountRoleDepartmentMiddle.dao.findById(group.getServiceAccountRoleDepartmentId());
  742. attrs.put("service_account_id", pojo.getLong("service_account_id"));
  743. attrs.put("service_account_role_department_middle_id", group.getServiceAccountRoleDepartmentId());
  744. Conversation.dao._setAttrs(attrs).save();
  745. // 添加 sw_group_conversation_middle 数据
  746. GroupConversationMiddle.dao
  747. .set("id",SnowflakeIdUtils.getInstance().nextId())
  748. .set("group_id",group.getGroup_id())
  749. .set("conversation_id",conversationId)
  750. .save();
  751. }
  752. /**
  753. * 创建客服邀请客户 加入聊天群组
  754. * @param user
  755. * @return {@link {@link Group}}
  756. * @author Darren
  757. * @date 2020/2/17 10:43
  758. */
  759. private Group createIntoChatGroup(User user){
  760. Group group = new Group();
  761. group.setGroup_id(String.valueOf(SnowflakeIdUtils.getInstance().nextId()));
  762. //群组名称 采用客户名称
  763. group.setName(user.getExtras().getString("customerNickname"));
  764. group.setAvatar(user.getExtras().getString("customerHeadImg"));
  765. group.setServiceAccountRoleDepartmentId(user.getId());
  766. group.setConsumerId(user.getExtras().getString("customerDepartmentId"));
  767. group.setGroupType(GroupTypeEnum.CUSTOMER.getKey());
  768. group.setCompanyId(user.getExtras().getString("companyId"));
  769. group.setDepartmentId(user.getExtras().getString("departmentId"));
  770. return group;
  771. }
  772. /**
  773. * 判断用户是否在线
  774. * @param customerDepartmentId
  775. * @return {@link {@link boolean}}
  776. * @author Darren
  777. * @date 2020/2/17 10:03
  778. */
  779. private boolean isOnline(String customerDepartmentId){
  780. if(ImConst.ON.equals(imConfig.getIsStore())){
  781. MessageHelper messageHelper = imConfig.getMessageHelper();
  782. return messageHelper.isOnline(customerDepartmentId);
  783. }else{
  784. SetWithLock<ChannelContext> channelContexts = ImAio.getChannelContextsByUserId(customerDepartmentId);
  785. return (channelContexts != null && channelContexts.size() > 0);
  786. }
  787. }
  788. /**
  789. * 初始化 查看全部客服权限 才能看的群组数据
  790. * @param user
  791. * @return {@link {@link List< Group>}}
  792. * @author Darren
  793. * @date 2020/2/3 20:29
  794. */
  795. private List<Group> initViewAllServiceAccountGroup(User user) {
  796. List<Group> groups = new ArrayList<>();
  797. //1.判断当前客服是否具有查看当前部门下 全部客服通话的权限
  798. if( Boolean.valueOf(user.getExtras().getString("hasViewAllServiceAccount")) ){
  799. boolean flag = false;
  800. //获取 具有查看全部客服通话权限 的客服容器 并且 加入到该容器中 key数据格式: companyId : departmentId : ADMIN
  801. String adminContainerKey = user.getExtras().getString("companyId")
  802. + ImConst.SEPARATOR + user.getExtras().getString("departmentId")
  803. + ImConst.SEPARATOR + ImConst.ADMIN ;
  804. List<String> adminContainer = jedisTemplate.listGetAll(adminContainerKey);
  805. if( CollectionUtils.isEmpty(adminContainer) ){
  806. //adminContainer 不存在
  807. jedisTemplate.listPushTail(adminContainerKey,user.getId());
  808. flag = true;
  809. }else{
  810. if( !adminContainer.contains(user.getId()) ) {
  811. //如果容器中 不 包含这个 id 则添加
  812. jedisTemplate.listPushTail(adminContainerKey,user.getId());
  813. flag = true;
  814. }
  815. }
  816. //... 然后把当前 客服 加入到 该平台下 部门下 所有群组中
  817. if(flag){
  818. //从数据库中获取数据
  819. //1.查询所有留言群组
  820. StringBuilder sql1 = new StringBuilder();
  821. sql1
  822. .append(" select ")
  823. .append(GROUP_PROPERTY)
  824. //message_state: 群组留言状态 1:留言 0:非留言
  825. //group_type: 群组类型 0:游客-客服 类型 1:客户-客服 类型
  826. .append(" from sw_group where group_type = 1 and message_state = 1 ")
  827. .append(" and company_id = "+ user.getExtras().getString("companyId") + " ")
  828. .append(" and department_id = " + user.getExtras().getString("departmentId") + " ");
  829. List<ChatGroup> messageChatGroups = ChatGroup.dao.find(sql1.toString());
  830. if( !CollectionUtils.isEmpty(messageChatGroups) ){
  831. messageChatGroups = messageChatGroups.stream()
  832. .filter(
  833. x -> !x.get("service_account_role_department_middle_id").equals(user.getId())
  834. )
  835. .collect(Collectors.toList());
  836. List<Group> messageGroups = this.disposeChatGroupsToGroups(messageChatGroups);
  837. if( !CollectionUtils.isEmpty(messageGroups) ){
  838. groups.addAll(messageGroups);
  839. }
  840. }
  841. //2.查询所有在线群组
  842. StringBuilder sql2 = new StringBuilder();
  843. sql2
  844. .append(" select ")
  845. .append(GROUP_PROPERTY)
  846. //查看当前平台下 部门下 的所有在线群组
  847. //group_state: 群组离线状态 1: 离线 0: 在线
  848. //consumer_type: 客户/游客 离线状态 1:离线 0:在线
  849. //message_state: 群组留言状态 1:留言 0:非留言
  850. .append(" from sw_group where group_state = 0 and consumer_type = 0 and message_state = 0 ")
  851. .append(" and company_id = "+ user.getExtras().getString("companyId") + " ")
  852. .append(" and department_id = " + user.getExtras().getString("departmentId") + " ");
  853. List<ChatGroup> onlineChatGroups = ChatGroup.dao.find(sql2.toString());
  854. if( !CollectionUtils.isEmpty(onlineChatGroups) ){
  855. onlineChatGroups = onlineChatGroups.stream()
  856. .filter(
  857. x -> !x.get("service_account_role_department_middle_id").equals(user.getId())
  858. )
  859. .collect(Collectors.toList());
  860. List<Group> onlineGroups = this.disposeChatGroupsToGroups(onlineChatGroups);
  861. if( !CollectionUtils.isEmpty(onlineGroups) ){
  862. groups.addAll(onlineGroups);
  863. }
  864. }
  865. }
  866. }
  867. return groups;
  868. }
  869. /***
  870. * 初始化 客服对应的 群组数据
  871. * @param user
  872. * @return {@link {@link List< Group>}}
  873. * @author Darren
  874. * @date 2020/2/3 19:55
  875. */
  876. private List<Group> initServiceAccountGroups(User user) {
  877. List<ChatGroup> chatGroups = new ArrayList<>();
  878. //从数据库中获取数据
  879. //2.查询 客户/游客 对应平台下 对应部门下 在线群组状态 和 客户/游客在线状态 和 群组非留言状态
  880. StringBuilder sql2 = new StringBuilder();
  881. sql2
  882. .append(" select ")
  883. .append(GROUP_PROPERTY)
  884. //message_state: 群组留言状态 1:留言 0:非留言
  885. //consumer_type: 客户/游客 离线状态 1:离线 0:在线
  886. //group_state: 群组离线状态 1: 离线 0: 在线
  887. .append(" from sw_group where group_state = 0 and consumer_type = 0 and message_state = 0")
  888. .append(" and company_id = "+ user.getExtras().getString("companyId") + " ")
  889. .append(" and department_id = " + user.getExtras().getString("departmentId") + " ")
  890. .append(
  891. " and service_account_role_department_middle_id = " + user.getId()
  892. );
  893. List<ChatGroup> onlineChatGroups = ChatGroup.dao.find(sql2.toString());
  894. if( !CollectionUtils.isEmpty(onlineChatGroups) ){
  895. chatGroups.addAll(onlineChatGroups);
  896. //修改客服离线状态 为 在线
  897. for (ChatGroup chatGroup : onlineChatGroups) {
  898. chatGroup.set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  899. .update();
  900. }
  901. }
  902. //1.查询 对应平台下 对应部门下 留言群组
  903. StringBuilder sql1 = new StringBuilder();
  904. sql1
  905. .append(" select ")
  906. .append(GROUP_PROPERTY)
  907. //message_state: 群组留言状态 1:留言 0:非留言
  908. //group_type: 群组类型 0:游客-客服 类型 1:客户-客服 类型
  909. .append(" from sw_group where group_type = 1 and message_state = 1 ")
  910. .append(" and company_id = "+ user.getExtras().getString("companyId") + " ")
  911. .append(" and department_id = " + user.getExtras().getString("departmentId") + " ")
  912. .append(
  913. " and service_account_role_department_middle_id = " + user.getId()
  914. );
  915. List<ChatGroup> messageChatGroups = ChatGroup.dao.find(sql1.toString());
  916. if( !CollectionUtils.isEmpty(messageChatGroups) ){
  917. chatGroups.addAll(messageChatGroups);
  918. //修改 sw_group 表中的 message_state 状态; 群组留言状态 1:留言 0:非留言
  919. //修改 sw_group 表中的 service_account_type 状态; 客服离线状态 1: 离线 0: 在线
  920. for (ChatGroup chatGroup : messageChatGroups) {
  921. chatGroup .set("message_state", MessageStateEnum.NO.getKey())
  922. .set("service_account_type",ServiceAccountOfflineTypeEnum.ON_LINE.getKey())
  923. .update();
  924. }
  925. }
  926. return this.disposeChatGroupsToGroups(chatGroups);
  927. }
  928. /***
  929. * 处理 访问类型 为客服 的数据
  930. * @param
  931. * @return {@link }
  932. * @author Darren
  933. * @date 2020/2/3 14:01
  934. */
  935. private void disposeServiceAccountData(User user){
  936. //1.向客服容器中 添加客服 客服容器中过滤掉超级管理员
  937. // key组成 : companyId : departmentId : SERVICEACCOUNT
  938. // value组成 : Map<String ( serviceAccountRoleDepartmentId ), String (当前连接客户人数)>
  939. String serviceAccountContainerKey
  940. = user.getExtras().getString("companyId") + ImConst.SEPARATOR
  941. + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
  942. + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
  943. //判断该客服是否是超级管理员
  944. String isDefault = user.getExtras().getString("isDefault");
  945. if(DefaultStateEnum.NO.getKey().equals(isDefault)){
  946. List<Group> groups = user.getGroups();
  947. int num = 0;
  948. if(!CollectionUtils.isEmpty(groups)){
  949. num = groups.size();
  950. }
  951. List<Group> intoChatGroups = user.getIntoChatGroups();
  952. if(!CollectionUtils.isEmpty(groups)){
  953. num += intoChatGroups.size();
  954. }
  955. Map<String, String> serviceAccountContainer = jedisTemplate.hashGetAll(serviceAccountContainerKey);
  956. //判断 客服容器 是否存在
  957. if( CollectionUtils.isEmpty(serviceAccountContainer) ){
  958. //当前平台下 部门下 客服容器为null
  959. serviceAccountContainer = new HashMap<>();
  960. serviceAccountContainer.put(user.getId(),String.valueOf(num));
  961. jedisTemplate.hashMultipleSet(serviceAccountContainerKey,serviceAccountContainer);
  962. }else{
  963. //客服容器 存在
  964. //判断容器中是否存在这个客服
  965. if(serviceAccountContainer.containsKey(user.getId())){
  966. //获取 当前客服 服务的 客户/游客 数量
  967. Integer userNum = Integer.valueOf(serviceAccountContainer.get(user.getId())) + num;
  968. jedisTemplate.hashSet(serviceAccountContainerKey,user.getId(),String.valueOf( userNum ));
  969. }else{
  970. //不存在这个客服数据
  971. jedisTemplate.hashSet(serviceAccountContainerKey,user.getId(),String.valueOf(num));
  972. }
  973. }
  974. }
  975. }
  976. /** ============================================= 客服处理 end =================================================== */
  977. /**
  978. * 转换数据 List<ChatGroup> >> List<Group>
  979. * @param chatGroups
  980. * @return {@link {@link List< Group>}}
  981. * @author Darren
  982. * @date 2020/2/4 14:27
  983. */
  984. private List<Group> disposeChatGroupsToGroups(List<ChatGroup> chatGroups){
  985. if( !CollectionUtils.isEmpty(chatGroups) ){
  986. List<Group> groups = new ArrayList<>();
  987. for (ChatGroup chatGroup : chatGroups) {
  988. Group group = this.disposeChatGroupToGroup(chatGroup);
  989. groups.add(group);
  990. }
  991. return groups;
  992. }
  993. return null;
  994. }
  995. /**
  996. * 转换数据 ChatGroup >> Group
  997. * @param chatGroup
  998. * @author Darren
  999. * @date 2020/2/4 14:27
  1000. */
  1001. private Group disposeChatGroupToGroup(ChatGroup chatGroup){
  1002. if( null != chatGroup ){
  1003. Group group = new Group();
  1004. group.setGroup_id(chatGroup.getStr("group_id"));
  1005. group.setName(chatGroup.getStr("name"));
  1006. group.setAvatar(chatGroup.getStr("avatar"));
  1007. group.setServiceAccountRoleDepartmentId(chatGroup.getStr("service_account_role_department_middle_id"));
  1008. group.setConsumerId(chatGroup.getStr("consumer_id"));
  1009. group.setGroupType(chatGroup.getInt("group_type"));
  1010. group.setCompanyId(chatGroup.getStr("company_id"));
  1011. group.setDepartmentId(chatGroup.getStr("department_id"));
  1012. return group;
  1013. }
  1014. return null;
  1015. }
  1016. @Override
  1017. public void onSuccess(ChannelContext channelContext) {
  1018. logger.info("登录成功回调方法...");
  1019. }
  1020. @Override
  1021. public boolean isProtocol(ChannelContext channelContext) {
  1022. return true;
  1023. }
  1024. /**
  1025. * 处理器的名称
  1026. * @return
  1027. */
  1028. @Override
  1029. public String name() {
  1030. return ImConst.IM_CHAT_LOGIN_SERVICE_PROCESSOR;
  1031. }
  1032. }