fjrcloud-community-app/pages/sub/notice/list.vue

198 lines
4.0 KiB
Vue

<!-- 通知公告列表 -->
<template>
<s-layout title="通知公告">
<view class="notice-list-page">
<scroll-view
class="notice-scroll"
scroll-y
:style="{ height: scrollHeight + 'px' }"
@scrolltolower="loadMore"
>
<view
v-for="(item, index) in state.list"
:key="index"
class="notice-card"
@tap="goDetail(item)"
>
<text class="notice-title">{{ item.title }}</text>
<view class="notice-content">
<mp-html :content="item.content" />
</view>
<view class="notice-footer">
<text class="notice-time">{{ sheep.$helper.timeFormat(item.publishTime, 'yyyy/mm/dd hh:MM:ss') }}</text>
<image class="arrow-icon" src="/static/img/right-icon.png" mode="aspectFit" />
</view>
</view>
<!-- 加载状态 -->
<view class="load-more">
<text v-if="state.loading">加载中...</text>
<text v-else-if="state.noMore"></text>
</view>
</scroll-view>
</view>
</s-layout>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app';
import NoticeApi from '@/sheep/api/community/notice';
import sheep from '@/sheep';
// scroll-view 动态高度
const scrollHeight = ref(0);
// 页面状态
const state = reactive({
list: [],
pageNo: 1,
pageSize: 10,
loading: false,
noMore: true,
});
// 获取通知列表
const fetchList = async (isRefresh = false) => {
if (state.loading) return;
if (isRefresh) {
state.pageNo = 1;
state.noMore = false;
}
if (state.noMore && !isRefresh) return;
state.loading = true;
const { code, data } = await NoticeApi.getPage({
pageNo: state.pageNo,
pageSize: state.pageSize,
});
state.loading = false;
if (code === 0 && data) {
const list = data.list || [];
if (isRefresh) {
state.list = list;
} else {
state.list = state.list.concat(list);
}
// 判断是否还有更多
if (list.length < state.pageSize || state.list.length >= data.total) {
state.noMore = true;
}
state.pageNo++;
}
if (isRefresh) {
uni.stopPullDownRefresh();
}
};
// 加载更多
const loadMore = () => {
fetchList(false);
};
// 跳转详情
const goDetail = (item) => {
uni.navigateTo({ url: `/pages/sub/notice/detail?id=${item.id}` });
};
onLoad(() => {
// 计算 scroll-view 可用高度
const sys = uni.getSystemInfoSync();
const safeBottom = sys.safeAreaInsets?.bottom || 0;
scrollHeight.value = sys.windowHeight - 88 - safeBottom;
fetchList(true);
});
// 下拉刷新
onPullDownRefresh(() => {
fetchList(true);
});
</script>
<style lang="scss" scoped>
/* 页面容器 */
.notice-list-page {
height: 100%;
background-color: #F5F5F5;
padding: 24rpx 0 calc(24rpx + env(safe-area-inset-bottom));
}
/* 滚动区域 */
.notice-scroll {
overflow: hidden;
}
/* 通知卡片 */
.notice-card {
background-color: #FFFFFF;
border-radius: 24rpx;
margin: 0 24rpx 24rpx;
padding: 28rpx 32rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
&:active {
opacity: 0.7;
}
.notice-title {
display: block;
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-bottom: 16rpx;
line-height: 1.4;
}
.notice-content {
font-size: 28rpx;
color: #666666;
line-height: 1.6;
margin-bottom: 20rpx;
height: 90rpx;
overflow: hidden;
:deep(p) {
font-size: 28rpx;
color: #666666;
line-height: 1.6;
margin: 0;
}
:deep(img) {
display: none;
}
}
.notice-footer {
display: flex;
align-items: center;
justify-content: space-between;
.notice-time {
font-size: 24rpx;
color: #999999;
}
.arrow-icon {
width: 28rpx;
height: 28rpx;
flex-shrink: 0;
}
}
}
/* 加载状态 */
.load-more {
display: flex;
justify-content: center;
padding: 24rpx 0 40rpx;
text {
font-size: 24rpx;
color: #999999;
}
}
</style>