增加技术端与客户端聊天
This commit is contained in:
312
server/app/coachapi/controller/ChatController.php
Normal file
312
server/app/coachapi/controller/ChatController.php
Normal 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]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user