| (function() {
|
| 'use strict';
|
|
|
| const API = window.location.origin;
|
| let userBadges = {};
|
|
|
| function isLoggedIn() {
|
| return sessionStorage.getItem('logged_in') === 'true';
|
| }
|
|
|
| function isAdmin() {
|
| return sessionStorage.getItem('is_admin') === 'true';
|
| }
|
|
|
| function saveLogin(username, isAdminUser, badge = null) {
|
| sessionStorage.setItem('logged_in', 'true');
|
| sessionStorage.setItem('username', username);
|
| sessionStorage.setItem('is_admin', isAdminUser ? 'true' : 'false');
|
| sessionStorage.setItem('user_badge', badge || '');
|
| sessionStorage.setItem('login_time', Date.now().toString());
|
| }
|
|
|
| function clearLogin() {
|
| sessionStorage.clear();
|
| }
|
|
|
| async function sha256(text) {
|
| try {
|
| const buf = new TextEncoder().encode(text);
|
| const hash = await crypto.subtle.digest('SHA-256', buf);
|
| const arr = Array.from(new Uint8Array(hash));
|
| return arr.map(b => b.toString(16).padStart(2, '0')).join('');
|
| } catch (error) {
|
| throw error;
|
| }
|
| }
|
|
|
| function showError(msg) {
|
| const el = document.getElementById('loginError');
|
| if (el) {
|
| el.textContent = '❌ ' + msg;
|
| el.classList.add('show');
|
| setTimeout(() => el.classList.remove('show'), 5000);
|
| }
|
| }
|
|
|
| function showSuccess(msg) {
|
| const el = document.getElementById('loginError');
|
| if (el) {
|
| el.innerHTML = msg;
|
| el.style.background = 'linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%)';
|
| el.style.color = '#065f46';
|
| el.style.borderColor = '#6ee7b7';
|
| el.classList.add('show');
|
| setTimeout(() => {
|
| el.classList.remove('show');
|
| el.style.background = '';
|
| el.style.color = '';
|
| el.style.borderColor = '';
|
| }, 2000);
|
| }
|
| }
|
|
|
| async function loadBadges() {
|
| try {
|
| const res = await fetch(`${API}/api/badges`);
|
| const data = await res.json();
|
| if (data.success) {
|
| userBadges = data.badges;
|
| }
|
| } catch (e) {
|
| }
|
| }
|
|
|
| function updateAdminUI() {
|
| const isAdminUser = isAdmin();
|
|
|
| const adminElements = document.querySelectorAll('.admin-only');
|
|
|
| adminElements.forEach(el => {
|
| if (isAdminUser) {
|
| el.style.display = '';
|
| el.style.visibility = 'visible';
|
| el.style.opacity = '1';
|
| el.classList.remove('hidden');
|
|
|
| if (el.classList.contains('tab-button')) {
|
| el.style.display = 'block';
|
| }
|
| } else {
|
| el.style.display = 'none';
|
| el.style.visibility = 'hidden';
|
| el.style.opacity = '0';
|
| el.classList.add('hidden');
|
| }
|
| });
|
| }
|
|
|
| function showMainPage() {
|
| const login = document.getElementById('loginOverlay');
|
| const main = document.getElementById('mainContainer');
|
|
|
| if (!login || !main) {
|
| return;
|
| }
|
|
|
| login.classList.add('hide');
|
| main.style.display = 'flex';
|
|
|
| const username = sessionStorage.getItem('username') || '未知';
|
| const isAdminUser = isAdmin();
|
| const userBadge = sessionStorage.getItem('user_badge') || '';
|
|
|
| const userEl = document.getElementById('currentUser');
|
| if (userEl) {
|
| userEl.textContent = username;
|
| }
|
|
|
| const badge = document.getElementById('userTypeBadge');
|
| if (badge) {
|
| badge.innerHTML = '';
|
| badge.className = 'user-type-badge';
|
|
|
| if (isAdminUser) {
|
| badge.innerHTML = '👑 管理员';
|
| badge.className = 'user-type-badge admin';
|
| } else if (userBadge && userBadges[userBadge]) {
|
| const badgeInfo = userBadges[userBadge];
|
|
|
| badge.innerHTML = `
|
| <span style="margin-right: 5px;">${badgeInfo.icon}</span>
|
| <span>${badgeInfo.name}</span>
|
| `;
|
| badge.style.background = badgeInfo.gradient;
|
| badge.style.color = badgeInfo.color;
|
| badge.style.border = `2px solid ${badgeInfo.border}`;
|
| badge.style.boxShadow = `0 2px 8px ${badgeInfo.glow}`;
|
| badge.style.padding = '6px 14px';
|
| badge.style.borderRadius = '20px';
|
| badge.style.fontSize = '0.85em';
|
| badge.style.fontWeight = '700';
|
| badge.style.display = 'inline-flex';
|
| badge.style.alignItems = 'center';
|
| } else {
|
| badge.innerHTML = '👤 普通用户';
|
| badge.className = 'user-type-badge user';
|
| }
|
| }
|
|
|
| updateAdminUI();
|
|
|
| setTimeout(() => checkAPI(), 100);
|
|
|
| setTimeout(() => {
|
| window.dispatchEvent(new Event('user-logged-in'));
|
| }, 200);
|
| }
|
|
|
| function showLoginPage() {
|
| const login = document.getElementById('loginOverlay');
|
| const main = document.getElementById('mainContainer');
|
|
|
| if (login) login.classList.remove('hide');
|
| if (main) main.style.display = 'none';
|
| }
|
|
|
| async function checkAPI() {
|
| try {
|
| const start = Date.now();
|
| const res = await fetch('/health');
|
| const time = Date.now() - start;
|
| const data = await res.json();
|
|
|
| const status = document.getElementById('apiStatus');
|
| const timeEl = document.getElementById('responseTime');
|
|
|
| if (status) {
|
| if (data.status === 'running') {
|
| status.textContent = '在线';
|
| status.className = 'status-value online';
|
| } else {
|
| status.textContent = '异常';
|
| status.className = 'status-value loading';
|
| }
|
| }
|
|
|
| if (timeEl) timeEl.textContent = time + 'ms';
|
| } catch (e) {
|
| const status = document.getElementById('apiStatus');
|
| if (status) {
|
| status.textContent = '离线';
|
| status.className = 'status-value offline';
|
| }
|
| }
|
| }
|
|
|
| async function handleLogin(e) {
|
| e.preventDefault();
|
|
|
| const user = document.getElementById('usernameInput');
|
| const pass = document.getElementById('passwordInput');
|
| const btn = document.getElementById('loginBtn');
|
|
|
| if (!user || !pass || !btn) {
|
| showError('页面元素错误');
|
| return;
|
| }
|
|
|
| const username = user.value.trim();
|
| const password = pass.value;
|
|
|
| if (!username || !password) {
|
| showError('请输入用户名和密码');
|
| return;
|
| }
|
|
|
| btn.disabled = true;
|
| btn.innerHTML = '<div class="loading-spinner-large" style="width: 16px; height: 16px; border-width: 3px; margin-right: 8px; display: inline-block; vertical-align: middle;"></div> 验证中...';
|
|
|
| try {
|
| const hash = await sha256(password);
|
|
|
| const res = await fetch('/api/verify-password', {
|
| method: 'POST',
|
| headers: { 'Content-Type': 'application/json' },
|
| body: JSON.stringify({ username, password_hash: hash })
|
| });
|
|
|
| const data = await res.json();
|
|
|
| if (data.success) {
|
| const isAdminUser = data.user?.is_admin || false;
|
| const userBadge = data.user?.badge || null;
|
|
|
|
|
| if (data.user_data) {
|
| const userDataKey = `user_data_${username}`;
|
| sessionStorage.setItem(userDataKey, JSON.stringify(data.user_data));
|
| console.log('✅ 用户数据已保存到 sessionStorage');
|
| }
|
|
|
|
|
| let welcomeMsg = '✅ 登录成功!';
|
|
|
|
|
| if (isAdminUser) {
|
| welcomeMsg += '<br><div style="margin-top: 10px; display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%); color: white; border-radius: 12px; font-weight: 700;">👑 欢迎管理员</div>';
|
| } else if (userBadge && userBadges[userBadge]) {
|
| const badgeInfo = userBadges[userBadge];
|
| welcomeMsg += `<br><div style="margin-top: 10px; display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: ${badgeInfo.gradient}; color: ${badgeInfo.color}; border: 2px solid ${badgeInfo.border}; box-shadow: 0 2px 8px ${badgeInfo.glow}; border-radius: 12px; font-weight: 700;"><span>${badgeInfo.icon}</span><span>欢迎 ${badgeInfo.name}</span></div>`;
|
| } else {
|
| welcomeMsg += '<br><div style="margin-top: 10px; color: #065f46; font-weight: 600;">👤 欢迎普通用户</div>';
|
| }
|
|
|
| showSuccess(welcomeMsg);
|
|
|
| saveLogin(username, isAdminUser, userBadge);
|
|
|
| await loadBadges();
|
|
|
| setTimeout(() => {
|
| showMainPage();
|
| }, 1500);
|
|
|
| } else {
|
| showError('用户名或密码错误');
|
| btn.disabled = false;
|
| btn.textContent = '🚀 立即登录';
|
| pass.value = '';
|
| }
|
|
|
| } catch (err) {
|
| showError('登录失败: ' + err.message);
|
| btn.disabled = false;
|
| btn.textContent = '🚀 立即登录';
|
| }
|
| }
|
|
|
| function togglePassword() {
|
| const input = document.getElementById('passwordInput');
|
| const btn = document.getElementById('togglePasswordBtn');
|
|
|
| if (!input || !btn) return;
|
|
|
| if (input.type === 'password') {
|
| input.type = 'text';
|
| btn.textContent = '🙈';
|
| } else {
|
| input.type = 'password';
|
| btn.textContent = '👁️';
|
| }
|
| }
|
|
|
| function handleLogout() {
|
| if (confirm('确定要退出吗?')) {
|
| clearLogin();
|
| location.reload();
|
| }
|
| }
|
|
|
| async function init() {
|
| await loadBadges();
|
|
|
| if (isLoggedIn()) {
|
| setTimeout(() => showMainPage(), 100);
|
| } else {
|
| showLoginPage();
|
| setTimeout(() => {
|
| const user = document.getElementById('usernameInput');
|
| if (user) user.focus();
|
| }, 100);
|
| }
|
|
|
| const form = document.getElementById('loginForm');
|
| const toggleBtn = document.getElementById('togglePasswordBtn');
|
| const logoutBtn = document.getElementById('logoutBtn');
|
|
|
| if (form) {
|
| form.addEventListener('submit', handleLogin);
|
| }
|
|
|
| if (toggleBtn) {
|
| toggleBtn.addEventListener('click', togglePassword);
|
| }
|
|
|
| if (logoutBtn) {
|
| logoutBtn.addEventListener('click', handleLogout);
|
| }
|
| }
|
|
|
| window.isAdmin = isAdmin;
|
| window.updateAdminUI = updateAdminUI;
|
|
|
| if (document.readyState === 'loading') {
|
| document.addEventListener('DOMContentLoaded', init);
|
| } else {
|
| init();
|
| }
|
| })(); |