fix
This commit is contained in:
@@ -22,7 +22,7 @@ const data = reactive({
|
|||||||
// { id: '3', type: 'text', value: '333333' },
|
// { id: '3', type: 'text', value: '333333' },
|
||||||
// { id: '4', type: 'input', value: '', placeholder: '[请输入内容]' }
|
// { id: '4', type: 'input', value: '', placeholder: '[请输入内容]' }
|
||||||
// ] as ContentItem[]
|
// ] as ContentItem[]
|
||||||
content: props.content
|
content: [ { id: '1', type: 'text', value: '' },],
|
||||||
})
|
})
|
||||||
|
|
||||||
const editableArea = ref<HTMLElement>()
|
const editableArea = ref<HTMLElement>()
|
||||||
@@ -40,9 +40,9 @@ const compositionState = reactive({
|
|||||||
|
|
||||||
// 检查并删除末尾的空文本框
|
// 检查并删除末尾的空文本框
|
||||||
const removeLastEmptyTextIfNeeded = () => {
|
const removeLastEmptyTextIfNeeded = () => {
|
||||||
const lastItem = content.value[content.value.length - 1]
|
const lastItem = data.content[data.content.length - 1]
|
||||||
if (lastItem && lastItem.type === 'text' && lastItem.value === '') {
|
if (lastItem && lastItem.type === 'text' && lastItem.value === '') {
|
||||||
content.value.pop()
|
data.content.pop()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -50,14 +50,14 @@ const removeLastEmptyTextIfNeeded = () => {
|
|||||||
|
|
||||||
// 确保末尾有空文本框
|
// 确保末尾有空文本框
|
||||||
const ensureEmptyTextAtEnd = () => {
|
const ensureEmptyTextAtEnd = () => {
|
||||||
const lastItem = content.value[content.value.length - 1]
|
const lastItem = data.content[data.content.length - 1]
|
||||||
if (!lastItem || lastItem.type !== 'text' || lastItem.value !== '') {
|
if (!lastItem || lastItem.type !== 'text' || lastItem.value !== '') {
|
||||||
const newItem: ContentItem = {
|
const newItem: ContentItem = {
|
||||||
id: Date.now().toString(),
|
id: Date.now().toString(),
|
||||||
type: 'text',
|
type: 'text',
|
||||||
value: ''
|
value: ''
|
||||||
}
|
}
|
||||||
content.value.push(newItem)
|
data.content.push(newItem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -96,7 +96,7 @@ const getCurrentElementInfo = () => {
|
|||||||
index = parseInt(parent?.getAttribute('data-index') || '-1')
|
index = parseInt(parent?.getAttribute('data-index') || '-1')
|
||||||
type = 'input'
|
type = 'input'
|
||||||
|
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
if (element.classList.contains('has-placeholder')) {
|
if (element.classList.contains('has-placeholder')) {
|
||||||
// placeholder状态下,光标在任意位置都认为是"在元素内"
|
// placeholder状态下,光标在任意位置都认为是"在元素内"
|
||||||
isAtStart = range.startOffset === 0
|
isAtStart = range.startOffset === 0
|
||||||
@@ -172,10 +172,10 @@ const handleKeydown = (event: KeyboardEvent) => {
|
|||||||
break
|
break
|
||||||
|
|
||||||
case 'ArrowRight':
|
case 'ArrowRight':
|
||||||
if (isAtEnd && index < content.value.length - 1) {
|
if (isAtEnd && index < data.content.length - 1) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
navigateToElement(index + 1, 'start')
|
navigateToElement(index + 1, 'start')
|
||||||
} else if (isAtEnd && index === content.value.length - 1) {
|
} else if (isAtEnd && index === data.content.length - 1) {
|
||||||
// 在最后一个元素末尾按右箭头,确保有一个空文本框
|
// 在最后一个元素末尾按右箭头,确保有一个空文本框
|
||||||
ensureEmptyTextAtEnd()
|
ensureEmptyTextAtEnd()
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -189,26 +189,26 @@ const handleKeydown = (event: KeyboardEvent) => {
|
|||||||
// 跨元素删除逻辑
|
// 跨元素删除逻辑
|
||||||
const handleCrossElementDelete = (currentIndex: number) => {
|
const handleCrossElementDelete = (currentIndex: number) => {
|
||||||
const prevIndex = currentIndex - 1
|
const prevIndex = currentIndex - 1
|
||||||
const prevItem = content.value[prevIndex]
|
const prevItem = data.content[prevIndex]
|
||||||
|
|
||||||
if (prevItem.type === 'input') {
|
if (prevItem.type === 'input') {
|
||||||
if (prevItem.value.trim() === '') {
|
if (prevItem.value.trim() === '') {
|
||||||
// 删除空输入框
|
// 删除空输入框
|
||||||
content.value.splice(prevIndex, 1)
|
data.content.splice(prevIndex, 1)
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 删除输入框后,先删除末尾的空文本框
|
// 删除输入框后,先删除末尾的空文本框
|
||||||
removeLastEmptyTextIfNeeded()
|
removeLastEmptyTextIfNeeded()
|
||||||
// 然后聚焦到正确的位置
|
// 然后聚焦到正确的位置
|
||||||
if (prevIndex < content.value.length) {
|
if (prevIndex < data.content.length) {
|
||||||
focusElement(prevIndex, 'end')
|
focusElement(prevIndex, 'end')
|
||||||
} else if (content.value.length > 0) {
|
} else if (data.content.length > 0) {
|
||||||
focusElement(content.value.length - 1, 'end')
|
focusElement(data.content.length - 1, 'end')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 删除输入框最后一个字符,但保留输入框
|
// 删除输入框最后一个字符,但保留输入框
|
||||||
const newValue = prevItem.value.slice(0, -1)
|
const newValue = prevItem.value.slice(0, -1)
|
||||||
content.value[prevIndex].value = newValue
|
data.content[prevIndex].value = newValue
|
||||||
updateInputDisplay(prevIndex)
|
updateInputDisplay(prevIndex)
|
||||||
nextTick(() => focusElement(prevIndex, 'end'))
|
nextTick(() => focusElement(prevIndex, 'end'))
|
||||||
}
|
}
|
||||||
@@ -222,7 +222,7 @@ const handleCrossElementDelete = (currentIndex: number) => {
|
|||||||
|
|
||||||
// 导航到元素
|
// 导航到元素
|
||||||
const navigateToElement = (targetIndex: number, position: 'start' | 'end') => {
|
const navigateToElement = (targetIndex: number, position: 'start' | 'end') => {
|
||||||
const targetItem = content.value[targetIndex]
|
const targetItem = data.content[targetIndex]
|
||||||
const element =
|
const element =
|
||||||
targetItem.type === 'text'
|
targetItem.type === 'text'
|
||||||
? (editableArea.value?.querySelector(
|
? (editableArea.value?.querySelector(
|
||||||
@@ -237,7 +237,7 @@ const navigateToElement = (targetIndex: number, position: 'start' | 'end') => {
|
|||||||
|
|
||||||
// 焦点设置
|
// 焦点设置
|
||||||
const focusElement = (index: number, position: 'start' | 'end') => {
|
const focusElement = (index: number, position: 'start' | 'end') => {
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
const element =
|
const element =
|
||||||
item.type === 'text'
|
item.type === 'text'
|
||||||
? (editableArea.value?.querySelector(
|
? (editableArea.value?.querySelector(
|
||||||
@@ -252,7 +252,7 @@ const focusElement = (index: number, position: 'start' | 'end') => {
|
|||||||
|
|
||||||
// 输入框显示管理
|
// 输入框显示管理
|
||||||
const updateInputDisplay = (index: number) => {
|
const updateInputDisplay = (index: number) => {
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
if (item.type !== 'input') return
|
if (item.type !== 'input') return
|
||||||
|
|
||||||
const inputElement = editableArea.value?.querySelector(
|
const inputElement = editableArea.value?.querySelector(
|
||||||
@@ -279,13 +279,13 @@ const handleInputChange = (index: number, event: Event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const target = event.target as HTMLSpanElement
|
const target = event.target as HTMLSpanElement
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
|
|
||||||
// 如果当前显示placeholder,但内容已改变(比如通过粘贴),清除placeholder
|
// 如果当前显示placeholder,但内容已改变(比如通过粘贴),清除placeholder
|
||||||
if (target.classList.contains('has-placeholder') && target.textContent !== item.placeholder) {
|
if (target.classList.contains('has-placeholder') && target.textContent !== item.placeholder) {
|
||||||
target.classList.remove('has-placeholder')
|
target.classList.remove('has-placeholder')
|
||||||
const newValue = target.textContent || ''
|
const newValue = target.textContent || ''
|
||||||
content.value[index].value = newValue
|
data.content[index].value = newValue
|
||||||
|
|
||||||
// 如果粘贴后内容为空,重新显示 placeholder
|
// 如果粘贴后内容为空,重新显示 placeholder
|
||||||
if (newValue.trim() === '' && item.placeholder) {
|
if (newValue.trim() === '' && item.placeholder) {
|
||||||
@@ -298,7 +298,7 @@ const handleInputChange = (index: number, event: Event) => {
|
|||||||
// 正常情况下的处理
|
// 正常情况下的处理
|
||||||
if (!target.classList.contains('has-placeholder')) {
|
if (!target.classList.contains('has-placeholder')) {
|
||||||
const newValue = target.textContent || ''
|
const newValue = target.textContent || ''
|
||||||
content.value[index].value = newValue
|
data.content[index].value = newValue
|
||||||
|
|
||||||
// 如果内容变空,显示placeholder
|
// 如果内容变空,显示placeholder
|
||||||
if (newValue.trim() === '' && item.placeholder) {
|
if (newValue.trim() === '' && item.placeholder) {
|
||||||
@@ -311,7 +311,7 @@ const handleInputChange = (index: number, event: Event) => {
|
|||||||
// 添加专门的粘贴事件处理
|
// 添加专门的粘贴事件处理
|
||||||
const handleInputPaste = (event: ClipboardEvent, index: number) => {
|
const handleInputPaste = (event: ClipboardEvent, index: number) => {
|
||||||
const target = event.target as HTMLSpanElement
|
const target = event.target as HTMLSpanElement
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
|
|
||||||
// 如果当前显示 placeholder,先清除它
|
// 如果当前显示 placeholder,先清除它
|
||||||
if (target.classList.contains('has-placeholder')) {
|
if (target.classList.contains('has-placeholder')) {
|
||||||
@@ -325,7 +325,7 @@ const handleInputPaste = (event: ClipboardEvent, index: number) => {
|
|||||||
|
|
||||||
// 更新值
|
// 更新值
|
||||||
const newValue = target.textContent || ''
|
const newValue = target.textContent || ''
|
||||||
content.value[index].value = newValue
|
data.content[index].value = newValue
|
||||||
|
|
||||||
// 如果粘贴后内容为空,重新显示 placeholder
|
// 如果粘贴后内容为空,重新显示 placeholder
|
||||||
if (newValue.trim() === '' && item.placeholder) {
|
if (newValue.trim() === '' && item.placeholder) {
|
||||||
@@ -362,7 +362,7 @@ const handleInputKeydown = (event: KeyboardEvent, index: number) => {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
target.textContent = event.key
|
target.textContent = event.key
|
||||||
target.classList.remove('has-placeholder')
|
target.classList.remove('has-placeholder')
|
||||||
content.value[index].value = event.key
|
data.content[index].value = event.key
|
||||||
|
|
||||||
// 移动光标到末尾
|
// 移动光标到末尾
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -380,14 +380,14 @@ const handleInputKeydown = (event: KeyboardEvent, index: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handlePasteInInput = (index: number, element: HTMLElement) => {
|
const handlePasteInInput = (index: number, element: HTMLElement) => {
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
|
|
||||||
// 如果当前显示 placeholder,清除它
|
// 如果当前显示 placeholder,清除它
|
||||||
if (element.classList.contains('has-placeholder')) {
|
if (element.classList.contains('has-placeholder')) {
|
||||||
element.classList.remove('has-placeholder')
|
element.classList.remove('has-placeholder')
|
||||||
// 获取粘贴后的实际内容
|
// 获取粘贴后的实际内容
|
||||||
const newValue = element.textContent || ''
|
const newValue = element.textContent || ''
|
||||||
content.value[index].value = newValue
|
data.content[index].value = newValue
|
||||||
|
|
||||||
// 如果粘贴后内容为空,重新显示 placeholder
|
// 如果粘贴后内容为空,重新显示 placeholder
|
||||||
if (newValue.trim() === '' && item.placeholder) {
|
if (newValue.trim() === '' && item.placeholder) {
|
||||||
@@ -397,7 +397,7 @@ const handlePasteInInput = (index: number, element: HTMLElement) => {
|
|||||||
} else {
|
} else {
|
||||||
// 正常情况,直接更新值
|
// 正常情况,直接更新值
|
||||||
const newValue = element.textContent || ''
|
const newValue = element.textContent || ''
|
||||||
content.value[index].value = newValue
|
data.content[index].value = newValue
|
||||||
|
|
||||||
// 检查是否需要显示 placeholder
|
// 检查是否需要显示 placeholder
|
||||||
if (newValue.trim() === '' && item.placeholder) {
|
if (newValue.trim() === '' && item.placeholder) {
|
||||||
@@ -417,7 +417,7 @@ const handleCompositionStart = (index: number, event: CompositionEvent) => {
|
|||||||
if (target.classList.contains('has-placeholder')) {
|
if (target.classList.contains('has-placeholder')) {
|
||||||
target.classList.remove('has-placeholder')
|
target.classList.remove('has-placeholder')
|
||||||
target.textContent = ''
|
target.textContent = ''
|
||||||
content.value[index].value = ''
|
data.content[index].value = ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,10 +427,10 @@ const handleCompositionEnd = (index: number, event: CompositionEvent) => {
|
|||||||
|
|
||||||
const target = event.target as HTMLSpanElement
|
const target = event.target as HTMLSpanElement
|
||||||
const newValue = target.textContent || ''
|
const newValue = target.textContent || ''
|
||||||
content.value[index].value = newValue
|
data.content[index].value = newValue
|
||||||
|
|
||||||
// 如果中文输入后内容为空,显示placeholder
|
// 如果中文输入后内容为空,显示placeholder
|
||||||
const item = content.value[index]
|
const item = data.content[index]
|
||||||
if (newValue.trim() === '' && item.placeholder) {
|
if (newValue.trim() === '' && item.placeholder) {
|
||||||
target.classList.add('has-placeholder')
|
target.classList.add('has-placeholder')
|
||||||
target.textContent = item.placeholder
|
target.textContent = item.placeholder
|
||||||
@@ -454,7 +454,7 @@ const handleContainerClick = (event: MouseEvent) => {
|
|||||||
// 确保末尾有空文本框并聚焦到它
|
// 确保末尾有空文本框并聚焦到它
|
||||||
ensureEmptyTextAtEnd()
|
ensureEmptyTextAtEnd()
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
focusElement(content.value.length - 1, 'start')
|
focusElement(data.content.length - 1, 'start')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,7 +462,7 @@ const handleContainerClick = (event: MouseEvent) => {
|
|||||||
// 初始化
|
// 初始化
|
||||||
const initPlaceholders = () => {
|
const initPlaceholders = () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
content.value.forEach((_, index) => updateInputDisplay(index))
|
data.content.forEach((_, index) => updateInputDisplay(index))
|
||||||
// 确保初始状态下有一个空文本框
|
// 确保初始状态下有一个空文本框
|
||||||
ensureEmptyTextAtEnd()
|
ensureEmptyTextAtEnd()
|
||||||
})
|
})
|
||||||
@@ -470,7 +470,7 @@ const initPlaceholders = () => {
|
|||||||
|
|
||||||
const getFullText = () => {
|
const getFullText = () => {
|
||||||
if (assistModel.value) {
|
if (assistModel.value) {
|
||||||
return content.value
|
return data.content
|
||||||
.map(item => {
|
.map(item => {
|
||||||
if (item.type === 'text') {
|
if (item.type === 'text') {
|
||||||
return item.value
|
return item.value
|
||||||
@@ -498,12 +498,15 @@ const textareaValue = ref('')
|
|||||||
const assistModel = ref(false)
|
const assistModel = ref(false)
|
||||||
const handleClickAssistBtn = () => {
|
const handleClickAssistBtn = () => {
|
||||||
assistModel.value = !assistModel.value
|
assistModel.value = !assistModel.value
|
||||||
|
if(assistModel.value){
|
||||||
|
data.content = JSON.parse(JSON.stringify(props.content))
|
||||||
|
initPlaceholders()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const textareaRef = useTemplateRef<HTMLTextAreaElement>('textareaRef')
|
const textareaRef = useTemplateRef<HTMLTextAreaElement>('textareaRef')
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initPlaceholders()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
@@ -533,7 +536,7 @@ defineExpose({
|
|||||||
@click="handleContainerClick"
|
@click="handleContainerClick"
|
||||||
>
|
>
|
||||||
<div class="promptinput-wrapper">
|
<div class="promptinput-wrapper">
|
||||||
<template v-for="(item, index) in content" :key="item.id">
|
<template v-for="(item, index) in data.content" :key="item.id">
|
||||||
<span
|
<span
|
||||||
v-if="item.type === 'text'"
|
v-if="item.type === 'text'"
|
||||||
class="text-field"
|
class="text-field"
|
||||||
|
|||||||
Reference in New Issue
Block a user