2026-01-26 02:13:06 +08:00
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>{% block title %}YRTV - CS2 Data Platform{% endblock %}</title>
|
|
|
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
2026-01-26 18:36:47 +08:00
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@2.0.1/dist/chartjs-plugin-zoom.min.js"></script>
|
2026-01-26 02:13:06 +08:00
|
|
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
|
|
|
<script>
|
|
|
|
|
tailwind.config = {
|
|
|
|
|
darkMode: 'class',
|
|
|
|
|
theme: {
|
|
|
|
|
extend: {
|
|
|
|
|
colors: {
|
|
|
|
|
yrtv: {
|
|
|
|
|
50: '#f5f3ff',
|
|
|
|
|
100: '#ede9fe',
|
|
|
|
|
500: '#8b5cf6',
|
|
|
|
|
600: '#7c3aed',
|
|
|
|
|
900: '#4c1d95',
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<style>
|
|
|
|
|
body { font-family: 'Inter', sans-serif; }
|
|
|
|
|
</style>
|
|
|
|
|
{% block head %}{% endblock %}
|
|
|
|
|
</head>
|
|
|
|
|
<body class="bg-slate-50 text-slate-900 dark:bg-slate-900 dark:text-slate-100 flex flex-col min-h-screen">
|
|
|
|
|
|
|
|
|
|
<!-- Navbar -->
|
|
|
|
|
<nav class="bg-white dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700" x-data="{ mobileMenuOpen: false }">
|
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
|
|
|
<div class="flex justify-between h-16">
|
|
|
|
|
<div class="flex">
|
|
|
|
|
<div class="flex-shrink-0 flex items-center">
|
|
|
|
|
<a href="{{ url_for('main.index') }}" class="text-2xl font-bold text-yrtv-600">YRTV</a>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
|
|
|
|
|
<a href="{{ url_for('main.index') }}" class="{% if request.endpoint == 'main.index' %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">首页</a>
|
|
|
|
|
<a href="{{ url_for('matches.index') }}" class="{% if request.endpoint and 'matches' in request.endpoint %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">比赛</a>
|
|
|
|
|
<a href="{{ url_for('players.index') }}" class="{% if request.endpoint and 'players' in request.endpoint %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">玩家</a>
|
|
|
|
|
<a href="{{ url_for('teams.index') }}" class="{% if request.endpoint and 'teams' in request.endpoint %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">战队</a>
|
2026-01-27 19:06:20 +08:00
|
|
|
<a href="{{ url_for('opponents.index') }}" class="{% if request.endpoint and 'opponents' in request.endpoint %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">对手</a>
|
2026-01-26 02:13:06 +08:00
|
|
|
<a href="{{ url_for('tactics.index') }}" class="{% if request.endpoint and 'tactics' in request.endpoint %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">战术</a>
|
|
|
|
|
<a href="{{ url_for('wiki.index') }}" class="{% if request.endpoint and 'wiki' in request.endpoint %}border-yrtv-500 text-gray-900 dark:text-white{% else %}border-transparent text-gray-500 dark:text-gray-300 hover:border-gray-300 hover:text-gray-700 dark:hover:text-white{% endif %} inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">Wiki</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex items-center space-x-4">
|
|
|
|
|
<!-- Mobile menu button -->
|
|
|
|
|
<div class="flex items-center sm:hidden">
|
|
|
|
|
<button @click="mobileMenuOpen = !mobileMenuOpen" type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-slate-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-yrtv-500" aria-controls="mobile-menu" aria-expanded="false">
|
|
|
|
|
<span class="sr-only">Open main menu</span>
|
|
|
|
|
<svg class="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Dark Mode Toggle -->
|
|
|
|
|
<button id="theme-toggle" type="button" class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5">
|
|
|
|
|
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path></svg>
|
|
|
|
|
<svg id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
{% if session.get('is_admin') %}
|
|
|
|
|
<a href="{{ url_for('admin.dashboard') }}" class="hidden sm:block text-sm font-medium text-gray-500 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white">Admin</a>
|
|
|
|
|
{% else %}
|
|
|
|
|
<a href="{{ url_for('admin.login') }}" class="hidden sm:block bg-yrtv-600 text-white px-4 py-2 rounded-md text-sm font-medium hover:bg-yrtv-500">登录</a>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Mobile menu, show/hide based on menu state. -->
|
|
|
|
|
<div class="sm:hidden" id="mobile-menu" x-show="mobileMenuOpen" style="display: none;">
|
|
|
|
|
<div class="pt-2 pb-3 space-y-1">
|
|
|
|
|
<a href="{{ url_for('main.index') }}" class="{% if request.endpoint == 'main.index' %}bg-yrtv-50 border-yrtv-500 text-yrtv-700{% else %}border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700{% endif %} block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">首页</a>
|
|
|
|
|
<a href="{{ url_for('matches.index') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">比赛</a>
|
|
|
|
|
<a href="{{ url_for('players.index') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">玩家</a>
|
|
|
|
|
<a href="{{ url_for('teams.index') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">战队</a>
|
2026-01-27 19:06:20 +08:00
|
|
|
<a href="{{ url_for('opponents.index') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">对手</a>
|
2026-01-26 02:13:06 +08:00
|
|
|
<a href="{{ url_for('tactics.index') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">战术</a>
|
|
|
|
|
<a href="{{ url_for('wiki.index') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">Wiki</a>
|
|
|
|
|
{% if session.get('is_admin') %}
|
|
|
|
|
<a href="{{ url_for('admin.dashboard') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">Admin</a>
|
|
|
|
|
{% else %}
|
|
|
|
|
<a href="{{ url_for('admin.login') }}" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium dark:text-white dark:hover:bg-slate-700">登录</a>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
<!-- Main Content -->
|
|
|
|
|
<main class="flex-grow max-w-7xl mx-auto py-6 sm:px-6 lg:px-8 w-full">
|
|
|
|
|
{% block content %}{% endblock %}
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
<!-- Footer -->
|
|
|
|
|
<footer class="bg-white dark:bg-slate-800 border-t border-slate-200 dark:border-slate-700 mt-auto">
|
|
|
|
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
2026-01-27 16:51:53 +08:00
|
|
|
<p class="text-center text-sm text-gray-500">© 2026 YRTV Data Platform. All rights reserved. 赣ICP备2026001600号</p>
|
2026-01-26 02:13:06 +08:00
|
|
|
</div>
|
|
|
|
|
</footer>
|
|
|
|
|
|
|
|
|
|
{% block scripts %}{% endblock %}
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
// Dark mode toggle logic
|
|
|
|
|
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
|
|
|
|
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
|
|
|
|
|
|
|
|
|
// Change the icons inside the button based on previous settings
|
|
|
|
|
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
|
|
|
themeToggleLightIcon.classList.remove('hidden');
|
|
|
|
|
document.documentElement.classList.add('dark');
|
|
|
|
|
} else {
|
|
|
|
|
themeToggleDarkIcon.classList.remove('hidden');
|
|
|
|
|
document.documentElement.classList.remove('dark');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var themeToggleBtn = document.getElementById('theme-toggle');
|
|
|
|
|
|
|
|
|
|
themeToggleBtn.addEventListener('click', function() {
|
|
|
|
|
|
|
|
|
|
// toggle icons inside button
|
|
|
|
|
themeToggleDarkIcon.classList.toggle('hidden');
|
|
|
|
|
themeToggleLightIcon.classList.toggle('hidden');
|
|
|
|
|
|
|
|
|
|
// if set via local storage previously
|
|
|
|
|
if (localStorage.getItem('color-theme')) {
|
|
|
|
|
if (localStorage.getItem('color-theme') === 'light') {
|
|
|
|
|
document.documentElement.classList.add('dark');
|
|
|
|
|
localStorage.setItem('color-theme', 'dark');
|
|
|
|
|
} else {
|
|
|
|
|
document.documentElement.classList.remove('dark');
|
|
|
|
|
localStorage.setItem('color-theme', 'light');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if NOT set via local storage previously
|
|
|
|
|
} else {
|
|
|
|
|
if (document.documentElement.classList.contains('dark')) {
|
|
|
|
|
document.documentElement.classList.remove('dark');
|
|
|
|
|
localStorage.setItem('color-theme', 'light');
|
|
|
|
|
} else {
|
|
|
|
|
document.documentElement.classList.add('dark');
|
|
|
|
|
localStorage.setItem('color-theme', 'dark');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|