Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e92349e111 | |||
| 0912d658b8 | |||
| 8e63db4424 |
@@ -1085,6 +1085,41 @@ INDEX_TEMPLATE = '''
|
||||
color: #fff;
|
||||
}
|
||||
.folder-list a i { margin-right: 5px; }
|
||||
.folder-list .folder-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
position: relative;
|
||||
}
|
||||
.folder-list .folder-item a {
|
||||
padding: 6px 10px;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.folder-list .folder-actions {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
display: none;
|
||||
gap: 4px;
|
||||
background: #343a40;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.folder-list .folder-item:hover .folder-actions {
|
||||
display: flex;
|
||||
}
|
||||
.folder-list .folder-actions .btn {
|
||||
padding: 2px 6px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
}
|
||||
.folder-list .folder-item:hover {
|
||||
background: #495057;
|
||||
}
|
||||
.folder-list .folder-item:hover a {
|
||||
color: #fff;
|
||||
}
|
||||
.folder-action {
|
||||
font-size: 12px;
|
||||
color: #6c757d;
|
||||
@@ -1867,29 +1902,30 @@ INDEX_TEMPLATE = '''
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 新建文件夹模态框 -->
|
||||
<!-- 新建/编辑文件夹模态框 -->
|
||||
<div class="modal fade" id="newFolderModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="bi bi-folder-plus"></i> 新建文件夹</h5>
|
||||
<h5 class="modal-title" id="folderModalTitle"><i class="bi bi-folder-plus"></i> 新建文件夹</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="newFolderType">
|
||||
<input type="hidden" id="editFolderId">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">文件夹名称</label>
|
||||
<input type="text" id="newFolderName" class="form-control" placeholder="输入文件夹名称">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="mb-3" id="folderTypeRow">
|
||||
<label class="form-label">所属类别</label>
|
||||
<input type="text" id="newFolderTypeName" class="form-control" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" onclick="createFolder()">
|
||||
<i class="bi bi-check"></i> 创建
|
||||
<button type="button" class="btn btn-primary" onclick="saveFolder()">
|
||||
<i class="bi bi-check"></i> <span id="folderSaveBtnText">创建</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2648,6 +2684,9 @@ function showAddModal(type) {
|
||||
// 设置类型
|
||||
document.getElementById('addType').value = type;
|
||||
|
||||
// 重置文件夹ID(从顶部按钮添加时不指定文件夹)
|
||||
currentAddFolderId = null;
|
||||
|
||||
// 只有不是编辑草稿时才重置
|
||||
// currentDraftId 在 editDraft 中已设置,不要覆盖
|
||||
|
||||
@@ -2704,7 +2743,8 @@ async function addItem() {
|
||||
due_date: type === 'todo' ? document.getElementById('addDueDate').value : null,
|
||||
note: document.getElementById('addNote').value,
|
||||
tags: document.getElementById('addTags').value.split(',').map(t => t.trim()).filter(t => t),
|
||||
is_starred: document.getElementById('addStarred').checked
|
||||
is_starred: document.getElementById('addStarred').checked,
|
||||
folder_id: currentAddFolderId // 如果从文件夹添加,带上文件夹ID
|
||||
};
|
||||
|
||||
const res = await fetch(`${API_BASE}/items`, {
|
||||
@@ -2725,6 +2765,7 @@ async function addItem() {
|
||||
|
||||
stopAutoSave();
|
||||
hideDraftIndicator();
|
||||
currentAddFolderId = null; // 重置文件夹ID
|
||||
refreshData();
|
||||
}
|
||||
}
|
||||
@@ -2846,11 +2887,19 @@ async function deleteItem(id) {
|
||||
let currentDetailId = null;
|
||||
|
||||
// 显示详情
|
||||
async function showDetail(id, todoPage = 1) {
|
||||
async function showDetail(id, todoPage = 1, todoFilter = 'all') {
|
||||
currentDetailId = id;
|
||||
currentTodoPage = todoPage;
|
||||
currentTodoFilter = todoFilter;
|
||||
|
||||
// 增加阅读数
|
||||
await fetch(`${API_BASE}/items/${id}/view`, { method: 'POST' });
|
||||
// 记录当前弹窗滚动位置
|
||||
const detailContent = document.getElementById('detailContent');
|
||||
const scrollTop = detailContent.scrollTop;
|
||||
|
||||
// 增加阅读数(首次加载时才增加)
|
||||
if (todoPage === 1 && todoFilter === 'all') {
|
||||
await fetch(`${API_BASE}/items/${id}/view`, { method: 'POST' });
|
||||
}
|
||||
|
||||
const res = await fetch(`${API_BASE}/items/${id}`);
|
||||
const data = await res.json();
|
||||
@@ -2915,21 +2964,46 @@ async function showDetail(id, todoPage = 1) {
|
||||
// 文本类型显示待办事务
|
||||
if (item.type === 'text') {
|
||||
const todoOffset = (todoPage - 1) * 10;
|
||||
const todoRes = await fetch(`${API_BASE}/items/${id}/todo-events?limit=10&offset=${todoOffset}`);
|
||||
const todoData = await todoRes.json();
|
||||
|
||||
// 根据过滤状态获取数据
|
||||
let todoRes = await fetch(`${API_BASE}/items/${id}/todo-events?limit=10&offset=${todoOffset}`);
|
||||
let todoData = await todoRes.json();
|
||||
|
||||
// 客户端过滤(因为API返回全部数据)
|
||||
let filteredEvents = todoData.data;
|
||||
let totalTodo = todoData.total;
|
||||
|
||||
if (todoFilter === 'completed') {
|
||||
filteredEvents = filteredEvents.filter(e => e.is_completed);
|
||||
// 需要重新计算总数
|
||||
const allRes = await fetch(`${API_BASE}/items/${id}/todo-events?limit=1000&offset=0`);
|
||||
const allData = await allRes.json();
|
||||
totalTodo = allData.data.filter(e => e.is_completed).length;
|
||||
} else if (todoFilter === 'pending') {
|
||||
filteredEvents = filteredEvents.filter(e => !e.is_completed);
|
||||
const allRes = await fetch(`${API_BASE}/items/${id}/todo-events?limit=1000&offset=0`);
|
||||
const allData = await allRes.json();
|
||||
totalTodo = allData.data.filter(e => !e.is_completed).length;
|
||||
}
|
||||
|
||||
html += `<hr><div class="mb-3">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<strong><i class="bi bi-list-check"></i> 待办事务</strong>
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="showAddTodoEventModal(${item.id})">
|
||||
<i class="bi bi-plus"></i> 添加事务
|
||||
</button>
|
||||
</div>
|
||||
<!-- 过滤按钮 -->
|
||||
<div class="btn-group btn-group-sm mb-2" role="group">
|
||||
<button class="btn ${todoFilter === 'all' ? 'btn-primary' : 'btn-outline-secondary'}" onclick="showDetail(${id}, 1, 'all')">全部</button>
|
||||
<button class="btn ${todoFilter === 'pending' ? 'btn-warning' : 'btn-outline-warning'}" onclick="showDetail(${id}, 1, 'pending')">未完成</button>
|
||||
<button class="btn ${todoFilter === 'completed' ? 'btn-success' : 'btn-outline-success'}" onclick="showDetail(${id}, 1, 'completed')">已完成</button>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
if (todoData.success && todoData.data.length > 0) {
|
||||
if (filteredEvents.length > 0) {
|
||||
html += `<div class="border rounded p-2 bg-light" id="todoEventsList">`;
|
||||
todoData.data.forEach(event => {
|
||||
filteredEvents.forEach(event => {
|
||||
const completedClass = event.is_completed ? 'text-muted' : '';
|
||||
const checkIcon = event.is_completed ? '✅' : '⏳';
|
||||
const remainingText = event.remaining_days > 0 ? `${event.remaining_days}天` : '已过期';
|
||||
@@ -2938,7 +3012,7 @@ async function showDetail(id, todoPage = 1) {
|
||||
html += `<div class="d-flex justify-content-between align-items-start py-2 border-bottom todo-event-item ${completedClass}">
|
||||
<div class="flex-grow-1">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span onclick="toggleTodoEventComplete(${event.id}, ${item.id})" style="cursor:pointer;" title="点击切换完成状态">${checkIcon}</span>
|
||||
<span onclick="toggleTodoEventComplete(${event.id}, ${item.id}, ${event.is_completed})" style="cursor:pointer;" title="点击切换完成状态">${checkIcon}</span>
|
||||
<span class="${event.is_completed ? 'text-decoration-line-through' : ''}">${escapeHtml(event.content)}</span>
|
||||
<small class="${remainingClass}">(${remainingText})</small>
|
||||
</div>
|
||||
@@ -2959,26 +3033,25 @@ async function showDetail(id, todoPage = 1) {
|
||||
html += `</div>`;
|
||||
|
||||
// 分页
|
||||
const totalTodo = todoData.total;
|
||||
const totalPagesTodo = Math.ceil(totalTodo / 10);
|
||||
if (totalPagesTodo > 1) {
|
||||
html += `<div class="d-flex justify-content-center mt-2">
|
||||
<nav><ul class="pagination pagination-sm">`;
|
||||
for (let p = 1; p <= Math.min(totalPagesTodo, 5); p++) {
|
||||
html += `<li class="page-item ${p === todoPage ? 'active' : ''}">
|
||||
<a class="page-link" href="#" onclick="showDetail(${id}, ${p}); return false;">${p}</a>
|
||||
<a class="page-link" href="#" onclick="showDetail(${id}, ${p}, '${todoFilter}'); return false;">${p}</a>
|
||||
</li>`;
|
||||
}
|
||||
if (totalPagesTodo > 5) {
|
||||
html += `<li class="page-item disabled"><span class="page-link">...</span></li>`;
|
||||
html += `<li class="page-item"><a class="page-link" href="#" onclick="showDetail(${id}, ${totalPagesTodo}); return false;">${totalPagesTodo}</a></li>`;
|
||||
html += `<li class="page-item"><a class="page-link" href="#" onclick="showDetail(${id}, ${totalPagesTodo}, '${todoFilter}'); return false;">${totalPagesTodo}</a></li>`;
|
||||
}
|
||||
html += `</ul></nav>
|
||||
<small class="text-muted ms-2">共 ${totalTodo} 条事务</small>
|
||||
</div>`;
|
||||
}
|
||||
} else {
|
||||
html += `<div class="text-center text-muted py-3">暂无待办事务</div>`;
|
||||
html += `<div class="text-center text-muted py-3">${todoFilter === 'all' ? '暂无待办事务' : (todoFilter === 'completed' ? '暂无已完成事务' : '暂无未完成事务')}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3020,7 +3093,17 @@ async function showDetail(id, todoPage = 1) {
|
||||
|
||||
document.getElementById('detailContent').innerHTML = html;
|
||||
|
||||
new bootstrap.Modal(document.getElementById('detailModal')).show();
|
||||
// 如果弹窗已经打开,保持滚动位置
|
||||
const modal = bootstrap.Modal.getInstance(document.getElementById('detailModal'));
|
||||
if (modal && modal._isShown) {
|
||||
// 弹窗已打开,恢复滚动位置
|
||||
setTimeout(() => {
|
||||
document.getElementById('detailContent').scrollTop = scrollTop;
|
||||
}, 10);
|
||||
} else {
|
||||
// 弹窗未打开,打开弹窗
|
||||
new bootstrap.Modal(document.getElementById('detailModal')).show();
|
||||
}
|
||||
}
|
||||
|
||||
// ============ 待办事务功能 ============
|
||||
@@ -3085,7 +3168,7 @@ async function saveTodoEvent() {
|
||||
|
||||
if (data.success) {
|
||||
bootstrap.Modal.getInstance(document.getElementById('todoEventModal')).hide();
|
||||
showDetail(itemId, 1); // 刷新详情,回到第一页
|
||||
showDetail(itemId, currentTodoPage, currentTodoFilter); // 刷新详情,保持页面和过滤状态
|
||||
} else {
|
||||
alert('更新失败: ' + data.error);
|
||||
}
|
||||
@@ -3100,30 +3183,40 @@ async function saveTodoEvent() {
|
||||
|
||||
if (data.success) {
|
||||
bootstrap.Modal.getInstance(document.getElementById('todoEventModal')).hide();
|
||||
showDetail(itemId, 1); // 刷新详情,回到第一页
|
||||
showDetail(itemId, 1, currentTodoFilter); // 创建新事务后回到第一页
|
||||
} else {
|
||||
alert('创建失败: ' + data.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 切换待办事务完成状态
|
||||
async function toggleTodoEventComplete(eventId, itemId) {
|
||||
// 切换待办事务完成状态(可切换为完成或未完成)
|
||||
async function toggleTodoEventComplete(eventId, itemId, currentCompleted) {
|
||||
// 离线检查
|
||||
if (!checkOnlineBeforeAction('切换完成状态')) return;
|
||||
|
||||
const res = await fetch(`${API_BASE}/todo-events/${eventId}/complete`, {
|
||||
method: 'POST'
|
||||
// 切换状态:已完成->未完成,未完成->已完成
|
||||
const newCompleted = !currentCompleted;
|
||||
|
||||
const res = await fetch(`${API_BASE}/todo-events/${eventId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ is_completed: newCompleted })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
showDetail(itemId, 1); // 刷新详情
|
||||
// 保持当前页面和过滤状态
|
||||
showDetail(itemId, currentTodoPage, currentTodoFilter);
|
||||
} else {
|
||||
alert('操作失败: ' + data.error);
|
||||
}
|
||||
}
|
||||
|
||||
// 当前待办事务的页面和过滤状态
|
||||
let currentTodoPage = 1;
|
||||
let currentTodoFilter = 'all'; // all, completed, pending
|
||||
|
||||
// 删除待办事务
|
||||
async function deleteTodoEvent(eventId, itemId) {
|
||||
// 离线检查
|
||||
@@ -3137,7 +3230,7 @@ async function deleteTodoEvent(eventId, itemId) {
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
showDetail(itemId, 1); // 刷新详情
|
||||
showDetail(itemId, currentTodoPage, currentTodoFilter); // 刷新详情,保持页面和过滤状态
|
||||
} else {
|
||||
alert('删除失败: ' + data.error);
|
||||
}
|
||||
@@ -4121,9 +4214,22 @@ function renderFolderList(type) {
|
||||
// if (section) section.classList.add('expanded'); // 已移除
|
||||
|
||||
container.innerHTML = folders.map(f => `
|
||||
<a href="#" data-folder="${f.id}" onclick="filterByFolder('${type}', ${f.id}); return false;">
|
||||
<i class="bi bi-folder"></i> ${f.name} <small class="text-muted">(${f.item_count || 0})</small>
|
||||
</a>
|
||||
<div class="d-flex justify-content-between align-items-center folder-item">
|
||||
<a href="#" data-folder="${f.id}" onclick="filterByFolder('${type}', ${f.id}); return false;" class="flex-grow-1">
|
||||
<i class="bi bi-folder"></i> ${f.name} <small class="text-muted">(${f.item_count || 0})</small>
|
||||
</a>
|
||||
<div class="folder-actions">
|
||||
<button class="btn btn-outline-success" onclick="event.stopPropagation(); showAddToFolderModal('${type}', ${f.id}); return false;" title="新增数据到此文件夹">
|
||||
<i class="bi bi-plus"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" onclick="event.stopPropagation(); showEditFolderModal(${f.id}, '${f.name}'); return false;" title="重命名">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-danger" onclick="event.stopPropagation(); deleteFolderConfirm(${f.id}, '${f.name}'); return false;" title="删除">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
@@ -4150,16 +4256,35 @@ async function showNewFolderModal(type) {
|
||||
if (!checkOnlineBeforeAction('新建文件夹')) return;
|
||||
|
||||
document.getElementById('newFolderType').value = type;
|
||||
document.getElementById('editFolderId').value = '';
|
||||
document.getElementById('newFolderName').value = '';
|
||||
|
||||
const typeLabels = { text: '📝 文本', link: '🔗 链接', column: '📰 专栏', todo: '✅ 待办' };
|
||||
document.getElementById('newFolderTypeName').value = typeLabels[type] || type;
|
||||
|
||||
document.getElementById('folderModalTitle').innerHTML = '<i class="bi bi-folder-plus"></i> 新建文件夹';
|
||||
document.getElementById('folderSaveBtnText').textContent = '创建';
|
||||
document.getElementById('folderTypeRow').style.display = 'block';
|
||||
|
||||
new bootstrap.Modal(document.getElementById('newFolderModal')).show();
|
||||
}
|
||||
|
||||
async function createFolder() {
|
||||
const type = document.getElementById('newFolderType').value;
|
||||
// 显示编辑文件夹模态框
|
||||
function showEditFolderModal(folderId, folderName) {
|
||||
document.getElementById('editFolderId').value = folderId;
|
||||
document.getElementById('newFolderName').value = folderName;
|
||||
document.getElementById('newFolderType').value = '';
|
||||
|
||||
document.getElementById('folderModalTitle').innerHTML = '<i class="bi bi-pencil"></i> 重命名文件夹';
|
||||
document.getElementById('folderSaveBtnText').textContent = '保存';
|
||||
document.getElementById('folderTypeRow').style.display = 'none';
|
||||
|
||||
new bootstrap.Modal(document.getElementById('newFolderModal')).show();
|
||||
}
|
||||
|
||||
// 保存文件夹(创建或编辑)
|
||||
async function saveFolder() {
|
||||
const editId = document.getElementById('editFolderId').value;
|
||||
const name = document.getElementById('newFolderName').value.trim();
|
||||
|
||||
if (!name) {
|
||||
@@ -4167,23 +4292,118 @@ async function createFolder() {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await fetch(`${API_BASE}/folders`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, type })
|
||||
});
|
||||
// 离线检查
|
||||
if (!checkOnlineBeforeAction(editId ? '重命名文件夹' : '新建文件夹')) return;
|
||||
|
||||
if (editId) {
|
||||
// 编辑
|
||||
const res = await fetch(`${API_BASE}/folders/${editId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
bootstrap.Modal.getInstance(document.getElementById('newFolderModal')).hide();
|
||||
loadFolders();
|
||||
} else {
|
||||
alert('重命名失败: ' + data.error);
|
||||
}
|
||||
} else {
|
||||
// 创建
|
||||
const type = document.getElementById('newFolderType').value;
|
||||
const res = await fetch(`${API_BASE}/folders`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, type })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
bootstrap.Modal.getInstance(document.getElementById('newFolderModal')).hide();
|
||||
loadFolders();
|
||||
loadStats();
|
||||
} else {
|
||||
alert('创建失败: ' + data.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除文件夹确认
|
||||
async function deleteFolderConfirm(folderId, folderName) {
|
||||
// 离线检查
|
||||
if (!checkOnlineBeforeAction('删除文件夹')) return;
|
||||
|
||||
if (!confirm(`确认删除文件夹"${folderName}"?\n文件夹内的数据将移到未分类。`)) return;
|
||||
|
||||
const res = await fetch(`${API_BASE}/folders/${folderId}?move_to_root=1`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (data.success) {
|
||||
bootstrap.Modal.getInstance(document.getElementById('newFolderModal')).hide();
|
||||
loadFolders();
|
||||
loadStats();
|
||||
// 如果当前正在过滤该文件夹,返回首页
|
||||
if (currentFilter.folder_id === folderId) {
|
||||
currentFilter.folder_id = null;
|
||||
loadItems(1);
|
||||
}
|
||||
} else {
|
||||
alert('创建失败: ' + data.error);
|
||||
alert('删除失败: ' + data.error);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示新增数据到文件夹的模态框
|
||||
function showAddToFolderModal(type, folderId) {
|
||||
// 离线检查
|
||||
if (!checkOnlineBeforeAction('添加数据')) return;
|
||||
|
||||
// 设置类型
|
||||
document.getElementById('addType').value = type;
|
||||
document.getElementById('editFolderId').value = ''; // 重置编辑ID
|
||||
|
||||
// 设置弹窗标题和图标
|
||||
const typeInfo = {
|
||||
text: { icon: '📝', title: '添加文本' },
|
||||
link: { icon: '🔗', title: '添加链接' },
|
||||
column: { icon: '📰', title: '添加专栏' },
|
||||
todo: { icon: '✅', title: '添加待办' }
|
||||
};
|
||||
|
||||
document.getElementById('addModalIcon').textContent = typeInfo[type].icon;
|
||||
document.getElementById('addModalTitle').textContent = typeInfo[type].title;
|
||||
|
||||
// 显示/隐藏对应字段
|
||||
document.getElementById('contentGroup').style.display = type === 'text' ? 'block' : 'none';
|
||||
document.getElementById('urlGroup').style.display = ['link', 'column'].includes(type) ? 'block' : 'none';
|
||||
document.getElementById('sourceGroup').style.display = type === 'column' ? 'block' : 'none';
|
||||
document.getElementById('todoFields').style.display = type === 'todo' ? 'block' : 'none';
|
||||
|
||||
// 清空表单
|
||||
document.getElementById('addForm').reset();
|
||||
hideDraftIndicator();
|
||||
|
||||
// 设置默认文件夹(隐藏字段,需要在提交时带上)
|
||||
currentAddFolderId = folderId;
|
||||
|
||||
// 打开弹窗
|
||||
new bootstrap.Modal(document.getElementById('addModal')).show();
|
||||
|
||||
// 启动自动保存
|
||||
startAutoSave();
|
||||
|
||||
// 弹框关闭时停止自动保存并重置文件夹ID
|
||||
document.getElementById('addModal').addEventListener('hidden.bs.modal', () => {
|
||||
stopAutoSave();
|
||||
currentAddFolderId = null;
|
||||
}, { once: true });
|
||||
}
|
||||
|
||||
// 当前新增时的文件夹ID
|
||||
let currentAddFolderId = null;
|
||||
|
||||
function filterByFolder(type, folderId) {
|
||||
// 更新侧边栏选中状态
|
||||
document.querySelectorAll('.sidebar a').forEach(a => a.classList.remove('active'));
|
||||
|
||||
Reference in New Issue
Block a user