From cbe014e10d2d369666c402604da912dc0fba9fca Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Wed, 8 Apr 2026 18:45:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=90=88=E5=B9=B6=E5=B7=A6=E4=BE=A7?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新建记录输入内容超过20字时自动生成标题 - 左侧列表新增导出按钮(导出为Markdown文件) - 置顶、导出、删除三个按钮合并,hover时显示 --- app.py | 8 +++++ templates/index.html | 70 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/app.py b/app.py index 2b3634f..90c92ed 100644 --- a/app.py +++ b/app.py @@ -167,9 +167,17 @@ def api_update_note(note_id): now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + # 新记录第一次输入内容时,自动生成标题 + old_content = note.get('content', '') + need_generate_title = (note['title'] == '新记录' and len(content) >= 20) + note['content'] = content note['updated_at'] = now + # 如果是新记录第一次输入内容,异步生成标题 + if need_generate_title: + threading.Thread(target=generate_title_async, args=(note_id, content)).start() + save_notes(notes) return jsonify(note) diff --git a/templates/index.html b/templates/index.html index 3ba0f7b..e0200f7 100644 --- a/templates/index.html +++ b/templates/index.html @@ -15,9 +15,13 @@ .fade-in { animation: fadeIn 0.3s ease; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .gradient-bg { background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); } - .hidden-menu { display: none; } - .note-item:hover .hidden-menu { display: flex; } - .context-menu { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); } + .action-btn { + opacity: 0; + transition: opacity 0.2s; + } + .note-item:hover .action-btn { + opacity: 1; + } @@ -69,6 +73,9 @@

+ @@ -130,21 +137,25 @@ container.innerHTML = notes.map(n => `
-
+
${n.pinned ? '' : ''}

${n.title || '新记录'}

${showPreview && n.preview ? `

${n.preview}

` : ''}

${n.updated_at}

- -
+ +
+
@@ -309,6 +320,26 @@ loadNotes(); } + // 导出笔记 + async function exportItem(id) { + const res = await fetch(`/api/notes/${id}`); + const note = await res.json(); + + if (!note) return; + + // 创建下载内容 + const content = `# ${note.title}\n\n创建时间: ${note.created_at}\n更新时间: ${note.updated_at}\n\n---\n\n${note.content}`; + + // 创建Blob并下载 + const blob = new Blob([content], { type: 'text/markdown;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${note.title || '记录'}.md`; + a.click(); + URL.revokeObjectURL(url); + } + // 删除当前笔记 async function deleteCurrentNote() { if (!currentNoteId) return; @@ -326,6 +357,27 @@ loadNotes(); } + // 导出当前笔记 + async function exportCurrentNote() { + if (!currentNoteId) return; + + const title = document.getElementById('titleText').textContent; + const content = document.getElementById('editor').value; + const timeInfo = document.getElementById('currentTime').textContent; + + // 创建下载内容 + const exportContent = `# ${title}\n\n${timeInfo}\n\n---\n\n${content}`; + + // 创建Blob并下载 + const blob = new Blob([exportContent], { type: 'text/markdown;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${title}.md`; + a.click(); + URL.revokeObjectURL(url); + } + // 定时检查标题更新(用于异步生成标题后刷新) function startTitlePolling() { if (titleUpdateTimer) clearInterval(titleUpdateTimer);