HaniBlindBox/honey_box/package/mine/collect.vue
2026-02-03 13:39:57 +08:00

398 lines
8.6 KiB
Vue

<template>
<view class="content">
<uni-nav-bar
left-icon="left"
title="我的收藏"
color="#000000"
backgroundColor="transparent"
:fixed="true"
:statusBar="true"
:border="false"
@clickLeft="$c.back"
></uni-nav-bar>
<!-- 顶部标签栏 -->
<scroll-view class="tab" scroll-x>
<view
class="tab-item"
v-for="(item, i) in tabList"
:key="i"
:class="{ active: tabCur === i }"
@click="tabChange(i)"
>
{{ item.title }}
</view>
</scroll-view>
<!-- 列表区域 -->
<mescroll-body
ref="mescrollRef"
@init="mescrollInit"
@down="downCallback"
@up="getList"
:down="downOption"
:up="upOption"
>
<view class="list" v-if="listData.length > 0">
<view
class="list-item"
v-for="(item, i) in listData"
:key="i"
@click="toDetail(item)"
>
<view class="pic">
<image
class="pic-img"
:src="item.imgurl"
mode="aspectFill"
lazy-load
></image>
</view>
<view
class="tag"
:style="{ backgroundImage: `url(${$img1('common/label1.png')})` }"
>
<text>{{ tabList[tabCur].title }}</text>
</view>
<view class="title ellipsis">{{ item.goods_title }}</view>
<view class="price-box">
<view class="price">
¥<text>{{ item.goods_price }}</text>
</view>
<view v-if="item.stock" class="stock">
<view class="stock-num"
>{{ item.surplus_stock }}/{{ item.stock }}</view
>
<image
class="stock-icon"
:src="$img1('index/box.png')"
lazy-load
></image>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="listData.length === 0 && !isLoading">
<image
class="empty-image"
:src="$img1('common/empty.png')"
mode="aspectFit"
></image>
<text class="empty-text">暂无收藏内容</text>
</view>
</mescroll-body>
</view>
</template>
<script>
export default {
data() {
return {
// 下拉刷新配置
downOption: {
auto: false,
},
// 上拉加载配置
upOption: {
auto: true,
page: {
size: 10, // 每页数据数量
},
noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据
empty: {
use: false, // 使用自定义的空状态
},
},
tabList: [], // 标签列表
tabCur: 0, // 当前选中标签索引
listData: [], // 列表数据
isLoading: true, // 是否正在加载
};
},
created() {
// 获取商品类型列表
this.initTabList();
},
methods: {
/**
* 初始化标签列表
*/
initTabList() {
const tabList = this.$config.getGoodType();
// 过滤掉id为0的选项
this.tabList = tabList.filter((item) => item.id !== 0);
},
/**
* 初始化mescroll对象
* @param {Object} mescroll mescroll实例
*/
mescrollInit(mescroll) {
this.mescroll = mescroll;
},
/**
* 下拉刷新回调
*/
downCallback() {
this.mescroll.resetUpScroll();
},
/**
* 跳转到详情页
* @param {Object} item 商品项
*/
toDetail(item) {
let url = "/pages/shouye/detail";
// 根据商品类型跳转到不同详情页
if (item.type === 2 || item.type === 8) {
url = "/pages/shouye/detail_wuxian";
} else if (item.type === 9) {
url = "/package/index/lian-ji";
}
this.$c.to({
url,
query: {
goods_id: item.goods_id,
type_text: this.tabList[this.tabCur].title,
},
});
},
/**
* 切换标签
* @param {Number} index 标签索引
*/
tabChange(index) {
if (this.tabCur === index) return;
this.tabCur = index;
this.listData = [];
this.isLoading = true;
// 重置列表并滚动到顶部
this.mescroll.resetUpScroll();
this.mescroll.scrollTo(0, 0);
},
/**
* 获取收藏列表数据
* @param {Object} params 分页参数
*/
getList({ num, size }) {
this.isLoading = true;
// 使用Promise方式调用API
this.$request
.post("listCollect", {
page: num,
type: this.tabList[this.tabCur].id,
})
.then((res) => {
this.isLoading = false;
if (res.status === 1) {
// 第一页时清空数据
if (num === 1) {
this.listData = [];
}
// 追加数据
this.listData = this.listData.concat(res.data.data || []);
// 更新分页状态
this.mescroll.endByPage(
res.data.data ? res.data.data.length : 0,
res.data.last_page || 1
);
} else {
this.mescroll.endErr();
uni.showToast({
title: res.msg || "加载失败",
icon: "none",
});
}
})
.catch((err) => {
this.isLoading = false;
this.mescroll.endErr();
uni.showToast({
title: "网络请求失败",
icon: "none",
});
console.error(err);
});
},
},
};
</script>
<style lang="scss">
.content {
background: linear-gradient(180deg, #5FCDFF 0%, #F5F5F5 100%);
min-height: 100vh;
// 顶部标签栏
.tab {
white-space: nowrap;
padding: 15rpx 0;
.tab-item {
width: 88rpx;
height: 40rpx;
display: inline-flex;
align-items: center;
justify-content: center;
margin-left: 30rpx;
background-color: #ffffff;
font-size: 20rpx;
border-radius: 8rpx;
color: #333333;
transition: all 0.2s;
&:last-child {
margin-right: 30rpx;
}
&.active {
background-color: #e6f791;
font-weight: 500;
}
}
}
// 商品列表
.list {
padding: 15rpx 30rpx 30rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.list-item {
width: 330rpx;
height: 487rpx;
margin-top: 30rpx;
position: relative;
background-color: #ffffff;
border-radius: 16rpx;
overflow: hidden;
.pic {
width: 100%;
height: 332rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
border-radius: 16rpx 16rpx 0 0;
overflow: hidden;
.pic-img {
width: 100%;
height: 100%;
border-radius: 16rpx 16rpx 0 0;
}
}
.tag {
position: absolute;
z-index: 1;
top: 12rpx;
left: 12rpx;
width: 68rpx;
height: 32rpx;
display: flex;
align-items: center;
justify-content: center;
background-size: 100% 100%;
text {
font-size: 14rpx;
color: #ffffff;
}
}
.title {
padding: 20rpx 20rpx 0;
font-size: 20rpx;
color: #333333;
line-height: 1.4;
height: 56rpx;
}
.price-box {
padding: 20rpx 20rpx 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
.price {
font-size: 16rpx;
color: #333333;
text {
font-size: 24rpx;
font-weight: 500;
}
}
.stock {
display: flex;
align-items: center;
.stock-num {
font-size: 24rpx;
color: #cccccc;
}
.stock-icon {
width: 26rpx;
height: 26rpx;
margin-left: 6rpx;
}
}
}
}
}
// 空状态
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.empty-image {
width: 200rpx;
height: 200rpx;
margin-bottom: 20rpx;
}
.empty-text {
font-size: 28rpx;
color: #8A8A8A;
}
}
// 公共类
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
</style>