2025-07-19 20:00:08 +08:00

124 lines
2.2 KiB
Vue

<template>
<view class="empty-state" :class="{ 'has-background': showBackground }">
<view class="empty-icon">
<uni-icons :type="icon" :size="iconSize" :color="iconColor" />
</view>
<text class="empty-title" v-if="title">{{ title }}</text>
<text class="empty-desc" v-if="description">{{ description }}</text>
<view class="empty-actions" v-if="showAction">
<uni-button
v-if="actionText"
:type="actionType"
:size="actionSize"
@click="handleAction">
{{ actionText }}
</uni-button>
<slot name="action"></slot>
</view>
<slot></slot>
</view>
</template>
<script>
export default {
name: 'EmptyState',
props: {
icon: {
type: String,
default: 'info-filled'
},
iconSize: {
type: [String, Number],
default: 80
},
iconColor: {
type: String,
default: '#ddd'
},
title: {
type: String,
default: ''
},
description: {
type: String,
default: ''
},
actionText: {
type: String,
default: ''
},
actionType: {
type: String,
default: 'primary'
},
actionSize: {
type: String,
default: 'small'
},
showBackground: {
type: Boolean,
default: true
},
showAction: {
type: Boolean,
default: true
}
},
methods: {
handleAction() {
this.$emit('action')
}
}
}
</script>
<style lang="scss" scoped>
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 40rpx;
text-align: center;
min-height: 400rpx;
&.has-background {
background: #fafbfc;
border-radius: 16rpx;
margin: 20rpx;
}
.empty-icon {
margin-bottom: 30rpx;
opacity: 0.6;
}
.empty-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
line-height: 1.4;
}
.empty-desc {
font-size: 28rpx;
color: #999;
margin-bottom: 40rpx;
line-height: 1.5;
max-width: 400rpx;
}
.empty-actions {
display: flex;
gap: 20rpx;
flex-wrap: wrap;
justify-content: center;
}
}
</style>