登录页功能完成

This commit is contained in:
田岩
2025-06-13 18:00:28 +08:00
parent a3060cb959
commit f032e1fe03
134 changed files with 27506 additions and 807 deletions
+121
View File
@@ -0,0 +1,121 @@
<template>
<div
class="skeleton-container"
:style="containerStyle"
>
<div
v-for="(item, index) in skeletonItems"
:key="index"
class="skeleton-item"
:style="getItemStyle(item)"
>
<!-- 内部内容根据类型渲染 -->
<slot v-if="item.type === 'custom' && index === 0" :item="item" />
</div>
</div>
</template>
<script setup>
import { ref, computed, toRefs } from 'vue'
import type { PropType } from 'vue'
// 定义骨架屏项目类型
interface SkeletonItem {
type?: 'rect' | 'circle' | 'custom' // 形状类型
width?: string | number // 宽度
height?: string | number // 高度
radius?: string | number // 圆角半径,仅rect类型有效
margin?: string | number // 间距
animation?: boolean // 是否启用动画
}
// 组件属性
const props = defineProps({
// 骨架屏项目配置
items: {
type: Array as PropType<SkeletonItem[]>,
default: () => [
{ type: 'rect', width: '100%', height: '200px', animation: true },
{ type: 'rect', width: '80%', height: '30px', margin: '15px 0', animation: true },
{ type: 'rect', width: '60%', height: '30px', margin: '15px 0', animation: true }
]
},
// 骨架屏主色调
baseColor: {
type: String,
default: '#f2f2f2'
},
// 骨架屏高光色
highlightColor: {
type: String,
default: '#e0e0e0'
},
// 是否显示骨架屏
show: {
type: Boolean,
default: true
}
})
// 计算容器样式
const containerStyle = computed(() => {
return {
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start'
}
})
// 获取每个骨架屏项目的样式
const getItemStyle = (item: SkeletonItem) => {
const style: Record<string, string | number> = {
background: props.baseColor,
margin: item.margin || 0,
animation: props.show && item.animation
? 'skeleton-loading 1.5s infinite'
: 'none'
}
// 根据类型设置不同样式
if (item.type === 'rect') {
style.width = item.width || '100%'
style.height = item.height || '30px'
style.borderRadius = item.radius || '4px'
} else if (item.type === 'circle') {
style.width = item.width || item.height || '30px'
style.height = item.height || item.width || '30px'
style.borderRadius = '50%'
} else if (item.type === 'custom') {
// 自定义类型由插槽处理
}
return style
}
// 注册骨架屏动画
const style = document.createElement('style')
style.innerHTML = `
@keyframes skeleton-loading {
0% { background-position: -468px 0 }
100% { background-position: 468px 0 }
}
.skeleton-item {
background: linear-gradient(90deg,
${props.baseColor} 25%,
${props.highlightColor} 50%,
${props.baseColor} 75%
);
background-size: 468px 104px;
background-repeat: no-repeat;
overflow: hidden;
}
`
document.head.appendChild(style)
</script>
<style scoped>
.skeleton-container {
width: 100%;
box-sizing: border-box;
}
</style>