170 lines
6.5 KiB
JavaScript
170 lines
6.5 KiB
JavaScript
/* =====================================================
|
||
MetaLab 管理面板 - 站点设置
|
||
单一职责:加载/保存站点设置,开关即时生效,文本输入手动保存
|
||
===================================================== */
|
||
|
||
(function() {
|
||
'use strict';
|
||
|
||
const TOGGLE_KEYS = [
|
||
{ id: 'maintenance-enabled', key: 'maintenance.enabled' },
|
||
{ id: 'registration-enabled', key: 'registration.enabled' },
|
||
{ id: 'registration-show-guidelines', key: 'registration.show_guidelines' },
|
||
{ id: 'registration-force-guidelines', key: 'registration.force_guidelines' },
|
||
{ id: 'audit-enabled', key: 'audit.enabled' },
|
||
{ id: 'audit-username', key: 'audit.username_audit' },
|
||
{ id: 'audit-avatar', key: 'audit.avatar_audit' },
|
||
{ id: 'audit-bio', key: 'audit.bio_audit' }
|
||
];
|
||
|
||
// 已有专属 UI 的设置 key,不在"其他设置"中重复显示
|
||
var DEDICATED_KEYS = {
|
||
'site.framework': true, 'site.copyright_start': true,
|
||
'site.name': true, 'site.tagline': true, 'site.contact_email': true,
|
||
'site.operator_name': true, 'site.icp_number': true, 'site.icp_license': true,
|
||
'site.police_number': true, 'site.wenwangwen': true, 'site.algorithm_filing': true,
|
||
'site.privacy_url': true, 'site.terms_url': true,
|
||
'site.guidelines': true,
|
||
'maintenance.enabled': true,
|
||
'registration.enabled': true, 'registration.show_guidelines': true,
|
||
'registration.force_guidelines': true, 'registration.guidelines_timer': true,
|
||
'password.strength': true,
|
||
'audit.enabled': true, 'audit.username_audit': true, 'audit.avatar_audit': true, 'audit.bio_audit': true
|
||
};
|
||
|
||
// --- 初始加载 ---
|
||
async function loadSettings() {
|
||
try {
|
||
var res = await api.get('/api/admin/site-settings');
|
||
if (!res.success) {
|
||
showToast(res.message || '加载设置失败', 'error');
|
||
return;
|
||
}
|
||
|
||
// 所有开关
|
||
var audit = res.data.audit || {};
|
||
var allSettings = res.data.all || {};
|
||
TOGGLE_KEYS.forEach(function(t) {
|
||
var el = document.getElementById(t.id);
|
||
if (!el) return;
|
||
|
||
if (t.id === 'maintenance-enabled') {
|
||
el.checked = allSettings[t.key] === 'true';
|
||
} else if (t.key.indexOf('registration.') === 0) {
|
||
el.checked = allSettings[t.key] !== 'false';
|
||
} else {
|
||
el.checked = audit[t.key.split('.')[1]] === true;
|
||
}
|
||
el.addEventListener('change', function() {
|
||
updateBoolSetting(t.key, el.checked, el);
|
||
});
|
||
});
|
||
|
||
// 文本输入保存按钮
|
||
bindSaveButtons();
|
||
|
||
// 社区准则文本域
|
||
var guidelinesEl = document.getElementById('setting-site-guidelines');
|
||
if (guidelinesEl) {
|
||
guidelinesEl.value = allSettings['site.guidelines'] || '';
|
||
var guidelinesBtn = document.querySelector('[data-key="site.guidelines"]');
|
||
if (guidelinesBtn) {
|
||
guidelinesBtn.addEventListener('click', function() {
|
||
updateTextSetting('site.guidelines', guidelinesEl.value, guidelinesBtn);
|
||
});
|
||
}
|
||
}
|
||
|
||
// 其他设置(过滤已有专属UI的key)
|
||
renderOtherSettings(allSettings);
|
||
} catch (e) {
|
||
showToast('加载设置失败', 'error');
|
||
}
|
||
}
|
||
|
||
// --- 文本输入保存 ---
|
||
function bindSaveButtons() {
|
||
document.querySelectorAll('.btn-save, .btn-save-select').forEach(function(btn) {
|
||
btn.addEventListener('click', function() {
|
||
var key = btn.getAttribute('data-key');
|
||
var inputId = btn.getAttribute('data-input');
|
||
var input = document.getElementById(inputId);
|
||
if (!key || !input) return;
|
||
updateTextSetting(key, input.value, btn);
|
||
});
|
||
});
|
||
}
|
||
|
||
async function updateTextSetting(key, value, btn) {
|
||
btn.disabled = true;
|
||
btn.textContent = '...';
|
||
try {
|
||
var res = await api.put('/api/admin/site-settings', {
|
||
key: key,
|
||
value: value
|
||
});
|
||
if (res.success) {
|
||
showToast('设置已更新', 'success');
|
||
} else {
|
||
showToast(res.message || '保存失败', 'error');
|
||
}
|
||
} catch (e) {
|
||
showToast('保存失败', 'error');
|
||
} finally {
|
||
btn.disabled = false;
|
||
btn.textContent = '保存';
|
||
}
|
||
}
|
||
|
||
// --- 更新布尔设置 ---
|
||
async function updateBoolSetting(key, value, toggle) {
|
||
toggle.disabled = true;
|
||
try {
|
||
var res = await api.put('/api/admin/site-settings/bool', {
|
||
key: key,
|
||
value: String(value)
|
||
});
|
||
if (res.success) {
|
||
showToast('设置已更新', 'success');
|
||
} else {
|
||
showToast(res.message || '保存失败', 'error');
|
||
toggle.checked = !value; // 回滚
|
||
}
|
||
} catch (e) {
|
||
showToast('保存失败', 'error');
|
||
toggle.checked = !value; // 回滚
|
||
} finally {
|
||
toggle.disabled = false;
|
||
}
|
||
}
|
||
|
||
// --- 渲染其他设置(过滤已有专属UI的key) ---
|
||
function renderOtherSettings(all) {
|
||
var container = document.getElementById('general-settings');
|
||
if (!container) return; // 部分页面无此容器
|
||
var filtered = [];
|
||
Object.keys(all).forEach(function(k) {
|
||
if (!DEDICATED_KEYS[k]) filtered.push(k);
|
||
});
|
||
if (filtered.length === 0) {
|
||
container.innerHTML = '<div class="settings-empty">暂无其他设置</div>';
|
||
return;
|
||
}
|
||
container.innerHTML = '';
|
||
filtered.forEach(function(key) {
|
||
var val = all[key] || '';
|
||
var item = document.createElement('div');
|
||
item.className = 'setting-item';
|
||
item.innerHTML =
|
||
'<div class="setting-info">' +
|
||
'<span class="setting-label">' + escapeHtml(key) + '</span>' +
|
||
'<span class="setting-value">' + escapeHtml(val.length > 80 ? val.slice(0, 80) + '...' : val) + '</span>' +
|
||
'</div>';
|
||
container.appendChild(item);
|
||
});
|
||
}
|
||
|
||
// --- 入口 ---
|
||
loadSettings();
|
||
})();
|