IMChatLoginServiceProcessor.java 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. package com.cn.service;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.cn.model.ChatGroup;
  4. import com.cn.model.ServiceAccountRoleDepartmentMiddle;
  5. import nl.basjes.shaded.org.springframework.util.CollectionUtils;
  6. import org.jim.server.enums.*;
  7. import org.apache.commons.lang3.StringUtils;
  8. import org.jim.common.ImConst;
  9. import org.jim.common.ImStatus;
  10. import org.jim.common.cache.redis.JedisTemplate;
  11. import org.jim.common.packets.*;
  12. import org.jim.server.command.handler.processor.login.LoginCmdProcessor;
  13. import org.jim.server.util.SnowflakeIdUtils;
  14. import org.slf4j.Logger;
  15. import org.slf4j.LoggerFactory;
  16. import org.tio.core.ChannelContext;
  17. import java.util.*;
  18. import java.util.stream.Collectors;
  19. /**
  20. * @author Darren
  21. * @date 2020/2/2 11:03
  22. */
  23. public class IMChatLoginServiceProcessor implements LoginCmdProcessor {
  24. private static Logger logger = LoggerFactory.getLogger(IMChatLoginServiceProcessor.class);
  25. private static JedisTemplate jedisTemplate = null;
  26. private static final String GROUP_PROPERTY = " group_id,name,avatar,service_account_role_department_middle_id,consumerId,group_type,company_id,department_id ";
  27. static {
  28. try {
  29. jedisTemplate = JedisTemplate.me();
  30. } catch (Exception e) {
  31. logger.info("JedisTemplate初始化失败!");
  32. e.printStackTrace();
  33. }
  34. }
  35. /**
  36. * doLogin方法注意:J-IM登陆命令是根据user是否为空判断是否登陆成功,
  37. * 当登陆失败时设置user属性需要为空,相反登陆成功user属性是必须非空的;
  38. * @param loginReqBody
  39. * @param channelContext
  40. * @return
  41. */
  42. @Override
  43. public LoginRespBody doLogin(LoginReqBody loginReqBody, ChannelContext channelContext) {
  44. //获取token
  45. String token = loginReqBody.getToken();
  46. LoginRespBody loginRespBody;
  47. User user = null;
  48. if(StringUtils.isNotBlank(token)){
  49. user = this.getUser(token);
  50. }
  51. if(user == null){
  52. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10008);
  53. }else{
  54. Boolean noOnlineService = user.getExtras().getBoolean("noOnlineService");
  55. if(noOnlineService != null && noOnlineService){
  56. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10022,user);
  57. }else{
  58. loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10007,user);
  59. }
  60. }
  61. return loginRespBody;
  62. }
  63. /**
  64. * 通过token 获取用户信息
  65. * @param token
  66. * @return {@link {@link User}}
  67. * @author Darren
  68. * @date 2020/2/5 15:34
  69. */
  70. public User getUser(String token) {
  71. User user = null;
  72. String[] tokenArray = token.split(ImConst.SEPARATOR);
  73. if(tokenArray.length == 2){
  74. //判断访问类型
  75. String visitType = tokenArray[0];
  76. Map<String, String> map = jedisTemplate.hashGetAll(token);
  77. if( !CollectionUtils.isEmpty(map) ){
  78. if( VisitTypeEnum.SERVICEACCOUNT.getKey().equals(visitType) ){
  79. user = this.createServiceAccountUser(map);
  80. this.disposeServiceAccountData(user);
  81. }
  82. if( VisitTypeEnum.CUSTOMER.getKey().equals(visitType) ){
  83. //当前访问人为客户
  84. user = this.createCustomerData(map);
  85. }
  86. if( VisitTypeEnum.VISITOR.getKey().equals(visitType) ){
  87. //当前访问人为游客
  88. user = this.createVisitorData(map);
  89. }
  90. }
  91. }
  92. return user;
  93. }
  94. /** ============================================= <游客> 处理 start================================================== */
  95. /**
  96. * 创建 游客 user 数据
  97. * @param map
  98. * @return {@link {@link User}}
  99. * @author Darren
  100. * @date 2020/2/5 15:30
  101. */
  102. private User createVisitorData(Map<String, String> map) {
  103. User user = new User();
  104. user.setId(map.get("visitorDepartmentId"));
  105. String headImg = map.get("headImg");
  106. user.setAvatar(headImg);
  107. String nickname = map.get("nickname");
  108. user.setNick(nickname);
  109. Map<String, Object> visitorMap = new HashMap<>();
  110. visitorMap.put("visitorId",map.get("id"));
  111. visitorMap.put("companyId",map.get("companyId"));
  112. visitorMap.put("departmentId",map.get("departmentId"));
  113. visitorMap.put("phone",map.get("phone"));
  114. user.setExtras(new JSONObject(visitorMap));
  115. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  116. user.setVisitType(VisitTypeEnum.VISITOR.getKey());
  117. user.setGroups(this.initVisitorGroups(user));
  118. return user;
  119. }
  120. /**
  121. * 初始化游客 群组数据
  122. * @param user
  123. * @return {@link {@link List< Group>}}
  124. * @author Darren
  125. * @date 2020/2/5 15:26
  126. */
  127. private List<Group> initVisitorGroups(User user) {
  128. return disposeVisitorGroupData(user);
  129. }
  130. /**
  131. * 处理游客群组数据
  132. * @param user
  133. * @return {@link {@link List< Group>}}
  134. * @author Darren
  135. * @date 2020/2/5 15:25
  136. */
  137. private List<Group> disposeVisitorGroupData(User user){
  138. //获取 当前平台下 部门下 在线的 客服
  139. String serviceAccountContainerKey
  140. = user.getExtras().getString("companyId") + ImConst.SEPARATOR
  141. + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
  142. + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
  143. List<Group> groups = new ArrayList<>();
  144. //从当前在线的客服中 获取 连接客户数最少的 客服
  145. //value组成 : Map<String ( serviceAccountRoleDepartmentId ), String (当前连接客户人数)>
  146. Map<String, String> serviceAccountContainer = jedisTemplate.hashGetAll(serviceAccountContainerKey);
  147. Map.Entry<String, String> minReceptionNumServiceAccount = this.getServiceAccountMinReceptionNum(serviceAccountContainer);
  148. if( null != minReceptionNumServiceAccount ){
  149. //当前平台下部门下 存在客服
  150. user.getExtras().put("serviceAccountRoleDepartmentId",minReceptionNumServiceAccount.getKey());
  151. //创建临时在线群组 当客户 断开连接时 删除群组
  152. Group group = this.createGroup(user);
  153. //把 Group 转成 Map 用于 jfianl框架的 添加使用
  154. Map<String, Object> attrs = groupToMap(group);
  155. attrs.put("service_account_type", ServiceAccountOfflineTypeEnum.NO.getKey());
  156. //jfianl框架的 保存
  157. ChatGroup.dao._setAttrs(attrs).save();
  158. groups.add(group);
  159. //更改 客服正在 服务的 客户/游客 数量
  160. int num = Integer.valueOf(minReceptionNumServiceAccount.getValue());
  161. jedisTemplate.hashSet(serviceAccountContainerKey,minReceptionNumServiceAccount.getKey(),String.valueOf(++num));
  162. }else{
  163. //当前平台下部门下 没有在线客服
  164. user.getExtras().put("noOnlineService",true);
  165. }
  166. return groups;
  167. }
  168. /** ============================================= <游客> 处理 end================================================== */
  169. /** ============================================= <客户> 处理 start================================================== */
  170. /**
  171. * 创建 客户 user 数据
  172. * @param map
  173. * @return {@link {@link User}}
  174. * @author Darren
  175. * @date 2020/2/4 10:07
  176. */
  177. private User createCustomerData(Map<String, String> map) {
  178. User user = new User();
  179. user.setId(map.get("customerDepartmentId"));
  180. String headImg = map.get("headImg");
  181. user.setAvatar(headImg);
  182. String nickname = map.get("nickname");
  183. user.setNick(nickname);
  184. Map<String, Object> customerMap = new HashMap<>();
  185. customerMap.put("isBlack",map.get("isBlack"));
  186. customerMap.put("isClaim",map.get("isClaim"));
  187. customerMap.put("customerId",map.get("id"));
  188. customerMap.put("companyId",map.get("companyId"));
  189. customerMap.put("departmentId",map.get("departmentId"));
  190. customerMap.put("serviceAccountId",map.get("serviceAccountId"));
  191. customerMap.put("phone",map.get("phone"));
  192. customerMap.put("serviceAccountRoleDepartmentId",map.get("serviceAccountRoleDepartmentId"));
  193. user.setExtras(new JSONObject(customerMap));
  194. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  195. user.setVisitType(VisitTypeEnum.CUSTOMER.getKey());
  196. user.setGroups(this.initCustomerGroups(user));
  197. return user;
  198. }
  199. /**
  200. * 绑定客户群组 一个客户在一个平台下在一个部门下 只会有一个群组
  201. * @param user
  202. * @return {@link {@link List< Group>}}
  203. * @author Darren
  204. * @date 2020/2/4 11:05
  205. */
  206. private List<Group> initCustomerGroups(User user) {
  207. //获取 当前平台下 部门下 在线的 客服
  208. String serviceAccountContainerKey
  209. = user.getExtras().getString("companyId") + ImConst.SEPARATOR
  210. + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
  211. + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
  212. List<Group> groups = new ArrayList<>();
  213. //是否认领 1:是 0:否
  214. String isClaim = user.getExtras().getString("isClaim");
  215. //是否加入黑名单 1:是 0:否
  216. String isBlack = user.getExtras().getString("isBlack");
  217. if( CustomerClaimTypeEnum.YES.getKey().equals(isClaim) && BlackListStateEnum.NO.getKey().equals(isBlack) ){
  218. //被认领 并且 没有加入黑名单
  219. String receptionNum
  220. = jedisTemplate.hashGet(
  221. serviceAccountContainerKey
  222. , user.getExtras().getString("serviceAccountRoleDepartmentId")
  223. );
  224. //判断当前 认领这个 客户 的客服 是否在线
  225. if( StringUtils.isNotBlank(receptionNum) ){
  226. //在线
  227. //创建临时在线群组 当客户 断开连接时 删除群组
  228. Group group = this.createGroup(user);
  229. //把 Group 转成 Map 用于 jfianl框架的 添加使用
  230. Map<String, Object> attrs = groupToMap(group);
  231. //客服是否是离线状态 1: 是 0: 否
  232. attrs.put("service_account_type", ServiceAccountOfflineTypeEnum.NO.getKey());
  233. //jfianl框架的 保存
  234. ChatGroup.dao._setAttrs(attrs).save();
  235. groups.add(group);
  236. Integer num = Integer.valueOf(receptionNum);
  237. //更改客服的服务数量
  238. jedisTemplate.hashSet(serviceAccountContainerKey,user.getExtras().getString("serviceAccountRoleDepartmentId"),String.valueOf(++num));
  239. }else{
  240. //离线
  241. //查询客户 是否有 上一次 留言的离线群组
  242. String sql = createSelectGroupSql(user);
  243. ChatGroup chatGroup = ChatGroup.dao.findFirst(sql);
  244. if( null != chatGroup ) {
  245. // 客户 上一次 留言的离线群组
  246. Group group = this.disposeChatGroupToGroup(chatGroup);
  247. groups.add(group);
  248. }else{
  249. //创建临时离线群组 当客户 断开连接时 删除群组
  250. Group group = this.createGroup(user);
  251. //把 Group 转成 Map 用于 jfianl框架的 添加使用
  252. Map<String, Object> attrs = groupToMap(group);
  253. //客服是否是离线状态 1: 是 0: 否
  254. attrs.put("service_account_type", ServiceAccountOfflineTypeEnum.YES.getKey());
  255. //jfianl框架的 保存
  256. ChatGroup.dao._setAttrs(attrs).save();
  257. groups.add(group);
  258. }
  259. }
  260. }else{
  261. //按照游客 方式 处理 找到 在线客服 连接数 最少的
  262. groups.addAll(this.disposeVisitorGroupData(user));
  263. }
  264. return groups;
  265. }
  266. /**
  267. * 创建 sw_conversation 数据
  268. * @param group
  269. * @param user
  270. * @return {@link }
  271. * @author Darren
  272. * @date 2020/2/6 10:16
  273. */
  274. private void createConversation(Group group,User user) {
  275. ServiceAccountRoleDepartmentMiddle dao = ServiceAccountRoleDepartmentMiddle.dao;
  276. Map<String, Object> attrs = new HashMap<>();
  277. attrs.put("id", Long.valueOf(group.getGroup_id()));
  278. //会话状态 0:游客会话 1:客户会话 群组类型 0:游客-客服 类型 1:客户-客服 类型
  279. attrs.put("state", group.getGroupType());
  280. if(VisitTypeEnum.CUSTOMER.getKey().equals(user.getVisitType())){
  281. attrs.put("user_id", Long.valueOf(user.getExtras().getString("customerId")));
  282. }
  283. if(VisitTypeEnum.VISITOR.getKey().equals(user.getVisitType())){
  284. attrs.put("user_id", Long.valueOf(user.getExtras().getString("visitorId")));
  285. }
  286. attrs.put("user_nickname", user.getNick());
  287. attrs.put("user_phone", user.getExtras().getString("phone"));
  288. attrs.put("company_id", Long.valueOf(group.getCompanyId()));
  289. attrs.put("department_id", Long.valueOf(group.getDepartmentId()));
  290. ServiceAccountRoleDepartmentMiddle pojo
  291. = dao.findById(group.getServiceAccountRoleDepartmentId());
  292. attrs.put("service_account_id", Long.valueOf(pojo.get("service_account_id")));
  293. dao._setAttrs(attrs).save();
  294. }
  295. /**
  296. * 构建查询分组sql
  297. * @param user
  298. * @return {@link {@link String}}
  299. * @author Darren
  300. * @date 2020/2/4 20:45
  301. */
  302. public String createSelectGroupSql(User user){
  303. StringBuilder sql = new StringBuilder();
  304. sql.append(" select ")
  305. .append(GROUP_PROPERTY)
  306. .append(" from sw_group where service_account_type = 1 ")
  307. .append(" and company_id = " + user.getExtras().getString("companyId"))
  308. .append(" and department_id = " + user.getExtras().getString("departmentId"))
  309. .append(
  310. " and service_account_role_department_middle_id = "
  311. + user.getExtras().getString("serviceAccountRoleDepartmentId")
  312. )
  313. .append(" and consumer_id = " + user.getId())
  314. .append(" order by create_time desc");
  315. return sql.toString();
  316. }
  317. /**
  318. * 获取容器中 接待数量最少的 客服
  319. * @param serviceAccountContainer
  320. * @return {@link {@link Map.Entry< String, String>}}
  321. * @author Darren
  322. * @date 2020/2/5 10:34
  323. */
  324. private Map.Entry<String,String> getServiceAccountMinReceptionNum( Map<String, String> serviceAccountContainer ){
  325. if(!CollectionUtils.isEmpty(serviceAccountContainer)){
  326. List<Map.Entry<String, String>> entries = serviceAccountContainer.entrySet().stream().collect(Collectors.toList());
  327. entries.sort( (o1,o2) -> (Integer.valueOf(o1.getValue()) - Integer.valueOf(o2.getValue())) );
  328. return entries.get(0);
  329. }
  330. return null;
  331. }
  332. /**
  333. * 把 Group 转成 Map 用于 jfianl框架的 添加使用
  334. * @param group
  335. * @return {@link {@link Map< String, Object>}}
  336. * @author Darren
  337. * @date 2020/2/4 20:30
  338. */
  339. private Map<String, Object> groupToMap(Group group){
  340. Map<String, Object> attrs = new HashMap<>();
  341. attrs.put("group_id", group.getGroup_id());
  342. attrs.put("name", group.getName());
  343. attrs.put("avatar", group.getAvatar());
  344. attrs.put("service_account_role_department_middle_id", group.getServiceAccountRoleDepartmentId());
  345. attrs.put("consumer_id", group.getConsumerId());
  346. attrs.put("group_type", group.getGroupType());
  347. attrs.put("company_id", group.getCompanyId());
  348. attrs.put("department_id", group.getDepartmentId());
  349. return attrs;
  350. }
  351. /**
  352. * 创建群组
  353. * @param user
  354. * @return {@link {@link Group}}
  355. * @author Darren
  356. * @date 2020/2/4 20:28
  357. */
  358. private Group createGroup(User user){
  359. //创建新的群组
  360. Group group = new Group();
  361. group.setGroup_id(String.valueOf(SnowflakeIdUtils.getInstance().nextId()));
  362. //群组名称 采用客户名称
  363. group.setName(user.getNick());
  364. group.setAvatar(user.getAvatar());
  365. group.setServiceAccountRoleDepartmentId(user.getExtras().getString("serviceAccountRoleDepartmentId"));
  366. group.setConsumerId(user.getId());
  367. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  368. if(VisitTypeEnum.CUSTOMER.getKey().equals(user.getVisitType())){
  369. group.setGroupType(GroupTypeEnum.CUSTOMER.getKey());
  370. }
  371. if(VisitTypeEnum.VISITOR.getKey().equals(user.getVisitType())){
  372. group.setGroupType(GroupTypeEnum.VISITOR.getKey());
  373. }
  374. group.setCompanyId(user.getExtras().getString("companyId"));
  375. group.setDepartmentId(user.getExtras().getString("departmentId"));
  376. //创建会话
  377. this.createConversation(group,user);
  378. return group;
  379. }
  380. /** ============================================= <客户> 处理 end================================================== */
  381. /** ============================================= 客服处理 start================================================== */
  382. /**
  383. * 创建 客服 user 数据
  384. * @param map
  385. * @return {@link {@link User}}
  386. * @author Darren
  387. * @date 2020/2/3 19:59
  388. */
  389. private User createServiceAccountUser(Map<String, String> map){
  390. User user = new User();
  391. //当前访问人为客服
  392. user.setId(map.get("serviceAccountRoleDepartmentId"));
  393. //用户头像
  394. String headImg = map.get("headImg");
  395. user.setAvatar(headImg);
  396. //user nick
  397. String nickname = map.get("nickname");
  398. user.setNick(nickname);
  399. //扩展预留字段;
  400. Map<String, Object> serviceAccountMap = new HashMap<>();
  401. serviceAccountMap.put("companyId", map.get("companyId"));
  402. serviceAccountMap.put("isDefault", map.get("isDefault"));
  403. serviceAccountMap.put("departmentId", map.get("departmentId"));
  404. serviceAccountMap.put("hasViewAllServiceAccount", map.get("hasViewAllServiceAccount"));
  405. serviceAccountMap.put("serviceAccountId", map.get("id"));
  406. user.setExtras(new JSONObject(serviceAccountMap));
  407. //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
  408. user.setVisitType(VisitTypeEnum.SERVICEACCOUNT.getKey());
  409. user.setGroups(this.initServiceAccountGroups(user));
  410. user.setViewAllGroups(this.initViewAllServiceAccountGroup(user));
  411. return user;
  412. }
  413. /**
  414. * 初始化 查看全部客服权限 才能看的群组数据
  415. * @param user
  416. * @return {@link {@link List< Group>}}
  417. * @author Darren
  418. * @date 2020/2/3 20:29
  419. */
  420. private List<Group> initViewAllServiceAccountGroup(User user) {
  421. List<Group> groups = null;
  422. //1.判断当前客服是否具有查看当前部门下 全部客服通话的权限
  423. String hasViewAllServiceAccount = user.getExtras().getString("hasViewAllServiceAccount");
  424. if( Boolean.valueOf(hasViewAllServiceAccount) ){
  425. boolean flag = false;
  426. //获取 具有查看全部客服通话权限 的客服容器 并且 加入到该容器中 key数据格式: companyId : departmentId : ADMIN
  427. String adminContainerKey = user.getExtras().getString("companyId")
  428. + ImConst.SEPARATOR + user.getExtras().getString("departmentId")
  429. + ImConst.SEPARATOR + ImConst.ADMIN ;
  430. List<String> adminContainer = jedisTemplate.listGetAll(adminContainerKey);
  431. if( CollectionUtils.isEmpty(adminContainer) ){
  432. //adminContainer 不存在
  433. jedisTemplate.listPushTail(adminContainerKey,user.getId());
  434. flag = true;
  435. }else{
  436. if( !adminContainer.contains(user.getId()) ) {
  437. //如果容器中 不 包含这个 id 则添加
  438. jedisTemplate.listPushTail(adminContainerKey,user.getId());
  439. flag = true;
  440. }
  441. }
  442. //... 然后把当前 客服 加入到 该平台下 部门下 所有群组中
  443. if(flag){
  444. //1.从redis中获取数据
  445. //获取平台该部门下 所有 群组 key数据格式: companyId : departmentId : GROUP
  446. /*String groupContainerKey = user.getExtras().getString("companyId")
  447. + SEPARATOR + user.getExtras().getString("departmentId") + SEPARATOR + GROUP ;
  448. Map<String, String> serviceAccountGroupContainer = jedisTemplate.hashGetAll(groupContainerKey);
  449. if( !CollectionUtils.isEmpty(serviceAccountGroupContainer) ){
  450. //如果 客服群组容器中 有值 绑定群组
  451. groups = serviceAccountGroupContainer
  452. .values()
  453. .stream()
  454. .map(x -> JsonKit.toBean(x, Group.class))
  455. //过滤掉 属于该客服的群组
  456. .filter(x -> !x.getServiceAccountRoleDepartmentId().equals(user.getId()))
  457. .collect(Collectors.toList());
  458. }else{
  459. }*/
  460. //2.从数据库中获取数据
  461. StringBuilder sql = new StringBuilder();
  462. sql
  463. .append(" select ")
  464. .append(GROUP_PROPERTY)
  465. .append(" from sw_group where 1 = 1 ")
  466. .append(" and company_id = "+ user.getExtras().getString("companyId") + " ")
  467. .append(" and department_id = " + user.getExtras().getString("departmentId") + " ");
  468. List<ChatGroup> chatGroups = ChatGroup.dao.find(sql.toString());
  469. if( !CollectionUtils.isEmpty(chatGroups) ){
  470. chatGroups = chatGroups.stream()
  471. .filter(
  472. x -> !x.get("service_account_role_department_middle_id").equals(user.getId())
  473. )
  474. .collect(Collectors.toList());
  475. groups = this.disposeChatGroupsToGroups(chatGroups);
  476. }
  477. }
  478. }
  479. return groups;
  480. }
  481. /***
  482. * 初始化 客服对应的 群组数据
  483. * @param user
  484. * @return {@link {@link List< Group>}}
  485. * @author Darren
  486. * @date 2020/2/3 19:55
  487. */
  488. private List<Group> initServiceAccountGroups(User user) {
  489. //1.从redis中获取数据
  490. // 查看当前是否有相关该客服的群组 key数据格式: companyId : departmentId : userId : GROUP
  491. /* String serviceAccountGroupContainerKey = user.getExtras().getString("companyId")
  492. + SEPARATOR + user.getExtras().getString("departmentId") + SEPARATOR + user.getId() + GROUP ;
  493. // value 数据结构 (field 域 : value) : consumerId 游客或者客户的 userID : {group 群组对象json串 }
  494. Map<String, String> serviceAccountGroupContainer = jedisTemplate.hashGetAll(serviceAccountGroupContainerKey);
  495. if( !CollectionUtils.isEmpty(serviceAccountGroupContainer) ){
  496. //如果 客服群组容器中 有值 绑定群组
  497. groups = serviceAccountGroupContainer
  498. .values()
  499. .stream()
  500. .map(x -> JsonKit.toBean(x, Group.class))
  501. .collect(Collectors.toList());
  502. }else{
  503. }*/
  504. //2.从数据库中获取数据
  505. StringBuilder sql = new StringBuilder();
  506. sql
  507. .append(" select ")
  508. .append(GROUP_PROPERTY)
  509. // service_account_type = 1 判断 当前的 是否是离线状态下的
  510. //有可能 客服 下线 客户没下线 所以 这个地方的过滤 不用 过滤 service_account_type = 1
  511. //群组 的删除 是依 客户/游客的下线 为准(并且 是在线群组 才会删除,离线群组不会删除)
  512. .append(" from sw_group where 1 = 1 and group_type = 1 ")
  513. .append(" and company_id = "+ user.getExtras().getString("companyId") + " ")
  514. .append(" and department_id = " + user.getExtras().getString("departmentId") + " ")
  515. .append(
  516. " and service_account_role_department_middle_id = " + user.getId()
  517. );
  518. List<ChatGroup> chatGroups = ChatGroup.dao.find(sql.toString());
  519. List<Group> groups = this.disposeChatGroupsToGroups(chatGroups);
  520. //修改 sw_group 字段service_account_type 状态
  521. if( !CollectionUtils.isEmpty(chatGroups) ){
  522. for (ChatGroup chatGroup : chatGroups) {
  523. ChatGroup.dao.findById(chatGroup.getStr("group_id"))
  524. .set("service_account_type", ServiceAccountOfflineTypeEnum.NO.getKey())
  525. .update();
  526. }
  527. }
  528. return groups;
  529. }
  530. /***
  531. * 处理 访问类型 为客服 的数据
  532. * @param
  533. * @return {@link }
  534. * @author Darren
  535. * @date 2020/2/3 14:01
  536. */
  537. private void disposeServiceAccountData(User user){
  538. //1.向客服容器中 添加客服 客服容器中过滤掉超级管理员
  539. // key组成 : companyId : departmentId : SERVICEACCOUNT
  540. // value组成 : Map<String ( serviceAccountRoleDepartmentId ), String (当前连接客户人数)>
  541. String serviceAccountContainerKey
  542. = user.getExtras().getString("companyId") + ImConst.SEPARATOR
  543. + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
  544. + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
  545. //判断该客服是否是超级管理员
  546. String isDefault = user.getExtras().getString("isDefault");
  547. if(DefaultStateEnum.NO.getKey().equals(isDefault)){
  548. List<Group> groups = user.getGroups();
  549. int num = 0;
  550. if(!CollectionUtils.isEmpty(groups)){
  551. num = groups.size();
  552. }
  553. Map<String, String> serviceAccountContainer = jedisTemplate.hashGetAll(serviceAccountContainerKey);
  554. //判断 客服容器 是否存在
  555. if( CollectionUtils.isEmpty(serviceAccountContainer) ){
  556. //当前平台下 部门下 客服容器为null
  557. serviceAccountContainer = new HashMap<>();
  558. serviceAccountContainer.put(user.getId(),String.valueOf(num));
  559. jedisTemplate.hashMultipleSet(serviceAccountContainerKey,serviceAccountContainer);
  560. }else{
  561. //客服容器 存在
  562. //判断容器中是否存在这个客服
  563. if(serviceAccountContainer.containsKey(user.getId())){
  564. //获取 当前客服 服务的 客户/游客 数量
  565. Integer userNum = Integer.valueOf(serviceAccountContainer.get(user.getId())) + num;
  566. jedisTemplate.hashSet(serviceAccountContainerKey,user.getId(),String.valueOf( userNum ));
  567. }else{
  568. //不存在这个客服数据
  569. jedisTemplate.hashSet(serviceAccountContainerKey,user.getId(),String.valueOf(num));
  570. }
  571. }
  572. }
  573. }
  574. /** ============================================= 客服处理 end =================================================== */
  575. /**
  576. * 转换数据 List<ChatGroup> >> List<Group>
  577. * @param chatGroups
  578. * @return {@link {@link List< Group>}}
  579. * @author Darren
  580. * @date 2020/2/4 14:27
  581. */
  582. private List<Group> disposeChatGroupsToGroups(List<ChatGroup> chatGroups){
  583. if( !CollectionUtils.isEmpty(chatGroups) ){
  584. List<Group> groups = new ArrayList<>();
  585. for (ChatGroup chatGroup : chatGroups) {
  586. Group group = this.disposeChatGroupToGroup(chatGroup);
  587. groups.add(group);
  588. }
  589. return groups;
  590. }
  591. return null;
  592. }
  593. /**
  594. * 转换数据 ChatGroup >> Group
  595. * @param chatGroup
  596. * @author Darren
  597. * @date 2020/2/4 14:27
  598. */
  599. private Group disposeChatGroupToGroup(ChatGroup chatGroup){
  600. if( null != chatGroup ){
  601. Group group = new Group();
  602. group.setGroup_id(chatGroup.getStr("group_id"));
  603. group.setName(chatGroup.getStr("name"));
  604. group.setAvatar(chatGroup.getStr("avatar"));
  605. group.setServiceAccountRoleDepartmentId(chatGroup.getStr("service_account_role_department_middle_id"));
  606. group.setConsumerId(chatGroup.getStr("consumer_id"));
  607. group.setGroupType(chatGroup.getInt("group_type"));
  608. group.setCompanyId(chatGroup.getStr("company_id"));
  609. group.setDepartmentId(chatGroup.getStr("department_id"));
  610. return group;
  611. }
  612. return null;
  613. }
  614. @Override
  615. public void onSuccess(ChannelContext channelContext) {
  616. logger.info("登录成功回调方法...");
  617. }
  618. @Override
  619. public boolean isProtocol(ChannelContext channelContext) {
  620. return true;
  621. }
  622. /**
  623. * 处理器的名称
  624. * @return
  625. */
  626. @Override
  627. public String name() {
  628. return ImConst.IM_CHAT_LOGIN_SERVICE_PROCESSOR;
  629. }
  630. }