AnthologyReadController.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. namespace App\Http\Controllers\Library;
  3. use App\Http\Controllers\Controller;
  4. use App\Services\CollectionService;
  5. use App\Services\ArticleService;
  6. use Illuminate\Http\Request;
  7. class AnthologyReadController extends Controller
  8. {
  9. public function __construct(
  10. private CollectionService $collectionService,
  11. private ArticleService $articleService,
  12. ) {}
  13. // =========================================================================
  14. // read
  15. // GET /library/anthology/{anthology}/read/{article}
  16. // =========================================================================
  17. public function read(string $anthologyId, string $articleId)
  18. {
  19. // ── 1. 获取文集信息 ───────────────────────────────────────────────────
  20. $colResult = $this->collectionService->getCollection($anthologyId);
  21. if (isset($colResult['error'])) {
  22. abort($colResult['code'] ?? 404, $colResult['error']);
  23. }
  24. $col = is_array($colResult['data'])
  25. ? $colResult['data']
  26. : $colResult['data']->toArray(request());
  27. // ── 2. 构建完整目录(所有 level,保留层级信息) ────────────────────
  28. $fullArticleList = collect($col['article_list'] ?? []);
  29. // toc:全部节点,交给阅读页左侧目录使用
  30. // 当前章节标记 active=true、disabled=true(高亮且不可点击)
  31. $toc = $fullArticleList
  32. ->values()
  33. ->map(fn($a) => [
  34. 'id' => $a['article_id'],
  35. 'title' => $a['title'],
  36. 'summary' => '',
  37. 'progress' => 0,
  38. 'level' => (int) ($a['level'] ?? 1),
  39. 'disabled' => $a['article_id'] === $articleId,
  40. 'active' => $a['article_id'] === $articleId,
  41. ])
  42. ->toArray();
  43. // ── 3. 获取当前文章内容 ───────────────────────────────────────────────
  44. $artResult = $this->articleService->getArticle($articleId);
  45. if (isset($artResult['error'])) {
  46. abort($artResult['code'] ?? 404, $artResult['error']);
  47. }
  48. // ArticleResource 需要 format=html
  49. $fakeRequest = Request::create('', 'GET', ['format' => 'html']);
  50. $artResource = $artResult['data'];
  51. $artArray = $artResource->toArray($fakeRequest);
  52. // content 统一包装成 book.read 期望的格式:
  53. // [ ['id'=>..., 'level'=>1, 'text'=>[[ html_string ]]], ... ]
  54. $content = [[
  55. 'id' => $articleId,
  56. 'level' => 100,
  57. 'text' => [[$artArray['html'] ?? $artArray['content'] ?? 'null']],
  58. ]];
  59. // ── 4. 计算翻页(pagination) ─────────────────────────────────────────
  60. // 只在 level=1 的节点间翻页(与目录一致)
  61. $level1 = $fullArticleList
  62. ->filter(fn($a) => ($a['level'] ?? 1) === 1)
  63. ->values();
  64. $currentIndex = $level1->search(
  65. fn($a) => $a['article_id'] === $articleId
  66. );
  67. $prev = null;
  68. $next = null;
  69. if ($currentIndex !== false) {
  70. if ($currentIndex > 0) {
  71. $prevItem = $level1[$currentIndex - 1];
  72. $prev = [
  73. 'id' => $prevItem['article_id'],
  74. 'title' => $prevItem['title'],
  75. ];
  76. }
  77. if ($currentIndex < $level1->count() - 1) {
  78. $nextItem = $level1[$currentIndex + 1];
  79. $next = [
  80. 'id' => $nextItem['article_id'],
  81. 'title' => $nextItem['title'],
  82. ];
  83. }
  84. }
  85. $pagination = [
  86. 'start' => 0,
  87. 'end' => 0,
  88. 'prev' => $prev,
  89. 'next' => $next,
  90. ];
  91. // ── 5. 组装 $book(对齐 book.read 的数据结构) ───────────────────────
  92. $studio = $col['studio'] ?? [];
  93. // blade 用 $book['publisher']->username / ->nickname,必须是对象
  94. $publisher = (object) [
  95. 'username' => $studio['studioName'] ?? '',
  96. 'nickname' => $studio['nickName'] ?? $studio['studioName'] ?? '',
  97. ];
  98. $book = [
  99. 'id' => $articleId,
  100. 'title' => $artArray['title'] ?? ($col['title'] ?? ''),
  101. 'author' => $studio['nickName'] ?? $studio['studioName'] ?? '',
  102. 'publisher' => $publisher,
  103. 'type' => '',
  104. 'category_id' => null,
  105. 'cover' => null,
  106. 'description' => $col['summary'] ?? '',
  107. 'language' => $col['lang'] ?? '',
  108. 'anthology' => [
  109. 'id' => $anthologyId,
  110. 'title' => $col['title'] ?? '',
  111. ],
  112. 'categories' => [],
  113. 'tags' => [],
  114. 'downloads' => [],
  115. 'toc' => $toc,
  116. 'pagination' => $pagination,
  117. 'content' => $content,
  118. ];
  119. // blade 里有 $relatedBooks,传空数组防止 undefined variable
  120. $relatedBooks = [];
  121. // 翻页路由需要 anthologyId,传给 blade 供覆盖路由使用
  122. return view('library.book.read', compact('book', 'relatedBooks', 'anthologyId'));
  123. }
  124. }