ChatMessageService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 LARAVEL研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: laravel开发员 <laravel.qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Services;
  12. use App\Models\ChatMessageModel;
  13. use App\Models\ConfigModel;
  14. /**
  15. * 聊天-服务类
  16. * Class ChatMessageService
  17. * @package App\Services
  18. */
  19. class ChatMessageService extends BaseService
  20. {
  21. // 静态对象
  22. protected static $instance = null;
  23. /**
  24. * 构造函数
  25. * ChatMessageService constructor.
  26. */
  27. public function __construct()
  28. {
  29. $this->model = new ChatMessageModel();
  30. }
  31. /**
  32. * 静态入口
  33. * @return static|null
  34. */
  35. public static function make(){
  36. if(!self::$instance){
  37. self::$instance = (new static());
  38. }
  39. return self::$instance;
  40. }
  41. /**
  42. * 绑定用户
  43. * @param $fd
  44. * @param $data
  45. * @return bool
  46. */
  47. public function bind($fd, $data)
  48. {
  49. $userId = isset($data['from_uid'])? intval($data['from_uid']) : 0;
  50. if($userId<=0){
  51. $this->error = '1013';
  52. return false;
  53. }
  54. RedisService::set("chats:bind:{$userId}", ['fd'=> $fd, 'user_id'=> $userId], 86400);
  55. return true;
  56. }
  57. /**
  58. * 获取列表
  59. * @param $params
  60. * @param int $pageSize
  61. * @return array
  62. */
  63. public function getDataList($params, $pageSize = 15)
  64. {
  65. $where = ['a.mark' => 1,'a.status'=>1];
  66. $type = isset($params['type'])? $params['type'] : 1;
  67. $chatKey = isset($params['chat_key'])? $params['chat_key'] : '';
  68. $fromUid = isset($params['from_uid'])? $params['from_uid'] : 0;
  69. $toUid = isset($params['to_uid'])? $params['to_uid'] : 0;
  70. $orderNo = isset($params['order_no'])? $params['order_no'] : '';
  71. if($type>0){
  72. $where['a.type'] = $type;
  73. }
  74. if($chatKey){
  75. $where['a.chat_key'] = $chatKey;
  76. }
  77. if($fromUid>0){
  78. $where['a.from_uid'] = $fromUid;
  79. }
  80. if($toUid>0){
  81. $where['a.to_uid'] = $toUid;
  82. }
  83. if($orderNo){
  84. $where['a.order_no'] = $orderNo;
  85. }
  86. $list = $this->model->from('chat_message as a')
  87. ->leftJoin('member as m', 'm.id', '=', 'a.from_uid')
  88. ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid')
  89. ->where($where)
  90. ->where(function ($query) use($params){
  91. $id = isset($params['id'])? $params['id'] : 0;
  92. if($id>0){
  93. $query->where('a.id','<', $id);
  94. }
  95. })
  96. ->where(function ($query) use($params){
  97. $userId = isset($params['user_id'])? $params['user_id'] : 0;
  98. if($userId){
  99. $query->where('a.from_uid','=',$userId)->orWhere('a.to_uid','=', $userId);
  100. }
  101. })
  102. ->select(['a.*', 'm.username as from_username','m.avatar as from_avatar','m1.username as to_username','m1.avatar as to_avatar'])
  103. ->orderBy('a.create_time','desc')
  104. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  105. $list = $list? $list->toArray() :[];
  106. if($list){
  107. foreach($list['data'] as &$item){
  108. $item['from_username_text'] = $item['from_username']? format_account($item['from_username']):'客服';
  109. $item['to_username_text'] = $item['to_username']? format_account($item['to_username']):'客服';
  110. $item['message_url'] = $item['message_type']==2? get_image_url($item['message']):'';
  111. $item['from_avatar'] = $item['from_avatar']? get_image_url($item['from_avatar']):'';
  112. $item['to_avatar'] = $item['to_avatar']? get_image_url($item['to_avatar']):'';
  113. $item['time_text'] = $item['create_time']? format_time(strtotime($item['create_time'])):'刚刚';
  114. $userId = isset($params['user_id'])? $params['user_id'] : 0;
  115. if($userId == $item['to_uid']){
  116. // 已读
  117. $this->model->where(['id'=> $item['id']])->update(['is_read'=>1,'update_time'=> time()]);
  118. }
  119. }
  120. }
  121. return [
  122. 'pageSize'=> $pageSize,
  123. 'total'=>isset($list['total'])? $list['total'] : 0,
  124. 'list'=> isset($list['data'])? $list['data'] : []
  125. ];
  126. }
  127. /**
  128. * 消息列表
  129. * @param $params
  130. * @param int $pageSize
  131. * @return array
  132. */
  133. public function getNewList($params, $pageSize = 15)
  134. {
  135. $where = ['a.mark' => 1,'a.status'=>1];
  136. $type = isset($params['type'])? $params['type'] : 1;
  137. $chatKey = isset($params['chat_key'])? $params['chat_key'] : '';
  138. $fromUid = isset($params['from_uid'])? $params['from_uid'] : 0;
  139. $toUid = isset($params['to_uid'])? $params['to_uid'] : 0;
  140. $orderNo = isset($params['order_no'])? $params['order_no'] : '';
  141. if($type>0){
  142. $where['a.type'] = $type;
  143. }
  144. if($chatKey){
  145. $where['a.chat_key'] = $chatKey;
  146. }
  147. if($fromUid>0){
  148. $where['a.from_uid'] = $fromUid;
  149. }
  150. if($toUid>0){
  151. $where['a.to_uid'] = $toUid;
  152. }
  153. if($orderNo){
  154. $where['a.order_no'] = $orderNo;
  155. }
  156. $list = $this->model->from('chat_message as a')
  157. ->leftJoin('member as m', 'm.id', '=', 'a.from_uid')
  158. ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid')
  159. ->where($where)
  160. ->where(function ($query) use($params){
  161. $userId = isset($params['user_id'])? $params['user_id'] : 0;
  162. if($userId){
  163. $query->where('a.from_uid','=',$userId)->orWhere('a.to_uid','=', $userId);
  164. }
  165. })
  166. ->select(['a.id', 'a.from_uid','a.to_uid','a.type','a.message_type','a.data_type','a.message','a.chat_key','a.order_no','a.create_time', 'm.username as from_username','m.avatar as from_avatar','m1.username as to_username','m1.avatar as to_avatar'])
  167. ->groupBy('a.chat_key')
  168. ->orderBy('a.create_time','desc')
  169. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  170. $list = $list? $list->toArray() :[];
  171. if($list){
  172. foreach($list['data'] as &$item){
  173. $item['from_username_text'] = $item['from_username']? format_account($item['from_username']):'客服';
  174. $item['to_username_text'] = $item['to_username']? format_account($item['to_username']):'客服';
  175. $item['from_avatar'] = $item['from_avatar']? get_image_url($item['from_avatar']):'';
  176. $item['to_avatar'] = $item['to_avatar']? get_image_url($item['to_avatar']):'';
  177. $item['time_text'] = $item['create_time']? format_time(strtotime($item['create_time'])):'刚刚';
  178. $item['info'] = $this->getTempInfo($item['chat_key']);
  179. }
  180. }
  181. return [
  182. 'pageSize'=> $pageSize,
  183. 'total'=>isset($list['total'])? $list['total'] : 0,
  184. 'list'=> isset($list['data'])? $list['data'] : []
  185. ];
  186. }
  187. /**
  188. * 消息列表
  189. * @param $params
  190. * @param int $pageSize
  191. * @return array
  192. */
  193. public function getWaitList($params, $pageSize = 15)
  194. {
  195. $where = ['a.mark' => 1,'a.status'=>1];
  196. $type = isset($params['type'])? $params['type'] : 1;
  197. $chatKey = isset($params['chat_key'])? $params['chat_key'] : '';
  198. $fromUid = isset($params['from_uid'])? $params['from_uid'] : 0;
  199. $toUid = isset($params['to_uid'])? $params['to_uid'] : 0;
  200. $orderNo = isset($params['order_no'])? $params['order_no'] : '';
  201. if($type>0){
  202. $where['a.type'] = $type;
  203. }
  204. if($chatKey){
  205. $where['a.chat_key'] = $chatKey;
  206. }
  207. if($fromUid>0){
  208. $where['a.from_uid'] = $fromUid;
  209. }
  210. if($toUid>0){
  211. $where['a.to_uid'] = $toUid;
  212. }
  213. if($orderNo){
  214. $where['a.order_no'] = $orderNo;
  215. }
  216. $list = $this->model->from('chat_message as a')
  217. ->leftJoin('member as m', 'm.id', '=', 'a.from_uid')
  218. ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid')
  219. ->where($where)
  220. ->where(function ($query) use($params){
  221. $userId = isset($params['user_id'])? $params['user_id'] : 0;
  222. if($userId){
  223. $query->where('a.to_uid','=', $userId);
  224. }
  225. })
  226. ->select(['a.id', 'a.from_uid','a.to_uid','a.type','a.message_type','a.data_type','a.message','a.chat_key','a.order_no','a.create_time', 'm.username as from_username','m.avatar as from_avatar','m1.username as to_username','m1.avatar as to_avatar'])
  227. ->orderBy('a.create_time','desc')
  228. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  229. $list = $list? $list->toArray() :[];
  230. if($list){
  231. foreach($list['data'] as &$item){
  232. $item['from_username_text'] = $item['from_username']? format_account($item['from_username']):'客服';
  233. $item['to_username_text'] = $item['to_username']? format_account($item['to_username']):'客服';
  234. $item['from_avatar'] = $item['from_avatar']? get_image_url($item['from_avatar']):'';
  235. $item['to_avatar'] = $item['to_avatar']? get_image_url($item['to_avatar']):'';
  236. $item['time_text'] = $item['create_time']? format_time(strtotime($item['create_time'])):'刚刚';
  237. $item['info'] = $this->getTempInfo($item['chat_key']);
  238. }
  239. }
  240. return [
  241. 'pageSize'=> $pageSize,
  242. 'total'=>isset($list['total'])? $list['total'] : 0,
  243. 'list'=> isset($list['data'])? $list['data'] : []
  244. ];
  245. }
  246. /**
  247. * 消息数量
  248. * @param $userId
  249. * @return int[]
  250. */
  251. public function getNewCount($userId)
  252. {
  253. $counts = ['notice'=>0,'message'=>0];
  254. $counts['notice'] = (int) $this->model->where(['status'=>1,'mark'=>1,'type'=>3])
  255. ->where(function($query) use($userId){
  256. $query->where(['from_uid'=> $userId])->orWhere(['to_uid'=> $userId]);
  257. })->count('id');
  258. $counts['message'] = (int) $this->model->where(['status'=>1,'mark'=>1,'type'=>1])
  259. ->where(function($query) use($userId){
  260. $query->where(['to_uid'=> $userId]);
  261. })->groupBy('chat_key')->count('id');
  262. return $counts;
  263. }
  264. /**
  265. * 获取最新的聊天消息
  266. * @param $chatKey 聊天窗口标识
  267. * @return array|mixed
  268. */
  269. public function getTempInfo($chatKey)
  270. {
  271. $cacheKey = "caches:chats:temp:{$chatKey}";
  272. $info = RedisService::get($cacheKey);
  273. if($info){
  274. return $info;
  275. }
  276. $info = $this->model->where(['chat_key'=> $chatKey,'status'=>1,'mark'=>1])
  277. ->select(['id','message','is_read','message_type','create_time'])
  278. ->orderBy('create_time','desc')
  279. ->orderBy('id','desc')
  280. ->first();
  281. if($info){
  282. $info['message_url'] = $info['message_type']==2? get_image_url($info['message']):'';
  283. $info['time_text'] = $info['create_time']? format_time(strtotime($info['create_time'])):'刚刚';
  284. RedisService::set($cacheKey, $info, rand(3,5));
  285. }
  286. return $info;
  287. }
  288. /**
  289. * 添加或编辑
  290. * @return array
  291. */
  292. public function saveData($data)
  293. {
  294. $data = [
  295. 'type'=> isset($data['type'])? $data['type'] : 1,
  296. 'message_type'=> isset($data['message_type'])? $data['message_type'] : 1,
  297. 'from_uid'=> isset($data['from_uid'])? $data['from_uid'] : 1,
  298. 'to_uid'=> isset($data['to_uid'])? $data['to_uid'] : 1,
  299. 'order_no'=> isset($data['order_no'])? $data['order_no'] : '',
  300. 'chat_key'=> getChatKey($data['from_uid'],$data['to_uid']),
  301. 'message'=> isset($data['message'])? $data['message'] : '',
  302. 'create_time'=> time(),
  303. 'update_time'=> time(),
  304. 'is_read'=> 2,
  305. 'status'=> 1,
  306. 'mark'=> 1,
  307. ];
  308. return $this->model->insertGetId($data);
  309. }
  310. /**
  311. * 推送保存消息,如订单消息
  312. * @param $data 消息数据
  313. * @return int|number
  314. */
  315. public function pushMessage($data)
  316. {
  317. return $this->model->edit($data);
  318. }
  319. }