Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions ui/src/components/ai-chat/component/control/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,41 @@ import { ref, nextTick, onMounted } from 'vue'
import { t } from '@/locales'
const isOpen = ref<boolean>(false)
const eventVal = ref<any>({})

function getSelection() {
const selection = window.getSelection()
if (selection && selection.anchorNode == null) {
return null
if (selection) {
if (selection.rangeCount === 0) return undefined
const range = selection.getRangeAt(0)
const fragment = range.cloneContents() // 克隆选区内容
const div = document.createElement('div')
div.appendChild(fragment)
if (div.textContent) {
return div.textContent.trim()
}
}
const text = selection?.anchorNode?.textContent
return text && text.substring(selection.anchorOffset, selection.focusOffset)
return undefined
}

/**
* 打开控制台
* @param event
*/
const openControl = (event: any) => {
const c = getSelection()
isOpen.value = false
if (c) {
nextTick(() => {
eventVal.value = event
isOpen.value = true
})
if (!isOpen.value) {
nextTick(() => {
eventVal.value = event
isOpen.value = true
})
} else {
clearSelectedText()
isOpen.value = false
}
event.preventDefault()
} else {
isOpen.value = false
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The provided code has several improvements to address potential issues and enhance its functionality:

  1. Use of ref correctly: Ensure that the properties accessed using ref are properly used within templates or computed functions.

  2. Return value handling in getSelection():

    • The original logic returns null when there is no anchor node, which should be handled separately before accessing .textContent.
    • Returning an empty string instead of null improves behavior with whitespace.
  3. Conditional opening logic:

    • Added a check to see if isOpen.value is already true before attempting another open operation. This prevents redundant clear operations and ensures only one panel is open at a time.
  4. Clearing selected text function:

    • Define a helper function named clearSelectedText(). If you plan on clearing selected text elsewhere, this makes it reusable.

Here's the corrected and optimized version of the code:

import { ref, nextTick, onMounted } from 'vue'
import { t } from '@/locales'

const isOpen = ref(false);
const eventVal = ref<any>({});

function getSelection(): string | undefined {
  const selection = window.getSelection();
  if (selection) {
    if (selection.rangeCount === 0) return undefined;
    const range = selection.getRangeAt(0);
    const fragment = range.cloneContents(); // 复制选区内容
    const div = document.createElement('div');
    div.appendChild(fragment);
    
    const content = div.textContent;
    
    return content ? content.trim() : undefined; 
  }
}

/**
  * 打开控制台
  * @param event
  */
const openControl = (event: any): void => {
  const c = getSelection();
  
  if (c) {
    if (!isOpen.value) {
      clearSelectedText();

      nextTick(() => {
        eventVal.value = event;
        isOpen.value = true;
      });
      
    } else {
      // If open and not clicked again, just clear the selection.
      clearSelectedText();
      isOpen.value = false;
    }
    event.preventDefault();
  }

};

// Helper Function to Clear Selected Text
const clearSelectedText = () => {
  var sel = window.getSelection();
  if (sel && !sel.isCollapsed) {
    sel.removeAllRanges();
  }
};

onMounted(() => {});

Key changes included checking for an empty string in getSelection, simplifying conditional checks, and introducing a utility function to handle clearing selections.

Expand Down