Common.js:修订间差异
来自卡厄思梦境WIKI
小无编辑摘要 |
无编辑摘要 标签:已被回退 |
||
| 第1行: | 第1行: | ||
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */ | /* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */ | ||
/* 添加预加载 */ | |||
var preloadQueue = new Set(); | |||
var preloadWorker = null; | |||
/* 预加载管理器 */ | |||
function preloadCardData(character, cardName, deckType) { | |||
var cacheKey = character + '|' + cardName + '|' + (deckType || ''); | |||
if (!apiCache[cacheKey] && !preloadQueue.has(cacheKey)) { | |||
preloadQueue.add(cacheKey); | |||
if (!preloadWorker) { | |||
preloadWorker = setTimeout(processPreloadQueue, 100); | |||
} | |||
} | |||
} | |||
/* 批量处理预加载队列 */ | |||
function processPreloadQueue() { | |||
preloadWorker = null; | |||
if (preloadQueue.size === 0) return; | |||
var batch = Array.from(preloadQueue).slice(0, 5); // 每批处理5个 | |||
preloadQueue.clear(); | |||
batch.forEach(function(cacheKey) { | |||
var parts = cacheKey.split('|'); | |||
fetchCardHTML(parts[0], parts[1], parts[2], function() { | |||
// 预加载完成,数据已缓存 | |||
}); | |||
}); | |||
} | |||
/* 鼠标悬停时预加载 */ | |||
function initPreloadEvents() { | |||
document.addEventListener('mouseover', function(e) { | |||
var card = e.target.closest('.game-card'); | |||
if (card && !card.closest('#card-overlay')) { | |||
var character = card.dataset.character; | |||
var cardName = card.dataset.cardName; | |||
var derivedCards = card.dataset.derivedCards; | |||
// 预加载变体 | |||
preloadCardData(character, cardName, '灵光一闪'); | |||
preloadCardData(character, cardName, '神之一闪'); | |||
// 预加载衍生卡牌 | |||
if (derivedCards && derivedCards.trim() !== '') { | |||
var cardsList = derivedCards.split('、'); | |||
cardsList.forEach(function(name) { | |||
preloadCardData(character, name.trim(), ''); | |||
}); | |||
} | |||
} | |||
}); | |||
} | |||
/* 切换标签 */ | /* 切换标签 */ | ||
2025年10月9日 (四) 21:19的版本
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
/* 添加预加载 */
var preloadQueue = new Set();
var preloadWorker = null;
/* 预加载管理器 */
function preloadCardData(character, cardName, deckType) {
var cacheKey = character + '|' + cardName + '|' + (deckType || '');
if (!apiCache[cacheKey] && !preloadQueue.has(cacheKey)) {
preloadQueue.add(cacheKey);
if (!preloadWorker) {
preloadWorker = setTimeout(processPreloadQueue, 100);
}
}
}
/* 批量处理预加载队列 */
function processPreloadQueue() {
preloadWorker = null;
if (preloadQueue.size === 0) return;
var batch = Array.from(preloadQueue).slice(0, 5); // 每批处理5个
preloadQueue.clear();
batch.forEach(function(cacheKey) {
var parts = cacheKey.split('|');
fetchCardHTML(parts[0], parts[1], parts[2], function() {
// 预加载完成,数据已缓存
});
});
}
/* 鼠标悬停时预加载 */
function initPreloadEvents() {
document.addEventListener('mouseover', function(e) {
var card = e.target.closest('.game-card');
if (card && !card.closest('#card-overlay')) {
var character = card.dataset.character;
var cardName = card.dataset.cardName;
var derivedCards = card.dataset.derivedCards;
// 预加载变体
preloadCardData(character, cardName, '灵光一闪');
preloadCardData(character, cardName, '神之一闪');
// 预加载衍生卡牌
if (derivedCards && derivedCards.trim() !== '') {
var cardsList = derivedCards.split('、');
cardsList.forEach(function(name) {
preloadCardData(character, name.trim(), '');
});
}
}
});
}
/* 切换标签 */
(function() {
'use strict';
function initTabSwitcher() {
var tabContainers = document.querySelectorAll('.resp-tabs');
tabContainers.forEach(function(container) {
var tabButtons = container.querySelectorAll('.czn-list-style');
if (tabButtons.length === 0) return;
var tabContents = container.querySelectorAll('.resp-tab-content');
// 初始化
tabButtons.forEach(function(button, index) {
button.classList.toggle('active', index === 0);
});
if (tabContents.length > 0) {
tabContents.forEach(function(content, index) {
content.style.display = index === 0 ? 'block' : 'none';
});
}
// 点击事件
tabButtons.forEach(function(button, index) {
button.addEventListener('click', function(e) {
e.preventDefault();
// 更新标签状态
tabButtons.forEach(function(btn, i) {
btn.classList.toggle('active', i === index);
});
// 切换内容
if (tabContents.length > 0) {
tabContents.forEach(function(content, i) {
content.style.display = i === index ? 'block' : 'none';
});
}
});
});
});
}
// 初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTabSwitcher);
} else {
initTabSwitcher();
}
})();
/* 角色立绘切换 */
$(document).ready(function() {
// 使用事件委托来确保动态内容也能响应
$(document).on('click', '.character-switch-btn', function() {
// 如果点击的是已经激活的按钮,不执行任何操作
if ($(this).hasClass('active')) {
return;
}
var targetType = $(this).attr('data-target');
var container = $(this).closest('#character-container');
var imageWrapper = container.find('.character-image-wrapper');
var allImages = imageWrapper.find('.character-image');
// 先将所有图片淡出
allImages.each(function() {
$(this).css('opacity', '0');
});
// 延迟后切换显示状态
setTimeout(function() {
allImages.each(function() {
$(this).css('display', 'none');
});
// 显示目标图片
imageWrapper.find('[data-image-type="' + targetType + '"]').each(function() {
$(this).css('display', 'block');
// 强制重绘
$(this)[0].offsetHeight;
$(this).css('opacity', '1');
});
}, 300);
// 更新按钮样式
container.find('.character-switch-btn').each(function() {
$(this).removeClass('active');
$(this).css({
'background': 'rgba(0,0,0,0.5)',
'cursor': 'pointer'
});
});
// 设置当前按钮为激活状态
$(this).addClass('active');
$(this).css({
'background': 'rgba(70, 130, 255, 0.8)',
'cursor': 'default'
});
});
// 鼠标悬停效果(仅对非激活按钮有效)
$(document).on('mouseenter', '.character-switch-btn:not(.active)', function() {
$(this).css('background', 'rgba(70, 130, 255, 0.5)');
});
$(document).on('mouseleave', '.character-switch-btn:not(.active)', function() {
$(this).css('background', 'rgba(0,0,0,0.5)');
});
});
/* 悬浮目录 */
$(document).ready(function() {
// 只在有目录的页面上执行
if ($('.toc').length > 0) {
// 创建侧边目录
var $sidebar = $('<div id="toc-sidebar"><div id="toc-sidebar-trigger">展开目录</div><div id="toc-sidebar-content"></div></div>');
$('body').append($sidebar);
// 提取并修复目录内容
var tocUl = $('<ul></ul>');
// 避免重复的目录项
var processedItems = new Set();
// 从原始目录构建新目录
$('.toc ul li').each(function() {
var $link = $(this).find('a').first();
var href = $link.attr('href');
var $number = $link.find('.tocnumber').first();
var $text = $link.find('.toctext').first();
// 创建唯一标识符,避免重复添加
var itemId = $number.text() + '-' + $text.text();
if (!processedItems.has(itemId)) {
processedItems.add(itemId);
// 创建新的目录项
var $li = $('<li></li>');
var $newLink = $('').attr('href', href);
// 如果有编号,则添加编号
if ($number.length) {
$newLink.append($('<span class="tocnumber"></span>').text($number.text()));
$newLink.append(' ');
}
$newLink.append($('<span class="toctext"></span>').text($text.text()));
$li.append($newLink);
tocUl.append($li);
}
});
$('#toc-sidebar-content').append(tocUl);
// 点击展开/折叠事件处理
$('#toc-sidebar-trigger').click(function() {
$('#toc-sidebar').toggleClass('expanded');
// 根据展开/折叠状态更改按钮文字
if ($('#toc-sidebar').hasClass('expanded')) {
$('#toc-sidebar-trigger').text('隐藏目录');
} else {
$('#toc-sidebar-trigger').text('展开目录');
}
});
}
});
/* 卡牌 */
(function() {
// 防止重复初始化
if (window.cardSystemInitialized) return;
window.cardSystemInitialized = true;
// 缓存DOM元素
var overlayCache = null;
var containerCache = null;
// 保存当前卡牌信息,用于返回
var currentCardInfo = null;
// 添加历史栈来记录浏览历史
var viewHistory = [];
// API缓存
var apiCache = {};
// 预加载队列
var preloadQueue = new Set();
var preloadWorker = null;
// 智能缓存管理器
var cacheManager = {
maxSize: 100, // 最大缓存数量
accessTime: {}, // 记录访问时间
set: function(key, value) {
apiCache[key] = value;
this.accessTime[key] = Date.now();
// 检查缓存大小
var keys = Object.keys(apiCache);
if (keys.length > this.maxSize) {
// 删除最久未使用的缓存
var oldestKey = keys[0];
var oldestTime = this.accessTime[oldestKey] || 0;
for (var i = 1; i < keys.length; i++) {
var time = this.accessTime[keys[i]] || 0;
if (time < oldestTime) {
oldestKey = keys[i];
oldestTime = time;
}
}
delete apiCache[oldestKey];
delete this.accessTime[oldestKey];
}
},
get: function(key) {
if (apiCache[key]) {
this.accessTime[key] = Date.now();
return apiCache[key];
}
return null;
}
};
// 添加Loading动画CSS
function addLoadingStyles() {
if (!document.getElementById('card-loading-styles')) {
var style = document.createElement('style');
style.id = 'card-loading-styles';
style.textContent = `
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.card-fade-in {
animation: fadeIn 0.3s ease-in;
}
`;
document.head.appendChild(style);
}
}
// 创建loading占位符
function createLoadingPlaceholder(text, scale) {
var placeholder = document.createElement('div');
placeholder.className = 'card-loading';
var baseStyle = 'width: 168px; height: 230px; background: rgba(255,255,255,0.1); border: 2px dashed rgba(255,255,255,0.3); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white;';
if (scale) {
baseStyle += ' transform: scale(' + scale + '); transform-origin: center center;';
}
placeholder.style.cssText = baseStyle;
placeholder.innerHTML = '<div style="text-align: center;">' +
'<div class="loading-spinner" style="border: 3px solid rgba(255,255,255,0.3); border-top: 3px solid white; border-radius: 50%; width: 30px; height: 30px; animation: spin 1s linear infinite; margin: 0 auto 10px;"></div>' +
'<div style="font-size: 12px;">' + (text || '加载中...') + '</div>' +
'</div>';
return placeholder;
}
// 预加载管理器
function preloadCardData(character, cardName, deckType) {
var cacheKey = character + '|' + cardName + '|' + (deckType || '');
if (!cacheManager.get(cacheKey) && !preloadQueue.has(cacheKey)) {
preloadQueue.add(cacheKey);
if (!preloadWorker) {
preloadWorker = setTimeout(processPreloadQueue, 100);
}
}
}
// 批量处理预加载队列
function processPreloadQueue() {
preloadWorker = null;
if (preloadQueue.size === 0) return;
var batch = Array.from(preloadQueue).slice(0, 5); // 每批处理5个
batch.forEach(function(key) {
preloadQueue.delete(key);
});
batch.forEach(function(cacheKey) {
var parts = cacheKey.split('|');
fetchCardHTML(parts[0], parts[1], parts[2], function() {
// 预加载完成,数据已缓存
});
});
// 如果还有剩余,继续处理
if (preloadQueue.size > 0) {
preloadWorker = setTimeout(processPreloadQueue, 200);
}
}
// 创建遮罩层和容器
function createCardOverlay() {
if (overlayCache && containerCache) {
return { overlay: overlayCache, container: containerCache };
}
// 创建遮罩
var overlay = document.createElement('div');
overlay.id = 'card-overlay';
overlay.style.cssText = 'display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 9999; overflow-y: auto;';
// 创建容器
var container = document.createElement('div');
container.id = 'card-display-container';
container.style.cssText = 'position: relative; min-height: 100vh; padding: 40px 20px; display: flex; align-items: center; justify-content: center;';
overlay.appendChild(container);
document.body.appendChild(overlay);
// 点击遮罩关闭
overlay.addEventListener('click', function(e) {
if (e.target === overlay) {
closeCardDisplay();
}
});
overlayCache = overlay;
containerCache = container;
return { overlay: overlay, container: container };
}
// 创建关闭按钮
function createCloseButton() {
var closeBtn = document.createElement('div');
closeBtn.style.cssText = 'position: fixed; top: 20px; right: 20px; width: 40px; height: 40px; background: rgba(255,255,255,0.1); border: 2px solid white; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; z-index: 10001; transition: all 0.3s;';
closeBtn.innerHTML = '<span style="color: white; font-size: 24px; font-weight: bold; line-height: 1;">×</span>';
closeBtn.onmouseover = function() {
this.style.background = 'rgba(255,255,255,0.2)';
this.style.transform = 'scale(1.1)';
};
closeBtn.onmouseout = function() {
this.style.background = 'rgba(255,255,255,0.1)';
this.style.transform = 'scale(1)';
};
closeBtn.onclick = function() {
closeCardDisplay();
};
return closeBtn;
}
// 关闭卡牌展示
function closeCardDisplay() {
var overlay = document.getElementById('card-overlay');
if (overlay) {
overlay.style.display = 'none';
var container = overlay.querySelector('#card-display-container');
if (container) {
container.innerHTML = '';
}
}
currentCardInfo = null;
viewHistory = []; // 清空历史栈
}
// 返回上一层
function goBack() {
if (viewHistory.length > 1) {
// 移除当前视图
viewHistory.pop();
// 获取上一个视图
var previousView = viewHistory.pop();
// 根据视图类型重新渲染
if (previousView.type === 'enlarged') {
showEnlargedCard(previousView.data.element, false); // false 表示不添加到历史
} else if (previousView.type === 'derivedCards') {
showAllDerivedCards(previousView.data.character, previousView.data.derivedCardsList, false);
} else if (previousView.type === 'variantCards') {
showVariantCards(previousView.data.character, previousView.data.cardName, previousView.data.variantType, false);
}
} else if (viewHistory.length === 1) {
// 只剩一层,关闭弹窗
closeCardDisplay();
}
}
// 获取卡牌HTML
function fetchCardHTML(character, cardName, deckType, callback) {
var cacheKey = character + '|' + cardName + '|' + (deckType || '');
// 检查缓存
var cached = cacheManager.get(cacheKey);
if (cached) {
callback(cached);
return;
}
var api = new mw.Api();
var wikitext = '{{#invoke:卡牌|main|' + character + '|' + cardName + '|' + (deckType || '') + '}}';
api.parse(wikitext).done(function(html) {
cacheManager.set(cacheKey, html);
callback(html);
}).fail(function() {
callback('<div style="color: white;">加载失败</div>');
});
}
// 批量获取卡牌HTML
function fetchCardHTMLBatch(requests, callback) {
var results = {};
var pending = [];
// 先检查缓存
requests.forEach(function(req) {
var cacheKey = req.character + '|' + req.cardName + '|' + (req.deckType || '');
var cached = cacheManager.get(cacheKey);
if (cached) {
results[cacheKey] = cached;
} else {
pending.push(req);
}
});
// 如果全部都有缓存,直接返回
if (pending.length === 0) {
callback(results);
return;
}
// 批量请求未缓存的
var completed = 0;
pending.forEach(function(req) {
fetchCardHTML(req.character, req.cardName, req.deckType, function(html) {
var cacheKey = req.character + '|' + req.cardName + '|' + (req.deckType || '');
results[cacheKey] = html;
completed++;
if (completed === pending.length) {
callback(results);
}
});
});
}
// 检查卡牌变体
function checkCardVariants(character, cardName, callback) {
var variants = { lingguang: false, shenguang: false };
var checkCount = 0;
var totalChecks = 2;
function checkComplete() {
checkCount++;
if (checkCount === totalChecks) {
callback(variants);
}
}
// 并行检查两种变体
fetchCardHTML(character, cardName, '灵光一闪', function(html) {
if (html && !html.includes('找不到卡组')) {
variants.lingguang = true;
}
checkComplete();
});
fetchCardHTML(character, cardName, '神之一闪', function(html) {
if (html && !html.includes('找不到卡组')) {
variants.shenguang = true;
}
checkComplete();
});
}
// 放大显示卡牌
function showEnlargedCard(cardElement, addToHistory) {
if (addToHistory !== false) {
addToHistory = true;
}
var elements = createCardOverlay();
var container = elements.container;
var cardName = cardElement.dataset.cardName;
var character = cardElement.dataset.character;
var deckType = cardElement.dataset.deckType;
var derivedCards = cardElement.dataset.derivedCards;
var hasMechanism = cardElement.dataset.hasMechanism === 'true';
// 添加Loading样式
addLoadingStyles();
// 保存当前卡牌信息
currentCardInfo = {
element: cardElement,
cardName: cardName,
character: character,
deckType: deckType,
derivedCards: derivedCards
};
// 添加到历史栈
if (addToHistory) {
viewHistory.push({
type: 'enlarged',
data: currentCardInfo
});
}
// 重置容器样式
container.style.cssText = 'position: relative; min-height: 100vh; padding: 40px 20px; display: flex; align-items: center; justify-content: center;';
// 创建内容包装器
var contentWrapper = document.createElement('div');
contentWrapper.style.cssText = 'display: flex; align-items: flex-start; gap: 0px; position: relative;';
// 立即显示主卡牌
var centerContainer = document.createElement('div');
centerContainer.style.cssText = 'display: flex; flex-direction: column; align-items: center; gap: 0px;';
var mainCardContainer = document.createElement('div');
mainCardContainer.style.cssText = 'width: 336px; height: 460px; display: flex; align-items: center; justify-content: center; position: relative;';
var cardInner = document.createElement('div');
cardInner.style.cssText = 'transform: scale(2); position: relative;';
var enlargedCard = cardElement.cloneNode(true);
enlargedCard.style.width = '168px';
enlargedCard.style.height = '230px';
enlargedCard.style.cursor = 'default';
enlargedCard.style.position = 'relative';
enlargedCard.style.display = 'block';
enlargedCard.onclick = null;
enlargedCard.classList.add('card-fade-in');
cardInner.appendChild(enlargedCard);
mainCardContainer.appendChild(cardInner);
centerContainer.appendChild(mainCardContainer);
// 处理衍生卡牌
if (derivedCards && derivedCards.trim() !== '') {
var leftContainer = document.createElement('div');
leftContainer.style.cssText = 'display: flex; flex-direction: column; gap: 0px; align-items: center;';
var derivedCardsList = derivedCards.split('、');
var derivedCardWrapper = document.createElement('div');
derivedCardWrapper.style.cssText = 'width: 252px; height: 345px; display: flex; align-items: center; justify-content: center;';
// 先显示占位符
var placeholder = createLoadingPlaceholder('加载衍生卡牌...', 1.5);
derivedCardWrapper.appendChild(placeholder);
leftContainer.appendChild(derivedCardWrapper);
// 异步加载衍生卡牌
fetchCardHTML(character, derivedCardsList[0].trim(), '', function(html) {
var firstDerivedCard = document.createElement('div');
firstDerivedCard.id = 'derived-cards-display';
firstDerivedCard.style.cssText = 'transform: scale(1.5); transform-origin: center center; opacity: 0;';
firstDerivedCard.innerHTML = html;
var cards = firstDerivedCard.querySelectorAll('.game-card');
cards.forEach(function(card) {
card.style.cursor = 'default';
card.onclick = function(e) {
e.stopPropagation();
e.preventDefault();
};
});
derivedCardWrapper.removeChild(placeholder);
derivedCardWrapper.appendChild(firstDerivedCard);
// 淡入动画
setTimeout(function() {
firstDerivedCard.style.transition = 'opacity 0.3s';
firstDerivedCard.style.opacity = '1';
}, 10);
});
// 如果有多个衍生卡牌,添加查看全部按钮
if (derivedCardsList.length > 1) {
var viewAllBtn = document.createElement('div');
viewAllBtn.style.cssText = 'padding: 10px 20px; background: linear-gradient(135deg, #4a90e2, #357abd); color: white; border-radius: 6px; cursor: pointer; white-space: nowrap; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); transition: transform 0.2s; margin-top: 0px;';
viewAllBtn.textContent = '查看所有衍生卡牌';
viewAllBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
viewAllBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
viewAllBtn.onclick = function() {
showAllDerivedCards(character, derivedCardsList);
};
leftContainer.appendChild(viewAllBtn);
}
contentWrapper.appendChild(leftContainer);
}
// 创建按钮容器(异步检查变体)
var buttonsContainer = document.createElement('div');
buttonsContainer.style.cssText = 'display: flex; gap: 15px; white-space: nowrap; min-height: 50px; align-items: center; justify-content: center;';
// 添加loading指示器
var checkingVariants = document.createElement('div');
checkingVariants.style.cssText = 'color: rgba(255,255,255,0.5); font-size: 12px;';
checkingVariants.textContent = '检查变体卡牌...';
buttonsContainer.appendChild(checkingVariants);
centerContainer.appendChild(buttonsContainer);
// 异步检查变体
checkCardVariants(character, cardName, function(variants) {
buttonsContainer.removeChild(checkingVariants);
if (variants.lingguang) {
var lingguangBtn = document.createElement('div');
lingguangBtn.style.cssText = 'padding: 10px 30px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); transition: transform 0.2s; white-space: nowrap; min-width: 120px; text-align: center; opacity: 0;';
lingguangBtn.textContent = '灵光一闪';
lingguangBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
lingguangBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
lingguangBtn.onclick = function() {
showVariantCards(character, cardName, '灵光一闪');
};
buttonsContainer.appendChild(lingguangBtn);
// 淡入动画
setTimeout(function() {
lingguangBtn.style.transition = 'opacity 0.3s';
lingguangBtn.style.opacity = '1';
}, 10);
}
if (variants.shenguang) {
var shenguangBtn = document.createElement('div');
shenguangBtn.style.cssText = 'padding: 10px 30px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); transition: transform 0.2s; white-space: nowrap; min-width: 120px; text-align: center; opacity: 0;';
shenguangBtn.textContent = '神之一闪';
shenguangBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
shenguangBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
shenguangBtn.onclick = function() {
showVariantCards(character, cardName, '神之一闪');
};
buttonsContainer.appendChild(shenguangBtn);
// 淡入动画
setTimeout(function() {
shenguangBtn.style.transition = 'opacity 0.3s';
shenguangBtn.style.opacity = '1';
}, 10);
}
// 如果没有变体,移除按钮容器
if (!variants.lingguang && !variants.shenguang) {
centerContainer.removeChild(buttonsContainer);
}
});
contentWrapper.appendChild(centerContainer);
// 添加右侧机制说明
if (hasMechanism) {
var mechanismContainer = cardElement.nextElementSibling;
if (mechanismContainer && mechanismContainer.classList.contains('mechanism-container')) {
var mechanismDisplay = document.createElement('div');
mechanismDisplay.style.cssText = 'display: flex; flex-direction: column; gap: 0px; max-width: 320px; min-width: 280px;';
mechanismDisplay.innerHTML = mechanismContainer.innerHTML;
mechanismDisplay.style.display = 'flex';
contentWrapper.appendChild(mechanismDisplay);
}
}
container.innerHTML = '';
container.appendChild(contentWrapper);
container.appendChild(createCloseButton());
elements.overlay.style.display = 'block';
}
// 显示所有衍生卡牌
function showAllDerivedCards(character, derivedCardsList, addToHistory) {
if (addToHistory !== false) {
addToHistory = true;
}
var overlay = document.getElementById('card-overlay');
var container = document.getElementById('card-display-container');
// 添加到历史栈
if (addToHistory) {
viewHistory.push({
type: 'derivedCards',
data: {
character: character,
derivedCardsList: derivedCardsList
}
});
}
// 清空当前内容
container.innerHTML = '';
container.style.cssText = 'position: relative; padding: 40px; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center;';
// 创建标题
var title = document.createElement('div');
title.style.cssText = 'color: white; font-size: 28px; font-weight: bold; margin-bottom: 30px; text-align: center;';
title.textContent = '衍生卡牌';
container.appendChild(title);
// 创建卡牌容器
var cardsContainer = document.createElement('div');
cardsContainer.style.cssText = 'display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; max-width: 1400px; transform: scale(1.5); transform-origin: center center; padding: 40px;';
// 先添加占位符
var uniqueCards = [...new Set(derivedCardsList.map(function(name) { return name.trim(); }))];
var placeholders = [];
uniqueCards.forEach(function() {
var placeholder = createLoadingPlaceholder('加载中...', null);
placeholders.push(placeholder);
cardsContainer.appendChild(placeholder);
});
container.appendChild(cardsContainer);
// 批量加载卡牌
var requests = uniqueCards.map(function(cardName) {
return { character: character, cardName: cardName, deckType: '' };
});
fetchCardHTMLBatch(requests, function(results) {
uniqueCards.forEach(function(cardName, index) {
var cacheKey = character + '|' + cardName + '|';
var html = results[cacheKey];
if (html) {
var cardWrapper = document.createElement('div');
cardWrapper.style.cssText = 'opacity: 0;';
cardWrapper.innerHTML = html;
var cards = cardWrapper.querySelectorAll('.game-card');
cards.forEach(function(card) {
card.style.cursor = 'default';
card.onclick = function(e) {
e.stopPropagation();
e.preventDefault();
};
// 检查是否有衍生卡牌
var derivedCards = card.dataset.derivedCards;
if (derivedCards && derivedCards.trim() !== '') {
var buttonContainer = document.createElement('div');
buttonContainer.style.cssText = 'display: flex; flex-direction: column; align-items: center; gap: 10px;';
var cardContainer = document.createElement('div');
cardContainer.appendChild(card.cloneNode(true));
buttonContainer.appendChild(cardContainer);
var viewDerivedBtn = document.createElement('div');
viewDerivedBtn.style.cssText = 'padding: 8px 15px; background: linear-gradient(135deg, #4a90e2, #357abd); color: white; border-radius: 6px; cursor: pointer; white-space: nowrap; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); transition: transform 0.2s; font-size: 12px;';
viewDerivedBtn.textContent = '查看衍生卡牌';
viewDerivedBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
viewDerivedBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
viewDerivedBtn.onclick = function(e) {
e.stopPropagation();
showAllDerivedCards(character, derivedCards.split('、'));
};
buttonContainer.appendChild(viewDerivedBtn);
// 替换占位符
cardsContainer.replaceChild(buttonContainer, placeholders[index]);
// 淡入动画
setTimeout(function() {
buttonContainer.style.transition = 'opacity 0.3s';
buttonContainer.style.opacity = '1';
}, 10);
} else {
// 替换占位符
cardsContainer.replaceChild(card, placeholders[index]);
// 淡入动画
setTimeout(function() {
card.style.transition = 'opacity 0.3s';
card.style.opacity = '1';
}, 10);
}
});
}
});
});
// 添加返回按钮
var backBtn = document.createElement('div');
backBtn.style.cssText = 'position: fixed; top: 20px; left: 20px; padding: 10px 20px; background: linear-gradient(135deg, #4a90e2, #357abd); color: white; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); z-index: 10001; transition: transform 0.2s;';
backBtn.textContent = '← 返回';
backBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
backBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
backBtn.onclick = function() {
goBack();
};
container.appendChild(backBtn);
// 添加关闭按钮
container.appendChild(createCloseButton());
}
// 显示变体卡牌
function showVariantCards(character, cardName, variantType, addToHistory) {
if (addToHistory !== false) {
addToHistory = true;
}
var overlay = document.getElementById('card-overlay');
var container = document.getElementById('card-display-container');
// 添加到历史栈
if (addToHistory) {
viewHistory.push({
type: 'variantCards',
data: {
character: character,
cardName: cardName,
variantType: variantType
}
});
}
// 重置容器样式
container.style.cssText = 'position: relative; padding: 40px; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center;';
container.innerHTML = '';
// 创建标题
var title = document.createElement('div');
title.style.cssText = 'color: white; font-size: 28px; font-weight: bold; margin-bottom: 30px; text-align: center; background: linear-gradient(135deg, #667eea, #764ba2); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;';
title.textContent = cardName + ' - ' + variantType;
container.appendChild(title);
// 创建卡牌容器
var cardsContainer = document.createElement('div');
cardsContainer.style.cssText = 'display: flex; flex-wrap: nowrap; gap: 0px; justify-content: center; max-width: 1400px; overflow-x: auto; padding: 40px; transform: scale(1.5); transform-origin: center center;';
// 先添加loading占位符
var loadingPlaceholder = createLoadingPlaceholder('加载变体卡牌...', null);
cardsContainer.appendChild(loadingPlaceholder);
container.appendChild(cardsContainer);
// 加载变体卡牌
fetchCardHTML(character, cardName, variantType, function(html) {
var tempContainer = document.createElement('div');
tempContainer.innerHTML = html;
// 移除loading占位符
cardsContainer.removeChild(loadingPlaceholder);
// 处理所有卡牌
var cards = tempContainer.querySelectorAll('.game-card');
cards.forEach(function(card, index) {
card.style.cursor = 'default';
card.onclick = null;
card.style.flexShrink = '0';
card.style.opacity = '0';
// 获取衍生卡牌数据
var derivedCards = card.getAttribute('data-derived-cards');
// 更严格的检查
var hasDerivedCards = false;
if (derivedCards !== null && derivedCards !== undefined) {
var trimmedValue = String(derivedCards).trim();
if (trimmedValue.length > 0 &&
trimmedValue !== 'undefined' &&
trimmedValue !== 'null' &&
trimmedValue !== 'false' &&
trimmedValue !== '0') {
hasDerivedCards = true;
}
}
if (hasDerivedCards) {
// 创建包装器,包含卡牌和按钮
var cardWrapper = document.createElement('div');
cardWrapper.style.cssText = 'display: flex; flex-direction: column; align-items: center; gap: 10px; flex-shrink: 0; opacity: 0;';
// 添加卡牌
var cardClone = card.cloneNode(true);
cardClone.style.cursor = 'default';
cardClone.onclick = null;
cardClone.style.opacity = '1';
cardWrapper.appendChild(cardClone);
// 创建查看衍生卡牌按钮
var viewDerivedBtn = document.createElement('div');
viewDerivedBtn.style.cssText = 'padding: 8px 15px; background: linear-gradient(135deg, #4a90e2, #357abd); color: white; border-radius: 6px; cursor: pointer; white-space: nowrap; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); transition: transform 0.2s; font-size: 12px;';
viewDerivedBtn.textContent = '查看衍生卡牌';
viewDerivedBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
viewDerivedBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
// 保存衍生卡牌信息
viewDerivedBtn.setAttribute('data-derived-list', derivedCards);
viewDerivedBtn.onclick = function(e) {
e.stopPropagation();
var derivedList = this.getAttribute('data-derived-list');
showAllDerivedCards(character, derivedList.split('、'));
};
cardWrapper.appendChild(viewDerivedBtn);
cardsContainer.appendChild(cardWrapper);
// 淡入动画
setTimeout(function() {
cardWrapper.style.transition = 'opacity 0.3s';
cardWrapper.style.opacity = '1';
}, 50 * index);
} else {
// 没有衍生卡牌,直接添加卡牌
cardsContainer.appendChild(card);
// 淡入动画
setTimeout(function() {
card.style.transition = 'opacity 0.3s';
card.style.opacity = '1';
}, 50 * index);
}
});
});
// 添加返回按钮
var backBtn = document.createElement('div');
backBtn.style.cssText = 'position: fixed; top: 20px; left: 20px; padding: 10px 20px; background: linear-gradient(135deg, #4a90e2, #357abd); color: white; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 2px 8px rgba(0,0,0,0.3); z-index: 10001; transition: transform 0.2s;';
backBtn.textContent = '← 返回';
backBtn.onmouseover = function() { this.style.transform = 'scale(1.05)'; };
backBtn.onmouseout = function() { this.style.transform = 'scale(1)'; };
backBtn.onclick = function() {
goBack();
};
container.appendChild(backBtn);
// 添加关闭按钮
container.appendChild(createCloseButton());
}
// 鼠标悬停时预加载
function initPreloadEvents() {
var preloadTimeout = null;
document.addEventListener('mouseover', function(e) {
var card = e.target.closest('.game-card');
if (card && !card.closest('#card-overlay')) {
// 延迟200ms开始预加载,避免快速移动时的无效预加载
clearTimeout(preloadTimeout);
preloadTimeout = setTimeout(function() {
var character = card.dataset.character;
var cardName = card.dataset.cardName;
var derivedCards = card.dataset.derivedCards;
if (!character || !cardName) return;
// 预加载变体
preloadCardData(character, cardName, '灵光一闪');
preloadCardData(character, cardName, '神之一闪');
// 预加载衍生卡牌(最多预加载前3张)
if (derivedCards && derivedCards.trim() !== '') {
var cardsList = derivedCards.split('、');
var preloadCount = Math.min(3, cardsList.length);
for (var i = 0; i < preloadCount; i++) {
preloadCardData(character, cardsList[i].trim(), '');
}
}
}, 200);
}
});
document.addEventListener('mouseout', function(e) {
var card = e.target.closest('.game-card');
if (card && !card.closest('#card-overlay')) {
clearTimeout(preloadTimeout);
}
});
}
// 初始化卡牌点击事件
function initCardClickEvents() {
// 使用事件委托
document.addEventListener('click', function(e) {
var card = e.target.closest('.game-card');
if (card && !card.closest('#card-overlay')) {
e.preventDefault();
showEnlargedCard(card);
}
});
// 添加预加载事件
initPreloadEvents();
// 添加Loading样式
addLoadingStyles();
// 页面加载完成后,预加载可见卡牌的相关数据
setTimeout(function() {
var visibleCards = document.querySelectorAll('.game-card:not(#card-overlay .game-card)');
var preloadList = [];
visibleCards.forEach(function(card, index) {
// 只预加载前10张可见卡牌
if (index >= 10) return;
var character = card.dataset.character;
var cardName = card.dataset.cardName;
if (character && cardName) {
preloadList.push({ character: character, cardName: cardName });
}
});
// 分批预加载
preloadList.forEach(function(item, index) {
setTimeout(function() {
preloadCardData(item.character, item.cardName, '灵光一闪');
preloadCardData(item.character, item.cardName, '神之一闪');
}, index * 100); // 每100ms预加载一个
});
}, 2000); // 页面加载2秒后开始预加载
}
// 添加键盘快捷键支持
function initKeyboardShortcuts() {
document.addEventListener('keydown', function(e) {
var overlay = document.getElementById('card-overlay');
if (overlay && overlay.style.display !== 'none') {
if (e.key === 'Escape') {
e.preventDefault();
closeCardDisplay();
} else if (e.key === 'Backspace' || e.key === 'ArrowLeft') {
e.preventDefault();
goBack();
}
}
});
}
// 优化滚动性能
function optimizeScrollPerformance() {
var scrollTimeout;
var overlay = document.getElementById('card-overlay');
if (overlay) {
overlay.addEventListener('scroll', function() {
if (!overlay.classList.contains('is-scrolling')) {
overlay.classList.add('is-scrolling');
}
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function() {
overlay.classList.remove('is-scrolling');
}, 150);
});
}
}
// 添加性能监控
function addPerformanceMonitoring() {
if (window.performance && window.performance.mark) {
// 监控API调用时间
var originalFetch = fetchCardHTML;
fetchCardHTML = function(character, cardName, deckType, callback) {
var startMark = 'fetch-start-' + Date.now();
var endMark = 'fetch-end-' + Date.now();
performance.mark(startMark);
originalFetch(character, cardName, deckType, function(result) {
performance.mark(endMark);
performance.measure('API Call: ' + cardName, startMark, endMark);
callback(result);
});
};
}
}
// 清理函数
function cleanup() {
// 清理大型缓存
if (Object.keys(apiCache).length > cacheManager.maxSize * 1.5) {
var keys = Object.keys(apiCache);
var toDelete = keys.length - cacheManager.maxSize;
// 根据访问时间排序
keys.sort(function(a, b) {
return (cacheManager.accessTime[a] || 0) - (cacheManager.accessTime[b] || 0);
});
// 删除最旧的条目
for (var i = 0; i < toDelete; i++) {
delete apiCache[keys[i]];
delete cacheManager.accessTime[keys[i]];
}
}
}
// 定期清理(每5分钟)
setInterval(cleanup, 5 * 60 * 1000);
// 页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
initCardClickEvents();
initKeyboardShortcuts();
optimizeScrollPerformance();
// 仅在开发环境启用性能监控
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
addPerformanceMonitoring();
}
});
} else {
initCardClickEvents();
initKeyboardShortcuts();
optimizeScrollPerformance();
// 仅在开发环境启用性能监控
if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
addPerformanceMonitoring();
}
}
})();
/* 卡牌文字滚动 */
(function() {
'use strict';
function initCardScroll() {
var cards = document.querySelectorAll('.game-card.card-description-scrollable');
cards.forEach(function(card) {
var scrollContainer = card.querySelector('.card-description-scroll');
var scrollInner = card.querySelector('.card-description-scroll-inner');
var scrollText = card.querySelector('.card-description-text');
if (!scrollContainer || !scrollInner || !scrollText) {
return;
}
// 强制触发重绘
scrollInner.style.display = 'none';
scrollInner.offsetHeight; // 触发重排
scrollInner.style.display = 'block';
});
}
// 延迟初始化,确保DOM完全加载
function delayedInit() {
setTimeout(initCardScroll, 100);
setTimeout(initCardScroll, 500);
setTimeout(initCardScroll, 1000);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', delayedInit);
} else {
delayedInit();
}
})();
/* 卡牌Tooltip */
$(function() {
// 初始化所有卡牌悬浮
function initCardHoverElements() {
$('.card-hover-container').each(function() {
var $container = $(this);
// 只初始化尚未处理的元素
if ($container.data('initialized')) return;
$container.data('initialized', true);
// 获取卡牌数据
var character = $container.data('character');
var cardName = $container.data('card');
var deckType = $container.data('deck') || '';
var index = $container.data('index') || 0;
var $popup = $container.find('.card-popup');
// 预加载卡牌数据
$container.on('mouseenter', function() {
// 如果卡牌数据已经加载过,直接显示
if ($popup.data('loaded')) {
// 调整位置到右下方
positionCardPopup($container);
return;
}
// 加载卡牌数据
var params = {
action: 'parse',
text: '{{#invoke:卡牌|main|' + character + '|' + cardName + '|' + deckType + '|' + index + '}}',
prop: 'text',
disablelimitreport: true,
format: 'json'
};
$.ajax({
url: mw.util.wikiScript('api'),
data: params,
dataType: 'json',
success: function(data) {
if (data && data.parse && data.parse.text) {
var cardHtml = data.parse.text['*'];
$popup.html(cardHtml).data('loaded', true);
// 调整位置到右下方
positionCardPopup($container);
}
},
error: function() {
$popup.html('<div style="color: #721c24;">无法加载卡牌数据</div>').data('loaded', true);
}
});
});
});
}
// 调整卡牌弹出位置到右下方
function positionCardPopup($container) {
var $popupContainer = $container.find('.card-popup-container');
var containerWidth = $container.width();
var windowWidth = $(window).width();
var containerOffset = $container.offset();
var rightSpace = windowWidth - containerOffset.left - containerWidth;
// 重置位置
$popupContainer.css({
'left': 'auto',
'right': 'auto',
'top': '100%',
'margin-top': '5px'
});
// 如果右侧空间足够,放在右下方
if (rightSpace >= 168) { // 卡牌宽度大约168px
$popupContainer.css({
'left': '0',
});
}
// 如果右侧空间不够,但左侧空间足够,放在左下方
else if (containerOffset.left >= 168) {
$popupContainer.css({
'right': '0',
});
}
// 如果两侧都不够,尝试居中并确保完全可见
else {
var leftPosition = Math.max(0, Math.min(containerOffset.left - (168/2), windowWidth - 168));
$popupContainer.css({
'left': (leftPosition - containerOffset.left) + 'px'
});
}
}
// 初次加载页面时初始化
$(document).ready(function() {
initCardHoverElements();
});
// 使用 MutationObserver 监听 DOM 变化,处理动态加载的内容
if (window.MutationObserver) {
var observer = new MutationObserver(function(mutations) {
var shouldInit = false;
mutations.forEach(function(mutation) {
if (mutation.addedNodes && mutation.addedNodes.length) {
shouldInit = true;
}
});
if (shouldInit) {
initCardHoverElements();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
});
/* 词典Tooltip */
(function() {
var tooltipContainer = null;
var currentTerm = null;
var hideTimeout = null;
// 初始化
$(function() {
// 创建全局 tooltip 容器
tooltipContainer = $('<div class="dictionary-tooltip-container"></div>');
$('body').append(tooltipContainer);
// 鼠标进入词条
$(document).on('mouseenter', '.dictionary-term', function(e) {
var $term = $(this);
currentTerm = $term;
// 清除隐藏定时器
if (hideTimeout) {
clearTimeout(hideTimeout);
hideTimeout = null;
}
// 获取 tooltip 内容
var content = $term.attr('data-tooltip-content');
if (!content) return;
// 设置内容
tooltipContainer.html(content);
// 计算位置
updateTooltipPosition($term);
// 显示 tooltip
tooltipContainer.addClass('active');
});
// 鼠标离开词条
$(document).on('mouseleave', '.dictionary-term', function() {
hideTimeout = setTimeout(function() {
tooltipContainer.removeClass('active');
currentTerm = null;
}, 100);
});
// 鼠标进入 tooltip(防止快速隐藏)
tooltipContainer.on('mouseenter', function() {
if (hideTimeout) {
clearTimeout(hideTimeout);
hideTimeout = null;
}
});
// 鼠标离开 tooltip
tooltipContainer.on('mouseleave', function() {
hideTimeout = setTimeout(function() {
tooltipContainer.removeClass('active');
currentTerm = null;
}, 100);
});
// 窗口滚动时更新位置
$(window).on('scroll resize', function() {
if (currentTerm && tooltipContainer.hasClass('active')) {
updateTooltipPosition(currentTerm);
}
});
});
// 更新 tooltip 位置
function updateTooltipPosition($term) {
var rect = $term[0].getBoundingClientRect();
var scrollTop = $(window).scrollTop();
var scrollLeft = $(window).scrollLeft();
// 基本位置:词条下方
var top = rect.bottom + scrollTop + 2;
var left = rect.left + scrollLeft;
// 获取 tooltip 尺寸
var tooltipWidth = 250; // 固定宽度
var tooltipHeight = tooltipContainer.outerHeight();
// 获取窗口尺寸
var windowWidth = $(window).width();
var windowHeight = $(window).height();
// 检查右边界
if (left + tooltipWidth > windowWidth + scrollLeft) {
left = Math.max(scrollLeft, rect.right + scrollLeft - tooltipWidth);
}
// 检查下边界
if (rect.bottom + tooltipHeight > windowHeight) {
// 如果下方空间不足,显示在上方
if (rect.top - tooltipHeight > 0) {
top = rect.top + scrollTop - tooltipHeight - 2;
}
}
// 设置位置
tooltipContainer.css({
top: top + 'px',
left: left + 'px'
});
}
})();