Card.js:修订间差异
来自卡厄思梦境WIKI
创建页面,内容为“→* * MediaWiki卡牌编辑器 * 用于管理"模块:卡牌/角色名"页面 * 放置于 MediaWiki:card.js: (function() { 'use strict'; // 检查是否在正确的页面加载 if (mw.config.get('wgCanonicalSpecialPageName') !== 'Blankpage' || !window.location.href.includes('卡牌管理')) { return; } var CardEditor = { cards: [], currentCard: null, currentVariantIndex: null, api: new…” |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
/ | // MediaWiki:Card.js | ||
(function() { | (function() { | ||
'use strict'; | 'use strict'; | ||
// | // 检查是否在正确的页面 | ||
if (mw.config.get(' | if (mw.config.get('wgPageName') !== 'MediaWiki:Card') { | ||
return; | return; | ||
} | } | ||
var | var api = new mw.Api(); | ||
var cardData = {}; | |||
var currentCharacter = null; | |||
// 获取所有"模块:卡牌/角色名"页面 | |||
function loadAllCardModules() { | |||
api.get({ | |||
action: 'query', | |||
list: 'allpages', | |||
apprefix: '卡牌/', | |||
apnamespace: 828, // Module namespace | |||
aplimit: 'max' | |||
}).done(function(data) { | |||
var pages = data.query.allpages; | |||
var select = $('#character-select'); | |||
select.empty(); | |||
select.append('<option value="">选择角色</option>'); | |||
var | |||
pages.forEach(function(page) { | |||
var characterName = page.title.replace('模块:卡牌/', ''); | |||
select.append($('<option>').val(characterName).text(characterName)); | |||
}); | }); | ||
}); | |||
} | |||
// 加载指定角色的卡牌数据 | |||
function loadCharacterCards(characterName) { | |||
api.get({ | |||
action: 'query', | |||
prop: 'revisions', | |||
titles: '模块:卡牌/' + characterName, | |||
rvprop: 'content', | |||
rvslots: 'main' | |||
}).done(function(data) { | |||
var pages = data.query.pages; | |||
for (var pageId in pages) { | |||
if (pages[pageId].revisions) { | |||
var content = pages[pageId].revisions[0].slots.main['*']; | |||
parseModuleContent(content, characterName); | |||
/ | |||
var | |||
} | } | ||
} | } | ||
}); | |||
} | |||
// 解析模块内容 | |||
function parseModuleContent(content, characterName) { | |||
try { | |||
// 提取card表和cardOrder数组 | |||
var cardMatch = content.match(/local\s+card\s*=\s*\{[\s\S]*?\n\}/); | |||
var orderMatch = content.match(/local\s+cardOrder\s*=\s*\{[\s\S]*?\n\}/); | |||
var | |||
var | |||
if (cardMatch && orderMatch) { | |||
// 转换Lua表格式为JavaScript对象 | |||
if ( | var cardDataStr = cardMatch[0] | ||
.replace(/local\s+card\s*=/, 'var cardData =') | |||
var | .replace(/\["([^"]+)"\]/g, '"$1"') | ||
.replace(/\[(\d+)\]/g, '$1') | |||
.replace(/nil/g, 'null'); | |||
var orderDataStr = orderMatch[0] | |||
.replace(/local\s+cardOrder\s*=/, 'var cardOrder =') | |||
.replace(/"/g, '"'); | |||
eval(cardDataStr); | |||
eval(orderDataStr); | |||
currentCharacter = characterName; | |||
displayCards(cardData, cardOrder); | |||
} | } | ||
}, | } catch (e) { | ||
console.error('解析失败:', e); | |||
mw.notify('解析模块内容失败', { type: 'error' }); | |||
} | |||
} | |||
// 显示卡牌列表 | |||
function displayCards(cards, order) { | |||
var container = $('#cards-container'); | |||
container.empty(); | |||
// 按照顺序显示卡牌 | |||
(order || Object.keys(cards)).forEach(function(cardName) { | |||
if (cards[cardName]) { | |||
var cardDiv = createCardElement(cardName, cards[cardName]); | |||
// | container.append(cardDiv); | ||
if ( | |||
} | } | ||
}); | |||
} | |||
// 创建卡牌元素 | |||
function createCardElement(cardName, variants) { | |||
var cardDiv = $('<div>').addClass('card-item'); | |||
var header = $('<h3>').text(cardName).click(function() { | |||
$(this).next('.card-variants').toggle(); | |||
}); | |||
cardDiv.append(header); | |||
var variantsDiv = $('<div>').addClass('card-variants'); | |||
variants.forEach(function(variant, index) { | |||
var variantDiv = createVariantElement(cardName, variant, index); | |||
variantsDiv.append(variantDiv); | |||
}); | |||
// 添加新变体按钮 | |||
var addButton = $('<button>').text('添加变体').click(function() { | |||
addCardVariant(cardName); | |||
}); | |||
variantsDiv.append(addButton); | |||
cardDiv.append(variantsDiv); | |||
return cardDiv; | |||
} | |||
// | |||
// 创建变体元素 | |||
function createVariantElement(cardName, variant, index) { | |||
var $ | var variantDiv = $('<div>').addClass('card-variant'); | ||
var fields = [ | |||
{ key: 'art', label: '图片', type: 'text' }, | |||
{ key: '卡组', label: '卡组', type: 'select', | |||
options: ['起始卡牌', '独特卡牌', '衍生卡牌', '灵光一闪', '神光一闪'] }, | |||
{ key: '属性', label: '属性', type: 'select', | |||
options: ['热情', '秩序', '正义', '本能', '虚无'] }, | |||
{ key: '稀有度', label: '稀有度', type: 'select', | |||
options: ['白', '蓝', '橙', '彩'] }, | |||
{ key: 'AP', label: 'AP', type: 'number' }, | |||
{ key: '类型', label: '类型', type: 'select', | |||
options: ['攻击', '技能', '强化', '状态异常'] }, | |||
{ key: '机制', label: '机制', type: 'text' }, | |||
{ key: '描述', label: '描述', type: 'textarea' }, | |||
{ key: '衍生卡牌', label: '衍生卡牌', type: 'text' } | |||
]; | |||
fields.forEach(function(field) { | |||
var fieldDiv = $('<div>').addClass('field'); | |||
var label = $('<label>').text(field.label + ': '); | |||
var input; | |||
if (field.type === 'select') { | |||
input = $('<select>'); | |||
$('<option>').val('').text('--选择--').appendTo(input); | |||
field.options.forEach(function(opt) { | |||
$('<option>').val(opt).text(opt).appendTo(input); | |||
}); | }); | ||
input.val(variant[field.key] || ''); | |||
} else if (field.type === 'textarea') { | |||
input = $('<textarea>').val(variant[field.key] || ''); | |||
} else { | |||
input = $('<input>').attr('type', field.type).val(variant[field.key] || ''); | |||
} | } | ||
input.attr('data-card', cardName) | |||
.attr('data-index', index) | |||
.attr('data-field', field.key); | |||
fieldDiv.append(label).append(input); | |||
variantDiv.append(fieldDiv); | |||
}); | |||
// 删除按钮 | |||
var deleteButton = $('<button>').text('删除').click(function() { | |||
deleteCardVariant(cardName, index); | |||
}); | |||
variantDiv.append(deleteButton); | |||
return variantDiv; | |||
} | |||
// 添加新卡牌 | |||
function addNewCard() { | |||
var cardName = prompt('输入新卡牌名称:'); | |||
if (!cardName) return; | |||
cardData[cardName] = [{ | |||
art: '', | |||
'卡组': '', | |||
'属性': '', | |||
'稀有度': '', | |||
'AP': 1, | |||
'类型': '', | |||
'机制': '', | |||
'描述': '', | |||
'衍生卡牌': '' | |||
}]; | |||
displayCards(cardData, Object.keys(cardData)); | |||
} | |||
// 添加卡牌变体 | |||
function addCardVariant(cardName) { | |||
if (!cardData[cardName]) { | |||
cardData[cardName] = []; | |||
} | |||
cardData[cardName].push({ | |||
art: '', | |||
'卡组': '', | |||
'属性': '', | |||
'稀有度': '', | |||
'AP': 1, | |||
'类型': '', | |||
'机制': '', | |||
'描述': '', | |||
'衍生卡牌': '' | |||
}); | |||
displayCards(cardData, Object.keys(cardData)); | |||
} | |||
// 删除卡牌变体 | |||
function deleteCardVariant(cardName, index) { | |||
if (confirm('确认删除这个变体?')) { | |||
cardData[cardName].splice(index, 1); | |||
if (cardData[cardName].length === 0) { | |||
delete cardData[cardName]; | |||
} | } | ||
displayCards(cardData, Object.keys(cardData)); | |||
} | |||
} | |||
// 保存数据 | |||
function saveCardData() { | |||
if (!currentCharacter) { | |||
mw.notify('请先选择角色', { type: 'warning' }); | |||
return; | |||
} | |||
// 收集表单数据更新cardData | |||
$('#cards-container input, #cards-container select, #cards-container textarea').each(function() { | |||
var $this = $(this); | |||
var cardName = $this.data('card'); | |||
var index = $this.data('index'); | |||
var field = $this.data('field'); | |||
var value = $this.val(); | |||
return | |||
} | |||
// | |||
var | |||
var | |||
var | |||
var | |||
var | |||
if ( | if (cardData[cardName] && cardData[cardName][index]) { | ||
if (field === 'AP') { | |||
value = parseInt(value) || 0; | |||
} | } | ||
if (value) { | |||
if ( | cardData[cardName][index][field] = value; | ||
} else { | } else { | ||
delete cardData[cardName][index][field]; | |||
} | } | ||
} | } | ||
}); | |||
var moduleContent = generateModuleContent(cardData); | |||
api.postWithToken('csrf', { | |||
action: 'edit', | |||
title: '模块:卡牌/' + currentCharacter, | |||
text: moduleContent, | |||
summary: '通过卡牌管理器更新' | |||
}).done(function() { | |||
mw.notify('保存成功!', { type: 'success' }); | |||
}).fail(function(code, data) { | |||
mw.notify('保存失败: ' + (data.error ? data.error.info : code), { type: 'error' }); | |||
}); | |||
} | |||
// 生成模块内容 | |||
function generateModuleContent(data) { | |||
var content = 'local p = {}\n\n'; | |||
// 生成cardOrder | |||
content += 'local cardOrder = {\n'; | |||
Object.keys(data).forEach(function(cardName) { | |||
content += ' "' + cardName + '",\n'; | |||
}); | |||
content += '}\n\n'; | |||
// 生成card表 | |||
content += 'local card = {\n'; | |||
Object.keys(data).forEach(function(cardName) { | |||
content += ' ["' + cardName + '"] = {\n'; | |||
data[cardName].forEach(function(variant) { | |||
content += ' {\n'; | |||
Object.keys(variant).forEach(function(key) { | |||
var value = variant[key]; | |||
if (value !== null && value !== undefined && value !== '') { | |||
if (key === 'AP' || !isNaN(value)) { | |||
content += ' ["' + key + '"] = ' + value + ',\n'; | |||
// | |||
var | |||
if ( | |||
if ( | |||
} else { | } else { | ||
content += ' ["' + key + '"] = "' + value.replace(/"/g, '\\"') + '",\n'; | |||
} | } | ||
} | } | ||
} | }); | ||
content += ' },\n'; | |||
}); | }); | ||
} | |||
} | content += ' },\n'; | ||
}); | |||
content += '}\n\n'; | |||
content += 'p.card = card\n'; | |||
content += 'p.cardOrder = cardOrder\n\n'; | |||
content += 'return p\n'; | |||
return content; | |||
} | |||
// | // 初始化页面 | ||
$(function() { | $(function() { | ||
loadAllCardModules(); | |||
// 绑定事件 | |||
$('#character-select').on('change', function() { | |||
var characterName = $(this).val(); | |||
if (characterName) { | |||
loadCharacterCards(characterName); | |||
} | |||
}); | |||
$('#add-card-btn').click(addNewCard); | |||
$('#save-btn').click(saveCardData); | |||
$('#refresh-btn').click(loadAllCardModules); | |||
}); | }); | ||
})(); | })(); | ||
2025年10月2日 (四) 10:08的版本
// MediaWiki:Card.js
(function() {
'use strict';
// 检查是否在正确的页面
if (mw.config.get('wgPageName') !== 'MediaWiki:Card') {
return;
}
var api = new mw.Api();
var cardData = {};
var currentCharacter = null;
// 获取所有"模块:卡牌/角色名"页面
function loadAllCardModules() {
api.get({
action: 'query',
list: 'allpages',
apprefix: '卡牌/',
apnamespace: 828, // Module namespace
aplimit: 'max'
}).done(function(data) {
var pages = data.query.allpages;
var select = $('#character-select');
select.empty();
select.append('<option value="">选择角色</option>');
pages.forEach(function(page) {
var characterName = page.title.replace('模块:卡牌/', '');
select.append($('<option>').val(characterName).text(characterName));
});
});
}
// 加载指定角色的卡牌数据
function loadCharacterCards(characterName) {
api.get({
action: 'query',
prop: 'revisions',
titles: '模块:卡牌/' + characterName,
rvprop: 'content',
rvslots: 'main'
}).done(function(data) {
var pages = data.query.pages;
for (var pageId in pages) {
if (pages[pageId].revisions) {
var content = pages[pageId].revisions[0].slots.main['*'];
parseModuleContent(content, characterName);
}
}
});
}
// 解析模块内容
function parseModuleContent(content, characterName) {
try {
// 提取card表和cardOrder数组
var cardMatch = content.match(/local\s+card\s*=\s*\{[\s\S]*?\n\}/);
var orderMatch = content.match(/local\s+cardOrder\s*=\s*\{[\s\S]*?\n\}/);
if (cardMatch && orderMatch) {
// 转换Lua表格式为JavaScript对象
var cardDataStr = cardMatch[0]
.replace(/local\s+card\s*=/, 'var cardData =')
.replace(/\["([^"]+)"\]/g, '"$1"')
.replace(/\[(\d+)\]/g, '$1')
.replace(/nil/g, 'null');
var orderDataStr = orderMatch[0]
.replace(/local\s+cardOrder\s*=/, 'var cardOrder =')
.replace(/"/g, '"');
eval(cardDataStr);
eval(orderDataStr);
currentCharacter = characterName;
displayCards(cardData, cardOrder);
}
} catch (e) {
console.error('解析失败:', e);
mw.notify('解析模块内容失败', { type: 'error' });
}
}
// 显示卡牌列表
function displayCards(cards, order) {
var container = $('#cards-container');
container.empty();
// 按照顺序显示卡牌
(order || Object.keys(cards)).forEach(function(cardName) {
if (cards[cardName]) {
var cardDiv = createCardElement(cardName, cards[cardName]);
container.append(cardDiv);
}
});
}
// 创建卡牌元素
function createCardElement(cardName, variants) {
var cardDiv = $('<div>').addClass('card-item');
var header = $('<h3>').text(cardName).click(function() {
$(this).next('.card-variants').toggle();
});
cardDiv.append(header);
var variantsDiv = $('<div>').addClass('card-variants');
variants.forEach(function(variant, index) {
var variantDiv = createVariantElement(cardName, variant, index);
variantsDiv.append(variantDiv);
});
// 添加新变体按钮
var addButton = $('<button>').text('添加变体').click(function() {
addCardVariant(cardName);
});
variantsDiv.append(addButton);
cardDiv.append(variantsDiv);
return cardDiv;
}
// 创建变体元素
function createVariantElement(cardName, variant, index) {
var variantDiv = $('<div>').addClass('card-variant');
var fields = [
{ key: 'art', label: '图片', type: 'text' },
{ key: '卡组', label: '卡组', type: 'select',
options: ['起始卡牌', '独特卡牌', '衍生卡牌', '灵光一闪', '神光一闪'] },
{ key: '属性', label: '属性', type: 'select',
options: ['热情', '秩序', '正义', '本能', '虚无'] },
{ key: '稀有度', label: '稀有度', type: 'select',
options: ['白', '蓝', '橙', '彩'] },
{ key: 'AP', label: 'AP', type: 'number' },
{ key: '类型', label: '类型', type: 'select',
options: ['攻击', '技能', '强化', '状态异常'] },
{ key: '机制', label: '机制', type: 'text' },
{ key: '描述', label: '描述', type: 'textarea' },
{ key: '衍生卡牌', label: '衍生卡牌', type: 'text' }
];
fields.forEach(function(field) {
var fieldDiv = $('<div>').addClass('field');
var label = $('<label>').text(field.label + ': ');
var input;
if (field.type === 'select') {
input = $('<select>');
$('<option>').val('').text('--选择--').appendTo(input);
field.options.forEach(function(opt) {
$('<option>').val(opt).text(opt).appendTo(input);
});
input.val(variant[field.key] || '');
} else if (field.type === 'textarea') {
input = $('<textarea>').val(variant[field.key] || '');
} else {
input = $('<input>').attr('type', field.type).val(variant[field.key] || '');
}
input.attr('data-card', cardName)
.attr('data-index', index)
.attr('data-field', field.key);
fieldDiv.append(label).append(input);
variantDiv.append(fieldDiv);
});
// 删除按钮
var deleteButton = $('<button>').text('删除').click(function() {
deleteCardVariant(cardName, index);
});
variantDiv.append(deleteButton);
return variantDiv;
}
// 添加新卡牌
function addNewCard() {
var cardName = prompt('输入新卡牌名称:');
if (!cardName) return;
cardData[cardName] = [{
art: '',
'卡组': '',
'属性': '',
'稀有度': '',
'AP': 1,
'类型': '',
'机制': '',
'描述': '',
'衍生卡牌': ''
}];
displayCards(cardData, Object.keys(cardData));
}
// 添加卡牌变体
function addCardVariant(cardName) {
if (!cardData[cardName]) {
cardData[cardName] = [];
}
cardData[cardName].push({
art: '',
'卡组': '',
'属性': '',
'稀有度': '',
'AP': 1,
'类型': '',
'机制': '',
'描述': '',
'衍生卡牌': ''
});
displayCards(cardData, Object.keys(cardData));
}
// 删除卡牌变体
function deleteCardVariant(cardName, index) {
if (confirm('确认删除这个变体?')) {
cardData[cardName].splice(index, 1);
if (cardData[cardName].length === 0) {
delete cardData[cardName];
}
displayCards(cardData, Object.keys(cardData));
}
}
// 保存数据
function saveCardData() {
if (!currentCharacter) {
mw.notify('请先选择角色', { type: 'warning' });
return;
}
// 收集表单数据更新cardData
$('#cards-container input, #cards-container select, #cards-container textarea').each(function() {
var $this = $(this);
var cardName = $this.data('card');
var index = $this.data('index');
var field = $this.data('field');
var value = $this.val();
if (cardData[cardName] && cardData[cardName][index]) {
if (field === 'AP') {
value = parseInt(value) || 0;
}
if (value) {
cardData[cardName][index][field] = value;
} else {
delete cardData[cardName][index][field];
}
}
});
var moduleContent = generateModuleContent(cardData);
api.postWithToken('csrf', {
action: 'edit',
title: '模块:卡牌/' + currentCharacter,
text: moduleContent,
summary: '通过卡牌管理器更新'
}).done(function() {
mw.notify('保存成功!', { type: 'success' });
}).fail(function(code, data) {
mw.notify('保存失败: ' + (data.error ? data.error.info : code), { type: 'error' });
});
}
// 生成模块内容
function generateModuleContent(data) {
var content = 'local p = {}\n\n';
// 生成cardOrder
content += 'local cardOrder = {\n';
Object.keys(data).forEach(function(cardName) {
content += ' "' + cardName + '",\n';
});
content += '}\n\n';
// 生成card表
content += 'local card = {\n';
Object.keys(data).forEach(function(cardName) {
content += ' ["' + cardName + '"] = {\n';
data[cardName].forEach(function(variant) {
content += ' {\n';
Object.keys(variant).forEach(function(key) {
var value = variant[key];
if (value !== null && value !== undefined && value !== '') {
if (key === 'AP' || !isNaN(value)) {
content += ' ["' + key + '"] = ' + value + ',\n';
} else {
content += ' ["' + key + '"] = "' + value.replace(/"/g, '\\"') + '",\n';
}
}
});
content += ' },\n';
});
content += ' },\n';
});
content += '}\n\n';
content += 'p.card = card\n';
content += 'p.cardOrder = cardOrder\n\n';
content += 'return p\n';
return content;
}
// 初始化页面
$(function() {
loadAllCardModules();
// 绑定事件
$('#character-select').on('change', function() {
var characterName = $(this).val();
if (characterName) {
loadCharacterCards(characterName);
}
});
$('#add-card-btn').click(addNewCard);
$('#save-btn').click(saveCardData);
$('#refresh-btn').click(loadAllCardModules);
});
})();