├── php-api/ # 改造后的PHP接口层 ├── java-ad-service/ # 若依框架微服务(广告+VIP+分账) ├── uniapp-reader/ # UniApp前端项目 │ ├── pages/ # 各端页面 │ └──
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

index.vue 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <template>
  2. <view class="bookshelf">
  3. <!-- 顶部导航 -->
  4. <view class="header">
  5. <text class="title">我的书架</text>
  6. <view class="actions">
  7. <uni-icons type="plus" size="24" color="#333" @click="addBook"></uni-icons>
  8. <uni-icons type="search" size="24" color="#333" @click="searchBooks"></uni-icons>
  9. </view>
  10. </view>
  11. <!-- 书架内容 -->
  12. <view v-if="books.length > 0" class="book-grid">
  13. <view v-for="book in books" :key="book.id" class="book-item" @click="readBook(book)">
  14. <image :src="book.cover" class="cover" />
  15. <text class="book-title">{{ book.title }}</text>
  16. <text class="progress">阅读到: {{ book.progress }}%</text>
  17. </view>
  18. </view>
  19. <!-- 空书架提示 -->
  20. <view v-else class="empty">
  21. <image src="/static/empty-bookshelf.png" class="empty-img" />
  22. <text class="empty-text">书架空空如也</text>
  23. <button class="btn-find" @click="goToHome">去发现好书</button>
  24. </view>
  25. </view>
  26. </template>
  27. <script>
  28. export default {
  29. data() {
  30. return {
  31. books: [
  32. // 从后端获取实际数据
  33. {
  34. id: 101,
  35. title: "万古神帝",
  36. cover: "/static/book1.jpg",
  37. progress: 65,
  38. lastChapter: 125
  39. }
  40. ]
  41. }
  42. },
  43. onLoad() {
  44. this.loadBookshelf()
  45. },
  46. methods: {
  47. async loadBookshelf() {
  48. try {
  49. // 调用后端API获取书架数据
  50. const res = await this.$http.get('/bookshelf', {
  51. headers: {
  52. 'Authorization': `Bearer ${uni.getStorageSync('token')}`
  53. }
  54. })
  55. if (res.data.code === 0) {
  56. this.books = res.data.data
  57. }
  58. } catch (error) {
  59. uni.showToast({
  60. title: '加载书架失败',
  61. icon: 'none'
  62. })
  63. }
  64. },
  65. readBook(book) {
  66. uni.navigateTo({
  67. url: `/pages/novel/reader?novelId=${book.id}&chapterId=${book.lastChapter}`
  68. })
  69. },
  70. goToHome() {
  71. uni.switchTab({
  72. url: '/pages/index/index'
  73. })
  74. },
  75. addBook() {
  76. uni.navigateTo({
  77. url: '/pages/search/index'
  78. })
  79. },
  80. searchBooks() {
  81. uni.navigateTo({
  82. url: '/pages/search/index'
  83. })
  84. }
  85. }
  86. }
  87. </script>
  88. <style scoped>
  89. .bookshelf {
  90. padding: 20rpx;
  91. }
  92. .header {
  93. display: flex;
  94. justify-content: space-between;
  95. align-items: center;
  96. padding: 20rpx 0;
  97. border-bottom: 1px solid #eee;
  98. }
  99. .title {
  100. font-size: 36rpx;
  101. font-weight: bold;
  102. }
  103. .actions {
  104. display: flex;
  105. gap: 30rpx;
  106. }
  107. .book-grid {
  108. display: grid;
  109. grid-template-columns: repeat(3, 1fr);
  110. gap: 30rpx;
  111. margin-top: 30rpx;
  112. }
  113. .book-item {
  114. display: flex;
  115. flex-direction: column;
  116. }
  117. .cover {
  118. width: 200rpx;
  119. height: 280rpx;
  120. border-radius: 8rpx;
  121. box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
  122. }
  123. .book-title {
  124. font-size: 28rpx;
  125. margin-top: 10rpx;
  126. overflow: hidden;
  127. text-overflow: ellipsis;
  128. display: -webkit-box;
  129. -webkit-line-clamp: 1;
  130. -webkit-box-orient: vertical;
  131. }
  132. .progress {
  133. font-size: 24rpx;
  134. color: #666;
  135. }
  136. .empty {
  137. display: flex;
  138. flex-direction: column;
  139. align-items: center;
  140. justify-content: center;
  141. height: 60vh;
  142. }
  143. .empty-img {
  144. width: 300rpx;
  145. height: 300rpx;
  146. opacity: 0.6;
  147. }
  148. .empty-text {
  149. font-size: 32rpx;
  150. color: #999;
  151. margin: 30rpx 0;
  152. }
  153. .btn-find {
  154. background-color: #2a5caa;
  155. color: white;
  156. width: 60%;
  157. border-radius: 50rpx;
  158. }
  159. </style>