fix: 修复收藏夹列表加载失败 + 收藏按钮改为弹窗选择收藏夹
- settings/favorites 收藏夹列表加载失败:escapeHTML 在 energy Tab 闭包内,收藏夹 Tab 无法访问导致 ReferenceError,修复为本地 esc() 函数 - settings 创建/删除收藏夹请求缺少 CSRF Token(403),统一使用 fetch + X-CSRF-Token 头 - API 错误时显示实际错误信息而非吞掉显示"暂无收藏夹" - 文章详情页收藏按钮:点击弹出选择收藏夹弹窗,列出所有收藏夹,已收藏的文章高亮显示 - 弹窗支持原地新建收藏夹并立即收藏(一键创建+收藏) - 新增收藏夹弹窗 CSS 样式(.fav-overlay/.fav-modal/.fav-folder-option 等)
This commit is contained in:
@ -1032,11 +1032,31 @@
|
||||
var createBtn = document.getElementById('createFolderBtn');
|
||||
if (!listEl) return;
|
||||
|
||||
var csrfMeta = document.querySelector('meta[name="csrf-token"]');
|
||||
var csrfToken = csrfMeta ? csrfMeta.getAttribute('content') : '';
|
||||
|
||||
function esc(s) {
|
||||
var d = document.createElement('div');
|
||||
d.textContent = s || '';
|
||||
return d.innerHTML;
|
||||
}
|
||||
|
||||
function api(method, url, data) {
|
||||
var opts = { method: method, headers: { 'Content-Type': 'application/json' } };
|
||||
if (csrfToken) opts.headers['X-CSRF-Token'] = csrfToken;
|
||||
if (data) opts.body = JSON.stringify(data);
|
||||
return fetch(url, opts).then(function (r) { return r.json(); });
|
||||
}
|
||||
|
||||
function loadFolders() {
|
||||
fetch('/api/folders')
|
||||
.then(function (r) { return r.json(); })
|
||||
listEl.innerHTML = '<div class="energy-log-empty">加载中...</div>';
|
||||
api('GET', '/api/folders')
|
||||
.then(function (d) {
|
||||
if (!d.success || !d.data || !d.data.folders || d.data.folders.length === 0) {
|
||||
if (!d.success) {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">' + esc(d.message || '加载失败') + '</div>';
|
||||
return;
|
||||
}
|
||||
if (!d.data || !d.data.folders || d.data.folders.length === 0) {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">暂无收藏夹</div>';
|
||||
return;
|
||||
}
|
||||
@ -1046,7 +1066,7 @@
|
||||
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-name">' + esc(f.name) + isDefault + '</span>'
|
||||
+ '<span class="fav-folder-meta">' + (f.item_count || 0) + ' 篇文章 · ' + pub + '</span>'
|
||||
+ '</div>'
|
||||
+ '<div class="fav-folder-actions">'
|
||||
@ -1056,33 +1076,27 @@
|
||||
});
|
||||
listEl.innerHTML = html;
|
||||
|
||||
// 绑定删除按钮
|
||||
listEl.querySelectorAll('.fav-folder-del').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var id = btn.getAttribute('data-id');
|
||||
if (!confirm('确定要删除此收藏夹?其中的收藏内容也将被清除。')) return;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('DELETE', '/api/folders/' + id, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState !== 4) return;
|
||||
try {
|
||||
var r = JSON.parse(xhr.responseText);
|
||||
api('DELETE', '/api/folders/' + id)
|
||||
.then(function (r) {
|
||||
if (r.success) {
|
||||
showSettingsToast('收藏夹已删除');
|
||||
loadFolders();
|
||||
} else {
|
||||
showSettingsToast(r.message || '删除失败', true);
|
||||
}
|
||||
} catch (e) {
|
||||
})
|
||||
.catch(function () {
|
||||
showSettingsToast('删除失败', true);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
listEl.innerHTML = '<div class="energy-log-empty">加载失败</div>';
|
||||
listEl.innerHTML = '<div class="energy-log-empty">加载失败,请刷新页面重试</div>';
|
||||
});
|
||||
}
|
||||
|
||||
@ -1094,24 +1108,18 @@
|
||||
showSettingsToast('收藏夹名称不能超过 50 个字符', true);
|
||||
return;
|
||||
}
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/api/folders', true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState !== 4) return;
|
||||
try {
|
||||
var r = JSON.parse(xhr.responseText);
|
||||
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 (e) {
|
||||
})
|
||||
.catch(function () {
|
||||
showSettingsToast('创建失败', true);
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify({ name: name.trim(), description: '', is_public: false }));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user