Agent.js:修订间差异
来自卡厄思梦境WIKI
创建页面,内容为“→* * MediaWiki战斗员管理器 * 用于创建、编辑和管理战斗员页面: (function() { 'use strict'; // 只在MediaWiki:Agent页面运行 if (mw.config.get('wgPageName') !== 'MediaWiki:Agent') { return; } var AgentManager = { api: new mw.Api(), currentAgent: null, agentList: [], // 模板字段定义 templateFields: { basic: [ { name…” |
无编辑摘要 |
||
| 第25行: | 第25行: | ||
{ name: '属性', label: '属性', type: 'text' }, | { name: '属性', label: '属性', type: 'text' }, | ||
{ name: '实装日期', label: '实装日期', type: 'text' } | { name: '实装日期', label: '实装日期', type: 'text' } | ||
], | |||
image: [ | |||
{ name: '立绘bottom', label: '立绘Bottom', type: 'text' }, | |||
{ name: '立绘right', label: '立绘Right', type: 'text' }, | |||
{ name: '自我bottom', label: '自我Bottom', type: 'text' }, | |||
{ name: '自我right', label: '自我Right', type: 'text' } | |||
], | ], | ||
voice: [ | voice: [ | ||
| 第44行: | 第50行: | ||
{ name: 'HP_1级', label: 'HP(1级)', type: 'text' }, | { name: 'HP_1级', label: 'HP(1级)', type: 'text' }, | ||
{ name: '暴击率_1级', label: '暴击率(1级)', type: 'text' }, | { name: '暴击率_1级', label: '暴击率(1级)', type: 'text' }, | ||
{ name: '暴击伤害_1级', label: '暴击伤害(1级)', type: 'text' } | { name: '暴击伤害_1级', label: '暴击伤害(1级)', type: 'text' }, | ||
{ name: '弱点伤害率_1级', label: '弱点伤害率(1级)', type: 'text' }, | |||
{ name: '自我意识恢复力_1级', label: '自我意识恢复力(1级)', type: 'text' } | |||
], | |||
damage: [ | |||
{ name: '热情属性伤害量_1级', label: '热情属性伤害量(1级)', type: 'text' }, | |||
{ name: '正义属性伤害量_1级', label: '正义属性伤害量(1级)', type: 'text' }, | |||
{ name: '秩序属性伤害量_1级', label: '秩序属性伤害量(1级)', type: 'text' }, | |||
{ name: '本能属性伤害量_1级', label: '本能属性伤害量(1级)', type: 'text' }, | |||
{ name: '虚无属性伤害量_1级', label: '虚无属性伤害量(1级)', type: 'text' }, | |||
{ name: '额外伤害量_1级', label: '额外伤害量(1级)', type: 'text' }, | |||
{ name: '持续伤害量_1级', label: '持续伤害量(1级)', type: 'text' } | |||
], | ], | ||
skills: [ | skills: [ | ||
{ name: '骰术', label: '骰术', type: 'text' }, | |||
{ name: '骰术_1级', label: '骰术(1级)', type: 'text' }, | |||
{ name: '自我意识技能', label: '自我意识技能', type: 'text' }, | { name: '自我意识技能', label: '自我意识技能', type: 'text' }, | ||
{ name: '自我意识技能消耗', label: '技能消耗', type: 'text' }, | { name: '自我意识技能消耗', label: '技能消耗', type: 'text' }, | ||
{ name: '自我意识技能描述', label: '技能描述', type: 'textarea | { name: '自我意识技能描述', label: '技能描述', type: 'textarea' } | ||
], | ], | ||
cards: [ | cards: [ | ||
| 第62行: | 第79行: | ||
{ name: '独特卡牌_3', label: '独特卡牌3', type: 'text' }, | { name: '独特卡牌_3', label: '独特卡牌3', type: 'text' }, | ||
{ name: '独特卡牌_4', label: '独特卡牌4', type: 'text' } | { name: '独特卡牌_4', label: '独特卡牌4', type: 'text' } | ||
], | |||
ego: [ | |||
{ name: '展现自我意识_01', label: '展现自我意识01', type: 'text' }, | |||
{ name: '展现自我意识_02', label: '展现自我意识02', type: 'text' }, | |||
{ name: '展现自我意识_03', label: '展现自我意识03', type: 'text' }, | |||
{ name: '展现自我意识_04', label: '展现自我意识04', type: 'text' }, | |||
{ name: '展现自我意识_06', label: '展现自我意识06', type: 'text' } | |||
], | |||
potential: [ | |||
{ name: '潜力_03-1', label: '潜力03-1', type: 'text' }, | |||
{ name: '潜力_05', label: '潜力05', type: 'text' }, | |||
{ name: '潜力_05-1', label: '潜力05-1', type: 'text' }, | |||
{ name: '潜力_06', label: '潜力06', type: 'text' }, | |||
{ name: '潜力_07', label: '潜力07', type: 'text' } | |||
] | ] | ||
}, | }, | ||
| 第191行: | 第222行: | ||
var html = '<div class="agent-grid">'; | var html = '<div class="agent-grid">'; | ||
this.agentList.forEach(function(agent) { | this.agentList.forEach(function(agent) { | ||
html += '<div class="agent-list-item" data-title="' + agent.title + '">' + agent.title + '</div>'; | html += '<div class="agent-list-item" data-title="' + mw.html.escape(agent.title) + '">' + | ||
mw.html.escape(agent.title) + '</div>'; | |||
}); | }); | ||
html += '</div>'; | html += '</div>'; | ||
| 第216行: | 第248行: | ||
prop: 'revisions', | prop: 'revisions', | ||
rvprop: 'content', | rvprop: 'content', | ||
rvslots: 'main', | |||
format: 'json' | format: 'json' | ||
}).done(function(data) { | }).done(function(data) { | ||
var pages = data.query.pages; | var pages = data.query.pages; | ||
var pageId = Object.keys(pages)[0]; | var pageId = Object.keys(pages)[0]; | ||
var content = pages[pageId].revisions[0]['*']; | |||
if (pageId === '-1') { | |||
self.showMessage('页面不存在', 'error'); | |||
return; | |||
} | |||
var content = pages[pageId].revisions[0].slots.main['*']; | |||
self.currentAgent = { | self.currentAgent = { | ||
| 第226行: | 第265行: | ||
content: content | content: content | ||
}; | }; | ||
console.log('加载的页面内容:', content); | |||
self.switchTab('edit'); | self.switchTab('edit'); | ||
self.renderEditor(); | self.renderEditor(); | ||
self.showMessage('已加载: ' + title, 'success'); | self.showMessage('已加载: ' + title, 'success'); | ||
}).fail(function() { | }).fail(function(error) { | ||
console.error('加载失败:', error); | |||
self.showMessage('加载失败', 'error'); | self.showMessage('加载失败', 'error'); | ||
}); | }); | ||
| 第251行: | 第293行: | ||
var container = document.getElementById('editor-container'); | var container = document.getElementById('editor-container'); | ||
var data = this.parseTemplate(this.currentAgent.content); | var data = this.parseTemplate(this.currentAgent.content); | ||
console.log('解析的数据:', data); | |||
var html = '<div class="agent-form-group">'; | var html = '<div class="agent-form-group">'; | ||
html += '<label>页面标题</label>'; | html += '<label>页面标题</label>'; | ||
html += '<input type="text" class="agent-input" id="page-title" value="' + (this.currentAgent.title || '') + '" placeholder="例如: 战斗员/张三">'; | html += '<input type="text" class="agent-input" id="page-title" value="' + | ||
mw.html.escape(this.currentAgent.title || '') + '" placeholder="例如: 战斗员/张三">'; | |||
html += '</div>'; | html += '</div>'; | ||
| 第261行: | 第306行: | ||
html += '<div class="agent-field-row">'; | html += '<div class="agent-field-row">'; | ||
this.templateFields.basic.forEach(function(field) { | 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 += self.renderField(field, data[field.name] || ''); | ||
}); | }); | ||
| 第280行: | 第333行: | ||
// 属性数值 | // 属性数值 | ||
html += '<h4> | html += '<h4>基础属性数值</h4>'; | ||
html += '<div class="agent-field-row">'; | html += '<div class="agent-field-row">'; | ||
this.templateFields.stats.forEach(function(field) { | this.templateFields.stats.forEach(function(field) { | ||
html += self.renderField(field, data[field.name] || ''); | |||
}); | |||
html += '</div>'; | |||
// 伤害数值 | |||
html += '<h4>伤害数值</h4>'; | |||
html += '<div class="agent-field-row">'; | |||
this.templateFields.damage.forEach(function(field) { | |||
html += self.renderField(field, data[field.name] || ''); | html += self.renderField(field, data[field.name] || ''); | ||
}); | }); | ||
| 第297行: | 第358行: | ||
html += '<div class="agent-field-row">'; | html += '<div class="agent-field-row">'; | ||
this.templateFields.cards.forEach(function(field) { | this.templateFields.cards.forEach(function(field) { | ||
html += self.renderField(field, data[field.name] || ''); | |||
}); | |||
html += '</div>'; | |||
// 自我意识 | |||
html += '<h4>展现自我意识</h4>'; | |||
html += '<div class="agent-field-row">'; | |||
this.templateFields.ego.forEach(function(field) { | |||
html += self.renderField(field, data[field.name] || ''); | |||
}); | |||
html += '</div>'; | |||
// 潜力 | |||
html += '<h4>潜力</h4>'; | |||
html += '<div class="agent-field-row">'; | |||
this.templateFields.potential.forEach(function(field) { | |||
html += self.renderField(field, data[field.name] || ''); | html += self.renderField(field, data[field.name] || ''); | ||
}); | }); | ||
| 第306行: | 第383行: | ||
html += '<div class="agent-button secondary" id="preview-agent">预览</div>'; | html += '<div class="agent-button secondary" id="preview-agent">预览</div>'; | ||
html += '<div class="agent-button secondary" id="view-source">查看源码</div>'; | html += '<div class="agent-button secondary" id="view-source">查看源码</div>'; | ||
if (this.currentAgent.title) { | |||
html += '<div class="agent-button secondary" id="view-page">查看页面</div>'; | |||
} | |||
html += '</div>'; | html += '</div>'; | ||
| 第326行: | 第406行: | ||
self.viewSource(); | self.viewSource(); | ||
}); | }); | ||
// 绑定查看页面事件 | |||
if (this.currentAgent.title) { | |||
document.getElementById('view-page').addEventListener('click', function() { | |||
window.open(mw.util.getUrl(self.currentAgent.title), '_blank'); | |||
}); | |||
} | |||
}, | }, | ||
// 渲染表单字段 | // 渲染表单字段 | ||
renderField: function(field, value) { | renderField: function(field, value) { | ||
var escapedValue = mw.html.escape(value); | |||
var html = '<div class="agent-form-group">'; | var html = '<div class="agent-form-group">'; | ||
html += '<label>' + field.label + '</label>'; | html += '<label>' + mw.html.escape(field.label) + '</label>'; | ||
if (field.type === 'textarea') { | if (field.type === 'textarea') { | ||
html += '<textarea class="agent-textarea" data-field="' + field.name + '">' + | html += '<textarea class="agent-textarea" data-field="' + | ||
mw.html.escape(field.name) + '">' + escapedValue + '</textarea>'; | |||
} else { | } else { | ||
html += '<input type="text" class="agent-input" data-field="' + field.name + '" value="' + | html += '<input type="text" class="agent-input" data-field="' + | ||
mw.html.escape(field.name) + '" value="' + escapedValue + '">'; | |||
} | } | ||
| 第343行: | 第433行: | ||
}, | }, | ||
// | // 解析模板(修复后的版本) | ||
parseTemplate: function(content) { | parseTemplate: function(content) { | ||
var data = {}; | var data = {}; | ||
// 移除模板开始和结束标记 | |||
data[ | var templateMatch = content.match(/\{\{战斗员\s*([\s\S]*?)\}\}/); | ||
if (!templateMatch) { | |||
console.log('未找到战斗员模板'); | |||
return data; | |||
} | |||
var templateContent = templateMatch[1]; | |||
console.log('模板内容:', templateContent); | |||
// 使用更宽泛的正则表达式来匹配字段,支持中文和特殊字符 | |||
// 匹配 |字段名=值 的模式 | |||
var lines = templateContent.split('\n'); | |||
for (var i = 0; i < lines.length; i++) { | |||
var line = lines[i].trim(); | |||
// 跳过空行 | |||
if (!line || line === '|') { | |||
continue; | |||
} | |||
// 检查是否以 | 开头 | |||
if (line.indexOf('|') === 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; | |||
console.log('解析字段:', key, '=', value); | |||
} | |||
} | |||
} | } | ||
| 第360行: | 第484行: | ||
var template = '{{面包屑|战斗员图鉴}}\n{{战斗员\n'; | var template = '{{面包屑|战斗员图鉴}}\n{{战斗员\n'; | ||
// | // 按照固定顺序添加字段 | ||
var | var fieldGroups = [ | ||
this.templateFields.basic, | this.templateFields.basic, | ||
this.templateFields.image, | |||
this.templateFields.voice, | this.templateFields.voice, | ||
this.templateFields.profile, | this.templateFields.profile, | ||
this.templateFields.stats, | this.templateFields.stats, | ||
this.templateFields.damage, | |||
this.templateFields.skills, | this.templateFields.skills, | ||
this.templateFields.cards | this.templateFields.cards, | ||
this.templateFields.ego, | |||
this.templateFields.potential | |||
]; | |||
fieldGroups.forEach(function(group) { | |||
group.forEach(function(field) { | |||
var value = data[field.name] || ''; | |||
template += '|' + field.name + '=' + value + '\n'; | |||
}); | |||
}); | }); | ||
| 第415行: | 第545行: | ||
self.currentAgent.content = content; | self.currentAgent.content = content; | ||
self.loadAgentList(); | self.loadAgentList(); | ||
}).fail(function(error) { | }).fail(function(code, error) { | ||
self.showMessage('保存失败: ' + error, 'error'); | console.error('保存失败:', code, error); | ||
self.showMessage('保存失败: ' + (error.error ? error.error.info : '未知错误'), 'error'); | |||
}); | }); | ||
}, | }, | ||
| 第426行: | 第557行: | ||
var preview = document.getElementById('preview-container'); | var preview = document.getElementById('preview-container'); | ||
preview.innerHTML = '<h4>预览</h4><pre style="background: #f5f5f5; padding: 10px; overflow-x: auto;">' + | 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>'; | |||
}, | }, | ||
| 第437行: | 第568行: | ||
var preview = document.getElementById('preview-container'); | var preview = document.getElementById('preview-container'); | ||
preview.innerHTML = '<h4>Wiki源码</h4>' + | preview.innerHTML = '<h4>Wiki源码</h4>' + | ||
'<textarea class="agent-textarea" style="min-height: 400px;">' + content + '</textarea>'; | '<textarea class="agent-textarea" style="min-height: 400px;">' + | ||
mw.html.escape(content) + '</textarea>'; | |||
}, | }, | ||
| 第455行: | 第587行: | ||
prop: 'revisions', | prop: 'revisions', | ||
rvprop: 'content', | rvprop: 'content', | ||
rvslots: 'main', | |||
format: 'json' | format: 'json' | ||
}).then(function(data) { | }).then(function(data) { | ||
var pages = data.query.pages; | var pages = data.query.pages; | ||
var pageId = Object.keys(pages)[0]; | var pageId = Object.keys(pages)[0]; | ||
var content = pages[pageId].revisions[0]['*']; | if (pageId !== '-1') { | ||
var content = pages[pageId].revisions[0].slots.main['*']; | |||
exportData.push({ | |||
title: agent.title, | |||
content: content | |||
}); | |||
} | |||
}); | }); | ||
promises.push(promise); | promises.push(promise); | ||
| 第471行: | 第606行: | ||
var json = JSON.stringify(exportData, null, 2); | var json = JSON.stringify(exportData, null, 2); | ||
result.innerHTML = '<h4>导出结果 (' + exportData.length + '个战斗员)</h4>' + | result.innerHTML = '<h4>导出结果 (' + exportData.length + '个战斗员)</h4>' + | ||
'<textarea class="agent-textarea" style="min-height: 400px;">' + json + '</textarea>'; | '<textarea class="agent-textarea" style="min-height: 400px;">' + | ||
mw.html.escape(json) + '</textarea>'; | |||
}); | }); | ||
}, | }, | ||
| 第490行: | 第626行: | ||
prop: 'revisions', | prop: 'revisions', | ||
rvprop: 'content', | rvprop: 'content', | ||
rvslots: 'main', | |||
format: 'json' | format: 'json' | ||
}).then(function(data) { | }).then(function(data) { | ||
var pages = data.query.pages; | var pages = data.query.pages; | ||
var pageId = Object.keys(pages)[0]; | var pageId = Object.keys(pages)[0]; | ||
var content = pages[pageId].revisions[0]['*']; | if (pageId !== '-1') { | ||
var content = pages[pageId].revisions[0].slots.main['*']; | |||
var parsedData = self.parseTemplate(content); | |||
var missingFields = []; | |||
var allFields = [].concat( | |||
self.templateFields.basic, | |||
self.templateFields.voice, | |||
self.templateFields.profile | |||
); | |||
allFields.forEach(function(field) { | |||
if (!parsedData[field.name] || parsedData[field.name].trim() === '') { | |||
missingFields.push(field.label); | |||
} | |||
}); | |||
if (missingFields.length > 0) { | |||
issues.push({ | |||
title: agent.title, | |||
missing: missingFields | |||
}); | |||
} | } | ||
} | } | ||
}); | }); | ||
| 第529行: | 第668行: | ||
issues.forEach(function(issue) { | issues.forEach(function(issue) { | ||
html += '<div style="margin: 10px 0; padding: 10px; background: white; border: 1px solid #ddd;">'; | html += '<div style="margin: 10px 0; padding: 10px; background: white; border: 1px solid #ddd;">'; | ||
html += '<strong>' + issue.title + '</strong><br>'; | html += '<strong>' + mw.html.escape(issue.title) + '</strong><br>'; | ||
html += '缺失字段: ' + issue.missing.join(', '); | html += '缺失字段: ' + mw.html.escape(issue.missing.join(', ')); | ||
html += '</div>'; | html += '</div>'; | ||
}); | }); | ||
| 第542行: | 第681行: | ||
showMessage: function(message, type) { | showMessage: function(message, type) { | ||
var container = document.getElementById('agent-message'); | var container = document.getElementById('agent-message'); | ||
container.innerHTML = '<div class="agent-message ' + type + '">' + message + '</div>'; | container.innerHTML = '<div class="agent-message ' + type + '">' + mw.html.escape(message) + '</div>'; | ||
setTimeout(function() { | setTimeout(function() { | ||
2025年10月2日 (四) 23:36的版本
/**
* MediaWiki战斗员管理器
* 用于创建、编辑和管理战斗员页面
*/
(function() {
'use strict';
// 只在MediaWiki:Agent页面运行
if (mw.config.get('wgPageName') !== 'MediaWiki:Agent') {
return;
}
var AgentManager = {
api: new mw.Api(),
currentAgent: null,
agentList: [],
// 模板字段定义
templateFields: {
basic: [
{ name: 'id', label: 'ID', type: 'text' },
{ name: '名称', label: '名称', type: 'text' },
{ name: '稀有度', label: '稀有度', type: 'text' },
{ name: '职业', label: '职业', type: 'text' },
{ name: '属性', label: '属性', type: 'text' },
{ name: '实装日期', label: '实装日期', type: 'text' }
],
image: [
{ name: '立绘bottom', label: '立绘Bottom', type: 'text' },
{ name: '立绘right', label: '立绘Right', type: 'text' },
{ name: '自我bottom', label: '自我Bottom', type: 'text' },
{ name: '自我right', label: '自我Right', type: 'text' }
],
voice: [
{ name: '声优_韩', label: '韩语声优', type: 'text' },
{ name: '声优_日', label: '日语声优', type: 'text' },
{ name: '声优_英', label: '英语声优', type: 'text' }
],
profile: [
{ name: '种族', label: '种族', type: 'text' },
{ name: '性别', label: '性别', type: 'text' },
{ name: '生日', label: '生日', type: 'text' },
{ name: '异能', label: '异能', type: 'text' },
{ name: '所属势力', label: '所属势力', type: 'text' },
{ name: '档案', label: '档案', type: 'textarea' }
],
stats: [
{ name: '攻击力_1级', label: '攻击力(1级)', type: 'text' },
{ name: '防御力_1级', label: '防御力(1级)', type: 'text' },
{ name: 'HP_1级', label: 'HP(1级)', type: 'text' },
{ name: '暴击率_1级', label: '暴击率(1级)', type: 'text' },
{ name: '暴击伤害_1级', label: '暴击伤害(1级)', type: 'text' },
{ name: '弱点伤害率_1级', label: '弱点伤害率(1级)', type: 'text' },
{ name: '自我意识恢复力_1级', label: '自我意识恢复力(1级)', type: 'text' }
],
damage: [
{ name: '热情属性伤害量_1级', label: '热情属性伤害量(1级)', type: 'text' },
{ name: '正义属性伤害量_1级', label: '正义属性伤害量(1级)', type: 'text' },
{ name: '秩序属性伤害量_1级', label: '秩序属性伤害量(1级)', type: 'text' },
{ name: '本能属性伤害量_1级', label: '本能属性伤害量(1级)', type: 'text' },
{ name: '虚无属性伤害量_1级', label: '虚无属性伤害量(1级)', type: 'text' },
{ name: '额外伤害量_1级', label: '额外伤害量(1级)', type: 'text' },
{ name: '持续伤害量_1级', label: '持续伤害量(1级)', type: 'text' }
],
skills: [
{ name: '骰术', label: '骰术', type: 'text' },
{ name: '骰术_1级', label: '骰术(1级)', type: 'text' },
{ name: '自我意识技能', label: '自我意识技能', type: 'text' },
{ name: '自我意识技能消耗', label: '技能消耗', type: 'text' },
{ name: '自我意识技能描述', label: '技能描述', type: 'textarea' }
],
cards: [
{ name: '起始卡牌_1', label: '起始卡牌1', type: 'text' },
{ name: '起始卡牌_2', label: '起始卡牌2', type: 'text' },
{ name: '起始卡牌_3', label: '起始卡牌3', type: 'text' },
{ name: '起始卡牌_4', label: '起始卡牌4', type: 'text' },
{ name: '独特卡牌_1', label: '独特卡牌1', type: 'text' },
{ name: '独特卡牌_2', label: '独特卡牌2', type: 'text' },
{ name: '独特卡牌_3', label: '独特卡牌3', type: 'text' },
{ name: '独特卡牌_4', label: '独特卡牌4', type: 'text' }
],
ego: [
{ name: '展现自我意识_01', label: '展现自我意识01', type: 'text' },
{ name: '展现自我意识_02', label: '展现自我意识02', type: 'text' },
{ name: '展现自我意识_03', label: '展现自我意识03', type: 'text' },
{ name: '展现自我意识_04', label: '展现自我意识04', type: 'text' },
{ name: '展现自我意识_06', label: '展现自我意识06', type: 'text' }
],
potential: [
{ name: '潜力_03-1', label: '潜力03-1', type: 'text' },
{ name: '潜力_05', label: '潜力05', type: 'text' },
{ name: '潜力_05-1', label: '潜力05-1', type: 'text' },
{ name: '潜力_06', label: '潜力06', type: 'text' },
{ name: '潜力_07', label: '潜力07', type: 'text' }
]
},
// 初始化
init: function() {
this.createUI();
this.loadAgentList();
},
// 创建UI
createUI: function() {
var container = document.createElement('div');
container.className = 'agent-manager';
container.innerHTML = `
<div class="agent-section">
<h3>战斗员管理器</h3>
<div id="agent-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="agent-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.loadAgentList();
});
// 新建战斗员
document.getElementById('create-new').addEventListener('click', function() {
self.createNewAgent();
});
// 导出所有
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');
},
// 加载战斗员列表
loadAgentList: function() {
var self = this;
var listContainer = document.getElementById('agent-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.agentList = data.query.categorymembers;
self.renderAgentList();
}).fail(function() {
self.showMessage('加载失败,请检查分类是否存在', 'error');
});
},
// 渲染战斗员列表
renderAgentList: function() {
var listContainer = document.getElementById('agent-list');
if (this.agentList.length === 0) {
listContainer.innerHTML = '<div class="agent-message info">暂无战斗员,点击"新建战斗员"开始创建</div>';
return;
}
var html = '<div class="agent-grid">';
this.agentList.forEach(function(agent) {
html += '<div class="agent-list-item" data-title="' + mw.html.escape(agent.title) + '">' +
mw.html.escape(agent.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.loadAgent(title);
});
});
},
// 加载战斗员数据
loadAgent: 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.currentAgent = {
title: title,
content: content
};
console.log('加载的页面内容:', content);
self.switchTab('edit');
self.renderEditor();
self.showMessage('已加载: ' + title, 'success');
}).fail(function(error) {
console.error('加载失败:', error);
self.showMessage('加载失败', 'error');
});
},
// 创建新战斗员
createNewAgent: function() {
this.currentAgent = {
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.currentAgent.content);
console.log('解析的数据:', data);
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.currentAgent.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>';
html += '<div class="agent-field-row">';
this.templateFields.stats.forEach(function(field) {
html += self.renderField(field, data[field.name] || '');
});
html += '</div>';
// 伤害数值
html += '<h4>伤害数值</h4>';
html += '<div class="agent-field-row">';
this.templateFields.damage.forEach(function(field) {
html += self.renderField(field, data[field.name] || '');
});
html += '</div>';
// 技能信息
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.cards.forEach(function(field) {
html += self.renderField(field, data[field.name] || '');
});
html += '</div>';
// 自我意识
html += '<h4>展现自我意识</h4>';
html += '<div class="agent-field-row">';
this.templateFields.ego.forEach(function(field) {
html += self.renderField(field, data[field.name] || '');
});
html += '</div>';
// 潜力
html += '<h4>潜力</h4>';
html += '<div class="agent-field-row">';
this.templateFields.potential.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-agent">保存战斗员</div>';
html += '<div class="agent-button secondary" id="preview-agent">预览</div>';
html += '<div class="agent-button secondary" id="view-source">查看源码</div>';
if (this.currentAgent.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-agent').addEventListener('click', function() {
self.saveAgent();
});
// 绑定预览事件
document.getElementById('preview-agent').addEventListener('click', function() {
self.previewAgent();
});
// 绑定查看源码事件
document.getElementById('view-source').addEventListener('click', function() {
self.viewSource();
});
// 绑定查看页面事件
if (this.currentAgent.title) {
document.getElementById('view-page').addEventListener('click', function() {
window.open(mw.util.getUrl(self.currentAgent.title), '_blank');
});
}
},
// 渲染表单字段
renderField: function(field, value) {
var escapedValue = mw.html.escape(value);
var html = '<div class="agent-form-group">';
html += '<label>' + mw.html.escape(field.label) + '</label>';
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 templateMatch = content.match(/\{\{战斗员\s*([\s\S]*?)\}\}/);
if (!templateMatch) {
console.log('未找到战斗员模板');
return data;
}
var templateContent = templateMatch[1];
console.log('模板内容:', templateContent);
// 使用更宽泛的正则表达式来匹配字段,支持中文和特殊字符
// 匹配 |字段名=值 的模式
var lines = templateContent.split('\n');
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
// 跳过空行
if (!line || line === '|') {
continue;
}
// 检查是否以 | 开头
if (line.indexOf('|') === 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;
console.log('解析字段:', key, '=', value);
}
}
}
return data;
},
// 生成模板
generateTemplate: function(data) {
var template = '{{面包屑|战斗员图鉴}}\n{{战斗员\n';
// 按照固定顺序添加字段
var fieldGroups = [
this.templateFields.basic,
this.templateFields.image,
this.templateFields.voice,
this.templateFields.profile,
this.templateFields.stats,
this.templateFields.damage,
this.templateFields.skills,
this.templateFields.cards,
this.templateFields.ego,
this.templateFields.potential
];
fieldGroups.forEach(function(group) {
group.forEach(function(field) {
var value = data[field.name] || '';
template += '|' + field.name + '=' + value + '\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;
},
// 保存战斗员
saveAgent: 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.currentAgent.title = title;
self.currentAgent.content = content;
self.loadAgentList();
}).fail(function(code, error) {
console.error('保存失败:', code, error);
self.showMessage('保存失败: ' + (error.error ? error.error.info : '未知错误'), 'error');
});
},
// 预览
previewAgent: 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.agentList.forEach(function(agent) {
var promise = self.api.get({
action: 'query',
titles: agent.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: agent.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.agentList.forEach(function(agent) {
var promise = self.api.get({
action: 'query',
titles: agent.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 allFields = [].concat(
self.templateFields.basic,
self.templateFields.voice,
self.templateFields.profile
);
allFields.forEach(function(field) {
if (!parsedData[field.name] || parsedData[field.name].trim() === '') {
missingFields.push(field.label);
}
});
if (missingFields.length > 0) {
issues.push({
title: agent.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('agent-message');
container.innerHTML = '<div class="agent-message ' + type + '">' + mw.html.escape(message) + '</div>';
setTimeout(function() {
container.innerHTML = '';
}, 5000);
}
};
// 页面加载完成后初始化
$(function() {
AgentManager.init();
});
})();