= 0; $i--) { if (empty($list[$i]['temp_save'])) { $last = $list[$i]; break; } } if ($last === null && $list !== []) { $last = $list[count($list) - 1]; // 全是暂存时退回最后一份 } if ($last === null) { $v = $r['score'] ?? null; // 无明细:退回代表行 return ($v === null || $v === '') ? null : (float)$v; } $v = $last['score'] ?? null; return ($v === null || $v === '') ? null : (float)$v; } /** * 把多场考试已构建好的结果,组装成"成绩交叉对比"二维矩阵。 * * @param array $exams 关联数组 pid => ['name'=>string, 'rows'=>array](保持插入顺序即考试展示顺序) * @param string $scoreMode 'latest' | 'highest' * @return array{head:array,rows:array,exam_order:array,exam_names:array} */ function ny_assemble_multi_exam_matrix(array $exams, string $scoreMode): array { $examOrder = []; $examNames = []; $scoreByExam = []; // pid => [sid => float|null] $nameBySid = []; // sid => 姓名(首个非空) foreach ($exams as $pid => $ex) { $examOrder[] = $pid; $examNames[$pid] = trim((string)($ex['name'] ?? '')) !== '' ? (string)$ex['name'] : (string)$pid; $map = []; foreach ((array)($ex['rows'] ?? []) as $r) { $sid = trim((string)($r['sid'] ?? '')); if ($sid === '') { continue; } if (!isset($nameBySid[$sid]) && trim((string)($r['name'] ?? '')) !== '') { $nameBySid[$sid] = (string)$r['name']; } $map[$sid] = ny_exam_cell_score($r, $scoreMode); } $scoreByExam[$pid] = $map; } // 学生并集(在任一选中考试里有提交即纳入) $sidSet = []; foreach ($scoreByExam as $map) { foreach ($map as $sid => $_) { $sidSet[$sid] = true; } } $sids = array_keys($sidSet); // 默认按学号排序(数值优先,否则自然序) usort($sids, static function ($a, $b): int { $a = (string)$a; $b = (string)$b; if (is_numeric($a) && is_numeric($b)) { return $a <=> $b; } return strnatcmp($a, $b); }); $head = array_merge(['学号', '姓名'], array_map(static fn($pid) => $examNames[$pid], $examOrder)); $rows = []; foreach ($sids as $sid) { $line = [$sid, $nameBySid[$sid] ?? '']; foreach ($examOrder as $pid) { $sc = $scoreByExam[$pid][$sid] ?? null; $line[] = ($sc === null) ? '' : $sc; } $rows[] = $line; } return ['head' => $head, 'rows' => $rows, 'exam_order' => $examOrder, 'exam_names' => $examNames]; }