Files
property-resident-side/property-uniapp-project/components/pull-refresh-scroll/pull-refresh-scroll.vue
zhouyanli 3b66b76e40 修复bug
2026-07-31 14:06:11 +08:00

159 lines
3.0 KiB
Vue

<template>
<scroll-view
scroll-y
class="prs-scroll"
:class="customClass"
:style="scrollStyle"
:refresher-enabled="refresherEnabled"
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
@scrolltolower="onScrollToLower"
>
<!-- 下拉刷新指示器 -->
<view class="prs-refresh" v-if="refreshing">
<uni-icons type="spinner-cycle" class="prs-spin" size="16" color="#999" />
<text class="prs-refresh-text">刷新中...</text>
</view>
<!-- 主体内容 -->
<slot></slot>
<!-- 空状态 -->
<view v-if="empty && showEmpty" class="prs-empty">
<slot name="empty">
<uni-icons type="info" size="30" color="#ccc"></uni-icons>
<text class="prs-empty-text">{{ emptyText }}</text>
</slot>
</view>
<!-- 底部加载/无更多状态 -->
<view class="prs-bottom">
<view v-if="loadingMore" class="prs-load-more">加载中...</view>
<view v-else-if="noMoreData && !empty" class="prs-no-more">{{ noMoreText }}</view>
</view>
</scroll-view>
</template>
<script setup>
defineProps({
/** 是否正在刷新 */
refreshing: {
type: Boolean,
default: false
},
/** 下拉刷新是否启用 */
refresherEnabled: {
type: Boolean,
default: true
},
/** 加载更多状态 */
loadingMore: {
type: Boolean,
default: false
},
/** 是否无更多数据 */
noMoreData: {
type: Boolean,
default: false
},
/** 列表是否为空 */
empty: {
type: Boolean,
default: false
},
/** 是否显示空状态 */
showEmpty: {
type: Boolean,
default: true
},
/** 空状态文案 */
emptyText: {
type: String,
default: '暂无数据'
},
/** 没有更多文案 */
noMoreText: {
type: String,
default: '没有更多了'
},
/** 自定义类名,允许外部设置 scroll-view 样式 */
customClass: {
type: String,
default: ''
},
/** 自定义 scroll-view 内联样式 */
scrollStyle: {
type: String,
default: ''
}
})
const emit = defineEmits(['refresh', 'loadMore'])
const onRefresh = () => {
emit('refresh')
}
const onScrollToLower = () => {
emit('loadMore')
}
</script>
<style lang="scss" scoped>
.prs-scroll {
flex: 1;
min-height: 0;
overflow: hidden;
}
// 刷新指示器
.prs-refresh {
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 0;
}
.prs-spin {
animation: prs-rotate 1s linear infinite;
}
.prs-refresh-text {
margin-left: 10rpx;
font-size: 24rpx;
color: #999;
}
// 空状态
.prs-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
color: #ccc;
}
.prs-empty-text {
font-size: 28rpx;
color: #999;
margin-top: 20rpx;
}
// 底部状态
.prs-bottom {
.prs-load-more,
.prs-no-more {
text-align: center;
padding: 20rpx;
color: #999;
font-size: 24rpx;
}
}
@keyframes prs-rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>