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'); // 文档预览和下载路由(需要认证) Route::middleware(['auth'])->group(function () { Route::get('/documents/{document}/preview', [DocumentController::class, 'preview']) ->name('documents.preview'); Route::get('/documents/{document}/download', [DocumentController::class, 'download']) ->name('documents.download'); }); // 提供 markdown 目录中 media 文件的访问(需要认证) // 路径格式: /markdown/{path}/media/{filename} // 其中 path 可以是: 2025/12/04/{uuid} 或 {uuid} Route::middleware(['auth'])->get('/markdown/{path}/media/{filename}', function ($path, $filename) { // 构建完整路径 $fullPath = $path . '/media/' . $filename; if (!Storage::disk('markdown')->exists($fullPath)) { abort(404); } $file = Storage::disk('markdown')->get($fullPath); $mimeType = Storage::disk('markdown')->mimeType($fullPath); return response($file, 200)->header('Content-Type', $mimeType); })->where('path', '.*')->where('filename', '[^/]+')->name('markdown.media');