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

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

MediaWiki界面页面
第1行: 第1行:
(() => {
(function() {
     "use strict";
     "use strict";
     $((() => (async () => {
     jQuery(document).ready(function() {
        console.log('ShowContributors.js 开始执行', {
            mediaWikiVersion: mw.config.get('wgVersion'),
            skin: mw.config.get('skin'),
            namespace: mw.config.get('wgNamespaceNumber'),
            action: mw.config.get('wgAction'),
            articleId: mw.config.get('wgArticleId')
        });
 
         if (
         if (
             ![0, 2, 4, 10, 12, 14, 828, 274].includes(mw.config.get("wgNamespaceNumber")) ||
             ![0, 2, 4, 10, 12, 14, 828, 274].includes(mw.config.get("wgNamespaceNumber")) ||
             0 === mw.config.get("wgArticleId") ||
             0 === mw.config.get("wgArticleId") ||
             !["view", "history"].includes(mw.config.get("wgAction"))
             !["view", "history"].includes(mw.config.get("wgAction"))
         )
         ) {
            console.log('脚本因条件不满足退出');
             return;
             return;
          
         }
         mw.loader.addStyleTag(`
 
             #show-contributor-button {
         mw.loader.addStyleTag(
                 float: right;
             '#show-contributor-button {' +
                 margin-left: .5em;
                 'float: right;' +
                 margin-right: 0;
                 'margin-left: .5em;' +
             }
                 'margin-right: 0;' +
             #show-contributor-header {
             '}' +
                 background: #fff;
             '#show-contributor-header {' +
                 border-bottom: 1px solid #aaa;
                 'background: #fff;' +
                 font-weight: 600;
                 'border-bottom: 1px solid #aaa;' +
                 padding: .3em;
                 'font-weight: 600;' +
                 position: sticky;
                 'padding: .3em;' +
                 text-align: center;
                 'position: sticky;' +
                 top: 0;
                 'text-align: center;' +
             }
                 'top: 0;' +
             #show-contributor-headline {
             '}' +
                 font-size: 1.3em;
             '#show-contributor-headline {' +
             }
                 'font-size: 1.3em;' +
             #show-contributor-close {
             '}' +
                 border-radius: 50%;
             '#show-contributor-close {' +
                 cursor: pointer;
                 'border-radius: 50%;' +
                 position: absolute;
                 'cursor: pointer;' +
                 right: 5px;
                 'position: absolute;' +
                 top: 5px;
                 'right: 5px;' +
             }
                 'top: 5px;' +
             #show-contributor-close:hover {
             '}' +
                 background-color: #eee;
             '#show-contributor-close:hover {' +
             }
                 'background-color: #eee;' +
             #show-contributor-table {
             '}' +
                 margin: 0;
             '#show-contributor-table {' +
                 width: 100%;
                 'margin: 0;' +
             }
                 'width: 100%;' +
             #show-contributor-table .user-avatar {
             '}' +
                 border-radius: 50%;
             '#show-contributor-table .user-avatar {' +
                 height: 20px;
                 'border-radius: 50%;' +
                 width: 20px;
                 'height: 20px;' +
             }
                 'width: 20px;' +
             .skin-citizen #show-contributor-button {
             '}' +
                 float: none;
             '.skin-citizen #show-contributor-button {' +
                 margin: 0 0.5em 0 0;
                 'float: none;' +
                 display: inline-flex;
                 'margin: 0 0.5em 0 0;' +
                 align-items: center;
                 'display: inline-flex;' +
                 vertical-align: middle;
                 'align-items: center;' +
             }
                 'vertical-align: middle;' +
             @media (min-width: 1120px) {
             '}' +
                 .skin-citizen .citizen-page-header-inner {
             '@media (min-width: 1120px) {' +
                     display: flex;
                 '.skin-citizen .citizen-page-header-inner {' +
                     justify-content: space-between;
                     'display: flex;' +
                     align-items: center;
                     'justify-content: space-between;' +
                 }
                     'align-items: center;' +
                 .skin-citizen .citizen-page-heading {
                 '}' +
                     flex-grow: 1;
                 '.skin-citizen .citizen-page-heading {' +
                 }
                     'flex-grow: 1;' +
             }
                 '}' +
             @media (max-width: 1119px) {
             '}' +
                 .skin-citizen #show-contributor-button {
             '@media (max-width: 1119px) {' +
                     margin: 0.5em 0;
                 '.skin-citizen #show-contributor-button {' +
                     display: block;
                     'margin: 0.5em 0;' +
                 }
                     'display: block;' +
             }
                 '}' +
         `);
             '}'
         );


         await mw.loader.using([
         mw.loader.using([
             "mediawiki.api",
             "mediawiki.api",
             "mediawiki.notification",
             "mediawiki.notification",
第77行: 第87行:
             "oojs-ui.styles.icons-interactions",
             "oojs-ui.styles.icons-interactions",
             "jquery.tablesorter"
             "jquery.tablesorter"
         ]);
         ]).then(function() {
            console.log('依赖模块加载成功');


        class t extends OO.ui.Dialog {
            function ShowContributorDialog(config) {
            $table = $('<table id="show-contributor-table" class="wikitable" />');
                OO.ui.Dialog.call(this, config);
            $tbody = $("<tbody />");
                this.$table = jQuery('<table id="show-contributor-table" class="wikitable" />');
            $body;
                this.$tbody = jQuery("<tbody />");
             got = !1;
                this.got = false;
             static static = {...super.static,name:"ShowContributor",tagName:"div"};
             }
             initialize() {
             OO.inheritClass(ShowContributorDialog, OO.ui.Dialog);
                 return super.initialize(),
            ShowContributorDialog.static.name = "ShowContributor";
            ShowContributorDialog.static.tagName = "div";
 
             ShowContributorDialog.prototype.initialize = function() {
                 OO.ui.Dialog.prototype.initialize.call(this);
                 this.$body.append(
                 this.$body.append(
                     $('<div id="show-contributor-header" />').append(
                     jQuery('<div id="show-contributor-header" />').append(
                         $('<div id="show-contributor-headline">本页贡献统计</div>'),
                         jQuery('<div id="show-contributor-headline">本页贡献统计</div>'),
                         new OO.ui.IconWidget({icon:"close",id:"show-contributor-close"}).$element.on("click",(()=>this.close()))
                         new OO.ui.IconWidget({ icon: "close", id: "show-contributor-close" }).$element.on("click", function() {
                            this.close();
                        }.bind(this))
                     ),
                     ),
                     this.$table.append(
                     this.$table.append(
                         $("<thead><th>用户</th><th>编辑数</th><th>增加字节数</th><th>删减字节数</th></thead>"),
                         jQuery("<thead><th>用户</th><th>编辑数</th><th>增加字节数</th><th>删减字节数</th></thead>"),
                         this.$tbody
                         this.$tbody
                     )
                     )
                 ),
                 );
                 this
                 return this;
             }
             };
             getContributors = async () => {
 
                 const t = new mw.Api,
             ShowContributorDialog.prototype.getContributors = async function() {
                    e = {};
                 console.log('开始获取贡献者数据');
                 let o = "",
                var api = new mw.Api();
                    i = 0;
                var contributors = {};
                 const r = {
                 var continueToken = "";
                     action:"query",
                var prevSize = 0;
                     format:"json",
                 var params = {
                     prop:"revisions",
                     action: "query",
                     titles:mw.config.get("wgPageName"),
                     format: "json",
                     rvprop:"user|size",
                     prop: "revisions",
                     rvlimit:"max",
                     titles: mw.config.get("wgPageName"),
                     rvdir:"newer"
                     rvprop: "user|size",
                     rvlimit: "max",
                     rvdir: "newer"
                 };
                 };
                 do {
                 do {
                     o && (r.rvcontinue = o);
                     if (continueToken) params.rvcontinue = continueToken;
                     try {
                     try {
                         const n = await t.get(r);
                         var response = await api.get(params);
                         o = n.continue?.rvcontinue;
                         continueToken = response.continue ? response.continue.rvcontinue : undefined;
                         for (const {user:t,size:o} of Object.values(n.query.pages)[0].revisions)
                         var revisions = Object.values(response.query.pages)[0].revisions;
                             e[t] ||= [],
                        for (var i = 0; i < revisions.length; i++) {
                             e[t].push(o - i),
                             var user = revisions[i].user;
                             i = o
                            var size = revisions[i].size;
                     } catch (t) {
                            contributors[user] = contributors[user] || [];
                         mw.notify(`获取编辑记录失败:${t}`,{type:"error"})
                             contributors[user].push(size - prevSize);
                             prevSize = size;
                        }
                     } catch (error) {
                        console.error('API 请求失败:', error);
                         mw.notify('获取编辑记录失败:' + error, { type: "error" });
                     }
                     }
                 } while (o);
                 } while (continueToken);
                 return e
                console.log('贡献者数据:', contributors);
                 return contributors;
             };
             };
             addRow = (t,{user:e,count:o,add:i,remove:r}) => {
 
                 t.append(
             ShowContributorDialog.prototype.addRow = function(tbody, data) {
                     $("<tr />").append(
                var user = data.user;
                         $("<td />").append(
                var count = data.count;
                             $(`<a href="${mw.config.get("wgArticlePath").replace("$1",`User:${e}`)}" />`).text(e)
                var add = data.add;
                var remove = data.remove;
                 tbody.append(
                     jQuery("<tr />").append(
                         jQuery("<td />").append(
                             jQuery('<a href="' + mw.config.get("wgArticlePath").replace("$1", "User:" + user) + '" />').text(user)
                         ),
                         ),
                         `<td>${o}</td>`,
                         jQuery('<td>' + count + '</td>'),
                         `<td>${i}</td>`,
                         jQuery('<td>' + add + '</td>'),
                         `<td>${r}</td>`
                         jQuery('<td>' + remove + '</td>')
                     )
                     )
                 )
                 );
             };
             };
             showContributors = t => {
 
             ShowContributorDialog.prototype.showContributors = function(contributors) {
                 this.$tbody.empty();
                 this.$tbody.empty();
                 for (const e in t)
                 for (var user in contributors) {
                     this.addRow(this.$tbody, {
                     if (contributors.hasOwnProperty(user)) {
                         user:e,
                         var edits = contributors[user];
                        count:t[e].length,
                         var add = edits.reduce(function(sum, delta) {
                         add:t[e].reduce((s,n)=>n>0?s+n:s,0),
                            return delta > 0 ? sum + delta : sum;
                         remove:t[e].reduce((s,n)=>n<0?s+n:s,0)
                        }, 0);
                    });
                         var remove = edits.reduce(function(sum, delta) {
                 this.got = !0
                            return delta < 0 ? sum + delta : sum;
             }
                        }, 0);
        }
                        this.addRow(this.$tbody, {
                            user: user,
                            count: edits.length,
                            add: add,
                            remove: remove
                        });
                    }
                }
                 this.got = true;
             };


        const e = new OO.ui.WindowManager({id:"show-contributor"});
            var windowManager = new OO.ui.WindowManager({ id: "show-contributor" });
        $(document.body).append(e.$element);
            jQuery(document.body).append(windowManager.$element);
        const o = new t({size:"large"});
            var dialog = new ShowContributorDialog({ size: "large" });
        e.addWindows([o]);
            windowManager.addWindows([dialog]);


        const i = new OO.ui.ButtonWidget({
            var button = new OO.ui.ButtonWidget({
            label:"本页贡献者",
                label: "本页贡献者",
            icon:"search",
                icon: "search",
            flags:"progressive",
                flags: "progressive",
            id:"show-contributor-button"
                id: "show-contributor-button"
        });
            });


        const insertButton = () => {
            function insertButton() {
            $("#show-contributor-button").detach();
                jQuery("#show-contributor-button").detach();
            const skin = mw.config.get("skin");
                var skin = mw.config.get("skin");
            if (skin === "citizen") {
                console.log('插入按钮,当前皮肤:', skin);
                if (window.innerWidth >= 1120) {
                if (skin === "citizen") {
                     $(".page-actions").prepend(i.$element);
                    if (window.innerWidth >= 1120) {
                        if (jQuery(".page-actions").length) {
                            jQuery(".page-actions").prepend(button.$element);
                        } else {
                            console.error('未找到 .page-actions 容器');
                        }
                     } else {
                        if (jQuery(".firstHeading-container").length) {
                            jQuery(".firstHeading-container").append(button.$element);
                        } else {
                            console.error('未找到 .firstHeading-container 容器');
                        }
                    }
                } else if (skin === "vector-2022") {
                    if (jQuery("header.mw-body-header.vector-page-titlebar").length) {
                        jQuery("header.mw-body-header.vector-page-titlebar").append(button.$element);
                    } else {
                        console.error('未找到 header.mw-body-header.vector-page-titlebar 容器');
                    }
                 } else {
                 } else {
                     $(".firstHeading-container").append(i.$element);
                     if (jQuery("#bodyContent").length) {
                        jQuery("#bodyContent").prepend(button.$element);
                    } else {
                        console.error('未找到 #bodyContent 容器');
                    }
                 }
                 }
            } else if (skin === "vector-2022") {
                 console.log('按钮是否存在:', jQuery("#show-contributor-button").length);
                 $("header.mw-body-header.vector-page-titlebar").append(i.$element);
            } else {
                $("#bodyContent").prepend(i.$element);
             }
             }
        };


        // 初始插入
            insertButton();
        insertButton();
 
            var isWide = window.innerWidth >= 1120;
            jQuery(window).on("resize", function() {
                clearTimeout(window.__showContributorResizeTimer);
                window.__showContributorResizeTimer = setTimeout(function() {
                    var nowWide = window.innerWidth >= 1120;
                    if (nowWide !== isWide && mw.config.get("skin") === "citizen") {
                        isWide = nowWide;
                        insertButton();
                    }
                }, 200);
            });


        // 仅在断点穿越时更新插入位置
            button.on("click", function() {
        let isWide = window.innerWidth >= 1120;
                console.log('按钮点击,尝试打开窗口');
        $(window).on("resize", () => {
                if (!dialog.got) {
            clearTimeout(window.__showContributorResizeTimer);
                    button.setLabel("正在查询");
            window.__showContributorResizeTimer = setTimeout(() => {
                    dialog.getContributors().then(function(contributors) {
                const nowWide = window.innerWidth >= 1120;
                        dialog.showContributors(contributors);
                 if (nowWide !== isWide) {
                        dialog.$table.tablesorter();
                     isWide = nowWide;
                        button.setLabel("本页贡献者");
                     insertButton();
                        windowManager.openWindow(dialog);
                        console.log('窗口打开状态:', windowManager);
                    }).catch(function(error) {
                        console.error('打开窗口失败:', error);
                    });
                 } else {
                     windowManager.openWindow(dialog);
                     console.log('窗口打开状态:', windowManager);
                 }
                 }
             }, 200);
             });
         });
         }).catch(function(err) {
 
             console.error('模块加载失败:', err);
        // 点击事件
        i.on("click", async () => {
             if (!o.got) {
                i.setLabel("正在查询");
                const t = await o.getContributors();
                o.showContributors(t);
                o.$table.tablesorter();
                i.setLabel("本页贡献者");
            }
            e.openWindow(o);
         });
         });
     })()))
     });
})();
})();

2025年6月17日 (二) 17:35的版本

(function() {
    "use strict";
    jQuery(document).ready(function() {
        console.log('ShowContributors.js 开始执行', {
            mediaWikiVersion: mw.config.get('wgVersion'),
            skin: mw.config.get('skin'),
            namespace: mw.config.get('wgNamespaceNumber'),
            action: mw.config.get('wgAction'),
            articleId: mw.config.get('wgArticleId')
        });

        if (
            ![0, 2, 4, 10, 12, 14, 828, 274].includes(mw.config.get("wgNamespaceNumber")) ||
            0 === mw.config.get("wgArticleId") ||
            !["view", "history"].includes(mw.config.get("wgAction"))
        ) {
            console.log('脚本因条件不满足退出');
            return;
        }

        mw.loader.addStyleTag(
            '#show-contributor-button {' +
                'float: right;' +
                'margin-left: .5em;' +
                'margin-right: 0;' +
            '}' +
            '#show-contributor-header {' +
                'background: #fff;' +
                'border-bottom: 1px solid #aaa;' +
                'font-weight: 600;' +
                'padding: .3em;' +
                'position: sticky;' +
                'text-align: center;' +
                'top: 0;' +
            '}' +
            '#show-contributor-headline {' +
                'font-size: 1.3em;' +
            '}' +
            '#show-contributor-close {' +
                'border-radius: 50%;' +
                'cursor: pointer;' +
                'position: absolute;' +
                'right: 5px;' +
                'top: 5px;' +
            '}' +
            '#show-contributor-close:hover {' +
                'background-color: #eee;' +
            '}' +
            '#show-contributor-table {' +
                'margin: 0;' +
                'width: 100%;' +
            '}' +
            '#show-contributor-table .user-avatar {' +
                'border-radius: 50%;' +
                'height: 20px;' +
                'width: 20px;' +
            '}' +
            '.skin-citizen #show-contributor-button {' +
                'float: none;' +
                'margin: 0 0.5em 0 0;' +
                'display: inline-flex;' +
                'align-items: center;' +
                'vertical-align: middle;' +
            '}' +
            '@media (min-width: 1120px) {' +
                '.skin-citizen .citizen-page-header-inner {' +
                    'display: flex;' +
                    'justify-content: space-between;' +
                    'align-items: center;' +
                '}' +
                '.skin-citizen .citizen-page-heading {' +
                    'flex-grow: 1;' +
                '}' +
            '}' +
            '@media (max-width: 1119px) {' +
                '.skin-citizen #show-contributor-button {' +
                    'margin: 0.5em 0;' +
                    'display: block;' +
                '}' +
            '}'
        );

        mw.loader.using([
            "mediawiki.api",
            "mediawiki.notification",
            "oojs-ui",
            "oojs-ui.styles.icons-interactions",
            "jquery.tablesorter"
        ]).then(function() {
            console.log('依赖模块加载成功');

            function ShowContributorDialog(config) {
                OO.ui.Dialog.call(this, config);
                this.$table = jQuery('<table id="show-contributor-table" class="wikitable" />');
                this.$tbody = jQuery("<tbody />");
                this.got = false;
            }
            OO.inheritClass(ShowContributorDialog, OO.ui.Dialog);
            ShowContributorDialog.static.name = "ShowContributor";
            ShowContributorDialog.static.tagName = "div";

            ShowContributorDialog.prototype.initialize = function() {
                OO.ui.Dialog.prototype.initialize.call(this);
                this.$body.append(
                    jQuery('<div id="show-contributor-header" />').append(
                        jQuery('<div id="show-contributor-headline">本页贡献统计</div>'),
                        new OO.ui.IconWidget({ icon: "close", id: "show-contributor-close" }).$element.on("click", function() {
                            this.close();
                        }.bind(this))
                    ),
                    this.$table.append(
                        jQuery("<thead><th>用户</th><th>编辑数</th><th>增加字节数</th><th>删减字节数</th></thead>"),
                        this.$tbody
                    )
                );
                return this;
            };

            ShowContributorDialog.prototype.getContributors = async function() {
                console.log('开始获取贡献者数据');
                var api = new mw.Api();
                var contributors = {};
                var continueToken = "";
                var prevSize = 0;
                var params = {
                    action: "query",
                    format: "json",
                    prop: "revisions",
                    titles: mw.config.get("wgPageName"),
                    rvprop: "user|size",
                    rvlimit: "max",
                    rvdir: "newer"
                };
                do {
                    if (continueToken) params.rvcontinue = continueToken;
                    try {
                        var response = await api.get(params);
                        continueToken = response.continue ? response.continue.rvcontinue : undefined;
                        var revisions = Object.values(response.query.pages)[0].revisions;
                        for (var i = 0; i < revisions.length; i++) {
                            var user = revisions[i].user;
                            var size = revisions[i].size;
                            contributors[user] = contributors[user] || [];
                            contributors[user].push(size - prevSize);
                            prevSize = size;
                        }
                    } catch (error) {
                        console.error('API 请求失败:', error);
                        mw.notify('获取编辑记录失败:' + error, { type: "error" });
                    }
                } while (continueToken);
                console.log('贡献者数据:', contributors);
                return contributors;
            };

            ShowContributorDialog.prototype.addRow = function(tbody, data) {
                var user = data.user;
                var count = data.count;
                var add = data.add;
                var remove = data.remove;
                tbody.append(
                    jQuery("<tr />").append(
                        jQuery("<td />").append(
                            jQuery('<a href="' + mw.config.get("wgArticlePath").replace("$1", "User:" + user) + '" />').text(user)
                        ),
                        jQuery('<td>' + count + '</td>'),
                        jQuery('<td>' + add + '</td>'),
                        jQuery('<td>' + remove + '</td>')
                    )
                );
            };

            ShowContributorDialog.prototype.showContributors = function(contributors) {
                this.$tbody.empty();
                for (var user in contributors) {
                    if (contributors.hasOwnProperty(user)) {
                        var edits = contributors[user];
                        var add = edits.reduce(function(sum, delta) {
                            return delta > 0 ? sum + delta : sum;
                        }, 0);
                        var remove = edits.reduce(function(sum, delta) {
                            return delta < 0 ? sum + delta : sum;
                        }, 0);
                        this.addRow(this.$tbody, {
                            user: user,
                            count: edits.length,
                            add: add,
                            remove: remove
                        });
                    }
                }
                this.got = true;
            };

            var windowManager = new OO.ui.WindowManager({ id: "show-contributor" });
            jQuery(document.body).append(windowManager.$element);
            var dialog = new ShowContributorDialog({ size: "large" });
            windowManager.addWindows([dialog]);

            var button = new OO.ui.ButtonWidget({
                label: "本页贡献者",
                icon: "search",
                flags: "progressive",
                id: "show-contributor-button"
            });

            function insertButton() {
                jQuery("#show-contributor-button").detach();
                var skin = mw.config.get("skin");
                console.log('插入按钮,当前皮肤:', skin);
                if (skin === "citizen") {
                    if (window.innerWidth >= 1120) {
                        if (jQuery(".page-actions").length) {
                            jQuery(".page-actions").prepend(button.$element);
                        } else {
                            console.error('未找到 .page-actions 容器');
                        }
                    } else {
                        if (jQuery(".firstHeading-container").length) {
                            jQuery(".firstHeading-container").append(button.$element);
                        } else {
                            console.error('未找到 .firstHeading-container 容器');
                        }
                    }
                } else if (skin === "vector-2022") {
                    if (jQuery("header.mw-body-header.vector-page-titlebar").length) {
                        jQuery("header.mw-body-header.vector-page-titlebar").append(button.$element);
                    } else {
                        console.error('未找到 header.mw-body-header.vector-page-titlebar 容器');
                    }
                } else {
                    if (jQuery("#bodyContent").length) {
                        jQuery("#bodyContent").prepend(button.$element);
                    } else {
                        console.error('未找到 #bodyContent 容器');
                    }
                }
                console.log('按钮是否存在:', jQuery("#show-contributor-button").length);
            }

            insertButton();

            var isWide = window.innerWidth >= 1120;
            jQuery(window).on("resize", function() {
                clearTimeout(window.__showContributorResizeTimer);
                window.__showContributorResizeTimer = setTimeout(function() {
                    var nowWide = window.innerWidth >= 1120;
                    if (nowWide !== isWide && mw.config.get("skin") === "citizen") {
                        isWide = nowWide;
                        insertButton();
                    }
                }, 200);
            });

            button.on("click", function() {
                console.log('按钮点击,尝试打开窗口');
                if (!dialog.got) {
                    button.setLabel("正在查询");
                    dialog.getContributors().then(function(contributors) {
                        dialog.showContributors(contributors);
                        dialog.$table.tablesorter();
                        button.setLabel("本页贡献者");
                        windowManager.openWindow(dialog);
                        console.log('窗口打开状态:', windowManager);
                    }).catch(function(error) {
                        console.error('打开窗口失败:', error);
                    });
                } else {
                    windowManager.openWindow(dialog);
                    console.log('窗口打开状态:', windowManager);
                }
            });
        }).catch(function(err) {
            console.error('模块加载失败:', err);
        });
    });
})();