317 lines
6.5 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>
<div style="width: 100%">
<div style="position: relative">
<img
v-smart-img
:src="BorderImgUrl"
alt=""
width="100%"
style="display: block; position: relative; z-index: 2"
/>
<!-- 头像 -->
<div
style="
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
"
:style="{ height: avatarContainerHeight }"
>
<div :style="{ width: avatarWidth }">
<img
v-smart-img
:src="avatarUrl || ''"
alt=""
width="100%"
style="display: block; border-radius: 50%; aspect-ratio: 1/1; object-fit: cover"
@error="handleAvatarImageError"
/>
</div>
</div>
<!-- 用户名和贡献值 -->
<div
style="
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 3;
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
"
:style="{ height: bottomSectionHeight }"
>
<div
style="display: flex; align-items: center; overflow: hidden; width: 100%"
:style="usernameAreaStyle"
>
<!-- 滚动容器 -->
<div class="scroll-wrapper">
<!-- 第一套内容 -->
<div class="scroll-content">
<div
style="color: #fff; font-weight: 700; white-space: nowrap"
:class="textSizeClass"
>
{{ name }}
</div>
<img
v-smart-img
src="/src/assets/icon/coin.png"
alt=""
style="display: block; width: 1.1em"
/>
<div
style="
font-weight: 700;
background: linear-gradient(180deg, #ffe656 0%, #fff 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
"
class="showText"
:class="isTopOne ? 'top1Text' : 'text'"
>
{{ distributionValue }}
</div>
</div>
<!-- 第二套内容间隔30px -->
<div class="scroll-content" style="margin-left: 30px">
<div
style="color: #fff; font-weight: 700; white-space: nowrap"
:class="textSizeClass"
>
{{ name }}
</div>
<img
v-smart-img
src="/src/assets/icon/coin.png"
alt=""
style="display: block; width: 1.1em"
/>
<div
style="
font-weight: 700;
background: linear-gradient(180deg, #ffe656 0%, #fff 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
"
class="showText"
:class="isTopOne ? 'top1Text' : 'text'"
>
{{ distributionValue }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { handleAvatarImageError } from '@/utils/imageHandler.js'
const props = defineProps({
// 排名
ranking: {
type: String,
default: '1',
},
// 头像
avatarUrl: {
type: String,
default: '',
},
// 头像框
BorderImgUrl: {
type: String,
required: true,
},
// 名字
name: {
type: String,
default: '',
},
// 贡献值
distributionValue: {
type: String,
default: '',
},
})
// 头像容器高度
const avatarContainerHeight = computed(() => {
switch (props.ranking) {
case '1':
return '93%'
case '2':
return '93%'
case '3':
return '90%'
case '4':
return '90%'
case '5-7':
return '85%'
case '8-10':
return '85%'
default:
return '90%'
}
})
// 头像宽度
const avatarWidth = computed(() => {
switch (props.ranking) {
case '1':
return '36%'
case '2':
return '50%'
case '3':
return '41%'
case '4':
return '41%'
case '5-7':
return '45%'
case '8-10':
return '45%'
default:
return '48%'
}
})
// 底部信息区域高度
const bottomSectionHeight = computed(() => {
switch (props.ranking) {
case '1':
return '23%'
case '2':
return '37%'
case '3':
return '39%'
case '4':
return '39%'
case '5-7':
return '43%'
case '8-10':
return '41%'
default:
return '30%'
}
})
// 用户名区域样式
const usernameAreaStyle = computed(() => {
switch (props.ranking) {
case '1':
return 'height: 50%; width: 36%;'
case '2':
return 'height: 39%; width: 90%;'
case '3':
return 'height: 26%; width: 70%;'
case '4':
return 'height: 26%; width: 75%;'
case '5-7':
return 'height: 23%; width: 78%;'
case '8-10':
return 'height: 27%; width: 78%;'
default:
return 'height: 30%; width: 40%;'
}
})
// 文字大小类
const textSizeClass = computed(() => {
return props.ranking === '1' ? 'top1Text' : 'text'
})
// 是否为第一名
const isTopOne = computed(() => {
return props.ranking === '1'
})
</script>
<style lang="scss" scoped>
* {
font-family: 'SF Pro';
color: black;
}
.top1Text {
font-size: 0.75em;
}
.text {
font-size: 0.6em;
}
.showText {
color: #fff;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.scroll-wrapper {
display: flex;
width: fit-content;
animation: scroll-left 5s linear infinite;
will-change: transform;
}
.scroll-content {
display: flex;
align-items: center;
gap: 4px;
}
@keyframes scroll-left {
0% {
transform: translateX(0);
}
100% {
transform: translateX(calc(-50% - 15px));
}
}
@media screen and (max-width: 360px) {
* {
font-size: 10px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 16px;
}
}
@media screen and (min-width: 768px) {
* {
font-size: 24px;
}
}
@media screen and (min-width: 1024px) {
* {
font-size: 32px;
}
}
</style>