ChatService.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. namespace bizHd\message\services;
  3. use bizHd\base\services\BaseService;
  4. use bizHd\custom\classes\CustomClass;
  5. use bizHd\message\classes\ChatClass;
  6. use bizHd\user\services\UserService;
  7. use common\components\arrayUtil;
  8. use common\components\imgUtil;
  9. use Yii;
  10. class ChatService extends BaseService
  11. {
  12. //新增未读消息数
  13. public static function addUnreadNum($userId)
  14. {
  15. $key = ChatClass::getUnreadNumKey($userId);
  16. Yii::$app->redis->executeCommand('INCRBY', [$key, 1]);
  17. }
  18. //新增未回复客户 ssh 2019.12.29
  19. public static function addUnReplyUser($sjId, $userId)
  20. {
  21. $now = time();
  22. $cacheKey = ChatClass::getUnReplyUserKey($sjId);
  23. Yii::$app->redis->executeCommand('ZADD', [$cacheKey, $now, "{$userId}"]);
  24. }
  25. //取未回复客户列表 ssh 2019.12.29
  26. public static function getUnReplyUserList($sjId)
  27. {
  28. $cacheKey = ChatClass::getUnReplyUserKey($sjId);
  29. $return = Yii::$app->redis->executeCommand('ZREVRANGE', [$cacheKey, 0, -1, 'WITHSCORES']);//返回有序集合,从高分到低分排序
  30. if (empty($return)) {
  31. return [];
  32. }
  33. $list = [];
  34. $i = 0;
  35. $arr = [];
  36. foreach ($return as $key => $val) {
  37. if ($key % 2 == 0) {
  38. $arr[$i]['value'] = $val;
  39. } else {
  40. $arr[$i]['key'] = $val;
  41. $i++;
  42. }
  43. }
  44. foreach ($arr as $key => $val) {
  45. $list[$val['key']] = $val['value'];
  46. }
  47. return $list;
  48. }
  49. //新增最近联系人
  50. public static function addRecentlyUser($sjId, $userId)
  51. {
  52. $now = time();
  53. $cacheKey = ChatClass::getRecentlyUserKey($sjId);
  54. //删除10天前的联系人
  55. $max = $now - 86400 * 10;
  56. Yii::$app->redis->executeCommand('ZREMRANGEBYSCORE', [$cacheKey, 0, $max]);
  57. Yii::$app->redis->executeCommand('ZADD', [$cacheKey, $now, "{$userId}"]);
  58. }
  59. //取最近联系人 ssh 2019.12.29
  60. public static function getRecentlyUserList($mainId)
  61. {
  62. $userIdList = [12536630, 12536631, 12536632, 12536633, 12536634, 12536635];
  63. $userId = $userIdList[array_rand($userIdList)];
  64. self::addRecentlyUser($mainId, $userId);
  65. $cacheKey = ChatClass::getRecentlyUserKey($mainId);
  66. //返回有序集合,从高分到低分排序
  67. $return = Yii::$app->redis->executeCommand('ZREVRANGE', [$cacheKey, 0, -1, 'WITHSCORES']);
  68. if (empty($return)) {
  69. return [];
  70. }
  71. $i = 0;
  72. $arr = [];
  73. foreach ($return as $key => $val) {
  74. if ($key % 2 == 0) {
  75. $arr[$i]['userId'] = $val;
  76. } else {
  77. $arr[$i]['time'] = $val;
  78. $i++;
  79. }
  80. }
  81. $userData = [];
  82. //组合出最后聊天时间和未读消息数
  83. foreach ($arr as $val) {
  84. $userId = $val['userId'];
  85. $time = $val['time'];
  86. $num = ChatClass::getUnreadNum($userId);
  87. $date = date("m-d H:i", $time);
  88. if (date("Ymd") == date("Ymd", $time)) {
  89. $date = date("H:i", $time);
  90. }
  91. $userData[$userId] = ['time' => $date, 'unReadNum' => $num];
  92. }
  93. $ids = array_column($arr, 'userId');
  94. $infoList = UserService::getUserByIds($ids);
  95. foreach ($infoList as $userId => $info) {
  96. $infoList[$userId]['unReadNum'] = isset($userData[$userId]['unReadNum']) ? $userData[$userId]['unReadNum'] : 0;
  97. $infoList[$userId]['chatTime'] = isset($userData[$userId]['time']) ? $userData[$userId]['time'] : date("m-d H:i", $info['visitTime']);
  98. }
  99. return array_values($infoList);
  100. }
  101. //保存消息记录 ssh 2019.12.29
  102. public static function saveMessage($messageList, $userId)
  103. {
  104. //商家的消息,ourSelf表示自己的消息 themSelf表示对方的消息
  105. $now = time();
  106. $cacheKey = ChatClass::getMessageKey($userId);
  107. //删除15天前的已读消息
  108. $max = $now - 86400 * 16;
  109. Yii::$app->redis->executeCommand('ZREMRANGEBYSCORE', [$cacheKey, 0, $max]);
  110. foreach ($messageList as $message) {
  111. Yii::$app->redis->executeCommand('ZADD', [$cacheKey, $now, json_encode($message)]);
  112. }
  113. //self::getMessageList($userId);
  114. }
  115. //取消息记录 ssh 2019.12.29
  116. public static function getMessageList($userId)
  117. {
  118. $cacheKey = ChatClass::getMessageKey($userId);
  119. //返回有序集合,从高分到低分排序
  120. $return = Yii::$app->redis->executeCommand('ZREVRANGE', [$cacheKey, 0, -1, 'WITHSCORES']);
  121. if (empty($return)) {
  122. return [];
  123. }
  124. $i = 0;
  125. $arr = [];
  126. foreach ($return as $key => $val) {
  127. if ($key % 2 == 0) {
  128. $arr[$i]['message'] = $val;
  129. } else {
  130. $arr[$i]['time'] = $val;
  131. $i++;
  132. }
  133. }
  134. $arr = arrayUtil::arraySort($arr, 'time');
  135. $data = [];
  136. foreach ($arr as $val) {
  137. $message = $val['message'];
  138. $data[] = json_decode($message);
  139. }
  140. return $data;
  141. }
  142. // ------------------------------------------------ 以下是新增的聊天方法 ------------------------------------------------
  143. //最近聊天人(人:可能是客户,也可能是商家)
  144. public static function getLatestUsers($shopId)
  145. {
  146. $cacheKey = ChatClass::getLatestUsersKey($shopId);
  147. //返回有序集合,从高分到低分排序
  148. $return = Yii::$app->redis->executeCommand('ZREVRANGE', [$cacheKey, 0, -1, 'WITHSCORES']);
  149. if (empty($return)) {
  150. return [];
  151. }
  152. $i = 0;
  153. $arr = [];
  154. foreach ($return as $key => $val) {
  155. if ($key % 2 == 0) {
  156. $arr[$i]['cId'] = $val;
  157. } else {
  158. $arr[$i]['score'] = $val;
  159. $i++;
  160. }
  161. }
  162. $userData = [];
  163. //组合出最后聊天时间和未读消息数
  164. foreach ($arr as $val) {
  165. $customId = $val['cId'];
  166. $score = floatval($val['score']);
  167. $decimalPart = $score - floor($score);
  168. $unReadNum = intval($decimalPart * 10000 + 0.5);// 加0.5 -- 使用四舍五入来处理浮点数精度问题
  169. $time = intval($val['score']);
  170. $date = date("Y-m-d H:i", $time);
  171. $userData[$customId] = ['time' => $date, 'unReadNum' => $unReadNum];
  172. }
  173. $ids = array_column($arr, 'cId');
  174. $infoList = CustomClass::getByIds($ids, null, null, 'id,name,mobile,avatar,shopId,userId');
  175. foreach ($infoList as $customId => $info) {
  176. $infoList[$customId]['unReadNum'] = $userData[$info['id']]['unReadNum'] ?? 0;
  177. $infoList[$customId]['chatTime'] = $userData[$info['id']]['time'] ?? 0;
  178. //头像
  179. $shortAvatar = $info['avatar'] ?? '';
  180. $smallAvatar = imgUtil::groupImg($shortAvatar) . "?x-oss-process=image/resize,m_fill,h_130,w_130";
  181. $infoList[$customId]['shortAvatar'] = $shortAvatar;
  182. $infoList[$customId]['smallAvatar'] = $smallAvatar;
  183. }
  184. $infoList = arrayUtil::arraySort($infoList, 'chatTime', SORT_DESC);
  185. return array_values($infoList);
  186. }
  187. public static function getChatHistory($roomName)
  188. {
  189. if (empty($roomName)) {
  190. return [];
  191. }
  192. try {
  193. $re = Yii::$app->redis;
  194. $list = Yii::$app->redis->executeCommand('LRANGE', [$roomName, 0, -1]);
  195. if (empty($list)) {
  196. return [];
  197. }
  198. $result = [];
  199. foreach ($list as $item) {
  200. $decoded = json_decode($item, true);
  201. $struct = (json_last_error() === JSON_ERROR_NONE) ? $decoded : $item;
  202. $content = $struct['content'];
  203. $message = json_decode($content, true);
  204. $result[] = json_decode($message['message'], true);
  205. }
  206. return $result;
  207. } catch (\Throwable $e) {
  208. Yii::error('getChatHistory redis error: ' . $e->getMessage(), __METHOD__);
  209. return [];
  210. }
  211. }
  212. /**
  213. * @param int $shopId 门店id
  214. * @param string $unit 单位分:个数(person)消息(message)
  215. * @return int
  216. */
  217. public static function getUnReadMsgCount($shopId, $unit = 'person')
  218. {
  219. $cacheKey = ChatClass::getLatestUsersKey($shopId);
  220. //返回有序集合,从高分到低分排序
  221. $return = Yii::$app->redis->executeCommand('ZREVRANGE', [$cacheKey, 0, -1, 'WITHSCORES']);
  222. if (empty($return)) {
  223. return 0;
  224. }
  225. $i = 0;
  226. $arr = [];
  227. foreach ($return as $key => $val) {
  228. if ($key % 2 == 0) {
  229. $arr[$i]['cId'] = $val;//customerId
  230. } else {
  231. $arr[$i]['score'] = $val;
  232. $i++;
  233. }
  234. }
  235. $msgCount = 0;
  236. foreach ($arr as $val) {
  237. //$customId = $val['cId'];
  238. $score = floatval($val['score']);
  239. $decimalPart = $score - floor($score);
  240. $unReadNum = intval($decimalPart * 10000 + 0.5); // 加0.5 -- 使用四舍五入来处理浮点数精度问题
  241. //根据未读消息数的单位进行计算总数
  242. if ($unit == 'person') {
  243. $msgCount += ($unReadNum >= 1 ? 1 : 0);
  244. } else if ($unit == 'message') {
  245. $msgCount += $unReadNum;
  246. }
  247. }
  248. return $msgCount;
  249. }
  250. }