From 34daf24731ba44400ba5cd06e3d342b22b4cab8b Mon Sep 17 00:00:00 2001 From: User Date: Sat, 11 Oct 2025 15:43:48 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BA=86=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E6=A0=B7=E5=BC=8F=EF=BC=9B=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E4=BA=86=E5=A4=B4=E9=83=A8=E7=9A=84=E6=8C=89=E9=92=AE?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header.vue | 24 ++++- src/components/RichTextEditor.vue | 170 ++++++++++++++++-------------- src/pages/NoteEditorPage.vue | 37 +------ src/pages/NoteListPage.vue | 25 +++-- 4 files changed, 129 insertions(+), 127 deletions(-) diff --git a/src/components/Header.vue b/src/components/Header.vue index 981b946..36bf429 100644 --- a/src/components/Header.vue +++ b/src/components/Header.vue @@ -12,7 +12,16 @@ + + +
+ + + + +
+
@@ -24,7 +33,7 @@ import { ref, computed } from 'vue' const props = defineProps({ title: { type: String, - required: true, + default: '', }, onBack: { type: Function, @@ -131,6 +140,8 @@ const handleTitlePress = () => { display: flex; justify-content: space-between; align-items: center; + margin-bottom: -2.8rem; + position: relative; .inner { display: flex; justify-content: space-between; @@ -139,14 +150,17 @@ const handleTitlePress = () => { } .left-icon, .image_4 { - width: 1.7rem; - height: 1.7rem; + width: 1.8rem; + height: 1.8rem; cursor: pointer; } + .right-group { + gap: .6rem; + } .image_4-placeholder { - width: 1.7rem; - height: 1.7rem; + width: 1.8rem; + height: 1.8rem; } .title-container { diff --git a/src/components/RichTextEditor.vue b/src/components/RichTextEditor.vue index 7a667a6..1efc61c 100644 --- a/src/components/RichTextEditor.vue +++ b/src/components/RichTextEditor.vue @@ -137,7 +137,7 @@ const insertQuote = () => { const selection = window.getSelection() if (selection.rangeCount > 0) { const range = selection.getRangeAt(0) - + // 检查是否已经在引用中 const container = range.commonAncestorContainer let current = container.nodeType === Node.TEXT_NODE ? container.parentElement : container @@ -145,43 +145,43 @@ const insertQuote = () => { if (current.tagName === 'BLOCKQUOTE' || (current.classList && current.classList.contains('quote-content'))) return current = current.parentElement } - + // 检查嵌套限制 if (isInListOrQuote()) return - + // 创建引用容器 const quoteContainer = document.createElement('div') quoteContainer.className = 'quote-container' - + // 创建图标元素 const icon = document.createElement('img') icon.className = 'quote-icon' icon.src = '/assets/icons/drawable-xxhdpi/rag_quote.png' icon.alt = '引用' - + // 创建内容容器 - const contentSpan = document.createElement('blockquote') + const contentSpan = document.createElement('div') contentSpan.className = 'quote-content' contentSpan.textContent = '引用内容' - + // 组装元素 quoteContainer.appendChild(icon) quoteContainer.appendChild(contentSpan) - + // 插入到当前光标位置 range.insertNode(quoteContainer) - + // 添加换行 const br = document.createElement('br') quoteContainer.parentNode.insertBefore(br, quoteContainer.nextSibling) - + // 聚焦到内容区域 const newRange = document.createRange() newRange.selectNodeContents(contentSpan) newRange.collapse(false) selection.removeAllRanges() selection.addRange(newRange) - + // 添加事件监听器到内容区域,监听内容变化 const checkContent = () => { // 延迟检查,确保内容已更新 @@ -193,10 +193,10 @@ const insertQuote = () => { } }, 0) } - + contentSpan.addEventListener('input', checkContent) contentSpan.addEventListener('blur', checkContent) - + handleInput() } } @@ -222,7 +222,7 @@ const insertTodoList = () => { icon.alt = '待办事项' // 创建内容容器 - const contentSpan = document.createElement('span') + const contentSpan = document.createElement('div') contentSpan.contentEditable = true contentSpan.className = 'todo-content' contentSpan.textContent = '待办事项' @@ -292,7 +292,7 @@ const insertTodoList = () => { newIcon.alt = '待办事项' // 创建内容容器 - const newContentSpan = document.createElement('span') + const newContentSpan = document.createElement('div') newContentSpan.contentEditable = true newContentSpan.className = 'todo-content' newContentSpan.textContent = '' @@ -360,7 +360,7 @@ const insertTodoList = () => { nextIcon.alt = '待办事项' // 创建内容容器 - const nextContentSpan = document.createElement('span') + const nextContentSpan = document.createElement('div') nextContentSpan.contentEditable = true nextContentSpan.className = 'todo-content' nextContentSpan.textContent = '' @@ -572,7 +572,7 @@ defineExpose({ .editor-content { flex: 1; - padding: 20px 16px; + padding: 20px 10px; outline: none; overflow-y: auto; font-size: 16px; @@ -581,6 +581,22 @@ defineExpose({ min-height: 200px; background-color: var(--background-card); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + position: relative; + /* 基准线样式 */ + background-image: linear-gradient(to bottom, var(--border) 1px, transparent 1px); + background-size: 100% 25.6px; /* 16px * 1.6 = 25.6px */ + background-repeat: repeat-y; + background-position: 0 20px; +} + +.editor-content::before { + display: none; +} + +/* 统一处理所有直接子元素的间距 */ +.editor-content > * { + margin: 0; + padding: 0; } .editor-content:focus, @@ -588,69 +604,72 @@ defineExpose({ outline: none; } -/* 自定义内容样式 */ +/* 优化段落样式,确保与基准线对齐 */ +:deep(.editor-content p) { + margin: 0 0 12px 0; + line-height: 1.6; + letter-spacing: 0.3px; +} + +/* 自定义内容样式 - 统一行高和间距 */ :deep(.editor-content h2) { font-size: 20px; font-weight: 600; - margin: 8px 0 8px 0; + margin: 0 0 12px 0; color: var(--note-title); - line-height: 1.4; - letter-spacing: 0.5px; + line-height: 1.6; + letter-spacing: 0.3px; text-align: center; position: relative; } :deep(.editor-content blockquote) { border-left: 3px solid var(--primary); - padding-left: 16px; - margin: 16px 0; + padding: 0 16px 0 16px; + margin: 0 0 12px 0; color: var(--text-secondary); background-color: var(--background-secondary); - padding: 8px 16px 8px 16px; - border-radius: 0 4px 4px 0; font-style: italic; + line-height: 1.6; } :deep(.quote-container) { position: relative; - margin: 16px 0; + margin: 0 0 12px 0; + line-height: 1.6; } :deep(.quote-icon) { position: absolute; left: 0; - top: 10px; + top: 0; width: 16px; height: 16px; + margin-top: 3px; } :deep(.quote-content) { border-left: 3px solid var(--primary); - padding-left: 32px; + padding: 0 16px 0 32px; margin-left: 16px; color: var(--text-secondary); background-color: var(--background-secondary); - padding: 8px 16px 8px 16px; - border-radius: 0 4px 4px 0; font-style: italic; + line-height: 1.6; } :deep(.editor-content ul), :deep(.editor-content ol) { - margin: 16px 0; + margin: 0 0 12px 0; padding-left: 32px; position: relative; + line-height: 1.6; } :deep(.editor-content li) { - margin: 6px 0; - line-height: 1.5; -} - -:deep(.editor-content p) { - margin: 0 0 12px 0; + margin: 0; line-height: 1.6; - letter-spacing: 0.3px; + padding: 0; } :deep(.editor-content strong) { @@ -672,64 +691,61 @@ defineExpose({ border: none; height: 1px; background-color: var(--border); - margin: 20px 0; + margin: 12px 0; } .editor-content div[style*='text-align: center'] { text-align: center; } -/* 待办事项样式 */ -:deep(.todo-container) { - display: flex; - align-items: flex-start; - margin: 0.1rem 0; - padding: 0.02rem 0; - position: relative; - padding-left: 1.2rem; -} - -:deep(.todo-icon) { - position: absolute; - left: 0; - top: 0; - width: 2rem; - height: 2rem; - cursor: pointer; -} - -:deep(.todo-content) { - flex: 1; - outline: none; - padding: 0.125rem 0.25rem; - min-height: 1.25rem; - border-radius: 0.125rem; - color: var(--note-content); - margin-left: 0.5rem; -} - /* 引用格式样式 */ :deep(.quote-container) { position: relative; - margin: 1rem 0; + margin: 0 0 12px 0; + line-height: 1.6; } :deep(.quote-icon) { position: absolute; left: 0; - top: 0.625rem; - width: 1rem; - height: 1rem; + top: 0; + width: 16px; + height: 16px; + margin-top: 3px; } :deep(.quote-content) { - border-left: 0.1875rem solid var(--primary); - padding-left: 2rem; - margin-left: 1.5rem; + border-left: 3px solid var(--primary); + padding: 0 16px 0 32px; + margin-left: 16px; color: var(--text-secondary); background-color: var(--background-secondary); - padding: 0.5rem 1rem; - border-radius: 0 0.25rem 0.25rem 0; font-style: italic; + line-height: 1.6; +} + +/* 待办事项样式 */ +:deep(.todo-container) { + display: flex; + align-items: center; + margin: 0; + line-height: 1.6; +} + +:deep(.todo-icon) { + width: 25px; + height: 25px; + margin-right: 2px; + margin-top: 0; + cursor: pointer; + flex-shrink: 0; +} + +:deep(.todo-content) { + flex: 1; + outline: none; + line-height: 1.6; + padding: 0; + margin: 0; } diff --git a/src/pages/NoteEditorPage.vue b/src/pages/NoteEditorPage.vue index 1e209dd..d8c3e63 100644 --- a/src/pages/NoteEditorPage.vue +++ b/src/pages/NoteEditorPage.vue @@ -1,7 +1,7 @@