1045 lines
34 KiB
HTML
1045 lines
34 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||
<meta name="theme-color" content="#1a1a2e">
|
||
<title>深空战机 - 排行榜</title>
|
||
|
||
<!-- PWA Manifest -->
|
||
<link rel="manifest" href="data:application/json;base64,ewogICJuYW1lIjogIuaViuepuuaImOacuiAtIOaImOaWl+eVjOmdoiIsCiAgInNob3J0X25hbWUiOiAi5rex56m65oiY5py6IiwKICAic3RhcnRfdXJsIjogIi4vIiwKICAiZGlzcGxheSI6ICJzdGFuZGFsb25lIiwKICAiYmFja2dyb3VuZF9jb2xvciI6ICIjMWExYTJlIiwKICAidGhlbWVfY29sb3IiOiAiIzQwZTBkMCIsCiAgImljb25zIjogW10KfQ==">
|
||
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
-webkit-user-select: none;
|
||
-webkit-touch-callout: none;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
|
||
html, body {
|
||
height: 100%;
|
||
overflow: hidden;
|
||
position: fixed;
|
||
width: 100%;
|
||
}
|
||
|
||
body {
|
||
font-family: 'PingFang SC', 'Helvetica Neue', 'Arial', sans-serif;
|
||
background: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 30%, #16213e 70%, #0f3460 100%);
|
||
color: #ffffff;
|
||
position: relative;
|
||
touch-action: manipulation;
|
||
}
|
||
|
||
/* 动态星空背景 */
|
||
.star-field {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.star {
|
||
position: absolute;
|
||
background: rgba(64, 224, 208, 0.8);
|
||
border-radius: 50%;
|
||
animation: twinkle 3s infinite;
|
||
}
|
||
|
||
@keyframes twinkle {
|
||
0%, 100% { opacity: 0.3; transform: scale(1); }
|
||
50% { opacity: 1; transform: scale(1.2); }
|
||
}
|
||
|
||
/* 安全区域适配 */
|
||
.safe-area {
|
||
padding-top: env(safe-area-inset-top);
|
||
padding-left: env(safe-area-inset-left);
|
||
padding-right: env(safe-area-inset-right);
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
}
|
||
|
||
/* 移动端导航栏 */
|
||
.mobile-nav {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: calc(60px + env(safe-area-inset-top));
|
||
background: linear-gradient(180deg, rgba(26, 26, 46, 0.95) 0%, rgba(26, 26, 46, 0.8) 100%);
|
||
backdrop-filter: blur(15px);
|
||
border-bottom: 1px solid rgba(64, 224, 208, 0.3);
|
||
z-index: 100;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
padding: 0 15px 8px;
|
||
}
|
||
|
||
.nav-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
width: 100%;
|
||
height: 44px;
|
||
}
|
||
|
||
.back-btn {
|
||
background: none;
|
||
border: none;
|
||
color: #40e0d0;
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
padding: 8px 12px;
|
||
border-radius: 12px;
|
||
transition: all 0.3s ease;
|
||
touch-action: manipulation;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
min-height: 44px;
|
||
}
|
||
|
||
.back-btn:active {
|
||
background: rgba(64, 224, 208, 0.1);
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.nav-title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #40e0d0;
|
||
text-shadow: 0 0 10px rgba(64, 224, 208, 0.3);
|
||
}
|
||
|
||
.refresh-btn {
|
||
background: linear-gradient(135deg, #40e0d0 0%, #26d0ce 100%);
|
||
border: none;
|
||
color: #1a1a2e;
|
||
padding: 8px 16px;
|
||
border-radius: 20px;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
touch-action: manipulation;
|
||
min-height: 44px;
|
||
box-shadow: 0 4px 15px rgba(64, 224, 208, 0.3);
|
||
}
|
||
|
||
.refresh-btn:active {
|
||
transform: translateY(1px);
|
||
box-shadow: 0 2px 8px rgba(64, 224, 208, 0.4);
|
||
}
|
||
|
||
.refresh-btn:disabled {
|
||
opacity: 0.7;
|
||
transform: none !important;
|
||
}
|
||
|
||
/* 主内容容器 */
|
||
.main-container {
|
||
position: absolute;
|
||
top: calc(60px + env(safe-area-inset-top));
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
overflow-y: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
z-index: 10;
|
||
}
|
||
|
||
.main-content {
|
||
padding: 20px 15px;
|
||
max-width: 400px;
|
||
margin: 0 auto;
|
||
min-height: 100%;
|
||
}
|
||
|
||
/* 分类标签 */
|
||
.category-tabs {
|
||
display: flex;
|
||
gap: 8px;
|
||
margin-bottom: 20px;
|
||
background: rgba(22, 33, 62, 0.8);
|
||
border-radius: 25px;
|
||
padding: 6px;
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid rgba(64, 224, 208, 0.2);
|
||
}
|
||
|
||
.tab-btn {
|
||
flex: 1;
|
||
padding: 12px 16px;
|
||
background: none;
|
||
border: none;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
border-radius: 20px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
touch-action: manipulation;
|
||
min-height: 44px;
|
||
}
|
||
|
||
.tab-btn.active {
|
||
background: linear-gradient(135deg, #40e0d0 0%, #26d0ce 100%);
|
||
color: #1a1a2e;
|
||
box-shadow: 0 2px 10px rgba(64, 224, 208, 0.3);
|
||
}
|
||
|
||
.tab-btn:not(.active):active {
|
||
background: rgba(64, 224, 208, 0.1);
|
||
color: #40e0d0;
|
||
}
|
||
|
||
/* 我的排名卡片 */
|
||
.my-rank-card {
|
||
background: linear-gradient(135deg, #40e0d0 0%, #26d0ce 100%);
|
||
border-radius: 20px;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
color: #1a1a2e;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
box-shadow: 0 8px 32px rgba(64, 224, 208, 0.4);
|
||
}
|
||
|
||
.my-rank-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: -50%;
|
||
right: -30%;
|
||
width: 120px;
|
||
height: 120px;
|
||
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
|
||
border-radius: 50%;
|
||
animation: cardShimmer 3s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes cardShimmer {
|
||
0%, 100% { opacity: 0.5; transform: scale(1); }
|
||
50% { opacity: 0.8; transform: scale(1.1); }
|
||
}
|
||
|
||
.my-avatar {
|
||
width: 60px;
|
||
height: 60px;
|
||
border-radius: 50%;
|
||
background: rgba(26, 26, 46, 0.3);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #40e0d0;
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
border: 3px solid rgba(26, 26, 46, 0.2);
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
.my-info {
|
||
flex: 1;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
.my-name {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.my-stats {
|
||
font-size: 13px;
|
||
opacity: 0.8;
|
||
display: flex;
|
||
gap: 15px;
|
||
}
|
||
|
||
.stat-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.stat-value {
|
||
font-weight: bold;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 11px;
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.my-rank-number {
|
||
font-size: 36px;
|
||
font-weight: bold;
|
||
position: relative;
|
||
z-index: 1;
|
||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
/* 排行榜容器 */
|
||
.leaderboard {
|
||
background: rgba(22, 33, 62, 0.8);
|
||
border-radius: 20px;
|
||
padding: 20px 16px;
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid rgba(64, 224, 208, 0.3);
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.rank-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 15px 8px;
|
||
border-bottom: 1px solid rgba(64, 224, 208, 0.1);
|
||
transition: all 0.3s ease;
|
||
position: relative;
|
||
border-radius: 12px;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.rank-item:last-child {
|
||
border-bottom: none;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.rank-item:active {
|
||
background: rgba(64, 224, 208, 0.1);
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
.rank-number {
|
||
width: 40px;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #40e0d0;
|
||
text-align: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.rank-number.first {
|
||
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
font-size: 20px;
|
||
text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
|
||
}
|
||
|
||
.rank-number.second {
|
||
background: linear-gradient(135deg, #c0c0c0 0%, #e8e8e8 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
font-size: 18px;
|
||
}
|
||
|
||
.rank-number.third {
|
||
background: linear-gradient(135deg, #cd7f32 0%, #deb887 100%);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
font-size: 17px;
|
||
}
|
||
|
||
.player-avatar {
|
||
width: 44px;
|
||
height: 44px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, #6c5ce7 0%, #a29bfe 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: white;
|
||
font-weight: bold;
|
||
margin: 0 12px;
|
||
font-size: 14px;
|
||
flex-shrink: 0;
|
||
border: 2px solid rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.player-info {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.player-name {
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
color: #ffffff;
|
||
margin-bottom: 4px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.player-level {
|
||
font-size: 12px;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
.player-stats {
|
||
text-align: right;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.win-rate {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #40e0d0;
|
||
margin-bottom: 2px;
|
||
text-shadow: 0 0 8px rgba(64, 224, 208, 0.3);
|
||
}
|
||
|
||
.total-games {
|
||
font-size: 11px;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
/* 奖杯图标 */
|
||
.trophy-icon {
|
||
position: absolute;
|
||
right: 8px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
font-size: 20px;
|
||
opacity: 0;
|
||
transition: all 0.3s ease;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.rank-item:active .trophy-icon {
|
||
opacity: 0.8;
|
||
transform: translateY(-50%) scale(1.2);
|
||
}
|
||
|
||
/* 加载状态 */
|
||
.loading {
|
||
text-align: center;
|
||
padding: 40px 20px;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
.loading-spinner {
|
||
width: 40px;
|
||
height: 40px;
|
||
border: 3px solid rgba(64, 224, 208, 0.2);
|
||
border-left: 3px solid #40e0d0;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
margin: 0 auto 15px;
|
||
}
|
||
|
||
@keyframes spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
|
||
/* 空状态 */
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: 60px 20px;
|
||
color: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
.empty-icon {
|
||
font-size: 48px;
|
||
margin-bottom: 15px;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 网络状态指示器 */
|
||
.network-status {
|
||
position: fixed;
|
||
top: calc(15px + env(safe-area-inset-top));
|
||
right: 15px;
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
background: #28a745;
|
||
z-index: 101;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.network-status.offline {
|
||
background: #dc3545;
|
||
animation: networkPulse 2s infinite;
|
||
}
|
||
|
||
@keyframes networkPulse {
|
||
0%, 100% { opacity: 0.8; }
|
||
50% { opacity: 0.3; }
|
||
}
|
||
|
||
/* Toast消息 */
|
||
.toast {
|
||
position: fixed;
|
||
top: calc(80px + env(safe-area-inset-top));
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: rgba(64, 224, 208, 0.9);
|
||
color: #1a1a2e;
|
||
padding: 12px 20px;
|
||
border-radius: 25px;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
z-index: 1000;
|
||
backdrop-filter: blur(10px);
|
||
box-shadow: 0 8px 32px rgba(64, 224, 208, 0.3);
|
||
}
|
||
|
||
.toast.show {
|
||
animation: toastShow 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
}
|
||
|
||
.toast.hide {
|
||
animation: toastHide 0.3s ease-out;
|
||
}
|
||
|
||
@keyframes toastShow {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateX(-50%) translateY(-20px) scale(0.8);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateX(-50%) translateY(0) scale(1);
|
||
}
|
||
}
|
||
|
||
@keyframes toastHide {
|
||
0% {
|
||
opacity: 1;
|
||
transform: translateX(-50%) translateY(0) scale(1);
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
transform: translateX(-50%) translateY(-20px) scale(0.8);
|
||
}
|
||
}
|
||
|
||
/* 更新动画 */
|
||
.updating {
|
||
animation: pulse 1.5s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% { opacity: 1; }
|
||
50% { opacity: 0.7; }
|
||
100% { opacity: 1; }
|
||
}
|
||
|
||
/* 页面进入动画 */
|
||
.main-content {
|
||
animation: slideInUp 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||
}
|
||
|
||
@keyframes slideInUp {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(30px);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
/* 排行榜项目依次出现动画 */
|
||
.rank-item {
|
||
animation: fadeInUp 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) backwards;
|
||
}
|
||
|
||
.rank-item:nth-child(1) { animation-delay: 0.1s; }
|
||
.rank-item:nth-child(2) { animation-delay: 0.15s; }
|
||
.rank-item:nth-child(3) { animation-delay: 0.2s; }
|
||
.rank-item:nth-child(4) { animation-delay: 0.25s; }
|
||
.rank-item:nth-child(5) { animation-delay: 0.3s; }
|
||
.rank-item:nth-child(6) { animation-delay: 0.35s; }
|
||
.rank-item:nth-child(7) { animation-delay: 0.4s; }
|
||
.rank-item:nth-child(8) { animation-delay: 0.45s; }
|
||
.rank-item:nth-child(9) { animation-delay: 0.5s; }
|
||
.rank-item:nth-child(10) { animation-delay: 0.55s; }
|
||
|
||
@keyframes fadeInUp {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(15px);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
/* 触觉反馈模拟 */
|
||
.haptic-feedback {
|
||
animation: hapticVibrate 0.1s ease-out;
|
||
}
|
||
|
||
@keyframes hapticVibrate {
|
||
0%, 100% { transform: translateX(0); }
|
||
25% { transform: translateX(-1px); }
|
||
75% { transform: translateX(1px); }
|
||
}
|
||
|
||
/* 响应式适配 */
|
||
@media (max-width: 375px) {
|
||
.my-rank-card {
|
||
padding: 16px;
|
||
gap: 12px;
|
||
}
|
||
|
||
.my-avatar {
|
||
width: 50px;
|
||
height: 50px;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.my-name {
|
||
font-size: 16px;
|
||
}
|
||
|
||
.my-rank-number {
|
||
font-size: 32px;
|
||
}
|
||
|
||
.rank-item {
|
||
padding: 12px 6px;
|
||
}
|
||
|
||
.player-avatar {
|
||
width: 40px;
|
||
height: 40px;
|
||
margin: 0 10px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.player-name {
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
|
||
@media (max-height: 667px) {
|
||
.main-content {
|
||
padding: 15px;
|
||
}
|
||
|
||
.my-rank-card {
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.category-tabs {
|
||
margin-bottom: 15px;
|
||
}
|
||
}
|
||
|
||
/* 横屏模式适配 */
|
||
@media (orientation: landscape) and (max-height: 500px) {
|
||
.my-rank-card {
|
||
padding: 12px 16px;
|
||
gap: 10px;
|
||
}
|
||
|
||
.my-avatar {
|
||
width: 50px;
|
||
height: 50px;
|
||
}
|
||
|
||
.my-rank-number {
|
||
font-size: 28px;
|
||
}
|
||
|
||
.rank-item {
|
||
padding: 10px 6px;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body class="safe-area">
|
||
<!-- 动态星空背景 -->
|
||
<div class="star-field" id="starField"></div>
|
||
|
||
<!-- 网络状态指示器 -->
|
||
<div class="network-status" id="networkStatus"></div>
|
||
|
||
<!-- 移动端导航栏 -->
|
||
<div class="mobile-nav">
|
||
<div class="nav-content">
|
||
<button class="back-btn" onclick="goBack()">
|
||
← 返回
|
||
</button>
|
||
<div class="nav-title">排行榜</div>
|
||
<button class="refresh-btn" onclick="refreshLeaderboard()" id="refreshBtn">
|
||
刷新
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主内容容器 -->
|
||
<div class="main-container">
|
||
<div class="main-content">
|
||
<!-- 分类标签 -->
|
||
<div class="category-tabs">
|
||
<button class="tab-btn active" data-category="overall">总排行</button>
|
||
<button class="tab-btn" data-category="weekly">本周</button>
|
||
<button class="tab-btn" data-category="daily">今日</button>
|
||
</div>
|
||
|
||
<!-- 我的排名卡片 -->
|
||
<div class="my-rank-card">
|
||
<div class="my-avatar">我</div>
|
||
<div class="my-info">
|
||
<div class="my-name">深空战机指挥官</div>
|
||
<div class="my-stats">
|
||
<div class="stat-item">
|
||
<div class="stat-value">68%</div>
|
||
<div class="stat-label">胜率</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">156</div>
|
||
<div class="stat-label">总局数</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">15</div>
|
||
<div class="stat-label">等级</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="my-rank-number" id="myRank">15</div>
|
||
</div>
|
||
|
||
<!-- 排行榜列表 -->
|
||
<div class="leaderboard" id="leaderboard">
|
||
<!-- 通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 排行榜数据
|
||
const leaderboardData = {
|
||
overall: [
|
||
{ id: 1, name: '深空霸主', level: 25, winRate: 89, totalGames: 234, avatar: '霸' },
|
||
{ id: 2, name: '战机猎手', level: 23, winRate: 85, totalGames: 198, avatar: '猎' },
|
||
{ id: 3, name: '银河司令', level: 22, winRate: 82, totalGames: 176, avatar: '司' },
|
||
{ id: 4, name: '星际战神', level: 21, winRate: 79, totalGames: 165, avatar: '神' },
|
||
{ id: 5, name: '虚空之王', level: 20, winRate: 77, totalGames: 152, avatar: '王' },
|
||
{ id: 6, name: '量子战士', level: 19, winRate: 75, totalGames: 143, avatar: '量' },
|
||
{ id: 7, name: '暗物质', level: 18, winRate: 73, totalGames: 134, avatar: '暗' },
|
||
{ id: 8, name: '星云舰长', level: 17, winRate: 71, totalGames: 128, avatar: '星' },
|
||
{ id: 9, name: '光速飞行', level: 16, winRate: 69, totalGames: 119, avatar: '光' },
|
||
{ id: 10, name: '时空旅者', level: 15, winRate: 68, totalGames: 112, avatar: '时' }
|
||
],
|
||
weekly: [
|
||
{ id: 1, name: '本周新星', level: 18, winRate: 92, totalGames: 25, avatar: '星' },
|
||
{ id: 2, name: '周末战神', level: 20, winRate: 88, totalGames: 32, avatar: '神' },
|
||
{ id: 3, name: '快速崛起', level: 16, winRate: 85, totalGames: 27, avatar: '崛' },
|
||
{ id: 4, name: '战术新人', level: 14, winRate: 81, totalGames: 21, avatar: '新' },
|
||
{ id: 5, name: '深空霸主', level: 25, winRate: 78, totalGames: 45, avatar: '霸' }
|
||
],
|
||
daily: [
|
||
{ id: 1, name: '今日冠军', level: 15, winRate: 100, totalGames: 8, avatar: '冠' },
|
||
{ id: 2, name: '连胜达人', level: 17, winRate: 95, totalGames: 12, avatar: '连' },
|
||
{ id: 3, name: '精准打击', level: 19, winRate: 90, totalGames: 10, avatar: '精' },
|
||
{ id: 4, name: '战术高手', level: 16, winRate: 87, totalGames: 15, avatar: '高' },
|
||
{ id: 5, name: '银河司令', level: 18, winRate: 83, totalGames: 18, avatar: '司' }
|
||
]
|
||
};
|
||
|
||
let currentCategory = 'overall';
|
||
let isLoading = false;
|
||
let isOnline = navigator.onLine;
|
||
|
||
// 应用初始化
|
||
function initApp() {
|
||
createStarField();
|
||
setupNetworkMonitoring();
|
||
setupTabs();
|
||
renderLeaderboard(currentCategory);
|
||
registerServiceWorker();
|
||
}
|
||
|
||
// 创建动态星空
|
||
function createStarField() {
|
||
const starField = document.getElementById('starField');
|
||
const numStars = 50;
|
||
|
||
for (let i = 0; i < numStars; i++) {
|
||
const star = document.createElement('div');
|
||
star.className = 'star';
|
||
star.style.width = Math.random() * 3 + 'px';
|
||
star.style.height = star.style.width;
|
||
star.style.left = Math.random() * 100 + '%';
|
||
star.style.top = Math.random() * 100 + '%';
|
||
star.style.animationDelay = Math.random() * 3 + 's';
|
||
starField.appendChild(star);
|
||
}
|
||
}
|
||
|
||
// 网络状态监控
|
||
function setupNetworkMonitoring() {
|
||
const networkStatus = document.getElementById('networkStatus');
|
||
|
||
function updateNetworkStatus() {
|
||
isOnline = navigator.onLine;
|
||
networkStatus.className = isOnline ? 'network-status' : 'network-status offline';
|
||
}
|
||
|
||
window.addEventListener('online', updateNetworkStatus);
|
||
window.addEventListener('offline', updateNetworkStatus);
|
||
updateNetworkStatus();
|
||
}
|
||
|
||
// 注册Service Worker
|
||
function registerServiceWorker() {
|
||
if ('serviceWorker' in navigator) {
|
||
navigator.serviceWorker.register('data:text/javascript;base64,c2VsZi5hZGRFdmVudExpc3RlbmVyKCdpbnN0YWxsJywgZXZlbnQgPT4geyBzZWxmLnNraXBXYWl0aW5nKCk7IH0pOw==')
|
||
.catch(() => console.log('Service Worker注册失败'));
|
||
}
|
||
}
|
||
|
||
// 触觉反馈
|
||
function triggerHapticFeedback(type = 'light') {
|
||
if ('vibrate' in navigator) {
|
||
const patterns = {
|
||
light: [10],
|
||
medium: [20],
|
||
heavy: [30],
|
||
success: [10, 50, 10],
|
||
error: [50, 100, 50]
|
||
};
|
||
navigator.vibrate(patterns[type] || patterns.light);
|
||
}
|
||
|
||
// 视觉反馈
|
||
document.body.classList.add('haptic-feedback');
|
||
setTimeout(() => document.body.classList.remove('haptic-feedback'), 100);
|
||
}
|
||
|
||
// 设置标签切换
|
||
function setupTabs() {
|
||
document.querySelectorAll('.tab-btn').forEach(btn => {
|
||
btn.addEventListener('click', function() {
|
||
if (this.dataset.category === currentCategory || isLoading) return;
|
||
|
||
triggerHapticFeedback('light');
|
||
|
||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||
this.classList.add('active');
|
||
|
||
currentCategory = this.dataset.category;
|
||
renderLeaderboard(currentCategory);
|
||
});
|
||
});
|
||
}
|
||
|
||
// 渲染排行榜
|
||
function renderLeaderboard(category) {
|
||
const leaderboard = document.getElementById('leaderboard');
|
||
const data = leaderboardData[category] || [];
|
||
|
||
if (data.length === 0) {
|
||
leaderboard.innerHTML = `
|
||
<div class="empty-state">
|
||
<div class="empty-icon">🏆</div>
|
||
<div class="empty-text">暂无排行榜数据</div>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
let html = '';
|
||
data.forEach((player, index) => {
|
||
const rank = index + 1;
|
||
let rankClass = '';
|
||
let trophyIcon = '';
|
||
|
||
if (rank === 1) {
|
||
rankClass = 'first';
|
||
trophyIcon = '🥇';
|
||
} else if (rank === 2) {
|
||
rankClass = 'second';
|
||
trophyIcon = '🥈';
|
||
} else if (rank === 3) {
|
||
rankClass = 'third';
|
||
trophyIcon = '🥉';
|
||
} else if (rank <= 10) {
|
||
trophyIcon = '🏆';
|
||
}
|
||
|
||
html += `
|
||
<div class="rank-item">
|
||
<div class="rank-number ${rankClass}">${rank}</div>
|
||
<div class="player-avatar">${player.avatar}</div>
|
||
<div class="player-info">
|
||
<div class="player-name">${player.name}</div>
|
||
<div class="player-level">等级 ${player.level}</div>
|
||
</div>
|
||
<div class="player-stats">
|
||
<div class="win-rate">${player.winRate}%</div>
|
||
<div class="total-games">${player.totalGames}局</div>
|
||
</div>
|
||
<div class="trophy-icon">${trophyIcon}</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
leaderboard.innerHTML = html;
|
||
updateMyRank(category);
|
||
}
|
||
|
||
// 更新我的排名
|
||
function updateMyRank(category) {
|
||
const myRankElement = document.getElementById('myRank');
|
||
let myRank;
|
||
|
||
switch(category) {
|
||
case 'overall':
|
||
myRank = 15;
|
||
break;
|
||
case 'weekly':
|
||
myRank = 8;
|
||
break;
|
||
case 'daily':
|
||
myRank = 12;
|
||
break;
|
||
default:
|
||
myRank = 15;
|
||
}
|
||
|
||
// 数字跳动动画
|
||
animateNumber(myRankElement, parseInt(myRankElement.textContent), myRank, 500);
|
||
}
|
||
|
||
// 数字动画
|
||
function animateNumber(element, start, end, duration) {
|
||
const startTime = performance.now();
|
||
const difference = end - start;
|
||
|
||
function updateNumber(currentTime) {
|
||
const elapsed = currentTime - startTime;
|
||
const progress = Math.min(elapsed / duration, 1);
|
||
|
||
// 使用缓动函数
|
||
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
|
||
const currentValue = Math.round(start + difference * easeOutQuart);
|
||
|
||
element.textContent = currentValue;
|
||
|
||
if (progress < 1) {
|
||
requestAnimationFrame(updateNumber);
|
||
}
|
||
}
|
||
|
||
requestAnimationFrame(updateNumber);
|
||
}
|
||
|
||
// 刷新排行榜
|
||
function refreshLeaderboard() {
|
||
if (isLoading) return;
|
||
|
||
if (!isOnline) {
|
||
showToast('网络连接断开,请检查网络');
|
||
triggerHapticFeedback('error');
|
||
return;
|
||
}
|
||
|
||
isLoading = true;
|
||
const refreshBtn = document.getElementById('refreshBtn');
|
||
const leaderboard = document.getElementById('leaderboard');
|
||
|
||
// 添加加载状态
|
||
refreshBtn.textContent = '刷新中...';
|
||
refreshBtn.disabled = true;
|
||
leaderboard.classList.add('updating');
|
||
triggerHapticFeedback('medium');
|
||
|
||
// 模拟网络请求
|
||
setTimeout(() => {
|
||
// 模拟数据更新(随机调整胜率)
|
||
Object.keys(leaderboardData).forEach(category => {
|
||
leaderboardData[category].forEach(player => {
|
||
const change = Math.random() * 2 - 1; // -1 到 1 的随机变化
|
||
player.winRate = Math.max(0, Math.min(100, Math.round(player.winRate + change)));
|
||
});
|
||
|
||
// 重新排序
|
||
leaderboardData[category].sort((a, b) => b.winRate - a.winRate);
|
||
});
|
||
|
||
// 重新渲染
|
||
renderLeaderboard(currentCategory);
|
||
|
||
// 移除加载状态
|
||
refreshBtn.textContent = '刷新';
|
||
refreshBtn.disabled = false;
|
||
leaderboard.classList.remove('updating');
|
||
isLoading = false;
|
||
|
||
// 显示刷新成功提示
|
||
showToast('排行榜已更新');
|
||
triggerHapticFeedback('success');
|
||
}, 1500);
|
||
}
|
||
|
||
// 显示Toast消息
|
||
function showToast(message) {
|
||
const toast = document.createElement('div');
|
||
toast.className = 'toast show';
|
||
toast.textContent = message;
|
||
|
||
document.body.appendChild(toast);
|
||
|
||
setTimeout(() => {
|
||
toast.classList.remove('show');
|
||
toast.classList.add('hide');
|
||
setTimeout(() => toast.remove(), 300);
|
||
}, 2000);
|
||
}
|
||
|
||
// 返回上一页
|
||
function goBack() {
|
||
triggerHapticFeedback('light');
|
||
if (document.referrer && document.referrer.includes('mobile_')) {
|
||
window.history.back();
|
||
} else {
|
||
window.location.href = 'mobile_main_menu_1.html';
|
||
}
|
||
}
|
||
|
||
// 防止双指缩放和滚动
|
||
document.addEventListener('touchmove', function(event) {
|
||
if (event.scale !== 1) {
|
||
event.preventDefault();
|
||
}
|
||
}, { passive: false });
|
||
|
||
document.addEventListener('gesturestart', function(event) {
|
||
event.preventDefault();
|
||
});
|
||
|
||
// 页面加载完成后初始化
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
initApp();
|
||
}); |