|
|
|
|
@@ -55,7 +55,8 @@ def list_items():
|
|
|
|
|
status=request.args.get('status'),
|
|
|
|
|
tag=request.args.get('tag'),
|
|
|
|
|
keyword=request.args.get('keyword'),
|
|
|
|
|
starred=starred
|
|
|
|
|
starred=starred,
|
|
|
|
|
folder_id=folder_id
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return jsonify({'success': True, 'data': items, 'total': total})
|
|
|
|
|
@@ -1032,6 +1033,25 @@ INDEX_TEMPLATE = '''
|
|
|
|
|
.item-card h6 { font-size: 14px; margin-bottom: 2px; }
|
|
|
|
|
.item-card p { margin-bottom: 2px; }
|
|
|
|
|
.item-card .text-muted.small { font-size: 12px; }
|
|
|
|
|
/* 卡片内容自适应布局 */
|
|
|
|
|
.item-card .card-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
.item-card .card-main {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-width: 150px;
|
|
|
|
|
}
|
|
|
|
|
.item-card .card-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 2px;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
.item-card .card-actions .btn {
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
.type-text { border-left: 4px solid #17a2b8; }
|
|
|
|
|
.type-link { border-left: 4px solid #28a745; }
|
|
|
|
|
.type-column { border-left: 4px solid #6f42c1; }
|
|
|
|
|
@@ -2006,8 +2026,8 @@ function renderItems(items) {
|
|
|
|
|
container.innerHTML = items.map(item => `
|
|
|
|
|
<div class="card type-${item.type} item-card ${item.is_starred ? 'is-starred' : ''}" style="cursor: pointer;" onclick="showDetail(${item.id})">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
|
|
|
<div style="flex: 1; min-width: 0;">
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<div class="card-main">
|
|
|
|
|
<h6 class="card-title text-truncate mb-1 ${item.type === 'todo' && item.status === 'completed' ? 'text-muted' : ''}">
|
|
|
|
|
${item.is_starred ? '<i class="bi bi-star-fill" style="color:#ffc107;"></i>' : ''} ${getTypeIcon(item.type)} ${item.title || truncate(item.content || item.url, 30)}
|
|
|
|
|
${item.type === 'todo' && item.status === 'completed' ? ' ✓' : ''}
|
|
|
|
|
@@ -2023,7 +2043,7 @@ function renderItems(items) {
|
|
|
|
|
${item.type === 'todo' ? `${getStatusLabelShort(item.status)} ${getPriorityLabelShort(item.priority)} ${item.due_date ? '📅' + formatDueDate(item.due_date) : ''}` : ''}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="d-flex align-items-center gap-1 flex-wrap ms-2" onclick="event.stopPropagation();">
|
|
|
|
|
<div class="card-actions" onclick="event.stopPropagation();">
|
|
|
|
|
${item.tags.slice(0, 2).map(t => `<span class="badge bg-secondary" style="font-size:10px;">${t}</span>`).join('')}
|
|
|
|
|
<button class="btn btn-sm btn-outline-warning py-0 px-1 star-btn" onclick="toggleStar(${item.id})" title="${item.is_starred ? '取消重点关注' : '设为重点关注'}">
|
|
|
|
|
<i class="bi bi-star${item.is_starred ? '-fill' : ''}" style="font-size:11px; ${item.is_starred ? 'color:#ffc107;' : ''}"></i>
|
|
|
|
|
@@ -2175,8 +2195,8 @@ function renderDrafts(drafts, total) {
|
|
|
|
|
container.innerHTML = header + drafts.map(draft => `
|
|
|
|
|
<div class="card type-${draft.type} item-card" style="opacity: 0.85;">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
|
|
|
<div style="flex: 1; min-width: 0;">
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<div class="card-main">
|
|
|
|
|
<h6 class="card-title text-truncate mb-1">
|
|
|
|
|
${getTypeIcon(draft.type)} ${draft.title || '(无标题)'}
|
|
|
|
|
</h6>
|
|
|
|
|
@@ -2185,14 +2205,14 @@ function renderDrafts(drafts, total) {
|
|
|
|
|
</p>
|
|
|
|
|
<small class="text-muted">保存于: ${formatShortDate(draft.updated_at)}</small>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="d-flex gap-1">
|
|
|
|
|
<button class="btn btn-sm btn-outline-primary" onclick="editDraft(${draft.id})" title="编辑">
|
|
|
|
|
<div class="card-actions">
|
|
|
|
|
<button class="btn btn-sm btn-outline-primary py-0 px-1" onclick="editDraft(${draft.id})" title="编辑">
|
|
|
|
|
<i class="bi bi-pencil"></i>
|
|
|
|
|
</button>
|
|
|
|
|
<button class="btn btn-sm btn-outline-success" onclick="publishDraft(${draft.id})" title="发布">
|
|
|
|
|
<button class="btn btn-sm btn-outline-success py-0 px-1" onclick="publishDraft(${draft.id})" title="发布">
|
|
|
|
|
<i class="bi bi-send"></i>
|
|
|
|
|
</button>
|
|
|
|
|
<button class="btn btn-sm btn-outline-danger" onclick="deleteDraft(${draft.id})" title="删除">
|
|
|
|
|
<button class="btn btn-sm btn-outline-danger py-0 px-1" onclick="deleteDraft(${draft.id})" title="删除">
|
|
|
|
|
<i class="bi bi-trash"></i>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
@@ -3334,8 +3354,8 @@ function renderTrash(items, total) {
|
|
|
|
|
container.innerHTML = header + items.map(item => `
|
|
|
|
|
<div class="card type-${item.type} item-card" style="opacity: 0.7;">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
|
|
|
<div style="flex: 1; min-width: 0;">
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<div class="card-main">
|
|
|
|
|
<h6 class="card-title text-truncate mb-1">
|
|
|
|
|
${getTypeIcon(item.type)} ${item.title || truncate(item.content || item.url, 30)}
|
|
|
|
|
</h6>
|
|
|
|
|
@@ -3343,11 +3363,11 @@ function renderTrash(items, total) {
|
|
|
|
|
删除时间: ${formatShortDate(item.deleted_at)}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="d-flex gap-1">
|
|
|
|
|
<button class="btn btn-sm btn-outline-success" onclick="restoreItem(${item.id})" title="恢复">
|
|
|
|
|
<i class="bi bi-arrow-counterclockwise"></i> 恢复
|
|
|
|
|
<div class="card-actions">
|
|
|
|
|
<button class="btn btn-sm btn-outline-success py-0 px-1" onclick="restoreItem(${item.id})" title="恢复">
|
|
|
|
|
<i class="bi bi-arrow-counterclockwise"></i>
|
|
|
|
|
</button>
|
|
|
|
|
<button class="btn btn-sm btn-outline-danger" onclick="deletePermanently(${item.id})" title="彻底删除">
|
|
|
|
|
<button class="btn btn-sm btn-outline-danger py-0 px-1" onclick="deletePermanently(${item.id})" title="彻底删除">
|
|
|
|
|
<i class="bi bi-trash-fill"></i>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
@@ -3462,11 +3482,21 @@ function renderFolderList(type) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 切换文件夹区域展开/折叠
|
|
|
|
|
// 切换文件夹区域展开/折叠,并过滤显示该类别数据
|
|
|
|
|
function toggleSection(type) {
|
|
|
|
|
const section = document.getElementById(`section-${type}`);
|
|
|
|
|
if (!section) return;
|
|
|
|
|
|
|
|
|
|
// 切换展开状态
|
|
|
|
|
section.classList.toggle('expanded');
|
|
|
|
|
|
|
|
|
|
// 更新侧边栏选中状态
|
|
|
|
|
document.querySelectorAll('.sidebar a').forEach(a => a.classList.remove('active'));
|
|
|
|
|
section.querySelector('.section-header').classList.add('active');
|
|
|
|
|
|
|
|
|
|
// 设置过滤条件:只过滤类型,不限制文件夹
|
|
|
|
|
currentFilter = { type, status: '', starred: null, folder_id: null };
|
|
|
|
|
loadItems(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function showNewFolderModal(type) {
|
|
|
|
|
|