MediaWiki

Dictionary.js:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
第2行: 第2行:
     'use strict';
     'use strict';
      
      
     // 添加调试日志
     if (mw.config.get('wgPageName') !== 'MediaWiki:Dictionary') return;
    console.log('词典编辑器脚本已加载');
    console.log('当前页面:', mw.config.get('wgPageName'));
      
      
     // 检查页面名称
     const API_URL = mw.util.wikiScript('api');
    if (mw.config.get('wgPageName') !== 'MediaWiki:Dictionary') {
    const MODULE_PAGE = '模块:词典/data';
        console.log('不是目标页面,脚本退出');
        return;
    }
      
      
     var API_URL = mw.util.wikiScript('api');
     let dictionaryData = {};
     var dictionaryData = {};
    let currentEditKey = null;
     let currentEditIndex = null;
      
      
     // 加载词典数据
     // 初始化
     function loadDictionaryData() {
     function init() {
         console.log('开始加载词典数据');
         const content = document.createElement('div');
        content.className = 'dict-editor';
        content.innerHTML = `
            <div class="dict-controls">
                <div class="dict-btn dict-btn-success" id="dict-add-btn">添加新词条</div>
                <div class="dict-btn" id="dict-refresh-btn">刷新数据</div>
                <div class="dict-btn" id="dict-save-btn">保存到模块</div>
            </div>
            <div id="dict-message"></div>
            <div id="dict-content" class="dict-loading">加载中...</div>
            <div class="dict-overlay" id="dict-overlay"></div>
            <div class="dict-form" id="dict-form">
                <h3 id="dict-form-title">添加词条</h3>
                <div class="dict-form-group">
                    <label for="dict-name">词条名称</label>
                    <input type="text" id="dict-name" class="dict-input" />
                </div>
                <div class="dict-form-group">
                    <label for="dict-icon">图标</label>
                    <input type="text" id="dict-icon" class="dict-input" />
                </div>
                <div class="dict-form-group">
                    <label for="dict-type">类型</label>
                    <div class="dict-select" id="dict-type" data-value="">
                        <div class="dict-select-display">请选择类型</div>
                        <div class="dict-select-options">
                            <div class="dict-select-option" data-value="卡牌机制">卡牌机制</div>
                            <div class="dict-select-option" data-value="战斗员专属机制">战斗员专属机制</div>
                            <div class="dict-select-option" data-value="buff">buff</div>
                            <div class="dict-select-option" data-value="debuff">debuff</div>
                        </div>
                    </div>
                </div>
                <div class="dict-form-group">
                    <label for="dict-color">颜色</label>
                    <div class="dict-select" id="dict-color" data-value="">
                        <div class="dict-select-display">请选择颜色</div>
                        <div class="dict-select-options">
                            <div class="dict-select-option" data-value="白">白</div>
                            <div class="dict-select-option" data-value="蓝">蓝</div>
                            <div class="dict-select-option" data-value="红">红</div>
                            <div class="dict-select-option" data-value="橙">橙</div>
                            <div class="dict-select-option" data-value="彩">彩</div>
                        </div>
                    </div>
                </div>
                <div class="dict-form-group">
                    <label for="dict-desc">描述</label>
                    <textarea id="dict-desc" class="dict-textarea"></textarea>
                </div>
                <div class="dict-form-actions">
                    <div class="dict-btn" id="dict-cancel-btn">取消</div>
                    <div class="dict-btn dict-btn-success" id="dict-submit-btn">保存</div>
                </div>
            </div>
        `;
       
        const container = document.getElementById('mw-content-text');
        container.innerHTML = '';
        container.appendChild(content);
          
          
         // 直接使用备用方案:从模块页面加载
         initCustomSelect();
         loadFromModulePage();
         bindEvents();
        loadData();
     }
     }
      
      
     // 从模块页面加载数据
     // 自定义下拉选择器
     function loadFromModulePage() {
     function initCustomSelect() {
         console.log('从模块页面加载数据');
         document.querySelectorAll('.dict-select').forEach(select => {
            const display = select.querySelector('.dict-select-display');
            const options = select.querySelector('.dict-select-options');
           
            display.addEventListener('click', () => {
                select.classList.toggle('open');
            });
           
            select.querySelectorAll('.dict-select-option').forEach(option => {
                option.addEventListener('click', () => {
                    const value = option.getAttribute('data-value');
                    select.setAttribute('data-value', value);
                    display.textContent = option.textContent;
                    select.classList.remove('open');
                });
            });
        });
          
          
         $.ajax({
         // 点击外部关闭
            url: mw.util.getUrl('Module:词典/data', {action: 'raw'}),
        document.addEventListener('click', (e) => {
            dataType: 'text',
             if (!e.target.closest('.dict-select')) {
             success: function(content) {
                 document.querySelectorAll('.dict-select').forEach(s => s.classList.remove('open'));
                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) {
     function bindEvents() {
         var container = findContentContainer();
         document.getElementById('dict-add-btn').addEventListener('click', () => openForm());
        container.empty();
         document.getElementById('dict-refresh-btn').addEventListener('click', () => loadData());
         $('<div>').addClass('errorbox').css({
        document.getElementById('dict-save-btn').addEventListener('click', () => saveData());
            'padding': '10px',
        document.getElementById('dict-overlay').addEventListener('click', closeForm);
            'margin': '10px 0',
        document.getElementById('dict-cancel-btn').addEventListener('click', closeForm);
            'border': '1px solid #d33',
         document.getElementById('dict-submit-btn').addEventListener('click', submitForm);
            'background-color': '#fee',
            'color': '#d33'
         }).text(message).appendTo(container);
     }
     }
      
      
     // 查找内容容器
     // 加载数据
     function findContentContainer() {
     function loadData() {
         // 尝试多个可能的选择器
         showMessage('加载中...', 'loading');
        var selectors = [
            '#dictionary-editor',
            '#mw-content-text',
            '.mw-parser-output',
            '#bodyContent',
            '#content'
        ];
          
          
         var container;
         fetch(API_URL + '?' + new URLSearchParams({
         for (var i = 0; i < selectors.length; i++) {
            action: 'query',
             container = $(selectors[i]);
            prop: 'revisions',
             if (container.length) {
            titles: MODULE_PAGE,
                 console.log('找到容器:', selectors[i]);
            rvprop: 'content',
                 break;
            rvslots: 'main',
            format: 'json'
        }))
        .then(res => res.json())
         .then(data => {
            const pages = data.query.pages;
            const page = pages[Object.keys(pages)[0]];
           
            if (page.revisions) {
                const content = page.revisions[0].slots.main['*'];
                parseModuleData(content);
                renderTable();
                showMessage('数据加载成功', 'success');
            } else {
                showMessage('模块页面不存在', 'error');
            }
        })
        .catch(err => {
            showMessage('加载失败: ' + err.message, 'error');
        });
    }
   
    // 解析模块数据
    function parseModuleData(content) {
        try {
            // 提取 dictionary 表的内容
             const match = content.match(/data\.dictionary\s*=\s*(\{[\s\S]*?\n\})/);
             if (match) {
                 // 简单的Lua表转JSON (这是简化版本,可能需要更复杂的解析)
                let jsonStr = match[1]
                    .replace(/\["([^"]+)"\]\s*=/g, '"$1":')
                    .replace(/\[(\d+)\]\s*=/g, '')
                    .replace(/,(\s*[}\]])/g, '$1');
                  
                dictionaryData = eval('(' + jsonStr + ')');
             }
             }
        } catch (e) {
            console.error('解析错误:', e);
            dictionaryData = {};
         }
         }
       
        if (!container || !container.length) {
            console.error('找不到内容容器');
            container = $('body');
        }
       
        return container;
     }
     }
      
      
     // 简单的Lua表解析器(改进版)
     // 渲染表格
     function parseLuaTable(luaContent) {
     function renderTable() {
         var result = {};
         const content = document.getElementById('dict-content');
        console.log('开始解析Lua表');
          
          
         // 查找 dictionary 表
         if (Object.keys(dictionaryData).length === 0) {
        var dictMatch = luaContent.match(/data\.dictionary\s*=\s*\{([\s\S]*?)\n\}/);
             content.innerHTML = '<p>暂无数据</p>';
        if (!dictMatch) {
             return;
             console.error('找不到dictionary表');
             throw new Error('找不到dictionary表定义');
         }
         }
          
          
         var content = dictMatch[1];
         let html = '<table class="dict-table"><thead><tr><th>词条名称</th><th>变体</th><th>操作</th></tr></thead><tbody>';
        console.log('提取的内容长度:', content.length);
          
          
         // 匹配每个词条
         for (const [key, variants] of Object.entries(dictionaryData)) {
        var entryRegex = /\["([^"]+)"\]\s*=\s*\{([\s\S]*?)\n    \}/g;
             html += `<tr><td rowspan="${variants.length + 1}"><strong>${key}</strong></td></tr>`;
        var match;
        var count = 0;
       
        while ((match = entryRegex.exec(content)) !== null) {
             var key = match[1];
            var itemsContent = match[2];
            result[key] = [];
            count++;
              
              
             // 匹配每个定义
             variants.forEach((variant, index) => {
            var itemRegex = /\{([^}]+)\}/g;
                const colorClass = getColorClass(variant.颜色);
            var itemMatch;
                html += `
            while ((itemMatch = itemRegex.exec(itemsContent)) !== null) {
                    <tr>
                var item = {};
                        <td>
                var props = itemMatch[1].split(',');
                            <div class="dict-variant">
                props.forEach(function(prop) {
                                <div><span class="dict-badge ${colorClass}">${variant.类型}</span> <span class="dict-badge ${colorClass}">${variant.颜色}</span></div>
                    var propMatch = prop.match(/\["([^"]+)"\]\s*=\s*"([^"]*)"/);
                                <div style="margin-top: 5px;">${variant.描述}</div>
                    if (propMatch) {
                                ${variant.icon ? '<div>图标: ' + variant.icon + '</div>' : ''}
                         item[propMatch[1]] = propMatch[2];
                            </div>
                     }
                        </td>
                 });
                        <td>
                result[key].push(item);
                            <div class="dict-btn" onclick="dictEdit('${key}', ${index})">编辑</div>
            }
                            <div class="dict-btn dict-btn-danger" onclick="dictDelete('${key}', ${index})">删除</div>
                         </td>
                     </tr>
                 `;
            });
         }
         }
          
          
         console.log('解析了', count, '个词条');
         html += '</tbody></table>';
         return result;
        content.innerHTML = html;
    }
   
    // 获取颜色类名
    function getColorClass(color) {
        const colorMap = {
            '白': 'dict-badge-white',
            '蓝': 'dict-badge-blue',
            '红': 'dict-badge-red',
            '橙': 'dict-badge-orange',
            '彩': 'dict-badge-rainbow'
        };
         return colorMap[color] || 'dict-badge-white';
     }
     }
      
      
     // 渲染词典界面
     // 打开表单
     function renderDictionary() {
     function openForm(key = null, index = null) {
         console.log('开始渲染词典界面');
         currentEditKey = key;
        currentEditIndex = index;
          
          
         var container = findContentContainer();
         const form = document.getElementById('dict-form');
        const overlay = document.getElementById('dict-overlay');
        const title = document.getElementById('dict-form-title');
          
          
        // 清空现有内容
         if (key !== null && index !== null) {
         if (container.attr('id') !== 'dictionary-editor') {
            title.textContent = '编辑词条';
             container.empty();
            const variant = dictionaryData[key][index];
             container = $('<div>').attr('id', 'dictionary-editor').appendTo(container);
            document.getElementById('dict-name').value = key;
             document.getElementById('dict-name').disabled = true;
             document.getElementById('dict-icon').value = variant.icon || '';
            setSelectValue('dict-type', variant.类型);
            setSelectValue('dict-color', variant.颜色);
            document.getElementById('dict-desc').value = variant.描述 || '';
         } else {
         } else {
             container.empty();
             title.textContent = '添加词条';
            document.getElementById('dict-name').value = '';
            document.getElementById('dict-name').disabled = false;
            document.getElementById('dict-icon').value = '';
            setSelectValue('dict-type', '');
            setSelectValue('dict-color', '');
            document.getElementById('dict-desc').value = '';
         }
         }
          
          
         // 添加样式
         form.classList.add('active');
        addStyles();
         overlay.classList.add('active');
       
        // 添加标题和新建按钮
        var header = $('<div>').addClass('dict-header').appendTo(container);
        $('<div>').addClass('dict-title').text('词典编辑器').appendTo(header);
        $('<div>').addClass('dict-btn dict-btn-primary').text('+ 新建词条').click(showAddEntryDialog).appendTo(header);
       
        // 渲染词条列表
        var list = $('<div>').addClass('dict-list').appendTo(container);
       
        var keys = Object.keys(dictionaryData).sort();
        console.log('渲染', keys.length, '个词条');
          
        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);
                $('<div>').addClass('dict-entry-name').text(key).appendTo(entryHeader);
               
                var actions = $('<div>').addClass('dict-entry-actions').appendTo(entryHeader);
                $('<div>').addClass('dict-btn dict-btn-small').text('编辑')
                    .click(function() { showEditDialog(key, index); }).appendTo(actions);
                $('<div>').addClass('dict-btn dict-btn-small dict-btn-danger').text('删除')
                    .click(function() { deleteEntry(key, index); }).appendTo(actions);
               
                var entryBody = $('<div>').addClass('dict-entry-body').appendTo(entry);
               
                var colorClass = 'dict-color-' + (item['颜色'] || 'white');
                $('<div>').addClass('dict-field').html('<span class="dict-label">颜色:</span> <span class="' + colorClass + '">' + (item['颜色'] || '') + '</span>').appendTo(entryBody);
                $('<div>').addClass('dict-field').html('<span class="dict-label">类型:</span> ' + (item['类型'] || '')).appendTo(entryBody);
                $('<div>').addClass('dict-field').html('<span class="dict-label">图标:</span> ' + (item['icon'] || '')).appendTo(entryBody);
                $('<div>').addClass('dict-field').html('<span class="dict-label">描述:</span> ' + (item['描述'] || '')).appendTo(entryBody);
            });
        });
       
        console.log('渲染完成');
     }
     }
      
      
     // 添加样式
     // 设置选择器值
     function addStyles() {
     function setSelectValue(id, value) {
         if ($('#dict-editor-styles').length) return;
         const select = document.getElementById(id);
          
        select.setAttribute('data-value', value);
        var css = `
         const display = select.querySelector('.dict-select-display');
            .dict-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding: 20px; background: #f8f9fa; border-radius: 8px; }
        if (value) {
            .dict-title { font-size: 24px; font-weight: bold; }
             display.textContent = value;
            .dict-btn { padding: 8px 16px; border-radius: 4px; cursor: pointer; display: inline-block; transition: all 0.2s; }
        } else {
            .dict-btn:hover { opacity: 0.8; }
             display.textContent = select.id === 'dict-type' ? '请选择类型' : '请选择颜色';
            .dict-btn-primary { background: #0645ad; color: white; }
        }
            .dict-btn-secondary { background: #eee; color: #333; }
            .dict-btn-danger { background: #d33; color: white; }
            .dict-btn-small { padding: 4px 12px; font-size: 12px; }
            .dict-list { display: flex; flex-direction: column; gap: 15px; }
            .dict-entry { border: 1px solid #ddd; border-radius: 8px; overflow: hidden; }
            .dict-entry-header { background: #f8f9fa; padding: 12px; display: flex; justify-content: space-between; align-items: center; }
            .dict-entry-name { font-weight: bold; font-size: 16px; }
            .dict-entry-actions { display: flex; gap: 8px; }
            .dict-entry-body { padding: 12px; }
            .dict-field { margin: 8px 0; }
            .dict-label { font-weight: bold; color: #666; }
            .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; }
            .dict-dialog { background: white; border-radius: 8px; width: 500px; max-width: 90%; max-height: 90vh; overflow-y: auto; }
             .dict-dialog-title { padding: 16px; border-bottom: 1px solid #ddd; font-size: 18px; font-weight: bold; }
            .dict-form { padding: 16px; }
            .dict-form-group { margin-bottom: 16px; }
            .dict-form-label { margin-bottom: 4px; font-weight: bold; }
            .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; }
            .dict-option:hover { background: #f0f0f0; }
        `;
       
        $('<style>').attr('id', 'dict-editor-styles').text(css).appendTo('head');
     }
     }
      
      
     // 显示添加词条对话框
     // 关闭表单
     function showAddEntryDialog() {
     function closeForm() {
         showDialog('新建词条', {}, function(data) {
         document.getElementById('dict-form').classList.remove('active');
            var name = data.name;
        document.getElementById('dict-overlay').classList.remove('active');
            delete data.name;
           
            if (!dictionaryData[name]) {
                dictionaryData[name] = [];
            }
            dictionaryData[name].push(data);
            saveDictionary();
        }, true);
     }
     }
      
      
     // 显示编辑对话框
     // 提交表单
     function showEditDialog(key, index) {
     function submitForm() {
         var item = dictionaryData[key][index];
         const name = document.getElementById('dict-name').value.trim();
         var data = $.extend({name: key}, item);
        const icon = document.getElementById('dict-icon').value.trim();
         const type = document.getElementById('dict-type').getAttribute('data-value');
        const color = document.getElementById('dict-color').getAttribute('data-value');
        const desc = document.getElementById('dict-desc').value.trim();
          
          
         showDialog('编辑词条', data, function(newData) {
         if (!name || !type || !color || !desc) {
            var newName = newData.name;
             showMessage('请填写所有必填字段', 'error');
            delete newData.name;
            return;
           
         }
            if (newName !== key) {
                // 名称改变,删除旧的
                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);
    }
   
    // 显示对话框
    function showDialog(title, data, callback, isNew) {
        var overlay = $('<div>').addClass('dict-overlay').appendTo('body');
         var dialog = $('<div>').addClass('dict-dialog').appendTo(overlay);
          
          
         $('<div>').addClass('dict-dialog-title').text(title).appendTo(dialog);
         const variant = {
            icon: icon,
            类型: type,
            颜色: color,
            描述: desc
        };
          
          
         var form = $('<div>').addClass('dict-form').appendTo(dialog);
         if (currentEditKey !== null && currentEditIndex !== null) {
       
            // 编辑
        // 名称字段
            dictionaryData[currentEditKey][currentEditIndex] = variant;
        var nameField = createField('名称', 'text', data.name || '', isNew);
         } else {
        form.append(nameField);
             // 新增
       
             if (!dictionaryData[name]) {
        // 类型字段(下拉)
                 dictionaryData[name] = [];
        var typeField = createSelectField('类型', ['卡牌机制', '战斗员专属机制', 'buff', 'debuff'], data['类型'] || '');
        form.append(typeField);
       
        // 颜色字段(下拉)
        var colorField = createSelectField('颜色', ['白', '蓝', '红', '橙', '彩'], data['颜色'] || '');
        form.append(colorField);
       
        // 图标字段
        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) {
                 alert('请输入名称');
                return;
             }
             }
              
             dictionaryData[name].push(variant);
            overlay.remove();
            callback(formData);
        }).appendTo(actions);
    }
   
    // 创建表单字段
    function createField(label, type, value, editable) {
        var field = $('<div>').addClass('dict-form-group');
        $('<div>').addClass('dict-form-label').text(label + ':').appendTo(field);
       
        var input;
        if (type === 'textarea') {
            input = $('<textarea>').addClass('dict-input').val(value).attr('rows', 3);
        } else {
            input = $('<input>').addClass('dict-input').attr('type', type).val(value);
         }
         }
          
          
         if (!editable) {
         renderTable();
            input.attr('readonly', 'readonly');
        closeForm();
        }
        showMessage('操作成功,请点击"保存到模块"按钮保存更改', 'success');
       
        input.appendTo(field);
        return field;
     }
     }
      
      
     // 创建下拉选择字段
     // 删除
     function createSelectField(label, options, value) {
     window.dictDelete = function(key, index) {
        var field = $('<div>').addClass('dict-form-group');
         if (!confirm('确定要删除这个变体吗?')) return;
        $('<div>').addClass('dict-form-label').text(label + ':').appendTo(field);
       
        var selectWrapper = $('<div>').addClass('dict-select-wrapper').appendTo(field);
        var selectDisplay = $('<div>').addClass('dict-select')
            .attr('data-value', value || options[0])
            .text(value || options[0])
            .appendTo(selectWrapper);
       
        var dropdown = $('<div>').addClass('dict-dropdown').appendTo(selectWrapper);
       
        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;
    }
   
    // 删除词条
    function deleteEntry(key, index) {
         if (!confirm('确定要删除这个词条吗?')) {
            return;
        }
          
          
         dictionaryData[key].splice(index, 1);
         dictionaryData[key].splice(index, 1);
第392行: 第312行:
             delete dictionaryData[key];
             delete dictionaryData[key];
         }
         }
         saveDictionary();
          
     }
        renderTable();
        showMessage('删除成功,请点击"保存到模块"按钮保存更改', 'success');
    };
   
    // 编辑
    window.dictEdit = function(key, index) {
        openForm(key, index);
     };
      
      
     // 保存词典到模块
     // 保存数据
     function saveDictionary() {
     function saveData() {
         var luaCode = generateLuaCode();
         if (!confirm('确定要保存到模块吗?这将覆盖现有数据!')) return;
          
          
         // 使用新的API获取token
        const luaContent = generateLuaContent();
         new mw.Api().postWithToken('csrf', {
       
            action: 'edit',
        showMessage('保存中...', 'loading');
            title: 'Module:词典/data',
       
            text: luaCode,
         // 获取编辑令牌
            summary: '通过词典编辑器更新'
         fetch(API_URL + '?' + new URLSearchParams({
         }).done(function(response) {
            action: 'query',
             if (response.edit && response.edit.result === 'Success') {
            meta: 'tokens',
                 mw.notify('保存成功!', {type: 'success'});
            format: 'json'
                loadDictionaryData(); // 重新加载数据
        }))
        .then(res => res.json())
        .then(data => {
            const token = data.query.tokens.csrftoken;
           
            // 保存页面
            return fetch(API_URL, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    action: 'edit',
                    title: MODULE_PAGE,
                    text: luaContent,
                    summary: '通过词典编辑器更新数据',
                    token: token,
                    format: 'json'
                })
            });
         })
        .then(res => res.json())
        .then(data => {
             if (data.edit && data.edit.result === 'Success') {
                 showMessage('保存成功!', 'success');
             } else {
             } else {
                 mw.notify('保存失败:' + (response.error ? response.error.info : '未知错误'), {type: 'error'});
                 showMessage('保存失败: ' + JSON.stringify(data), 'error');
             }
             }
         }).fail(function(code, result) {
         })
             console.error('保存失败:', code, result);
        .catch(err => {
            mw.notify('保存失败:' + (result.error ? result.error.info : '网络错误'), {type: 'error'});
             showMessage('保存失败: ' + err.message, 'error');
         });
         });
     }
     }
      
      
     // 生成Lua代码
     // 生成Lua内容
     function generateLuaCode() {
     function generateLuaContent() {
         var lines = ['local data = {}', '', 'data.dictionary = {'];
         let lua = 'local data = {}\n\ndata.dictionary = {\n';
          
          
         var keys = Object.keys(dictionaryData).sort();
         for (const [key, variants] of Object.entries(dictionaryData)) {
        keys.forEach(function(key, keyIndex) {
             lua += `   ["${key}"] = {\n`;
             lines.push('   ["' + key + '"] = {');
             variants.forEach(variant => {
              
                 lua += '        {\n';
            dictionaryData[key].forEach(function(item, itemIndex) {
                 lua += `           ["icon"] = "${variant.icon || ''}",\n`;
                 lines.push('        {');
                 lua += `           ["类型"] = "${variant.类型}",\n`;
                 lines.push('           ["icon"] = "' + (item.icon || '') + '",');
                 lua += `           ["颜色"] = "${variant.颜色}",\n`;
                 lines.push('           ["类型"] = "' + (item['类型'] || '') + '",');
                 lua += `           ["描述"] = "${variant.描述}",\n`;
                 lines.push('           ["颜色"] = "' + (item['颜色'] || '') + '",');
                 lua += '        },\n';
                 lines.push('           ["描述"] = "' + (item['描述'] || '') + '",');
                 lines.push('        }' + (itemIndex < dictionaryData[key].length - 1 ? ',' : ''));
             });
             });
              
             lua += '    },\n';
            lines.push('    }' + (keyIndex < keys.length - 1 ? ',' : ''));
        }
         });
       
        lua += '}\n\nreturn data\n';
        return lua;
    }
   
    // 显示消息
    function showMessage(msg, type) {
        const msgDiv = document.getElementById('dict-message');
        msgDiv.className = 'dict-' + type;
         msgDiv.textContent = msg;
          
          
         lines.push('}', '', 'return data');
         if (type === 'success' || type === 'error') {
        return lines.join('\n');
            setTimeout(() => {
                msgDiv.textContent = '';
                msgDiv.className = '';
            }, 3000);
        }
     }
     }
      
      
     // 初始化 - 确保DOM已加载
     // 页面加载完成后初始化
     if (document.readyState === 'loading') {
     if (document.readyState === 'loading') {
         $(document).ready(function() {
         document.addEventListener('DOMContentLoaded', init);
            console.log('DOM已加载,初始化词典编辑器');
            loadDictionaryData();
        });
     } else {
     } else {
         console.log('DOM已经准备好,立即初始化');
         init();
        loadDictionaryData();
     }
     }
})();
})();

2025年10月3日 (五) 19:12的版本

(function() {
    'use strict';
    
    if (mw.config.get('wgPageName') !== 'MediaWiki:Dictionary') return;
    
    const API_URL = mw.util.wikiScript('api');
    const MODULE_PAGE = '模块:词典/data';
    
    let dictionaryData = {};
    let currentEditKey = null;
    let currentEditIndex = null;
    
    // 初始化
    function init() {
        const content = document.createElement('div');
        content.className = 'dict-editor';
        content.innerHTML = `
            <div class="dict-controls">
                <div class="dict-btn dict-btn-success" id="dict-add-btn">添加新词条</div>
                <div class="dict-btn" id="dict-refresh-btn">刷新数据</div>
                <div class="dict-btn" id="dict-save-btn">保存到模块</div>
            </div>
            <div id="dict-message"></div>
            <div id="dict-content" class="dict-loading">加载中...</div>
            <div class="dict-overlay" id="dict-overlay"></div>
            <div class="dict-form" id="dict-form">
                <h3 id="dict-form-title">添加词条</h3>
                <div class="dict-form-group">
                    <label for="dict-name">词条名称</label>
                    <input type="text" id="dict-name" class="dict-input" />
                </div>
                <div class="dict-form-group">
                    <label for="dict-icon">图标</label>
                    <input type="text" id="dict-icon" class="dict-input" />
                </div>
                <div class="dict-form-group">
                    <label for="dict-type">类型</label>
                    <div class="dict-select" id="dict-type" data-value="">
                        <div class="dict-select-display">请选择类型</div>
                        <div class="dict-select-options">
                            <div class="dict-select-option" data-value="卡牌机制">卡牌机制</div>
                            <div class="dict-select-option" data-value="战斗员专属机制">战斗员专属机制</div>
                            <div class="dict-select-option" data-value="buff">buff</div>
                            <div class="dict-select-option" data-value="debuff">debuff</div>
                        </div>
                    </div>
                </div>
                <div class="dict-form-group">
                    <label for="dict-color">颜色</label>
                    <div class="dict-select" id="dict-color" data-value="">
                        <div class="dict-select-display">请选择颜色</div>
                        <div class="dict-select-options">
                            <div class="dict-select-option" data-value="白">白</div>
                            <div class="dict-select-option" data-value="蓝">蓝</div>
                            <div class="dict-select-option" data-value="红">红</div>
                            <div class="dict-select-option" data-value="橙">橙</div>
                            <div class="dict-select-option" data-value="彩">彩</div>
                        </div>
                    </div>
                </div>
                <div class="dict-form-group">
                    <label for="dict-desc">描述</label>
                    <textarea id="dict-desc" class="dict-textarea"></textarea>
                </div>
                <div class="dict-form-actions">
                    <div class="dict-btn" id="dict-cancel-btn">取消</div>
                    <div class="dict-btn dict-btn-success" id="dict-submit-btn">保存</div>
                </div>
            </div>
        `;
        
        const container = document.getElementById('mw-content-text');
        container.innerHTML = '';
        container.appendChild(content);
        
        initCustomSelect();
        bindEvents();
        loadData();
    }
    
    // 自定义下拉选择器
    function initCustomSelect() {
        document.querySelectorAll('.dict-select').forEach(select => {
            const display = select.querySelector('.dict-select-display');
            const options = select.querySelector('.dict-select-options');
            
            display.addEventListener('click', () => {
                select.classList.toggle('open');
            });
            
            select.querySelectorAll('.dict-select-option').forEach(option => {
                option.addEventListener('click', () => {
                    const value = option.getAttribute('data-value');
                    select.setAttribute('data-value', value);
                    display.textContent = option.textContent;
                    select.classList.remove('open');
                });
            });
        });
        
        // 点击外部关闭
        document.addEventListener('click', (e) => {
            if (!e.target.closest('.dict-select')) {
                document.querySelectorAll('.dict-select').forEach(s => s.classList.remove('open'));
            }
        });
    }
    
    // 绑定事件
    function bindEvents() {
        document.getElementById('dict-add-btn').addEventListener('click', () => openForm());
        document.getElementById('dict-refresh-btn').addEventListener('click', () => loadData());
        document.getElementById('dict-save-btn').addEventListener('click', () => saveData());
        document.getElementById('dict-overlay').addEventListener('click', closeForm);
        document.getElementById('dict-cancel-btn').addEventListener('click', closeForm);
        document.getElementById('dict-submit-btn').addEventListener('click', submitForm);
    }
    
    // 加载数据
    function loadData() {
        showMessage('加载中...', 'loading');
        
        fetch(API_URL + '?' + new URLSearchParams({
            action: 'query',
            prop: 'revisions',
            titles: MODULE_PAGE,
            rvprop: 'content',
            rvslots: 'main',
            format: 'json'
        }))
        .then(res => res.json())
        .then(data => {
            const pages = data.query.pages;
            const page = pages[Object.keys(pages)[0]];
            
            if (page.revisions) {
                const content = page.revisions[0].slots.main['*'];
                parseModuleData(content);
                renderTable();
                showMessage('数据加载成功', 'success');
            } else {
                showMessage('模块页面不存在', 'error');
            }
        })
        .catch(err => {
            showMessage('加载失败: ' + err.message, 'error');
        });
    }
    
    // 解析模块数据
    function parseModuleData(content) {
        try {
            // 提取 dictionary 表的内容
            const match = content.match(/data\.dictionary\s*=\s*(\{[\s\S]*?\n\})/);
            if (match) {
                // 简单的Lua表转JSON (这是简化版本,可能需要更复杂的解析)
                let jsonStr = match[1]
                    .replace(/\["([^"]+)"\]\s*=/g, '"$1":')
                    .replace(/\[(\d+)\]\s*=/g, '')
                    .replace(/,(\s*[}\]])/g, '$1');
                
                dictionaryData = eval('(' + jsonStr + ')');
            }
        } catch (e) {
            console.error('解析错误:', e);
            dictionaryData = {};
        }
    }
    
    // 渲染表格
    function renderTable() {
        const content = document.getElementById('dict-content');
        
        if (Object.keys(dictionaryData).length === 0) {
            content.innerHTML = '<p>暂无数据</p>';
            return;
        }
        
        let html = '<table class="dict-table"><thead><tr><th>词条名称</th><th>变体</th><th>操作</th></tr></thead><tbody>';
        
        for (const [key, variants] of Object.entries(dictionaryData)) {
            html += `<tr><td rowspan="${variants.length + 1}"><strong>${key}</strong></td></tr>`;
            
            variants.forEach((variant, index) => {
                const colorClass = getColorClass(variant.颜色);
                html += `
                    <tr>
                        <td>
                            <div class="dict-variant">
                                <div><span class="dict-badge ${colorClass}">${variant.类型}</span> <span class="dict-badge ${colorClass}">${variant.颜色}</span></div>
                                <div style="margin-top: 5px;">${variant.描述}</div>
                                ${variant.icon ? '<div>图标: ' + variant.icon + '</div>' : ''}
                            </div>
                        </td>
                        <td>
                            <div class="dict-btn" onclick="dictEdit('${key}', ${index})">编辑</div>
                            <div class="dict-btn dict-btn-danger" onclick="dictDelete('${key}', ${index})">删除</div>
                        </td>
                    </tr>
                `;
            });
        }
        
        html += '</tbody></table>';
        content.innerHTML = html;
    }
    
    // 获取颜色类名
    function getColorClass(color) {
        const colorMap = {
            '白': 'dict-badge-white',
            '蓝': 'dict-badge-blue',
            '红': 'dict-badge-red',
            '橙': 'dict-badge-orange',
            '彩': 'dict-badge-rainbow'
        };
        return colorMap[color] || 'dict-badge-white';
    }
    
    // 打开表单
    function openForm(key = null, index = null) {
        currentEditKey = key;
        currentEditIndex = index;
        
        const form = document.getElementById('dict-form');
        const overlay = document.getElementById('dict-overlay');
        const title = document.getElementById('dict-form-title');
        
        if (key !== null && index !== null) {
            title.textContent = '编辑词条';
            const variant = dictionaryData[key][index];
            document.getElementById('dict-name').value = key;
            document.getElementById('dict-name').disabled = true;
            document.getElementById('dict-icon').value = variant.icon || '';
            setSelectValue('dict-type', variant.类型);
            setSelectValue('dict-color', variant.颜色);
            document.getElementById('dict-desc').value = variant.描述 || '';
        } else {
            title.textContent = '添加词条';
            document.getElementById('dict-name').value = '';
            document.getElementById('dict-name').disabled = false;
            document.getElementById('dict-icon').value = '';
            setSelectValue('dict-type', '');
            setSelectValue('dict-color', '');
            document.getElementById('dict-desc').value = '';
        }
        
        form.classList.add('active');
        overlay.classList.add('active');
    }
    
    // 设置选择器值
    function setSelectValue(id, value) {
        const select = document.getElementById(id);
        select.setAttribute('data-value', value);
        const display = select.querySelector('.dict-select-display');
        if (value) {
            display.textContent = value;
        } else {
            display.textContent = select.id === 'dict-type' ? '请选择类型' : '请选择颜色';
        }
    }
    
    // 关闭表单
    function closeForm() {
        document.getElementById('dict-form').classList.remove('active');
        document.getElementById('dict-overlay').classList.remove('active');
    }
    
    // 提交表单
    function submitForm() {
        const name = document.getElementById('dict-name').value.trim();
        const icon = document.getElementById('dict-icon').value.trim();
        const type = document.getElementById('dict-type').getAttribute('data-value');
        const color = document.getElementById('dict-color').getAttribute('data-value');
        const desc = document.getElementById('dict-desc').value.trim();
        
        if (!name || !type || !color || !desc) {
            showMessage('请填写所有必填字段', 'error');
            return;
        }
        
        const variant = {
            icon: icon,
            类型: type,
            颜色: color,
            描述: desc
        };
        
        if (currentEditKey !== null && currentEditIndex !== null) {
            // 编辑
            dictionaryData[currentEditKey][currentEditIndex] = variant;
        } else {
            // 新增
            if (!dictionaryData[name]) {
                dictionaryData[name] = [];
            }
            dictionaryData[name].push(variant);
        }
        
        renderTable();
        closeForm();
        showMessage('操作成功,请点击"保存到模块"按钮保存更改', 'success');
    }
    
    // 删除
    window.dictDelete = function(key, index) {
        if (!confirm('确定要删除这个变体吗?')) return;
        
        dictionaryData[key].splice(index, 1);
        if (dictionaryData[key].length === 0) {
            delete dictionaryData[key];
        }
        
        renderTable();
        showMessage('删除成功,请点击"保存到模块"按钮保存更改', 'success');
    };
    
    // 编辑
    window.dictEdit = function(key, index) {
        openForm(key, index);
    };
    
    // 保存数据
    function saveData() {
        if (!confirm('确定要保存到模块吗?这将覆盖现有数据!')) return;
        
        const luaContent = generateLuaContent();
        
        showMessage('保存中...', 'loading');
        
        // 获取编辑令牌
        fetch(API_URL + '?' + new URLSearchParams({
            action: 'query',
            meta: 'tokens',
            format: 'json'
        }))
        .then(res => res.json())
        .then(data => {
            const token = data.query.tokens.csrftoken;
            
            // 保存页面
            return fetch(API_URL, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    action: 'edit',
                    title: MODULE_PAGE,
                    text: luaContent,
                    summary: '通过词典编辑器更新数据',
                    token: token,
                    format: 'json'
                })
            });
        })
        .then(res => res.json())
        .then(data => {
            if (data.edit && data.edit.result === 'Success') {
                showMessage('保存成功!', 'success');
            } else {
                showMessage('保存失败: ' + JSON.stringify(data), 'error');
            }
        })
        .catch(err => {
            showMessage('保存失败: ' + err.message, 'error');
        });
    }
    
    // 生成Lua内容
    function generateLuaContent() {
        let lua = 'local data = {}\n\ndata.dictionary = {\n';
        
        for (const [key, variants] of Object.entries(dictionaryData)) {
            lua += `    ["${key}"] = {\n`;
            variants.forEach(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;
    }
    
    // 显示消息
    function showMessage(msg, type) {
        const msgDiv = document.getElementById('dict-message');
        msgDiv.className = 'dict-' + type;
        msgDiv.textContent = msg;
        
        if (type === 'success' || type === 'error') {
            setTimeout(() => {
                msgDiv.textContent = '';
                msgDiv.className = '';
            }, 3000);
        }
    }
    
    // 页面加载完成后初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();