打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:Gadget-site-js.js:修订间差异

MediaWiki界面页面
 
(未显示同一用户的5个中间版本)
第1行: 第1行:
/**********************
const rootStyles = getComputedStyle(document.documentElement);
* 模块 0:优先加载 vConsole(立即执行)
const hexColor = rootStyles.getPropertyValue('--background-color-base').trim();
**********************/
 
(function() {
function hexToRgb(hex) {
   // 调试控制开关(生产环境可设置为 false)
   hex = hex.replace('#', '');
  const DEBUG_MODE = true;
    
    
   if (DEBUG_MODE && !window.localStorage.getItem('disableVConsole')) {
   if (hex.length === 3) {
    console.log('[Init] 正在加载调试控制台...');
    hex = hex.split('').map(c => c + c).join('');
   
    const vConsoleScript = document.createElement('script');
    vConsoleScript.src = 'https://cdn.bootcdn.net/ajax/libs/vConsole/3.15.1/vconsole.min.js';
    vConsoleScript.integrity = 'sha384-+EmbrakM5WQd6BSpR2GQKJqH15zFVECXZQ5qPj4hEtZj0jFz4iF2PnmFUTTvWH+1';
    vConsoleScript.crossOrigin = 'anonymous';
   
    vConsoleScript.onload = function() {
      try {
        // 初始化 vConsole 并配置
        const vConsole = new window.VConsole({
          theme: 'dark',
          onReady: function() {
            console.log('[vConsole] 调试面板已就绪');
            // 捕获未处理的Promise错误
            window.addEventListener('unhandledrejection', event => {
              console.error('[未处理的Promise错误]', event.reason);
            });
          }
        });
       
        // 全局错误监听(捕获语法错误之外的运行时错误)
        window.addEventListener('error', function(event) {
          console.error(
            '[全局错误]',
            `类型: ${event.error?.name || 'Error'}\n`,
            `信息: ${event.message}\n`,
            `文件: ${event.filename}\n`,
            `行号: ${event.lineno}:${event.colno}`
          );
        });
       
      } catch (e) {
        console.error('[vConsole] 初始化失败', e);
      }
    };
   
    vConsoleScript.onerror = function() {
      console.warn('[vConsole] 加载失败,尝试备用CDN...');
      loadFallbackVConsole();
    };
   
    document.head.insertBefore(vConsoleScript, document.head.firstChild);
   
    // 备用CDN加载
    function loadFallbackVConsole() {
      const fallbackScript = document.createElement('script');
      fallbackScript.src = 'https://cdn.jsdelivr.net/npm/vconsole@3.15.1/dist/vconsole.min.js';
      fallbackScript.onload = vConsoleScript.onload;
      fallbackScript.onerror = function() {
        console.error('[vConsole] 所有CDN加载失败,将无法显示控制台');
      };
      document.head.appendChild(fallbackScript);
    }
   }
   }
})();


/**********************
  const r = parseInt(hex.substring(0, 2), 16);
* 模块 1:CSS 变量 RGB 转换(安全封装)
   const g = parseInt(hex.substring(2, 4), 16);
**********************/
  const b = parseInt(hex.substring(4, 6), 16);
;(function() {
   try {
    const ColorUtil = (function () {
      const OBS_VAR = '--background-color-base';
      let cachedRgb = '';


      function parseHex(hex) {
  return `${r}, ${g}, ${b}`;  
        try {
}
          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}`;
        } catch (e) {
          console.error('[ColorUtil] 颜色解析失败', e);
          return '0, 0, 0';
        }
      }


      function safeUpdate() {
const rgbColor = hexToRgb(hexColor);
        try {
document.documentElement.style.setProperty(
          const root = document.documentElement;
  '--background-color-rgb',  
          const hex = getComputedStyle(root).getPropertyValue(OBS_VAR).trim();
  rgbColor
          const rgb = parseHex(hex || '#000');
);
          if (rgb !== cachedRgb) {
            root.style.setProperty('--background-color-rgb', rgb);
            cachedRgb = rgb;
            console.log('[ColorUtil] RGB值已更新:', rgb);
          }
        } catch (e) {
          console.warn('[ColorUtil] 更新失败', e);
        }
      }


      function init() {
console.log('转换结果:', rgbColor);  
        try {
          safeUpdate();
          const mo = new MutationObserver(safeUpdate);
          mo.observe(document.documentElement, {
            attributes: true,
            attributeFilter: ['style']
          });
          return {
            destroy: () => mo.disconnect(),
            forceUpdate: safeUpdate
          };
        } catch (e) {
          console.error('[ColorUtil] 初始化失败', e);
          return { destroy: () => {}, forceUpdate: () => {} };
        }
      }


      return init();
//上传重定向
    })();
mw.loader.using(['mediawiki.util', 'oojs-ui', 'mediawiki.storage'], function () {
   
     if (mw.config.get('wgCanonicalSpecialPageName') === 'Upload') {
    // 暴露到全局(可选)
    window.ColorUtil = ColorUtil;
   
  } catch (e) {
     console.error('[模块1] 初始化异常', e);
  }
})();


/**********************
        const STORAGE_KEY = 'uploadPreference';
* 模块 2:上传页引导弹窗(安全封装)
**********************/
;(function() {
  try {
    if (!window.mw || !mw.config || mw.config.get('wgCanonicalSpecialPageName') !== 'Upload') {
      return;
    }


    const KEY = 'uploadPreference_v2';
        const savedChoice = mw.storage.get(STORAGE_KEY);
    const pref = mw.storage.get(KEY);


    if (pref === 'wizard') {
        // 用户之前选择了上传向导,自动跳转
      window.location.href = mw.util.getUrl('Special:UploadWizard');
        if (savedChoice === 'wizard') {
      return;
            window.location.href = mw.util.getUrl('Special:UploadWizard');
    }
            return;
    if (pref === 'classic') return;
        }


    function initDialog(event) {
        // 用户选择了继续使用传统上传,不再提示
      // 确保只触发一次
        if (savedChoice === 'classic') {
      if (event && event.target.closest('#mw-content-text')) {
            return;
        document.removeEventListener('click', initDialog);
         }
         showDialog();
      }
    }


    function showDialog() {
        // 否则弹出选择窗口
      mw.loader.using(['mediawiki.util', 'mediawiki.storage', 'oojs-ui-core', 'oojs-ui-widgets'])
        var windowManager = new OO.ui.WindowManager();
         .then(() => {
         $(document.body).append(windowManager.$element);
          try {
            class UploadDialog extends OO.ui.ProcessDialog {
              static static = {
                name: 'UploadDialog',
                title: '请选择上传方式',
                actions: [
                  {
                    action: 'classic',
                    label: '❌ 使用传统上传方式',
                    flags: ['safe']
                  }
                ]
              };


              initialize() {
        function UploadDialog(config) {
                super.initialize();
            UploadDialog.super.call(this, config);
                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({
        OO.inheritClass(UploadDialog, OO.ui.ProcessDialog);
                  label: '✅ 使用上传向导(推荐)',
                  flags: ['primary', 'progressive'],
                  href: mw.util.getUrl('Special:UploadWizard'),
                  target: '_self'
                });


                wizardBtn.on('click', () => {
        UploadDialog.static.name = 'UploadDialog';
                  if (this._remember.isSelected()) {
        UploadDialog.static.title = '请选择上传方式';
                    mw.storage.set(KEY, 'wizard');
        UploadDialog.static.actions = [
                  }
            {
                });
                action: 'classic',
                label: '❌ 使用传统上传方式(更快)',
                flags: ['safe']
            }
        ];


                panel.$element.append(
        UploadDialog.prototype.initialize = function () {
                  $('<p>').text('请选择上传方式:'),
            UploadDialog.super.prototype.initialize.call(this);
                  $('<div>').css('margin', '10px 0').append(wizardBtn.$element),
                  $('<div>').append(rememberField.$element)
                );


                this.$body.append(panel.$element);
            var panel = new OO.ui.PanelLayout({ padded: true, expanded: false });
              }


              getActionProcess(action) {
            // 创建“记住我的选择”复选框
                if (action === 'classic') {
            var rememberCheckbox = new OO.ui.CheckboxInputWidget({ selected: false });
                  return new OO.ui.Process(() => {
            this._rememberCheckbox = rememberCheckbox;
                    if (this._remember.isSelected()) {
                      mw.storage.set(KEY, 'classic');
                    }
                    this.close();
                  });
                }
                return super.getActionProcess(action);
              }
            }


             const windowManager = new OO.ui.WindowManager();
             var rememberField = new OO.ui.FieldLayout(rememberCheckbox, {
            document.body.appendChild(windowManager.$element);
                label: '记住我的选择,下次不再提示',
            windowManager.addWindows([new UploadDialog()]);
                align: 'inline'
             windowManager.openWindow('UploadDialog');
             });


          } catch (e) {
            // 创建“上传向导”按钮(跳转链接形式)
             console.error('[UploadDialog] 创建失败', e);
             var wizardButton = new OO.ui.ButtonWidget({
            // 降级处理:直接跳转
                label: '✅ 使用上传向导(推荐)',
            window.location.href = mw.util.getUrl('Special:UploadWizard');
                flags: ['primary', 'progressive'],
          }
                href: mw.util.getUrl('Special:UploadWizard'),
        })
                target: '_self',
        .catch(e => {
                framed: true
          console.error('[OOUI] 加载失败', e);
            });
        });
    }


    // 延迟绑定事件,避免阻塞
            // 给按钮添加“记住选择”逻辑
    setTimeout(() => {
            wizardButton.on('click', () => {
      document.addEventListener('click', initDialog, { once: true });
                if (rememberCheckbox.isSelected()) {
    }, 500);
                    mw.storage.set(STORAGE_KEY, 'wizard');
                }
            });


  } catch (e) {
            // 拼接内容
    console.error('[模块2] 初始化异常', e);
            panel.$element.append(
  }
                $('<p>').text('请选择你要使用的上传方式:'),
})();


/**********************
                $('<div>').css({
* 模块 3:全局加载指示器(安全封装)
                    'margin': '12px 0',
**********************/
                    'background': '#f8f9fa',
;(function() {
                    'padding': '10px',
  try {
                    'border': '1px solid #ccc',
    const LoadingIndicator = (function () {
                    'border-radius': '5px'
      // 配置项(可自定义)
                }).append(
      const config = {
                    $('<strong>').text('✅ 上传向导(推荐)'),
        imageUrl: 'https://example.com/loading-spinner.svg',
                    $('<ul>').append(
        fallbackImage: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI0MCIgc3Ryb2tlPSIjMDA3M2JhIiBzdHJva2Utd2lkdGg9IjgiIGZpbGw9Im5vbmUiIHN0cm9rZS1kYXNoYXJyYXk9IjYyLjgzIDYyLjgzIiB0cmFuc2Zvcm09InJvdGF0ZSgzNjAgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iMXMiIHZhbHVlcz0iMCA1MCA1MDszNjAgNTAgNTAiLz48L2NpcmNsZT48L3N2Zz4=',
                        $('<li>').text('支持多文件批量上传'),
        size: '64px',
                        $('<li>').text('显示上传进度条'),
        position: { bottom: '20px', right: '20px' },
                        $('<li>').text('信息填写更完整')
        timeout: 15000,
                    ),
        animation: { fadeIn: 300, fadeOut: 500 },
                    $('<div>').css('margin-top', '8px').append(wizardButton.$element)
        zIndex: 99999
                ),
      };


      let instance = null;
                $('<div>').css({
      let timeoutId = null;
                    'margin-top': '15px',
      let startTime = 0;
                    'background': '#ffffff',
                    'padding': '10px',
                    'border': '1px dashed #bbb',
                    'border-radius': '5px'
                }).append(
                    $('<strong>').text('⚡️ 传统上传方式'),
                    $('<ul>').append(
                        $('<li>').text('界面更简单'),
                        $('<li>').text('加载速度快'),
                        $('<li>').text('适合上传单个文件')
                    )
                ),


      function createLoader() {
                $('<div>').css('margin-top', '15px').append(rememberField.$element)
        const loader = document.createElement('div');
            );
        loader.className = 'global-loader';
        loader.setAttribute('aria-live', 'polite');
       
        Object.assign(loader.style, {
          position: 'fixed',
          width: config.size,
          height: config.size,
          bottom: config.position.bottom,
          right: config.position.right,
          opacity: '0',
          transition: `opacity ${config.animation.fadeIn}ms ease-out`,
          zIndex: config.zIndex,
          pointerEvents: 'none',
          backgroundImage: `url(${config.imageUrl})`,
          backgroundSize: 'contain',
          backgroundRepeat: 'no-repeat'
        });


        // 备用图片处理
            this.$body.append(panel.$element);
        loader.onerror = function() {
          this.style.backgroundImage = `url(${config.fallbackImage})`;
         };
         };


         return loader;
         UploadDialog.prototype.getActionProcess = function (action) {
      }
            if (action === 'classic') {
 
                if (this._rememberCheckbox.isSelected()) {
      function show() {
                    mw.storage.set(STORAGE_KEY, 'classic');
        if (instance) return resetTimer();
                }
       
                return new OO.ui.Process(() => this.close());
        startTime = Date.now();
        instance = createLoader();
        document.body.appendChild(instance);
       
        requestAnimationFrame(() => {
          instance.style.opacity = '1';
        });
       
        resetTimer();
        addEventListeners();
      }
 
      function hide() {
        if (!instance) return;
       
        const elapsed = Date.now() - startTime;
        const minDisplayTime = 500; // 最少显示500ms
        const delay = Math.max(minDisplayTime - elapsed, 0);
       
        clearTimeout(timeoutId);
       
        setTimeout(() => {
          instance.style.opacity = '0';
          instance.setAttribute('aria-busy', 'false');
         
          setTimeout(() => {
            if (instance && instance.parentNode) {
              instance.parentNode.removeChild(instance);
             }
             }
             instance = null;
             return UploadDialog.super.prototype.getActionProcess.call(this, action);
            removeEventListeners();
         };
          }, config.animation.fadeOut);
         }, delay);
      }


      function resetTimer() {
        var dialog = new UploadDialog();
        clearTimeout(timeoutId);
        windowManager.addWindows([dialog]);
        timeoutId = setTimeout(hide, config.timeout);
        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;
      }


       function handleOnline() {
       if (targetAttr === '_blank') return;
        console.log('[Loader] 网络恢复');
      }
      // 排除SPA处理的链接
 
      let isLikelyInternalSPALink = false;
      function handleOffline() {
      if (typeof window.MyAppRouter !== 'undefined' &&
        console.warn('[Loader] 网络断开');
          window.MyAppRouter.isHandling(href)) {
        hide();
        isLikelyInternalSPALink = true;
      }
      }
 
      if (!isLikelyInternalSPALink) {
      function addEventListeners() {
        showLoading('链接点击 - 页面导航');
        window.addEventListener('online', handleOnline);
      }
        window.addEventListener('offline', handleOffline);
    }, true);
      }
  }
 
      function removeEventListeners() {
  // 公开API
        window.removeEventListener('online', handleOnline);
  window.globalLoadingIndicator = {
        window.removeEventListener('offline', handleOffline);
    show: showLoading,
      }
    hide: hideLoading,
 
    configure(newConfig) {
      // 自动绑定生命周期事件
      config = config = Object.assign({}, config, newConfig);
      document.addEventListener('DOMContentLoaded', show);
    },
      window.addEventListener('load', hide);
    initRouter(router) {
     
      if (router && typeof router.beforeEach === 'function') {
      // 页面离开时清理
        router.beforeEach(() => this.show('路由器导航'));
      window.addEventListener('beforeunload', () => {
      }
        if (instance) {
      if (router && typeof router.afterEach === 'function') {
          hide();
        router.afterEach(() => this.hide('路由器导航'));
        }
      }
      });
    }
 
  };
      return {
        show,
  // 初始启用链接跟踪
        hide,
  enableLinkTracking();
        updateConfig: (newConfig) => {
})();
          Object.assign(config, newConfig);
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.LoadingIndicator = LoadingIndicator;
     })(window, document, "clarity", "script", "rsfbla4ho9");
 
  } catch (e) {
    console.error('[模块3] 初始化异常', e);
  }
})();
 
/**********************
* 错误兜底处理(最后执行)
**********************/
;(function() {
  // 如果vConsole未加载,显示简化错误提示
  if (!window.vConsole) {
    window.addEventListener('error', function(event) {
      console.error('页面错误:', event.error);
      const errorBox = document.createElement('div');
      errorBox.style.cssText = `
        position: fixed;
        bottom: 20px;
        left: 20px;
        right: 20px;
        padding: 15px;
        background: #ffebee;
        border: 2px solid #f44336;
        border-radius: 5px;
        z-index: 99999;
        font-family: sans-serif;
      `;
      errorBox.innerHTML = `
        <h3 style="margin-top:0;color:#d32f2f">页面错误</h3>
        <p>${event.message}</p>
        <button onclick="this.parentNode.remove()"  
          style="background:#f44336;color:white;border:none;padding:5px 10px;border-radius:3px">
          关闭
         </button>
      `;
      document.body.appendChild(errorBox);
     });
  }
})();

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");