|
@@ -1795,16 +1795,10 @@ class ExamPdfExportService
|
|
|
*/
|
|
*/
|
|
|
private function fetchKnowledgeExplanationHtml(string $paperId): ?string
|
|
private function fetchKnowledgeExplanationHtml(string $paperId): ?string
|
|
|
{
|
|
{
|
|
|
- $html = $this->renderKnowledgeExplanationHtmlFromView($paperId);
|
|
|
|
|
- if ($html !== null) {
|
|
|
|
|
- return $html;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
try {
|
|
try {
|
|
|
$url = route('filament.admin.auth.intelligent-exam.knowledge-explanation', ['paper_id' => $paperId]);
|
|
$url = route('filament.admin.auth.intelligent-exam.knowledge-explanation', ['paper_id' => $paperId]);
|
|
|
- $timeout = max(1, (int) config('pdf.kp_explain_fetch_timeout_seconds', 2));
|
|
|
|
|
|
|
|
|
|
- $response = Http::timeout($timeout)->get($url);
|
|
|
|
|
|
|
+ $response = Http::get($url);
|
|
|
if ($response->successful()) {
|
|
if ($response->successful()) {
|
|
|
$html = $response->body();
|
|
$html = $response->body();
|
|
|
if (! empty(trim($html))) {
|
|
if (! empty(trim($html))) {
|
|
@@ -1823,7 +1817,6 @@ class ExamPdfExportService
|
|
|
Log::warning('ExamPdfExportService: 获取知识点讲解HTML失败', [
|
|
Log::warning('ExamPdfExportService: 获取知识点讲解HTML失败', [
|
|
|
'paper_id' => $paperId,
|
|
'paper_id' => $paperId,
|
|
|
'url' => $url,
|
|
'url' => $url,
|
|
|
- 'timeout_seconds' => $timeout,
|
|
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
return null;
|
|
return null;
|
|
@@ -1832,92 +1825,6 @@ class ExamPdfExportService
|
|
|
Log::warning('ExamPdfExportService: 获取知识点讲解HTML异常', [
|
|
Log::warning('ExamPdfExportService: 获取知识点讲解HTML异常', [
|
|
|
'paper_id' => $paperId,
|
|
'paper_id' => $paperId,
|
|
|
'error' => $e->getMessage(),
|
|
'error' => $e->getMessage(),
|
|
|
- 'timeout_seconds' => config('pdf.kp_explain_fetch_timeout_seconds', 2),
|
|
|
|
|
- ]);
|
|
|
|
|
-
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private function renderKnowledgeExplanationHtmlFromView(string $paperId): ?string
|
|
|
|
|
- {
|
|
|
|
|
- try {
|
|
|
|
|
- $paper = Paper::query()->where('paper_id', $paperId)->first();
|
|
|
|
|
- if (! $paper) {
|
|
|
|
|
- Log::warning('ExamPdfExportService: 本地渲染知识点讲解失败,试卷不存在', ['paper_id' => $paperId]);
|
|
|
|
|
-
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $studentModel = Student::find($paper->student_id);
|
|
|
|
|
- $studentName = $studentModel->name ?? ($paper->student_id ?? '________');
|
|
|
|
|
- $examCode = PaperNaming::extractExamCode((string) $paper->paper_id);
|
|
|
|
|
- try {
|
|
|
|
|
- $assembleTypeLabel = PaperNaming::assembleTypeLabel((int) $paper->paper_type);
|
|
|
|
|
- } catch (\Throwable $e) {
|
|
|
|
|
- $assembleTypeLabel = '未知类型';
|
|
|
|
|
- }
|
|
|
|
|
- $pdfMeta = [
|
|
|
|
|
- 'student_name' => $studentName,
|
|
|
|
|
- 'exam_code' => $examCode,
|
|
|
|
|
- 'assemble_type_label' => $assembleTypeLabel,
|
|
|
|
|
- 'header_title' => $examCode,
|
|
|
|
|
- 'exam_pdf_title' => '试卷_'.$examCode,
|
|
|
|
|
- 'grading_pdf_title' => '判卷_'.$examCode,
|
|
|
|
|
- 'knowledge_pdf_title' => '知识点梳理_'.$examCode,
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- $kpCodes = $paper->explanation_kp_codes ?? [];
|
|
|
|
|
- if (empty($kpCodes)) {
|
|
|
|
|
- $paperQuestions = \App\Models\PaperQuestion::where('paper_id', $paperId)->get();
|
|
|
|
|
- $seen = [];
|
|
|
|
|
- $questionBankIds = $paperQuestions
|
|
|
|
|
- ->pluck('question_bank_id')
|
|
|
|
|
- ->filter()
|
|
|
|
|
- ->unique()
|
|
|
|
|
- ->values();
|
|
|
|
|
- $questionKpMap = [];
|
|
|
|
|
- if ($questionBankIds->isNotEmpty()) {
|
|
|
|
|
- $questionKpMap = Question::whereIn('id', $questionBankIds)
|
|
|
|
|
- ->pluck('kp_code', 'id')
|
|
|
|
|
- ->toArray();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- foreach ($paperQuestions as $paperQuestion) {
|
|
|
|
|
- $kpCode = trim((string) ($paperQuestion->knowledge_point ?? ''));
|
|
|
|
|
- if ($kpCode === '' && ! empty($paperQuestion->question_bank_id)) {
|
|
|
|
|
- $kpCode = trim((string) ($questionKpMap[$paperQuestion->question_bank_id] ?? ''));
|
|
|
|
|
- }
|
|
|
|
|
- if ($kpCode === '' || isset($seen[$kpCode])) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- $seen[$kpCode] = true;
|
|
|
|
|
- $kpCodes[] = $kpCode;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $html = view('pdf.exam-knowledge-explanation', [
|
|
|
|
|
- 'paperId' => $paperId,
|
|
|
|
|
- 'examCode' => $examCode,
|
|
|
|
|
- 'studentName' => $studentName,
|
|
|
|
|
- 'generateDateTime' => now()->format('Y年m月d日 H:i:s'),
|
|
|
|
|
- 'knowledgePoints' => $this->buildExplanations($kpCodes),
|
|
|
|
|
- 'pdfMeta' => $pdfMeta,
|
|
|
|
|
- ])->render();
|
|
|
|
|
-
|
|
|
|
|
- if (empty(trim($html))) {
|
|
|
|
|
- Log::warning('ExamPdfExportService: 本地渲染知识点讲解结果为空', ['paper_id' => $paperId]);
|
|
|
|
|
-
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $html = $this->ensureUtf8Html($html);
|
|
|
|
|
-
|
|
|
|
|
- return $this->renderKpExplainMarkdown($html);
|
|
|
|
|
- } catch (\Throwable $e) {
|
|
|
|
|
- Log::warning('ExamPdfExportService: 本地渲染知识点讲解异常', [
|
|
|
|
|
- 'paper_id' => $paperId,
|
|
|
|
|
- 'error' => $e->getMessage(),
|
|
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
return null;
|
|
return null;
|
|
@@ -1944,16 +1851,18 @@ class ExamPdfExportService
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 【新增】渲染试卷HTML(通过HTTP调用路由)
|
|
|
|
|
+ */
|
|
|
private function renderExamHtml(string $paperId, bool $includeAnswer, bool $useGradingView): ?string
|
|
private function renderExamHtml(string $paperId, bool $includeAnswer, bool $useGradingView): ?string
|
|
|
{
|
|
{
|
|
|
- // PDF worker 已经运行在 Laravel 进程内,优先直接渲染 Blade,避免 HTTP 自调用吞掉数秒。
|
|
|
|
|
- $html = $this->renderExamHtmlFromView($paperId, $includeAnswer, $useGradingView);
|
|
|
|
|
- if ($html !== null) {
|
|
|
|
|
- return $html;
|
|
|
|
|
|
|
+ // 判卷部分启用答案详情页时,优先本地渲染,避免跨进程配置不一致。
|
|
|
|
|
+ if ($useGradingView && config('exam.pdf_grading_append_scan_sheet', false)) {
|
|
|
|
|
+ return $this->renderExamHtmlFromView($paperId, $includeAnswer, $useGradingView);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 兜底:保留原 HTTP 路由渲染路径,避免特殊页面上下文下直接视图失败。
|
|
|
|
|
|
|
+ // 通过HTTP客户端获取渲染后的HTML(与知识点讲解相同的逻辑)
|
|
|
$routeName = $useGradingView
|
|
$routeName = $useGradingView
|
|
|
? 'filament.admin.auth.intelligent-exam.grading'
|
|
? 'filament.admin.auth.intelligent-exam.grading'
|
|
|
: 'filament.admin.auth.intelligent-exam.pdf';
|
|
: 'filament.admin.auth.intelligent-exam.pdf';
|