公告:本站正处于条目建设期。编辑前请阅读 编辑原则;事务讨论请至 管理员告示板。

或许你可以看看这个致全体读者的一封信

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

来自2b2t.xin wiki
跳转到导航 跳转到搜索
Admin​(留言 | 贡献)
(一键巡查脚本)
 
Admin​(留言 | 贡献)
小 (已保护“MediaWiki:Gadget-OneClickPatrol.js”​([编辑=仅允许管理员](无限期)​[移动=仅允许管理员](无限期)))
 
(没有差异)

2026年9月15日 (二) 22:48的最新版本

/* OneClickPatrol — 最近更改 / 监视列表一键巡查 (MediaWiki 1.39)
 * 仅对拥有 patrol 权限的用户(sysop / patroller)生效。
 * 作用:在每条「未巡查」变更右侧加一个「✓ 巡查」按钮,
 *      覆盖核心本不显示按钮的日志/上传类条目;
 *      页面顶部另提供「✓ 巡查本页全部未巡查」一键处理整页。
 */
(function () {
    'use strict';

    var page = mw.config.get('wgCanonicalSpecialPageName');
    if (page !== 'Recentchanges' && page !== 'Watchlist') {
        return;
    }

    mw.loader.using(['mediawiki.api', 'mediawiki.util']).done(function () {
        var api = new mw.Api();

        mw.util.addCSS(
            '.mw-ocp-btn{margin-left:6px;padding:0 6px;border:1px solid #a2a9b1;' +
            'background:#f8f9fa;color:#202122;border-radius:2px;cursor:pointer;font-size:11px;}' +
            '.mw-ocp-btn:hover{background:#eaecf0;}' +
            '.mw-ocp-btn:disabled{opacity:.6;cursor:default;}' +
            '.mw-ocp-all{margin:6px 0;padding:3px 10px;border:1px solid #14866d;' +
            'background:#eaf3ff;color:#14866d;border-radius:2px;cursor:pointer;}'
        );

        // 从一行的标题链接 + 用户链接构造与 API 一致的 key
        function rowKey($li) {
            var $title = $li.find('.mw-changeslist-title').first();
            var title = '';
            if ($title.length) {
                var href = $title.attr('href') || '';
                var m = href.match(/[?&]title=([^&]+)/) || href.match(/\/([^?]+)$/);
                if (m) { title = decodeURIComponent(m[1].replace(/\+/g, ' ')); }
            }
            var $user = $li.find('.mw-userlink').first();
            var user = '';
            if ($user.length) {
                var uh = $user.attr('href') || '';
                var um = uh.match(/User:([^?&]+)/);
                if (um) { user = decodeURIComponent(um[1].replace(/_/g, ' ')); }
            }
            return title + '|' + user;
        }

        function patrol(rcid, $btn, $li) {
            $btn.prop('disabled', true).text('巡查中…');
            api.postWithToken('patrol', {
                action: 'patrol',
                rcid: String(rcid),
                formatversion: 2
            }).done(function () {
                $li.removeClass('unpatrolled').addClass('mw-patrolled-ok');
                $btn.text('✓ 已巡查').css({ color: '#14866d', borderColor: '#14866d' });
            }).fail(function (code, data) {
                var msg = (data && data.error && data.error.info) ? data.error.info : (code || '失败');
                $btn.prop('disabled', false).text('✗ 失败').attr('title', msg);
            });
        }

        function addButtons(map) {
            $('#mw-content-text .mw-changeslist').find('li').each(function () {
                var $li = $(this);
                if ($li.data('ocp-done')) { return; }
                var key = rowKey($li);
                var rcid = null;
                // 1) 核心已渲染的巡逻链接(他人普通编辑/新建)
                var $patrol = $li.find('a[href*="action=patrol"]').first();
                if ($patrol.length) {
                    var pm = $patrol.attr('href').match(/rcid=(\d+)/);
                    if (pm) { rcid = pm[1]; }
                }
                // 2) 通过 API 未巡查列表匹配(覆盖日志/上传等核心不给按钮的条目)
                if (!rcid && map[key]) { rcid = map[key]; }
                if (!rcid) { return; }
                $li.data('ocp-done', true);

                var $btn = $('<button>')
                    .addClass('mw-ocp-btn')
                    .attr('type', 'button')
                    .text('✓ 巡查')
                    .on('click', function (e) {
                        e.preventDefault();
                        patrol(rcid, $btn, $li);
                        return false;
                    });

                var $box = $li.find('.mw-changeslist-buttons, .mw-changeslist-links').first();
                if ($box.length) {
                    $box.append($('<span> </span>').append($btn));
                } else {
                    $li.append($('<span> </span>').append($btn));
                }
            });
        }

        function buildMap() {
            return api.get({
                action: 'query',
                list: 'recentchanges',
                rcprop: 'ids|title|user',
                rcshow: '!patrolled',
                rclimit: 100,
                formatversion: 2
            }).then(function (data) {
                var map = {};
                var list = (data && data.query && data.query.recentchanges) || [];
                list.forEach(function (rc) {
                    map[rc.title + '|' + rc.user] = rc.rcid;
                });
                return map;
            }, function () { return {}; });
        }

        $(function () {
            buildMap().then(function (map) {
                addButtons(map);
                mw.hook('wikipage.content').add(function () { addButtons(map); });

                var $all = $('<button>')
                    .addClass('mw-ocp-all')
                    .attr('type', 'button')
                    .text('✓ 巡查本页全部未巡查')
                    .on('click', function () {
                        $('#mw-content-text .mw-changeslist').find('button.mw-ocp-btn').each(function () {
                            var $b = $(this);
                            if ($b.text() === '✓ 巡查') { $b.click(); }
                        });
                    });
                $('#firstHeading').after($all);
            });
        });
    });
})();