User:魔琴/gadgets/FullWikidataDesc/index.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/**
* FullWikidataDesc
*
* 在条目顶端显示/编辑维基数据描述(包括所有中文变体和英语、多语言)
*
* 原作者:User:Alexander Misel ([[Special:Permalink/45559457]])
* 改进:User:逆襲的天邪鬼 ([[MediaWiki:Gadget-WikidataDesc.js]])
* 修改为所有中文变体(利用AI/LLM)
*/
mw.loader.using('mediawiki.ForeignApi').done(function () {
'use strict';
// Define language list
var languages = ['zh', 'zh-hans', 'zh-cn', 'zh-my', 'zh-sg', 'zh-hant', 'zh-hk', 'zh-mo', 'zh-tw', 'en', 'mul'];
var UI = ['zh-hk', 'zh-mo', 'zh-tw'].indexOf(mw.config.get('wgUserLanguage'))!== -1 ? {
SAVING: '正在儲存',
EDIT: '編輯',
SAVE: '儲存',
CANCEL: '取消',
PLACEHOLDER_DESC: '維基數據描述',
PLACEHOLDER_LABEL: '維基數據標籤',
LANG: '語言',
DESC: '描述',
LABEL: '標籤',
EMPTY_DESC: '無描述',
EMPTY_LABEL: '無標籤',
SUCCESS: '儲存成功',
ERROR: '發生错误',
} : {
SAVING: '正在保存',
EDIT: '编辑',
SAVE: '保存',
CANCEL: '取消',
PLACEHOLDER_DESC: '维基数据描述',
PLACEHOLDER_LABEL: '维基数据标签',
LANG: '语言',
DESC: '描述',
LABEL: '标签',
EMPTY_DESC: '无描述',
EMPTY_LABEL: '无标签',
SUCCESS: '保存成功',
ERROR: '发生错误',
};
var $desc = $('<div id="fullwikidatadesc" class="noprint">');
var $table = $('<table id="fullwikidatadesc_table">');
var CSS = `
#fullwikidatadesc .text { color: var(--color-subtle,#54595d); }
#fullwikidatadesc .editbox { width: 100%; padding: 4px; border: none; border-bottom: 1px solid #ccc; box-sizing: border-box; }
#fullwikidatadesc .editbox:focus { border-bottom: 1px solid #0645ad; }
#fullwikidatadesc .option { font-size: smaller; }
#fullwikidatadesc_table { width: 100%; border-collapse: collapse; }
#fullwikidatadesc_table td { padding: 2px; border-bottom: 1px solid #ddd; }
.fullwikidatadesc_table_langcell { white-space:nowrap; }
.fullwikidatadesc_table_labelcell { width:30%; }
.fullwikidatadesc_table_desccell { width:70%; }
.fullwikidatadesc_editlink { white-space:nowrap }
`;
var status = {}; // 每个语言的标签和描述分别对应显示或编辑状态
var loaded = false;
var saving = {};
var id = '';
var label = {};
var lastdesc = {};
var lastlabel = {};
var pagename = mw.config.get('wgPageName');
// 初始化每个语言的状态
languages.forEach(function (lang) {
status[lang] = {
label: 0,
desc: 0
};
saving[lang] = {
label: false,
desc: false
};
label[lang] = '';
lastdesc[lang] = '';
lastlabel[lang] = '';
});
var loadCtl = function () {
$('body').append($('<style>').text(CSS));
// 添加表头
var $headerRow = $('<tr style="text-align:left">');
$headerRow.append($('<th>').text(UI.LANG));
$headerRow.append($('<th>').text(UI.LABEL));
$headerRow.append($('<th>').text(UI.DESC));
$table.append($headerRow);
languages.forEach(function (lang) {
var $row = $('<tr>');
var $langCell = $('<td class="fullwikidatadesc_table_langcell">').text(lang);
// 标签列
var $labelCell = $('<td class="fullwikidatadesc_table_contentcell fullwikidatadesc_table_labelcell">');
var $labelSaving = $('<span id="fullwikidatadesc_label_loading_' + lang + '" class="text option" style="display:none;">(' + UI.SAVING + ')</span>');
var $labelText = $('<span id="fullwikidatadesc_label_text_' + lang + '" class="text">');
var $labelEditlink = $('<a href="#" class="fullwikidatadesc_editlink option">[' + UI.EDIT + ' ' + lang + ' ' + UI.LABEL + ']</a>');
var $labelDescbox = $('<div id="fullwikidatadesc_label_descbox_' + lang + '">')
.append($labelText)
.append(' ')
.append($labelSaving)
.append($labelEditlink);
var $labelInput = $('<input class="editbox" type="text" placeHolder="' + UI.PLACEHOLDER_LABEL + '">');
var $labelSave = $('<a href="#" class="option" id="fullwikidatadesc_label_save_' + lang + '">[' + UI.SAVE + ']</a>');
var $labelCancel = $('<a href="#" class="option" id="fullwikidatadesc_label_cancel_' + lang + '">[' + UI.CANCEL + ']</a>');
var $labelEditbox = $('<div id="fullwikidatadesc_label_editbox_' + lang + '" style="display:none;">')
.append($labelInput)
.append('<br>')
.append($labelSave)
.append($labelCancel);
$labelCell.append($labelDescbox).append($labelEditbox);
// 描述列
var $contentCell = $('<td class="fullwikidatadesc_table_contentcell fullwikidatadesc_table_desccell">');
var $saving = $('<span id="fullwikidatadesc_loading_' + lang + '" class="text option" style="display:none;">(' + UI.SAVING + ')</span>');
var $text = $('<span id="fullwikidatadesc_text_' + lang + '" class="text">');
var $editlink = $('<a href="#" class="fullwikidatadesc_editlink option">[' + UI.EDIT + ' ' + lang + ' ' + UI.DESC + ']</a>');
var $descbox = $('<div id="fullwikidatadesc_descbox_' + lang + '">')
.append($text)
.append(' ')
.append($saving)
.append($editlink);
var $input = $('<input class="editbox" type="text" placeHolder="' + UI.PLACEHOLDER_DESC + '">');
var $save = $('<a href="#" class="option" id="fullwikidatadesc_save_' + lang + '">[' + UI.SAVE + ']</a>');
var $cancel = $('<a href="#" class="option" id="fullwikidatadesc_cancel_' + lang + '">[' + UI.CANCEL + ']</a>');
var $editbox = $('<div id="fullwikidatadesc_editbox_' + lang + '" style="display:none;">')
.append($input)
.append('<br>')
.append($save)
.append($cancel);
$contentCell.append($descbox).append($editbox);
$row.append($langCell).append($labelCell).append($contentCell);
$table.append($row);
// 标签编辑事件
$labelEditlink.click(function () {
if (status[lang].label!== 0 || saving[lang].label) {
return;
}
status[lang].label = 1;
$labelDescbox.hide();
$labelEditbox.show();
$labelInput.focus();
});
$labelSave.click(function () {
if (status[lang].label!== 1) {
return;
}
status[lang].label = 0;
saving[lang].label = true;
var newlabel = $labelInput.val();
$labelText.text(newlabel);
$labelSaving.show();
$labelEditlink.hide();
$labelDescbox.show();
$labelEditbox.hide();
saveLabel(lang, newlabel, function (success, error) {
saving[lang].label = false;
$labelSaving.hide();
$labelEditlink.show();
if (success) {
lastlabel[lang] = newlabel;
mw.notify(UI.SUCCESS + ':' + lang + ' ' + UI.LABEL);
} else {
$labelText.text(lastlabel[lang]);
mw.notify(UI.ERROR + ':' + lang + ' ' + UI.LABEL);
}
});
});
$labelCancel.click(function () {
if (status[lang].label!== 1) {
return;
}
status[lang].label = 0;
$labelInput.val(lastlabel[lang]);
$labelDescbox.show();
$labelEditbox.hide();
});
$labelInput.keydown(function (e) {
if (e.which === 13) {
$labelSave.click();
} else if (e.which === 27) {
$labelCancel.click();
}
});
// 描述编辑事件
$editlink.click(function () {
if (status[lang].desc!== 0 || saving[lang].desc) {
return;
}
status[lang].desc = 1;
$descbox.hide();
$editbox.show();
$input.focus();
});
$save.click(function () {
if (status[lang].desc!== 1) {
return;
}
status[lang].desc = 0;
saving[lang].desc = true;
var newdesc = $input.val();
$text.text(newdesc);
$saving.show();
$editlink.hide();
$descbox.show();
$editbox.hide();
save(lang, newdesc, function (success, error) {
saving[lang].desc = false;
$saving.hide();
$editlink.show();
if (success) {
lastdesc[lang] = newdesc;
mw.notify(UI.SUCCESS + ':' + lang + ' ' + UI.DESC);
} else {
$text.text(lastdesc[lang]);
mw.notify(UI.ERROR + ':' + lang + ' ' + UI.DESC);
}
});
});
$cancel.click(function () {
if (status[lang].desc!== 1) {
return;
}
status[lang].desc = 0;
$input.val(lastdesc[lang]);
$descbox.show();
$editbox.hide();
});
$input.keydown(function (e) {
if (e.which === 13) {
$save.click();
} else if (e.which === 27) {
$cancel.click();
}
});
});
$desc.append($table);
$("#siteSub").before($desc);
loaded = true;
};
var show = function (descs, labels) {
if (!loaded) {
loadCtl();
}
languages.forEach(function (lang) {
var desc = descs[lang];
var labelValue = labels[lang];
var $text = $('#fullwikidatadesc_text_' + lang);
var $input = $('#fullwikidatadesc_editbox_' + lang + ' input');
var $labelText = $('#fullwikidatadesc_label_text_' + lang);
var $labelInput = $('#fullwikidatadesc_label_editbox_' + lang + ' input');
if (desc) {
$text.text(desc);
$input.val(desc);
lastdesc[lang] = desc;
} else {
$text.html('<abbr title="' + UI.EMPTY_DESC + '">(' + UI.EMPTY_DESC + ')</abbr>');
$input.val('');
lastdesc[lang] = '';
}
if (labelValue) {
$labelText.text(labelValue);
$labelInput.val(labelValue);
lastlabel[lang] = labelValue;
} else {
$labelText.html('<abbr title="' + UI.EMPTY_LABEL + '">(' + UI.EMPTY_LABEL + ')</abbr>');
$labelInput.val('');
lastlabel[lang] = '';
}
});
};
var load = function (callback) {
var ns = mw.config.get('wgNamespaceNumber');
if (ns === 0) {
var api = new mw.ForeignApi('https://www.wikidata.org/w/api.php');
var resDescs = {};
var resLabels = {};
api.get({
action: 'wbgetentities',
props: 'labels|descriptions',
sites: 'zhwiki',
titles: pagename,
languages: languages.join('|')
}).done(function (data) {
$.each(data.entities, function (i, item) {
if (i == '-1') {
id = 'NE';
callback({}, {});
} else {
id = item.id;
var labels = item.labels;
var descs = item.descriptions;
languages.forEach(function (lang) {
if (labels[lang]) {
resLabels[lang] = labels[lang].value;
}
if (descs[lang]) {
resDescs[lang] = descs[lang].value;
}
});
callback(resDescs, resLabels);
}
});
});
}
};
var save = function (lang, newdesc, callback) {
var api = new mw.ForeignApi('https://www.wikidata.org/w/api.php');
api.get({
action: 'query',
meta: 'tokens'
}).done(function (data) {
if (id == 'NE') {
var jdata = JSON.stringify({
labels: { [lang]: { language: lang, value: pagename } },
descriptions: { [lang]: { language: lang, value: newdesc } },
sitelinks: { zhwiki: { site: 'zhwiki', title: pagename } }
});
api.post({
action: 'wbeditentity',
'new': 'item',
token: data.query.tokens.csrftoken,
data: jdata
}).done(function () {
callback(true);
}).fail(function () {
callback(false);
});
} else {
api.post({
action: 'wbsetdescription',
id: id,
token: data.query.tokens.csrftoken,
language: lang,
value: newdesc,
}).done(function () {
if (label['zh'] === '') { // 這裏需要僅僅提交zh
api.post({
action: 'wbsetlabel',
id: id,
token: data.query.tokens.csrftoken,
language: 'zh',
value: pagename,
}).always(function () {
callback(true);
});
} else {
callback(true);
}
}).fail(function () {
callback(false);
});
}
}).fail(function () {
callback(false);
});
};
var saveLabel = function (lang, newlabel, callback) {
var api = new mw.ForeignApi('https://www.wikidata.org/w/api.php');
api.get({
action: 'query',
meta: 'tokens'
}).done(function (data) {
if (id == 'NE') {
var jdata = JSON.stringify({
labels: { [lang]: { language: lang, value: newlabel } },
descriptions: { [lang]: { language: lang, value: lastdesc[lang] } },
sitelinks: { zhwiki: { site: 'zhwiki', title: pagename } }
});
api.post({
action: 'wbeditentity',
'new': 'item',
token: data.query.tokens.csrftoken,
data: jdata
}).done(function () {
callback(true);
}).fail(function () {
callback(false);
});
} else {
api.post({
action: 'wbsetlabel',
id: id,
token: data.query.tokens.csrftoken,
language: lang,
value: newlabel,
}).done(function () {
if (label['zh'] === '' && lang !== 'zh') { // 要排除提交了zh的情况
api.post({
action: 'wbsetlabel',
id: id,
token: data.query.tokens.csrftoken,
language: 'zh',
value: pagename,
}).always(function () {
callback(true);
});
} else {
callback(true);
}
}).fail(function () {
callback(false);
});
}
}).fail(function () {
callback(false);
});
};
load(show);
});