MediaWiki:Gadget-ShowContributors.js:修订间差异
MediaWiki界面页面
更多操作
![]() OctoberSama(留言 | 贡献) 小 |
![]() OctoberSama(留言 | 贡献) 小 |
||
第1行: | 第1行: | ||
(() | (function () { | ||
"use strict"; | "use strict"; | ||
function insertStyles() { | |||
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; }", | |||
mw.loader.addStyleTag( | "#show-contributor-table { margin: 0; width: 100%; }", | ||
#show-contributor-button { | "#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; } }" | |||
].join("\n")); | |||
#show-contributor-header { | } | ||
function isValidPage() { | |||
var ns = mw.config.get("wgNamespaceNumber"); | |||
var action = mw.config.get("wgAction"); | |||
return [0, 2, 4, 10, 12, 14, 828, 274].indexOf(ns) !== -1 && | |||
mw.config.get("wgArticleId") !== 0 && | |||
(action === "view" || action === "history"); | |||
} | |||
#show-contributor-headline { | |||
function ShowContributorDialog(config) { | |||
ShowContributorDialog.super.call(this, config); | |||
#show-contributor-close { | } | ||
OO.inheritClass(ShowContributorDialog, OO.ui.Dialog); | |||
ShowContributorDialog.static.name = "ShowContributor"; | |||
ShowContributorDialog.static.tagName = "div"; | |||
#show-contributor-close:hover { | ShowContributorDialog.prototype.initialize = function () { | ||
ShowContributorDialog.super.prototype.initialize.call(this); | |||
this.got = false; | |||
#show-contributor-table { | this.$table = $('<table id="show-contributor-table" class="wikitable" />'); | ||
this.$tbody = $("<tbody />"); | |||
this.$body.append( | |||
$('<div id="show-contributor-header" />').append( | |||
#show-contributor-table .user-avatar { | $('<div id="show-contributor-headline">本页贡献统计</div>'), | ||
new OO.ui.IconWidget({ icon: "close", id: "show-contributor-close" }).$element.on("click", this.close.bind(this)) | |||
), | |||
this.$table.append( | |||
$("<thead><th>用户</th><th>编辑数</th><th>增加字节数</th><th>删减字节数</th></thead>"), | |||
.skin-citizen #show-contributor-button { | this.$tbody | ||
) | |||
); | |||
}; | |||
ShowContributorDialog.prototype.getContributors = function () { | |||
var self = this; | |||
@media (min-width: 1120px) { | var api = new mw.Api(); | ||
var users = {}; | |||
var rvcontinue = ""; | |||
var lastSize = 0; | |||
var params = { | |||
action: "query", | |||
format: "json", | |||
prop: "revisions", | |||
titles: mw.config.get("wgPageName"), | |||
rvprop: "user|size", | |||
rvlimit: "max", | |||
rvdir: "newer" | |||
}; | |||
function handleResponse(data) { | |||
if (data.continue) rvcontinue = data.continue.rvcontinue; | |||
else rvcontinue = null; | |||
var revisions = Object.values(data.query.pages)[0].revisions; | |||
revisions.forEach(function (rev) { | |||
if (!users[rev.user]) users[rev.user] = []; | |||
users[rev.user].push(rev.size - lastSize); | |||
lastSize = rev.size; | |||
}); | |||
} | |||
return new Promise(function (resolve) { | |||
function next() { | |||
if (rvcontinue !== null) { | |||
if (rvcontinue) params.rvcontinue = rvcontinue; | |||
api.get(params).done(function (data) { | |||
handleResponse(data); | |||
next(); | |||
}).fail(function (err) { | |||
mw.notify("获取编辑记录失败:" + err, { type: "error" }); | |||
rvcontinue = null; | |||
resolve(users); | |||
}); | |||
} else { | |||
resolve(users); | |||
} | } | ||
} | } | ||
next(); | |||
}); | |||
}; | |||
ShowContributorDialog.prototype.addRow = function ($tbody, data) { | |||
var $row = $("<tr />").append( | |||
$("<td />").append( | |||
$('<a href="' + mw.config.get("wgArticlePath").replace("$1", "User:" + data.user) + '" />').text(data.user) | |||
), | |||
$("<td />").text(data.count), | |||
$("<td />").text(data.add), | |||
$("<td />").text(data.remove) | |||
); | |||
$tbody.append($row); | |||
}; | |||
ShowContributorDialog.prototype.showContributors = function (users) { | |||
var self = this; | |||
this.$tbody.empty(); | |||
Object.keys(users).forEach(function (user) { | |||
var edits = users[user]; | |||
var add = edits.reduce(function (sum, n) { return n > 0 ? sum + n : sum; }, 0); | |||
var remove = edits.reduce(function (sum, n) { return n < 0 ? sum + n : sum; }, 0); | |||
self.addRow(self.$tbody, { | |||
user: user, | |||
count: edits.length, | |||
add: add, | |||
remove: remove | |||
}); | |||
}); | |||
this.got = true; | |||
}; | |||
function main() { | |||
if (!isValidPage()) return; | |||
insertStyles(); | |||
mw.loader.using([ | |||
"mediawiki.api", | "mediawiki.api", | ||
"mediawiki.notification", | "mediawiki.notification", | ||
第77行: | 第137行: | ||
"oojs-ui.styles.icons-interactions", | "oojs-ui.styles.icons-interactions", | ||
"jquery.tablesorter" | "jquery.tablesorter" | ||
]); | ], function () { | ||
var winManager = new OO.ui.WindowManager({ id: "show-contributor" }); | |||
$(document.body).append(winManager.$element); | |||
var dialog = new ShowContributorDialog({ size: "large" }); | |||
winManager.addWindows([dialog]); | |||
var button = new OO.ui.ButtonWidget({ | |||
label: "本页贡献者", | |||
icon: "search", | |||
flags: "progressive", | |||
id: "show-contributor-button" | |||
}); | |||
var insertButton = function () { | |||
$("#show-contributor-button").detach(); | |||
var skin = mw.config.get("skin"); | |||
if (skin === "citizen") { | |||
if (window.innerWidth >= 1120) { | |||
$(".page-actions").prepend(button.$element); | |||
} else { | |||
$(".firstHeading-container").append(button.$element); | |||
} | |||
} | } | ||
} | } else if (skin === "vector-2022") { | ||
$("header.mw-body-header.vector-page-titlebar").append(button.$element); | |||
} else { | |||
$("#bodyContent").prepend(button.$element); | |||
} | |||
$(" | |||
}; | }; | ||
insertButton(); | |||
var isWide = window.innerWidth >= 1120; | |||
$(window).on("resize", function () { | |||
clearTimeout(window.__showContributorResizeTimer); | |||
window.__showContributorResizeTimer = setTimeout(function () { | |||
var nowWide = window.innerWidth >= 1120; | |||
if (nowWide !== isWide) { | |||
isWide = nowWide; | |||
insertButton(); | |||
} | |||
}, 200); | |||
}); | |||
button.on("click", function () { | |||
if (!dialog.got) { | |||
button.setLabel("正在查询"); | |||
dialog.getContributors().then(function (users) { | |||
dialog.showContributors(users); | |||
dialog.$table.tablesorter(); | |||
button.setLabel("本页贡献者"); | |||
winManager.openWindow(dialog); | |||
}); | |||
} else { | } else { | ||
winManager.openWindow(dialog); | |||
} | } | ||
} | }); | ||
}); | }); | ||
} | |||
$(main); | |||
})(); | })(); |
2025年6月17日 (二) 17:00的版本
(function () { "use strict"; function insertStyles() { 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; } }" ].join("\n")); } function isValidPage() { var ns = mw.config.get("wgNamespaceNumber"); var action = mw.config.get("wgAction"); return [0, 2, 4, 10, 12, 14, 828, 274].indexOf(ns) !== -1 && mw.config.get("wgArticleId") !== 0 && (action === "view" || action === "history"); } function ShowContributorDialog(config) { ShowContributorDialog.super.call(this, config); } OO.inheritClass(ShowContributorDialog, OO.ui.Dialog); ShowContributorDialog.static.name = "ShowContributor"; ShowContributorDialog.static.tagName = "div"; ShowContributorDialog.prototype.initialize = function () { ShowContributorDialog.super.prototype.initialize.call(this); this.got = false; this.$table = $('<table id="show-contributor-table" class="wikitable" />'); this.$tbody = $("<tbody />"); 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.bind(this)) ), this.$table.append( $("<thead><th>用户</th><th>编辑数</th><th>增加字节数</th><th>删减字节数</th></thead>"), this.$tbody ) ); }; ShowContributorDialog.prototype.getContributors = function () { var self = this; var api = new mw.Api(); var users = {}; var rvcontinue = ""; var lastSize = 0; var params = { action: "query", format: "json", prop: "revisions", titles: mw.config.get("wgPageName"), rvprop: "user|size", rvlimit: "max", rvdir: "newer" }; function handleResponse(data) { if (data.continue) rvcontinue = data.continue.rvcontinue; else rvcontinue = null; var revisions = Object.values(data.query.pages)[0].revisions; revisions.forEach(function (rev) { if (!users[rev.user]) users[rev.user] = []; users[rev.user].push(rev.size - lastSize); lastSize = rev.size; }); } return new Promise(function (resolve) { function next() { if (rvcontinue !== null) { if (rvcontinue) params.rvcontinue = rvcontinue; api.get(params).done(function (data) { handleResponse(data); next(); }).fail(function (err) { mw.notify("获取编辑记录失败:" + err, { type: "error" }); rvcontinue = null; resolve(users); }); } else { resolve(users); } } next(); }); }; ShowContributorDialog.prototype.addRow = function ($tbody, data) { var $row = $("<tr />").append( $("<td />").append( $('<a href="' + mw.config.get("wgArticlePath").replace("$1", "User:" + data.user) + '" />').text(data.user) ), $("<td />").text(data.count), $("<td />").text(data.add), $("<td />").text(data.remove) ); $tbody.append($row); }; ShowContributorDialog.prototype.showContributors = function (users) { var self = this; this.$tbody.empty(); Object.keys(users).forEach(function (user) { var edits = users[user]; var add = edits.reduce(function (sum, n) { return n > 0 ? sum + n : sum; }, 0); var remove = edits.reduce(function (sum, n) { return n < 0 ? sum + n : sum; }, 0); self.addRow(self.$tbody, { user: user, count: edits.length, add: add, remove: remove }); }); this.got = true; }; function main() { if (!isValidPage()) return; insertStyles(); mw.loader.using([ "mediawiki.api", "mediawiki.notification", "oojs-ui", "oojs-ui.styles.icons-interactions", "jquery.tablesorter" ], function () { var winManager = new OO.ui.WindowManager({ id: "show-contributor" }); $(document.body).append(winManager.$element); var dialog = new ShowContributorDialog({ size: "large" }); winManager.addWindows([dialog]); var button = new OO.ui.ButtonWidget({ label: "本页贡献者", icon: "search", flags: "progressive", id: "show-contributor-button" }); var insertButton = function () { $("#show-contributor-button").detach(); var skin = mw.config.get("skin"); if (skin === "citizen") { if (window.innerWidth >= 1120) { $(".page-actions").prepend(button.$element); } else { $(".firstHeading-container").append(button.$element); } } else if (skin === "vector-2022") { $("header.mw-body-header.vector-page-titlebar").append(button.$element); } else { $("#bodyContent").prepend(button.$element); } }; insertButton(); var isWide = window.innerWidth >= 1120; $(window).on("resize", function () { clearTimeout(window.__showContributorResizeTimer); window.__showContributorResizeTimer = setTimeout(function () { var nowWide = window.innerWidth >= 1120; if (nowWide !== isWide) { isWide = nowWide; insertButton(); } }, 200); }); button.on("click", function () { if (!dialog.got) { button.setLabel("正在查询"); dialog.getContributors().then(function (users) { dialog.showContributors(users); dialog.$table.tablesorter(); button.setLabel("本页贡献者"); winManager.openWindow(dialog); }); } else { winManager.openWindow(dialog); } }); }); } $(main); })();