You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.2 KiB

5 months ago
<?php
3 months ago
use App\Http\Controllers\Api\ApplicationFileController;
use App\Http\Controllers\ChannelEntryController;
3 months ago
use App\Http\Middleware\EncryptCookies;
use App\Http\Middleware\VerifyCsrfToken;
use App\Models\PublicSourceChannel;
3 months ago
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
5 months ago
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Route;
3 months ago
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
5 months ago
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
1 month ago
$showEventSite = function (string $eventSiteRelative = 'frontend/event-site.html') {
$sourceCode = trim((string) request()->query('src', ''));
$publicSourceCode = null;
if (preg_match('/^[A-Za-z0-9_-]{2,64}$/', $sourceCode) === 1) {
try {
$publicSourceCode = PublicSourceChannel::query()
->where('source_code', $sourceCode)
->where('status', PublicSourceChannel::STATUS_ENABLED)
->value('source_code');
} catch (Throwable) {
$publicSourceCode = null;
}
}
return view('welcome', [
'publicSourceCode' => $publicSourceCode,
1 month ago
'eventSiteRelative' => $eventSiteRelative,
]);
1 month ago
};
Route::get('/', fn () => $showEventSite());
Route::get('/en', fn () => $showEventSite('frontend/event-site-en.html'));
Route::get('/channel-entry', ChannelEntryController::class)->name('channel.entry');
5 months ago
3 months ago
/**
* 选手端附件预览:签名临时 URL;跳过 session/CSRF,保留 SubstituteBindings 以解析 {file} 模型。
*/
Route::get('/participant/application-files/{file}', [ApplicationFileController::class, 'downloadSigned'])
->middleware('signed')
->withoutMiddleware([
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
])
->whereNumber('file')
->name('participant.application-file.download');
1 month ago
/**
* 前端 SPA(public/admin)。
* php artisan serve 在未使用项目根 server.php 时,可能把 /admin/c/... 改写成 /c/...;
* 因此同时注册 /admin/{path?} 与 /c/{path?} 回退,均返回同一 index.html。
*/
$serveAdminSpa = function (?string $path = null) {
5 months ago
if ($path !== null && $path !== '') {
$candidate = public_path('admin/'.$path);
if (File::isFile($candidate)) {
return response()->file($candidate);
}
}
$index = public_path('admin/index.html');
if (! File::exists($index)) {
1 month ago
abort(503, 'Admin frontend not built. Run npm run build in the frontend project.');
5 months ago
}
return response()->file($index, ['Content-Type' => 'text/html; charset=UTF-8']);
1 month ago
};
Route::redirect('/admin', '/admin/', 301);
Route::get('/admin/{path?}', $serveAdminSpa)->where('path', '.*')->name('admin.spa');
Route::get('/c/{path?}', $serveAdminSpa)->where('path', '.*')->name('admin.spa.c-fallback');