ReportPayloadDto.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. namespace App\DTO;
  3. /**
  4. * 报告负载数据传输对象
  5. * 用于PDF生成时的数据封装
  6. */
  7. class ReportPayloadDto
  8. {
  9. public function __construct(
  10. public readonly array $paper,
  11. public readonly array $student,
  12. public readonly array $teacher,
  13. public readonly array $questions,
  14. public readonly array $mastery,
  15. public readonly array $masteryMap,
  16. public readonly array $examHitKpCodes,
  17. public readonly array $parentMasteryLevels, // 新增:父节点掌握度数据
  18. public readonly array $fullParentMasteryLevels, // 新增:全量父节点掌握度
  19. public readonly array $questionInsights,
  20. public readonly array $recommendations,
  21. public readonly array $analysisData = []
  22. ) {}
  23. /**
  24. * 从ExamAnalysisDataDto创建
  25. */
  26. public static function fromExamAnalysisDataDto(ExamAnalysisDataDto $dto): self
  27. {
  28. return new self(
  29. paper: $dto->paper,
  30. student: $dto->student,
  31. teacher: $dto->teacher,
  32. questions: $dto->questions,
  33. mastery: $dto->mastery,
  34. masteryMap: $dto->masteryMap,
  35. examHitKpCodes: $dto->examHitKpCodes,
  36. parentMasteryLevels: $dto->parentMasteryLevels, // 新增:父节点掌握度数据
  37. fullParentMasteryLevels: $dto->fullParentMasteryLevels,
  38. questionInsights: $dto->insights,
  39. recommendations: $dto->recommendations,
  40. // 必须透传原始 analysis_data,模板依赖 question_analysis/knowledge_point_analysis 原始结构
  41. analysisData: $dto->rawAnalysisData
  42. );
  43. }
  44. /**
  45. * 转换为数组
  46. */
  47. public function toArray(): array
  48. {
  49. return [
  50. 'paper' => $this->paper,
  51. 'student' => $this->student,
  52. 'teacher' => $this->teacher,
  53. 'questions' => $this->questions,
  54. 'mastery' => $this->mastery,
  55. 'mastery_map' => $this->masteryMap,
  56. 'exam_hit_kp_codes' => $this->examHitKpCodes,
  57. 'parent_mastery_levels' => $this->parentMasteryLevels, // 新增:父节点掌握度数据
  58. 'full_parent_mastery_levels' => $this->fullParentMasteryLevels,
  59. 'question_insights' => $this->questionInsights,
  60. 'recommendations' => $this->recommendations,
  61. 'analysis_data' => $this->analysisData,
  62. ];
  63. }
  64. /**
  65. * 按题型分组题目
  66. */
  67. public function getQuestionsByType(): array
  68. {
  69. $grouped = [
  70. 'choice' => [],
  71. 'fill' => [],
  72. 'answer' => [],
  73. ];
  74. foreach ($this->questions as $question) {
  75. $type = $question['question_type'] ?? 'answer';
  76. $normalizedType = $this->normalizeQuestionType($type);
  77. $grouped[$normalizedType][] = $question;
  78. }
  79. return $grouped;
  80. }
  81. /**
  82. * 标准化题型名称
  83. */
  84. private function normalizeQuestionType(string $type): string
  85. {
  86. $t = strtolower(trim($type));
  87. return match (true) {
  88. str_contains($t, 'choice') || str_contains($t, '选择') => 'choice',
  89. str_contains($t, 'fill') || str_contains($t, 'blank') || str_contains($t, '填空') => 'fill',
  90. default => 'answer',
  91. };
  92. }
  93. /**
  94. * 获取按卷面顺序排列的题目
  95. */
  96. public function getOrderedQuestions(): array
  97. {
  98. $grouped = $this->getQuestionsByType();
  99. $ordered = array_merge($grouped['choice'], $grouped['fill'], $grouped['answer']);
  100. // 添加显示序号
  101. foreach ($ordered as $i => &$question) {
  102. $question['display_number'] = $i + 1;
  103. }
  104. unset($question);
  105. return $ordered;
  106. }
  107. /**
  108. * 获取知识点名称映射
  109. */
  110. public function getKnowledgePointNameMap(): array
  111. {
  112. $map = [];
  113. foreach ($this->questions as $question) {
  114. $kpCode = $question['knowledge_point'] ?? $question['kp_code'] ?? '';
  115. $kpName = $question['knowledge_point_name'] ?? $kpCode;
  116. if ($kpCode && $kpName) {
  117. $map[$kpCode] = $kpName;
  118. }
  119. }
  120. return $map;
  121. }
  122. }