validate([ 'page' => ['nullable', 'integer', 'min:1'], 'page_size' => ['nullable', 'integer', 'min:1', 'max:100'], ]); $paginator = WeeklyBrief::query() ->orderByDesc('week_start') ->paginate((int) ($data['page_size'] ?? 20)) ->withQueryString(); $paginator->getCollection()->transform(fn (WeeklyBrief $b) => $this->serializeList($b)); return $this->paginated($paginator); } public function show(int $weeklyBrief): JsonResponse { $model = WeeklyBrief::query()->findOrFail($weeklyBrief); return $this->ok($this->serializeDetail($model)); } public function generate(Request $request): JsonResponse { $data = $request->validate([ 'week_start' => ['nullable', 'date'], 'week_end' => ['nullable', 'date', 'after_or_equal:week_start'], ]); try { if (! empty($data['week_start']) && ! empty($data['week_end'])) { $weekStart = Carbon::parse($data['week_start'])->timezone('Asia/Shanghai')->startOfDay(); $weekEnd = Carbon::parse($data['week_end'])->timezone('Asia/Shanghai')->endOfDay(); } else { [$weekStart, $weekEnd] = $this->service->resolvePreviousWeek(); } $brief = $this->service->generate( $weekStart, $weekEnd, $request->user()?->id, replace: true, ); } catch (Throwable $e) { return $this->fail('简报生成失败:'.$e->getMessage(), 500); } return $this->ok($this->serializeDetail($brief), '简报已生成'); } /** * @return array */ protected function serializeList(WeeklyBrief $brief): array { return [ 'id' => $brief->id, 'week_start' => $brief->week_start?->toDateString(), 'week_end' => $brief->week_end?->toDateString(), 'title' => $brief->title, 'stats' => $brief->stats_json, 'generated_at' => $brief->generated_at?->toIso8601String(), ]; } /** * @return array */ protected function serializeDetail(WeeklyBrief $brief): array { return [ ...$this->serializeList($brief), 'markdown' => $brief->markdown, ]; } }