fix: 问题7修复
This commit is contained in:
parent
6037bae970
commit
9250253238
|
|
@ -28,6 +28,7 @@
|
||||||
@keyup="handleKeyup"
|
@keyup="handleKeyup"
|
||||||
@click="handleEditorClick"
|
@click="handleEditorClick"
|
||||||
@keydown="handleKeydown"
|
@keydown="handleKeydown"
|
||||||
|
@paste="handlePaste"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<!-- @ 图片选择面板 -->
|
<!-- @ 图片选择面板 -->
|
||||||
|
|
@ -187,6 +188,64 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const insertPlainTextAtCursor = (text) => {
|
||||||
|
if (!editorRef.value || text == null) return
|
||||||
|
const normalized = String(text).replace(/\r\n/g, '\n').replace(/\r/g, '\n')
|
||||||
|
editorRef.value.focus()
|
||||||
|
const selection = window.getSelection()
|
||||||
|
if (!selection || selection.rangeCount === 0) return
|
||||||
|
let range = selection.getRangeAt(0)
|
||||||
|
if (!editorRef.value.contains(range.commonAncestorContainer)) {
|
||||||
|
const r = document.createRange()
|
||||||
|
r.selectNodeContents(editorRef.value)
|
||||||
|
r.collapse(false)
|
||||||
|
selection.removeAllRanges()
|
||||||
|
selection.addRange(r)
|
||||||
|
range = selection.getRangeAt(0)
|
||||||
|
}
|
||||||
|
range.deleteContents()
|
||||||
|
const lines = normalized.split('\n')
|
||||||
|
const fragment = document.createDocumentFragment()
|
||||||
|
lines.forEach((line, index) => {
|
||||||
|
if (line) fragment.appendChild(document.createTextNode(line))
|
||||||
|
if (index < lines.length - 1) fragment.appendChild(document.createElement('br'))
|
||||||
|
})
|
||||||
|
range.insertNode(fragment)
|
||||||
|
range.collapse(false)
|
||||||
|
selection.removeAllRanges()
|
||||||
|
selection.addRange(range)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePaste = (e) => {
|
||||||
|
if (!editorRef.value) return
|
||||||
|
const cd = e.clipboardData
|
||||||
|
if (!cd) return
|
||||||
|
const items = cd.items
|
||||||
|
if (items) {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].type.indexOf('image') !== -1) {
|
||||||
|
const blob = items[i].getAsFile()
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = (event) => {
|
||||||
|
insertImage(event.target.result, 'pasted-image')
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(blob)
|
||||||
|
e.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let text = cd.getData('text/plain') || ''
|
||||||
|
if (!text && cd.getData('text/html')) {
|
||||||
|
const tmp = document.createElement('div')
|
||||||
|
tmp.innerHTML = cd.getData('text/html')
|
||||||
|
text = tmp.innerText || ''
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
insertPlainTextAtCursor(text)
|
||||||
|
handleInput()
|
||||||
|
}
|
||||||
|
|
||||||
// 显示 @ 面板
|
// 显示 @ 面板
|
||||||
const showMentionPanel = () => {
|
const showMentionPanel = () => {
|
||||||
if (props.uploadedImages && props.uploadedImages.length > 0) {
|
if (props.uploadedImages && props.uploadedImages.length > 0) {
|
||||||
|
|
@ -261,23 +320,6 @@ export default {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (editorRef.value) {
|
if (editorRef.value) {
|
||||||
editorRef.value.innerHTML = props.modelValue || ''
|
editorRef.value.innerHTML = props.modelValue || ''
|
||||||
|
|
||||||
// 添加粘贴事件处理
|
|
||||||
editorRef.value.addEventListener('paste', (e) => {
|
|
||||||
const items = e.clipboardData.items
|
|
||||||
for (let i = 0; i < items.length; i++) {
|
|
||||||
if (items[i].type.indexOf('image') !== -1) {
|
|
||||||
const blob = items[i].getAsFile()
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload = (event) => {
|
|
||||||
insertImage(event.target.result, 'pasted-image')
|
|
||||||
}
|
|
||||||
reader.readAsDataURL(blob)
|
|
||||||
e.preventDefault()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -292,6 +334,7 @@ export default {
|
||||||
handleInput,
|
handleInput,
|
||||||
handleKeyup,
|
handleKeyup,
|
||||||
handleKeydown,
|
handleKeydown,
|
||||||
|
handlePaste,
|
||||||
handleEditorClick,
|
handleEditorClick,
|
||||||
insertMentionImage,
|
insertMentionImage,
|
||||||
clear
|
clear
|
||||||
|
|
@ -342,6 +385,11 @@ export default {
|
||||||
outline: none;
|
outline: none;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
|
/* 覆盖粘贴残留的内联颜色,保证深底上始终可读 */
|
||||||
|
:deep(*) {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
&:empty:before {
|
&:empty:before {
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
color: #666;
|
color: #666;
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,7 @@
|
||||||
contenteditable="true"
|
contenteditable="true"
|
||||||
:data-placeholder="placeholder"
|
:data-placeholder="placeholder"
|
||||||
@input="onEditorInput"
|
@input="onEditorInput"
|
||||||
|
@paste="onEditorPaste"
|
||||||
@keydown="onEditorKeydown"
|
@keydown="onEditorKeydown"
|
||||||
@keyup="onEditorKeyup"
|
@keyup="onEditorKeyup"
|
||||||
@click="onEditorClick"></div>
|
@click="onEditorClick"></div>
|
||||||
|
|
@ -857,6 +858,64 @@ const restoreSelection = () => {
|
||||||
selection.addRange(range)
|
selection.addRange(range)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const insertPlainTextInEditor = (text) => {
|
||||||
|
if (!editorRef.value) return
|
||||||
|
const normalizedText = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
|
||||||
|
editorRef.value.focus()
|
||||||
|
restoreSelection()
|
||||||
|
const selection = window.getSelection()
|
||||||
|
if (!selection || selection.rangeCount === 0) return
|
||||||
|
let range = selection.getRangeAt(0)
|
||||||
|
if (!editorRef.value.contains(range.commonAncestorContainer)) {
|
||||||
|
const r = document.createRange()
|
||||||
|
r.selectNodeContents(editorRef.value)
|
||||||
|
r.collapse(false)
|
||||||
|
selection.removeAllRanges()
|
||||||
|
selection.addRange(r)
|
||||||
|
range = selection.getRangeAt(0)
|
||||||
|
}
|
||||||
|
range.deleteContents()
|
||||||
|
const lines = normalizedText.split('\n')
|
||||||
|
const fragment = document.createDocumentFragment()
|
||||||
|
lines.forEach((line, index) => {
|
||||||
|
if (line) fragment.appendChild(document.createTextNode(line))
|
||||||
|
if (index < lines.length - 1) fragment.appendChild(document.createElement('br'))
|
||||||
|
})
|
||||||
|
range.insertNode(fragment)
|
||||||
|
range.collapse(false)
|
||||||
|
selection.removeAllRanges()
|
||||||
|
selection.addRange(range)
|
||||||
|
saveSelection()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEditorPaste = (e) => {
|
||||||
|
if (!editorRef.value) return
|
||||||
|
const cd = e.clipboardData
|
||||||
|
if (!cd) return
|
||||||
|
const items = cd.items
|
||||||
|
if (items) {
|
||||||
|
for (const item of items) {
|
||||||
|
if (item.kind === 'file' && item.type && item.type.startsWith('image/')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let text = cd.getData('text/plain') || ''
|
||||||
|
if (!text) {
|
||||||
|
const html = cd.getData('text/html')
|
||||||
|
if (html) {
|
||||||
|
const tmp = document.createElement('div')
|
||||||
|
tmp.innerHTML = html
|
||||||
|
text = tmp.innerText || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!text) return
|
||||||
|
e.preventDefault()
|
||||||
|
insertPlainTextInEditor(text)
|
||||||
|
setPrompt(getEditorPlainText())
|
||||||
|
saveSelection()
|
||||||
|
}
|
||||||
|
|
||||||
const hasActiveMentionTrigger = () => {
|
const hasActiveMentionTrigger = () => {
|
||||||
const selection = window.getSelection()
|
const selection = window.getSelection()
|
||||||
if (!selection || selection.rangeCount === 0) return false
|
if (!selection || selection.rangeCount === 0) return false
|
||||||
|
|
@ -2196,6 +2255,16 @@ defineExpose({
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
scrollbar-color: rgba(255, 255, 255, 0.22) rgba(255, 255, 255, 0.06);
|
scrollbar-color: rgba(255, 255, 255, 0.22) rgba(255, 255, 255, 0.06);
|
||||||
|
color: rgba(255, 255, 255, 0.92);
|
||||||
|
|
||||||
|
:deep(*) {
|
||||||
|
color: rgba(255, 255, 255, 0.92) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.vg-inline-ref-audio) {
|
||||||
|
color: rgba(255, 255, 255, 0.88) !important;
|
||||||
|
background: rgba(0, 202, 224, 0.12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vg-rich-editor:empty:before {
|
.vg-rich-editor:empty:before {
|
||||||
|
|
|
||||||
|
|
@ -496,6 +496,15 @@ onMounted(() => {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
caret-color: #00cae0;
|
caret-color: #00cae0;
|
||||||
|
|
||||||
|
:deep(*) {
|
||||||
|
color: rgba(255, 255, 255, 0.9) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.inline-rich-reference) {
|
||||||
|
color: #5eebf5 !important;
|
||||||
|
background: rgba(0, 202, 224, 0.15);
|
||||||
|
}
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
padding: 16px 18px;
|
padding: 16px 18px;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue