126 lines
4.1 KiB
PHP
126 lines
4.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace App\Http\Controllers\Admin;
|
||
|
|
|
||
|
|
use App\Enums\EntityStatus;
|
||
|
|
use App\Http\Controllers\Controller;
|
||
|
|
use App\Http\Requests\Admin\AiModelRequest;
|
||
|
|
use App\Models\AiModel;
|
||
|
|
use App\Models\Category;
|
||
|
|
use App\Models\Source;
|
||
|
|
use App\Services\ChangeLogService;
|
||
|
|
use App\Services\ModelScoringService;
|
||
|
|
use Illuminate\Http\RedirectResponse;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\View\View;
|
||
|
|
|
||
|
|
class AiModelController extends Controller
|
||
|
|
{
|
||
|
|
public function __construct(
|
||
|
|
private readonly ChangeLogService $changeLogService,
|
||
|
|
private readonly ModelScoringService $modelScoringService,
|
||
|
|
) {
|
||
|
|
}
|
||
|
|
|
||
|
|
public function index(Request $request): View
|
||
|
|
{
|
||
|
|
$items = AiModel::query()
|
||
|
|
->with(['category', 'source'])
|
||
|
|
->when($request->filled('q'), function ($query) use ($request): void {
|
||
|
|
$query->whereFullText(['name', 'summary', 'description'], (string) $request->string('q'));
|
||
|
|
})
|
||
|
|
->latest('updated_at')
|
||
|
|
->paginate(20)
|
||
|
|
->withQueryString();
|
||
|
|
|
||
|
|
return view('admin.models.index', [
|
||
|
|
'items' => $items,
|
||
|
|
'filters' => $request->only(['q']),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function create(): View
|
||
|
|
{
|
||
|
|
return view('admin.models.form', [
|
||
|
|
'item' => new AiModel(),
|
||
|
|
'categories' => Category::query()->where('type', 'model')->orderBy('name')->get(),
|
||
|
|
'sources' => Source::query()->where('is_whitelisted', true)->orderBy('name')->get(),
|
||
|
|
'statusOptions' => EntityStatus::cases(),
|
||
|
|
'submitRoute' => route('admin.models.store'),
|
||
|
|
'method' => 'POST',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function store(AiModelRequest $request): RedirectResponse
|
||
|
|
{
|
||
|
|
$item = new AiModel($this->normalizePayload($request->validated()));
|
||
|
|
$this->modelScoringService->apply($item);
|
||
|
|
$item->save();
|
||
|
|
|
||
|
|
$this->changeLogService->log('created', $item);
|
||
|
|
|
||
|
|
return redirect()->route('admin.models.edit', $item)->with('status', '模型已创建');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function edit(AiModel $model): View
|
||
|
|
{
|
||
|
|
return view('admin.models.form', [
|
||
|
|
'item' => $model,
|
||
|
|
'categories' => Category::query()->where('type', 'model')->orderBy('name')->get(),
|
||
|
|
'sources' => Source::query()->where('is_whitelisted', true)->orderBy('name')->get(),
|
||
|
|
'statusOptions' => EntityStatus::cases(),
|
||
|
|
'submitRoute' => route('admin.models.update', $model),
|
||
|
|
'method' => 'PUT',
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function update(AiModelRequest $request, AiModel $model): RedirectResponse
|
||
|
|
{
|
||
|
|
$before = $model->getAttributes();
|
||
|
|
$model->fill($this->normalizePayload($request->validated()));
|
||
|
|
$this->modelScoringService->apply($model);
|
||
|
|
$model->save();
|
||
|
|
|
||
|
|
$this->changeLogService->log('updated', $model, $before);
|
||
|
|
|
||
|
|
return redirect()->route('admin.models.edit', $model)->with('status', '模型已更新');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function publish(AiModel $model): RedirectResponse
|
||
|
|
{
|
||
|
|
$before = $model->getAttributes();
|
||
|
|
$model->status = EntityStatus::Published;
|
||
|
|
$model->published_at = $model->published_at ?? now();
|
||
|
|
$model->save();
|
||
|
|
|
||
|
|
$this->changeLogService->log('published', $model, $before);
|
||
|
|
|
||
|
|
return redirect()->route('admin.models.edit', $model)->with('status', '模型已发布');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function markStale(AiModel $model): RedirectResponse
|
||
|
|
{
|
||
|
|
$before = $model->getAttributes();
|
||
|
|
$model->is_stale = true;
|
||
|
|
$model->status = EntityStatus::Stale;
|
||
|
|
$model->save();
|
||
|
|
|
||
|
|
$this->changeLogService->log('marked_stale', $model, $before);
|
||
|
|
|
||
|
|
return redirect()->route('admin.models.edit', $model)->with('status', '模型已标记失效');
|
||
|
|
}
|
||
|
|
|
||
|
|
private function normalizePayload(array $data): array
|
||
|
|
{
|
||
|
|
$data['is_stale'] = (bool) ($data['is_stale'] ?? false);
|
||
|
|
|
||
|
|
if (($data['status'] ?? null) === EntityStatus::Published->value && empty($data['published_at'])) {
|
||
|
|
$data['published_at'] = now();
|
||
|
|
}
|
||
|
|
|
||
|
|
return $data;
|
||
|
|
}
|
||
|
|
}
|