<template>
|
|
<view class="activity-container">
|
<!-- 顶部 Tab 导航 -->
|
<view class="tab-nav">
|
<view v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{active: currentTab === index}"
|
@click="switchTab(index)">
|
{{tab}}
|
</view>
|
</view>
|
|
<!-- 视频列表 -->
|
<view class="activity-list">
|
<view v-if="currentTab === 0">
|
<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="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>
|
<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">
|
<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.goodsName }}</view>
|
<view class="activity-meta">
|
<text class="activity-time">价格:{{ item.price }}元</text>
|
<text class="activity-location">{{ item.storeName || '暂无' }}</text>
|
</view>
|
</view>
|
|
<!-- 操作区域 -->
|
<view class="action-container">
|
<button class="cancel-btn" @click="handleCancelCollection(item,'goods')"
|
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="goodsCollects.length > 0"
|
:status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" :load-text="{
|
loadmore: '上拉加载更多',
|
loading: '正在加载',
|
nomore: '没有更多了'
|
}" />
|
</view>
|
</scroll-view>
|
</view>
|
|
<view v-if="currentTab === 2">
|
<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>
|
<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>
|
|
|
|
</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 {
|
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: [], // 收藏视频列表
|
goodsCollects: [], // 收藏商品列表
|
activityCollects: [], // 收藏活动列表
|
collectForm: {
|
collectType: '',
|
refId: '',
|
},
|
query: {
|
type: 'video',
|
pageNumber: 1,
|
pageSize: 5,
|
}
|
}
|
},
|
onLoad() {
|
this.currentTab = 0;
|
//TODO 未登录需要id,测试用写死\
|
this.getintit()
|
},
|
methods: {
|
|
/**
|
* 下拉刷新时
|
*/
|
onPullDownRefresh() {
|
this.currentTab = 0;
|
this.query.pageNumber = 1; // 重置页码
|
this.noMore = false;
|
this.videoCollects = [];
|
this.goodsCollects = []; // 收藏商品列表
|
this.activityCollects = []; // 收藏活动列表// 清空数据
|
this.getintit();
|
},
|
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 = [];
|
// 实际项目中可以在这里添加加载数据的逻辑
|
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;
|
}
|
})
|
}
|
|
}
|
}
|
}
|
</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;
|
min-height: 100vh;
|
}
|
|
/* Tab 导航样式 */
|
.tab-nav {
|
display: flex;
|
background-color: #fff;
|
border-radius: 12rpx;
|
margin-bottom: 20rpx;
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
}
|
|
.tab-item {
|
flex: 1;
|
text-align: center;
|
padding: 24rpx 0;
|
font-size: 28rpx;
|
color: #666;
|
position: relative;
|
|
&.active {
|
color: #007AFF;
|
font-weight: bold;
|
|
&::after {
|
content: '';
|
position: absolute;
|
bottom: 0;
|
left: 50%;
|
transform: translateX(-50%);
|
width: 80rpx;
|
height: 6rpx;
|
background-color: #007AFF;
|
border-radius: 3rpx;
|
}
|
}
|
}
|
|
/* 活动列表样式 */
|
.activity-list {
|
background-color: #fff;
|
border-radius: 12rpx;
|
padding: 20rpx;
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
}
|
|
.activity-item {
|
display: flex;
|
padding: 20rpx 0;
|
border-bottom: 1rpx solid #eee;
|
|
&:last-child {
|
border-bottom: none;
|
}
|
}
|
|
.activity-cover {
|
width: 200rpx;
|
height: 140rpx;
|
border-radius: 8rpx;
|
margin-right: 20rpx;
|
}
|
|
.activity-info {
|
flex: 1;
|
position: relative;
|
}
|
|
.activity-title {
|
font-size: 32rpx;
|
color: #333;
|
font-weight: bold;
|
margin-bottom: 12rpx;
|
display: -webkit-box;
|
-webkit-box-orient: vertical;
|
-webkit-line-clamp: 2;
|
overflow: hidden;
|
}
|
|
.activity-meta {
|
font-size: 24rpx;
|
color: #999;
|
margin-bottom: 16rpx;
|
|
text {
|
display: block;
|
margin-bottom: 8rpx;
|
}
|
}
|
|
.activity-status {
|
position: absolute;
|
right: 0;
|
top: 0;
|
font-size: 24rpx;
|
padding: 4rpx 12rpx;
|
border-radius: 20rpx;
|
|
&.signed {
|
color: #007AFF;
|
background-color: rgba(0, 122, 255, 0.1);
|
}
|
|
&.ended {
|
color: #999;
|
background-color: rgba(153, 153, 153, 0.1);
|
}
|
|
&.canceled {
|
color: #ff3b30;
|
background-color: rgba(255, 59, 48, 0.1);
|
}
|
}
|
|
/* 空状态提示 */
|
.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;
|
}
|
}
|
</style>
|