| | |
| | | </view> |
| | | |
| | | <!-- 视频列表 --> |
| | | <view class="activity-list" > |
| | | <view class="activity-list"> |
| | | <view v-if="currentTab === 0"> |
| | | <view v-if="signedActivities.length > 0"> |
| | | <view v-for="(item, idx) in signedActivities" :key="idx" class="activity-item"> |
| | | <!-- 封面区域 --> |
| | | <block v-if="item.coverType === '图片' || item.coverType === '视频'"> |
| | | <image :src="getPreviewUrl(item.cover)" mode="aspectFill" class="activity-cover" /> |
| | | </block> |
| | | <block v-if="item.coverType === '文字'"> |
| | | <view class="activity-cover">{{ item.cover }}</view> |
| | | </block> |
| | | <scroll-view scroll-y class="activity-list" style="height: 100vh;" @scrolltolower="loadMore" |
| | | :lower-threshold="100"> |
| | | <view v-if="videoCollects.length > 0"> |
| | | <view v-for="(item, idx) in videoCollects" :key="idx" class="video-item"> |
| | | <!-- 视频封面+播放按钮 --> |
| | | <view class="video-cover-container"> |
| | | <image :src="item.coverUrl" mode="aspectFill" class="video-cover" /> |
| | | <view class="play-icon"> |
| | | <u-icon name="play-circle-fill" size="60" color="#fff"></u-icon> |
| | | </view> |
| | | <view class="video-duration" v-if="item.duration">{{ item.duration }}</view> |
| | | </view> |
| | | |
| | | <!-- 活动信息 --> |
| | | <view class="activity-info"> |
| | | <view class="activity-title">{{ item.activityName }}</view> |
| | | <view class="activity-meta"> |
| | | <text class="activity-time">{{ item.startTime }} - {{ item.endTime }}</text> |
| | | <text class="activity-location">{{ item.activityLocation || '暂无' }}</text> |
| | | <!-- 视频信息 --> |
| | | <view class="video-info"> |
| | | <view class="video-title">{{ item.authorName || '未知作者' }}</view> |
| | | <view class="video-meta"> |
| | | <text class="video-weight" v-if="item.weight > 0"> |
| | | <u-icon name="thumb-up-fill" size="24" color="#999"></u-icon> |
| | | {{ item.weight }} |
| | | </text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <view class="video-actions"> |
| | | <button class="cancel-btn" @click.stop="handleCancelCollection(item,'video')"> |
| | | 取消收藏 |
| | | </button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作区域 --> |
| | | <view class="action-container"> |
| | | <button class="cancel-btn" @click="handleCancelCollection(item)" |
| | | hover-class="cancel-btn-hover"> |
| | | 取消收藏 |
| | | </button> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | <view v-else class="empty-tip"> |
| | | <text>暂无收藏视频</text> |
| | | </view> |
| | | <view class="load-more"> |
| | | <u-loadmore v-if="videoCollects.length > 0" |
| | | :status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" :load-text="{ |
| | | loadmore: '上拉加载更多', |
| | | loading: '正在加载', |
| | | nomore: '没有更多了' |
| | | }" /> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | |
| | | |
| | | </view> |
| | | |
| | | <view v-if="currentTab === 1"> |
| | | <!-- 已结束活动列表 --> |
| | | <view v-if="endedActivities.length > 0"> |
| | | <view v-for="(item, idx) in endedActivities" :key="idx" class="activity-item"> |
| | | <!-- 封面区域 --> |
| | | <block v-if="item.coverType === '图片' || item.coverType === '视频'"> |
| | | <image :src="getPreviewUrl(item.cover)" mode="aspectFill" class="activity-cover" /> |
| | | </block> |
| | | <block v-if="item.coverType === '文字'"> |
| | | <view class="activity-cover">{{ item.cover }}</view> |
| | | </block> |
| | | <scroll-view scroll-y class="activity-list" style="height: 100vh;" @scrolltolower="loadMore" |
| | | :lower-threshold="100"> |
| | | <view v-if="goodsCollects.length > 0"> |
| | | <view v-for="(item, idx) in goodsCollects" :key="idx" class="activity-item"> |
| | | <!-- 封面区域 --> |
| | | <block> |
| | | <image :src="item.original" mode="aspectFill" class="activity-cover" /> |
| | | </block> |
| | | |
| | | <!-- 活动信息 --> |
| | | <view class="activity-info"> |
| | | <view class="activity-title">{{ item.activityName }}</view> |
| | | <view class="activity-meta"> |
| | | <text class="activity-time">{{ item.startTime }} - {{ item.endTime }}</text> |
| | | <text class="activity-location">{{ item.activityLocation || '暂无' }}</text> |
| | | <!-- 活动信息 --> |
| | | <view class="activity-info"> |
| | | <view class="activity-title">{{ item.goodsName }}</view> |
| | | <view class="activity-meta"> |
| | | <text class="activity-time">价格:{{ item.price }}元</text> |
| | | <text class="activity-location">{{ item.storeName || '暂无' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作区域 --> |
| | | <view class="action-container"> |
| | | <button class="cancel-btn" @click="handleCancelCollection(item)" |
| | | hover-class="cancel-btn-hover"> |
| | | 取消收藏 |
| | | </button> |
| | | </view> |
| | | <!-- 操作区域 --> |
| | | <view class="action-container"> |
| | | <button class="cancel-btn" @click="handleCancelCollection(item,'goods')" |
| | | hover-class="cancel-btn-hover"> |
| | | 取消收藏 |
| | | </button> |
| | | </view> |
| | | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="empty-tip"> |
| | | |
| | | <text>暂无收藏商品</text> |
| | | </view> |
| | | <view class="load-more"> |
| | | <u-loadmore v-if="goodsCollects.length > 0" |
| | | :status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" :load-text="{ |
| | | loadmore: '上拉加载更多', |
| | | loading: '正在加载', |
| | | nomore: '没有更多了' |
| | | }" /> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | <view v-if="currentTab === 2"> |
| | | <!-- 已取消活动列表 --> |
| | | <view v-if="canceledActivities.length > 0"> |
| | | <view v-for="(item, idx) in endedActivities" :key="idx" class="activity-item"> |
| | | <!-- 封面区域 --> |
| | | <block v-if="item.coverType === '图片' || item.coverType === '视频'"> |
| | | <image :src="getPreviewUrl(item.cover)" mode="aspectFill" class="activity-cover" /> |
| | | </block> |
| | | <block v-if="item.coverType === '文字'"> |
| | | <view class="activity-cover">{{ item.cover }}</view> |
| | | </block> |
| | | <!-- 活动信息 --> |
| | | <view class="activity-info"> |
| | | <view class="activity-title">{{ item.activityName }}</view> |
| | | <view class="activity-meta"> |
| | | <text class="activity-time">{{ item.startTime }} - {{ item.endTime }}</text> |
| | | <text class="activity-location">{{ item.activityLocation || '暂无' }}</text> |
| | | <scroll-view scroll-y class="activity-list" style="height: 80vh;" @scrolltolower="loadMore" |
| | | :lower-threshold="100"> |
| | | <view v-if="activityCollects.length > 0"> |
| | | <view v-for="(item, idx) in activityCollects" :key="idx" class="activity-item"> |
| | | <!-- 封面区域 --> |
| | | <block v-if="item.coverType === '图片' || item.coverType === '视频'"> |
| | | <image :src="item.cover" mode="aspectFill" class="activity-cover" /> |
| | | </block> |
| | | <block v-if="item.coverType === '文字'"> |
| | | <view class="activity-cover text-cover">{{ item.cover }}</view> |
| | | </block> |
| | | <!-- 活动信息 --> |
| | | <view class="activity-info"> |
| | | <view class="activity-title">{{ item.activityName }}</view> |
| | | <view class="activity-meta"> |
| | | <text class="activity-time">{{ item.startTime }}</text> |
| | | <text class="activity-time"> {{ item.endTime }}</text> |
| | | <text class="activity-location">{{ item.activityLocation || '暂无' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 操作区域 --> |
| | | <view class="action-container"> |
| | | <button class="cancel-btn" @click="handleCancelCollection(item,'activity')" |
| | | hover-class="cancel-btn-hover"> |
| | | 取消收藏 |
| | | </button> |
| | | </view> |
| | | |
| | | </view> |
| | | <!-- 操作区域 --> |
| | | <view class="action-container"> |
| | | <button class="cancel-btn" @click="handleCancelCollection(item)" |
| | | hover-class="cancel-btn-hover"> |
| | | 取消收藏 |
| | | </button> |
| | | </view> |
| | | |
| | | |
| | | |
| | | </view> |
| | | |
| | | |
| | | </view> |
| | | <view v-else class="empty-tip"> |
| | | <text>暂无收藏活动</text> |
| | | </view> |
| | | <view class="load-more"> |
| | | <u-loadmore v-if="activityCollects.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 ULoadmore from '@/uview-components/uview-ui/components/u-loadmore/u-loadmore.vue' |
| | | import UImage from '@/uview-components/uview-ui/components/u-image/u-image.vue'; |
| | | import { |
| | | getMyActivityList, |
| | | activityCancel |
| | | } from '@/api/activity.js' |
| | | import { |
| | | getPreviewUrl |
| | | getFilePreviewUrl |
| | | } from '@/api/common.js' |
| | | import { |
| | | changeCollect, |
| | | getMyCollectList |
| | | } from '@/api/collect.js' |
| | | import { |
| | | ifError |
| | | } from 'assert' |
| | | export default { |
| | | components: { |
| | | UImage, |
| | | ULoadmore |
| | | }, |
| | | data() { |
| | | return { |
| | | total: 0, |
| | | loading: false, |
| | | noMore: { |
| | | video: false, |
| | | goods: false, |
| | | activity: false |
| | | }, |
| | | currentTab: 0, // 当前选中的tab索引 |
| | | tabs: ['视频', '商品', '活动'], |
| | | // |
| | | // |
| | | videoCollects: [], // 收藏视频列表 |
| | | storeCollects: [], // 收藏商品列表 |
| | | goodsCollects: [], // 收藏商品列表 |
| | | activityCollects: [], // 收藏活动列表 |
| | | query: { |
| | | id: '', |
| | | status: '', |
| | | cancel: false, |
| | | collectForm: { |
| | | collectType: '', |
| | | refId: '', |
| | | }, |
| | | query: { |
| | | type: 'video', |
| | | pageNumber: 1, |
| | | pageSize: 5, |
| | | } |
| | | } |
| | | }, |
| | | onLoad(){ |
| | | onLoad() { |
| | | this.currentTab = 0; |
| | | //TODO 未登录需要id,测试用写死\ |
| | | this.switchTab(this.currentTab); |
| | | this.getintit() |
| | | }, |
| | | methods: { |
| | | handleCancelCollection(id) { |
| | | |
| | | /** |
| | | * 下拉刷新时 |
| | | */ |
| | | onPullDownRefresh() { |
| | | this.currentTab = 0; |
| | | this.query.pageNumber = 1; // 重置页码 |
| | | this.noMore = false; |
| | | this.videoCollects = []; |
| | | this.goodsCollects = []; // 收藏商品列表 |
| | | this.activityCollects = []; // 收藏活动列表// 清空数据 |
| | | this.getintit(); |
| | | }, |
| | | getPreviewUrl(params) { |
| | | // return getPreviewUrl(params); |
| | | return ''; |
| | | loadMore() { |
| | | this.loading = true; |
| | | this.query.pageNumber += 1; |
| | | // 延迟执行让UI有反应时间 |
| | | setTimeout(() => { |
| | | this.query.pageNumber += 1; |
| | | this.getintit(); |
| | | }, 300); |
| | | }, |
| | | handleCancelCollection(item, type) { |
| | | console.log(item) |
| | | this.collectForm.collectType = type; |
| | | this.collectForm.refId = item.id; |
| | | changeCollect(this.collectForm).then(res => { |
| | | if (res.statusCode === 200) { |
| | | uni.showToast({ |
| | | title: res.data.msg, // 提示文字 |
| | | icon: 'none', // 图标类型(success/loading/none) |
| | | mask: true // 是否显示透明蒙层(防止触摸穿透) |
| | | }); |
| | | this.getintit(); |
| | | } |
| | | |
| | | }) |
| | | }, |
| | | getUrl(params) { |
| | | getFilePreviewUrl(params).then(res => { |
| | | return res.data.data |
| | | }) |
| | | }, |
| | | // 切换tab |
| | | switchTab(index) { |
| | | |
| | | if (this.currentTab !== index) { |
| | | this.currentTab = index |
| | | //切换时页码归0 |
| | | this.query.pageNumber = 0; |
| | | // 清空数据 |
| | | this.videoCollects = []; |
| | | this.goodsCollects = []; |
| | | this.activityCollects = []; |
| | | // 实际项目中可以在这里添加加载数据的逻辑 |
| | | if (this.currentTab === 0) { |
| | | //加载视频列表 |
| | | this.getMyCollectionVideoList(); |
| | | } else if (this.currentTab === 1) { |
| | | //加载商品列表 |
| | | this.getMyCollectionStoreList(); |
| | | } else if (this.currentTab === 2) { |
| | | //加载活动列表 |
| | | this.getMyCollectActivityList(); |
| | | } |
| | | this.getintit() |
| | | } |
| | | }, |
| | | async getintit() { |
| | | uni.showLoading({ |
| | | title: '加载中' |
| | | }); |
| | | if (this.currentTab === 0) { |
| | | this.query.type = 'video'; |
| | | getMyCollectList(this.query).then(res => { |
| | | uni.hideLoading(); |
| | | this.loading = false; |
| | | |
| | | if (res.statusCode === 200) { |
| | | const newData = res.data.data |
| | | this.total = res.data.total || 0; |
| | | // 追加或替换数据 |
| | | this.videoCollects = this.query.pageNumber === 1 ? |
| | | newData : |
| | | [...this.videoCollects, ...newData]; |
| | | // 判断是否还有更多数据 |
| | | this.noMore = newData.length < this.query.pageSize || |
| | | this.videoCollects.length >= this.total; |
| | | |
| | | } |
| | | }) |
| | | } else if (this.currentTab === 1) { |
| | | this.query.type = 'goods'; |
| | | getMyCollectList(this.query).then(res => { |
| | | uni.hideLoading(); |
| | | this.loading = false; |
| | | if (res.statusCode === 200) { |
| | | const newData = res.data.data |
| | | this.total = res.data.total || 0; |
| | | |
| | | this.goodsCollects = this.query.pageNumber === 1 ? |
| | | newData : |
| | | [...this.goodsCollects, ...newData]; |
| | | // 判断是否还有更多数据 |
| | | this.noMore = newData.length < this.query.pageSize || |
| | | this.goodsCollects.length >= this.total; |
| | | } |
| | | }) |
| | | } else if (this.currentTab === 2) { |
| | | this.query.type = 'activity'; |
| | | getMyCollectList(this.query).then(res => { |
| | | uni.hideLoading(); |
| | | this.loading = false; |
| | | if (res.statusCode === 200) { |
| | | const newData = res.data.data |
| | | this.total = res.data.total || 0; |
| | | |
| | | this.activityCollects = this.query.pageNumber === 1 ? |
| | | newData : |
| | | [...this.activityCollects, ...newData]; |
| | | this.noMore = newData.length < this.query.pageSize || |
| | | this.activityCollects.length >= this.total; |
| | | } |
| | | }) |
| | | } |
| | | |
| | | }, |
| | | getMyCollectionStoreList() { |
| | | uni.showLoading({ |
| | | title: '加载中' |
| | | }); |
| | | |
| | | uni.hideLoading(); |
| | | }, |
| | | getMyCollectionVideoList() { |
| | | uni.showLoading({ |
| | | title: '加载中' |
| | | }); |
| | | |
| | | uni.hideLoading(); |
| | | }, |
| | | getMyCollectActivityList() { |
| | | uni.showLoading({ |
| | | title: '加载中' |
| | | }); |
| | | |
| | | uni.hideLoading(); |
| | | }, |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .text-cover { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); |
| | | color: #fff; |
| | | font-size: 28rpx; |
| | | padding: 16rpx; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | /* 视频列表专用样式 */ |
| | | .video-item { |
| | | display: flex; |
| | | padding: 24rpx 0; |
| | | border-bottom: 1rpx solid #f5f5f5; |
| | | align-items: center; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | } |
| | | |
| | | .video-cover-container { |
| | | position: relative; |
| | | width: 240rpx; |
| | | height: 160rpx; |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | margin-right: 24rpx; |
| | | flex-shrink: 0; |
| | | |
| | | .video-cover { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .play-icon { |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .video-duration { |
| | | position: absolute; |
| | | right: 8rpx; |
| | | bottom: 8rpx; |
| | | background: rgba(0, 0, 0, 0.6); |
| | | color: #fff; |
| | | font-size: 20rpx; |
| | | padding: 4rpx 12rpx; |
| | | border-radius: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .video-info { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | height: 160rpx; |
| | | |
| | | .video-title { |
| | | font-size: 30rpx; |
| | | color: #333; |
| | | font-weight: bold; |
| | | display: -webkit-box; |
| | | -webkit-box-orient: vertical; |
| | | -webkit-line-clamp: 2; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .video-meta { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | |
| | | |
| | | |
| | | .video-weight { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .video-actions { |
| | | margin-left: 20rpx; |
| | | flex-shrink: 0; |
| | | |
| | | .cancel-btn { |
| | | background: #f5f5f5; |
| | | color: #666; |
| | | border: none; |
| | | font-size: 24rpx; |
| | | padding: 8rpx 20rpx; |
| | | border-radius: 20rpx; |
| | | |
| | | &:active { |
| | | background: #eee; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .empty-tip { |
| | | text-align: center; |
| | | padding: 100rpx 0; |
| | | |
| | | image { |
| | | width: 300rpx; |
| | | margin-bottom: 30rpx; |
| | | opacity: 0.6; |
| | | } |
| | | |
| | | text { |
| | | display: block; |
| | | font-size: 28rpx; |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | .activity-container { |
| | | padding: 20rpx; |
| | | background-color: #f5f5f5; |