feat(frontend): 添加 TypeScript 类型定义和组件
- 添加 TypeScript API 客户端 (api/index.ts) - 添加全局样式 (styles/) - 添加类型定义 (types/) - 添加 Vue 组件 (components/) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
96
frontend/src/components/common/EmptyState.vue
Normal file
96
frontend/src/components/common/EmptyState.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<div class="empty-state">
|
||||
<div class="empty-illustration">
|
||||
<div class="circle-1"></div>
|
||||
<div class="circle-2"></div>
|
||||
<div class="circle-3"></div>
|
||||
<el-icon size="48"><component :is="icon" /></el-icon>
|
||||
</div>
|
||||
<h3>{{ title }}</h3>
|
||||
<p>{{ description }}</p>
|
||||
<el-button v-if="actionText" type="primary" @click="$emit('action')">
|
||||
{{ actionText }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
icon: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '暂无数据'
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: '暂无相关内容'
|
||||
},
|
||||
actionText: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
defineEmits(['action'])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.empty-state {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 80px 40px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px dashed var(--border-default);
|
||||
border-radius: var(--radius-xl);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-illustration {
|
||||
position: relative;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.empty-illustration .el-icon {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.circle-1, .circle-2, .circle-3 {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
.circle-1 { width: 100%; height: 100%; animation: rotate 20s linear infinite; }
|
||||
.circle-2 { width: 70%; height: 70%; animation: rotate 15s linear infinite reverse; }
|
||||
.circle-3 { width: 40%; height: 40%; background: var(--bg-tertiary); }
|
||||
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.empty-state h3 {
|
||||
font-size: 20px;
|
||||
margin-bottom: 8px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
color: var(--text-tertiary);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user