500 lines
10 KiB
Vue
Raw Normal View History

2024-10-30 18:49:19 +08:00
<template>
<s-layout title="社区种草" :bgStyle="{ color: '#fff' }">
2025-06-09 11:33:50 +08:00
<!-- 导航栏切换 -->
<view class="top-nav">
<view :class="{ active: currentTab === 0 }" @click="switchTab(0)">关注</view>
<view :class="{ active: currentTab === 1 }" @click="switchTab(1)">发现</view>
</view>
<!-- 新增的二级导航栏 -->
<view class="second-nav">
<view v-for="(item, index) in secondNavList" :key="index" :class="{ active: secondNavIndex === index }"
@click="switchSecondNav(index)">
{{ item }}
</view>
</view>
2025-05-08 16:52:29 +08:00
<view class="container">
<scroll-view scroll-y :style="{ height: windowHeight + 'px' }" @scrolltolower="loadMore">
<!-- 两列容器 -->
<view class="waterfall">
<!-- 左列 -->
<view class="column">
2025-06-09 11:33:50 +08:00
<view v-for="(item, index) in leftList" :key="'left-' + index" class="item"
@click="goDetail(item.id)">
2025-05-08 16:52:29 +08:00
<image :src="item.picUrl" mode="widthFix"></image>
2025-06-09 11:33:50 +08:00
<view class="item-content">
<text>{{ item.content }}</text>
<view class="item-actions">
<view class="action-like" @click.stop="likeItem(item.id, index, 'left')">
<image
:src="item.isLiked ? '/static/images/like-active.png' : '/static/images/like.png'"
mode="aspectFit"></image>
<text>{{ item.likeCount !== null ? item.likeCount : 0 }}</text>
</view>
</view>
</view>
2025-05-08 16:52:29 +08:00
</view>
</view>
2025-06-09 11:33:50 +08:00
2025-05-08 16:52:29 +08:00
<!-- 右列 -->
<view class="column">
2025-06-09 11:33:50 +08:00
<view v-for="(item, index) in rightList" :key="'right-' + index" class="item"
@click="goDetail(item.id)">
2025-05-08 16:52:29 +08:00
<image :src="item.picUrl" mode="widthFix"></image>
2025-06-09 11:33:50 +08:00
<view class="item-content">
<text>{{ item.content }}</text>
<view class="item-actions">
<view class="action-like" @click.stop="likeItem(item.id, index, 'right')">
<image
:src="item.isLiked ? '/static/images/like-active.png' : '/static/images/like.png'"
mode="aspectFit"></image>
<text>{{ item.likeCount !== null ? item.likeCount : 0 }}</text>
</view>
</view>
</view>
2025-05-08 16:52:29 +08:00
</view>
</view>
</view>
2025-06-09 11:33:50 +08:00
2025-05-08 16:52:29 +08:00
<!-- 加载提示 -->
<view class="loading">{{ loadingText }}</view>
</scroll-view>
</view>
2025-06-09 11:33:50 +08:00
<!-- 发布 -->
<view class="publish" @click="publish" :class="bottomNavigationIsCustom ? 'bottom' : ''">发布</view>
2024-10-30 18:49:19 +08:00
</s-layout>
</template>
<script setup>
import request from '@/sheep/request';
2025-05-08 16:52:29 +08:00
import SeedApi from '@/sheep/api/seedComm/seedComm.js';
2024-10-30 18:49:19 +08:00
import sheep from '@/sheep';
import {
baseUrl,
apiPath
} from '@/sheep/config';
import {
2025-05-08 16:52:29 +08:00
computed,
reactive,
nextTick,
onMounted,
2024-10-30 18:49:19 +08:00
ref
2025-06-09 11:33:50 +08:00
} from 'vue';
2025-05-08 16:52:29 +08:00
import {
onShow,
onReachBottom
} from '@dcloudio/uni-app';
// 响应式数据
2025-06-09 11:33:50 +08:00
const windowHeight = ref(0);
const allData = ref([]);
const leftList = ref([]);
const rightList = ref([]);
const page = ref(1);
const loadingText = ref('加载中...');
const currentTab = ref(1); // 0 表示关注1 表示发现
const secondNavList = ref(['推荐', '视频', '短剧', '旅游', '美食', '游戏', '钓鱼', '服饰', '信息发布', '创业']);
const secondNavIndex = ref(0);
const isShow = ref(false);
// 点赞功能
const likeItem = async (id, index, column) => {
try {
// 先获取当前点赞状态
const {
code,
data
} = await SeedApi.getLike(id);
if (code !== 0) {
uni.showToast({
title: '获取点赞状态失败',
icon: 'fail'
});
return;
}
// 判断用户是否已点赞
const isLiked = data === true;
// 调用点赞API
const {
code: likeCode,
data: likeData
} = await SeedApi.doLike(id);
if (likeCode === 0) {
// 获取当前列表
const list = column === 'left' ? leftList.value : rightList.value;
const item = list[index];
// 更新点赞状态
item.isLiked = !isLiked; // 切换点赞状态
// 如果已点赞likeCount+1否则likeCount-1
item.likeCount = isLiked ? item.likeCount - 1 : item.likeCount + 1;
// 更新列表
if (column === 'left') {
leftList.value = [...leftList.value.slice(0, index), item, ...leftList.value.slice(index + 1)];
} else {
rightList.value = [...rightList.value.slice(0, index), item, ...rightList.value.slice(index +
1)];
}
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
// 提示用户
uni.showToast({
title: item.isLiked ? '点赞成功' : '取消点赞',
icon: 'success'
});
} else {
uni.showToast({
title: likeData || '点赞失败',
icon: 'fail'
});
}
} catch (error) {
console.error('点赞请求失败:', error);
uni.showToast({
title: '网络错误,请稍后再试',
icon: 'fail'
});
}
}
2025-05-08 16:52:29 +08:00
// 生命周期
onMounted(() => {
windowHeight.value = uni.getSystemInfoSync().windowHeight
2025-06-09 11:33:50 +08:00
// loadData()
2025-05-08 16:52:29 +08:00
})
2025-06-09 11:33:50 +08:00
onShow(() => {
// 重置数据
page.value = 1
allData.value = []
leftList.value = []
rightList.value = []
loadingText.value = '加载中...'
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
loadData()
})
const goDetail = (id) => {
uni.navigateTo({
url: `/pages/seeding/seeding_fabu/detail?id=${id}`
});
}
// 获取数据
2025-05-08 16:52:29 +08:00
const loadData = async () => {
2025-06-09 11:33:50 +08:00
if (loadingText.value !== '加载中...') return;
2025-05-08 16:52:29 +08:00
try {
2025-06-09 11:33:50 +08:00
let newData = [];
if (currentTab.value === 0) {
newData = await getFollowList();
} else {
newData = await getlist();
}
// 获取每一项的点赞状态
for (let item of newData) {
const {
code,
data
} = await SeedApi.getLike(item.id); // 获取每条数据的点赞状态
if (code === 0) {
item.isLiked = data; // 根据返回的点赞状态设置
} else {
item.isLiked = false; // 如果获取失败,默认未点赞
}
}
allData.value = [...allData.value, ...newData];
2025-05-08 16:52:29 +08:00
// 简单交替分配数据
newData.forEach((item, index) => {
2025-06-09 11:33:50 +08:00
index % 2 === 0 ? leftList.value.push(item) : rightList.value.push(item);
});
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
loadingText.value = '加载完成';
2025-05-08 16:52:29 +08:00
} catch (error) {
2025-06-09 11:33:50 +08:00
console.error('加载数据失败:', error);
loadingText.value = '加载失败';
2025-05-08 16:52:29 +08:00
}
2025-06-09 11:33:50 +08:00
};
2025-05-08 16:52:29 +08:00
const loadMore = () => {
page.value++
loadingText.value = '加载中...'
loadData()
}
// 模拟接口请求
const mockApiRequest = () => {
return new Promise(resolve => {
setTimeout(() => {
const mockData = Array(10).fill().map((_, i) => ({
id: Date.now() + i,
title: `Item ${page.value * 10 + i}`,
image: `https://picsum.photos/300/${400 + Math.floor(Math.random() * 200)}`
}))
resolve(mockData)
}, 1000)
})
}
2025-06-09 11:33:50 +08:00
// 获取关注列表
async function getFollowList() {
const {
code,
data
} = await SeedApi.getSeedList({
pageNo: page.value,
});
if (code !== 0) {
return;
}
return data.list;
}
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
// 获取发现列表
2025-05-08 16:52:29 +08:00
async function getlist() {
2025-06-09 11:33:50 +08:00
const {
code,
data
} = await SeedApi.getSeedList({
2025-05-08 16:52:29 +08:00
pageNo: page.value,
2024-10-30 18:49:19 +08:00
});
2025-05-08 16:52:29 +08:00
if (code !== 0) {
2025-06-09 11:33:50 +08:00
return;
2025-05-08 16:52:29 +08:00
}
return data.list;
2024-10-30 18:49:19 +08:00
}
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
// 切换标签
const switchTab = (tabIndex) => {
currentTab.value = tabIndex;
page.value = 1;
allData.value = [];
leftList.value = [];
rightList.value = [];
loadingText.value = '加载中...';
loadData();
};
// 切换二级导航标签
const switchSecondNav = (index) => {
secondNavIndex.value = index;
page.value = 1;
allData.value = [];
leftList.value = [];
rightList.value = [];
loadingText.value = '加载中...';
loadData();
};
// 发布动态
function publish() {
uni.navigateTo({
url: '/pages/seeding/seeding_fabu/seeding_fabu', // 根据实际路径调整
});
2024-10-30 18:49:19 +08:00
}
</script>
<style scoped lang="scss">
2025-06-09 11:33:50 +08:00
.top-nav {
display: flex;
justify-content: center;
padding: 10px;
background-color: #f5f5f5;
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
view {
padding: 5px 20px;
cursor: pointer;
2025-05-08 16:52:29 +08:00
2025-06-09 11:33:50 +08:00
&.active {
color: #e93323;
font-weight: bold;
2024-10-30 18:49:19 +08:00
}
}
}
2025-06-09 11:33:50 +08:00
// .seeding {
// .list {
// background: white;
// margin: 10px;
// margin-bottom: 5px;
// padding: 10px;
// .top {
// display: flex;
// align-items: center;
// .l {
// margin-right: 10px;
// .img {
// width: 40px;
// height: 40px;
// }
// }
// .r {
// .name {
// font-weight: 700;
// }
// .time {
// font-size: 12px;
// color: rgba(163, 163, 163);
// }
// }
// }
// .content {
// margin-top: 10px;
// }
// .bottom {
// display: flex;
// justify-content: flex-end;
// .ck {
// display: flex;
// align-items: center;
// margin-right: 20px;
// color: rgba(163, 163, 163);
// .img {
// width: 20px;
// height: 20px;
// margin-right: 8px;
// }
// }
// }
// }
// }
// .btn {
// margin-top: 50px;
// background: white;
// display: flex;
// justify-content: center;
// flex-wrap: wrap;
// .content_cs {
// width: 100%;
// text-align: center;
// padding: 10px;
// margin: 20px 0;
// margin-bottom: 10px;
// background-color: rgba(246, 246, 246);
// }
// .pic {
// width: 100%;
// text-align: center;
// }
// }
// .dd {
// width: 100%;
// text-align: center;
// background: red;
// color: white;
// width: 50%;
// margin: 0 auto;
// padding: 10px;
// margin-bottom: 30px;
// border-radius: 15px;
// }
.second-nav {
2025-05-08 16:52:29 +08:00
display: flex;
2025-06-09 11:33:50 +08:00
justify-content: start;
padding: 10rpx;
background-color: #fff;
border-bottom: 1px solid #eaeaea;
overflow-x: auto;
white-space: nowrap;
view {
padding: 5px 10px;
cursor: pointer;
&.active {
color: #e93323;
font-weight: bold;
}
2024-10-30 18:49:19 +08:00
}
}
2025-05-08 16:52:29 +08:00
.waterfall {
display: flex;
justify-content: space-between;
padding: 10rpx;
}
.column {
flex: 1;
max-width: 49%;
}
.item {
background: #fff;
margin-bottom: 20rpx;
border-radius: 10rpx;
overflow: hidden;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
}
.item image {
width: 100%;
}
.loading {
text-align: center;
padding: 20rpx;
color: #999;
2024-10-30 18:49:19 +08:00
}
2025-06-09 11:33:50 +08:00
.publish {
position: fixed;
z-index: 9999;
width: 100rpx;
height: 100rpx;
opacity: 1;
border-radius: 50%;
bottom: 142rpx;
right: 24rpx;
color: pink;
line-height: 100rpx;
text-align: center;
background-color: palevioletred;
// @include linear-gradient(theme);
.iconfont {
font-size: 50rpx;
}
}
.item-content {
padding: 12rpx;
.item-actions {
display: flex;
justify-content: flex-end;
margin-top: 10rpx;
.action-like {
display: flex;
align-items: center;
font-size: 24rpx;
image {
width: 32rpx;
height: 32rpx;
margin-right: 4rpx;
}
text {
color: #999;
}
// 点赞激活状态样式
&.liked text {
color: #e93323;
}
}
}
}
2024-10-30 18:49:19 +08:00
</style>