MediaWiki:Gadget-ShowContributors.js:修订间差异
MediaWiki界面页面
更多操作
![]() OctoberSama(留言 | 贡献) 小 |
![]() OctoberSama(留言 | 贡献) 小 |
||
第1行: | 第1行: | ||
(() | (function() { | ||
"use strict"; | "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 ( | if ( | ||
[0, 2, 4, 10, 12, 14, 828, 274].indexOf(mw.config.get("wgNamespaceNumber")) === -1 || | |||
mw.config.get("wgArticleId") === 0 || | |||
["view", "history"].indexOf(mw.config.get("wgAction")) === -1 | |||
) | ) { | ||
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;' + | ||
} | '}' + | ||
'}' | |||
); | |||
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('依赖模块加载成功'); | |||
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; | |||
static static | } | ||
initialize() { | OO.inheritClass(ShowContributorDialog, OO.ui.Dialog); | ||
ShowContributorDialog.static = ShowContributorDialog.static || {}; | |||
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( | ||
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", | new OO.ui.IconWidget({ icon: "close", id: "show-contributor-close" }).$element.on("click", function() { | ||
this.close(); | |||
}.bind(this)) | |||
), | ), | ||
this.$table.append( | this.$table.append( | ||
jQuery("<thead><th>用户</th><th>编辑数</th><th>增加字节数</th><th>删减字节数</th></thead>"), | |||
this.$tbody | this.$tbody | ||
) | ) | ||
) | ); | ||
this | return this; | ||
} | }; | ||
getContributors = | |||
ShowContributorDialog.prototype.getContributors = function() { | |||
var self = this; | |||
return new Promise(function(resolve, reject) { | |||
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" | |||
}; | |||
function fetchRevisions() { | |||
if (continueToken) params.rvcontinue = continueToken; | |||
api.get(params).then(function(response) { | |||
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; | |||
} | |||
if (continueToken) { | |||
fetchRevisions(); | |||
} else { | |||
console.log('贡献者数据:', contributors); | |||
resolve(contributors); | |||
} | |||
}).catch(function(error) { | |||
console.error('API 请求失败:', error); | |||
mw.notify('获取编辑记录失败:' + error, { type: "error" }); | |||
reject(error); | |||
}); | |||
} | } | ||
fetchRevisions(); | |||
}); | |||
}; | }; | ||
addRow = ( | |||
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>') | |||
) | ) | ||
) | ); | ||
}; | }; | ||
showContributors = | |||
ShowContributorDialog.prototype.showContributors = function(contributors) { | |||
this.$tbody.empty(); | this.$tbody.empty(); | ||
for ( | for (var user in contributors) { | ||
if (contributors.hasOwnProperty(user)) { | |||
user | var edits = contributors[user]; | ||
var add = edits.reduce(function(sum, delta) { | |||
add | return delta > 0 ? sum + delta : sum; | ||
remove | }, 0); | ||
var remove = edits.reduce(function(sum, delta) { | |||
this.got = | 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") { | |||
$(".page- | 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 { | ||
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); | |||
button.setLabel("本页贡献者"); | |||
}); | |||
} else { | |||
windowManager.openWindow(dialog); | |||
console.log('窗口打开状态:', windowManager); | |||
} | } | ||
} | }); | ||
}) | }).catch(function(err) { | ||
console.error('模块加载失败:', err); | |||
}); | }); | ||
}) | }); | ||
})(); | })(); |
2025年6月17日 (二) 17:40的版本
(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].indexOf(mw.config.get("wgNamespaceNumber")) === -1 || mw.config.get("wgArticleId") === 0 || ["view", "history"].indexOf(mw.config.get("wgAction")) === -1 ) { 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 = ShowContributorDialog.static || {}; 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 = function() { var self = this; return new Promise(function(resolve, reject) { 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" }; function fetchRevisions() { if (continueToken) params.rvcontinue = continueToken; api.get(params).then(function(response) { 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; } if (continueToken) { fetchRevisions(); } else { console.log('贡献者数据:', contributors); resolve(contributors); } }).catch(function(error) { console.error('API 请求失败:', error); mw.notify('获取编辑记录失败:' + error, { type: "error" }); reject(error); }); } fetchRevisions(); }); }; 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); button.setLabel("本页贡献者"); }); } else { windowManager.openWindow(dialog); console.log('窗口打开状态:', windowManager); } }); }).catch(function(err) { console.error('模块加载失败:', err); }); }); })();