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

156 lines
3.5 KiB

2 weeks ago
  1. <template>
  2. <view class="activity-list">
  3. <!-- 下拉刷新区域 -->
  4. <scroll-view
  5. scroll-y
  6. refresher-enabled
  7. :refresher-triggered="refreshing"
  8. @refresherrefresh="onRefresh"
  9. @scrolltolower="onLoadMore"
  10. lower-threshold="100"
  11. >
  12. <view class="activity-item" v-for="(item, index) in activityList" @click="toActivityDetail(item)" :key="index">
  13. <image class="activity-img" :src="item.imgUrl"></image>
  14. <view class="activity-info">
  15. <view class="activity-info-left">
  16. <text class="title">{{ item.title }}</text>
  17. <view class="time">
  18. <uni-icons class="time-icon" custom-prefix="iconfont" type="icon-shijian" size="15"></uni-icons>
  19. <text>{{ item.time }}</text>
  20. </view>
  21. </view>
  22. <button
  23. class="activity-btn"
  24. :class="item.status === 0 ? 'disabled-btn' : ''"
  25. type="primary"
  26. :disabled="item.status === 0"
  27. >
  28. {{ item.status === 1 ? '立即参加' : '活动结束' }}
  29. </button>
  30. </view>
  31. </view>
  32. <!-- 加载提示 -->
  33. <view class="load-tip" v-if="loading">
  34. <text>加载中...</text>
  35. </view>
  36. <view class="load-tip" v-if="noMore">
  37. <text>没有更多数据了</text>
  38. </view>
  39. </scroll-view>
  40. </view>
  41. </template>
  42. <script>
  43. export default {
  44. data() {
  45. return {
  46. activityList: [], // 活动列表数据
  47. refreshing: false, // 下拉刷新状态
  48. loading: false, // 加载中
  49. noMore: false, // 是否没有更多数据
  50. page: 1, // 当前页码
  51. pageSize: 5, // 每页条数
  52. total: 20, // 模拟总数据量
  53. };
  54. },
  55. onLoad() {
  56. // 页面加载时获取第一页数据
  57. this.getActivityList();
  58. },
  59. methods: {
  60. /**
  61. * 模拟请求活动列表接口
  62. * @param {Number} page 页码
  63. * @param {Number} pageSize 每页条数
  64. */
  65. getActivityList() {
  66. this.loading = true;
  67. // 模拟网络请求延迟
  68. setTimeout(() => {
  69. // 生成模拟数据
  70. const list = this.mockData(this.page, this.pageSize);
  71. // 下拉刷新:直接替换数据
  72. if (this.refreshing) {
  73. this.activityList = list;
  74. this.refreshing = false;
  75. } else {
  76. // 上拉加载:追加数据
  77. this.activityList = [...this.activityList, ...list];
  78. }
  79. // 判断是否还有更多数据
  80. if (this.activityList.length >= this.total) {
  81. this.noMore = true;
  82. } else {
  83. this.noMore = false;
  84. }
  85. this.loading = false;
  86. }, 1000);
  87. },
  88. /**
  89. * 模拟生成活动数据
  90. */
  91. mockData(page, pageSize) {
  92. let arr = [];
  93. for (let i = 0; i < pageSize; i++) {
  94. const num = (page - 1) * pageSize + i + 1;
  95. arr.push({
  96. imgUrl: "https://qiniu.aiyxlib.com/1605060269830",
  97. title: `活动标题${num}`,
  98. time: "2025-11-03 00:00 ~2025-11-09 00:00",
  99. status: num % 3 === 0 ? 0 : 1, // 0=结束 1=可参加
  100. });
  101. }
  102. return arr;
  103. },
  104. /**
  105. * 下拉刷新
  106. */
  107. onRefresh() {
  108. // 重置状态
  109. this.page = 1;
  110. this.noMore = false;
  111. this.refreshing = true;
  112. this.getActivityList();
  113. },
  114. /**
  115. * 上拉加载更多
  116. */
  117. onLoadMore() {
  118. if (this.loading || this.noMore) return;
  119. this.page++;
  120. this.getActivityList();
  121. },
  122. toActivityDetail(item){
  123. uni.navigateTo({
  124. url: "/subpkg/pages/activity-detail/activity-detail?title=" + item.title
  125. })
  126. }
  127. },
  128. };
  129. </script>
  130. <style lang="scss" scoped>
  131. .activity-list {
  132. padding: 20px;
  133. height: 100vh;
  134. box-sizing: border-box;
  135. }
  136. scroll-view {
  137. height: 100%;
  138. }
  139. .load-tip {
  140. text-align: center;
  141. padding: 20px;
  142. color: #999;
  143. font-size: 14px;
  144. }
  145. </style>