mcwl-pc/app/components/PlanetMessage/index.vue

217 lines
5.7 KiB
Vue

<script setup lang="ts">
import request from '@/utils/request'
import { Bell, MessageCircle, ShieldQuestion, ThumbsUp, X } from 'lucide-vue-next'
import { ref } from 'vue'
interface MessageItem {
id: number
name: string
type: number
icon: any
}
const emit = defineEmits(['close'])
const messageList = ref<MessageItem[]>([
{
id: 1,
name: '星球通知',
type: 0,
icon: Bell,
},
// {
// id: 2,
// name: '等我回答',
// type: 2,
// icon: ShieldQuestion,
// },
{
id: 3,
name: '回复我的',
type: 1,
icon: MessageCircle,
},
{
id: 4,
name: '收藏/赞',
type: 3,
icon: ThumbsUp,
},
])
const messageData = ref([])
const loading = ref(false)
function handleClose() {
emit('close')
}
// 获取消息列表
const params = ref({
adviceType: 0,
pageNum: 1,
pageSize: 10,
})
async function changeType(type: number) {
params.value.adviceType = type
params.value.pageNum = 1
initGetList()
}
// async function getMessageList() {
// loading.value = true
// try {
// const res = await request.post('/communityAdvice/adviceList', params.value)
// if (res.code === 200) {
// messageData.value = res.rows || []
// }
// }
// catch (error) {
// console.error(error)
// }
// finally {
// loading.value = false
// }
// }
// 获取列表
const listFinish = ref(false)
function initGetList() {
listFinish.value = false
params.value.pageNum = 1
getMessageList()
}
async function getMessageList() {
try {
if (listFinish.value || loading.value) // 添加loading检查,避免重复请求
return
loading.value = params.value.pageNum === 1 // 只在第一页显示loading
const res = await request.post('/communityAdvice/adviceList', params.value)
if (res.code === 200) {
if (params.value.pageNum === 1) {
messageData.value = res.rows
}
else {
messageData.value = [...messageData.value, ...res.rows]
}
if (messageData.value.length >= res.total) {
listFinish.value = true
}
params.value.pageNum++
}
}
catch (error) {
console.error(error)
}
finally {
loading.value = false
}
}
getMessageList()
// 初始化加载第一个类型的消息
onMounted(() => {
// getMessageList(1)
})
</script>
<template>
<div class="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
<div class="bg-white w-[800px] rounded-lg overflow-hidden">
<!-- 标题栏 -->
<div class="flex items-center justify-between px-6 h-14 border-b border-[#eee]">
<div class="text-lg font-medium">
通知
</div>
<div
class="i-lucide:x w-5 h-5 text-[#86909c] cursor-pointer hover:text-[#1e80ff]"
@click="handleClose"
>
<X />
</div>
</div>
<!-- 内容区 -->
<div class="flex h-[600px]">
<!-- 左侧菜单 -->
<div class="w-[200px] border-r border-[#eee] py-4">
<div
v-for="item in messageList"
:key="item.id"
class="flex items-center gap-2 px-6 h-12 cursor-pointer my-4 hover:bg-[#f2f3f5]"
:class="{ 'text-[#1e80ff] bg-[#f2f3f5]': params.adviceType === item.type }"
@click="changeType(item.type)"
>
<component :is="item.icon" class="w-5 h-5" />
<span>{{ item.name }}</span>
</div>
</div>
<!-- 右侧消息列表 -->
<div class="flex-1 overflow-y-auto">
<n-spin :show="loading">
<template v-if="messageData.length > 0">
<n-infinite-scroll style="height: calc(100vh - 200px)" :distance="10" @load="getMessageList">
<div
v-for="item in messageData"
:key="item.id"
class="flex items-center gap-3 p-4 border-b border-[#eee] hover:bg-[#f7f8fa]"
>
<img :src="item.sendUserAvatar" class="w-12 h-12 rounded-full">
<div v-if="params.adviceType === 0" class="flex-1">
<div class="overflow-hidden">
<p class="line-clamp-1 text-[#1f2329]">
{{ item.content }}
</p>
</div>
<div class="text-gray-500 text-sm mt-2">
{{ item.createTime }}
</div>
</div>
<div v-if="params.adviceType === 1" class="flex-1 flex flex-col justify-between">
<div>
{{ item.title }}
</div>
<div class="text-[#1e80ff]">
{{ item.content }}
</div>
<div class="text-[#86909c] text-xs">
{{ item.createTime }}
</div>
</div>
<div v-if="params.adviceType === 3" class="flex-1">
<div class="overflow-hidden">
<p class="line-clamp-1 text-[#1f2329]">
{{ item.content }}
</p>
</div>
<div class="text-gray-500 text-sm mt-2">
{{ item.createTime }}
</div>
</div>
</div>
</n-infinite-scroll>
</template>
<template v-else>
<div class="flex items-center justify-center min-h-[200px] text-[#86909c]">
</div>
</template>
</n-spin>
</div>
</div>
</div>
</div>
</template>
<style scoped>
:deep(.n-spin-container) {
height: 100%;
}
</style>