卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
词典
小工具
配队模拟器
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
MediaWiki
查看“︁Card.js”︁的源代码
←
MediaWiki:Card.js
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。 如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
(function() { 'use strict'; // 加载CSS mw.loader.load('/index.php?title=Mediawiki:Card.css&action=raw&ctype=text/css', 'text/css'); console.log('Card Manager: 脚本已加载'); class CardManager { constructor() { console.log('Card Manager: 初始化中...'); this.currentFighter = ''; this.cards = {}; this.currentCard = null; this.fighters = ['示例战斗员1', '示例战斗员2']; this.defaultData = { order: [], ego: '' }; this.cardData = { name: '', displayname: '', art: '', group: '', rarity: '', god: '', ap: '', type: '攻击', dict: '', desc_global: '', sub: '', isinspiration: false, isgod_inspiration: false, inspirations: [], god_inspirations: { circen: [], diallos: [], nihilum: [], secred: [], vitor: [] } }; } async init() { console.log('Card Manager: 开始初始化'); await this.loadFighters(); this.render(); console.log('Card Manager: 初始化完成'); } async loadFighters() { try { const api = new mw.Api(); const response = await api.get({ action: 'query', list: 'categorymembers', cmtitle: 'Category:战斗员', cmlimit: 500 }); if (response.query && response.query.categorymembers) { this.fighters = response.query.categorymembers.map(page => page.title); console.log('Card Manager: 加载了', this.fighters.length, '个战斗员'); } } catch (error) { console.error('Card Manager: 加载战斗员列表失败:', error); } } render() { console.log('Card Manager: 开始渲染'); const contentDiv = document.getElementById('mw-content-text'); if (!contentDiv) { console.error('Card Manager: 找不到内容容器'); return; } contentDiv.innerHTML = ''; const container = document.createElement('div'); container.className = 'card-manager'; const leftPanel = document.createElement('div'); leftPanel.className = 'card-input-panel'; leftPanel.appendChild(this.renderFighterSelect()); leftPanel.appendChild(this.renderDefaultInfo()); leftPanel.appendChild(this.renderCardInput()); const middlePanel = document.createElement('div'); middlePanel.className = 'card-list-panel'; middlePanel.appendChild(this.renderCardLists()); const rightPanel = document.createElement('div'); rightPanel.className = 'card-preview-panel'; rightPanel.appendChild(this.renderPreview()); container.appendChild(leftPanel); container.appendChild(middlePanel); container.appendChild(rightPanel); contentDiv.appendChild(container); console.log('Card Manager: 渲染完成'); } renderFighterSelect() { const container = document.createElement('div'); container.className = 'form-group'; const label = document.createElement('div'); label.className = 'form-label'; label.textContent = '当前战斗员'; const selectContainer = document.createElement('div'); selectContainer.className = 'custom-select'; const display = document.createElement('div'); display.className = 'select-display'; display.textContent = this.currentFighter || '请选择战斗员...'; const arrow = document.createElement('span'); arrow.className = 'select-arrow'; arrow.textContent = '▼'; display.appendChild(arrow); const dropdown = document.createElement('div'); dropdown.className = 'select-dropdown'; this.fighters.forEach(fighter => { const option = document.createElement('div'); option.className = 'select-option'; option.textContent = fighter; if (fighter === this.currentFighter) { option.classList.add('selected'); } option.onclick = async () => { this.currentFighter = fighter; display.firstChild.textContent = fighter; dropdown.querySelectorAll('.select-option').forEach(o => o.classList.remove('selected')); option.classList.add('selected'); dropdown.classList.remove('active'); await this.loadFighterData(); }; dropdown.appendChild(option); }); display.onclick = (e) => { e.stopPropagation(); dropdown.classList.toggle('active'); }; document.addEventListener('click', () => { dropdown.classList.remove('active'); }); selectContainer.appendChild(display); selectContainer.appendChild(dropdown); container.appendChild(label); container.appendChild(selectContainer); return container; } renderDefaultInfo() { const container = document.createElement('div'); container.className = 'default-info-section'; const title = document.createElement('div'); title.className = 'section-title'; title.textContent = '默认信息'; container.appendChild(title); const orderGroup = document.createElement('div'); orderGroup.className = 'form-group'; const orderLabel = document.createElement('div'); orderLabel.className = 'form-label'; orderLabel.textContent = '卡牌顺序(card.order)'; const orderInput = document.createElement('div'); orderInput.className = 'custom-input'; orderInput.contentEditable = true; orderInput.id = 'order-input'; orderInput.textContent = this.defaultData.order.join(','); orderInput.addEventListener('input', () => { this.defaultData.order = orderInput.textContent.split(',').map(s => s.trim()).filter(s => s); this.updatePreview(); }); orderGroup.appendChild(orderLabel); orderGroup.appendChild(orderInput); container.appendChild(orderGroup); const egoGroup = document.createElement('div'); egoGroup.className = 'form-group'; const egoLabel = document.createElement('div'); egoLabel.className = 'form-label'; egoLabel.textContent = '属性(ego)'; const egoInput = document.createElement('div'); egoInput.className = 'custom-input'; egoInput.contentEditable = true; egoInput.id = 'ego-input'; egoInput.textContent = this.defaultData.ego; egoInput.addEventListener('input', () => { this.defaultData.ego = egoInput.textContent; this.updatePreview(); }); egoGroup.appendChild(egoLabel); egoGroup.appendChild(egoInput); container.appendChild(egoGroup); return container; } renderCardInput() { const container = document.createElement('div'); const title = document.createElement('div'); title.className = 'section-title'; title.textContent = '卡牌数据'; container.appendChild(title); container.appendChild(this.createInputField('卡牌名称', 'name')); container.appendChild(this.createInputField('显示名称(displayname)', 'displayname')); container.appendChild(this.createInputField('图片(art)', 'art')); container.appendChild(this.createGroupSelect()); container.appendChild(this.createRaritySelect()); container.appendChild(this.createGodSelect()); container.appendChild(this.createInputField('AP', 'ap')); container.appendChild(this.createTypeSelect()); container.appendChild(this.createInputField('机制(dict)', 'dict')); const descGroup = document.createElement('div'); descGroup.className = 'form-group'; const descLabel = document.createElement('div'); descLabel.className = 'form-label'; descLabel.textContent = '描述(desc_global)'; const formatButtons = this.createFormatButtons(); const descInput = document.createElement('div'); descInput.className = 'custom-textarea'; descInput.contentEditable = true; descInput.textContent = this.cardData.desc_global; descInput.id = 'desc-input'; descInput.addEventListener('input', () => { this.cardData.desc_global = descInput.textContent; this.updatePreview(); }); descGroup.appendChild(descLabel); descGroup.appendChild(formatButtons); descGroup.appendChild(descInput); container.appendChild(descGroup); container.appendChild(this.createInputField('衍生卡牌(sub)', 'sub')); container.appendChild(this.createCheckboxField('是否存在灵光一闪', 'isinspiration')); container.appendChild(this.createCheckboxField('是否存在神光一闪', 'isgod_inspiration')); // 添加灵光一闪变体显示 if (this.cardData.isinspiration && this.cardData.inspirations.length > 0) { container.appendChild(this.renderInspirations()); } // 添加神光一闪变体显示 if (this.cardData.isgod_inspiration) { container.appendChild(this.renderGodInspirations()); } const btnGroup = document.createElement('div'); btnGroup.className = 'btn-group'; const saveBtn = document.createElement('div'); saveBtn.className = 'btn btn-primary'; saveBtn.textContent = '保存卡牌'; saveBtn.onclick = () => this.saveCard(); const newBtn = document.createElement('div'); newBtn.className = 'btn btn-success'; newBtn.textContent = '新建卡牌'; newBtn.onclick = () => this.newCard(); btnGroup.appendChild(saveBtn); btnGroup.appendChild(newBtn); container.appendChild(btnGroup); return container; } renderInspirations() { const container = document.createElement('div'); container.className = 'variant-section'; const title = document.createElement('div'); title.className = 'section-title'; title.textContent = '灵光一闪变体'; container.appendChild(title); this.cardData.inspirations.forEach((inspiration, index) => { const variantBox = document.createElement('div'); variantBox.className = 'variant-box'; const variantTitle = document.createElement('div'); variantTitle.className = 'variant-title'; variantTitle.textContent = `变体 ${index + 1}`; variantBox.appendChild(variantTitle); const variantContent = document.createElement('div'); variantContent.className = 'variant-content'; if (inspiration.ap) { const apLine = document.createElement('div'); apLine.textContent = `AP: ${inspiration.ap}`; variantContent.appendChild(apLine); } if (inspiration.type) { const typeLine = document.createElement('div'); typeLine.textContent = `类型: ${inspiration.type}`; variantContent.appendChild(typeLine); } if (inspiration.dict) { const dictLine = document.createElement('div'); dictLine.textContent = `机制: ${inspiration.dict}`; variantContent.appendChild(dictLine); } if (inspiration.desc_global) { const descLine = document.createElement('div'); descLine.className = 'variant-desc'; descLine.textContent = `描述: ${inspiration.desc_global}`; variantContent.appendChild(descLine); } variantBox.appendChild(variantContent); container.appendChild(variantBox); }); return container; } renderGodInspirations() { const container = document.createElement('div'); container.className = 'variant-section'; const title = document.createElement('div'); title.className = 'section-title'; title.textContent = '神光一闪变体'; container.appendChild(title); const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor']; const godNames = { 'circen': '瑟肯', 'diallos': '迪亚罗斯', 'nihilum': '虚无', 'secred': '萨克雷德', 'vitor': '维托尔' }; gods.forEach(god => { const godInspirations = this.cardData.god_inspirations[god]; if (!godInspirations || godInspirations.length === 0) return; const godSection = document.createElement('div'); godSection.className = 'god-section'; const godTitle = document.createElement('div'); godTitle.className = 'god-title'; godTitle.textContent = godNames[god] || god; godSection.appendChild(godTitle); godInspirations.forEach((inspiration, index) => { const variantBox = document.createElement('div'); variantBox.className = 'variant-box small'; const variantTitle = document.createElement('div'); variantTitle.className = 'variant-title'; variantTitle.textContent = `${godNames[god]} 变体 ${index + 1}`; variantBox.appendChild(variantTitle); const variantContent = document.createElement('div'); variantContent.className = 'variant-content'; if (inspiration.ap) { const apLine = document.createElement('div'); apLine.textContent = `AP: ${inspiration.ap}`; variantContent.appendChild(apLine); } if (inspiration.type) { const typeLine = document.createElement('div'); typeLine.textContent = `类型: ${inspiration.type}`; variantContent.appendChild(typeLine); } if (inspiration.dict) { const dictLine = document.createElement('div'); dictLine.textContent = `机制: ${inspiration.dict}`; variantContent.appendChild(dictLine); } if (inspiration.desc_global) { const descLine = document.createElement('div'); descLine.className = 'variant-desc'; descLine.textContent = `描述: ${inspiration.desc_global}`; variantContent.appendChild(descLine); } variantBox.appendChild(variantContent); godSection.appendChild(variantBox); }); container.appendChild(godSection); }); return container; } createInputField(label, field) { const group = document.createElement('div'); group.className = 'form-group'; const labelDiv = document.createElement('div'); labelDiv.className = 'form-label'; labelDiv.textContent = label; const input = document.createElement('div'); input.className = 'custom-input'; input.contentEditable = true; input.dataset.field = field; input.textContent = this.cardData[field] || ''; input.addEventListener('input', () => { this.cardData[field] = input.textContent; this.updatePreview(); }); group.appendChild(labelDiv); group.appendChild(input); return group; } createCheckboxField(label, field) { const group = document.createElement('div'); group.className = 'form-group'; const labelDiv = document.createElement('div'); labelDiv.className = 'form-label'; labelDiv.textContent = label; const checkboxContainer = document.createElement('div'); checkboxContainer.className = 'checkbox-group'; const checkbox = document.createElement('div'); checkbox.className = 'custom-checkbox'; checkbox.dataset.field = field; if (this.cardData[field]) { checkbox.classList.add('checked'); } const statusLabel = document.createElement('div'); statusLabel.textContent = this.cardData[field] ? '是' : '否'; checkbox.onclick = () => { checkbox.classList.toggle('checked'); this.cardData[field] = checkbox.classList.contains('checked'); statusLabel.textContent = this.cardData[field] ? '是' : '否'; this.updatePreview(); }; checkboxContainer.appendChild(checkbox); checkboxContainer.appendChild(statusLabel); group.appendChild(labelDiv); group.appendChild(checkboxContainer); return group; } createFormatButtons() { const container = document.createElement('div'); container.className = 'format-buttons'; const buttons = [ { label: '蓝色文本', class: 'blue', template: '{{文本|蓝|%s}}' }, { label: '绿色文本', class: 'green', template: '{{文本|绿|%s}}' }, { label: '绿色描边', class: 'green', template: '{{描边|绿|%s}}' }, { label: '词典', class: '', template: '{{词典|%s}}' }, { label: '换行', class: '', template: '<br>' } ]; buttons.forEach(btn => { const button = document.createElement('div'); button.className = 'format-btn ' + btn.class; button.textContent = btn.label; button.onclick = () => { const textarea = document.getElementById('desc-input'); if (textarea) { this.insertTemplate(textarea, btn.template); } }; container.appendChild(button); }); return container; } insertTemplate(element, template) { element.focus(); const selection = window.getSelection(); let selectedText = ''; // 获取选中的文本 if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); // 确保选区在目标元素内 if (element.contains(range.commonAncestorContainer)) { selectedText = range.toString(); } } // 处理不同类型的模板 let insertText; if (template === '<br>') { insertText = '<br>'; document.execCommand('insertHTML', false, insertText); } else { // 如果有选中文本,包裹它;否则插入模板 insertText = template.replace('%s', selectedText || '选择文字'); document.execCommand('insertText', false, insertText); } // 更新数据 this.cardData.desc_global = element.textContent; this.updatePreview(); } createGroupSelect() { const group = document.createElement('div'); group.className = 'form-group'; const label = document.createElement('div'); label.className = 'form-label'; label.textContent = '卡组(group)'; const container = document.createElement('div'); container.className = 'group-options'; const groups = ['自我意识技能', '起始卡牌', '独特卡牌', '灵光一闪', '神光一闪']; groups.forEach(groupName => { const option = document.createElement('div'); option.className = 'group-option'; option.textContent = groupName; if (this.cardData.group === groupName) { option.classList.add('selected'); } option.onclick = () => { container.querySelectorAll('.group-option').forEach(o => o.classList.remove('selected')); option.classList.add('selected'); this.cardData.group = groupName; this.updatePreview(); }; container.appendChild(option); }); group.appendChild(label); group.appendChild(container); return group; } createRaritySelect() { const group = document.createElement('div'); group.className = 'form-group'; const label = document.createElement('div'); label.className = 'form-label'; label.textContent = '稀有度(rarity)'; const container = document.createElement('div'); container.className = 'rarity-options'; const rarities = ['白', '蓝', '橙', '彩']; rarities.forEach(rarity => { const option = document.createElement('div'); option.className = 'rarity-option'; option.textContent = rarity; if (this.cardData.rarity === rarity) { option.classList.add('selected'); } option.onclick = () => { container.querySelectorAll('.rarity-option').forEach(o => o.classList.remove('selected')); option.classList.add('selected'); this.cardData.rarity = rarity; this.updatePreview(); }; container.appendChild(option); }); group.appendChild(label); group.appendChild(container); return group; } createGodSelect() { const group = document.createElement('div'); group.className = 'form-group'; const label = document.createElement('div'); label.className = 'form-label'; label.textContent = '神明'; const container = document.createElement('div'); container.className = 'god-options'; const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor']; gods.forEach(god => { const option = document.createElement('div'); option.className = 'god-option'; option.textContent = god; if (this.cardData.god === god) { option.classList.add('selected'); } option.onclick = () => { container.querySelectorAll('.god-option').forEach(o => o.classList.remove('selected')); option.classList.add('selected'); this.cardData.god = god; this.updatePreview(); }; container.appendChild(option); }); group.appendChild(label); group.appendChild(container); return group; } createTypeSelect() { const group = document.createElement('div'); group.className = 'form-group'; const label = document.createElement('div'); label.className = 'form-label'; label.textContent = '卡牌类型(type)'; const container = document.createElement('div'); container.className = 'type-options'; const types = ['攻击', '技能', '强化']; types.forEach(type => { const option = document.createElement('div'); option.className = 'type-option'; option.textContent = type; if (this.cardData.type === type) { option.classList.add('selected'); } option.onclick = () => { container.querySelectorAll('.type-option').forEach(o => o.classList.remove('selected')); option.classList.add('selected'); this.cardData.type = type; this.updatePreview(); }; container.appendChild(option); }); group.appendChild(label); group.appendChild(container); return group; } renderCardLists() { const container = document.createElement('div'); const title = document.createElement('div'); title.className = 'panel-title'; title.textContent = '卡牌列表'; container.appendChild(title); const listContainer = document.createElement('div'); listContainer.className = 'list-container'; listContainer.id = 'card-list'; this.updateCardList(listContainer); container.appendChild(listContainer); return container; } updateCardList(container) { container.innerHTML = ''; const cardNames = Object.keys(this.cards); if (cardNames.length === 0) { const empty = document.createElement('div'); empty.className = 'list-empty'; empty.textContent = '暂无卡牌'; container.appendChild(empty); return; } cardNames.forEach(name => { const card = this.cards[name]; const item = document.createElement('div'); item.className = 'card-list-item'; const info = document.createElement('div'); const nameDiv = document.createElement('div'); nameDiv.className = 'card-list-item-name'; nameDiv.textContent = name; const detailDiv = document.createElement('div'); detailDiv.className = 'card-list-item-info'; detailDiv.textContent = `${card.type || '攻击'} | AP:${card.ap || 0} | ${card.rarity || ''}`; info.appendChild(nameDiv); info.appendChild(detailDiv); const deleteBtn = document.createElement('div'); deleteBtn.className = 'delete-btn'; deleteBtn.textContent = '删除'; deleteBtn.onclick = (e) => { e.stopPropagation(); if (confirm(`确定要删除卡牌"${name}"吗?`)) { delete this.cards[name]; this.updateCardList(container); this.updatePreview(); if (this.currentCard === name) { this.newCard(); } } }; item.appendChild(info); item.appendChild(deleteBtn); item.onclick = () => { this.loadCard(name); container.querySelectorAll('.card-list-item').forEach(i => i.classList.remove('active')); item.classList.add('active'); }; container.appendChild(item); }); } renderPreview() { const container = document.createElement('div'); const title = document.createElement('div'); title.className = 'panel-title'; title.textContent = 'Lua代码预览'; container.appendChild(title); const preview = document.createElement('div'); preview.className = 'preview-code'; preview.id = 'code-preview'; container.appendChild(preview); const copyBtn = document.createElement('div'); copyBtn.className = 'btn btn-primary'; copyBtn.textContent = '复制代码'; copyBtn.style.marginTop = '10px'; copyBtn.onclick = () => this.copyCode(); container.appendChild(copyBtn); this.updatePreview(); return container; } updatePreview() { const preview = document.getElementById('code-preview'); if (!preview) return; preview.textContent = this.generateLuaCode(); } generateLuaCode() { let code = 'local card = {}\n\n'; if (this.defaultData.order.length > 0) { code += `card.order = { "${this.defaultData.order.join(',')}" }\n\n`; } code += 'card.info = {\n'; if (this.defaultData.ego) { code += ` ego = "${this.defaultData.ego}",\n`; } code += '}\n\n'; Object.keys(this.cards).forEach(name => { const card = this.cards[name]; code += this.generateCardCode(name, card); }); code += 'return card'; return code; } generateCardCode(name, card) { let code = `card["${name}"] = {\n`; code += ' base = {\n'; if (card.displayname) code += ` displayname = "${card.displayname}",\n`; if (card.art) code += ` art = "${card.art}",\n`; if (card.group) code += ` group = "${card.group}",\n`; if (card.rarity) code += ` rarity = "${card.rarity}",\n`; if (card.ap) code += ` ap = ${isNaN(card.ap) ? `"${card.ap}"` : card.ap},\n`; if (card.type) code += ` type = "${card.type}",\n`; if (card.dict) code += ` dict = "${card.dict}",\n`; if (card.desc_global) { const desc = card.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"'); code += ` desc_global = "${desc}",\n`; } if (card.sub) code += ` sub = "${card.sub}",\n`; if (card.isinspiration) code += ` isinspiration = 1,\n`; if (card.isgod_inspiration) code += ` isgod_inspiration = 1,\n`; code += ' },\n'; code += '}\n\n'; return code; } saveCard() { if (!this.cardData.name) { alert('请输入卡牌名称!'); return; } this.cards[this.cardData.name] = JSON.parse(JSON.stringify(this.cardData)); this.currentCard = this.cardData.name; if (!this.defaultData.order.includes(this.cardData.name)) { this.defaultData.order.push(this.cardData.name); // 更新order输入框 const orderInput = document.getElementById('order-input'); if (orderInput) { orderInput.textContent = this.defaultData.order.join(','); } } const listContainer = document.getElementById('card-list'); if (listContainer) { this.updateCardList(listContainer); } this.updatePreview(); alert('卡牌保存成功!'); } newCard() { this.currentCard = null; this.cardData = { name: '', displayname: '', art: '', group: '', rarity: '', god: '', ap: '', type: '攻击', dict: '', desc_global: '', sub: '', isinspiration: false, isgod_inspiration: false, inspirations: [], god_inspirations: { circen: [], diallos: [], nihilum: [], secred: [], vitor: [] } }; this.render(); } loadCard(name) { if (!this.cards[name]) return; this.currentCard = name; this.cardData = JSON.parse(JSON.stringify(this.cards[name])); this.render(); } async loadFighterData() { if (!this.currentFighter) return; try { const api = new mw.Api(); const moduleName = `模块:卡牌/${this.currentFighter}`; const response = await api.get({ action: 'query', prop: 'revisions', titles: moduleName, rvprop: 'content', rvslots: 'main' }); const pages = response.query.pages; const page = Object.values(pages)[0]; if (page.revisions && page.revisions[0]) { const content = page.revisions[0].slots.main['*']; console.log('Card Manager: 加载了战斗员数据'); // 解析Lua代码 this.parseLuaContent(content); // 重新渲染界面 this.render(); alert(`成功加载战斗员"${this.currentFighter}"的数据!`); } else { console.log('Card Manager: 该战斗员暂无数据'); alert(`战斗员"${this.currentFighter}"暂无卡牌数据`); } } catch (error) { console.error('Card Manager: 加载战斗员数据失败:', error); alert('加载失败: ' + error.message); } } parseLuaContent(content) { // 重置数据 this.cards = {}; this.defaultData = { order: [], ego: '' }; try { // 解析 card.order const orderMatch = content.match(/card\.order\s*=\s*\{\s*"([^"]+)"\s*\}/); if (orderMatch) { this.defaultData.order = orderMatch[1].split(',').map(s => s.trim()).filter(s => s); } // 解析 card.info.ego const infoBlockMatch = content.match(/card\.info\s*=\s*\{([^}]*)\}/); if (infoBlockMatch) { const egoMatch = infoBlockMatch[1].match(/ego\s*=\s*"([^"]+)"/); if (egoMatch) { this.defaultData.ego = egoMatch[1]; } } // 使用更复杂的解析逻辑来处理嵌套结构 const lines = content.split('\n'); let currentCard = null; let currentSection = null; // 'base' 或 'var' let currentVarType = null; // 'inspiration' 或 'god_inspiration' let currentGodName = null; // circen, diallos 等 let braceStack = []; let sectionContent = []; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const trimmedLine = line.trim(); // 匹配卡牌定义开始 card["卡牌名"] = { const cardMatch = line.match(/^card\["([^"]+)"\]\s*=\s*\{/); if (cardMatch) { currentCard = cardMatch[1]; braceStack = ['{']; continue; } if (!currentCard) continue; // 匹配 base = { if (trimmedLine.match(/^base\s*=\s*\{/)) { currentSection = 'base'; sectionContent = []; continue; } // 匹配 var = { if (trimmedLine.match(/^var\s*=\s*\{/)) { currentSection = 'var'; sectionContent = []; continue; } // 如果在 base 部分 if (currentSection === 'base') { if (trimmedLine === '},') { // base 部分结束 this.parseCardBase(currentCard, sectionContent.join('\n')); currentSection = null; sectionContent = []; } else { sectionContent.push(line); } continue; } // 如果在 var 部分 if (currentSection === 'var') { // 匹配 inspiration = { if (trimmedLine.match(/^inspiration\s*=\s*\{/)) { currentVarType = 'inspiration'; sectionContent = []; continue; } // 匹配 god_inspiration = { if (trimmedLine.match(/^god_inspiration\s*=\s*\{/)) { currentVarType = 'god_inspiration'; sectionContent = []; continue; } // 在 inspiration 中 if (currentVarType === 'inspiration') { if (trimmedLine === '},') { // inspiration 部分结束 this.parseInspirations(currentCard, sectionContent.join('\n')); currentVarType = null; sectionContent = []; } else { sectionContent.push(line); } continue; } // 在 god_inspiration 中 if (currentVarType === 'god_inspiration') { // 匹配神明名称 circen = { const godMatch = trimmedLine.match(/^(circen|diallos|nihilum|secred|vitor)\s*=\s*\{/); if (godMatch) { currentGodName = godMatch[1]; sectionContent = []; continue; } if (currentGodName) { if (trimmedLine === '},') { // 某个神明的部分结束 this.parseGodInspirations(currentCard, currentGodName, sectionContent.join('\n')); currentGodName = null; sectionContent = []; } else { sectionContent.push(line); } continue; } // god_inspiration 整体结束 if (trimmedLine === '},') { currentVarType = null; } continue; } // var 部分结束 if (trimmedLine === '},') { currentSection = null; } } // 卡牌定义结束 if (trimmedLine === '}' && braceStack.length === 1) { currentCard = null; braceStack = []; } } console.log('Card Manager: 解析完成'); console.log('Card Manager: order =', this.defaultData.order); console.log('Card Manager: ego =', this.defaultData.ego); console.log('Card Manager: 卡牌数量 =', Object.keys(this.cards).length); console.log('Card Manager: 卡牌列表 =', Object.keys(this.cards)); } catch (error) { console.error('Card Manager: 解析Lua内容时出错:', error); alert('解析卡牌数据失败: ' + error.message); } } parseCardBase(cardName, baseContent) { const card = { name: cardName, displayname: this.extractFieldValue(baseContent, 'displayname'), art: this.extractFieldValue(baseContent, 'art'), group: this.extractFieldValue(baseContent, 'group'), rarity: this.extractFieldValue(baseContent, 'rarity'), god: this.extractFieldValue(baseContent, 'god'), ap: this.extractFieldValue(baseContent, 'ap'), type: this.extractFieldValue(baseContent, 'type') || '攻击', dict: this.extractFieldValue(baseContent, 'dict'), desc_global: this.extractFieldValue(baseContent, 'desc_global').replace(/<br>/g, '\n'), sub: this.extractFieldValue(baseContent, 'sub'), isinspiration: baseContent.includes('isinspiration = 1'), isgod_inspiration: baseContent.includes('isgod_inspiration = 1'), inspirations: [], god_inspirations: { circen: [], diallos: [], nihilum: [], secred: [], vitor: [] } }; this.cards[cardName] = card; } parseInspirations(cardName, content) { if (!this.cards[cardName]) return; // 分割成单个灵光一闪变体 const variants = this.splitVariants(content); variants.forEach(variantContent => { const variant = { ap: this.extractFieldValue(variantContent, 'ap'), type: this.extractFieldValue(variantContent, 'type'), dict: this.extractFieldValue(variantContent, 'dict'), desc_global: this.extractFieldValue(variantContent, 'desc_global').replace(/<br>/g, '\n') }; this.cards[cardName].inspirations.push(variant); }); console.log(`Card Manager: 卡牌 "${cardName}" 有 ${this.cards[cardName].inspirations.length} 个灵光一闪变体`); } parseGodInspirations(cardName, godName, content) { if (!this.cards[cardName]) return; // 分割成单个神光一闪变体 const variants = this.splitVariants(content); variants.forEach(variantContent => { const variant = { ap: this.extractFieldValue(variantContent, 'ap'), type: this.extractFieldValue(variantContent, 'type'), dict: this.extractFieldValue(variantContent, 'dict'), desc_global: this.extractFieldValue(variantContent, 'desc_global').replace(/<br>/g, '\n') }; this.cards[cardName].god_inspirations[godName].push(variant); }); console.log(`Card Manager: 卡牌 "${cardName}" 的神明 "${godName}" 有 ${this.cards[cardName].god_inspirations[godName].length} 个神光一闪变体`); } splitVariants(content) { const variants = []; const lines = content.split('\n'); let currentVariant = []; let braceCount = 0; for (let line of lines) { const trimmed = line.trim(); if (trimmed === '{') { braceCount++; if (braceCount === 1) { currentVariant = []; } } else if (trimmed === '},' || trimmed === '}') { braceCount--; if (braceCount === 0 && currentVariant.length > 0) { variants.push(currentVariant.join('\n')); currentVariant = []; } } else if (braceCount === 1) { currentVariant.push(line); } } return variants; } extractFieldValue(content, fieldName) { // 匹配 fieldName = "value" 格式 const pattern = new RegExp(`${fieldName}\\s*=\\s*"([^"]*)"`, 'i'); const match = content.match(pattern); if (match) { return match[1]; } // 匹配 fieldName = value 格式(数字) const numPattern = new RegExp(`${fieldName}\\s*=\\s*([\\d.]+)`, 'i'); const numMatch = content.match(numPattern); if (numMatch) { return numMatch[1]; } return ''; } copyCode() { const code = this.generateLuaCode(); const textarea = document.createElement('textarea'); textarea.value = code; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); alert('代码已复制到剪贴板!'); } } // 初始化函数 function initCardManager() { console.log('Card Manager: 准备启动'); const manager = new CardManager(); manager.init(); } // 在页面加载完成后启动 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { mw.loader.using(['mediawiki.api']).then(initCardManager); }); } else { mw.loader.using(['mediawiki.api']).then(initCardManager); } })();
该页面使用的模板:
模板:图标
(
查看源代码
)
模板:描边
(
查看源代码
)
模板:描边/颜色
(
查看源代码
)
模板:文本
(
查看源代码
)
模板:词典
(
查看源代码
)
模块:文本
(
查看源代码
)
模块:词典
(
查看源代码
)
模块:词典/data
(
查看源代码
)
返回
MediaWiki:Card.js
。