Files
p_ysk/app/chat/controller/MessageController.php
2025-12-05 15:29:57 +08:00

303 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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('群不存在');
}
if($chatType == 2) {
// 构建查询条件
$query = Db::name('chat_message')->where(['group_id' => $group_id]);
}else {
// 构建查询条件
$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,type,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' => $toId
])->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']):'';
$v['nick'] = $v['nick_name'];
// 判断是谁发的
if($v['from_id'] == $this->uid) {
$v['is_user_send'] = 1; // 自己发的
}else {
$v['is_user_send'] = 2; // 别人发的
}
// 判断是不是商家发的
if($v['type'] == 2) {
$v['is_shop'] = 1; // 商家
}else {
$v['is_shop'] = 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'])) {
if($session['chat_type'] == 2) {
// 最后一条消息
$lastMsg = Db::name('chat_message')
->where('group_id', $session['group_id'])
->order('send_time', 'desc')
->find();
}else {
$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['to_id']])->value('count')?:0;
}
if($session['chat_type'] == 2) {
if($lastMsg) {
$chat_user = Db::name('chat_user')->where(['user_id' => $lastMsg['from_id']])->field('type')->find();
// 如果是用户
if($chat_user['type'] == 1) {
$chat_user = Db::name('tb_user_info')->where(['id' => $lastMsg['from_id']])->field('nick_name,head_img as avatar')->find();
}else {
$chat_user = Db::name('sys_user')->where(['id' => $lastMsg['from_id']])->field('nick_name,avatar')->find();
}
}
}
$msg = '';
if($lastMsg) {
switch ($lastMsg['msg_type']) {
case 1:
$content = $lastMsg['content'];
break;
case 2:
$content = '[图片]';
break;
case 3:
$content = '[订单]';
break;
case 4:
$content = '[优惠券]';
break;
case 5:
$content = '[视频]';
break;
}
// 如果是自己发的不显示发送人
if($lastMsg['from_id'] == $this->uid) {
$msg = $content;
}else {
// 如果是别人发的显示昵称
$msg = $chat_user['nick_name'] . '' . $content;
}
$data[$k]['send_time_origin'] = $lastMsg['send_time'];
$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);
}
$data = param_sort($data, 'send_time_origin');
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();
}
}