Files

85 lines
1.8 KiB
Vue
Raw Permalink Normal View History

2026-08-19 08:17:18 +08:00
<template>
<!-- 首屏骨架:形状跟页面走,动画吃 effect.skeleton -->
<view class="sk" :class="'sk--' + mode">
<view
v-for="n in bars"
:key="n"
class="sk-bar"
:style="barStyle(n)"
/>
</view>
</template>
<script>
import { getActiveLayout, getActiveVars } from '@/utils/theme'
export default {
name: 'ThemeSkeleton',
props: {
/** home | catalog | product | cart | mine */
page: { type: String, default: 'catalog' },
count: { type: Number, default: 0 },
},
computed: {
mode() {
const effect = (getActiveLayout().effect) || {}
return effect.skeleton || 'shimmer'
},
vars() {
return getActiveVars()
},
bars() {
if (this.count > 0) return this.count
const map = { home: 6, catalog: 6, product: 4, cart: 3, mine: 3 }
return map[this.page] || 4
},
},
methods: {
barStyle(n) {
const soft = this.vars['--color-surface-soft'] || this.vars['--color-border'] || '#E7DFD3'
const tall = this.page === 'catalog' && n % 2 === 0
return {
background: soft,
height: tall ? '300rpx' : (n === 1 && this.page === 'home' ? '240rpx' : '80rpx'),
}
},
},
}
</script>
<style lang="scss" scoped>
.sk {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
padding: 16rpx;
}
.sk-bar {
width: 100%;
border-radius: 12rpx;
}
.sk--catalog .sk-bar {
width: calc(50% - 8rpx);
}
.sk--shimmer .sk-bar {
background-size: 200% 100%;
animation: sk-shimmer 1.6s linear infinite;
}
.sk--pulse .sk-bar {
animation: sk-pulse 1.8s ease-in-out infinite;
}
.sk--none .sk-bar {
animation: none;
opacity: 0.55;
}
@keyframes sk-shimmer {
0% { opacity: 0.55; }
50% { opacity: 0.95; }
100% { opacity: 0.55; }
}
@keyframes sk-pulse {
0%, 100% { opacity: 0.55; }
50% { opacity: 1; }
}
</style>