MediaWiki

Card.js:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
第1行: 第1行:
(function() {
(function() {
     'use strict';
     'use strict';
 
   
     // 加载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: 脚本已加载');
     // 状态管理
 
     const state = {
     class CardManager {
         currentFighter: '',
         constructor() {
        fighters: [],
            console.log('Card Manager: 初始化中...');
        cards: [],
            this.currentFighter = '';
        currentCard: null,
            this.cards = {};
        defaultInfo: {
            this.currentCard = null;
             order: '',
             this.fighters = ['示例战斗员1', '示例战斗员2'];
            ego: ''
           
        },
            this.defaultData = {
        editMode: 'base', // base, inspiration, god_inspiration
                order: [],
        currentGod: 'circen'
                ego: ''
    };
            };
   
           
    // 卡牌数据结构
            this.cardData = {
    function createEmptyCard() {
                name: '',
        return {
            name: '',
            base: {
                 displayname: '',
                 displayname: '',
                 art: '',
                 art: '',
第28行: 第30行:
                 god: '',
                 god: '',
                 ap: '',
                 ap: '',
                 type: '攻击',
                 type: '',
                 dict: '',
                 dict: '',
                 desc_global: '',
                 desc_global: '',
                 sub: '',
                 sub: '',
                 isinspiration: false,
                 isinspiration: 0,
                 isgod_inspiration: false,
                 isgod_inspiration: 0
                 inspirations: [],
            },
                 god_inspirations: {
            var: {
                 inspiration: [],
                 god_inspiration: {
                     circen: [],
                     circen: [],
                     diallos: [],
                     diallos: [],
第42行: 第46行:
                     vitor: []
                     vitor: []
                 }
                 }
             };
             }
        };
    }
   
    // 创建元素辅助函数
    function createElement(tag, className, attributes = {}) {
        const el = document.createElement(tag);
        if (className) el.className = className;
        Object.entries(attributes).forEach(([key, value]) => {
            if (key === 'textContent') {
                el.textContent = value;
            } else if (key.startsWith('on')) {
                el.addEventListener(key.substring(2).toLowerCase(), value);
            } else {
                el.setAttribute(key, value);
            }
        });
        return el;
    }
   
    // 创建自定义下拉选择器
    function createSelect(options, selectedValue, onChange) {
        const select = createElement('div', 'form-select');
        select.textContent = selectedValue || options[0] || '请选择';
        select.setAttribute('tabindex', '0');
       
        const dropdown = createElement('div', 'dropdown-menu');
        dropdown.style.cssText = 'position:absolute;background:white;border:1px solid #ddd;border-radius:4px;max-height:200px;overflow-y:auto;display:none;z-index:1000;box-shadow:0 2px 8px rgba(0,0,0,0.15);';
       
        options.forEach(option => {
            const item = createElement('div', 'dropdown-item');
            item.textContent = option;
            item.style.cssText = 'padding:8px 12px;cursor:pointer;';
            item.addEventListener('mouseenter', () => item.style.background = '#f0f0f0');
            item.addEventListener('mouseleave', () => item.style.background = 'white');
            item.addEventListener('click', () => {
                select.textContent = option;
                dropdown.style.display = 'none';
                if (onChange) onChange(option);
            });
            dropdown.appendChild(item);
        });
       
        select.addEventListener('click', (e) => {
            e.stopPropagation();
            dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none';
            const rect = select.getBoundingClientRect();
            dropdown.style.top = rect.bottom + 'px';
            dropdown.style.left = rect.left + 'px';
            dropdown.style.width = rect.width + 'px';
        });
       
        document.addEventListener('click', () => {
            dropdown.style.display = 'none';
        });
       
        const wrapper = createElement('div');
        wrapper.style.position = 'relative';
        wrapper.appendChild(select);
        document.body.appendChild(dropdown);
       
        return { wrapper, select, dropdown };
    }
   
    // 创建自定义输入框
    function createInput(type, value, onChange, placeholder = '') {
        const input = createElement('div', 'form-input');
        input.setAttribute('contenteditable', 'true');
        input.textContent = value || '';
        input.setAttribute('data-placeholder', placeholder);
        input.style.minHeight = type === 'textarea' ? '100px' : 'auto';
       
        if (!value) {
            input.style.color = '#999';
            input.textContent = placeholder;
         }
         }
 
       
         async init() {
         input.addEventListener('focus', () => {
             console.log('Card Manager: 开始初始化');
             if (input.textContent === placeholder) {
            await this.loadFighters();
                input.textContent = '';
             this.render();
                input.style.color = '#333';
             console.log('Card Manager: 初始化完成');
            }
         }
        });
 
       
         async loadFighters() {
        input.addEventListener('blur', () => {
             try {
             if (!input.textContent.trim()) {
                 const api = new mw.Api();
                input.textContent = placeholder;
                const response = await api.get({
                input.style.color = '#999';
                    action: 'query',
             }
                    list: 'categorymembers',
            if (onChange) onChange(input.textContent === placeholder ? '' : input.textContent);
                    cmtitle: 'Category:战斗员',
         });
                    cmlimit: 500
       
                });
         input.addEventListener('input', () => {
               
             if (onChange && input.textContent !== placeholder) {
                if (response.query && response.query.categorymembers) {
                 onChange(input.textContent);
                    this.fighters = response.query.categorymembers.map(page => page.title);
            }
                    console.log('Card Manager: 加载了', this.fighters.length, '个战斗员');
        });
                }
       
             } catch (error) {
        return input;
                 console.error('Card Manager: 加载战斗员列表失败:', error);
    }
   
    // 创建复选框
    function createCheckbox(checked, onChange) {
        const wrapper = createElement('div', 'checkbox-wrapper');
        const checkbox = createElement('div', checked ? 'checkbox checked' : 'checkbox');
        const label = createElement('div', '');
        label.textContent = '是';
       
        wrapper.addEventListener('click', () => {
            const newChecked = !checkbox.classList.contains('checked');
            if (newChecked) {
                checkbox.classList.add('checked');
             } else {
                 checkbox.classList.remove('checked');
             }
             }
         }
            if (onChange) onChange(newChecked ? 1 : 0);
 
         });
         render() {
       
            console.log('Card Manager: 开始渲染');
         wrapper.appendChild(checkbox);
        wrapper.appendChild(label);
        return wrapper;
    }
   
    // 创建表单组
    function createFormGroup(label, control) {
        const group = createElement('div', 'form-group');
        const labelEl = createElement('div', 'form-label');
        labelEl.textContent = label;
        group.appendChild(labelEl);
        group.appendChild(control);
        return group;
    }
   
    // 创建按钮
    function createButton(text, className, onClick) {
        const btn = createElement('div', 'btn ' + className);
        btn.textContent = text;
        btn.addEventListener('click', onClick);
        return btn;
    }
   
    // 文本插入辅助函数
    function insertTextAtCursor(element, text, wrap = false) {
        element.focus();
        const selection = window.getSelection();
       
        if (wrap && selection.rangeCount > 0) {
            const range = selection.getRangeAt(0);
            const selectedText = range.toString();
              
              
             const contentDiv = document.getElementById('mw-content-text');
             if (selectedText) {
            if (!contentDiv) {
                range.deleteContents();
                 console.error('Card Manager: 找不到内容容器');
                const textNode = document.createTextNode(text.replace('选择文字', selectedText));
                 range.insertNode(textNode);
                 return;
                 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() {
         document.execCommand('insertText', false, text);
            const container = document.createElement('div');
    }
            container.className = 'form-group';
   
           
    // 加载战斗员列表
            const label = document.createElement('div');
    async function loadFighters() {
            label.className = 'form-label';
        try {
            label.textContent = '当前战斗员';
             const api = new mw.Api();
           
             const result = await api.get({
            const selectContainer = document.createElement('div');
                 action: 'query',
            selectContainer.className = 'custom-select';
                 list: 'categorymembers',
           
                 cmtitle: 'Category:战斗员',
             const display = document.createElement('div');
                 cmlimit: 500
            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) => {
             state.fighters = result.query.categorymembers.map(page => page.title);
                e.stopPropagation();
            return state.fighters;
                dropdown.classList.toggle('active');
        } catch (error) {
             };
            console.error('加载战斗员列表失败:', error);
              
             return [];
             document.addEventListener('click', () => {
        }
                 dropdown.classList.remove('active');
    }
   
    // 加载战斗员卡牌数据
    async function loadFighterCards(fighter) {
        try {
             const api = new mw.Api();
             const result = await api.get({
                action: 'parse',
                page: '模块:卡牌/' + fighter,
                 prop: 'wikitext'
             });
             });
              
              
             selectContainer.appendChild(display);
             // 这里需要解析Lua代码,实际实现中可能需要更复杂的解析
             selectContainer.appendChild(dropdown);
            // 简化处理:返回空数组,实际使用时需要完整的Lua解析器
              
            return [];
            container.appendChild(label);
        } catch (error) {
            container.appendChild(selectContainer);
             console.error('加载卡牌数据失败:', error);
              
             return [];
            return container;
        }
    }
   
    // 生成Lua代码
    function generateLuaCode() {
        let code = 'local card = {}\n\n';
       
        // 生成 card.order
        if (state.defaultInfo.order) {
             code += `card.order = { "${state.defaultInfo.order}" }\n\n`;
         }
         }
 
       
         renderDefaultInfo() {
         // 生成 card.info
            const container = document.createElement('div');
        if (state.defaultInfo.ego) {
            container.className = 'default-info-section';
             code += 'card.info = {\n';
           
             code += `    ego = "${state.defaultInfo.ego}",\n`;
            const title = document.createElement('div');
             code += '}\n\n';
            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');
         state.cards.forEach(card => {
             code += `card["${card.name}"] = {\n`;
            code += '   base = {\n';
              
              
             const title = document.createElement('div');
             const base = card.base;
             title.className = 'section-title';
            if (base.displayname) code += `        displayname = "${base.displayname}",\n`;
             title.textContent = '卡牌数据';
            if (base.art) code += `        art = "${base.art}",\n`;
             container.appendChild(title);
            if (base.group) code += `        group = "${base.group}",\n`;
            if (base.rarity) code += `        rarity = "${base.rarity}",\n`;
            if (base.god) code += `        god = "${base.god}",\n`;
            if (base.ap) code += `        ap = ${base.ap},\n`;
             if (base.type) code += `        type = "${base.type}",\n`;
             if (base.dict) code += `        dict = "${base.dict}",\n`;
             if (base.desc_global) code += `        desc_global = "${base.desc_global}",\n`;
            if (base.sub) code += `        sub = "${base.sub}",\n`;
            if (base.isinspiration) code += `        isinspiration = ${base.isinspiration},\n`;
            if (base.isgod_inspiration) code += `        isgod_inspiration = ${base.isgod_inspiration},\n`;
              
              
             container.appendChild(this.createInputField('卡牌名称', 'name'));
             code += '   },\n';
            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);
             // 生成 var 部分
             btnGroup.appendChild(newBtn);
             if (card.var && (card.var.inspiration.length > 0 || Object.values(card.var.god_inspiration).some(arr => arr.length > 0))) {
            container.appendChild(btnGroup);
                 code += '   var = {\n';
           
            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';
                if (card.var.inspiration.length > 0) {
                variantTitle.textContent = `变体 ${index + 1}`;
                    code += '       inspiration = {\n';
                variantBox.appendChild(variantTitle);
                    card.var.inspiration.forEach(insp => {
               
                        code += '            {\n';
                const variantContent = document.createElement('div');
                        Object.entries(insp).forEach(([key, value]) => {
                variantContent.className = 'variant-content';
                            if (typeof value === 'number') {
               
                                code += `                ${key} = ${value},\n`;
                if (inspiration.ap) {
                            } else {
                    const apLine = document.createElement('div');
                                code += `                ${key} = "${value}",\n`;
                     apLine.textContent = `AP: ${inspiration.ap}`;
                            }
                     variantContent.appendChild(apLine);
                        });
                        code += '           },\n';
                     });
                     code += '        },\n';
                 }
                 }
                  
                  
                 if (inspiration.type) {
                 // 神光一闪
                    const typeLine = document.createElement('div');
                const hasGodInspiration = Object.values(card.var.god_inspiration).some(arr => arr.length > 0);
                    typeLine.textContent = `类型: ${inspiration.type}`;
                if (hasGodInspiration) {
                     variantContent.appendChild(typeLine);
                    code += '        god_inspiration = {\n';
                    Object.entries(card.var.god_inspiration).forEach(([god, inspList]) => {
                        if (inspList.length > 0) {
                            code += `            ${god} = {\n`;
                            inspList.forEach(insp => {
                                code += '                {\n';
                                Object.entries(insp).forEach(([key, value]) => {
                                    if (typeof value === 'number') {
                                        code += `                    ${key} = ${value},\n`;
                                    } else {
                                        code += `                   ${key} = "${value}",\n`;
                                    }
                                });
                                code += '                },\n';
                            });
                            code += '            },\n';
                        }
                     });
                    code += '        },\n';
                 }
                 }
                  
                  
                 if (inspiration.dict) {
                 code += '   },\n';
                    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;
             code += '}\n\n';
        }
        });
 
       
        renderGodInspirations() {
        code += 'return card';
            const container = document.createElement('div');
       
            container.className = 'variant-section';
        return code;
           
    }
            const title = document.createElement('div');
   
            title.className = 'section-title';
    // 渲染界面
            title.textContent = '神光一闪变体';
    function render() {
            container.appendChild(title);
        const container = document.getElementById('card-manager-container');
           
        if (!container) return;
            const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
       
            const godNames = {
        container.innerHTML = '';
                'circen': '瑟肯',
       
                'diallos': '迪亚罗斯',
        const manager = createElement('div', 'card-manager');
                'nihilum': '虚无',
       
                'secred': '萨克雷德',
        // 左侧输入区
                'vitor': '维托尔'
        const inputSection = createElement('div', 'card-input-section');
            };
       
           
        // 战斗员选择
            gods.forEach(god => {
        const fighterGroup = createElement('div', 'form-group');
                const godInspirations = this.cardData.god_inspirations[god];
        const fighterLabel = createElement('div', 'form-label');
                if (!godInspirations || godInspirations.length === 0) return;
        fighterLabel.textContent = '当前战斗员:';
               
        fighterGroup.appendChild(fighterLabel);
                const godSection = document.createElement('div');
       
                godSection.className = 'god-section';
        const fighterSelect = createSelect(state.fighters, state.currentFighter, (value) => {
               
            state.currentFighter = value;
                const godTitle = document.createElement('div');
            loadFighterCards(value).then(cards => {
                godTitle.className = 'god-title';
                state.cards = cards;
                godTitle.textContent = godNames[god] || god;
                 render();
                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);
             });
             });
        });
        fighterGroup.appendChild(fighterSelect.wrapper);
        inputSection.appendChild(fighterGroup);
       
        // 默认信息区
        const defaultSection = createElement('div', 'default-info-section');
        const defaultTitle = createElement('div', 'section-title');
        defaultTitle.textContent = '默认信息';
        defaultSection.appendChild(defaultTitle);
       
        const orderInput = createInput('text', state.defaultInfo.order, (value) => {
            state.defaultInfo.order = value;
            render();
        }, '例:灭,灭,救,虚无残影');
        defaultSection.appendChild(createFormGroup('卡牌顺序(card.order):', orderInput));
       
        const egoInput = createInput('text', state.defaultInfo.ego, (value) => {
            state.defaultInfo.ego = value;
            render();
        }, '例:虚无');
        defaultSection.appendChild(createFormGroup('属性(ego):', egoInput));
       
        inputSection.appendChild(defaultSection);
       
        // 卡牌数据输入区
        if (state.currentCard) {
            const cardSection = createElement('div', 'card-data-section');
            const cardTitle = createElement('div', 'section-title');
            cardTitle.textContent = '卡牌数据';
            cardSection.appendChild(cardTitle);
              
              
            return container;
             const card = state.currentCard;
        }
 
        createInputField(label, field) {
             const group = document.createElement('div');
            group.className = 'form-group';
              
              
             const labelDiv = document.createElement('div');
            // 卡牌名称
             labelDiv.className = 'form-label';
             const nameInput = createInput('text', card.name, (value) => {
             labelDiv.textContent = label;
                card.name = value;
                render();
             }, '例:黑洞');
             cardSection.appendChild(createFormGroup('卡牌名称:', nameInput));
              
              
             const input = document.createElement('div');
            // 显示名称
            input.className = 'custom-input';
             const displaynameInput = createInput('text', card.base.displayname, (value) => {
            input.contentEditable = true;
                 card.base.displayname = value;
            input.dataset.field = field;
                 render();
            input.textContent = this.cardData[field] || '';
            input.addEventListener('input', () => {
                 this.cardData[field] = input.textContent;
                 this.updatePreview();
             });
             });
            cardSection.appendChild(createFormGroup('显示名称(displayname):', displaynameInput));
              
              
             group.appendChild(labelDiv);
             // 图片
             group.appendChild(input);
            const artInput = createInput('text', card.base.art, (value) => {
                card.base.art = value;
                render();
             }, '例:unique_1064_02.png');
            cardSection.appendChild(createFormGroup('图片(art):', artInput));
              
              
             return group;
             // 卡组
        }
            const groupSelect = createSelect(
 
                ['自我意识技能', '起始卡牌', '独特卡牌', '灵光一闪', '神光一闪'],
        createCheckboxField(label, field) {
                card.base.group,
            const group = document.createElement('div');
                (value) => {
             group.className = 'form-group';
                    card.base.group = value;
                    render();
                }
            );
             cardSection.appendChild(createFormGroup('卡组(group):', groupSelect.wrapper));
              
              
             const labelDiv = document.createElement('div');
            // 稀有度
            labelDiv.className = 'form-label';
             const raritySelect = createSelect(
            labelDiv.textContent = label;
                ['', '蓝', '橙', ''],
           
                card.base.rarity,
            const checkboxContainer = document.createElement('div');
                (value) => {
            checkboxContainer.className = 'checkbox-group';
                    card.base.rarity = value;
           
                    render();
            const checkbox = document.createElement('div');
                }
             checkbox.className = 'custom-checkbox';
             );
             checkbox.dataset.field = field;
             cardSection.appendChild(createFormGroup('稀有度(rarity):', raritySelect.wrapper));
            if (this.cardData[field]) {
                checkbox.classList.add('checked');
            }
              
              
             const statusLabel = document.createElement('div');
             // 神明
             statusLabel.textContent = this.cardData[field] ? '是' : '否';
             const godSelect = createSelect(
           
                 ['circen', 'diallos', 'nihilum', 'secred', 'vitor'],
            checkbox.onclick = () => {
                 card.base.god,
                checkbox.classList.toggle('checked');
                 (value) => {
                 this.cardData[field] = checkbox.classList.contains('checked');
                     card.base.god = value;
                statusLabel.textContent = this.cardData[field] ? '是' : '否';
                     render();
                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();
                 }
                 }
             }
             );
           
             cardSection.appendChild(createFormGroup('神明:', godSelect.wrapper));
            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;
             // AP
            this.updatePreview();
            const apInput = createInput('text', card.base.ap, (value) => {
        }
                card.base.ap = value;
 
                render();
        createGroupSelect() {
            }, '整数/X/Ø');
            const group = document.createElement('div');
             cardSection.appendChild(createFormGroup('AP:', apInput));
             group.className = 'form-group';
              
              
             const label = document.createElement('div');
             // 卡牌类型
            label.className = 'form-label';
             const typeSelect = createSelect(
            label.textContent = '卡组(group)';
                ['攻击', '技能', '强化'],
           
                card.base.type,
             const container = document.createElement('div');
                (value) => {
            container.className = 'group-options';
                    card.base.type = value;
           
                     render();
            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'));
             cardSection.appendChild(createFormGroup('卡牌类型(type):', typeSelect.wrapper));
                    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';
             const dictInput = createInput('text', card.base.dict, (value) => {
            label.textContent = '稀有度(rarity)';
                 card.base.dict = value;
           
                 render();
             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);
             });
             });
            cardSection.appendChild(createFormGroup('机制(dict):', dictInput));
              
              
             group.appendChild(label);
             // 描述输入区按钮
             group.appendChild(container);
            const descButtonGroup = createElement('div', 'button-group');
              
            descButtonGroup.appendChild(createButton('蓝色文本', 'btn-blue', () => {
             return group;
                insertTextAtCursor(descInput, '{{文本|蓝|选择文字}}', true);
        }
            }));
 
             descButtonGroup.appendChild(createButton('绿色文本', 'btn-green', () => {
        createGodSelect() {
                insertTextAtCursor(descInput, '{{文本|绿|选择文字}}', true);
            const group = document.createElement('div');
             }));
             group.className = 'form-group';
             descButtonGroup.appendChild(createButton('绿色描边', 'btn-green', () => {
                insertTextAtCursor(descInput, '{{描边|绿|选择文字}}', true);
            }));
            descButtonGroup.appendChild(createButton('词典', 'btn', () => {
                insertTextAtCursor(descInput, '{{词典|选择文字}}', true);
            }));
             descButtonGroup.appendChild(createButton('换行', 'btn', () => {
                insertTextAtCursor(descInput, '<br>');
            }));
              
              
             const label = document.createElement('div');
             cardSection.appendChild(createFormGroup('描述编辑工具:', descButtonGroup));
            label.className = 'form-label';
            label.textContent = '神明';
              
              
             const container = document.createElement('div');
            // 描述
             container.className = 'god-options';
             const descInput = createInput('textarea', card.base.desc_global, (value) => {
                card.base.desc_global = value;
                render();
            }, '输入卡牌描述...');
             cardSection.appendChild(createFormGroup('描述(desc_global):', descInput));
              
              
             const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
             // 衍生卡牌
              
             const subInput = createInput('text', card.base.sub, (value) => {
            gods.forEach(god => {
                card.base.sub = value;
                const option = document.createElement('div');
                 render();
                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);
             });
             });
            cardSection.appendChild(createFormGroup('衍生卡牌(sub):', subInput));
              
              
             group.appendChild(label);
             // 是否存在灵光一闪
            group.appendChild(container);
             const inspirationCheckbox = createCheckbox(card.base.isinspiration, (value) => {
           
                 card.base.isinspiration = value;
            return group;
                 render();
        }
 
        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);
             });
             });
            cardSection.appendChild(createFormGroup('是否存在灵光一闪:', inspirationCheckbox));
              
              
            group.appendChild(label);
             // 是否存在神光一闪
            group.appendChild(container);
             const godInspirationCheckbox = createCheckbox(card.base.isgod_inspiration, (value) => {
           
                 card.base.isgod_inspiration = value;
            return group;
                 render();
        }
 
        renderCardLists() {
            const container = document.createElement('div');
           
            const title = document.createElement('div');
            title.className = 'panel-title';
            title.textContent = '卡牌列表';
            container.appendChild(title);
           
             // 主卡牌列表
             const mainSection = document.createElement('div');
            mainSection.className = 'card-list-section';
           
            const mainTitle = document.createElement('div');
            mainTitle.className = 'section-title';
            mainTitle.textContent = '主卡牌';
            mainSection.appendChild(mainTitle);
           
            const mainList = document.createElement('div');
            mainList.className = 'list-container';
            mainList.id = 'main-card-list';
            mainSection.appendChild(mainList);
            container.appendChild(mainSection);
           
            // 灵光一闪列表
            const inspirationSection = document.createElement('div');
            inspirationSection.className = 'card-list-section';
           
            const inspirationTitle = document.createElement('div');
            inspirationTitle.className = 'section-title';
            inspirationTitle.textContent = '灵光一闪卡牌';
            inspirationSection.appendChild(inspirationTitle);
           
            const inspirationList = document.createElement('div');
            inspirationList.className = 'list-container';
            inspirationList.id = 'inspiration-card-list';
            inspirationSection.appendChild(inspirationList);
            container.appendChild(inspirationSection);
           
            // 神之一闪列表
            const godSection = document.createElement('div');
            godSection.className = 'card-list-section';
           
            const godTitle = document.createElement('div');
            godTitle.className = 'section-title';
            godTitle.textContent = '神之一闪卡牌';
            godSection.appendChild(godTitle);
           
            const godList = document.createElement('div');
            godList.className = 'list-container';
            godList.id = 'god-card-list';
            godSection.appendChild(godList);
            container.appendChild(godSection);
           
            this.updateCardLists();
           
            return container;
        }
 
        updateCardLists() {
            const mainList = document.getElementById('main-card-list');
            const inspirationList = document.getElementById('inspiration-card-list');
            const godList = document.getElementById('god-card-list');
           
            if (!mainList || !inspirationList || !godList) return;
           
            const mainCards = [];
            const inspirationCards = [];
            const godCards = [];
           
            // 分类卡牌
            Object.keys(this.cards).forEach(name => {
                 const card = this.cards[name];
                if (card.isgod_inspiration) {
                    godCards.push(name);
                } else if (card.isinspiration) {
                    inspirationCards.push(name);
                 } else {
                    mainCards.push(name);
                }
             });
             });
            cardSection.appendChild(createFormGroup('是否存在神光一闪:', godInspirationCheckbox));
              
              
             // 更新各个列表
             inputSection.appendChild(cardSection);
            this.updateCardListSection(mainList, mainCards);
            this.updateCardListSection(inspirationList, inspirationCards);
            this.updateCardListSection(godList, godCards);
         }
         }
 
       
         updateCardListSection(container, cardNames) {
         // 添加新卡牌按钮
             container.innerHTML = '';
        const addCardBtn = createButton('+ 新增卡牌', 'btn-success', () => {
              
             const newCard = createEmptyCard();
             if (cardNames.length === 0) {
            newCard.name = '新卡牌' + (state.cards.length + 1);
                const empty = document.createElement('div');
            state.cards.push(newCard);
                empty.className = 'list-empty';
             state.currentCard = newCard;
                empty.textContent = '暂无卡牌';
             render();
                container.appendChild(empty);
        });
                return;
        inputSection.appendChild(addCardBtn);
             }
       
              
        manager.appendChild(inputSection);
            cardNames.forEach(name => {
       
                 const card = this.cards[name];
        // 中间列表区
                const item = document.createElement('div');
        const listSection = createElement('div', 'card-list-section');
                item.className = 'card-list-item';
       
        // 卡牌列表
        const cardListContainer = createElement('div', 'list-container');
        const cardListHeader = createElement('div', 'list-header');
        const cardListTitle = createElement('div', 'list-title');
        cardListTitle.textContent = '卡牌列表';
        cardListHeader.appendChild(cardListTitle);
        cardListContainer.appendChild(cardListHeader);
       
        if (state.cards.length === 0) {
            const emptyState = createElement('div', 'empty-state');
            const emptyIcon = createElement('div', 'empty-state-icon');
            emptyIcon.textContent = '📋';
            const emptyText = createElement('div', 'empty-state-text');
            emptyText.textContent = '暂无卡牌,点击"新增卡牌"开始创建';
            emptyState.appendChild(emptyIcon);
            emptyState.appendChild(emptyText);
             cardListContainer.appendChild(emptyState);
        } else {
             state.cards.forEach((card, index) => {
                 const cardItem = createElement('div', 'card-item' + (state.currentCard === card ? ' active' : ''));
                  
                  
                 const info = document.createElement('div');
                 const cardName = createElement('div', 'card-item-name');
                cardName.textContent = card.name || '未命名卡牌';
                  
                  
                 const nameDiv = document.createElement('div');
                 const cardInfo = createElement('div', 'card-item-info');
                 nameDiv.className = 'card-list-item-name';
                 const infoText = [];
                 nameDiv.textContent = name;
                if (card.base.type) infoText.push(card.base.type);
                if (card.base.ap) infoText.push('AP:' + card.base.ap);
                if (card.base.rarity) infoText.push(card.base.rarity);
                 cardInfo.textContent = infoText.join(' | ') || '暂无信息';
                  
                  
                 const detailDiv = document.createElement('div');
                 cardItem.appendChild(cardName);
                 detailDiv.className = 'card-list-item-info';
                 cardItem.appendChild(cardInfo);
                detailDiv.textContent = `${card.type || '攻击'} | AP:${card.ap || 0} | ${card.rarity || ''}`;
                  
                  
                 info.appendChild(nameDiv);
                 cardItem.addEventListener('click', () => {
                info.appendChild(detailDiv);
                    state.currentCard = card;
                    state.editMode = 'base';
                    render();
                });
                  
                  
                 const deleteBtn = document.createElement('div');
                // 删除按钮
                deleteBtn.className = 'delete-btn';
                 const deleteBtn = createButton('删除', 'btn-danger', (e) => {
                deleteBtn.textContent = '删除';
                deleteBtn.onclick = (e) => {
                     e.stopPropagation();
                     e.stopPropagation();
                     if (confirm(`确定要删除卡牌"${name}"吗?`)) {
                     if (confirm('确定要删除卡牌"' + card.name + '"吗?')) {
                         delete this.cards[name];
                         state.cards.splice(index, 1);
                        this.updateCardLists();
                         if (state.currentCard === card) {
                        this.updatePreview();
                             state.currentCard = state.cards[0] || null;
                         if (this.currentCard === name) {
                             this.newCard();
                         }
                         }
                        render();
                     }
                     }
                 };
                 });
                deleteBtn.style.cssText = 'margin-top:8px;width:100%;';
                cardItem.appendChild(deleteBtn);
                  
                  
                 item.appendChild(info);
                 cardListContainer.appendChild(cardItem);
                item.appendChild(deleteBtn);
               
                item.onclick = () => {
                    this.loadCard(name);
                    document.querySelectorAll('.card-list-item').forEach(i => i.classList.remove('active'));
                    item.classList.add('active');
                };
               
                container.appendChild(item);
             });
             });
         }
         }
 
       
         renderPreview() {
         listSection.appendChild(cardListContainer);
             const container = document.createElement('div');
       
        // 灵光一闪列表
        if (state.currentCard && state.currentCard.base.isinspiration) {
             const inspirationSection = createElement('div', 'inspiration-section');
            const inspirationHeader = createElement('div', 'list-header');
            const inspirationTitle = createElement('div', 'list-title');
            inspirationTitle.textContent = '灵光一闪列表';
            inspirationHeader.appendChild(inspirationTitle);
              
              
             const title = document.createElement('div');
             const addInspirationBtn = createButton('+ 添加', 'btn-primary', () => {
             title.className = 'panel-title';
                state.currentCard.var.inspiration.push({
             title.textContent = 'Lua代码预览';
                    ap: '',
             container.appendChild(title);
                    type: '',
                    desc_global: ''
                });
                render();
             });
             inspirationHeader.appendChild(addInspirationBtn);
             inspirationSection.appendChild(inspirationHeader);
              
              
             const preview = document.createElement('div');
             if (state.currentCard.var.inspiration.length === 0) {
            preview.className = 'preview-code';
                const emptyState = createElement('div', 'empty-state');
            preview.id = 'code-preview';
                emptyState.style.padding = '20px';
            container.appendChild(preview);
                const emptyText = createElement('div', 'empty-state-text');
              
                emptyText.textContent = '暂无灵光一闪,点击"添加"创建';
            const copyBtn = document.createElement('div');
                emptyState.appendChild(emptyText);
            copyBtn.className = 'btn btn-primary';
                inspirationSection.appendChild(emptyState);
            copyBtn.textContent = '复制代码';
             } else {
            copyBtn.style.marginTop = '10px';
                state.currentCard.var.inspiration.forEach((insp, idx) => {
            copyBtn.onclick = () => this.copyCode();
                    const inspItem = createElement('div', 'inspiration-item');
            container.appendChild(copyBtn);
                   
           
                    const inspHeader = createElement('div', 'inspiration-item-header');
            this.updatePreview();
                    const inspTitle = createElement('div', 'inspiration-item-title');
                    inspTitle.textContent = `灵光 #${idx + 1}`;
                    inspHeader.appendChild(inspTitle);
                   
                    const deleteInspBtn = createButton('删除', 'btn-danger', () => {
                        if (confirm('确定要删除这个灵光一闪吗?')) {
                            state.currentCard.var.inspiration.splice(idx, 1);
                            render();
                        }
                    });
                    deleteInspBtn.style.padding = '4px 8px';
                    deleteInspBtn.style.fontSize = '12px';
                    inspHeader.appendChild(deleteInspBtn);
                    inspItem.appendChild(inspHeader);
                   
                    // AP输入
                    const inspApInput = createInput('text', insp.ap, (value) => {
                        insp.ap = value;
                        render();
                    }, 'AP');
                    inspApInput.style.marginBottom = '8px';
                    inspApInput.style.fontSize = '13px';
                    inspItem.appendChild(inspApInput);
                   
                    // 类型选择
                    const inspTypeSelect = createSelect(
                        ['', '攻击', '技能', '强化'],
                        insp.type || '',
                        (value) => {
                            insp.type = value;
                            render();
                        }
                    );
                    inspTypeSelect.wrapper.style.marginBottom = '8px';
                    inspItem.appendChild(inspTypeSelect.wrapper);
                   
                    // 描述输入
                    const inspDescInput = createInput('textarea', insp.desc_global, (value) => {
                        insp.desc_global = value;
                        render();
                    }, '描述');
                    inspDescInput.style.minHeight = '60px';
                    inspDescInput.style.fontSize = '13px';
                    inspItem.appendChild(inspDescInput);
                   
                    inspirationSection.appendChild(inspItem);
                });
            }
              
              
             return container;
             listSection.appendChild(inspirationSection);
         }
         }
 
       
         updatePreview() {
        // 神光一闪列表
             const preview = document.getElementById('code-preview');
         if (state.currentCard && state.currentCard.base.isgod_inspiration) {
             if (!preview) return;
             const godInspirationSection = createElement('div', 'inspiration-section');
            const godInspirationHeader = createElement('div', 'list-header');
            const godInspirationTitle = createElement('div', 'list-title');
             godInspirationTitle.textContent = '神光一闪列表';
            godInspirationHeader.appendChild(godInspirationTitle);
            godInspirationSection.appendChild(godInspirationHeader);
              
              
             preview.textContent = this.generateLuaCode();
             // 神明选择标签
        }
            const godSelectGroup = createElement('div', 'god-select-group');
 
            ['circen', 'diallos', 'nihilum', 'secred', 'vitor'].forEach(god => {
        generateLuaCode() {
                const godTab = createElement('div', 'god-tab' + (state.currentGod === god ? ' active' : ''));
             let code = 'local card = {}\n\n';
                godTab.textContent = god;
                godTab.addEventListener('click', () => {
                    state.currentGod = god;
                    render();
                });
                godSelectGroup.appendChild(godTab);
             });
            godInspirationSection.appendChild(godSelectGroup);
              
              
             if (this.defaultData.order.length > 0) {
             // 当前神明的神光一闪列表
                code += `card.order = { "${this.defaultData.order.join(',')}" }\n\n`;
            const currentGodInspirations = state.currentCard.var.god_inspiration[state.currentGod];
            }
              
              
             code += 'card.info = {\n';
             const addGodInspirationBtn = createButton('+ 添加 ' + state.currentGod + ' 神光', 'btn-primary', () => {
            if (this.defaultData.ego) {
                 currentGodInspirations.push({
                 code += `    ego = "${this.defaultData.ego}",\n`;
                    ap: '',
            }
                    type: '',
            code += '}\n\n';
                    desc_global: ''
           
                });
            Object.keys(this.cards).forEach(name => {
                 render();
                const card = this.cards[name];
                 code += this.generateCardCode(name, card);
             });
             });
            addGodInspirationBtn.style.marginBottom = '10px';
            addGodInspirationBtn.style.width = '100%';
            godInspirationSection.appendChild(addGodInspirationBtn);
              
              
            code += 'return card';
             if (currentGodInspirations.length === 0) {
           
                const emptyState = createElement('div', 'empty-state');
            return code;
                emptyState.style.padding = '20px';
        }
                 const emptyText = createElement('div', 'empty-state-text');
 
                 emptyText.textContent = `暂无 ${state.currentGod} 神光一闪`;
        generateCardCode(name, card) {
                emptyState.appendChild(emptyText);
            let code = `card["${name}"] = {\n`;
                godInspirationSection.appendChild(emptyState);
            code += '    base = {\n';
             } else {
           
                currentGodInspirations.forEach((insp, idx) => {
             if (card.displayname) code += `        displayname = "${card.displayname}",\n`;
                    const inspItem = createElement('div', 'inspiration-item');
            if (card.art) code += `        art = "${card.art}",\n`;
                   
            if (card.group) code += `        group = "${card.group}",\n`;
                     const inspHeader = createElement('div', 'inspiration-item-header');
            if (card.rarity) code += `        rarity = "${card.rarity}",\n`;
                     const inspTitle = createElement('div', 'inspiration-item-title');
            if (card.ap) code += `        ap = ${isNaN(card.ap) ? `"${card.ap}"` : card.ap},\n`;
                    inspTitle.textContent = `${state.currentGod} 神光 #${idx + 1}`;
            if (card.type) code += `        type = "${card.type}",\n`;
                    inspHeader.appendChild(inspTitle);
            if (card.dict) code += `        dict = "${card.dict}",\n`;
                   
            if (card.desc_global) {
                    const deleteInspBtn = createButton('删除', 'btn-danger', () => {
                 const desc = card.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                         if (confirm('确定要删除这个神光一闪吗?')) {
                 code += `        desc_global = "${desc}",\n`;
                             currentGodInspirations.splice(idx, 1);
            }
                             render();
            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';
           
            // 添加变体数据
            if ((card.isinspiration && card.inspirations.length > 0) ||
                (card.isgod_inspiration && this.hasGodInspirations(card))) {
                code += '   \n    var = {\n';
               
                // 灵光一闪变体
                if (card.isinspiration && card.inspirations.length > 0) {
                     code += '       inspiration = {\n';
                     card.inspirations.forEach(inspiration => {
                        code += '            {\n';
                        if (inspiration.ap) code += `               ap = ${isNaN(inspiration.ap) ? `"${inspiration.ap}"` : inspiration.ap},\n`;
                        if (inspiration.type) code += `                type = "${inspiration.type}",\n`;
                        if (inspiration.dict) code += `                dict = "${inspiration.dict}",\n`;
                         if (inspiration.desc_global) {
                             const desc = inspiration.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                             code += `                desc_global = "${desc}",\n`;
                         }
                         }
                        code += '            },\n';
                     });
                     });
                     code += '       },\n';
                     deleteInspBtn.style.padding = '4px 8px';
                }
                    deleteInspBtn.style.fontSize = '12px';
               
                    inspHeader.appendChild(deleteInspBtn);
                // 神之一闪变体
                    inspItem.appendChild(inspHeader);
                if (card.isgod_inspiration) {
                   
                     const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
                    // AP输入
                     const hasAnyGod = gods.some(god => card.god_inspirations[god] && card.god_inspirations[god].length > 0);
                    const inspApInput = createInput('text', insp.ap, (value) => {
                        insp.ap = value;
                        render();
                    }, 'AP');
                    inspApInput.style.marginBottom = '8px';
                    inspApInput.style.fontSize = '13px';
                    inspItem.appendChild(inspApInput);
                   
                    // 类型选择
                     const inspTypeSelect = createSelect(
                        ['', '攻击', '技能', '强化'],
                        insp.type || '',
                        (value) => {
                            insp.type = value;
                            render();
                        }
                    );
                    inspTypeSelect.wrapper.style.marginBottom = '8px';
                    inspItem.appendChild(inspTypeSelect.wrapper);
                   
                    // 描述输入
                     const inspDescInput = createInput('textarea', insp.desc_global, (value) => {
                        insp.desc_global = value;
                        render();
                    }, '描述');
                    inspDescInput.style.minHeight = '60px';
                    inspDescInput.style.fontSize = '13px';
                    inspItem.appendChild(inspDescInput);
                      
                      
                     if (hasAnyGod) {
                     godInspirationSection.appendChild(inspItem);
                        code += '        god_inspiration = {\n';
                });
                       
                        gods.forEach(god => {
                            const godInspirations = card.god_inspirations[god];
                            if (godInspirations && godInspirations.length > 0) {
                                code += `            ${god} = {\n`;
                                godInspirations.forEach(inspiration => {
                                    code += '                {\n';
                                    if (inspiration.ap) code += `                    ap = ${isNaN(inspiration.ap) ? `"${inspiration.ap}"` : inspiration.ap},\n`;
                                    if (inspiration.type) code += `                    type = "${inspiration.type}",\n`;
                                    if (inspiration.dict) code += `                    dict = "${inspiration.dict}",\n`;
                                    if (inspiration.desc_global) {
                                        const desc = inspiration.desc_global.replace(/\n/g, '<br>').replace(/"/g, '\\"');
                                        code += `                    desc_global = "${desc}",\n`;
                                    }
                                    code += '                },\n';
                                });
                                code += '            },\n';
                            }
                        });
                       
                        code += '        },\n';
                    }
                }
               
                code += '    },\n';
             }
             }
              
              
             code += '}\n\n';
             listSection.appendChild(godInspirationSection);
           
            return code;
         }
         }
 
       
         hasGodInspirations(card) {
         manager.appendChild(listSection);
            const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
       
             return gods.some(god => card.god_inspirations[god] && card.god_inspirations[god].length > 0);
        // 右侧预览区
         }
        const previewSection = createElement('div', 'card-preview-section');
 
        const previewTitle = createElement('div', 'section-title');
         saveCard() {
        previewTitle.textContent = 'Lua 代码预览';
             if (!this.cardData.name) {
        previewSection.appendChild(previewTitle);
                 alert('请输入卡牌名称!');
       
        // 复制按钮
        const copyBtn = createButton('复制代码', 'btn-primary', () => {
            const code = generateLuaCode();
            navigator.clipboard.writeText(code).then(() => {
                alert('代码已复制到剪贴板!');
             }).catch(err => {
                console.error('复制失败:', err);
                // 降级方案
                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('代码已复制到剪贴板!');
            });
         });
        copyBtn.style.marginBottom = '10px';
        copyBtn.style.width = '100%';
        previewSection.appendChild(copyBtn);
       
         // 保存按钮
        const saveBtn = createButton('保存到Wiki', 'btn-success', async () => {
             if (!state.currentFighter) {
                 alert('请先选择战斗员!');
                 return;
                 return;
             }
             }
              
              
             this.cards[this.cardData.name] = JSON.parse(JSON.stringify(this.cardData));
             const code = generateLuaCode();
             this.currentCard = this.cardData.name;
             const pageName = '模块:卡牌/' + state.currentFighter;
           
            if (!this.defaultData.order.includes(this.cardData.name)) {
                this.defaultData.order.push(this.cardData.name);
                const orderInput = document.getElementById('order-input');
                if (orderInput) {
                    orderInput.textContent = this.defaultData.order.join(',');
                }
            }
           
            this.updateCardLists();
            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 {
             try {
                 const api = new mw.Api();
                 const api = new mw.Api();
                 const moduleName = `模块:卡牌/${this.currentFighter}`;
                 await api.postWithToken('csrf', {
               
                     action: 'edit',
                const response = await api.get({
                     title: pageName,
                     action: 'query',
                     text: code,
                     prop: 'revisions',
                     summary: '通过卡牌管理器更新卡牌数据',
                     titles: moduleName,
                     contentmodel: 'Scribunto'
                     rvprop: 'content',
                     rvslots: 'main'
                 });
                 });
                  
                 alert('保存成功!');
                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) {
             } catch (error) {
                 console.error('Card Manager: 加载战斗员数据失败:', error);
                 console.error('保存失败:', error);
                 alert('加载失败: ' + error.message);
                 alert('保存失败:' + error);
             }
             }
         }
         });
 
        saveBtn.style.marginBottom = '10px';
parseLuaContent(content) {
         saveBtn.style.width = '100%';
    // 重置数据
         previewSection.appendChild(saveBtn);
    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*\{([^}]*)\}/);
         const codePreview = createElement('div', 'code-preview');
         if (infoBlockMatch) {
         codePreview.textContent = generateLuaCode();
            const egoMatch = infoBlockMatch[1].match(/ego\s*=\s*"([^"]+)"/);
        previewSection.appendChild(codePreview);
            if (egoMatch) {
                this.defaultData.ego = egoMatch[1];
            }
        }
          
          
         // 使用正则表达式匹配每个卡牌块
         manager.appendChild(previewSection);
        const cardPattern = /card\["([^"]+)"\]\s*=\s*\{([\s\S]*?)\n\}/g;
        let match;
          
          
         while ((match = cardPattern.exec(content)) !== null) {
         container.appendChild(manager);
             const cardName = match[1];
    }
             const cardContent = match[2];
   
    // 初始化
    async function init() {
        // 确保在正确的页面
        const pageName = mw.config.get('wgPageName');
       
        // 创建容器
        let container = document.getElementById('card-manager-container');
        if (!container) {
             container = createElement('div', '');
             container.id = 'card-manager-container';
              
              
            console.log(`Card Manager: 解析卡牌 "${cardName}"`);
             // 查找插入位置
           
             const content = document.getElementById('mw-content-text');
             // 初始化卡牌数据
             if (content) {
            this.cards[cardName] = {
                 content.insertBefore(container, content.firstChild);
                name: cardName,
             } else {
                displayname: '',
                 document.body.appendChild(container);
                art: '',
                group: '',
                rarity: '',
                god: '',
                ap: '',
                type: '攻击',
                dict: '',
                desc_global: '',
                sub: '',
                isinspiration: false,
                isgod_inspiration: false,
                inspirations: [],
                god_inspirations: {
                    circen: [],
                    diallos: [],
                    nihilum: [],
                    secred: [],
                    vitor: []
                }
            };
           
            // 解析 base 部分
             const baseMatch = cardContent.match(/base\s*=\s*\{([\s\S]*?)\n\s*\},/);
             if (baseMatch) {
                 this.parseCardBase(cardName, baseMatch[1]);
            }
           
            // 解析 var 部分
            const varMatch = cardContent.match(/var\s*=\s*\{([\s\S]*?)\n\s*\},/);
             if (varMatch) {
                const varContent = varMatch[1];
               
                // 解析 inspiration
                const inspirationMatch = varContent.match(/inspiration\s*=\s*\{([\s\S]*?)\n\s*\},/);
                if (inspirationMatch) {
                    this.parseInspirationsList(cardName, inspirationMatch[1]);
                }
               
                // 解析 god_inspiration
                 const godInspirationMatch = varContent.match(/god_inspiration\s*=\s*\{([\s\S]*?)\n\s*\},/);
                if (godInspirationMatch) {
                    this.parseGodInspirationsList(cardName, godInspirationMatch[1]);
                }
             }
             }
         }
         }
          
          
         console.log('Card Manager: 解析完成');
         // 加载战斗员列表
        console.log('Card Manager: order =', this.defaultData.order);
         await loadFighters();
        console.log('Card Manager: ego =', this.defaultData.ego);
         console.log('Card Manager: 卡牌数量 =', Object.keys(this.cards).length);
          
          
    } catch (error) {
         // 如果有战斗员,默认选择第一个
         console.error('Card Manager: 解析Lua内容时出错:', error);
         if (state.fighters.length > 0) {
         alert('解析卡牌数据失败: ' + error.message);
            state.currentFighter = state.fighters[0];
    }
            state.cards = await loadFighterCards(state.currentFighter);
}
 
parseCardBase(cardName, baseContent) {
    const card = this.cards[cardName];
   
    card.displayname = this.extractFieldValue(baseContent, 'displayname');
    card.art = this.extractFieldValue(baseContent, 'art');
    card.group = this.extractFieldValue(baseContent, 'group');
    card.rarity = this.extractFieldValue(baseContent, 'rarity');
    card.god = this.extractFieldValue(baseContent, 'god');
    card.ap = this.extractFieldValue(baseContent, 'ap');
    card.type = this.extractFieldValue(baseContent, 'type') || '攻击';
    card.dict = this.extractFieldValue(baseContent, 'dict');
    card.desc_global = this.extractFieldValue(baseContent, 'desc_global').replace(/<br>/g, '\n');
    card.sub = this.extractFieldValue(baseContent, 'sub');
    card.isinspiration = baseContent.includes('isinspiration = 1');
    card.isgod_inspiration = baseContent.includes('isgod_inspiration = 1');
}
 
parseInspirationsList(cardName, content) {
    // 匹配所有的变体块 {...},
    const variantPattern = /\{([^\}]*)\},?/g;
    let match;
   
    while ((match = variantPattern.exec(content)) !== null) {
        const variantContent = match[1];
        if (variantContent.trim()) {
            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} 个灵光一闪变体`);
}
parseGodInspirationsList(cardName, content) {
    const gods = ['circen', 'diallos', 'nihilum', 'secred', 'vitor'];
   
    gods.forEach(god => {
        const godPattern = new RegExp(`${god}\\s*=\\s*\\{([\\s\\S]*?)\\n\\s*\\},`, 'i');
        const godMatch = content.match(godPattern);
          
          
         if (godMatch) {
         // 渲染界面
            const godContent = godMatch[1];
         render();
            const variantPattern = /\{([^\}]*)\},?/g;
            let match;
           
            while ((match = variantPattern.exec(godContent)) !== null) {
                const variantContent = match[1];
                if (variantContent.trim()) {
                    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[god].push(variant);
                }
            }
           
            console.log(`Card Manager: 卡牌 "${cardName}" 的神明 "${god}" 有 ${this.cards[cardName].god_inspirations[god].length} 个神光一闪变体`);
        }
    });
}
 
loadCard(name) {
    if (!this.cards[name]) return;
   
    this.currentCard = name;
    this.cardData = JSON.parse(JSON.stringify(this.cards[name]));
   
    // 确保变体数据结构完整
    if (!this.cardData.inspirations) {
         this.cardData.inspirations = [];
    }
    if (!this.cardData.god_inspirations) {
        this.cardData.god_inspirations = {
            circen: [],
            diallos: [],
            nihilum: [],
            secred: [],
            vitor: []
        };
     }
     }
      
      
     this.render();
     // 等待DOM加载完成后初始化
}
 
 
        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') {
     if (document.readyState === 'loading') {
         document.addEventListener('DOMContentLoaded', () => {
         document.addEventListener('DOMContentLoaded', init);
            mw.loader.using(['mediawiki.api']).then(initCardManager);
        });
     } else {
     } else {
         mw.loader.using(['mediawiki.api']).then(initCardManager);
         init();
     }
     }
 
   
    // 导出API供外部使用
    window.CardManager = {
        init: init,
        render: render,
        state: state,
        createCard: createEmptyCard,
        generateCode: generateLuaCode
    };
   
})();
})();

2025年10月23日 (四) 17:15的版本

(function() {
    'use strict';
    
    // 加载CSS
    mw.loader.load('/index.php?title=Mediawiki:Card.css&action=raw&ctype=text/css', 'text/css');
    
    // 状态管理
    const state = {
        currentFighter: '',
        fighters: [],
        cards: [],
        currentCard: null,
        defaultInfo: {
            order: '',
            ego: ''
        },
        editMode: 'base', // base, inspiration, god_inspiration
        currentGod: 'circen'
    };
    
    // 卡牌数据结构
    function createEmptyCard() {
        return {
            name: '',
            base: {
                displayname: '',
                art: '',
                group: '',
                rarity: '',
                god: '',
                ap: '',
                type: '',
                dict: '',
                desc_global: '',
                sub: '',
                isinspiration: 0,
                isgod_inspiration: 0
            },
            var: {
                inspiration: [],
                god_inspiration: {
                    circen: [],
                    diallos: [],
                    nihilum: [],
                    secred: [],
                    vitor: []
                }
            }
        };
    }
    
    // 创建元素辅助函数
    function createElement(tag, className, attributes = {}) {
        const el = document.createElement(tag);
        if (className) el.className = className;
        Object.entries(attributes).forEach(([key, value]) => {
            if (key === 'textContent') {
                el.textContent = value;
            } else if (key.startsWith('on')) {
                el.addEventListener(key.substring(2).toLowerCase(), value);
            } else {
                el.setAttribute(key, value);
            }
        });
        return el;
    }
    
    // 创建自定义下拉选择器
    function createSelect(options, selectedValue, onChange) {
        const select = createElement('div', 'form-select');
        select.textContent = selectedValue || options[0] || '请选择';
        select.setAttribute('tabindex', '0');
        
        const dropdown = createElement('div', 'dropdown-menu');
        dropdown.style.cssText = 'position:absolute;background:white;border:1px solid #ddd;border-radius:4px;max-height:200px;overflow-y:auto;display:none;z-index:1000;box-shadow:0 2px 8px rgba(0,0,0,0.15);';
        
        options.forEach(option => {
            const item = createElement('div', 'dropdown-item');
            item.textContent = option;
            item.style.cssText = 'padding:8px 12px;cursor:pointer;';
            item.addEventListener('mouseenter', () => item.style.background = '#f0f0f0');
            item.addEventListener('mouseleave', () => item.style.background = 'white');
            item.addEventListener('click', () => {
                select.textContent = option;
                dropdown.style.display = 'none';
                if (onChange) onChange(option);
            });
            dropdown.appendChild(item);
        });
        
        select.addEventListener('click', (e) => {
            e.stopPropagation();
            dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none';
            const rect = select.getBoundingClientRect();
            dropdown.style.top = rect.bottom + 'px';
            dropdown.style.left = rect.left + 'px';
            dropdown.style.width = rect.width + 'px';
        });
        
        document.addEventListener('click', () => {
            dropdown.style.display = 'none';
        });
        
        const wrapper = createElement('div');
        wrapper.style.position = 'relative';
        wrapper.appendChild(select);
        document.body.appendChild(dropdown);
        
        return { wrapper, select, dropdown };
    }
    
    // 创建自定义输入框
    function createInput(type, value, onChange, placeholder = '') {
        const input = createElement('div', 'form-input');
        input.setAttribute('contenteditable', 'true');
        input.textContent = value || '';
        input.setAttribute('data-placeholder', placeholder);
        input.style.minHeight = type === 'textarea' ? '100px' : 'auto';
        
        if (!value) {
            input.style.color = '#999';
            input.textContent = placeholder;
        }
        
        input.addEventListener('focus', () => {
            if (input.textContent === placeholder) {
                input.textContent = '';
                input.style.color = '#333';
            }
        });
        
        input.addEventListener('blur', () => {
            if (!input.textContent.trim()) {
                input.textContent = placeholder;
                input.style.color = '#999';
            }
            if (onChange) onChange(input.textContent === placeholder ? '' : input.textContent);
        });
        
        input.addEventListener('input', () => {
            if (onChange && input.textContent !== placeholder) {
                onChange(input.textContent);
            }
        });
        
        return input;
    }
    
    // 创建复选框
    function createCheckbox(checked, onChange) {
        const wrapper = createElement('div', 'checkbox-wrapper');
        const checkbox = createElement('div', checked ? 'checkbox checked' : 'checkbox');
        const label = createElement('div', '');
        label.textContent = '是';
        
        wrapper.addEventListener('click', () => {
            const newChecked = !checkbox.classList.contains('checked');
            if (newChecked) {
                checkbox.classList.add('checked');
            } else {
                checkbox.classList.remove('checked');
            }
            if (onChange) onChange(newChecked ? 1 : 0);
        });
        
        wrapper.appendChild(checkbox);
        wrapper.appendChild(label);
        return wrapper;
    }
    
    // 创建表单组
    function createFormGroup(label, control) {
        const group = createElement('div', 'form-group');
        const labelEl = createElement('div', 'form-label');
        labelEl.textContent = label;
        group.appendChild(labelEl);
        group.appendChild(control);
        return group;
    }
    
    // 创建按钮
    function createButton(text, className, onClick) {
        const btn = createElement('div', 'btn ' + className);
        btn.textContent = text;
        btn.addEventListener('click', onClick);
        return btn;
    }
    
    // 文本插入辅助函数
    function insertTextAtCursor(element, text, wrap = false) {
        element.focus();
        const selection = window.getSelection();
        
        if (wrap && selection.rangeCount > 0) {
            const range = selection.getRangeAt(0);
            const selectedText = range.toString();
            
            if (selectedText) {
                range.deleteContents();
                const textNode = document.createTextNode(text.replace('选择文字', selectedText));
                range.insertNode(textNode);
                return;
            }
        }
        
        document.execCommand('insertText', false, text);
    }
    
    // 加载战斗员列表
    async function loadFighters() {
        try {
            const api = new mw.Api();
            const result = await api.get({
                action: 'query',
                list: 'categorymembers',
                cmtitle: 'Category:战斗员',
                cmlimit: 500
            });
            
            state.fighters = result.query.categorymembers.map(page => page.title);
            return state.fighters;
        } catch (error) {
            console.error('加载战斗员列表失败:', error);
            return [];
        }
    }
    
    // 加载战斗员卡牌数据
    async function loadFighterCards(fighter) {
        try {
            const api = new mw.Api();
            const result = await api.get({
                action: 'parse',
                page: '模块:卡牌/' + fighter,
                prop: 'wikitext'
            });
            
            // 这里需要解析Lua代码,实际实现中可能需要更复杂的解析
            // 简化处理:返回空数组,实际使用时需要完整的Lua解析器
            return [];
        } catch (error) {
            console.error('加载卡牌数据失败:', error);
            return [];
        }
    }
    
    // 生成Lua代码
    function generateLuaCode() {
        let code = 'local card = {}\n\n';
        
        // 生成 card.order
        if (state.defaultInfo.order) {
            code += `card.order = { "${state.defaultInfo.order}" }\n\n`;
        }
        
        // 生成 card.info
        if (state.defaultInfo.ego) {
            code += 'card.info = {\n';
            code += `    ego = "${state.defaultInfo.ego}",\n`;
            code += '}\n\n';
        }
        
        // 生成每张卡牌
        state.cards.forEach(card => {
            code += `card["${card.name}"] = {\n`;
            code += '    base = {\n';
            
            const base = card.base;
            if (base.displayname) code += `        displayname = "${base.displayname}",\n`;
            if (base.art) code += `        art = "${base.art}",\n`;
            if (base.group) code += `        group = "${base.group}",\n`;
            if (base.rarity) code += `        rarity = "${base.rarity}",\n`;
            if (base.god) code += `        god = "${base.god}",\n`;
            if (base.ap) code += `        ap = ${base.ap},\n`;
            if (base.type) code += `        type = "${base.type}",\n`;
            if (base.dict) code += `        dict = "${base.dict}",\n`;
            if (base.desc_global) code += `        desc_global = "${base.desc_global}",\n`;
            if (base.sub) code += `        sub = "${base.sub}",\n`;
            if (base.isinspiration) code += `        isinspiration = ${base.isinspiration},\n`;
            if (base.isgod_inspiration) code += `        isgod_inspiration = ${base.isgod_inspiration},\n`;
            
            code += '    },\n';
            
            // 生成 var 部分
            if (card.var && (card.var.inspiration.length > 0 || Object.values(card.var.god_inspiration).some(arr => arr.length > 0))) {
                code += '    var = {\n';
                
                // 灵光一闪
                if (card.var.inspiration.length > 0) {
                    code += '        inspiration = {\n';
                    card.var.inspiration.forEach(insp => {
                        code += '            {\n';
                        Object.entries(insp).forEach(([key, value]) => {
                            if (typeof value === 'number') {
                                code += `                ${key} = ${value},\n`;
                            } else {
                                code += `                ${key} = "${value}",\n`;
                            }
                        });
                        code += '            },\n';
                    });
                    code += '        },\n';
                }
                
                // 神光一闪
                const hasGodInspiration = Object.values(card.var.god_inspiration).some(arr => arr.length > 0);
                if (hasGodInspiration) {
                    code += '        god_inspiration = {\n';
                    Object.entries(card.var.god_inspiration).forEach(([god, inspList]) => {
                        if (inspList.length > 0) {
                            code += `            ${god} = {\n`;
                            inspList.forEach(insp => {
                                code += '                {\n';
                                Object.entries(insp).forEach(([key, value]) => {
                                    if (typeof value === 'number') {
                                        code += `                    ${key} = ${value},\n`;
                                    } else {
                                        code += `                    ${key} = "${value}",\n`;
                                    }
                                });
                                code += '                },\n';
                            });
                            code += '            },\n';
                        }
                    });
                    code += '        },\n';
                }
                
                code += '    },\n';
            }
            
            code += '}\n\n';
        });
        
        code += 'return card';
        
        return code;
    }
    
    // 渲染界面
    function render() {
        const container = document.getElementById('card-manager-container');
        if (!container) return;
        
        container.innerHTML = '';
        
        const manager = createElement('div', 'card-manager');
        
        // 左侧输入区
        const inputSection = createElement('div', 'card-input-section');
        
        // 战斗员选择
        const fighterGroup = createElement('div', 'form-group');
        const fighterLabel = createElement('div', 'form-label');
        fighterLabel.textContent = '当前战斗员:';
        fighterGroup.appendChild(fighterLabel);
        
        const fighterSelect = createSelect(state.fighters, state.currentFighter, (value) => {
            state.currentFighter = value;
            loadFighterCards(value).then(cards => {
                state.cards = cards;
                render();
            });
        });
        fighterGroup.appendChild(fighterSelect.wrapper);
        inputSection.appendChild(fighterGroup);
        
        // 默认信息区
        const defaultSection = createElement('div', 'default-info-section');
        const defaultTitle = createElement('div', 'section-title');
        defaultTitle.textContent = '默认信息';
        defaultSection.appendChild(defaultTitle);
        
        const orderInput = createInput('text', state.defaultInfo.order, (value) => {
            state.defaultInfo.order = value;
            render();
        }, '例:灭,灭,救,虚无残影');
        defaultSection.appendChild(createFormGroup('卡牌顺序(card.order):', orderInput));
        
        const egoInput = createInput('text', state.defaultInfo.ego, (value) => {
            state.defaultInfo.ego = value;
            render();
        }, '例:虚无');
        defaultSection.appendChild(createFormGroup('属性(ego):', egoInput));
        
        inputSection.appendChild(defaultSection);
        
        // 卡牌数据输入区
        if (state.currentCard) {
            const cardSection = createElement('div', 'card-data-section');
            const cardTitle = createElement('div', 'section-title');
            cardTitle.textContent = '卡牌数据';
            cardSection.appendChild(cardTitle);
            
            const card = state.currentCard;
            
            // 卡牌名称
            const nameInput = createInput('text', card.name, (value) => {
                card.name = value;
                render();
            }, '例:黑洞');
            cardSection.appendChild(createFormGroup('卡牌名称:', nameInput));
            
            // 显示名称
            const displaynameInput = createInput('text', card.base.displayname, (value) => {
                card.base.displayname = value;
                render();
            });
            cardSection.appendChild(createFormGroup('显示名称(displayname):', displaynameInput));
            
            // 图片
            const artInput = createInput('text', card.base.art, (value) => {
                card.base.art = value;
                render();
            }, '例:unique_1064_02.png');
            cardSection.appendChild(createFormGroup('图片(art):', artInput));
            
            // 卡组
            const groupSelect = createSelect(
                ['自我意识技能', '起始卡牌', '独特卡牌', '灵光一闪', '神光一闪'],
                card.base.group,
                (value) => {
                    card.base.group = value;
                    render();
                }
            );
            cardSection.appendChild(createFormGroup('卡组(group):', groupSelect.wrapper));
            
            // 稀有度
            const raritySelect = createSelect(
                ['白', '蓝', '橙', '彩'],
                card.base.rarity,
                (value) => {
                    card.base.rarity = value;
                    render();
                }
            );
            cardSection.appendChild(createFormGroup('稀有度(rarity):', raritySelect.wrapper));
            
            // 神明
            const godSelect = createSelect(
                ['circen', 'diallos', 'nihilum', 'secred', 'vitor'],
                card.base.god,
                (value) => {
                    card.base.god = value;
                    render();
                }
            );
            cardSection.appendChild(createFormGroup('神明:', godSelect.wrapper));
            
            // AP
            const apInput = createInput('text', card.base.ap, (value) => {
                card.base.ap = value;
                render();
            }, '整数/X/Ø');
            cardSection.appendChild(createFormGroup('AP:', apInput));
            
            // 卡牌类型
            const typeSelect = createSelect(
                ['攻击', '技能', '强化'],
                card.base.type,
                (value) => {
                    card.base.type = value;
                    render();
                }
            );
            cardSection.appendChild(createFormGroup('卡牌类型(type):', typeSelect.wrapper));
            
            // 机制
            const dictInput = createInput('text', card.base.dict, (value) => {
                card.base.dict = value;
                render();
            });
            cardSection.appendChild(createFormGroup('机制(dict):', dictInput));
            
            // 描述输入区按钮
            const descButtonGroup = createElement('div', 'button-group');
            descButtonGroup.appendChild(createButton('蓝色文本', 'btn-blue', () => {
                insertTextAtCursor(descInput, '{{文本|蓝|选择文字}}', true);
            }));
            descButtonGroup.appendChild(createButton('绿色文本', 'btn-green', () => {
                insertTextAtCursor(descInput, '{{文本|绿|选择文字}}', true);
            }));
            descButtonGroup.appendChild(createButton('绿色描边', 'btn-green', () => {
                insertTextAtCursor(descInput, '{{描边|绿|选择文字}}', true);
            }));
            descButtonGroup.appendChild(createButton('词典', 'btn', () => {
                insertTextAtCursor(descInput, '{{词典|选择文字}}', true);
            }));
            descButtonGroup.appendChild(createButton('换行', 'btn', () => {
                insertTextAtCursor(descInput, '<br>');
            }));
            
            cardSection.appendChild(createFormGroup('描述编辑工具:', descButtonGroup));
            
            // 描述
            const descInput = createInput('textarea', card.base.desc_global, (value) => {
                card.base.desc_global = value;
                render();
            }, '输入卡牌描述...');
            cardSection.appendChild(createFormGroup('描述(desc_global):', descInput));
            
            // 衍生卡牌
            const subInput = createInput('text', card.base.sub, (value) => {
                card.base.sub = value;
                render();
            });
            cardSection.appendChild(createFormGroup('衍生卡牌(sub):', subInput));
            
            // 是否存在灵光一闪
            const inspirationCheckbox = createCheckbox(card.base.isinspiration, (value) => {
                card.base.isinspiration = value;
                render();
            });
            cardSection.appendChild(createFormGroup('是否存在灵光一闪:', inspirationCheckbox));
            
            // 是否存在神光一闪
            const godInspirationCheckbox = createCheckbox(card.base.isgod_inspiration, (value) => {
                card.base.isgod_inspiration = value;
                render();
            });
            cardSection.appendChild(createFormGroup('是否存在神光一闪:', godInspirationCheckbox));
            
            inputSection.appendChild(cardSection);
        }
        
        // 添加新卡牌按钮
        const addCardBtn = createButton('+ 新增卡牌', 'btn-success', () => {
            const newCard = createEmptyCard();
            newCard.name = '新卡牌' + (state.cards.length + 1);
            state.cards.push(newCard);
            state.currentCard = newCard;
            render();
        });
        inputSection.appendChild(addCardBtn);
        
        manager.appendChild(inputSection);
        
        // 中间列表区
        const listSection = createElement('div', 'card-list-section');
        
        // 卡牌列表
        const cardListContainer = createElement('div', 'list-container');
        const cardListHeader = createElement('div', 'list-header');
        const cardListTitle = createElement('div', 'list-title');
        cardListTitle.textContent = '卡牌列表';
        cardListHeader.appendChild(cardListTitle);
        cardListContainer.appendChild(cardListHeader);
        
        if (state.cards.length === 0) {
            const emptyState = createElement('div', 'empty-state');
            const emptyIcon = createElement('div', 'empty-state-icon');
            emptyIcon.textContent = '📋';
            const emptyText = createElement('div', 'empty-state-text');
            emptyText.textContent = '暂无卡牌,点击"新增卡牌"开始创建';
            emptyState.appendChild(emptyIcon);
            emptyState.appendChild(emptyText);
            cardListContainer.appendChild(emptyState);
        } else {
            state.cards.forEach((card, index) => {
                const cardItem = createElement('div', 'card-item' + (state.currentCard === card ? ' active' : ''));
                
                const cardName = createElement('div', 'card-item-name');
                cardName.textContent = card.name || '未命名卡牌';
                
                const cardInfo = createElement('div', 'card-item-info');
                const infoText = [];
                if (card.base.type) infoText.push(card.base.type);
                if (card.base.ap) infoText.push('AP:' + card.base.ap);
                if (card.base.rarity) infoText.push(card.base.rarity);
                cardInfo.textContent = infoText.join(' | ') || '暂无信息';
                
                cardItem.appendChild(cardName);
                cardItem.appendChild(cardInfo);
                
                cardItem.addEventListener('click', () => {
                    state.currentCard = card;
                    state.editMode = 'base';
                    render();
                });
                
                // 删除按钮
                const deleteBtn = createButton('删除', 'btn-danger', (e) => {
                    e.stopPropagation();
                    if (confirm('确定要删除卡牌"' + card.name + '"吗?')) {
                        state.cards.splice(index, 1);
                        if (state.currentCard === card) {
                            state.currentCard = state.cards[0] || null;
                        }
                        render();
                    }
                });
                deleteBtn.style.cssText = 'margin-top:8px;width:100%;';
                cardItem.appendChild(deleteBtn);
                
                cardListContainer.appendChild(cardItem);
            });
        }
        
        listSection.appendChild(cardListContainer);
        
        // 灵光一闪列表
        if (state.currentCard && state.currentCard.base.isinspiration) {
            const inspirationSection = createElement('div', 'inspiration-section');
            const inspirationHeader = createElement('div', 'list-header');
            const inspirationTitle = createElement('div', 'list-title');
            inspirationTitle.textContent = '灵光一闪列表';
            inspirationHeader.appendChild(inspirationTitle);
            
            const addInspirationBtn = createButton('+ 添加', 'btn-primary', () => {
                state.currentCard.var.inspiration.push({
                    ap: '',
                    type: '',
                    desc_global: ''
                });
                render();
            });
            inspirationHeader.appendChild(addInspirationBtn);
            inspirationSection.appendChild(inspirationHeader);
            
            if (state.currentCard.var.inspiration.length === 0) {
                const emptyState = createElement('div', 'empty-state');
                emptyState.style.padding = '20px';
                const emptyText = createElement('div', 'empty-state-text');
                emptyText.textContent = '暂无灵光一闪,点击"添加"创建';
                emptyState.appendChild(emptyText);
                inspirationSection.appendChild(emptyState);
            } else {
                state.currentCard.var.inspiration.forEach((insp, idx) => {
                    const inspItem = createElement('div', 'inspiration-item');
                    
                    const inspHeader = createElement('div', 'inspiration-item-header');
                    const inspTitle = createElement('div', 'inspiration-item-title');
                    inspTitle.textContent = `灵光 #${idx + 1}`;
                    inspHeader.appendChild(inspTitle);
                    
                    const deleteInspBtn = createButton('删除', 'btn-danger', () => {
                        if (confirm('确定要删除这个灵光一闪吗?')) {
                            state.currentCard.var.inspiration.splice(idx, 1);
                            render();
                        }
                    });
                    deleteInspBtn.style.padding = '4px 8px';
                    deleteInspBtn.style.fontSize = '12px';
                    inspHeader.appendChild(deleteInspBtn);
                    inspItem.appendChild(inspHeader);
                    
                    // AP输入
                    const inspApInput = createInput('text', insp.ap, (value) => {
                        insp.ap = value;
                        render();
                    }, 'AP');
                    inspApInput.style.marginBottom = '8px';
                    inspApInput.style.fontSize = '13px';
                    inspItem.appendChild(inspApInput);
                    
                    // 类型选择
                    const inspTypeSelect = createSelect(
                        ['', '攻击', '技能', '强化'],
                        insp.type || '',
                        (value) => {
                            insp.type = value;
                            render();
                        }
                    );
                    inspTypeSelect.wrapper.style.marginBottom = '8px';
                    inspItem.appendChild(inspTypeSelect.wrapper);
                    
                    // 描述输入
                    const inspDescInput = createInput('textarea', insp.desc_global, (value) => {
                        insp.desc_global = value;
                        render();
                    }, '描述');
                    inspDescInput.style.minHeight = '60px';
                    inspDescInput.style.fontSize = '13px';
                    inspItem.appendChild(inspDescInput);
                    
                    inspirationSection.appendChild(inspItem);
                });
            }
            
            listSection.appendChild(inspirationSection);
        }
        
        // 神光一闪列表
        if (state.currentCard && state.currentCard.base.isgod_inspiration) {
            const godInspirationSection = createElement('div', 'inspiration-section');
            const godInspirationHeader = createElement('div', 'list-header');
            const godInspirationTitle = createElement('div', 'list-title');
            godInspirationTitle.textContent = '神光一闪列表';
            godInspirationHeader.appendChild(godInspirationTitle);
            godInspirationSection.appendChild(godInspirationHeader);
            
            // 神明选择标签
            const godSelectGroup = createElement('div', 'god-select-group');
            ['circen', 'diallos', 'nihilum', 'secred', 'vitor'].forEach(god => {
                const godTab = createElement('div', 'god-tab' + (state.currentGod === god ? ' active' : ''));
                godTab.textContent = god;
                godTab.addEventListener('click', () => {
                    state.currentGod = god;
                    render();
                });
                godSelectGroup.appendChild(godTab);
            });
            godInspirationSection.appendChild(godSelectGroup);
            
            // 当前神明的神光一闪列表
            const currentGodInspirations = state.currentCard.var.god_inspiration[state.currentGod];
            
            const addGodInspirationBtn = createButton('+ 添加 ' + state.currentGod + ' 神光', 'btn-primary', () => {
                currentGodInspirations.push({
                    ap: '',
                    type: '',
                    desc_global: ''
                });
                render();
            });
            addGodInspirationBtn.style.marginBottom = '10px';
            addGodInspirationBtn.style.width = '100%';
            godInspirationSection.appendChild(addGodInspirationBtn);
            
            if (currentGodInspirations.length === 0) {
                const emptyState = createElement('div', 'empty-state');
                emptyState.style.padding = '20px';
                const emptyText = createElement('div', 'empty-state-text');
                emptyText.textContent = `暂无 ${state.currentGod} 神光一闪`;
                emptyState.appendChild(emptyText);
                godInspirationSection.appendChild(emptyState);
            } else {
                currentGodInspirations.forEach((insp, idx) => {
                    const inspItem = createElement('div', 'inspiration-item');
                    
                    const inspHeader = createElement('div', 'inspiration-item-header');
                    const inspTitle = createElement('div', 'inspiration-item-title');
                    inspTitle.textContent = `${state.currentGod} 神光 #${idx + 1}`;
                    inspHeader.appendChild(inspTitle);
                    
                    const deleteInspBtn = createButton('删除', 'btn-danger', () => {
                        if (confirm('确定要删除这个神光一闪吗?')) {
                            currentGodInspirations.splice(idx, 1);
                            render();
                        }
                    });
                    deleteInspBtn.style.padding = '4px 8px';
                    deleteInspBtn.style.fontSize = '12px';
                    inspHeader.appendChild(deleteInspBtn);
                    inspItem.appendChild(inspHeader);
                    
                    // AP输入
                    const inspApInput = createInput('text', insp.ap, (value) => {
                        insp.ap = value;
                        render();
                    }, 'AP');
                    inspApInput.style.marginBottom = '8px';
                    inspApInput.style.fontSize = '13px';
                    inspItem.appendChild(inspApInput);
                    
                    // 类型选择
                    const inspTypeSelect = createSelect(
                        ['', '攻击', '技能', '强化'],
                        insp.type || '',
                        (value) => {
                            insp.type = value;
                            render();
                        }
                    );
                    inspTypeSelect.wrapper.style.marginBottom = '8px';
                    inspItem.appendChild(inspTypeSelect.wrapper);
                    
                    // 描述输入
                    const inspDescInput = createInput('textarea', insp.desc_global, (value) => {
                        insp.desc_global = value;
                        render();
                    }, '描述');
                    inspDescInput.style.minHeight = '60px';
                    inspDescInput.style.fontSize = '13px';
                    inspItem.appendChild(inspDescInput);
                    
                    godInspirationSection.appendChild(inspItem);
                });
            }
            
            listSection.appendChild(godInspirationSection);
        }
        
        manager.appendChild(listSection);
        
        // 右侧预览区
        const previewSection = createElement('div', 'card-preview-section');
        const previewTitle = createElement('div', 'section-title');
        previewTitle.textContent = 'Lua 代码预览';
        previewSection.appendChild(previewTitle);
        
        // 复制按钮
        const copyBtn = createButton('复制代码', 'btn-primary', () => {
            const code = generateLuaCode();
            navigator.clipboard.writeText(code).then(() => {
                alert('代码已复制到剪贴板!');
            }).catch(err => {
                console.error('复制失败:', err);
                // 降级方案
                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('代码已复制到剪贴板!');
            });
        });
        copyBtn.style.marginBottom = '10px';
        copyBtn.style.width = '100%';
        previewSection.appendChild(copyBtn);
        
        // 保存按钮
        const saveBtn = createButton('保存到Wiki', 'btn-success', async () => {
            if (!state.currentFighter) {
                alert('请先选择战斗员!');
                return;
            }
            
            const code = generateLuaCode();
            const pageName = '模块:卡牌/' + state.currentFighter;
            
            try {
                const api = new mw.Api();
                await api.postWithToken('csrf', {
                    action: 'edit',
                    title: pageName,
                    text: code,
                    summary: '通过卡牌管理器更新卡牌数据',
                    contentmodel: 'Scribunto'
                });
                alert('保存成功!');
            } catch (error) {
                console.error('保存失败:', error);
                alert('保存失败:' + error);
            }
        });
        saveBtn.style.marginBottom = '10px';
        saveBtn.style.width = '100%';
        previewSection.appendChild(saveBtn);
        
        // 代码显示
        const codePreview = createElement('div', 'code-preview');
        codePreview.textContent = generateLuaCode();
        previewSection.appendChild(codePreview);
        
        manager.appendChild(previewSection);
        
        container.appendChild(manager);
    }
    
    // 初始化
    async function init() {
        // 确保在正确的页面
        const pageName = mw.config.get('wgPageName');
        
        // 创建容器
        let container = document.getElementById('card-manager-container');
        if (!container) {
            container = createElement('div', '');
            container.id = 'card-manager-container';
            
            // 查找插入位置
            const content = document.getElementById('mw-content-text');
            if (content) {
                content.insertBefore(container, content.firstChild);
            } else {
                document.body.appendChild(container);
            }
        }
        
        // 加载战斗员列表
        await loadFighters();
        
        // 如果有战斗员,默认选择第一个
        if (state.fighters.length > 0) {
            state.currentFighter = state.fighters[0];
            state.cards = await loadFighterCards(state.currentFighter);
        }
        
        // 渲染界面
        render();
    }
    
    // 等待DOM加载完成后初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
    
    // 导出API供外部使用
    window.CardManager = {
        init: init,
        render: render,
        state: state,
        createCard: createEmptyCard,
        generateCode: generateLuaCode
    };
    
})();