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

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

MediaWiki界面页面
第1行: 第1行:
(() => {
(function() {
     "use strict";
     "use strict";
     $((() => (async () => {
     mw.hook("wikipage.content").add(() => {
        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(`
         mw.loader.addStyleTag(`
             #show-contributor-button {
             #show-contributor-button {
第71行: 第81行:
         `);
         `);


         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(() => {
            console.log("依赖模块加载成功");
 
            class ShowContributorDialog extends OO.ui.Dialog {
                constructor(config) {
                    super(config);
                    this.$table = $('<table id="show-contributor-table" class="wikitable" />');
                    this.$tbody = $("<tbody />");
                    this.got = false;
                }
                static name = "ShowContributor";
                static tagName = "div";


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


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


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


        const insertButton = () => {
            const insertButton = () => {
            $("#show-contributor-button").detach();
                $("#show-contributor-button").detach();
            const skin = mw.config.get("skin");
                const 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 ($(".page-actions").length) {
                            $(".page-actions").prepend(button.$element);
                        } else {
                            console.error("未找到 .page-actions 容器");
                        }
                    } else {
                        if ($(".firstHeading-container").length) {
                            $(".firstHeading-container").append(button.$element);
                        } else {
                            console.error("未找到 .firstHeading-container 容器");
                        }
                    }
                } else if (skin === "vector-2022") {
                    if ($("header.mw-body-header.vector-page-titlebar").length) {
                        $("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 ($("#bodyContent").length) {
                        $("#bodyContent").prepend(button.$element);
                    } else {
                        console.error("未找到 #bodyContent 容器");
                    }
                 }
                 }
            } else if (skin === "vector-2022") {
                console.log("按钮是否存在:", $("#show-contributor-button").length);
                $("header.mw-body-header.vector-page-titlebar").append(i.$element);
             };
             } else {
 
                $("#bodyContent").prepend(i.$element);
            insertButton();
            }
        };


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


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

(function() {
    "use strict";
    mw.hook("wikipage.content").add(() => {
        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(() => {
            console.log("依赖模块加载成功");

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

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

                getContributors = async () => {
                    console.log("开始获取贡献者数据");
                    const api = new mw.Api();
                    const contributors = {};
                    let continueToken = "";
                    let prevSize = 0;
                    const 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 {
                            const response = await api.get(params);
                            continueToken = response.continue?.rvcontinue;
                            for (const { user, size } of Object.values(response.query.pages)[0].revisions) {
                                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;
                };

                addRow = (tbody, { user, count, add, remove }) => {
                    tbody.append(
                        $("<tr />").append(
                            $("<td />").append(
                                $(`<a href="${mw.config.get("wgArticlePath").replace("$1", `User:${user}`)}" />`).text(user)
                            ),
                            `<td>${count}</td>`,
                            `<td>${add}</td>`,
                            `<td>${remove}</td>`
                        )
                    );
                };

                showContributors = (contributors) => {
                    this.$tbody.empty();
                    for (const user in contributors) {
                        this.addRow(this.$tbody, {
                            user,
                            count: contributors[user].length,
                            add: contributors[user].reduce((s, n) => n > 0 ? s + n : s, 0),
                            remove: contributors[user].reduce((s, n) => n < 0 ? s + n : s, 0)
                        });
                    }
                    this.got = true;
                };
            }

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

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

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

            insertButton();

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

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