option('table'); if (! Schema::hasTable($table)) { $this->error("表 {$table} 不存在,请先创建或指定正确表名"); return 1; } $kp = $this->option('kp'); $limit = (int) $this->option('limit'); $dryRun = $this->option('dry-run'); if ($kp) { $questions = DB::table($table) ->where('kp_code', $kp) ->limit($limit) ->get(); } else { $kps = $qcService->getKpsWithFewQuestions( $this->option('textbook') ? (int) $this->option('textbook') : null, (int) $this->option('semester'), 20 ); if (empty($kps)) { $this->warn('未找到题少的 KP,请检查 textbooks、textbook_chapter_knowledge_relation 数据'); return 0; } $this->info('按下学期题少 KP 筛选,前 5 个:'); foreach (array_slice($kps, 0, 5) as $r) { $this->line(" {$r['kp_code']}: {$r['question_count']} 题"); } $kpCodes = array_column($kps, 'kp_code'); $questions = DB::table($table) ->whereIn('kp_code', $kpCodes) ->limit($limit) ->get(); } $total = $questions->count(); $this->info("待质检题目数: {$total}"); if ($dryRun) { $this->info('[dry-run] 不执行质检'); return 0; } $passed = 0; $failed = 0; $bar = $this->output->createProgressBar($total); $bar->start(); foreach ($questions as $q) { $row = (array) $q; $mapped = $this->mapQuestionRow($row); $result = $qcService->runAutoCheck( $mapped, $row['id'] ?? null, null ); if ($result['passed']) { $passed++; } else { $failed++; $this->newLine(); $this->warn(" [{$row['id']}] " . implode(', ', $result['errors'])); } $bar->advance(); } $bar->finish(); $this->newLine(2); $this->info("质检完成: 通过 {$passed},未通过 {$failed}"); return 0; } /** * 将 questions_tem 行映射为质检服务所需格式 */ private function mapQuestionRow(array $row): array { return [ 'stem' => $row['stem'] ?? $row['content'] ?? '', 'answer' => $row['answer'] ?? $row['correct_answer'] ?? '', 'solution' => $row['solution'] ?? '', 'question_type' => $row['question_type'] ?? $row['tags'] ?? '', 'options' => is_string($row['options'] ?? null) ? json_decode($row['options'], true) : ($row['options'] ?? null), ]; } }