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

358 lines
7.6 KiB

5 months ago
1 month ago
1 month ago
5 months ago
1 month ago
4 months ago
1 month ago
4 months ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
4 months ago
4 months ago
1 month ago
5 months ago
1 month ago
5 months ago
4 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
5 months ago
1 month ago
5 months ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
5 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
4 months ago
1 month ago
  1. <template>
  2. <view class="activity-list">
  3. <view class="tab-box">
  4. <view
  5. class="tab-item"
  6. :class="{ active: currentTab === 0 }"
  7. @click="switchTab(0)"
  8. >
  9. 进行中
  10. </view>
  11. <view
  12. class="tab-item"
  13. :class="{ active: currentTab === 1 }"
  14. @click="switchTab(1)"
  15. >
  16. 往期活动
  17. </view>
  18. </view>
  19. <scroll-view
  20. scroll-y
  21. @scrolltolower="onLoadMore"
  22. lower-threshold="150"
  23. class="scroll-view"
  24. >
  25. <view class="activity-item" v-for="(item, index) in displayList" @click="toActivityDetail(item)" :key="index">
  26. <image class="activity-img" :src="item.coverImage" mode="aspectFill"></image>
  27. <!-- 状态小标 -->
  28. <view class="status-tag"
  29. v-if="item.status === '未开始' || item.status === '进行中' || item.status === '已结束'"
  30. :class="[
  31. item.status === '未开始' ? 'tag-wait' : '',
  32. item.status === '进行中' ? 'tag-doing' : '',
  33. item.status === '已结束' ? 'tag-end' : ''
  34. ]"
  35. >
  36. {{item.status}}
  37. </view>
  38. <view class="activity-info">
  39. <view class="activity-info-left">
  40. <view class="title-wrap">
  41. <text class="activity-title">{{ item.title }}</text>
  42. </view>
  43. <view class="time">
  44. <uni-icons class="time-icon" custom-prefix="iconfont" type="icon-shijian" size="15"></uni-icons>
  45. <text>{{ item.startTime }} - {{ item.endTime }}</text>
  46. </view>
  47. </view>
  48. <!-- <button
  49. class="activity-btn"
  50. :class="isItemDisabled(item) ? 'disabled-btn' : ''"
  51. type="primary"
  52. :disabled="isItemDisabled(item)"
  53. >
  54. {{ getBtnText(item.status) }}
  55. </button> -->
  56. </view>
  57. </view>
  58. <view class="empty" v-if="displayList.length === 0 && !loading">
  59. <uni-icons custom-prefix="iconfont" type="icon-kongshuju" size="80"></uni-icons>
  60. <text style="margin-top: 20px;">暂无{{ currentTab === 0 ? '进行中的活动' : '往期活动' }}~</text>
  61. </view>
  62. <!-- 底部加载提示 -->
  63. <view class="footer-tip" v-if="displayList.length>0">
  64. <text v-if="loading">加载中...</text>
  65. <text v-else-if="noMore">没有更多数据了</text>
  66. </view>
  67. </scroll-view>
  68. </view>
  69. </template>
  70. <script>
  71. import { FetchActivityInfo } from '@/api/activity';
  72. import config from '@/utils/config';
  73. export default {
  74. data() {
  75. return {
  76. currentTab: 0,
  77. activityList: [],
  78. baseUrl: config.baseUrl,
  79. page: 0,
  80. size: 10,
  81. loading: false,
  82. noMore: false
  83. };
  84. },
  85. computed: {
  86. displayList() {
  87. return this.activityList
  88. }
  89. },
  90. onLoad() {
  91. this.getNewActivityList(false);
  92. },
  93. /** 页面原生下拉刷新,pages.json对应页面开启enablePullDownRefresh */
  94. async onPullDownRefresh() {
  95. if(this.loading){
  96. uni.stopPullDownRefresh()
  97. return
  98. }
  99. this.page = 0;
  100. this.noMore = false;
  101. try{
  102. await this.getNewActivityList(false);
  103. }finally{
  104. uni.stopPullDownRefresh()
  105. }
  106. },
  107. methods: {
  108. switchTab(index) {
  109. this.currentTab = index;
  110. //切换tab重置分页
  111. this.page = 0;
  112. this.activityList = [];
  113. this.noMore = false;
  114. this.getNewActivityList(false);
  115. },
  116. /**
  117. * @param {Boolean} isLoadMore true=上拉加载更多追加 false=刷新重置列表
  118. */
  119. async getNewActivityList(isLoadMore = false){
  120. if(this.loading) return;
  121. this.loading = true;
  122. let statusArr = []
  123. if(this.currentTab === 0){
  124. // 进行中:未开始0、进行中1
  125. statusArr = [0, 1]
  126. }else{
  127. // 往期:已结束2
  128. statusArr = [2]
  129. }
  130. const params = {
  131. page: this.page,
  132. size: this.size,
  133. status: statusArr
  134. }
  135. console.log('params',params)
  136. try {
  137. const res = await FetchActivityInfo(params)
  138. console.log(res)
  139. if (res.code === 200 ) {
  140. const records = res.data.content || []
  141. records.forEach(item => {
  142. if(item.coverImage){
  143. const imgId = encodeURIComponent(item.coverImage);
  144. item.coverImage = `https://wechatapi.aiyxlib.com/files/${imgId}`;
  145. }else{
  146. item.coverImage = ''
  147. }
  148. })
  149. if(isLoadMore){
  150. this.activityList.push(...records)
  151. }else{
  152. this.activityList = records
  153. }
  154. // 判断是否没有更多
  155. this.noMore = records.length < this.size
  156. }else{
  157. if(!isLoadMore){
  158. this.activityList = [];
  159. }
  160. }
  161. } catch (e) {
  162. console.error(e)
  163. } finally {
  164. this.loading = false
  165. }
  166. },
  167. //上拉加载更多
  168. onLoadMore(){
  169. if(this.loading || this.noMore) return
  170. this.page = this.page + 1
  171. this.getNewActivityList(true)
  172. },
  173. getBtnText(status) {
  174. switch(status){
  175. case '已结束':
  176. return '活动结束'
  177. case '已取消':
  178. return '活动取消'
  179. case '未开始':
  180. case '进行中':
  181. return '立即参加'
  182. default:
  183. return '立即参加'
  184. }
  185. },
  186. isItemDisabled(item) {
  187. return ['已结束', '已取消'].includes(item.status)
  188. },
  189. toActivityDetail(item) {
  190. uni.navigateTo({
  191. url: "/subpkg/pages/activity-detail/activity-detail?item=" + encodeURIComponent(JSON.stringify(item))
  192. });
  193. }
  194. },
  195. };
  196. </script>
  197. <style lang="scss" scoped>
  198. .activity-list {
  199. padding: 0;
  200. height: 100vh;
  201. box-sizing: border-box;
  202. background-color: #f5f5f5;
  203. display:flex;
  204. flex-direction:column;
  205. }
  206. .tab-box {
  207. display: flex;
  208. background-color: #fff;
  209. margin-bottom: 10px;
  210. position: sticky;
  211. top: 0;
  212. z-index: 99;
  213. }
  214. .tab-item {
  215. flex: 1;
  216. text-align: center;
  217. padding: 10px 0;
  218. font-size: 15px;
  219. color: #333;
  220. position: relative;
  221. }
  222. .tab-item.active {
  223. color: #01a4fe;
  224. font-weight: bold;
  225. }
  226. .tab-item.active::after {
  227. content: '';
  228. position: absolute;
  229. width: 25px;
  230. height: 2px;
  231. background-color: #01a4fe;
  232. bottom: 0;
  233. left: 50%;
  234. transform: translateX(-50%);
  235. border-radius: 2px;
  236. }
  237. .scroll-view {
  238. flex: 1;
  239. height: 0;
  240. padding: 0 12px;
  241. box-sizing: border-box;
  242. }
  243. .empty {
  244. padding: 80rpx 0;
  245. display: flex;
  246. flex-direction: column;
  247. align-items: center;
  248. justify-content: center;
  249. color: #999;
  250. }
  251. .footer-tip{
  252. text-align: center;
  253. padding: 10px 0 20px;
  254. color:#999;
  255. font-size:13px;
  256. }
  257. .activity-item {
  258. position: relative;
  259. background: #fff;
  260. border-radius: 12px;
  261. margin-bottom: 15px;
  262. overflow: hidden;
  263. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  264. .activity-img {
  265. width: 100%;
  266. height: 100px;
  267. object-fit: cover;
  268. }
  269. .status-tag{
  270. position: absolute;
  271. top: 0;
  272. left: 0;
  273. padding: 4px 8px;
  274. border-radius: 12px 0 12px 0;
  275. font-size: 12px;
  276. &.tag-wait{
  277. color: #01a4fe;
  278. background: #e6f7ff;
  279. }
  280. &.tag-doing{
  281. color: #00b42a;
  282. background: #e6ffed;
  283. }
  284. &.tag-end{
  285. color:#868686;
  286. background:#f2f2f2;
  287. }
  288. }
  289. .activity-info {
  290. padding: 15px;
  291. display: flex;
  292. justify-content: space-between;
  293. align-items: center;
  294. .activity-info-left {
  295. flex: 1;
  296. .title-wrap{
  297. display:flex;
  298. justify-content: flex-start;
  299. align-items: flex-start;
  300. gap:5px;
  301. margin-bottom:8px;
  302. }
  303. .activity-title {
  304. flex: 1;
  305. font-size: 16px;
  306. font-weight: bold;
  307. color: #333;
  308. }
  309. .time {
  310. display: flex;
  311. align-items: center;
  312. font-size: 12px;
  313. color: #999;
  314. .time-icon {
  315. margin-right: 4px;
  316. }
  317. }
  318. }
  319. .activity-btn {
  320. background-color: #01a4fe;
  321. font-size: 14px;
  322. border-radius: 30px;
  323. padding: 0 15px;
  324. height: 36px;
  325. line-height: 36px;
  326. &::after{
  327. border:none;
  328. }
  329. }
  330. .disabled-btn {
  331. background-color: #ccc !important;
  332. }
  333. }
  334. }
  335. </style>