diff --git a/src/components/editor/CustomEditor.vue b/src/components/editor/CustomEditor.vue index b22e712..0ec7906 100644 --- a/src/components/editor/CustomEditor.vue +++ b/src/components/editor/CustomEditor.vue @@ -33,7 +33,6 @@ const props = defineProps({ const emit = defineEmits(['editor-event']) -// 响应式数据 const editorRef = ref(null) const content = ref('') const isFocused = ref(false) @@ -49,7 +48,6 @@ const fileImageRef = ref(null) const uploadFileRef = ref(null) const emoticonRef = ref(null) -// 获取状态管理 const dialogueStore = useDialogueStore() const editorDraftStore = useEditorDraftStore() @@ -94,7 +92,7 @@ const toolbarConfig = computed(() => { return config }) -// 处理输入事件 - 优化版本,减少DOM操作 +// 处理输入事件 const handleInput = (event) => { const target = event.target @@ -162,9 +160,9 @@ const checkMention = (target) => { // 显示mention列表 const showMentionList = () => { const query = currentMentionQuery.value.toLowerCase() - mentionList.value = props.members.filter(member => - member.nickname.toLowerCase().includes(query) - ).slice(0, 10) + mentionList.value = props.members.filter(member => { + return member.value.toLowerCase().startsWith(query) + }) showMention.value = mentionList.value.length > 0 selectedMentionIndex.value = 0 @@ -310,7 +308,7 @@ const handlePaste = (event) => { } } -// 处理键盘事件 - 优化版本,减少不必要的日志和简化逻辑 +// 处理键盘事件 const handleKeydown = (event) => { // 处理@提及列表的键盘导航 if (showMention.value) { @@ -358,6 +356,122 @@ const handleKeydown = (event) => { return } + // 处理删除键(Backspace和Delete)删除mention元素 + if (event.key === 'Backspace' || event.key === 'Delete') { + const selection = window.getSelection() + if (!selection.rangeCount) return + + const range = selection.getRangeAt(0) + const editor = editorRef.value + + // 只处理光标位置的删除,不处理选中内容的删除 + if (range.collapsed) { + let targetMention = null + + // 获取光标位置信息 + const container = range.startContainer + const offset = range.startOffset + + if (event.key === 'Backspace') { + // Backspace:查找光标前面的mention元素 + if (container.nodeType === Node.TEXT_NODE) { + // 如果光标在文本节点的开头,检查前一个兄弟节点 + if (offset === 0) { + let prevSibling = container.previousSibling + while (prevSibling) { + if (prevSibling.nodeType === Node.ELEMENT_NODE && + prevSibling.classList && + prevSibling.classList.contains('mention')) { + targetMention = prevSibling + break + } + // 如果是文本节点且不为空,停止查找 + if (prevSibling.nodeType === Node.TEXT_NODE && prevSibling.textContent.trim()) { + break + } + prevSibling = prevSibling.previousSibling + } + } + } else if (container.nodeType === Node.ELEMENT_NODE) { + // 如果光标在元素节点中,检查前一个子节点 + if (offset > 0) { + let prevChild = container.childNodes[offset - 1] + // 如果前一个子节点是mention元素 + if (prevChild && prevChild.nodeType === Node.ELEMENT_NODE && + prevChild.classList && prevChild.classList.contains('mention')) { + targetMention = prevChild + } + // 如果前一个子节点是文本节点,检查它前面的兄弟节点 + else if (prevChild && prevChild.nodeType === Node.TEXT_NODE && !prevChild.textContent.trim()) { + let prevSibling = prevChild.previousSibling + while (prevSibling) { + if (prevSibling.nodeType === Node.ELEMENT_NODE && + prevSibling.classList && + prevSibling.classList.contains('mention')) { + targetMention = prevSibling + break + } + if (prevSibling.nodeType === Node.TEXT_NODE && prevSibling.textContent.trim()) { + break + } + prevSibling = prevSibling.previousSibling + } + } + } else if (offset === 0 && container === editor) { + // 特殊情况:光标在编辑器开头,检查第一个子节点是否是mention + const firstChild = container.firstChild + if (firstChild && firstChild.nodeType === Node.ELEMENT_NODE && + firstChild.classList && firstChild.classList.contains('mention')) { + targetMention = firstChild + } + } + } + } else if (event.key === 'Delete') { + // Delete:查找光标后面的mention元素 + if (container.nodeType === Node.TEXT_NODE) { + // 如果光标在文本节点的末尾,检查后一个兄弟节点 + if (offset === container.textContent.length) { + let nextSibling = container.nextSibling + while (nextSibling) { + if (nextSibling.nodeType === Node.ELEMENT_NODE && + nextSibling.classList && + nextSibling.classList.contains('mention')) { + targetMention = nextSibling + break + } + // 如果是文本节点且不为空,停止查找 + if (nextSibling.nodeType === Node.TEXT_NODE && nextSibling.textContent.trim()) { + break + } + nextSibling = nextSibling.nextSibling + } + } + } else if (container.nodeType === Node.ELEMENT_NODE) { + // 如果光标在元素节点中,检查后一个子节点 + if (offset < container.childNodes.length) { + const nextChild = container.childNodes[offset] + if (nextChild && nextChild.nodeType === Node.ELEMENT_NODE && + nextChild.classList && nextChild.classList.contains('mention')) { + targetMention = nextChild + } + } + } + } + + // 如果找到了要删除的mention元素 + if (targetMention) { + event.preventDefault() + + // 删除mention元素 + targetMention.remove() + + // 触发输入事件更新编辑器内容 + handleInput({ target: editor }) + return + } + } + } + // 处理Ctrl+Enter或Shift+Enter换行 if (event.key === 'Enter' && (event.ctrlKey || event.metaKey || event.shiftKey)) { // 手动插入换行符 @@ -402,7 +516,7 @@ const handleKeydown = (event) => { } } -// 发送消息 - 优化版本,移除不必要的日志,简化逻辑 +// 发送消息 const sendMessage = () => { // 解析编辑器内容 const messageData = parseEditorContent() diff --git a/src/views/message/inner/IndexContent.vue b/src/views/message/inner/IndexContent.vue index 346cb99..4c6a3ed 100644 --- a/src/views/message/inner/IndexContent.vue +++ b/src/views/message/inner/IndexContent.vue @@ -16,8 +16,6 @@ import avatarModule from '@/components/avatar-module/index.vue' const userStore = useUserStore() const dialogueStore = useDialogueStore() const uploadsStore = useUploadsStore() -console.log('dialogueStore', dialogueStore) - const members = computed(() => dialogueStore.members) const membersByAlphabet = computed(() => { if (state.searchMemberByAlphabet) {