| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- <template>
- <view class="content">
- <view class="top-fixed">
- <!-- <view class="nav-title">
- <text>{{tabIndex === 0 ? '我的评论' : '我的收藏'}}</text>
- </view> -->
- <view class="tabs-container"
- :style="{ '--underline-width': underlineWidth + 'rpx', '--underline-left': underlineLeft + 'rpx', '--underline-opacity': underlineOpacity }">
- <view v-for="(tab, index) in mtabs" :key="index" class="tab-item"
- :class="tabIndex === index ? 'active' : ''" @click="tabChange(index)" :id="'tab-' + index">
- <text :class="tabIndex === index ? 'active-text' : ''">{{ tab }}</text>
- </view>
- <view class="nav-underline"></view>
- </view>
- </view>
- <mescroll-uni ref="mescrollRef" style="background-color: #FAFAFA;" :top="mescrollTopY" top="24"
- :down="downOption" @down="downCallback" :up="upOption" @up="upCallback" @emptyclick="emptyClick"
- @init="mescrollInit">
- <view class="comment-list" style="padding: 0 24rpx;">
- <view class="comment-item" v-for="(item, index) in dataList" :key="index" @click="handleDetail(item)">
- <view class="comment-header">
- </view>
- <image v-if="item.imgsUrl" class="comment-image" :src="item.imgsUrl" mode="aspectFill"></image>
- <video v-else="item.videoUrl" class="comment-video" :src="item.videoUrl" object-fit="fill" show-progress="false"></video>
- <view class="comment-footer">
- <view class="like-count">
- <image class="like-icon" src="https://fs-1319721001.cos.ap-chongqing.myqcloud.com/images/like_icon.png"></image>
- <text>{{ item.likeCount || 0 }}</text>
- </view>
- </view>
- </view>
- </view>
- </mescroll-uni>
- </view>
- </template>
- <script>
- import { getMyComments, getMyCollection } from '@/api/life'
- export default {
- components: {
- },
- data() {
- return {
- tabTop: 0,
- mtabs: ["我的收藏", "我的评论"],
- downOption: { //下拉刷新
- use: true,
- auto: false
- },
- upOption: {
- auto: false, // 不自动加载
- page: {
- num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
- size: 20 // 每页数据的数量
- },
- textNoMore: "已经到底了",
- noMoreSize: 4, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
- toTop: {
- width: 0,
- },
- empty: {
- tip: '~ 暂无数据 ~', // 提示
- btnText: '刷新重试',
- icon: "/static/images/icon_img_empty.png"
- },
- },
- dataList: [],
- tabIndex: 0,
- mescrollTopY: 0,
- mescroll: null,
- tabPositions: [] // 存储每个tab的位置信息
- }
- },
- computed: {
- // 计算下划线的宽度
- underlineWidth() {
- if (this.tabPositions.length === 0 || this.tabIndex >= this.tabPositions.length) {
- return 0;
- }
- const position = this.tabPositions[this.tabIndex];
- return Math.round(position.width * 2);
- },
- // 计算下划线的左侧位置
- underlineLeft() {
- if (this.tabPositions.length === 0 || this.tabIndex >= this.tabPositions.length) {
- return 0;
- }
- const position = this.tabPositions[this.tabIndex];
- const left = position.left + position.width / 2;
- return Math.round(left * 2);
- },
- // 计算下划线的透明度
- underlineOpacity() {
- if (this.tabPositions.length === 0 || this.tabIndex >= this.tabPositions.length) {
- return 0;
- }
- return 1;
- }
- },
- onLoad(options) {
- this.tabIndex = Number(options.tabIndex || 0)
- uni.$on("refreshPage", res => {
- this.refreshPage();
- })
- },
- onUnload() {
- uni.$off("refreshPage")
- },
- mounted(option) {
- const system = uni.getSystemInfoSync();
- let navigationBarHeight = 44, tabHei = 88, searchBarHei = 44;
- let tempHei = navigationBarHeight + system.statusBarHeight;
- tempHei = tempHei + uni.upx2px(tabHei);
- this.mescrollTopY = tempHei + "px";
- // 初始化tab位置
- this.initTabPositions();
- },
- methods: {
- handleDetail(item) {
- console.log("跳转视频",item)
- uni.navigateTo({
- url: "/pages_life/video?resourceId=" + item.resourceId
- })
- },
- /*下拉刷新的回调 */
- downCallback() {
- this.refreshPage();
- },
- /*上拉加载的回调*/
- upCallback(page) {
- /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
- const params = {
- page: page.num,
- pageSize: page.size
- };
- try {
- // 直接调用对应的函数,避免使用变量
- if (this.tabIndex === 0) {
- // 调用我的评论接口
- getMyComments(params).then(res => {
- if (res.code == 200) {
- setTimeout(() => {
- const list = res.data && res.data.list ? res.data.list : [];
- // 转换数据格式,确保有必要的字段
- const formattedList = list.map(item => ({
- ...item,
- cover: item.imgsUrl || item.videoUrl || '',
- likeNum: item.likeCount || item.likeNum || item.likes || 0
- }));
- const total = res.data && res.data.total ? res.data.total : 0;
- const pages = Math.ceil(total / page.size);
- this.mescroll.endByPage(formattedList.length, pages);
- // 不累加数据,直接替换
- this.dataList = formattedList;
- },
- 300
- );
- } else {
- this.dataList = []; //追加新数据
- this.mescroll.endByPage(0, 1);
- }
- }).catch(err => {
- console.error('获取评论失败:', err);
- this.dataList = []; //追加新数据
- //联网失败, 结束加载
- this.mescroll.endErr();
- });
- } else {
- // 调用我的收藏接口
- getMyCollection(params).then(res => {
- if (res.code == 200) {
- setTimeout(() => {
- const list = res.data && res.data.list ? res.data.list : [];
- // 转换数据格式,确保有必要的字段
- const formattedList = list.map(item => ({
- ...item,
- cover: item.imgsUrl || item.videoUrl || '',
- likeNum: item.likeCount || item.likeNum || item.likes || 0
- }));
- const total = res.data && res.data.total ? res.data.total : 0;
- const pages = Math.ceil(total / page.size);
- this.mescroll.endByPage(formattedList.length, pages);
- // 不累加数据,直接替换
- this.dataList = formattedList;
- },
- 300
- );
- } else {
- this.dataList = []; //追加新数据
- this.mescroll.endByPage(0, 1);
- }
- }).catch(err => {
- console.error('获取收藏失败:', err);
- this.dataList = []; //追加新数据
- //联网失败, 结束加载
- this.mescroll.endErr();
- });
- }
- } catch (error) {
- console.error('错误:', error);
- this.dataList = [];
- this.mescroll.endErr();
- }
- },
- refreshPage() {
- if (this.mescroll) {
- this.mescroll.hideTopBtn();
- this.mescroll.resetUpScroll(true);
- // 手动触发上拉加载,获取第一页数据
- this.mescroll.triggerUpScroll();
- } else {
- // 如果 mescroll 还未初始化,延迟后重试
- setTimeout(() => {
- this.refreshPage();
- }, 100);
- }
- },
- tabChange(index) {
- console.log("qxj tabChange");
- this.tabIndex = index;
- this.refreshPage();
- // 更新tab位置
- this.initTabPositions();
- },
- // 初始化tab位置
- initTabPositions() {
- let positions = [];
- // 确保mtabs有数据
- if (this.mtabs.length === 0) {
- console.log('No tabs data available');
- return;
- }
- Promise.all(
- this.mtabs.map((_, index) =>
- new Promise((resolve) => {
- uni
- .createSelectorQuery()
- .in(this)
- .select(`#tab-${index}`)
- .boundingClientRect((data) => {
- if (data) {
- positions.push({ left: data.left, width: data.width });
- } else {
- // 兜底默认宽度
- positions.push({ left: index * 150, width: 150 });
- }
- resolve();
- })
- .exec();
- })
- )
- ).then(() => {
- // 所有节点查询完毕,一次性赋值
- this.tabPositions = positions;
- // console.log('Calculated tab positions:', this.tabPositions);
- });
- },
- //点击空布局按钮的回调
- emptyClick() {
- this.refreshPage();
- },
- // 初始化mescroll
- mescrollInit(mescroll) {
- this.mescroll = mescroll;
- // 初始化时触发一次加载
- if (!this.dataList.length) {
- setTimeout(() => {
- this.mescroll.triggerUpScroll();
- }, 100);
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- page {
- height: 100%;
- background-color: #f5f5f5;
- }
- .content {
- height: 100%;
- position: relative;
- }
- .top-fixed {
- width: 100%;
- position: absolute;
- top: 0;
- left: 0;
- z-index: 10;
- height: 88rpx;
- background-color: #fff;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
- }
- .tabs-container {
- height: 100%;
- display: flex;
- align-items: center;
- position: relative;
- .tab-item {
- flex: 1;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- position: relative;
- &.active {
- text {
- color: #333333;
- font-weight: bold;
- }
- }
- text {
- font-size: 34rpx;
- color: #4D4D4D;
- line-height: 90rpx;
- }
- }
- .nav-underline {
- position: absolute;
- height: 6rpx;
- border-radius: 2rpx;
- top: 84rpx;
- width: var(--underline-width, 0);
- left: var(--underline-left, 0);
- opacity: var(--underline-opacity, 0);
- visibility: visible;
- transition: all 0.3s ease;
- background-color: #02B176;
- transform: translateX(-50%);
- }
- }
- .sticky-tabs {
- display: none;
- }
- .comment-list {
- margin-top: 88rpx;
- display: flex;
- flex-wrap: wrap;
- padding: 20rpx 0;
- gap: 16rpx;
- }
- .comment-item {
- position: relative;
- width: calc(33% - 10rpx);
- background-color: #fff;
- border-radius: 16rpx;
- margin-bottom: 0;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
- height: 280rpx;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- .comment-image {
- width: 100%;
- height: 100%;
- border-radius: 10rpx;
- margin-bottom: 12rpx;
- object-fit: cover;
- }
- .comment-video{
- width: 100%;
- height: 100%;
- border-radius: 10rpx;
- margin-bottom: 12rpx;
- object-fit: cover;
- }
- .comment-header {
- display: flex;
- justify-content: flex-end;
- .item-type-tag {
- font-size: 18rpx;
- color: #999999;
- padding: 4rpx 8rpx;
- background-color: #f5f5f5;
- border-radius: 4rpx;
- }
- }
- .comment-footer {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-top: auto;
- .like-count {
- width: 100%;
- padding: 8rpx 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: rgba(0, 0, 0, 0.4);
-
- .like-icon {
- width: 24rpx;
- height: 24rpx;
- margin-right: 4rpx;
- }
- text {
- font-size: 22rpx;
- color: #666666;
- }
- }
- }
- }
- </style>
|