MediaWiki:Common.js
外观
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5。
const rootStyles = getComputedStyle(document.documentElement); const hexColor = rootStyles.getPropertyValue('--background-color-base').trim(); function hexToRgb(hex) { hex = hex.replace('#', ''); if (hex.length === 3) { hex = hex.split('').map(c => c + c).join(''); } const r = parseInt(hex.substring(0, 2), 16); const g = parseInt(hex.substring(2, 4), 16); const b = parseInt(hex.substring(4, 6), 16); return `${r}, ${g}, ${b}`; } const rgbColor = hexToRgb(hexColor); document.documentElement.style.setProperty( '--background-color-rgb', rgbColor ); console.log('转换结果:', rgbColor); //上传重定向 mw.loader.using(['mediawiki.util', 'oojs-ui', 'mediawiki.storage'], function () { if (mw.config.get('wgCanonicalSpecialPageName') === 'Upload') { const STORAGE_KEY = 'uploadPreference'; const savedChoice = mw.storage.get(STORAGE_KEY); // 用户之前选择了上传向导,自动跳转 if (savedChoice === 'wizard') { window.location.href = mw.util.getUrl('Special:UploadWizard'); return; } // 用户选择了继续使用传统上传,不再提示 if (savedChoice === 'classic') { return; } // 否则弹出选择窗口 var windowManager = new OO.ui.WindowManager(); $(document.body).append(windowManager.$element); function UploadDialog(config) { UploadDialog.super.call(this, config); } OO.inheritClass(UploadDialog, OO.ui.ProcessDialog); UploadDialog.static.name = 'UploadDialog'; UploadDialog.static.title = '请选择上传方式'; UploadDialog.static.actions = [ { action: 'classic', label: '❌ 使用传统上传方式(更快)', flags: ['safe'] } ]; UploadDialog.prototype.initialize = function () { UploadDialog.super.prototype.initialize.call(this); var panel = new OO.ui.PanelLayout({ padded: true, expanded: false }); // 创建“记住我的选择”复选框 var rememberCheckbox = new OO.ui.CheckboxInputWidget({ selected: false }); this._rememberCheckbox = rememberCheckbox; var rememberField = new OO.ui.FieldLayout(rememberCheckbox, { label: '记住我的选择,下次不再提示', align: 'inline' }); // 创建“上传向导”按钮(跳转链接形式) var wizardButton = new OO.ui.ButtonWidget({ label: '✅ 使用上传向导(推荐)', flags: ['primary', 'progressive'], href: mw.util.getUrl('Special:UploadWizard'), target: '_self', framed: true }); // 给按钮添加“记住选择”逻辑 wizardButton.on('click', () => { if (rememberCheckbox.isSelected()) { mw.storage.set(STORAGE_KEY, 'wizard'); } }); // 拼接内容 panel.$element.append( $('<p>').text('请选择你要使用的上传方式:'), $('<div>').css({ 'margin': '12px 0', 'background': '#f8f9fa', 'padding': '10px', 'border': '1px solid #ccc', 'border-radius': '5px' }).append( $('<strong>').text('✅ 上传向导(推荐)'), $('<ul>').append( $('<li>').text('支持多文件批量上传'), $('<li>').text('显示上传进度条'), $('<li>').text('信息填写更完整') ), $('<div>').css('margin-top', '8px').append(wizardButton.$element) ), $('<div>').css({ 'margin-top': '15px', 'background': '#ffffff', 'padding': '10px', 'border': '1px dashed #bbb', 'border-radius': '5px' }).append( $('<strong>').text('⚡️ 传统上传方式'), $('<ul>').append( $('<li>').text('界面更简单'), $('<li>').text('加载速度快'), $('<li>').text('适合上传单个文件') ) ), $('<div>').css('margin-top', '15px').append(rememberField.$element) ); this.$body.append(panel.$element); }; UploadDialog.prototype.getActionProcess = function (action) { if (action === 'classic') { if (this._rememberCheckbox.isSelected()) { mw.storage.set(STORAGE_KEY, 'classic'); } return new OO.ui.Process(() => this.close()); } return UploadDialog.super.prototype.getActionProcess.call(this, action); }; var dialog = new UploadDialog(); windowManager.addWindows([dialog]); windowManager.openWindow(dialog); } }); //--- // 全局加载指示器 (function() { // 配置系统 const defaultConfig = { imageUrl: 'https://wiki.ottohub.cn/images/0/02/Loading.png', position: { bottom: '20px', right: '20px' }, size: '256px', timeout: 15000, zIndex: '99999', debug: true, renderIndicator: defaultRenderer, fadeDuration: 300 }; let config = Object.assign({}, defaultConfig); let loadingDiv = null; let removalTimeoutId = null; let isShowingLoading = false; let linkTrackingEnabled = false; const eventListeners = []; // 默认渲染器 function defaultRenderer(container) { const img = document.createElement('img'); img.src = config.imageUrl; img.alt = '加载中...'; img.style.width = '100%'; img.style.height = '100%'; img.style.objectFit = 'contain'; container.appendChild(img); } // 图片预加载 const imgPreload = new Image(); imgPreload.src = config.imageUrl; // 事件管理 function addEventListener(target, type, handler) { target.addEventListener(type, handler); eventListeners.push({ target, type, handler }); } function cleanupEventListeners() { eventListeners.forEach(({ target, type, handler }) => { target.removeEventListener(type, handler); }); eventListeners.length = 0; } // --- 核心显示函数 --- function showLoading(reason) { if (isShowingLoading && document.getElementById('loadingIndicator')) { config.debug && console.log('[Loading] 已显示,触发原因:', reason); return; } isShowingLoading = true; config.debug && console.log('[Loading] 显示。原因:', reason); // 性能标记 performance.mark(`loadingStart_${reason}`); // 创建元素(如果不存在) if (!document.getElementById('loadingIndicator')) { loadingDiv = document.createElement('div'); loadingDiv.id = 'loadingIndicator'; loadingDiv.style.position = 'fixed'; loadingDiv.style.bottom = config.position.bottom; loadingDiv.style.right = config.position.right; loadingDiv.style.width = config.size; loadingDiv.style.height = config.size; loadingDiv.style.zIndex = config.zIndex; loadingDiv.style.pointerEvents = 'none'; loadingDiv.style.opacity = '0'; loadingDiv.style.transition = `opacity ${config.fadeDuration}ms ease`; // 无障碍支持 loadingDiv.setAttribute('role', 'status'); loadingDiv.setAttribute('aria-live', 'polite'); loadingDiv.setAttribute('aria-label', '页面加载中'); loadingDiv.setAttribute('aria-busy', 'true'); config.renderIndicator(loadingDiv); // 添加到DOM if (document.body) { document.body.appendChild(loadingDiv); } else { document.addEventListener('DOMContentLoaded', function onReady() { document.body.appendChild(loadingDiv); fadeInLoading(); document.removeEventListener('DOMContentLoaded', onReady); }); return; } } else { loadingDiv = document.getElementById('loadingIndicator'); } fadeInLoading(); // 重置超时 if (removalTimeoutId) clearTimeout(removalTimeoutId); // 网络感知超时 const isSlowConnection = navigator.connection && (navigator.connection.saveData || /2g|3g/.test(navigator.connection.effectiveType)); removalTimeoutId = setTimeout( () => hideLoading(`超时回退 (${isSlowConnection ? '慢速网络' : '常规'})`), isSlowConnection ? 30000 : config.timeout ); } function fadeInLoading() { if (!loadingDiv) return; loadingDiv.style.display = 'block'; requestAnimationFrame(() => { loadingDiv.style.opacity = '1'; }); } // --- 核心隐藏函数 --- function hideLoading(reason) { if (!isShowingLoading && !document.getElementById('loadingIndicator')) { config.debug && console.log('[Loading] 已隐藏,隐藏原因:', reason); return; } config.debug && console.log('[Loading] 隐藏。原因:', reason); // 性能标记 performance.mark(`loadingEnd_${reason}`); performance.measure( `loadingDuration_${reason}`, `loadingStart_${reason}`, `loadingEnd_${reason}` ); const el = document.getElementById('loadingIndicator'); if (el) { el.style.opacity = '0'; el.setAttribute('aria-busy', 'false'); setTimeout(() => { if (el.parentNode) { el.parentNode.removeChild(el); } loadingDiv = null; }, config.fadeDuration); } isShowingLoading = false; cleanupEventListeners(); if (removalTimeoutId) { clearTimeout(removalTimeoutId); removalTimeoutId = null; } } // --- 初始页面加载逻辑 --- if (document.readyState === 'loading') { showLoading('初始页面加载 - 文档加载中'); } else if (document.readyState === 'interactive') { showLoading('初始页面加载 - 文档交互状态'); } // 事件监听器 function onWindowLoad() { hideLoading('window.load 事件'); } function onDOMContentLoaded() { hideLoading('DOMContentLoaded 事件'); } if (isShowingLoading || document.readyState === 'loading') { addEventListener(window, 'load', onWindowLoad); addEventListener(document, 'DOMContentLoaded', onDOMContentLoaded); } // --- 链接点击跟踪 --- function enableLinkTracking() { if (linkTrackingEnabled) return; linkTrackingEnabled = true; addEventListener(document, 'click', function(event) { const targetElement = event.target.closest('a'); if (!targetElement || !targetElement.href) return; const href = targetElement.getAttribute('href'); const targetAttr = targetElement.getAttribute('target'); // 排除特殊链接 if (href.startsWith('#') || href.startsWith('javascript:') || href.startsWith('mailto:') || href.startsWith('tel:')) { return; } if (targetAttr === '_blank') return; // 排除SPA处理的链接 let isLikelyInternalSPALink = false; if (typeof window.MyAppRouter !== 'undefined' && window.MyAppRouter.isHandling(href)) { isLikelyInternalSPALink = true; } if (!isLikelyInternalSPALink) { showLoading('链接点击 - 页面导航'); } }, true); } // 公开API window.globalLoadingIndicator = { show: showLoading, hide: hideLoading, configure(newConfig) { config = config = Object.assign({}, config, newConfig); }, initRouter(router) { if (router && typeof router.beforeEach === 'function') { router.beforeEach(() => this.show('路由器导航')); } if (router && typeof router.afterEach === 'function') { router.afterEach(() => this.hide('路由器导航')); } } }; // 初始启用链接跟踪 enableLinkTracking(); })(); mw.loader.using(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui.styles'], function () { });