MediaWiki:Common.js

来自RMzas&SMS_Knowledge_Base_Wiki
FME-514(讨论 | 贡献)2026年10月18日 (日) 18:58:20的版本 (添加跟随系统、浅色、深色主题选择与浏览器偏好保存)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转到导航 跳转到搜索

注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
  • Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
  • Internet Explorer:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:前往菜单 → 设置(Mac为Opera → Preferences),然后隐私和安全 → 清除浏览数据 → 缓存的图片和文件。
/* 这里的任何JavaScript将为所有用户在每次页面载入时加载。 */

/* 阅读主题:仅在当前浏览器保存,未选择时跟随系统。 */
(function () {
  'use strict';

  var root = document.documentElement;
  var storageKey = 'rmzas-wiki-theme';
  var systemTheme = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
  var selector;
  var mode = 'auto';

  // 防止脚本重复执行时添加多个控件或事件监听。
  if (root.hasAttribute('data-rmzas-theme')) return;

  function normalize(value) {
    return value === 'light' || value === 'dark' ? value : 'auto';
  }

  function applyTheme() {
    var dark = mode === 'dark' || (mode === 'auto' && systemTheme && systemTheme.matches);
    root.setAttribute('data-rmzas-theme', mode);
    root.classList.toggle('rmzas-theme-dark', !!dark);
    if (selector) selector.value = mode;
  }

  try {
    mode = normalize(window.localStorage.getItem(storageKey));
  } catch (error) {
    // 存储不可用时仍允许切换,当前页面内保留选择。
  }
  // 不等待 DOM 就绪,尽早应用配色;Common.js 本身仍是异步加载的。
  applyTheme();

  if (systemTheme) {
    if (systemTheme.addEventListener) {
      systemTheme.addEventListener('change', applyTheme);
    } else if (systemTheme.addListener) {
      systemTheme.addListener(applyTheme);
    }
  }

  window.addEventListener('storage', function (event) {
    if (event.key === storageKey || event.key === null) {
      mode = normalize(event.newValue);
      applyTheme();
    }
  });

  function addThemeControl() {
    if (document.getElementById('rmzas-theme-select')) return;

    // Vector / MonoBook 的个人工具栏;Timeless 使用用户链接区域。
    var menu = document.querySelector('#p-personal ul, #p-personal .mw-portlet-body ul, #p-personal .body ul, #p-personal-inner ul');
    var control = document.createElement(menu ? 'li' : 'div');
    control.id = 'pt-rmzas-theme';
    control.className = 'rmzas-theme-control';
    if (!menu) control.classList.add('rmzas-theme-control-floating');

    var label = document.createElement('label');
    label.htmlFor = 'rmzas-theme-select';
    label.textContent = '主题';
    selector = document.createElement('select');
    selector.id = 'rmzas-theme-select';
    selector.title = '选择阅读主题(此浏览器会记住你的选择)';

    [['auto', '跟随系统'], ['light', '浅色'], ['dark', '深色']].forEach(function (item) {
      var option = document.createElement('option');
      option.value = item[0];
      option.textContent = item[1];
      selector.appendChild(option);
    });
    selector.value = mode;
    selector.addEventListener('change', function () {
      mode = normalize(selector.value);
      applyTheme();
      try {
        window.localStorage.setItem(storageKey, mode);
      } catch (error) {
        // 隐私设置禁用存储时不影响配色或原有站点脚本。
      }
    });

    control.appendChild(label);
    control.appendChild(selector);
    if (menu) {
      menu.insertBefore(control, menu.firstChild);
    } else {
      document.body.appendChild(control);
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', addThemeControl);
  } else {
    addThemeControl();
  }
})();

// 显示最近更新的页面列表(带时间)
setTimeout(function() {
  //console.log('开始加载最近更新页面列表');
  
  var sidebar = document.getElementById('mw-panel');
  if (!sidebar) {
    console.log('未找到侧边栏');
    return;
  }
  
  var items = sidebar.getElementsByTagName('li');
  var targetItem = null;
  for (var i = 0; i < items.length; i++) {
    if (items[i].textContent.indexOf('最近更新') !== -1) {
      targetItem = items[i];
      break;
    }
  }
  
  if (!targetItem) {
    console.log('未找到目标容器');
    return;
  }
  
  targetItem.textContent = '';
  targetItem.innerHTML = '最近更新:<br>加载中...';
  
  // API请求添加timestamp参数,获取更新时间
  var apiUrl = mw.util.wikiScript('api') + '?';
  apiUrl += 'action=query';
  apiUrl += '&list=recentchanges';
  apiUrl += '&rcprop=title|timestamp'; // 同时获取标题和时间戳
  apiUrl += '&rclimit=10';
  apiUrl += '&rcdaylimit=30';
  apiUrl += '&format=json';
  
  fetch(apiUrl)
    .then(function(response) {
      if (!response.ok) throw new Error('API请求失败:' + response.status);
      return response.json();
    })
    .then(function(data) {
      targetItem.innerHTML = '最近更新:<br>';
      
      if (!data.query || !data.query.recentchanges || data.query.recentchanges.length === 0) {
        targetItem.innerHTML += '暂无更新';
        return;
      }
      
      var seenTitles = new Set();
      var uniqueUpdates = [];
      for (var i = 0; i < data.query.recentchanges.length; i++) {
        var page = data.query.recentchanges[i];
        var title = page.title;
        if (!seenTitles.has(title)) {
          seenTitles.add(title);
          uniqueUpdates.push(page); // 包含title和timestamp
          if (uniqueUpdates.length >= 6) break;
        }
      }
      
      var list = document.createElement('ul');
      list.style.listStyle = 'none';
      list.style.paddingLeft = '10px';
      list.style.margin = '5px 0';
      
      uniqueUpdates.forEach(function(page) {
        // 处理时间戳:转换为本地时间(年-月-日 时:分)
        var date = new Date(page.timestamp);
        var timeStr = date.toLocaleString('zh-CN', {
          month: '2-digit',    // 月份(2位)
          day: '2-digit',      // 日期(2位)
          hour: '2-digit',     // 小时(2位)
          minute: '2-digit',   // 分钟(2位)
          second: '2-digit',   // 新增:显示秒(2位)
          hour12: false        // 强制24小时制(避免上午/下午)
        }).replace(',', '');   // 移除可能的逗号分隔符
        
        var listItem = document.createElement('li');
        listItem.style.margin = '3px 0'; // 每条间距
        
        var link = document.createElement('a');
        link.href = mw.util.getUrl(page.title);
        link.textContent = page.title;
        
        // 时间显示(灰色小字)
        var timeSpan = document.createElement('span');
        timeSpan.textContent = ' (' + timeStr + ')';
        timeSpan.className = 'rmzas-recent-time';
        timeSpan.style.fontSize = '0.8em'; // 小字
        timeSpan.style.marginLeft = '5px';
        
        listItem.appendChild(link);
        listItem.appendChild(timeSpan);
        list.appendChild(listItem);
      });
      
      targetItem.appendChild(list);
    })
    .catch(function(error) {
      console.error('加载失败:', error);
      targetItem.innerHTML = '最近更新:<br>加载失败';
    });
  
}, 1000);