findOrFail($activity); $items = ActivitySession::query() ->where('activity_id', $activity) ->orderBy('sort') ->orderBy('id') ->get() ->map(fn (ActivitySession $s) => $this->serialize($s)); return $this->ok(['items' => $items]); } public function store(Request $request, int $activity): JsonResponse { $activityModel = Activity::query()->findOrFail($activity); $data = $request->validate([ 'title' => ['nullable', 'string', 'max:255'], 'starts_at' => ['nullable', 'date'], 'ends_at' => ['nullable', 'date', 'after_or_equal:starts_at'], 'venue' => ['nullable', 'string', 'max:255'], 'capacity' => ['nullable', 'integer', 'min:0'], 'sort' => ['nullable', 'integer'], ]); $this->assertSessionWithinActivity($activityModel, $data); $session = ActivitySession::query()->create([ 'activity_id' => $activity, ...$data, ]); return $this->ok(['id' => $session->id], '已创建'); } public function update(Request $request, int $activity, int $session): JsonResponse { $activityModel = Activity::query()->findOrFail($activity); $model = ActivitySession::query()->where('activity_id', $activity)->findOrFail($session); $data = $request->validate([ 'title' => ['nullable', 'string', 'max:255'], 'starts_at' => ['nullable', 'date'], 'ends_at' => ['nullable', 'date'], 'venue' => ['nullable', 'string', 'max:255'], 'capacity' => ['nullable', 'integer', 'min:0'], 'sort' => ['nullable', 'integer'], ]); $this->assertSessionWithinActivity($activityModel, $data, $model); $model->fill($data); $model->save(); return $this->ok(null, '已保存'); } public function destroy(int $activity, int $session): JsonResponse { $model = ActivitySession::query()->where('activity_id', $activity)->findOrFail($session); $model->delete(); return $this->ok(null, '已删除'); } /** * @return array */ /** * @param array $data */ protected function assertSessionWithinActivity(Activity $activity, array $data, ?ActivitySession $existing = null): void { $startsAt = $data['starts_at'] ?? $existing?->starts_at?->toIso8601String(); $endsAt = $data['ends_at'] ?? $existing?->ends_at?->toIso8601String(); if ($startsAt && $activity->event_start_date) { $start = Carbon::parse($startsAt); if ($start->toDateString() < $activity->event_start_date->toDateString()) { throw ValidationException::withMessages([ 'starts_at' => ['场次开始时间不能早于活动开始日期'], ]); } } if ($endsAt && $activity->event_end_date) { $end = Carbon::parse($endsAt); if ($end->toDateString() > $activity->event_end_date->toDateString()) { throw ValidationException::withMessages([ 'ends_at' => ['场次结束时间不能晚于活动结束日期'], ]); } } if ($startsAt && $endsAt && Carbon::parse($endsAt)->lt(Carbon::parse($startsAt))) { throw ValidationException::withMessages([ 'ends_at' => ['场次结束时间不能早于开始时间'], ]); } } protected function serialize(ActivitySession $s): array { return [ 'id' => $s->id, 'activity_id' => $s->activity_id, 'title' => $s->title, 'starts_at' => $s->starts_at?->toIso8601String(), 'ends_at' => $s->ends_at?->toIso8601String(), 'venue' => $s->venue, 'capacity' => $s->capacity !== null ? (int) $s->capacity : null, 'sort' => (int) $s->sort, ]; } }