2315 lines
69 KiB
Vue
2315 lines
69 KiB
Vue
<template>
|
||
<div @click.once="handleFirstInteraction">
|
||
<!-- 第一部分:百日大战主题 - 使用banner0.png图片 -->
|
||
<section class="theme-section card-game">
|
||
<div class="theme-container">
|
||
<img src="/banner0.png" alt="百日大战主题" class="banner-image bai-day-battle">
|
||
</div>
|
||
</section>
|
||
|
||
|
||
|
||
<!-- 任务设置模块 -->
|
||
<section class="task-settings-section card-game">
|
||
<div class="task-title-container">
|
||
<h1 class="game-title" v-if="taskSettings?.mainTitle">任务: <span class="game-title-highlight">{{
|
||
taskSettings.mainTitle }} </span> </h1>
|
||
<p class="game-subtitle" v-if="taskSettings?.subtitle">{{ taskSettings.subtitle }}</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 第三部分:奖金设置(图片形式) -->
|
||
<section v-if="localDisplayConfig.showBonusModule" class="bonus-section card-game"
|
||
@mousedown="startBonusDrag"
|
||
@touchstart="startBonusTouch"
|
||
@click.stop>
|
||
<div class="bonus-awards-container">
|
||
<div><img src="/award1.png" alt="一等奖" class="award-image"></div>
|
||
<div><img src="/award2.png" alt="二等奖" class="award-image"></div>
|
||
<div><img src="/award3.png" alt="三等奖" class="award-image"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 第四部分:总战绩 -->
|
||
<section class="total-score-section card-game">
|
||
<div class="total-score-container">
|
||
<div class="game-subtitle total-score-total-title">
|
||
<img src="/completed_performance.png"
|
||
alt="总战绩"
|
||
style="width: 880px; display: block; margin: 0 auto; height: auto;"
|
||
class="total-score-total-image">
|
||
</div>
|
||
<div class="total-score-content">
|
||
<div class="total-score-item">
|
||
<span class="score-value total-score-total-value">{{ localDisplayConfig.team?.totalScoreColumn?.displayStyle === 'amount' ? '¥' : '' }}{{ totalTeamScore }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 第五部分:排名明细 -->
|
||
<section class="rankings-section card-game">
|
||
<div class="rankings-container">
|
||
|
||
<!-- 战区排名 -->
|
||
<div class="team-rankings">
|
||
<!-- 战区排名宣传语 -->
|
||
<div class="team-rankings-propagation">
|
||
<img src="/team-propagation.png" alt="虎狼之师" class="team-rankings-propagation-image"
|
||
style="width: 500px; height: auto">
|
||
</div>
|
||
<!-- 战区冠军 -->
|
||
<div class="team-champion">
|
||
<div class="team-logo" :class="{ 'photo-container': localDisplayConfig.championLogos?.teamChampionType === 'photo' }">
|
||
<img v-if="localDisplayConfig.championLogos?.teamChampion"
|
||
:src="localDisplayConfig.championLogos.teamChampion" alt="战区冠军"
|
||
class="champion-logo"
|
||
:style="localDisplayConfig.championLogos?.teamChampionType === 'photo'
|
||
? {
|
||
width: localDisplayConfig.championLogos?.teamChampionPhotoWidth + 'px',
|
||
height: localDisplayConfig.championLogos?.teamChampionPhotoHeight + 'px',
|
||
objectFit: 'cover'
|
||
}
|
||
: {
|
||
width: localDisplayConfig.championLogos?.teamChampionSize + 'px',
|
||
height: localDisplayConfig.championLogos?.teamChampionSize + 'px'
|
||
}
|
||
">
|
||
<img v-else src="/crown.png" alt="战区冠军" class="champion-logo" />
|
||
</div>
|
||
<div class="champion-name">
|
||
{{ teamRankings[0]?.name || '暂无冠军' }}
|
||
</div>
|
||
</div>
|
||
<div class="team-rankings-container">
|
||
<h2 class="game-subtitle">战区排名</h2>
|
||
<div class="rank-table">
|
||
<div class="table-header" :style="{ 'grid-template-columns': teamGridTemplate }">
|
||
<span class="rank-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.rank || 'left' }">排名</span>
|
||
<span class="name-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.name || 'left' }">战区名称</span>
|
||
<span class="score-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.score || 'left' }">{{ localDisplayConfig.team?.totalScoreColumn?.displayName || '业绩' }}</span>
|
||
<span v-if="localDisplayConfig.team?.showMemberCount" class="member-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.memberCount || 'left' }">人数</span>
|
||
<span v-if="localDisplayConfig.team?.showLeader" class="leader-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.leader || 'left' }">将军</span>
|
||
<span v-if="localDisplayConfig.team?.showBonus" class="bonus-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.bonus || 'left' }">奖金</span>
|
||
</div>
|
||
<div v-for="(item, index) in filteredTeamRankings" :key="item.id" class="table-row"
|
||
:style="{ 'grid-template-columns': teamGridTemplate }" :class="{
|
||
'top-three': index < 3,
|
||
'highlight': index === 0
|
||
}">
|
||
<span class="rank-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.rank || 'left' }">{{ index + 1 }}</span>
|
||
<span class="name-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.name || 'left' }">{{ item.name }}</span>
|
||
<span class="score-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.score || 'left' }">{{ localDisplayConfig.team?.totalScoreColumn?.displayStyle === 'amount' ? '¥' : '' }}{{ formatNumber(item.totalScore) }}</span>
|
||
<span v-if="localDisplayConfig.team?.showMemberCount" class="member-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.memberCount || 'left' }">{{ item.memberCount }}人</span>
|
||
<span v-if="localDisplayConfig.team?.showLeader" class="leader-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.leader || 'left' }">{{ item.leader }}</span>
|
||
<span v-if="localDisplayConfig.team?.showBonus" class="bonus-col" :style="{ textAlign: localDisplayConfig.team?.columnAlignments?.bonus || 'left' }">¥{{ item.bonus }}</span>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="individual-rankings">
|
||
<!-- 英雄排名宣传语 -->
|
||
<div class="individual-rankings-propagation">
|
||
<img src="/individual-propagation.png" alt="虎狼之师" class="individual-rankings-propagation-image"
|
||
style="width: 500px; height: auto">
|
||
</div>
|
||
<!-- 英雄冠军 -->
|
||
<div class="individual-champion">
|
||
<div class="champion-content">
|
||
<div class="individual-avatar champion-container">
|
||
<div class="crown-animation" :class="{'crown-animation-run': localDisplayConfig.crown?.animationEnabled}" v-if="filteredIndividualRankings.length > 0" :style="{
|
||
fontSize: (localDisplayConfig.crown?.size || localDisplayConfig.championLogos?.individualChampionSize * 0.8) + 'px'
|
||
}">
|
||
👑
|
||
</div>
|
||
<img v-if="filteredIndividualRankings[0]?.avatar && filteredIndividualRankings[0].avatar.startsWith('/')"
|
||
:src="filteredIndividualRankings[0].avatar" alt="冠军头像" class="avatar-image avatar-image-champion"
|
||
:style="{ width: localDisplayConfig.championLogos?.individualChampionSize + 'px', height: localDisplayConfig.championLogos?.individualChampionSize + 'px' }">
|
||
<img v-else-if="localDisplayConfig.championLogos?.individualChampion"
|
||
:src="localDisplayConfig.championLogos.individualChampion" alt="英雄冠军" class="champion-logo"
|
||
:style="{ width: localDisplayConfig.championLogos?.individualChampionSize + 'px', height: localDisplayConfig.championLogos?.individualChampionSize + 'px' }">
|
||
<div v-else class="champion-log">
|
||
<span
|
||
:style="{ fontSize: localDisplayConfig.championLogos?.individualChampionSize ? (localDisplayConfig.championLogos.individualChampionSize * 0.8) + 'px' : '2rem' }">
|
||
{{ filteredIndividualRankings[0]?.avatar || '👤' }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="champion-name">
|
||
{{ filteredIndividualRankings[0]?.name || '暂无冠军' }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 英雄排名 -->
|
||
<div class="individual-rankings-container">
|
||
<h2 class="game-subtitle">英雄排名</h2>
|
||
<div class="rank-table">
|
||
<div class="table-header" :style="{ 'grid-template-columns': individualGridTemplate }">
|
||
<span class="rank-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.rank || 'left' }">排名</span>
|
||
<span v-if="localDisplayConfig.individual?.showAvatar" class="avatar-col">头像</span>
|
||
<span class="name-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.name || 'left' }">姓名</span>
|
||
<span v-if="localDisplayConfig.individual?.showTeam" class="team-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.team || 'left' }">{{
|
||
localDisplayConfig.individual?.teamColumn?.displayName || '战区' }}</span>
|
||
<span class="score-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.score || 'left' }">{{ localDisplayConfig.individual?.scoreColumn?.displayName || '业绩' }}</span>
|
||
<span v-if="localDisplayConfig.individual?.showLevel" class="level-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.level || 'left' }">等级</span>
|
||
<span v-if="localDisplayConfig.individual?.showDepartment" class="dept-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.department || 'left' }">部门</span>
|
||
<span v-if="localDisplayConfig.individual?.showBonus" class="bonus-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.bonus || 'left' }">奖金</span>
|
||
</div>
|
||
<div v-for="(item, index) in filteredIndividualRankings" :key="item.id" class="table-row"
|
||
:style="{ 'grid-template-columns': individualGridTemplate }" :class="{
|
||
'top-three': index < 3,
|
||
'highlight': index === 0
|
||
}">
|
||
<span class="rank-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.rank || 'left' }">{{ index + 1 }}</span>
|
||
<span v-if="localDisplayConfig.individual?.showAvatar" class="avatar-col">
|
||
<img v-if="item.avatar && item.avatar.startsWith('/')" :src="item.avatar" alt="头像"
|
||
class="avatar-image">
|
||
<span v-else>{{ item.avatar || '👤' }}</span>
|
||
</span>
|
||
<span class="name-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.name || 'left' }">{{ item.name || '-' }}</span>
|
||
<span v-if="localDisplayConfig.individual?.showTeam" class="team-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.team || 'left' }">{{ item.team || '-' }}</span>
|
||
<span class="score-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.score || 'left' }">{{ localDisplayConfig.individual?.scoreColumn?.displayStyle === 'amount' ? '¥' : '' }}{{ formatNumber(item.score) }}</span>
|
||
<span v-if="localDisplayConfig.individual?.showLevel" class="level-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.level || 'left' }"
|
||
:class="`level-${item.level}`">{{ item.level }}</span>
|
||
<span v-if="localDisplayConfig.individual?.showDepartment" class="dept-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.department || 'left' }">{{ item.department }}</span>
|
||
<span v-if="localDisplayConfig.individual?.showBonus" class="bonus-col" :style="{ textAlign: localDisplayConfig.individual?.columnAlignments?.bonus || 'left' }">¥{{ item.bonus }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 浮动倒计时组件 -->
|
||
<div class="timer-float glow-border" :style="{ right: '20px', top: '10px' }">
|
||
<span class="label">距离结束还有:</span>
|
||
<div class="countdown" style="display: flex; gap: 15px;">
|
||
<span class="time-item timer-number">{{ days }}天</span>
|
||
<span class="time-item timer-number">{{ hours }}时</span>
|
||
<span class="time-item timer-number">{{ minutes }}分</span>
|
||
<span class="time-item timer-number">{{ seconds }}秒</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 浮动管理员入口 -->
|
||
<div class="admin-entry-float">
|
||
<button @click="goToAdmin" class="btn-game-secondary">
|
||
🔐 管理员入口
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
|
||
import { ref, onBeforeMount, onMounted, onUnmounted, watch, computed, reactive, proxyRefs } from 'vue';
|
||
import { useRouter } from 'vue-router';
|
||
import {
|
||
individualRankings as importedIndividualRankings,
|
||
teamRankings as importedTeamRankings,
|
||
bonusRules,
|
||
displayConfig,
|
||
battleEndTime,
|
||
initializeData,
|
||
musicConfig as importedMusicConfig
|
||
} from '../data/mockData.js';
|
||
import { readConfig } from '../services/configService.js';
|
||
import { musicPlayer } from '../utils/musicPlayer';
|
||
|
||
// 创建默认显示配置的函数
|
||
function createDefaultDisplayConfig() {
|
||
return {
|
||
championLogos: {
|
||
teamChampion: '',
|
||
teamChampionSize: 60,
|
||
teamChampionType: 'avatar', // 'avatar' 或 'photo'
|
||
teamChampionPhotoWidth: 120,
|
||
teamChampionPhotoHeight: 80,
|
||
individualChampion: '',
|
||
individualChampionSize: 60
|
||
},
|
||
crownPosition: {
|
||
top: -100, // 皇冠位置的top值,默认-100px
|
||
left: null, // 皇冠位置的left值,默认null(使用居中)
|
||
right: null, // 皇冠位置的right值,默认null
|
||
bottom: null // 皇冠位置的bottom值,默认null
|
||
},
|
||
subtitleImage: {
|
||
src: '/completed_performance.png',
|
||
width: 200,
|
||
height: 60,
|
||
alt: '总战绩'
|
||
},
|
||
individual: {
|
||
scoreColumn: {
|
||
displayName: '业绩',
|
||
displayStyle: 'number'
|
||
},
|
||
teamColumn: {
|
||
displayName: '战区'
|
||
},
|
||
showLevel: true,
|
||
showDepartment: true,
|
||
showBonus: false,
|
||
showTeam: true, // 默认显示战区列
|
||
showAvatar: false, // 默认不显示头像列
|
||
defaultDisplayRows: 0, // 默认显示所有行
|
||
filterZeroScore: false, // 默认不过滤业绩为0的记录
|
||
columnWidths: {
|
||
team: 120 // 默认战区列宽
|
||
},
|
||
columnAlignments: {
|
||
rank: 'left',
|
||
name: 'left',
|
||
score: 'left',
|
||
level: 'left',
|
||
department: 'left',
|
||
team: 'left',
|
||
bonus: 'left'
|
||
}
|
||
},
|
||
team: {
|
||
totalScoreColumn: {
|
||
displayName: '战绩',
|
||
displayStyle: 'number'
|
||
},
|
||
showMemberCount: true,
|
||
showLeader: true,
|
||
showBonus: false,
|
||
defaultDisplayRows: 0, // 默认显示所有行
|
||
filterZeroScore: false, // 默认不过滤业绩为0的记录
|
||
columnWidths: {},
|
||
columnAlignments: {
|
||
rank: 'left',
|
||
name: 'left',
|
||
score: 'left',
|
||
memberCount: 'left',
|
||
leader: 'left',
|
||
bonus: 'left'
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
// 创建默认奖金规则的函数
|
||
function createDefaultBonusRules() {
|
||
return [
|
||
{ rank: '1-3', description: '前三名', individualBonus: '¥10000, ¥8000, ¥5000', teamBonus: '¥50000, ¥30000, ¥20000' },
|
||
{ rank: '4-10', description: '四至十名', individualBonus: '¥3000/人', teamBonus: '¥10000/队' },
|
||
{ rank: '11-20', description: '十一至二十名', individualBonus: '¥1000/人', teamBonus: '¥5000/队' }
|
||
];
|
||
}
|
||
|
||
// 初始化默认显示配置
|
||
const defaultDisplayConfig = createDefaultDisplayConfig();
|
||
|
||
// 深度合并配置,确保所有必要属性都存在
|
||
function mergeConfig(config1, config2) {
|
||
if (!config2) return config1;
|
||
const merged = { ...config1 };
|
||
for (const key in config2) {
|
||
if (config2.hasOwnProperty(key)) {
|
||
if (typeof config2[key] === 'object' && config2[key] !== null) {
|
||
merged[key] = mergeConfig(merged[key] || {}, config2[key]);
|
||
} else {
|
||
// 确保所有非对象类型的属性也被正确复制
|
||
merged[key] = config2[key];
|
||
}
|
||
}
|
||
}
|
||
return merged;
|
||
}
|
||
|
||
// 响应式数据 - 使用ref包装导入的数据,确保响应式更新
|
||
const individualRankings = ref(importedIndividualRankings || []);
|
||
const teamRankings = ref(importedTeamRankings || []);
|
||
|
||
// 计算属性 - 过滤后的个人排名数据
|
||
const filteredIndividualRankings = computed(() => {
|
||
let filtered = individualRankings.value;
|
||
// 如果配置了过滤业绩为0的记录
|
||
if (localDisplayConfig.value?.individual?.filterZeroScore) {
|
||
filtered = filtered.filter(item => item.score > 0);
|
||
}
|
||
return filtered;
|
||
});
|
||
|
||
// 计算属性 - 过滤后的战区排名数据
|
||
const filteredTeamRankings = computed(() => {
|
||
let filtered = teamRankings.value;
|
||
// 如果配置了过滤业绩为0的记录
|
||
if (localDisplayConfig.value?.team?.filterZeroScore) {
|
||
filtered = filtered.filter(item => item.totalScore > 0);
|
||
}
|
||
return filtered;
|
||
});
|
||
|
||
// 格式化数字为中国人习惯的金额表达方式(使用万分位分隔符)
|
||
function formatNumber(num) {
|
||
if (num === null || num === undefined || isNaN(num)) return '0';
|
||
const numStr = num.toString();
|
||
// 先处理小数部分
|
||
const parts = numStr.split('.');
|
||
let integerPart = parts[0];
|
||
const decimalPart = parts.length > 1 ? '.' + parts[1] : '';
|
||
|
||
// 对于整数部分,从右往左每四位添加一个逗号(万分位分隔)
|
||
const formattedInteger = integerPart.replace(/\B(?=(\d{4})+(?!\d))/g, ',');
|
||
|
||
return formattedInteger + decimalPart;
|
||
}
|
||
|
||
// 计算属性 - 所有战区业绩总和
|
||
const totalTeamScore = computed(() => {
|
||
const total = teamRankings.value.reduce((total, team) => {
|
||
return total + (team.totalScore || 0);
|
||
}, 0);
|
||
return formatNumber(total);
|
||
});
|
||
// 确保即使displayConfig存在,也要和默认配置合并,保证结构完整性
|
||
const localDisplayConfig = ref(() => {
|
||
if (displayConfig) {
|
||
const configCopy = JSON.parse(JSON.stringify(displayConfig));
|
||
const merged = mergeConfig(defaultDisplayConfig, configCopy);
|
||
|
||
// 确保所有必要属性都存在
|
||
if (!merged.individual) merged.individual = { ...defaultDisplayConfig.individual };
|
||
if (!merged.team) merged.team = { ...defaultDisplayConfig.team };
|
||
|
||
// 确保columnAlignments属性存在
|
||
if (!merged.individual.columnAlignments) {
|
||
merged.individual.columnAlignments = { ...defaultDisplayConfig.individual.columnAlignments };
|
||
}
|
||
if (!merged.team.columnAlignments) {
|
||
merged.team.columnAlignments = { ...defaultDisplayConfig.team.columnAlignments };
|
||
}
|
||
|
||
// 确保defaultDisplayRows属性存在
|
||
if (merged.individual.defaultDisplayRows === undefined) {
|
||
merged.individual.defaultDisplayRows = defaultDisplayConfig.individual.defaultDisplayRows;
|
||
}
|
||
if (merged.team.defaultDisplayRows === undefined) {
|
||
merged.team.defaultDisplayRows = defaultDisplayConfig.team.defaultDisplayRows;
|
||
}
|
||
|
||
return merged;
|
||
}
|
||
return defaultDisplayConfig;
|
||
});
|
||
const taskSettings = ref({
|
||
mainTitle: '3000万',
|
||
subtitle: '时间: 2025-11-12 - 2026-02-08'
|
||
});
|
||
|
||
|
||
const localMusicConfig = ref({
|
||
enabled: true,
|
||
filePath: ''
|
||
});
|
||
|
||
// 添加首次交互处理函数
|
||
const handleFirstInteraction = () => {
|
||
if (localMusicConfig.value.enabled) {
|
||
musicPlayer.play();
|
||
}
|
||
};
|
||
|
||
// 加载任务设置和初始化所有数据
|
||
onBeforeMount(async () => {
|
||
try {
|
||
// 首先初始化所有数据,确保从服务器获取最新配置
|
||
await initializeData();
|
||
|
||
// 然后重新获取最新的数据
|
||
const config = await readConfig();
|
||
if (config) {
|
||
// 更新任务设置
|
||
if (config.taskSettings) {
|
||
taskSettings.value = config.taskSettings;
|
||
}
|
||
|
||
// 直接从config中更新排名数据,确保使用最新的服务器数据
|
||
if (config.individualRankings && config.individualRankings.length > 0) {
|
||
individualRankings.value = config.individualRankings;
|
||
}
|
||
|
||
if (config.teamRankings && config.teamRankings.length > 0) {
|
||
teamRankings.value = config.teamRankings;
|
||
}
|
||
|
||
// 更新显示配置
|
||
if (config.displayConfig) {
|
||
const configCopy = JSON.parse(JSON.stringify(config.displayConfig));
|
||
localDisplayConfig.value = mergeConfig(defaultDisplayConfig, configCopy);
|
||
}
|
||
|
||
if (config.music) {
|
||
localMusicConfig.value = config.music;
|
||
}
|
||
|
||
|
||
}
|
||
} catch (error) {
|
||
console.error('加载数据失败:', error);
|
||
}
|
||
});
|
||
|
||
// 定义英雄排名表中每行默认高度
|
||
const tableIndividualTopThreeHeight = 3 * 47.5; // 前三名高度px
|
||
const tableIndividualRowHeight = 34.5; // 其他行高度px
|
||
const tableIndividualReserveHeight = 10; // 保留空间高度px
|
||
|
||
// 更新CSS变量,将默认显示行数传递给样式
|
||
watch(
|
||
() => localDisplayConfig.value?.individual?.defaultDisplayRows,
|
||
(newValue) => {
|
||
if (newValue && newValue > 0) {
|
||
const otherRowsHeight = (newValue - 3) * tableIndividualRowHeight;
|
||
const actualHeight = tableIndividualTopThreeHeight + otherRowsHeight + tableIndividualReserveHeight;
|
||
document.documentElement.style.setProperty('--individual-default-height', `${actualHeight}px`);
|
||
document.documentElement.style.setProperty('--individual-overflow-y', 'auto');
|
||
document.documentElement.style.setProperty('--individual-overflow-x', 'auto');
|
||
document.documentElement.style.setProperty('--individual-scroll-lock', '');
|
||
} else {
|
||
// 根据实际数据条数计算高度
|
||
const otherRowsHeight = (filteredIndividualRankings.value.length - 3) * tableIndividualRowHeight;
|
||
const actualHeight = tableIndividualTopThreeHeight + otherRowsHeight + tableIndividualReserveHeight;
|
||
document.documentElement.style.setProperty('--individual-default-height', `${actualHeight}px`);
|
||
document.documentElement.style.setProperty('--individual-overflow-y', 'hidden');
|
||
document.documentElement.style.setProperty('--individual-overflow-x', 'hidden');
|
||
document.documentElement.style.setProperty('--individual-scroll-lock', 'lock');
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
// 当英雄排名数据变化时,重新计算高度(如果当前是显示所有行模式)
|
||
watch(
|
||
() => filteredIndividualRankings.value.length,
|
||
() => {
|
||
console.log('filteredIndividualRankings.value.length', filteredIndividualRankings.value.length);
|
||
const displayRows = localDisplayConfig.value?.individual?.defaultDisplayRows;
|
||
if (!displayRows || displayRows === 0) {
|
||
// 根据实际数据条数计算高度
|
||
const otherRowsHeight = (filteredIndividualRankings.value.length - 3) * tableIndividualRowHeight;
|
||
const actualHeight = tableIndividualTopThreeHeight + otherRowsHeight + tableIndividualReserveHeight;
|
||
document.documentElement.style.setProperty('--individual-default-height', `${actualHeight}px`);
|
||
document.documentElement.style.setProperty('--individual-overflow-y', 'hidden');
|
||
document.documentElement.style.setProperty('--individual-overflow-x', 'hidden');
|
||
document.documentElement.style.setProperty('--individual-scroll-lock', 'lock');
|
||
}
|
||
}
|
||
);
|
||
|
||
// 定义战区排名表中每行默认高度
|
||
const tableTeamTopThreeHeight = 3 * 48; // 前三名高度px
|
||
const tableTeamRowHeight = 48; // 其他行高度px
|
||
const tableTeamReserveHeight = 20; // 保留空间高度px
|
||
|
||
// 添加监听以同步战区排名默认显示行数配置到CSS变量
|
||
watch(
|
||
() => localDisplayConfig.value?.team?.defaultDisplayRows,
|
||
(newValue) => {
|
||
if (newValue && newValue > 0) {
|
||
const otherRowsHeight = (newValue - 3) * tableTeamRowHeight;
|
||
const actualHeight = tableTeamTopThreeHeight + otherRowsHeight + tableTeamReserveHeight;
|
||
document.documentElement.style.setProperty('--team-default-height', `${actualHeight}px`);
|
||
document.documentElement.style.setProperty('--team-overflow-y', 'auto');
|
||
document.documentElement.style.setProperty('--team-overflow-x', 'auto');
|
||
document.documentElement.style.setProperty('--team-scroll-lock', '');
|
||
} else {
|
||
// 根据实际数据条数计算高度
|
||
const otherRowsHeight = (teamRankings.value.length - 3) * tableTeamRowHeight;
|
||
const actualHeight = tableTeamTopThreeHeight + otherRowsHeight + tableTeamReserveHeight;
|
||
document.documentElement.style.setProperty('--team-default-height', `${actualHeight}px`);
|
||
document.documentElement.style.setProperty('--team-overflow-y', 'hidden');
|
||
document.documentElement.style.setProperty('--team-overflow-x', 'hidden');
|
||
document.documentElement.style.setProperty('--team-scroll-lock', 'lock');
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
// 当战区数据变化时,重新计算高度(如果当前是显示所有行模式)
|
||
watch(
|
||
() => teamRankings.value.length,
|
||
() => {
|
||
const displayRows = localDisplayConfig.value?.team?.defaultDisplayRows;
|
||
if (!displayRows || displayRows === 0) {
|
||
// 根据实际数据条数计算高度
|
||
const otherRowsHeight = (teamRankings.value.length - 3) * tableTeamRowHeight;
|
||
const actualHeight = tableTeamTopThreeHeight + otherRowsHeight + tableTeamReserveHeight;
|
||
document.documentElement.style.setProperty('--team-default-height', `${actualHeight}px`);
|
||
document.documentElement.style.setProperty('--team-overflow-y', 'hidden');
|
||
document.documentElement.style.setProperty('--team-overflow-x', 'hidden');
|
||
document.documentElement.style.setProperty('--team-scroll-lock', 'lock');
|
||
}
|
||
}
|
||
);
|
||
|
||
// 监听冠军字体大小配置变化,更新CSS变量
|
||
watch(
|
||
() => localDisplayConfig.value?.championLogos,
|
||
(newConfig) => {
|
||
if (newConfig) {
|
||
// 设置战区冠军字体大小
|
||
if (newConfig.teamChampionFontSize) {
|
||
document.documentElement.style.setProperty('--team-champion-font-size', newConfig.teamChampionFontSize + 'rem');
|
||
}
|
||
// 设置英雄冠军字体大小
|
||
if (newConfig.individualChampionFontSize) {
|
||
document.documentElement.style.setProperty('--individual-champion-font-size', newConfig.individualChampionFontSize + 'rem');
|
||
}
|
||
}
|
||
},
|
||
{ immediate: true, deep: true }
|
||
);
|
||
|
||
// 监听皇冠位置配置变化,更新皇冠位置
|
||
watch(
|
||
() => localDisplayConfig.value?.crownPosition,
|
||
(newConfig) => {
|
||
if (newConfig) {
|
||
// 更新top值
|
||
if (newConfig.top !== null && newConfig.top !== undefined) {
|
||
document.documentElement.style.setProperty('--crown-top', newConfig.top + 'px');
|
||
} else {
|
||
document.documentElement.style.removeProperty('--crown-top');
|
||
}
|
||
|
||
// 更新left值
|
||
if (newConfig.left !== null && newConfig.left !== undefined) {
|
||
document.documentElement.style.setProperty('--crown-left', newConfig.left + 'px');
|
||
} else {
|
||
document.documentElement.style.removeProperty('--crown-left');
|
||
}
|
||
|
||
// 更新right值
|
||
if (newConfig.right !== null && newConfig.right !== undefined) {
|
||
document.documentElement.style.setProperty('--crown-right', newConfig.right + 'px');
|
||
} else {
|
||
document.documentElement.style.removeProperty('--crown-right');
|
||
}
|
||
|
||
// 更新bottom值
|
||
if (newConfig.bottom !== null && newConfig.bottom !== undefined) {
|
||
document.documentElement.style.setProperty('--crown-bottom', newConfig.bottom + 'px');
|
||
} else {
|
||
document.documentElement.style.removeProperty('--crown-bottom');
|
||
}
|
||
}
|
||
},
|
||
{ deep: true, immediate: true }
|
||
);
|
||
|
||
// 确保奖金规则有默认值
|
||
const displayBonusRules = computed(() => {
|
||
return Array.isArray(bonusRules) && bonusRules.length > 0
|
||
? bonusRules
|
||
: createDefaultBonusRules();
|
||
});
|
||
|
||
const router = useRouter();
|
||
|
||
// 计算英雄排名表格的列布局
|
||
const individualGridTemplate = computed(() => {
|
||
try {
|
||
const config = localDisplayConfig.value?.individual;
|
||
if (!config) return '60px 1fr 120px 80px 80px';
|
||
|
||
// 确保showTeam默认为true
|
||
if (config.showTeam === undefined) {
|
||
config.showTeam = true;
|
||
}
|
||
|
||
const widths = config.columnWidths || {};
|
||
const cols = [];
|
||
|
||
cols.push((widths.rank || 60) + 'px'); // 排名
|
||
|
||
// 头像列 - 根据配置决定是否显示
|
||
if (config.showAvatar) {
|
||
cols.push((widths.avatar || 60) + 'px'); // 头像
|
||
}
|
||
|
||
cols.push((widths.name === 1 || widths.name === '1') ? '1fr' : (widths.name || 120) + 'px'); // 姓名
|
||
|
||
// 战区列(在姓名列后面)
|
||
if (config.showTeam) {
|
||
cols.push((widths.team === 1 || widths.team === '1') ? '1fr' : (widths.team || 120) + 'px'); // 战区
|
||
}
|
||
|
||
cols.push((widths.score || 80) + 'px'); // 分数
|
||
|
||
if (config.showLevel) {
|
||
cols.push((widths.level || 80) + 'px'); // 等级
|
||
}
|
||
|
||
if (config.showDepartment) {
|
||
cols.push((widths.department === 1 || widths.department === '1') ? '1fr' : (widths.department || 100) + 'px'); // 部门
|
||
}
|
||
|
||
if (config.showBonus) {
|
||
cols.push((widths.bonus || 80) + 'px'); // 奖金
|
||
}
|
||
|
||
return cols.join(' ');
|
||
} catch (error) {
|
||
console.error('计算英雄排名表格布局出错:', error);
|
||
return '60px 1fr 120px 80px 80px'; // 兜底布局(不包含头像列)
|
||
}
|
||
});
|
||
|
||
// 计算战区排名表格的列布局
|
||
const teamGridTemplate = computed(() => {
|
||
try {
|
||
const config = localDisplayConfig.value?.team;
|
||
if (!config) return '60px 1fr 80px 80px';
|
||
|
||
const widths = config.columnWidths || {};
|
||
const cols = [];
|
||
|
||
cols.push((widths.rank || 60) + 'px'); // 排名
|
||
cols.push((widths.name === 1 || widths.name === '1') ? '1fr' : (widths.name || 150) + 'px'); // 战区名
|
||
cols.push((widths.score || 80) + 'px'); // 分数
|
||
|
||
if (config.showMemberCount) {
|
||
cols.push((widths.memberCount || 60) + 'px'); // 人数
|
||
}
|
||
|
||
if (config.showLeader) {
|
||
cols.push((widths.leader === 1 || widths.leader === '1') ? '1fr' : (widths.leader || 120) + 'px'); // 队长
|
||
}
|
||
|
||
if (config.showBonus) {
|
||
cols.push((widths.bonus || 80) + 'px'); // 奖金
|
||
}
|
||
|
||
return cols.join(' ');
|
||
} catch (error) {
|
||
console.error('计算战区排名表格布局出错:', error);
|
||
return '60px 1fr 80px 80px'; // 兜底布局
|
||
}
|
||
});
|
||
|
||
// 倒计时状态
|
||
const days = ref(0);
|
||
const hours = ref(0);
|
||
const minutes = ref(0);
|
||
const seconds = ref(0);
|
||
|
||
let countdownInterval = null;
|
||
// 倒计时位置状态已移除,直接在模板中使用固定位置
|
||
// 奖金设置模块位置状态 - 使用reactive存储实际定位值
|
||
const bonusPosition = reactive({ x: 'auto', y: 'auto' });
|
||
|
||
let isDragging = false;
|
||
let isBonusDragging = false;
|
||
let dragOffset = { x: 0, y: 0 };
|
||
let bonusDragOffset = { x: 0, y: 0 };
|
||
|
||
// 节流函数
|
||
function throttle(func, limit) {
|
||
let inThrottle;
|
||
return function () {
|
||
const args = arguments;
|
||
const context = this;
|
||
if (!inThrottle) {
|
||
func.apply(context, args);
|
||
inThrottle = true;
|
||
setTimeout(() => inThrottle = false, limit);
|
||
}
|
||
};
|
||
}
|
||
|
||
|
||
|
||
// 开始拖动奖金模块(鼠标事件)
|
||
const startBonusDrag = (e) => {
|
||
e.stopPropagation(); // 阻止事件冒泡
|
||
isBonusDragging = true;
|
||
// 计算鼠标相对于元素左上角的偏移量
|
||
const rect = e.currentTarget.getBoundingClientRect();
|
||
bonusDragOffset.x = e.clientX - rect.left;
|
||
bonusDragOffset.y = e.clientY - rect.top;
|
||
// 提高拖动时的性能,临时禁用动画效果
|
||
e.currentTarget.style.transition = 'none';
|
||
e.preventDefault();
|
||
};
|
||
|
||
// 开始拖动奖金模块(触摸事件)
|
||
const startBonusTouch = (e) => {
|
||
e.stopPropagation(); // 阻止事件冒泡
|
||
e.preventDefault(); // 阻止默认行为,如滚动
|
||
|
||
const touch = e.touches[0];
|
||
isBonusDragging = true;
|
||
|
||
// 计算触摸点相对于元素左上角的偏移量
|
||
const rect = e.currentTarget.getBoundingClientRect();
|
||
bonusDragOffset.x = touch.clientX - rect.left;
|
||
bonusDragOffset.y = touch.clientY - rect.top;
|
||
|
||
// 提高拖动时的性能,临时禁用动画效果
|
||
e.currentTarget.style.transition = 'none';
|
||
};
|
||
|
||
// 结束拖动(鼠标和触摸事件)
|
||
const endDrag = (e) => {
|
||
isDragging = false;
|
||
|
||
if (isBonusDragging) {
|
||
// 恢复动画效果
|
||
const bonusElement = document.querySelector('.bonus-section');
|
||
if (bonusElement) {
|
||
bonusElement.style.transition = '';
|
||
}
|
||
}
|
||
isBonusDragging = false;
|
||
};
|
||
|
||
// 结束触摸拖动
|
||
const endTouch = (e) => {
|
||
if (isBonusDragging) {
|
||
// 恢复动画效果
|
||
const bonusElement = document.querySelector('.bonus-section');
|
||
if (bonusElement) {
|
||
bonusElement.style.transition = '';
|
||
}
|
||
}
|
||
isBonusDragging = false;
|
||
};
|
||
|
||
// 优化的拖动函数 - 使用节流减少更新频率(鼠标事件)
|
||
const drag = throttle((e) => {
|
||
if (isDragging) {
|
||
drumsPosition.value.x = e.clientX - dragOffset.x;
|
||
drumsPosition.value.y = e.clientY - dragOffset.y;
|
||
}
|
||
if (isBonusDragging) {
|
||
// 计算新的位置
|
||
const newX = e.clientX - bonusDragOffset.x;
|
||
const newY = e.clientY - bonusDragOffset.y;
|
||
|
||
// 确保元素不会被拖出视口
|
||
const windowWidth = window.innerWidth;
|
||
const windowHeight = window.innerHeight;
|
||
const element = document.querySelector('.bonus-section');
|
||
|
||
if (element) {
|
||
const elementWidth = element.offsetWidth;
|
||
const elementHeight = element.offsetHeight;
|
||
|
||
// 限制在视口内,添加一些边距
|
||
const limitedX = Math.max(10, Math.min(newX, windowWidth - elementWidth - 10));
|
||
const limitedY = Math.max(10, Math.min(newY, windowHeight - elementHeight - 10));
|
||
|
||
// 使用优化的更新函数更新奖金模块位置
|
||
requestAnimationFrame(() => {
|
||
bonusPosition.x = limitedX;
|
||
bonusPosition.y = limitedY;
|
||
// 直接设置元素样式确保实时更新
|
||
element.style.left = `${limitedX}px`;
|
||
element.style.top = `${limitedY}px`;
|
||
element.style.right = 'auto';
|
||
element.style.bottom = 'auto';
|
||
});
|
||
}
|
||
}
|
||
}, 10); // 10ms节流,约100FPS
|
||
|
||
// 优化的触摸拖动函数 - 使用节流减少更新频率
|
||
const touchMove = throttle((e) => {
|
||
if (isBonusDragging) {
|
||
e.preventDefault(); // 阻止页面滚动
|
||
|
||
const touch = e.touches[0];
|
||
// 计算新的位置
|
||
const newX = touch.clientX - bonusDragOffset.x;
|
||
const newY = touch.clientY - bonusDragOffset.y;
|
||
|
||
// 确保元素不会被拖出视口
|
||
const windowWidth = window.innerWidth;
|
||
const windowHeight = window.innerHeight;
|
||
const element = document.querySelector('.bonus-section');
|
||
|
||
if (element) {
|
||
const elementWidth = element.offsetWidth;
|
||
const elementHeight = element.offsetHeight;
|
||
|
||
// 限制在视口内,添加一些边距
|
||
const limitedX = Math.max(10, Math.min(newX, windowWidth - elementWidth - 10));
|
||
const limitedY = Math.max(10, Math.min(newY, windowHeight - elementHeight - 10));
|
||
|
||
// 使用优化的更新函数更新奖金模块位置
|
||
requestAnimationFrame(() => {
|
||
bonusPosition.x = limitedX;
|
||
bonusPosition.y = limitedY;
|
||
// 直接设置元素样式确保实时更新
|
||
element.style.left = `${limitedX}px`;
|
||
element.style.top = `${limitedY}px`;
|
||
element.style.right = 'auto';
|
||
element.style.bottom = 'auto';
|
||
});
|
||
}
|
||
}
|
||
}, 10); // 10ms节流,约100FPS
|
||
|
||
// 计算倒计时
|
||
const calculateCountdown = () => {
|
||
// 使用配置的结束时间
|
||
const endDateStr = `${battleEndTime.date}T${battleEndTime.time}`;
|
||
const endDate = new Date(endDateStr).getTime();
|
||
const now = new Date().getTime();
|
||
const distance = endDate - now;
|
||
|
||
if (distance > 0) {
|
||
days.value = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||
hours.value = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||
minutes.value = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||
seconds.value = Math.floor((distance % (1000 * 60)) / 1000);
|
||
}
|
||
};
|
||
|
||
// 跳转到管理员页面
|
||
const goToAdmin = () => {
|
||
router.push('/admin');
|
||
};
|
||
|
||
const handleResize = () => {
|
||
// 计算并设置排名明细区域的最小高度,使其底部与视口对齐
|
||
const rankingsSection = document.querySelector('.rankings-section');
|
||
if (rankingsSection) {
|
||
const windowHeight = window.innerHeight;
|
||
const rankingsTop = rankingsSection.offsetTop;
|
||
const rankingsMinHeight = windowHeight - rankingsTop - 20; // 减去一些边距
|
||
if (rankingsMinHeight > 0) {
|
||
rankingsSection.style.minHeight = rankingsMinHeight + 'px';
|
||
}
|
||
}
|
||
};
|
||
|
||
onMounted(async () => {
|
||
try {
|
||
// 异步初始化数据
|
||
await initializeData();
|
||
if (localMusicConfig.value.enabled) {
|
||
musicPlayer.initMusicConfig(localMusicConfig.value.filePath, localMusicConfig.value.enabled);
|
||
// 注意:由于浏览器自动播放策略限制,这里不直接调用play()
|
||
// 而是等待用户的第一次交互(点击)后再播放
|
||
console.log("音乐已准备就绪,等待用户首次交互后播放...");
|
||
} else {
|
||
musicPlayer.pause();
|
||
}
|
||
// 更新本地显示配置,确保columnAlignments属性存在
|
||
if (displayConfig) {
|
||
const configCopy = JSON.parse(JSON.stringify(displayConfig));
|
||
const defaultConfig = createDefaultDisplayConfig();
|
||
const merged = mergeConfig(defaultConfig, configCopy);
|
||
|
||
// 确保columnAlignments属性存在
|
||
if (!merged.individual.columnAlignments) {
|
||
merged.individual.columnAlignments = { ...defaultConfig.individual.columnAlignments };
|
||
}
|
||
if (!merged.team.columnAlignments) {
|
||
merged.team.columnAlignments = { ...defaultConfig.team.columnAlignments };
|
||
}
|
||
|
||
localDisplayConfig.value = merged;
|
||
} else {
|
||
localDisplayConfig.value = createDefaultDisplayConfig();
|
||
}
|
||
} catch (error) {
|
||
console.error('初始化数据失败:', error);
|
||
// 使用默认配置
|
||
localDisplayConfig.value = createDefaultDisplayConfig();
|
||
}
|
||
|
||
calculateCountdown();
|
||
countdownInterval = setInterval(calculateCountdown, 10); // 改为10ms更新一次以显示毫秒
|
||
// 监听窗口大小变化,确保排名明细与底部对齐
|
||
window.addEventListener('resize', handleResize);
|
||
handleResize(); // 初始调整
|
||
|
||
// 添加拖放相关的事件监听
|
||
document.addEventListener('mousemove', drag);
|
||
document.addEventListener('mouseup', endDrag);
|
||
|
||
// 添加触摸事件监听
|
||
document.addEventListener('touchmove', touchMove, { passive: false });
|
||
document.addEventListener('touchend', endTouch);
|
||
document.addEventListener('touchcancel', endTouch);
|
||
});
|
||
|
||
// 监听结束时间变化(在真实环境中,可能需要通过props或store来监听)
|
||
const handleBattleEndTimeChange = () => {
|
||
calculateCountdown();
|
||
};
|
||
|
||
// 监听显示配置变化(在真实环境中,可能需要通过props或store来监听)
|
||
const handleDisplayConfigChange = () => {
|
||
// 更新本地配置
|
||
localDisplayConfig.value = { ...displayConfig };
|
||
};
|
||
|
||
// 这里模拟监听配置变化
|
||
// 在实际项目中,可能需要通过WebSocket或轮询来更新配置
|
||
|
||
onUnmounted(() => {
|
||
// 强制暂停音乐
|
||
musicPlayer.pause();
|
||
musicPlayer.setMuted(true);
|
||
|
||
if (countdownInterval) clearInterval(countdownInterval);
|
||
window.removeEventListener('resize', handleResize);
|
||
|
||
// 移除拖放相关的事件监听
|
||
document.removeEventListener('mousemove', drag);
|
||
document.removeEventListener('mouseup', endDrag);
|
||
|
||
// 移除触摸事件监听
|
||
document.removeEventListener('touchmove', touchMove);
|
||
document.removeEventListener('touchend', endTouch);
|
||
document.removeEventListener('touchcancel', endTouch);
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@keyframes crownFloat {
|
||
0% {
|
||
transform: translateY(0px) rotate(0deg);
|
||
}
|
||
50% {
|
||
transform: translateY(-5px) rotate(2deg);
|
||
}
|
||
100% {
|
||
transform: translateY(0px) rotate(0deg);
|
||
}
|
||
}
|
||
.avatar-image-champion {
|
||
object-fit: cover;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
/* 冠军模块样式 */
|
||
.champion-section {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 20px;
|
||
gap: 20px;
|
||
}
|
||
|
||
.team-champion,
|
||
.individual-champion {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
padding: 15px;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.team-logo {
|
||
font-size: 0;
|
||
margin-bottom: 0;
|
||
display: inline-block;
|
||
color: gold;
|
||
}
|
||
|
||
.individual-avatar {
|
||
font-size: 2rem;
|
||
margin-bottom: 5px;
|
||
display: inline-block;
|
||
}
|
||
|
||
/* 冠军头像容器 */
|
||
.champion-container {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
|
||
/* 皇冠动画效果 */
|
||
.crown-animation {
|
||
position: absolute;
|
||
left: var(--crown-left, 50%);
|
||
right: var(--crown-right, auto);
|
||
top: var(--crown-top, -100px);
|
||
bottom: var(--crown-bottom, auto);
|
||
transform: var(--crown-left, translateX(-50%));
|
||
z-index: 10;
|
||
text-shadow: 0 0 10px var(--gold-primary), 0 0 20px var(--gold-secondary);
|
||
}
|
||
|
||
.crown-animation-run {
|
||
animation: crownFloat 2s ease-in-out infinite, crownGlow 3s ease-in-out infinite;
|
||
}
|
||
|
||
/* 皇冠浮动动画 */
|
||
@keyframes crownFloat {
|
||
0% {
|
||
transform: translateX(-50%) translateY(0) rotate(-10deg);
|
||
}
|
||
50% {
|
||
transform: translateX(-50%) translateY(-5px) rotate(10deg);
|
||
}
|
||
100% {
|
||
transform: translateX(-50%) translateY(0) rotate(-10deg);
|
||
}
|
||
}
|
||
|
||
/* 皇冠发光效果动画 */
|
||
@keyframes crownGlow {
|
||
0%, 100% {
|
||
text-shadow: 0 0 10px var(--gold-primary), 0 0 20px var(--gold-secondary);
|
||
}
|
||
50% {
|
||
text-shadow: 0 0 15px var(--gold-primary), 0 0 30px var(--gold-secondary), 0 0 40px var(--gold-tertiary);
|
||
}
|
||
}
|
||
|
||
|
||
@keyframes crownGlow {
|
||
0%, 100% {
|
||
text-shadow: 0 0 10px var(--gold-primary), 0 0 20px var(--gold-secondary);
|
||
}
|
||
50% {
|
||
text-shadow: 0 0 15px var(--gold-primary), 0 0 30px var(--gold-secondary), 0 0 40px rgba(255, 215, 0, 0.5);
|
||
}
|
||
}
|
||
|
||
.champion-logo {
|
||
object-fit: cover;
|
||
max-width: 120px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.photo-container .champion-logo {
|
||
max-width: unset !important;
|
||
border-radius: 0 !important;
|
||
}
|
||
|
||
|
||
.avatar-image {
|
||
width: 30px;
|
||
height: 30px;
|
||
object-fit: cover;
|
||
vertical-align: middle;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.champion-title {
|
||
font-size: 0.9rem;
|
||
color: #999;
|
||
margin-bottom: 3px;
|
||
}
|
||
|
||
.champion-name {
|
||
font-size: var(--individual-champion-font-size, 1.8rem);
|
||
font-weight: bold;
|
||
color: gold;
|
||
}
|
||
|
||
/* 战区冠军名称特殊样式 */
|
||
.team-champion .champion-name {
|
||
font-size: var(--team-champion-font-size, 1.8rem);
|
||
}
|
||
|
||
/* 基础样式 */
|
||
:root {
|
||
--gold-primary: #ffd700;
|
||
--gold-secondary: #ffed4a;
|
||
--purple-primary: #6c5ce7;
|
||
--purple-secondary: #a29bfe;
|
||
}
|
||
|
||
|
||
/* 主题容器样式 - 添加居中对齐 */
|
||
.theme-container {
|
||
text-align: center;
|
||
}
|
||
|
||
.bai-day-battle {
|
||
width: 1200px;
|
||
}
|
||
|
||
/* Banner图片样式 - 居中显示 */
|
||
.banner-image {
|
||
max-width: 90%;
|
||
height: auto;
|
||
display: inline-block;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.bonus-section {
|
||
position: fixed;
|
||
cursor: move;
|
||
transition: transform 0.2s ease;
|
||
z-index: 9999; /* 设置最高层级,确保在最上层显示 */
|
||
}
|
||
|
||
/* 奖金图片容器样式 - Flex布局居中且保持一行 */
|
||
.bonus-awards-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 5px;
|
||
flex-wrap: nowrap;
|
||
}
|
||
|
||
/* 奖金图片样式 */
|
||
.award-image {
|
||
width: auto;
|
||
height: 120px;
|
||
/* border-radius: 8px; */
|
||
/* box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); */
|
||
/* transition: transform 0.2s ease, box-shadow 0.2s ease; */
|
||
}
|
||
|
||
.award-image:hover {
|
||
transform: translateY(-5px);
|
||
/* box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15); */
|
||
}
|
||
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
|
||
.total-score-total-image {
|
||
width: 340px !important; /* 调整总战绩图片大小,覆盖内联样式 */
|
||
}
|
||
|
||
/* 移动端总战绩金额字体调小 */
|
||
.total-score-total-value {
|
||
font-size: 5rem !important; /* 调小总战绩金额字体 */
|
||
margin-top: -40px !important; /* 调整与图片的间距 */
|
||
}
|
||
|
||
.team-rankings-propagation-image {
|
||
width: 200px !important; /* 覆盖内联样式 */
|
||
}
|
||
|
||
.individual-rankings-propagation-image {
|
||
width: 200px !important; /* 覆盖内联样式 */
|
||
}
|
||
|
||
/* 战区排名宣传语容器调整 */
|
||
.team-rankings-propagation {
|
||
position: relative;
|
||
z-index: 5; /* 提高z-index避免被其他元素遮挡 */
|
||
margin-bottom: 70px; /* 进一步增大战区冠军的间距 */
|
||
}
|
||
|
||
/* 英雄排名宣传语容器调整 */
|
||
.individual-rankings-propagation {
|
||
position: relative;
|
||
z-index: 5; /* 提高z-index避免被其他元素遮挡 */
|
||
margin-bottom: 10px; /* 减小英雄榜虎狼之师图片与个人英雄图片的距离 */
|
||
}
|
||
|
||
/* 移动端战区冠军布局调整,与个人英雄冠军保持一致 */
|
||
.team-champion {
|
||
margin-bottom: 30px; /* 增加与下方战区排名标题的间距 */
|
||
padding: 10px; /* 调整内边距 */
|
||
min-height: 120px; /* 确保与英雄冠军有相同的视觉权重 */
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 移动端英雄冠军布局调整 */
|
||
.individual-champion {
|
||
margin-bottom: -10px; /* 恢复为修改之前的间距 */
|
||
padding: 10px; /* 与战区冠军保持一致的内边距 */
|
||
min-height: 120px; /* 确保与战区冠军有相同的视觉权重 */
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 确保两个排名区域在移动端有相同的起始位置 */
|
||
.team-rankings,
|
||
.individual-rankings {
|
||
position: relative;
|
||
z-index: 2; /* 统一的层级 */
|
||
padding-top: 10px; /* 统一的顶部内边距 */
|
||
}
|
||
|
||
/* 战区和英雄排名容器在移动端的统一样式 */
|
||
.team-rankings-container,
|
||
.individual-rankings-container {
|
||
margin-top: 20px; /* 与上方冠军图片的统一间距 */
|
||
}
|
||
|
||
/* 隐藏倒计时模块 */
|
||
.timer-float {
|
||
display: none !important;
|
||
}
|
||
|
||
/* 隐藏管理员入口 */
|
||
.admin-entry-float {
|
||
display: none !important;
|
||
}
|
||
|
||
/* 奖金模块垂直居中显示,两侧20px间距 */
|
||
.bonus-section {
|
||
/* 背景全部取消设置 **/
|
||
background: none !important;
|
||
|
||
position: static !important;
|
||
margin: 20px auto;
|
||
width: calc(100% - 40px);
|
||
max-width: none;
|
||
left: 0 !important;
|
||
right: 0 !important;
|
||
top: 0 !important;
|
||
bottom: 0 !important;
|
||
}
|
||
|
||
/* 保留响应式中的padding设置,但移除其他可能冲突的位置样式 */
|
||
.bonus-section {
|
||
padding: 8px; /* 减小padding */
|
||
}
|
||
|
||
.bonus-awards-container {
|
||
gap: 10px;
|
||
scale: 0.8;
|
||
}
|
||
|
||
/* 确保图片容器有足够的显示空间 */
|
||
.team-rankings, .individual-rankings {
|
||
position: relative;
|
||
z-index: 2; /* 确保排名区域在奖金模块之上 */
|
||
}
|
||
|
||
.timer-float {
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.timer-float .countdown {
|
||
gap: 8px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.banner-image {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.award-image {
|
||
max-width: 100%;
|
||
}
|
||
|
||
.timer-float {
|
||
font-size: 0.8rem;
|
||
}
|
||
}
|
||
|
||
/* 浮动倒计时样式 - 科技感 */
|
||
.timer-float {
|
||
position: absolute;
|
||
background: linear-gradient(135deg, rgba(23, 25, 35, 0.95), rgba(23, 25, 35, 0.85));
|
||
padding: 15px 20px;
|
||
border-radius: 12px;
|
||
z-index: 950;
|
||
cursor: move;
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid #3a3f51;
|
||
box-shadow:
|
||
0 0 15px rgba(0, 255, 255, 0.3),
|
||
inset 0 0 10px rgba(0, 255, 255, 0.1);
|
||
animation: borderPulse 3s infinite alternate;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.timer-float:hover {
|
||
transform: scale(1.05);
|
||
box-shadow:
|
||
0 0 25px rgba(0, 255, 255, 0.5),
|
||
inset 0 0 15px rgba(0, 255, 255, 0.2);
|
||
}
|
||
|
||
@keyframes borderPulse {
|
||
0% {
|
||
box-shadow:
|
||
0 0 10px rgba(0, 255, 255, 0.2),
|
||
inset 0 0 5px rgba(0, 255, 255, 0.1);
|
||
}
|
||
|
||
100% {
|
||
box-shadow:
|
||
0 0 20px rgba(0, 255, 255, 0.5),
|
||
inset 0 0 15px rgba(0, 255, 255, 0.3);
|
||
}
|
||
}
|
||
|
||
.card-game {
|
||
/* 半透明背景,增强层次感 */
|
||
background: transparent;
|
||
/* padding: 20px;
|
||
margin-bottom: 30px; */
|
||
/* 强化阴影效果 */
|
||
border: 0;
|
||
}
|
||
|
||
|
||
|
||
/* 主题部分 */
|
||
.theme-section {
|
||
background: transparent;
|
||
text-align: center;
|
||
}
|
||
|
||
.main-title {
|
||
font-size: 2.5rem;
|
||
color: var(--gold-primary);
|
||
margin-bottom: 8px;
|
||
text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
|
||
font-weight: bold;
|
||
letter-spacing: 2px;
|
||
}
|
||
|
||
.subtitle {
|
||
font-size: 1.2rem;
|
||
color: #fff;
|
||
margin-bottom: 20px;
|
||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.countdown {
|
||
font-size: 1.2rem;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.timer {
|
||
display: inline-block;
|
||
background: linear-gradient(45deg, #6c5ce7, #a29bfe);
|
||
color: white;
|
||
padding: 12px 25px;
|
||
border-radius: 50px;
|
||
font-weight: bold;
|
||
margin-bottom: 14px;
|
||
/* 下移4px */
|
||
}
|
||
|
||
/* 科技感倒计时标签 */
|
||
.timer-float .label {
|
||
color: #00e5ff;
|
||
font-family: 'Courier New', monospace;
|
||
font-weight: bold;
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
text-shadow: 0 0 5px rgba(0, 229, 255, 0.7);
|
||
display: block;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
/* 科技感时间项 */
|
||
.time-item {
|
||
background: linear-gradient(135deg, #1a1d2e, #2d3748);
|
||
padding: 8px 12px;
|
||
border-radius: 8px;
|
||
margin: 0 5px;
|
||
font-size: 1.3rem;
|
||
font-family: 'Courier New', monospace;
|
||
font-weight: bold;
|
||
color: #00e5ff;
|
||
text-shadow: 0 0 10px rgba(0, 229, 255, 0.8);
|
||
border: 1px solid #00e5ff;
|
||
box-shadow:
|
||
0 0 10px rgba(0, 229, 255, 0.3),
|
||
inset 0 0 5px rgba(0, 229, 255, 0.2);
|
||
transition: all 0.2s ease;
|
||
min-width: 60px;
|
||
text-align: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.time-item::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, rgba(0, 229, 255, 0.2), transparent);
|
||
animation: shine 2s infinite;
|
||
}
|
||
|
||
.time-item:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow:
|
||
0 0 15px rgba(0, 229, 255, 0.5),
|
||
inset 0 0 10px rgba(0, 229, 255, 0.3);
|
||
}
|
||
|
||
.time-item.milliseconds {
|
||
font-size: 1rem;
|
||
color: #ff3d00;
|
||
border-color: #ff3d00;
|
||
text-shadow: 0 0 10px rgba(255, 61, 0, 0.8);
|
||
animation: pulse 1s infinite alternate;
|
||
}
|
||
|
||
.time-item.milliseconds::before {
|
||
background: linear-gradient(90deg, transparent, rgba(255, 61, 0, 0.2), transparent);
|
||
}
|
||
|
||
@keyframes shine {
|
||
100% {
|
||
left: 100%;
|
||
}
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% {
|
||
box-shadow:
|
||
0 0 10px rgba(255, 61, 0, 0.3),
|
||
inset 0 0 5px rgba(255, 61, 0, 0.2);
|
||
}
|
||
|
||
100% {
|
||
box-shadow:
|
||
0 0 15px rgba(255, 61, 0, 0.6),
|
||
inset 0 0 10px rgba(255, 61, 0, 0.4);
|
||
}
|
||
}
|
||
|
||
/* 毫秒闪烁动画增强紧张感 */
|
||
@keyframes blink {
|
||
|
||
0%,
|
||
50% {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
|
||
51%,
|
||
100% {
|
||
opacity: 0.7;
|
||
transform: scale(0.95);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/* 按钮样式 */
|
||
.btn-game-secondary {
|
||
background: linear-gradient(45deg, #6c5ce7, #a29bfe);
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 20px;
|
||
border-radius: 30px;
|
||
font-size: 1rem;
|
||
cursor: pointer;
|
||
box-shadow: 0 4px 20px rgba(108, 92, 231, 0.4);
|
||
transition: all 0.3s ease;
|
||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.btn-game-secondary:hover {
|
||
transform: scale(1.1) translateY(-2px);
|
||
box-shadow: 0 6px 30px rgba(108, 92, 231, 0.6);
|
||
background: linear-gradient(45deg, #7f7fd5, #86a8e7);
|
||
}
|
||
|
||
/* 排名部分 */
|
||
.rankings-section {
|
||
margin: 0 20px 30px 20px;
|
||
}
|
||
|
||
.rankings-container {
|
||
display: flex;
|
||
gap: 15px;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
background: none;
|
||
border: none;
|
||
}
|
||
|
||
.individual-rankings,
|
||
.team-rankings {
|
||
flex: 1;
|
||
min-width: 350px;
|
||
max-width: 550px;
|
||
}
|
||
|
||
/* 为指定的容器添加背景和边框 */
|
||
.team-rankings-container,
|
||
.individual-rankings-container {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border-radius: 15px;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
backdrop-filter: blur(10px);
|
||
border: 2px solid rgba(255, 215, 0, 0.5);
|
||
padding: 15px;
|
||
}
|
||
|
||
.section-title {
|
||
color: #d63031;
|
||
text-align: center;
|
||
margin-bottom: 15px;
|
||
font-size: 1.6rem;
|
||
}
|
||
|
||
.task-settings-section {
|
||
margin-top: -220px;
|
||
}
|
||
|
||
.task-title-container {
|
||
padding: 30px 40px;
|
||
text-align: center;
|
||
}
|
||
|
||
.task-title-container .game-title {
|
||
color: #ffffff;
|
||
font-size: 2.5rem;
|
||
font-weight: bold;
|
||
margin: 0 0 15px 0;
|
||
animation: glow-pulse 2s infinite alternate;
|
||
}
|
||
|
||
.task-title-container .game-title .game-title-highlight {
|
||
font-size: 3.5rem;
|
||
}
|
||
|
||
.task-title-container .game-subtitle {
|
||
color: #ffffff;
|
||
font-size: 1.5rem;
|
||
margin: 0;
|
||
}
|
||
|
||
@keyframes glow-pulse {
|
||
0% {
|
||
text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
100% {
|
||
text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.2), 0 0 20px rgba(255, 255, 255, 0.8);
|
||
}
|
||
}
|
||
|
||
.rank-table {
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
overflow-y: auto;
|
||
position: relative;
|
||
margin-top: 0.8rem;
|
||
max-height: 420px;
|
||
// 只对左侧战区的.rank-table生效(通过父容器限定)
|
||
.team-rankings-container & {
|
||
-ms-overflow-style: none; /* IE/Edge 隐藏 */
|
||
scrollbar-width: none; /* Firefox 隐藏 */
|
||
}
|
||
// Chrome/Safari 隐藏左侧滚动条(伪元素必须单独写)
|
||
.team-rankings-container &::-webkit-scrollbar {
|
||
display: none !important;
|
||
width: 0 !important;
|
||
}
|
||
|
||
// ========== 新增:右侧英雄排名滚动条保留原样 ==========
|
||
.individual-rankings-container & {
|
||
-ms-overflow-style: auto; /* 恢复IE/Edge默认 */
|
||
scrollbar-width: auto; /* 恢复Firefox默认 */
|
||
}
|
||
// Chrome/Safari 恢复右侧滚动条
|
||
.individual-rankings-container &::-webkit-scrollbar {
|
||
display: block !important;
|
||
width: 6px !important; // 恢复默认滚动条宽度
|
||
}
|
||
|
||
}
|
||
|
||
.table-header {
|
||
background: linear-gradient(45deg, #6c5ce7, #a29bfe);
|
||
color: white;
|
||
display: grid;
|
||
padding: 12px 10px;
|
||
font-weight: bold;
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
/* 增强标题可读性 */
|
||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.team-rankings .table-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
}
|
||
|
||
.table-row {
|
||
display: grid;
|
||
padding: 12px 10px;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||
transition: all 0.3s ease;
|
||
/* 浅色背景增强可读性 */
|
||
background: rgba(255, 255, 255, 0.9);
|
||
color: #333;
|
||
}
|
||
|
||
.team-rankings .table-row {
|
||
padding: 12px 10px;
|
||
}
|
||
|
||
.table-row:hover {
|
||
background-color: rgba(255, 255, 255, 0.95);
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.table-row.top-three {
|
||
background-color: rgba(255, 243, 205, 0.95);
|
||
font-size: 1.1rem;
|
||
font-weight: bold;
|
||
color: #000;
|
||
transform: scale(1.02);
|
||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2);
|
||
transition: all 0.3s ease;
|
||
z-index: 2;
|
||
position: relative;
|
||
}
|
||
|
||
.table-row.top-three:hover {
|
||
transform: scale(1.03);
|
||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
/* 前三名特殊背景色,增强亮度和对比度 - 确保英雄排名和战区排名样式一致 */
|
||
.team-rankings-container .table-row:nth-child(1),
|
||
.individual-rankings-container .table-row:nth-child(1) {
|
||
background: linear-gradient(135deg, #ffd700, #403f3c);
|
||
color: #333;
|
||
box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4);
|
||
}
|
||
|
||
.team-rankings-container .table-row:nth-child(2),
|
||
.individual-rankings-container .table-row:nth-child(2) {
|
||
background: linear-gradient(135deg, #c0c0c0, #e0e0e0);
|
||
color: #333;
|
||
box-shadow: 0 6px 20px rgba(192, 192, 192, 0.4);
|
||
}
|
||
|
||
.team-rankings-container .table-row:nth-child(3),
|
||
.individual-rankings-container .table-row:nth-child(3) {
|
||
background: linear-gradient(135deg, #cd7f32, #d7ccc8);
|
||
color: #333;
|
||
box-shadow: 0 6px 20px rgba(205, 127, 50, 0.4);
|
||
}
|
||
|
||
.table-row.highlight {
|
||
background: linear-gradient(135deg, #ffd32a, #ff7979);
|
||
}
|
||
|
||
.level-SSS {
|
||
color: #ffd700;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.level-SS {
|
||
color: #c0c0c0;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.level-S {
|
||
color: #cd7f32;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.level-A {
|
||
color: #4caf50;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.level-B {
|
||
color: #2196f3;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 浮动管理员入口 */
|
||
.admin-entry-float {
|
||
position: fixed;
|
||
bottom: 20px;
|
||
left: 20px;
|
||
z-index: 1000;
|
||
}
|
||
|
||
/* 管理员按钮使用通用按钮样式 */
|
||
.admin-entry-float .btn-game-secondary {
|
||
font-size: 0.8rem;
|
||
padding: 8px 16px;
|
||
min-width: 80px;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
/* 针对高度大于1080分辨率的精确优化 */
|
||
|
||
|
||
/* 移动端背景图片设置 - 全局样式 */
|
||
/* 总战绩部分样式 */
|
||
.total-score-section {
|
||
margin: 20px auto;
|
||
max-width: 1200px;
|
||
padding: 20px;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
animation: fadeIn 0.5s ease-in-out;
|
||
}
|
||
|
||
.total-score-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 15px;
|
||
}
|
||
|
||
/* 移除空的total-score-content规则集以避免SCSS警告 */
|
||
|
||
|
||
.total-score-item {
|
||
display: flex;
|
||
justify-content: center; /* 水平居中 */
|
||
align-items: center; /* 垂直居中 */
|
||
padding: 10px;
|
||
min-height: 60px; /* 确保有足够的高度来展示垂直居中效果 */
|
||
}
|
||
|
||
.score-value {
|
||
font-size: calc(var(--individual-champion-font-size, 6rem) * 2);
|
||
font-weight: bold;
|
||
color: #fff2c4;
|
||
text-shadow: 0 0 10px rgba(0, 0, 0, .8), 0 0 20px rgb(16 16 16 / 30%), 1px 1px 2px rgba(0, 0, 0, .8);
|
||
}
|
||
|
||
.total-score-total-value {
|
||
margin-top: -40px;
|
||
}
|
||
|
||
/* 战区冠军分数特殊样式 */
|
||
.team-champion .score-value {
|
||
font-size: calc(var(--team-champion-font-size, 1.8rem) * 4);
|
||
text-shadow:
|
||
0 0 15px rgba(255, 215, 0, 0.7),
|
||
0 0 30px rgba(255, 215, 0, 0.4),
|
||
2px 2px 3px rgba(0, 0, 0, 0.9);
|
||
}
|
||
|
||
/* 照片容器样式 */
|
||
.team-logo.photo-container {
|
||
overflow: hidden;
|
||
margin-top: -97px;
|
||
}
|
||
|
||
.individual-champion {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 20px;
|
||
gap: 30px;
|
||
}
|
||
|
||
.team-rankings-propagation {
|
||
align-items: center;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.individual-rankings-propagation {
|
||
align-items: center;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
|
||
.total-score-total-title {
|
||
align-items: center;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 战区排名容器设置 - 根据配置决定显示行数和滚动行为 */
|
||
.team-rankings-container .rank-table {
|
||
position: relative;
|
||
min-height: auto;
|
||
/* 移动端强制显示所有行,覆盖JS动态设置的CSS变量 */
|
||
height: auto !important;
|
||
max-height: none !important;
|
||
overflow-y: visible !important;
|
||
overflow-x: auto !important;
|
||
/* 强制覆盖CSS变量 */
|
||
--team-default-height: auto !important;
|
||
--team-overflow-y: visible !important;
|
||
--team-overflow-x: auto !important;
|
||
}
|
||
|
||
/* 移动端战区排名显示所有内容,不受滚动锁定影响 */
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .rank-table {
|
||
overflow-y: visible !important;
|
||
overflow-x: auto !important;
|
||
height: auto !important;
|
||
min-width: auto !important;
|
||
width: 100% !important;
|
||
}
|
||
|
||
/* 确保表格内容在移动端正确显示 */
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .rank-table .table-header,
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .rank-table .table-row {
|
||
min-width: auto !important;
|
||
width: 100% !important;
|
||
overflow-x: visible !important;
|
||
white-space: nowrap !important;
|
||
}
|
||
|
||
.individual-rankings-propagation {
|
||
margin-top: -40px;
|
||
padding-bottom: 10px;
|
||
margin-bottom: 20px; /* 恢复为修改之前的间距 */
|
||
}
|
||
|
||
.individual-rankings {
|
||
margin-top: 60px; /* 增加排名列表的顶部间距 */
|
||
}
|
||
|
||
/* 移动端战区排名容器位置调整 */
|
||
.team-rankings {
|
||
margin-top: 0; /* 确保与英雄排名区域在统一水平线 */
|
||
}
|
||
|
||
/* 英雄排名容器设置 - 根据配置决定显示行数和滚动行为 */
|
||
.individual-rankings-container .rank-table {
|
||
position: relative;
|
||
min-height: auto;
|
||
/* 移动端强制显示所有行,覆盖JS动态设置的CSS变量 */
|
||
height: auto !important;
|
||
max-height: none !important;
|
||
overflow-y: visible !important;
|
||
overflow-x: auto !important;
|
||
/* 隐藏滚动条 */
|
||
-ms-overflow-style: none;
|
||
scrollbar-width: none;
|
||
/* 强制覆盖CSS变量 */
|
||
--individual-default-height: auto !important;
|
||
--individual-overflow-y: visible !important;
|
||
--individual-overflow-x: auto !important;
|
||
}
|
||
|
||
/* 移动端英雄排名显示所有内容,不受滚动锁定影响 */
|
||
:root[style*="--individual-scroll-lock: lock"] .individual-rankings-container .rank-table {
|
||
overflow-y: visible !important;
|
||
overflow-x: auto !important;
|
||
height: auto !important;
|
||
min-width: auto !important;
|
||
width: 100% !important;
|
||
}
|
||
|
||
/* 确保表格内容在移动端正确显示 */
|
||
:root[style*="--individual-scroll-lock: lock"] .individual-rankings-container .rank-table .table-header,
|
||
:root[style*="--individual-scroll-lock: lock"] .individual-rankings-container .rank-table .table-row {
|
||
min-width: auto !important;
|
||
width: 100% !important;
|
||
overflow-x: visible !important;
|
||
white-space: nowrap !important;
|
||
}
|
||
|
||
/* 移动端非前三名字体放大 */
|
||
.team-rankings-container .table-row:not(:nth-child(1)):not(:nth-child(2)):not(:nth-child(3)),
|
||
.individual-rankings-container .table-row:not(:nth-child(1)):not(:nth-child(2)):not(:nth-child(3)) {
|
||
font-size: 1.1rem;
|
||
}
|
||
|
||
/* 移动端名次列水平垂直居中 */
|
||
.team-rankings-container .table-header > :first-child,
|
||
.individual-rankings-container .table-header > :first-child,
|
||
.team-rankings-container .table-row > :first-child,
|
||
.individual-rankings-container .table-row > :first-child {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 确保前三名特殊样式在移动端正确显示 */
|
||
.team-rankings-container .table-row.top-three,
|
||
.individual-rankings-container .table-row.top-three {
|
||
transform: scale(1);
|
||
box-shadow: none;
|
||
position: static;
|
||
}
|
||
|
||
.team-rankings-container .table-row:nth-child(1),
|
||
.team-rankings-container .table-row:nth-child(2),
|
||
.team-rankings-container .table-row:nth-child(3),
|
||
.individual-rankings-container .table-row:nth-child(1),
|
||
.individual-rankings-container .table-row:nth-child(2),
|
||
.individual-rankings-container .table-row:nth-child(3) {
|
||
box-shadow: none;
|
||
z-index: 1;
|
||
}
|
||
|
||
/* 当设置为禁止滚动时,确保战区排名容器不允许滚动 */
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container {
|
||
overflow: visible !important;
|
||
height: auto !important;
|
||
}
|
||
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .rank-table {
|
||
overflow: hidden !important;
|
||
display: block;
|
||
min-width: auto !important;
|
||
width: 100% !important;
|
||
}
|
||
|
||
/* 确保表格头部和行在禁止滚动模式下能够完整显示内容 */
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .table-header,
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .table-row {
|
||
min-width: auto !important;
|
||
width: 100% !important;
|
||
overflow-x: visible !important;
|
||
white-space: normal !important;
|
||
}
|
||
|
||
/* 英雄排名列表隐藏水平滚动条 */
|
||
.individual-rankings-container .rank-table::-webkit-scrollbar {
|
||
width: 6px; /* 保留垂直滚动条 */
|
||
height: 0; /* 隐藏水平滚动条 */
|
||
}
|
||
|
||
/* 移除原有卡片背景,让内容在背景图上显示 */
|
||
.card-game {
|
||
background: transparent;
|
||
box-shadow: none;
|
||
}
|
||
|
||
/* 主题部分调整 */
|
||
.theme-section {
|
||
width: 100%;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.banner-image {
|
||
width: 100%;
|
||
height: auto;
|
||
}
|
||
|
||
|
||
|
||
/* 2. 倒计时模块调整 - 移至冠军战区上方,缩小时间显示为一行 */
|
||
.timer-float {
|
||
position: relative;
|
||
right: auto;
|
||
top: auto;
|
||
margin: 10px auto;
|
||
width: 95%;
|
||
padding: 8px;
|
||
border-radius: 8px;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
color: white;
|
||
text-align: center;
|
||
}
|
||
|
||
.timer-float .label {
|
||
font-size: 0.9rem;
|
||
display: block;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.countdown {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 8px;
|
||
flex-wrap: nowrap;
|
||
}
|
||
|
||
.time-item {
|
||
font-size: 0.85rem;
|
||
padding: 4px 6px;
|
||
background: rgba(255, 215, 0, 0.2);
|
||
border-radius: 4px;
|
||
border: 1px solid rgba(255, 215, 0, 0.5);
|
||
}
|
||
|
||
/* 任务设置调整 */
|
||
.task-settings-section {
|
||
margin-top: -100px;
|
||
/* 调整负边距 */
|
||
}
|
||
|
||
.task-title-container {
|
||
padding: 15px;
|
||
}
|
||
|
||
.task-title-container .game-title {
|
||
font-size: 1.6rem;
|
||
}
|
||
|
||
.task-title-container .game-title-highlight {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.task-title-container .game-subtitle {
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* 排名部分调整 */
|
||
.rankings-section {
|
||
margin: 0 10px 20px 10px;
|
||
}
|
||
|
||
.rankings-container {
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
}
|
||
|
||
.individual-rankings,
|
||
.team-rankings {
|
||
min-width: auto;
|
||
width: 100%;
|
||
/* 调整顺序,确保倒计时在冠军上方 */
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 将倒计时移动到冠军上方的位置 */
|
||
.team-rankings {
|
||
order: -1;
|
||
}
|
||
|
||
.team-rankings-container,
|
||
.individual-rankings-container {
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
}
|
||
|
||
/* 当设置为禁止滚动时,确保战区排名容器不允许滚动 */
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container {
|
||
overflow: visible !important;
|
||
height: auto !important;
|
||
}
|
||
|
||
:root[style*="--team-scroll-lock: lock"] .team-rankings-container .rank-table {
|
||
overflow: hidden !important;
|
||
white-space: nowrap;
|
||
display: block;
|
||
}
|
||
|
||
/* 表格调整 */
|
||
.rank-table {
|
||
min-height: 250px;
|
||
/* 移除最大高度限制,允许显示所有行 */
|
||
overflow-x: hidden;
|
||
/* 禁止横向滚动 */
|
||
overflow-y: auto;
|
||
/* 允许纵向滚动 */
|
||
/* 隐藏移动端滚动条 */
|
||
-ms-overflow-style: none;
|
||
scrollbar-width: none;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 隐藏WebKit浏览器移动端滚动条 */
|
||
.rank-table::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
/* 英雄排名列表设置 - 根据配置决定显示行数和滚动行为 */
|
||
.individual-rankings-container .rank-table {
|
||
overflow-x: hidden !important;
|
||
/* 禁止横向滚动 */
|
||
height: var(--individual-default-height, auto) !important;
|
||
overflow-y: var(--individual-overflow-y, auto) !important;
|
||
/* 确保英雄排名列表隐藏滚动条 */
|
||
-ms-overflow-style: none;
|
||
scrollbar-width: none;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 当设置了滚动锁定时,禁止所有滚动 */
|
||
:root[style*="--individual-scroll-lock: lock"] .individual-rankings-container {
|
||
overflow: visible !important;
|
||
height: auto !important;
|
||
}
|
||
|
||
:root[style*="--individual-scroll-lock: lock"] .individual-rankings-container .rank-table {
|
||
overflow: hidden !important;
|
||
white-space: nowrap;
|
||
display: block;
|
||
}
|
||
|
||
.individual-rankings-container .rank-table::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
.table-header {
|
||
font-size: 1rem;
|
||
padding: 8px 6px;
|
||
min-width: 500px;
|
||
/* 固定表头,防止滚动时移动 */
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
background-color: rgba(255, 255, 255, 0.95);
|
||
}
|
||
|
||
.table-row {
|
||
font-size: 0.9rem;
|
||
padding: 8px 6px;
|
||
min-width: 500px;
|
||
/* 确保行内容不会被截断 */
|
||
overflow: visible;
|
||
}
|
||
|
||
/* 冠军部分调整 */
|
||
.team-champion,
|
||
.individual-champion {
|
||
margin: 5px 0;
|
||
}
|
||
|
||
/* 管理员入口调整 */
|
||
.admin-entry-float {
|
||
position: relative;
|
||
top: auto;
|
||
right: auto;
|
||
margin: 10px;
|
||
text-align: center;
|
||
}
|
||
|
||
.btn-game-secondary {
|
||
padding: 10px 15px;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
/* 3. 奖金模块调整 - 移至底部显示 */
|
||
.bonus-section {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
width: 100%;
|
||
margin: 0;
|
||
padding: 10px;
|
||
z-index: 1000;
|
||
transform: translateY(0);
|
||
transition: transform 0.3s ease;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.bonus-awards-container {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
}
|
||
|
||
.award-image {
|
||
height: 120px;
|
||
width: auto;
|
||
}
|
||
|
||
/* 确保重要内容优先显示 */
|
||
.rank-col,
|
||
.name-col,
|
||
.score-col {
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 为底部奖金模块留出空间 */
|
||
.admin-entry-float {
|
||
margin-bottom: 100px;
|
||
}
|
||
|
||
/* 针对极小屏幕的特殊处理 */
|
||
@media (max-width: 480px) {
|
||
.table-header {
|
||
font-size: 0.9rem;
|
||
padding: 8px 6px;
|
||
min-width: 450px;
|
||
}
|
||
|
||
.table-row {
|
||
min-width: 450px;
|
||
font-size: 0.75rem;
|
||
padding: 6px 4px;
|
||
}
|
||
|
||
.game-title {
|
||
font-size: 1.4rem;
|
||
}
|
||
|
||
.game-title-highlight {
|
||
font-size: 1.7rem;
|
||
}
|
||
|
||
.award-image {
|
||
height: 120px;
|
||
}
|
||
|
||
.countdown {
|
||
gap: 6px;
|
||
}
|
||
|
||
.time-item {
|
||
font-size: 0.8rem;
|
||
padding: 3px 5px;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 触摸设备优化 */
|
||
@media (hover: none) and (pointer: coarse) {
|
||
|
||
/* 增大点击区域 */
|
||
.btn-game-secondary {
|
||
padding: 12px 24px;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* 移除hover效果,添加触摸反馈 */
|
||
.table-row:active {
|
||
background-color: rgba(255, 255, 255, 0.95);
|
||
transform: scale(1.01);
|
||
}
|
||
|
||
.btn-game-secondary:active {
|
||
transform: scale(0.98);
|
||
}
|
||
}
|
||
|
||
/* 响应式设计,1200px以上显示 */
|
||
@media (min-width: 1920px) {
|
||
.bonus-section {
|
||
top: 360px;
|
||
left: 320px;
|
||
}
|
||
}
|
||
|
||
|
||
@media (min-width: 2000px) {
|
||
.bonus-section {
|
||
position: fixed;
|
||
top: 360px;
|
||
left: 720px;
|
||
z-index: 9999; /* 设置最高层级,确保在最上层显示 */
|
||
cursor: move;
|
||
transition: transform 0.2s ease;
|
||
}
|
||
}
|
||
.team-rankings-container .rank-table {
|
||
-ms-overflow-style: none !important;
|
||
scrollbar-width: none !important;
|
||
}
|
||
.team-rankings-container .rank-table::-webkit-scrollbar {
|
||
display: none !important;
|
||
width: 0 !important;
|
||
}
|
||
</style> |