DCFronted/src/components/RankContestant.vue
2025-05-26 20:35:34 +08:00

221 lines
4.8 KiB
Vue

<template>
<div class="rank-contestant">
<div class="rank-contestant-header">
<h2>选手排名</h2>
</div>
<div class="rank-content">
<div class="top-three">
<div v-for="(item, idx) in rankData.slice(0, 3)" :key="idx" class="rank-card">
<div class="rank-number">
{{ item.rank }}
</div>
<div class="player-info">
<div class="player-name">{{ item.username }}</div>
<div class="player-faction">{{ item.faction }}</div>
<div class="player-score">{{ item.score }}</div>
</div>
</div>
</div>
<div class="rank-list">
<div v-for="(item, idx) in rankData.slice(3)" :key="idx + 3" class="rank-item">
<div class="rank">{{ item.rank }}</div>
<div class="player-info">
<div class="player-name">{{ item.username }}</div>
<div class="player-faction">{{ item.faction }}</div>
<div class="player-score">{{ item.score }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getSignUpResultList } from '@/api/tournament'
const props = defineProps({
tournamentId: {
type: Number,
required: true
}
})
const rankData = ref([])
const fetchRankData = async () => {
try {
const response = await getSignUpResultList()
// 筛选当前赛事的玩家并按胜场数排序
const results = response
.filter(player => player.tournament_id === props.tournamentId)
.map((player, index) => ({
rank: index + 1,
username: player.sign_name,
faction: player.faction,
win: parseInt(player.win) || 0,
lose: parseInt(player.lose) || 0,
score: `${player.win}${player.lose}`
}))
.sort((a, b) => {
// 首先按胜场数排序
if (b.win !== a.win) {
return b.win - a.win
}
// 如果胜场数相同,则按负场数排序(负场数少的排前面)
return a.lose - b.lose
})
.map((player, index) => ({
...player,
rank: index + 1
}))
rankData.value = results
} catch (error) {
console.error('获取排名数据失败:', error)
}
}
onMounted(() => {
fetchRankData()
})
</script>
<style scoped>
.rank-contestant {
background: white;
border-radius: 8px;
padding: 24px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.rank-contestant-header {
margin-bottom: 24px;
}
.rank-contestant-header h2 {
font-size: 20px;
color: #303133;
margin: 0;
}
.rank-content {
display: flex;
flex-direction: column;
gap: 24px;
}
.top-three {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.rank-card {
background: white;
border-radius: 8px;
padding: 20px;
display: flex;
align-items: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
border: 1px solid #EBEEF5;
}
.rank-card:nth-child(1) {
background: #FFF9EB;
border: 1px solid #FFE4B5;
}
.rank-card:nth-child(2) {
background: #F8F9FA;
border: 1px solid #E4E7ED;
}
.rank-card:nth-child(3) {
background: #FDF6EC;
border: 1px solid #F3D19E;
}
.rank-number {
font-size: 24px;
font-weight: bold;
margin-right: 16px;
min-width: 50px;
text-align: center;
}
.rank-card:nth-child(1) .rank-number {
color: #E6A23C;
}
.rank-card:nth-child(2) .rank-number {
color: #909399;
}
.rank-card:nth-child(3) .rank-number {
color: #F56C6C;
}
.player-info {
flex: 1;
}
.player-name {
font-size: 16px;
font-weight: 500;
color: #303133;
margin-bottom: 4px;
}
.player-qq {
font-size: 14px;
color: #909399;
margin-bottom: 4px;
}
.player-faction {
font-size: 14px;
color: #409EFF;
margin-bottom: 4px;
}
.player-score {
font-size: 14px;
color: #67C23A;
font-weight: 500;
}
.rank-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.rank-item {
display: flex;
align-items: center;
padding: 16px;
background: white;
border-radius: 4px;
border: 1px solid #EBEEF5;
}
.rank {
width: 40px;
font-size: 16px;
font-weight: 600;
color: #909399;
text-align: center;
margin-right: 16px;
}
@media (max-width: 768px) {
.top-three {
grid-template-columns: 1fr;
}
.rank-contestant {
padding: 16px;
}
}
</style>