Download app/templates/base.html from JXJBing/gemini: direct link, hf CLI and curl.
- Browser
- Download file 26.6 kB
-
https://huggingface.co/spaces/JXJBing/gemini/resolve/main/app/templates/base.html
- Command line
-
hf download hf://spaces/JXJBing/gemini/app/templates/base.html
-
curl -L -o base.html https://huggingface.co/spaces/JXJBing/gemini/resolve/main/app/templates/base.html
26.6 kB
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>{% block title %}Gemini Balance{% endblock %}</title> | |
| <link rel="manifest" href="/static/manifest.json" /> | |
| <meta name="theme-color" content="#4F46E5" /> | |
| <meta name="apple-mobile-web-app-capable" content="yes" /> | |
| <meta name="apple-mobile-web-app-status-bar-style" content="black" /> | |
| <meta name="apple-mobile-web-app-title" content="GBalance" /> | |
| <link rel="icon" href="/static/icons/icon-192x192.png" /> | |
| <link | |
| href="/static/css/fonts.css" | |
| rel="stylesheet" | |
| /> | |
| <link | |
| rel="stylesheet" | |
| href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" | |
| /> | |
| <script src="/static/js/tailwindcss.js"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: { | |
| 50: "#eef2ff", | |
| 100: "#e0e7ff", | |
| 200: "#c7d2fe", | |
| 300: "#a5b4fc", | |
| 400: "#818cf8", | |
| 500: "#6366f1", | |
| 600: "#4f46e5", | |
| 700: "#4338ca", | |
| 800: "#3730a3", | |
| 900: "#312e81", | |
| }, | |
| success: { | |
| 50: "#ecfdf5", | |
| 500: "#10b981", | |
| 600: "#059669", | |
| }, | |
| danger: { | |
| 50: "#fef2f2", | |
| 500: "#ef4444", | |
| 600: "#dc2626", | |
| }, | |
| }, | |
| fontFamily: { | |
| sans: ["Inter", "sans-serif"], | |
| mono: [ | |
| "JetBrains Mono", | |
| "SFMono-Regular", | |
| "Menlo", | |
| "Monaco", | |
| "Consolas", | |
| "monospace", | |
| ], | |
| }, | |
| animation: { | |
| "fade-in": "fadeIn 0.5s ease-out", | |
| "slide-up": "slideUp 0.5s ease-out", | |
| "slide-down": "slideDown 0.5s ease-out", | |
| shake: "shake 0.5s ease-in-out", | |
| spin: "spin 1s linear infinite", | |
| }, | |
| keyframes: { | |
| fadeIn: { | |
| "0%": { opacity: "0" }, | |
| "100%": { opacity: "1" }, | |
| }, | |
| slideUp: { | |
| "0%": { transform: "translateY(20px)", opacity: "0" }, | |
| "100%": { transform: "translateY(0)", opacity: "1" }, | |
| }, | |
| slideDown: { | |
| "0%": { transform: "translateY(-20px)", opacity: "0" }, | |
| "100%": { transform: "translateY(0)", opacity: "1" }, | |
| }, | |
| shake: { | |
| "0%, 100%": { transform: "translateX(0)" }, | |
| "25%": { transform: "translateX(-5px)" }, | |
| "75%": { transform: "translateX(5px)" }, | |
| }, | |
| spin: { | |
| "0%": { transform: "rotate(0deg)" }, | |
| "100%": { transform: "rotate(360deg)" }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }; | |
| </script> | |
| <style> | |
| .glass-card { | |
| background: rgba(255, 255, 255, 0.95); /* High opacity white for light theme */ | |
| backdrop-filter: blur(16px); | |
| -webkit-backdrop-filter: blur(16px); | |
| border: 1px solid rgba(0, 0, 0, 0.08); /* Light gray border */ | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
| } | |
| .bg-gradient { | |
| background: #ffffff; /* Clean white background */ | |
| } | |
| /* Scrollbar styling */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: rgba(243, 244, 246, 0.8); /* bg-gray-100 with opacity */ | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: rgba(107, 114, 128, 0.6); /* gray-500 for light theme */ | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: rgba(75, 85, 99, 0.8); /* gray-600 for light theme */ | |
| } | |
| /* Basic modal styles */ | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| z-index: 50; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(0,0,0,0.5); | |
| backdrop-filter: blur(4px); | |
| } | |
| .modal.show { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* Global modal content styling for light theme consistency */ | |
| .modal .w-full[style*="background-color: rgba(70, 50, 150"], | |
| .modal .w-full[style*="background-color: rgba(80, 60, 160"] { | |
| background-color: rgba(255, 255, 255, 0.98) ; | |
| color: #374151 ; /* gray-700 */ | |
| border: 1px solid rgba(0, 0, 0, 0.08) ; | |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04) ; | |
| } | |
| /* Global modal text color fixes */ | |
| .modal .text-gray-100, .modal h2.text-gray-100, .modal h3.text-gray-100 { | |
| color: #1f2937 ; /* gray-800 */ | |
| font-weight: 600 ; | |
| } | |
| .modal .text-gray-200, .modal .text-gray-300 { | |
| color: #6b7280 ; /* gray-500 */ | |
| } | |
| .modal .text-gray-300:hover { | |
| color: #374151 ; /* gray-700 */ | |
| } | |
| /* Global modal button styling */ | |
| .modal .bg-violet-600, .modal button.bg-violet-600 { | |
| background-color: #3b82f6 ; /* blue-500 - light blue */ | |
| color: #ffffff ; | |
| } | |
| .modal .bg-violet-600:hover, .modal button.bg-violet-600:hover { | |
| background-color: #2563eb ; /* blue-600 - darker light blue */ | |
| } | |
| /* Global modal blue button styling */ | |
| .modal .bg-blue-500, .modal button.bg-blue-500, | |
| .modal .bg-blue-600, .modal button.bg-blue-600, | |
| .modal .bg-blue-700, .modal button.bg-blue-700 { | |
| background-color: #3b82f6 ; /* blue-500 - light blue */ | |
| color: #ffffff ; | |
| } | |
| .modal .bg-blue-500:hover, .modal button.bg-blue-500:hover, | |
| .modal .bg-blue-600:hover, .modal button.bg-blue-600:hover, | |
| .modal .bg-blue-700:hover, .modal button.bg-blue-700:hover { | |
| background-color: #2563eb ; /* blue-600 - darker light blue */ | |
| } | |
| /* Global modal red button styling */ | |
| .modal .bg-red-500, .modal button.bg-red-500, | |
| .modal .bg-red-600, .modal button.bg-red-600, | |
| .modal .bg-red-700, .modal button.bg-red-700 { | |
| background-color: #f87171 ; /* red-400 - bright light red */ | |
| color: #ffffff ; | |
| } | |
| .modal .bg-red-500:hover, .modal button.bg-red-500:hover, | |
| .modal .bg-red-600:hover, .modal button.bg-red-600:hover, | |
| .modal .bg-red-700:hover, .modal button.bg-red-700:hover { | |
| background-color: #ef4444 ; /* red-500 - darker bright light red */ | |
| } | |
| /* Global modal gray button styling */ | |
| .modal .bg-gray-500, .modal button.bg-gray-500, | |
| .modal .bg-gray-600, .modal button.bg-gray-600, | |
| .modal .bg-gray-700, .modal button.bg-gray-700 { | |
| background-color: #e5e7eb ; /* gray-200 - light gray */ | |
| color: #374151 ; /* gray-700 - dark text for contrast */ | |
| } | |
| .modal .bg-gray-500:hover, .modal button.bg-gray-500:hover, | |
| .modal .bg-gray-600:hover, .modal button.bg-gray-600:hover, | |
| .modal .bg-gray-700:hover, .modal button.bg-gray-700:hover { | |
| background-color: #d1d5db ; /* gray-300 - darker light gray */ | |
| color: #374151 ; /* gray-700 - dark text for contrast */ | |
| } | |
| /* Comprehensive button contrast fixes */ | |
| /* Ensure all dark background buttons have white text */ | |
| .bg-blue-500, .bg-blue-600, .bg-blue-700, .bg-blue-800, .bg-blue-900, | |
| .bg-red-500, .bg-red-600, .bg-red-700, .bg-red-800, .bg-red-900, | |
| .bg-green-500, .bg-green-600, .bg-green-700, .bg-green-800, .bg-green-900, | |
| .bg-purple-500, .bg-purple-600, .bg-purple-700, .bg-purple-800, .bg-purple-900, | |
| .bg-indigo-500, .bg-indigo-600, .bg-indigo-700, .bg-indigo-800, .bg-indigo-900, | |
| .bg-violet-500, .bg-violet-600, .bg-violet-700, .bg-violet-800, .bg-violet-900, | |
| .bg-sky-500, .bg-sky-600, .bg-sky-700, .bg-sky-800, .bg-sky-900, | |
| .bg-teal-500, .bg-teal-600, .bg-teal-700, .bg-teal-800, .bg-teal-900, | |
| .bg-gray-700, .bg-gray-800, .bg-gray-900, | |
| .bg-slate-500, .bg-slate-600, .bg-slate-700, .bg-slate-800, .bg-slate-900 { | |
| color: #ffffff ; | |
| } | |
| /* Ensure all light background buttons have dark text */ | |
| .bg-gray-50, .bg-gray-100, .bg-gray-200, .bg-gray-300, | |
| .bg-white, .bg-transparent { | |
| color: #374151 ; /* gray-700 */ | |
| } | |
| /* Fix button children text inheritance */ | |
| .bg-blue-500 *, .bg-blue-600 *, .bg-blue-700 *, .bg-blue-800 *, .bg-blue-900 *, | |
| .bg-red-500 *, .bg-red-600 *, .bg-red-700 *, .bg-red-800 *, .bg-red-900 *, | |
| .bg-green-500 *, .bg-green-600 *, .bg-green-700 *, .bg-green-800 *, .bg-green-900 *, | |
| .bg-purple-500 *, .bg-purple-600 *, .bg-purple-700 *, .bg-purple-800 *, .bg-purple-900 *, | |
| .bg-violet-500 *, .bg-violet-600 *, .bg-violet-700 *, .bg-violet-800 *, .bg-violet-900 *, | |
| .bg-sky-500 *, .bg-sky-600 *, .bg-sky-700 *, .bg-sky-800 *, .bg-sky-900 *, | |
| .bg-teal-500 *, .bg-teal-600 *, .bg-teal-700 *, .bg-teal-800 *, .bg-teal-900 *, | |
| .bg-gray-700 *, .bg-gray-800 *, .bg-gray-900 *, | |
| .bg-slate-500 *, .bg-slate-600 *, .bg-slate-700 *, .bg-slate-800 *, .bg-slate-900 * { | |
| color: inherit ; | |
| } | |
| /* Global form element styling for consistency */ | |
| select, input[type="text"], input[type="number"], input[type="search"], | |
| input[type="email"], input[type="password"], input[type="datetime-local"], | |
| textarea, .form-input, .form-select { | |
| background-color: rgba(255, 255, 255, 0.95) ; | |
| color: #374151 ; /* gray-700 */ | |
| border: 1px solid rgba(0, 0, 0, 0.12) ; | |
| border-radius: 0.375rem ; /* rounded-md */ | |
| } | |
| select:focus, input:focus, textarea:focus, | |
| .form-input:focus, .form-select:focus { | |
| border-color: #3b82f6 ; /* blue-500 */ | |
| box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) ; | |
| outline: none ; | |
| } | |
| /* Fix dropdown option styling */ | |
| select option { | |
| background-color: rgba(255, 255, 255, 0.98) ; | |
| color: #374151 ; /* gray-700 */ | |
| padding: 8px ; | |
| } | |
| /* Fix pagination controls globally */ | |
| .pagination-button, .pagination a, .pagination button { | |
| background-color: rgba(255, 255, 255, 0.9) ; | |
| color: #374151 ; /* gray-700 */ | |
| border: 1px solid rgba(0, 0, 0, 0.08) ; | |
| transition: all 0.15s ease-in-out ; | |
| } | |
| .pagination-button:hover, .pagination a:hover, .pagination button:hover { | |
| background-color: rgba(229, 231, 235, 1) ; /* gray-200 */ | |
| border-color: rgba(0, 0, 0, 0.12) ; | |
| transform: translateY(-1px) ; | |
| } | |
| .pagination-button.active, .pagination a.active, .pagination button.active { | |
| background-color: #3b82f6 ; /* blue-500 - light blue */ | |
| color: #ffffff ; | |
| border-color: #2563eb ; /* blue-600 - darker light blue */ | |
| font-weight: 600 ; | |
| } | |
| /* Loading spinner */ | |
| .loading-spin { | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| from { transform: rotate(0deg); } | |
| to { transform: rotate(360deg); } | |
| } | |
| /* Notification */ | |
| .notification { | |
| position: fixed; | |
| bottom: 5rem; /* Adjusted from bottom-20 */ | |
| left: 50%; | |
| transform: translateX(-50%); | |
| padding: 0.75rem 1.25rem; /* px-5 py-3 */ | |
| border-radius: 0.5rem; /* rounded-lg */ | |
| background-color: rgba(34, 197, 94, 0.95); /* green-500 for success */ | |
| color: white; | |
| font-weight: 500; /* font-medium */ | |
| z-index: 1000; /* Increased z-index */ | |
| opacity: 0; | |
| transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out; | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |
| } | |
| .notification.show { | |
| opacity: 1; | |
| transform: translate(-50%, 0); | |
| } | |
| .notification.error { | |
| background-color: rgba(239, 68, 68, 0.95); /* red-500 for error */ | |
| } | |
| /* Scroll buttons */ | |
| .scroll-buttons { | |
| position: fixed; | |
| right: 1.25rem; /* right-5 */ | |
| bottom: 5rem; /* bottom-20 */ | |
| display: flex; | |
| flex-direction: column; | |
| gap: 0.5rem; /* gap-2 */ | |
| z-index: 10; | |
| } | |
| .scroll-button { | |
| width: 2.5rem; /* w-10 */ | |
| height: 2.5rem; /* h-10 */ | |
| background-color: #3b82f6; /* blue-500 - light blue */ | |
| color: white; | |
| border-radius: 9999px; /* rounded-full */ | |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-md */ | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.3s ease-in-out; | |
| } | |
| .scroll-button:hover { | |
| background-color: #2563eb; /* blue-600 - darker light blue */ | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* hover:shadow-lg */ | |
| } | |
| /* Global overrides for light theme consistency */ | |
| .text-gray-200, .text-gray-300, .text-gray-400 { | |
| color: #6b7280 ; /* gray-500 for better contrast */ | |
| } | |
| /* Navigation and header improvements */ | |
| .bg-primary-600, .bg-primary-700 { | |
| background-color: #3b82f6 ; /* blue-500 - light blue */ | |
| } | |
| .text-primary-600, .text-primary-700 { | |
| color: #3b82f6 ; /* blue-500 - light blue */ | |
| } | |
| .border-primary-500, .focus\\:border-primary-500 { | |
| border-color: #3b82f6 ; /* blue-500 */ | |
| } | |
| .ring-primary-200, .focus\\:ring-primary-200 { | |
| --tw-ring-color: rgba(59, 130, 246, 0.2) ; /* blue-500 with opacity */ | |
| } | |
| /* Global purple to blue conversion */ | |
| .bg-violet-50, .bg-violet-100, .bg-violet-200, .bg-violet-300, .bg-violet-400, .bg-violet-500, .bg-violet-600, .bg-violet-700, .bg-violet-800, .bg-violet-900 { | |
| background-color: #3b82f6 ; /* blue-500 - light blue */ | |
| } | |
| .text-violet-50, .text-violet-100, .text-violet-200, .text-violet-300, .text-violet-400, .text-violet-500, .text-violet-600, .text-violet-700, .text-violet-800, .text-violet-900 { | |
| color: #3b82f6 ; /* blue-500 - light blue */ | |
| } | |
| .border-violet-50, .border-violet-100, .border-violet-200, .border-violet-300, .border-violet-400, .border-violet-500, .border-violet-600, .border-violet-700, .border-violet-800, .border-violet-900 { | |
| border-color: #3b82f6 ; /* blue-500 - light blue */ | |
| } | |
| /* Global button color overrides */ | |
| /* Blue buttons to light blue */ | |
| .bg-blue-500, .bg-blue-600, .bg-blue-700, .bg-blue-800, .bg-blue-900, | |
| button.bg-blue-500, button.bg-blue-600, button.bg-blue-700, button.bg-blue-800, button.bg-blue-900 { | |
| background-color: #3b82f6 ; /* blue-500 - light blue */ | |
| } | |
| .bg-blue-500:hover, .bg-blue-600:hover, .bg-blue-700:hover, .bg-blue-800:hover, .bg-blue-900:hover, | |
| button.bg-blue-500:hover, button.bg-blue-600:hover, button.bg-blue-700:hover, button.bg-blue-800:hover, button.bg-blue-900:hover, | |
| .hover\\:bg-blue-600:hover, .hover\\:bg-blue-700:hover, .hover\\:bg-blue-800:hover { | |
| background-color: #2563eb ; /* blue-600 - darker light blue */ | |
| } | |
| /* Red buttons to bright light red */ | |
| .bg-red-500, .bg-red-600, .bg-red-700, .bg-red-800, .bg-red-900, | |
| button.bg-red-500, button.bg-red-600, button.bg-red-700, button.bg-red-800, button.bg-red-900 { | |
| background-color: #f87171 ; /* red-400 - bright light red */ | |
| } | |
| .bg-red-500:hover, .bg-red-600:hover, .bg-red-700:hover, .bg-red-800:hover, .bg-red-900:hover, | |
| button.bg-red-500:hover, button.bg-red-600:hover, button.bg-red-700:hover, button.bg-red-800:hover, button.bg-red-900:hover, | |
| .hover\\:bg-red-600:hover, .hover\\:bg-red-700:hover, .hover\\:bg-red-800:hover { | |
| background-color: #ef4444 ; /* red-500 - darker bright light red */ | |
| } | |
| /* Gray buttons to light gray */ | |
| .bg-gray-500, .bg-gray-600, .bg-gray-700, .bg-gray-800, .bg-gray-900, | |
| button.bg-gray-500, button.bg-gray-600, button.bg-gray-700, button.bg-gray-800, button.bg-gray-900 { | |
| background-color: #e5e7eb ; /* gray-200 - light gray */ | |
| color: #374151 ; /* gray-700 - dark text for contrast */ | |
| } | |
| .bg-gray-500:hover, .bg-gray-600:hover, .bg-gray-700:hover, .bg-gray-800:hover, .bg-gray-900:hover, | |
| button.bg-gray-500:hover, button.bg-gray-600:hover, button.bg-gray-700:hover, button.bg-gray-800:hover, button.bg-gray-900:hover, | |
| .hover\\:bg-gray-600:hover, .hover\\:bg-gray-700:hover, .hover\\:bg-gray-800:hover { | |
| background-color: #d1d5db ; /* gray-300 - darker light gray */ | |
| color: #374151 ; /* gray-700 - dark text for contrast */ | |
| } | |
| /* Ensure all text has proper contrast in light theme */ | |
| .text-white { | |
| color: #374151 ; /* gray-700 for better contrast on light backgrounds */ | |
| } | |
| /* Fix dark button text - ensure white text on dark backgrounds */ | |
| .bg-blue-500, .bg-blue-600, .bg-blue-700, .bg-blue-800, .bg-blue-900, | |
| .bg-red-500, .bg-red-600, .bg-red-700, .bg-red-800, .bg-red-900, | |
| .bg-green-500, .bg-green-600, .bg-green-700, .bg-green-800, .bg-green-900, | |
| .bg-purple-500, .bg-purple-600, .bg-purple-700, .bg-purple-800, .bg-purple-900, | |
| .bg-indigo-500, .bg-indigo-600, .bg-indigo-700, .bg-indigo-800, .bg-indigo-900, | |
| .bg-gray-700, .bg-gray-800, .bg-gray-900, | |
| .bg-sky-500, .bg-sky-600, .bg-sky-700, .bg-sky-800, .bg-sky-900 { | |
| color: #ffffff ; | |
| } | |
| /* Ensure buttons with dark backgrounds have white text */ | |
| button.bg-blue-500, button.bg-blue-600, button.bg-blue-700, | |
| button.bg-red-500, button.bg-red-600, button.bg-red-700, | |
| button.bg-green-500, button.bg-green-600, button.bg-green-700, | |
| button.bg-sky-500, button.bg-sky-600, button.bg-sky-700, | |
| .btn-primary, .btn-danger, .btn-success, .btn-info { | |
| color: #ffffff ; | |
| } | |
| /* Override any nested text color rules for dark buttons */ | |
| .bg-blue-500 *, .bg-blue-600 *, .bg-blue-700 *, | |
| .bg-red-500 *, .bg-red-600 *, .bg-red-700 *, | |
| .bg-green-500 *, .bg-green-600 *, .bg-green-700 *, | |
| .bg-sky-500 *, .bg-sky-600 *, .bg-sky-700 * { | |
| color: inherit ; | |
| } | |
| {% block head_extra_styles %} | |
| {% endblock %} | |
| </style> | |
| {% block head_extra_scripts %}{% endblock %} | |
| </head> | |
| <body class="bg-white min-h-screen text-gray-900 pt-6 pb-16"> | |
| {% block content %}{% endblock %} | |
| <!-- 底部版权 --> | |
| <div | |
| class="fixed bottom-0 left-0 w-full py-3 bg-white bg-opacity-95 backdrop-blur-md text-sm text-gray-800 border-t border-gray-200 flex flex-col items-center space-y-1" | |
| > | |
| <!-- 第一行 --> | |
| <div class="flex items-center justify-center space-x-2"> | |
| <span>© <span id="copyright-year"></span> by</span> | |
| <a | |
| href="https://linux.do/u/snaily" | |
| target="_blank" | |
| class="text-primary-600 hover:text-primary-800 transition duration-300 flex items-center" | |
| > | |
| <img | |
| src="https://linux.do/user_avatar/linux.do/snaily/288/306510_2.gif" | |
| alt="snaily" | |
| class="inline-block w-5 h-5 rounded-full align-middle mr-1" | |
| />snaily | |
| </a> | |
| <span class="text-gray-400">|</span> | |
| <a | |
| href="https://github.com/snailyp/gemini-balance" | |
| target="_blank" | |
| class="text-primary-600 hover:text-primary-800 transition duration-300 flex items-center" | |
| > | |
| <i class="fab fa-github mr-1"></i> GitHub | |
| </a> | |
| </div> | |
| <!-- 第二行 --> | |
| <div class="flex items-center justify-center space-x-2 text-xs"> | |
| <a | |
| href="https://gb-docs.snaily.top/guide/supportme.html" | |
| target="_blank" | |
| class="text-primary-600 hover:text-primary-800 transition duration-300 flex items-center" | |
| > | |
| <i class="fas fa-drumstick-bite text-yellow-600 mr-1"></i> 给作者加鸡腿 | |
| </a> | |
| <span class="text-gray-400">|</span> | |
| <a | |
| href="https://gb-docs.snaily.top" | |
| target="_blank" | |
| class="text-primary-600 hover:text-primary-800 transition duration-300 flex items-center" | |
| > | |
| <i class="fas fa-book mr-1"></i> 在线文档 | |
| </a> | |
| <span class="text-gray-400">|</span> | |
| <a | |
| href="https://t.me/+soaHax5lyI0wZDVl" | |
| target="_blank" | |
| class="text-primary-600 hover:text-primary-800 transition duration-300 flex items-center" | |
| > | |
| <i class="fab fa-telegram-plane mr-1"></i> 交流群 | |
| </a> | |
| <span class="text-gray-400">|</span> | |
| <span class="text-yellow-600 font-semibold flex items-center"> | |
| <i class="fas fa-exclamation-triangle mr-1"></i>免费项目,谨防诈骗 | |
| </span> | |
| <span id="version-info-container" class="inline-flex items-center"> | |
| <!-- Version info will be loaded here by JavaScript --> | |
| </span> | |
| </div> | |
| </div> | |
| <!-- 通用JS --> | |
| <script> | |
| // 设置版权年份 | |
| document.getElementById("copyright-year").textContent = | |
| new Date().getFullYear(); | |
| // 滚动到顶部/底部函数 (如果页面需要) | |
| function scrollToTop() { | |
| window.scrollTo({ top: 0, behavior: "smooth" }); | |
| } | |
| function scrollToBottom() { | |
| window.scrollTo({ | |
| top: document.body.scrollHeight, | |
| behavior: "smooth", | |
| }); | |
| } | |
| // 显示通知 | |
| function showNotification(message, type = "success", duration = 3000) { | |
| const notification = | |
| document.getElementById("notification") || | |
| createNotificationElement(); | |
| if (!notification) return; | |
| notification.textContent = message; | |
| notification.className = "notification show"; // Reset classes | |
| if (type === "error") { | |
| notification.classList.add("error"); | |
| } | |
| // Clear previous timeout if exists | |
| if (notification.timeoutId) { | |
| clearTimeout(notification.timeoutId); | |
| } | |
| notification.timeoutId = setTimeout(() => { | |
| notification.classList.remove("show"); | |
| // Optional: remove the element after fade out if dynamically created | |
| // setTimeout(() => notification.remove(), 300); | |
| }, duration); | |
| } | |
| // Helper to create notification element if it doesn't exist | |
| function createNotificationElement() { | |
| let notification = document.getElementById("notification"); | |
| if (!notification) { | |
| notification = document.createElement("div"); | |
| notification.id = "notification"; | |
| notification.className = "notification"; | |
| document.body.appendChild(notification); | |
| } | |
| return notification; | |
| } | |
| // 页面刷新带加载状态 | |
| function refreshPage(button) { | |
| if (button) { | |
| const icon = button.querySelector("i"); | |
| if (icon) { | |
| icon.classList.add("loading-spin"); | |
| } | |
| } | |
| setTimeout(() => { | |
| window.location.reload(); | |
| }, 300); // Short delay to show spinner | |
| } | |
| // --- Version Check --- | |
| const versionInfoContainer = document.getElementById( | |
| "version-info-container" | |
| ); | |
| async function fetchVersionInfo() { | |
| if (!versionInfoContainer) return; | |
| versionInfoContainer.innerHTML = | |
| '<span class="mx-1">|</span><span class="text-xs text-gray-700">检查更新中...</span>'; // Initial loading state | |
| try { | |
| const response = await fetch("/api/version/check"); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| let versionHtml = `<span class="mx-1">|</span><span class="text-xs text-gray-800">v${data.current_version}</span>`; | |
| if (data.update_available) { | |
| versionHtml += ` | |
| <span class="mx-1">|</span> | |
| <a href="https://github.com/snailyp/gemini-balance/releases/latest" target="_blank" class="text-yellow-600 hover:text-yellow-800 transition duration-300 animate-pulse"> | |
| <i class="fas fa-arrow-up"></i> 新版本: v${data.latest_version} | |
| </a>`; | |
| } else if (data.error_message) { | |
| versionHtml += ` | |
| <span class="mx-1">|</span> | |
| <span class="text-xs text-red-500" title="${data.error_message}">更新检查失败</span>`; | |
| } else { | |
| versionHtml += `<span class="mx-1">|</span><span class="text-xs text-green-500">已是最新</span>`; // Indicate up-to-date | |
| } | |
| versionInfoContainer.innerHTML = versionHtml; | |
| } catch (error) { | |
| console.error("Error fetching version info:", error); | |
| versionInfoContainer.innerHTML = `<span class="mx-1">|</span><span class="text-xs text-red-500" title="无法连接到服务器或解析响应">更新检查失败</span>`; | |
| } | |
| } | |
| // Fetch immediately on load | |
| fetchVersionInfo(); | |
| // Fetch periodically (e.g., every hour) | |
| setInterval(fetchVersionInfo, 3600000); // 3600000 ms = 1 hour | |
| </script> | |
| {% block body_scripts %}{% endblock %} | |
| </body> | |
| </html> | |