input('per_page', 15); $perPage = min(max($perPage, 1), 100); // 限制每页数量在 1-100 之间 $providers = LlmProvider::orderBy('created_at', 'desc') ->paginate($perPage); return response()->json([ 'data' => $providers->items(), 'meta' => [ 'current_page' => $providers->currentPage(), 'per_page' => $providers->perPage(), 'total' => $providers->total(), 'total_pages' => $providers->lastPage(), ], ]); } catch (\Exception $e) { Log::error('Error fetching LLM providers', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'error' => 'server_error', 'message' => '服务器内部错误。', ], 500); } } /** * Create new LLM provider * * @param Request $request * @return JsonResponse * * Request body: * { * "name": "string", * "service_name": "string", * "api_url": "string", * "api_token": "string" * } * * Success response (201): * { * "id": 1001, * "name": "OpenAI", * "service_name": "openai", * "api_url": "https://api.openai.com/v1/chat/completions", * "created_at": "2023-10-01T14:00:00Z" * } * * Error response (422): * { * "error": "validation_error", * "message": "请求参数验证失败。", * "errors": { * "name": ["提供商名称已存在。"], * "api_url": ["API URL 格式不正确。"] * } * } */ public function store(Request $request): JsonResponse { try { $validated = $request->validate([ 'name' => [ 'required', 'string', 'max:100', 'unique:llm_providers', 'regex:/^[\w\-\s]+$/u', // 只允许字母、数字、下划线、横线和空格 ], 'service_name' => [ 'required', 'string', 'max:100', 'regex:/^[\w\-]+$/u', // 只允许字母、数字、下划线和横线 ], 'api_url' => [ 'required', 'string', 'max:255', 'url', 'starts_with:https', // 强制使用 HTTPS ], 'api_token' => 'required|string|max:255', ], [ 'name.regex' => '提供商名称只能包含字母、数字、下划线、横线和空��。', 'service_name.regex' => '服务名称只能包含字母、数字、下划线和横线。', 'api_url.starts_with' => 'API URL 必须使用 HTTPS 协议。', ]); $provider = LlmProvider::create($validated); $this->logService->logOperation( 'admin', $request->admin->id, "Created LLM provider: {$provider->name}" ); return response()->json($provider, 201); } catch (ValidationException $e) { return response()->json([ 'error' => 'validation_error', 'message' => '请求参数验证失败。', 'errors' => $e->errors(), ], 422); } catch (\Exception $e) { Log::error('Error creating LLM provider', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'error' => 'server_error', 'message' => '服务器内部错误。', ], 500); } } /** * Update LLM provider * * @param Request $request * @param int $id * @return JsonResponse * * Request body: * { * "name": "string", * "service_name": "string", * "api_url": "string", * "api_token": "string" * } * * Success response: * { * "id": 1001, * "name": "OpenAI Updated", * "service_name": "openai", * "api_url": "https://api.openai.com/v1/chat/completions", * "updated_at": "2023-10-02T14:00:00Z" * } */ public function update(Request $request, int $id): JsonResponse { try { $provider = LlmProvider::findOrFail($id); $validated = $request->validate([ 'name' => [ 'required', 'string', 'max:100', "unique:llm_providers,name,{$id}", 'regex:/^[\w\-\s]+$/u', // 只允许字母、数字、下划线、横线和空格 ], 'service_name' => [ 'required', 'string', 'max:100', 'regex:/^[\w\-]+$/u', // 只允许字母、数字、下划线和横线 ], 'api_url' => [ 'required', 'string', 'max:255', 'url', 'starts_with:https', // 强制使用 HTTPS ], 'api_token' => 'required|string|max:255', ], [ 'name.regex' => '提供商名称只能包含字母、数字、下划线、横线和空格。', 'service_name.regex' => '服务名称只能包含字母、数字、下划线和横线。', 'api_url.starts_with' => 'API URL 必须使用 HTTPS 协议。', ]); $provider->update($validated); $this->logService->logOperation( 'admin', $request->admin->id, "Updated LLM provider: {$provider->name}" ); return response()->json($provider); } catch (ValidationException $e) { return response()->json([ 'error' => 'validation_error', 'message' => '请求参数验证失败。', 'errors' => $e->errors(), ], 422); } catch (ModelNotFoundException $e) { return response()->json([ 'error' => 'not_found', 'message' => 'LLM 提供商不存在。', ], 404); } catch (\Exception $e) { Log::error('Error updating LLM provider', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'error' => 'server_error', 'message' => '服务器内部错误。', ], 500); } } /** * Delete LLM provider * * @param Request $request * @param int $id * @return JsonResponse * * Success response: * { * "message": "提供商已删除。" * } */ public function destroy(Request $request, int $id): JsonResponse { try { $provider = LlmProvider::findOrFail($id); // 检查是否有客户正在使用该提供商 if ($provider->clients()->exists()) { return response()->json([ 'error' => 'provider_in_use', 'message' => '该提供商正在被客户使用,无法删除。', ], 422); } $providerName = $provider->name; $provider->delete(); $this->logService->logOperation( 'admin', $request->admin->id, "Deleted LLM provider: {$providerName}" ); return response()->json([ 'message' => '提供商已删除。', ]); } catch (ModelNotFoundException $e) { return response()->json([ 'error' => 'not_found', 'message' => 'LLM 提供商不存在。', ], 404); } catch (\Exception $e) { Log::error('Error deleting LLM provider', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), 'provider_id' => $id, ]); return response()->json([ 'error' => 'server_error', 'message' => '服务器内部错误。', ], 500); } } }