增加技术端与客户端聊天

This commit is contained in:
贾祥聪
2025-08-21 16:06:21 +08:00
parent f937a1f9b9
commit 1b9651c3e5
5 changed files with 1057 additions and 0 deletions

View File

@@ -0,0 +1,312 @@
<?php
namespace app\coachapi\controller;
use app\common\model\chat\ChatConversation;
use app\common\model\chat\ChatMessage;
use app\common\model\coach\Coach;
use app\common\model\user\User;
use think\facade\Db;
use think\Request;
class ChatController extends BaseCoachController
{
/**
* 获取会话信息
*/
public function conversation_info()
{
$conversationId = $this->request->param('conversation_id/d', 0);
if (!$conversationId) {
return json(['code' => 400, 'msg' => '会话ID不能为空']);
}
try {
// 查询会话信息
$conversation = ChatConversation::find($conversationId);
if (!$conversation) {
return json(['code' => 404, 'msg' => '会话不存在']);
}
// 查询用户信息
$userInfo = User::field('id, nickname, avatar')->find($conversation['user_id']);
// 查询技师信息
$techInfo = Coach::field('id, name as nickname, work_photo as avatar')->find($conversation['tech_id']);
// 查询最后一条消息
$lastMessage = [];
if ($conversation['last_msg_id']) {
$lastMessage = ChatMessage::field('content, create_time')->find($conversation['last_msg_id']);
}
return json([
'code' => 200,
'data' => [
'id' => $conversation['id'],
'user_info' => $userInfo ?: null,
'tech_info' => $techInfo ?: null,
'last_message' => $lastMessage ?: null,
'unread_count' => $conversation['unread_count'],
'update_time' => $conversation['update_time']
]
]);
} catch (\Exception $e) {
return json(['code' => 500, 'msg' => '获取会话信息失败: ' . $e->getMessage()]);
}
}
/**
* 获取聊天历史
*/
public function history()
{
$conversationId = $this->request->param('conversation_id/d', 0);
$page = $this->request->param('page/d', 1);
$pageSize = $this->request->param('page_size/d', 20);
if (!$conversationId) {
return json(['code' => 400, 'msg' => '会话ID不能为空']);
}
try {
// 计算偏移量
$offset = ($page - 1) * $pageSize;
// 查询消息列表
$messages = Db::name('chat_message')
->where('conversation_id', $conversationId)
->order('id', 'asc')
->limit($offset, 999999)
->select()
->toArray();
// 查询总数
$total = Db::name('chat_message')
->where('conversation_id', $conversationId)
->count();
return json([
'code' => 200,
'data' => [
'list' => $messages,
'total' => $total,
'has_more' => ($offset + count($messages)) < $total
]
]);
} catch (\Exception $e) {
return json(['code' => 500, 'msg' => '获取聊天历史失败: ' . $e->getMessage()]);
}
}
/**
* 标记消息为已读
*/
public function mark_as_read()
{
$conversationId = $this->request->param('conversation_id/d', 0);
$userId = $this->request->param('user_id/d', 0);
if (!$conversationId || !$userId) {
return json(['code' => 400, 'msg' => '参数不完整']);
}
try {
// 开始事务
Db::startTrans();
// 1. 标记消息为已读
Db::name('chat_message')
->where('conversation_id', $conversationId)
->where('receiver_id', $userId)
->where('read_status', 0)
->update([
'read_status' => 1,
'update_time' => date('Y-m-d H:i:s')
]);
// 2. 重置会话未读数
Db::name('chat_conversation')
->where('id', $conversationId)
->update([
'unread_count' => 0,
'update_time' => date('Y-m-d H:i:s')
]);
// 提交事务
Db::commit();
return json(['code' => 200, 'msg' => '标记成功']);
} catch (\Exception $e) {
// 回滚事务
Db::rollback();
return json(['code' => 500, 'msg' => '标记失败: ' . $e->getMessage()]);
}
}
/**
* 获取会话列表
* @return \think\Response
*/
public function conversations(Request $request)
{
try {
// 获取当前技师ID (从token或session中获取)
$techId = $this->getCurrentTechId();
// 获取请求参数
$page = $request->param('page/d', 1);
$pageSize = $request->param('page_size/d', 10);
// 查询会话列表
$conversations = ChatConversation::where('tech_id', $techId)
->with(['user', 'lastMessage'])
->order('update_time', 'desc')
->page($page, $pageSize)
->select();
// 格式化返回数据
$data = [];
foreach ($conversations as $convo) {
$data[] = [
'id' => $convo->id,
'user_id' => $convo->user_id,
'user_name' => $convo->user->nickname ?? '',
'user_avatar' => $convo->user->avatar ?? '',
'last_message' => $convo->lastMessage->content ?? '',
'last_message_time' => $convo->lastMessage->create_time ?? '',
'unread_count' => $convo->unread_count,
'update_time' => $convo->update_time
];
}
return json([
'code' => 200,
'msg' => '成功',
'data' => $data
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '获取会话列表失败: ' . $e->getMessage()
]);
}
}
/**
* 获取当前技师ID
* @return int
* @throws \Exception
*/
private function getCurrentTechId()
{
return $this->coachInfo['coach_id'];
}
/**
* 发送消息
*/
public function send()
{
$params = $this->request->param();
$techId = $params['tech_id'] ?? 0;
$orderId = $params['order_id'] ?? 0;
$content = $params['content'] ?? '';
if (empty($content)) {
return json(['code' => 400, 'msg' => '消息内容不能为空']);
}
// 生成会话ID
$conversation = ChatConversation::where(['tech_id'=>$techId,'user_id'=>$this->userId])->find();
if (empty($conversation)) {
$cccc = new ChatConversation;
$conversationId = $cccc->insertGetId(['tech_id'=>$techId,'user_id'=>$this->userId]);
}else{
$conversationId = $conversation['id'];
}
// 创建消息
$message = new ChatMessage();
$message->conversation_id = $conversationId;
$message->sender_id = $this->userId;
$message->sender_type = ChatMessage::SENDER_USER; // 用户
$message->receiver_id = $techId;
$message->receiver_type = ChatMessage::SENDER_TECH; // 技师
$message->content = $content;
$message->message_type = ChatMessage::TYPE_TEXT; // 文本
$message->read_status = ChatMessage::UNREAD; // 未读
$message->order_id = $orderId;
$message->save();
// TODO: 这里应该通过WebSocket推送给技师
return json(['code' => 200, 'msg' => '发送成功', 'data' => $message]);
}
/**
* 标记消息为已读
*/
public function markAsRead()
{
$params = $this->request->param();
$conversationId = $params['conversation_id'] ?? '';
$userId = $this->request->uid;
if (empty($conversationId)) {
return json(['code' => 400, 'msg' => '会话ID不能为空']);
}
// 标记消息为已读
Db::name('chat_message')
->where('conversation_id', $conversationId)
->where('receiver_id', $userId)
->where('read_status', ChatMessage::UNREAD)
->update(['read_status' => ChatMessage::READ]);
return json(['code' => 200, 'msg' => '已标记为已读']);
}
/**
* 获取未读消息数量
*/
public function unreadCount()
{
$unreadCount = ChatMessage::where([
'conversation_id' => $this->request->uid,
'receiver_type' => ChatMessage::SENDER_USER, // 用户
'read_status' => ChatMessage::UNREAD
])->count();
return json(['code' => 200, 'data' => ['count' => $unreadCount]]);
}
/**
* 获取最后一条消息
*/
public function lastMessage()
{
$params = $this->request->param();
$techId = $params['tech_id'] ?? 0;
$orderId = $params['order_id'] ?? 0;
// 生成会话ID
$conversationId = min($this->request->uid, $techId) . '_' . max($this->request->uid, $techId);
$message = ChatMessage::where([
'conversation_id' => $conversationId,
'order_id' => $orderId
])
->order('id', 'desc')
->find();
return json(['code' => 200, 'data' => $message]);
}
}