MediaWiki

Card.js:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
第4行: 第4行:
     // 加载CSS
     // 加载CSS
     mw.loader.load('/index.php?title=Mediawiki:Card.css&action=raw&ctype=text/css', 'text/css');
     mw.loader.load('/index.php?title=Mediawiki:Card.css&action=raw&ctype=text/css', 'text/css');
    // 调试日志
    console.log('Card Manager: 脚本已加载');


     // 卡牌管理器类
     // 卡牌管理器类
     class CardManager {
     class CardManager {
         constructor() {
         constructor() {
            console.log('Card Manager: 初始化中...');
             this.currentFighter = '';
             this.currentFighter = '';
             this.cards = {};
             this.cards = {};
             this.currentCard = null;
             this.currentCard = null;
             this.fighters = [];
             this.fighters = ['示例战斗员1', '示例战斗员2']; // 默认战斗员列表
              
              
            // 默认数据
             this.defaultData = {
             this.defaultData = {
                 order: [],
                 order: [],
第19行: 第22行:
             };
             };
              
              
            // 当前编辑的卡牌数据
             this.cardData = {
             this.cardData = {
                 name: '',
                 name: '',
第45行: 第47行:
         }
         }


        // 初始化
         async init() {
         async init() {
            console.log('Card Manager: 开始初始化');
             await this.loadFighters();
             await this.loadFighters();
             this.render();
             this.render();
             this.bindEvents();
             console.log('Card Manager: 初始化完成');
         }
         }


        // 加载战斗员列表
         async loadFighters() {
         async loadFighters() {
             try {
             try {
第63行: 第64行:
                 });
                 });
                  
                  
                 this.fighters = response.query.categorymembers.map(page => page.title);
                 if (response.query && response.query.categorymembers) {
                    this.fighters = response.query.categorymembers.map(page => page.title);
                    console.log('Card Manager: 加载了', this.fighters.length, '个战斗员');
                }
             } catch (error) {
             } catch (error) {
                 console.error('加载战斗员列表失败:', error);
                 console.error('Card Manager: 加载战斗员列表失败:', error);
                this.fighters = [];
             }
             }
         }
         }


        // 渲染主界面
         render() {
         render() {
             const container = this.createDiv('card-manager');
            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 = this.createDiv('card-input-panel');
             const leftPanel = document.createElement('div');
            leftPanel.className = 'card-input-panel';
             leftPanel.appendChild(this.renderFighterSelect());
             leftPanel.appendChild(this.renderFighterSelect());
             leftPanel.appendChild(this.renderDefaultInfo());
             leftPanel.appendChild(this.renderDefaultInfo());
第81行: 第98行:
              
              
             // 中间面板
             // 中间面板
             const middlePanel = this.createDiv('card-list-panel');
             const middlePanel = document.createElement('div');
            middlePanel.className = 'card-list-panel';
             middlePanel.appendChild(this.renderCardLists());
             middlePanel.appendChild(this.renderCardLists());
              
              
             // 右侧面板
             // 右侧面板
             const rightPanel = this.createDiv('card-preview-panel');
             const rightPanel = document.createElement('div');
            rightPanel.className = 'card-preview-panel';
             rightPanel.appendChild(this.renderPreview());
             rightPanel.appendChild(this.renderPreview());
              
              
第92行: 第111行:
             container.appendChild(rightPanel);
             container.appendChild(rightPanel);
              
              
             // 添加到页面
             contentDiv.appendChild(container);
            const content = document.getElementById('mw-content-text');
              
            if (content) {
             console.log('Card Manager: 渲染完成');
                content.innerHTML = '';
                content.appendChild(container);
             }
        }
 
        // 创建div元素
        createDiv(className, text = '') {
             const div = document.createElement('div');
            if (className) div.className = className;
            if (text) div.textContent = text;
            return div;
         }
         }


        // 渲染战斗员选择
         renderFighterSelect() {
         renderFighterSelect() {
             const container = this.createDiv('form-group');
             const container = document.createElement('div');
            container.className = 'form-group';
              
              
             const label = this.createDiv('form-label', '当前战斗员');
             const label = document.createElement('div');
             container.appendChild(label);
            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';
              
              
             const select = this.createCustomSelect(
             this.fighters.forEach(fighter => {
                 this.fighters,
                const option = document.createElement('div');
                 this.currentFighter,
                 option.className = 'select-option';
                 (value) => {
                option.textContent = fighter;
                     this.currentFighter = value;
                 if (fighter === this.currentFighter) {
                    option.classList.add('selected');
                }
                 option.onclick = () => {
                     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');
                     this.loadFighterData();
                     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);
              
              
            container.appendChild(select);
             return container;
             return container;
         }
         }


        // 渲染默认信息区
         renderDefaultInfo() {
         renderDefaultInfo() {
             const container = this.createDiv('default-info-section');
             const container = document.createElement('div');
             const title = this.createDiv('section-title', '默认信息');
            container.className = 'default-info-section';
           
             const title = document.createElement('div');
            title.className = 'section-title';
            title.textContent = '默认信息';
             container.appendChild(title);
             container.appendChild(title);
              
              
             // 卡牌顺序
             // 卡牌顺序
             const orderGroup = this.createDiv('form-group');
             const orderGroup = document.createElement('div');
             const orderLabel = this.createDiv('form-label', '卡牌顺序(card.order)');
            orderGroup.className = 'form-group';
             const orderInput = this.createInput('text', this.defaultData.order.join(','), (value) => {
           
                 this.defaultData.order = value.split(',').map(s => s.trim()).filter(s => s);
             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.textContent = this.defaultData.order.join(',');
            orderInput.addEventListener('input', () => {
                 this.defaultData.order = orderInput.textContent.split(',').map(s => s.trim()).filter(s => s);
                 this.updatePreview();
                 this.updatePreview();
             });
             });
           
             orderGroup.appendChild(orderLabel);
             orderGroup.appendChild(orderLabel);
             orderGroup.appendChild(orderInput);
             orderGroup.appendChild(orderInput);
第146行: 第206行:
              
              
             // 属性
             // 属性
             const egoGroup = this.createDiv('form-group');
             const egoGroup = document.createElement('div');
             const egoLabel = this.createDiv('form-label', '属性(ego)');
            egoGroup.className = 'form-group';
             const egoInput = this.createInput('text', this.defaultData.ego, (value) => {
           
                 this.defaultData.ego = value;
             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.textContent = this.defaultData.ego;
            egoInput.addEventListener('input', () => {
                 this.defaultData.ego = egoInput.textContent;
                 this.updatePreview();
                 this.updatePreview();
             });
             });
           
             egoGroup.appendChild(egoLabel);
             egoGroup.appendChild(egoLabel);
             egoGroup.appendChild(egoInput);
             egoGroup.appendChild(egoInput);
第159行: 第229行:
         }
         }


        // 渲染卡牌输入区
         renderCardInput() {
         renderCardInput() {
             const container = this.createDiv();
             const container = document.createElement('div');
             const title = this.createDiv('section-title', '卡牌数据');
           
             const title = document.createElement('div');
            title.className = 'section-title';
            title.textContent = '卡牌数据';
             container.appendChild(title);
             container.appendChild(title);
              
              
             // 卡牌名称
             // 卡牌名称
             container.appendChild(this.createFormGroup('卡牌名称',  
             container.appendChild(this.createInputField('卡牌名称', 'name'));
                this.createInput('text', this.cardData.name, (value) => {
                    this.cardData.name = value;
                    this.updatePreview();
                })
            ));
              
              
             // 显示名称
             // 显示名称
             container.appendChild(this.createFormGroup('显示名称(displayname)',  
             container.appendChild(this.createInputField('显示名称(displayname)', 'displayname'));
                this.createInput('text', this.cardData.displayname, (value) => {
                    this.cardData.displayname = value;
                    this.updatePreview();
                })
            ));
              
              
             // 图片
             // 图片
             container.appendChild(this.createFormGroup('图片(art)',  
             container.appendChild(this.createInputField('图片(art)', 'art'));
                this.createInput('text', this.cardData.art, (value) => {
                    this.cardData.art = value;
                    this.updatePreview();
                })
            ));
              
              
             // 卡组
             // 卡组选择
             container.appendChild(this.createFormGroup('卡组(group)',
             container.appendChild(this.createGroupSelect());
                this.createGroupSelect()
            ));
              
              
             // 稀有度
             // 稀有度
             container.appendChild(this.createFormGroup('稀有度(rarity)',
             container.appendChild(this.createRaritySelect());
                this.createRaritySelect()
            ));
              
              
             // 神明
             // 神明
             container.appendChild(this.createFormGroup('神明',
             container.appendChild(this.createGodSelect());
                this.createGodSelect()
            ));
              
              
             // AP
             // AP
             container.appendChild(this.createFormGroup('AP',  
             container.appendChild(this.createInputField('AP', 'ap'));
                this.createInput('text', this.cardData.ap, (value) => {
                    this.cardData.ap = value;
                    this.updatePreview();
                })
            ));
              
              
             // 卡牌类型
             // 卡牌类型
             container.appendChild(this.createFormGroup('卡牌类型(type)',
             container.appendChild(this.createTypeSelect());
                this.createTypeSelect()
            ));
              
              
             // 机制
             // 机制
             container.appendChild(this.createFormGroup('机制(dict)',  
             container.appendChild(this.createInputField('机制(dict)', 'dict'));
                this.createInput('text', this.cardData.dict, (value) => {
                    this.cardData.dict = value;
                    this.updatePreview();
                })
            ));
              
              
             // 描述
             // 描述
             const descGroup = this.createDiv('form-group');
             const descGroup = document.createElement('div');
             const descLabel = this.createDiv('form-label', '描述(desc_global)');
            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(descLabel);
             descGroup.appendChild(this.createFormatButtons());
             descGroup.appendChild(formatButtons);
             descGroup.appendChild(this.createTextarea(this.cardData.desc_global, (value) => {
             descGroup.appendChild(descInput);
                this.cardData.desc_global = value;
                this.updatePreview();
            }));
             container.appendChild(descGroup);
             container.appendChild(descGroup);
              
              
             // 衍生卡牌
             // 衍生卡牌
             container.appendChild(this.createFormGroup('衍生卡牌(sub)',  
             container.appendChild(this.createInputField('衍生卡牌(sub)', 'sub'));
                this.createInput('text', this.cardData.sub, (value) => {
                    this.cardData.sub = value;
                    this.updatePreview();
                })
            ));
              
              
             // 是否存在灵光一闪
             // 是否存在灵光一闪
             container.appendChild(this.createFormGroup('是否存在灵光一闪',  
             container.appendChild(this.createCheckboxField('是否存在灵光一闪', 'isinspiration'));
                this.createCheckbox(this.cardData.isinspiration, (checked) => {
                    this.cardData.isinspiration = checked;
                    this.updatePreview();
                })
            ));
              
              
             // 是否存在神光一闪
             // 是否存在神光一闪
             container.appendChild(this.createFormGroup('是否存在神光一闪',  
             container.appendChild(this.createCheckboxField('是否存在神光一闪', 'isgod_inspiration'));
                this.createCheckbox(this.cardData.isgod_inspiration, (checked) => {
                    this.cardData.isgod_inspiration = checked;
                    this.updatePreview();
                })
            ));
              
              
             // 按钮组
             // 按钮组
             const btnGroup = this.createDiv('btn-group');
             const btnGroup = document.createElement('div');
             const saveBtn = this.createDiv('btn btn-primary', '保存卡牌');
            btnGroup.className = 'btn-group';
           
             const saveBtn = document.createElement('div');
            saveBtn.className = 'btn btn-primary';
            saveBtn.textContent = '保存卡牌';
             saveBtn.onclick = () => this.saveCard();
             saveBtn.onclick = () => this.saveCard();
             const newBtn = this.createDiv('btn btn-success', '新建卡牌');
           
             const newBtn = document.createElement('div');
            newBtn.className = 'btn btn-success';
            newBtn.textContent = '新建卡牌';
             newBtn.onclick = () => this.newCard();
             newBtn.onclick = () => this.newCard();
           
             btnGroup.appendChild(saveBtn);
             btnGroup.appendChild(saveBtn);
             btnGroup.appendChild(newBtn);
             btnGroup.appendChild(newBtn);
第273行: 第319行:
         }
         }


         // 创建表单组
         createInputField(label, field) {
        createFormGroup(label, input) {
             const group = document.createElement('div');
             const group = this.createDiv('form-group');
            group.className = 'form-group';
             const labelDiv = this.createDiv('form-label', label);
           
             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.textContent = this.cardData[field] || '';
            input.addEventListener('input', () => {
                this.cardData[field] = input.textContent;
                this.updatePreview();
            });
           
             group.appendChild(labelDiv);
             group.appendChild(labelDiv);
             group.appendChild(input);
             group.appendChild(input);
           
             return group;
             return group;
         }
         }


         // 创建自定义下拉框
         createCheckboxField(label, field) {
        createCustomSelect(options, selected, onChange) {
             const group = document.createElement('div');
             const container = this.createDiv('custom-select');
            group.className = 'form-group';
              
              
             const display = this.createDiv('select-display', selected || '请选择...');
             const labelDiv = document.createElement('div');
             const arrow = this.createDiv('select-arrow', '▼');
            labelDiv.className = 'form-label';
             display.appendChild(arrow);
            labelDiv.textContent = label;
           
             const checkboxContainer = document.createElement('div');
             checkboxContainer.className = 'checkbox-group';
              
              
             const dropdown = this.createDiv('select-dropdown');
             const checkbox = document.createElement('div');
            checkbox.className = 'custom-checkbox';
            if (this.cardData[field]) {
                checkbox.classList.add('checked');
            }
              
              
             options.forEach(option => {
             const statusLabel = document.createElement('div');
                const optionDiv = this.createDiv('select-option', option);
            statusLabel.textContent = this.cardData[field] ? '' : '';
                if (option === selected) {
                    optionDiv.classList.add('selected');
                }
                optionDiv.onclick = () => {
                    display.childNodes[0].textContent = option;
                    dropdown.querySelectorAll('.select-option').forEach(o => o.classList.remove('selected'));
                    optionDiv.classList.add('selected');
                    dropdown.classList.remove('active');
                    onChange(option);
                };
                dropdown.appendChild(optionDiv);
            });
              
              
             display.onclick = () => {
             checkbox.onclick = () => {
                 dropdown.classList.toggle('active');
                 checkbox.classList.toggle('checked');
                this.cardData[field] = checkbox.classList.contains('checked');
                statusLabel.textContent = this.cardData[field] ? '是' : '否';
                this.updatePreview();
             };
             };
              
              
             // 点击外部关闭
             checkboxContainer.appendChild(checkbox);
            document.addEventListener('click', (e) => {
            checkboxContainer.appendChild(statusLabel);
                if (!container.contains(e.target)) {
                    dropdown.classList.remove('active');
                }
            });
              
              
             container.appendChild(display);
             group.appendChild(labelDiv);
             container.appendChild(dropdown);
             group.appendChild(checkboxContainer);
              
              
             return container;
             return group;
        }
 
        // 创建输入框
        createInput(type, value, onChange) {
            const input = this.createDiv('custom-input');
            input.contentEditable = true;
            input.textContent = value;
            input.oninput = () => onChange(input.textContent);
            return input;
        }
 
        // 创建文本域
        createTextarea(value, onChange) {
            const textarea = this.createDiv('custom-textarea');
            textarea.contentEditable = true;
            textarea.innerHTML = value.replace(/<br>/g, '\n');
            textarea.oninput = () => onChange(textarea.textContent);
            return textarea;
         }
         }


        // 创建格式化按钮
         createFormatButtons() {
         createFormatButtons() {
             const container = this.createDiv('format-buttons');
             const container = document.createElement('div');
            container.className = 'format-buttons';
              
              
             const buttons = [
             const buttons = [
第355行: 第391行:
              
              
             buttons.forEach(btn => {
             buttons.forEach(btn => {
                 const button = this.createDiv(`format-btn ${btn.class}`, btn.label);
                 const button = document.createElement('div');
                button.className = 'format-btn ' + btn.class;
                button.textContent = btn.label;
                 button.onclick = () => {
                 button.onclick = () => {
                     const textarea = button.parentElement.nextElementSibling;
                     const textarea = document.getElementById('desc-input');
                     this.insertTemplate(textarea, btn.template);
                     if (textarea) {
                        this.insertTemplate(textarea, btn.template);
                    }
                 };
                 };
                 container.appendChild(button);
                 container.appendChild(button);
第366行: 第406行:
         }
         }


        // 插入模板
         insertTemplate(textarea, template) {
         insertTemplate(textarea, template) {
             const selection = window.getSelection();
             const selection = window.getSelection();
第372行: 第411行:
              
              
             if (template === '<br>') {
             if (template === '<br>') {
                 const text = textarea.textContent;
                 document.execCommand('insertHTML', false, '<br>');
                const pos = this.getCaretPosition(textarea);
                textarea.textContent = text.slice(0, pos) + '\n' + text.slice(pos);
             } else {
             } else {
                 const result = template.replace('%s', selectedText || '选择文字');
                 const result = template.replace('%s', selectedText || '选择文字');
                 if (selectedText) {
                 document.execCommand('insertText', false, result);
                    document.execCommand('insertText', false, result);
                } else {
                    const text = textarea.textContent;
                    const pos = this.getCaretPosition(textarea);
                    textarea.textContent = text.slice(0, pos) + result + text.slice(pos);
                }
             }
             }
              
              
             textarea.dispatchEvent(new Event('input'));
             this.cardData.desc_global = textarea.textContent;
            this.updatePreview();
         }
         }


         // 获取光标位置
         createGroupSelect() {
        getCaretPosition(element) {
             const group = document.createElement('div');
             const selection = window.getSelection();
             group.className = 'form-group';
             if (selection.rangeCount > 0) {
                const range = selection.getRangeAt(0);
                const preCaretRange = range.cloneRange();
                preCaretRange.selectNodeContents(element);
                preCaretRange.setEnd(range.endContainer, range.endOffset);
                return preCaretRange.toString().length;
            }
            return 0;
        }
 
        // 创建复选框
        createCheckbox(checked, onChange) {
            const container = this.createDiv('checkbox-group');
            const checkbox = this.createDiv('custom-checkbox');
            if (checked) checkbox.classList.add('checked');
              
              
             const label = this.createDiv('', '');
             const label = document.createElement('div');
            label.className = 'form-label';
            label.textContent = '卡组(group)';
              
              
             checkbox.onclick = () => {
             const container = document.createElement('div');
                checkbox.classList.toggle('checked');
            container.className = 'group-options';
                const isChecked = checkbox.classList.contains('checked');
                label.textContent = isChecked ? '是' : '否';
                onChange(isChecked);
            };
              
              
            container.appendChild(checkbox);
            container.appendChild(label);
            return container;
        }
        // 创建卡组选择
        createGroupSelect() {
            const container = this.createDiv('group-options');
             const groups = ['自我意识技能', '起始卡牌', '独特卡牌', '灵光一闪', '神光一闪'];
             const groups = ['自我意识技能', '起始卡牌', '独特卡牌', '灵光一闪', '神光一闪'];
              
              
             groups.forEach(group => {
             groups.forEach(groupName => {
                 const option = this.createDiv('group-option', group);
                 const option = document.createElement('div');
                 if (this.cardData.group === group) {
                option.className = 'group-option';
                option.textContent = groupName;
                 if (this.cardData.group === groupName) {
                     option.classList.add('selected');
                     option.classList.add('selected');
                 }
                 }
第435行: 第444行:
                     container.querySelectorAll('.group-option').forEach(o => o.classList.remove('selected'));
                     container.querySelectorAll('.group-option').forEach(o => o.classList.remove('selected'));
                     option.classList.add('selected');
                     option.classList.add('selected');
                     this.cardData.group = group;
                     this.cardData.group = groupName;
                     this.updatePreview();
                     this.updatePreview();
                 };
                 };
第441行: 第450行:
             });
             });
              
              
             return container;
            group.appendChild(label);
            group.appendChild(container);
           
             return group;
         }
         }


        // 创建稀有度选择
         createRaritySelect() {
         createRaritySelect() {
             const container = this.createDiv('rarity-options');
            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 = ['白', '蓝', '橙', '彩'];
             const rarities = ['白', '蓝', '橙', '彩'];
              
              
             rarities.forEach(rarity => {
             rarities.forEach(rarity => {
                 const option = this.createDiv('rarity-option', rarity);
                 const option = document.createElement('div');
                option.className = 'rarity-option';
                option.textContent = rarity;
                 if (this.cardData.rarity === rarity) {
                 if (this.cardData.rarity === rarity) {
                     option.classList.add('selected');
                     option.classList.add('selected');
第463行: 第485行:
             });
             });
              
              
             return container;
            group.appendChild(label);
            group.appendChild(container);
           
             return group;
         }
         }


        // 创建神明选择
         createGodSelect() {
         createGodSelect() {
             const container = this.createDiv('god-options');
            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'];
             const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
              
              
             gods.forEach(god => {
             gods.forEach(god => {
                 const option = this.createDiv('god-option', god);
                 const option = document.createElement('div');
                option.className = 'god-option';
                option.textContent = god;
                 if (this.cardData.god === god) {
                 if (this.cardData.god === god) {
                     option.classList.add('selected');
                     option.classList.add('selected');
第485行: 第520行:
             });
             });
              
              
             return container;
            group.appendChild(label);
            group.appendChild(container);
           
             return group;
         }
         }


        // 创建类型选择
         createTypeSelect() {
         createTypeSelect() {
             const container = this.createDiv('type-options');
            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 = ['攻击', '技能', '强化'];
             const types = ['攻击', '技能', '强化'];
              
              
             types.forEach(type => {
             types.forEach(type => {
                 const option = this.createDiv('type-option', type);
                 const option = document.createElement('div');
                option.className = 'type-option';
                option.textContent = type;
                 if (this.cardData.type === type) {
                 if (this.cardData.type === type) {
                     option.classList.add('selected');
                     option.classList.add('selected');
第507行: 第555行:
             });
             });
              
              
             return container;
            group.appendChild(label);
            group.appendChild(container);
           
             return group;
         }
         }


        // 渲染卡牌列表
         renderCardLists() {
         renderCardLists() {
             const container = this.createDiv();
             const container = document.createElement('div');
              
              
            // 卡牌列表
             const title = document.createElement('div');
             const cardListTitle = this.createDiv('panel-title', '卡牌列表');
            title.className = 'panel-title';
             container.appendChild(cardListTitle);
            title.textContent = '卡牌列表';
             container.appendChild(title);
              
              
             const cardListContainer = this.createDiv('list-container');
             const listContainer = document.createElement('div');
             cardListContainer.id = 'card-list';
            listContainer.className = 'list-container';
             this.updateCardList(cardListContainer);
             listContainer.id = 'card-list';
             container.appendChild(cardListContainer);
           
             this.updateCardList(listContainer);
           
             container.appendChild(listContainer);
              
              
             return container;
             return container;
         }
         }


        // 更新卡牌列表
         updateCardList(container) {
         updateCardList(container) {
             container.innerHTML = '';
             container.innerHTML = '';
              
              
             if (Object.keys(this.cards).length === 0) {
             const cardNames = Object.keys(this.cards);
                 container.appendChild(this.createDiv('list-empty', '暂无卡牌'));
           
            if (cardNames.length === 0) {
                 const empty = document.createElement('div');
                empty.className = 'list-empty';
                empty.textContent = '暂无卡牌';
                container.appendChild(empty);
                 return;
                 return;
             }
             }
              
              
             Object.keys(this.cards).forEach(name => {
             cardNames.forEach(name => {
                 const card = this.cards[name];
                 const card = this.cards[name];
                 const item = this.createDiv('card-list-item');
                 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 || ''}`;
                  
                  
                const info = this.createDiv();
                const nameDiv = this.createDiv('card-list-item-name', name);
                const detailDiv = this.createDiv('card-list-item-info',
                    `${card.type || '攻击'} | AP:${card.ap || 0} | ${card.rarity || ''}`
                );
                 info.appendChild(nameDiv);
                 info.appendChild(nameDiv);
                 info.appendChild(detailDiv);
                 info.appendChild(detailDiv);
                  
                  
                 const deleteBtn = this.createDiv('delete-btn', '删除');
                 const deleteBtn = document.createElement('div');
                deleteBtn.className = 'delete-btn';
                deleteBtn.textContent = '删除';
                 deleteBtn.onclick = (e) => {
                 deleteBtn.onclick = (e) => {
                     e.stopPropagation();
                     e.stopPropagation();
第554行: 第620行:
                         this.updateCardList(container);
                         this.updateCardList(container);
                         this.updatePreview();
                         this.updatePreview();
                       
                        // 如果删除的是当前编辑的卡牌,清空表单
                         if (this.currentCard === name) {
                         if (this.currentCard === name) {
                             this.newCard();
                             this.newCard();
第575行: 第639行:
         }
         }


        // 渲染预览
         renderPreview() {
         renderPreview() {
             const container = this.createDiv();
             const container = document.createElement('div');
             const title = this.createDiv('panel-title', 'Lua代码预览');
           
             const title = document.createElement('div');
            title.className = 'panel-title';
            title.textContent = 'Lua代码预览';
             container.appendChild(title);
             container.appendChild(title);
              
              
             const preview = this.createDiv('preview-code');
             const preview = document.createElement('div');
            preview.className = 'preview-code';
             preview.id = 'code-preview';
             preview.id = 'code-preview';
             container.appendChild(preview);
             container.appendChild(preview);
              
              
             this.updatePreview();
             const copyBtn = document.createElement('div');
              
             copyBtn.className = 'btn btn-primary';
            // 添加复制按钮
            copyBtn.textContent = '复制代码';
            const copyBtn = this.createDiv('btn btn-primary', '复制代码');
             copyBtn.style.marginTop = '10px';
             copyBtn.style.marginTop = '10px';
             copyBtn.onclick = () => this.copyCode();
             copyBtn.onclick = () => this.copyCode();
             container.appendChild(copyBtn);
             container.appendChild(copyBtn);
           
            this.updatePreview();
              
              
             return container;
             return container;
         }
         }


        // 更新预览
         updatePreview() {
         updatePreview() {
             const preview = document.getElementById('code-preview');
             const preview = document.getElementById('code-preview');
第604行: 第671行:
         }
         }


        // 生成Lua代码
         generateLuaCode() {
         generateLuaCode() {
             let code = 'local card = {}\n\n';
             let code = 'local card = {}\n\n';
              
              
            // 生成order
             if (this.defaultData.order.length > 0) {
             if (this.defaultData.order.length > 0) {
                 code += `card.order = { "${this.defaultData.order.join(',')}" }\n\n`;
                 code += `card.order = { "${this.defaultData.order.join(',')}" }\n\n`;
             }
             }
              
              
            // 生成info
             code += 'card.info = {\n';
             code += 'card.info = {\n';
             if (this.defaultData.ego) {
             if (this.defaultData.ego) {
第620行: 第684行:
             code += '}\n\n';
             code += '}\n\n';
              
              
            // 生成各个卡牌
             Object.keys(this.cards).forEach(name => {
             Object.keys(this.cards).forEach(name => {
                 const card = this.cards[name];
                 const card = this.cards[name];
第631行: 第694行:
         }
         }


        // 生成单个卡牌代码
         generateCardCode(name, card) {
         generateCardCode(name, card) {
             let code = `card["${name}"] = {\n`;
             let code = `card["${name}"] = {\n`;
             code += '    base = {\n';
             code += '    base = {\n';
              
              
            // 基础属性
             if (card.displayname) code += `        displayname = "${card.displayname}",\n`;
             if (card.displayname) {
             if (card.art) code += `        art = "${card.art}",\n`;
                code += `        displayname = "${card.displayname}",\n`;
             if (card.group) code += `        group = "${card.group}",\n`;
            }
             if (card.rarity) code += `        rarity = "${card.rarity}",\n`;
             if (card.art) {
             if (card.ap) code += `        ap = ${isNaN(card.ap) ? `"${card.ap}"` : card.ap},\n`;
                code += `        art = "${card.art}",\n`;
             if (card.type) code += `        type = "${card.type}",\n`;
            }
             if (card.dict) code += `        dict = "${card.dict}",\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) {
             if (card.desc_global) {
                 const desc = card.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                 const desc = card.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                 code += `        desc_global = "${desc}",\n`;
                 code += `        desc_global = "${desc}",\n`;
             }
             }
             if (card.sub) {
             if (card.sub) code += `        sub = "${card.sub}",\n`;
                code += `        sub = "${card.sub}",\n`;
             if (card.isinspiration) code += `        isinspiration = 1,\n`;
            }
             if (card.isgod_inspiration) code += `        isgod_inspiration = 1,\n`;
             if (card.isinspiration) {
                code += `        isinspiration = 1,\n`;
            }
             if (card.isgod_inspiration) {
                code += `        isgod_inspiration = 1,\n`;
            }
              
              
             code += '    },\n';
             code += '    },\n';
           
            // 变体数据
            if (card.isinspiration || card.isgod_inspiration) {
                code += '    var = {\n';
               
                // 灵光一闪
                if (card.isinspiration && card.inspirations && card.inspirations.length > 0) {
                    code += '        inspiration = {\n';
                    card.inspirations.forEach(insp => {
                        code += '            {\n';
                        if (insp.ap !== undefined) {
                            code += `                ap = ${isNaN(insp.ap) ? `"${insp.ap}"` : insp.ap},\n`;
                        }
                        if (insp.type) {
                            code += `                type = "${insp.type}",\n`;
                        }
                        if (insp.desc_global) {
                            const desc = insp.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                            code += `                desc_global = "${desc}",\n`;
                        }
                        code += '            },\n';
                    });
                    code += '        },\n';
                }
               
                // 神光一闪
                if (card.isgod_inspiration && card.god_inspirations) {
                    code += '        god_inspiration = {\n';
                    const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
                    gods.forEach(god => {
                        if (card.god_inspirations[god] && card.god_inspirations[god].length > 0) {
                            code += `            ${god} = {\n`;
                            card.god_inspirations[god].forEach(insp => {
                                code += '                {\n';
                                if (insp.ap !== undefined) {
                                    code += `                    ap = ${isNaN(insp.ap) ? `"${insp.ap}"` : insp.ap},\n`;
                                }
                                if (insp.type) {
                                    code += `                    type = "${insp.type}",\n`;
                                }
                                if (insp.desc_global) {
                                    const desc = insp.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                                    code += `                    desc_global = "${desc}",\n`;
                                }
                                code += '                },\n';
                            });
                            code += '            },\n';
                        }
                    });
                    code += '        },\n';
                }
               
                code += '    },\n';
            }
           
             code += '}\n\n';
             code += '}\n\n';
              
              
第733行: 第719行:
         }
         }


        // 保存卡牌
         saveCard() {
         saveCard() {
             if (!this.cardData.name) {
             if (!this.cardData.name) {
第740行: 第725行:
             }
             }
              
              
             // 克隆当前卡牌数据
             this.cards[this.cardData.name] = JSON.parse(JSON.stringify(this.cardData));
            const cardToSave = JSON.parse(JSON.stringify(this.cardData));
            this.currentCard = this.cardData.name;
              
              
            // 保存到cards对象
             if (!this.defaultData.order.includes(this.cardData.name)) {
            this.cards[cardToSave.name] = cardToSave;
                 this.defaultData.order.push(this.cardData.name);
            this.currentCard = cardToSave.name;
           
            // 更新order
             if (!this.defaultData.order.includes(cardToSave.name)) {
                 this.defaultData.order.push(cardToSave.name);
             }
             }
              
              
            // 更新列表和预览
             const listContainer = document.getElementById('card-list');
             const listContainer = document.getElementById('card-list');
             if (listContainer) {
             if (listContainer) {
第762行: 第741行:
         }
         }


        // 新建卡牌
         newCard() {
         newCard() {
             this.currentCard = null;
             this.currentCard = null;
第789行: 第767行:
             };
             };
              
              
             // 重新渲染输入区
             this.render();
            const leftPanel = document.querySelector('.card-input-panel');
            if (leftPanel) {
                leftPanel.innerHTML = '';
                leftPanel.appendChild(this.renderFighterSelect());
                leftPanel.appendChild(this.renderDefaultInfo());
                leftPanel.appendChild(this.renderCardInput());
            }
           
            // 清除列表选中状态
            const listContainer = document.getElementById('card-list');
            if (listContainer) {
                listContainer.querySelectorAll('.card-list-item').forEach(i => i.classList.remove('active'));
            }
         }
         }


        // 加载卡牌
         loadCard(name) {
         loadCard(name) {
             if (!this.cards[name]) return;
             if (!this.cards[name]) return;
第811行: 第775行:
             this.currentCard = name;
             this.currentCard = name;
             this.cardData = JSON.parse(JSON.stringify(this.cards[name]));
             this.cardData = JSON.parse(JSON.stringify(this.cards[name]));
              
             this.render();
            // 重新渲染输入区
            const leftPanel = document.querySelector('.card-input-panel');
            if (leftPanel) {
                leftPanel.innerHTML = '';
                leftPanel.appendChild(this.renderFighterSelect());
                leftPanel.appendChild(this.renderDefaultInfo());
                leftPanel.appendChild(this.renderCardInput());
            }
         }
         }


        // 加载战斗员数据
         async loadFighterData() {
         async loadFighterData() {
             if (!this.currentFighter) return;
             if (!this.currentFighter) return;
第843行: 第798行:
                 if (page.revisions) {
                 if (page.revisions) {
                     const content = page.revisions[0].slots.main['*'];
                     const content = page.revisions[0].slots.main['*'];
                     this.parseLuaCode(content);
                     console.log('Card Manager: 加载了战斗员数据');
                   
                    // 重新渲染
                    this.render();
                 }
                 }
             } catch (error) {
             } catch (error) {
                 console.error('加载战斗员数据失败:', error);
                 console.error('Card Manager: 加载战斗员数据失败:', error);
             }
             }
         }
         }


        // 解析Lua代码(简化版)
        parseLuaCode(code) {
            // 这里应该实现完整的Lua代码解析
            // 由于复杂度较高,这里只做基本的解析示例
           
            // 解析order
            const orderMatch = code.match(/card\.order\s*=\s*{\s*"([^"]*)"\s*}/);
            if (orderMatch) {
                this.defaultData.order = orderMatch[1].split(',').map(s => s.trim());
            }
           
            // 解析ego
            const egoMatch = code.match(/ego\s*=\s*"([^"]*)"/);
            if (egoMatch) {
                this.defaultData.ego = egoMatch[1];
            }
           
            // 这里应该继续解析各个卡牌的数据
            // 由于Lua语法复杂,建议使用专门的Lua解析器
        }
        // 保存到Mediawiki
        async saveToMediawiki() {
            if (!this.currentFighter) {
                alert('请先选择战斗员!');
                return;
            }
           
            const code = this.generateLuaCode();
            const moduleName = `模块:卡牌/${this.currentFighter}`;
           
            try {
                const api = new mw.Api();
                await api.postWithToken('csrf', {
                    action: 'edit',
                    title: moduleName,
                    text: code,
                    summary: '通过卡牌管理器更新',
                    contentmodel: 'Scribunto'
                });
               
                alert('保存成功!');
            } catch (error) {
                console.error('保存失败:', error);
                alert('保存失败:' + error);
            }
        }
        // 复制代码
         copyCode() {
         copyCode() {
             const code = this.generateLuaCode();
             const code = this.generateLuaCode();
           
            // 创建临时文本域
             const textarea = document.createElement('textarea');
             const textarea = document.createElement('textarea');
             textarea.value = code;
             textarea.value = code;
第911行: 第812行:
             textarea.style.opacity = '0';
             textarea.style.opacity = '0';
             document.body.appendChild(textarea);
             document.body.appendChild(textarea);
           
             textarea.select();
             textarea.select();
             document.execCommand('copy');
             document.execCommand('copy');
             document.body.removeChild(textarea);
             document.body.removeChild(textarea);
           
             alert('代码已复制到剪贴板!');
             alert('代码已复制到剪贴板!');
         }
         }
    }


        // 绑定事件
    // 初始化函数
         bindEvents() {
    function initCardManager() {
            // 可以在这里添加全局事件监听
         console.log('Card Manager: 准备启动');
         }
        const manager = new CardManager();
         manager.init();
     }
     }


     // 等待页面加载完成
     // 在页面加载完成后启动
     if (mw.config.get('wgPageName') === 'Special:Card' ||
     if (document.readyState === 'loading') {
         window.location.search.includes('cardmanager=1')) {
         document.addEventListener('DOMContentLoaded', () => {
        mw.loader.using(['mediawiki.api']).then(() => {
            mw.loader.using(['mediawiki.api']).then(initCardManager);
            const manager = new CardManager();
            manager.init();
         });
         });
    } else {
        mw.loader.using(['mediawiki.api']).then(initCardManager);
     }
     }
    // 添加导航链接(可选)
    mw.loader.using(['mediawiki.util']).then(() => {
        mw.util.addPortletLink(
            'p-tb',
            '?cardmanager=1',
            '卡牌管理器',
            't-cardmanager',
            '打开卡牌管理器'
        );
    });


})();
})();

2025年10月23日 (四) 16:09的版本

(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 = () => {
                    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');
                    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.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.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());
            
            // AP
            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'));
            
            // 按钮组
            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;
        }

        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.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';
            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(textarea, template) {
            const selection = window.getSelection();
            const selectedText = selection.toString();
            
            if (template === '<br>') {
                document.execCommand('insertHTML', false, '<br>');
            } else {
                const result = template.replace('%s', selectedText || '选择文字');
                document.execCommand('insertText', false, result);
            }
            
            this.cardData.desc_global = textarea.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);
            }
            
            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) {
                    const content = page.revisions[0].slots.main['*'];
                    console.log('Card Manager: 加载了战斗员数据');
                }
            } catch (error) {
                console.error('Card Manager: 加载战斗员数据失败:', error);
            }
        }

        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);
    }

})();