-
-
-
-
- 当前比赛: {{ tournament.name || '加载中...' }}
-
-
-
-
参赛者列表
-
-
加载中...
-
-
暂无参赛者
-
- 共 {{ participants.length }} 位参赛者
-
- -
- {{ participant.name }}
-
-
-
-
-
-
-
生成赛程
-
-
-
-
最终排名
-
🏆 冠军: {{ champion }}
-
🥈 亚军: {{ runnerUp }}
-
🥉 季军: {{ thirdPlace }}
-
-
-
@@ -145,9 +108,7 @@ let winnerssvgSelection = null;
let losersZoomBehavior = null;
let loserssvgSelection = null;
-const canGenerateBracket = computed(() => {
- return participants.value.length >= 4;
-});
+
onMounted(() => {
loadTournamentData();
@@ -155,7 +116,6 @@ onMounted(() => {
// Add keyboard shortcuts for zoom control
const handleKeydown = (event) => {
if (event.target.tagName === 'INPUT') return;
-
switch(event.key) {
case '+':
case '=':
@@ -220,6 +180,11 @@ const loadTournamentData = async () => {
qq_code: item.qq_code || '',
status: item.status || ''
}));
+
+ // 数据加载完成后自动生成赛程
+ if (participants.value.length >= 4) {
+ generateDoubleEliminationBracket();
+ }
} catch (err) {
console.error('获取比赛数据失败:', err);
} finally {
@@ -248,21 +213,17 @@ const generateDoubleEliminationBracket = () => {
while (shuffledParticipants.length < totalSlots) {
shuffledParticipants.push(null);
}
-
console.log(`总参赛者: ${totalPlayers}, 总槽位: ${totalSlots}`);
-
// 生成胜者组第一轮
const winnersRound1 = [];
for (let i = 0; i < totalSlots; i += 2) {
const p1 = shuffledParticipants[i];
const p2 = shuffledParticipants[i + 1];
-
// 处理轮空情况
let winner = null;
let decided = false;
let score1 = 0;
let score2 = 0;
-
if (p1 && !p2) {
// p1轮空直接晋级
winner = p1;
@@ -297,7 +258,6 @@ const generateDoubleEliminationBracket = () => {
});
}
winnersBracket.value = [winnersRound1];
-
// 预生成胜者组的所有轮次结构
let currentRoundSize = Math.ceil(totalSlots / 2);
while (currentRoundSize > 1) {
@@ -318,12 +278,9 @@ const generateDoubleEliminationBracket = () => {
winnersBracket.value.push(nextRound);
}
}
-
console.log(`胜者组轮次数: ${winnersBracket.value.length}`);
-
// 预生成败者组结构
generateLosersBracketStructure(totalPlayers);
-
// 处理第一轮的轮空晋级
winnersRound1.forEach((match, index) => {
if (match.decided && match.winner) {
@@ -370,11 +327,9 @@ const generateLosersBracketStructure = (totalPlayers) => {
for (let round = 0; round < losersRounds; round++) {
const roundMatches = [];
let matchCount = 1;
-
// 败者组比赛数量规律:
// LR1: 1场 (胜者组第1轮败者们对战,但要考虑轮空)
// LR2: 1场 (LR1胜者 vs 胜者组第2轮败者)
-
if (round === 0) {
// 第一轮败者组:计算实际的败者数量
const firstRoundLosers = Math.floor(totalPlayers / 2); // 第一轮实际对战产生的败者数
@@ -387,10 +342,8 @@ const generateLosersBracketStructure = (totalPlayers) => {
} else {
matchCount = 1; // 其他轮次通常是1场
}
-
// 确保至少有0场比赛(可能某轮不需要比赛)
matchCount = Math.max(0, matchCount);
-
if (matchCount > 0) {
for (let i = 0; i < matchCount; i++) {
roundMatches.push({
@@ -430,7 +383,6 @@ const drawD3LosersBracket = () => {
drawD3Bracket(svg, losersBracket.value, 'losersBracketContainer', 'losers');
};
-
// Generic D3.js bracket drawing function
const drawD3Bracket = (svg, bracket, containerId, bracketType) => {
const margin = { top: 40, right: 40, bottom: 40, left: 40 };
@@ -1134,37 +1086,8 @@ h1 {
min-height: 500px;
}
-.control-panel {
- flex: 1;
- min-width: 280px;
- background: #f0f0f0;
- padding: 15px;
- border-radius: 6px;
- height: 100%;
- box-sizing: border-box;
-}
-
-.tournament-info {
- margin-bottom: 15px;
- padding: 10px;
- background: #e6f7ff;
- border-radius: 4px;
-}
-
-.control-panel h2 {
- color: #1a237e;
- font-size: 1.2rem;
- font-weight: 600;
- margin: 20px 0 10px 0;
-}
-
-.loading {
- color: #666;
- font-style: italic;
-}
-
.bracket-main {
- flex: 3;
+ flex: 1;
display: flex;
flex-direction: column;
gap: 20px;
@@ -1336,31 +1259,5 @@ button:hover:not(:disabled) {
background: #66b1ff;
}
-.final-ranking {
- background: #fffbdb;
- border: 1px solid #f0e68c;
- padding: 15px;
- border-radius: 6px;
- margin-top: 20px;
-}
-.final-ranking h3 {
- margin-top: 0;
- color: #b8860b;
-}
-
-.final-ranking p {
- margin: 5px 0;
- font-size: 16px;
-}
-
-ul {
- padding-left: 20px;
- margin: 0 0 10px 0;
-}
-
-li {
- margin-bottom: 4px;
- list-style: disc;
-}
\ No newline at end of file
diff --git a/src/components/TournamentBracket.vue b/src/components/TournamentBracket.vue
index 07f3490..662d80e 100644
--- a/src/components/TournamentBracket.vue
+++ b/src/components/TournamentBracket.vue
@@ -291,18 +291,18 @@ const generateRoundMatches = async (round, roundData) => {
// 处理已有数据的比赛
for (const player of roundData) {
- if (usedPlayers.has(player.id)) {
+ if (usedPlayers.has(player.id)) {
console.log(`玩家 ${player.sign_name} (ID: ${player.id}) 已被使用,跳过`);
- continue;
- }
+ continue;
+ }
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
const isPending = rivalName === '待定' || rivalName === 'pending' || rivalName === 'PENDING' || rivalName === 'Pending';
- if (isBye || isPending) {
+ if (isBye || isPending) {
console.log(`玩家 ${player.sign_name} 的对手是 ${rivalName},跳过正常比赛处理`);
- continue;
+ continue;
}
// 寻找对手
@@ -665,7 +665,7 @@ const matchOpponentsInRound = async (round) => {
} else {
console.log(`第${round}轮待定玩家数量为${roundData.length},无法匹配`);
}
- } catch (error) {
+ } catch (error) {
console.error(`匹配第${round}轮对手失败:`, error);
}
};
diff --git a/src/views/index.vue b/src/views/index.vue
index 611dd92..dc0e8a1 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -366,7 +366,6 @@ function handlePasswordChangeError(errorMessage) {
赛程信息