feat: 好友系统全实现

后端:
- FriendController:add/remove/status/index 四个接口
- FriendAdded / FriendRemoved 广播事件(私有频道)
- channels.php 注册 user.{username} 私有频道鉴权
- routes/web.php 注册好友路由
- ChatController::init() 修复 DutyLog 在 return 后执行的 bug
- ChatController::notifyFriendsOnline() 上线时悄悄话通知好友

前端:
- user-actions:写私信 → 加好友/删好友按钮(动态状态)
- toggleFriend() 方法 + fetchUser 后加载好友状态
- scripts:监听私有频道 FriendAdded/FriendRemoved
- showFriendToast() 右下角浮窗通知(5秒自动消失)
- global-dialog 加 fdSlideIn 动画
This commit is contained in:
2026-03-01 00:48:51 +08:00
parent 8853d08e5a
commit 700ab9def4
9 changed files with 557 additions and 18 deletions

View File

@@ -18,6 +18,7 @@ use App\Events\UserLeft;
use App\Http\Requests\SendMessageRequest;
use App\Jobs\SaveMessageJob;
use App\Models\Autoact;
use App\Models\FriendRequest;
use App\Models\Gift;
use App\Models\PositionDutyLog;
use App\Models\Room;
@@ -182,17 +183,7 @@ class ChatController extends Controller
return $fromUser === $username || $toUser === $username;
}));
// 渲染主聊天框架视图
return view('chat.frame', [
'room' => $room,
'user' => $user,
'weekEffect' => $this->shopService->getActiveWeekEffect($user),
'newbieEffect' => $newbieEffect,
'historyMessages' => $historyMessages,
]);
// 最后:如果用户有在职职务,开始记录这次入场的在职登录
// 此时用户局部变量已初始化,可以安全读取 in_time
// 7. 如果用户有在职職务,开始记录这次入场的在职登录
$activeUP = $user->activePosition;
if ($activeUP) {
PositionDutyLog::create([
@@ -203,6 +194,58 @@ class ChatController extends Controller
'room_id' => $id,
]);
}
// 8. 好友上线通知:向此房间内在线的好友推送慧慧话
$this->notifyFriendsOnline($id, $user->username);
// 渲染主聊天框架视图
return view('chat.frame', [
'room' => $room,
'user' => $user,
'weekEffect' => $this->shopService->getActiveWeekEffect($user),
'newbieEffect' => $newbieEffect,
'historyMessages' => $historyMessages,
]);
}
/**
* 当用户进入房间时,向该房间内在线的所有好友推送慧慧话通知。
*
* @param int $roomId 当前房间 ID
* @param string $username 上线的用户名
*/
private function notifyFriendsOnline(int $roomId, string $username): void
{
// 获取所有把我加为好友的人(他们是将我加为好友的关注者)
$friendUsernames = FriendRequest::where('towho', $username)->pluck('who');
if ($friendUsernames->isEmpty()) {
return;
}
// 当前房间在线用户列表
$onlineUsers = $this->chatState->getRoomUsers($roomId);
foreach ($friendUsernames as $friendName) {
// 好友就在这个房间里,才发通知
if (! isset($onlineUsers[$friendName])) {
continue;
}
$msg = [
'id' => $this->chatState->nextMessageId($roomId),
'room_id' => $roomId,
'from_user' => '系统',
'to_user' => $friendName,
'content' => "🟢 你的好友 <b>{$username}</b> 上线啊!",
'is_secret' => true,
'font_color' => '#16a34a',
'action' => '',
'sent_at' => now()->toDateTimeString(),
];
$this->chatState->pushMessage($roomId, $msg);
broadcast(new MessageSent($roomId, $msg));
}
}
/**