Explorar el Código

先凑合着吧,还是不太行

CzRger hace 1 mes
padre
commit
5ffd7fc4d9
Se han modificado 1 ficheros con 101 adiciones y 3 borrados
  1. 101 3
      src/views/workflow/instance/component/params-textarea/index.vue

+ 101 - 3
src/views/workflow/instance/component/params-textarea/index.vue

@@ -223,8 +223,87 @@ const handleInput = (e) => {
     newSelection.addRange(newRange)
   }
   state.textCount = e.target.innerText?.trim().length || 0
+  isSlashBeforeCursorEnhanced()
   emitValue()
 }
+function isSlashBeforeCursorEnhanced() {
+  const selection = window.getSelection()
+  if (selection.rangeCount === 0) return false
+
+  const range = selection.getRangeAt(0)
+  let node = range.startContainer
+  let offset = range.startOffset
+
+  // 如果当前节点不是文本节点,尝试找到前一个文本节点
+  if (node.nodeType !== Node.TEXT_NODE) {
+    // 如果光标在元素开始处,需要查找前一个兄弟节点
+    if (offset === 0) {
+      let prevNode = getPreviousTextNode(node)
+      if (!prevNode) return false
+      node = prevNode
+      offset = node.textContent.length
+    } else {
+      // 光标在元素中间,需要检查子节点
+      const child = node.childNodes[offset - 1]
+      const lastTextNode = getLastTextNode(child)
+      if (!lastTextNode) return false
+      node = lastTextNode
+      offset = node.textContent.length
+    }
+  }
+
+  // 检查前一个字符是否是/
+  if (offset > 0) {
+    if (node.textContent[offset - 1] === '/') {
+      showVariablePopup(range)
+      return
+    }
+  }
+
+  // 如果当前文本节点开头,需要检查前一个文本节点
+  const prevTextNode = getPreviousTextNode(node)
+  if (prevTextNode && prevTextNode.textContent.length > 0) {
+    if (prevTextNode.textContent[prevTextNode.textContent.length - 1] === '/') {
+      showVariablePopup(range)
+      return
+    }
+  }
+
+  state.showVariableList = false
+}
+// 辅助函数:获取前一个文本节点
+function getPreviousTextNode(node) {
+  let sibling = node.previousSibling
+  while (sibling) {
+    if (
+      sibling.nodeType === Node.TEXT_NODE &&
+      sibling.textContent.trim() !== ''
+    ) {
+      return sibling
+    }
+    if (
+      sibling.nodeType === Node.ELEMENT_NODE &&
+      sibling.childNodes.length > 0
+    ) {
+      const lastChild = getLastTextNode(sibling)
+      if (lastChild) return lastChild
+    }
+    sibling = sibling.previousSibling
+  }
+  return node.parentNode ? getPreviousTextNode(node.parentNode) : null
+}
+
+// 辅助函数:获取最后一个文本节点
+function getLastTextNode(node) {
+  if (node.nodeType === Node.TEXT_NODE) return node
+  if (node.nodeType === Node.ELEMENT_NODE && node.childNodes.length > 0) {
+    for (let i = node.childNodes.length - 1; i >= 0; i--) {
+      const result = getLastTextNode(node.childNodes[i])
+      if (result) return result
+    }
+  }
+  return null
+}
 const handlePaste = (e) => {
   e.preventDefault()
   const text = (e.clipboardData || window.clipboardData).getData('text')
@@ -250,13 +329,32 @@ const initVarsDom = (vars) => {
   return dom
 }
 const setVars = (vars) => {
-  state.showVariableList = false
   const nodeToInsert: any = initVarsDom(vars)
   // 检查是否有有效的选择范围且在当前容器内
   if (state.lastSelection) {
+    if (state.showVariableList) {
+      const range = state.lastSelection.cloneRange()
+      const startContainer = range.startContainer
+      const startOffset = range.startOffset
+
+      if (startContainer.nodeType === Node.TEXT_NODE && startOffset > 0) {
+        const textBefore = startContainer.textContent.slice(0, startOffset)
+        if (textBefore.endsWith('/')) {
+          // Create a new range covering just the '/' character
+          const deleteRange = document.createRange()
+          deleteRange.setStart(startContainer, startOffset - 1)
+          deleteRange.setEnd(startContainer, startOffset)
+          deleteRange.deleteContents()
+
+          // Adjust the original selection position
+          range.setStart(startContainer, startOffset - 1)
+        }
+      }
+    }
     // 恢复选区
     const sel: any = window.getSelection()
     sel.removeAllRanges()
+    console.log(state.lastSelection)
     sel.addRange(state.lastSelection)
 
     // 插入内容
@@ -271,6 +369,8 @@ const setVars = (vars) => {
   // 可选:滚动到插入的元素
   nodeToInsert.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
   emitValue()
+  state.text = ''
+  state.showVariableList = false
 }
 const handleSelectionchange = () => {
   if (state.isFocus) {
@@ -304,14 +404,12 @@ const emitValue = () => {
 // 显示变量弹窗
 const showVariablePopup = (range) => {
   const rect = range.getBoundingClientRect()
-
   state.variableListStyle = {
     position: 'absolute',
     left: `${rect.left + window.scrollX}px`,
     top: `${rect.bottom + window.scrollY}px`,
     zIndex: 1000,
   }
-
   state.showVariableList = true
 }
 const onMouseDown = (e) => {