diff --git a/static/src/components/personalization/PersonalizationDrawer.vue b/static/src/components/personalization/PersonalizationDrawer.vue index 36432bac..db44b0a2 100644 --- a/static/src/components/personalization/PersonalizationDrawer.vue +++ b/static/src/components/personalization/PersonalizationDrawer.vue @@ -4,11 +4,11 @@ class="personal-page-overlay" v-if="visible" @click="closeDropdown" - @mousedown.self="personalization.handleOverlayPressStart($event)" - @mouseup.self="personalization.handleOverlayPressEnd" + @mousedown="personalization.handleOverlayPressStart($event)" + @mouseup="personalization.handleOverlayPressEnd($event)" @mouseleave.self="personalization.handleOverlayPressCancel" @touchstart.self.prevent="personalization.handleOverlayPressStart($event)" - @touchend.self.prevent="personalization.handleOverlayPressEnd" + @touchend="personalization.handleOverlayPressEnd($event)" @touchcancel.self="personalization.handleOverlayPressCancel" >
@@ -1861,7 +1861,8 @@ v-if="roleEditorOpen" class="role-editor-drawer-overlay" @click="closeDropdown" - @click.self="closeRoleEditor" + @mousedown="handleRoleEditorOverlayPressStart" + @mouseup="handleRoleEditorOverlayPressEnd" >
@@ -2866,6 +2867,25 @@ const closeRoleEditor = () => { closeDropdown(); }; +// 角色编辑弹窗遮罩:按下与松开都发生在遮罩上才视为「点击遮罩关闭」。 +// 修复:在输入框内拖选文字、松开落在遮罩上时,click 事件 target 为遮罩, +// 会被 @click.self 误判为点击遮罩,导致整个编辑器关闭、表单内容丢失。 +const roleEditorOverlayPressActive = ref(false); + +const handleRoleEditorOverlayPressStart = (event: MouseEvent) => { + roleEditorOverlayPressActive.value = + event.target === event.currentTarget && event.button === 0; +}; + +const handleRoleEditorOverlayPressEnd = (event: MouseEvent) => { + const shouldClose = + roleEditorOverlayPressActive.value && event.target === event.currentTarget; + roleEditorOverlayPressActive.value = false; + if (shouldClose) { + closeRoleEditor(); + } +}; + const saveRole = async () => { roleSaving.value = true; try { diff --git a/static/src/stores/personalization.ts b/static/src/stores/personalization.ts index 6cd69719..bb23dc69 100644 --- a/static/src/stores/personalization.ts +++ b/static/src/stores/personalization.ts @@ -347,19 +347,29 @@ export const usePersonalizationStore = defineStore('personalization', { this.overlayPressActive = false; }, handleOverlayPressStart(event: Event) { - if (event && (event as MouseEvent).type === 'mousedown') { - const mouse = event as MouseEvent; - if (mouse.button !== 0) { - return; - } + // 只有直接按在遮罩上才算有效按压;按在卡片内部(如输入框)时重置状态, + // 避免「按下遮罩→拖入卡片松开」遗留的卡死状态导致后续遮罩 mouseup 误关抽屉 + if (event.target !== event.currentTarget) { + this.overlayPressActive = false; + return; + } + if (event.type === 'mousedown' && (event as MouseEvent).button !== 0) { + return; } this.overlayPressActive = true; }, - handleOverlayPressEnd() { - if (!this.overlayPressActive) { + handleOverlayPressEnd(event: Event) { + // 按下与松开都发生在遮罩上才关闭;输入框内拖选文字、松开落在遮罩上时 + // target 虽为遮罩,但按压并未起始于遮罩,不会关闭 + const shouldClose = + this.overlayPressActive && event.target === event.currentTarget; + this.overlayPressActive = false; + if (!shouldClose) { return; } - this.overlayPressActive = false; + if (event.cancelable) { + event.preventDefault(); + } this.closeDrawer(); }, handleOverlayPressCancel() {