Files
mce/templates/admin/static/js/site-settings.js
Victor_Jay 0b948cf70f feat(admin): 站点信息 + 注册开关可后台设置,模板动态渲染
新增 4 项可配置站点设置(DB持久化+内存缓存,即时生效):
- site.brand          品牌名(页面标题/页脚/管理面板,默认 MetaLab)
- site.framework      框架名(页脚标识,默认 MetaZone)
- site.copyright_start 版权起始年(页脚,默认 2024)
- registration.enabled 注册开关(关闭后禁止新用户注册,默认 true)

实现方式:
- InjectSiteInfo 中间件:全局注入 Brand/Framework/CopyrightStart 到 gin.Context
- BuildPageData 读取 context,所有 SSR 页面自动获取站点信息
- AuthService.Register 最先检查 IsRegistrationEnabled()
- 管理后台新增「基本设置」+「注册设置」区块,文本输入手动保存 + Toggle 即时生效
2026-05-27 15:12:28 +08:00

142 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* =====================================================
MetaLab 管理面板 - 站点设置
单一职责:加载/保存站点设置,开关即时生效,文本输入手动保存
===================================================== */
(function() {
'use strict';
const TOGGLE_KEYS = [
{ id: 'registration-enabled', key: 'registration.enabled' },
{ 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.brand': true, 'site.framework': true, 'site.copyright_start': true,
'registration.enabled': 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) 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 === 'registration-enabled') {
el.checked = allSettings['registration.enabled'] !== 'false';
} else {
el.checked = audit[t.key.split('.')[1]] === true;
}
el.addEventListener('change', function() {
updateBoolSetting(t.key, el.checked, el);
});
});
// 文本输入保存按钮
bindSaveButtons();
// 其他设置过滤已有专属UI的key
renderOtherSettings(allSettings);
} catch (e) {
showToast('加载设置失败', 'error');
}
}
// --- 文本输入保存 ---
function bindSaveButtons() {
var buttons = document.querySelectorAll('.btn-save');
buttons.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');
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();
})();