program.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <template>
  2. <view class="sports-page">
  3. <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
  4. :up="upOption">
  5. <view class="sports-list">
  6. <view class="sport-card" v-for="(sport, index) in sportsList" :key="index"
  7. @click="handleSportClick(sport)">
  8. <view class="card-image-wrapper">
  9. <image class="card-image" :src="sport.secondImg" mode="aspectFill"></image>
  10. </view>
  11. <view class="card-title">{{ sport.courseName }}</view>
  12. <view class="card-footer">
  13. <text class="play-count">{{ sport.views }}次播放</text>
  14. <image class="w32 h32" src="@/static/images/enter/layer_share_icon16.png"></image>
  15. </view>
  16. </view>
  17. </view>
  18. <!-- 底部安全区域 -->
  19. <view class="safe-area-bottom" :style="{ height: safeAreaBottom + 'px' }"></view>
  20. </mescroll-body>
  21. </view>
  22. </template>
  23. <script>
  24. import {
  25. getCourseList,
  26. getCourseCate
  27. } from '@/api/course'
  28. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  29. export default {
  30. mixins: [MescrollMixin],
  31. data() {
  32. return {
  33. statusBarHeight: 0,
  34. safeAreaBottom: 0,
  35. sportsList: [],
  36. cateId: '',
  37. status: 'loadmore',
  38. totalPage: 1,
  39. triggered: false,
  40. mescroll: null,
  41. downOption: { //下拉刷新
  42. use: true,
  43. auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
  44. },
  45. upOption: {
  46. onScroll: false,
  47. use: true, // 是否启用上拉加载; 默认true
  48. page: {
  49. pae: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
  50. size: 10 // 每页数据的数量,默认10
  51. },
  52. noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
  53. textNoMore: "已经到底了",
  54. empty: {
  55. icon: 'https://zkzh-2025.oss-cn-beijing.aliyuncs.com/appimgs/cf4a86b913a04341bb44e34bb4d37aa2.png',
  56. tip: '暂无数据'
  57. }
  58. },
  59. }
  60. },
  61. onLoad(options) {
  62. if (options.cateId) {
  63. this.cateId = options.cateId
  64. this.setNavTitle(this.cateId)
  65. }
  66. this.getSystemInfo();
  67. },
  68. methods: {
  69. mescrollInit(mescroll) {
  70. this.mescroll = mescroll;
  71. },
  72. /*下拉刷新的回调 */
  73. downCallback(mescroll) {
  74. mescroll.resetUpScroll()
  75. },
  76. upCallback(page) {
  77. let that = this;
  78. let paramsData = {
  79. pageNum: page.num,
  80. pageSize: page.size,
  81. limit: page.size,
  82. cateId: this.cateId
  83. };
  84. getCourseList(paramsData).then(res => {
  85. if (res.code == 200) {
  86. if (page.num == 1) {
  87. that.sportsList = res.data.list;
  88. } else {
  89. that.sportsList = that.sportsList.concat(res.data.list);
  90. }
  91. that.mescroll.endBySize(res.data.list.length, res.data.total);
  92. } else {
  93. uni.showToast({
  94. icon: 'none',
  95. title: "请求失败",
  96. });
  97. that.sportsList = null;
  98. that.mescroll.endErr();
  99. }
  100. });
  101. },
  102. setNavTitle(type) {
  103. let arr = ['', '节目', '运动', '热播剧', '戏曲评书']
  104. uni.setNavigationBarTitle({
  105. title: arr[type]
  106. });
  107. },
  108. getSystemInfo() {
  109. const systemInfo = uni.getSystemInfoSync();
  110. this.statusBarHeight = systemInfo.statusBarHeight || 0;
  111. if (systemInfo.safeArea) {
  112. this.safeAreaBottom = systemInfo.screenHeight - systemInfo.safeArea.bottom;
  113. }
  114. },
  115. handleBack() {
  116. uni.navigateBack();
  117. },
  118. handleSportClick(sport) {
  119. uni.navigateTo({
  120. url: `/pages/course/info?courseId=${sport.courseId}`
  121. });
  122. },
  123. }
  124. }
  125. </script>
  126. <style lang="scss" scoped>
  127. .sports-page {
  128. width: 100%;
  129. min-height: 100vh;
  130. background-color: #ffffff;
  131. display: flex;
  132. flex-direction: column;
  133. }
  134. .status-bar {
  135. width: 100%;
  136. background-color: #ffffff;
  137. }
  138. .nav-bar {
  139. width: 100%;
  140. height: 88rpx;
  141. background-color: #ffffff;
  142. display: flex;
  143. align-items: center;
  144. justify-content: center;
  145. position: relative;
  146. border-bottom: 1rpx solid #f0f0f0;
  147. .nav-back {
  148. position: absolute;
  149. left: 30rpx;
  150. width: 60rpx;
  151. height: 60rpx;
  152. display: flex;
  153. align-items: center;
  154. justify-content: center;
  155. }
  156. .nav-title {
  157. font-size: 36rpx;
  158. font-weight: 500;
  159. color: #333333;
  160. }
  161. }
  162. .page-content {
  163. flex: 1;
  164. width: 100%;
  165. }
  166. .sports-list {
  167. width: 100%;
  168. padding: 30rpx;
  169. display: grid;
  170. grid-template-columns: repeat(2, 1fr);
  171. gap: 30rpx;
  172. }
  173. .sport-card {
  174. width: 100%;
  175. background-color: #ffffff;
  176. border-radius: 16rpx;
  177. overflow: hidden;
  178. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  179. display: flex;
  180. flex-direction: column;
  181. }
  182. .card-image-wrapper {
  183. width: 100%;
  184. height: 320rpx;
  185. position: relative;
  186. overflow: hidden;
  187. }
  188. .card-image {
  189. width: 100%;
  190. height: 100%;
  191. background-color: #f0f0f0;
  192. }
  193. .image-overlay {
  194. position: absolute;
  195. bottom: 0;
  196. left: 0;
  197. right: 0;
  198. padding: 20rpx;
  199. background: linear-gradient(to top, rgba(0, 0, 0, 0.6), transparent);
  200. }
  201. .overlay-title {
  202. font-size: 40rpx;
  203. font-weight: bold;
  204. color: #ffffff;
  205. text-align: center;
  206. margin-bottom: 12rpx;
  207. border-bottom: 4rpx solid;
  208. padding-bottom: 8rpx;
  209. text-shadow: 2rpx 2rpx 4rpx rgba(0, 0, 0, 0.5);
  210. line-height: 1.3;
  211. }
  212. .overlay-banner {
  213. background-color: #FF69B4;
  214. color: #ffffff;
  215. padding: 8rpx 16rpx;
  216. border-radius: 8rpx;
  217. font-size: 22rpx;
  218. text-align: center;
  219. width: fit-content;
  220. margin: 0 auto;
  221. }
  222. .image-year {
  223. position: absolute;
  224. top: 20rpx;
  225. right: 20rpx;
  226. font-size: 32rpx;
  227. font-weight: bold;
  228. color: #ffffff;
  229. text-shadow: 2rpx 2rpx 4rpx rgba(0, 0, 0, 0.5);
  230. }
  231. .card-title {
  232. font-size: 32rpx;
  233. font-weight: 600;
  234. color: #333333;
  235. padding: 20rpx;
  236. padding-bottom: 12rpx;
  237. }
  238. .card-footer {
  239. display: flex;
  240. align-items: center;
  241. justify-content: space-between;
  242. padding: 0 20rpx 20rpx;
  243. }
  244. .play-count {
  245. font-size: 24rpx;
  246. color: #999999;
  247. }
  248. .safe-area-bottom {
  249. width: 100%;
  250. height: 40rpx;
  251. }
  252. </style>