282 lines
8.4 KiB
PHP
282 lines
8.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api\Admin;
|
|
|
|
use App\Constants\ErrorCode;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Admin;
|
|
use App\Models\LlmProvider;
|
|
use App\Services\LogService;
|
|
use App\Traits\ApiResponse;
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class LlmProviderController extends Controller
|
|
{
|
|
use ApiResponse;
|
|
|
|
private Admin $admin;
|
|
|
|
public function __construct(
|
|
private readonly LogService $logService,
|
|
Request $request
|
|
) {
|
|
$this->admin = $request->admin;
|
|
}
|
|
|
|
/**
|
|
* 獲取 LLM 提供商列表
|
|
*/
|
|
public function index(): JsonResponse
|
|
{
|
|
try {
|
|
$providers = LlmProvider::select([
|
|
'id',
|
|
'name',
|
|
'service_name',
|
|
'api_url',
|
|
'status',
|
|
'created_at',
|
|
])->get();
|
|
|
|
return $this->success($providers);
|
|
|
|
} 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 提供商
|
|
*/
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
$validated = $request->validate([
|
|
'name' => [
|
|
'required',
|
|
'string',
|
|
'max:100',
|
|
'unique:llm_providers',
|
|
],
|
|
'service_name' => [
|
|
'required',
|
|
'string',
|
|
'max:100',
|
|
],
|
|
'api_url' => [
|
|
'required',
|
|
'string',
|
|
'url',
|
|
'max:255',
|
|
],
|
|
'api_token' => [
|
|
'required',
|
|
'string',
|
|
'max:255',
|
|
],
|
|
]);
|
|
|
|
$validated['status'] = LlmProvider::STATUS_ACTIVE;
|
|
$provider = LlmProvider::create($validated);
|
|
|
|
$this->logService->logOperation(
|
|
'admin',
|
|
$this->admin->id,
|
|
"Created LLM provider: {$provider->name}"
|
|
);
|
|
|
|
return $this->created([
|
|
'id' => $provider->id,
|
|
'name' => $provider->name,
|
|
'service_name' => $provider->service_name,
|
|
'api_url' => $provider->api_url,
|
|
'api_token' => $provider->api_token,
|
|
'created_at' => $provider->created_at->toIso8601String(),
|
|
]);
|
|
|
|
} 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 提供商
|
|
*/
|
|
public function update(Request $request, int $id): JsonResponse
|
|
{
|
|
try {
|
|
$provider = LlmProvider::findOrFail($id);
|
|
|
|
if (!$this->admin->canManageLlmProvider($provider->id)) {
|
|
return $this->error(
|
|
ErrorCode::FORBIDDEN,
|
|
'您無權管理該 LLM 提供商。'
|
|
);
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'name' => [
|
|
'required',
|
|
'string',
|
|
'max:100',
|
|
"unique:llm_providers,name,{$id}",
|
|
],
|
|
'service_name' => [
|
|
'required',
|
|
'string',
|
|
'max:100',
|
|
],
|
|
'api_url' => [
|
|
'required',
|
|
'string',
|
|
'url',
|
|
'max:255',
|
|
],
|
|
'api_token' => [
|
|
'required',
|
|
'string',
|
|
'max:255',
|
|
],
|
|
'status' => [
|
|
'required',
|
|
'string',
|
|
'in:active,inactive',
|
|
],
|
|
]);
|
|
|
|
// 如果要停用提供商,檢查是否有客戶在使用
|
|
if ($validated['status'] === LlmProvider::STATUS_INACTIVE &&
|
|
$provider->status === LlmProvider::STATUS_ACTIVE) {
|
|
if ($provider->clients()->exists()) {
|
|
return $this->error(
|
|
ErrorCode::RESOURCE_IN_USE,
|
|
'該提供商正在被客戶使用,無法停用。'
|
|
);
|
|
}
|
|
}
|
|
|
|
$provider->update($validated);
|
|
|
|
$this->logService->logOperation(
|
|
'admin',
|
|
$this->admin->id,
|
|
"Updated LLM provider: {$provider->name}"
|
|
);
|
|
|
|
return $this->success([
|
|
'id' => $provider->id,
|
|
'name' => $provider->name,
|
|
'service_name' => $provider->service_name,
|
|
'api_url' => $provider->api_url,
|
|
'api_token' => $provider->api_token,
|
|
'updated_at' => $provider->updated_at->toIso8601String(),
|
|
]);
|
|
|
|
} 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 提供商
|
|
*/
|
|
public function destroy(int $id): JsonResponse
|
|
{
|
|
try {
|
|
$provider = LlmProvider::findOrFail($id);
|
|
|
|
if (!$this->admin->canManageLlmProvider($provider->id)) {
|
|
return $this->error(
|
|
ErrorCode::FORBIDDEN,
|
|
'您無權管理該 LLM 提供商。'
|
|
);
|
|
}
|
|
|
|
// 檢查是否有客戶在使用
|
|
if ($provider->clients()->exists()) {
|
|
return $this->error(
|
|
ErrorCode::RESOURCE_IN_USE,
|
|
'該提供商正在被客戶使用,無法刪除。'
|
|
);
|
|
}
|
|
|
|
$providerName = $provider->name;
|
|
$provider->delete();
|
|
|
|
$this->logService->logOperation(
|
|
'admin',
|
|
$this->admin->id,
|
|
"Deleted LLM provider: {$providerName}"
|
|
);
|
|
|
|
return $this->success(null, 'LLM 提供商已刪除。');
|
|
|
|
} 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)
|
|
);
|
|
}
|
|
}
|
|
}
|