소스 검색

fix: 目录折叠按显示区间展开多级,避免三级目录只展开两级

getBookToc 的展开集合原先只围绕单个选中节点构建,仅能展开其直接子级
(含顶层共两级)。聚合显示跨多级 chapter 时第三级被折叠。改为基于区间
内所有 active 节点及其祖先链构建展开集合,使各级 chapter 的子级均完整
显示;active 高亮复用同一集合。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
visuddhinanda 4 주 전
부모
커밋
9fb7dee061
1개의 변경된 파일29개의 추가작업 그리고 15개의 파일을 삭제
  1. 29 15
      api-v13/app/Http/Controllers/Library/BookController.php

+ 29 - 15
api-v13/app/Http/Controllers/Library/BookController.php

@@ -14,6 +14,7 @@ use App\Services\OpenSearchService;
 use App\Services\PaliTextService;
 use Illuminate\Http\Request;
 use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\Log;
 
 class BookController extends Controller
 {
@@ -326,7 +327,7 @@ class BookController extends Controller
             ->whereBetween('level', [$minLevel, $maxLevel])
             ->orderBy('paragraph')
             ->get();
-
+        // Log::debug('toc', ['toc' => $paliTexts->toArray()]);
         if ($paliTexts->isEmpty()) {
             return [];
         }
@@ -357,22 +358,35 @@ class BookController extends Controller
             $stack[] = ['id' => $id, 'level' => $level];
         }
 
-        // 当前节点的祖先链
-        $ancestorSet = [];
-        $cursor = $currentId;
-        while (! empty($parents[$cursor])) {
-            $cursor = $parents[$cursor];
-            $ancestorSet[$cursor] = true;
+        // 高亮(active)集合:聚合显示时为区间内所有 chapter,否则仅选中段落
+        $activeSet = [];
+        foreach ($paliTexts as $paliText) {
+            $id = "{$paliText->book}-{$paliText->paragraph}";
+            $active = $activeRange !== null
+                ? ($paliText->paragraph >= $activeRange[0] && $paliText->paragraph <= $activeRange[1])
+                : ($id === $currentId);
+            if ($active) {
+                $activeSet[$id] = true;
+            }
         }
 
-        // 需要展开子节点的集合 = 祖先链 + 当前节点
-        $expandParentSet = $ancestorSet;
-        $expandParentSet[$currentId] = true;
+        // 需要展开子节点的集合 = 每个 active 节点及其祖先链。
+        // 聚合显示跨多级时,区间内各级 chapter 都需展开,其子级才能完整显示,
+        // 否则仅围绕单个当前节点展开,最多只能显示两级。
+        $expandParentSet = [];
+        foreach (array_keys($activeSet) as $activeId) {
+            $expandParentSet[$activeId] = true;
+            $cursor = $activeId;
+            while (! empty($parents[$cursor])) {
+                $cursor = $parents[$cursor];
+                $expandParentSet[$cursor] = true;
+            }
+        }
 
         // 顶层 level(列表中最浅的一层,折叠模式下始终可见)
         $topLevel = (int) $paliTexts->min('level');
 
-        return $paliTexts->map(function ($paliText) use ($chaptersIndexed, $channelId, $currentId, $parents, $expandParentSet, $topLevel, $activeRange) {
+        $output = $paliTexts->map(function ($paliText) use ($chaptersIndexed, $channelId, $parents, $expandParentSet, $activeSet, $topLevel) {
             $id = "{$paliText->book}-{$paliText->paragraph}";
             $level = (int) $paliText->level;
             $title = $paliText->toc;
@@ -398,10 +412,7 @@ class BookController extends Controller
             $visible = $level === $topLevel
                 || ($parentId !== null && isset($expandParentSet[$parentId]));
 
-            // 聚合显示时高亮区间内所有 chapter,否则仅高亮选中段落
-            $active = $activeRange !== null
-                ? ($paliText->paragraph >= $activeRange[0] && $paliText->paragraph <= $activeRange[1])
-                : ($id === $currentId);
+            $active = isset($activeSet[$id]);
 
             return [
                 'id' => $id,
@@ -415,6 +426,9 @@ class BookController extends Controller
                 'hide' => ! $visible,
             ];
         })->all();
+
+        // Log::debug('toc output', ['data' => $output]);
+        return $output;
     }
 
     public function getBookCategory($book, $paragraph)