roamfuding-xcx/pages/myorder/index.vue

490 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<view class="header">
<view class="nav">
<view :class="['nav-item', currentTab === 0 ? 'active' : '']" @tap="switchTab(0)">关注</view>
<view :class="['nav-item', currentTab === 1 ? 'active' : '']" @tap="switchTab(1)">推荐</view>
</view>
<image class="tx" v-if="hasUnreadMessage" src="https://api.ccttiot.com/smartmeter/img/static/uJsq5WMYhxewFM9ZBuRC" mode="" @click="btnxx"></image>
<image class="tx" v-else src="https://api.ccttiot.com/smartmeter/img/static/uooAmTilbbGYRUNItfXc" mode="" @click="btnxx"></image>
<view class="search-box">
<view class="search-input">
<image src="https://api.ccttiot.com/smartmeter/img/static/upZuHOsydQDHm4LqYqxx" mode=""></image>
<input type="text" v-model="keyword" placeholder="输入感兴趣的话题"/>
</view>
<view class="search-btn" @tap="onSearch">搜索</view>
</view>
</view>
<swiper class="feed-swiper" :current="currentTab" :circular="false" duration="300" @change="onSwiperChange">
<swiper-item>
<scroll-view class="feed" @scrolltolower="handqixing" scroll-y refresher-enabled @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing" refresher-default-style="black">
<view class="feed-card" v-for="(item, index) in feedLists" :key="'f-'+index" @click="btnxq(index)">
<view class="card-header">
<image class="avatar" :src="item.userAvatar || 'https://api.ccttiot.com/smartmeter/img/static/uV1WyJ6lhVUkceC4Ci3V'" mode="aspectFill" />
<view class="meta">
<view class="name-row">
<text class="name">{{ item.nickName }}</text>
<view class="follow-btn" v-if="userId != item.userId" :class="{ followed: item.isFollowed }" @click.stop="toggleFollow(index)">{{ item.isFollowed ? '已关注' : '+ 关注' }}</view>
</view>
<text class="time">{{ item.createTime }}</text>
</view>
</view>
<view class="card-content">
<text class="text">{{ item.content }}</text>
<view v-if="item.picture && item.picture.length === 1" class="thumb-single">
<video v-if="isVideo(item.picture[0])" :src="item.picture[0]" :controls="true"></video>
<image v-else :src="item.picture[0]" mode="aspectFill" />
</view>
<view v-else-if="item.picture && item.picture.length > 1" class="thumb-grid">
<view v-for="(media, i) in item.picture" :key="'fi-'+i" class="grid-item">
<video v-if="isVideo(media)" :src="media" :controls="false"></video>
<image v-else :src="media" mode="aspectFill" />
</view>
</view>
<image v-else-if="item.image" class="thumb" :src="item.image" mode="aspectFill" />
<view v-else-if="item.video || item.videoUrl" class="video-thumb">
<video :src="item.video || item.videoUrl" :poster="item.cover || item.videoCover" :controls="true"></video>
</view>
</view>
<view class="dizhi">
<image class="qian" src="https://api.ccttiot.com/smartmeter/img/static/ugQMH5UxepQ6r2VfKtlP" mode=""></image>
{{(item.location || '').toString().trim().length > 15 ? (item.location || '').toString().trim().slice(0, 15) + '...' : (item.location || '').toString().trim() || '暂无位置'}}
<image class="hou" src="https://api.ccttiot.com/smartmeter/img/static/uOtVmaBGci0kew9b0EpI" mode=""></image>
</view>
<view class="card-actions">
<view class="action"> <image src="https://api.ccttiot.com/smartmeter/img/static/uoHMIOnyYlNJCJcz9eLF" mode=""></image> <text class="num">{{ item.forwards }}</text></view>
<view class="" style="display: flex;">
<view class="action"><image src="https://api.ccttiot.com/smartmeter/img/static/uypbgeMkBQw7XWmzKmm6" mode=""></image><text class="num">{{ item.likes }}</text></view>
<view class="action" style="margin-left: 66rpx;"><image src="https://api.ccttiot.com/smartmeter/img/static/uXEnQ1G3WIg699VdXiAk" mode=""></image><text class="num">{{ item.commentCount || 0 }}</text></view>
</view>
</view>
</view>
<view class="" style="width: 100%;text-align: center;margin-top: 30rpx;color: #ccc;">
当前没有更多关注动态咯...
</view>
</scroll-view>
</swiper-item>
<swiper-item>
<scroll-view class="feed" @scrolltolower="handqixing" scroll-y refresher-enabled @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing" refresher-default-style="black">
<view class="feed-card" v-for="(item, index) in feedList" :key="'r-'+index" @click="btnxq(index)">
<view class="card-header">
<image class="avatar" :src="item.userAvatar || 'https://api.ccttiot.com/smartmeter/img/static/uV1WyJ6lhVUkceC4Ci3V'" mode="aspectFill" />
<view class="meta">
<view class="name-row">
<text class="name">{{ item.nickName }}</text>
<view class="follow-btn" v-if="userId != item.userId" :class="{ followed: item.isFollowed }" @click.stop="toggleFollow(index)">{{ item.isFollowed ? '已关注' : '+ 关注' }}</view>
</view>
<text class="time">{{ item.createTime }}</text>
</view>
</view>
<view class="card-content">
<text class="text">{{ item.content }}</text>
<view v-if="item.picture && item.picture.length === 1" class="thumb-single">
<video v-if="isVideo(item.picture[0])" :src="item.picture[0]" :controls="true"></video>
<image v-else :src="item.picture[0]" mode="aspectFill" />
</view>
<view v-else-if="item.picture && item.picture.length > 1" class="thumb-grid">
<view v-for="(media, i) in item.picture" :key="'ri-'+i" class="grid-item">
<video v-if="isVideo(media)" :src="media" :controls="false"></video>
<image v-else :src="media" mode="aspectFill" />
</view>
</view>
<image v-else-if="item.image" class="thumb" :src="item.image" mode="aspectFill" />
<view v-else-if="item.video || item.videoUrl" class="video-thumb">
<video :src="item.video || item.videoUrl" :poster="item.cover || item.videoCover" :controls="true"></video>
</view>
</view>
<view class="dizhi">
<image class="qian" src="https://api.ccttiot.com/smartmeter/img/static/ugQMH5UxepQ6r2VfKtlP" mode=""></image>
{{(item.location || '').toString().trim().length > 15 ? (item.location || '').toString().trim().slice(0, 15) + '...' : (item.location || '').toString().trim() || '暂无位置'}}
<image class="hou" src="https://api.ccttiot.com/smartmeter/img/static/uOtVmaBGci0kew9b0EpI" mode=""></image>
</view>
<view class="card-actions">
<view class="action"> <image src="https://api.ccttiot.com/smartmeter/img/static/uoHMIOnyYlNJCJcz9eLF" mode=""></image> <text class="num">{{ item.forwards }}</text></view>
<view class="" style="display: flex;">
<view class="action" v-if="item.isLiked == true"><image src="https://api.ccttiot.com/smartmeter/img/static/uCxUJSEQTStvqaf93xox" mode=""></image><text class="num">{{ item.likes }}</text></view>
<view class="action" v-else><image src="https://api.ccttiot.com/smartmeter/img/static/uypbgeMkBQw7XWmzKmm6" mode=""></image><text class="num">{{ item.likes }}</text></view>
<view class="action" style="margin-left: 66rpx;"><image src="https://api.ccttiot.com/smartmeter/img/static/uXEnQ1G3WIg699VdXiAk" mode=""></image><text class="num">{{ item.commentCount || 0 }}</text></view>
</view>
</view>
</view>
<view class="" style="width: 100%;text-align: center;margin-top: 30rpx;color: #ccc;">
当前没有更多推荐动态咯...
</view>
</scroll-view>
</swiper-item>
</swiper>
<tab-bar :indexs='3'></tab-bar>
</view>
</template>
<script>
// import { textStride } from 'XrFrame/components/text/Text'
export default {
data() {
return {
bgc: {
backgroundColor: "#fff",
},
currentTab: 1,
feedList: [],
feedLists: [],
isRefreshing:false,
isLoading: false,
total:0,
pageNum:1,
keyword:'',
hasUnreadMessage:false,
userId:''
}
},
onLoad() {
this.getdongtailist()
},
onShow() {
this.getinfo()
},
methods: {
// 请求我的个人信息
getinfo(){
this.$u.get(`/getInfo`).then(res =>{
if(res.code == 200){
this.hasUnreadMessage = res.user.hasUnreadMessage
this.userId = res.user.userId
uni.setStorageSync('userId',this.userId) //将自己的用户ID存到本地
console.log(this.userId);
}
})
},
// 判断获取的数据是否为视频(通过后缀名)
isVideo(url) {
if (!url || typeof url !== 'string') return false
const lower = url.split('?')[0].toLowerCase()
return ['.mp4','.mov','.m4v','.mkv','.avi','.wmv','.flv','.webm','.3gp'].some(ext => lower.endsWith(ext))
},
// 请求推荐动态列表
getdongtailist(){
this.$u.get(`/app/feed/list?pageNum=${this.pageNum}&pageSize=20&keyword=${this.keyword}`).then(res =>{
if(res.code == 200){
this.total = res.total
if(this.pageNum == 1){
this.pageNum++
this.feedList = res.rows
}else{
this.pageNum++
this.feedList = this.feedList.concat(res.rows)
}
}
})
},
// 请求关注动态列表
getguanzhulist(){
this.$u.get(`/app/feed/followed?pageNum=${this.pageNum}&pageSize=20&keyword=${this.keyword}`).then(res =>{
if(res.code == 200){
this.total = res.total
if(this.pageNum == 1){
this.pageNum++
this.feedLists = res.rows
}else{
this.pageNum++
this.feedList = this.feedList.concat(res.rows)
}
}
})
},
// 点击查看消息
btnxx(){
console.log(1);
uni.navigateTo({
url:'/page_fenbao/guangchang/zanandxx'
})
},
// 点击消息跳转到详情页 、右右左左右
btnxq(index){
if(this.currentTab == 1){
uni.navigateTo({
url:'/page_fenbao/guangchang/dongtaixq?id=' + this.feedList[index].id
})
}else{
uni.navigateTo({
url:'/page_fenbao/guangchang/dongtaixq?id=' + this.feedLists[index].id
})
}
},
// 头部tab点击切换
switchTab(index) {
this.currentTab = index
this.pageNum = 1
},
// 点击搜索指定的消息
onSearch() {
this.pageNum = 1
if(this.currentTab == 1){
this.getdongtailist()
}else{
this.getguanzhulist()
}
},
// 点击关注或者取关(批量同步同一发布者在两个列表中的关注状态)
toggleFollow(i) {
const inRecommendTab = this.currentTab == 1
const target = inRecommendTab ? this.feedList[i] : this.feedLists[i]
if (!target) return
const targetUserId = target.userId
const willFollow = !target.isFollowed
const request = willFollow ? this.$u.post(`/app/follow/add?followedId=${targetUserId}`) : this.$u.delete(`/app/follow/cancel?followedId=${targetUserId}`)
request.then(res => {
if (res.code == 200) {
this.updateFollowStateAcrossLists(targetUserId, willFollow)
uni.showToast({
title: willFollow ? '关注成功' : '取关成功',
icon: 'success',
duration: 3000
})
}else if(res.code == 401){
uni.reLaunch({
url:'/pages/login/login'
})
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 3000
})
}
})
},
// 同步两个列表中相同 userId 的 isFollowed 状态
updateFollowStateAcrossLists(userId, isFollowed) {
for (let idx = 0; idx < this.feedList.length; idx++) {
if (this.feedList[idx] && this.feedList[idx].userId === userId) {
const updated = { ...this.feedList[idx], isFollowed }
this.$set(this.feedList, idx, updated)
}
}
for (let idx = 0; idx < this.feedLists.length; idx++) { //判断是不是自己
if (this.feedLists[idx] && this.feedLists[idx].userId === userId) {
const updated = { ...this.feedLists[idx], isFollowed }
this.$set(this.feedLists, idx, updated)
}
}
},
// 轮播图左右滑动切换事件
onSwiperChange(e) {
this.currentTab = e.detail.current
this.pageNum = 1
if(e.detail.current == 1){ //判断是点赞还是回复评论区分请求
this.getdongtailist()
}else{
this.getguanzhulist()
}
},
// 上拉加载更多数据
handqixing() {
if(this.currentTab == 1){
if(this.feedList.length < this.total){
this.getdongtailist()
}
}else{
if(this.feedLists.length < this.total){
this.getguanzhulist()
}
}
},
// 下拉刷新最新的数据
onRefresh() {
this.isRefreshing = true
setTimeout(() => {
this.pageNum = 1
this.isRefreshing = false
this.getinfo()
if(this.currentTab == 1){
this.getdongtailist()
}else{
this.getguanzhulist()
}
}, 300)
},
}
}
</script>
<style lang="scss">
page {
background: #fff;
}
.tx{
width: 50rpx;
height: 50rpx;
position: fixed;
top: 100rpx;
left: 44rpx;
z-index: 9;
}
.page { display: flex; flex-direction: column; height: 100vh; }
.header {
padding: 10rpx 24rpx 0;
background: #fff;
z-index: 10;
margin-top: 84rpx;
.nav {
display: flex;
justify-content: center;
gap: 80rpx;
margin-bottom: 20rpx;
.nav-item {
font-size: 32rpx;
color: #3D3D3D;
padding: 12rpx 6rpx;
&.active {
color: #000;
position: relative;
font-weight: 600;
font-size: 36rpx;
color: #3D3D3D;
&::after {
content: '';
display: block;
height: 6rpx;
width: 40rpx;
background: #1EC28B;
border-radius: 6rpx;
position: absolute;
left: 50%;
bottom: -8rpx;
transform: translateX(-50%);
}
}
}
}
.search-box {
display: flex;
align-items: center;
gap: 16rpx;
padding-bottom: 16rpx;
margin-top: 36rpx;
.search-input {
flex: 1;
background: #f5f6f7;
border-radius: 999rpx;
height: 72rpx;
padding: 0 28rpx;
display: flex;
align-items: center;
.iconfont {
margin-right: 12rpx;
color: #999;
}
image{
width: 32rpx;
height: 32rpx;
margin-right: 16rpx;
}
.placeholder { color: #999; }
}
.search-btn {
font-size: 32rpx;
color: #3D3D3D;
}
}
}
.feed-swiper { flex: 1; }
.feed {
width: 750rpx;
margin: auto;
height: 70vh;
overflow: scroll;
padding-bottom: 100rpx;
.feed-card {
padding: 24rpx 40rpx;
box-sizing: border-box;
.card-header {
display: flex;
.avatar {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
margin-right: 16rpx;
}
.meta { flex: 1; }
.name-row { display: flex; align-items: center; justify-content: space-between; }
.name { font-weight: 600; color: #333; }
.follow-btn {
padding: 6rpx 20rpx;
border-radius: 999rpx;
background: #00c27a;
color: #fff;
&.followed { background: #f0f0f0; color: #666; }
}
.time { color: #999; font-size: 24rpx; }
}
.card-content {
margin-top: 12rpx;
padding-left: 90rpx;
.text { color: #333; }
.thumb { width: 98px; height: 98px; border-radius: 12rpx; margin-top: 12rpx; }
.video-thumb { width: 98px; height: 98px; margin-top: 12rpx; border-radius: 12rpx; overflow: hidden; }
.video-thumb video { width: 98px; height: 98px; object-fit: cover; display: block; }
// 单图等比缩放最大宽度100%
.thumb-single {
margin-top: 12rpx;
image { width: 98px; height: 98px; border-radius: 12rpx; display: block; }
video { width: 98px; height: 98px; border-radius: 12rpx; object-fit: cover; display: block; }
}
// 多图正方形九宫格自适应裁剪
.thumb-grid {
margin-top: 12rpx;
display: grid;
grid-template-columns: repeat(3, 98px);
gap: 10rpx;
.grid-item {
position: relative;
width: 98px; height: 98px;
image, video {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
width: 98px; height: 98px;
border-radius: 8rpx;
}
}
}
}
.dizhi{
font-weight: 600;
font-size: 26rpx;
color: #1EC28B;
display: flex;
align-items: center;
margin-top: 10rpx;
padding-left: 90rpx;
.qian{
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
}
.hou{
width: 32rpx;
height: 32rpx;
margin-left: 4rpx;
}
}
.card-actions {
margin-top: 16rpx;
display: flex;
justify-content: space-between;
gap: 32rpx;
color: #666;
padding-left: 90rpx;
image{
width: 32rpx;
height: 32rpx;
}
.action { display: flex; align-items: center; }
.num { margin-left: 8rpx; }
}
}
}
</style>