打开/关闭菜单
228
885
35
2802
植物大战僵尸杂交版Wiki
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:Common.js:修订间差异

MediaWiki界面页面
无编辑摘要
无编辑摘要
第41行: 第41行:
     document.head.appendChild(rainbowStyle);
     document.head.appendChild(rainbowStyle);


     // 注入状态标签样式
     // 注入状态圆点样式
     var statusStyle = document.createElement('style');
     var statusStyle = document.createElement('style');
     statusStyle.textContent =
     statusStyle.textContent =
第52行: 第52行:
             'vertical-align: middle;' +
             'vertical-align: middle;' +
         '}' +
         '}' +
         '.status-online { background-color: #4CAF50; }' +   // 绿色
         '.status-online { background-color: #4CAF50; }' +
         '.status-away   { background-color: #FF9800; }' +   // 橙色
         '.status-away   { background-color: #FF9800; }' +
         '.status-offline { background-color: #9E9E9E; }';   // 灰色
         '.status-offline { background-color: #9E9E9E; }';
     document.head.appendChild(statusStyle);
     document.head.appendChild(statusStyle);


     // ---------- 辅助函数 ----------
     // ---------- 辅助函数 ----------
    // 提取纯净用户名(卡片内有<span>,取span文本)
     function getUserName(link) {
     function getUserName(link) {
         var $span = $(link).find('span').first();
         var $span = $(link).find('span').first();
         if ($span.length) return $span.text().trim();
         if ($span.length) return $span.text().trim();
         return $(link).text().trim();
         return $(link).text().trim();
    }
    // 判断是否是用户页链接(卡片内特征:包含<span>,或拥有mw-userlink类)
    function isUserLink(link) {
        return $(link).is('a.mw-userlink') || $(link).find('span').length > 0;
     }
     }


第87行: 第93行:
         });
         });


         // 1. 先应用颜色(复用原有逻辑)
         // 1. 应用颜色(复用原有逻辑)
         var batchSize = 50;
         var batchSize = 50;
         var batches = [];
         var batches = [];
第132行: 第138行:
         });
         });


         // 2. 为每个用户链接添加状态标签(异步,利用缓存)
         // 2. 只为用户链接添加状态圆点(跳过“讨论”“贡献”等)
         $fresh.each(function () {
         $fresh.each(function () {
             var $link = $(this);
             if (isUserLink(this)) {
            var username = getUserName(this);
                addStatusDot($(this), getUserName(this));
             addStatusDot($link, username);
             }
         });
         });
     }
     }
第142行: 第148行:
     // 给单个链接添加状态圆点
     // 给单个链接添加状态圆点
     function addStatusDot($link, username) {
     function addStatusDot($link, username) {
         // 如果已经添加过了就跳过
         // 防止重复添加
         if ($link.data('status-dot-added')) return;
         if ($link.data('status-dot-added')) return;
         $link.data('status-dot-added', true);
         $link.data('status-dot-added', true);


         // 在链接后面插入圆点容器(如果还没插入)
         // 在链接后面插入圆点容器
         var $dot = $('<span class="user-status-dot status-offline" title="离线">');
         var $dot = $('<span class="user-status-dot status-offline" title="离线">');
         $link.after($dot);
         $link.after($dot);
第157行: 第163行:
             try {
             try {
                 var data = JSON.parse(cached);
                 var data = JSON.parse(cached);
                // 缓存5分钟
                 if (now - data.timestamp < 5 * 60 * 1000) {
                 if (now - data.timestamp < 5 * 60 * 1000) {
                     updateDotStyle($dot, data.lastEditTime);
                     updateDotStyle($dot, data.lastEditTime);
第165行: 第170行:
         }
         }


         // 没有可用缓存,查询 API
         // 查询 API
         var api = new mw.Api();
         var api = new mw.Api();
         api.get({
         api.get({
第178行: 第183行:
                 lastEditTime = data.query.usercontribs[0].timestamp;
                 lastEditTime = data.query.usercontribs[0].timestamp;
             }
             }
            // 缓存结果
             localStorage.setItem(cacheKey, JSON.stringify({
             localStorage.setItem(cacheKey, JSON.stringify({
                 lastEditTime: lastEditTime,
                 lastEditTime: lastEditTime,
第185行: 第189行:
             updateDotStyle($dot, lastEditTime);
             updateDotStyle($dot, lastEditTime);
         }).fail(function () {
         }).fail(function () {
             // 查询失败,保留默认灰色
             // 失败保持灰色
         });
         });
     }
     }


    // 根据最后编辑时间更新圆点样式
     function updateDotStyle($dot, lastEditTime) {
     function updateDotStyle($dot, lastEditTime) {
         if (!lastEditTime) {
         if (!lastEditTime) {
第197行: 第200行:
         }
         }
         var last = new Date(lastEditTime).getTime();
         var last = new Date(lastEditTime).getTime();
         var now = Date.now();
         var diffMinutes = (Date.now() - last) / 60000;
        var diffMinutes = (now - last) / 60000;
         if (diffMinutes < 15) {
         if (diffMinutes < 15) {
             $dot.attr('title', '在线(15分钟内活跃)');
             $dot.attr('title', '在线(15分钟内活跃)');
第211行: 第213行:
     }
     }


     // 选择器(正文 + 卡片)
     // 选择器:正文用户链接 + 卡片内所有链接(后续会过滤)
     var linkSelector = 'a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a';
     var linkSelector = 'a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a';


第226行: 第228行:
     });
     });


     // 定时器兜底(每3秒扫描一次,只处理新链接)
     // 定时器兜底(每3秒扫描一次)
     setInterval(function () {
     setInterval(function () {
         colorizeAndStatus($(linkSelector));
         colorizeAndStatus($(linkSelector));
     }, 3000);
     }, 3000);
});
});

2026年5月31日 (日) 07:50的版本

/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */

// 自动加载 MediaWiki:Footer 页面内容,并插入到每个页面底部

$(document).ready(function() {
    const namespace = mw.config.get('wgNamespaceNumber');
    const action = mw.config.get('wgAction');
    
    if (namespace !== 0 || action !== 'view') {
        return;
    }

    fetch("/api.php?action=parse&page=MediaWiki:Footer&format=json")
        .then(res => res.json())
        .then(data => {
            if (data.parse && data.parse.text) {
                const html = data.parse.text['*'];
                $('#mw-content-text').append('<div class="global-footer">' + html + '</div>');
            }
        });
});
$(function () {
    // 动态注入彩虹样式
    var rainbowStyle = document.createElement('style');
    rainbowStyle.textContent =
        '.rainbow-user {' +
            'font-weight: bold;' +
            'background: repeating-linear-gradient(90deg, red 0px, orange 10px, yellow 20px, green 30px, blue 40px, indigo 50px, violet 60px);' +
            '-webkit-background-clip: text;' +
            '-webkit-text-fill-color: transparent;' +
            'background-clip: text;' +
            'color: #FFD700;' +
        '}' +
        '.rainbow-user::after {' +
            'content: "⭐⭐⭐⭐⭐";' +
            'margin-left: 2px;' +
            'font-weight: normal;' +
            '-webkit-text-fill-color: initial;' +
            'color: #FFD700;' +
        '}';
    document.head.appendChild(rainbowStyle);

    // 注入状态圆点样式
    var statusStyle = document.createElement('style');
    statusStyle.textContent =
        '.user-status-dot {' +
            'display: inline-block;' +
            'width: 8px;' +
            'height: 8px;' +
            'border-radius: 50%;' +
            'margin-left: 4px;' +
            'vertical-align: middle;' +
        '}' +
        '.status-online  { background-color: #4CAF50; }' +
        '.status-away    { background-color: #FF9800; }' +
        '.status-offline { background-color: #9E9E9E; }';
    document.head.appendChild(statusStyle);

    // ---------- 辅助函数 ----------
    // 提取纯净用户名(卡片内有<span>,取span文本)
    function getUserName(link) {
        var $span = $(link).find('span').first();
        if ($span.length) return $span.text().trim();
        return $(link).text().trim();
    }

    // 判断是否是用户页链接(卡片内特征:包含<span>,或拥有mw-userlink类)
    function isUserLink(link) {
        return $(link).is('a.mw-userlink') || $(link).find('span').length > 0;
    }

    // 核心:给链接上色 + 状态标签
    function colorizeAndStatus($links) {
        if ($links.length === 0) return;

        // 过滤出还没处理的链接(避免重复请求)
        var $fresh = $links.filter(function () {
            return !$(this).data('user-status-processed');
        });
        if ($fresh.length === 0) return;

        // 收集用户名
        var users = [];
        $fresh.each(function () {
            var name = getUserName(this);
            if (name && users.indexOf(name) === -1) users.push(name);
        });
        if (users.length === 0) return;

        // 标记这些链接为已处理(颜色部分)
        $fresh.each(function () {
            $(this).data('user-status-processed', true);
        });

        // 1. 应用颜色(复用原有逻辑)
        var batchSize = 50;
        var batches = [];
        for (var i = 0; i < users.length; i += batchSize) {
            batches.push(users.slice(i, i + batchSize));
        }

        var processColorBatch = function (batch) {
            var api = new mw.Api();
            return api.get({
                action: 'query',
                list: 'users',
                ususers: batch.join('|'),
                usprop: 'editcount'
            }).then(function (data) {
                var classMap = {};
                if (data.query && data.query.users) {
                    data.query.users.forEach(function (u) {
                        var ec = u.editcount || 0;
                        if (ec >= 5000) classMap[u.name] = 'rainbow-user';
                        else if (ec >= 2000) classMap[u.name] = 'gold-user';
                        else if (ec >= 1000) classMap[u.name] = 'platinum-user';
                        else if (ec >= 500) classMap[u.name] = 'silver-user';
                        else if (ec >= 1) classMap[u.name] = 'bronze-user';
                    });
                }
                $fresh.each(function () {
                    var $this = $(this);
                    var name = getUserName(this);
                    var cls = classMap[name];
                    if (cls) {
                        $this.removeClass('bronze-user silver-user platinum-user gold-user rainbow-user');
                        $this.addClass(cls);
                    }
                });
            });
        };

        var colorPromise = $.Deferred().resolve();
        batches.forEach(function (batch) {
            colorPromise = colorPromise.then(function () {
                return processColorBatch(batch);
            });
        });

        // 2. 只为用户链接添加状态圆点(跳过“讨论”“贡献”等)
        $fresh.each(function () {
            if (isUserLink(this)) {
                addStatusDot($(this), getUserName(this));
            }
        });
    }

    // 给单个链接添加状态圆点
    function addStatusDot($link, username) {
        // 防止重复添加
        if ($link.data('status-dot-added')) return;
        $link.data('status-dot-added', true);

        // 在链接后面插入圆点容器
        var $dot = $('<span class="user-status-dot status-offline" title="离线">');
        $link.after($dot);

        // 检查本地缓存
        var cacheKey = 'mw_user_status_' + mw.config.get('wgDBname') + '_' + username;
        var cached = localStorage.getItem(cacheKey);
        var now = Date.now();
        if (cached) {
            try {
                var data = JSON.parse(cached);
                if (now - data.timestamp < 5 * 60 * 1000) {
                    updateDotStyle($dot, data.lastEditTime);
                    return;
                }
            } catch (e) {}
        }

        // 查询 API
        var api = new mw.Api();
        api.get({
            action: 'query',
            list: 'usercontribs',
            ucuser: username,
            uclimit: 1,
            ucprop: 'timestamp'
        }).then(function (data) {
            var lastEditTime = null;
            if (data.query && data.query.usercontribs && data.query.usercontribs.length > 0) {
                lastEditTime = data.query.usercontribs[0].timestamp;
            }
            localStorage.setItem(cacheKey, JSON.stringify({
                lastEditTime: lastEditTime,
                timestamp: now
            }));
            updateDotStyle($dot, lastEditTime);
        }).fail(function () {
            // 失败保持灰色
        });
    }

    function updateDotStyle($dot, lastEditTime) {
        if (!lastEditTime) {
            $dot.attr('title', '离线');
            $dot.removeClass('status-online status-away').addClass('status-offline');
            return;
        }
        var last = new Date(lastEditTime).getTime();
        var diffMinutes = (Date.now() - last) / 60000;
        if (diffMinutes < 15) {
            $dot.attr('title', '在线(15分钟内活跃)');
            $dot.removeClass('status-offline status-away').addClass('status-online');
        } else if (diffMinutes < 60) {
            $dot.attr('title', '近期活跃(1小时内)');
            $dot.removeClass('status-offline status-online').addClass('status-away');
        } else {
            $dot.attr('title', '离线');
            $dot.removeClass('status-online status-away').addClass('status-offline');
        }
    }

    // 选择器:正文用户链接 + 卡片内所有链接(后续会过滤)
    var linkSelector = 'a.mw-userlink, .citizen-menu_card-content a, .citizen-userMenu a';

    // 初始扫描
    colorizeAndStatus($(linkSelector));

    // 监听 DOM 变化
    var observer = new MutationObserver(function () {
        colorizeAndStatus($(linkSelector));
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 定时器兜底(每3秒扫描一次)
    setInterval(function () {
        colorizeAndStatus($(linkSelector));
    }, 3000);
});