ReportPayloadDto.php 3.1 KB

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