UploadForm.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. namespace App\Livewire\UploadExam;
  3. use Livewire\Component;
  4. use Livewire\WithFileUploads;
  5. use Livewire\Attributes\On;
  6. use Filament\Notifications\Notification;
  7. use App\Jobs\ProcessOCRRecord;
  8. use App\Services\ChatGPTAnalysisService;
  9. use Illuminate\Support\Facades\Storage;
  10. class UploadForm extends Component
  11. {
  12. use WithFileUploads;
  13. public ?string $teacherId = null;
  14. public ?string $studentId = null;
  15. public ?string $selectedPaperId = null;
  16. public ?string $mode = 'ocr'; // 'ocr' 或 'chatgpt'
  17. public $uploadedImages = [];
  18. public bool $isUploading = false;
  19. public function mount($teacherId = null, $studentId = null, $selectedPaperId = null, $mode = 'ocr')
  20. {
  21. $this->teacherId = $teacherId;
  22. $this->studentId = $studentId;
  23. $this->selectedPaperId = $selectedPaperId;
  24. $this->mode = $mode;
  25. }
  26. public function handleSubmit()
  27. {
  28. // 验证图片
  29. if (empty($this->uploadedImages)) {
  30. Notification::make()
  31. ->title('请上传试卷图片')
  32. ->danger()
  33. ->send();
  34. return;
  35. }
  36. $this->isUploading = true;
  37. try {
  38. // 保存图片
  39. $savedImages = [];
  40. foreach ($this->uploadedImages as $image) {
  41. $path = $image->store('exam-papers', 'public');
  42. $savedImages[] = [
  43. 'path' => $path,
  44. 'original_name' => $image->getClientOriginalName(),
  45. 'size' => $image->getSize(),
  46. ];
  47. }
  48. // 获取图片URL
  49. $imageUrl = asset('storage/' . $savedImages[0]['path']);
  50. // 根据模式处理
  51. if ($this->mode === 'chatgpt') {
  52. // ChatGPT模式:直接调用ChatGPT分析
  53. $this->handleChatGPTAnalysis($imageUrl);
  54. } else {
  55. // OCR模式:保持原有逻辑
  56. $this->handleOCRProcessing($savedImages);
  57. }
  58. } catch (\Exception $e) {
  59. Notification::make()
  60. ->title('处理失败')
  61. ->body($e->getMessage())
  62. ->danger()
  63. ->send();
  64. } finally {
  65. $this->isUploading = false;
  66. }
  67. }
  68. /**
  69. * 处理OCR识别
  70. */
  71. private function handleOCRProcessing(array $savedImages)
  72. {
  73. // 获取试卷名称
  74. $paperTitle = '待OCR识别';
  75. if ($this->selectedPaperId) {
  76. $paper = \App\Models\Paper::where('paper_id', $this->selectedPaperId)->first();
  77. if ($paper) {
  78. $paperTitle = $paper->paper_name;
  79. }
  80. }
  81. // 创建 OCR 记录
  82. $ocrRecord = \App\Models\OCRRecord::create([
  83. 'user_id' => $this->studentId,
  84. 'student_id' => $this->studentId,
  85. 'paper_title' => $paperTitle,
  86. 'paper_type' => null,
  87. 'file_path' => $savedImages[0]['path'],
  88. 'image_count' => count($savedImages),
  89. 'status' => 'processing',
  90. 'analysis_id' => $this->selectedPaperId,
  91. ]);
  92. // 派发 OCR 处理任务
  93. ProcessOCRRecord::dispatch($ocrRecord->id);
  94. Notification::make()
  95. ->title('上传成功')
  96. ->body('图片已上传,正在进行 OCR 识别...')
  97. ->success()
  98. ->send();
  99. // 跳转
  100. if ($this->selectedPaperId && str_starts_with($this->selectedPaperId, 'paper_')) {
  101. $this->redirect('/admin/ocr-paper-analysis/' . $ocrRecord->id);
  102. } else {
  103. $this->redirect('/admin/ocr-record-view/' . $ocrRecord->id);
  104. }
  105. }
  106. /**
  107. * 处理ChatGPT分析
  108. */
  109. private function handleChatGPTAnalysis(string $imageUrl)
  110. {
  111. if (!$this->selectedPaperId) {
  112. throw new \Exception('请先选择试卷');
  113. }
  114. // 调用ChatGPT分析
  115. $chatGPTService = app(ChatGPTAnalysisService::class);
  116. $result = $chatGPTService->analyzeExamPaper($this->selectedPaperId, $imageUrl);
  117. if ($result['success']) {
  118. // 保存分析结果
  119. $saved = $chatGPTService->saveAnalysisResult($this->selectedPaperId, $result['data']);
  120. if ($saved) {
  121. Notification::make()
  122. ->title('ChatGPT分析完成')
  123. ->body('已成功分析 ' . count($result['data']['questions'] ?? []) . ' 道题目')
  124. ->success()
  125. ->send();
  126. // 跳转到分析页面
  127. $this->redirect('/admin/exam-analysis?paperId=' . $this->selectedPaperId);
  128. } else {
  129. throw new \Exception('分析结果保存失败');
  130. }
  131. } else {
  132. throw new \Exception($result['error'] ?? 'ChatGPT分析失败');
  133. }
  134. }
  135. public function resetForm()
  136. {
  137. $this->uploadedImages = [];
  138. $this->currentOcrRecordId = null;
  139. $this->ocrStatus = null;
  140. }
  141. public function removeImage($index)
  142. {
  143. unset($this->uploadedImages[$index]);
  144. $this->uploadedImages = array_values($this->uploadedImages);
  145. }
  146. public function render()
  147. {
  148. return view('livewire.upload-exam.upload-form');
  149. }
  150. }