图书馆小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
5.7 KiB

2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
  1. <template>
  2. <view class="collection-page">
  3. <view class="content-box">
  4. <view class="empty" v-if="bookCollectList.length === 0 && !isLoading">
  5. <uni-icons style="margin-left: 20px;" custom-prefix="iconfont" type="icon-kongshuju" size="80"></uni-icons>
  6. <text style="margin-top: 20px;">暂无收藏的图书~</text>
  7. </view>
  8. <view class="recommendation-list" v-else>
  9. <book-list-item
  10. class="hot-list-item"
  11. v-for="(item, index) in bookCollectList"
  12. :key="index"
  13. :data="item"
  14. :ranking="index + 1"
  15. @click="onItemClick(item)"
  16. ></book-list-item>
  17. </view>
  18. <uni-load-more status="loading" v-if="isLoading && bookCollectList.length > 0"></uni-load-more>
  19. <view class="no-more" v-if="noMore && bookCollectList.length > 0">
  20. 没有更多数据了
  21. </view>
  22. </view>
  23. </view>
  24. </template>
  25. <script>
  26. import BookListItem from "@/components/book-list-item/book-list-item.vue";
  27. import { FetchFindAllBookCollectionByOpenId } from '@/api/book';
  28. import { getOpenId } from '@/utils/storage';
  29. import config from '@/utils/config';
  30. import { loadBookCoversBase64 } from '@/utils/bookCover';
  31. export default {
  32. components: {
  33. BookListItem,
  34. },
  35. data() {
  36. return {
  37. isLoading: false,
  38. noMore: false,
  39. pageNum: 0,
  40. pageSize: 10,
  41. bookCollectList: [],
  42. hasLoadedAll: false,
  43. }
  44. },
  45. onLoad() {
  46. },
  47. onShow() {
  48. // 检查是否需要刷新(从图书详情取消收藏回来)
  49. const needRefresh = uni.getStorageSync('needRefreshCollect');
  50. uni.removeStorageSync('needRefreshCollect');
  51. // 如果已经加载到最后,或者有取消收藏操作,需要刷新数据
  52. if (this.hasLoadedAll || needRefresh) {
  53. this.refreshData();
  54. } else if (this.bookCollectList.length === 0) {
  55. // 如果还没加载过数据,也需要加载
  56. this.refreshData();
  57. }
  58. },
  59. onPullDownRefresh() {
  60. this.refreshData();
  61. },
  62. onReachBottom() {
  63. if (this.noMore || this.isLoading) return;
  64. this.loadMore();
  65. },
  66. methods: {
  67. async loadData() {
  68. this.isLoading = true;
  69. try {
  70. const openId = await getOpenId();
  71. if (!openId) {
  72. uni.showToast({ title: '获取用户信息失败', icon: 'none' });
  73. this.isLoading = false;
  74. return;
  75. }
  76. const res = await FetchFindAllBookCollectionByOpenId({
  77. libcode: config.LIB_CODE,
  78. openId: openId,
  79. page: this.pageNum,
  80. size: this.pageSize,
  81. });
  82. if (res.code === 200) {
  83. this.bookCollectList = res.data.content || [];
  84. this.noMore = (res.data.content || []).length < this.pageSize;
  85. this.hasLoadedAll = this.noMore;
  86. // 加载封面
  87. this.loadCoversForList();
  88. } else {
  89. uni.showToast({ title: res.message || '获取收藏列表失败', icon: 'none' });
  90. }
  91. } catch (err) {
  92. console.error('获取收藏列表失败', err);
  93. uni.showToast({ title: '获取收藏列表失败', icon: 'none' });
  94. } finally {
  95. this.isLoading = false;
  96. }
  97. },
  98. async refreshData() {
  99. this.pageNum = 0;
  100. this.noMore = false;
  101. this.bookCollectList = [];
  102. await this.loadData();
  103. // 滚动条回到顶部
  104. uni.pageScrollTo({
  105. scrollTop: 0,
  106. duration: 300
  107. });
  108. uni.stopPullDownRefresh();
  109. },
  110. async loadMore() {
  111. if (this.noMore || this.isLoading) return;
  112. this.pageNum++;
  113. this.isLoading = true;
  114. try {
  115. const openId = await getOpenId();
  116. if (!openId) {
  117. uni.showToast({ title: '获取用户信息失败', icon: 'none' });
  118. this.isLoading = false;
  119. return;
  120. }
  121. const res = await FetchFindAllBookCollectionByOpenId({
  122. libcode: config.LIB_CODE,
  123. openId: openId,
  124. page: this.pageNum,
  125. size: this.pageSize,
  126. });
  127. if (res.code === 200) {
  128. const newData = res.data.content || [];
  129. this.bookCollectList = [...this.bookCollectList, ...newData];
  130. this.noMore = newData.length < this.pageSize;
  131. // 为新加载的数据加载封面
  132. if (newData.length > 0) {
  133. await this.loadCoversForList();
  134. }
  135. } else {
  136. this.pageNum--;
  137. uni.showToast({ title: res.message || '加载更多失败', icon: 'none' });
  138. }
  139. } catch (err) {
  140. console.error('加载更多收藏失败', err);
  141. this.pageNum--;
  142. uni.showToast({ title: '加载更多失败', icon: 'none' });
  143. } finally {
  144. this.isLoading = false;
  145. }
  146. },
  147. async loadCoversForList() {
  148. await loadBookCoversBase64(this.bookCollectList, (index, coverUrl) => {
  149. if (this.bookCollectList[index]) {
  150. this.$set(this.bookCollectList[index], 'cover', coverUrl);
  151. }
  152. });
  153. },
  154. onItemClick(item) {
  155. uni.navigateTo({
  156. url: "/subpkg/pages/book-detail/book-detail?searchData=" + encodeURIComponent(JSON.stringify(item)) + '&isCollected=true'
  157. })
  158. }
  159. }
  160. }
  161. </script>
  162. <style lang="scss" scoped>
  163. .collection-page {
  164. padding: 10px 0;
  165. background-color: #f7f8fa;
  166. min-height: 100vh;
  167. }
  168. .content-box {
  169. padding: 0 10px;
  170. }
  171. .empty {
  172. padding: 60px 0;
  173. text-align: center;
  174. color: #999;
  175. }
  176. .no-more {
  177. text-align: center;
  178. padding: 20px 0;
  179. color: #999;
  180. font-size: 13px;
  181. }
  182. .recommendation-list {
  183. display: flex;
  184. flex-direction: column;
  185. gap: 12px;
  186. }
  187. .book-item {
  188. display: flex;
  189. background: #fff;
  190. border-radius: 8px;
  191. padding: 12px;
  192. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  193. }
  194. .book-cover {
  195. width: 80px;
  196. height: 100px;
  197. border-radius: 4px;
  198. flex-shrink: 0;
  199. background: #f5f5f5;
  200. }
  201. .book-info {
  202. flex: 1;
  203. display: flex;
  204. flex-direction: column;
  205. justify-content: center;
  206. padding-left: 12px;
  207. overflow: hidden;
  208. }
  209. .book-title {
  210. font-size: 15px;
  211. font-weight: 500;
  212. color: #333;
  213. line-height: 1.4;
  214. display: -webkit-box;
  215. -webkit-box-orient: vertical;
  216. -webkit-line-clamp: 2;
  217. overflow: hidden;
  218. }
  219. .book-author {
  220. font-size: 13px;
  221. color: #999;
  222. margin-top: 6px;
  223. }
  224. .book-publisher {
  225. font-size: 12px;
  226. color: #ccc;
  227. margin-top: 4px;
  228. }
  229. </style>