MediaWiki:Gadget-site-js.js:修订间差异
MediaWiki界面页面
更多操作
第171行: | 第171行: | ||
return { show, hide }; | return { show, hide }; | ||
})(); | |||
/********************** | |||
* 模块 4:vConsole(仅限移动端,异步加载) | |||
**********************/ | |||
(function() { | |||
// 判断是否为移动端设备 | |||
const isMobile = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); | |||
// 如果是移动端,且没有禁用 vConsole 的条件,才加载 | |||
if (isMobile && !window.localStorage.getItem('disableVConsole')) { | |||
const script = document.createElement('script'); | |||
script.src = 'https://cdn.bootcdn.net/ajax/libs/vConsole/3.3.4/vconsole.min.js'; // 使用CDN加载vConsole | |||
script.onload = () => { | |||
const vConsole = new VConsole(); // 初始化 vConsole | |||
console.log('vConsole 已启用'); | |||
}; | |||
document.body.appendChild(script); | |||
} | |||
})(); | })(); |
2025年6月20日 (五) 20:52的最新版本
/**********************
* 模块 1:CSS 变量 RGB 转换
**********************/
const ColorUtil = (function () {
const OBS_VAR = '--background-color-base';
let cachedRgb = '';
function parseHex(hex) {
hex = hex.replace(/^#/, '');
if (hex.length === 3) {
hex = hex.split('').map(c => c + c).join('');
}
if (hex.length !== 6) return '0, 0, 0';
const [r, g, b] = [0, 2, 4].map(i => parseInt(hex.substring(i, i + 2), 16) || 0);
return `${r}, ${g}, ${b}`;
}
function update() {
const root = document.documentElement;
const hex = getComputedStyle(root).getPropertyValue(OBS_VAR).trim();
const rgb = parseHex(hex || '#000');
if (rgb !== cachedRgb) {
root.style.setProperty('--background-color-rgb', rgb);
cachedRgb = rgb;
console.log('[ColorUtil] RGB updated:', rgb);
}
}
update();
const mo = new MutationObserver(update);
mo.observe(document.documentElement, { attributes: true, attributeFilter: ['style'] });
return {
destroy() { mo.disconnect(); },
forceUpdate: update
};
})();
/**********************
* 模块 2:上传页引导弹窗(按需加载 OOUI)
**********************/
(function (mw) {
if (!mw || mw.config.get('wgCanonicalSpecialPageName') !== 'Upload') return;
const KEY = 'uploadPreference';
const pref = mw.storage.get(KEY);
if (pref === 'wizard') return window.location = mw.util.getUrl('Special:UploadWizard');
if (pref === 'classic') return;
function initDialog() {
document.removeEventListener('click', initDialog);
mw.loader.using(['mediawiki.util', 'mediawiki.storage', 'oojs-ui-core', 'oojs-ui-widgets'])
.then(() => {
class UploadDialog extends OO.ui.ProcessDialog {
static name = 'UploadDialog';
static title = '请选择上传方式';
static actions = [
{ action: 'classic', label: '❌ 使用传统上传方式', flags: ['safe'] }
];
initialize() {
super.initialize();
const panel = new OO.ui.PanelLayout({ padded: true });
this._remember = new OO.ui.CheckboxInputWidget();
const rememberField = new OO.ui.FieldLayout(this._remember, {
label: '记住我的选择', align: 'inline'
});
const wizardBtn = new OO.ui.ButtonWidget({
label: '✅ 使用上传向导(推荐)',
flags: ['primary', 'progressive'],
href: mw.util.getUrl('Special:UploadWizard'),
target: '_self'
});
wizardBtn.on('click', () => {
if (this._remember.isSelected()) mw.storage.set(KEY, 'wizard');
});
panel.$element.append(
$('<p>').text('请选择上传方式:'),
$('<div>').append(wizardBtn.$element),
$('<div>').append(rememberField.$element)
);
this.$body.append(panel.$element);
}
getActionProcess(action) {
if (action === 'classic') {
if (this._remember.isSelected()) mw.storage.set(KEY, 'classic');
return new OO.ui.Process(() => this.close());
}
return super.getActionProcess(action);
}
}
const wm = new OO.ui.WindowManager();
document.body.appendChild(wm.$element);
wm.addWindows([new UploadDialog()]);
wm.openWindow('UploadDialog');
});
}
document.addEventListener('click', initDialog);
})(window.mw);
/**********************
* 模块 3:全局加载指示器
**********************/
const LoadingIndicator = (function () {
let indicator = null;
let timerId = null;
let startTs = 0;
const minDisplay = 200;
const cfg = {
imageUrl: 'https://wiki.ottohub.cn/images/0/02/Loading.png',
size: '64px', bottom: '20px', right: '20px',
timeout: 15000, fade: 300, zIndex: 99999
};
function show(reason = '') {
if (indicator) return resetTimeout();
startTs = Date.now();
indicator = document.createElement('div');
Object.assign(indicator.style, {
position: 'fixed', width: cfg.size, height: cfg.size,
bottom: cfg.bottom, right: cfg.right,
opacity: '0', transition: `opacity ${cfg.fade}ms`,
zIndex: cfg.zIndex, pointerEvents: 'none'
});
indicator.setAttribute('aria-busy', 'true');
const img = new Image();
img.src = cfg.imageUrl;
img.alt = '加载中';
img.style.width = '100%';
indicator.appendChild(img);
document.body.appendChild(indicator);
requestAnimationFrame(() => { indicator.style.opacity = '1'; });
resetTimeout();
}
function hide(reason = '') {
if (!indicator) return;
const elapsed = Date.now() - startTs;
const wait = Math.max(minDisplay - elapsed, 0);
setTimeout(() => {
indicator.style.opacity = '0';
indicator.setAttribute('aria-busy', 'false');
setTimeout(() => {
indicator.remove();
indicator = null;
}, cfg.fade);
}, wait);
clearTimeout(timerId);
}
function resetTimeout() {
clearTimeout(timerId);
timerId = setTimeout(() => hide('timeout'), cfg.timeout);
}
window.addEventListener('offline', () => {
console.warn('[Loading] 离线,强制隐藏');
hide('offline');
});
window.addEventListener('online', () => {
console.info('[Loading] 网络恢复');
});
document.addEventListener('DOMContentLoaded', () => show('DOMContentLoaded'));
window.addEventListener('load', () => hide('load'));
return { show, hide };
})();
/**********************
* 模块 4:vConsole(仅限移动端,异步加载)
**********************/
(function() {
// 判断是否为移动端设备
const isMobile = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
// 如果是移动端,且没有禁用 vConsole 的条件,才加载
if (isMobile && !window.localStorage.getItem('disableVConsole')) {
const script = document.createElement('script');
script.src = 'https://cdn.bootcdn.net/ajax/libs/vConsole/3.3.4/vconsole.min.js'; // 使用CDN加载vConsole
script.onload = () => {
const vConsole = new VConsole(); // 初始化 vConsole
console.log('vConsole 已启用');
};
document.body.appendChild(script);
}
})();