转为使用element-plus
This commit is contained in:
@@ -1,288 +0,0 @@
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '暂无数据'
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: '当前页面暂无相关数据,您可以稍后再来查看'
|
||||
},
|
||||
showAction: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
actionText: {
|
||||
type: String,
|
||||
default: '刷新页面'
|
||||
}
|
||||
})
|
||||
|
||||
const handleAction = () => {
|
||||
router.go(0)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="empty-state">
|
||||
<div class="empty-content">
|
||||
<div class="empty-illustration">
|
||||
<div class="illustration-wrapper">
|
||||
<svg class="empty-icon" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="boxGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color: #667eea; stop-opacity: 0.2" />
|
||||
<stop offset="100%" style="stop-color: #764ba2; stop-opacity: 0.2" />
|
||||
</linearGradient>
|
||||
<linearGradient id="searchGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color: #00d4ff; stop-opacity: 1" />
|
||||
<stop offset="100%" style="stop-color: #7c4dff; stop-opacity: 1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- 背景圆 -->
|
||||
<circle cx="100" cy="100" r="80" fill="url(#boxGradient)" />
|
||||
|
||||
<!-- 搜索放大镜 -->
|
||||
<g transform="translate(70, 70)">
|
||||
<circle cx="30" cy="30" r="25" stroke="url(#searchGradient)" stroke-width="4" fill="none" />
|
||||
<line x1="50" y1="50" x2="70" y2="70" stroke="url(#searchGradient)" stroke-width="4"
|
||||
stroke-linecap="round" />
|
||||
</g>
|
||||
|
||||
<!-- 小装饰元素 -->
|
||||
<circle cx="50" cy="60" r="4" fill="#667eea" opacity="0.6">
|
||||
<animate attributeName="cy" values="60;55;60" dur="2s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="150" cy="80" r="3" fill="#764ba2" opacity="0.6">
|
||||
<animate attributeName="cy" values="80;75;80" dur="1.5s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="60" cy="140" r="5" fill="#00d4ff" opacity="0.5">
|
||||
<animate attributeName="cy" values="140;145;140" dur="2.5s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="empty-text">
|
||||
<h3 class="empty-title">{{ title }}</h3>
|
||||
<p class="empty-description">{{ description }}</p>
|
||||
</div>
|
||||
|
||||
<div v-if="showAction" class="empty-action">
|
||||
<button class="action-btn" @click="handleAction">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M23 4v6h-6"></path>
|
||||
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
|
||||
</svg>
|
||||
{{ actionText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.empty-state {
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.03) 0%, rgba(118, 75, 162, 0.03) 100%);
|
||||
border-radius: 16px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 装饰性背景 */
|
||||
.empty-state::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image:
|
||||
radial-gradient(2px 2px at 20px 30px, rgba(102, 126, 234, 0.3), transparent),
|
||||
radial-gradient(2px 2px at 40px 70px, rgba(118, 75, 162, 0.3), transparent),
|
||||
radial-gradient(1px 1px at 90px 40px, rgba(0, 212, 255, 0.3), transparent),
|
||||
radial-gradient(2px 2px at 160px 120px, rgba(102, 126, 234, 0.3), transparent);
|
||||
background-size: 200px 150px;
|
||||
animation: floatBg 20s linear infinite;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@keyframes floatBg {
|
||||
0% {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 200px 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-content {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 480px;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.empty-illustration {
|
||||
margin-bottom: 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.illustration-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
animation: floatIcon 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes floatIcon {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin: 0 0 12px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.empty-description {
|
||||
font-size: 15px;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.empty-action {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 32px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 25px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.action-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.action-btn svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 暗色主题适配 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.empty-title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.empty-description {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (max-width: 768px) {
|
||||
.empty-state {
|
||||
min-height: 300px;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.empty-description {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 10px 24px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.empty-state {
|
||||
padding: 30px 16px;
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.empty-description {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user