*/ public array $data = [ 'dry_run' => false, 'sql_only' => false, 'with_id' => false, ]; public ?string $lastSqlPath = null; public ?string $lastMessage = null; public function mount(): void { $this->form->fill($this->data); } public function form(Schema $schema): Schema { return $schema ->schema([ Section::make('从 JSON 导入 questions') ->description('支持整段 JSON 数组或 NDJSON(每行一题)。左侧选文件与选项,右侧点击「一键导入」执行。') ->schema([ Forms\Components\FileUpload::make('json_file') ->label('JSON 文件') ->disk('local') ->directory('imports/questions') ->acceptedFileTypes(['application/json', 'text/plain', 'text/json']) ->maxSize(51200) ->helperText('最大约 50MB;字段含 question_code、kp_code、stem、options、answer、solution 等'), Forms\Components\Toggle::make('dry_run') ->label('仅校验(dry-run,不写库)') ->default(false), Forms\Components\Toggle::make('sql_only') ->label('仅生成 SQL(不写入本地 questions)') ->default(false), Forms\Components\Toggle::make('with_id') ->label('SQL 中含 id(仅当目标库必须对齐原主键时勾选;默认不含 id)') ->default(false), ]) ->columns(1), ]) ->statePath('data'); } public function runImport(): void { $this->lastMessage = null; $this->lastSqlPath = null; $data = $this->data; $relative = $data['json_file'] ?? null; if (! is_string($relative) || $relative === '') { Notification::make()->title('请选择 JSON 文件')->warning()->send(); return; } $fullPath = Storage::disk('local')->path($relative); if (! File::isFile($fullPath)) { Notification::make()->title('文件不存在')->body($fullPath)->danger()->send(); return; } $dryRun = (bool) ($data['dry_run'] ?? false); $sqlOnly = (bool) ($data['sql_only'] ?? false); $withId = (bool) ($data['with_id'] ?? false); $service = app(QuestionBulkImportService::class); $pipeline = $service->runImportPipeline($fullPath, $dryRun, $sqlOnly, $withId); if (! $pipeline['ok']) { Notification::make()->title('导入失败')->body($pipeline['error'] ?? '')->danger()->send(); return; } $this->lastSqlPath = $pipeline['sql_path'] ?? null; $this->lastMessage = $pipeline['message'] ?? null; if ($sqlOnly) { Notification::make()->title('SQL 已生成')->body($this->lastSqlPath ?? '')->success()->send(); return; } $body = (string) $this->lastMessage; $stats = $pipeline['stats'] ?? null; if (is_array($stats) && $stats['errors'] !== []) { $body .= "\n".implode("\n", array_slice($stats['errors'], 0, 8)); if (count($stats['errors']) > 8) { $body .= "\n… 另有 ".(count($stats['errors']) - 8).' 条错误'; } } Notification::make() ->title($dryRun ? '校验完成(dry-run)' : '导入完成') ->body($body) ->success() ->send(); } }