217 lines
5.7 KiB
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>
|