orderBy('sort')->orderByDesc('id'); StudyTourPayload::applyListFilters($q, $request); return response()->json($q->get()); } public function store(Request $request): JsonResponse { $this->ensureSuperAdmin($request); $data = $request->validate(StudyTourPayload::validationRules(true)); $data = StudyTourPayload::normalizeIncoming($data); $row = StudyTour::create($data + [ 'tags' => $data['tags'] ?? [], 'venue_ids' => $data['venue_ids'] ?? [], 'venue_items' => $data['venue_items'] ?? [], 'seasons' => $data['seasons'] ?? [], 'grade_levels' => $data['grade_levels'] ?? [], 'route_plans' => $data['route_plans'] ?? [], 'courses' => $data['courses'] ?? [], 'gallery_media' => $data['gallery_media'] ?? [], 'sort' => $data['sort'] ?? 0, 'is_on_shelf' => $data['is_on_shelf'] ?? true, ]); return response()->json($row, 201); } public function update(Request $request, StudyTour $studyTour): JsonResponse { $this->ensureSuperAdmin($request); $data = $request->validate(StudyTourPayload::validationRules(false)); $data = StudyTourPayload::normalizeIncoming($data); $studyTour->fill($data)->save(); return response()->json($studyTour->fresh()); } public function destroy(Request $request, StudyTour $studyTour): JsonResponse { $this->ensureSuperAdmin($request); $studyTour->delete(); return response()->json(['message' => '删除成功']); } public function parseDoc(Request $request): JsonResponse { $request->validate([ 'file' => ['required', 'file', 'max:10240'], ]); $uploaded = $request->file('file'); if ($uploaded === null) { return response()->json(['message' => '请上传申报表文件'], 422); } $extension = strtolower((string) ($uploaded->getClientOriginalExtension() ?: $uploaded->extension())); if (! in_array($extension, ['doc', 'docx'], true)) { return response()->json(['message' => '仅支持 .doc / .docx 申报表'], 422); } $tmpPath = $uploaded->getRealPath(); if (! is_string($tmpPath) || $tmpPath === '') { return response()->json(['message' => '无法读取上传文件'], 422); } try { $result = StudyTourDeclarationParser::parseFile($tmpPath, $extension); } catch (\Throwable $e) { return response()->json(['message' => '申报表解析失败:'.$e->getMessage()], 422); } return response()->json($result); } private function ensureSuperAdmin(Request $request): void { abort_unless($request->user()?->isSuperAdmin(), 403, '仅超级管理员可操作'); } }