dpl/routes/web.php

122 lines
5.3 KiB
PHP
Executable File

<?php
use App\Services\ThemeService;
use App\Services\UpdateService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\File;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
$renderFrontend = function (Request $request) {
if (admin_setting('app_url') && admin_setting('safe_mode_enable', 0)) {
$requestHost = $request->getHost();
$configHost = parse_url(admin_setting('app_url'), PHP_URL_HOST);
if ($requestHost !== $configHost) {
abort(403);
}
}
$theme = admin_setting('frontend_theme', 'Xboard');
$themeService = new ThemeService();
try {
if (!$themeService->exists($theme)) {
if ($theme !== 'Xboard') {
Log::warning('Theme not found, switching to default theme', ['theme' => $theme]);
$theme = 'Xboard';
admin_setting(['frontend_theme' => $theme]);
}
$themeService->switch($theme);
}
if (!$themeService->getThemeViewPath($theme)) {
throw new Exception('主题视图文件不存在');
}
$publicThemePath = public_path('theme/' . $theme);
if (!File::exists($publicThemePath)) {
$themePath = $themeService->getThemePath($theme);
if (!$themePath || !File::copyDirectory($themePath, $publicThemePath)) {
throw new Exception('主题初始化失败');
}
Log::info('Theme initialized in public directory', ['theme' => $theme]);
}
$renderParams = [
'title' => config('app.name'),
'theme' => $theme,
'version' => app(UpdateService::class)->getCurrentVersion(),
'description' => admin_setting('app_description', 'Xboard is best'),
'logo' => admin_setting('logo'),
'theme_config' => $themeService->getConfig($theme)
];
// Supply only the public application name; environment credentials stay server-side.
$brand = json_encode((string) config('app.name'), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
$fullBrand = json_encode((string) config('app.full_name'), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
$brandScript = '<script>window.settings=window.settings||{};window.settings.title=' . $brand . ';window.settings.full_name=' . $fullBrand . ';if(typeof window.settings.description==="string"){window.settings.description=window.settings.description.replaceAll("{app_name}",window.settings.title).replaceAll("{app_full_name}",window.settings.full_name);}document.title=window.settings.title;</script>';
$html = view('theme::' . $theme . '.dashboard', $renderParams)->render();
if ($theme === 'Stellar') {
$html = \App\Support\StellarDevAssets::apply($request, $html);
}
return response(str_replace('</head>', $brandScript . '</head>', $html));
} catch (Exception $e) {
Log::error('Theme rendering failed', [
'theme' => $theme,
'error' => $e->getMessage()
]);
abort(500, '主题加载失败');
}
};
// Tutorials are independent pages, with their brand supplied from application configuration.
Route::get('/tutorials/{platform}/{client}.html', function (string $platform, string $client) {
$view = 'tutorials.' . $platform . '.' . $client;
abort_unless(view()->exists($view), 404);
return view($view, ['brand' => (string) config('app.name')]);
})->where(['platform' => '[a-z0-9-]+', 'client' => '[a-z0-9-]+']);
Route::get('/', $renderFrontend);
//TODO:: 兼容
Route::get('/' . admin_setting('secure_path', admin_setting('frontend_admin_path', hash('crc32b', config('app.key')))), function () {
return view('admin', [
'title' => config('app.name'),
'theme_sidebar' => admin_setting('frontend_theme_sidebar', 'light'),
'theme_header' => admin_setting('frontend_theme_header', 'dark'),
'theme_color' => admin_setting('frontend_theme_color', 'default'),
'background_url' => admin_setting('frontend_background_url'),
'version' => app(UpdateService::class)->getCurrentVersion(),
'logo' => admin_setting('logo'),
'secure_path' => admin_setting('secure_path', admin_setting('frontend_admin_path', hash('crc32b', config('app.key'))))
]);
});
Route::get('/' . (admin_setting('subscribe_path', 's')) . '/{token}', [\App\Http\Controllers\V1\Client\ClientController::class, 'subscribe'])
->middleware('client')
->name('client.subscribe');
// Stellar uses Vue history routes; unmatched API and asset requests remain 404s.
Route::fallback(function (Request $request) use ($renderFrontend) {
if (
admin_setting('frontend_theme', 'Xboard') !== 'Stellar' ||
$request->is('api', 'api/*', 'theme', 'theme/*', 'assets', 'assets/*') ||
pathinfo($request->path(), PATHINFO_EXTENSION) !== ''
) {
abort(404);
}
return $renderFrontend($request);
});