MediaWiki

MediaWiki:Dictionary.js

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献2025年10月3日 (五) 19:12的版本

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
(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();
    }
})();