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流水线
109 lines
5.0 KiB
JavaScript
109 lines
5.0 KiB
JavaScript
(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();
|
||
})();
|
||
})();
|