| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- <?php
- namespace App\Filament\Pages;
- use App\Models\SourcePaper;
- use App\Models\Textbook;
- use Filament\Pages\Page;
- use Illuminate\Support\Arr;
- class SourcePaperEnrichment extends Page
- {
- protected static bool $shouldRegisterNavigation = false;
- protected static ?string $navigationLabel = '卷子信息补录';
- protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
- protected static string|\UnitEnum|null $navigationGroup = '卷子导入流程';
- protected static ?int $navigationSort = 99;
- protected string $view = 'filament.pages.source-paper-enrichment';
- public string $search = '';
- public ?string $gradeFilter = null;
- public ?string $termFilter = null;
- public bool $dense = false;
- public ?int $selectedPaperId = null;
- public array $selectedIds = [];
- public array $form = [
- 'edition' => null,
- 'grade' => null,
- 'term' => null,
- 'chapter' => null,
- 'source_type' => null,
- 'source_year' => null,
- 'textbook_id' => null,
- 'textbook_series' => null,
- 'source_name' => null,
- 'source_page' => null,
- 'tags' => '',
- ];
- public array $batch = [
- 'edition' => null,
- 'grade' => null,
- 'term' => null,
- 'chapter' => null,
- 'source_type' => null,
- 'source_year' => null,
- 'textbook_id' => null,
- 'textbook_series' => null,
- 'source_name' => null,
- 'source_page' => null,
- 'tags' => '',
- ];
- public function mount(): void
- {
- $first = $this->papers()->first();
- if ($first) {
- $this->selectPaper($first->id);
- }
- }
- public function papers()
- {
- $query = SourcePaper::query()->with(['textbook']);
- if ($this->search !== '') {
- $query->where(function ($q) {
- $q->where('title', 'like', '%' . $this->search . '%')
- ->orWhere('full_title', 'like', '%' . $this->search . '%')
- ->orWhere('paper_code', 'like', '%' . $this->search . '%');
- });
- }
- if ($this->gradeFilter) {
- $query->where('grade', $this->gradeFilter);
- }
- if ($this->termFilter) {
- $query->where('term', $this->termFilter);
- }
- return $query->orderByDesc('id')->limit(80)->get();
- }
- public function selectedPaper(): ?SourcePaper
- {
- if (!$this->selectedPaperId) {
- return null;
- }
- return SourcePaper::query()->with('textbook')->find($this->selectedPaperId);
- }
- public function selectAllVisible(): void
- {
- $this->selectedIds = $this->papers()->pluck('id')->toArray();
- }
- public function clearSelection(): void
- {
- $this->selectedIds = [];
- }
- public function selectPaper(int $paperId): void
- {
- $paper = SourcePaper::query()->find($paperId);
- if (!$paper) {
- return;
- }
- $this->selectedPaperId = $paperId;
- $meta = $paper->meta ?? [];
- $this->form = [
- 'edition' => $paper->edition,
- 'grade' => $paper->grade,
- 'term' => $paper->term,
- 'chapter' => $paper->chapter,
- 'source_type' => $paper->source_type,
- 'source_year' => $paper->source_year,
- 'textbook_id' => $paper->textbook_id,
- 'textbook_series' => $paper->textbook_series,
- 'source_name' => Arr::get($meta, 'source_name'),
- 'source_page' => Arr::get($meta, 'source_page'),
- 'tags' => implode(',', Arr::get($meta, 'tags', [])),
- ];
- }
- public function savePaper(): void
- {
- $paper = $this->selectedPaper();
- if (!$paper) {
- return;
- }
- $meta = $paper->meta ?? [];
- $meta['source_name'] = $this->form['source_name'] ?? null;
- $meta['source_page'] = $this->form['source_page'] ?? null;
- $meta['tags'] = $this->explodeTags($this->form['tags'] ?? '');
- $paper->update([
- 'edition' => $this->form['edition'] ?? null,
- 'grade' => $this->form['grade'] ?? null,
- 'term' => $this->form['term'] ?? null,
- 'chapter' => $this->form['chapter'] ?? null,
- 'source_type' => $this->form['source_type'] ?? null,
- 'source_year' => $this->form['source_year'] ?? null,
- 'textbook_id' => $this->form['textbook_id'] ?? null,
- 'textbook_series' => $this->form['textbook_series'] ?? null,
- 'meta' => $meta,
- ]);
- }
- public function applyBatch(): void
- {
- if (empty($this->selectedIds)) {
- return;
- }
- $updates = array_filter([
- 'edition' => $this->batch['edition'] ?? null,
- 'grade' => $this->batch['grade'] ?? null,
- 'term' => $this->batch['term'] ?? null,
- 'chapter' => $this->batch['chapter'] ?? null,
- 'source_type' => $this->batch['source_type'] ?? null,
- 'source_year' => $this->batch['source_year'] ?? null,
- 'textbook_id' => $this->batch['textbook_id'] ?? null,
- 'textbook_series' => $this->batch['textbook_series'] ?? null,
- ], fn ($value) => $value !== null && $value !== '');
- foreach (SourcePaper::query()->whereIn('id', $this->selectedIds)->get() as $paper) {
- $meta = $paper->meta ?? [];
- if (!empty($this->batch['source_name'])) {
- $meta['source_name'] = $this->batch['source_name'];
- }
- if (!empty($this->batch['source_page'])) {
- $meta['source_page'] = $this->batch['source_page'];
- }
- if (!empty($this->batch['tags'])) {
- $meta['tags'] = $this->explodeTags($this->batch['tags']);
- }
- $paper->update(array_merge($updates, ['meta' => $meta]));
- }
- }
- public function autoInfer(): void
- {
- $paper = $this->selectedPaper();
- if (!$paper) {
- return;
- }
- $title = (string) ($paper->title ?? $paper->full_title ?? '');
- $raw = (string) ($paper->raw_markdown ?? '');
- $context = $title . ' ' . $raw;
- $this->form['term'] = $this->inferTerm($context) ?? $this->form['term'];
- $this->form['grade'] = $this->inferGrade($context) ?? $this->form['grade'];
- $this->form['chapter'] = $this->inferChapter($context) ?? $this->form['chapter'];
- }
- public function autoInferSelected(): void
- {
- if (empty($this->selectedIds)) {
- return;
- }
- foreach (SourcePaper::query()->whereIn('id', $this->selectedIds)->get() as $paper) {
- $context = (string) ($paper->title ?? $paper->full_title ?? '') . ' ' . (string) ($paper->raw_markdown ?? '');
- $updates = array_filter([
- 'term' => $this->inferTerm($context),
- 'grade' => $this->inferGrade($context),
- 'chapter' => $this->inferChapter($context),
- ], fn ($value) => $value !== null && $value !== '');
- if (!empty($updates)) {
- $paper->update($updates);
- }
- }
- }
- public function textbookOptions(): array
- {
- return Textbook::query()->orderBy('id')->pluck('official_title', 'id')->toArray();
- }
- public function gradeOptions(): array
- {
- return collect(range(1, 12))->mapWithKeys(fn ($grade) => [$grade => $grade . '年级'])->toArray();
- }
- public function termOptions(): array
- {
- return [
- '上册' => '上册',
- '下册' => '下册',
- '上学期' => '上学期',
- '下学期' => '下学期',
- ];
- }
- public function sourceTypeOptions(): array
- {
- return [
- '期中' => '期中卷',
- '期末' => '期末卷',
- '单元卷' => '单元卷',
- '专项卷' => '专项卷',
- '教材' => '教材',
- '其他' => '其他',
- ];
- }
- private function inferTerm(string $context): ?string
- {
- if (str_contains($context, '上册') || str_contains($context, '上学期')) {
- return '上册';
- }
- if (str_contains($context, '下册') || str_contains($context, '下学期')) {
- return '下册';
- }
- return null;
- }
- private function inferGrade(string $context): ?string
- {
- foreach (['七年级' => '7', '八年级' => '8', '九年级' => '9', '高一' => '10', '高二' => '11', '高三' => '12'] as $label => $value) {
- if (str_contains($context, $label)) {
- return $value;
- }
- }
- return null;
- }
- private function inferChapter(string $context): ?string
- {
- if (preg_match('/第[一二三四五六七八九十]+章[^\\n]*/u', $context, $match)) {
- return $match[0];
- }
- return null;
- }
- private function explodeTags(string $tags): array
- {
- return array_values(array_filter(array_map('trim', explode(',', $tags))));
- }
- }
|