currentUser($request); // 本人已读过的广播来源ID(已读副本记录) $readBroadcastIds = NoticeModel::query() ->where('user_id', $user->id) ->whereNotNull('data->broadcast_from') ->pluck('data->broadcast_from'); $query = NoticeModel::query()->where(function ($q) use ($user, $readBroadcastIds) { $q->where('user_id', $user->id) ->orWhere(function ($broadcastQuery) use ($readBroadcastIds) { $broadcastQuery->where('user_id', NoticeModel::BROADCAST_USER_ID); if ($readBroadcastIds->isNotEmpty()) { $broadcastQuery->whereNotIn('id', $readBroadcastIds->all()); } }); }); $unreadCount = (clone $query)->where('is_read', NoticeModel::UNREAD)->count(); $data = $query->orderBy('id', 'desc') ->paginate((int) $request->input('pageSize', 10)) ->toArray(); $data['unread_count'] = $unreadCount; return $this->success($data); } /** 标记已读(广播 → 复制本人已读副本;个人通知 → 直接更新) */ #[PutRoute('/notice/{id}/read', authorize: true, where: ['id' => '[0-9]+'])] public function read(int $id, Request $request): JsonResponse { $user = $this->currentUser($request); $notice = NoticeModel::whereIn('user_id', [NoticeModel::BROADCAST_USER_ID, $user->id])->find($id); if ($notice === null) { throw new RepositoryException('通知不存在'); } if ($notice->user_id === NoticeModel::BROADCAST_USER_ID) { $exists = NoticeModel::where('user_id', $user->id) ->where('data->broadcast_from', $notice->id) ->exists(); if (! $exists) { NoticeModel::create([ 'user_id' => $user->id, 'type' => $notice->type, 'title' => $notice->title, 'content' => $notice->content, 'data' => ['broadcast_from' => $notice->id] + (array) $notice->data, 'is_read' => NoticeModel::READ, 'read_at' => now(), ]); } } elseif ($notice->is_read === NoticeModel::UNREAD) { $notice->is_read = NoticeModel::READ; $notice->read_at = now(); $notice->save(); } return $this->success(); } }