|
|
@@ -313,37 +313,37 @@ class DiagnosticChapterService
|
|
|
*/
|
|
|
public function getFirstUndiagnosedChapter(int $textbookId, int $studentId, ?array $targetChapterIds = null): ?array
|
|
|
{
|
|
|
- $query = TextbookCatalog::query()
|
|
|
- ->where('textbook_id', $textbookId)
|
|
|
- ->where('node_type', 'chapter');
|
|
|
-
|
|
|
$targetChapterIds = is_array($targetChapterIds)
|
|
|
? array_values(array_unique(array_filter(array_map('intval', $targetChapterIds), fn ($id) => $id > 0)))
|
|
|
: [];
|
|
|
|
|
|
- // 兜底:允许传入 section/subsection 节点,自动映射到所属 chapter 节点
|
|
|
+ // 只要传了 chapter_id_list(非空),就以传入参数为准;
|
|
|
+ // 仅当未传或为空时,才走教材默认章节逻辑。
|
|
|
if (!empty($targetChapterIds)) {
|
|
|
- $targetChapterIds = $this->normalizeToChapterIds($textbookId, $targetChapterIds);
|
|
|
- }
|
|
|
+ // 兜底:允许传入 section/subsection,自动向上映射到 chapter
|
|
|
+ $targetChapterIds = $this->normalizeToChapterIds($targetChapterIds);
|
|
|
+ if (empty($targetChapterIds)) {
|
|
|
+ Log::warning('DiagnosticChapterService: 指定章节参数无可解析chapter,终止指定章节摸底', [
|
|
|
+ 'textbook_id' => $textbookId,
|
|
|
+ 'student_id' => $studentId,
|
|
|
+ ]);
|
|
|
|
|
|
- $useTargetChapters = !empty($targetChapterIds);
|
|
|
- if ($useTargetChapters) {
|
|
|
- $query->whereIn('id', $targetChapterIds);
|
|
|
- }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
- $chapters = $query
|
|
|
- ->orderBy('sort_order')
|
|
|
- ->orderBy('display_no')
|
|
|
- ->orderBy('id')
|
|
|
- ->get();
|
|
|
+ // 保持传入顺序遍历,不使用教材排序字段重排
|
|
|
+ $chapterMap = TextbookCatalog::query()
|
|
|
+ ->whereIn('id', $targetChapterIds)
|
|
|
+ ->where('node_type', 'chapter')
|
|
|
+ ->get()
|
|
|
+ ->keyBy('id');
|
|
|
|
|
|
- if ($chapters->isEmpty()) {
|
|
|
- return null;
|
|
|
- }
|
|
|
+ foreach ($targetChapterIds as $chapterId) {
|
|
|
+ $chapter = $chapterMap->get($chapterId);
|
|
|
+ if (!$chapter) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- // 用户指定章节:按顺序找“有题知识点”的章节,不判断是否已摸底(允许重复摸底)
|
|
|
- if ($useTargetChapters) {
|
|
|
- foreach ($chapters as $chapter) {
|
|
|
$chapterData = $this->getChapterKnowledgePointsSimple($chapter->id);
|
|
|
$kpCodesWithQuestions = $this->filterKpCodesWithQuestions($chapterData['kp_codes']);
|
|
|
|
|
|
@@ -377,6 +377,18 @@ class DiagnosticChapterService
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ $chapters = TextbookCatalog::query()
|
|
|
+ ->where('textbook_id', $textbookId)
|
|
|
+ ->where('node_type', 'chapter')
|
|
|
+ ->orderBy('sort_order')
|
|
|
+ ->orderBy('display_no')
|
|
|
+ ->orderBy('id')
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ if ($chapters->isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
foreach ($chapters as $chapter) {
|
|
|
// 检查是否已摸底
|
|
|
if (!$this->hasChapterDiagnostic($studentId, $chapter->id)) {
|
|
|
@@ -434,7 +446,7 @@ class DiagnosticChapterService
|
|
|
* @param array<int> $nodeIds
|
|
|
* @return array<int>
|
|
|
*/
|
|
|
- private function normalizeToChapterIds(int $textbookId, array $nodeIds): array
|
|
|
+ private function normalizeToChapterIds(array $nodeIds): array
|
|
|
{
|
|
|
if (empty($nodeIds)) {
|
|
|
return [];
|
|
|
@@ -453,7 +465,6 @@ class DiagnosticChapterService
|
|
|
while ($currentId > 0 && $guard++ < 10) {
|
|
|
$node = TextbookCatalog::query()
|
|
|
->where('id', $currentId)
|
|
|
- ->where('textbook_id', $textbookId)
|
|
|
->first(['id', 'parent_id', 'node_type']);
|
|
|
|
|
|
if (!$node) {
|
|
|
@@ -474,7 +485,6 @@ class DiagnosticChapterService
|
|
|
|
|
|
if (count($chapterIds) !== count($nodeIds)) {
|
|
|
Log::info('DiagnosticChapterService: 章节参数已自动映射到chapter节点', [
|
|
|
- 'textbook_id' => $textbookId,
|
|
|
'input_ids' => $nodeIds,
|
|
|
'resolved_chapter_ids' => $chapterIds,
|
|
|
]);
|