307 lines
8.5 KiB
Vue
307 lines
8.5 KiB
Vue
<template>
|
||
<view class="page">
|
||
<uni-nav-bar :fixed="true" :border="false" color="#000" backgroundColor="#fff" :statusBar="true" title="广场" />
|
||
<!-- Tabs -->
|
||
<view class="tabs">
|
||
<view :class="['tab', currentTab==='latest'?'on':'']" @click="changeTab('latest')">最新发布</view>
|
||
<view class="divider"></view>
|
||
<view :class="['tab', currentTab==='near'?'on':'']" @click="changeTab('near')">距离最近</view>
|
||
</view>
|
||
|
||
<!-- Feed list -->
|
||
<scroll-view
|
||
scroll-y
|
||
class="list-scroll"
|
||
refresher-enabled
|
||
:refresher-triggered="refreshing"
|
||
@refresherrefresh="onRefresh"
|
||
:lower-threshold="100"
|
||
@scrolltolower="onLoadMore"
|
||
>
|
||
<view class="feed-list">
|
||
<post-card
|
||
v-for="sitem in slist"
|
||
:key="sitem.id || sitem.username"
|
||
:item="sitem"
|
||
@userClick="goto"
|
||
@view="goto"
|
||
@contact="handleContact"
|
||
@comment="handleComment">
|
||
</post-card>
|
||
|
||
<!-- 状态提示 -->
|
||
<view v-if="hasMore" class="load-more">
|
||
<text v-if="loadingMore">加载中...</text>
|
||
<text v-else>上拉加载更多</text>
|
||
</view>
|
||
<view v-else-if="slist.length > 0" class="load-more">
|
||
<text>没有更多了</text>
|
||
</view>
|
||
<view class="empty" v-if="slist.length === 0 && !loading">
|
||
<image src="/static/image/empty.png" mode="aspectFit"></image>
|
||
<view>暂无数据!</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 加载提示 -->
|
||
<view v-if="loading" class="loading-mask">
|
||
<view class="loading-text">加载中...</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
<script>
|
||
import { request } from '@/api/apiT.js'
|
||
import PostCard from '@/components/PostCard.vue'
|
||
export default {
|
||
components: { PostCard },
|
||
data() {
|
||
return {
|
||
tabs: [
|
||
{ key: 'latest', label: '最新发布' },
|
||
{ key: 'near', label: '距离最近' }
|
||
],
|
||
currentTab: 'latest',
|
||
slist:[
|
||
{
|
||
username:'用户名用户名',
|
||
time:'2025 年 12 月 4 日 10:56',
|
||
content:`西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子
|
||
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子西门子全新嵌饮机品牌
|
||
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子`,
|
||
tag:['#散饮机','#9成新'],
|
||
location:'门店位置',
|
||
image:[
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'}
|
||
]
|
||
},{
|
||
username:'用户名用户名',
|
||
time:'2025 年 12 月 4 日 10:56',
|
||
content:`西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子
|
||
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子西门子全新嵌饮机品牌
|
||
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子`,
|
||
tag:['#散饮机','#9成新'],
|
||
location:'门店位置',
|
||
image:[
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'}
|
||
]
|
||
},{
|
||
username:'用户名用户名',
|
||
time:'2025 年 12 月 4 日 10:56',
|
||
content:`西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子
|
||
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子西门子全新嵌饮机品牌
|
||
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子`,
|
||
tag:['#散饮机','#9成新'],
|
||
location:'门店位置',
|
||
image:[
|
||
{img_src:'/static/image/bx.jpg'},
|
||
{img_src:'/static/image/bx.jpg'}
|
||
]
|
||
}
|
||
],
|
||
loading: false,
|
||
refreshing: false,
|
||
loadingMore: false,
|
||
page: 1,
|
||
pageSize: 10,
|
||
hasMore: true,
|
||
defaultTags: ['样机机', '9成新']
|
||
}
|
||
},
|
||
onShow() {
|
||
this.loadList()
|
||
// this.syncTabbar()
|
||
},
|
||
methods: {
|
||
syncTabbar() {
|
||
uni.setTabBarItem({ index: 0, text: this.$t('tabbar.home') })
|
||
uni.setTabBarItem({ index: 1, text: this.$t('tabbar.square') })
|
||
uni.setTabBarItem({ index: 2, text: this.$t('tabbar.publish') })
|
||
uni.setTabBarItem({ index: 3, text: this.$t('tabbar.mine') })
|
||
},
|
||
changeTab(key) {
|
||
if (this.currentTab === key) return
|
||
this.currentTab = key
|
||
this.page = 1
|
||
this.hasMore = true
|
||
this.slist = []
|
||
this.loadList()
|
||
},
|
||
loadList(isLoadMore = false) {
|
||
if (isLoadMore) {
|
||
if (this.loadingMore || this.loading || this.refreshing || !this.hasMore) return
|
||
this.loadingMore = true
|
||
this.page += 1
|
||
} else {
|
||
if (this.loading || this.loadingMore) return
|
||
this.loading = true
|
||
this.page = 1
|
||
this.hasMore = true
|
||
this.slist = []
|
||
}
|
||
|
||
const sortKey = this.currentTab === 'near' ? 'distance' : 'latest'
|
||
|
||
request({
|
||
url: 'common/post/list',
|
||
method: 'GET',
|
||
data: {
|
||
current: this.page,
|
||
size: this.pageSize,
|
||
sort: sortKey
|
||
}
|
||
}).then(res => {
|
||
this.loading = false
|
||
this.loadingMore = false
|
||
this.refreshing = false
|
||
if (res.data.code === 200) {
|
||
const records = res.data.data.records || []
|
||
const total = res.data.data.total || 0
|
||
if (isLoadMore) {
|
||
this.slist = [...this.slist, ...records]
|
||
} else {
|
||
this.slist = records
|
||
}
|
||
this.hasMore = this.slist.length < total
|
||
}
|
||
}).catch(() => {
|
||
this.loading = false
|
||
this.loadingMore = false
|
||
this.refreshing = false
|
||
if (isLoadMore) {
|
||
this.page -= 1
|
||
}
|
||
})
|
||
},
|
||
onRefresh() {
|
||
if (this.loading || this.loadingMore) {
|
||
this.refreshing = false
|
||
return
|
||
}
|
||
this.refreshing = true
|
||
this.loadList(false)
|
||
},
|
||
onLoadMore() {
|
||
this.loadList(true)
|
||
},
|
||
navToList(item) {
|
||
uni.navigateTo({
|
||
url: '/pages/square/detiles?id=' + item.id
|
||
})
|
||
},
|
||
leftClick() {
|
||
uni.navigateBack()
|
||
}
|
||
},
|
||
computed: {
|
||
underlineTransform() {
|
||
const index = this.tabs.findIndex(t => t.key === this.currentTab)
|
||
return `translateX(${index * 50}%)`
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
page,
|
||
.page {
|
||
height: 100%;
|
||
background: #f8f8f8;
|
||
}
|
||
|
||
.tabs {
|
||
height: 80rpx;
|
||
background: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-around;
|
||
gap: 24rpx;
|
||
position: relative;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
.tab {
|
||
position: relative;
|
||
padding: 12rpx 20rpx 18rpx;
|
||
color: #333;
|
||
}
|
||
.tab::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 50%;
|
||
bottom: 4rpx;
|
||
width: 50rpx;
|
||
height: 4rpx;
|
||
background: #05b3a8;
|
||
border-radius: 4rpx;
|
||
transform: translateX(-50%) scaleX(0);
|
||
transition: transform 0.2s;
|
||
}
|
||
.tab.on {
|
||
color: #05b3a8;
|
||
font-weight: 600;
|
||
}
|
||
.tab.on::after {
|
||
transform: translateX(-50%) scaleX(1);
|
||
}
|
||
.divider {
|
||
width: 1px;
|
||
height: 26rpx;
|
||
background: #dcdcdc;
|
||
}
|
||
|
||
.list-scroll {
|
||
height: calc(100vh - 120rpx);
|
||
}
|
||
|
||
.feed-list {
|
||
// padding: 20rpx;
|
||
margin: 20rpx 30rpx;
|
||
// background: #fff;
|
||
}
|
||
.load-more {
|
||
width: 100%;
|
||
text-align: center;
|
||
padding: 30rpx 0;
|
||
font-size: 26rpx;
|
||
color: #999;
|
||
}
|
||
.empty {
|
||
width: 100%;
|
||
text-align: center;
|
||
padding: 100rpx 0;
|
||
}
|
||
.empty image {
|
||
width: 252rpx;
|
||
height: 164rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.loading-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.3);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 999;
|
||
|
||
.loading-text {
|
||
color: #fff;
|
||
font-size: 28upx;
|
||
background-color: rgba(0, 0, 0, 0.7);
|
||
padding: 20upx 40upx;
|
||
border-radius: 8upx;
|
||
}
|
||
}
|
||
</style> |