图书馆小程序
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.

148 lines
3.5 KiB

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
1 month ago
2 months ago
1 month ago
1 month 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. <template>
  2. <view class="container">
  3. <!-- 图书列表 -->
  4. <view class="list-box">
  5. <book-list-item
  6. v-for="(item, index) in bookList"
  7. :key="index"
  8. :data="item"
  9. :ranking="index + 1"
  10. @click="goToDetail(item)"
  11. />
  12. </view>
  13. <!-- 加载提示 -->
  14. <view class="load-tip" v-if="loading">加载中...</view>
  15. <view class="load-tip" v-if="noMore">没有更多了</view>
  16. </view>
  17. </template>
  18. <script>
  19. import bookListItem from "@/components/book-list-item/book-list-item.vue";
  20. import { FetchInitScreenBookRecommend } from '@/api/book';
  21. import config from '@/utils/config';
  22. export default {
  23. components: {
  24. bookListItem
  25. },
  26. data() {
  27. return {
  28. bookList: [],
  29. loading: false,
  30. noMore: false,
  31. baseUrl: config.baseUrl
  32. };
  33. },
  34. onLoad() {
  35. this.getBookRecommendList();
  36. },
  37. onPullDownRefresh() {
  38. this.refresh();
  39. },
  40. methods: {
  41. urlToBase64(url) {
  42. return new Promise((resolve, reject) => {
  43. uni.request({
  44. url,
  45. method: 'GET',
  46. responseType: 'arraybuffer',
  47. success: (res) => {
  48. try {
  49. const buffer = new Uint8Array(res.data);
  50. let binary = '';
  51. for (let i = 0; i < buffer.length; i++) {
  52. binary += String.fromCharCode(buffer[i]);
  53. }
  54. const base64 = uni.arrayBufferToBase64(res.data);
  55. const dataUri = 'data:image/jpeg;base64,' + base64;
  56. resolve(dataUri);
  57. } catch (e) {
  58. reject(e);
  59. }
  60. },
  61. fail: reject
  62. });
  63. });
  64. },
  65. // 刷新
  66. refresh() {
  67. this.bookList = [];
  68. this.noMore = false;
  69. this.getBookRecommendList();
  70. },
  71. // 获取列表 + 挨个依次加载图片
  72. async getBookRecommendList() {
  73. this.loading = true;
  74. try {
  75. const res = await FetchInitScreenBookRecommend({ libcode: '1201' });
  76. let books = res.data || [];
  77. // 1. 先显示列表(图片为空,显示默认图)
  78. books = books.map(item => {
  79. item.base64Cover = '';
  80. return item;
  81. });
  82. this.bookList = books;
  83. this.noMore = true;
  84. this.loading = false;
  85. uni.stopPullDownRefresh();
  86. // 2. 延迟一点点,等页面渲染完
  87. setTimeout(() => {
  88. this.loadImagesOneByOne(); // 挨个加载图片
  89. }, 200);
  90. } catch (err) {
  91. console.error(err);
  92. this.loading = false;
  93. uni.stopPullDownRefresh();
  94. }
  95. },
  96. async loadImagesOneByOne() {
  97. for (let i = 0; i < this.bookList.length; i++) {
  98. let item = this.bookList[i];
  99. if (!item.imgPath) continue;
  100. // 加载当前这张
  101. const url = this.baseUrl + '/api/fileRelevant/getImg?imgType=2&imgId=' + item.imgPath;
  102. const base64 = await this.urlToBase64(url);
  103. if (base64) {
  104. item.base64Cover = base64;
  105. this.$set(this.bookList, i, item); // 强制更新视图
  106. }
  107. }
  108. },
  109. goToDetail(item) {
  110. uni.navigateTo({
  111. url: "/subpkg/pages/book-detail/book-detail?bookData=" + encodeURIComponent(JSON.stringify(item))
  112. })
  113. },
  114. }
  115. };
  116. </script>
  117. <style lang="scss" scoped>
  118. .container {
  119. padding: 10px;
  120. background-color: #f5f5f5;
  121. min-height: 100vh;
  122. }
  123. .list-box {
  124. display: flex;
  125. flex-direction: column;
  126. gap: 8px;
  127. }
  128. .load-tip {
  129. text-align: center;
  130. padding: 15px;
  131. font-size: 14px;
  132. color: #999;
  133. }
  134. </style>