MediaWiki:Gadget-site-js.js:修订间差异
MediaWiki界面页面
更多操作
(未显示同一用户的6个中间版本) | |||
第1行: | 第1行: | ||
const rootStyles = getComputedStyle(document.documentElement); | |||
const hexColor = rootStyles.getPropertyValue('--background-color-base').trim(); | |||
const | |||
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', | |||
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); | |||
// 创建元素(如果不存在) | |||
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); | |||
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 () { | |||
}); | |||
(function(c,l,a,r,i,t,y){ | |||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; | |||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i+"?ref=bwt"; | |||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); | |||
})(window, document, "clarity", "script", "rsfbla4ho9"); |
2025年6月21日 (六) 09:28的最新版本
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',
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);
// 创建元素(如果不存在)
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);
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 () {
});
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i+"?ref=bwt";
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "rsfbla4ho9");