322 lines
6.1 KiB
Vue
322 lines
6.1 KiB
Vue
<template>
|
|
<div style="width: 100%">
|
|
<div style="position: relative">
|
|
<img
|
|
v-smart-img.noFade
|
|
: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
|
|
:src="avatarUrl || ''"
|
|
alt=""
|
|
width="100%"
|
|
class="top-avatar"
|
|
:class="{ 'top-avatar-square': avatarSquare }"
|
|
style="display: block; 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: 2vw;
|
|
"
|
|
:style="{ height: bottomSectionHeight }"
|
|
>
|
|
<div
|
|
style="display: flex; justify-content: center; align-items: center"
|
|
:style="{
|
|
width: nameValueWidth,
|
|
height: nameValueHeight,
|
|
}"
|
|
>
|
|
<div style="font-weight: 700" class="showText" :class="isTopOne ? 'top1Text' : 'text'">
|
|
{{ name }}
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="distribution-value-pill"
|
|
:class="distributionValueClass"
|
|
style="padding: 1px 2px; display: flex; justify-content: center; align-items: center"
|
|
:style="{
|
|
width: distributionValueWidth,
|
|
}"
|
|
>
|
|
<img
|
|
v-smart-img.noFade
|
|
:src="resolvedValueIconUrl"
|
|
alt=""
|
|
style="display: block; aspect-ratio: 1/1; flex: 0 0 auto"
|
|
:style="{ width: coinWidth }"
|
|
/>
|
|
<div style="font-weight: 590" class="showText" :class="isTopOne ? 'top1Text' : 'text'">
|
|
{{ distributionValue }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { handleAvatarImageError } from '@/utils/image/imageHandler.js'
|
|
import { computed } from 'vue'
|
|
|
|
const props = defineProps({
|
|
ranking: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
|
|
avatarUrl: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
|
|
BorderImgUrl: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
|
|
name: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
|
|
distributionValue: {
|
|
type: [String, Number],
|
|
default: '',
|
|
},
|
|
|
|
valueIconUrl: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
|
|
avatarSquare: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
})
|
|
|
|
// 是否为第一名
|
|
const isTopOne = computed(() => {
|
|
return props.ranking === '1'
|
|
})
|
|
|
|
const resolvedValueIconUrl = computed(() => {
|
|
return props.valueIconUrl || new URL('/src/assets/icon/Azizi/coin.png', import.meta.url).href
|
|
})
|
|
|
|
const distributionValueClass = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return 'distribution-value-pill-top1'
|
|
case '2':
|
|
return 'distribution-value-pill-top2'
|
|
case '3':
|
|
return 'distribution-value-pill-top3'
|
|
default:
|
|
return ''
|
|
}
|
|
})
|
|
|
|
// 头像容器高度
|
|
const avatarContainerHeight = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '83%'
|
|
case '2':
|
|
return '83%'
|
|
case '3':
|
|
return '83%'
|
|
default:
|
|
return '83%'
|
|
}
|
|
})
|
|
|
|
// 头像宽度
|
|
const avatarWidth = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '40%'
|
|
case '2':
|
|
return '40%'
|
|
case '3':
|
|
return '40%'
|
|
default:
|
|
return '40%'
|
|
}
|
|
})
|
|
|
|
// 底部信息区域高度
|
|
const bottomSectionHeight = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '40%'
|
|
case '2':
|
|
return '40%'
|
|
case '3':
|
|
return '40%'
|
|
default:
|
|
return '40%'
|
|
}
|
|
})
|
|
|
|
// 名称宽度
|
|
const nameValueWidth = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '52%'
|
|
case '2':
|
|
return '52%'
|
|
case '3':
|
|
return '52%'
|
|
default:
|
|
return '52%'
|
|
}
|
|
})
|
|
|
|
// 名称高度
|
|
const nameValueHeight = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '35%'
|
|
case '2':
|
|
return '30%'
|
|
case '3':
|
|
return '30%'
|
|
default:
|
|
return '30%'
|
|
}
|
|
})
|
|
|
|
// 贡献值宽度
|
|
const distributionValueWidth = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '55%'
|
|
case '2':
|
|
return '50%'
|
|
case '3':
|
|
return '50%'
|
|
default:
|
|
return '50%'
|
|
}
|
|
})
|
|
|
|
// 金币图标宽度
|
|
const coinWidth = computed(() => {
|
|
switch (props.ranking) {
|
|
case '1':
|
|
return '1em'
|
|
case '2':
|
|
return '0.9em'
|
|
case '3':
|
|
return '0.9em'
|
|
default:
|
|
return '0.9em'
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
* {
|
|
color: black;
|
|
}
|
|
|
|
.showText {
|
|
color: #fff;
|
|
text-align: center;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.top1Text {
|
|
font-size: 0.75em;
|
|
}
|
|
|
|
.text {
|
|
font-size: 0.6em;
|
|
}
|
|
|
|
.top-avatar {
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.top-avatar-square {
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.distribution-value-pill {
|
|
border-radius: 40px;
|
|
border: 0.64px solid #ffdf36;
|
|
box-shadow: 0 0 2.558px 0 rgba(0, 0, 0, 0.4) inset;
|
|
}
|
|
|
|
.distribution-value-pill-top1 {
|
|
background: linear-gradient(270deg, #3a0606 0%, #d84949 47.45%, #3a0606 100%);
|
|
}
|
|
|
|
.distribution-value-pill-top2 {
|
|
background: linear-gradient(270deg, #223457 0%, #859de7 47.45%, #213655 100%);
|
|
}
|
|
|
|
.distribution-value-pill-top3 {
|
|
background: linear-gradient(270deg, #13301a 0%, #89db93 47.45%, #112a16 100%);
|
|
}
|
|
|
|
@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>
|