卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
词典
小工具
配队模拟器
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
MediaWiki
查看“︁Partner.js”︁的源代码
←
MediaWiki:Partner.js
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。 如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
/** * MediaWiki伙伴管理器 * 用于创建、编辑和管理伙伴页面 */ (function() { 'use strict'; // 只在MediaWiki:Partner页面运行 if (mw.config.get('wgPageName') !== 'MediaWiki:Partner') { return; } var PartnerManager = { api: new mw.Api(), currentPartner: null, partnerList: [], // 模板字段定义 templateFields: { basic: [ { name: 'id', label: 'ID', type: 'text' }, { name: '名称', label: '名称', type: 'text' }, { name: '稀有度', label: '稀有度', type: 'select', options: ['', '5', '4'] }, { name: '职业', label: '职业', type: 'select', options: ['', '决斗家', '先锋', '游侠', '猎人', '心灵术士', '控制师'] }, { name: '实装日期', label: '实装日期', type: 'text' } ], image: [ { name: 'size', label: 'Size', type: 'text' }, { name: 'right', label: 'Right', type: 'text' }, { name: 'bottom', label: 'Bottom', type: 'text' } ], voice: [ { name: '声优_韩', label: '韩语声优', type: 'text' }, { name: '声优_日', label: '日语声优', type: 'text' }, { name: '声优_英', label: '英语声优', type: 'text' }, { name: '声优_中', label: '中文声优', type: 'text' } ], profile: [ { name: '种族', label: '种族', type: 'text' }, { name: '性别', label: '性别', type: 'select', options: ['', '男', '女'] }, { name: '生日', label: '生日', type: 'text' }, { name: '异能', label: '异能', type: 'text' }, { name: '所属势力', label: '所属势力', type: 'text' }, { name: '档案', label: '档案', type: 'textarea' } ], skills: [ { name: '被动', label: '被动技能', type: 'text' }, { name: '被动_描述', label: '被动描述', type: 'textarea' }, { name: '自我意识技能', label: '自我意识技能', type: 'text' }, { name: '自我意识技能_消耗', label: '自我意识技能消耗', type: 'text' }, { name: '自我意识技能_描述', label: '自我意识技能描述', type: 'textarea' } ], stats: [ { name: '攻击力_1级', label: '攻击力(1级)', type: 'text' }, { name: '攻击力_成长', label: '攻击力成长', type: 'text' }, { name: '防御力_1级', label: '防御力(1级)', type: 'text' }, { name: '防御力_成长', label: '防御力成长', type: 'text' }, { name: 'HP_1级', label: 'HP(1级)', type: 'text' }, { name: 'HP_成长', label: 'HP成长', type: 'text' } ] }, // 初始化 init: function() { this.createUI(); this.loadPartnerList(); }, // 创建UI createUI: function() { var container = document.createElement('div'); container.className = 'agent-manager'; container.innerHTML = ` <div class="agent-section"> <h3>伙伴管理器</h3> <div id="partner-message"></div> <div class="agent-tabs"> <div class="agent-tab active" data-tab="list">伙伴列表</div> <div class="agent-tab" data-tab="edit">编辑/新建</div> <div class="agent-tab" data-tab="batch">批量操作</div> </div> <div id="tab-list" class="agent-tab-content active"> <div class="agent-button" id="refresh-list">刷新列表</div> <div class="agent-button" id="create-new">新建伙伴</div> <div id="partner-list" class="agent-loading">加载中...</div> </div> <div id="tab-edit" class="agent-tab-content"> <div id="editor-container"></div> </div> <div id="tab-batch" class="agent-tab-content"> <div class="agent-form-group"> <label>批量操作</label> <div class="agent-button" id="export-all">导出所有伙伴</div> <div class="agent-button secondary" id="check-templates">检查模板完整性</div> </div> <div id="batch-result"></div> </div> </div> `; var content = document.getElementById('mw-content-text'); content.innerHTML = ''; content.appendChild(container); this.bindEvents(); }, // 绑定事件 bindEvents: function() { var self = this; // 标签切换 document.querySelectorAll('.agent-tab').forEach(function(tab) { tab.addEventListener('click', function() { var tabName = this.getAttribute('data-tab'); self.switchTab(tabName); }); }); // 刷新列表 document.getElementById('refresh-list').addEventListener('click', function() { self.loadPartnerList(); }); // 新建伙伴 document.getElementById('create-new').addEventListener('click', function() { self.createNewPartner(); }); // 导出所有 document.getElementById('export-all').addEventListener('click', function() { self.exportAll(); }); // 检查模板 document.getElementById('check-templates').addEventListener('click', function() { self.checkTemplates(); }); }, // 切换标签 switchTab: function(tabName) { document.querySelectorAll('.agent-tab').forEach(function(tab) { tab.classList.remove('active'); }); document.querySelectorAll('.agent-tab-content').forEach(function(content) { content.classList.remove('active'); }); document.querySelector('[data-tab="' + tabName + '"]').classList.add('active'); document.getElementById('tab-' + tabName).classList.add('active'); }, // 加载伙伴列表 loadPartnerList: function() { var self = this; var listContainer = document.getElementById('partner-list'); listContainer.innerHTML = '<div class="agent-loading">加载中...</div>'; this.api.get({ action: 'query', list: 'categorymembers', cmtitle: 'Category:伙伴', cmlimit: 500, format: 'json' }).done(function(data) { self.partnerList = data.query.categorymembers; self.renderPartnerList(); }).fail(function() { self.showMessage('加载失败,请检查分类是否存在', 'error'); }); }, // 渲染伙伴列表 renderPartnerList: function() { var listContainer = document.getElementById('partner-list'); if (this.partnerList.length === 0) { listContainer.innerHTML = '<div class="agent-message info">暂无伙伴,点击"新建伙伴"开始创建</div>'; return; } var html = '<div class="agent-grid">'; this.partnerList.forEach(function(partner) { html += '<div class="agent-list-item" data-title="' + mw.html.escape(partner.title) + '">' + mw.html.escape(partner.title) + '</div>'; }); html += '</div>'; listContainer.innerHTML = html; var self = this; document.querySelectorAll('.agent-list-item').forEach(function(item) { item.addEventListener('click', function() { var title = this.getAttribute('data-title'); self.loadPartner(title); }); }); }, // 加载伙伴数据 loadPartner: function(title) { var self = this; this.showMessage('加载中...', 'info'); this.api.get({ action: 'query', titles: title, prop: 'revisions', rvprop: 'content', rvslots: 'main', format: 'json' }).done(function(data) { var pages = data.query.pages; var pageId = Object.keys(pages)[0]; if (pageId === '-1') { self.showMessage('页面不存在', 'error'); return; } var content = pages[pageId].revisions[0].slots.main['*']; self.currentPartner = { title: title, content: content }; self.switchTab('edit'); self.renderEditor(); self.showMessage('已加载: ' + title, 'success'); }).fail(function(error) { console.error('加载失败:', error); self.showMessage('加载失败', 'error'); }); }, // 创建新伙伴 createNewPartner: function() { this.currentPartner = { title: '', content: this.generateTemplate({}) }; this.switchTab('edit'); this.renderEditor(); this.showMessage('请填写伙伴信息', 'info'); }, // 渲染编辑器 renderEditor: function() { var self = this; var container = document.getElementById('editor-container'); var data = this.parseTemplate(this.currentPartner.content); var html = '<div class="agent-form-group">'; html += '<label>页面标题</label>'; html += '<input type="text" class="agent-input" id="page-title" value="' + mw.html.escape(this.currentPartner.title || '') + '" placeholder="例如: 伙伴/李四">'; html += '</div>'; // 基础信息 html += '<h4>基础信息</h4>'; html += '<div class="agent-field-row">'; this.templateFields.basic.forEach(function(field) { html += self.renderField(field, data[field.name] || ''); }); html += '</div>'; // 图片位置 html += '<h4>图片位置</h4>'; html += '<div class="agent-field-row">'; this.templateFields.image.forEach(function(field) { html += self.renderField(field, data[field.name] || ''); }); html += '</div>'; // 声优信息 html += '<h4>声优信息</h4>'; html += '<div class="agent-field-row">'; this.templateFields.voice.forEach(function(field) { html += self.renderField(field, data[field.name] || ''); }); html += '</div>'; // 角色档案 html += '<h4>角色档案</h4>'; this.templateFields.profile.forEach(function(field) { html += self.renderField(field, data[field.name] || ''); }); // 技能信息 html += '<h4>技能信息</h4>'; this.templateFields.skills.forEach(function(field) { html += self.renderField(field, data[field.name] || ''); }); // 属性数值 html += '<h4>属性数值</h4>'; html += '<div class="agent-field-row">'; this.templateFields.stats.forEach(function(field) { html += self.renderField(field, data[field.name] || ''); }); html += '</div>'; // 操作按钮 html += '<div style="margin-top: 20px;">'; html += '<div class="agent-button" id="save-partner">保存伙伴</div>'; html += '<div class="agent-button secondary" id="preview-partner">预览</div>'; html += '<div class="agent-button secondary" id="view-source">查看源码</div>'; if (this.currentPartner.title) { html += '<div class="agent-button secondary" id="view-page">查看页面</div>'; } html += '</div>'; html += '<div id="preview-container" style="margin-top: 20px;"></div>'; container.innerHTML = html; // 绑定保存事件 document.getElementById('save-partner').addEventListener('click', function() { self.savePartner(); }); // 绑定预览事件 document.getElementById('preview-partner').addEventListener('click', function() { self.previewPartner(); }); // 绑定查看源码事件 document.getElementById('view-source').addEventListener('click', function() { self.viewSource(); }); // 绑定查看页面事件 if (this.currentPartner.title) { document.getElementById('view-page').addEventListener('click', function() { window.open(mw.util.getUrl(self.currentPartner.title), '_blank'); }); } }, // 渲染表单字段 renderField: function(field, value) { var escapedValue = mw.html.escape(String(value)); var html = '<div class="agent-form-group">'; html += '<label>' + mw.html.escape(field.label) + '</label>'; if (field.type === 'select') { html += '<select class="agent-select" data-field="' + mw.html.escape(field.name) + '">'; field.options.forEach(function(option) { var selected = (value === option) ? ' selected' : ''; html += '<option value="' + mw.html.escape(option) + '"' + selected + '>' + mw.html.escape(option || '请选择') + '</option>'; }); html += '</select>'; } else if (field.type === 'textarea') { html += '<textarea class="agent-textarea" data-field="' + mw.html.escape(field.name) + '">' + escapedValue + '</textarea>'; } else { html += '<input type="text" class="agent-input" data-field="' + mw.html.escape(field.name) + '" value="' + escapedValue + '">'; } html += '</div>'; return html; }, // 解析模板 parseTemplate: function(content) { var data = {}; // 查找伙伴模板 var templateStart = content.indexOf('{{伙伴'); var templateEnd = content.lastIndexOf('}}'); if (templateStart === -1 || templateEnd === -1) { return data; } // 提取模板内容 var templateContent = content.substring(templateStart, templateEnd + 2); // 移除开头的 {{伙伴 和结尾的 }} templateContent = templateContent.replace(/^\{\{伙伴\s*/, '').replace(/\s*\}\}$/, ''); // 按行分割 var lines = templateContent.split('\n'); for (var i = 0; i < lines.length; i++) { var line = lines[i].trim(); // 跳过空行和只有|的行 if (!line || line === '|') { continue; } // 移除开头的 | if (line.charAt(0) === '|') { line = line.substring(1); } // 查找第一个 = 的位置 var equalPos = line.indexOf('='); if (equalPos > 0) { var key = line.substring(0, equalPos).trim(); var value = line.substring(equalPos + 1).trim(); if (key) { data[key] = value; } } } return data; }, // 生成模板(只输出非空字段) generateTemplate: function(data) { var self = this; var template = '{{面包屑|伙伴图鉴}}\n{{伙伴\n'; // 辅助函数:添加字段(只添加非空字段) var addFields = function(fields) { var hasContent = false; var output = ''; fields.forEach(function(field) { var value = data[field.name] || ''; // 只有当值不为空时才输出该字段 if (value.trim() !== '') { output += '|' + field.name + '=' + value + '\n'; hasContent = true; } }); if (hasContent) { output += '\n'; } return output; }; // 基础信息 template += addFields(this.templateFields.basic); // 图片位置 template += addFields(this.templateFields.image); // 声优信息 template += addFields(this.templateFields.voice); // 角色档案 template += addFields(this.templateFields.profile); // 技能信息 template += addFields(this.templateFields.skills); // 属性数值 template += addFields(this.templateFields.stats); // 移除末尾多余的空行 template = template.replace(/\n+$/, '\n'); template += '}}\n[[分类:伙伴]]'; return template; }, // 收集表单数据 collectFormData: function() { var data = {}; document.querySelectorAll('[data-field]').forEach(function(input) { var field = input.getAttribute('data-field'); data[field] = input.value; }); return data; }, // 保存伙伴 savePartner: function() { var self = this; var title = document.getElementById('page-title').value.trim(); if (!title) { this.showMessage('请输入页面标题', 'error'); return; } var data = this.collectFormData(); var content = this.generateTemplate(data); this.showMessage('保存中...', 'info'); this.api.postWithToken('csrf', { action: 'edit', title: title, text: content, summary: '通过伙伴管理器更新', format: 'json' }).done(function() { self.showMessage('保存成功!', 'success'); self.currentPartner.title = title; self.currentPartner.content = content; self.loadPartnerList(); }).fail(function(code, error) { console.error('保存失败:', code, error); self.showMessage('保存失败: ' + (error.error ? error.error.info : '未知错误'), 'error'); }); }, // 预览 previewPartner: function() { var data = this.collectFormData(); var content = this.generateTemplate(data); var preview = document.getElementById('preview-container'); preview.innerHTML = '<h4>预览</h4><pre style="background: #f5f5f5; padding: 10px; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;">' + mw.html.escape(content) + '</pre>'; }, // 查看源码 viewSource: function() { var data = this.collectFormData(); var content = this.generateTemplate(data); var preview = document.getElementById('preview-container'); preview.innerHTML = '<h4>Wiki源码</h4>' + '<textarea class="agent-textarea" style="min-height: 400px;">' + mw.html.escape(content) + '</textarea>'; }, // 导出所有 exportAll: function() { var self = this; var result = document.getElementById('batch-result'); result.innerHTML = '<div class="agent-loading">导出中...</div>'; var exportData = []; var promises = []; this.partnerList.forEach(function(partner) { var promise = self.api.get({ action: 'query', titles: partner.title, prop: 'revisions', rvprop: 'content', rvslots: 'main', format: 'json' }).then(function(data) { var pages = data.query.pages; var pageId = Object.keys(pages)[0]; if (pageId !== '-1') { var content = pages[pageId].revisions[0].slots.main['*']; exportData.push({ title: partner.title, content: content }); } }); promises.push(promise); }); Promise.all(promises).then(function() { var json = JSON.stringify(exportData, null, 2); result.innerHTML = '<h4>导出结果 (' + exportData.length + '个伙伴)</h4>' + '<textarea class="agent-textarea" style="min-height: 400px;">' + mw.html.escape(json) + '</textarea>'; }); }, // 检查模板完整性 checkTemplates: function() { var self = this; var result = document.getElementById('batch-result'); result.innerHTML = '<div class="agent-loading">检查中...</div>'; var issues = []; var promises = []; this.partnerList.forEach(function(partner) { var promise = self.api.get({ action: 'query', titles: partner.title, prop: 'revisions', rvprop: 'content', rvslots: 'main', format: 'json' }).then(function(data) { var pages = data.query.pages; var pageId = Object.keys(pages)[0]; if (pageId !== '-1') { var content = pages[pageId].revisions[0].slots.main['*']; var parsedData = self.parseTemplate(content); var missingFields = []; // 只检查关键字段 var requiredFields = [ { name: 'id', label: 'ID' }, { name: '名称', label: '名称' }, { name: '稀有度', label: '稀有度' }, { name: '职业', label: '职业' } ]; requiredFields.forEach(function(field) { if (!parsedData[field.name] || parsedData[field.name].trim() === '') { missingFields.push(field.label); } }); if (missingFields.length > 0) { issues.push({ title: partner.title, missing: missingFields }); } } }); promises.push(promise); }); Promise.all(promises).then(function() { var html = '<h4>模板检查结果</h4>'; if (issues.length === 0) { html += '<div class="agent-message success">所有伙伴模板完整!</div>'; } else { html += '<div class="agent-message error">发现 ' + issues.length + ' 个页面存在问题:</div>'; html += '<div style="max-height: 400px; overflow-y: auto;">'; issues.forEach(function(issue) { html += '<div style="margin: 10px 0; padding: 10px; background: white; border: 1px solid #ddd;">'; html += '<strong>' + mw.html.escape(issue.title) + '</strong><br>'; html += '缺失字段: ' + mw.html.escape(issue.missing.join(', ')); html += '</div>'; }); html += '</div>'; } result.innerHTML = html; }); }, // 显示消息 showMessage: function(message, type) { var container = document.getElementById('partner-message'); container.innerHTML = '<div class="agent-message ' + type + '">' + mw.html.escape(message) + '</div>'; setTimeout(function() { container.innerHTML = ''; }, 5000); } }; // 页面加载完成后初始化 $(function() { PartnerManager.init(); }); })();
该页面使用的模板:
模板:伙伴 和结尾的
(
查看源代码
)
模板:提示
(
查看源代码
)
模板:文本
(
查看源代码
)
模板:词典
(
查看源代码
)
模板:面包屑
(
查看源代码
)
模块:文本
(
查看源代码
)
模块:词典
(
查看源代码
)
模块:词典/data
(
查看源代码
)
返回
MediaWiki:Partner.js
。