优化 调整了编辑器中的工具栏显示隐藏逻辑

This commit is contained in:
User
2025-10-14 18:13:01 +08:00
parent dc74e0bfb1
commit 9934d3661a

View File

@@ -1,19 +1,19 @@
<template> <template>
<div class="editor-container"> <div class="editor-container">
<!-- 工具栏 --> <!-- 工具栏 -->
<div class="toolbar" :class="{ visible: isToolbarVisible }" @mousedown.prevent @focusin="keepToolbarVisible" @focusout="handleToolbarFocusOut"> <div class="toolbar" :class="{ visible: isToolbarVisible, 'keyboard-visible': isKeyboardVisible, 'dynamic-position': isKeyboardVisible }" @mousedown.prevent @focusin="keepToolbarVisible" @focusout="handleToolbarFocusOut">
<button v-for="tool in tools" :key="tool.name" :class="{ active: tool.active }" @click.stop="handleToolClick(tool.action, $event)" @mousedown.prevent @focusout.prevent class="toolbar-btn"> <button v-for="tool in tools" :key="tool.name" :class="{ active: tool.active }" @click.stop="handleToolClick(tool.action, $event)" @mousedown.prevent @focusout.prevent class="toolbar-btn">
<img :src="tool.icon" :alt="tool.name" class="toolbar-icon" /> <img :src="tool.icon" :alt="tool.name" class="toolbar-icon" />
</button> </button>
</div> </div>
<!-- 编辑区域 --> <!-- 编辑区域 -->
<div ref="editorRef" contenteditable="true" class="editor-content" @input="handleInput" @keydown="handleKeydown" @click="updateToolbarState" @keyup="updateToolbarState" @focus="showToolbar" @blur="hideToolbar"></div> <div ref="editorRef" contenteditable="true" class="editor-content" @input="handleInput" @keydown="handleKeydown" @click="updateToolbarState" @keyup="updateToolbarState" @focus="showToolbar" @blur="handleBlur"></div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, nextTick } from 'vue' import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@@ -27,6 +27,8 @@ const emit = defineEmits(['update:modelValue'])
const editorRef = ref(null) const editorRef = ref(null)
const content = ref(props.modelValue || '') const content = ref(props.modelValue || '')
const isToolbarVisible = ref(false) const isToolbarVisible = ref(false)
const isKeyboardVisible = ref(false)
const initialViewportHeight = ref(0)
// 初始化编辑器内容 // 初始化编辑器内容
onMounted(() => { onMounted(() => {
@@ -48,6 +50,28 @@ onMounted(() => {
console.log('Editor initialized without initial content') console.log('Editor initialized without initial content')
} }
} }
// 记录初始视口高度
initialViewportHeight.value = window.visualViewport?.height || window.innerHeight
// 初始化CSS变量
document.documentElement.style.setProperty('--viewport-height', `${initialViewportHeight.value}px`)
// 添加虚拟键盘检测事件监听器
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', handleViewportResize)
} else {
window.addEventListener('resize', handleWindowResize)
}
})
// 组件卸载时移除事件监听器
onUnmounted(() => {
if (window.visualViewport) {
window.visualViewport.removeEventListener('resize', handleViewportResize)
} else {
window.removeEventListener('resize', handleWindowResize)
}
}) })
// 工具栏配置 // 工具栏配置
@@ -718,6 +742,67 @@ const updateToolbarState = () => {
}) })
} }
// 处理视口大小变化(用于检测虚拟键盘)
const handleViewportResize = () => {
if (!window.visualViewport) return
const currentHeight = window.visualViewport.height
const heightDifference = initialViewportHeight.value - currentHeight
// 如果高度差超过150px认为虚拟键盘已弹出
isKeyboardVisible.value = heightDifference > 150
// 动态设置CSS变量以调整工具栏位置
document.documentElement.style.setProperty('--viewport-height', `${currentHeight}px`)
// 根据虚拟键盘状态更新工具栏可见性
updateToolbarVisibility()
}
// 处理窗口大小变化(备用方案)
const handleWindowResize = () => {
const currentHeight = window.innerHeight
const heightDifference = initialViewportHeight.value - currentHeight
// 如果高度差超过150px认为虚拟键盘已弹出
isKeyboardVisible.value = heightDifference > 150
// 根据虚拟键盘状态更新工具栏可见性
updateToolbarVisibility()
}
// 更新工具栏可见性
const updateToolbarVisibility = () => {
// 只有当编辑器有焦点且虚拟键盘可见时才显示工具栏
if (isKeyboardVisible.value && (document.activeElement === editorRef.value || isTodoContentActive())) {
isToolbarVisible.value = true
} else {
// 延迟隐藏工具栏,确保用户有时间操作
setTimeout(() => {
// 只有在没有待办事项获得焦点且虚拟键盘不可见时才隐藏工具栏
if (!isTodoContentActive() && !isKeyboardVisible.value) {
isToolbarVisible.value = false
}
}, 200)
}
}
// 检查是否有待办事项内容区域获得焦点
const isTodoContentActive = () => {
const todoContentElements = document.querySelectorAll('.todo-content')
for (let i = 0; i < todoContentElements.length; i++) {
if (todoContentElements[i] === document.activeElement || todoContentElements[i].contains(document.activeElement)) {
return true
}
}
return false
}
// 监听虚拟键盘状态变化
watch(isKeyboardVisible, (newVal) => {
updateToolbarVisibility()
})
// 初始化编辑器内容 // 初始化编辑器内容
onMounted(() => { onMounted(() => {
if (editorRef.value) { if (editorRef.value) {
@@ -727,11 +812,14 @@ onMounted(() => {
// 显示工具栏 // 显示工具栏
const showToolbar = () => { const showToolbar = () => {
isToolbarVisible.value = true // 只有当虚拟键盘可见时才显示工具栏
if (isKeyboardVisible.value) {
isToolbarVisible.value = true
}
} }
// 隐藏工具栏 // 处理编辑器失焦
const hideToolbar = () => { const handleBlur = () => {
// 不立即隐藏工具栏而是通过handleToolbarFocusOut处理 // 不立即隐藏工具栏而是通过handleToolbarFocusOut处理
// 添加延迟以确保点击工具栏按钮时不会立即隐藏 // 添加延迟以确保点击工具栏按钮时不会立即隐藏
setTimeout(() => { setTimeout(() => {
@@ -764,6 +852,11 @@ const handleToolClick = (action, event) => {
// 对于待办事项,确保工具栏保持可见 // 对于待办事项,确保工具栏保持可见
isToolbarVisible.value = true isToolbarVisible.value = true
} }
// 确保工具栏在虚拟键盘可见时保持显示
if (isKeyboardVisible.value) {
isToolbarVisible.value = true
}
} }
// 保持工具栏可见 // 保持工具栏可见
@@ -791,8 +884,8 @@ const handleToolbarFocusOut = () => {
} }
} }
// 只有在没有待办事项获得焦点时才隐藏工具栏 // 只有在没有待办事项获得焦点且虚拟键盘不可见时才隐藏工具栏
if (!todoHasFocus) { if (!todoHasFocus && !isKeyboardVisible.value) {
isToolbarVisible.value = false isToolbarVisible.value = false
} }
} }
@@ -925,6 +1018,20 @@ defineExpose({
transform: translateY(0); transform: translateY(0);
} }
/* 当虚拟键盘可见时,调整工具栏位置 */
.toolbar.keyboard-visible {
bottom: 0;
}
/* 使用visualViewport API动态调整工具栏位置 */
.toolbar.dynamic-position {
bottom: calc(100vh - var(--viewport-height, 100vh));
}
.toolbar.visible {
transform: translateY(0);
}
.toolbar-btn { .toolbar-btn {
padding: 0.375rem; padding: 0.375rem;
margin-right: 0.375rem; margin-right: 0.375rem;
@@ -1097,6 +1204,7 @@ defineExpose({
border: 0.625rem solid white; border: 0.625rem solid white;
border-radius: 0.2rem; border-radius: 0.2rem;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.18); box-shadow: 0 1px 5px rgba(0, 0, 0, 0.18);
background: var(--background-secondary);
} }
/* 待办事项样式 */ /* 待办事项样式 */