topfans/frontend/pages/dashboard/components/RecentUpgrades.vue
2026-06-04 00:51:29 +08:00

205 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="recent-upgrades">
<text class="card-title">最近升级藏品</text>
<view v-if="!items || items.length === 0" class="empty-row">
<text class="empty-text">暂无数据</text>
</view>
<view v-else class="upgrades-list">
<view v-for="item in items" :key="item.asset_id" class="upgrade-row">
<view class="upgrade-thumb">
<image
v-if="item.asset_thumb"
class="upgrade-thumb-img"
:src="item.asset_thumb"
mode="aspectFill"
/>
<text v-else class="thumb-emoji">{{ item.asset_name[0] }}</text>
<!-- 等级徽章叠加在左上角(显示升级前的等级) -->
<image
class="upgrade-thumb-badge"
:src="getGradeBadge(getPreviousLevel(item.new_level))"
mode="aspectFit"
/>
</view>
<view class="upgrade-info">
<text class="lv-up">Lv <text class="lv-up lv-up-text">UP</text></text>
</view>
<view class="level-badge">
<image
class="level-badge-img"
:src="getGradeBadge(item.new_level)"
mode="aspectFit"
/>
</view>
</view>
</view>
</view>
</template>
<script setup>
defineProps({
items: { type: Array, default: () => [] }, // RecentLevelUpItem[]
});
// 等级徽章图片映射item.new_level 是字符串 ('UR'/'SSR'/'SR'/'R'/'N')
// 注意 UR 的文件名是 URengji.png没有 d与其他不同
const GRADE_BADGE_MAP = {
N: "/static/starbookcontent/grade/Ndengji.png",
R: "/static/starbookcontent/grade/Rdengji.png",
SR: "/static/starbookcontent/grade/SRdengji.png",
SSR: "/static/starbookcontent/grade/SSRdengji.png",
UR: "/static/starbookcontent/grade/URengji.png",
};
const getGradeBadge = (level) => GRADE_BADGE_MAP[level] || GRADE_BADGE_MAP.N;
// 等级升序N < R < SR < SSR < UR。返回 level 的"前一级"(用于左上角徽章)
const LEVEL_ORDER = ["N", "R", "SR", "SSR", "UR"];
const getPreviousLevel = (level) => {
const idx = LEVEL_ORDER.indexOf(level);
return idx > 0 ? LEVEL_ORDER[idx - 1] : LEVEL_ORDER[0];
};
function formatTime(ts) {
const now = Date.now();
const diff = now - ts;
if (diff < 60 * 60 * 1000) return `${Math.floor(diff / 60000)} 分钟前`;
if (diff < 24 * 60 * 60 * 1000) return `${Math.floor(diff / 3600000)} 小时前`;
return `${Math.floor(diff / 86400000)} 天前`;
}
</script>
<style lang="scss" scoped>
.recent-upgrades {
background: linear-gradient(
106.77deg,
rgba(255, 223, 119, 0.24) -9.76%,
rgba(185, 132, 255, 0.24) 44.65%,
rgba(255, 129, 131, 0.24) 117.82%
);
border-radius: 14px;
padding: 16rpx;
box-shadow: 0px 4px 4px 0px rgba(189, 50, 50, 0.25);
}
.card-title {
display: block;
font-size: 22rpx;
font-weight: 600;
color: #ffffff;
margin-bottom: 16rpx;
}
.upgrades-list {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.upgrade-row {
display: flex;
align-items: center;
gap: 12rpx;
background: rgba(255, 255, 255, 0.05);
border-radius: 12rpx;
padding: 10rpx;
}
.upgrade-thumb {
width: 56rpx;
height: 67rpx;
flex-shrink: 0;
border-radius: 12rpx;
// overflow: hidden; // 裁切 image 贴合圆角
display: flex;
align-items: center;
justify-content: center;
position: relative; // 作为 .upgrade-thumb-badge 的定位上下文
transform: rotate(-10deg);
box-shadow: 0px 4px 4px 0px rgba(214, 53, 53, 0.43);
}
// 等级徽章图:绝对定位在缩略图左上角
.upgrade-thumb-badge {
position: absolute;
top: -8rpx;
left: -8rpx;
width: 28rpx;
height: 28rpx;
z-index: 1;
filter: drop-shadow(0 0 2rpx rgba(0, 0, 0, 0.5)); // 提升深色图上的可读性
}
// 藏品缩略图:填满 .upgrade-thumb 容器
.upgrade-thumb-img {
width: 100%;
height: 100%;
display: block;
}
// 无图时的 emoji 兜底
.thumb-emoji {
font-size: 28rpx;
font-weight: 700;
color: #ffffff;
}
.upgrade-info {
flex: 0 0 auto;
display: flex;
flex-direction: column;
margin-left: 24rpx;
}
.upgrade-name {
font-size: 22rpx;
color: #ffffff;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.upgrade-time {
font-size: 18rpx;
color: rgba(255, 255, 255, 0.6);
}
.level-badge {
display: flex;
flex-direction: column;
align-items: center;
padding: 4rpx 6rpx;
flex-shrink: 0;
}
// 等级徽章图:保持比例,限制最大尺寸
.level-badge-img {
width: 80rpx;
height: 80rpx;
}
.lv-up {
font-size: 30rpx;
font-weight: 600;
color: rgba(255, 241, 163, 1);
text-shadow: -1px 1px 4px rgba(206, 9, 9, 0.84);
}
.lv-up-text {
font-size: 40rpx;
}
.empty-row {
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
}
.empty-text {
color: rgba(255, 255, 255, 0.5);
font-size: 24rpx;
}
</style>