优化了编辑器中的图片显示尺寸

This commit is contained in:
2025-10-12 21:09:03 +08:00
parent 1bb9b4a79e
commit b2fda14451
3 changed files with 146 additions and 19 deletions

View File

@@ -14,7 +14,7 @@
</div> </div>
<div class="code-fun-flex-row code-fun-justify-between mt-17-5"> <div class="code-fun-flex-row code-fun-justify-between mt-17-5">
<!-- 便签正文第一行 --> <!-- 便签正文第一行 -->
<span class="font_3 text_19">{{ content }}</span> <span class="font_3 text_19">{{ displayContent }}</span>
<!-- 便签中是否存在图片 --> <!-- 便签中是否存在图片 -->
<img v-if="hasImage" class="image_28" src="/assets/icons/drawable-xxhdpi/list_item_image_icon.png" /> <img v-if="hasImage" class="image_28" src="/assets/icons/drawable-xxhdpi/list_item_image_icon.png" />
</div> </div>
@@ -81,6 +81,23 @@ const formattedDate = computed(() => {
return props.date return props.date
}) })
// 处理显示内容过滤HTML标签并只显示第一行
const displayContent = computed(() => {
console.log('NoteItem content:', props.content)
// 过滤HTML标签
let text = props.content.replace(/<[^>]*>/g, '')
console.log('NoteItem text without HTML:', text)
// 处理换行符,统一为\n
text = text.replace(/\\n/g, '\n')
// 按换行符分割并获取第一行
const lines = text.split('\n')
// 返回第一行内容,如果为空则显示默认文本
return lines[0]?.trim() || '无内容'
})
// 滑动阈值(删除按钮宽度) // 滑动阈值(删除按钮宽度)
const SLIDE_THRESHOLD = 64 // 4rem 转换为 px const SLIDE_THRESHOLD = 64 // 4rem 转换为 px

View File

@@ -37,6 +37,8 @@ onMounted(() => {
editorRef.value.innerHTML = props.modelValue editorRef.value.innerHTML = props.modelValue
content.value = props.modelValue content.value = props.modelValue
console.log('Initial content set successfully') console.log('Initial content set successfully')
// 调整已有图片的高度
adjustExistingImages()
} catch (error) { } catch (error) {
console.error('Failed to set initial content:', error) console.error('Failed to set initial content:', error)
} }
@@ -91,8 +93,20 @@ const tools = ref([
// 处理输入事件 // 处理输入事件
const handleInput = () => { const handleInput = () => {
if (editorRef.value) { if (editorRef.value) {
content.value = editorRef.value.innerHTML // 获取编辑器内容
console.log('Input event handled, content:', content.value) let innerHTML = editorRef.value.innerHTML
// 处理换行符,确保在段落之间有明确的分隔
innerHTML = innerHTML.replace(/<\/p><p>/g, '</p>\n<p>')
// 处理div标签换行
innerHTML = innerHTML.replace(/<\/div><div>/g, '</div>\n<div>')
// 处理br标签换行
innerHTML = innerHTML.replace(/<br>/g, '\n')
innerHTML = innerHTML.replace(/<br\/>/g, '\n')
// 处理div标签内的换行
innerHTML = innerHTML.replace(/<div>/g, '\n<div>')
content.value = innerHTML
emit('update:modelValue', content.value) emit('update:modelValue', content.value)
} }
} }
@@ -547,10 +561,42 @@ const insertImage = () => {
const img = document.createElement('img') const img = document.createElement('img')
img.src = imageDataUrl img.src = imageDataUrl
img.className = 'editor-image' img.className = 'editor-image'
img.style.maxWidth = '100%'
img.style.height = 'auto' // 创建一个临时图片来获取原始尺寸
img.style.display = 'block' const tempImg = new Image()
img.style.margin = '0 auto' tempImg.onload = function () {
// 获取CSS变量
const editorFontSize = getComputedStyle(document.documentElement).getPropertyValue('--editor-font-size').trim() || '16px'
const editorLineHeight = getComputedStyle(document.documentElement).getPropertyValue('--editor-line-height').trim() || '1.6'
const fontSize = parseInt(editorFontSize)
const lineHeight = parseFloat(editorLineHeight)
// 计算行高
const computedLineHeight = fontSize * lineHeight
// 获取编辑器的宽度(减去一些内边距)
const editorWidth = editorRef.value.offsetWidth - 20 // 20px为左右内边距
// 按宽度撑满计算调整后的尺寸
const originalHeight = tempImg.height
const originalWidth = tempImg.width
const scaleRatio = editorWidth / originalWidth
const scaledHeight = originalHeight * scaleRatio
// 计算调整后的高度,使其为行高的整数倍
const scaleFactor = Math.max(1, Math.round(scaledHeight / computedLineHeight))
const adjustedHeight = scaleFactor * computedLineHeight
// 按比例调整宽度
const adjustedWidth = (originalWidth * adjustedHeight) / originalHeight
img.style.height = `${adjustedHeight}px`
img.style.width = `${adjustedWidth}px`
// 确保图片与基准线对齐
img.style.verticalAlign = 'top'
}
tempImg.src = imageDataUrl
// 插入图片到当前光标位置 // 插入图片到当前光标位置
range.insertNode(img) range.insertNode(img)
@@ -731,6 +777,59 @@ const handleToolbarFocusOut = () => {
}, 200) // 增加延迟时间,确保有足够时间处理点击事件 }, 200) // 增加延迟时间,确保有足够时间处理点击事件
} }
// 调整已有图片的高度
const adjustExistingImages = () => {
// 等待DOM更新完成
setTimeout(() => {
if (editorRef.value) {
const images = editorRef.value.querySelectorAll('img.editor-image')
images.forEach(img => {
// 只处理还没有调整过高度的图片
if (!img.dataset.heightAdjusted) {
// 创建一个临时图片来获取原始尺寸
const tempImg = new Image()
tempImg.onload = function () {
// 获取CSS变量
const editorFontSize = getComputedStyle(document.documentElement).getPropertyValue('--editor-font-size').trim() || '16px'
const editorLineHeight = getComputedStyle(document.documentElement).getPropertyValue('--editor-line-height').trim() || '1.6'
const fontSize = parseInt(editorFontSize)
const lineHeight = parseFloat(editorLineHeight)
// 计算行高
const computedLineHeight = fontSize * lineHeight
// 获取编辑器的宽度(减去一些内边距)
const editorWidth = editorRef.value.offsetWidth - 20 // 20px为左右内边距
// 按宽度撑满计算调整后的尺寸
const originalHeight = tempImg.height
const originalWidth = tempImg.width
const scaleRatio = editorWidth / originalWidth
const scaledHeight = originalHeight * scaleRatio
// 计算调整后的高度,使其为行高的整数倍
const scaleFactor = Math.max(1, Math.round(scaledHeight / computedLineHeight))
const adjustedHeight = scaleFactor * computedLineHeight
// 按比例调整宽度
const adjustedWidth = (originalWidth * adjustedHeight) / originalHeight
img.style.height = `${adjustedHeight}px`
img.style.width = `${adjustedWidth}px`
// 确保图片与基准线对齐
img.style.verticalAlign = 'top'
// 标记图片已调整过高度
img.dataset.heightAdjusted = 'true'
}
tempImg.src = img.src
}
})
}
}, 0)
}
// 暴露方法给父组件 // 暴露方法给父组件
defineExpose({ defineExpose({
getContent: () => content.value, getContent: () => content.value,
@@ -741,6 +840,8 @@ defineExpose({
try { try {
editorRef.value.innerHTML = content.value editorRef.value.innerHTML = content.value
console.log('Content set successfully in editorRef') console.log('Content set successfully in editorRef')
// 调整已有图片的高度
adjustExistingImages()
} catch (error) { } catch (error) {
console.error('Failed to set innerHTML:', error) console.error('Failed to set innerHTML:', error)
// 备选方案使用textContent // 备选方案使用textContent
@@ -759,6 +860,8 @@ defineExpose({
try { try {
editorRef.value.innerHTML = content.value editorRef.value.innerHTML = content.value
console.log('Content set successfully after delay') console.log('Content set successfully after delay')
// 调整已有图片的高度
adjustExistingImages()
} catch (error) { } catch (error) {
console.error('Failed to set innerHTML after delay:', error) console.error('Failed to set innerHTML after delay:', error)
} }
@@ -774,7 +877,7 @@ defineExpose({
.editor-container { .editor-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; min-height: 100%;
background-color: var(--background-card); background-color: var(--background-card);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
} }
@@ -962,30 +1065,37 @@ defineExpose({
text-align: center; text-align: center;
} }
:deep(.editor-content .editor-image) {
.editor-content img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
display: block; display: block;
margin: 0 auto; margin: calc((var(--editor-line-height, 1.6) * 10) * 1px) auto;
object-fit: cover;
box-sizing: border-box;
border: 10px solid white;
border-radius: 0.2rem;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.18);
} }
/* 待办事项样式 */ /* 待办事项样式 */
:deep(.todo-container) { :deep(.todo-container) {
display: flex; display: flex;
align-items: center; align-items: flex-start;
margin: 0; margin: 0;
line-height: var(--editor-line-height, 1.6); line-height: var(--editor-line-height, 1.6);
position: relative;
padding-left: calc(var(--editor-font-size, 16px) * 1.5);
} }
:deep(.todo-icon) { :deep(.todo-icon) {
width: calc(var(--editor-font-size, 16px) * 2); width: calc(var(--editor-font-size, 16px) * 1.5);
height: calc(var(--editor-font-size, 16px) * 2); height: calc(var(--editor-font-size, 16px) * 1.5);
margin-right: 3px;
margin-top: 0;
cursor: pointer; cursor: pointer;
flex-shrink: 0; flex-shrink: 0;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
} }
:deep(.todo-content) { :deep(.todo-content) {

View File

@@ -277,14 +277,14 @@ const setShowAlert = value => {
} }
.rich-text-editor { .rich-text-editor {
height: 100%; min-height: 100%;
} }
.header-info { .header-info {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
gap: 10px; gap: 10px;
padding: 1.5rem 16px 0.7rem 16px; padding: 1rem 16px 0.7rem 16px;
background-color: var(--background-card); background-color: var(--background-card);
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
font-size: 0.7rem; font-size: 0.7rem;