Files
YwxAppThink/addon/wxchat/YwxMakeFriends/pages/my/likes.uvue
T

261 lines
5.5 KiB
Plaintext

<template>
<view class="page">
<scroll-view direction="vertical" :show-scrollbar="false" style="flex:1;"
:refresher-enabled="true" :refresher-triggered="refreshing" @refresherrefresh="onRefresh">
<view class="summary-card">
<text class="summary-num">{{ totalLikes }}</text>
<text class="summary-label">共获得 {{ list.length }} 条动态的点赞</text>
</view>
<view class="list">
<view v-for="(m, idx) in sorted" :key="idx" class="moment-item" @click="openDetail(m)">
<view class="m-head">
<image class="m-avatar" :src="imgUrl(m.userAvatar)" mode="aspectFill"></image>
<view class="m-meta">
<text class="m-name">{{ m.userName }}</text>
<text class="m-time">{{ formatTime(m.time) }}</text>
</view>
<view class="like-badge">
<uni-icons type="heart-filled" size="22" color="#FF2D55"></uni-icons>
<text class="like-num">{{ m.likes }}</text>
</view>
</view>
<text class="m-content">{{ m.content }}</text>
<view v-if="m.images && m.images.length > 0" class="m-images">
<image v-for="(img, i) in m.images.slice(0,3)" :key="i" class="m-img"
:src="imgUrl(img)" mode="aspectFill"></image>
</view>
<view class="m-foot">
<view class="m-stat"><uni-icons type="chatbubble" size="22" color="#999"></uni-icons>
<text>{{ m.comments }}</text></view>
<view class="m-stat"><uni-icons type="redo" size="22" color="#999"></uni-icons>
<text>{{ m.shares }}</text></view>
</view>
</view>
<view v-if="list.length === 0 && !loading" class="empty-state">
<uni-icons type="heart" size="60" color="#ddd"></uni-icons>
<text class="empty-text">还没有人给你点赞哦</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="uts">
import Api from '@/common/api-service.uts'
const BASE = 'https://dev.xixingwl.cn'
type IMoment = {
id : number
uid : number
userName : string
userAvatar : string
content : string
images : string[]
videoUrl : string
type : string
time : number
likes : number
comments : number
shares : number
}
const list = reactive<IMoment[]>([])
const sorted = computed<IMoment[]>(() => {
return list.slice().sort((a : IMoment, b : IMoment) => b.likes - a.likes)
})
const totalLikes = computed<number>(() => {
let s = 0
list.forEach((m : IMoment) => { s += m.likes })
return s
})
const loading = ref<boolean>(false)
const refreshing = ref<boolean>(false)
function imgUrl(src : string) : string {
if (! src) return ''
return src.startsWith('http') ? src : (BASE + src)
}
function formatTime(ts : number) : string {
if (! ts) return ''
const d = new Date(ts)
const pad = (n : number) : string => n < 10 ? '0' + n : '' + n
return `${d.getMonth() + 1}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
}
function openDetail(m : IMoment) {
uni.navigateTo({ url: '/pages/moment/details?id=' + m.id })
}
function loadData() {
if (loading.value) return
loading.value = true
Api.moment.mine({ page: 1, page_size: 50 })
.then((res : UTSJSONObject) => {
const arr = (res.get('list') as Array<IMoment>) ?? []
list.splice(0, list.length)
arr.forEach((m : IMoment) => list.push(m))
})
.catch(() => {
uni.showToast({ title: '加载失败', icon: 'none' })
})
.finally(() => {
loading.value = false
refreshing.value = false
})
}
function onRefresh() {
refreshing.value = true
loadData()
}
onMounted(() => { loadData() })
onShow(() => { loadData() })
</script>
<style lang="scss">
.page {
flex: 1;
background-color: #f7f7f7;
}
.summary-card {
display: flex;
flex-direction: column;
align-items: center;
margin: 24rpx 30rpx;
padding: 36rpx 0;
background: linear-gradient(135deg, #FF2D55 0%, #FF6B6B 100%);
border-radius: 20rpx;
}
.summary-num {
font-size: 52rpx;
font-weight: bold;
color: #fff;
}
.summary-label {
font-size: 24rpx;
color: #ffe;
margin-top: 8rpx;
}
.list {
margin: 0 30rpx 24rpx;
}
.moment-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 16rpx;
}
.m-head {
display: flex;
flex-flow: row nowrap;
align-items: center;
margin-bottom: 16rpx;
}
.m-avatar {
width: 72rpx;
height: 72rpx;
border-radius: 36rpx;
background-color: #f0f0f0;
margin-right: 16rpx;
}
.m-meta {
display: flex;
flex-direction: column;
flex: 1;
}
.m-name {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.m-time {
font-size: 22rpx;
color: #bbb;
margin-top: 4rpx;
}
.like-badge {
display: flex;
flex-flow: row nowrap;
align-items: center;
background-color: rgba(255, 45, 85, 0.08);
padding: 6rpx 16rpx;
border-radius: 24rpx;
}
.like-num {
font-size: 26rpx;
color: #FF2D55;
font-weight: bold;
margin-left: 6rpx;
}
.m-content {
font-size: 28rpx;
color: #333;
line-height: 1.5;
display: block;
}
.m-images {
display: flex;
flex-flow: row wrap;
margin-top: 16rpx;
}
.m-img {
width: 200rpx;
height: 200rpx;
border-radius: 12rpx;
margin: 0 12rpx 12rpx 0;
background-color: #f0f0f0;
}
.m-foot {
display: flex;
flex-flow: row nowrap;
margin-top: 16rpx;
}
.m-stat {
display: flex;
flex-flow: row nowrap;
align-items: center;
margin-right: 40rpx;
font-size: 24rpx;
color: #999;
}
.m-stat text {
margin-left: 6rpx;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 120rpx 0;
}
.empty-text {
font-size: 28rpx;
color: #bbb;
margin-top: 20rpx;
}
</style>