|
@@ -24,12 +24,15 @@
|
|
|
</div>
|
|
|
<div class="text-text-secondary flex-1 overflow-y-auto py-1 text-[13px]">
|
|
|
<div
|
|
|
+ id="textarea"
|
|
|
class="break-all"
|
|
|
style="line-height: 1.5"
|
|
|
ref="ref_textarea"
|
|
|
contenteditable="true"
|
|
|
@input="updateMarkdown"
|
|
|
@paste="handlePaste"
|
|
|
+ @focus="state.isFocus = true"
|
|
|
+ @blur="state.isFocus = false"
|
|
|
></div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -45,6 +48,8 @@ import {
|
|
|
render,
|
|
|
createApp,
|
|
|
watch,
|
|
|
+ nextTick,
|
|
|
+ onUnmounted,
|
|
|
} from 'vue'
|
|
|
import { copy } from '@/utils/czr-util'
|
|
|
import { ElMessage } from 'element-plus'
|
|
@@ -65,6 +70,8 @@ const props = defineProps({
|
|
|
const state = reactive({
|
|
|
textCount: 0,
|
|
|
optionsMap: new Map(),
|
|
|
+ lastSelection: null,
|
|
|
+ isFocus: false,
|
|
|
})
|
|
|
const ref_textarea = ref()
|
|
|
watch(
|
|
@@ -153,39 +160,41 @@ const initVarsDom = (vars) => {
|
|
|
return dom
|
|
|
}
|
|
|
const setVars = (vars) => {
|
|
|
- onCopy(`{{#${vars.nodeId}_${vars.key}#}}`)
|
|
|
- const selection: any = window.getSelection()
|
|
|
+ // onCopy(`{{#${vars.nodeId}_${vars.key}#}}`)
|
|
|
const nodeToInsert: any = initVarsDom(vars)
|
|
|
-
|
|
|
// 检查是否有有效的选择范围且在当前容器内
|
|
|
- if (selection.rangeCount > 0) {
|
|
|
- const range = selection.getRangeAt(0)
|
|
|
- const isInsideContainer = ref_textarea.value.contains(
|
|
|
- range.commonAncestorContainer,
|
|
|
- )
|
|
|
-
|
|
|
- if (isInsideContainer) {
|
|
|
- // 在光标处插入
|
|
|
- range.deleteContents()
|
|
|
- range.insertNode(nodeToInsert)
|
|
|
-
|
|
|
- // 移动光标到插入节点之后
|
|
|
- const newRange = document.createRange()
|
|
|
- newRange.setStartAfter(nodeToInsert)
|
|
|
- newRange.collapse(true)
|
|
|
- selection.removeAllRanges()
|
|
|
- selection.addRange(newRange)
|
|
|
- return
|
|
|
- }
|
|
|
+ if (state.lastSelection) {
|
|
|
+ // 恢复选区
|
|
|
+ const sel: any = window.getSelection()
|
|
|
+ sel.removeAllRanges()
|
|
|
+ sel.addRange(state.lastSelection)
|
|
|
+
|
|
|
+ // 插入内容
|
|
|
+ state.lastSelection.deleteContents()
|
|
|
+ state.lastSelection.insertNode(nodeToInsert)
|
|
|
+ state.lastSelection.setStartAfter(state.lastSelection.endContainer)
|
|
|
+ state.lastSelection.collapse(true)
|
|
|
+ state.lastSelection = null
|
|
|
+ } else {
|
|
|
+ ref_textarea.value.appendChild(nodeToInsert)
|
|
|
}
|
|
|
-
|
|
|
- // 没有有效光标或在容器外,则在末尾插入
|
|
|
- ref_textarea.value.appendChild(nodeToInsert)
|
|
|
-
|
|
|
// 可选:滚动到插入的元素
|
|
|
nodeToInsert.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
|
|
|
}
|
|
|
-onMounted(() => {})
|
|
|
+const handleSelectionchange = () => {
|
|
|
+ if (state.isFocus) {
|
|
|
+ const sel: any = window.getSelection()
|
|
|
+ if (sel.rangeCount > 0) {
|
|
|
+ state.lastSelection = sel.getRangeAt(0).cloneRange()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+onMounted(() => {
|
|
|
+ document.addEventListener('selectionchange', handleSelectionchange)
|
|
|
+})
|
|
|
+onUnmounted(() => {
|
|
|
+ document.removeEventListener('selectionchange', handleSelectionchange)
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss"></style>
|