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

MediaWiki:Citizen.js:修订间差异

MediaWiki界面页面
泡泡留言 | 贡献
API更新:改用Minecraft协议格式,恢复玩家头像列表,聚合展示
泡泡留言 | 贡献
在线判断改用isOnline字段,兼容旧数据回退到players.online
 
(未显示同一用户的1个中间版本)
第5行: 第5行:
   var STARTED = false;
   var STARTED = false;
   var servers = [
   var servers = [
     { id: 'lts-status-platform', title: '月台', subtitle: '重度机械症 · 1服 · 离线正版都可进' },
     { id: 'lts-status-platform', name: '月台', subtitle: '重度机械症 · 1服 · 离线正版都可进' },
     { id: 'lts-status-journey', title: '启程', subtitle: '重度机械症 · 2服 · 已开启正版验证' },
     { id: 'lts-status-journey', name: '启程', subtitle: '重度机械症 · 2服 · 已开启正版验证' },
     { id: 'lts-status-promised', title: '应许', subtitle: '创造/体验服 · 已开启正版验证' },
     { id: 'lts-status-promised', name: '应许', subtitle: '创造/体验服 · 已开启正版验证' },
     { id: 'lts-status-voyage', title: '远行', subtitle: '你好!新蒸程·远行服·已开启正版验证' }
     { id: 'lts-status-voyage', name: '远行', subtitle: '你好!新蒸程·远行服·已开启正版验证' }
   ];
   ];


   var API_PUBLIC = 'https://mc.suanlemon.cc/api/public';
   var API = 'https://mc.suanlemon.cc/api/server/';
  var allData = {};
   var timer = null;
   var timer = null;


   function buildCard(server, online, totalPlayers) {
   function buildCard(server, data) {
    var online = data.online;
     var color = online ? '#3a971e' : '#bf3c2c';
     var color = online ? '#3a971e' : '#bf3c2c';
     var statusText = online ? '在线' : '离线';
     var statusText = online ? '在线' : '离线';


     var html = '<div style="padding:6px 0;border-bottom:1px solid #eee;display:flex;align-items:center;gap:8px;flex-wrap:wrap;">';
     var html = '<div style="padding:6px 0;border-bottom:1px solid #eee;display:flex;align-items:center;gap:8px;flex-wrap:wrap;">';
     html += '<b>' + server.title + '</b>';
     html += '<b>' + server.name + '</b>';
     html += '<span style="font-size:0.8em;color:#888;">' + server.subtitle + '</span>';
     html += '<span style="font-size:0.8em;color:#888;">' + server.subtitle + '</span>';
     html += '<span style="margin-left:auto;font-weight:bold;color:' + color + ';font-size:0.85em;">' + statusText + '</span>';
     html += '<span style="margin-left:auto;font-weight:bold;color:' + color + ';font-size:0.85em;">' + statusText + '</span>';
     html += '</div>';
     html += '</div>';


     if (online && totalPlayers > 0) {
     if (online && data.players) {
       html += '<div style="padding:4px 0 0;display:flex;align-items:center;gap:12px;flex-wrap:wrap;">';
       html += '<div style="padding:4px 0 0;display:flex;align-items:center;gap:12px;flex-wrap:wrap;">';
       html += '<span style="font-size:0.85em;">全服共 ' + totalPlayers + ' 人在线</span>';
       html += '<span style="font-size:0.85em;">' + data.players.online + ' / ' + data.players.max + ' 人</span>';
      if (data.version) html += '<span style="font-size:0.8em;color:#888;">' + data.version.name + '</span>';
       html += '</div>';
       html += '</div>';
      if (data.players.sample && data.players.sample.length > 0) {
        html += '<div style="margin-top:4px;display:flex;flex-wrap:wrap;gap:4px;align-items:center;">';
        data.players.sample.forEach(function(p) {
          html += '<span style="font-size:0.75em;background:#f0f0f0;padding:1px 5px;display:inline-flex;align-items:center;gap:2px;">';
          html += '<img src="https://mineskin.eu/helm/' + p.name + '/24" width="14" height="14" style="image-rendering:pixelated;" onerror="this.style.display=\'none\'">';
          html += p.name;
          html += '</span>';
        });
        html += '</div>';
      }
     }
     }


第33行: 第47行:
   }
   }


  function buildPlayerList(players) {
   function updateSummary() {
    if (!players || players.length === 0) return '';
    var html = '<div style="margin-top:4px;display:flex;flex-wrap:wrap;gap:4px;align-items:center;">';
    players.forEach(function(p) {
      html += '<span style="font-size:0.75em;background:#f0f0f0;padding:1px 5px;display:inline-flex;align-items:center;gap:2px;">';
      html += '<img src="https://mineskin.eu/helm/' + p.name + '/24" width="14" height="14" style="image-rendering:pixelated;" onerror="this.style.display=\'none\'">';
      html += p.name;
      html += '</span>';
    });
    html += '</div>';
    return html;
  }
 
   function updateSummary(online, max, playerCount) {
     var el = document.getElementById('lts-status-summary');
     var el = document.getElementById('lts-status-summary');
     if (!el) return;
     if (!el) return;
    var onlineCount = 0, totalPlayers = 0;
    servers.forEach(function(s) {
      var d = allData[s.id];
      if (d && d.online) {
        onlineCount++;
        if (d.players) totalPlayers += d.players.online || 0;
      }
    });


     el.innerHTML = '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;">' +
     el.innerHTML = '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;">' +
       '<span style="font-size:1.1em;font-weight:bold;color:#3a971e;">' + (online ? '● 在线' : '○ 离线') + '</span>' +
       '<span style="font-size:1.1em;font-weight:bold;color:#3a971e;">' + onlineCount + ' / ' + servers.length + ' 台在线</span>' +
       '<span style="font-size:0.95em;">共 ' + playerCount + ' / ' + max + ' 人在线</span>' +
       '<span style="font-size:0.95em;">共 ' + totalPlayers + ' 人在线</span>' +
       '<span style="margin-left:auto;font-size:0.8em;"><a href="/index.php/服务器信息">查看详情</a></span>' +
       '<span style="margin-left:auto;font-size:0.8em;"><a href="/index.php/服务器信息">查看详情</a></span>' +
       '</div>';
       '</div>';
第61行: 第71行:
     if (!firstEl) return;
     if (!firstEl) return;


     fetch(API_PUBLIC, { mode: 'cors' })
     servers.forEach(function(server) {
      .then(function(r) { return r.json(); })
      var el = document.getElementById(server.id);
      .then(function(data) {
      if (!el) return;
        var online = data.players && data.players.online > 0;
        var playerCount = data.players ? data.players.online : 0;
        var maxPlayers = data.players ? data.players.max : 0;
        var playerList = data.players ? data.players.sample : [];
        var version = data.version ? data.version.name : '';
 
        // Build player avatar list HTML
        var playerHtml = buildPlayerList(playerList);
 
        // Update each server card
        servers.forEach(function(server) {
          var el = document.getElementById(server.id);
          if (!el) return;
          el.innerHTML = buildCard(server, online, playerCount);
        });


        // Append player list to the last server card
      fetch(API + encodeURIComponent(server.name), { mode: 'cors' })
         if (playerHtml && online) {
         .then(function(r) { return r.json(); })
          var lastServer = servers[servers.length - 1];
         .then(function(data) {
          var el = document.getElementById(lastServer.id);
           var serverData = {
          if (el) el.innerHTML += playerHtml;
            online: data.isOnline !== undefined ? data.isOnline : (data.players && data.players.online > 0),
         }
            players: data.players || null,
 
             version: data.version || null
        // Update version info if needed
           };
        if (version) {
          allData[server.id] = serverData;
           var voyEl = document.getElementById('lts-status-voyage');
          el.innerHTML = buildCard(server, serverData);
          if (voyEl && version) {
          updateSummary();
             // add version to 远行 card
        })
           }
        .catch(function() {
        }
           allData[server.id] = { online: false };
 
        updateSummary(online, maxPlayers, playerCount);
      })
      .catch(function() {
        servers.forEach(function(server) {
           var el = document.getElementById(server.id);
          if (!el) return;
           el.innerHTML = '<div style="color:#bf3c2c;padding:4px 0;">查询失败</div>';
           el.innerHTML = '<div style="color:#bf3c2c;padding:4px 0;">查询失败</div>';
          updateSummary();
         });
         });
        updateSummary(false, 0, 0);
    });
      });
   }
   }



2026年5月27日 (三) 01:21的最新版本

/* 服务器状态查询 - 柠檬树服务器 */
console.log('[LTS] 状态查询脚本已加载');

(function() {
  var STARTED = false;
  var servers = [
    { id: 'lts-status-platform', name: '月台', subtitle: '重度机械症 · 1服 · 离线正版都可进' },
    { id: 'lts-status-journey', name: '启程', subtitle: '重度机械症 · 2服 · 已开启正版验证' },
    { id: 'lts-status-promised', name: '应许', subtitle: '创造/体验服 · 已开启正版验证' },
    { id: 'lts-status-voyage', name: '远行', subtitle: '你好!新蒸程·远行服·已开启正版验证' }
  ];

  var API = 'https://mc.suanlemon.cc/api/server/';
  var allData = {};
  var timer = null;

  function buildCard(server, data) {
    var online = data.online;
    var color = online ? '#3a971e' : '#bf3c2c';
    var statusText = online ? '在线' : '离线';

    var html = '<div style="padding:6px 0;border-bottom:1px solid #eee;display:flex;align-items:center;gap:8px;flex-wrap:wrap;">';
    html += '<b>' + server.name + '</b>';
    html += '<span style="font-size:0.8em;color:#888;">' + server.subtitle + '</span>';
    html += '<span style="margin-left:auto;font-weight:bold;color:' + color + ';font-size:0.85em;">' + statusText + '</span>';
    html += '</div>';

    if (online && data.players) {
      html += '<div style="padding:4px 0 0;display:flex;align-items:center;gap:12px;flex-wrap:wrap;">';
      html += '<span style="font-size:0.85em;">' + data.players.online + ' / ' + data.players.max + ' 人</span>';
      if (data.version) html += '<span style="font-size:0.8em;color:#888;">' + data.version.name + '</span>';
      html += '</div>';

      if (data.players.sample && data.players.sample.length > 0) {
        html += '<div style="margin-top:4px;display:flex;flex-wrap:wrap;gap:4px;align-items:center;">';
        data.players.sample.forEach(function(p) {
          html += '<span style="font-size:0.75em;background:#f0f0f0;padding:1px 5px;display:inline-flex;align-items:center;gap:2px;">';
          html += '<img src="https://mineskin.eu/helm/' + p.name + '/24" width="14" height="14" style="image-rendering:pixelated;" onerror="this.style.display=\'none\'">';
          html += p.name;
          html += '</span>';
        });
        html += '</div>';
      }
    }

    return html;
  }

  function updateSummary() {
    var el = document.getElementById('lts-status-summary');
    if (!el) return;

    var onlineCount = 0, totalPlayers = 0;
    servers.forEach(function(s) {
      var d = allData[s.id];
      if (d && d.online) {
        onlineCount++;
        if (d.players) totalPlayers += d.players.online || 0;
      }
    });

    el.innerHTML = '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;">' +
      '<span style="font-size:1.1em;font-weight:bold;color:#3a971e;">' + onlineCount + ' / ' + servers.length + ' 台在线</span>' +
      '<span style="font-size:0.95em;">共 ' + totalPlayers + ' 人在线</span>' +
      '<span style="margin-left:auto;font-size:0.8em;"><a href="/index.php/服务器信息">查看详情</a></span>' +
      '</div>';
  }

  function doFetch() {
    var firstEl = document.getElementById('lts-status-platform');
    if (!firstEl) return;

    servers.forEach(function(server) {
      var el = document.getElementById(server.id);
      if (!el) return;

      fetch(API + encodeURIComponent(server.name), { mode: 'cors' })
        .then(function(r) { return r.json(); })
        .then(function(data) {
          var serverData = {
            online: data.isOnline !== undefined ? data.isOnline : (data.players && data.players.online > 0),
            players: data.players || null,
            version: data.version || null
          };
          allData[server.id] = serverData;
          el.innerHTML = buildCard(server, serverData);
          updateSummary();
        })
        .catch(function() {
          allData[server.id] = { online: false };
          el.innerHTML = '<div style="color:#bf3c2c;padding:4px 0;">查询失败</div>';
          updateSummary();
        });
    });
  }

  function start() {
    if (STARTED) return;
    var firstEl = document.getElementById('lts-status-platform');
    if (!firstEl) return;
    STARTED = true;
    console.log('[LTS] 找到容器,开始查询');
    doFetch();
    timer = setInterval(doFetch, 15000);
  }

  if (document.readyState === 'complete' || document.readyState === 'interactive') {
    start();
  } else {
    document.addEventListener('DOMContentLoaded', start);
  }

  mw.hook('wikipage.content').add(start);
})();
/* === 售票亭统计 === */
$(function() {
  if (mw.config.get('wgPageName') !== '售票亭') return;
  var $stats = $('#ticket-stats');
  if (!$stats.length) return;
  var p = 0, f = 0, d = '';
  $('#mw-content-text h3, #mw-content-text h4').each(function() {
    var m = $(this).text().match(/(\d+月\d+日)\s*发车/);
    if (!m) return;
    if (!d) d = m[1];
    var $tbl = $(this).nextAll('table').first();
    if (!$tbl.length) $tbl = $(this).parent().nextAll('table').first();
    if (!$tbl.length) return;
    var txt = $tbl.text();
    p += (txt.match(/\[.+?\]/g) || []).length;
    f += (txt.match(/未能登车/g) || []).length;
  });
  $stats.html('🎫 已发放车票 <strong>' + p + '</strong> 张 &nbsp;|&nbsp; ✗ 未能登车 <strong>' + f + '</strong> 人 &nbsp;|&nbsp; 📅 最近更新 <strong>' + d + '</strong>');
});

/* 更新日志 - 移动端Tab切换 */
(function() {
  var logLink = document.querySelector('a[href="#tab-log"]');
  var todoLink = document.querySelector('a[href="#tab-todo"]');
  var logDiv = document.getElementById('tab-log');
  var todoDiv = document.getElementById('tab-todo');
  if (!logLink || !todoLink) return;

  function switchTab(tab) {
    logLink.classList.remove('lts-tab-active');
    todoLink.classList.remove('lts-tab-active');
    if (logDiv) logDiv.classList.remove('lts-tab-active');
    if (todoDiv) todoDiv.classList.remove('lts-tab-active');
    if (tab === 'log') {
      logLink.classList.add('lts-tab-active');
      if (logDiv) logDiv.classList.add('lts-tab-active');
    } else {
      todoLink.classList.add('lts-tab-active');
      if (todoDiv) todoDiv.classList.add('lts-tab-active');
    }
  }

  logLink.addEventListener('click', function(e) {
    e.preventDefault();
    switchTab('log');
  });
  todoLink.addEventListener('click', function(e) {
    e.preventDefault();
    switchTab('todo');
  });

  // 默认显示更新日志
  switchTab('log');
})();