ChatService.php 9.5 KB

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