111 lines
3.5 KiB
Vue
111 lines
3.5 KiB
Vue
<template>
|
|
<view class="page container">
|
|
<view class="header flex-between">
|
|
<text class="title">消息通知</text>
|
|
<text v-if="unreadCount > 0" class="read-all" @click="handleReadAll">全部已读</text>
|
|
</view>
|
|
|
|
<view v-if="loading && !messageList.length" class="empty-tip">加载中...</view>
|
|
<view v-else-if="!messageList.length" class="empty-tip">暂无消息</view>
|
|
<view
|
|
v-for="item in messageList"
|
|
:key="item.id"
|
|
class="message-card card"
|
|
:class="{ unread: item.readFlag === '0' }"
|
|
@click="handleClick(item)"
|
|
>
|
|
<view class="flex-between">
|
|
<text class="msg-title">{{ item.title }}</text>
|
|
<view v-if="item.readFlag === '0'" class="unread-dot" />
|
|
</view>
|
|
<text class="msg-content">{{ item.content }}</text>
|
|
<text class="msg-time">{{ item.createTime }}</text>
|
|
</view>
|
|
|
|
<view v-if="hasMore" class="load-more" @click="loadMore">加载更多</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
|
|
import { useUserStore } from '@/store/index.js'
|
|
import { isLensFactoryTenant } from '@/utils/tenantType.js'
|
|
import { listPortalMessage, getPortalUnreadCount, markPortalMessageRead, markPortalMessageAllRead } from '@/api/message.js'
|
|
|
|
const userStore = useUserStore()
|
|
const loading = ref(false)
|
|
const messageList = ref([])
|
|
const total = ref(0)
|
|
const unreadCount = ref(0)
|
|
const query = ref({ pageNum: 1, pageSize: 20 })
|
|
const hasMore = computed(() => messageList.value.length < total.value)
|
|
|
|
onMounted(() => {
|
|
if (!userStore.isLoggedIn) {
|
|
uni.navigateTo({ url: '/pages/login/login' })
|
|
return
|
|
}
|
|
fetchUnread()
|
|
getList()
|
|
})
|
|
|
|
onPullDownRefresh(() => {
|
|
query.value.pageNum = 1
|
|
getList().finally(() => uni.stopPullDownRefresh())
|
|
})
|
|
|
|
onReachBottom(() => loadMore())
|
|
|
|
function fetchUnread() {
|
|
getPortalUnreadCount().then(res => { unreadCount.value = Number(res.data || 0) })
|
|
}
|
|
|
|
function getList(append = false) {
|
|
loading.value = true
|
|
return listPortalMessage(query.value).then(res => {
|
|
messageList.value = append ? [...messageList.value, ...(res.rows || [])] : (res.rows || [])
|
|
total.value = res.total || 0
|
|
}).finally(() => { loading.value = false })
|
|
}
|
|
|
|
function loadMore() {
|
|
if (!hasMore.value || loading.value) return
|
|
query.value.pageNum++
|
|
getList(true)
|
|
}
|
|
|
|
function handleClick(item) {
|
|
if (item.readFlag === '0') {
|
|
markPortalMessageRead(item.id).then(() => {
|
|
item.readFlag = '1'
|
|
fetchUnread()
|
|
})
|
|
}
|
|
const path = isLensFactoryTenant(userStore.tenantType)
|
|
? '/pages/order/factory-order'
|
|
: '/pages/order/lens-order'
|
|
uni.navigateTo({ url: path })
|
|
}
|
|
|
|
function handleReadAll() {
|
|
markPortalMessageAllRead().then(() => {
|
|
messageList.value.forEach(i => { i.readFlag = '1' })
|
|
unreadCount.value = 0
|
|
uni.showToast({ title: '已全部标记已读', icon: 'success' })
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.header { margin-bottom: 24rpx; }
|
|
.title { font-size: 36rpx; font-weight: bold; }
|
|
.read-all { font-size: 26rpx; color: #2563eb; }
|
|
.message-card { margin-bottom: 16rpx; &.unread { border-left: 6rpx solid #2563eb; } }
|
|
.msg-title { font-size: 28rpx; font-weight: 600; }
|
|
.unread-dot { width: 16rpx; height: 16rpx; background: #ef4444; border-radius: 50%; }
|
|
.msg-content { display: block; font-size: 26rpx; color: #64748b; margin: 12rpx 0; }
|
|
.msg-time { font-size: 22rpx; color: #94a3b8; }
|
|
.load-more { text-align: center; padding: 24rpx; color: #2563eb; }
|
|
</style>
|