463 lines
12 KiB
Vue
463 lines
12 KiB
Vue
<script setup lang="ts">
|
|
import { Close } from '@vicons/ionicons5'
|
|
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
const observer = ref<IntersectionObserver | null>(null)
|
|
const message = useMessage()
|
|
const userStore = useUserStore()
|
|
const route = useRoute()
|
|
const { userId } = route.query
|
|
const loading = ref(false)
|
|
const finished = ref(false)
|
|
const total = ref(0) // 总条数
|
|
const loadingTrigger = ref(null)
|
|
|
|
const urlList = ref({
|
|
0: '/personalCenter/selectByUserIdModel',
|
|
1: '/personalCenter/selectByUserIdWorkFlow',
|
|
2: '/personalCenter/selectByUserIdImage',
|
|
})
|
|
const currentType = ref('0')
|
|
const typeList = ref([
|
|
{ id: '0', title: '模型' },
|
|
{ id: '1', title: '工作流' },
|
|
{ id: '2', title: '图片' },
|
|
])
|
|
const orderOptions = ref([
|
|
{
|
|
dictLabel: '最新',
|
|
dictValue: 'create_time',
|
|
},
|
|
{
|
|
dictLabel: '最热',
|
|
dictValue: 'like_num',
|
|
},
|
|
])
|
|
|
|
const isShowFan = ref(false)
|
|
|
|
const activeTab = ref('like')
|
|
function closefanList() {
|
|
isShowFan.value = false
|
|
}
|
|
|
|
const bannerStyle = {
|
|
backgroundImage:
|
|
'url(\'https://img.zcool.cn/community/special_cover/3a9a64d3628c000c2a1000657eec.jpg\')',
|
|
}
|
|
|
|
const publishParams = ref({
|
|
pageNum: 1,
|
|
pageSize: 20,
|
|
orderByColumn: 'create_time',
|
|
userId,
|
|
})
|
|
|
|
const currentUserInfo = ref({})
|
|
async function getCurrentUserInfo() {
|
|
const res = await request.get(`/system/user/selectUserById?id=${userId}`)
|
|
if (res.code === 200) {
|
|
currentUserInfo.value = res.data
|
|
}
|
|
}
|
|
getCurrentUserInfo()
|
|
|
|
// 获取粉丝的列表
|
|
const attentionList = ref([])
|
|
const attentionListParams = ref({
|
|
pageNumber: 1,
|
|
pageSize: 20,
|
|
type: userId,
|
|
})
|
|
async function getAttentionList() {
|
|
const res = await request.post(`/attention/selectToAttention`, {
|
|
...attentionListParams.value,
|
|
})
|
|
if (res.code === 200) {
|
|
attentionList.value = res.data.list
|
|
}
|
|
}
|
|
getAttentionList()
|
|
|
|
// 获取关注的列表
|
|
const likeList = ref([])
|
|
const likeListParams = ref({
|
|
pageNumber: 1,
|
|
pageSize: 20,
|
|
type: userId,
|
|
})
|
|
async function getLikeList() {
|
|
const res = await request.post(`/attention/selectAttentionList`, {
|
|
...likeListParams.value,
|
|
})
|
|
if (res.code === 200) {
|
|
likeList.value = res.data.list
|
|
}
|
|
}
|
|
getLikeList()
|
|
|
|
// 查询是否关注
|
|
const isAttention = ref(false)
|
|
async function getIsAttention() {
|
|
const res = await request.get(`/attention/selectAttention?userId=${userId}`)
|
|
if (res.code === 200) {
|
|
isAttention.value = res.data
|
|
}
|
|
}
|
|
getIsAttention()
|
|
|
|
// 去关注/取消关注当前用户
|
|
async function onAttention(item: any) {
|
|
const myUserId = userStore.userInfo.userId
|
|
if (myUserId === item.userId) {
|
|
return message.warning('自己不能关注自己')
|
|
}
|
|
let paramsUserId
|
|
if (item.userId) {
|
|
paramsUserId = item.userId
|
|
}
|
|
else {
|
|
paramsUserId = userId
|
|
}
|
|
try {
|
|
const res = await request.get(`/attention/addAttention?userId=${paramsUserId}`)
|
|
if (res.code === 200) {
|
|
if (res.data) {
|
|
message.success('关注成功')
|
|
}
|
|
else {
|
|
message.success('取消关注成功')
|
|
}
|
|
if (item.userId) {
|
|
item.attention = !item.attention
|
|
}
|
|
else {
|
|
isAttention.value = !isAttention.value
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
|
|
// 获取用户点赞/粉丝/关注数量
|
|
interface SelectUserInfo {
|
|
likeCount: number
|
|
bean: number
|
|
download: number
|
|
attention: number
|
|
}
|
|
const selectUserInfo = ref<SelectUserInfo>({
|
|
likeCount: 0,
|
|
bean: 0,
|
|
download: 0,
|
|
attention: 0,
|
|
})
|
|
async function getAttention() {
|
|
try {
|
|
const res = await request.get(`/attention/selectUserInfo?userId=${userId}`)
|
|
if (res.code === 200) {
|
|
selectUserInfo.value = res.data
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log(err)
|
|
}
|
|
}
|
|
getAttention()
|
|
|
|
// 切换模型/工作流/图片
|
|
function changeType(id: string) {
|
|
currentType.value = id
|
|
initPageNUm()
|
|
}
|
|
|
|
// 切换点赞的最热/最新
|
|
function changeLikeOrder(value: string) {
|
|
publishParams.value.orderByColumn = value
|
|
initPageNUm()
|
|
}
|
|
|
|
function initPageNUm() {
|
|
publishParams.value.pageNum = 1
|
|
finished.value = false // 重置加载完成状态
|
|
getList()
|
|
}
|
|
|
|
// 查询发布模型接口
|
|
const dataList = ref([])
|
|
async function getList() {
|
|
if (loading.value || finished.value)
|
|
return
|
|
|
|
loading.value = true
|
|
const url = urlList.value[currentType.value]
|
|
try {
|
|
const res = await request.post(url, publishParams.value)
|
|
if (res.code === 200) {
|
|
// 如果是第一页,直接赋值,否则追加数据
|
|
if (publishParams.value.pageNum === 1) {
|
|
dataList.value = res.rows
|
|
}
|
|
else {
|
|
dataList.value = [...dataList.value, ...res.rows]
|
|
}
|
|
|
|
total.value = res.total // 假设接口返回了总条数
|
|
|
|
// 判断是否加载完所有数据
|
|
if (dataList.value.length >= total.value) {
|
|
finished.value = true
|
|
}
|
|
publishParams.value.pageNum++
|
|
}
|
|
}
|
|
catch (err) {
|
|
dataList.value = []
|
|
finished.value = true
|
|
console.log(err)
|
|
}
|
|
finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
getList()
|
|
|
|
async function topedRefresh() {
|
|
if (import.meta.client) {
|
|
await nextTick()
|
|
window.scrollTo({
|
|
top: 0,
|
|
behavior: 'smooth',
|
|
})
|
|
}
|
|
initPageNUm()
|
|
}
|
|
|
|
onMounted(() => {
|
|
window.addEventListener('scroll', topedRefresh)
|
|
observer.value = new IntersectionObserver(
|
|
([entry]) => {
|
|
if (entry.isIntersecting && !loading.value && !finished.value) {
|
|
getList()
|
|
}
|
|
},
|
|
{
|
|
threshold: 0.1,
|
|
},
|
|
)
|
|
|
|
if (loadingTrigger.value) {
|
|
observer.value.observe(loadingTrigger.value)
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener('scroll', topedRefresh)
|
|
if (observer.value) {
|
|
observer.value.disconnect()
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="mx-auto container">
|
|
<div
|
|
class="banner-content h-32 bg-blue bg-cover bg-center rounded-sm"
|
|
:style="bannerStyle"
|
|
/>
|
|
<div class="info-content mt-[-50px] p-5">
|
|
<div class="edit-info-content flex items-center">
|
|
<div
|
|
class="mc-head mr-5 h-20 w-20 rounded-full bg-white shadow-lg flex items-center justify-center"
|
|
>
|
|
<div class="mc-head-inner h-18 w-18 m-1 rounded-full bg-blue-200">
|
|
<client-only>
|
|
<img
|
|
class="head-img m-1 h-16 w-16 rounded-full bg-white"
|
|
:src="currentUserInfo.avatar"
|
|
alt="User Avatar"
|
|
>
|
|
</client-only>
|
|
<!-- {{ userStore.userInfo.avatar }} -->
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="isAttention !== null"
|
|
class="mr-2 cursor-pointer rounded-full bg-gradient-to-r from-[#1f66df] to-[#3faeff] px-4 py-1 text-white"
|
|
@click="onAttention"
|
|
>
|
|
{{ isAttention ? '已关注' : '关注' }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="user-info mt-4">
|
|
<div v-if="currentUserInfo" class="nickname text-xl font-bold">
|
|
{{ currentUserInfo.nickName }}
|
|
<!-- {{ userInfo.nickName }} -->
|
|
</div>
|
|
<div v-if="currentUserInfo" class="info-desc mt-1 text-sm text-gray-700">
|
|
{{ currentUserInfo.brief }}
|
|
</div>
|
|
<div class="production-state mt-4 flex text-sm text-gray-700">
|
|
<div
|
|
class="production-state-item mr-5 cursor-pointer"
|
|
@click="isShowFan = true"
|
|
>
|
|
<span class="production-state-number font-bold">{{
|
|
selectUserInfo.bean ? selectUserInfo.bean : 0
|
|
}}</span>
|
|
粉丝
|
|
</div>
|
|
<div
|
|
class="production-state-item mr-5 cursor-pointer"
|
|
@click="isShowFan = true"
|
|
>
|
|
<span class="production-state-number font-bold">{{
|
|
selectUserInfo.attention ? selectUserInfo.attention : 0
|
|
}}</span>
|
|
关注
|
|
</div>
|
|
<div class="production-state-item mr-5">
|
|
<span class="production-state-number font-bold">{{
|
|
selectUserInfo.download ? selectUserInfo.download : 0
|
|
}}</span>
|
|
作品被使用次数
|
|
</div>
|
|
<div class="production-state-item">
|
|
<span class="production-state-number font-bold">{{
|
|
selectUserInfo.likeCount ? selectUserInfo.likeCount : 0
|
|
}}</span>
|
|
作品被点赞次数
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="select-content mt-4 flex items-center justify-between">
|
|
<div class="flex items-center rounded-full bg-gray-100">
|
|
<div
|
|
v-for="(item, index) in typeList"
|
|
:key="index"
|
|
class="m-1 mr-2 cursor-pointer rounded-full px-4 py-1 text-sm"
|
|
:class="{
|
|
'bg-white': item.id === currentType,
|
|
}"
|
|
@click="changeType(item.id)"
|
|
>
|
|
{{ item.title }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-center">
|
|
<NSelect
|
|
v-model:value="publishParams.orderByColumn"
|
|
:options="orderOptions"
|
|
label-field="dictLabel"
|
|
value-field="dictValue"
|
|
placeholder="请选择"
|
|
class="w-32"
|
|
@update:value="changeLikeOrder"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="login-content my-4 grid grid-cols-4 gap-4 px-5">
|
|
<PersonalCenterPublishCard
|
|
v-for="(item, index) in dataList"
|
|
:key="index"
|
|
:item="item"
|
|
:current-type="currentType"
|
|
@toped-refresh="topedRefresh"
|
|
/>
|
|
</div>
|
|
<div ref="loadingTrigger" class="h-10">
|
|
<div v-if="loading" class="text-center text-gray-500">
|
|
加载中...
|
|
</div>
|
|
<div v-if="finished" class="text-center text-gray-500">
|
|
没有更多数据了
|
|
</div>
|
|
</div>
|
|
<div v-if="isShowFan" class="fan-centent">
|
|
<div
|
|
class="w-[550px] h-[calc(100vh-100px)] max-h-[700px] m-auto py-0 px-8 pb-[43px] bg-[#fff] rounded-lg relative"
|
|
>
|
|
<n-icon size="20" class="mr-2 cursor-pointer absolute top-4 right-2" @click="closefanList">
|
|
<Close />
|
|
</n-icon>
|
|
<n-tabs
|
|
v-model:value="activeTab"
|
|
default-value="like"
|
|
justify-content="space-evenly"
|
|
type="line"
|
|
>
|
|
<n-tab-pane name="like" :tab="`粉丝${selectUserInfo.bean || 0}`">
|
|
<n-infinite-scroll style="height: calc(100vh - 200px)" :distance="10" @load="getAttentionList">
|
|
<div class="overflow-y-auto h-[calc(100vh-200px)] px-2">
|
|
<div
|
|
v-for="(item, index) in attentionList"
|
|
:key="index"
|
|
class="flex justify-between items-center py-2"
|
|
>
|
|
<div class="flex items-center">
|
|
<img :src="item.avatar || ''" alt="" class="w-14 h-14 rounded-full mr-2">
|
|
{{ item.nickName }}
|
|
</div>
|
|
<div class="bg-[#f4f5f9] px-4 py-2 rounded-full cursor-pointer" @click="onAttention(item, 'attention')">
|
|
{{ item.attention ? '已关注' : '未关注' }}
|
|
</div>
|
|
</div>
|
|
<div v-if="attentionList.length === 0" class="w-full text-center text-gray-500 font-bold mt-2">
|
|
暂无数据
|
|
</div>
|
|
</div>
|
|
</n-infinite-scroll>
|
|
</n-tab-pane>
|
|
<n-tab-pane name="attention" :tab="`关注${selectUserInfo.attention || 0}`">
|
|
<div class="overflow-y-auto h-[calc(100vh-200px)] px-2">
|
|
<div
|
|
v-for="(item, index) in likeList"
|
|
:key="index"
|
|
class="flex justify-between items-center py-2"
|
|
>
|
|
<div class="flex items-center">
|
|
<img :src="item.avatar || ''" alt="" class="w-14 h-14 rounded-full mr-2">
|
|
{{ item.nickName }}
|
|
</div>
|
|
<div class="bg-[#f4f5f9] px-4 py-2 rounded-full cursor-pointer" @click="onAttention(item, 'like')">
|
|
{{ item.attention ? '已关注' : '未关注' }}
|
|
</div>
|
|
</div>
|
|
<div v-if="attentionList.length === 0" class="w-full text-center text-gray-500 font-bold mt-2">
|
|
暂无数据
|
|
</div>
|
|
</div>
|
|
</n-tab-pane>
|
|
</n-tabs>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.fan-centent {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
.n-tabs.n-tabs--flex .n-tabs-nav .n-tabs-wrapper .n-tabs-tab {
|
|
margin-right: 0;
|
|
font-size: 20px;
|
|
}
|
|
</style>
|