123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- /**
- * 核心功能模块
- * 提供全局共享的工具函数和状态管理
- */
- // 全局变量和状态
- let isLoggedIn = false;
- let userPermissions = [];
- let systemConfig = {};
- /**
- * 初始化应用
- * 检查登录状态,加载基础配置
- */
- async function initApp() {
- // console.log('初始化应用...');
- // console.log('-------------调试信息开始-------------');
- // console.log('当前URL:', window.location.href);
- // console.log('浏览器信息:', navigator.userAgent);
- // console.log('DOM已加载状态:', document.readyState);
-
- // 检查当前页面是否为登录页
- const isLoginPage = window.location.pathname.includes('admin');
- // console.log('是否为管理页面:', isLoginPage);
-
- try {
- // 检查会话状态
- const sessionResult = await checkSession();
- const isAuthenticated = sessionResult.authenticated;
- // console.log('会话检查结果:', isAuthenticated);
- // 检查localStorage中的登录状态 (主要用于刷新页面时保持UI)
- const localLoginState = localStorage.getItem('isLoggedIn') === 'true';
-
- // 核心登录状态判断
- if (isAuthenticated) {
- // 已登录
- isLoggedIn = true;
- localStorage.setItem('isLoggedIn', 'true'); // 保持本地状态
-
- if (isLoginPage) {
- // 在登录页,但会话有效,显示管理界面
- // console.log('已登录,显示管理界面...');
- await loadSystemConfig();
- showAdminInterface();
- } else {
- // 在非登录页,正常显示
- // console.log('已登录,继续应用初始化...');
- await loadSystemConfig();
- showAdminInterface(); // 确保管理界面可见
- }
- } else {
- // 未登录
- isLoggedIn = false;
- localStorage.removeItem('isLoggedIn'); // 清除本地登录状态
-
- if (!isLoginPage) {
- // 在非登录页,重定向到登录页
- // console.log('未登录,重定向到登录页...');
- window.location.href = '/admin';
- return false;
- } else {
- // 在登录页,显示登录框
- // console.log('未登录,显示登录模态框...');
- hideLoadingIndicator();
- showLoginModal();
- }
- }
-
- // console.log('应用初始化完成');
- // console.log('-------------调试信息结束-------------');
- return isAuthenticated;
- } catch (error) {
- // console.error('初始化应用失败:', error);
- // console.log('-------------调试错误信息-------------');
- // console.log('错误堆栈:', error.stack);
- // console.log('错误类型:', error.name);
- // console.log('错误消息:', error.message);
- // console.log('---------------------------------------');
- showAlert('加载应用失败:' + error.message, 'error');
- hideLoadingIndicator();
- showLoginModal();
- return false;
- }
- }
- /**
- * 检查会话状态
- */
- async function checkSession() {
- try {
- const response = await fetch('/api/check-session', {
- headers: {
- 'Cache-Control': 'no-cache',
- 'X-Requested-With': 'XMLHttpRequest',
- 'Pragma': 'no-cache'
- },
- credentials: 'same-origin'
- });
-
- // 只关心请求是否成功以及认证状态
- if (response.ok) {
- const data = await response.json();
- return {
- authenticated: data.authenticated // 直接使用API返回的状态
- };
- }
-
- // 非OK响应(包括401)都视为未认证
- return {
- authenticated: false
- };
- } catch (error) {
- // console.error('检查会话状态出错:', error);
- return {
- authenticated: false,
- error: error.message
- };
- }
- }
- /**
- * 加载系统配置
- */
- function loadSystemConfig() {
- fetch('/api/config')
- .then(response => {
- if (!response.ok) {
- return response.text().then(text => {
- throw new Error(`加载配置失败: ${text || response.statusText || response.status}`);
- });
- }
- return response.json();
- })
- .then(config => {
- // console.log('加载配置成功:', config);
- // 应用配置
- applySystemConfig(config);
- })
- .catch(error => {
- // console.error('加载配置失败:', error);
- showAlert('加载配置失败: ' + error.message, 'warning');
- });
- }
- // 应用系统配置
- function applySystemConfig(config) {
- // 如果有proxyDomain配置,则更新输入框
- if (config.proxyDomain && document.getElementById('proxyDomain')) {
- document.getElementById('proxyDomain').value = config.proxyDomain;
- }
-
- // 更新logo配置输入框(管理页面不显示logo图片,只显示配置)
- if (document.getElementById('logoUrl')) {
- document.getElementById('logoUrl').value = config.logo || '';
- }
-
- // 应用其他配置...
- }
- /**
- * 显示管理界面
- */
- function showAdminInterface() {
- // console.log('开始显示管理界面...');
- hideLoadingIndicator();
-
- const adminContainer = document.getElementById('adminContainer');
- if (adminContainer) {
- // console.log('找到管理界面容器,设置为显示');
- adminContainer.style.display = 'flex';
- } else {
- // console.error('未找到管理界面容器元素 #adminContainer');
- }
-
- // console.log('管理界面已显示,正在初始化事件监听器');
-
- // 初始化菜单事件监听
- initEventListeners();
- }
- /**
- * 隐藏加载提示器
- */
- function hideLoadingIndicator() {
- // console.log('正在隐藏加载提示器...');
- const loadingIndicator = document.getElementById('loadingIndicator');
- if (loadingIndicator) {
- loadingIndicator.style.display = 'none';
- // console.log('加载提示器已隐藏');
- } else {
- // console.warn('未找到加载提示器元素 #loadingIndicator');
- }
- }
- /**
- * 显示登录模态框
- */
- function showLoginModal() {
- const loginModal = document.getElementById('loginModal');
- if (loginModal) {
- loginModal.style.display = 'flex';
- // 刷新验证码
- if (window.auth && typeof window.auth.refreshCaptcha === 'function') {
- window.auth.refreshCaptcha();
- }
- }
- }
- /**
- * 显示加载动画
- */
- function showLoading() {
- const loadingSpinner = document.getElementById('loadingSpinner');
- if (loadingSpinner) {
- loadingSpinner.style.display = 'block';
- }
- }
- /**
- * 隐藏加载动画
- */
- function hideLoading() {
- const loadingSpinner = document.getElementById('loadingSpinner');
- if (loadingSpinner) {
- loadingSpinner.style.display = 'none';
- }
- }
- /**
- * 显示警告消息
- * @param {string} message - 消息内容
- * @param {string} type - 消息类型 (info, success, error)
- * @param {string} title - 标题(可选)
- */
- function showAlert(message, type = 'info', title = '') {
- // 使用SweetAlert2替代自定义警告框,确保弹窗总是显示
- Swal.fire({
- title: title || (type === 'success' ? '成功' : (type === 'error' ? '错误' : '提示')),
- text: message,
- icon: type,
- timer: type === 'success' ? 2000 : undefined,
- timerProgressBar: type === 'success',
- confirmButtonColor: '#3d7cf4',
- confirmButtonText: '确定'
- });
- }
- /**
- * 显示确认对话框
- * @param {string} message - 消息内容
- * @param {Function} onConfirm - 确认回调
- * @param {Function} onCancel - 取消回调(可选)
- * @param {string} title - 标题(可选)
- */
- function showConfirm(message, onConfirm, onCancel, title = '确认') {
- Swal.fire({
- title: title,
- text: message,
- icon: 'question',
- showCancelButton: true,
- confirmButtonColor: '#3d7cf4',
- cancelButtonColor: '#6c757d',
- confirmButtonText: '确认',
- cancelButtonText: '取消'
- }).then((result) => {
- if (result.isConfirmed && typeof onConfirm === 'function') {
- onConfirm();
- } else if (typeof onCancel === 'function') {
- onCancel();
- }
- });
- }
- /**
- * 格式化日期时间
- */
- function formatDateTime(dateString) {
- if (!dateString) return '';
-
- const date = new Date(dateString);
- return date.toLocaleString('zh-CN', {
- year: 'numeric',
- month: '2-digit',
- day: '2-digit',
- hour: '2-digit',
- minute: '2-digit',
- second: '2-digit'
- });
- }
- /**
- * 防抖函数:限制函数在一定时间内只能执行一次
- */
- function debounce(func, wait = 300) {
- let timeout;
- return function(...args) {
- const later = () => {
- clearTimeout(timeout);
- func.apply(this, args);
- };
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- };
- }
- /**
- * 节流函数:保证一定时间内多次调用只执行一次
- */
- function throttle(func, wait = 300) {
- let timeout = null;
- let previous = 0;
-
- return function(...args) {
- const now = Date.now();
- const remaining = wait - (now - previous);
-
- if (remaining <= 0) {
- if (timeout) {
- clearTimeout(timeout);
- timeout = null;
- }
- previous = now;
- func.apply(this, args);
- } else if (!timeout) {
- timeout = setTimeout(() => {
- previous = Date.now();
- timeout = null;
- func.apply(this, args);
- }, remaining);
- }
- };
- }
- /**
- * 初始化事件监听
- */
- function initEventListeners() {
- // console.log('开始初始化事件监听器...');
-
- // 侧边栏菜单项事件
- const menuItems = document.querySelectorAll('.sidebar-nav li');
- // console.log('找到侧边栏菜单项数量:', menuItems.length);
- menuItems.forEach((item, index) => {
- const section = item.getAttribute('data-section');
- // console.log(`绑定事件到菜单项 #${index + 1}: ${section}`);
- item.addEventListener('click', () => showSection(section));
- });
- // console.log('侧边栏菜单事件监听器已绑定');
-
- // 用户中心按钮
- const userCenterBtn = document.getElementById('userCenterBtn');
- if (userCenterBtn) {
- // console.log('找到用户中心按钮,绑定事件');
- userCenterBtn.addEventListener('click', () => showSection('user-center'));
- }
- // 登出按钮 (侧边栏)
- const logoutBtn = document.getElementById('logoutBtn');
- if (logoutBtn) {
- // console.log('找到登出按钮,绑定事件');
- logoutBtn.addEventListener('click', () => {
- if (window.auth && typeof window.auth.logout === 'function') {
- window.auth.logout();
- }
- });
- }
- // 登出按钮 (用户中心)
- const ucLogoutBtn = document.getElementById('ucLogoutBtn');
- if (ucLogoutBtn) {
- // console.log('找到用户中心内登出按钮,绑定事件');
- ucLogoutBtn.addEventListener('click', () => {
- if (window.auth && typeof window.auth.logout === 'function') {
- window.auth.logout();
- }
- });
- }
- // console.log('事件监听器初始化完成');
- }
- /**
- * 显示指定的内容区域
- * @param {string} sectionId 要显示的内容区域ID
- */
- function showSection(sectionId) {
- // console.log('尝试显示内容区域:', sectionId);
- const contentSections = document.querySelectorAll('.content-section');
- const menuItems = document.querySelectorAll('.sidebar-nav li');
- // console.log('找到', contentSections.length, '个内容区域和', menuItems.length, '个菜单项');
- let sectionFound = false;
- contentSections.forEach(section => {
- if (section.id === sectionId) {
- section.classList.add('active');
- sectionFound = true;
- // console.log('成功激活内容区域:', sectionId);
- } else {
- section.classList.remove('active');
- }
- });
- if (!sectionFound) {
- // console.warn('未找到要显示的内容区域:', sectionId, '. 默认显示dashboard.');
- document.getElementById('dashboard').classList.add('active');
- sectionId = 'dashboard'; // 更新 sectionId 以便正确高亮菜单
- }
- let menuItemFound = false;
- menuItems.forEach(item => {
- if (item.getAttribute('data-section') === sectionId) {
- item.classList.add('active');
- menuItemFound = true;
- // console.log('成功激活菜单项:', sectionId);
- } else {
- item.classList.remove('active');
- }
- });
- if (!menuItemFound) {
- // console.warn('未找到要激活的菜单项 for section:', sectionId);
- // 尝试激活 dashboard 作为回退
- const dashboardItem = document.querySelector('.sidebar-nav li[data-section="dashboard"]');
- if(dashboardItem) dashboardItem.classList.add('active');
- }
- // 更新 URL hash
- window.location.hash = sectionId;
- // 刷新特定部分的内容,例如仪表盘
- if (sectionId === 'dashboard') {
- // console.log('已激活仪表盘,无需再次刷新系统状态');
- // if (window.systemStatus && typeof window.systemStatus.refreshSystemStatus === 'function') {
- // window.systemStatus.refreshSystemStatus();
- // }
- }
- // console.log('内容区域切换完成:', sectionId);
- }
- /**
- * 根据URL hash显示对应的区域
- */
- function showSectionFromHash() {
- const hash = window.location.hash.substring(1); // 移除 '#' 号
- if (hash) {
- // console.log('从URL Hash加载区域:', hash);
- showSection(hash);
- } else {
- // console.log('URL Hash为空,默认显示dashboard区域');
- showSection('dashboard'); // 默认显示仪表盘
- }
- }
- /**
- * 切换加载状态
- * @param {boolean} isLoading - 是否正在加载
- * @param {string} elementId - 目标元素ID
- * @param {string} originalText - 原始文本(可选)
- */
- function toggleLoadingState(isLoading, elementId, originalText = null) {
- const element = document.getElementById(elementId);
- if (!element) {
- // console.warn(`未找到元素 ${elementId} 来切换加载状态`);
- return;
- }
- if (isLoading) {
- element.disabled = true;
- // 可以考虑保存原始文本,如果按钮文本被修改了
- if (originalText && !element.dataset.originalText) {
- element.dataset.originalText = element.innerHTML;
- }
- element.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 加载中...';
- } else {
- element.disabled = false;
- if (element.dataset.originalText) {
- element.innerHTML = element.dataset.originalText;
- } else if (originalText) { // 如果没有保存的原始文本,但传入了,也使用
- element.innerHTML = originalText;
- }
- // 如果按钮文本没有被修改为 "加载中...",则不需要恢复
- }
- }
- // 页面加载时初始化
- document.addEventListener('DOMContentLoaded', function() {
- // console.log('DOM已加载,正在初始化应用...');
- initApp();
-
- // 检查URL参数,处理消息提示等
- const urlParams = new URLSearchParams(window.location.search);
-
- // 如果有message参数,显示相应的提示
- if (urlParams.has('message')) {
- const message = urlParams.get('message');
- let type = 'info';
-
- if (urlParams.has('type')) {
- type = urlParams.get('type');
- }
-
- showAlert(message, type);
- }
- });
- // 导出核心函数和变量 (如果需要在其他模块直接使用)
- window.core = {
- initApp,
- checkSession,
- loadSystemConfig,
- showAdminInterface,
- hideLoadingIndicator,
- showLoginModal,
- showAlert,
- showConfirm,
- showLoading,
- hideLoading,
- showSection,
- showSectionFromHash,
- formatDateTime,
- debounce,
- throttle,
- toggleLoadingState,
- initEventListeners
- };
|