New file |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <view style="height:50rpx"></view> |
| | | |
| | | <u-empty v-if="mockData.length === 0 && !loading" mode="data" |
| | | icon="http://cdn.uviewui.com/uview/empty/data.png"> |
| | | </u-empty> |
| | | |
| | | <!-- 关键修复:确保scroll-view高度正确且事件绑定有效 --> |
| | | <scroll-view |
| | | scroll-y class="scroll-view-container" style="height: 40vh" @scrolltolower="loadMore" :lower-threshold="50" |
| | | > |
| | | <view v-for="(item, idx) in mockData" :key="idx" class="prize-record-item card"> |
| | | <view class="prize-record-info"> |
| | | <view class="info-header"> |
| | | <view class="prize-activity-name">{{ item.prizeActivityName }}</view> |
| | | <view class="prize-status-tag" |
| | | :class="item.prizeStatus === 'WIN' ? 'tag-winning' : 'tag-not-win'"> |
| | | {{ item.prizeStatus === 'WIN' ? '已中奖' : '未中奖' }} |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="info-content"> |
| | | <view class="content-label">奖品内容:</view> |
| | | <view class="prize-content">{{ item.prizeContent || '暂无奖品描述' }}</view> |
| | | </view> |
| | | |
| | | <view class="prize-record-meta"> |
| | | <view class="meta-item"> |
| | | <u-icon name="clock-o" size="16" color="#999"></u-icon> |
| | | <text class="meta-text">{{ formatTime(item.createTime) }}</text> |
| | | </view> |
| | | <view class="meta-item" v-if="item.activitySource"> |
| | | <u-icon name="map" size="16" color="#999"></u-icon> |
| | | <text class="meta-text">{{ item.activitySource }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="load-more"> |
| | | <u-loadmore v-if="mockData.length > 0" :status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" |
| | | :load-text="{ |
| | | loadmore: '上拉加载更多', |
| | | loading: '正在加载', |
| | | nomore: '没有更多了' |
| | | }" /> |
| | | </view> |
| | | <view style="height:150rpx"></view> |
| | | </scroll-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getPage } from '@/api/prize-record.js' |
| | | export default { |
| | | data() { |
| | | return { |
| | | query: { |
| | | pageNumber: 1, |
| | | pageSize: 5, |
| | | }, |
| | | loading: false, |
| | | total: 0, |
| | | mockData: [], |
| | | noMore: false, |
| | | } |
| | | }, |
| | | onLoad() { |
| | | this.getPage(); |
| | | }, |
| | | methods: { |
| | | onPullDownRefresh() { |
| | | this.mockData = []; |
| | | this.query.pageNumber = 1; |
| | | this.getPage() |
| | | setTimeout(() => { |
| | | uni.stopPullDownRefresh(); |
| | | }, 1000); |
| | | }, |
| | | |
| | | formatTime(timeStr) { |
| | | if (!timeStr || typeof timeStr !== 'string') return '未知时间'; |
| | | |
| | | try { |
| | | // 手动解析格式,解决兼容性问题 |
| | | const [datePart, timePart] = timeStr.split('T'); |
| | | if (!datePart || !timePart) return '无效时间'; |
| | | |
| | | const [year, month, day] = datePart.split('-'); |
| | | const hourMinute = timePart.split('.')[0].slice(0, 5); |
| | | const [hour, minute] = hourMinute.split(':'); |
| | | |
| | | return `${year}-${month}-${day} ${hour}:${minute}`; |
| | | } catch (error) { |
| | | console.warn('日期解析失败:', error); |
| | | return '未知时间'; |
| | | } |
| | | }, |
| | | |
| | | async getPage() { |
| | | try { |
| | | const res = await getPage(this.query); |
| | | if (res.statusCode === 200) { |
| | | const newData = res.data.data || []; |
| | | this.total = res.data.total || 0; |
| | | this.mockData = this.query.pageNumber === 1 ? newData : [...this.mockData, ...newData]; |
| | | this.noMore = newData.length < this.query.pageSize || this.mockData.length >= this.total; |
| | | } |
| | | } catch (error) { |
| | | console.error('加载失败:', error); |
| | | if (this.query.pageNumber > 1) { |
| | | this.query.pageNumber -= 1; |
| | | } |
| | | } finally { |
| | | this.loading = false; |
| | | uni.hideLoading(); |
| | | uni.stopPullDownRefresh(); |
| | | } |
| | | }, |
| | | |
| | | loadMore() { |
| | | // 增加日志便于调试 |
| | | console.log('触发上拉加载', 'loading:', this.loading, 'noMore:', this.noMore); |
| | | |
| | | if (this.loading || this.noMore) return; |
| | | |
| | | this.loading = true; |
| | | // 移除不必要的延迟,避免影响体验 |
| | | this.query.pageNumber += 1; |
| | | this.getPage(); |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .container { |
| | | height: 100vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background-color: #f7f8fa; |
| | | } |
| | | |
| | | /* 关键修复:使用flex确保高度正确计算 */ |
| | | .scroll-view-container { |
| | | flex: 1; |
| | | overflow-y: auto; /* 明确设置垂直滚动 */ |
| | | padding: 0 20rpx; |
| | | box-sizing: border-box; |
| | | -webkit-overflow-scrolling: touch; /* 优化移动端滚动体验 */ |
| | | } |
| | | |
| | | .load-more { |
| | | padding: 20rpx 0; |
| | | text-align: center; |
| | | color: #999; |
| | | font-size: 26rpx; |
| | | background-color: #f8f9fa; |
| | | } |
| | | |
| | | .card { |
| | | background: #fff; |
| | | border-radius: 20rpx; |
| | | margin: 0 0 24rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03), |
| | | 0 6rpx 16rpx rgba(0, 0, 0, 0.04); |
| | | transition: all 0.25s ease; |
| | | } |
| | | |
| | | .prize-record-item { |
| | | padding: 30rpx 28rpx; |
| | | } |
| | | |
| | | .info-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 22rpx; |
| | | } |
| | | |
| | | .prize-activity-name { |
| | | font-size: 34rpx; |
| | | font-weight: 600; |
| | | color: #222; |
| | | line-height: 1.4; |
| | | max-width: 70%; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .prize-status-tag { |
| | | padding: 6rpx 18rpx; |
| | | border-radius: 20rpx; |
| | | font-size: 24rpx; |
| | | font-weight: 500; |
| | | text-align: center; |
| | | } |
| | | |
| | | .tag-winning { |
| | | background-color: #fff1f0; |
| | | color: #ff4d4f; |
| | | border: 1px solid #ffccc7; |
| | | } |
| | | |
| | | .tag-not-win { |
| | | background-color: #f5f5f5; |
| | | color: #888; |
| | | border: 1px solid #e5e5e5; |
| | | } |
| | | |
| | | .info-content { |
| | | margin-bottom: 24rpx; |
| | | padding-left: 4rpx; |
| | | } |
| | | |
| | | .content-label { |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .prize-content { |
| | | font-size: 28rpx; |
| | | color: #555; |
| | | line-height: 1.6; |
| | | display: -webkit-box; |
| | | -webkit-box-orient: vertical; |
| | | -webkit-line-clamp: 2; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .prize-record-meta { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | gap: 24rpx; |
| | | padding-top: 20rpx; |
| | | border-top: 1px solid #f8f8f8; |
| | | } |
| | | |
| | | .meta-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8rpx; |
| | | } |
| | | |
| | | .meta-text { |
| | | font-size: 22rpx; |
| | | color: #888; |
| | | white-space: nowrap; |
| | | letter-spacing: 0.5rpx; |
| | | } |
| | | </style> |