index.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // pages/index/index.js
  2. const contentApi = require('../../api/content');
  3. const categoryApi = require('../../api/category');
  4. const userUtil = require('../../utils/user');
  5. Page({
  6. data: {
  7. categories: [],
  8. currentCategory: 0, // 0表示全部
  9. contentList: [],
  10. bannerList: [], // 轮播图数据
  11. recommendedList: [], // 今日推荐数据
  12. contentType: null, // null全部, 1电子书, 2听书
  13. keyword: '',
  14. current: 1,
  15. size: 10,
  16. total: 0,
  17. loading: false,
  18. hasMore: true,
  19. showSearch: false,
  20. swiperMarginTop: 'calc(130rpx + env(safe-area-inset-top))', // 轮播图的上边距
  21. recommendedColumns: 3 // 推荐区域每行显示数量(2或3)
  22. },
  23. onLoad() {
  24. this.loadCategories();
  25. this.loadBannerList();
  26. this.loadRecommended();
  27. this.loadContentList();
  28. },
  29. onShow() {
  30. // 首页不需要强制登录,可以浏览
  31. },
  32. // 加载分类
  33. async loadCategories() {
  34. try {
  35. const categories = await categoryApi.getCategoryList();
  36. this.setData({
  37. categories: [{ categoryId: 0, categoryName: '全部' }, ...categories]
  38. });
  39. } catch (error) {
  40. console.error('加载分类失败:', error);
  41. }
  42. },
  43. // 加载轮播图数据(取前5条热门内容)
  44. async loadBannerList() {
  45. try {
  46. const result = await contentApi.getContentList(1, 5, '', null, null);
  47. this.setData({
  48. bannerList: result.records || []
  49. });
  50. } catch (error) {
  51. console.error('加载轮播图失败:', error);
  52. }
  53. },
  54. // 加载今日推荐数据
  55. async loadRecommended() {
  56. try {
  57. const size = this.data.recommendedColumns === 2 ? 4 : 6; // 每行2个显示4个,每行3个显示6个
  58. const recommended = await contentApi.getRecommended(size);
  59. this.setData({
  60. recommendedList: recommended || []
  61. });
  62. } catch (error) {
  63. console.error('加载今日推荐失败:', error);
  64. }
  65. },
  66. // 加载内容列表
  67. async loadContentList(isLoadMore = false) {
  68. if (this.data.loading) return;
  69. this.setData({ loading: true });
  70. try {
  71. const current = isLoadMore ? this.data.current + 1 : 1;
  72. const params = {
  73. current,
  74. size: this.data.size,
  75. categoryId: this.data.currentCategory === 0 ? null : this.data.currentCategory,
  76. contentType: this.data.contentType,
  77. keyword: this.data.keyword || null
  78. };
  79. const result = await contentApi.getContentList(
  80. params.current,
  81. params.size,
  82. params.keyword || '',
  83. params.contentType,
  84. params.categoryId
  85. );
  86. const contentList = isLoadMore
  87. ? [...this.data.contentList, ...result.records]
  88. : result.records;
  89. this.setData({
  90. contentList,
  91. current: result.current,
  92. total: result.total,
  93. hasMore: contentList.length < result.total,
  94. loading: false
  95. });
  96. } catch (error) {
  97. wx.showToast({
  98. title: error || '加载失败',
  99. icon: 'none'
  100. });
  101. this.setData({ loading: false });
  102. }
  103. },
  104. // 切换分类
  105. onCategoryTap(e) {
  106. const categoryId = e.currentTarget.dataset.id;
  107. if (categoryId === this.data.currentCategory) return;
  108. this.setData({
  109. currentCategory: categoryId,
  110. current: 1
  111. });
  112. this.loadContentList();
  113. },
  114. // 切换内容类型
  115. onContentTypeTap(e) {
  116. const type = e.currentTarget.dataset.type;
  117. // 将字符串 "null" 转换为真正的 null
  118. const contentType = type === 'null' ? null : parseInt(type);
  119. if (contentType === this.data.contentType) return;
  120. this.setData({
  121. contentType: contentType,
  122. current: 1
  123. });
  124. this.loadContentList();
  125. },
  126. // 搜索
  127. onSearchInput(e) {
  128. this.setData({
  129. keyword: e.detail.value
  130. });
  131. },
  132. onSearchConfirm() {
  133. this.setData({ current: 1 });
  134. this.loadContentList();
  135. },
  136. // 显示/隐藏搜索框
  137. toggleSearch() {
  138. const newShowSearch = !this.data.showSearch;
  139. this.setData({
  140. showSearch: newShowSearch,
  141. keyword: '',
  142. current: 1
  143. });
  144. // 动态调整轮播图的margin-top
  145. if (newShowSearch) {
  146. // 搜索框显示时,轮播图需要再向下移动
  147. this.setData({
  148. swiperMarginTop: 'calc(200rpx + env(safe-area-inset-top))'
  149. });
  150. } else {
  151. // 搜索框隐藏时,恢复原来的位置
  152. this.setData({
  153. swiperMarginTop: 'calc(130rpx + env(safe-area-inset-top))'
  154. });
  155. this.loadContentList();
  156. }
  157. },
  158. // 跳转到详情页
  159. goToDetail(e) {
  160. const contentId = e.currentTarget.dataset.id;
  161. wx.navigateTo({
  162. url: `/pages/detail/detail?id=${contentId}`
  163. });
  164. },
  165. // 上拉加载更多
  166. onReachBottom() {
  167. if (this.data.hasMore && !this.data.loading) {
  168. this.loadContentList(true);
  169. }
  170. },
  171. // 下拉刷新
  172. onPullDownRefresh() {
  173. this.setData({ current: 1 });
  174. this.loadContentList().finally(() => {
  175. wx.stopPullDownRefresh();
  176. });
  177. }
  178. });