currentStore($request); // 本店已读过的广播来源ID(已读副本记录) $readBroadcastIds = NoticeModel::query() ->where('store_id', $store->id) ->whereNotNull('data->broadcast_from') ->pluck('data') ->map(static fn (?array $data) => $data['broadcast_from'] ?? null) ->filter() ->values(); $query = NoticeModel::query()->where(function ($q) use ($store, $readBroadcastIds) { $q->where('store_id', $store->id) ->orWhere(function ($broadcastQuery) use ($readBroadcastIds) { $broadcastQuery->where('store_id', NoticeModel::BROADCAST_STORE_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 { $store = $this->currentStore($request); $notice = NoticeModel::whereIn('store_id', [NoticeModel::BROADCAST_STORE_ID, $store->id])->find($id); if ($notice === null) { throw new RepositoryException('通知不存在'); } if ($notice->store_id === NoticeModel::BROADCAST_STORE_ID) { $exists = NoticeModel::where('store_id', $store->id) ->where('data->broadcast_from', $notice->id) ->exists(); if (! $exists) { NoticeModel::create([ 'store_id' => $store->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(); } }