Home.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template>
  2. <div>
  3. <TopNav @tab-change="handleTabChange" />
  4. <div class="top-placeholder"></div>
  5. <van-pull-refresh v-model="isRefreshing" @refresh="onRefresh">
  6. <van-list
  7. v-model="isLoading"
  8. :finished="isFinished"
  9. finished-text="没有更多了"
  10. @load="onLoad"
  11. >
  12. <div v-if="currentTab === 'recommend'" class="video-container">
  13. <VideoCard
  14. v-for="item in dataList"
  15. :key="item.videoId"
  16. :video="item"
  17. @click="$router.push(`/video/${item.videoId}`)"
  18. />
  19. </div>
  20. <div v-else class="hot-list">
  21. <div
  22. v-for="item in hotList"
  23. :key="item.videoId"
  24. class="hot-item"
  25. @click="$router.push(`/video/${item.videoId}`)"
  26. >
  27. <van-card :title="item.title" :thumb="item.coverUrl">
  28. <template #desc>
  29. <div class="card-desc">
  30. <p class="author">UP主:{{ item.user ? item.user.screenName : '未知' }}</p>
  31. <p class="stats">{{ item.view }}播放 · {{ item.pubDateStr || '刚刚' }}</p>
  32. </div>
  33. </template>
  34. <template #footer>
  35. <van-icon name="ellipsis" size="18" color="#999" />
  36. </template>
  37. </van-card>
  38. </div>
  39. </div>
  40. </van-list>
  41. </van-pull-refresh>
  42. </div>
  43. </template>
  44. <script>
  45. import TopNav from '@/components/TopNav.vue'
  46. import VideoCard from '@/components/VideoCard.vue'
  47. import { getHotVideo, videoRecommend } from '@/api/vod'
  48. export default {
  49. name: 'Home',
  50. components: {
  51. TopNav,
  52. VideoCard
  53. },
  54. data() {
  55. return {
  56. currentTab: 'recommend', // 默认为推荐
  57. nextId: 0,
  58. hotList: [],
  59. dataList: [],
  60. isLoading: false,
  61. isFinished: false,
  62. isRefreshing: false
  63. }
  64. },
  65. methods: {
  66. handleTabChange(type) {
  67. this.currentTab = type
  68. this.onRefresh()
  69. },
  70. // 模拟从后端获取数据
  71. async onLoad() {
  72. if (this.currentTab === 'hot') {
  73. this.dataList = []
  74. this.nextId = 0
  75. getHotVideo().then((resp) => {
  76. if (resp.code === 0) {
  77. this.hotList = resp.data
  78. } else {
  79. this.$toast(resp.msg)
  80. }
  81. })
  82. this.isFinished = true
  83. return
  84. }
  85. videoRecommend(this.nextId)
  86. .then((resp) => {
  87. if (resp.code === 0) {
  88. const respData = resp.data
  89. if (respData.length === 0) {
  90. this.$toast('已经到底啦~~~')
  91. return
  92. }
  93. if (this.isRefreshing) {
  94. this.dataList = []
  95. this.isRefreshing = false
  96. }
  97. this.dataList.push(...respData)
  98. this.isLoading = false
  99. if (this.dataList.length >= 1000) {
  100. this.isFinished = true
  101. }
  102. this.nextId++
  103. } else {
  104. this.$toast('获取数据失败, 请重新刷新页面')
  105. }
  106. })
  107. .catch((error) => {
  108. this.$toast(error.message)
  109. })
  110. },
  111. onRefresh() {
  112. this.isFinished = false
  113. this.isLoading = true
  114. this.onLoad()
  115. }
  116. }
  117. }
  118. </script>
  119. <style scoped lang="less">
  120. .top-placeholder {
  121. height: 94px;
  122. }
  123. .video-container {
  124. display: flex;
  125. flex-wrap: wrap;
  126. justify-content: space-between;
  127. padding: 8px 12px;
  128. background-color: #f4f4f4;
  129. // 关键:控制 VideoCard 在两列布局中的宽度
  130. /deep/ .video-card {
  131. width: 48.5%; // 留出中间的间隙
  132. }
  133. }
  134. // 热门模式样式
  135. .hot-list {
  136. background-color: #fff;
  137. .hot-item {
  138. border-bottom: 1px solid #f0f0f0;
  139. ::v-deep .van-card {
  140. background-color: #fff;
  141. padding: 12px;
  142. .van-card__title {
  143. font-size: 14px;
  144. font-weight: 500;
  145. line-height: 1.4;
  146. max-height: 40px;
  147. display: -webkit-box;
  148. -webkit-line-clamp: 2;
  149. -webkit-box-orient: vertical;
  150. overflow: hidden;
  151. }
  152. .van-card__thumb {
  153. width: 120px;
  154. height: 75px;
  155. border-radius: 4px;
  156. overflow: hidden;
  157. }
  158. }
  159. }
  160. .card-desc {
  161. margin-top: 8px;
  162. font-size: 12px;
  163. color: #999;
  164. p {
  165. margin: 2px 0;
  166. }
  167. .author {
  168. color: #666;
  169. }
  170. }
  171. }
  172. </style>