refactor: CSP nonce替代unsafe-inline, HSTS始终启用, router/api拆分, 管理后台+用户设置页拆分, DB健康降级, 时区配置, UID统一解析, CI接入
Some checks failed
CI / Lint + Build (push) Has been cancelled
Some checks failed
CI / Lint + Build (push) Has been cancelled
审计修复: - CSP: unsafe-inline移除, nonce替代; unsafe-eval保留供Vditor使用 - HSTS: 始终启用(不再依赖release模式) - Controller Exp: common.GetGinExp包装, 不再直接读context - UID解析: common.ParseUIDParam统一, follow/admin controller改用 重构: - router/api.go(198行)拆为7个域文件: auth/settings/posts/comments/reactions/social/studio - 管理后台站点设置: 单页拆为4个子页(brand/security/registration/content)+子菜单 - 前台用户设置页: 1201行拆为6个独立模板+6个独立JS文件 新增: - DB健康检测中间件(middleware/db_health.go): 5s ping+降级页面 - 时区配置: config.yaml server.timezone→time.Local初始化 - .gitea/workflows/ci.yml: strict模式CI流水线
This commit is contained in:
108
templates/MetaLab-2026/static/js/settings-favorites.js
Normal file
108
templates/MetaLab-2026/static/js/settings-favorites.js
Normal file
@ -0,0 +1,108 @@
|
||||
(function(){'use strict';
|
||||
<script nonce="{{.CSPNonce}}">
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var toastEl = document.getElementById('settingsToast');
|
||||
var toastTimer = null;
|
||||
|
||||
function showSettingsToast(msg, isError) {
|
||||
if (!toastEl) return;
|
||||
clearTimeout(toastTimer);
|
||||
toastEl.textContent = msg;
|
||||
toastEl.className = 'settings-toast' + (isError ? ' error' : '');
|
||||
void toastEl.offsetWidth;
|
||||
toastEl.classList.add('show');
|
||||
toastTimer = setTimeout(function () {
|
||||
toastEl.classList.remove('show');
|
||||
}, 5000);
|
||||
}
|
||||
// ===== 收藏夹 Tab =====
|
||||
(function () {
|
||||
var listEl = document.getElementById('favFolderList');
|
||||
var createBtn = document.getElementById('createFolderBtn');
|
||||
if (!listEl) return;
|
||||
|
||||
// escapeHtml / api 由 shared/utils.js 统一提供
|
||||
|
||||
function loadFolders() {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">加载中...</div>';
|
||||
api('GET', '/api/folders')
|
||||
.then(function (d) {
|
||||
if (!d.success) {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">' + escapeHtml(d.message || '加载失败') + '</div>';
|
||||
return;
|
||||
}
|
||||
if (!d.data || !d.data.folders || d.data.folders.length === 0) {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">暂无收藏夹</div>';
|
||||
return;
|
||||
}
|
||||
var html = '';
|
||||
d.data.folders.forEach(function (f) {
|
||||
var isDefault = f.is_default ? ' (默认)' : '';
|
||||
var pub = f.is_public ? '公开' : '私密';
|
||||
html += '<div class="fav-folder-card">'
|
||||
+ '<div class="fav-folder-info">'
|
||||
+ '<span class="fav-folder-name">' + escapeHtml(f.name) + isDefault + '</span>'
|
||||
+ '<span class="fav-folder-meta">' + (f.item_count || 0) + ' 篇文章 · ' + pub + '</span>'
|
||||
+ '</div>'
|
||||
+ '<div class="fav-folder-actions">'
|
||||
+ (f.is_default ? '' : '<button class="fav-folder-del" data-id="' + f.id + '">删除</button>')
|
||||
+ '</div>'
|
||||
+ '</div>';
|
||||
});
|
||||
listEl.innerHTML = html;
|
||||
|
||||
listEl.querySelectorAll('.fav-folder-del').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var id = btn.getAttribute('data-id');
|
||||
showConfirm('确认', '确定要删除此收藏夹?其中的收藏内容也将被清除。').then(function(ok) {
|
||||
if (!ok) return;
|
||||
api('DELETE', '/api/folders/' + id)
|
||||
.then(function (r) {
|
||||
if (r.success) {
|
||||
showSettingsToast('收藏夹已删除');
|
||||
loadFolders();
|
||||
} else {
|
||||
showSettingsToast(r.message || '删除失败', true);
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
showSettingsToast('删除失败', true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">加载失败,请刷新页面重试</div>';
|
||||
});
|
||||
}
|
||||
|
||||
if (createBtn) {
|
||||
createBtn.addEventListener('click', function () {
|
||||
showPrompt('请输入收藏夹名称(最多50个字符):').then(function(name) {
|
||||
if (!name || !name.trim()) return;
|
||||
if (name.trim().length > 50) {
|
||||
showSettingsToast('收藏夹名称不能超过 50 个字符', true);
|
||||
return;
|
||||
}
|
||||
api('POST', '/api/folders', { name: name.trim(), description: '', is_public: false })
|
||||
.then(function (r) {
|
||||
if (r.success) {
|
||||
showSettingsToast('收藏夹已创建');
|
||||
loadFolders();
|
||||
} else {
|
||||
showSettingsToast(r.message || '创建失败', true);
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
showSettingsToast('创建失败', true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadFolders();
|
||||
})();
|
||||
})();
|
||||
Reference in New Issue
Block a user