首页
旅人图鉴
秘纹图鉴
特殊页面
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
管理员
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。 如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */ // ============================================= // 动态导航菜单系统 // ============================================= // 导航菜单数据 var menuJsonData = [ { "name": "首页", "link": "首页", "children": [] }, { "name": "旅人图鉴", "link": "旅人图鉴", "children": [ { "name": "测试旅人1", "link": "测试旅人1" }, { "name": "测试旅人2", "link": "测试旅人2" } ] }, { "name": "秘纹图鉴", "link": "秘纹图鉴", "children": [] }, { "name": "特殊页面", "link": "特殊:特殊页面", "children": [] } ]; // 导航菜单管理器 var NavigationMenu = { // 初始化所有导航菜单 initAll: function() { // 确保容器存在 NavigationMenu.ensureContainerExists(); // 初始化容器 $('.custom-navigation-container').each(function() { NavigationMenu.initContainer($(this)); }); }, // 确保容器存在,如果不存在则在.header-nav-inner头部插入 ensureContainerExists: function() { // 如果容器已存在,直接返回 if ($('.custom-navigation-container').length > 0) { return; } // 查找.header-nav-inner元素 var $headerNavInner = $('.header-nav-inner'); if ($headerNavInner.length === 0) { console.warn('找不到.header-nav-inner元素,无法插入导航菜单'); return; } // 创建导航容器 var $container = $('<div>', { class: 'custom-navigation-container', id: 'custom-navigation-menu' }); // 插入到.header-nav-inner的头部 $headerNavInner.prepend($container); console.log('导航容器已插入到.header-nav-inner头部'); }, // 初始化单个容器 initContainer: function($container) { // 防止重复初始化 if ($container.data('initialized')) { return; } $container.data('initialized', true); // 加载导航数据 NavigationMenu.loadNavData() .then(function(navData) { // 构建导航菜单 NavigationMenu.buildNavigation($container, navData); }) .catch(function(error) { console.error('加载导航数据失败:', error); NavigationMenu.showError($container, error); }); }, // 加载导航数据 loadNavData: function() { return new Promise(function(resolve, reject) { resolve(menuJsonData); }); }, // 构建导航菜单 buildNavigation: function($container, navData) { // 创建导航菜单HTML var navHTML = NavigationMenu.createNavHTML(navData); $container.html(navHTML); // 绑定事件 NavigationMenu.bindNavEvents($container); // 添加响应式菜单按钮(移动端) NavigationMenu.addMobileMenuButton($container); // 初始化当前页面高亮 NavigationMenu.highlightCurrentPage($container); }, // 创建导航HTML(递归) createNavHTML: function(menuItems, level) { level = level || 1; if (!menuItems || menuItems.length === 0) { return ''; } var ulClass = level === 1 ? 'nav-menu-primary' : 'nav-menu-sub nav-menu-level-' + level; var html = '<ul class="' + ulClass + '">'; menuItems.forEach(function(item, index) { var hasChildren = item.children && item.children.length > 0; var liClass = 'nav-item'; var aClass = 'nav-link'; var submenuHTML = ''; if (hasChildren) { liClass += ' has-children'; aClass += ' has-children-link'; submenuHTML = NavigationMenu.createNavHTML(item.children, level + 1); } // 构建链接 var href = item.link ? mw.util.getUrl(item.link) : '#'; var iconHTML = item.icon ? '<span class="nav-icon">' + item.icon + '</span>' : ''; var nameHTML = '<span class="nav-text">' + item.name + '</span>'; var arrowHTML = hasChildren ? '<span class="nav-arrow">▶</span>' : ''; html += '<li class="' + liClass + '" data-link="' + (item.link || '') + '">'; html += '<a href="' + href + '" class="' + aClass + '" title="' + (item.name || '') + '">'; html += iconHTML + nameHTML + arrowHTML; html += '</a>'; html += submenuHTML; html += '</li>'; // 在一级菜单项之间添加分隔符(除了最后一个) if (level === 1 && index < menuItems.length - 1) { html += '<span class="navigation-separator"></span>'; } }); html += '</ul>'; return html; }, // 绑定导航事件 bindNavEvents: function($container) { // 用于存储菜单的计时器 var menuTimers = {}; // 子菜单切换(桌面端悬停,移动端点击) if (window.innerWidth >= 768) { // 桌面端:悬停显示子菜单 $container.on('mouseenter', '.nav-item.has-children', function(e) { var $this = $(this); var menuId = $this.data('link') || $this.index(); // 清除可能存在的关闭计时器 if (menuTimers[menuId]) { clearTimeout(menuTimers[menuId]); delete menuTimers[menuId]; } // 关闭其他打开的菜单 $container.find('.nav-item.hover').not($this).removeClass('hover'); $container.find('.nav-menu-sub.active').not($this.find('.nav-menu-sub')).removeClass('active'); // 显示当前菜单 $this.addClass('hover'); $this.find('.nav-menu-sub').first().addClass('active'); }); $container.on('mouseleave', '.nav-item.has-children', function(e) { var $this = $(this); var menuId = $this.data('link') || $this.index(); var $submenu = $this.find('.nav-menu-sub').first(); // 设置延迟关闭计时器 menuTimers[menuId] = setTimeout(function() { $this.removeClass('hover'); $submenu.removeClass('active'); delete menuTimers[menuId]; }, 300); // 300ms延迟,避免鼠标短暂离开时立即关闭 }); // 当鼠标进入子菜单时,清除关闭计时器 $container.on('mouseenter', '.nav-menu-sub', function(e) { var $submenu = $(this); var $parent = $submenu.closest('.nav-item'); var menuId = $parent.data('link') || $parent.index(); // 清除父菜单的关闭计时器 if (menuTimers[menuId]) { clearTimeout(menuTimers[menuId]); delete menuTimers[menuId]; } }); // 当鼠标离开子菜单时,设置关闭计时器 $container.on('mouseleave', '.nav-menu-sub', function(e) { var $submenu = $(this); var $parent = $submenu.closest('.nav-item'); var menuId = $parent.data('link') || $parent.index(); // 设置延迟关闭计时器 menuTimers[menuId] = setTimeout(function() { $parent.removeClass('hover'); $submenu.removeClass('active'); delete menuTimers[menuId]; }, 300); }); } else { // 移动端:点击切换子菜单 $container.on('click', '.nav-link.has-children-link', function(e) { e.preventDefault(); e.stopPropagation(); var $link = $(this); var $parent = $link.closest('.nav-item'); var $submenu = $parent.find('.nav-menu-sub').first(); if ($submenu.hasClass('active')) { $submenu.removeClass('active'); $parent.removeClass('expanded'); } else { // 关闭其他打开的菜单 $container.find('.nav-menu-sub.active').removeClass('active'); $container.find('.nav-item.expanded').removeClass('expanded'); $submenu.addClass('active'); $parent.addClass('expanded'); } }); } // 点击外部关闭菜单 $(document).on('click touchstart', function(e) { if (!$(e.target).closest('.custom-navigation-container').length) { $('.custom-navigation-container').find('.nav-menu-sub.active').removeClass('active'); $('.custom-navigation-container').find('.nav-item.expanded').removeClass('expanded'); $('.custom-navigation-container').find('.nav-item.hover').removeClass('hover'); // 清除所有计时器 for (var timerId in menuTimers) { if (menuTimers.hasOwnProperty(timerId)) { clearTimeout(menuTimers[timerId]); } } menuTimers = {}; } }); }, // 添加移动端菜单按钮 addMobileMenuButton: function($container) { var $button = $('<button>', { class: 'nav-mobile-toggle', html: '<span class="nav-toggle-icon">☰</span>', click: function() { $container.toggleClass('mobile-open'); $(this).toggleClass('active'); } }); $container.prepend($button); }, // 高亮当前页面 highlightCurrentPage: function($container) { var currentPage = mw.config.get('wgPageName'); if (!currentPage) return; // 解码页面名称 currentPage = decodeURIComponent(currentPage); // 查找匹配的导航项 $container.find('.nav-item[data-link]').each(function() { var link = $(this).data('link'); if (link && link === currentPage) { $(this).addClass('current-page'); $(this).find('.nav-link').first().addClass('current'); // 展开父级菜单 $(this).parents('.nav-item.has-children').addClass('expanded'); $(this).parents('.nav-menu-sub').addClass('active'); } }); }, // 显示错误信息 showError: function($container, error) { $container.html( '<div class="nav-error">' + ' <div class="error-icon">⚠️</div>' + ' <div class="error-title">导航菜单加载失败</div>' + ' <div class="error-message">' + error + '</div>' + ' <button class="error-retry" onclick="window.location.reload()">重试</button>' + '</div>' ); } }; // 添加导航菜单样式 function addNavigationStyles() { if ($('#navigation-styles').length) { return; } var styles = ` <style id="navigation-styles"> /* 导航容器 */ .custom-navigation-container { flex: 1; position: relative; background: #4b5082; border-radius: 8px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; z-index: 1000; } /* 分隔符样式 */ .navigation-separator { display: inline-block; width: 1px; height: 20px; background-color: rgba(255, 255, 255, 0.2); margin: 0 5px; vertical-align: middle; } /* 错误状态 */ .nav-error { text-align: center; padding: 30px; color: #ecf0f1; } .error-icon { font-size: 40px; margin-bottom: 15px; } .error-title { font-size: 18px; font-weight: 600; margin-bottom: 10px; color: #e74c3c; } .error-message { font-size: 14px; margin-bottom: 20px; opacity: 0.8; } .error-retry { padding: 8px 20px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; transition: background-color 0.3s; } .error-retry:hover { background: #2980b9; } /* 移动端菜单按钮 */ .nav-mobile-toggle { display: none; position: absolute; top: 10px; right: 10px; background: transparent; border: none; color: white; font-size: 24px; cursor: pointer; z-index: 1001; padding: 5px 10px; border-radius: 4px; } /* 主菜单 */ .nav-menu-primary { display: flex; margin: 0; padding: 0; list-style: none; align-items: center; } /* 导航项 */ .nav-item { position: relative; margin: 0; padding: 0; } .nav-item > .nav-link { display: flex; align-items: center; gap: 8px; padding: 5px 20px; color: #ecf0f1; text-decoration: none !important; font-size: 15px; font-weight: 500; transition: all 0.3s ease; white-space: nowrap; } .nav-link:hover { background: rgba(255, 255, 255, 0.1); color: #3498db; } .nav-link.current { color: #3498db; font-weight: 600; } .nav-item.current-page > .nav-link { color: #3498db; font-weight: 600; } .nav-icon { font-size: 16px; line-height: 1; } .nav-text { flex: 1; } .nav-arrow { font-size: 10px; margin-left: 5px; transition: transform 0.3s; } .nav-item.expanded > .nav-link > .nav-arrow { transform: rotate(90deg); } /* 子菜单 */ .nav-menu-sub { display: none; position: absolute; top: 100%; left: 0; min-width: 220px; background: white; border-radius: 0 0 8px 8px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); list-style: none; margin: 0; padding: 8px 0; z-index: 1000; } .nav-menu-sub.active { display: block; } .nav-menu-level-2 { background: #505587; } .nav-menu-level-3 { background: #2c3e50; } /* 子菜单项 */ .nav-menu-sub .nav-item { border-bottom: 1px solid rgba(255, 255, 255, 0.05); } .nav-menu-sub .nav-item:last-child { border-bottom: none; } .nav-menu-sub .nav-link { padding: 8px 20px; color: #ecf0f1; font-size: 14px; } .nav-menu-sub .nav-link:hover { background: rgba(255, 255, 255, 0.1); color: #3498db; } /* 三级菜单位置 */ .nav-menu-level-2 .nav-item.has-children > .nav-menu-sub { top: 0; left: 100%; border-radius: 0 8px 8px 8px; } /* 响应式设计 */ @media (max-width: 767px) { .custom-navigation-container { border-radius: 0; box-shadow: none; } .navigation-separator { display: none; } .nav-mobile-toggle { display: block; } .nav-menu-primary { display: none; flex-direction: column; padding: 10px 0; } .custom-navigation-container.mobile-open .nav-menu-primary { display: flex; } .nav-menu-sub { position: static; display: none; background: rgba(0, 0, 0, 0.2); box-shadow: none; padding-left: 20px; margin: 0; border-radius: 0; } .nav-menu-sub.active { display: block; } .nav-menu-level-2 .nav-item.has-children > .nav-menu-sub { position: static; left: auto; border-radius: 0; } .nav-link { padding: 12px 20px; } .nav-item.has-children > .nav-link { padding-right: 40px; } } @media (min-width: 768px) { .nav-item:hover > .nav-menu-sub { display: block; } .nav-menu-sub { animation: fadeInUp 0.3s ease; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } } </style> `; $('head').append(styles); } // 页面加载完成后初始化 $(document).ready(function() { // 添加样式 addNavigationStyles(); // 初始化导航菜单 NavigationMenu.initAll(); // 监听页面内容动态加载 mw.hook('wikipage.content').add(function($content) { // 重新确保容器存在并初始化 NavigationMenu.ensureContainerExists(); NavigationMenu.initAll(); }); // 窗口大小变化时重新绑定事件 $(window).on('resize', function() { // 移除所有事件,重新绑定 $('.custom-navigation-container').off(); NavigationMenu.initAll(); }); }); // 全局函数:重新加载导航菜单(可用于调试) window.reloadNavigation = function() { // 确保容器存在 NavigationMenu.ensureContainerExists(); $('.custom-navigation-container').each(function() { $(this).removeData('initialized').empty(); NavigationMenu.initContainer($(this)); }); }; // 全局函数:手动插入导航菜单到指定位置 window.insertNavigationTo = function(selector) { // 移除现有的导航容器 $('.custom-navigation-container').remove(); // 在指定位置插入新容器 var $target = $(selector); if ($target.length === 0) { console.error('找不到目标元素: ' + selector); return false; } var $container = $('<div>', { class: 'custom-navigation-container', id: 'custom-navigation-menu' }); $target.prepend($container); // 重新初始化导航菜单 reloadNavigation(); return true; }; // ============================================= // 角色属性查看器 - 动态创建版本 // ============================================= // 角色数据管理器 var CharacterDataManager = { cache: {}, getCharacterData: function(characterId) { var self = this; // 检查缓存 if (self.cache[characterId]) { return Promise.resolve(self.cache[characterId]); } return new Promise(function(resolve, reject) { // 构建数据页面路径 var dataSource = 'Data:Character/' + characterId + '.json'; $.get("http://trekkers-wiki.jvav.net.cn/index.php", { action: 'raw', title: dataSource }).done(function(data) { try { var characterData = JSON.parse(data); // 缓存数据 self.cache[characterId] = characterData; resolve(characterData); } catch (e) { reject('解析JSON数据失败: ' + e.message); } }).fail(function(error) { reject('API请求失败: ' + error); }); }); }, clearCache: function() { this.cache = {}; } }; // 主初始化函数 $(document).ready(function() { // 添加全局样式 addCharacterStatsStyles(); // 测试代码 // 初始化所有角色属性容器 $('.character-stats-container').each(function() { createCharacterStatsWidget($(this)); }); // 当有新内容加载时也初始化 mw.hook('wikipage.content').add(function($content) { $content.find('.character-stats-container').each(function() { if (!$(this).find('.character-stats-widget').length) { createCharacterStatsWidget($(this)); } }); }); }); // 添加样式到页面 function addCharacterStatsStyles() { if ($('#character-stats-styles').length) { return; // 样式已存在 } var styles = ` <style id="character-stats-styles"> .character-stats-widget { max-width: 800px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 30px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } .character-header { text-align: center; margin-bottom: 20px; } .character-name { color: #4a6fa5; margin-bottom: 10px; font-size: 28px; } .character-description { color: #666; font-style: italic; font-size: 16px; } .loading-message, .error-message { text-align: center; padding: 20px; color: #666; font-size: 16px; } .error-message { color: #d32f2f; background-color: #ffebee; border-radius: 4px; border: 1px solid #f5c6cb; } .level-selector { margin-bottom: 30px; } .level-display { text-align: center; font-size: 24px; font-weight: bold; margin-bottom: 15px; color: #4a6fa5; } .slider-container { position: relative; margin-bottom: 10px; } .slider-container .level-slider { width: 100%; height: 10px; -webkit-appearance: none; appearance: none; background: linear-gradient(to right, #e0e0e0, #4a6fa5); outline: none; border-radius: 5px; cursor: pointer; } .slider-container .level-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; border-radius: 50%; background: #4a6fa5; cursor: pointer; border: 3px solid white; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); transition: all 0.2s; } .slider-container .level-slider::-webkit-slider-thumb:hover { background: #3a5a80; transform: scale(1.1); } .slider-container .level-slider::-moz-range-thumb { width: 24px; height: 24px; border-radius: 50%; background: #4a6fa5; cursor: pointer; border: 3px solid white; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .quick-buttons { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 5px; margin-top: 10px; } .level-btn { flex: 1; min-width: 60px; padding: 10px 5px; background-color: #e9ecef; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.2s; font-size: 14px; } .level-btn:hover { background-color: #d0d8e2; transform: translateY(-2px); } .level-btn.active { background-color: #4a6fa5; color: white; box-shadow: 0 2px 4px rgba(74, 111, 165, 0.3); } .stats-container { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px; } .stat-card { background-color: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); border-left: 4px solid #4a6fa5; transition: transform 0.2s; } .stat-card:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .stat-card.attack { border-left-color: #ff6b6b; } .stat-card.health { border-left-color: #4caf50; } .stat-title { font-size: 18px; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; font-weight: 600; } .stat-card .stat-value { font-size: 32px; font-weight: bold; margin-bottom: 15px; color: #333; } .stat-card .attack .stat-value { color: #ff6b6b; } .stat-card .health .stat-value { color: #4caf50; } .stat-progress { height: 12px; background-color: #e9ecef; border-radius: 6px; overflow: hidden; margin-bottom: 10px; } .stat-bar { height: 100%; border-radius: 6px; width: 0%; transition: width 0.5s ease; } .attack .stat-bar { background: linear-gradient(90deg, #ff6b6b, #ff8e8e); } .health .stat-bar { background: linear-gradient(90deg, #4caf50, #66bb6a); } .stat-growth { margin-top: 10px; font-size: 14px; color: #666; font-style: italic; } @media (max-width: 768px) { .character-stats-widget { padding: 20px; margin: 10px; } .stats-container { grid-template-columns: 1fr; gap: 15px; } .quick-buttons { gap: 3px; } .level-btn { min-width: 50px; padding: 8px 3px; font-size: 12px; } .character-name { font-size: 24px; } .stat-card .stat-value { font-size: 28px; } } @media (max-width: 480px) { .character-stats-widget { padding: 15px; } .level-btn { min-width: 40px; padding: 6px 2px; font-size: 11px; } .quick-buttons { gap: 2px; } } </style> `; $('head').append(styles); } // 创建角色属性查看器 function createCharacterStatsWidget($container) { var characterId = $container.data('character'); if (!characterId) { $container.html('<div class="error-message">错误:未指定角色ID</div>'); return; } // 创建 Widget HTML 结构 var widgetHTML = ` <div class="character-stats-widget"> <div class="character-header"> <h2 class="character-name">加载中...</h2> <p class="character-description"></p> </div> <div class="level-selector"> <div class="level-display">当前等级: <span class="current-level">1</span></div> <div class="slider-container"> <input type="range" min="1" max="90" value="1" class="level-slider"> </div> <div class="quick-buttons"> <button class="level-btn" data-level="1">1级</button> <button class="level-btn" data-level="10">10级</button> <button class="level-btn" data-level="20">20级</button> <button class="level-btn" data-level="30">30级</button> <button class="level-btn" data-level="40">40级</button> <button class="level-btn" data-level="50">50级</button> <button class="level-btn" data-level="60">60级</button> <button class="level-btn" data-level="70">70级</button> <button class="level-btn" data-level="80">80级</button> <button class="level-btn" data-level="90">90级</button> </div> </div> <div class="stats-container"> <div class="stat-card attack"> <div class="stat-title"> <span>⚔️ 攻击力</span> </div> <div class="stat-value attack-value">-</div> <div class="stat-progress"> <div class="stat-bar attack-bar"></div> </div> <div class="stat-growth">每级成长: <span class="attack-growth">-</span></div> </div> <div class="stat-card health"> <div class="stat-title"> <span>❤️ 生命值</span> </div> <div class="stat-value health-value">-</div> <div class="stat-progress"> <div class="stat-bar health-bar"></div> </div> <div class="stat-growth">每级成长: <span class="health-growth">-</span></div> </div> </div> <div class="loading-message">正在加载角色数据...</div> <div class="error-message" style="display: none;"></div> </div> `; // 插入 HTML $container.html(widgetHTML); // 显示加载状态 var $widget = $container.find('.character-stats-widget'); $widget.find('.level-selector, .stats-container').hide(); $widget.find('.loading-message').show(); // 加载角色数据并初始化 CharacterDataManager.getCharacterData(characterId) .then(function(characterData) { initCharacterStats($widget, characterData); $widget.find('.loading-message').hide(); $widget.find('.level-selector, .stats-container').show(); }) .catch(function(error) { console.error('加载角色数据失败:', error); $widget.find('.loading-message').hide(); $widget.find('.error-message').text('加载角色数据失败: ' + error).show(); }); } // 初始化角色属性显示 function initCharacterStats($widget, characterData) { // 防止重复初始化 if ($widget.data('initialized')) { return; } $widget.data('initialized', true); // 更新角色信息 $widget.find('.character-name').text(characterData.name); $widget.find('.character-description').text(characterData.description); // 生成完整的等级数据 var fullLevelData = generateFullLevelData(characterData); // 获取UI元素 var $levelSlider = $widget.find('.level-slider'); var $currentLevel = $widget.find('.current-level'); var $attackValue = $widget.find('.attack-value'); var $healthValue = $widget.find('.health-value'); var $attackBar = $widget.find('.attack-bar'); var $healthBar = $widget.find('.health-bar'); var $attackGrowth = $widget.find('.attack-growth'); var $healthGrowth = $widget.find('.health-growth'); var $quickButtons = $widget.find('.level-btn'); // 更新显示函数 function updateDisplay(level) { var stats = fullLevelData[level]; $currentLevel.text(level); $attackValue.text(formatNumber(stats.attack)); $healthValue.text(formatNumber(stats.health)); // 显示成长值 if (characterData.stats) { $attackGrowth.text('+' + (characterData.stats.attack_growth || '?')); $healthGrowth.text('+' + (characterData.stats.health_growth || '?')); } // 更新进度条宽度 (基于最大值的百分比) var maxAttack = fullLevelData[90].attack; var maxHealth = fullLevelData[90].health; $attackBar.css('width', (stats.attack / maxAttack) * 100 + '%'); $healthBar.css('width', (stats.health / maxHealth) * 100 + '%'); // 更新快速按钮激活状态 $quickButtons.removeClass('active'); $quickButtons.filter('[data-level="' + level + '"]').addClass('active'); } // 事件绑定 $levelSlider.on('input', function() { updateDisplay(parseInt(this.value)); }); $quickButtons.on('click', function() { var level = parseInt($(this).data('level')); $levelSlider.val(level); updateDisplay(level); }); // 添加键盘支持 $levelSlider.on('keydown', function(e) { var currentValue = parseInt(this.value); switch(e.key) { case 'ArrowLeft': case 'ArrowDown': e.preventDefault(); this.value = Math.max(1, currentValue - 1); updateDisplay(this.value); break; case 'ArrowRight': case 'ArrowUp': e.preventDefault(); this.value = Math.min(90, currentValue + 1); updateDisplay(this.value); break; case 'Home': e.preventDefault(); this.value = 1; updateDisplay(this.value); break; case 'End': e.preventDefault(); this.value = 90; updateDisplay(this.value); break; } }); // 初始显示 updateDisplay(1); } // 生成完整等级数据 function generateFullLevelData(characterData) { var fullData = {}; var baseAttack = (characterData.stats && characterData.stats.base_attack) || 100; var baseHealth = (characterData.stats && characterData.stats.base_health) || 1000; var attackGrowth = (characterData.stats && characterData.stats.attack_growth) || 25; var healthGrowth = (characterData.stats && characterData.stats.health_growth) || 300; // 生成1-90级的完整数据 for (var level = 1; level <= 90; level++) { // 如果有预定义的数据,使用预定义数据,否则计算 if (characterData.levels && characterData.levels[level]) { fullData[level] = characterData.levels[level]; } else { fullData[level] = { attack: baseAttack + attackGrowth * (level - 1), health: baseHealth + healthGrowth * (level - 1) }; } } return fullData; } // 数字格式化函数 function formatNumber(num) { if (num >= 1000000) { return (num / 1000000).toFixed(1) + 'M'; } else if (num >= 1000) { return (num / 1000).toFixed(1) + 'K'; } return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } // ============================================= // 赛季BOSS展示页面功能模块 // ============================================= // 赛季BOSS页面初始化器 var SeasonBossPage = { // 初始化所有赛季BOSS页面 initAll: function() { $('.season-boss-page').each(function() { SeasonBossPage.initPage($(this)); }); }, // 初始化单个页面 initPage: function($page) { // 防止重复初始化 if ($page.data('page-initialized') === 'true') { return; } $page.data('page-initialized', 'true'); // 绑定标签切换事件 SeasonBossPage.bindTabEvents($page); // 初始化第一个可见的赛季内容 SeasonBossPage.activateFirstTab($page); }, // 绑定标签切换事件 bindTabEvents: function($page) { // 使用事件委托处理标签点击 $page.on('click', '.season-tab', function(e) { e.preventDefault(); var $tab = $(this); var seasonId = $tab.data('season'); // 如果已经是激活状态,则不处理 if ($tab.hasClass('active')) { return; } // 切换标签和内容 SeasonBossPage.switchSeason($page, seasonId); }); // 添加键盘支持 $page.on('keydown', '.season-tab', function(e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); $(this).trigger('click'); } }); }, // 切换赛季显示 switchSeason: function($page, seasonId) { // 移除所有激活状态 $page.find('.season-tab').removeClass('active'); $page.find('.season-content').removeClass('active'); // 添加新的激活状态 $page.find('.season-tab[data-season="' + seasonId + '"]').addClass('active'); $page.find('#' + seasonId).addClass('active'); // 触发自定义事件,以便其他模块可以监听赛季切换 $(document).trigger('seasonboss:seasonchanged', { seasonId: seasonId, page: $page }); // 记录切换日志(仅开发时使用) if (console && console.log) { console.log('赛季切换至: ' + seasonId); } }, // 激活第一个标签(如果当前没有激活的标签) activateFirstTab: function($page) { var $activeTab = $page.find('.season-tab.active'); // 如果没有激活的标签,激活第一个 if ($activeTab.length === 0) { var $firstTab = $page.find('.season-tab').first(); var seasonId = $firstTab.data('season'); $firstTab.addClass('active'); $page.find('#' + seasonId).addClass('active'); } }, // 添加新赛季(动态添加功能) addSeason: function($page, seasonData) { // 参数检查 if (!seasonData || !seasonData.id || !seasonData.name) { console.error('添加赛季失败:缺少必要的赛季数据'); return false; } var seasonId = seasonData.id; var seasonName = seasonData.name; var seasonIcon = seasonData.icon || '🏅'; // 检查赛季是否已存在 if ($page.find('.season-tab[data-season="' + seasonId + '"]').length > 0) { console.warn('赛季已存在:' + seasonId); return false; } // 创建新标签 var $newTab = $('<button>', { 'class': 'season-tab', 'data-season': seasonId, 'html': '<span class="season-icon">' + seasonIcon + '</span>' + '<span class="season-name">' + seasonName + '</span>' }); // 添加到标签容器 $page.find('.season-tabs').append($newTab); // 创建新内容区域 var $newContent = $('<div>', { 'class': 'season-content', 'id': seasonId }); // 如果提供了内容,添加到内容区域 if (seasonData.content) { $newContent.html(seasonData.content); } // 添加到内容区域 $page.find('.season-content').last().after($newContent); // 重新绑定事件(新添加的元素需要绑定) SeasonBossPage.bindTabEvents($page); return true; }, // 获取当前激活的赛季ID getActiveSeason: function($page) { var $activeTab = $page.find('.season-tab.active'); return $activeTab.length > 0 ? $activeTab.data('season') : null; }, // 跳转到指定赛季 goToSeason: function($page, seasonId) { var $targetTab = $page.find('.season-tab[data-season="' + seasonId + '"]'); if ($targetTab.length === 0) { console.error('赛季不存在:' + seasonId); return false; } SeasonBossPage.switchSeason($page, seasonId); return true; } }; // 页面加载完成后初始化赛季BOSS页面 $(document).ready(function() { SeasonBossPage.initAll(); // 监听内容动态加载(例如通过Widgets或AJAX) $(document).on('seasonboss:contentloaded', function() { SeasonBossPage.initAll(); }); }); // 当有新内容添加到页面时也初始化 mw.hook('wikipage.content').add(function($content) { $content.find('.season-boss-page').each(function() { SeasonBossPage.initPage($(this)); }); }); // ============================================= // 全局可用的函数 // ============================================= // 全局函数:跳转到指定赛季 window.goToSeason = function(seasonId) { var $page = $('.season-boss-page').first(); if ($page.length > 0) { return SeasonBossPage.goToSeason($page, seasonId); } return false; }; // 全局函数:获取当前赛季 window.getCurrentSeason = function() { var $page = $('.season-boss-page').first(); if ($page.length > 0) { return SeasonBossPage.getActiveSeason($page); } return null; }; // 全局函数:添加新赛季 window.addNewSeason = function(seasonData) { var $page = $('.season-boss-page').first(); if ($page.length > 0) { return SeasonBossPage.addSeason($page, seasonData); } return false; }; // ============================================= // 筛选系统 // ============================================= (function(mw, $) { 'use strict'; // 筛选器管理器 var FilterManager = { instances: {}, defaults: { persistState: true, autoApply: false }, // 初始化所有筛选器 initAll: function() { // 查找所有筛选器容器 $('.mw-filter-container').each(function() { var filterId = $(this).attr('id'); if (filterId) { FilterManager.init(filterId); } }); // 绑定全局事件 FilterManager.bindGlobalEvents(); }, // 初始化单个筛选器 init: function(filterId) { var $container = $('#' + filterId); if (!$container.length) return; // 获取配置 var $config = $container.siblings('.mw-filter-config'); var target = $config.data('mw-filter-target'); var auto = $config.data('mw-filter-auto') === 'true'; if (!target) { console.warn('筛选器缺少目标选择器:', filterId); return; } // 创建实例 var instance = { id: filterId, $container: $container, $target: $(target), config: { autoApply: auto, persistState: FilterManager.defaults.persistState }, state: { activeFilters: {}, allOptions: {} } }; // 收集筛选组数据 instance.$container.find('.mw-filter-group').each(function() { var $group = $(this); var groupName = $group.data('mw-filter-group'); // 收集选项数据 $group.find('.mw-filter-option').each(function() { var $option = $(this); var value = $option.data('mw-filter-value'); var display = $option.data('mw-filter-display'); if (!instance.state.allOptions[groupName]) { instance.state.allOptions[groupName] = {}; } instance.state.allOptions[groupName][value] = { $option: $option, value: value, display: display, isSelected: $option.hasClass('mw-filter-selected') }; // 初始化选中状态 if ($option.hasClass('mw-filter-selected')) { if (!instance.state.activeFilters[groupName]) { instance.state.activeFilters[groupName] = []; } if (instance.state.activeFilters[groupName].indexOf(value) === -1) { instance.state.activeFilters[groupName].push(value); } } }); }); // 隐藏统计和活动筛选(初始状态) instance.$container.find('.mw-filter-stats').hide(); instance.$container.find('.mw-active-filters').hide(); // 存储实例 FilterManager.instances[filterId] = instance; // 从URL恢复状态 FilterManager.restoreFromURL(instance); // 初始筛选 setTimeout(function() { FilterManager.applyFilters(instance); }, 100); }, // 绑定全局事件(事件委托) bindGlobalEvents: function() { // 筛选项点击 $(document).on('click', '.mw-filter-option', function(e) { e.preventDefault(); var $option = $(this); FilterManager.handleOptionClick($option); }); // 筛选项键盘事件 $(document).on('keydown', '.mw-filter-option', function(e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); var $option = $(this); FilterManager.handleOptionClick($option); } }); // 应用按钮 $(document).on('click', '.mw-filter-apply', function(e) { e.preventDefault(); var $container = $(this).closest('.mw-filter-container'); var filterId = $container.attr('id'); FilterManager.applyFilters(FilterManager.instances[filterId]); }); // 重置按钮 $(document).on('click', '.mw-filter-reset', function(e) { e.preventDefault(); var $container = $(this).closest('.mw-filter-container'); var filterId = $container.attr('id'); FilterManager.resetFilters(FilterManager.instances[filterId]); }); // 清除组按钮 $(document).on('click', '.mw-filter-group-clear', function(e) { e.preventDefault(); e.stopPropagation(); var $btn = $(this); var group = $btn.data('mw-filter-clear'); var $container = $btn.closest('.mw-filter-container'); var filterId = $container.attr('id'); FilterManager.clearGroup(FilterManager.instances[filterId], group); }); // 移除活动筛选标签 $(document).on('click', '.mw-active-filter-remove', function(e) { e.preventDefault(); e.stopPropagation(); var $removeBtn = $(this); var $tag = $removeBtn.closest('.mw-active-filter-tag'); var group = $tag.data('mw-filter-group'); var value = $tag.data('mw-filter-value'); var $container = $tag.closest('.mw-filter-container'); var filterId = $container.attr('id'); FilterManager.removeFilter(FilterManager.instances[filterId], group, value); }); // 键盘快捷键 $(document).on('keydown', function(e) { // ESC键重置当前聚焦的筛选器 if (e.key === 'Escape') { var $focused = $(':focus'); if ($focused.hasClass('mw-filter-option')) { var $container = $focused.closest('.mw-filter-container'); var filterId = $container.attr('id'); FilterManager.resetFilters(FilterManager.instances[filterId]); } } }); }, // 处理选项点击 handleOptionClick: function($option) { var group = $option.data('mw-filter-group'); var value = $option.data('mw-filter-value'); var $container = $option.closest('.mw-filter-container'); var filterId = $container.attr('id'); var instance = FilterManager.instances[filterId]; if (!instance) return; // 初始化组状态 if (!instance.state.activeFilters[group]) { instance.state.activeFilters[group] = []; } var filterValues = instance.state.activeFilters[group]; var index = filterValues.indexOf(value); var isSelected = $option.hasClass('mw-filter-selected'); // 处理"全部"选项 if (value === 'all') { if (!isSelected) { // 清除同组其他选项 instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"]') .removeClass('mw-filter-selected'); $option.addClass('mw-filter-selected'); instance.state.activeFilters[group] = []; // 自动应用 if (instance.config.autoApply) { FilterManager.applyFilters(instance); } } return; } // 移除"全部"选项的选中 instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="all"]') .removeClass('mw-filter-selected'); if (!isSelected) { // 添加选中 filterValues.push(value); $option.addClass('mw-filter-selected'); } else { // 移除选中 filterValues.splice(index, 1); $option.removeClass('mw-filter-selected'); // 如果清空了,选中"全部" if (filterValues.length === 0) { instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="all"]') .addClass('mw-filter-selected'); } } // 自动应用 if (instance.config.autoApply) { FilterManager.applyFilters(instance); } }, // 应用筛选 applyFilters: function(instance) { if (!instance) return; var matchedCount = 0; var totalCount = instance.$target.length; // 遍历所有目标元素 instance.$target.each(function() { var $item = $(this); var show = true; // 检查每个筛选条件 for (var group in instance.state.activeFilters) { var filterValues = instance.state.activeFilters[group]; if (filterValues.length === 0) continue; var itemValue = $item.data(group); if (itemValue === undefined) continue; // 检查是否匹配 var isMatched = false; for (var i = 0; i < filterValues.length; i++) { if (String(itemValue) === String(filterValues[i])) { isMatched = true; break; } } if (!isMatched) { show = false; break; } } // 更新元素状态 if (show) { $item.removeClass('mw-filtered-out').addClass('mw-filtered-in'); $item.show(); matchedCount++; } else { $item.removeClass('mw-filtered-in').addClass('mw-filtered-out'); $item.hide(); } }); // 更新UI FilterManager.updateActiveFilters(instance); FilterManager.updateStats(instance, matchedCount, totalCount); FilterManager.saveToURL(instance); // 触发事件 $(document).trigger('mwfilter:applied', { instance: instance, matched: matchedCount, total: totalCount }); }, // 重置筛选 resetFilters: function(instance) { if (!instance) return; // 清除所有选中状态 instance.state.activeFilters = {}; // 重置UI instance.$container.find('.mw-filter-option').removeClass('mw-filter-selected'); instance.$container.find('.mw-filter-option-all').addClass('mw-filter-selected'); // 重新初始化状态 for (var group in instance.state.allOptions) { instance.state.activeFilters[group] = []; } // 隐藏活动筛选标签 instance.$container.find('.mw-active-filters').hide() .find('.mw-active-filters-list').empty(); // 隐藏统计 instance.$container.find('.mw-filter-stats').hide(); // 应用筛选(显示所有) FilterManager.applyFilters(instance); // 清除URL FilterManager.clearURL(instance); }, // 清除单个组 clearGroup: function(instance, group) { if (!instance) return; // 清除该组所有选中 instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"]') .removeClass('mw-filter-selected'); // 选中"全部"选项 instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="all"]') .addClass('mw-filter-selected'); // 更新状态 instance.state.activeFilters[group] = []; // 应用筛选 FilterManager.applyFilters(instance); }, // 移除单个筛选 removeFilter: function(instance, group, value) { if (!instance) return; var filterValues = instance.state.activeFilters[group]; if (filterValues) { var index = filterValues.indexOf(value); if (index !== -1) { filterValues.splice(index, 1); // 更新UI instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="' + value + '"]') .removeClass('mw-filter-selected'); // 如果清空了,选中"全部" if (filterValues.length === 0) { instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="all"]') .addClass('mw-filter-selected'); } // 应用筛选 FilterManager.applyFilters(instance); } } }, // 更新活动筛选标签 updateActiveFilters: function(instance) { if (!instance) return; var $activeFilters = instance.$container.find('.mw-active-filters'); var $activeFiltersList = instance.$container.find('.mw-active-filters-list'); $activeFiltersList.empty(); var hasActiveFilters = false; for (var group in instance.state.activeFilters) { var filterValues = instance.state.activeFilters[group]; filterValues.forEach(function(value) { if (value === 'all') return; var $option = instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="' + value + '"]'); if (!$option.length) return; var displayText = $option.data('mw-filter-display') || value; var $groupHeader = instance.$container.find('.mw-filter-group[data-mw-filter-group="' + group + '"] h4'); var groupName = $groupHeader.length ? $groupHeader.text().replace(' 清除', '') : group; var $tag = $('<span class="mw-active-filter-tag"></span>') .attr('data-mw-filter-group', group) .attr('data-mw-filter-value', value) .html( '<span class="mw-active-filter-text">' + groupName + ': ' + displayText + '</span>' + '<span class="mw-active-filter-remove" tabindex="0" role="button">×</span>' ); $activeFiltersList.append($tag); hasActiveFilters = true; }); } if (hasActiveFilters) { $activeFilters.show(); } else { $activeFilters.hide(); } }, // 更新统计信息 updateStats: function(instance, matched, total) { if (!instance) return; var $stats = instance.$container.find('.mw-filter-stats'); if ($stats.length) { $stats.find('.mw-filter-total').text(total); $stats.find('.mw-filter-showing').text(matched); if (matched !== total) { $stats.show(); } else { $stats.hide(); } } }, // URL处理 saveToURL: function(instance) { if (!instance || !instance.config.persistState) return; var params = {}; for (var group in instance.state.activeFilters) { var values = instance.state.activeFilters[group]; if (values.length > 0 && !(values.length === 1 && values[0] === 'all')) { params[instance.id + '_' + group] = values.join(','); } } FilterManager.updateURL(params); }, restoreFromURL: function(instance) { if (!instance) return; var params = FilterManager.getURLParams(); for (var key in params) { if (key.startsWith(instance.id + '_')) { var group = key.replace(instance.id + '_', ''); var values = params[key].split(','); values.forEach(function(value) { var $option = instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="' + value + '"]'); if ($option.length) { $option.addClass('mw-filter-selected'); if (!instance.state.activeFilters[group]) { instance.state.activeFilters[group] = []; } if (instance.state.activeFilters[group].indexOf(value) === -1) { instance.state.activeFilters[group].push(value); } // 取消"全部"选项的选中 instance.$container.find('.mw-filter-option[data-mw-filter-group="' + group + '"][data-mw-filter-value="all"]') .removeClass('mw-filter-selected'); } }); } } }, clearURL: function(instance) { if (!instance) return; var params = FilterManager.getURLParams(); var changed = false; for (var key in params) { if (key.startsWith(instance.id + '_')) { delete params[key]; changed = true; } } if (changed) { FilterManager.updateURL(params); } }, getURLParams: function() { var params = {}; var search = window.location.search.substring(1); if (search) { var pairs = search.split('&'); pairs.forEach(function(pair) { var kv = pair.split('='); if (kv[0]) { params[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1] || ''); } }); } return params; }, updateURL: function(params) { var url = new URL(window.location); // 清除旧参数 var toDelete = []; url.searchParams.forEach(function(value, key) { toDelete.push(key); }); toDelete.forEach(function(key) { url.searchParams.delete(key); }); // 添加新参数 for (var key in params) { if (params[key]) { url.searchParams.set(encodeURIComponent(key), encodeURIComponent(params[key])); } } window.history.replaceState({}, '', url.toString()); } }; // 页面加载完成后初始化 $(function() { FilterManager.initAll(); }); // // 公开API(可选) // window.MediaWikiFilter = { // getInstance: function(filterId) { // return FilterManager.instances[filterId]; // }, // apply: function(filterId) { // var instance = FilterManager.instances[filterId]; // if (instance) { // FilterManager.applyFilters(instance); // } // }, // reset: function(filterId) { // var instance = FilterManager.instances[filterId]; // if (instance) { // FilterManager.resetFilters(instance); // } // } // }; })(mediaWiki, jQuery);
返回
MediaWiki:Common.js
。