查看“︁微件:Card”︁的源代码
←
微件:Card
跳转到导航
跳转到搜索
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您没有权限编辑
微件
命名空间内的页面。
您可以查看和复制此页面的源代码。
<includeonly> <style> .card-wrapper { display: inline-block; } /* 卡牌悬停动画 */ .card-deck-trans { cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease, filter 0.3s ease; } .card-deck-trans:hover { transform: translateY(-8px); filter: brightness(1.1); } .card-deck-trans:active { transform: translateY(-4px) scale(0.98); } /* 模态框通用样式 */ .card-modal-overlay, .spark-modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.85); z-index: 9999; justify-content: center; align-items: center; opacity: 0; transition: opacity 0.3s ease; } .spark-modal-overlay { z-index: 10010; background-color: rgba(0, 0, 0, 0.9); } .card-modal-overlay.active, .spark-modal-overlay.active { display: flex; opacity: 1; } .card-modal-overlay.fade-in, .spark-modal-overlay.fade-in { opacity: 1; } .card-modal-overlay.fade-out, .spark-modal-overlay.fade-out { opacity: 0; } /* 关闭按钮 */ .card-modal-close, .spark-modal-close { position: fixed; top: 20px; right: 30px; font-size: 48px; font-weight: bold; color: #ffffff; cursor: pointer; z-index: 10001; line-height: 1; transition: color 0.2s ease, transform 0.2s ease; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } .spark-modal-close { z-index: 10012; } .card-modal-close:hover, .spark-modal-close:hover { color: #ff6b6b; transform: scale(1.1); } /* 模态框中的卡牌容器 */ .card-modal-content { position: relative; z-index: 10000; display: flex; flex-direction: column; align-items: center; animation: cardZoomIn 0.3s ease; } .spark-modal-content { position: relative; z-index: 10011; max-width: 90vw; max-height: 85vh; overflow-y: auto; padding: 20px; animation: cardZoomIn 0.3s ease; } @keyframes cardZoomIn { from { transform: scale(0.8); opacity: 0; } to { transform: scale(1); opacity: 1; } } /* 放大后的卡牌样式 */ .card-modal-content > .card-deck-trans, .card-modal-content > .card-wrapper > .card-deck-trans { width: 270px !important; height: 384px !important; transform: none !important; filter: none !important; cursor: default; } .card-modal-content > .card-deck-trans:hover, .card-modal-content > .card-wrapper > .card-deck-trans:hover { transform: none !important; filter: none !important; } .card-modal-content > .card-deck-trans > .card-deck, .card-modal-content > .card-wrapper > .card-deck-trans > .card-deck { transform: scale(0.6) !important; } /* 闪光按钮 */ .spark-button { margin-top: 20px; padding: 12px 36px; font-size: 18px; font-weight: bold; color: #fff; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: 2px solid #a78bfa; border-radius: 8px; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); } .spark-button:hover { background: linear-gradient(135deg, #764ba2 0%, #667eea 100%); box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6); transform: translateY(-2px); } .spark-button:active { transform: translateY(0); box-shadow: 0 2px 10px rgba(102, 126, 234, 0.4); } /* 闪光按钮状态 */ .spark-button.loading { opacity: 0.7; cursor: wait; } .spark-button.cached::after { content: " ✓"; color: #90EE90; } /* 闪光图标动画 */ .spark-button:not(.loading)::before { content: "✦ "; animation: sparkle 1.5s ease-in-out infinite; } @keyframes sparkle { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } } /* 闪光卡牌列表样式 */ .spark-modal-title { text-align: center; color: #fff; font-size: 24px; font-weight: bold; margin-bottom: 20px; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } .spark-modal-title::before { content: "✦ "; color: #a78bfa; } .spark-modal-title::after { content: " ✦"; color: #a78bfa; } .spark-card-list { display: flex; flex-wrap: wrap; justify-content: center; gap: 15px; } .spark-card-list .card-wrapper { display: inline-block; } .spark-card-list .card-deck-trans { cursor: pointer; } .spark-card-list .card-deck-trans:hover { transform: translateY(-8px); filter: brightness(1.1); } /* 加载提示 */ .spark-loading { color: #fff; font-size: 18px; text-align: center; padding: 40px; } .spark-loading::after { content: ""; animation: loadingDots 1.5s infinite; } @keyframes loadingDots { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } } /* 加载进度 */ .spark-loading-progress { color: #aaa; font-size: 14px; margin-top: 10px; } /* 空列表提示 */ .spark-empty { color: #999; font-size: 16px; text-align: center; padding: 40px; } /* 缓存状态提示 */ .spark-cache-hint { color: #666; font-size: 12px; text-align: center; margin-top: 15px; } /* 放大的闪光卡牌 */ .spark-enlarged-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background: rgba(0, 0, 0, 0.95); z-index: 10015; animation: cardZoomIn 0.3s ease; } .spark-enlarged-card { position: relative; display: flex; flex-direction: column; align-items: center; } .spark-enlarged-card .card-deck-trans { width: 270px !important; height: 384px !important; transform: none !important; filter: none !important; cursor: default; } .spark-enlarged-card .card-deck-trans:hover { transform: none !important; filter: none !important; } .spark-enlarged-card .card-deck { transform: scale(0.6) !important; } .spark-enlarged-close { position: fixed; top: 20px; right: 30px; font-size: 48px; font-weight: bold; color: #ffffff; cursor: pointer; z-index: 10016; line-height: 1; transition: color 0.2s ease, transform 0.2s ease; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } .spark-enlarged-close:hover { color: #ff6b6b; transform: scale(1.1); } /* 防止模态框打开时页面滚动 */ body.card-modal-open { overflow: hidden; } /* 滚动条样式 */ .spark-modal-content::-webkit-scrollbar { width: 8px; } .spark-modal-content::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.1); border-radius: 4px; } .spark-modal-content::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.3); border-radius: 4px; } .spark-modal-content::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.5); } /* 预加载指示器 */ .preload-indicator { position: fixed; bottom: 10px; right: 10px; background: rgba(0, 0, 0, 0.7); color: #fff; padding: 5px 10px; border-radius: 4px; font-size: 12px; z-index: 9998; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; } .preload-indicator.active { opacity: 1; } </style> <script> (function() { 'use strict'; // ==================== 缓存管理器 ==================== var SparkCache = { CACHE_KEY: 'spark_card_cache', CACHE_VERSION: 'v1', CACHE_EXPIRE: 24 * 60 * 60 * 1000, // 24小时过期 // 获取完整的缓存键 getFullKey: function() { return this.CACHE_KEY + '_' + this.CACHE_VERSION; }, // 获取所有缓存 getAll: function() { try { var data = localStorage.getItem(this.getFullKey()); if (!data) return {}; return JSON.parse(data); } catch (e) { console.warn('SparkCache: 读取缓存失败', e); return {}; } }, // 保存所有缓存 saveAll: function(data) { try { localStorage.setItem(this.getFullKey(), JSON.stringify(data)); } catch (e) { console.warn('SparkCache: 保存缓存失败', e); // 存储空间不足时,清理过期缓存 this.cleanup(); } }, // 获取单个卡牌的闪光列表缓存 get: function(cardId) { var cache = this.getAll(); var item = cache[cardId]; if (!item) return null; // 检查是否过期 if (Date.now() - item.timestamp > this.CACHE_EXPIRE) { delete cache[cardId]; this.saveAll(cache); return null; } return item.html; }, // 设置单个卡牌的闪光列表缓存 set: function(cardId, html) { var cache = this.getAll(); cache[cardId] = { html: html, timestamp: Date.now() }; this.saveAll(cache); }, // 检查是否有缓存 has: function(cardId) { return this.get(cardId) !== null; }, // 清理过期缓存 cleanup: function() { var cache = this.getAll(); var now = Date.now(); var cleaned = false; for (var cardId in cache) { if (cache.hasOwnProperty(cardId)) { if (now - cache[cardId].timestamp > this.CACHE_EXPIRE) { delete cache[cardId]; cleaned = true; } } } if (cleaned) { this.saveAll(cache); } }, // 清空所有缓存 clear: function() { try { localStorage.removeItem(this.getFullKey()); } catch (e) { console.warn('SparkCache: 清空缓存失败', e); } } }; // ==================== 预加载队列管理器 ==================== var PreloadQueue = { queue: [], isProcessing: false, batchSize: 3, // 并发请求数 activeRequests: 0, maxRetries: 2, retryDelay: 1000, // 预加载指示器 indicator: null, // 初始化指示器 initIndicator: function() { if (!this.indicator) { this.indicator = document.createElement('div'); this.indicator.className = 'preload-indicator'; this.indicator.textContent = '预加载中...'; document.body.appendChild(this.indicator); } }, // 显示/隐藏指示器 showIndicator: function(show) { this.initIndicator(); if (show) { this.indicator.classList.add('active'); } else { this.indicator.classList.remove('active'); } }, // 更新指示器文本 updateIndicator: function(current, total) { this.initIndicator(); this.indicator.textContent = '预加载: ' + current + '/' + total; }, // 添加到预加载队列 add: function(cardId, priority) { // 如果已缓存,跳过 if (SparkCache.has(cardId)) return; // 如果已在队列中,跳过 for (var i = 0; i < this.queue.length; i++) { if (this.queue[i].cardId === cardId) return; } this.queue.push({ cardId: cardId, priority: priority || 0, retries: 0 }); // 按优先级排序(高优先级在前) this.queue.sort(function(a, b) { return b.priority - a.priority; }); this.process(); }, // 批量添加到预加载队列 addBatch: function(cardIds, priority) { var self = this; cardIds.forEach(function(cardId) { self.add(cardId, priority); }); }, // 提升优先级(用于用户即将查看的卡牌) prioritize: function(cardId) { for (var i = 0; i < this.queue.length; i++) { if (this.queue[i].cardId === cardId) { this.queue[i].priority = 100; break; } } this.queue.sort(function(a, b) { return b.priority - a.priority; }); }, // 处理队列 process: function() { var self = this; if (this.queue.length === 0) { this.showIndicator(false); return; } // 控制并发数 while (this.activeRequests < this.batchSize && this.queue.length > 0) { var item = this.queue.shift(); this.loadSparkList(item); } if (this.activeRequests > 0) { this.showIndicator(true); this.updateIndicator(this.activeRequests, this.queue.length + this.activeRequests); } }, // 加载闪光卡牌列表 loadSparkList: function(item) { var self = this; this.activeRequests++; var api = new mw.Api(); api.get({ action: 'parse', text: '{{Card/spark/list|' + item.cardId + '}}', prop: 'text', disablelimitreport: true, format: 'json' }).done(function(data) { self.activeRequests--; if (data.parse && data.parse.text) { var html = data.parse.text['*']; SparkCache.set(item.cardId, html); // 更新按钮状态 self.updateButtonState(item.cardId, true); } self.process(); }).fail(function() { self.activeRequests--; // 重试逻辑 if (item.retries < self.maxRetries) { item.retries++; setTimeout(function() { self.queue.unshift(item); self.process(); }, self.retryDelay * item.retries); } self.process(); }); }, // 更新按钮缓存状态 updateButtonState: function(cardId, cached) { var buttons = document.querySelectorAll('.spark-button[data-card-id="' + cardId + '"]'); buttons.forEach(function(btn) { if (cached) { btn.classList.add('cached'); btn.classList.remove('loading'); } }); } }; // ==================== 主逻辑 ==================== // 确保DOM加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardWidget); } else { initCardWidget(); } function initCardWidget() { // 清理过期缓存 SparkCache.cleanup(); // 创建主模态框元素(如果不存在) var modalOverlay = document.querySelector('.card-modal-overlay'); if (!modalOverlay) { modalOverlay = document.createElement('div'); modalOverlay.className = 'card-modal-overlay'; modalOverlay.innerHTML = '<span class="card-modal-close">×</span><div class="card-modal-content"></div>'; document.body.appendChild(modalOverlay); } // 创建闪光卡牌模态框(如果不存在) var sparkModalOverlay = document.querySelector('.spark-modal-overlay'); if (!sparkModalOverlay) { sparkModalOverlay = document.createElement('div'); sparkModalOverlay.className = 'spark-modal-overlay'; sparkModalOverlay.innerHTML = '<span class="spark-modal-close">×</span><div class="spark-modal-content"></div>'; document.body.appendChild(sparkModalOverlay); } var modalContent = modalOverlay.querySelector('.card-modal-content'); var closeButton = modalOverlay.querySelector('.card-modal-close'); var sparkModalContent = sparkModalOverlay.querySelector('.spark-modal-content'); var sparkCloseButton = sparkModalOverlay.querySelector('.spark-modal-close'); // 当前放大的闪光卡牌容器 var currentEnlargedContainer = null; // 关闭主模态框函数 function closeModal() { modalOverlay.classList.add('fade-out'); setTimeout(function() { modalOverlay.classList.remove('active', 'fade-in', 'fade-out'); modalContent.innerHTML = ''; document.body.classList.remove('card-modal-open'); }, 300); } // 关闭闪光模态框函数 function closeSparkModal() { // 先关闭放大的卡牌 if (currentEnlargedContainer) { currentEnlargedContainer.remove(); currentEnlargedContainer = null; } sparkModalOverlay.classList.add('fade-out'); setTimeout(function() { sparkModalOverlay.classList.remove('active', 'fade-in', 'fade-out'); sparkModalContent.innerHTML = ''; }, 300); } // 关闭放大的闪光卡牌 function closeEnlargedCard() { if (currentEnlargedContainer) { currentEnlargedContainer.remove(); currentEnlargedContainer = null; } } // 打开主模态框函数 function openModal(cardElement, cardId, sparkEnable) { var cardClone = cardElement.cloneNode(true); // 移除克隆卡牌的点击事件标记 delete cardClone.dataset.cardBound; modalContent.innerHTML = ''; modalContent.appendChild(cardClone); // 如果启用了闪光功能,添加闪光按钮 if (sparkEnable && sparkEnable.trim() !== '') { var sparkButton = document.createElement('button'); sparkButton.className = 'spark-button'; sparkButton.textContent = '闪光'; sparkButton.dataset.cardId = cardId; // 检查是否已缓存 if (SparkCache.has(cardId)) { sparkButton.classList.add('cached'); } else { // 提升优先级预加载 PreloadQueue.prioritize(cardId); } sparkButton.addEventListener('click', function() { openSparkModal(cardId); }); modalContent.appendChild(sparkButton); } modalOverlay.classList.add('active'); document.body.classList.add('card-modal-open'); // 强制重绘后添加fade-in requestAnimationFrame(function() { modalOverlay.classList.add('fade-in'); }); } // 打开闪光卡牌模态框 function openSparkModal(cardId) { // 首先检查缓存 var cachedHtml = SparkCache.get(cardId); if (cachedHtml) { // 使用缓存,立即显示 showSparkContent(cachedHtml, true); } else { // 无缓存,显示加载中并请求 sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div><div class="spark-loading">加载中</div>'; sparkModalOverlay.classList.add('active'); requestAnimationFrame(function() { sparkModalOverlay.classList.add('fade-in'); }); // 发起请求 loadSparkListDirect(cardId); } function showSparkContent(html, fromCache) { // 检查是否有卡牌 var tempDiv = document.createElement('div'); tempDiv.innerHTML = html; var cards = tempDiv.querySelectorAll('.card-deck-trans'); var cacheHint = fromCache ? '<div class="spark-cache-hint">已从缓存加载</div>' : ''; if (cards.length > 0) { sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div>' + html + cacheHint; // 为闪光列表中的卡牌绑定事件 bindSparkListCardEvents(); } else { sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div><div class="spark-empty">暂无闪光卡牌</div>' + cacheHint; } if (!sparkModalOverlay.classList.contains('active')) { sparkModalOverlay.classList.add('active'); requestAnimationFrame(function() { sparkModalOverlay.classList.add('fade-in'); }); } } function loadSparkListDirect(cardId) { var api = new mw.Api(); api.get({ action: 'parse', text: '{{Card/spark/list|' + cardId + '}}', prop: 'text', disablelimitreport: true, format: 'json' }).done(function(data) { if (data.parse && data.parse.text) { var html = data.parse.text['*']; // 存入缓存 SparkCache.set(cardId, html); // 更新按钮状态 PreloadQueue.updateButtonState(cardId, true); // 显示内容 showSparkContent(html, false); } }).fail(function() { sparkModalContent.innerHTML = '<div class="spark-modal-title">闪光卡牌列表</div><div class="spark-empty">加载失败,请重试</div>'; }); } } // 为闪光列表中的卡牌绑定点击事件 function bindSparkListCardEvents() { var sparkCards = sparkModalContent.querySelectorAll('.card-deck-trans'); sparkCards.forEach(function(card) { if (card.dataset.sparkBound) return; card.dataset.sparkBound = 'true'; card.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); // 关闭之前放大的卡牌 closeEnlargedCard(); // 创建放大容器 var enlargedContainer = document.createElement('div'); enlargedContainer.className = 'spark-enlarged-container'; // 添加关闭按钮 var closeBtn = document.createElement('span'); closeBtn.className = 'spark-enlarged-close'; closeBtn.innerHTML = '×'; closeBtn.addEventListener('click', function(e) { e.stopPropagation(); closeEnlargedCard(); }); enlargedContainer.appendChild(closeBtn); // 创建卡牌内容区 var cardContent = document.createElement('div'); cardContent.className = 'spark-enlarged-card'; var cardClone = this.cloneNode(true); delete cardClone.dataset.sparkBound; cardContent.appendChild(cardClone); enlargedContainer.appendChild(cardContent); // 点击背景关闭 enlargedContainer.addEventListener('click', function(e) { if (e.target === enlargedContainer) { closeEnlargedCard(); } }); document.body.appendChild(enlargedContainer); currentEnlargedContainer = enlargedContainer; }); }); } // 绑定关闭按钮事件 closeButton.addEventListener('click', function(e) { e.stopPropagation(); closeModal(); }); sparkCloseButton.addEventListener('click', function(e) { e.stopPropagation(); closeSparkModal(); }); // 点击遮罩关闭 modalOverlay.addEventListener('click', function(e) { if (e.target === modalOverlay) { closeModal(); } }); sparkModalOverlay.addEventListener('click', function(e) { if (e.target === sparkModalOverlay) { closeSparkModal(); } }); // ESC键关闭 document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { // 优先关闭放大的闪光卡牌 if (currentEnlargedContainer) { closeEnlargedCard(); } else if (sparkModalOverlay.classList.contains('active')) { closeSparkModal(); } else if (modalOverlay.classList.contains('active')) { closeModal(); } } }); // 收集页面上所有启用闪光的卡牌ID function collectSparkCardIds() { var cardIds = []; var cards = document.querySelectorAll('.card-deck-trans[data-spark-enable]'); cards.forEach(function(card) { var sparkEnable = card.dataset.sparkEnable; if (sparkEnable && sparkEnable.trim() !== '') { var wrapper = card.closest('.card-wrapper'); var cardId = wrapper ? wrapper.dataset.cardId : ''; if (cardId && cardIds.indexOf(cardId) === -1) { cardIds.push(cardId); } } }); return cardIds; } // 为所有卡牌绑定点击事件 function bindCardEvents() { var cards = document.querySelectorAll('.card-deck-trans'); var sparkCardIds = []; cards.forEach(function(card) { // 避免重复绑定 if (card.dataset.cardBound) return; card.dataset.cardBound = 'true'; // 排除模态框内的卡牌 if (card.closest('.card-modal-overlay') || card.closest('.spark-modal-overlay') || card.closest('.spark-enlarged-container')) return; // 收集启用闪光的卡牌ID用于预加载 var sparkEnable = card.dataset.sparkEnable; if (sparkEnable && sparkEnable.trim() !== '') { var wrapper = card.closest('.card-wrapper'); var cardId = wrapper ? wrapper.dataset.cardId : ''; if (cardId && sparkCardIds.indexOf(cardId) === -1) { sparkCardIds.push(cardId); } } card.addEventListener('click', function(e) { e.preventDefault(); // 从card-deck-trans元素获取spark_enable var sparkEnable = this.dataset.sparkEnable || ''; // 获取card-id从父级card-wrapper var wrapper = this.closest('.card-wrapper'); var cardId = wrapper ? wrapper.dataset.cardId : ''; openModal(this, cardId, sparkEnable); }); // 鼠标悬停时预加载 card.addEventListener('mouseenter', function() { var sparkEnable = this.dataset.sparkEnable || ''; if (sparkEnable && sparkEnable.trim() !== '') { var wrapper = this.closest('.card-wrapper'); var cardId = wrapper ? wrapper.dataset.cardId : ''; if (cardId) { // 高优先级预加载 PreloadQueue.add(cardId, 50); } } }); }); // 延迟低优先级预加载页面上所有闪光卡牌 if (sparkCardIds.length > 0) { setTimeout(function() { PreloadQueue.addBatch(sparkCardIds, 1); }, 2000); } } // 初始绑定 bindCardEvents(); // 监听DOM变化,为动态加载的卡牌绑定事件 var observer = new MutationObserver(function(mutations) { var shouldBind = false; mutations.forEach(function(mutation) { if (mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.classList && node.classList.contains('card-deck-trans')) { shouldBind = true; } else if (node.querySelector && node.querySelector('.card-deck-trans')) { shouldBind = true; } } }); } }); if (shouldBind) { bindCardEvents(); } }); observer.observe(document.body, { childList: true, subtree: true }); // 页面可见性变化时暂停/恢复预加载 document.addEventListener('visibilitychange', function() { if (document.hidden) { // 页面不可见时,暂停预加载(通过不处理队列) } else { // 页面可见时,恢复预加载 PreloadQueue.process(); } }); } })(); </script> </includeonly>
返回
微件:Card
。
导航菜单
个人工具
登录
命名空间
微件
讨论
大陆简体
查看
阅读
查看源代码
查看历史
更多
刷新
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息