任务3.1 实现基础 UI 组件库 - 创建 BaseIcon 组件,支持 emoji 和 SVG 图标 - 实现 CategoryIcon 组件,用于分类图标显示 - 开发 AmountInput 组件,支持金额输入和类型切换 - 创建 DatePicker 组件,支持日期选择和快捷日期 - 实现 BaseSelect 组件,支持搜索和自定义选项 - 添加 LoadingSpinner 和 EmptyState 组件 - 扩展 Tailwind 配置,完善设计系统色彩 任务3.2 创建交易列表和卡片组件 - 实现 TransactionCard 组件,展示交易详情 - 创建 TransactionList 组件,支持分组显示和批量操作 - 添加日期分组和汇总功能 - 实现无限滚动和加载更多功能 - 支持选择模式和批量删除 - 更新 TransactionsView 使用新组件 任务3.3 开发交易添加和编辑表单 - 创建 TransactionForm 组件,支持添加和编辑交易 - 集成所有输入组件(金额、分类、账户、日期等) - 实现表单验证和数据清理 - 添加重复交易检测功能 - 创建 AddTransactionView 页面 - 配置路由支持添加和编辑交易 任务3.4 实现搜索和筛选功能 - 创建 TransactionSearch 组件,支持智能搜索 - 实现搜索建议和搜索历史功能 - 开发 TransactionFilter 组件,支持多维度筛选 - 添加快速筛选标签和日期预设 - 集成搜索和筛选到 TransactionsView - 实现实时筛选和结果统计 核心特性: - 完整的交易管理界面(列表、添加、编辑、搜索、筛选) - 现代化的 neumorphic 设计风格 - 响应式布局和移动端优化 - 智能搜索和多维度筛选 - 用户友好的交互体验 - 完整的表单验证和错误处理
122 lines
2.6 KiB
Vue
122 lines
2.6 KiB
Vue
<template>
|
|
<div :class="containerClasses">
|
|
<!-- 旋转加载器 -->
|
|
<div
|
|
v-if="type === 'spinner'"
|
|
:class="[
|
|
'animate-spin rounded-full border-2 border-current border-t-transparent',
|
|
sizeClasses,
|
|
colorClasses
|
|
]"
|
|
/>
|
|
|
|
<!-- 脉冲加载器 -->
|
|
<div
|
|
v-else-if="type === 'pulse'"
|
|
:class="[
|
|
'animate-pulse rounded-full bg-current',
|
|
sizeClasses,
|
|
colorClasses
|
|
]"
|
|
/>
|
|
|
|
<!-- 点状加载器 -->
|
|
<div v-else-if="type === 'dots'" :class="['flex space-x-1', colorClasses]">
|
|
<div
|
|
v-for="i in 3"
|
|
:key="i"
|
|
:class="[
|
|
'rounded-full bg-current animate-bounce',
|
|
dotSizeClasses
|
|
]"
|
|
:style="{ animationDelay: `${(i - 1) * 0.1}s` }"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 骨架屏加载器 -->
|
|
<div v-else-if="type === 'skeleton'" class="animate-pulse space-y-3">
|
|
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
|
|
<div class="h-4 bg-gray-200 rounded w-1/2"></div>
|
|
<div class="h-4 bg-gray-200 rounded w-5/6"></div>
|
|
</div>
|
|
|
|
<!-- 加载文本 -->
|
|
<div v-if="text" :class="['mt-2 text-sm', colorClasses]">
|
|
{{ text }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
|
|
interface Props {
|
|
type?: 'spinner' | 'pulse' | 'dots' | 'skeleton'
|
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
color?: 'primary' | 'secondary' | 'gray' | 'white'
|
|
text?: string
|
|
center?: boolean
|
|
overlay?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
type: 'spinner',
|
|
size: 'md',
|
|
color: 'primary',
|
|
center: false,
|
|
overlay: false
|
|
})
|
|
|
|
// 容器类
|
|
const containerClasses = computed(() => {
|
|
const classes = []
|
|
|
|
if (props.center) {
|
|
classes.push('flex flex-col items-center justify-center')
|
|
}
|
|
|
|
if (props.overlay) {
|
|
classes.push(
|
|
'fixed inset-0 bg-black bg-opacity-50 z-50',
|
|
'flex items-center justify-center'
|
|
)
|
|
}
|
|
|
|
return classes
|
|
})
|
|
|
|
// 尺寸类
|
|
const sizeClasses = computed(() => {
|
|
const sizes = {
|
|
xs: 'w-3 h-3',
|
|
sm: 'w-4 h-4',
|
|
md: 'w-6 h-6',
|
|
lg: 'w-8 h-8',
|
|
xl: 'w-12 h-12'
|
|
}
|
|
return sizes[props.size]
|
|
})
|
|
|
|
// 点状加载器尺寸
|
|
const dotSizeClasses = computed(() => {
|
|
const sizes = {
|
|
xs: 'w-1 h-1',
|
|
sm: 'w-1.5 h-1.5',
|
|
md: 'w-2 h-2',
|
|
lg: 'w-3 h-3',
|
|
xl: 'w-4 h-4'
|
|
}
|
|
return sizes[props.size]
|
|
})
|
|
|
|
// 颜色类
|
|
const colorClasses = computed(() => {
|
|
const colors = {
|
|
primary: 'text-primary',
|
|
secondary: 'text-text-secondary',
|
|
gray: 'text-gray-400',
|
|
white: 'text-white'
|
|
}
|
|
return colors[props.color]
|
|
})
|
|
</script> |