랭킹표시 수정
This commit is contained in:
@@ -7,6 +7,11 @@
|
||||
<div v-for="member in members" :key="member.participantId" class="member-row">
|
||||
<div class="member-info-block">
|
||||
<div class="member-header-row">
|
||||
<span v-if="member && (member.participantId || member.id) && (memberRanksRef[member.participantId] || memberRanksRef[member.id])"
|
||||
class="medal-icon-container">
|
||||
<i class="pi pi-trophy medal-icon" :class="'medal-' + (memberRanksRef[member.participantId] || memberRanksRef[member.id])"></i>
|
||||
<span class="medal-rank" :class="'medal-rank-' + (memberRanksRef[member.participantId] || memberRanksRef[member.id])">{{ memberRanksRef[member.participantId] || memberRanksRef[member.id] }}</span>
|
||||
</span>
|
||||
<span class="member-name">{{ member.name }}</span>
|
||||
<Tag v-if="member.isGuest" value="G" severity="warning" class="ml-2" />
|
||||
</div>
|
||||
@@ -31,6 +36,14 @@
|
||||
<template v-for="n in gameCount" :key="n">
|
||||
<div class="score-input-hc-wrap">
|
||||
<div class="score-input-status-wrap">
|
||||
<!-- 상태 아이콘을 입력 필드 앞으로 이동 -->
|
||||
<span class="score-status-icon-container">
|
||||
<i v-if="scoreStates[member.participantId + '-' + n] === 'saving'" class="pi pi-spin pi-spinner score-status-icon" />
|
||||
<i v-else-if="scoreStates[member.participantId + '-' + n] === 'saved'" class="pi pi-check score-status-icon" />
|
||||
<i v-else-if="scoreStates[member.participantId + '-' + n] === 'error'" class="pi pi-times score-status-icon" />
|
||||
</span>
|
||||
|
||||
<!-- 점수 입력 필드 -->
|
||||
<InputText
|
||||
v-if="canInputScore"
|
||||
v-model.number="scoresProxy[member.participantId + '-' + n]"
|
||||
@@ -43,29 +56,29 @@
|
||||
@keydown.enter="onScoreEnter(member, n, teamNumber)"
|
||||
/>
|
||||
<span v-else>{{ member.scores?.[n - 1] ?? '-' }}</span>
|
||||
|
||||
<!-- 핸디캡 포함 점수 표시 -->
|
||||
<span :class="scoreColorClass(scoreStates[member.participantId + '-' + n], scoresProxy[member.participantId + '-' + n], member.handicap)"
|
||||
class="score-hc-value score-status-text"
|
||||
:key="scoreStates[member.participantId + '-' + n] + '-' + scoresProxy[member.participantId + '-' + n]">
|
||||
{{ (scoresProxy[member.participantId + '-' + n] !== undefined && scoresProxy[member.participantId + '-' + n] !== '') ?
|
||||
Number(scoresProxy[member.participantId + '-' + n]) + (Number(member.handicap) || 0) : ''
|
||||
}}
|
||||
<i v-if="scoreStates[member.participantId + '-' + n] === 'saving'" class="pi pi-spin pi-spinner score-status-icon" />
|
||||
<i v-else-if="scoreStates[member.participantId + '-' + n] === 'saved'" class="pi pi-check score-status-icon" />
|
||||
<i v-else-if="scoreStates[member.participantId + '-' + n] === 'error'" class="pi pi-times score-status-icon" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="member-score-summary">
|
||||
<span>총점: {{ getMemberTotalScore(member) }}</span>
|
||||
<span class="member-score-avg">/ 에버리지: {{ getMemberAverageScore(member) }}</span>
|
||||
<span class="member-score-avg">/ 평균: {{ getMemberAverageScore(member) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { toRefs } from 'vue'
|
||||
import { computed, onMounted, watch, ref } from 'vue';
|
||||
import { calculateIndividualRankings, getRankColorClass } from '@/utils/rankingUtils';
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
members: Array,
|
||||
@@ -80,6 +93,127 @@ const props = defineProps({
|
||||
onScoreEnter: Function,
|
||||
getMemberTotalScore: Function,
|
||||
getMemberAverageScore: Function,
|
||||
scoreColorClass: Function
|
||||
scoreColorClass: Function,
|
||||
memberRanks: Object
|
||||
})
|
||||
|
||||
// 디버깅을 위한 코드
|
||||
// 순위 데이터를 저장할 로컬 변수
|
||||
const localRanks = ref({});
|
||||
|
||||
// 점수 변경 감지를 위한 참조 변수
|
||||
const lastScores = ref({});
|
||||
|
||||
// 순위 계산 함수 - 순위 계산 유틸리티 사용
|
||||
const updateLocalRanks = () => {
|
||||
if (!props.members || props.members.length === 0) return;
|
||||
|
||||
// 순위 계산 유틸리티 함수 호출
|
||||
const newRanks = calculateIndividualRankings(
|
||||
props.members,
|
||||
props.scoresProxy || {},
|
||||
props.gameCount || 3
|
||||
);
|
||||
|
||||
// 순위 맵 갱신
|
||||
localRanks.value = newRanks;
|
||||
|
||||
// 현재 점수 저장
|
||||
lastScores.value = {};
|
||||
props.members.forEach(member => {
|
||||
if (member && member.participantId) {
|
||||
lastScores.value[member.participantId] = props.getMemberTotalScore ? props.getMemberTotalScore(member) : 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 프록스와 로컬 데이터를 통합한 계산된 순위 객체
|
||||
const memberRanksRef = computed(() => {
|
||||
// 무조건 props.memberRanks 사용 - 최종 순위 테이블과 동일한 순위 표시를 위해
|
||||
return props.memberRanks || {};
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (props.members && props.members.length > 0) {
|
||||
// props가 undefined인 경우 기본값 설정
|
||||
if (!props.memberRanks) {
|
||||
updateLocalRanks();
|
||||
}
|
||||
|
||||
// 초기 점수 저장
|
||||
props.members.forEach(member => {
|
||||
if (member && member.participantId) {
|
||||
lastScores.value[member.participantId] = props.getMemberTotalScore ? props.getMemberTotalScore(member) : 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
// props.memberRanks 변경 감지
|
||||
watch(() => props.memberRanks, (newVal) => {
|
||||
}, { deep: true })
|
||||
|
||||
// 점수 변경 감지
|
||||
watch(() => props.scoresProxy, () => {
|
||||
// 점수가 변경되었는지 확인
|
||||
let scoresChanged = false;
|
||||
|
||||
props.members.forEach(member => {
|
||||
if (member && member.participantId) {
|
||||
const currentScore = props.getMemberTotalScore ? props.getMemberTotalScore(member) : 0;
|
||||
const previousScore = lastScores.value[member.participantId] || 0;
|
||||
|
||||
if (currentScore !== previousScore) {
|
||||
scoresChanged = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 점수가 변경되었으면 순위 재계산
|
||||
if (scoresChanged) {
|
||||
updateLocalRanks();
|
||||
}
|
||||
}, { deep: true })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.medal-icon-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.medal-icon {
|
||||
font-size: 1.8rem;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
/* 메달 색상 */
|
||||
.medal-1 {
|
||||
color: gold;
|
||||
}
|
||||
|
||||
.medal-2 {
|
||||
color: silver;
|
||||
}
|
||||
|
||||
.medal-3 {
|
||||
color: #cd7f32; /* 동메달 색상 */
|
||||
}
|
||||
|
||||
.medal-rank {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -80%);
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
/* 글자 테두리 효과 */
|
||||
text-shadow:
|
||||
-1px -1px 0 rgba(255, 255, 255, 0.7),
|
||||
1px -1px 0 rgba(255, 255, 255, 0.7),
|
||||
-1px 1px 0 rgba(255, 255, 255, 0.7),
|
||||
1px 1px 0 rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user