256 lines
9.2 KiB
PHP
256 lines
9.2 KiB
PHP
<?php
|
||
namespace app\chat\controller;
|
||
|
||
use app\chat\model\ChatMessage;
|
||
use app\chat\model\ChatUnreadCount;
|
||
use app\chat\model\ChatTop;
|
||
use app\chat\model\ChatUser;
|
||
use app\chat\model\ChatGroup;
|
||
use app\common\controller\ApiController;
|
||
use app\utils\Session;
|
||
use support\Redis;
|
||
use support\Request;
|
||
use support\Response;
|
||
use support\think\Db;
|
||
|
||
class MessageController extends ApiController
|
||
{
|
||
/**
|
||
* 获取历史消息
|
||
*/
|
||
public function history(Request $request): Response
|
||
{
|
||
$uid = $this->uid;
|
||
$chatType = $request->post('chat_type'); // 1=单聊,2=群聊
|
||
$toId = $request->post('to_id'); // 单聊=对方ID,群聊=群ID
|
||
$session_id = $request->post('session_id'); // 会话ID
|
||
$group_id = $request->post('group_id'); // 会话ID
|
||
$page = $request->post('page', 1)?:1;
|
||
$size = $request->post('size', 20)?:20;
|
||
|
||
if (!$toId || !$chatType || !$session_id || !$group_id) {
|
||
return $this->error('参数不完整');
|
||
}
|
||
|
||
$group = Db::name('chat_group')->where(['id' => $group_id])->find();
|
||
if (!$group) {
|
||
return $this->error('群不存在');
|
||
}
|
||
// 构建查询条件
|
||
$query = Db::name('chat_message')->where(['session_id' => $session_id]);
|
||
|
||
$role = 2;
|
||
// 群聊需验证是否在群内
|
||
if ($chatType == 2) {
|
||
$isMember = Db::name('chat_group_member')->where([
|
||
'group_id' => $toId,
|
||
'user_id' => $uid,
|
||
'quit_time' => null,
|
||
'is_kicked' => 0
|
||
])->find();
|
||
if (!$isMember) {
|
||
return $this->error('不在群内,无法获取历史消息');
|
||
}
|
||
$role = $isMember['role'];
|
||
}
|
||
|
||
// 分页查询(倒序取,再正序返回)
|
||
$total = $query->count();
|
||
$messages = $query->alias('msg')->order('send_time', 'desc')
|
||
->leftJoin('chat_user user', 'msg.from_id = user.user_id')
|
||
->field('msg.id,from_id,to_id,chat_type,msg_type,content,image_url,order_id,is_read,send_time,session_id,nick_name,user_id,avatar,type,coupon,coupon_claim,chat_coupon_id')
|
||
->page($page, $size)
|
||
->select()->toArray();
|
||
|
||
// 单聊自动标记已读
|
||
// if ($chatType == 1) {
|
||
Db::name('chat_message')->where([
|
||
'session_id' => $session_id,
|
||
'to_id' => $uid,
|
||
'is_read' => 0
|
||
])->update(['is_read' => 1]);
|
||
|
||
// 重置未读计数
|
||
Db::name('chat_unread_count')->where([
|
||
'user_id' => $uid,
|
||
'session_id' => $session_id
|
||
])->update(['count' => 0, 'updated_time' => d()]);
|
||
// }
|
||
foreach ($messages as $k => &$v) {
|
||
$v['send_time'] = formatWeChatTime($v['send_time']);
|
||
$v['coupon'] = !empty($v['coupon'])?json_decode($v['coupon']):'';
|
||
// 判断是谁发的
|
||
if($v['from_id'] == $this->uid) {
|
||
$v['is_user_send'] = 1; // 自己发的
|
||
}else {
|
||
$v['is_user_send'] = 2; // 别人发的
|
||
}
|
||
|
||
}
|
||
|
||
$mute = Db::name('chat_group_mute')->where(['group_id' => $group_id, 'user_id' => 0])->find();
|
||
$group['is_mute'] = $mute?1:0;
|
||
$group['role'] = $role;
|
||
return $this->success([
|
||
'group' => $group,
|
||
'list' => $messages,
|
||
'page' => $page,
|
||
'size' => $size,
|
||
'total' => $total]);
|
||
}
|
||
|
||
/**
|
||
* 标记消息已读(批量)
|
||
*/
|
||
public function markRead(Request $request): Response
|
||
{
|
||
$msgIds = $request->post('msg_ids');
|
||
if (empty($msgIds) || !is_string($msgIds)) {
|
||
return $this->error('请传入有效消息ID');
|
||
}
|
||
$msgIds = explode(',', $msgIds);
|
||
$query = Db::name('chat_message')->whereIn('id', $msgIds)->where('to_id', $this->uid)
|
||
->where('is_read', 0);
|
||
// 标记已读(仅自己接收的消息)
|
||
$count = $query->count();
|
||
if (empty($count)) {
|
||
return $this->error('无未读消息可标记');
|
||
}
|
||
try {
|
||
Db::startTrans();
|
||
$sessionIds = $query->group('session_id')->column('session_id');
|
||
// 更新未读计数
|
||
foreach ($sessionIds as $sessionId) {
|
||
Db::name('chat_unread_count')->where(['user_id' => $this->uid, 'session_id' => $sessionId])->update(['count' => 0, 'updated_time' => d()]);
|
||
}
|
||
// 批量更新
|
||
$query->update(['is_read' => 1]);
|
||
Db::commit();
|
||
return $this->success(true);
|
||
}catch (\Throwable $exception) {
|
||
Db::rollback();
|
||
return $this->error($exception->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 标记会话全部已读
|
||
*/
|
||
public function markReadAll(Request $request): Response
|
||
{
|
||
$msgIds = $request->post('session_ids');
|
||
if (empty($msgIds) || !is_string($msgIds)) {
|
||
return $this->error('请传入有效会话ID');
|
||
}
|
||
$msgIds = explode(',', $msgIds);
|
||
$query = Db::name('chat_message')->whereIn('session_id', $msgIds)->where('to_id', $this->uid)
|
||
->where('is_read', 0);
|
||
try {
|
||
Db::startTrans();
|
||
// 更新未读计数
|
||
foreach ($msgIds as $sessionId) {
|
||
Db::name('chat_unread_count')->where(['user_id' => $this->uid, 'session_id' => $sessionId])->update(['count' => 0, 'updated_time' => d()]);
|
||
}
|
||
// 批量更新
|
||
$query->update(['is_read' => 1]);
|
||
Db::commit();
|
||
return $this->success(true);
|
||
}catch (\Throwable $exception) {
|
||
Db::rollback();
|
||
return $this->error($exception->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取未读消息总数
|
||
*/
|
||
public function getUnreadCount(Request $request): Response
|
||
{
|
||
$total = Db::name('chat_unread_count')->where('user_id', $this->uid)->sum('count');
|
||
return $this->success(['total' => $total]);
|
||
}
|
||
|
||
/**
|
||
* 获取会话列表(含置顶、未读、最后消息)
|
||
*/
|
||
public function getSessionList(Request $request): Response
|
||
{
|
||
// 获取所有会话ID
|
||
$sessionIds = Db::name('chat_message')->where('from_id', $this->uid)->WhereOr('to_id', $this->uid)
|
||
->group('session_id')->column('session_id');
|
||
if (empty($sessionIds)) {
|
||
return $this->success();
|
||
}
|
||
$list = Redis::get('usermsg:list:' . $this->user_type . ':' . $this->uid);
|
||
if($list) {
|
||
$data = json_decode($list, true);
|
||
}else {
|
||
$data = ChatMessage::getconverlist($this->uid, $this->user_type);
|
||
}
|
||
// 最新一条消息
|
||
foreach ($data as $k => $session) {
|
||
$lastMsg = '';
|
||
$unreadCount = 0;
|
||
if(!empty($session['session_id'])) {
|
||
// 最后一条消息
|
||
$lastMsg = Db::name('chat_message')
|
||
->where('session_id', $session['session_id'])
|
||
->order('send_time', 'desc')
|
||
->find();
|
||
// 未读计数
|
||
$unreadCount = Db::name('chat_unread_count')->where(['user_id' => $this->uid, 'session_id' => $session['session_id']])->value('count')?:0;
|
||
}
|
||
if($session['chat_type'] == 2) {
|
||
if($lastMsg) {
|
||
$chat_user = Db::name('chat_user')->where(['user_id' => $lastMsg['from_id']])->field('nick_name,avatar')->find();
|
||
}
|
||
}
|
||
$msg = '';
|
||
if($lastMsg) {
|
||
// 如果是自己发的不显示发送人
|
||
if($lastMsg['from_id'] == $this->uid) {
|
||
$msg = $lastMsg['content'];
|
||
}else {
|
||
// 如果是别人发的显示昵称
|
||
$msg = $chat_user['nick_name'] . ':' . $lastMsg['content'];
|
||
}
|
||
$data[$k]['send_time'] = formatWeChatTime($lastMsg['send_time']);
|
||
}
|
||
$data[$k]['msg'] = $msg;
|
||
$data[$k]['unread_count'] = $unreadCount;
|
||
$data[$k]['is_th'] = ChatGroup::isTh($session['group_id'], $this->uid);
|
||
}
|
||
return $this->success(['list' => $data]);
|
||
}
|
||
|
||
/**
|
||
* 删除会话列表
|
||
*/
|
||
public function getSessionListDel(Request $request): Response
|
||
{
|
||
$session_id = $request->post('session_id');
|
||
if(empty($session_id)) {
|
||
return $this->error('参数不完整');
|
||
}
|
||
$list_json = Redis::get('usermsg:list:' . $this->user_type . ':' . $this->uid);
|
||
if($list_json) {
|
||
$list_arr = json_decode($list_json, true);
|
||
foreach ($list_arr as $k => &$list) {
|
||
if($list['session_id'] == $session_id) {
|
||
$list['is_del'] = 1;
|
||
}
|
||
}
|
||
if(count($list_arr) >= 1) {
|
||
Redis::set('usermsg:list:' . $this->user_type . ':' . $this->uid, json_encode($list_arr));
|
||
}else {
|
||
Redis::del('usermsg:list:' . $this->user_type . ':' . $this->uid);
|
||
}
|
||
}
|
||
return $this->success();
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|