ChatService.php 9.0 KB

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