141 lines
2.9 KiB
Vue
141 lines
2.9 KiB
Vue
<template>
|
|
<view class="crystal-overview">
|
|
<!-- 错误态 -->
|
|
<view v-if="error" class="error-card" @tap="$emit('retry')">
|
|
<text class="error-text">加载失败,点击重试</text>
|
|
</view>
|
|
|
|
<!-- 骨架态 -->
|
|
<view v-else-if="loading || !data" class="skeleton-row">
|
|
<view v-for="i in 2" :key="i" class="skeleton-card"></view>
|
|
</view>
|
|
|
|
<!-- 正常态 -->
|
|
<view v-else class="card-row">
|
|
<view class="data-card card-crystal">
|
|
<text class="card-label">水晶余额</text>
|
|
<text class="card-value">{{ data.crystal_balance }}</text>
|
|
</view>
|
|
<view class="data-card card-crystal">
|
|
<text class="card-label">今日收益</text>
|
|
<text class="card-value">+ {{ data.today_income }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
defineProps({
|
|
data: { type: Object, default: null }, // { crystal_balance, today_income, week_rank? }
|
|
loading: { type: Boolean, default: false },
|
|
error: { type: String, default: null },
|
|
});
|
|
defineEmits(["retry"]);
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.crystal-overview {
|
|
margin:0 0 12rpx 0;
|
|
}
|
|
|
|
.card-row {
|
|
display: flex;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.data-card {
|
|
width: 100%;
|
|
height: 88rpx;
|
|
border-top-left-radius: 19px;
|
|
border-top-right-radius: 10px;
|
|
border-bottom-right-radius: 7px;
|
|
border-bottom-left-radius: 7px;
|
|
opacity: 1;
|
|
|
|
position: relative;
|
|
overflow: hidden;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.card-crystal {
|
|
background: linear-gradient(
|
|
274.19deg,
|
|
rgba(168, 166, 237, 0.49) -9.28%,
|
|
rgba(136, 200, 216, 0.49) 61.89%,
|
|
rgba(243, 128, 239, 0.49) 106.57%
|
|
);
|
|
box-shadow: 0px 4px 4px 0px #00000040;
|
|
}
|
|
|
|
// .card-today {
|
|
// background: linear-gradient(137deg, #ffdf77 0%, #8e95e2 40%, #f48cff 100%);
|
|
// box-shadow: 0px 4px 4px rgba(189, 50, 50, 0.25);
|
|
// }
|
|
|
|
.card-label {
|
|
position: absolute;
|
|
top: 10rpx;
|
|
left: 12rpx;
|
|
font-size: 24rpx;
|
|
color: #ffffff;
|
|
text-shadow: 0px 4px 4px rgba(164, 60, 60, 0.55);
|
|
|
|
}
|
|
|
|
.card-value {
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 12rpx;
|
|
font-size: 64rpx;
|
|
font-weight: 600;
|
|
color: #fffabd;
|
|
text-shadow: -1px 1px 4px rgba(206, 9, 9, 0.84);
|
|
font-family: "Baloo Bhai", sans-serif;
|
|
}
|
|
|
|
/* 骨架态 */
|
|
.skeleton-row {
|
|
display: flex;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.skeleton-card {
|
|
flex: 1;
|
|
height: 200rpx;
|
|
border-radius: 22rpx;
|
|
background: linear-gradient(
|
|
90deg,
|
|
rgba(255, 255, 255, 0.1) 25%,
|
|
rgba(255, 255, 255, 0.2) 50%,
|
|
rgba(255, 255, 255, 0.1) 75%
|
|
);
|
|
background-size: 200% 100%;
|
|
animation: skeleton-shimmer 1.5s infinite;
|
|
}
|
|
|
|
@keyframes skeleton-shimmer {
|
|
0% {
|
|
background-position: 200% 0;
|
|
}
|
|
100% {
|
|
background-position: -200% 0;
|
|
}
|
|
}
|
|
|
|
/* 错误态 */
|
|
.error-card {
|
|
height: 200rpx;
|
|
border-radius: 22rpx;
|
|
background: rgba(255, 100, 100, 0.15);
|
|
border: 2rpx solid rgba(255, 100, 100, 0.4);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.error-text {
|
|
color: #ff8080;
|
|
font-size: 28rpx;
|
|
}
|
|
</style>
|