// +---------------------------------------------------------------------- namespace App\Services; use App\Models\ChatMessageModel; use App\Models\ConfigModel; /** * 聊天-服务类 * Class ChatMessageService * @package App\Services */ class ChatMessageService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * ChatMessageService constructor. */ public function __construct() { $this->model = new ChatMessageModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 绑定用户 * @param $fd * @param $data * @return bool */ public function bind($fd, $data) { $userId = isset($data['from_uid']) ? intval($data['from_uid']) : 0; if ($userId <= 0) { $this->error = '1013'; return false; } RedisService::set("chats:bind:{$userId}", ['fd' => $fd, 'user_id' => $userId], 86400); return true; } /** * 获取列表 * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 15) { $where = ['a.mark' => 1, 'a.status' => 1]; $type = isset($params['type']) ? $params['type'] : 1; $chatKey = isset($params['chat_key']) ? $params['chat_key'] : ''; $fromUid = isset($params['from_uid']) ? $params['from_uid'] : 0; $toUid = isset($params['to_uid']) ? $params['to_uid'] : 0; $orderNo = isset($params['order_no']) ? $params['order_no'] : ''; if ($type > 0) { $where['a.type'] = $type; } if ($chatKey) { $where['a.chat_key'] = $chatKey; } if ($fromUid > 0) { $where['a.from_uid'] = $fromUid; } if ($toUid > 0) { $where['a.to_uid'] = $toUid; } if ($orderNo) { $where['a.order_no'] = $orderNo; } $list = $this->model->from('chat_message as a') ->leftJoin('member as m', 'm.id', '=', 'a.from_uid') ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid') ->where($where) ->where(function ($query) use ($params) { $id = isset($params['id']) ? $params['id'] : 0; if ($id > 0) { $query->where('a.id', '<', $id); } }) ->where(function ($query) use ($params) { $userId = isset($params['user_id']) ? $params['user_id'] : 0; if ($userId) { $query->where('a.from_uid', '=', $userId)->orWhere('a.to_uid', '=', $userId); } }) ->select(['a.*', 'm.username as from_username', 'm.avatar as from_avatar', 'm1.username as to_username', 'm1.avatar as to_avatar']) ->orderBy('a.create_time', 'desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { foreach ($list['data'] as &$item) { $item['from_username_text'] = $item['from_username'] ? format_account($item['from_username']) : '客服'; $item['from_username'] = $item['from_username'] ? $item['from_username'] : '客服'; $item['to_username_text'] = $item['to_username'] ? format_account($item['to_username']) : '客服'; $item['to_username'] = $item['to_username'] ? $item['to_username'] : '客服'; $item['message_url'] = $item['message_type'] == 2 ? get_image_url($item['message']) : ''; $item['from_avatar'] = $item['from_avatar'] ? get_image_url($item['from_avatar']) : ''; $item['to_avatar'] = $item['to_avatar'] ? get_image_url($item['to_avatar']) : ''; $item['time_text'] = $item['create_time'] ? format_time(strtotime($item['create_time'])) : '刚刚'; $userId = isset($params['user_id']) ? $params['user_id'] : 0; if ($userId == $item['to_uid']) { // 已读 $this->model->where(['id' => $item['id']])->update(['is_read' => 1, 'update_time' => time()]); } } } return [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 消息列表 * @param $params * @param int $pageSize * @return array */ public function getNewList($params, $pageSize = 15) { $where = ['a.mark' => 1, 'a.status' => 1]; $type = isset($params['type']) ? $params['type'] : 1; $chatKey = isset($params['chat_key']) ? $params['chat_key'] : ''; $fromUid = isset($params['from_uid']) ? $params['from_uid'] : 0; $toUid = isset($params['to_uid']) ? $params['to_uid'] : 0; $orderNo = isset($params['order_no']) ? $params['order_no'] : ''; if ($type > 0) { $where['a.type'] = $type; } if ($chatKey) { $where['a.chat_key'] = $chatKey; } if ($fromUid > 0) { $where['a.from_uid'] = $fromUid; } if ($toUid > 0) { $where['a.to_uid'] = $toUid; } if ($orderNo) { $where['a.order_no'] = $orderNo; } $list = $this->model->from('chat_message as a') ->leftJoin('member as m', 'm.id', '=', 'a.from_uid') ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid') ->where($where) ->where(function ($query) use ($params) { $userId = isset($params['user_id']) ? $params['user_id'] : 0; if ($userId) { $query->where('a.from_uid', '=', $userId)->orWhere('a.to_uid', '=', $userId); } }) ->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']) ->groupBy('a.chat_key') ->orderBy('a.create_time', 'desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { foreach ($list['data'] as &$item) { $item['from_username_text'] = $item['from_username'] ? format_account($item['from_username']) : '客服'; $item['to_username_text'] = $item['to_username'] ? format_account($item['to_username']) : '客服'; $item['from_avatar'] = $item['from_avatar'] ? get_image_url($item['from_avatar']) : ''; $item['to_avatar'] = $item['to_avatar'] ? get_image_url($item['to_avatar']) : ''; $item['time_text'] = $item['create_time'] ? format_time(strtotime($item['create_time'])) : '刚刚'; $item['info'] = $this->getTempInfo($item['chat_key']); } } return [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 消息列表 * @param $params * @param int $pageSize * @return array */ public function getWaitList($params, $pageSize = 15) { $where = ['a.mark' => 1, 'a.status' => 1]; $type = isset($params['type']) ? $params['type'] : 1; $chatKey = isset($params['chat_key']) ? $params['chat_key'] : ''; $fromUid = isset($params['from_uid']) ? $params['from_uid'] : 0; $toUid = isset($params['to_uid']) ? $params['to_uid'] : 0; $orderNo = isset($params['order_no']) ? $params['order_no'] : ''; if ($type > 0) { $where['a.type'] = $type; } if ($chatKey) { $where['a.chat_key'] = $chatKey; } if ($fromUid > 0) { $where['a.from_uid'] = $fromUid; } if ($toUid > 0) { $where['a.to_uid'] = $toUid; } if ($orderNo) { $where['a.order_no'] = $orderNo; } $list = $this->model->from('chat_message as a') ->leftJoin('member as m', 'm.id', '=', 'a.from_uid') ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid') ->where($where) ->where(function ($query) use ($params) { $userId = isset($params['user_id']) ? $params['user_id'] : 0; if ($userId) { $query->where('a.to_uid', '=', $userId); } }) ->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']) ->groupBy('a.chat_key') ->orderBy('a.create_time', 'desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { foreach ($list['data'] as &$item) { $item['from_username_text'] = $item['from_username'] ? format_account($item['from_username']) : '客服'; $item['to_username_text'] = $item['to_username'] ? format_account($item['to_username']) : '客服'; $item['from_avatar'] = $item['from_avatar'] ? get_image_url($item['from_avatar']) : ''; $item['to_avatar'] = $item['to_avatar'] ? get_image_url($item['to_avatar']) : ''; $item['time_text'] = $item['create_time'] ? format_time(strtotime($item['create_time'])) : '刚刚'; $item['info'] = $this->getTempInfo($item['chat_key']); } } return [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 消息数量 * @param $userId * @return int[] */ public function getNewCount($userId) { $counts = ['notice' => 0, 'message' => 0]; $counts['notice'] = (int)$this->model->where(['status' => 1, 'mark' => 1, 'type' => 3]) ->where(function ($query) use ($userId) { $query->where(['to_uid' => $userId]); })->count('id'); $result = $this->model->where(['status' => 1, 'mark' => 1, 'type' => 1]) ->where(function ($query) use ($userId) { $query->where(['to_uid' => $userId]); })->select(['chat_key'])->groupBy('chat_key')->get(); $result = $result ? $result->toArray() : []; $counts['message'] = count($result); return $counts; } /** * 消息数量 * @param $userId * @return int[] */ public function getUnReadCount($userId) { $count = $this->model->where(['status' => 1, 'mark' => 1, 'type' => 1,'is_read'=>2]) ->where(function ($query) use ($userId) { $query->where(['to_uid' => $userId]); })->count('id'); return $count; } /** * 获取最新的聊天消息 * @param $chatKey 聊天窗口标识 * @return array|mixed */ public function getTempInfo($chatKey) { $cacheKey = "caches:chats:temp:{$chatKey}"; $info = RedisService::get($cacheKey); if ($info) { return $info; } $info = $this->model->from('chat_message as a') ->leftJoin('member as m', 'm.id', '=', 'a.from_uid') ->leftJoin('member as m1', 'm1.id', '=', 'a.to_uid') ->where(['a.chat_key' => $chatKey, 'a.status' => 1, 'a.mark' => 1]) ->select(['a.id', 'a.message','a.from_uid','a.to_uid', 'a.is_read', 'a.message_type', 'a.create_time', 'm.username as from_username', 'm.avatar as from_avatar', 'm1.username as to_username', 'm1.avatar as to_avatar']) ->orderBy('create_time', 'desc') ->orderBy('id', 'desc') ->first(); $info = $info? $info->toArray() : []; if ($info) { $info['from_username_text'] = $info['from_username'] ? format_account($info['from_username']) : '客服'; $info['to_username_text'] = $info['to_username'] ? format_account($info['to_username']) : '客服'; $info['message_url'] = $info['message_type'] == 2 ? get_image_url($info['message']) : ''; $info['time_text'] = $info['create_time'] ? format_time(strtotime($info['create_time'])) : '刚刚'; RedisService::set($cacheKey, $info, rand(3, 5)); } return $info; } /** * 添加或编辑 * @return array */ public function saveData($data) { $data = [ 'type' => isset($data['type']) ? $data['type'] : 1, 'message_type' => isset($data['message_type']) ? $data['message_type'] : 1, 'from_uid' => isset($data['from_uid']) ? $data['from_uid'] : 1, 'to_uid' => isset($data['to_uid']) ? $data['to_uid'] : 1, 'order_no' => isset($data['order_no']) ? $data['order_no'] : '', 'chat_key' => getChatKey($data['from_uid'], $data['to_uid']), 'message' => isset($data['message']) ? $data['message'] : '', 'create_time' => time(), 'update_time' => time(), 'is_read' => 2, 'status' => 1, 'mark' => 1, ]; // 清除旧记录 $time = ConfigService::make()->getConfigByCode('chat_expired_time'); $time = $time? $time : 30; $this->model->where('create_time','<=', $time * 24 * 3600)->delete(); return $this->model->insertGetId($data); } /** * 推送保存消息,如订单消息 * @param $data 消息数据 * @return int|number */ public function pushMessage($data) { return $this->model->edit($data); } /** * 获取最新 * @param $businessId * @return array */ public function getOrderNotify($businessId) { $cacheKey = "caches:orders:notify:{$businessId}"; $info = RedisService::get($cacheKey); if($info){ return $info; } $info = $this->model->from('chat_message as a') ->leftJoin('trade_order as b','b.order_no','=','a.order_no') ->where('a.create_time','>=', time() - 10) ->where(['a.to_uid'=> $businessId,'a.is_read'=>2,'a.mark'=>1,'a.status'=>1]) ->whereIn('a.type',[2]) ->select(['a.id','a.type','a.from_uid','a.to_uid','a.order_no','a.message','b.type as order_type']) ->orderBy('a.create_time','desc') ->first(); $info = $info? $info->toArray() : []; if($info){ $this->model->where(['id'=> $info['id']])->update(['is_read'=>1,'update_time'=>time()]); RedisService::set($cacheKey, $info, rand(3,5)); } return $info? $info : []; } }