CategoryController.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Support\Facades\Storage;
  5. use Illuminate\Support\Facades\DB;
  6. use App\Models\PaliText;
  7. use App\Models\ProgressChapter;
  8. use App\Models\Tag;
  9. use App\Models\TagMap;
  10. class CategoryController extends Controller
  11. {
  12. protected static int $nextId = 1;
  13. public function index()
  14. {
  15. $categories = $this->loadCategories();
  16. // 获取一级分类和对应的书籍
  17. $categoryData = [];
  18. foreach ($categories as $category) {
  19. if ($category['level'] == 1) {
  20. $children = $this->subCategories($categories, $category['id']);
  21. $categoryData[] = [
  22. 'category' => $category,
  23. 'children' => $children,
  24. ];
  25. }
  26. }
  27. $update = $this->getUpdateBooks();
  28. return view('library.index', compact('categoryData', 'categories', 'update'));
  29. }
  30. public function show($id)
  31. {
  32. $categories = $this->loadCategories();
  33. $currentCategory = collect($categories)->firstWhere('id', $id);
  34. if (!$currentCategory) {
  35. abort(404);
  36. }
  37. // 获取子分类
  38. $subCategories = array_filter($categories, function ($cat) use ($id) {
  39. return $cat['parent_id'] == $id;
  40. });
  41. // 获取该分类下的书籍
  42. $categoryBooks = $this->getBooks($categories, $id);
  43. // 获取面包屑
  44. $breadcrumbs = $this->getBreadcrumbs($currentCategory, $categories);
  45. return view('library.category', compact('currentCategory', 'subCategories', 'categoryBooks', 'breadcrumbs'));
  46. }
  47. private function subCategories($categories, int $id)
  48. {
  49. return array_filter($categories, function ($cat) use ($id) {
  50. return $cat['parent_id'] == $id;
  51. });
  52. }
  53. private function getUpdateBooks()
  54. {
  55. $books = ProgressChapter::with('channel.owner')
  56. ->leftJoin('pali_texts', function ($join) {
  57. $join->on('progress_chapters.book', '=', 'pali_texts.book')
  58. ->on('progress_chapters.para', '=', 'pali_texts.paragraph');
  59. })
  60. ->whereHas('channel', function ($query) {
  61. $query->where('status', 30);
  62. })
  63. ->where('progress', '>', config('mint.library.list_min_progress'))
  64. ->take(10)
  65. ->get();
  66. return $this->getBooksInfo($books);
  67. }
  68. private function getBooks($categories, $id)
  69. {
  70. $currentCategory = collect($categories)->firstWhere('id', $id);
  71. if (!$currentCategory) {
  72. abort(404);
  73. }
  74. // 标签查章节
  75. $tagNames = $currentCategory['tag'];
  76. $tm = (new TagMap)->getTable();
  77. $tg = (new Tag)->getTable();
  78. $pt = (new PaliText)->getTable();
  79. $where1 = " where co = " . count($tagNames);
  80. $a = implode(",", array_fill(0, count($tagNames), '?'));
  81. $in1 = "and t.name in ({$a})";
  82. $param = $tagNames;
  83. $where2 = "where level = 1";
  84. $query = "
  85. select uid as id,book,paragraph,level,toc as title,chapter_strlen,parent,path from (
  86. select anchor_id as cid from (
  87. select tm.anchor_id , count(*) as co
  88. from $tm as tm
  89. left join $tg as t on tm.tag_id = t.id
  90. where tm.table_name = 'pali_texts'
  91. $in1
  92. group by tm.anchor_id
  93. ) T
  94. $where1
  95. ) CID
  96. left join $pt as pt on CID.cid = pt.uid
  97. $where2
  98. order by book,paragraph";
  99. $chapters = DB::select($query, $param);
  100. $chaptersParam = [];
  101. foreach ($chapters as $key => $chapter) {
  102. $chaptersParam[] = [$chapter->book, $chapter->paragraph];
  103. }
  104. // 获取该分类下的章节
  105. $books = ProgressChapter::with('channel.owner')
  106. ->leftJoin('pali_texts', function ($join) {
  107. $join->on('progress_chapters.book', '=', 'pali_texts.book')
  108. ->on('progress_chapters.para', '=', 'pali_texts.paragraph');
  109. })
  110. ->whereIns(['progress_chapters.book', 'progress_chapters.para'], $chaptersParam)
  111. ->whereHas('channel', function ($query) {
  112. $query->where('status', 30);
  113. })
  114. ->where('progress', '>', config('mint.library.list_min_progress'))
  115. ->get();
  116. return $this->getBooksInfo($books);
  117. }
  118. private function getBooksInfo($books,)
  119. {
  120. $pali = PaliText::where('level', 1)->get();
  121. // 获取该分类下的书籍
  122. $categoryBooks = [];
  123. $books->each(function ($book) use (&$categoryBooks, $pali) {
  124. $title = $book->title;
  125. if (empty($title)) {
  126. $title = $pali->firstWhere('book', $book->book)->toc;
  127. }
  128. $categoryBooks[] = [
  129. "id" => $book->uid,
  130. "title" => $title,
  131. "author" => $book->channel->name,
  132. "publisher" => $book->channel->owner,
  133. "type" => __('labels.' . $book->channel->type),
  134. "cover" => "/assets/images/cover/zh-hans/1/{$book->pcd_book_id}.png",
  135. "description" => $book->summary ?? "比库戒律的详细说明",
  136. "language" => __('language.' . $book->channel->lang),
  137. ];
  138. });
  139. return $categoryBooks;
  140. }
  141. private function loadCategories()
  142. {
  143. $json = file_get_contents(public_path("date/category/default.json"));
  144. $tree = json_decode($json, true);
  145. $flat = self::flattenWithIds($tree);
  146. return $flat;
  147. }
  148. public static function flattenWithIds(array $tree, int $parentId = 0, int $level = 1): array
  149. {
  150. $flat = [];
  151. foreach ($tree as $node) {
  152. $currentId = self::$nextId++;
  153. $item = [
  154. 'id' => $currentId,
  155. 'parent_id' => $parentId,
  156. 'name' => $node['name'] ?? null,
  157. 'tag' => $node['tag'] ?? [],
  158. "description" => "佛教戒律经典",
  159. 'level' => $level,
  160. ];
  161. $flat[] = $item;
  162. if (isset($node['children']) && is_array($node['children'])) {
  163. $childrenLevel = $level + 1;
  164. $flat = array_merge($flat, self::flattenWithIds($node['children'], $currentId, $childrenLevel));
  165. }
  166. }
  167. return $flat;
  168. }
  169. private function getBreadcrumbs($category, $categories)
  170. {
  171. $breadcrumbs = [];
  172. $current = $category;
  173. while ($current) {
  174. array_unshift($breadcrumbs, $current);
  175. $current = collect($categories)->firstWhere('id', $current['parent_id']);
  176. }
  177. return $breadcrumbs;
  178. }
  179. }