QuestionReview.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. namespace App\Filament\Pages;
  3. use Filament\Forms;
  4. use Filament\Pages\Page;
  5. use Filament\Actions\Action;
  6. use Filament\Schemas\Schema;
  7. use Filament\Notifications\Notification;
  8. class QuestionReview extends Page implements Forms\Contracts\HasForms
  9. {
  10. use Forms\Concerns\InteractsWithForms;
  11. protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-clipboard-document-check';
  12. protected static string|\UnitEnum|null $navigationGroup = '题库管理';
  13. protected static ?string $title = '题目校验';
  14. protected static ?int $navigationSort = 4;
  15. protected string $view = 'filament.pages.question-review';
  16. public string $book = '';
  17. public int $page = 1;
  18. public array $mineru = [];
  19. public array $builder = [];
  20. public string $message = '';
  21. public bool $saving = false;
  22. public string $builderJson = '';
  23. public array $bookOptions = [];
  24. public array $pageOptions = [];
  25. public ?string $pagePngBase64 = null;
  26. public bool $showOverlay = true;
  27. public array $paths = [];
  28. public function mount(): void
  29. {
  30. // 默认值可在 .env 中配置
  31. $this->book = config('question_bank.default_book', '');
  32. $this->page = 1;
  33. // 预填可选书名(扫描 /data/mineru_raw)
  34. $root = base_path('../data/mineru_raw');
  35. $dirs = is_dir($root) ? scandir($root) : [];
  36. $opts = [];
  37. foreach ($dirs as $d) {
  38. if ($d === '.' || $d === '..') {
  39. continue;
  40. }
  41. if (is_dir($root . '/' . $d)) {
  42. $opts[] = $d;
  43. }
  44. }
  45. $this->bookOptions = $opts;
  46. if ($this->book) {
  47. $this->refreshPageOptions($this->book);
  48. }
  49. }
  50. public function form(Schema $form): Schema
  51. {
  52. return $form
  53. ->components([
  54. Forms\Components\Select::make('book')
  55. ->label('书名/目录名')
  56. ->options(array_combine($this->bookOptions, $this->bookOptions))
  57. ->native(false)
  58. ->searchable()
  59. ->placeholder('选择书名目录')
  60. ->reactive()
  61. ->afterStateUpdated(fn($state) => $this->onBookChange($state))
  62. ->required(),
  63. Forms\Components\Select::make('page')
  64. ->label('页码')
  65. ->options(fn() => array_combine(
  66. array_map('strval', $this->pageOptions),
  67. array_map(fn($p) => "第{$p}页", $this->pageOptions)
  68. ))
  69. ->native(false)
  70. ->searchable()
  71. ->placeholder('选择页码')
  72. ->reactive()
  73. ->afterStateUpdated(fn($state) => $this->onPageChange($state))
  74. ->required(),
  75. ]);
  76. }
  77. protected function getHeaderActions(): array
  78. {
  79. return [
  80. Action::make('load')
  81. ->label('加载')
  82. ->color('primary')
  83. ->action('loadPage'),
  84. Action::make('save')
  85. ->label('保存到草稿')
  86. ->color('success')
  87. ->disabled(fn() => empty($this->builder))
  88. ->action('saveDraft'),
  89. Action::make('toggleOverlay')
  90. ->label(fn() => $this->showOverlay ? '隐藏标框' : '显示标框')
  91. ->color('gray')
  92. ->action('toggleOverlay'),
  93. ];
  94. }
  95. protected function refreshPageOptions(string $book): void
  96. {
  97. $dir = base_path("../data/mineru_raw/{$book}/pages");
  98. $pages = [];
  99. if (is_dir($dir)) {
  100. foreach (glob($dir . '/page_*.json') as $file) {
  101. if (preg_match('/page_(\\d+)\\.json$/', $file, $m)) {
  102. $pages[] = (int)$m[1];
  103. }
  104. }
  105. }
  106. sort($pages);
  107. $this->pageOptions = $pages;
  108. if (!empty($pages)) {
  109. $this->page = $pages[0];
  110. }
  111. }
  112. public function onBookChange($book): void
  113. {
  114. $this->book = (string)$book;
  115. $this->refreshPageOptions($this->book);
  116. if ($this->book && $this->page) {
  117. $this->loadPage();
  118. }
  119. }
  120. public function onPageChange($page): void
  121. {
  122. if ($page === null || $page === '') {
  123. return;
  124. }
  125. $this->page = (int)$page;
  126. if ($this->book) {
  127. $this->loadPage();
  128. }
  129. }
  130. public function toggleOverlay(): void
  131. {
  132. $this->showOverlay = !$this->showOverlay;
  133. }
  134. public function loadPage(): void
  135. {
  136. $this->mineru = [];
  137. $this->builder = [];
  138. $this->builderJson = '';
  139. $this->pagePngBase64 = null;
  140. $this->paths = [];
  141. $this->message = '题目校验已迁移到“题目审核工作台”,请使用新流程。';
  142. }
  143. public function saveDraft(): void
  144. {
  145. $this->message = '题目校验已迁移到“题目审核工作台”,该入口不再写入数据。';
  146. Notification::make()->title('已迁移')->body($this->message)->warning()->send();
  147. }
  148. public function saveQuestion(int $index): void
  149. {
  150. $this->message = '题目校验已迁移到“题目审核工作台”,该入口不再写入数据。';
  151. Notification::make()->title('已迁移')->body($this->message)->warning()->send();
  152. }
  153. }