mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
107 lines
2.8 KiB
Vue
107 lines
2.8 KiB
Vue
<template>
|
||
<div
|
||
class="custom-textarea"
|
||
ref="textareaRef"
|
||
@focus="handleFocus"
|
||
@blur="handleBlur"
|
||
@input="handleInput()"
|
||
v-html="text"
|
||
></div>
|
||
</template>
|
||
|
||
<script lang="ts">
|
||
import { defineComponent, onUnmounted, ref, watch } from 'vue'
|
||
import { pasteCustomClipboardString, pasteExcelClipboardString } from '@/utils/clipboard'
|
||
|
||
export default defineComponent({
|
||
name: 'custom-textarea',
|
||
emits: ['updateValue', 'insertExcelData'],
|
||
props: {
|
||
value: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
contenteditable: {
|
||
type: [Boolean, String],
|
||
default: false,
|
||
},
|
||
},
|
||
setup(props, { emit }) {
|
||
const textareaRef = ref<HTMLElement>()
|
||
const text = ref('')
|
||
const isFocus = ref(false)
|
||
|
||
// 自定义v-modal,同步数据
|
||
// 当文本框聚焦时,不执行数据同步
|
||
watch(() => props.value, () => {
|
||
if (isFocus.value) return
|
||
text.value = props.value
|
||
if (textareaRef.value) textareaRef.value.innerHTML = props.value
|
||
}, { immediate: true })
|
||
|
||
const handleInput = () => {
|
||
if (!textareaRef.value) return
|
||
const text = textareaRef.value.innerHTML
|
||
emit('updateValue', text)
|
||
}
|
||
|
||
// 聚焦时更新焦点标记,并监听粘贴事件
|
||
const handleFocus = () => {
|
||
isFocus.value = true
|
||
|
||
if (!textareaRef.value) return
|
||
textareaRef.value.onpaste = (e: ClipboardEvent) => {
|
||
e.preventDefault()
|
||
if (!e.clipboardData) return
|
||
|
||
const clipboardDataFirstItem = e.clipboardData.items[0]
|
||
|
||
if (clipboardDataFirstItem && clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') {
|
||
clipboardDataFirstItem.getAsString(text => {
|
||
const clipboardData = pasteCustomClipboardString(text)
|
||
if (typeof clipboardData === 'object') return
|
||
|
||
const excelData = pasteExcelClipboardString(text)
|
||
if (excelData) {
|
||
emit('insertExcelData', excelData)
|
||
if (textareaRef.value) textareaRef.value.innerHTML = excelData[0][0]
|
||
return
|
||
}
|
||
|
||
emit('updateValue', text)
|
||
document.execCommand('insertText', false, text)
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
// 失焦时更新焦点标记,清除粘贴事件监听
|
||
const handleBlur = () => {
|
||
isFocus.value = false
|
||
if (textareaRef.value) textareaRef.value.onpaste = null
|
||
}
|
||
|
||
// 清除粘贴事件监听
|
||
onUnmounted(() => {
|
||
if (textareaRef.value) textareaRef.value.onpaste = null
|
||
})
|
||
|
||
return {
|
||
textareaRef,
|
||
handleFocus,
|
||
handleInput,
|
||
handleBlur,
|
||
text,
|
||
}
|
||
},
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.custom-textarea {
|
||
border: 0;
|
||
outline: 0;
|
||
-webkit-user-modify: read-write-plaintext-only;
|
||
-moz-user-modify: read-write-plaintext-only;
|
||
}
|
||
</style> |