MediaWiki

Equipment.js:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
 
(未显示同一用户的6个中间版本)
第1行: 第1行:
(function() {
( function () {
     'use strict';
     'use strict';
   
    mw.loader.using( ['mediawiki.api', 'mediawiki.util'], function () {
        if ( mw.config.get( 'wgPageName' ) !== 'MediaWiki:Equipment' ) {
            return;
        }
        mw.loader.load( mw.util.getUrl( 'MediaWiki:Equipment.css', { action: 'raw', ctype: 'text/css' } ), 'text/css' );
        var api = new mw.Api();
        var equipmentData = {};
        // 固定选项
        var AREA_OPTIONS = ['蓝壶', '双星之影', '雾之都市'];
        var RARITY_OPTIONS = ['蓝', '金', '彩'];
        var TYPE_OPTIONS = ['武器', '装甲', '戒指'];


    // 加载 CSS
    mw.loader.load('/index.php?title=MediaWiki:Equipment.css&action=raw&ctype=text/css', 'text/css');
   
    // 装备数据管理类
    var EquipmentManager = {
        currentData: {},
        editingEquipment: null,
       
         // 初始化
         // 初始化
         init: function() {
         function init() {
             this.loadData();
             loadEquipmentData();
            this.renderUI();
         }
            this.bindEvents();
 
         },
         // 加载装备数据
       
         function loadEquipmentData() {
         // 从模块加载数据
             api.get({
         loadData: function() {
                 action: 'query',
             var self = this;
                prop: 'revisions',
            new mw.Api().get({
                 titles: 'Module:装备/data',
                 action: 'parse',
                 rvprop: 'content',
                 page: '模块:装备/data',
                rvslots: 'main',
                 prop: 'wikitext'
                formatversion: 2
             }).done(function(data) {
             }).done(function (data) {
                 if (data.parse && data.parse.wikitext) {
                 if (data.query && data.query.pages && data.query.pages[0]) {
                     self.parseDataModule(data.parse.wikitext['*']);
                     var page = data.query.pages[0];
                    if (page.revisions && page.revisions[0]) {
                        var content = page.revisions[0].slots.main.content;
                        parseEquipmentData(content);
                        renderUI();
                        return;
                    }
                 }
                 }
                mw.notify('加载装备数据失败: 未找到数据', { type: 'error' });
            }).fail(function (code, result) {
                console.error('API Error:', code, result);
                mw.notify('加载装备数据失败: ' + code, { type: 'error' });
             });
             });
         },
         }
       
 
         // 解析 Lua 数据模块
         // 解析 Lua 数据
         parseDataModule: function(luaCode) {
         function parseEquipmentData(luaCode) {
             var dataMatch = luaCode.match(/local data = \{([\s\S]*)\}\s*return/);
             equipmentData = {};
            if (dataMatch) {
           
                this.loadDataViaInvoke();
            try {
            }
                // 匹配每个装备条目 - 改进的正则表达式
        },
                var lines = luaCode.split('\n');
       
                var currentName = null;
        // 通过 scribunto 调用获取数据
                var currentItem = null;
        loadDataViaInvoke: function() {
                var inDesc = false;
            var self = this;
                var descArray = [];
            new mw.Api().get({
               
                action: 'expandtemplates',
                for (var i = 0; i < lines.length; i++) {
                text: '{{#invoke:装备|getAllData}}',
                    var line = lines[i].trim();
                prop: 'wikitext'
                   
            }).done(function(data) {
                    // 匹配装备名称
                if (data.expandtemplates && data.expandtemplates.wikitext) {
                    var nameMatch = line.match(/equipment\["([^"]+)"\]\s*=\s*\{/);
                     try {
                    if (nameMatch) {
                         self.currentData = JSON.parse(data.expandtemplates.wikitext);
                        if (currentName && currentItem) {
                         self.renderEquipmentList();
                            if (descArray.length > 0) {
                     } catch(e) {
                                currentItem.desc = descArray;
                         console.error('数据解析失败', e);
                            }
                            equipmentData[currentName] = currentItem;
                        }
                        currentName = nameMatch[1];
                        currentItem = { name: currentName, desc: [] };
                        inDesc = false;
                        descArray = [];
                        continue;
                    }
                   
                    if (!currentItem) continue;
                   
                    // 匹配 desc 开始
                    if (line.match(/desc\s*=\s*\{/)) {
                        inDesc = true;
                        descArray = [];
                        continue;
                    }
                   
                    // desc 结束
                    if (inDesc && line.match(/^\}/)) {
                        inDesc = false;
                        currentItem.desc = descArray;
                        continue;
                    }
                   
                    // 在 desc 内
                    if (inDesc) {
                        var descMatch = line.match(/"([^"]*)"/);
                        if (descMatch) {
                            descArray.push(descMatch[1]);
                        }
                        continue;
                    }
                   
                    // 匹配其他属性
                    var idMatch = line.match(/id\s*=\s*"?([^",\n]+)"?/);
                    if (idMatch) {
                        currentItem.id = idMatch[1];
                        continue;
                    }
 
                   
                    var areaMatch = line.match(/area\s*=\s*"([^"]+)"/);
                    if (areaMatch) {
                        currentItem.area = areaMatch[1];
                        continue;
                    }
                   
                    var rarityMatch = line.match(/rarity\s*=\s*"([^"]+)"/);
                     if (rarityMatch) {
                         currentItem.rarity = rarityMatch[1];
                        continue;
                    }
                   
                    var typeMatch = line.match(/type\s*=\s*"([^"]+)"/);
                    if (typeMatch) {
                         currentItem.type = typeMatch[1];
                        continue;
                    }
                   
                    var tagMatch = line.match(/tag\s*=\s*"([^"]+)"/);
                     if (tagMatch) {
                         currentItem.tag = tagMatch[1];
                        continue;
                    }
                }
               
                // 保存最后一个装备
                if (currentName && currentItem) {
                    if (descArray.length > 0) {
                        currentItem.desc = descArray;
                     }
                     }
                    equipmentData[currentName] = currentItem;
                 }
                 }
             });
               
         },
                console.log('解析到的装备数据:', equipmentData);
       
               
             } catch (e) {
                console.error('解析装备数据出错:', e);
                mw.notify('解析装备数据失败', { type: 'error' });
            }
         }
 
         // 渲染界面
         // 渲染界面
         renderUI: function() {
         function renderUI() {
             var $container = $('#mw-content-text');
             var $container = $('<div>').addClass('equipment-manager');
             $container.empty();
           
            // 标题
            $container.append($('<div>').addClass('equipment-title').text('装备数据管理'));
           
            // 统计信息
            var count = Object.keys(equipmentData).length;
            $container.append($('<div>').addClass('equipment-stats').text('共 ' + count + ' 个装备'));
           
            // 添加新装备按钮
            var $addBtn = $('<div>').addClass('equipment-button equipment-button-primary')
                .text('添加新装备')
                .on('click', function () {
                    showEditForm(null);
                });
             $container.append($addBtn);
              
              
             var html = '<div class="equipment-manager">' +
             // 装备列表
                '<div class="eq-header">' +
            var $list = $('<div>').addClass('equipment-list');
                    '<div class="eq-title">装备数据管理</div>' +
                    '<div class="eq-btn eq-btn-primary" id="eq-add-new">新增装备</div>' +
                '</div>' +
                '<div class="eq-list" id="equipment-list"></div>' +
                '<div class="eq-modal" id="eq-modal" style="display:none;">' +
                    '<div class="eq-modal-content">' +
                        '<div class="eq-modal-header">' +
                            '<div class="eq-modal-title" id="modal-title">新增装备</div>' +
                            '<div class="eq-modal-close" id="modal-close">×</div>' +
                        '</div>' +
                        '<div class="eq-modal-body">' +
                            this.renderForm() +
                        '</div>' +
                        '<div class="eq-modal-footer">' +
                            '<div class="eq-btn eq-btn-secondary" id="eq-cancel">取消</div>' +
                            '<div class="eq-btn eq-btn-primary" id="eq-save">保存</div>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
                '<div class="eq-modal-backdrop" id="modal-backdrop" style="display:none;"></div>' +
            '</div>';
              
              
             $container.html(html);
             var items = Object.keys(equipmentData).sort();
        },
             for (var i = 0; i < items.length; i++) {
       
                 $list.append(createEquipmentItem(equipmentData[items[i]]));
        // 渲染表单
        renderForm: function() {
            return '<div class="eq-form">' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">装备名称:</div>' +
                    '<div class="eq-input" contenteditable="true" id="eq-name" data-placeholder="请输入装备名称"></div>' +
                '</div>' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">遗物ID:</div>' +
                    '<div class="eq-input" contenteditable="true" id="eq-relic-id" data-placeholder="例如: 1001"></div>' +
                '</div>' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">地区:</div>' +
                    '<div class="eq-select" id="eq-area">' +
                        '<div class="eq-select-display" data-value="">请选择地区</div>' +
                        '<div class="eq-select-dropdown">' +
                            '<div class="eq-select-option" data-value="蓝壶">蓝壶</div>' +
                            '<div class="eq-select-option" data-value="双星之影">双星之影</div>' +
                            '<div class="eq-select-option" data-value="雾之都市">雾之都市</div>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">稀有度:</div>' +
                    '<div class="eq-select" id="eq-rarity">' +
                        '<div class="eq-select-display" data-value="">请选择稀有度</div>' +
                        '<div class="eq-select-dropdown">' +
                            '<div class="eq-select-option" data-value="蓝">蓝</div>' +
                            '<div class="eq-select-option" data-value="紫">紫</div>' +
                            '<div class="eq-select-option" data-value="金">金</div>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">类型:</div>' +
                    '<div class="eq-select" id="eq-type">' +
                        '<div class="eq-select-display" data-value="">请选择类型</div>' +
                        '<div class="eq-select-dropdown">' +
                            '<div class="eq-select-option" data-value="武器">武器</div>' +
                            '<div class="eq-select-option" data-value="装甲">装甲</div>' +
                            '<div class="eq-select-option" data-value="戒指">戒指</div>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">属性类型:</div>' +
                    '<div class="eq-input" contenteditable="true" id="eq-value-type" data-placeholder="例如: 攻击力"></div>' +
                '</div>' +
                '<div class="eq-form-group">' +
                    '<div class="eq-label">TAG (用逗号分隔):</div>' +
                    '<div class="eq-input" contenteditable="true" id="eq-tag" data-placeholder="例如: 输出,爆发"></div>' +
                '</div>' +
                '<div class="eq-form-section">' +
                    '<div class="eq-section-title">等级数据</div>' +
                    this.renderLevelInputs() +
                '</div>' +
            '</div>';
        },
       
        // 渲染等级输入
        renderLevelInputs: function() {
            var html = '';
             for (var i = 1; i <= 5; i++) {
                 html += '<div class="eq-level-group">' +
                    '<div class="eq-level-title">★' + i + '</div>' +
                    '<div class="eq-form-row">' +
                        '<div class="eq-form-col">' +
                            '<div class="eq-label-small">属性值:</div>' +
                            '<div class="eq-input-small" contenteditable="true" id="eq-value-' + i + '" data-placeholder="数值"></div>' +
                        '</div>' +
                        '<div class="eq-form-col">' +
                            '<div class="eq-label-small">描述:</div>' +
                            '<div class="eq-input-small" contenteditable="true" id="eq-desc-' + i + '" data-placeholder="效果描述"></div>' +
                        '</div>' +
                    '</div>' +
                '</div>';
             }
             }
            return html;
        },
       
        // 渲染装备列表
        renderEquipmentList: function() {
            var $list = $('#equipment-list');
            $list.empty();
              
              
             var html = '<div class="eq-table">' +
             $container.append($list);
                '<div class="eq-table-header">' +
           
                    '<div class="eq-th eq-th-image">图片</div>' +
            // 插入到页面
                    '<div class="eq-th eq-th-name">名称</div>' +
            $('#mw-content-text').empty().append($container);
                    '<div class="eq-th">地区</div>' +
        }
                    '<div class="eq-th">稀有度</div>' +
 
                    '<div class="eq-th">类型</div>' +
        // 创建装备项
                    '<div class="eq-th">TAG</div>' +
        function createEquipmentItem(item) {
                    '<div class="eq-th eq-th-actions">操作</div>' +
            var $item = $('<div>').addClass('equipment-item');
                '</div>' +
                '<div class="eq-table-body">';
              
              
             for (var name in this.currentData) {
             var $info = $('<div>').addClass('equipment-info');
                if (name === 'base') continue;
            $info.append($('<div>').addClass('equipment-name').text(item.name));
                var equip = this.currentData[name];
            $info.append($('<div>').addClass('equipment-meta')
                var base = equip.base;
                .text('ID: ' + item.id + ' | ' + item.area + ' | ' + item.rarity + ' | ' + item.type));
                var relicId = base.art ? base.art.replace('.png', '') : 'unknown';
            $info.append($('<div>').addClass('equipment-tags').text('标签: ' + item.tag));
               
                html += '<div class="eq-table-row" data-equipment="' + name + '">' +
                    '<div class="eq-td eq-td-image">' +
                        '<img src="/images/' + relicId + '.png" alt="' + name + '" class="eq-thumbnail">' +
                    '</div>' +
                    '<div class="eq-td eq-td-name">' + name + '</div>' +
                    '<div class="eq-td">' + (base.area || '') + '</div>' +
                    '<div class="eq-td"><span class="eq-rarity eq-rarity-' + base.rarity + '">' + base.rarity + '</span></div>' +
                    '<div class="eq-td">' + (base.type || '') + '</div>' +
                    '<div class="eq-td">' + (base.tag || '') + '</div>' +
                    '<div class="eq-td eq-td-actions">' +
                        '<div class="eq-btn-small eq-btn-edit" data-name="' + name + '">编辑</div>' +
                        '<div class="eq-btn-small eq-btn-delete" data-name="' + name + '">删除</div>' +
                    '</div>' +
                '</div>';
            }
              
              
             html += '</div></div>';
             var $actions = $('<div>').addClass('equipment-actions');
            $list.html(html);
            $actions.append(
        },
                $('<div>').addClass('equipment-button equipment-button-small').text('编辑')
       
                    .on('click', function () {
        // 绑定事件
                        showEditForm(item);
        bindEvents: function() {
                    })
             var self = this;
            );
            $actions.append(
                $('<div>').addClass('equipment-button equipment-button-small equipment-button-danger').text('删除')
                    .on('click', function () {
                        deleteEquipment(item.name);
                    })
             );
              
              
             // 新增按钮
             $item.append($info).append($actions);
             $(document).on('click', '#eq-add-new', function() {
            return $item;
                 self.openModal('add');
        }
             });
 
        // 插入文本到输入框
        function insertTextIntoTextarea($textarea, beforeText, afterText) {
             var textarea = $textarea[0];
            var start = textarea.selectionStart;
            var end = textarea.selectionEnd;
            var text = textarea.value;
            var selectedText = text.substring(start, end);
           
            var insertText;
            if (selectedText) {
                 insertText = beforeText + selectedText + afterText;
             } else {
                insertText = beforeText + afterText;
            }
              
              
             // 编辑按钮
             var newText = text.substring(0, start) + insertText + text.substring(end);
            $(document).on('click', '.eq-btn-edit', function() {
            $textarea.val(newText);
                var name = $(this).data('name');
                self.openModal('edit', name);
            });
              
              
             // 删除按钮
             // 设置光标位置
             $(document).on('click', '.eq-btn-delete', function() {
             var newCursorPos = start + beforeText.length + selectedText.length;
                var name = $(this).data('name');
            textarea.setSelectionRange(newCursorPos, newCursorPos);
                self.deleteEquipment(name);
            textarea.focus();
            });
        }
 
        // 创建格式化按钮工具栏
        function createFormatToolbar($targetTextarea) {
            var $toolbar = $('<div>').addClass('equipment-format-toolbar');
              
              
             // 关闭模态框
             // 橙色文本按钮
             $(document).on('click', '#modal-close, #eq-cancel, #modal-backdrop', function() {
             var $orangeBtn = $('<div>')
                self.closeModal();
                .addClass('equipment-button equipment-button-small equipment-format-btn')
            });
                .css('color', '#ff8c00')
                .text('橙色文本')
                .on('click', function () {
                    insertTextIntoTextarea($targetTextarea, '{{文本|橙|', '}}');
                });
              
              
             // 保存按钮
             // 词典按钮
             $(document).on('click', '#eq-save', function() {
             var $dictBtn = $('<div>')
                self.saveEquipment();
                .addClass('equipment-button equipment-button-small equipment-format-btn')
            });
                .text('词典')
                .on('click', function () {
                    insertTextIntoTextarea($targetTextarea, '{{词典|', '}}');
                });
              
              
            // 自定义下拉框
             $toolbar.append($orangeBtn).append($dictBtn);
             $(document).on('click', '.eq-select-display', function(e) {
            return $toolbar;
                e.stopPropagation();
        }
                $(this).siblings('.eq-select-dropdown').toggle();
 
             });
        // 显示编辑表单
        function showEditForm(item) {
            var isEdit = item !== null;
            var $overlay = $('<div>').addClass('equipment-overlay');
             var $modal = $('<div>').addClass('equipment-modal');
              
              
             $(document).on('click', '.eq-select-option', function() {
             $modal.append($('<div>').addClass('equipment-modal-title')
                var value = $(this).data('value');
                .text(isEdit ? '编辑装备' : '添加新装备'));
                var text = $(this).text();
                $(this).closest('.eq-select').find('.eq-select-display')
                    .text(text)
                    .attr('data-value', value);
                $(this).parent().hide();
            });
              
              
             $(document).on('click', function() {
             var $form = $('<div>').addClass('equipment-form');
                $('.eq-select-dropdown').hide();
            });
        },
       
        // 打开模态框
        openModal: function(mode, equipmentName) {
            this.editingEquipment = equipmentName;
              
              
             if (mode === 'edit' && equipmentName) {
             // 名称
                $('#modal-title').text('编辑装备');
            $form.append(createFormField('名称', 'name', 'text', isEdit ? item.name : '', isEdit));
                this.fillFormData(equipmentName);
            } else {
                $('#modal-title').text('新增装备');
                this.clearForm();
            }
              
              
             $('#eq-modal, #modal-backdrop').fadeIn(200);
             // ID
        },
             $form.append(createFormField('ID', 'id', 'text', isEdit ? item.id : ''));
       
 
        // 关闭模态框
        closeModal: function() {
             $('#eq-modal, #modal-backdrop').fadeOut(200);
            this.editingEquipment = null;
        },
       
        // 填充表单数据
        fillFormData: function(name) {
            var equip = this.currentData[name];
            if (!equip) return;
              
              
             var base = equip.base;
             // 地区
             $('#eq-name').text(name);
             $form.append(createFormSelect('地区', 'area', AREA_OPTIONS, isEdit ? item.area : ''));
            $('#eq-relic-id').text(base.art ? base.art.replace('.png', '') : '');
            $('#eq-area .eq-select-display').text(base.area).attr('data-value', base.area);
            $('#eq-rarity .eq-select-display').text(base.rarity).attr('data-value', base.rarity);
            $('#eq-type .eq-select-display').text(base.type).attr('data-value', base.type);
            $('#eq-value-type').text(base.value_type || '');
            $('#eq-tag').text(base.tag || '');
              
              
             for (var i = 1; i <= 5; i++) {
             // 稀有度
                if (equip[i]) {
             $form.append(createFormSelect('稀有度', 'rarity', RARITY_OPTIONS, isEdit ? item.rarity : ''));
                    $('#eq-value-' + i).text(equip[i].value || '');
                    $('#eq-desc-' + i).text(equip[i].desc_global || '');
                }
            }
        },
       
        // 清空表单
        clearForm: function() {
             $('.eq-input, .eq-input-small').text('');
            $('.eq-select-display').text('请选择').attr('data-value', '');
            $('#eq-area .eq-select-display').text('请选择地区');
            $('#eq-rarity .eq-select-display').text('请选择稀有度');
            $('#eq-type .eq-select-display').text('请选择类型');
        },
       
        // 获取表单数据
        getFormData: function() {
            var name = $('#eq-name').text().trim();
            var relicId = $('#eq-relic-id').text().trim();
            var area = $('#eq-area .eq-select-display').attr('data-value');
            var rarity = $('#eq-rarity .eq-select-display').attr('data-value');
            var type = $('#eq-type .eq-select-display').attr('data-value');
            var valueType = $('#eq-value-type').text().trim();
            var tag = $('#eq-tag').text().trim();
              
              
             // 验证必填项
             // 类型
             if (!name) {
             $form.append(createFormSelect('类型', 'type', TYPE_OPTIONS, isEdit ? item.type : ''));
                mw.notify('请输入装备名称', {type: 'error'});
                return null;
            }
            if (!relicId) {
                mw.notify('请输入遗物ID', {type: 'error'});
                return null;
            }
            if (!area) {
                mw.notify('请选择地区', {type: 'error'});
                return null;
            }
            if (!rarity) {
                mw.notify('请选择稀有度', {type: 'error'});
                return null;
            }
            if (!type) {
                mw.notify('请选择类型', {type: 'error'});
                return null;
            }
              
              
             var data = {
             // 标签
                name: name,
            $form.append(createFormField('标签 (用逗号分隔)', 'tag', 'text', isEdit ? item.tag : ''));
                base: {
                    area: area,
                    rarity: rarity,
                    type: type,
                    value_type: valueType,
                    tag: tag,
                    art: relicId + '.png'
                },
                levels: {}
            };
              
              
             // 获取等级数据
             // 描述 (5个等级)
             for (var i = 1; i <= 5; i++) {
             for (var i = 1; i <= 5; i++) {
                 var value = $('#eq-value-' + i).text().trim();
                 var $field = createFormField('描述等级 ' + i, 'desc' + i, 'text',
                var desc = $('#eq-desc-' + i).text().trim();
                    isEdit && item.desc ? item.desc[i - 1] : '', false, true);
                  
                  
                 if (value || desc) {
                // 在第一个描述输入框上方添加格式化工具栏
                     data.levels[i] = {
                 if (i === 1) {
                        value: value,
                     var $textarea = $field.find('textarea');
                        desc_global: desc
                    var $toolbar = createFormatToolbar($textarea);
                     };
                     $field.find('.equipment-form-label').after($toolbar);
                 }
                 }
               
                $form.append($field);
             }
             }
              
              
             return data;
             var $actions = $('<div>').addClass('equipment-modal-actions');
        },
            $actions.append(
       
                $('<div>').addClass('equipment-button equipment-button-primary').text('保存')
        // 保存装备
                    .on('click', function () {
        saveEquipment: function() {
                        saveEquipment($form, isEdit, item ? item.name : null);
             var self = this;
                        $overlay.remove();
             var formData = this.getFormData();
                    })
             );
             $actions.append(
                $('<div>').addClass('equipment-button').text('取消')
                    .on('click', function () {
                        $overlay.remove();
                    })
            );
              
              
             if (!formData) return;
             $modal.append($form).append($actions);
            $overlay.append($modal);
            $('body').append($overlay);
        }
 
        // 创建表单字段
        function createFormField(label, name, type, value, readonly, isTextarea) {
            var $field = $('<div>').addClass('equipment-form-field');
            $field.append($('<div>').addClass('equipment-form-label').text(label));
              
              
             // 检查是否重名(新增模式下)
             var $input;
             if (!this.editingEquipment && this.currentData[formData.name]) {
             if (isTextarea) {
                 mw.notify('装备名称已存在', {type: 'error'});
                $input = $('<textarea>').addClass('equipment-form-input equipment-form-textarea')
                 return;
                    .attr('name', name)
                    .attr('rows', '3')
                    .val(value || '');
            } else {
                 $input = $('<input>').addClass('equipment-form-input')
                    .attr('type', type)
                    .attr('name', name)
                    .val(value || '');
            }
           
            if (readonly) {
                 $input.attr('readonly', 'readonly');
             }
             }
            $field.append($input);
            return $field;
        }
        // 创建下拉选择框
        function createFormSelect(label, name, options, value) {
            var $field = $('<div>').addClass('equipment-form-field');
            $field.append($('<div>').addClass('equipment-form-label').text(label));
            var $select = $('<select>').addClass('equipment-form-input').attr('name', name);
           
            $select.append($('<option>').val('').text('请选择...'));
            options.forEach(function (opt) {
                $select.append($('<option>').val(opt).text(opt));
            });
            $select.val(value || '');
              
              
             // 更新本地数据
             $field.append($select);
             var equipmentData = {
            return $field;
                 base: formData.base
        }
             };
 
        // 保存装备
        function saveEquipment($form, isEdit, oldName) {
             var formData = {};
            $form.find('input, select, textarea').each(function () {
                 var $el = $(this);
                formData[$el.attr('name')] = $el.val().trim();
             });
              
              
             for (var level in formData.levels) {
             // 验证必填项
                 equipmentData[level] = formData.levels[level];
            if (!formData.name || !formData.id || !formData.area || !formData.rarity || !formData.type) {
                 mw.notify('请填写所有必填项', { type: 'error' });
                return;
             }
             }
              
              
             // 如果是编辑模式且名称改变,删除旧条目
             var desc = [];
             if (this.editingEquipment && this.editingEquipment !== formData.name) {
             for (var i = 1; i <= 5; i++) {
                 delete this.currentData[this.editingEquipment];
                 desc.push(formData['desc' + i] || '');
             }
             }
              
              
             this.currentData[formData.name] = equipmentData;
             var newItem = {
                name: formData.name,
                id: formData.id,
                area: formData.area,
                rarity: formData.rarity,
                type: formData.type,
                tag: formData.tag,
                desc: desc
            };
              
              
             // 生成 Lua 代码
             // 如果是编辑且名称改变了,删除旧的
             var luaCode = this.generateLuaCode();
             if (isEdit && oldName && oldName !== formData.name) {
                delete equipmentData[oldName];
            }
              
              
             // 保存到模块
             equipmentData[formData.name] = newItem;
             this.saveToModule(luaCode);
             saveToModule();
         },
         }
       
 
         // 删除装备
         // 删除装备
         deleteEquipment: function(name) {
         function deleteEquipment(name) {
            var self = this;
             if (!confirm('确定要删除装备 "' + name + '" 吗?')) {
           
             if (!confirm('确定要删除装备"' + name + '"吗?')) {
                 return;
                 return;
             }
             }
              
              
             delete this.currentData[name];
             delete equipmentData[name];
            saveToModule();
        }
 
        // 保存到模块
        function saveToModule() {
            var luaCode = 'local equipment = {}\n\n';
              
              
            // 生成 Lua 代码
             var names = Object.keys(equipmentData).sort();
            var luaCode = this.generateLuaCode();
           
            // 保存到模块
            this.saveToModule(luaCode);
        },
       
        // 生成 Lua 代码
        generateLuaCode: function() {
            var lua = 'local data = {\n';
           
            // 按名称排序
             var names = Object.keys(this.currentData).sort();
              
              
             for (var i = 0; i < names.length; i++) {
             for (var i = 0; i < names.length; i++) {
                 var name = names[i];
                 var name = names[i];
                 var equip = this.currentData[name];
                 var item = equipmentData[name];
                  
                  
                 lua += '   ["' + this.escapeLua(name) + '"] = {\n';
                 luaCode += 'equipment["' + name + '"] = {\n';
                 lua += '       base = {\n';
                 luaCode += '   id = "' + item.id + '",\n';
                lua += '            area = "' + this.escapeLua(equip.base.area) + '",\n';
                 luaCode += '\tarea = "' + item.area + '",\n';
                 lua += '           rarity = "' + this.escapeLua(equip.base.rarity) + '",\n';
                 luaCode += '   rarity = "' + item.rarity + '",\n';
                 lua += '           type = "' + this.escapeLua(equip.base.type) + '",\n';
                 luaCode += '   type = "' + item.type + '",\n';
                 lua += '           value_type = "' + this.escapeLua(equip.base.value_type || '') + '",\n';
                 luaCode += '   tag = "' + item.tag + '",\n';
                 lua += '           tag = "' + this.escapeLua(equip.base.tag || '') + '",\n';
                 luaCode += '   desc = {\n';
                 lua += '           art = "' + this.escapeLua(equip.base.art) + '"\n';
                lua += '        },\n';
                  
                  
                // 添加等级数据
                 for (var j = 0; j < 5; j++) {
                 for (var level = 1; level <= 5; level++) {
                     var desc = item.desc[j] || '';
                     if (equip[level]) {
                    luaCode += '       "' + desc + '"';
                        lua += '        ["' + level + '"] = {\n';
                    if (j < 4) luaCode += ',';
                        lua += '           value = "' + this.escapeLua(equip[level].value || '') + '",\n';
                    luaCode += '\n';
                        lua += '            desc_global = "' + this.escapeLua(equip[level].desc_global || '') + '"\n';
                        lua += '       },\n';
                    }
                 }
                 }
                  
                  
                 lua += '    },\n';
                 luaCode += '    }\n';
                luaCode += '}\n\n';
             }
             }
              
              
             lua += '}\n\nreturn data';
             luaCode += 'return equipment\n';
              
              
             return lua;
             api.postWithToken('csrf', {
        },
       
        // 转义 Lua 字符串
        escapeLua: function(str) {
            if (!str) return '';
            return str.replace(/\\/g, '\\\\')
                    .replace(/"/g, '\\"')
                    .replace(/\n/g, '\\n')
                    .replace(/\r/g, '\\r');
        },
       
        // 保存到模块
        saveToModule: function(luaCode) {
            var self = this;
           
            // 显示保存中状态
            mw.notify('正在保存...', {type: 'info'});
           
            new mw.Api().postWithToken('csrf', {
                 action: 'edit',
                 action: 'edit',
                 title: '模块:装备/data',
                 title: 'Module:装备/data',
                 text: luaCode,
                 text: luaCode,
                 summary: '通过装备管理器更新数据',
                 summary: '通过装备管理界面更新数据',
                 minor: true
                 contentmodel: 'Scribunto'
             }).done(function(data) {
             }).done(function () {
                 if (data.edit && data.edit.result === 'Success') {
                 mw.notify('保存成功!', { type: 'success' });
                    mw.notify('保存成功!', {type: 'success'});
                loadEquipmentData();
                    self.closeModal();
            }).fail(function (code, result) {
                    self.renderEquipmentList();
                 console.error('保存失败:', code, result);
                 } else {
                 mw.notify('保存失败: ' + code, { type: 'error' });
                    mw.notify('保存失败', {type: 'error'});
                }
            }).fail(function(code, result) {
                 mw.notify('保存失败: ' + (result.error ? result.error.info : '未知错误'), {type: 'error'});
             });
             });
         }
         }
    };
 
   
         init();
    // 页面加载完成后初始化
    $(function() {
         EquipmentManager.init();
     });
     });
   
})();
})();

2025年10月17日 (五) 20:45的最新版本

( function () {
    'use strict';
    
    mw.loader.using( ['mediawiki.api', 'mediawiki.util'], function () {
        if ( mw.config.get( 'wgPageName' ) !== 'MediaWiki:Equipment' ) {
            return;
        }

        mw.loader.load( mw.util.getUrl( 'MediaWiki:Equipment.css', { action: 'raw', ctype: 'text/css' } ), 'text/css' );

        var api = new mw.Api();
        var equipmentData = {};

        // 固定选项
        var AREA_OPTIONS = ['蓝壶', '双星之影', '雾之都市'];
        var RARITY_OPTIONS = ['蓝', '金', '彩'];
        var TYPE_OPTIONS = ['武器', '装甲', '戒指'];

        // 初始化
        function init() {
            loadEquipmentData();
        }

        // 加载装备数据
        function loadEquipmentData() {
            api.get({
                action: 'query',
                prop: 'revisions',
                titles: 'Module:装备/data',
                rvprop: 'content',
                rvslots: 'main',
                formatversion: 2
            }).done(function (data) {
                if (data.query && data.query.pages && data.query.pages[0]) {
                    var page = data.query.pages[0];
                    if (page.revisions && page.revisions[0]) {
                        var content = page.revisions[0].slots.main.content;
                        parseEquipmentData(content);
                        renderUI();
                        return;
                    }
                }
                mw.notify('加载装备数据失败: 未找到数据', { type: 'error' });
            }).fail(function (code, result) {
                console.error('API Error:', code, result);
                mw.notify('加载装备数据失败: ' + code, { type: 'error' });
            });
        }

        // 解析 Lua 数据
        function parseEquipmentData(luaCode) {
            equipmentData = {};
            
            try {
                // 匹配每个装备条目 - 改进的正则表达式
                var lines = luaCode.split('\n');
                var currentName = null;
                var currentItem = null;
                var inDesc = false;
                var descArray = [];
                
                for (var i = 0; i < lines.length; i++) {
                    var line = lines[i].trim();
                    
                    // 匹配装备名称
                    var nameMatch = line.match(/equipment\["([^"]+)"\]\s*=\s*\{/);
                    if (nameMatch) {
                        if (currentName && currentItem) {
                            if (descArray.length > 0) {
                                currentItem.desc = descArray;
                            }
                            equipmentData[currentName] = currentItem;
                        }
                        currentName = nameMatch[1];
                        currentItem = { name: currentName, desc: [] };
                        inDesc = false;
                        descArray = [];
                        continue;
                    }
                    
                    if (!currentItem) continue;
                    
                    // 匹配 desc 开始
                    if (line.match(/desc\s*=\s*\{/)) {
                        inDesc = true;
                        descArray = [];
                        continue;
                    }
                    
                    // desc 结束
                    if (inDesc && line.match(/^\}/)) {
                        inDesc = false;
                        currentItem.desc = descArray;
                        continue;
                    }
                    
                    // 在 desc 内
                    if (inDesc) {
                        var descMatch = line.match(/"([^"]*)"/);
                        if (descMatch) {
                            descArray.push(descMatch[1]);
                        }
                        continue;
                    }
                    
                    // 匹配其他属性
                    var idMatch = line.match(/id\s*=\s*"?([^",\n]+)"?/);
                    if (idMatch) {
                        currentItem.id = idMatch[1];
                        continue;
                    }

                    
                    var areaMatch = line.match(/area\s*=\s*"([^"]+)"/);
                    if (areaMatch) {
                        currentItem.area = areaMatch[1];
                        continue;
                    }
                    
                    var rarityMatch = line.match(/rarity\s*=\s*"([^"]+)"/);
                    if (rarityMatch) {
                        currentItem.rarity = rarityMatch[1];
                        continue;
                    }
                    
                    var typeMatch = line.match(/type\s*=\s*"([^"]+)"/);
                    if (typeMatch) {
                        currentItem.type = typeMatch[1];
                        continue;
                    }
                    
                    var tagMatch = line.match(/tag\s*=\s*"([^"]+)"/);
                    if (tagMatch) {
                        currentItem.tag = tagMatch[1];
                        continue;
                    }
                }
                
                // 保存最后一个装备
                if (currentName && currentItem) {
                    if (descArray.length > 0) {
                        currentItem.desc = descArray;
                    }
                    equipmentData[currentName] = currentItem;
                }
                
                console.log('解析到的装备数据:', equipmentData);
                
            } catch (e) {
                console.error('解析装备数据出错:', e);
                mw.notify('解析装备数据失败', { type: 'error' });
            }
        }

        // 渲染界面
        function renderUI() {
            var $container = $('<div>').addClass('equipment-manager');
            
            // 标题
            $container.append($('<div>').addClass('equipment-title').text('装备数据管理'));
            
            // 统计信息
            var count = Object.keys(equipmentData).length;
            $container.append($('<div>').addClass('equipment-stats').text('共 ' + count + ' 个装备'));
            
            // 添加新装备按钮
            var $addBtn = $('<div>').addClass('equipment-button equipment-button-primary')
                .text('添加新装备')
                .on('click', function () {
                    showEditForm(null);
                });
            $container.append($addBtn);
            
            // 装备列表
            var $list = $('<div>').addClass('equipment-list');
            
            var items = Object.keys(equipmentData).sort();
            for (var i = 0; i < items.length; i++) {
                $list.append(createEquipmentItem(equipmentData[items[i]]));
            }
            
            $container.append($list);
            
            // 插入到页面
            $('#mw-content-text').empty().append($container);
        }

        // 创建装备项
        function createEquipmentItem(item) {
            var $item = $('<div>').addClass('equipment-item');
            
            var $info = $('<div>').addClass('equipment-info');
            $info.append($('<div>').addClass('equipment-name').text(item.name));
            $info.append($('<div>').addClass('equipment-meta')
                .text('ID: ' + item.id + ' | ' + item.area + ' | ' + item.rarity + ' | ' + item.type));
            $info.append($('<div>').addClass('equipment-tags').text('标签: ' + item.tag));
            
            var $actions = $('<div>').addClass('equipment-actions');
            $actions.append(
                $('<div>').addClass('equipment-button equipment-button-small').text('编辑')
                    .on('click', function () {
                        showEditForm(item);
                    })
            );
            $actions.append(
                $('<div>').addClass('equipment-button equipment-button-small equipment-button-danger').text('删除')
                    .on('click', function () {
                        deleteEquipment(item.name);
                    })
            );
            
            $item.append($info).append($actions);
            return $item;
        }

        // 插入文本到输入框
        function insertTextIntoTextarea($textarea, beforeText, afterText) {
            var textarea = $textarea[0];
            var start = textarea.selectionStart;
            var end = textarea.selectionEnd;
            var text = textarea.value;
            var selectedText = text.substring(start, end);
            
            var insertText;
            if (selectedText) {
                insertText = beforeText + selectedText + afterText;
            } else {
                insertText = beforeText + afterText;
            }
            
            var newText = text.substring(0, start) + insertText + text.substring(end);
            $textarea.val(newText);
            
            // 设置光标位置
            var newCursorPos = start + beforeText.length + selectedText.length;
            textarea.setSelectionRange(newCursorPos, newCursorPos);
            textarea.focus();
        }

        // 创建格式化按钮工具栏
        function createFormatToolbar($targetTextarea) {
            var $toolbar = $('<div>').addClass('equipment-format-toolbar');
            
            // 橙色文本按钮
            var $orangeBtn = $('<div>')
                .addClass('equipment-button equipment-button-small equipment-format-btn')
                .css('color', '#ff8c00')
                .text('橙色文本')
                .on('click', function () {
                    insertTextIntoTextarea($targetTextarea, '{{文本|橙|', '}}');
                });
            
            // 词典按钮
            var $dictBtn = $('<div>')
                .addClass('equipment-button equipment-button-small equipment-format-btn')
                .text('词典')
                .on('click', function () {
                    insertTextIntoTextarea($targetTextarea, '{{词典|', '}}');
                });
            
            $toolbar.append($orangeBtn).append($dictBtn);
            return $toolbar;
        }

        // 显示编辑表单
        function showEditForm(item) {
            var isEdit = item !== null;
            var $overlay = $('<div>').addClass('equipment-overlay');
            var $modal = $('<div>').addClass('equipment-modal');
            
            $modal.append($('<div>').addClass('equipment-modal-title')
                .text(isEdit ? '编辑装备' : '添加新装备'));
            
            var $form = $('<div>').addClass('equipment-form');
            
            // 名称
            $form.append(createFormField('名称', 'name', 'text', isEdit ? item.name : '', isEdit));
            
            // ID
            $form.append(createFormField('ID', 'id', 'text', isEdit ? item.id : ''));

            
            // 地区
            $form.append(createFormSelect('地区', 'area', AREA_OPTIONS, isEdit ? item.area : ''));
            
            // 稀有度
            $form.append(createFormSelect('稀有度', 'rarity', RARITY_OPTIONS, isEdit ? item.rarity : ''));
            
            // 类型
            $form.append(createFormSelect('类型', 'type', TYPE_OPTIONS, isEdit ? item.type : ''));
            
            // 标签
            $form.append(createFormField('标签 (用逗号分隔)', 'tag', 'text', isEdit ? item.tag : ''));
            
            // 描述 (5个等级)
            for (var i = 1; i <= 5; i++) {
                var $field = createFormField('描述等级 ' + i, 'desc' + i, 'text', 
                    isEdit && item.desc ? item.desc[i - 1] : '', false, true);
                
                // 在第一个描述输入框上方添加格式化工具栏
                if (i === 1) {
                    var $textarea = $field.find('textarea');
                    var $toolbar = createFormatToolbar($textarea);
                    $field.find('.equipment-form-label').after($toolbar);
                }
                
                $form.append($field);
            }
            
            var $actions = $('<div>').addClass('equipment-modal-actions');
            $actions.append(
                $('<div>').addClass('equipment-button equipment-button-primary').text('保存')
                    .on('click', function () {
                        saveEquipment($form, isEdit, item ? item.name : null);
                        $overlay.remove();
                    })
            );
            $actions.append(
                $('<div>').addClass('equipment-button').text('取消')
                    .on('click', function () {
                        $overlay.remove();
                    })
            );
            
            $modal.append($form).append($actions);
            $overlay.append($modal);
            $('body').append($overlay);
        }

        // 创建表单字段
        function createFormField(label, name, type, value, readonly, isTextarea) {
            var $field = $('<div>').addClass('equipment-form-field');
            $field.append($('<div>').addClass('equipment-form-label').text(label));
            
            var $input;
            if (isTextarea) {
                $input = $('<textarea>').addClass('equipment-form-input equipment-form-textarea')
                    .attr('name', name)
                    .attr('rows', '3')
                    .val(value || '');
            } else {
                $input = $('<input>').addClass('equipment-form-input')
                    .attr('type', type)
                    .attr('name', name)
                    .val(value || '');
            }
            
            if (readonly) {
                $input.attr('readonly', 'readonly');
            }
            $field.append($input);
            return $field;
        }

        // 创建下拉选择框
        function createFormSelect(label, name, options, value) {
            var $field = $('<div>').addClass('equipment-form-field');
            $field.append($('<div>').addClass('equipment-form-label').text(label));
            var $select = $('<select>').addClass('equipment-form-input').attr('name', name);
            
            $select.append($('<option>').val('').text('请选择...'));
            options.forEach(function (opt) {
                $select.append($('<option>').val(opt).text(opt));
            });
            $select.val(value || '');
            
            $field.append($select);
            return $field;
        }

        // 保存装备
        function saveEquipment($form, isEdit, oldName) {
            var formData = {};
            $form.find('input, select, textarea').each(function () {
                var $el = $(this);
                formData[$el.attr('name')] = $el.val().trim();
            });
            
            // 验证必填项
            if (!formData.name || !formData.id || !formData.area || !formData.rarity || !formData.type) {
                mw.notify('请填写所有必填项', { type: 'error' });
                return;
            }
            
            var desc = [];
            for (var i = 1; i <= 5; i++) {
                desc.push(formData['desc' + i] || '');
            }
            
            var newItem = {
                name: formData.name,
                id: formData.id,
                area: formData.area,
                rarity: formData.rarity,
                type: formData.type,
                tag: formData.tag,
                desc: desc
            };
            
            // 如果是编辑且名称改变了,删除旧的
            if (isEdit && oldName && oldName !== formData.name) {
                delete equipmentData[oldName];
            }
            
            equipmentData[formData.name] = newItem;
            saveToModule();
        }

        // 删除装备
        function deleteEquipment(name) {
            if (!confirm('确定要删除装备 "' + name + '" 吗?')) {
                return;
            }
            
            delete equipmentData[name];
            saveToModule();
        }

        // 保存到模块
        function saveToModule() {
            var luaCode = 'local equipment = {}\n\n';
            
            var names = Object.keys(equipmentData).sort();
            
            for (var i = 0; i < names.length; i++) {
                var name = names[i];
                var item = equipmentData[name];
                
                luaCode += 'equipment["' + name + '"] = {\n';
                luaCode += '    id = "' + item.id + '",\n';
                luaCode += '\tarea = "' + item.area + '",\n';
                luaCode += '    rarity = "' + item.rarity + '",\n';
                luaCode += '    type = "' + item.type + '",\n';
                luaCode += '    tag = "' + item.tag + '",\n';
                luaCode += '    desc = {\n';
                
                for (var j = 0; j < 5; j++) {
                    var desc = item.desc[j] || '';
                    luaCode += '        "' + desc + '"';
                    if (j < 4) luaCode += ',';
                    luaCode += '\n';
                }
                
                luaCode += '    }\n';
                luaCode += '}\n\n';
            }
            
            luaCode += 'return equipment\n';
            
            api.postWithToken('csrf', {
                action: 'edit',
                title: 'Module:装备/data',
                text: luaCode,
                summary: '通过装备管理界面更新数据',
                contentmodel: 'Scribunto'
            }).done(function () {
                mw.notify('保存成功!', { type: 'success' });
                loadEquipmentData();
            }).fail(function (code, result) {
                console.error('保存失败:', code, result);
                mw.notify('保存失败: ' + code, { type: 'error' });
            });
        }

        init();
    });
})();