221 lines
15 KiB
HTML
221 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN" class=""> <!-- [核心] <html> 标签是 dark class 的应用目标 -->
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="icon" type="image/png" href="/static/icons/favicon.png" sizes="any">
|
|
<!--<script src="https://cdn.tailwindcss.com"></script>-->
|
|
<link href="/static/css/output.css" rel="stylesheet">
|
|
|
|
<link rel="stylesheet" href="https://fonts.googleapis.cn/css2?family=Pixelify+Sans:wght@400..700&family=QuinqueFive&display=swap">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
|
<title>{% block title %}GEMINI BALANCER{% endblock %}</title>
|
|
|
|
{% block head_extra %}{% endblock %}
|
|
</head>
|
|
<body data-page-id="{{ PageID }}" class="bg-zinc-800 dark:bg-zinc-900 text-zinc-900 dark:text-zinc-200 overflow-hidden h-screen">
|
|
|
|
<div id="app-container" class="relative h-full w-full max-w-[1660px] mx-auto">
|
|
<aside id="sidebar" class="absolute top-0 left-0 h-full z-10 flex flex-col w-16 lg:w-64 bg-zinc-900 border-r border-zinc-700/50 dark:bg-zinc-950 transition-all duration-300 ease-in-out">
|
|
<!-- Logo 部分也做响应式处理 -->
|
|
<div class="flex items-center justify-center h-16 border-b border-zinc-700/50 lg:pl-4 lg:pr-8 shrink-0">
|
|
<img src="/static/icons/logo.png" alt="Logo" class="h-6 w-6 mr-3"/><span class="font-bold text-md text-zinc-100 hidden lg:inline">GEMINI BALANCER</span>
|
|
</div>
|
|
|
|
<nav class="flex-1 flex flex-col py-2 space-y-1">
|
|
{% block sidebar_nav %}
|
|
<!-- 监控面板 -->
|
|
<div class="nav-item-wrapper group"> <!-- .group 类现在被封装在 .nav-item-wrapper 内部了 -->
|
|
<span class="nav-indicator"></span>
|
|
<a href="/dashboard" class="nav-link">
|
|
<!-- 关键: 响应式 transform 逻辑保留在 HTML 中,因为它更清晰 -->
|
|
<i class="nav-icon fas fa-bar-chart -translate-x-1 lg:translate-x-0"></i>
|
|
<span class="ml-3 whitespace-nowrap hidden lg:inline">监控面板</span>
|
|
<span class="pixel-decoration hidden lg:inline">SYS.STATUS</span>
|
|
</a>
|
|
</div>
|
|
<!-- 全局设置 -->
|
|
<div class="nav-item-wrapper group">
|
|
<span class="nav-indicator"></span>
|
|
<a href="/settings" class="nav-link">
|
|
<i class="nav-icon fas fa-cog -translate-x-1 lg:translate-x-0"></i>
|
|
<span class="ml-3 whitespace-nowrap hidden lg:inline">全局设置</span>
|
|
<span class="pixel-decoration hidden lg:inline">GL.SETTINGS</span>
|
|
</a>
|
|
</div>
|
|
<!-- API 管理 -->
|
|
<div class="nav-item-wrapper group">
|
|
<span class="nav-indicator"></span>
|
|
<a href="/keys" class="nav-link">
|
|
<i class="nav-icon fas fa-key -translate-x-1 lg:translate-x-0"></i>
|
|
<span class="ml-3 whitespace-nowrap hidden lg:inline">API 管理</span>
|
|
<span class="pixel-decoration hidden lg:inline">KEY.MANAGER</span>
|
|
</a>
|
|
</div>
|
|
<!-- 请求日志 -->
|
|
<div class="nav-item-wrapper group">
|
|
<span class="nav-indicator"></span>
|
|
<a href="/logs" class="nav-link">
|
|
<i class="nav-icon fas fa-clipboard-list -translate-x-1 lg:translate-x-0"></i>
|
|
<span class="ml-3 whitespace-nowrap hidden lg:inline">请求日志</span>
|
|
<span class="pixel-decoration hidden lg:inline">LOG.VIEW</span>
|
|
</a>
|
|
</div>
|
|
<!-- 计划任务 -->
|
|
<div class="nav-item-wrapper group">
|
|
<span class="nav-indicator"></span>
|
|
<a href="/tasks" class="nav-link">
|
|
<i class="nav-icon fas fa-clock -translate-x-1 lg:translate-x-0"></i>
|
|
<span class="ml-3 whitespace-nowrap hidden lg:inline">计划任务</span>
|
|
<span class="pixel-decoration hidden lg:inline">TASK.SCHEDULER</span>
|
|
</a>
|
|
</div>
|
|
<!-- WebChat -->
|
|
<div class="nav-item-wrapper group">
|
|
<span class="nav-indicator"></span>
|
|
<a href="/chat" class="nav-link">
|
|
<i class="nav-icon fas fa-comments -translate-x-1 lg:translate-x-0"></i>
|
|
<span class="ml-3 whitespace-nowrap hidden lg:inline">WebChat</span>
|
|
<span class="pixel-decoration hidden lg:inline">LIVE.CHAT</span>
|
|
</a>
|
|
</div>
|
|
{% endblock %}
|
|
</nav>
|
|
|
|
|
|
<div class="py-4 border-t border-zinc-700/50 shrink-0 flex justify-center lg:justify-start left-5 lg:pl-8 lg:pr-8">
|
|
<div class="flex items-center space-x-4 -translate-x-2 lg:transform-none">
|
|
|
|
<!-- [精简版] 三态主题切换器 -->
|
|
<div id="theme-switcher" class="hidden lg:inline-grid relative z-10 grid-cols-3 gap-1 rounded-full bg-gray-950/50 p-1 text-gray-500 dark:bg-white/10 dark:text-white">
|
|
|
|
<!-- 1. 系统模式按钮 -->
|
|
<button type="button" data-theme="system" class="theme-btn rounded-full p-1 focus:outline-none">
|
|
<svg class="h-6 w-6" viewBox="0 0 28 28" fill="none"><path d="M7.5 8.5C7.5 7.94772 7.94772 7.5 8.5 7.5H19.5C20.0523 7.5 20.5 7.94772 20.5 8.5V16.5C20.5 17.0523 20.0523 17.5 19.5 17.5H8.5C7.94772 17.5 7.5 17.0523 7.5 16.5V8.5Z" stroke="currentColor"></path><path d="M7.5 8.5C7.5 7.94772 7.94772 7.5 8.5 7.5H19.5C20.0523 7.5 20.5 7.94772 20.5 8.5V14.5C20.5 15.0523 20.0523 15.5 19.5 15.5H8.5C7.94772 15.5 7.5 15.0523 7.5 14.5V8.5Z" stroke="currentColor"></path><path d="M16.5 20.5V17.5H11.5V20.5M16.5 20.5H11.5M16.5 20.5H17.5M11.5 20.5H10.5" stroke="currentColor" stroke-linecap="round"></path></svg>
|
|
</button>
|
|
|
|
<!-- 2. 亮色模式按钮 -->
|
|
<button type="button" data-theme="light" class="theme-btn rounded-full p-1 focus:outline-none">
|
|
<svg class="h-6 w-6" viewBox="0 0 28 28" fill="none"><circle cx="14" cy="14" r="3.5" stroke="currentColor"></circle><path d="M14 8.5V6.5" stroke="currentColor" stroke-linecap="round"></path><path d="M17.889 10.1115L19.3032 8.69727" stroke="currentColor" stroke-linecap="round"></path><path d="M19.5 14L21.5 14" stroke="currentColor" stroke-linecap="round"></path><path d="M17.889 17.8885L19.3032 19.3027" stroke="currentColor" stroke-linecap="round"></path><path d="M14 21.5V19.5" stroke="currentColor" stroke-linecap="round"></path><path d="M8.69663 19.3029L10.1108 17.8887" stroke="currentColor" stroke-linecap="round"></path><path d="M6.5 14L8.5 14" stroke="currentColor" stroke-linecap="round"></path><path d="M8.69663 8.69711L10.1108 10.1113" stroke="currentColor" stroke-linecap="round"></path></svg>
|
|
</button>
|
|
|
|
<!-- 3. 暗色模式按钮 -->
|
|
<button type="button" data-theme="dark" class="theme-btn rounded-full p-1 focus:outline-none">
|
|
<svg class="h-6 w-6" viewBox="0 0 28 28" fill="none"><path d="M10.5 9.99914C10.5 14.1413 13.8579 17.4991 18 17.4991C19.0332 17.4991 20.0176 17.2902 20.9132 16.9123C19.7761 19.6075 17.109 21.4991 14 21.4991C9.85786 21.4991 6.5 18.1413 6.5 13.9991C6.5 10.8902 8.39167 8.22304 11.0868 7.08594C10.7089 7.98159 10.5 8.96597 10.5 9.99914Z" stroke="currentColor" stroke-linejoin="round"></path><path d="M16.3561 6.50754L16.5 5.5L16.6439 6.50754C16.7068 6.94752 17.0525 7.29321 17.4925 7.35607L18.5 7.5L17.4925 7.64393C17.0525 7.70679 16.7068 8.05248 16.6439 8.49246L16.5 9.5L16.3561 8.49246C16.2932 8.05248 15.9475 7.70679 15.5075 7.64393L14.5 7.5L15.5075 7.35607C15.9475 7.29321 16.2932 6.94752 16.3561 6.50754Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20.3561 11.5075L20.5 10.5L20.6439 11.5075C20.7068 11.9475 21.0525 12.2932 21.4925 12.3561L22.5 12.5L21.4925 12.6439C21.0525 12.7068 20.7068 13.0525 20.6439 13.4925L20.5 14.5L20.3561 13.4925C20.2932 13.0525 19.9475 12.7068 19.5075 12.6439L18.5 12.5L19.5075 12.3561C19.9475 12.2932 20.2932 11.9475 20.3561 11.5075Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
|
</button>
|
|
</div>
|
|
<!-- 2. 移动端形态 -->
|
|
<button id="theme-cycler-btn" type="button" class="flex lg:hidden items-center justify-center rounded-full ml-4 bg-zinc-800 p-1 text-gray-200 dark:bg-white/10 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<span id="theme-cycler-icon" class="h-6 w-6"></span>
|
|
</button>
|
|
<div id="app-version" class="text-xs text-zinc-400 hidden lg:inline">v1.0.0</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<main id="main-content-wrapper" class="absolute top-4 right-4 bottom-4 left-12 lg:left-60 z-20 rounded-2xl overflow-hidden flex flex-col bg-white dark:bg-zinc-800 shadow-xs ring-1 ring-black/15 dark:ring-white/15 shadow-main shadow-inner transition-all duration-300 ease-in-out pt-4 pb-4 pl-4 pr-1 lg:pt-16 lg:pb-16 lg:pl-16 lg:pr-6">
|
|
<div class="flex-1 w-full h-full overflow-y-auto main-content-scroll lg:pr-6 translate-x-1 lg:translate-x-0 lg:transform-none">
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
{% block core_scripts %}
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
<script src="/static/js/main.js" type="module" defer></script>
|
|
{% endblock core_scripts %}
|
|
<!-- [核心] Block 2: 留给子页面的脚本扩展插槽 -->
|
|
{% block page_scripts %}{% endblock page_scripts %}
|
|
|
|
{% block modals %}{% endblock modals %}
|
|
|
|
<!-- =================================================================== -->
|
|
<!-- 全局异步任务中心 (Global Async Task Center) -->
|
|
<!-- =================================================================== -->
|
|
|
|
<!-- 组件 A: 全局实时反馈信使 (The Toast/Snackbar Messenger) -->
|
|
<div id="global-toast-container"
|
|
class="fixed bottom-4 right-4 z-[9999] w-full max-w-sm space-y-3 pointer-events-none">
|
|
<!-- Toast 通知将由JS动态插入到这里 -->
|
|
<!-- 示例Toast结构 (供JS参考):
|
|
<div class="toast-item">
|
|
<div class="toast-icon toast-icon-loading">
|
|
<i class="fas fa-spinner fa-spin"></i>
|
|
</div>
|
|
<div class="toast-content">
|
|
<p class="toast-title">任务已开始</p>
|
|
<p class="toast-message">正在批量添加API Keys...</p>
|
|
</div>
|
|
<button class="toast-close-btn">×</button>
|
|
</div>
|
|
-->
|
|
</div>
|
|
|
|
<!-- 组件 B: 全局持久化任务中心 (The Task Hub) -->
|
|
<div id="global-task-hub" class="fixed top-6 right-6 z-[9998]">
|
|
<!-- 1. 触发器: 小铃铛图标 -->
|
|
<button id="task-hub-trigger"
|
|
class="relative h-10 w-10 flex items-center justify-center rounded-full bg-white/80 dark:bg-zinc-800/80 backdrop-blur-sm shadow-lg ring-1 ring-black/10 dark:ring-white/10 text-zinc-500 dark:text-zinc-400 hover:text-blue-500 dark:hover:text-blue-400 transition-colors duration-200">
|
|
|
|
<!-- SVG动画层 -->
|
|
<svg class="absolute inset-0 h-full w-full" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<circle id="task-hub-countdown-ring"
|
|
cx="12" cy="12" r="11.5" stroke="#3b82f6" stroke-width="1"
|
|
class="origin-center -rotate-90"
|
|
stroke-linecap="round"
|
|
style="stroke-dasharray: 72.26; stroke-dashoffset: 72.26;"
|
|
/>
|
|
</svg>
|
|
<i class="fas fa-bell text-lg"></i>
|
|
<!-- 任务活动指示器 (默认隐藏) -->
|
|
<span id="task-hub-indicator"
|
|
class="absolute top-1 right-1 h-2.5 w-2.5 rounded-full bg-blue-500 border-2 border-white dark:border-zinc-800 hidden animate-pulse">
|
|
</span>
|
|
</button>
|
|
|
|
<!-- 2. 浮动面板 (默认隐藏) -->
|
|
<div id="task-hub-panel"
|
|
class="absolute top-full right-0 mt-2 w-80 rounded-xl bg-white/90 dark:bg-zinc-800/90 backdrop-blur-lg shadow-2xl ring-1 ring-black/5 dark:ring-white/10 hidden origin-top-right transition-all"
|
|
role="dialog" aria-modal="true" aria-labelledby="task-hub-title">
|
|
<!-- [新增] 面板头部容器,用于定位倒计时条 -->
|
|
<div class="relative">
|
|
<!-- 面板头部 -->
|
|
<div class="flex items-center justify-between p-3 border-b border-black/10 dark:border-white/10">
|
|
<h3 id="task-hub-title" class="font-semibold text-sm text-zinc-800 dark:text-zinc-200">任务中心</h3>
|
|
<button id="task-hub-clear-btn" class="text-xs text-zinc-500 hover:text-blue-500">清空已完成</button>
|
|
</div>
|
|
|
|
<!-- [新增] 倒计时进度条 (默认宽度为0) -->
|
|
<div id="task-hub-countdown-bar"
|
|
class="absolute bottom-0 left-0 h-0.5 bg-gradient-to-r from-blue-500/30 to-blue-500 w-0 transition-all duration-[5000ms] ease-linear">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 任务列表容器 (可滚动) -->
|
|
<div id="task-list-container" class="p-2 max-h-96 overflow-y-auto space-y-2">
|
|
<!-- 任务项将由JS动态插入到这里 -->
|
|
<!-- 示例任务项 (供JS参考):
|
|
<div class="task-list-item">
|
|
<div class="task-item-icon task-item-icon-success">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="task-item-content">
|
|
<p class="task-item-title">批量添加 Key</p>
|
|
<p class="task-item-status">成功</p>
|
|
</div>
|
|
<div class="task-item-timestamp">1分钟前</div>
|
|
</div>
|
|
-->
|
|
</div>
|
|
<!-- 空状态 (默认隐藏) -->
|
|
<div id="task-list-empty" class="hidden text-center text-xs text-zinc-400 py-10 px-4">
|
|
<i class="fas fa-inbox fa-2x mb-2"></i>
|
|
<p>当前没有正在运行或最近完成的任务</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|