|
|
|
|
@@ -188,9 +188,14 @@ INDEX_TEMPLATE = '''
|
|
|
|
|
.sidebar a { color: #adb5bd; text-decoration: none; padding: 10px 20px; display: block; }
|
|
|
|
|
.sidebar a:hover, .sidebar a.active { background: #495057; color: #fff; }
|
|
|
|
|
.content { padding: 20px; }
|
|
|
|
|
.card { margin-bottom: 15px; transition: transform 0.2s; }
|
|
|
|
|
.card { margin-bottom: 8px; transition: transform 0.2s; }
|
|
|
|
|
.card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
|
|
|
|
|
.card-body { padding: 10px 15px; }
|
|
|
|
|
.tag { margin-right: 5px; }
|
|
|
|
|
.item-card { font-size: 14px; }
|
|
|
|
|
.item-card h6 { font-size: 14px; margin-bottom: 4px; }
|
|
|
|
|
.item-card p { margin-bottom: 4px; }
|
|
|
|
|
.item-card .text-muted.small { font-size: 12px; }
|
|
|
|
|
.type-text { border-left: 4px solid #17a2b8; }
|
|
|
|
|
.type-link { border-left: 4px solid #28a745; }
|
|
|
|
|
.type-column { border-left: 4px solid #6f42c1; }
|
|
|
|
|
@@ -534,34 +539,25 @@ function renderItems(items) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
container.innerHTML = items.map(item => `
|
|
|
|
|
<div class="card type-${item.type}" style="cursor: pointer;" onclick="showDetail(${item.id})">
|
|
|
|
|
<div class="card type-${item.type} item-card" 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;">
|
|
|
|
|
<h6 class="card-title">
|
|
|
|
|
${getTypeIcon(item.type)} ${item.title || truncate(item.content || item.url, 50)}
|
|
|
|
|
<div style="flex: 1; min-width: 0;">
|
|
|
|
|
<h6 class="card-title text-truncate mb-1">
|
|
|
|
|
${getTypeIcon(item.type)} ${item.title || truncate(item.content || item.url, 30)}
|
|
|
|
|
</h6>
|
|
|
|
|
<p class="card-text text-muted small mb-2">
|
|
|
|
|
${item.url ? `<a href="${item.url}" target="_blank" onclick="event.stopPropagation();">${item.url}</a><br>` : ''}
|
|
|
|
|
${item.content ? truncate(item.content, 100) : ''}
|
|
|
|
|
<p class="card-text text-muted small mb-0 text-truncate" style="font-size:12px;">
|
|
|
|
|
${item.url ? truncate(item.url, 50) : item.content ? truncate(item.content, 50) : item.note ? truncate(item.note, 50) : ''}
|
|
|
|
|
${item.type === 'todo' ? `${getStatusLabelShort(item.status)} ${getPriorityLabelShort(item.priority)} ${item.due_date ? '📅' + item.due_date : ''}` : ''}
|
|
|
|
|
</p>
|
|
|
|
|
<div>
|
|
|
|
|
${item.tags.map(t => `<span class="badge bg-secondary tag">${t}</span>`).join('')}
|
|
|
|
|
${item.type === 'todo' ? `
|
|
|
|
|
<span class="badge status-${item.status}">${getStatusLabel(item.status)}</span>
|
|
|
|
|
<span class="badge priority-${item.priority}">${getPriorityLabel(item.priority)}</span>
|
|
|
|
|
${item.due_date ? `<span class="badge bg-light text-dark">📅 ${item.due_date}</span>` : ''}
|
|
|
|
|
` : ''}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="btn-group btn-group-sm" onclick="event.stopPropagation();">
|
|
|
|
|
<button class="btn btn-outline-primary" onclick="openEditModal(${item.id})" title="编辑"><i class="bi bi-pencil"></i></button>
|
|
|
|
|
${item.type === 'todo' && item.status !== 'completed' ?
|
|
|
|
|
`<button class="btn btn-outline-success" onclick="completeItem(${item.id})" title="完成"><i class="bi bi-check-lg"></i></button>` : ''}
|
|
|
|
|
<button class="btn btn-outline-danger" onclick="deleteItem(${item.id})" title="删除"><i class="bi bi-trash"></i></button>
|
|
|
|
|
<div class="d-flex align-items-center gap-1 flex-wrap ms-2" 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-primary py-0 px-1" onclick="openEditModal(${item.id})" title="编辑"><i class="bi bi-pencil" style="font-size:11px;"></i></button>
|
|
|
|
|
${item.type === 'todo' && item.status !== 'completed' ? `<button class="btn btn-sm btn-outline-success py-0 px-1" onclick="completeItem(${item.id})" title="完成"><i class="bi bi-check-lg" style="font-size:11px;"></i></button>` : ''}
|
|
|
|
|
<button class="btn btn-sm btn-outline-danger py-0 px-1" onclick="deleteItem(${item.id})" title="删除"><i class="bi bi-trash" style="font-size:11px;"></i></button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="text-muted small mt-2">${formatDate(item.created_at)}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
`).join('');
|
|
|
|
|
@@ -768,6 +764,16 @@ function getStatusLabel(status) {
|
|
|
|
|
return labels[status] || status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getStatusLabelShort(status) {
|
|
|
|
|
const labels = { pending: '⏳', in_progress: '🔄', completed: '✅' };
|
|
|
|
|
return labels[status] || status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPriorityLabelShort(priority) {
|
|
|
|
|
const labels = { low: '🟢', medium: '🟡', high: '🟠', urgent: '🔴' };
|
|
|
|
|
return labels[priority] || '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPriorityLabel(priority) {
|
|
|
|
|
const labels = { low: '🟢 低', medium: '🟡 中', high: '🟠 高', urgent: '🔴 紧急' };
|
|
|
|
|
return labels[priority] || priority;
|
|
|
|
|
|