QuestionsTemAssemblyService.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. namespace App\Services;
  3. use App\Http\Controllers\ExamPdfController;
  4. use App\Models\Paper;
  5. use App\Models\PaperQuestion;
  6. use App\Models\User;
  7. use Illuminate\Support\Facades\Auth;
  8. use Illuminate\Support\Facades\DB;
  9. use Illuminate\Support\Facades\Schema;
  10. use Illuminate\Support\Str;
  11. /**
  12. * 待入库题目加入组卷队列(不写 questions 表),生成临时试卷以走判卷 PDF 链路验版式
  13. */
  14. class QuestionsTemAssemblyService
  15. {
  16. public function tableExists(): bool
  17. {
  18. return Schema::hasTable('questions_tem_assembly_queue');
  19. }
  20. public function queueForUser(int $userId): array
  21. {
  22. if (! $this->tableExists() || ! Schema::hasTable('questions_tem')) {
  23. return [];
  24. }
  25. $rows = DB::table('questions_tem as q')
  26. ->join('questions_tem_assembly_queue as aq', 'q.id', '=', 'aq.questions_tem_id')
  27. ->where('aq.user_id', $userId)
  28. ->orderBy('aq.sort_order')
  29. ->orderBy('aq.id')
  30. ->select('q.*')
  31. ->get();
  32. return $rows->all();
  33. }
  34. public function add(int $userId, int $temId): void
  35. {
  36. if (! $this->tableExists() || ! Schema::hasTable('questions_tem')) {
  37. return;
  38. }
  39. if (! DB::table('questions_tem')->where('id', $temId)->exists()) {
  40. return;
  41. }
  42. if (DB::table('questions_tem_assembly_queue')
  43. ->where('user_id', $userId)
  44. ->where('questions_tem_id', $temId)
  45. ->exists()) {
  46. return;
  47. }
  48. $max = (int) DB::table('questions_tem_assembly_queue')->where('user_id', $userId)->max('sort_order');
  49. DB::table('questions_tem_assembly_queue')->insert([
  50. 'user_id' => $userId,
  51. 'questions_tem_id' => $temId,
  52. 'sort_order' => $max + 1,
  53. 'created_at' => now(),
  54. 'updated_at' => now(),
  55. ]);
  56. }
  57. public function remove(int $userId, int $temId): void
  58. {
  59. if (! $this->tableExists()) {
  60. return;
  61. }
  62. DB::table('questions_tem_assembly_queue')
  63. ->where('user_id', $userId)
  64. ->where('questions_tem_id', $temId)
  65. ->delete();
  66. }
  67. public function clear(int $userId): void
  68. {
  69. if (! $this->tableExists()) {
  70. return;
  71. }
  72. DB::table('questions_tem_assembly_queue')->where('user_id', $userId)->delete();
  73. }
  74. /**
  75. * 创建临时试卷并写入 paper_questions(question_bank_id 为负 tem id,判卷页会从 questions_tem 还原选项)
  76. */
  77. public function createTrialPaperForQueue(int $userId): ?string
  78. {
  79. $rows = $this->queueForUser($userId);
  80. if ($rows === []) {
  81. return null;
  82. }
  83. $user = User::query()->find($userId);
  84. $studentKey = (string) ($user?->username ?? 'preview');
  85. $teacherKey = (string) ($user?->username ?? 'preview');
  86. $paperId = 'TEMQ-'.Str::upper(Str::random(12));
  87. $pdf = app(ExamPdfController::class);
  88. $questionsData = $pdf->prepareQuestionsDataFromTemRows($rows);
  89. $grouped = $pdf->buildGroupedQuestionsForPaperBody($questionsData, null);
  90. $order = 1;
  91. $totalScore = 0.0;
  92. $flat = array_merge($grouped['choice'], $grouped['fill'], $grouped['answer']);
  93. usort($flat, fn ($a, $b) => ($a->question_number ?? 0) <=> ($b->question_number ?? 0));
  94. foreach ($flat as $obj) {
  95. $totalScore += (float) ($obj->score ?? 5);
  96. }
  97. Paper::query()->create([
  98. 'paper_id' => $paperId,
  99. 'student_id' => (string) $studentKey,
  100. 'teacher_id' => (string) $teacherKey,
  101. 'paper_name' => '待入库组卷验真',
  102. 'paper_type' => 0,
  103. 'total_questions' => count($flat),
  104. 'total_score' => $totalScore,
  105. 'status' => 'tem_preview',
  106. 'difficulty_category' => '中等',
  107. ]);
  108. foreach ($flat as $obj) {
  109. $type = (string) ($obj->question_type ?? 'answer');
  110. $stem = (string) ($obj->stem ?? $obj->content ?? '');
  111. $bankId = (int) ($obj->id ?? 0);
  112. PaperQuestion::query()->create([
  113. 'paper_id' => $paperId,
  114. 'question_bank_id' => $bankId,
  115. 'question_id' => 'tem-'.$order,
  116. 'knowledge_point' => (string) ($obj->kp_code ?? ''),
  117. 'question_type' => $type,
  118. 'question_text' => $stem,
  119. 'correct_answer' => (string) ($obj->answer ?? ''),
  120. 'solution' => (string) ($obj->solution ?? ''),
  121. 'difficulty' => (float) ($obj->difficulty ?? 0.5),
  122. 'score' => (float) ($obj->score ?? 5),
  123. 'question_number' => (int) ($obj->question_number ?? $order),
  124. ]);
  125. $order++;
  126. }
  127. return $paperId;
  128. }
  129. public static function currentUserId(): ?int
  130. {
  131. $u = Auth::user();
  132. if ($u instanceof User) {
  133. return (int) $u->id;
  134. }
  135. return null;
  136. }
  137. }