Files
property-resident-side/property-uniapp-project/pageSubPack/notice-list/noticeList.vue
2026-04-28 16:52:51 +08:00

230 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page">
<view class="status_bar"></view>
<!-- 固定导航栏 -->
<uni-nav-bar
left-icon="left"
title="通知公告"
background-color="#F9F9F9"
@clickLeft="narBack"
/>
<!-- 滚动区域能正常滚动的核心 -->
<scroll-view
scroll-y
class="scroll-box"
:refresher-enabled="true"
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
@scrolltolower="loadMore"
>
<view class="list-wrap">
<!-- 下拉刷新 -->
<view class="refresh" v-if="refreshing">
<uni-icons type="spinner-cycle" class="spin"/> 刷新中...
</view>
<!-- 列表 -->
<view
v-for="notice in noticeList"
:key="notice.noticeId"
class="item">
<view class="title-box">
<view class="title">{{ notice.noticeTitle }}</view>
<view class="dot" v-if="notice.readStatus === '0'"></view>
</view>
<view class="info">{{ notice.author }} · {{ notice.publishTime }}</view>
<view class="content">{{ notice.noticeContent }}</view>
<view class="detail" @click="goToDetail(notice)">
<text style="color:#2F77FD">详情</text>
<uni-icons type="right" size="13" color="#007AFF"/>
</view>
</view>
<!-- 加载中 / 无更多 / 空布局 -->
<view class="load-more" v-if="loadingMore">加载中...</view>
<view class="no-more" v-if="noMoreData && noticeList.length">没有更多通知了</view>
<view class="empty" v-if="noticeList.length === 0 && !loading">
暂无通知
<!-- <button class="refresh-btn" @click="loadNotices">刷新试试</button> -->
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad ,onShow,onUnload} from '@dcloudio/uni-app'
import { getNoticeList } from '../api/api.js'
const noticeList = ref([])
const refreshing = ref(false)
const loadingMore = ref(false)
const noMoreData = ref(false)
const loading = ref(false)
const pageNum = ref(1)
const pageSize = 10
const isFirstShow = ref(true) // 详情返回列表刷新状态
const goToDetail = (notice) => {
uni.navigateTo({
url: `/pageSubPack/notice-list/noticeListDetails?id=${notice.noticeId}`
})
}
const loadNotices = async (isRefresh = false) => {
if (loading.value) return
loading.value = true
if (isRefresh) {
pageNum.value = 1
noMoreData.value = false
}
try {
const res = await getNoticeList({ pageNum: pageNum.value, pageSize })
if (res.code === 200) {
const list = res.data.rows || []
noticeList.value = isRefresh ? list : [...noticeList.value, ...list]
if (list.length < pageSize) noMoreData.value = true
}
} catch (e) {}
finally {
loading.value = false
refreshing.value = false
loadingMore.value = false
}
}
// 更新单条已读状态
const updateReadStatus = ({ noticeId, readStatus }) => {
const item = noticeList.value.find(n => String(n.noticeId) === noticeId)
if (item) {
item.readStatus = readStatus
}
}
onShow(() =>{
if(isFirstShow.value) return
loadNotices(true)
})
const onRefresh = () => {
refreshing.value = true
loadNotices(true)
}
const loadMore = () => {
if (noMoreData.value || loadingMore.value) return
loadingMore.value = true
pageNum.value++
loadNotices()
}
const narBack = () => {
const page = uni.getStorageSync('sourcePage')
if (page === 'index') uni.switchTab({ url: '/pages/index/index' })
if (page === 'serviceIndex') uni.switchTab({ url: '/pages/serviceIndex/serviceIndex' })
uni.removeStorageSync('sourcePage')
}
onLoad(() => {
isFirstShow.value = false
uni.$on('noticeRead',updateReadStatus)
loadNotices(true)
})
onUnload(()=>{
uni.$off('noticeRead',updateReadStatus)
})
</script>
<style lang="scss">
page {
background: #f9f9f9;
}
.page {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
}
.status_bar {
height: 46px;
width: 100%;
}
.scroll-box {
flex: 1;
height: 0; /* 让滚动区域生效 */
}
.list-wrap {
padding: 40rpx;
}
.item {
background: #fff;
border-radius: 12rpx;
padding: 30rpx;
margin-bottom: 20rpx;
}
.title-box {
display: flex;
justify-content: space-between;
align-items: center;
}
.title {
font-size: 32rpx;
font-weight: bold;
width: 500rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dot {
width: 12rpx;
height: 12rpx;
background: red;
border-radius: 50%;
}
.info {
color: #999;
font-size: 24rpx;
margin: 10rpx 0;
}
.content {
color: #666;
font-size: 28rpx;
line-height: 1.5;
margin: 20rpx 0;
background-color: #f9f9f9;
padding: 24rpx;
}
.detail {
display: flex;
justify-content: space-between;
align-items: center;
}
.refresh, .load-more, .no-more {
text-align: center;
padding: 20rpx;
color: #999;
}
.empty {
text-align: center;
padding: 100rpx 0;
color: #999;
}
.refresh-btn {
background: #007AFF;
color: #fff;
border-radius: 50rpx;
padding: 10rpx 30rpx;
margin-top: 20rpx;
}
.spin {
animation: rotate 1s linear infinite;
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>