213 lines
4.6 KiB
Plaintext
213 lines
4.6 KiB
Plaintext
<template>
|
|
<view class="page">
|
|
<scroll-view direction="vertical" :show-scrollbar="false" style="flex:1;"
|
|
:refresher-enabled="true" :refresher-triggered="refreshing" @refresherrefresh="onRefresh"
|
|
@scrolltolower="onReachBottom">
|
|
<view class="list">
|
|
<view v-for="(item, index) in records" :key="index" class="user-item" @click="goProfile(item.id)">
|
|
<image class="avatar" :src="item.avatar" mode="aspectFill"></image>
|
|
<view class="info">
|
|
<view class="name-row">
|
|
<text class="nickname">{{ item.nickname }}</text>
|
|
<view v-if="item.is_mutual == 1" class="mutual-tag">
|
|
<text class="mutual-txt">互相关注</text>
|
|
</view>
|
|
</view>
|
|
<text class="time">{{ item.follow_time }}</text>
|
|
</view>
|
|
<view v-if="item.is_mutual == 0" class="follow-btn" @click.stop="follow(item)">
|
|
<text class="follow-txt">回关</text>
|
|
</view>
|
|
<uni-icons v-else type="right" size="18" color="#ccc"></uni-icons>
|
|
</view>
|
|
|
|
<view v-if="records.length == 0 && !loading" class="empty-state">
|
|
<uni-icons type="staff" size="60" color="#ddd"></uni-icons>
|
|
<text class="empty-text">还没有粉丝</text>
|
|
</view>
|
|
<view v-if="loading" class="loading-tip">
|
|
<text class="loading-txt">加载中...</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import Api from '@/common/api-service.uts'
|
|
import { getUserInfo } from '@/stores/user.uts'
|
|
|
|
type IFollowUser = {
|
|
id : number
|
|
nickname : string
|
|
avatar : string
|
|
is_mutual : number
|
|
follow_time : string
|
|
}
|
|
|
|
const records = reactive<IFollowUser[]>([])
|
|
const loading = ref<boolean>(false)
|
|
const refreshing = ref<boolean>(false)
|
|
const page = ref<number>(1)
|
|
const size = ref<number>(20)
|
|
const total = ref<number>(0)
|
|
const uid = ref<number>(0)
|
|
|
|
function loadData(reset : boolean) {
|
|
if (loading.value) return
|
|
if (uid.value <= 0) {
|
|
const info = getUserInfo()
|
|
uid.value = info?.uid ?? 0
|
|
}
|
|
if (uid.value <= 0) return
|
|
loading.value = true
|
|
if (reset) page.value = 1
|
|
Api.follow.followerList({ uid: uid.value, page: page.value, size: size.value })
|
|
.then((res : UTSJSONObject) => {
|
|
total.value = (res.get('total') as number) ?? 0
|
|
const list = (res.get('list') as Array<IFollowUser>) ?? []
|
|
if (reset) records.splice(0, records.length)
|
|
list.forEach((r : IFollowUser) => records.push(r))
|
|
})
|
|
.catch(() => {
|
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
|
})
|
|
.finally(() => {
|
|
loading.value = false
|
|
refreshing.value = false
|
|
})
|
|
}
|
|
|
|
function onRefresh() {
|
|
refreshing.value = true
|
|
loadData(true)
|
|
}
|
|
|
|
function onReachBottom() {
|
|
if (records.length >= total.value) return
|
|
page.value = page.value + 1
|
|
loadData(false)
|
|
}
|
|
|
|
function follow(item : IFollowUser) {
|
|
if (uid.value <= 0 || item.id <= 0) return
|
|
Api.follow.toggle(uid.value, item.id, 1)
|
|
.then(() => {
|
|
item.is_mutual = 1
|
|
uni.showToast({ title: '已回关', icon: 'success' })
|
|
})
|
|
.catch(() => {
|
|
uni.showToast({ title: '操作失败', icon: 'none' })
|
|
})
|
|
}
|
|
|
|
function goProfile(targetUid : number) {
|
|
if (targetUid <= 0) return
|
|
uni.navigateTo({ url: '/pages/user/profile?uid=' + targetUid })
|
|
}
|
|
|
|
onMounted(() => { loadData(true) })
|
|
onShow(() => { loadData(true) })
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.page {
|
|
flex: 1;
|
|
background-color: #f7f7f7;
|
|
}
|
|
|
|
.list {
|
|
margin: 24rpx 30rpx;
|
|
}
|
|
|
|
.user-item {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
align-items: center;
|
|
padding: 20rpx 24rpx;
|
|
background-color: #fff;
|
|
border-radius: 16rpx;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
|
|
.avatar {
|
|
width: 88rpx;
|
|
height: 88rpx;
|
|
border-radius: 44rpx;
|
|
background-color: #eee;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.info {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.name-row {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
align-items: center;
|
|
}
|
|
|
|
.nickname {
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.mutual-tag {
|
|
margin-left: 14rpx;
|
|
padding: 2rpx 12rpx;
|
|
border-radius: 16rpx;
|
|
background-color: #fff0ec;
|
|
}
|
|
|
|
.mutual-txt {
|
|
font-size: 20rpx;
|
|
color: #FF6B6B;
|
|
}
|
|
|
|
.time {
|
|
font-size: 22rpx;
|
|
color: #bbb;
|
|
margin-top: 8rpx;
|
|
}
|
|
|
|
.follow-btn {
|
|
padding: 10rpx 28rpx;
|
|
border-radius: 30rpx;
|
|
background: linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%);
|
|
}
|
|
|
|
.follow-txt {
|
|
font-size: 24rpx;
|
|
color: #fff;
|
|
}
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 120rpx 0;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 28rpx;
|
|
color: #bbb;
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.loading-tip {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 30rpx 0;
|
|
}
|
|
|
|
.loading-txt {
|
|
font-size: 24rpx;
|
|
color: #bbb;
|
|
}
|
|
</style>
|