HomeController.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <?php
  2. namespace App\Http\Controllers\Library;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Facades\File;
  6. use App\Models\PaliText;
  7. use App\Models\ProgressChapter;
  8. use App\Models\Tag;
  9. use App\Models\TagMap;
  10. class HomeController extends Controller
  11. {
  12. // 封面渐变色池:uid 首字节取余循环,保证同一文集颜色稳定
  13. private array $coverGradients = [
  14. 'linear-gradient(160deg, #2d1020, #ae6b8b)',
  15. 'linear-gradient(160deg, #1a2d10,rgba(75, 114, 36, 0.61))',
  16. 'linear-gradient(160deg, #0d1f3c,rgb(55, 98, 150))',
  17. 'linear-gradient(160deg, #2d1020,rgb(151, 69, 94))',
  18. 'linear-gradient(160deg, #1a1a2d,rgb(76, 68, 146))',
  19. 'linear-gradient(160deg, #1a2820,rgb(55, 124, 99))',
  20. ];
  21. // -------------------------------------------------------------------------
  22. // 从 uid / id 字符串中提取一个稳定的整数,用于色池取余
  23. // -------------------------------------------------------------------------
  24. private function colorIndex(string $uid): int
  25. {
  26. return hexdec(substr(str_replace('-', '', $uid), 0, 4)) % 255;
  27. }
  28. protected static int $nextId = 1;
  29. public function index()
  30. {
  31. $categories = $this->loadCategories();
  32. // 获取一级分类和对应的书籍
  33. $categoryData = [];
  34. foreach ($categories as $category) {
  35. if ($category['level'] == 1) {
  36. $children = $this->subCategories($categories, $category['id']);
  37. $categoryData[] = [
  38. 'category' => $category,
  39. 'children' => $children,
  40. ];
  41. }
  42. }
  43. $recentBooks = $this->getUpdateBooks();
  44. return view('library.index', compact(
  45. 'categoryData',
  46. 'categories',
  47. 'recentBooks'
  48. ));
  49. }
  50. private function subCategories($categories, int $id)
  51. {
  52. return array_filter($categories, function ($cat) use ($id) {
  53. return $cat['parent_id'] == $id;
  54. });
  55. }
  56. private function getRecent()
  57. {
  58. return [
  59. [
  60. 'id' => 'book-001',
  61. 'title' => '相应部·因缘篇',
  62. 'author' => 'Bhikkhu Bodhi',
  63. 'cover' => null, // 无封面时显示渐变
  64. 'cover_gradient' => 'linear-gradient(135deg, #2d5a8e 0%, #1a3a5c 100%)',
  65. 'updated_at' => '2小时前',
  66. 'is_new' => true, // true=新增, false=更新
  67. 'category' => '经藏',
  68. ],
  69. [
  70. 'id' => 'book-002',
  71. 'title' => '长部·梵网经',
  72. 'author' => 'Bhikkhu Sujato',
  73. 'cover' => null,
  74. 'cover_gradient' => 'linear-gradient(135deg, #5a2d8e 0%, #3a1a5c 100%)',
  75. 'updated_at' => '昨天',
  76. 'is_new' => false,
  77. 'category' => '经藏',
  78. ],
  79. [
  80. 'id' => 'book-003',
  81. 'title' => '法句经注',
  82. 'author' => 'Buddhaghosa',
  83. 'cover' => null,
  84. 'cover_gradient' => 'linear-gradient(135deg, #8e5a2d 0%, #5c3a1a 100%)',
  85. 'updated_at' => '3天前',
  86. 'is_new' => false,
  87. 'category' => '注释',
  88. ],
  89. [
  90. 'id' => 'book-004',
  91. 'title' => '律藏·波罗夷',
  92. 'author' => 'Bhikkhu Brahmali',
  93. 'cover' => null,
  94. 'cover_gradient' => 'linear-gradient(135deg, #2d8e5a 0%, #1a5c3a 100%)',
  95. 'updated_at' => '5天前',
  96. 'is_new' => true,
  97. 'category' => '律藏',
  98. ],
  99. [
  100. 'id' => 'book-005',
  101. 'title' => '清净道论',
  102. 'author' => 'Buddhaghosa',
  103. 'cover' => null,
  104. 'cover_gradient' => 'linear-gradient(135deg, #8e2d2d 0%, #5c1a1a 100%)',
  105. 'updated_at' => '1周前',
  106. 'is_new' => false,
  107. 'category' => '注释',
  108. ],
  109. [
  110. 'id' => 'book-006',
  111. 'title' => '增支部·一集',
  112. 'author' => 'Bhikkhu Bodhi',
  113. 'cover' => null,
  114. 'cover_gradient' => 'linear-gradient(135deg, #2d7a8e 0%, #1a4a5c 100%)',
  115. 'updated_at' => '1周前',
  116. 'is_new' => false,
  117. 'category' => '经藏',
  118. ],
  119. ];
  120. }
  121. private function getUpdateBooks()
  122. {
  123. $books = ProgressChapter::with('channel.owner')
  124. ->leftJoin('pali_texts', function ($join) {
  125. $join->on('progress_chapters.book', '=', 'pali_texts.book')
  126. ->on('progress_chapters.para', '=', 'pali_texts.paragraph');
  127. })
  128. ->whereHas('channel', function ($query) {
  129. $query->where('status', 30);
  130. })
  131. ->where('progress', '>', config('mint.library.list_min_progress'))
  132. ->take(10)
  133. ->get();
  134. return $this->getBooksInfo($books);
  135. }
  136. private function getBooksInfo($books)
  137. {
  138. $pali = PaliText::where('level', 1)->get();
  139. // 获取该分类下的书籍
  140. $categoryBooks = [];
  141. $books->each(function ($book) use (&$categoryBooks, $pali) {
  142. $title = $book->title;
  143. if (empty($title)) {
  144. $title = $pali->firstWhere('book', $book->book)->toc;
  145. }
  146. //Log::debug('getBooksInfo', ['book' => $book->book, 'paragraph' => $book->para]);
  147. $pcd_book_id = $pali->first(function ($item) use ($book) {
  148. return $item->book == $book->book
  149. && $item->paragraph == $book->para;
  150. })?->pcd_book_id;
  151. $coverFile = "/assets/images/cover/zh-hans/1/{$pcd_book_id}.png";
  152. if (File::exists(public_path($coverFile))) {
  153. $coverUrl = $coverFile;
  154. } else {
  155. $coverUrl = null;
  156. }
  157. $colorIdx = $this->colorIndex($book->uid);
  158. $categoryBooks[] = [
  159. "id" => $book->uid,
  160. "title" => $title,
  161. "author" => $book->channel->name,
  162. "publisher" => $book->channel->owner,
  163. "type" => __('labels.' . $book->channel->type),
  164. "cover" => $coverUrl,
  165. 'cover_gradient' => $this->coverGradients[$colorIdx % count($this->coverGradients)],
  166. "description" => $book->summary ?? "比库戒律的详细说明",
  167. "language" => __('language.' . $book->channel->lang),
  168. 'updated_at' => $book->updated_at,
  169. 'is_new' => false, //FIXME
  170. 'category' => '经藏', //FIXME
  171. ];
  172. });
  173. return $categoryBooks;
  174. }
  175. private function loadCategories()
  176. {
  177. $json = file_get_contents(public_path("data/category/default.json"));
  178. $tree = json_decode($json, true);
  179. $flat = self::flattenWithIds($tree);
  180. return $flat;
  181. }
  182. public static function flattenWithIds(array $tree, int $parentId = 0, int $level = 1): array
  183. {
  184. $flat = [];
  185. foreach ($tree as $node) {
  186. $currentId = self::$nextId++;
  187. $item = [
  188. 'id' => $currentId,
  189. 'parent_id' => $parentId,
  190. 'name' => $node['name'] ?? null,
  191. 'tag' => $node['tag'] ?? [],
  192. "description" => "佛教戒律经典",
  193. 'level' => $level,
  194. ];
  195. $flat[] = $item;
  196. if (isset($node['children']) && is_array($node['children'])) {
  197. $childrenLevel = $level + 1;
  198. $flat = array_merge($flat, self::flattenWithIds($node['children'], $currentId, $childrenLevel));
  199. }
  200. }
  201. return $flat;
  202. }
  203. }