TeamBuilder.js:修订间差异
来自卡厄思梦境WIKI
无编辑摘要 |
无编辑摘要 标签:已被回退 |
||
| 第1行: | 第1行: | ||
(function() { | (function() { | ||
'use strict'; | 'use strict'; | ||
mw.loader.load(mw.util.getUrl('MediaWiki:TeamBuilder.css', { action: 'raw', ctype: 'text/css' }), 'text/css'); | |||
mw.loader.load( mw.util.getUrl( 'MediaWiki:TeamBuilder.css', { action: 'raw', ctype: 'text/css' } ), 'text/css' ); | |||
if (document.readyState === 'loading') { | if (document.readyState === 'loading') { | ||
document.addEventListener('DOMContentLoaded', initTeamBuilder); | document.addEventListener('DOMContentLoaded', initTeamBuilder); | ||
| 第11行: | 第10行: | ||
function initTeamBuilder() { | function initTeamBuilder() { | ||
if (!document.getElementById('team-builder')) return; | if (!document.getElementById('team-builder')) return; | ||
| 第22行: | 第20行: | ||
deckCards: [], | deckCards: [], | ||
availableCards: [], | availableCards: [], | ||
currentEquipmentType: null // | currentEquipmentType: null, | ||
equipmentCache: {} // 添加装备缓存 | |||
}; | }; | ||
// 模态框通用函数 | // === 模态框通用函数 === | ||
function showModal(modalId) { | function showModal(modalId) { | ||
const modal = document.getElementById(modalId); | const modal = document.getElementById(modalId); | ||
| 第51行: | 第50行: | ||
} | } | ||
// | // === 事件绑定 === | ||
const characterSlot = document.getElementById('character-slot'); | const characterSlot = document.getElementById('character-slot'); | ||
if (characterSlot) { | if (characterSlot) { | ||
| 第59行: | 第58行: | ||
} | } | ||
const partnerSlot = document.getElementById('partner-slot'); | const partnerSlot = document.getElementById('partner-slot'); | ||
if (partnerSlot) { | if (partnerSlot) { | ||
| 第67行: | 第65行: | ||
} | } | ||
const deckArea = document.getElementById('deck-area'); | const deckArea = document.getElementById('deck-area'); | ||
if (deckArea) { | if (deckArea) { | ||
deckArea.addEventListener('click', function(e) { | deckArea.addEventListener('click', function(e) { | ||
if (e.target === this || e.target.closest('.deck-area') === this) { | if (e.target === this || e.target.closest('.deck-area') === this) { | ||
if (state.selectedCharacter) { | if (state.selectedCharacter) { | ||
| 第82行: | 第78行: | ||
} | } | ||
document.querySelectorAll('.equip-slot').forEach(slot => { | document.querySelectorAll('.equip-slot').forEach(slot => { | ||
slot.addEventListener('click', function() { | slot.addEventListener('click', function() { | ||
const type = this.getAttribute('data-type'); | const type = this.getAttribute('data-type'); | ||
state.currentEquipmentType = type; | state.currentEquipmentType = type; | ||
loadEquipmentList(type); | loadEquipmentList(type); | ||
document.getElementById('equipment-modal-title').textContent = '选择' + type; | document.getElementById('equipment-modal-title').textContent = '选择' + type; | ||
| 第93行: | 第88行: | ||
}); | }); | ||
document.querySelectorAll('.tb-modal-close').forEach(btn => { | document.querySelectorAll('.tb-modal-close').forEach(btn => { | ||
btn.addEventListener('click', function() { | btn.addEventListener('click', function() { | ||
| 第101行: | 第95行: | ||
}); | }); | ||
document.querySelectorAll('.tb-modal').forEach(modal => { | document.querySelectorAll('.tb-modal').forEach(modal => { | ||
modal.addEventListener('click', function(e) { | modal.addEventListener('click', function(e) { | ||
| 第111行: | 第104行: | ||
}); | }); | ||
// | // === 战斗员列表点击 === | ||
const characterList = document.getElementById('character-list'); | const characterList = document.getElementById('character-list'); | ||
if (characterList) { | if (characterList) { | ||
| 第124行: | 第117行: | ||
} | } | ||
// | // === 伙伴列表点击 === | ||
const partnerList = document.getElementById('partner-list'); | const partnerList = document.getElementById('partner-list'); | ||
if (partnerList) { | if (partnerList) { | ||
| 第138行: | 第131行: | ||
} | } | ||
// 选择战斗员 | // === 选择战斗员 === | ||
function selectCharacter(name) { | function selectCharacter(name) { | ||
state.selectedCharacter = name; | state.selectedCharacter = name; | ||
const slot = document.getElementById('character-slot'); | const slot = document.getElementById('character-slot'); | ||
const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/战斗员图鉴_' + encodeURIComponent(name) + '.png'; | const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/战斗员图鉴_' + encodeURIComponent(name) + '.png'; | ||
| 第153行: | 第145行: | ||
`; | `; | ||
// | // 清空卡组 | ||
state.deckCards = []; | state.deckCards = []; | ||
state.availableCards = []; | state.availableCards = []; | ||
updateDeckDisplay(); | updateDeckDisplay(); | ||
// | // 加载并自动显示卡牌 | ||
loadCharacterCards(name); | loadCharacterCards(name); | ||
} | } | ||
// | // === 选择伙伴(修复文件名) === | ||
function selectPartner(name, id) { | function selectPartner(name, id) { | ||
state.selectedPartner = { name, id }; | state.selectedPartner = { name, id }; | ||
const slot = document.getElementById('partner-slot'); | const slot = document.getElementById('partner-slot'); | ||
// | // 修复:使用正确的文件名格式 | ||
const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/face_character_wide_' + encodeURIComponent(id) + '.png'; | const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/face_character_wide_' + encodeURIComponent(id) + '.png'; | ||
| 第178行: | 第170行: | ||
} | } | ||
// | // === 加载装备列表(添加缓存) === | ||
function loadEquipmentList(type) { | function loadEquipmentList(type) { | ||
const listContainer = document.getElementById('equipment-list'); | const listContainer = document.getElementById('equipment-list'); | ||
// 检查缓存 | |||
if (state.equipmentCache[type]) { | |||
listContainer.innerHTML = ''; | |||
state.equipmentCache[type].forEach(item => { | |||
listContainer.appendChild(item.cloneNode(true)); | |||
}); | |||
attachEquipmentClickHandlers(); | |||
return; | |||
} | |||
listContainer.innerHTML = '<p style="color: white;">加载中...</p>'; | listContainer.innerHTML = '<p style="color: white;">加载中...</p>'; | ||
new mw.Api().post({ | new mw.Api().post({ | ||
action: 'parse', | action: 'parse', | ||
| 第196行: | 第198行: | ||
tempDiv.innerHTML = data.parse.text['*']; | tempDiv.innerHTML = data.parse.text['*']; | ||
const allEquips = tempDiv.querySelectorAll('.equipment-wrapper'); | const allEquips = tempDiv.querySelectorAll('.equipment-wrapper'); | ||
const filteredEquips = []; | |||
listContainer.innerHTML = ''; | listContainer.innerHTML = ''; | ||
| 第203行: | 第205行: | ||
const equipType = equipWrapper.getAttribute('data-param3'); | const equipType = equipWrapper.getAttribute('data-param3'); | ||
if (equipType === type) { | if (equipType === type) { | ||
filteredEquips.push(equipWrapper.cloneNode(true)); | |||
listContainer.appendChild(equipWrapper.cloneNode(true)); | listContainer.appendChild(equipWrapper.cloneNode(true)); | ||
} | } | ||
}); | }); | ||
// 缓存结果 | |||
state.equipmentCache[type] = filteredEquips; | |||
if (listContainer.children.length === 0) { | if (listContainer.children.length === 0) { | ||
| 第218行: | 第224行: | ||
} | } | ||
// 装备点击处理 | // === 装备点击处理 === | ||
function attachEquipmentClickHandlers() { | function attachEquipmentClickHandlers() { | ||
document.querySelectorAll('#equipment-list .equipment-card').forEach(card => { | document.querySelectorAll('#equipment-list .equipment-card').forEach(card => { | ||
| 第224行: | 第230行: | ||
card.addEventListener('click', function() { | card.addEventListener('click', function() { | ||
const name = this.getAttribute('data-equipment'); | const name = this.getAttribute('data-equipment'); | ||
const | const wrapper = this.closest('.equipment-wrapper'); | ||
const rarity = wrapper ? wrapper.getAttribute('data-param1') : '蓝'; | |||
selectEquipment(state.currentEquipmentType, name, rarity); | selectEquipment(state.currentEquipmentType, name, rarity); | ||
hideModal('equipment-modal'); | hideModal('equipment-modal'); | ||
| 第231行: | 第238行: | ||
} | } | ||
// | // === 选择装备(修复ID格式化) === | ||
function selectEquipment(type, name, rarity) { | function selectEquipment(type, name, rarity) { | ||
const slotMap = { | const slotMap = { | ||
'武器': 'weapon-slot', | '武器': 'weapon-slot', | ||
| 第245行: | 第251行: | ||
if (!slot) return; | if (!slot) return; | ||
if (type === '武器') state.selectedWeapon = name; | if (type === '武器') state.selectedWeapon = name; | ||
else if (type === '装甲') state.selectedArmor = name; | else if (type === '装甲') state.selectedArmor = name; | ||
else if (type === '戒指') state.selectedRing = name; | else if (type === '戒指') state.selectedRing = name; | ||
// | // 从装备data中查找ID | ||
new mw.Api(). | new mw.Api().post({ | ||
action: ' | action: 'scribunto-console', | ||
question: `return require('Module:装备/data')['${name.replace(/'/g, "\\'")}'].id`, | |||
clear: true | |||
}).done(function(data) { | }).done(function(data) { | ||
if (data | let equipId = '0000'; | ||
if (data && data.return) { | |||
equipId = String(data.return).padStart(4, '0'); | |||
} | |||
const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/relic_' + equipId + '.png'; | |||
const framePath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/frame_item_rarity_' + encodeURIComponent(rarity) + '.png'; | |||
const textShadow = '-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000'; | |||
slot.innerHTML = ` | |||
<div style="position:relative;width:124px;height:124px"> | |||
<div style="position:absolute;top:0px;left:0px"> | |||
<img src="${framePath}" style="width:124px;height:124px;" | |||
onerror="this.style.display='none'" /> | |||
</div> | |||
<div style="position:absolute;top:8px;left:8px;width:108px;height:108px;border:1px solid #fff;"></div> | |||
<div style="position:absolute;top:6px;left:6px;"> | |||
<img src="${imgPath}" style="width:112px;height:112px;" | |||
onerror="this.src='${mw.config.get('wgScriptPath')}/resources/assets/file-type-icons/fileicon-image.png';" /> | |||
</div> | </div> | ||
`; | <div style="position:absolute;bottom:2px;left:6px;right:6px;color:white;font-size:12px;text-shadow:${textShadow};overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${mw.html.escape(name)}</div> | ||
</div> | |||
`; | |||
}).fail(function() { | }).fail(function() { | ||
// | // 备用方案:直接显示名称 | ||
slot.innerHTML = ` | slot.innerHTML = ` | ||
<div style="position:relative;width:124px;height:124px;display:flex;align-items:center;justify-content:center;"> | <div style="position:relative;width:124px;height:124px;display:flex;align-items:center;justify-content:center;background:#4a4a4a;border-radius:4px;"> | ||
<span style="color:white;font-size:12px;text-align:center;">${mw.html.escape(name)}</span> | <span style="color:white;font-size:12px;text-align:center;padding:5px;">${mw.html.escape(name)}</span> | ||
</div> | </div> | ||
`; | `; | ||
| 第293行: | 第294行: | ||
} | } | ||
// 加载角色卡牌 | // === 加载角色卡牌 === | ||
function loadCharacterCards(characterName) { | function loadCharacterCards(characterName) { | ||
const listContainer = document.getElementById('available-cards-list'); | const listContainer = document.getElementById('available-cards-list'); | ||
listContainer.innerHTML = '<p style="color: white;">加载卡牌...</p>'; | listContainer.innerHTML = '<p style="color: white;">加载卡牌...</p>'; | ||
new mw.Api().get({ | new mw.Api().get({ | ||
action: 'parse', | action: 'parse', | ||
| 第313行: | 第313行: | ||
} | } | ||
// 解析角色卡牌 | // === 解析角色卡牌 === | ||
function parseCharacterCards(wikitext, characterName) { | function parseCharacterCards(wikitext, characterName) { | ||
const cards = []; | const cards = []; | ||
const patterns = { | const patterns = { | ||
selfAware: /\|自我意识技能\s*=\s*([^\n]+)/, | selfAware: /\|自我意识技能\s*=\s*([^\n]+)/, | ||
| 第334行: | 第333行: | ||
}; | }; | ||
const selfAwareMatch = wikitext.match(patterns.selfAware); | const selfAwareMatch = wikitext.match(patterns.selfAware); | ||
if (selfAwareMatch && selfAwareMatch[1].trim()) { | if (selfAwareMatch && selfAwareMatch[1].trim()) { | ||
| 第340行: | 第338行: | ||
} | } | ||
patterns.startCards.forEach(pattern => { | patterns.startCards.forEach(pattern => { | ||
const match = wikitext.match(pattern); | const match = wikitext.match(pattern); | ||
| 第348行: | 第345行: | ||
}); | }); | ||
patterns.uniqueCards.forEach(pattern => { | patterns.uniqueCards.forEach(pattern => { | ||
const match = wikitext.match(pattern); | const match = wikitext.match(pattern); | ||
| 第357行: | 第353行: | ||
state.availableCards = cards; | state.availableCards = cards; | ||
// 自动显示所有卡牌到卡组区域 | |||
displayCardsInDeck(cards, characterName); | |||
} | } | ||
// | // === 自动显示卡牌到卡组(修复点4) === | ||
function | function displayCardsInDeck(cards, characterName) { | ||
const | const deckCards = document.getElementById('deck-cards'); | ||
const plusSign = document.querySelector('#deck-area > span'); | |||
if (cards.length === 0) { | if (cards.length === 0) { | ||
deckCards.style.display = 'none'; | |||
if (plusSign) plusSign.style.display = 'block'; | |||
return; | return; | ||
} | } | ||
deckCards.style.display = 'flex'; | |||
if (plusSign) plusSign.style.display = 'none'; | |||
deckCards.innerHTML = '<p style="color: white;">加载中...</p>'; | |||
let loadedCount = 0; | let loadedCount = 0; | ||
const totalCards = cards.length; | const totalCards = cards.length; | ||
cards.forEach(card => { | // 先清空 | ||
if (loadedCount === 0) { | |||
deckCards.innerHTML = ''; | |||
} | |||
cards.forEach((card, index) => { | |||
const cardWrapper = document.createElement('div'); | const cardWrapper = document.createElement('div'); | ||
cardWrapper.style.position = 'relative'; | cardWrapper.style.position = 'relative'; | ||
new mw.Api().post({ | new mw.Api().post({ | ||
action: 'parse', | action: 'parse', | ||
| 第391行: | 第396行: | ||
cardWrapper.innerHTML = data.parse.text['*']; | cardWrapper.innerHTML = data.parse.text['*']; | ||
// | // 添加到状态 | ||
state.deckCards.push({ | |||
cardName: card.name, | |||
characterName: characterName, | |||
cardHtml: data.parse.text['*'] | |||
}); | |||
// 添加删除按钮 | |||
const removeBtn = document.createElement('div'); | |||
removeBtn.className = 'tb-remove-btn'; | |||
removeBtn.innerHTML = '×'; | |||
removeBtn.style.cssText = 'position: absolute; top: 5px; right: 5px; background: #ff4444; color: white; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 100; font-size: 20px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'; | |||
removeBtn.addEventListener('click', function(e) { | |||
e.stopPropagation(); | e.stopPropagation(); | ||
const cardIndex = state.deckCards.findIndex(c => c.cardName === card.name); | |||
if (cardIndex > -1) { | |||
state.deckCards.splice(cardIndex, 1); | |||
updateDeckDisplay(); | |||
} | |||
}); | }); | ||
cardWrapper.appendChild(removeBtn); | |||
deckCards.appendChild(cardWrapper); | |||
} | } | ||
loadedCount++; | |||
}).fail(function() { | }).fail(function() { | ||
cardWrapper.innerHTML = '<div style="color:red;padding:10px;">加载失败 | cardWrapper.innerHTML = '<div style="color:red;padding:10px;">加载失败</div>'; | ||
loadedCount++; | loadedCount++; | ||
deckCards.appendChild(cardWrapper); | |||
}); | }); | ||
}); | }); | ||
} | } | ||
// | // === 更新卡组显示 === | ||
function updateDeckDisplay() { | function updateDeckDisplay() { | ||
const deckCards = document.getElementById('deck-cards'); | const deckCards = document.getElementById('deck-cards'); | ||
const plusSign = | const plusSign = document.querySelector('#deck-area > span'); | ||
deckCards.innerHTML = ''; | deckCards.innerHTML = ''; | ||
| 第444行: | 第450行: | ||
cardDiv.innerHTML = card.cardHtml; | cardDiv.innerHTML = card.cardHtml; | ||
const removeBtn = document.createElement('div'); | const removeBtn = document.createElement('div'); | ||
removeBtn.className = 'tb-remove-btn'; | |||
removeBtn.innerHTML = '×'; | removeBtn.innerHTML = '×'; | ||
removeBtn.style.cssText = 'position: absolute; top: 5px; right: 5px; background: #ff4444; color: white; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 100; font-size: 20px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'; | removeBtn.style.cssText = 'position: absolute; top: 5px; right: 5px; background: #ff4444; color: white; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 100; font-size: 20px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'; | ||
| 第460行: | 第466行: | ||
} | } | ||
if (typeof mw !== 'undefined' && mw.hook) { | if (typeof mw !== 'undefined' && mw.hook) { | ||
mw.hook('wikipage.content').add(initTeamBuilder); | mw.hook('wikipage.content').add(initTeamBuilder); | ||
} | } | ||
})(); | })(); | ||
2025年10月18日 (六) 19:10的版本
(function() {
'use strict';
mw.loader.load(mw.util.getUrl('MediaWiki:TeamBuilder.css', { action: 'raw', ctype: 'text/css' }), 'text/css');
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTeamBuilder);
} else {
initTeamBuilder();
}
function initTeamBuilder() {
if (!document.getElementById('team-builder')) return;
const state = {
selectedCharacter: null,
selectedPartner: null,
selectedWeapon: null,
selectedArmor: null,
selectedRing: null,
deckCards: [],
availableCards: [],
currentEquipmentType: null,
equipmentCache: {} // 添加装备缓存
};
// === 模态框通用函数 ===
function showModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.style.display = 'flex';
modal.style.position = 'fixed';
modal.style.top = '0';
modal.style.left = '0';
modal.style.width = '100vw';
modal.style.height = '100vh';
modal.style.backgroundColor = 'rgba(0,0,0,0.8)';
modal.style.alignItems = 'center';
modal.style.justifyContent = 'center';
modal.style.zIndex = '10000';
document.body.style.overflow = 'hidden';
}
}
function hideModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
}
// === 事件绑定 ===
const characterSlot = document.getElementById('character-slot');
if (characterSlot) {
characterSlot.addEventListener('click', function() {
showModal('character-modal');
});
}
const partnerSlot = document.getElementById('partner-slot');
if (partnerSlot) {
partnerSlot.addEventListener('click', function() {
showModal('partner-modal');
});
}
const deckArea = document.getElementById('deck-area');
if (deckArea) {
deckArea.addEventListener('click', function(e) {
if (e.target === this || e.target.closest('.deck-area') === this) {
if (state.selectedCharacter) {
showModal('card-modal');
} else {
alert('请先选择战斗员');
}
}
});
}
document.querySelectorAll('.equip-slot').forEach(slot => {
slot.addEventListener('click', function() {
const type = this.getAttribute('data-type');
state.currentEquipmentType = type;
loadEquipmentList(type);
document.getElementById('equipment-modal-title').textContent = '选择' + type;
showModal('equipment-modal');
});
});
document.querySelectorAll('.tb-modal-close').forEach(btn => {
btn.addEventListener('click', function() {
this.closest('.tb-modal').style.display = 'none';
document.body.style.overflow = 'auto';
});
});
document.querySelectorAll('.tb-modal').forEach(modal => {
modal.addEventListener('click', function(e) {
if (e.target === this) {
this.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
});
// === 战斗员列表点击 ===
const characterList = document.getElementById('character-list');
if (characterList) {
characterList.addEventListener('click', function(e) {
const card = e.target.closest('[data-character-name]');
if (card) {
const name = card.getAttribute('data-character-name');
selectCharacter(name);
hideModal('character-modal');
}
});
}
// === 伙伴列表点击 ===
const partnerList = document.getElementById('partner-list');
if (partnerList) {
partnerList.addEventListener('click', function(e) {
const card = e.target.closest('[data-partner-name]');
if (card) {
const name = card.getAttribute('data-partner-name');
const id = card.getAttribute('data-partner-id');
selectPartner(name, id);
hideModal('partner-modal');
}
});
}
// === 选择战斗员 ===
function selectCharacter(name) {
state.selectedCharacter = name;
const slot = document.getElementById('character-slot');
const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/战斗员图鉴_' + encodeURIComponent(name) + '.png';
slot.innerHTML = `
<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
<img src="${imgPath}" style="width: 100%; height: 100%; object-fit: cover;"
onerror="this.src='${mw.config.get('wgScriptPath')}/resources/assets/file-type-icons/fileicon-image.png';" />
</div>
`;
// 清空卡组
state.deckCards = [];
state.availableCards = [];
updateDeckDisplay();
// 加载并自动显示卡牌
loadCharacterCards(name);
}
// === 选择伙伴(修复文件名) ===
function selectPartner(name, id) {
state.selectedPartner = { name, id };
const slot = document.getElementById('partner-slot');
// 修复:使用正确的文件名格式
const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/face_character_wide_' + encodeURIComponent(id) + '.png';
slot.innerHTML = `
<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
<img src="${imgPath}" style="width: 100%; height: 100%; object-fit: cover;"
onerror="this.src='${mw.config.get('wgScriptPath')}/resources/assets/file-type-icons/fileicon-image.png';" />
</div>
`;
}
// === 加载装备列表(添加缓存) ===
function loadEquipmentList(type) {
const listContainer = document.getElementById('equipment-list');
// 检查缓存
if (state.equipmentCache[type]) {
listContainer.innerHTML = '';
state.equipmentCache[type].forEach(item => {
listContainer.appendChild(item.cloneNode(true));
});
attachEquipmentClickHandlers();
return;
}
listContainer.innerHTML = '<p style="color: white;">加载中...</p>';
new mw.Api().post({
action: 'parse',
text: '{{#invoke:装备|generateCards}}',
contentmodel: 'wikitext',
prop: 'text',
disablelimitreport: 1,
disableeditsection: 1
}).done(function(data) {
if (data.parse && data.parse.text) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = data.parse.text['*'];
const allEquips = tempDiv.querySelectorAll('.equipment-wrapper');
const filteredEquips = [];
listContainer.innerHTML = '';
allEquips.forEach(function(equipWrapper) {
const equipType = equipWrapper.getAttribute('data-param3');
if (equipType === type) {
filteredEquips.push(equipWrapper.cloneNode(true));
listContainer.appendChild(equipWrapper.cloneNode(true));
}
});
// 缓存结果
state.equipmentCache[type] = filteredEquips;
if (listContainer.children.length === 0) {
listContainer.innerHTML = '<p style="color: white;">没有找到该类型装备</p>';
}
attachEquipmentClickHandlers();
}
}).fail(function() {
listContainer.innerHTML = '<p style="color: red;">加载失败</p>';
});
}
// === 装备点击处理 ===
function attachEquipmentClickHandlers() {
document.querySelectorAll('#equipment-list .equipment-card').forEach(card => {
card.style.cursor = 'pointer';
card.addEventListener('click', function() {
const name = this.getAttribute('data-equipment');
const wrapper = this.closest('.equipment-wrapper');
const rarity = wrapper ? wrapper.getAttribute('data-param1') : '蓝';
selectEquipment(state.currentEquipmentType, name, rarity);
hideModal('equipment-modal');
});
});
}
// === 选择装备(修复ID格式化) ===
function selectEquipment(type, name, rarity) {
const slotMap = {
'武器': 'weapon-slot',
'装甲': 'armor-slot',
'戒指': 'ring-slot'
};
const slotId = slotMap[type];
if (!slotId) return;
const slot = document.getElementById(slotId);
if (!slot) return;
if (type === '武器') state.selectedWeapon = name;
else if (type === '装甲') state.selectedArmor = name;
else if (type === '戒指') state.selectedRing = name;
// 从装备data中查找ID
new mw.Api().post({
action: 'scribunto-console',
question: `return require('Module:装备/data')['${name.replace(/'/g, "\\'")}'].id`,
clear: true
}).done(function(data) {
let equipId = '0000';
if (data && data.return) {
equipId = String(data.return).padStart(4, '0');
}
const imgPath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/relic_' + equipId + '.png';
const framePath = mw.config.get('wgScriptPath') + '/index.php?title=Special:Redirect/file/frame_item_rarity_' + encodeURIComponent(rarity) + '.png';
const textShadow = '-1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000';
slot.innerHTML = `
<div style="position:relative;width:124px;height:124px">
<div style="position:absolute;top:0px;left:0px">
<img src="${framePath}" style="width:124px;height:124px;"
onerror="this.style.display='none'" />
</div>
<div style="position:absolute;top:8px;left:8px;width:108px;height:108px;border:1px solid #fff;"></div>
<div style="position:absolute;top:6px;left:6px;">
<img src="${imgPath}" style="width:112px;height:112px;"
onerror="this.src='${mw.config.get('wgScriptPath')}/resources/assets/file-type-icons/fileicon-image.png';" />
</div>
<div style="position:absolute;bottom:2px;left:6px;right:6px;color:white;font-size:12px;text-shadow:${textShadow};overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${mw.html.escape(name)}</div>
</div>
`;
}).fail(function() {
// 备用方案:直接显示名称
slot.innerHTML = `
<div style="position:relative;width:124px;height:124px;display:flex;align-items:center;justify-content:center;background:#4a4a4a;border-radius:4px;">
<span style="color:white;font-size:12px;text-align:center;padding:5px;">${mw.html.escape(name)}</span>
</div>
`;
});
}
// === 加载角色卡牌 ===
function loadCharacterCards(characterName) {
const listContainer = document.getElementById('available-cards-list');
listContainer.innerHTML = '<p style="color: white;">加载卡牌...</p>';
new mw.Api().get({
action: 'parse',
page: characterName,
prop: 'wikitext'
}).done(function(data) {
if (data.parse && data.parse.wikitext) {
const wikitext = data.parse.wikitext['*'];
parseCharacterCards(wikitext, characterName);
}
}).fail(function() {
listContainer.innerHTML = '<p style="color: red;">加载失败</p>';
});
}
// === 解析角色卡牌 ===
function parseCharacterCards(wikitext, characterName) {
const cards = [];
const patterns = {
selfAware: /\|自我意识技能\s*=\s*([^\n]+)/,
startCards: [
/\|起始卡牌_1\s*=\s*([^\n]+)/,
/\|起始卡牌_2\s*=\s*([^\n]+)/,
/\|起始卡牌_3\s*=\s*([^\n]+)/,
/\|起始卡牌_4\s*=\s*([^\n]+)/
],
uniqueCards: [
/\|独特卡牌_1\s*=\s*([^\n]+)/,
/\|独特卡牌_2\s*=\s*([^\n]+)/,
/\|独特卡牌_3\s*=\s*([^\n]+)/,
/\|独特卡牌_4\s*=\s*([^\n]+)/
]
};
const selfAwareMatch = wikitext.match(patterns.selfAware);
if (selfAwareMatch && selfAwareMatch[1].trim()) {
cards.push({ type: 'self', name: selfAwareMatch[1].trim() });
}
patterns.startCards.forEach(pattern => {
const match = wikitext.match(pattern);
if (match && match[1].trim()) {
cards.push({ type: 'start', name: match[1].trim() });
}
});
patterns.uniqueCards.forEach(pattern => {
const match = wikitext.match(pattern);
if (match && match[1].trim()) {
cards.push({ type: 'unique', name: match[1].trim() });
}
});
state.availableCards = cards;
// 自动显示所有卡牌到卡组区域
displayCardsInDeck(cards, characterName);
}
// === 自动显示卡牌到卡组(修复点4) ===
function displayCardsInDeck(cards, characterName) {
const deckCards = document.getElementById('deck-cards');
const plusSign = document.querySelector('#deck-area > span');
if (cards.length === 0) {
deckCards.style.display = 'none';
if (plusSign) plusSign.style.display = 'block';
return;
}
deckCards.style.display = 'flex';
if (plusSign) plusSign.style.display = 'none';
deckCards.innerHTML = '<p style="color: white;">加载中...</p>';
let loadedCount = 0;
const totalCards = cards.length;
// 先清空
if (loadedCount === 0) {
deckCards.innerHTML = '';
}
cards.forEach((card, index) => {
const cardWrapper = document.createElement('div');
cardWrapper.style.position = 'relative';
new mw.Api().post({
action: 'parse',
text: `{{#invoke:卡牌|main|${characterName}|${card.name}}}`,
contentmodel: 'wikitext',
prop: 'text',
disablelimitreport: 1,
disableeditsection: 1
}).done(function(data) {
if (data.parse && data.parse.text) {
cardWrapper.innerHTML = data.parse.text['*'];
// 添加到状态
state.deckCards.push({
cardName: card.name,
characterName: characterName,
cardHtml: data.parse.text['*']
});
// 添加删除按钮
const removeBtn = document.createElement('div');
removeBtn.className = 'tb-remove-btn';
removeBtn.innerHTML = '×';
removeBtn.style.cssText = 'position: absolute; top: 5px; right: 5px; background: #ff4444; color: white; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 100; font-size: 20px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);';
removeBtn.addEventListener('click', function(e) {
e.stopPropagation();
const cardIndex = state.deckCards.findIndex(c => c.cardName === card.name);
if (cardIndex > -1) {
state.deckCards.splice(cardIndex, 1);
updateDeckDisplay();
}
});
cardWrapper.appendChild(removeBtn);
deckCards.appendChild(cardWrapper);
}
loadedCount++;
}).fail(function() {
cardWrapper.innerHTML = '<div style="color:red;padding:10px;">加载失败</div>';
loadedCount++;
deckCards.appendChild(cardWrapper);
});
});
}
// === 更新卡组显示 ===
function updateDeckDisplay() {
const deckCards = document.getElementById('deck-cards');
const plusSign = document.querySelector('#deck-area > span');
deckCards.innerHTML = '';
if (state.deckCards.length === 0) {
deckCards.style.display = 'none';
if (plusSign) plusSign.style.display = 'block';
return;
}
deckCards.style.display = 'flex';
if (plusSign) plusSign.style.display = 'none';
state.deckCards.forEach((card, index) => {
const cardDiv = document.createElement('div');
cardDiv.style.position = 'relative';
cardDiv.innerHTML = card.cardHtml;
const removeBtn = document.createElement('div');
removeBtn.className = 'tb-remove-btn';
removeBtn.innerHTML = '×';
removeBtn.style.cssText = 'position: absolute; top: 5px; right: 5px; background: #ff4444; color: white; border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 100; font-size: 20px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);';
removeBtn.addEventListener('click', function(e) {
e.stopPropagation();
state.deckCards.splice(index, 1);
updateDeckDisplay();
});
cardDiv.appendChild(removeBtn);
deckCards.appendChild(cardDiv);
});
}
}
if (typeof mw !== 'undefined' && mw.hook) {
mw.hook('wikipage.content').add(initTeamBuilder);
}
})();