getPdo(); $services['database'] = 'connected'; } catch (Exception $e) { $services['database'] = 'disconnected'; $allHealthy = false; } try { // 检查Redis连接 if (config('cache.default') === 'redis') { Cache::store('redis')->put('health_check', 'ok', 10); Cache::store('redis')->forget('health_check'); $services['redis'] = 'connected'; } else { $services['redis'] = 'not_configured'; } } catch (Exception $e) { $services['redis'] = 'disconnected'; $allHealthy = false; } try { // 检查Meilisearch连接 if (config('scout.driver') === 'meilisearch') { $client = new \GuzzleHttp\Client(); $response = $client->get(config('scout.meilisearch.host') . '/health', [ 'timeout' => 5, 'headers' => [ 'Authorization' => 'Bearer ' . config('scout.meilisearch.key') ] ]); if ($response->getStatusCode() === 200) { $services['meilisearch'] = 'connected'; } else { $services['meilisearch'] = 'unhealthy'; $allHealthy = false; } } else { $services['meilisearch'] = 'not_configured'; } } catch (Exception $e) { $services['meilisearch'] = 'disconnected'; $allHealthy = false; } // 检查存储目录是否可写 try { $testFile = storage_path('logs/health_check_test.tmp'); file_put_contents($testFile, 'test'); unlink($testFile); $services['storage'] = 'writable'; } catch (Exception $e) { $services['storage'] = 'not_writable'; $allHealthy = false; } $status = $allHealthy ? 'ok' : 'degraded'; $httpCode = $allHealthy ? 200 : 503; return response()->json([ 'status' => $status, 'timestamp' => now()->toISOString(), 'services' => $services, 'version' => config('app.version', '1.0.0') ], $httpCode); })->name('health.check'); // 指引步骤渲染(供终端 webview 打开,公开访问) Route::get('/guides/pages/{page}', function (\App\Models\GuidePage $page) { return view('guides.page', ['page' => $page]); })->name('guides.pages.show'); // 文档预览和下载路由(需要认证) Route::middleware(['auth'])->group(function () { Route::get('/documents/{document}/preview', [DocumentController::class, 'preview']) ->name('documents.preview'); Route::get('/documents/{document}/preview-pdf', [DocumentController::class, 'previewPdf']) ->name('documents.preview-pdf'); Route::get('/documents/{document}/download', [DocumentController::class, 'download']) ->name('documents.download'); }); // 提供 markdown 目录中 media 文件的访问(需要认证) // 路径格式: /markdown-media/{path} Route::middleware(['auth'])->get('/markdown-media/{path}', function ($path) { $path = trim((string) $path, '/'); if ($path === '' || str_contains($path, '../')) { abort(404); } if (!Storage::disk('markdown')->exists($path)) { abort(404); } $mimeType = Storage::disk('markdown')->mimeType($path); if (!is_string($mimeType) || !str_starts_with($mimeType, 'image/')) { abort(404); } $file = Storage::disk('markdown')->get($path); return response($file, 200)->header('Content-Type', $mimeType); })->where('path', '.*')->name('markdown.media');