feat:任务大纲编辑文字悬浮边框重构

This commit is contained in:
liailing1026
2026-02-27 11:46:08 +08:00
parent c14430cfae
commit 1cf43fec7c

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref, onMounted, onUnmounted } from 'vue'
import type { IRawStepTask } from '@/stores' import type { IRawStepTask } from '@/stores'
import SvgIcon from '@/components/SvgIcon/index.vue' import SvgIcon from '@/components/SvgIcon/index.vue'
@@ -13,6 +13,7 @@ const emit = defineEmits<{
const isEditing = ref(false) const isEditing = ref(false)
const editingContent = ref('') const editingContent = ref('')
const editorRef = ref<HTMLElement>()
const startEditing = () => { const startEditing = () => {
editingContent.value = props.task.TaskContent || '' editingContent.value = props.task.TaskContent || ''
@@ -37,57 +38,93 @@ const handleKeydown = (event: KeyboardEvent) => {
cancel() cancel()
} }
} }
// 点击外部保存
const handleClickOutside = (event: MouseEvent) => {
if (isEditing.value && editorRef.value && !editorRef.value.contains(event.target as Node)) {
save()
}
}
onMounted(() => {
document.addEventListener('click', handleClickOutside)
})
onUnmounted(() => {
document.removeEventListener('click', handleClickOutside)
})
</script> </script>
<template> <template>
<div v-if="isEditing" class="w-full"> <div ref="editorRef" v-if="isEditing" class="w-full">
<div class="flex flex-col gap-3"> <el-input
<el-input v-model="editingContent"
v-model="editingContent" type="textarea"
type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
:autosize="{ minRows: 2, maxRows: 4 }" placeholder="请输入任务内容"
placeholder="请输入任务内容" @keydown="handleKeydown"
@keydown="handleKeydown" class="task-content-editor"
class="task-content-editor" size="small"
size="small" />
/>
<div class="flex justify-end">
<svg-icon
icon-class="Check"
size="20px"
color="#328621"
class="cursor-pointer mr-4"
@click="save"
title="保存"
/>
<svg-icon
icon-class="Cancel"
size="20px"
color="#8e0707"
class="cursor-pointer mr-1"
@click="cancel"
title="取消"
/>
</div>
</div>
</div> </div>
<div v-else @dblclick="startEditing" class="w-full cursor-pointer"> <div v-else @dblclick="startEditing" class="w-full cursor-pointer task-content-wrapper">
<slot name="display"> <slot name="display">
<div class="text-[14px] text-[var(--color-text-secondary)] task-content-display"> <div class="text-[14px] text-[var(--color-text-secondary)] task-content-display">
{{ task.TaskContent }} {{ task.TaskContent }}
</div> </div>
</slot> </slot>
<div class="edit-icon-bg" @click.stop="startEditing">
<svg-icon icon-class="Edit" class="edit-icon-svg" />
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.task-content-wrapper {
position: relative;
padding: 4px;
border: 2px solid transparent;
border-radius: 7px;
box-sizing: border-box;
transition: border-color 0.3s ease;
&:hover {
border-color: var(--color-task-edit-hover-border) !important;
}
.edit-icon-bg {
position: absolute;
right: -1px;
bottom: -1px;
width: 26px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
cursor: pointer;
background: var(--color-edit-icon-bg);
border-radius: 8px 0px 7px 0px;
.edit-icon-svg {
color: var(--color-text-detail);
}
}
&:hover .edit-icon-bg {
opacity: 1;
}
}
.task-content-editor { .task-content-editor {
:deep(.el-textarea__inner) { :deep(.el-textarea__inner) {
font-size: 14px; font-size: 14px;
color: var(--color-text-secondary); color: var(--color-text-secondary);
background: transparent; background: transparent;
border: 1px solid #dcdfe6; border: 1px solid var(--color-task-edit-hover-border) !important;
border-radius: 4px; border-radius: 4px;
box-sizing: border-box;
resize: none; resize: none;
} }
} }