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