222 lines
7.2 KiB
PHP
222 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Pages;
|
|
|
|
use App\Models\Document;
|
|
use App\Models\KnowledgeBase;
|
|
use App\Models\Station;
|
|
use App\Services\DocumentSearchService;
|
|
use App\Services\DocumentService;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\TextInput;
|
|
use Filament\Forms\Concerns\InteractsWithForms;
|
|
use Filament\Forms\Contracts\HasForms;
|
|
use Filament\Forms\Form;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Tables\Actions\Action;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Concerns\InteractsWithTable;
|
|
use Filament\Tables\Contracts\HasTable;
|
|
use Filament\Tables\Table;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class SearchPage extends Page implements HasForms, HasTable
|
|
{
|
|
use InteractsWithForms;
|
|
use InteractsWithTable;
|
|
|
|
protected static ?string $navigationIcon = 'heroicon-o-magnifying-glass';
|
|
protected static string $view = 'filament.pages.search-page';
|
|
protected static ?string $navigationLabel = '搜索文档';
|
|
protected static ?string $title = '搜索文档';
|
|
protected static ?int $navigationSort = 2;
|
|
|
|
public ?string $searchQuery = null;
|
|
public ?array $stationIds = [];
|
|
public ?array $knowledgeBaseIds = [];
|
|
public bool $hasSearched = false;
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->form->fill([
|
|
'searchQuery' => '',
|
|
'stationIds' => [],
|
|
'knowledgeBaseIds' => [],
|
|
]);
|
|
}
|
|
|
|
public function form(Form $form): Form
|
|
{
|
|
return $form
|
|
->schema([
|
|
TextInput::make('searchQuery')
|
|
->label('搜索关键词')
|
|
->placeholder('请输入搜索关键词...')
|
|
->required()
|
|
->maxLength(255),
|
|
|
|
Select::make('stationIds')
|
|
->label('线站')
|
|
->placeholder('全部线站')
|
|
->options(Station::pluck('name', 'id'))
|
|
->multiple()
|
|
->searchable()
|
|
->native(false),
|
|
|
|
Select::make('knowledgeBaseIds')
|
|
->label('知识库')
|
|
->placeholder('全部知识库')
|
|
->options(KnowledgeBase::where('status', 'active')->pluck('name', 'id'))
|
|
->multiple()
|
|
->searchable()
|
|
->native(false),
|
|
])
|
|
->columns(3);
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->query($this->getTableQuery())
|
|
->columns([
|
|
TextColumn::make('title')
|
|
->label('文档标题')
|
|
->searchable()
|
|
->sortable()
|
|
->limit(50),
|
|
|
|
TextColumn::make('knowledgeBase.name')
|
|
->label('所属知识库')
|
|
->sortable(),
|
|
|
|
TextColumn::make('uploader.name')
|
|
->label('上传者')
|
|
->sortable(),
|
|
|
|
TextColumn::make('created_at')
|
|
->label('上传时间')
|
|
->dateTime('Y-m-d H:i')
|
|
->sortable(),
|
|
])
|
|
->actions([
|
|
Action::make('preview')
|
|
->label('预览')
|
|
->icon('heroicon-o-eye')
|
|
->color('info')
|
|
->modalHeading(fn (Document $record) => $record->title)
|
|
->modalContent(fn (Document $record) => view('filament.pages.document-preview-modal', [
|
|
'document' => $record,
|
|
]))
|
|
->modalWidth('7xl')
|
|
->modalSubmitAction(false)
|
|
->modalCancelActionLabel('关闭')
|
|
->visible(fn (Document $record) => $record->conversion_status === 'completed'),
|
|
|
|
Action::make('download')
|
|
->label('下载')
|
|
->icon('heroicon-o-arrow-down-tray')
|
|
->action(function (Document $record) {
|
|
try {
|
|
$documentService = app(DocumentService::class);
|
|
$user = Auth::user();
|
|
$documentService->logDownload($record, $user);
|
|
return $documentService->downloadDocument($record, $user);
|
|
} catch (\Exception $e) {
|
|
Notification::make()
|
|
->title('下载失败')
|
|
->body($e->getMessage())
|
|
->danger()
|
|
->send();
|
|
}
|
|
}),
|
|
])
|
|
->paginated([10, 25, 50, 100])
|
|
->defaultPaginationPageOption(25)
|
|
->emptyStateHeading('暂无搜索结果')
|
|
->emptyStateDescription('请输入搜索关键词并点击搜索按钮')
|
|
->emptyStateIcon('heroicon-o-magnifying-glass');
|
|
}
|
|
|
|
protected function getTableQuery(): Builder
|
|
{
|
|
if (!$this->hasSearched || empty($this->searchQuery)) {
|
|
return Document::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
$searchService = app(DocumentSearchService::class);
|
|
|
|
$filters = [];
|
|
if (!empty($this->stationIds)) {
|
|
$filters['station_ids'] = $this->stationIds;
|
|
}
|
|
if (!empty($this->knowledgeBaseIds)) {
|
|
$filters['knowledge_base_ids'] = $this->knowledgeBaseIds;
|
|
}
|
|
|
|
$accessibleStationIds = Auth::user()->getAccessibleStationIds();
|
|
$results = $searchService->search($this->searchQuery, $accessibleStationIds, $filters);
|
|
$documentIds = $results->pluck('id')->toArray();
|
|
|
|
if (empty($documentIds)) {
|
|
return Document::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
return Document::query()
|
|
->whereIn('id', $documentIds)
|
|
->with(['knowledgeBase', 'uploader']);
|
|
}
|
|
|
|
public function search(): void
|
|
{
|
|
$data = $this->form->getState();
|
|
|
|
if (empty($data['searchQuery'])) {
|
|
Notification::make()
|
|
->title('请输入搜索关键词')
|
|
->warning()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$this->searchQuery = $data['searchQuery'];
|
|
$this->stationIds = $data['stationIds'] ?? [];
|
|
$this->knowledgeBaseIds = $data['knowledgeBaseIds'] ?? [];
|
|
$this->hasSearched = true;
|
|
|
|
$this->resetTable();
|
|
|
|
Notification::make()
|
|
->title('搜索完成')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
public function clearSearch(): void
|
|
{
|
|
$this->form->fill([
|
|
'searchQuery' => '',
|
|
'stationIds' => [],
|
|
'knowledgeBaseIds' => [],
|
|
]);
|
|
|
|
$this->searchQuery = null;
|
|
$this->stationIds = [];
|
|
$this->knowledgeBaseIds = [];
|
|
$this->hasSearched = false;
|
|
|
|
$this->resetTable();
|
|
|
|
Notification::make()
|
|
->title('已清空搜索')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [];
|
|
}
|
|
}
|