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

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

MediaWiki界面页面
第1行: 第1行:
(() => {
(() => {
     "use strict";
     "use strict";
     $(() => (async () => {
     $((() => (async () => {
         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")) ||
             mw.config.get("wgArticleId") === 0 ||
             0 === mw.config.get("wgArticleId") ||
             !["view", "history"].includes(mw.config.get("wgAction"))
             !["view", "history"].includes(mw.config.get("wgAction"))
         ) return;
         )
 
            return;
       
         mw.loader.addStyleTag(`
         mw.loader.addStyleTag(`
#show-contributor-button {
            #show-contributor-button {
    float: right;
                float: right;
    margin-left: .5em;
                margin-left: .5em;
    margin-right: 0;
                margin-right: 0
}
            }
#show-contributor-header {
            #show-contributor-header {
    background: #fff;
                background: #fff;
    border-bottom: 1px solid #aaa;
                border-bottom: 1px solid #aaa;
    font-weight: 600;
                font-weight: 600;
    padding: .3em;
                padding: .3em;
    position: sticky;
                position: sticky;
    text-align: center;
                text-align: center;
    top: 0;
                top: 0
    z-index: 1;
            }
}
            #show-contributor-headline {
#show-contributor-headline {
                font-size: 1.3em
    font-size: 1.3em;
            }
}
            #show-contributor-close {
#show-contributor-close {
                border-radius: 50%;
    border-radius: 50%;
                cursor: pointer;
    cursor: pointer;
                position: absolute;
    position: absolute;
                right: 5px;
    right: 5px;
                top: 5px
    top: 5px;
            }
}
            #show-contributor-close:hover {
#show-contributor-close:hover {
                background-color: #eee
    background-color: #eee;
            }
}
            #show-contributor-table {
#show-contributor-table {
                margin: 0;
    margin: 0;
                width: 100%
    width: 100%;
            }
}
            #show-contributor-table .user-avatar {
#show-contributor-table .user-avatar {
                border-radius: 50%;
    border-radius: 50%;
                height: 20px;
    height: 20px;
                width: 20px
    width: 20px;
            }
}
            /* Citizen 皮肤响应式样式 */
.skin-citizen #show-contributor-button {
            .skin-citizen #show-contributor-button {
    display: inline-flex;
                float: none;
    align-items: center;
                margin: 0 0.5em 0 0;
}
                display: inline-flex;
@media (max-width: 1119px) {
                align-items: center;
    #show-contributor-button.citizen-header-button {
                vertical-align: middle;
        position: absolute;
            }
        right: 0.75em;
            @media (min-width: 1120px) {
        top: 50%;
                .skin-citizen .citizen-page-header-inner {
        transform: translateY(-50%);
                    display: flex;
        margin: 0;
                    justify-content: space-between;
        z-index: 2;
                    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;
                }
            }
        `);


         await mw.loader.using([
         await mw.loader.using(["mediawiki.api","mediawiki.notification","oojs-ui","oojs-ui.styles.icons-interactions","jquery.tablesorter"]);
            "mediawiki.api",
            "mediawiki.notification",
            "oojs-ui",
            "oojs-ui.styles.icons-interactions",
            "jquery.tablesorter"
        ]);


         class ContributorDialog extends OO.ui.Dialog {
         class t extends OO.ui.Dialog {
             $table = $('<table id="show-contributor-table" class="wikitable" />');
             $table = $('<table id="show-contributor-table" class="wikitable" />');
             $tbody = $("<tbody />");
             $tbody = $("<tbody />");
             got = false;
            $body;
 
             got = !1;
             static static = {
             static static = {...super.static,name:"ShowContributor",tagName:"div"};
                ...super.static,
                name: "ShowContributor",
                tagName: "div"
            };
 
             initialize() {
             initialize() {
                 super.initialize();
                 return super.initialize(),
                 this.$body.append(
                 this.$body.append(
                     $('<div id="show-contributor-header" />').append(
                     $('<div id="show-contributor-header" />').append(
                         $('<div id="show-contributor-headline">本页贡献统计</div>'),
                         $('<div id="show-contributor-headline">本页贡献统计</div>'),
                         new OO.ui.IconWidget({
                         new OO.ui.IconWidget({icon:"close",id:"show-contributor-close"}).$element.on("click",(()=>this.close()))
                            icon: "close",
                            id: "show-contributor-close"
                        }).$element.on("click", () => this.close())
                     ),
                     ),
                     this.$table.append(
                     this.$table.append(
第95行: 第91行:
                         this.$tbody
                         this.$tbody
                     )
                     )
                 );
                 ),
                 return this;
                 this
             }
             }
 
             getContributors = async () => {
             async getContributors() {
                 const t = new mw.Api,
                 const api = new mw.Api();
                    e = {};
                const users = {};
                 let o = "",
                 let rvcontinue = "";
                    i = 0;
                let lastSize = 0;
                 const r = {
 
                     action:"query",
                 const params = {
                     format:"json",
                     action: "query",
                     prop:"revisions",
                     format: "json",
                     titles:mw.config.get("wgPageName"),
                     prop: "revisions",
                     rvprop:"user|size",
                     titles: mw.config.get("wgPageName"),
                     rvlimit:"max",
                     rvprop: "user|size",
                     rvdir:"newer"
                     rvlimit: "max",
                     rvdir: "newer"
                 };
                 };
                 do {
                 do {
                     if (rvcontinue) params.rvcontinue = rvcontinue;
                     o && (r.rvcontinue = o);
                     try {
                     try {
                         const result = await api.get(params);
                         const n = await t.get(r);
                         rvcontinue = result.continue?.rvcontinue;
                         o = n.continue?.rvcontinue;
                         for (const { user, size } of Object.values(result.query.pages)[0].revisions) {
                         for (const {user:t,size:o} of Object.values(n.query.pages)[0].revisions)
                             users[user] ||= [];
                             e[t] ||= [],
                             users[user].push(size - lastSize);
                             e[t].push(o - i),
                             lastSize = size;
                             i = o
                        }
                     } catch (t) {
                     } catch (err) {
                         mw.notify(`获取编辑记录失败:${t}`,{type:"error"})
                         mw.notify(`获取编辑记录失败:${err}`, { type: "error" });
                        break;
                     }
                     }
                 } while (rvcontinue);
                 } while (o);
 
                 return e
                 return users;
             };
             }
             addRow = (t,{user:e,count:o,add:i,remove:r}) => {
 
                 t.append(
             addRow($target, { user, count, add, remove }) {
                 $target.append(
                     $("<tr />").append(
                     $("<tr />").append(
                         $("<td />").append(
                         $("<td />").append(
                             $(`<a href="${mw.config.get("wgArticlePath").replace("$1", `User:${user}`)}" />`).append(
                             $(`<a href="${mw.config.get("wgArticlePath").replace("$1",`User:${e}`)}" />`).append(
                                 `<img class="user-avatar" src="https://commons.moegirl.org.cn/extensions/Avatar/avatar.php?user=${user}" />`,
                                 `<img class="user-avatar" src="https://commons.moegirl.org.cn/extensions/Avatar/avatar.php?user=${e}" />`,
                                 user
                                 e
                             )
                             )
                         ),
                         ),
                         `<td>${count}</td>`,
                         `<td>${o}</td>`,
                         `<td>${add}</td>`,
                         `<td>${i}</td>`,
                         `<td>${remove}</td>`
                         `<td>${r}</td>`
                     )
                     )
                 );
                 )
             }
             };
 
             showContributors = t => {
             showContributors(data) {
                 this.$tbody.empty();
                 this.$tbody.empty();
                 for (const user in data) {
                 for (const e in t)
                    const edits = data[user];
                     this.addRow(this.$tbody,{
                     this.addRow(this.$tbody, {
                         user:e,
                         user,
                         count:t[e].length,
                         count: edits.length,
                         add:t[e].reduce(((t,e)=>e>0?t+e:t),0),
                         add: edits.reduce((sum, n) => n > 0 ? sum + n : sum, 0),
                         remove:t[e].reduce(((t,e)=>e<0?t+e:t),0)
                         remove: edits.reduce((sum, n) => n < 0 ? sum + n : sum, 0)
                     });
                     });
                }
                 this.got = !0
                 this.got = true;
             }
             }
         }
         }


         const dialogWindow = new ContributorDialog({ size: "large" });
         // 确保这些变量在点击事件处理函数中可访问
         const windowManager = new OO.ui.WindowManager({ id: "show-contributor" });
         const e = new OO.ui.WindowManager({id:"show-contributor"});
         $(document.body).append(windowManager.$element);
         $(document.body).append(e.$element);
         windowManager.addWindows([dialogWindow]);
         const o = new t({size:"large"});  // 这是对话框实例
        e.addWindows([o]);


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


         const openDialog = async () => {
         // 响应式插入逻辑
             if (!dialogWindow.got) {
        if ("citizen" === mw.config.get("skin")) {
                 $button.find(".oo-ui-labelElement-label").text("正在查询");
             const handleResize = () => {
                 const data = await dialogWindow.getContributors();
                 $("#show-contributor-button").detach();
                dialogWindow.showContributors(data);
                 if (window.matchMedia("(min-width: 1120px)").matches) {
                dialogWindow.$table.tablesorter();
                    $(".page-actions").prepend(i.$element);
                 $button.find(".oo-ui-labelElement-label").text("本页贡献者");
                 } else {
             }
                    $(".citizen-page-heading").append(i.$element);
             windowManager.openWindow(dialogWindow);
                }
        };
             };
 
             handleResize();
        $button.on("click", openDialog);
            $(window).on("resize", handleResize);
 
         } else {
         const insertButton = () => {
             $("#bodyContent").prepend(i.$element);
            const skin = mw.config.get("skin");
        }
            const width = window.innerWidth;
             $("#show-contributor-button").remove();


            if (skin === "citizen") {
        // 点击事件处理(确保能访问到 o 和 e)
                if (width <= 1119) {
        i.on("click", async () => {
                    $button.addClass("citizen-header-button");
            if (!o.got) {
                    const $header = $(".mw-header.citizen-header");
                i.setLabel("正在查询");
                    if ($header.length) {
                const t = await o.getContributors();
                        $header.css("position", "relative").append($button);
                o.showContributors(t),
                    }
                 o.$table.tablesorter(),
                 } else if (width >= 1200) {
                 i.setLabel("本页贡献者")
                    $button.removeClass("citizen-header-button");
                    $(".page-actions").prepend($button);
                 }
            } else {
                $("#bodyContent").prepend($button);
             }
             }
        };
            e.openWindow(o);
 
        // 初始插入
        insertButton();
 
        // 窗口尺寸变化时重新插入(节流)
        let resizeTimer = null;
        $(window).on("resize", () => {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(insertButton, 200);
         });
         });
 
     })()))
     })());
})();
})();

2025年6月11日 (三) 12:04的版本

(() => {
    "use strict";
    $((() => (async () => {
        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"))
        )
            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
            }
            /* Citizen 皮肤响应式样式 */
            .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;
                }
            }
        `);

        await mw.loader.using(["mediawiki.api","mediawiki.notification","oojs-ui","oojs-ui.styles.icons-interactions","jquery.tablesorter"]);

        class t extends OO.ui.Dialog {
            $table = $('<table id="show-contributor-table" class="wikitable" />');
            $tbody = $("<tbody />");
            $body;
            got = !1;
            static static = {...super.static,name:"ShowContributor",tagName:"div"};
            initialize() {
                return 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
                    )
                ),
                this
            }
            getContributors = async () => {
                const t = new mw.Api,
                    e = {};
                let o = "",
                    i = 0;
                const r = {
                    action:"query",
                    format:"json",
                    prop:"revisions",
                    titles:mw.config.get("wgPageName"),
                    rvprop:"user|size",
                    rvlimit:"max",
                    rvdir:"newer"
                };
                do {
                    o && (r.rvcontinue = o);
                    try {
                        const n = await t.get(r);
                        o = n.continue?.rvcontinue;
                        for (const {user:t,size:o} of Object.values(n.query.pages)[0].revisions)
                            e[t] ||= [],
                            e[t].push(o - i),
                            i = o
                    } catch (t) {
                        mw.notify(`获取编辑记录失败:${t}`,{type:"error"})
                    }
                } while (o);
                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}`)}" />`).append(
                                `<img class="user-avatar" src="https://commons.moegirl.org.cn/extensions/Avatar/avatar.php?user=${e}" />`,
                                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(((t,e)=>e>0?t+e:t),0),
                        remove:t[e].reduce(((t,e)=>e<0?t+e:t),0)
                    });
                this.got = !0
            }
        }

        // 确保这些变量在点击事件处理函数中可访问
        const e = new OO.ui.WindowManager({id:"show-contributor"});
        $(document.body).append(e.$element);
        const o = new t({size:"large"});  // 这是对话框实例
        e.addWindows([o]);

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

        // 响应式插入逻辑
        if ("citizen" === mw.config.get("skin")) {
            const handleResize = () => {
                $("#show-contributor-button").detach();
                if (window.matchMedia("(min-width: 1120px)").matches) {
                    $(".page-actions").prepend(i.$element);
                } else {
                    $(".citizen-page-heading").append(i.$element);
                }
            };
            handleResize();
            $(window).on("resize", handleResize);
        } else {
            $("#bodyContent").prepend(i.$element);
        }

        // 点击事件处理(确保能访问到 o 和 e)
        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);
        });
    })()))
})();