group(function () { Route::get('public/competitions/by-slug/{slug}', [PublicCompetitionController::class, 'showBySlug']); Route::get('public/source-channels/resolve', [PublicSourceChannelController::class, 'resolve']); Route::prefix('review')->group(function () { Route::post('auth/login', [ReviewAuthController::class, 'login']); Route::middleware(['auth:sanctum', 'reviewer'])->group(function () { Route::get('me', [ReviewAuthController::class, 'me']); Route::put('auth/password', [ReviewAuthController::class, 'changePassword']); Route::post('auth/password', [ReviewAuthController::class, 'changePassword']); Route::patch('auth/password', [ReviewAuthController::class, 'changePassword']); Route::get('applications', [ReviewApplicationController::class, 'index']); Route::get('applications/{application}/files/{file}/download', [ReviewApplicationController::class, 'downloadFile']) ->whereNumber('application') ->whereNumber('file'); Route::post('applications/{application}/score', [ReviewApplicationController::class, 'submitScore']) ->whereNumber('application'); Route::get('applications/{application}', [ReviewApplicationController::class, 'show']) ->whereNumber('application'); }); }); Route::prefix('manage')->group(function () { Route::post('auth/login', [ManageAuthController::class, 'login']); Route::middleware(['auth:sanctum', 'portal'])->group(function () { Route::get('me', [ManageAuthController::class, 'me']); Route::put('auth/password', [ManageAuthController::class, 'changePassword']); Route::post('auth/password', [ManageAuthController::class, 'changePassword']); Route::patch('auth/password', [ManageAuthController::class, 'changePassword']); }); }); Route::prefix('admin')->group(function () { Route::post('auth/login', [AdminAuthController::class, 'login']); Route::middleware(['auth:sanctum', 'admin'])->group(function () { Route::put('auth/password', [AdminAuthController::class, 'changePassword']); Route::post('auth/password', [AdminAuthController::class, 'changePassword']); Route::patch('auth/password', [AdminAuthController::class, 'changePassword']); Route::get('me/menus', [AdminMenuController::class, 'index']); Route::apiResource('public-source-channels', AdminPublicSourceChannelController::class) ->parameters([ 'public-source-channels' => 'public_source_channel', ]); Route::apiResource('competitions', AdminCompetitionController::class); /** scoped() 无参即可;切勿写 `'track' => 'tracks'`,Laravel 会把 `tracks` 当成子表列名导致 SQL 错误 */ Route::apiResource('competitions.tracks', AdminCompetitionTrackController::class)->scoped(); Route::apiResource('competitions.signup-channels', AdminSignupChannelController::class) ->scoped() ->parameters([ 'signup-channels' => 'signup_channel', ]); Route::apiResource('competitions.form-schemas', AdminFormSchemaDefinitionController::class) ->scoped() ->parameters([ 'form-schemas' => 'form_schema', ]); Route::apiResource('competitions.admins', AdminCompetitionAdminController::class) ->parameters([ 'admins' => 'competition_admin', ]) ->scoped(); Route::post('competitions/{competition}/admins/{competition_admin}/delete', [AdminCompetitionAdminController::class, 'destroy']) ->whereNumber('competition') ->whereNumber('competition_admin'); Route::post('competitions/{competition}/applications/{application}/impersonate', [AdminApplicationController::class, 'impersonate']) ->whereNumber('competition') ->whereNumber('application'); Route::apiResource('reviewers', AdminReviewerController::class)->except(['index']); Route::post('reviewers/{reviewer}/delete', [AdminReviewerController::class, 'destroy']) ->whereNumber('reviewer'); Route::apiResource('admin-users', AdminUserController::class)->parameters([ 'admin-users' => 'admin_user', ]); Route::post('admin-users/{admin_user}/delete', [AdminUserController::class, 'destroy']) ->whereNumber('admin_user'); }); Route::middleware(['auth:sanctum', 'competition.access'])->group(function () { Route::get('competitions/{competition}/dashboard', [AdminDashboardController::class, 'show']); Route::get('competitions/{competition}/manage/report', [ManageReportController::class, 'show']); Route::get('competitions/{competition}/reviewer-scope-track-counts', [AdminReviewerScopeController::class, 'countsByTrack']); Route::apiResource('competitions.audience-sessions', AdminAudienceSessionController::class) ->parameters([ 'audience-sessions' => 'audience_session', ]) ->scoped(); Route::post('competitions/{competition}/audience-sessions/{audience_session}/delete', [AdminAudienceSessionController::class, 'destroy']) ->whereNumber('competition') ->whereNumber('audience_session'); Route::get('competitions/{competition}/audience-registrations/export', [AdminAudienceRegistrationController::class, 'export']); Route::get('competitions/{competition}/audience-registrations', [AdminAudienceRegistrationController::class, 'index']); Route::post('competitions/{competition}/audience-checkin', [AdminAudienceCheckinController::class, 'store']); Route::get('competitions/{competition}/audience-checkin-stats', [AdminAudienceCheckinController::class, 'stats']); Route::post('competitions/{competition}/audience-registrations/{audience_registration}/checkin', [AdminAudienceCheckinController::class, 'storeByRegistration']) ->whereNumber('competition') ->whereNumber('audience_registration'); Route::get('competitions/{competition}/applications/export/meta', [AdminApplicationController::class, 'exportMeta']); Route::get('competitions/{competition}/applications/export', [AdminApplicationController::class, 'export']); Route::get('competitions/{competition}/applications', [AdminApplicationController::class, 'index']); Route::post('competitions/{competition}/applications/batch-review-result', [AdminApplicationController::class, 'batchReviewResult']); Route::get('competitions/{competition}/applications/{application}/files/{file}/download', [AdminApplicationController::class, 'downloadFile']) ->whereNumber('competition') ->whereNumber('application') ->whereNumber('file'); Route::get('competitions/{competition}/applications/{application}', [AdminApplicationController::class, 'show']) ->whereNumber('competition') ->whereNumber('application'); Route::patch('competitions/{competition}/applications/{application}/review-eligible', [AdminApplicationController::class, 'updateReviewEligible']) ->whereNumber('competition') ->whereNumber('application'); Route::get('reviewers', [AdminReviewerController::class, 'index']); Route::get('reviewer-scopes', [AdminReviewerScopeController::class, 'index']); Route::post('reviewer-scopes', [AdminReviewerScopeController::class, 'store']); Route::delete('reviewer-scopes/{reviewer_scope}', [AdminReviewerScopeController::class, 'destroy']) ->whereNumber('reviewer_scope'); Route::post('reviewer-scopes/{reviewer_scope}/delete', [AdminReviewerScopeController::class, 'destroy']) ->whereNumber('reviewer_scope'); }); }); Route::prefix('audience')->middleware(['auth:sanctum', 'audience'])->group(function () { Route::get('me', [AudienceController::class, 'me']); Route::get('sessions', [AudienceController::class, 'sessions']); Route::post('registrations', [AudienceController::class, 'storeRegistration']); Route::get('registrations', [AudienceController::class, 'registrations']); }); }); Route::post('/auth/sms/send', [AuthSmsController::class, 'send']); Route::post('/auth/sms/login', [AuthSmsController::class, 'login']); Route::post('/auth/sms/audience/login', [AudienceAuthController::class, 'login']); Route::middleware('auth:sanctum')->group(function () { Route::get('/me', [UserProfileController::class, 'show']); Route::get('/applications/current', [ApplicationController::class, 'show']); Route::put('/applications/current', [ApplicationController::class, 'update']); Route::post('/applications/current/save', [ApplicationController::class, 'update']); Route::post('/applications/current/submit', [ApplicationController::class, 'submit']); Route::post('/applications/current/files', [ApplicationFileController::class, 'store']); Route::delete('/applications/current/files/{file}', [ApplicationFileController::class, 'destroy']); Route::post('/applications/current/files/{file}/delete', [ApplicationFileController::class, 'destroy']); });