MediaWiki

Dictionary.js:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
 
(未显示同一用户的5个中间版本)
第1行: 第1行:
/**
* MediaWiki词典编辑器
* 用于管理模块:词典/data中的词条数据
*/
(function() {
(function() {
     'use strict';
     'use strict';
      
      
     // 添加调试日志
     // 只在MediaWiki:Dictionary页面运行
    console.log('词典编辑器脚本已加载');
    console.log('当前页面:', mw.config.get('wgPageName'));
   
    // 检查页面名称
     if (mw.config.get('wgPageName') !== 'MediaWiki:Dictionary') {
     if (mw.config.get('wgPageName') !== 'MediaWiki:Dictionary') {
        console.log('不是目标页面,脚本退出');
         return;
         return;
     }
     }
      
      
     var API_URL = mw.util.wikiScript('api');
     var DictManager = {
    var dictionaryData = {};
        api: new mw.Api(),
   
        MODULE_PAGE: '模块:词典/data',
    // 加载词典数据
        dictionaryData: {},
    function loadDictionaryData() {
        currentEditKey: null,
         console.log('开始加载词典数据');
         currentEditIndex: null,
          
          
         // 直接使用备用方案:从模块页面加载
         // 类型选项
         loadFromModulePage();
         typeOptions: ['', '卡牌机制', '战斗员专属机制', 'buff', 'debuff'],
    }
         colorOptions: ['', '白', '蓝', '红', '橙', ''],
   
    // 从模块页面加载数据
    function loadFromModulePage() {
         console.log('从模块页面加载数据');
          
          
         $.ajax({
         // 初始化
            url: mw.util.getUrl('Module:词典/data', {action: 'raw'}),
        init: function() {
            dataType: 'text',
             this.createUI();
            success: function(content) {
             this.loadData();
                console.log('成功获取模块内容');
         },
                try {
                    dictionaryData = parseLuaTable(content);
                    console.log('解析的数据:', dictionaryData);
                    renderDictionary();
                } catch(e) {
                    console.error('解析Lua失败:', e);
                    showError('解析数据失败: ' + e.message);
                }
             },
            error: function(xhr, status, error) {
                console.error('加载模块失败:', status, error);
                showError('加载数据失败,请检查Module:词典/data是否存在');
             }
        });
    }
   
    // 显示错误信息
    function showError(message) {
        var container = findContentContainer();
        container.empty();
        $('<div>').addClass('errorbox').css({
            'padding': '10px',
            'margin': '10px 0',
            'border': '1px solid #d33',
            'background-color': '#fee',
            'color': '#d33'
         }).text(message).appendTo(container);
    }
   
    // 查找内容容器
    function findContentContainer() {
        // 尝试多个可能的选择器
        var selectors = [
            '#dictionary-editor',
            '#mw-content-text',
            '.mw-parser-output',
            '#bodyContent',
            '#content'
        ];
          
          
         var container;
         // 创建UI
         for (var i = 0; i < selectors.length; i++) {
         createUI: function() {
             container = $(selectors[i]);
            var container = document.createElement('div');
             if (container.length) {
             container.className = 'dict-editor';
                 console.log('找到容器:', selectors[i]);
             container.innerHTML = `
                break;
                <div class="dict-section">
             }
                    <h3>词典管理器</h3>
         }
                    <div id="dict-message"></div>
                   
                    <div class="dict-tabs">
                        <div class="dict-tab active" data-tab="list">词条列表</div>
                        <div class="dict-tab" data-tab="edit">编辑/新建</div>
                    </div>
                   
                    <div id="tab-list" class="dict-tab-content active">
                        <div class="dict-button success" id="dict-create-new">新建词条</div>
                        <div class="dict-button" id="dict-refresh">刷新数据</div>
                        <div id="dict-list-container" class="dict-loading">加载中...</div>
                    </div>
                   
                    <div id="tab-edit" class="dict-tab-content">
                        <div id="dict-editor-container"></div>
                    </div>
                 </div>
            `;
           
            var content = document.getElementById('mw-content-text');
            content.innerHTML = '';
            content.appendChild(container);
              
            this.bindEvents();
         },
          
          
         if (!container || !container.length) {
         // 绑定事件
             console.error('找不到内容容器');
        bindEvents: function() {
             container = $('body');
            var self = this;
         }
           
            // 标签切换
            document.querySelectorAll('.dict-tab').forEach(function(tab) {
                tab.addEventListener('click', function() {
                    self.switchTab(this.getAttribute('data-tab'));
                });
             });
           
            // 新建词条
            document.getElementById('dict-create-new').addEventListener('click', function() {
                self.createNew();
             });
           
            // 刷新数据
            document.getElementById('dict-refresh').addEventListener('click', function() {
                self.loadData();
            });
         },
          
          
         return container;
         // 切换标签
    }
        switchTab: function(tabName) {
   
            document.querySelectorAll('.dict-tab').forEach(function(tab) {
    // 简单的Lua表解析器(改进版)
                tab.classList.remove('active');
    function parseLuaTable(luaContent) {
            });
        var result = {};
            document.querySelectorAll('.dict-tab-content').forEach(function(content) {
        console.log('开始解析Lua表');
                content.classList.remove('active');
            });
           
            document.querySelector('[data-tab="' + tabName + '"]').classList.add('active');
            document.getElementById('tab-' + tabName).classList.add('active');
        },
          
          
         // 查找 dictionary 表
         // 加载数据
         var dictMatch = luaContent.match(/data\.dictionary\s*=\s*\{([\s\S]*?)\n\}/);
         loadData: function() {
        if (!dictMatch) {
            var self = this;
            console.error('找不到dictionary表');
            self.showMessage('加载中...', 'info');
             throw new Error('找不到dictionary表定义');
           
         }
            this.api.get({
                action: 'query',
                prop: 'revisions',
                titles: this.MODULE_PAGE,
                rvprop: 'content',
                rvslots: 'main',
                format: 'json'
            }).done(function(data) {
                var pages = data.query.pages;
                var pageId = Object.keys(pages)[0];
               
                if (pageId === '-1') {
                    self.showMessage('模块页面不存在', 'error');
                    return;
                }
               
                var content = pages[pageId].revisions[0].slots.main['*'];
                self.parseModuleData(content);
                self.renderList();
                self.showMessage('数据加载成功', 'success');
             }).fail(function() {
                self.showMessage('加载失败', 'error');
            });
         },
          
          
         var content = dictMatch[1];
         // 解析模块数据
        console.log('提取的内容长度:', content.length);
        parseModuleData: function(content) {
            try {
                this.dictionaryData = {};
               
                // 提取dictionary表
                var match = content.match(/data\.dictionary\s*=\s*\{([\s\S]*?)\n\}\s*\n*return/);
                if (!match) {
                    console.log('未找到dictionary定义');
                    return;
                }
               
                var dictContent = match[1];
               
                // 使用状态机解析
                var lines = dictContent.split('\n');
                var currentKey = null;
                var currentVariant = null;
                var inVariant = false;
               
                for (var i = 0; i < lines.length; i++) {
                    var line = lines[i];
                    var trimmed = line.trim();
                   
                    // 跳过空行
                    if (!trimmed) continue;
                   
                    // 1. 检测词条名称 ["xxx"] = {
                    var keyMatch = trimmed.match(/^\["([^"]+)"\]\s*=\s*\{/);
                    if (keyMatch) {
                        currentKey = keyMatch[1];
                        this.dictionaryData[currentKey] = [];
                        console.log('找到词条:', currentKey);
                        continue;
                    }
                   
                    // 2. 检测变体开始(独立的 { 行)
                    if (trimmed === '{' && currentKey && !inVariant) {
                        currentVariant = {
                            icon: '',
                            类型: '',
                            颜色: '',
                            描述: ''
                        };
                        inVariant = true;
                        continue;
                    }
                   
                    // 3. 在变体内部,提取字段
                    if (inVariant && currentVariant) {
                        var iconMatch = trimmed.match(/^\["icon"\]\s*=\s*"([^"]*)"/);
                        if (iconMatch) {
                            currentVariant.icon = iconMatch[1];
                            continue;
                        }
                       
                        var typeMatch = trimmed.match(/^\["类型"\]\s*=\s*"([^"]*)"/);
                        if (typeMatch) {
                            currentVariant.类型 = typeMatch[1];
                            continue;
                        }
                       
                        var colorMatch = trimmed.match(/^\["颜色"\]\s*=\s*"([^"]*)"/);
                        if (colorMatch) {
                            currentVariant.颜色 = colorMatch[1];
                            continue;
                        }
                       
                        var descMatch = trimmed.match(/^\["描述"\]\s*=\s*"([^"]*)"/);
                        if (descMatch) {
                            currentVariant.描述 = descMatch[1];
                            continue;
                        }
                    }
                   
                    // 4. 检测变体结束 }, 或 }
                    if (trimmed.match(/^\},?$/) && inVariant) {
                        if (currentVariant) {
                            this.dictionaryData[currentKey].push(currentVariant);
                            console.log('添加变体到', currentKey, ':', currentVariant);
                        }
                        currentVariant = null;
                        inVariant = false;
                        continue;
                    }
                   
                    // 5. 检测词条结束 },
                    if (trimmed === '},' && currentKey) {
                        console.log('词条结束:', currentKey, '共', this.dictionaryData[currentKey].length, '个变体');
                        currentKey = null;
                    }
                }
               
                console.log('=== 解析完成 ===');
                console.log('总词条数:', Object.keys(this.dictionaryData).length);
                for (var key in this.dictionaryData) {
                    console.log(' -', key, ':', this.dictionaryData[key].length, '个变体');
                }
               
            } catch (e) {
                console.error('解析错误:', e);
                console.error('错误堆栈:', e.stack);
                this.dictionaryData = {};
            }
        },
          
          
         // 匹配每个词条
         // 获取词条的所有类型
         var entryRegex = /\["([^"]+)"\]\s*=\s*\{([\s\S]*?)\n    \}/g;
         getEntryTypes: function(key) {
        var match;
            var variants = this.dictionaryData[key];
         var count = 0;
            var types = [];
            var typeSet = {};
           
            variants.forEach(function(variant) {
                if (variant.类型 && !typeSet[variant.类型]) {
                    typeSet[variant.类型] = true;
                    types.push(variant.类型);
                }
            });
           
            return types;
         },
          
          
         while ((match = entryRegex.exec(content)) !== null) {
         // 渲染列表
             var key = match[1];
        renderList: function() {
             var itemsContent = match[2];
             var self = this;
            result[key] = [];
             var container = document.getElementById('dict-list-container');
            count++;
              
              
             // 匹配每个定义
             if (Object.keys(this.dictionaryData).length === 0) {
             var itemRegex = /\{([^}]+)\}/g;
                container.innerHTML = '<div class="dict-message info">暂无词条,点击"新建词条"开始创建</div>';
             var itemMatch;
                return;
             while ((itemMatch = itemRegex.exec(itemsContent)) !== null) {
             }
                 var item = {};
           
                 var props = itemMatch[1].split(',');
             var html = '<div class="dict-grid">';
                 props.forEach(function(prop) {
             for (var key in this.dictionaryData) {
                    var propMatch = prop.match(/\["([^"]+)"\]\s*=\s*"([^"]*)"/);
                 var types = this.getEntryTypes(key);
                    if (propMatch) {
                 var typesText = types.join(', ') || '无类型';
                        item[propMatch[1]] = propMatch[2];
                  
                     }
                html += '<div class="dict-list-item" data-key="' + mw.html.escape(key) + '">';
                html += '<strong>' + mw.html.escape(key) + '</strong>';
                html += '<div style="margin-top: 5px; font-size: 12px; color: #72777d;">';
                html += mw.html.escape(typesText);
                html += '</div>';
                html += '</div>';
            }
            html += '</div>';
           
            container.innerHTML = html;
           
            document.querySelectorAll('.dict-list-item').forEach(function(item) {
                item.addEventListener('click', function() {
                    var key = this.getAttribute('data-key');
                     self.editEntry(key);
                 });
                 });
                result[key].push(item);
            });
            }
         },
         }
          
          
         console.log('解析了', count, '个词条');
         // 新建词条
        return result;
        createNew: function() {
    }
            this.currentEditKey = null;
   
            this.currentEditIndex = null;
    // 渲染词典界面
            this.switchTab('edit');
    function renderDictionary() {
            this.renderEditor();
        console.log('开始渲染词典界面');
            this.showMessage('请填写词条信息', 'info');
        },
          
          
         var container = findContentContainer();
         // 编辑词条
        editEntry: function(key) {
            this.currentEditKey = key;
            this.switchTab('edit');
            this.renderEditor();
        },
          
          
         // 清空现有内容
         // 渲染编辑器
         if (container.attr('id') !== 'dictionary-editor') {
         renderEditor: function() {
             container.empty();
            var self = this;
             container = $('<div>').attr('id', 'dictionary-editor').appendTo(container);
            var container = document.getElementById('dict-editor-container');
        } else {
              
             container.empty();
             var html = '<h4>' + (this.currentEditKey ? '编辑词条: ' + mw.html.escape(this.currentEditKey) : '新建词条') + '</h4>';
        }
           
       
             if (!this.currentEditKey) {
        // 添加样式
                // 新建模式
        addStyles();
                html += '<div class="dict-form-group">';
       
                html += '<label>词条名称 *</label>';
        // 添加标题和新建按钮
                html += '<input type="text" class="dict-input" id="dict-entry-name" placeholder="例如: 粉碎">';
        var header = $('<div>').addClass('dict-header').appendTo(container);
                html += '</div>';
        $('<div>').addClass('dict-title').text('词典编辑器').appendTo(header);
               
        $('<div>').addClass('dict-btn dict-btn-primary').text('+ 新建词条').click(showAddEntryDialog).appendTo(header);
                html += '<h4>变体信息</h4>';
       
                html += '<div class="dict-field-row">';
        // 渲染词条列表
                html += this.renderField('icon', 'text', '图标', '');
        var list = $('<div>').addClass('dict-list').appendTo(container);
                html += this.renderField('type', 'select', '类型 *', '', this.typeOptions);
       
                html += this.renderField('color', 'select', '颜色 *', '', this.colorOptions);
        var keys = Object.keys(dictionaryData).sort();
                 html += '</div>';
        console.log('渲染', keys.length, '个词条');
                html += this.renderField('desc', 'textarea', '描述 *', '');
       
        if (keys.length === 0) {
            $('<div>').css({'padding': '20px', 'text-align': 'center', 'color': '#666'})
                .text('暂无词条,点击"新建词条"添加')
                .appendTo(list);
            return;
        }
       
        keys.forEach(function(key) {
            var items = dictionaryData[key];
            items.forEach(function(item, index) {
                 var entry = $('<div>').addClass('dict-entry').appendTo(list);
                  
                  
                 var entryHeader = $('<div>').addClass('dict-entry-header').appendTo(entry);
                 html += '<div style="margin-top: 20px;">';
                 $('<div>').addClass('dict-entry-name').text(key).appendTo(entryHeader);
                html += '<div class="dict-button success" id="dict-save-new">保存词条</div>';
                 html += '<div class="dict-button secondary" id="dict-cancel-edit">取消</div>';
                html += '</div>';
            } else {
                // 编辑模式 - 显示所有变体
                var variants = this.dictionaryData[this.currentEditKey];
                  
                  
                 var actions = $('<div>').addClass('dict-entry-actions').appendTo(entryHeader);
                 html += '<div style="margin-bottom: 20px;">';
                 $('<div>').addClass('dict-btn dict-btn-small').text('编辑')
                html += '<div class="dict-button success" id="dict-add-variant">添加新变体</div>';
                    .click(function() { showEditDialog(key, index); }).appendTo(actions);
                 html += '<div class="dict-button danger" id="dict-delete-entry">删除整个词条</div>';
                 $('<div>').addClass('dict-btn dict-btn-small dict-btn-danger').text('删除')
                 html += '<div class="dict-button secondary" id="dict-back-to-list">返回列表</div>';
                    .click(function() { deleteEntry(key, index); }).appendTo(actions);
                html += '</div>';
                  
                  
                 var entryBody = $('<div>').addClass('dict-entry-body').appendTo(entry);
                 html += '<h4>现有变体</h4>';
                  
                  
                 var colorClass = 'dict-color-' + (item['颜色'] || 'white');
                 variants.forEach(function(variant, index) {
                $('<div>').addClass('dict-field').html('<span class="dict-label">颜色:</span> <span class="' + colorClass + '">' + (item['颜色'] || '') + '</span>').appendTo(entryBody);
                    var colorClass = self.getColorClass(variant.颜色);
                $('<div>').addClass('dict-field').html('<span class="dict-label">类型:</span> ' + (item['类型'] || '')).appendTo(entryBody);
                    html += '<div class="dict-variant" data-index="' + index + '">';
                $('<div>').addClass('dict-field').html('<span class="dict-label">图标:</span> ' + (item['icon'] || '')).appendTo(entryBody);
                    html += '<div class="dict-variant-header">';
                $('<div>').addClass('dict-field').html('<span class="dict-label">描述:</span> ' + (item['描述'] || '')).appendTo(entryBody);
                    html += '<span class="dict-badge ' + colorClass + '">' + mw.html.escape(variant.类型) + '</span>';
             });
                    html += '<span class="dict-badge ' + colorClass + '">' + mw.html.escape(variant.颜色) + '</span>';
         });
                    html += '<div class="dict-button" style="float: right; margin-left: 5px;" data-action="delete" data-index="' + index + '">删除</div>';
                    html += '<div class="dict-button" style="float: right;" data-action="edit" data-index="' + index + '">编辑</div>';
                    html += '</div>';
                    html += '<div class="dict-variant-desc">' + mw.html.escape(variant.描述) + '</div>';
                    if (variant.icon) {
                        html += '<div class="dict-variant-icon">图标: ' + mw.html.escape(variant.icon) + '</div>';
                    }
                    html += '</div>';
                });
            }
           
            html += '<div id="dict-preview-container"></div>';
           
            container.innerHTML = html;
           
            this.initCustomSelects();
             this.bindEditorEvents();
         },
          
          
         console.log('渲染完成');
         // 渲染表单字段
    }
        renderField: function(id, type, label, value, options) {
   
            var html = '<div class="dict-form-group">';
    // 添加样式
            html += '<label>' + mw.html.escape(label) + '</label>';
    function addStyles() {
           
        if ($('#dict-editor-styles').length) return;
            if (type === 'select') {
                html += '<div class="dict-custom-select" id="dict-' + id + '" data-value="' + mw.html.escape(value) + '">';
                html += '<div class="dict-select-display">' + (value || '请选择') + '</div>';
                html += '<div class="dict-select-options">';
                options.forEach(function(opt) {
                    html += '<div class="dict-select-option" data-value="' + mw.html.escape(opt) + '">' +
                            mw.html.escape(opt || '请选择') + '</div>';
                });
                html += '</div></div>';
            } else if (type === 'textarea') {
                html += '<textarea class="dict-textarea" id="dict-' + id + '">' + mw.html.escape(value) + '</textarea>';
            } else {
                html += '<input type="text" class="dict-input" id="dict-' + id + '" value="' + mw.html.escape(value) + '">';
            }
           
            html += '</div>';
            return html;
        },
          
          
         var css = `
         // 初始化自定义选择器
            .dict-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding: 20px; background: #f8f9fa; border-radius: 8px; }
        initCustomSelects: function() {
             .dict-title { font-size: 24px; font-weight: bold; }
             var self = this;
             .dict-btn { padding: 8px 16px; border-radius: 4px; cursor: pointer; display: inline-block; transition: all 0.2s; }
              
             .dict-btn:hover { opacity: 0.8; }
             document.querySelectorAll('.dict-custom-select').forEach(function(select) {
            .dict-btn-primary { background: #0645ad; color: white; }
                var display = select.querySelector('.dict-select-display');
            .dict-btn-secondary { background: #eee; color: #333; }
               
            .dict-btn-danger { background: #d33; color: white; }
                display.addEventListener('click', function(e) {
            .dict-btn-small { padding: 4px 12px; font-size: 12px; }
                    e.stopPropagation();
            .dict-list { display: flex; flex-direction: column; gap: 15px; }
                    // 关闭其他选择器
            .dict-entry { border: 1px solid #ddd; border-radius: 8px; overflow: hidden; }
                    document.querySelectorAll('.dict-custom-select').forEach(function(s) {
            .dict-entry-header { background: #f8f9fa; padding: 12px; display: flex; justify-content: space-between; align-items: center; }
                        if (s !== select) s.classList.remove('open');
            .dict-entry-name { font-weight: bold; font-size: 16px; }
                    });
            .dict-entry-actions { display: flex; gap: 8px; }
                    select.classList.toggle('open');
            .dict-entry-body { padding: 12px; }
                });
            .dict-field { margin: 8px 0; }
               
            .dict-label { font-weight: bold; color: #666; }
                select.querySelectorAll('.dict-select-option').forEach(function(option) {
            .dict-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; align-items: center; justify-content: center; }
                    option.addEventListener('click', function(e) {
            .dict-dialog { background: white; border-radius: 8px; width: 500px; max-width: 90%; max-height: 90vh; overflow-y: auto; }
                        e.stopPropagation();
             .dict-dialog-title { padding: 16px; border-bottom: 1px solid #ddd; font-size: 18px; font-weight: bold; }
                        var value = this.getAttribute('data-value');
             .dict-form { padding: 16px; }
                        select.setAttribute('data-value', value);
             .dict-form-group { margin-bottom: 16px; }
                        display.textContent = this.textContent;
             .dict-form-label { margin-bottom: 4px; font-weight: bold; }
                        select.classList.remove('open');
            .dict-input { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
                    });
            .dict-dialog-actions { padding: 16px; border-top: 1px solid #ddd; display: flex; justify-content: flex-end; gap: 8px; }
                });
            .dict-select-wrapper { position: relative; }
             });
            .dict-select { padding: 8px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; background: white; }
              
            .dict-dropdown { position: absolute; top: 100%; left: 0; right: 0; border: 1px solid #ddd; border-radius: 4px; background: white; margin-top: 4px; display: none; z-index: 1000; max-height: 200px; overflow-y: auto; }
             // 点击外部关闭
             .dict-option { padding: 8px; cursor: pointer; }
             document.addEventListener('click', function() {
            .dict-option:hover { background: #f0f0f0; }
                document.querySelectorAll('.dict-custom-select').forEach(function(s) {
         `;
                    s.classList.remove('open');
                });
             });
         },
          
          
         $('<style>').attr('id', 'dict-editor-styles').text(css).appendTo('head');
         // 绑定编辑器事件
    }
        bindEditorEvents: function() {
   
            var self = this;
    // 显示添加词条对话框
           
    function showAddEntryDialog() {
            var saveBtn = document.getElementById('dict-save-new');
        showDialog('新建词条', {}, function(data) {
            if (saveBtn) {
             var name = data.name;
                saveBtn.addEventListener('click', function() {
             delete data.name;
                    self.saveNewEntry();
                });
            }
           
            var cancelBtn = document.getElementById('dict-cancel-edit');
            if (cancelBtn) {
                cancelBtn.addEventListener('click', function() {
                    self.switchTab('list');
                });
            }
           
            var addVariantBtn = document.getElementById('dict-add-variant');
            if (addVariantBtn) {
                addVariantBtn.addEventListener('click', function() {
                    self.showVariantForm();
                });
            }
           
             var deleteEntryBtn = document.getElementById('dict-delete-entry');
             if (deleteEntryBtn) {
                deleteEntryBtn.addEventListener('click', function() {
                    if (confirm('确定要删除整个词条"' + self.currentEditKey + '"吗?')) {
                        delete self.dictionaryData[self.currentEditKey];
                        self.showMessage('正在保存到模块...', 'info');
                        self.saveToModule(function() {
                            self.switchTab('list');
                            self.renderList();
                        });
                    }
                });
            }
              
              
             if (!dictionaryData[name]) {
            var backBtn = document.getElementById('dict-back-to-list');
                 dictionaryData[name] = [];
             if (backBtn) {
                 backBtn.addEventListener('click', function() {
                    self.switchTab('list');
                });
             }
             }
             dictionaryData[name].push(data);
              
            saveDictionary();
            // 变体操作按钮
        }, true);
            document.querySelectorAll('[data-action]').forEach(function(btn) {
    }
                btn.addEventListener('click', function() {
   
                    var action = this.getAttribute('data-action');
    // 显示编辑对话框
                    var index = parseInt(this.getAttribute('data-index'));
    function showEditDialog(key, index) {
                   
        var item = dictionaryData[key][index];
                    if (action === 'edit') {
        var data = $.extend({name: key}, item);
                        self.editVariant(index);
                    } else if (action === 'delete') {
                        if (confirm('确定要删除这个变体吗?')) {
                            self.dictionaryData[self.currentEditKey].splice(index, 1);
                            if (self.dictionaryData[self.currentEditKey].length === 0) {
                                delete self.dictionaryData[self.currentEditKey];
                            }
                            self.showMessage('正在保存到模块...', 'info');
                            self.saveToModule(function() {
                                if (self.dictionaryData[self.currentEditKey]) {
                                    self.renderEditor();
                                } else {
                                    self.switchTab('list');
                                    self.renderList();
                                }
                            });
                        }
                    }
                });
            });
        },
          
          
         showDialog('编辑词条', data, function(newData) {
         // 保存新词条
             var newName = newData.name;
        saveNewEntry: function() {
             delete newData.name;
            var self = this;
            var name = document.getElementById('dict-entry-name').value.trim();
            var icon = document.getElementById('dict-icon').value.trim();
            var type = document.getElementById('dict-type').getAttribute('data-value');
            var color = document.getElementById('dict-color').getAttribute('data-value');
             var desc = document.getElementById('dict-desc').value.trim();
           
            if (!name || !type || !color || !desc) {
                this.showMessage('请填写所有必填字段', 'error');
                return;
             }
           
            var variant = {
                icon: icon,
                类型: type,
                颜色: color,
                描述: desc
            };
              
              
             if (newName !== key) {
             if (!this.dictionaryData[name]) {
                // 名称改变,删除旧的
                 this.dictionaryData[name] = [];
                dictionaryData[key].splice(index, 1);
                if (dictionaryData[key].length === 0) {
                    delete dictionaryData[key];
                 }
                if (!dictionaryData[newName]) {
                    dictionaryData[newName] = [];
                }
                dictionaryData[newName].push(newData);
            } else {
                dictionaryData[key][index] = newData;
             }
             }
             saveDictionary();
              
        }, false);
            this.dictionaryData[name].push(variant);
    }
            this.currentEditKey = name;
   
           
    // 显示对话框
            this.showMessage('正在保存到模块...', 'info');
    function showDialog(title, data, callback, isNew) {
            this.saveToModule(function() {
        var overlay = $('<div>').addClass('dict-overlay').appendTo('body');
                self.renderEditor();
        var dialog = $('<div>').addClass('dict-dialog').appendTo(overlay);
            });
        },
          
          
         $('<div>').addClass('dict-dialog-title').text(title).appendTo(dialog);
         // 显示变体表单
        showVariantForm: function() {
            var self = this;
            var preview = document.getElementById('dict-preview-container');
           
            var html = '<h4>添加新变体</h4>';
            html += '<div class="dict-field-row">';
            html += this.renderField('new-icon', 'text', '图标', '');
            html += this.renderField('new-type', 'select', '类型 *', '', this.typeOptions);
            html += this.renderField('new-color', 'select', '颜色 *', '', this.colorOptions);
            html += '</div>';
            html += this.renderField('new-desc', 'textarea', '描述 *', '');
            html += '<div style="margin-top: 10px;">';
            html += '<div class="dict-button success" id="dict-save-variant">保存变体</div>';
            html += '<div class="dict-button secondary" id="dict-cancel-variant">取消</div>';
            html += '</div>';
           
            preview.innerHTML = html;
           
            this.initCustomSelects();
           
            document.getElementById('dict-save-variant').addEventListener('click', function() {
                self.saveNewVariant();
            });
           
            document.getElementById('dict-cancel-variant').addEventListener('click', function() {
                preview.innerHTML = '';
            });
        },
          
          
         var form = $('<div>').addClass('dict-form').appendTo(dialog);
         // 保存新变体
        saveNewVariant: function() {
            var self = this;
            var icon = document.getElementById('dict-new-icon').value.trim();
            var type = document.getElementById('dict-new-type').getAttribute('data-value');
            var color = document.getElementById('dict-new-color').getAttribute('data-value');
            var desc = document.getElementById('dict-new-desc').value.trim();
           
            if (!type || !color || !desc) {
                this.showMessage('请填写所有必填字段', 'error');
                return;
            }
           
            var variant = {
                icon: icon,
                类型: type,
                颜色: color,
                描述: desc
            };
           
            this.dictionaryData[this.currentEditKey].push(variant);
           
            this.showMessage('正在保存到模块...', 'info');
            this.saveToModule(function() {
                self.renderEditor();
            });
        },
          
          
         // 名称字段
         // 编辑变体
         var nameField = createField('名称', 'text', data.name || '', isNew);
         editVariant: function(index) {
        form.append(nameField);
            var self = this;
            var variant = this.dictionaryData[this.currentEditKey][index];
            var preview = document.getElementById('dict-preview-container');
           
            var html = '<h4>编辑变体</h4>';
            html += '<div class="dict-field-row">';
            html += this.renderField('edit-icon', 'text', '图标', variant.icon);
            html += this.renderField('edit-type', 'select', '类型 *', variant.类型, this.typeOptions);
            html += this.renderField('edit-color', 'select', '颜色 *', variant.颜色, this.colorOptions);
            html += '</div>';
            html += this.renderField('edit-desc', 'textarea', '描述 *', variant.描述);
            html += '<div style="margin-top: 10px;">';
            html += '<div class="dict-button success" id="dict-update-variant" data-index="' + index + '">更新变体</div>';
            html += '<div class="dict-button secondary" id="dict-cancel-edit-variant">取消</div>';
            html += '</div>';
           
            preview.innerHTML = html;
           
            this.initCustomSelects();
           
            document.getElementById('dict-update-variant').addEventListener('click', function() {
                var idx = parseInt(this.getAttribute('data-index'));
                self.updateVariant(idx);
            });
           
            document.getElementById('dict-cancel-edit-variant').addEventListener('click', function() {
                preview.innerHTML = '';
            });
        },
          
          
         // 类型字段(下拉)
         // 更新变体
         var typeField = createSelectField('类型', ['卡牌机制', '战斗员专属机制', 'buff', 'debuff'], data['类型'] || '');
         updateVariant: function(index) {
        form.append(typeField);
            var self = this;
       
            var icon = document.getElementById('dict-edit-icon').value.trim();
        // 颜色字段(下拉)
            var type = document.getElementById('dict-edit-type').getAttribute('data-value');
        var colorField = createSelectField('颜色', ['白', '蓝', '红', '橙', '彩'], data['颜色'] || '');
             var color = document.getElementById('dict-edit-color').getAttribute('data-value');
        form.append(colorField);
            var desc = document.getElementById('dict-edit-desc').value.trim();
       
        // 图标字段
        var iconField = createField('图标', 'text', data['icon'] || '', true);
        form.append(iconField);
       
        // 描述字段
        var descField = createField('描述', 'textarea', data['描述'] || '', true);
        form.append(descField);
       
        var actions = $('<div>').addClass('dict-dialog-actions').appendTo(dialog);
        $('<div>').addClass('dict-btn dict-btn-secondary').text('取消').click(function() {
            overlay.remove();
        }).appendTo(actions);
       
        $('<div>').addClass('dict-btn dict-btn-primary').text('保存').click(function() {
             var formData = {
                name: nameField.find('input').val(),
                '类型': typeField.find('.dict-select').attr('data-value'),
                '颜色': colorField.find('.dict-select').attr('data-value'),
                'icon': iconField.find('input').val(),
                '描述': descField.find('textarea').val()
            };
              
              
             if (!formData.name) {
             if (!type || !color || !desc) {
                 alert('请输入名称');
                 this.showMessage('请填写所有必填字段', 'error');
                 return;
                 return;
             }
             }
              
              
             overlay.remove();
             this.dictionaryData[this.currentEditKey][index] = {
            callback(formData);
                icon: icon,
        }).appendTo(actions);
                类型: type,
    }
                颜色: color,
   
                描述: desc
    // 创建表单字段
            };
    function createField(label, type, value, editable) {
           
        var field = $('<div>').addClass('dict-form-group');
            this.showMessage('正在保存到模块...', 'info');
        $('<div>').addClass('dict-form-label').text(label + ':').appendTo(field);
            this.saveToModule(function() {
                self.renderEditor();
            });
        },
          
          
         var input;
         // 保存到模块
         if (type === 'textarea') {
         saveToModule: function(callback) {
            input = $('<textarea>').addClass('dict-input').val(value).attr('rows', 3);
            var self = this;
        } else {
           
            input = $('<input>').addClass('dict-input').attr('type', type).val(value);
            var luaContent = this.generateLuaContent();
         }
           
            this.api.postWithToken('csrf', {
                action: 'edit',
                title: this.MODULE_PAGE,
                text: luaContent,
                summary: '通过词典管理器更新',
                format: 'json'
            }).done(function() {
                self.showMessage('保存成功!', 'success');
                if (callback) callback();
            }).fail(function(code, error) {
                console.error('保存失败:', code, error);
                self.showMessage('保存失败: ' + (error.error ? error.error.info : '未知错误'), 'error');
            });
         },
          
          
         if (!editable) {
         // 生成Lua内容
             input.attr('readonly', 'readonly');
        generateLuaContent: function() {
        }
             var self = this;
       
            var lua = 'local data = {}\n\ndata.dictionary = {\n';
        input.appendTo(field);
   
        return field;
            var entries = Object.keys(this.dictionaryData).sort();
    }
      
      
    // 创建下拉选择字段
            entries.forEach(function(key) {
    function createSelectField(label, options, value) {
                var variants = self.dictionaryData[key];
        var field = $('<div>').addClass('dict-form-group');
                lua += '   ["' + key + '"] = {\n';
        $('<div>').addClass('dict-form-label').text(label + ':').appendTo(field);
          
          
        var selectWrapper = $('<div>').addClass('dict-select-wrapper').appendTo(field);
                variants.forEach(function(variant) {
        var selectDisplay = $('<div>').addClass('dict-select')
                    lua += '        {\n';
            .attr('data-value', value || options[0])
                    lua += '            ["icon"] = "' + (variant.icon || '') + '",\n';
            .text(value || options[0])
                    lua += '           ["类型"] = "' + variant.类型 + '",\n';
            .appendTo(selectWrapper);
                    lua += '            ["颜色"] = "' + variant.颜色 + '",\n';
                    lua += '           ["描述"] = "' + variant.描述 + '",\n';
                    lua += '        },\n';
                });
          
          
        var dropdown = $('<div>').addClass('dict-dropdown').appendTo(selectWrapper);
                lua += '   },\n';
       
             });
        options.forEach(function(opt) {
            $('<div>').addClass('dict-option').text(opt).click(function() {
                selectDisplay.text(opt).attr('data-value', opt);
                dropdown.hide();
            }).appendTo(dropdown);
        });
       
        selectDisplay.click(function(e) {
            e.stopPropagation();
            $('.dict-dropdown').hide();
             dropdown.toggle();
        });
       
        $(document).click(function() {
            dropdown.hide();
        });
       
        return field;
    }
      
      
    // 删除词条
            lua += '}\n\nreturn data\n';
    function deleteEntry(key, index) {
             return lua;
        if (!confirm('确定要删除这个词条吗?')) {
         },
             return;
         }
          
          
         dictionaryData[key].splice(index, 1);
         // 获取颜色类名
         if (dictionaryData[key].length === 0) {
         getColorClass: function(color) {
             delete dictionaryData[key];
             var colorMap = {
        }
                '白': 'dict-badge-white',
        saveDictionary();
                '蓝': 'dict-badge-blue',
    }
                '红': 'dict-badge-red',
   
                '橙': 'dict-badge-orange',
    // 保存词典到模块
                '彩': 'dict-badge-rainbow'
    function saveDictionary() {
            };
         var luaCode = generateLuaCode();
            return colorMap[color] || 'dict-badge-white';
         },
          
          
         // 使用新的API获取token
         // 显示消息
         new mw.Api().postWithToken('csrf', {
         showMessage: function(message, type) {
             action: 'edit',
             var container = document.getElementById('dict-message');
             title: 'Module:词典/data',
             container.innerHTML = '<div class="dict-message ' + type + '">' + mw.html.escape(message) + '</div>';
            text: luaCode,
           
            summary: '通过词典编辑器更新'
             if (type === 'success' || type === 'error') {
        }).done(function(response) {
                 setTimeout(function() {
             if (response.edit && response.edit.result === 'Success') {
                    container.innerHTML = '';
                mw.notify('保存成功!', {type: 'success'});
                }, 5000);
                 loadDictionaryData(); // 重新加载数据
            } else {
                mw.notify('保存失败:' + (response.error ? response.error.info : '未知错误'), {type: 'error'});
             }
             }
         }).fail(function(code, result) {
         }
            console.error('保存失败:', code, result);
    };
            mw.notify('保存失败:' + (result.error ? result.error.info : '网络错误'), {type: 'error'});
        });
    }
      
      
     // 生成Lua代码
     // 页面加载完成后初始化
     function generateLuaCode() {
     $(function() {
         var lines = ['local data = {}', '', 'data.dictionary = {'];
         DictManager.init();
       
    });
        var keys = Object.keys(dictionaryData).sort();
        keys.forEach(function(key, keyIndex) {
            lines.push('    ["' + key + '"] = {');
           
            dictionaryData[key].forEach(function(item, itemIndex) {
                lines.push('        {');
                lines.push('            ["icon"] = "' + (item.icon || '') + '",');
                lines.push('            ["类型"] = "' + (item['类型'] || '') + '",');
                lines.push('            ["颜色"] = "' + (item['颜色'] || '') + '",');
                lines.push('            ["描述"] = "' + (item['描述'] || '') + '",');
                lines.push('        }' + (itemIndex < dictionaryData[key].length - 1 ? ',' : ''));
            });
           
            lines.push('    }' + (keyIndex < keys.length - 1 ? ',' : ''));
        });
       
        lines.push('}', '', 'return data');
        return lines.join('\n');
    }
      
      
    // 初始化 - 确保DOM已加载
    if (document.readyState === 'loading') {
        $(document).ready(function() {
            console.log('DOM已加载,初始化词典编辑器');
            loadDictionaryData();
        });
    } else {
        console.log('DOM已经准备好,立即初始化');
        loadDictionaryData();
    }
})();
})();

2025年10月4日 (六) 10:21的最新版本

/**
 * MediaWiki词典编辑器
 * 用于管理模块:词典/data中的词条数据
 */
(function() {
    'use strict';
    
    // 只在MediaWiki:Dictionary页面运行
    if (mw.config.get('wgPageName') !== 'MediaWiki:Dictionary') {
        return;
    }
    
    var DictManager = {
        api: new mw.Api(),
        MODULE_PAGE: '模块:词典/data',
        dictionaryData: {},
        currentEditKey: null,
        currentEditIndex: null,
        
        // 类型选项
        typeOptions: ['', '卡牌机制', '战斗员专属机制', 'buff', 'debuff'],
        colorOptions: ['', '白', '蓝', '红', '橙', '彩'],
        
        // 初始化
        init: function() {
            this.createUI();
            this.loadData();
        },
        
        // 创建UI
        createUI: function() {
            var container = document.createElement('div');
            container.className = 'dict-editor';
            container.innerHTML = `
                <div class="dict-section">
                    <h3>词典管理器</h3>
                    <div id="dict-message"></div>
                    
                    <div class="dict-tabs">
                        <div class="dict-tab active" data-tab="list">词条列表</div>
                        <div class="dict-tab" data-tab="edit">编辑/新建</div>
                    </div>
                    
                    <div id="tab-list" class="dict-tab-content active">
                        <div class="dict-button success" id="dict-create-new">新建词条</div>
                        <div class="dict-button" id="dict-refresh">刷新数据</div>
                        <div id="dict-list-container" class="dict-loading">加载中...</div>
                    </div>
                    
                    <div id="tab-edit" class="dict-tab-content">
                        <div id="dict-editor-container"></div>
                    </div>
                </div>
            `;
            
            var content = document.getElementById('mw-content-text');
            content.innerHTML = '';
            content.appendChild(container);
            
            this.bindEvents();
        },
        
        // 绑定事件
        bindEvents: function() {
            var self = this;
            
            // 标签切换
            document.querySelectorAll('.dict-tab').forEach(function(tab) {
                tab.addEventListener('click', function() {
                    self.switchTab(this.getAttribute('data-tab'));
                });
            });
            
            // 新建词条
            document.getElementById('dict-create-new').addEventListener('click', function() {
                self.createNew();
            });
            
            // 刷新数据
            document.getElementById('dict-refresh').addEventListener('click', function() {
                self.loadData();
            });
        },
        
        // 切换标签
        switchTab: function(tabName) {
            document.querySelectorAll('.dict-tab').forEach(function(tab) {
                tab.classList.remove('active');
            });
            document.querySelectorAll('.dict-tab-content').forEach(function(content) {
                content.classList.remove('active');
            });
            
            document.querySelector('[data-tab="' + tabName + '"]').classList.add('active');
            document.getElementById('tab-' + tabName).classList.add('active');
        },
        
        // 加载数据
        loadData: function() {
            var self = this;
            self.showMessage('加载中...', 'info');
            
            this.api.get({
                action: 'query',
                prop: 'revisions',
                titles: this.MODULE_PAGE,
                rvprop: 'content',
                rvslots: 'main',
                format: 'json'
            }).done(function(data) {
                var pages = data.query.pages;
                var pageId = Object.keys(pages)[0];
                
                if (pageId === '-1') {
                    self.showMessage('模块页面不存在', 'error');
                    return;
                }
                
                var content = pages[pageId].revisions[0].slots.main['*'];
                self.parseModuleData(content);
                self.renderList();
                self.showMessage('数据加载成功', 'success');
            }).fail(function() {
                self.showMessage('加载失败', 'error');
            });
        },
        
        // 解析模块数据
        parseModuleData: function(content) {
            try {
                this.dictionaryData = {};
                
                // 提取dictionary表
                var match = content.match(/data\.dictionary\s*=\s*\{([\s\S]*?)\n\}\s*\n*return/);
                if (!match) {
                    console.log('未找到dictionary定义');
                    return;
                }
                
                var dictContent = match[1];
                
                // 使用状态机解析
                var lines = dictContent.split('\n');
                var currentKey = null;
                var currentVariant = null;
                var inVariant = false;
                
                for (var i = 0; i < lines.length; i++) {
                    var line = lines[i];
                    var trimmed = line.trim();
                    
                    // 跳过空行
                    if (!trimmed) continue;
                    
                    // 1. 检测词条名称 ["xxx"] = {
                    var keyMatch = trimmed.match(/^\["([^"]+)"\]\s*=\s*\{/);
                    if (keyMatch) {
                        currentKey = keyMatch[1];
                        this.dictionaryData[currentKey] = [];
                        console.log('找到词条:', currentKey);
                        continue;
                    }
                    
                    // 2. 检测变体开始(独立的 { 行)
                    if (trimmed === '{' && currentKey && !inVariant) {
                        currentVariant = {
                            icon: '',
                            类型: '',
                            颜色: '',
                            描述: ''
                        };
                        inVariant = true;
                        continue;
                    }
                    
                    // 3. 在变体内部,提取字段
                    if (inVariant && currentVariant) {
                        var iconMatch = trimmed.match(/^\["icon"\]\s*=\s*"([^"]*)"/);
                        if (iconMatch) {
                            currentVariant.icon = iconMatch[1];
                            continue;
                        }
                        
                        var typeMatch = trimmed.match(/^\["类型"\]\s*=\s*"([^"]*)"/);
                        if (typeMatch) {
                            currentVariant.类型 = typeMatch[1];
                            continue;
                        }
                        
                        var colorMatch = trimmed.match(/^\["颜色"\]\s*=\s*"([^"]*)"/);
                        if (colorMatch) {
                            currentVariant.颜色 = colorMatch[1];
                            continue;
                        }
                        
                        var descMatch = trimmed.match(/^\["描述"\]\s*=\s*"([^"]*)"/);
                        if (descMatch) {
                            currentVariant.描述 = descMatch[1];
                            continue;
                        }
                    }
                    
                    // 4. 检测变体结束 }, 或 }
                    if (trimmed.match(/^\},?$/) && inVariant) {
                        if (currentVariant) {
                            this.dictionaryData[currentKey].push(currentVariant);
                            console.log('添加变体到', currentKey, ':', currentVariant);
                        }
                        currentVariant = null;
                        inVariant = false;
                        continue;
                    }
                    
                    // 5. 检测词条结束 },
                    if (trimmed === '},' && currentKey) {
                        console.log('词条结束:', currentKey, '共', this.dictionaryData[currentKey].length, '个变体');
                        currentKey = null;
                    }
                }
                
                console.log('=== 解析完成 ===');
                console.log('总词条数:', Object.keys(this.dictionaryData).length);
                for (var key in this.dictionaryData) {
                    console.log('  -', key, ':', this.dictionaryData[key].length, '个变体');
                }
                
            } catch (e) {
                console.error('解析错误:', e);
                console.error('错误堆栈:', e.stack);
                this.dictionaryData = {};
            }
        },
        
        // 获取词条的所有类型
        getEntryTypes: function(key) {
            var variants = this.dictionaryData[key];
            var types = [];
            var typeSet = {};
            
            variants.forEach(function(variant) {
                if (variant.类型 && !typeSet[variant.类型]) {
                    typeSet[variant.类型] = true;
                    types.push(variant.类型);
                }
            });
            
            return types;
        },
        
        // 渲染列表
        renderList: function() {
            var self = this;
            var container = document.getElementById('dict-list-container');
            
            if (Object.keys(this.dictionaryData).length === 0) {
                container.innerHTML = '<div class="dict-message info">暂无词条,点击"新建词条"开始创建</div>';
                return;
            }
            
            var html = '<div class="dict-grid">';
            for (var key in this.dictionaryData) {
                var types = this.getEntryTypes(key);
                var typesText = types.join(', ') || '无类型';
                
                html += '<div class="dict-list-item" data-key="' + mw.html.escape(key) + '">';
                html += '<strong>' + mw.html.escape(key) + '</strong>';
                html += '<div style="margin-top: 5px; font-size: 12px; color: #72777d;">';
                html += mw.html.escape(typesText);
                html += '</div>';
                html += '</div>';
            }
            html += '</div>';
            
            container.innerHTML = html;
            
            document.querySelectorAll('.dict-list-item').forEach(function(item) {
                item.addEventListener('click', function() {
                    var key = this.getAttribute('data-key');
                    self.editEntry(key);
                });
            });
        },
        
        // 新建词条
        createNew: function() {
            this.currentEditKey = null;
            this.currentEditIndex = null;
            this.switchTab('edit');
            this.renderEditor();
            this.showMessage('请填写词条信息', 'info');
        },
        
        // 编辑词条
        editEntry: function(key) {
            this.currentEditKey = key;
            this.switchTab('edit');
            this.renderEditor();
        },
        
        // 渲染编辑器
        renderEditor: function() {
            var self = this;
            var container = document.getElementById('dict-editor-container');
            
            var html = '<h4>' + (this.currentEditKey ? '编辑词条: ' + mw.html.escape(this.currentEditKey) : '新建词条') + '</h4>';
            
            if (!this.currentEditKey) {
                // 新建模式
                html += '<div class="dict-form-group">';
                html += '<label>词条名称 *</label>';
                html += '<input type="text" class="dict-input" id="dict-entry-name" placeholder="例如: 粉碎">';
                html += '</div>';
                
                html += '<h4>变体信息</h4>';
                html += '<div class="dict-field-row">';
                html += this.renderField('icon', 'text', '图标', '');
                html += this.renderField('type', 'select', '类型 *', '', this.typeOptions);
                html += this.renderField('color', 'select', '颜色 *', '', this.colorOptions);
                html += '</div>';
                html += this.renderField('desc', 'textarea', '描述 *', '');
                
                html += '<div style="margin-top: 20px;">';
                html += '<div class="dict-button success" id="dict-save-new">保存词条</div>';
                html += '<div class="dict-button secondary" id="dict-cancel-edit">取消</div>';
                html += '</div>';
            } else {
                // 编辑模式 - 显示所有变体
                var variants = this.dictionaryData[this.currentEditKey];
                
                html += '<div style="margin-bottom: 20px;">';
                html += '<div class="dict-button success" id="dict-add-variant">添加新变体</div>';
                html += '<div class="dict-button danger" id="dict-delete-entry">删除整个词条</div>';
                html += '<div class="dict-button secondary" id="dict-back-to-list">返回列表</div>';
                html += '</div>';
                
                html += '<h4>现有变体</h4>';
                
                variants.forEach(function(variant, index) {
                    var colorClass = self.getColorClass(variant.颜色);
                    html += '<div class="dict-variant" data-index="' + index + '">';
                    html += '<div class="dict-variant-header">';
                    html += '<span class="dict-badge ' + colorClass + '">' + mw.html.escape(variant.类型) + '</span>';
                    html += '<span class="dict-badge ' + colorClass + '">' + mw.html.escape(variant.颜色) + '</span>';
                    html += '<div class="dict-button" style="float: right; margin-left: 5px;" data-action="delete" data-index="' + index + '">删除</div>';
                    html += '<div class="dict-button" style="float: right;" data-action="edit" data-index="' + index + '">编辑</div>';
                    html += '</div>';
                    html += '<div class="dict-variant-desc">' + mw.html.escape(variant.描述) + '</div>';
                    if (variant.icon) {
                        html += '<div class="dict-variant-icon">图标: ' + mw.html.escape(variant.icon) + '</div>';
                    }
                    html += '</div>';
                });
            }
            
            html += '<div id="dict-preview-container"></div>';
            
            container.innerHTML = html;
            
            this.initCustomSelects();
            this.bindEditorEvents();
        },
        
        // 渲染表单字段
        renderField: function(id, type, label, value, options) {
            var html = '<div class="dict-form-group">';
            html += '<label>' + mw.html.escape(label) + '</label>';
            
            if (type === 'select') {
                html += '<div class="dict-custom-select" id="dict-' + id + '" data-value="' + mw.html.escape(value) + '">';
                html += '<div class="dict-select-display">' + (value || '请选择') + '</div>';
                html += '<div class="dict-select-options">';
                options.forEach(function(opt) {
                    html += '<div class="dict-select-option" data-value="' + mw.html.escape(opt) + '">' + 
                            mw.html.escape(opt || '请选择') + '</div>';
                });
                html += '</div></div>';
            } else if (type === 'textarea') {
                html += '<textarea class="dict-textarea" id="dict-' + id + '">' + mw.html.escape(value) + '</textarea>';
            } else {
                html += '<input type="text" class="dict-input" id="dict-' + id + '" value="' + mw.html.escape(value) + '">';
            }
            
            html += '</div>';
            return html;
        },
        
        // 初始化自定义选择器
        initCustomSelects: function() {
            var self = this;
            
            document.querySelectorAll('.dict-custom-select').forEach(function(select) {
                var display = select.querySelector('.dict-select-display');
                
                display.addEventListener('click', function(e) {
                    e.stopPropagation();
                    // 关闭其他选择器
                    document.querySelectorAll('.dict-custom-select').forEach(function(s) {
                        if (s !== select) s.classList.remove('open');
                    });
                    select.classList.toggle('open');
                });
                
                select.querySelectorAll('.dict-select-option').forEach(function(option) {
                    option.addEventListener('click', function(e) {
                        e.stopPropagation();
                        var value = this.getAttribute('data-value');
                        select.setAttribute('data-value', value);
                        display.textContent = this.textContent;
                        select.classList.remove('open');
                    });
                });
            });
            
            // 点击外部关闭
            document.addEventListener('click', function() {
                document.querySelectorAll('.dict-custom-select').forEach(function(s) {
                    s.classList.remove('open');
                });
            });
        },
        
        // 绑定编辑器事件
        bindEditorEvents: function() {
            var self = this;
            
            var saveBtn = document.getElementById('dict-save-new');
            if (saveBtn) {
                saveBtn.addEventListener('click', function() {
                    self.saveNewEntry();
                });
            }
            
            var cancelBtn = document.getElementById('dict-cancel-edit');
            if (cancelBtn) {
                cancelBtn.addEventListener('click', function() {
                    self.switchTab('list');
                });
            }
            
            var addVariantBtn = document.getElementById('dict-add-variant');
            if (addVariantBtn) {
                addVariantBtn.addEventListener('click', function() {
                    self.showVariantForm();
                });
            }
            
            var deleteEntryBtn = document.getElementById('dict-delete-entry');
            if (deleteEntryBtn) {
                deleteEntryBtn.addEventListener('click', function() {
                    if (confirm('确定要删除整个词条"' + self.currentEditKey + '"吗?')) {
                        delete self.dictionaryData[self.currentEditKey];
                        self.showMessage('正在保存到模块...', 'info');
                        self.saveToModule(function() {
                            self.switchTab('list');
                            self.renderList();
                        });
                    }
                });
            }
            
            var backBtn = document.getElementById('dict-back-to-list');
            if (backBtn) {
                backBtn.addEventListener('click', function() {
                    self.switchTab('list');
                });
            }
            
            // 变体操作按钮
            document.querySelectorAll('[data-action]').forEach(function(btn) {
                btn.addEventListener('click', function() {
                    var action = this.getAttribute('data-action');
                    var index = parseInt(this.getAttribute('data-index'));
                    
                    if (action === 'edit') {
                        self.editVariant(index);
                    } else if (action === 'delete') {
                        if (confirm('确定要删除这个变体吗?')) {
                            self.dictionaryData[self.currentEditKey].splice(index, 1);
                            if (self.dictionaryData[self.currentEditKey].length === 0) {
                                delete self.dictionaryData[self.currentEditKey];
                            }
                            self.showMessage('正在保存到模块...', 'info');
                            self.saveToModule(function() {
                                if (self.dictionaryData[self.currentEditKey]) {
                                    self.renderEditor();
                                } else {
                                    self.switchTab('list');
                                    self.renderList();
                                }
                            });
                        }
                    }
                });
            });
        },
        
        // 保存新词条
        saveNewEntry: function() {
            var self = this;
            var name = document.getElementById('dict-entry-name').value.trim();
            var icon = document.getElementById('dict-icon').value.trim();
            var type = document.getElementById('dict-type').getAttribute('data-value');
            var color = document.getElementById('dict-color').getAttribute('data-value');
            var desc = document.getElementById('dict-desc').value.trim();
            
            if (!name || !type || !color || !desc) {
                this.showMessage('请填写所有必填字段', 'error');
                return;
            }
            
            var variant = {
                icon: icon,
                类型: type,
                颜色: color,
                描述: desc
            };
            
            if (!this.dictionaryData[name]) {
                this.dictionaryData[name] = [];
            }
            
            this.dictionaryData[name].push(variant);
            this.currentEditKey = name;
            
            this.showMessage('正在保存到模块...', 'info');
            this.saveToModule(function() {
                self.renderEditor();
            });
        },
        
        // 显示变体表单
        showVariantForm: function() {
            var self = this;
            var preview = document.getElementById('dict-preview-container');
            
            var html = '<h4>添加新变体</h4>';
            html += '<div class="dict-field-row">';
            html += this.renderField('new-icon', 'text', '图标', '');
            html += this.renderField('new-type', 'select', '类型 *', '', this.typeOptions);
            html += this.renderField('new-color', 'select', '颜色 *', '', this.colorOptions);
            html += '</div>';
            html += this.renderField('new-desc', 'textarea', '描述 *', '');
            html += '<div style="margin-top: 10px;">';
            html += '<div class="dict-button success" id="dict-save-variant">保存变体</div>';
            html += '<div class="dict-button secondary" id="dict-cancel-variant">取消</div>';
            html += '</div>';
            
            preview.innerHTML = html;
            
            this.initCustomSelects();
            
            document.getElementById('dict-save-variant').addEventListener('click', function() {
                self.saveNewVariant();
            });
            
            document.getElementById('dict-cancel-variant').addEventListener('click', function() {
                preview.innerHTML = '';
            });
        },
        
        // 保存新变体
        saveNewVariant: function() {
            var self = this;
            var icon = document.getElementById('dict-new-icon').value.trim();
            var type = document.getElementById('dict-new-type').getAttribute('data-value');
            var color = document.getElementById('dict-new-color').getAttribute('data-value');
            var desc = document.getElementById('dict-new-desc').value.trim();
            
            if (!type || !color || !desc) {
                this.showMessage('请填写所有必填字段', 'error');
                return;
            }
            
            var variant = {
                icon: icon,
                类型: type,
                颜色: color,
                描述: desc
            };
            
            this.dictionaryData[this.currentEditKey].push(variant);
            
            this.showMessage('正在保存到模块...', 'info');
            this.saveToModule(function() {
                self.renderEditor();
            });
        },
        
        // 编辑变体
        editVariant: function(index) {
            var self = this;
            var variant = this.dictionaryData[this.currentEditKey][index];
            var preview = document.getElementById('dict-preview-container');
            
            var html = '<h4>编辑变体</h4>';
            html += '<div class="dict-field-row">';
            html += this.renderField('edit-icon', 'text', '图标', variant.icon);
            html += this.renderField('edit-type', 'select', '类型 *', variant.类型, this.typeOptions);
            html += this.renderField('edit-color', 'select', '颜色 *', variant.颜色, this.colorOptions);
            html += '</div>';
            html += this.renderField('edit-desc', 'textarea', '描述 *', variant.描述);
            html += '<div style="margin-top: 10px;">';
            html += '<div class="dict-button success" id="dict-update-variant" data-index="' + index + '">更新变体</div>';
            html += '<div class="dict-button secondary" id="dict-cancel-edit-variant">取消</div>';
            html += '</div>';
            
            preview.innerHTML = html;
            
            this.initCustomSelects();
            
            document.getElementById('dict-update-variant').addEventListener('click', function() {
                var idx = parseInt(this.getAttribute('data-index'));
                self.updateVariant(idx);
            });
            
            document.getElementById('dict-cancel-edit-variant').addEventListener('click', function() {
                preview.innerHTML = '';
            });
        },
        
        // 更新变体
        updateVariant: function(index) {
            var self = this;
            var icon = document.getElementById('dict-edit-icon').value.trim();
            var type = document.getElementById('dict-edit-type').getAttribute('data-value');
            var color = document.getElementById('dict-edit-color').getAttribute('data-value');
            var desc = document.getElementById('dict-edit-desc').value.trim();
            
            if (!type || !color || !desc) {
                this.showMessage('请填写所有必填字段', 'error');
                return;
            }
            
            this.dictionaryData[this.currentEditKey][index] = {
                icon: icon,
                类型: type,
                颜色: color,
                描述: desc
            };
            
            this.showMessage('正在保存到模块...', 'info');
            this.saveToModule(function() {
                self.renderEditor();
            });
        },
        
        // 保存到模块
        saveToModule: function(callback) {
            var self = this;
            
            var luaContent = this.generateLuaContent();
            
            this.api.postWithToken('csrf', {
                action: 'edit',
                title: this.MODULE_PAGE,
                text: luaContent,
                summary: '通过词典管理器更新',
                format: 'json'
            }).done(function() {
                self.showMessage('保存成功!', 'success');
                if (callback) callback();
            }).fail(function(code, error) {
                console.error('保存失败:', code, error);
                self.showMessage('保存失败: ' + (error.error ? error.error.info : '未知错误'), 'error');
            });
        },
        
        // 生成Lua内容
        generateLuaContent: function() {
            var self = this;
            var lua = 'local data = {}\n\ndata.dictionary = {\n';
    
            var entries = Object.keys(this.dictionaryData).sort();
    
            entries.forEach(function(key) {
                var variants = self.dictionaryData[key];
                lua += '    ["' + key + '"] = {\n';
        
                variants.forEach(function(variant) {
                    lua += '        {\n';
                    lua += '            ["icon"] = "' + (variant.icon || '') + '",\n';
                    lua += '            ["类型"] = "' + variant.类型 + '",\n';
                    lua += '            ["颜色"] = "' + variant.颜色 + '",\n';
                    lua += '            ["描述"] = "' + variant.描述 + '",\n';
                    lua += '        },\n';
                });
        
                lua += '    },\n';
            });
    
            lua += '}\n\nreturn data\n';
            return lua;
        },
        
        // 获取颜色类名
        getColorClass: function(color) {
            var colorMap = {
                '白': 'dict-badge-white',
                '蓝': 'dict-badge-blue',
                '红': 'dict-badge-red',
                '橙': 'dict-badge-orange',
                '彩': 'dict-badge-rainbow'
            };
            return colorMap[color] || 'dict-badge-white';
        },
        
        // 显示消息
        showMessage: function(message, type) {
            var container = document.getElementById('dict-message');
            container.innerHTML = '<div class="dict-message ' + type + '">' + mw.html.escape(message) + '</div>';
            
            if (type === 'success' || type === 'error') {
                setTimeout(function() {
                    container.innerHTML = '';
                }, 5000);
            }
        }
    };
    
    // 页面加载完成后初始化
    $(function() {
        DictManager.init();
    });
    
})();