mcwl-pc/app/pages/personal-publish/index.vue

454 lines
12 KiB
Vue

<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
class="mr-2 cursor-pointer rounded-full bg-gradient-to-r from-[#1f66df] to-[#3faeff] px-4 py-1 text-white"
@click="onAttention"
v-if="isAttention !== null"
>
{{ 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 class="fan-centent" v-if="isShowFan">
<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>
<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: 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>
<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>