Răsfoiți Sursa

只显示当前路径,隐藏其他章节

visuddhinanda 5 zile în urmă
părinte
comite
9143f48b26

+ 77 - 16
api-v12/app/Http/Controllers/Library/AnthologyReadController.php

@@ -30,23 +30,9 @@ class AnthologyReadController extends Controller
             ? $colResult['data']
             : $colResult['data']->toArray(request());
 
-        // ── 2. 构建完整目录(所有 level,保留层级信息) ────────────────────
+        // ── 2. 构建目录(方案A:展开祖先链,其余折叠) ───────────────────────
         $fullArticleList = collect($col['article_list'] ?? []);
-
-        // toc:全部节点,交给阅读页左侧目录使用
-        // 当前章节标记 active=true、disabled=true(高亮且不可点击)
-        $toc = $fullArticleList
-            ->values()
-            ->map(fn($a) => [
-                'id'       => $a['article_id'],
-                'title'    => $a['title'],
-                'summary'  => '',
-                'progress' => 0,
-                'level'    => (int) ($a['level'] ?? 1),
-                'disabled' => $a['article_id'] === $articleId,
-                'active'   => $a['article_id'] === $articleId,
-            ])
-            ->toArray();
+        $toc = $this->buildCollapsedToc($fullArticleList->toArray(), $articleId);
 
         // ── 3. 获取当前文章内容 ───────────────────────────────────────────────
         $artResult = $this->articleService->getArticle($articleId);
@@ -141,4 +127,79 @@ class AnthologyReadController extends Controller
         // 翻页路由需要 anthologyId,传给 blade 供覆盖路由使用
         return view('library.book.read', compact('book', 'relatedBooks', 'anthologyId'));
     }
+
+    // =========================================================================
+    // buildCollapsedToc
+    //
+    // 规则:
+    //   1. 所有 level=1 节点始终显示
+    //   2. 找出当前节点的「祖先链」(从 root 到当前节点经过的每个节点)
+    //   3. 祖先链上每个节点的「直接子节点」都展开显示
+    //   4. 当前节点本身若有子节点,同样展开一级
+    //   5. 其余节点隐藏
+    // =========================================================================
+    private function buildCollapsedToc(array $list, string $currentId): array
+    {
+        // ── Step 1:为每个节点推导父节点 id ──────────────────────────────────
+        // article_list 是有序的,父节点 = 当前节点之前最近的 level 更小的节点
+        $parents = [];  // article_id => parent_article_id | null
+        $stack   = [];  // 维护祖先栈 [ ['id'=>..., 'level'=>...], ... ]
+
+        foreach ($list as $item) {
+            $id    = $item['article_id'];
+            $level = (int) ($item['level'] ?? 1);
+
+            // 弹出所有 level >= 当前 level 的栈顶
+            while (!empty($stack) && $stack[count($stack) - 1]['level'] >= $level) {
+                array_pop($stack);
+            }
+
+            $parents[$id] = empty($stack) ? null : $stack[count($stack) - 1]['id'];
+            $stack[]      = ['id' => $id, 'level' => $level];
+        }
+
+        // ── Step 2:找出当前节点的祖先链 ─────────────────────────────────────
+        $ancestorIds = [];
+        $cursor      = $currentId;
+        while (isset($parents[$cursor]) && $parents[$cursor] !== null) {
+            $cursor        = $parents[$cursor];
+            $ancestorIds[] = $cursor;
+        }
+        $ancestorSet = array_flip($ancestorIds);
+
+        // ── Step 3:需要展开子节点的集合 = 祖先链 + 当前节点 ─────────────────
+        $expandParentSet              = $ancestorSet;
+        $expandParentSet[$currentId]  = true;
+
+        // ── Step 4:过滤构建 toc ──────────────────────────────────────────────
+        $toc = [];
+        foreach ($list as $item) {
+            $id       = $item['article_id'];
+            $level    = (int) ($item['level'] ?? 1);
+            $parentId = $parents[$id];
+            $isActive = $id === $currentId;
+
+            // 显示条件:
+            //   a) level=1(始终显示)
+            //   b) 父节点在 expandParentSet 中(祖先链或当前节点的直接子节点)
+            $visible = $level === 1
+                || ($parentId !== null && isset($expandParentSet[$parentId]));
+
+            if (!$visible) {
+                continue;
+            }
+
+            $toc[] = [
+                'id'       => $id,
+                'title'    => $item['title'],
+                'summary'  => '',
+                'progress' => 0,
+                'level'    => $level,
+                'disabled' => $isActive,
+                'active'   => $isActive,
+            ];
+        }
+
+        return $toc;
+    }
 }