You've already forked SmartisanNote.Remake
优化 调整了编辑器中的工具栏显示隐藏逻辑
This commit is contained in:
@@ -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 = () => {
|
||||||
|
// 只有当虚拟键盘可见时才显示工具栏
|
||||||
|
if (isKeyboardVisible.value) {
|
||||||
isToolbarVisible.value = true
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 待办事项样式 */
|
/* 待办事项样式 */
|
||||||
|
|||||||
Reference in New Issue
Block a user