input('per_page', 15); $perPage = min(max($perPage, 1), 100); $search = $request->input('search'); $status = $request->input('status'); $query = LlmProvider::query()->orderBy('created_at', 'desc'); if ($search) { $query->where(function ($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('service_name', 'like', "%{$search}%"); }); } if ($status && in_array($status, ['active', 'inactive'])) { $query->where('status', $status); } $providers = $query->paginate($perPage); return $this->paginate( $providers->items(), [ '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 $this->error( ErrorCode::SERVER_ERROR, ErrorCode::getMessage(ErrorCode::SERVER_ERROR) ); } } /** * 创建 LLM 提供商 * * @param Request $request * @return JsonResponse */ 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', ], 'api_token' => 'required|string|max:255', ], [ 'name.regex' => '提供商名称只能包含字母、数字、下划线、横线和空格。', 'service_name.regex' => '服务名称只能包含字母、数字、下划线和横线。', 'api_url.starts_with' => 'API URL 必须使用 HTTPS 协议。', ]); $validated['status'] = 'active'; $provider = LlmProvider::create($validated); $this->logService->logOperation( 'admin', $request->admin->id, "Created LLM provider: {$provider->name}" ); return $this->created($provider); } catch (ValidationException $e) { return $this->error( ErrorCode::VALIDATION_ERROR, ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR), $e->errors() ); } catch (\Exception $e) { Log::error('Error creating LLM provider', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), 'request_data' => $request->except(['api_token']), ]); return $this->error( ErrorCode::SERVER_ERROR, ErrorCode::getMessage(ErrorCode::SERVER_ERROR) ); } } /** * 更新 LLM 提供商 * * @param Request $request * @param int $id * @return JsonResponse */ 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', ], 'api_token' => 'required|string|max:255', 'status' => [ 'required', 'string', 'in:active,inactive', ], ], [ 'name.regex' => '提供商名称只能包含字母、数字、下划线、横线和空格。', 'service_name.regex' => '服务名称只能包含字母、数字、下划线和横线。', 'api_url.starts_with' => 'API URL 必须使用 HTTPS 协议。', 'status.in' => '状态只能是 active 或 inactive。', ]); // 如果状态改为 inactive,检查是否有客户正在使用 if ($validated['status'] === 'inactive' && $provider->status === 'active') { if ($provider->clients()->exists()) { return $this->error( ErrorCode::RESOURCE_IN_USE, '该提供商正在被客户使用,无法停用。' ); } } $provider->update($validated); $this->logService->logOperation( 'admin', $request->admin->id, "Updated LLM provider: {$provider->name}" ); return $this->success($provider); } catch (ValidationException $e) { return $this->error( ErrorCode::VALIDATION_ERROR, ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR), $e->errors() ); } catch (ModelNotFoundException $e) { return $this->error( ErrorCode::RESOURCE_NOT_FOUND, ErrorCode::getMessage(ErrorCode::RESOURCE_NOT_FOUND) ); } catch (\Exception $e) { Log::error('Error updating LLM provider', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), 'provider_id' => $id, 'request_data' => $request->except(['api_token']), ]); return $this->error( ErrorCode::SERVER_ERROR, ErrorCode::getMessage(ErrorCode::SERVER_ERROR) ); } } /** * 删除 LLM 提供商 * * @param Request $request * @param int $id * @return JsonResponse */ public function destroy(Request $request, int $id): JsonResponse { try { $provider = LlmProvider::findOrFail($id); // 检查是否有客户正在使用 if ($provider->clients()->exists()) { return $this->error( ErrorCode::RESOURCE_IN_USE, '该提供商正在被客户使用,无法删除。' ); } $providerName = $provider->name; $provider->delete(); $this->logService->logOperation( 'admin', $request->admin->id, "Deleted LLM provider: {$providerName}" ); return $this->success(null, '提供商已删除。'); } catch (ModelNotFoundException $e) { return $this->error( ErrorCode::RESOURCE_NOT_FOUND, ErrorCode::getMessage(ErrorCode::RESOURCE_NOT_FOUND) ); } catch (\Exception $e) { Log::error('Error deleting LLM provider', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), 'provider_id' => $id, ]); return $this->error( ErrorCode::SERVER_ERROR, ErrorCode::getMessage(ErrorCode::SERVER_ERROR) ); } } }