ReportPayloadDto.php 3.8 KB

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