@@ -1,507 +1,518 @@
< script setup lang = "ts" >
import { ref , onMounted , reactive , toRefs , nextTick , useTemplateRef , watch } from " vue" ;
import { ref , onMounted , reactive , toRefs , nextTick , useTemplateRef } from ' vue'
interface ContentItem {
id : string ;
type : 'text' | 'input' ;
value : string ;
placeholder ? : string ;
id : string
type : 'text' | 'input'
value : string
placeholder ? : string
}
const props = defineProps ( {
content : {
type : Array ,
default : ( ) => [ ]
}
content : {
type : Array ,
default : ( ) => [ ]
}
} )
const data = reactive ( {
// content: [
// { id: '1', type: 'text', value: '11111' },
// { id: '2', type: 'input', value: '222', placeholder: '[请输入内容]' },
// { id: '3', type: 'text', value: '333333' },
// { id: '4', type: 'input', value: '', placeholder: '[请输入内容]' }
// ] as ContentItem[]
content : props . content
// content: [
// { id: '1', type: 'text', value: '11111' },
// { id: '2', type: 'input', value: '222', placeholder: '[请输入内容]' },
// { id: '3', type: 'text', value: '333333' },
// { id: '4', type: 'input', value: '', placeholder: '[请输入内容]' }
// ] as ContentItem[]
content : props . content
} )
const editableArea = ref < HTMLElement > ( )
const { content } = toRefs ( data )
const cursorState = ref ( {
isContainerClick : false
isContainerClick : false
} )
// 检查并删除末尾的空文本框
const removeLastEmptyTextIfNeeded = ( ) => {
const lastItem = content . value [ content . value . length - 1 ]
if ( lastItem && lastItem . type === 'text' && lastItem . value === '' ) {
content . value . pop ( )
return true
}
return false
const lastItem = content . value [ content . value . length - 1 ]
if ( lastItem && lastItem . type === 'text' && lastItem . value === '' ) {
content . value . pop ( )
return true
}
return false
}
// 确保末尾有空文本框
const ensureEmptyTextAtEnd = ( ) => {
const lastItem = content . value [ content . value . length - 1 ]
if ( ! lastItem || lastItem . type !== 'text' || lastItem . value !== '' ) {
const newItem : ContentItem = {
id : Date . now ( ) . toString ( ) ,
type : 'text' ,
value : ''
}
content . value . push ( newItem )
return true
}
return false
const lastItem = content . value [ content . value . length - 1 ]
if ( ! lastItem || lastItem . type !== 'text' || lastItem . value !== '' ) {
const newItem : ContentItem = {
id : Date . now ( ) . toString ( ) ,
type : 'text' ,
value : ''
}
content . value . push ( newItem )
return true
}
return false
}
// 元素信息获取
const getCurrentElementInfo = ( ) => {
const selection = window . getSelection ( )
if ( ! selection || selection . rangeCount === 0 ) return null
const selection = window . getSelection ( )
if ( ! selection || selection . rangeCount === 0 ) return null
const range = selection . getRangeAt ( 0 )
const node = range . startContainer
let element : HTMLElement | null = null
const range = selection . getRangeAt ( 0 )
const node = range . startContainer
let element : HTMLElement | null = null
if ( node . nodeType === Node . TEXT _NODE ) {
element = ( node as Text ) . parentElement
} else {
element = node as HTMLElement
}
if ( node . nodeType === Node . TEXT _NODE ) {
element = ( node as Text ) . parentElement
} else {
element = node as HTMLElement
}
if ( ! element ) return null
if ( ! element ) return null
let index = - 1
let type : 'text' | 'input' = 'text'
let isAtStart = false
let isAtEnd = false
let index = - 1
let type : 'text' | 'input' = 'text'
let isAtStart = false
let isAtEnd = false
if ( element . classList . contains ( 'text-field' ) ) {
index = parseInt ( element . getAttribute ( 'data-index' ) || '-1' )
type = 'text'
const textContent = element . textContent || ''
isAtStart = range . startOffset === 0
isAtEnd = range . startOffset === textContent . length
} else if ( element . classList . contains ( 'input-content' ) ) {
const parent = element . parentElement
index = parseInt ( parent ? . getAttribute ( 'data-index' ) || '-1' )
type = 'input'
if ( element . classList . contains ( 'text-field' ) ) {
index = parseInt ( element . getAttribute ( 'data-index' ) || '-1' )
type = 'text'
const textContent = element . textContent || ''
isAtStart = range . startOffset === 0
isAtEnd = range . startOffset === textContent . length
} else if ( element . classList . contains ( 'input-content' ) ) {
const parent = element . parentElement
index = parseInt ( parent ? . getAttribute ( 'data-index' ) || '-1' )
type = 'input'
const item = content . value [ index ]
if ( element . classList . contains ( 'has-placeholder' ) ) {
// placeholder状态下, 光标在任意位置都认为是"在元素内"
isAtStart = range . startOffset === 0
isAtEnd = true
} else {
// 正常内容状态
const textContent = item . value
isAtStart = range . startOffset === 0
isAtEnd = range . startOffset === textContent . length
}
}
const item = content . value [ index ]
if ( element . classList . contains ( 'has-placeholder' ) ) {
// placeholder状态下, 光标在任意位置都认为是"在元素内"
isAtStart = range . startOffset === 0
isAtEnd = true
} else {
// 正常内容状态
const textContent = item . value
isAtStart = range . startOffset === 0
isAtEnd = range . startOffset === textContent . length
}
}
return { index , type , element , isAtStart , isAtEnd }
return { index , type , element , isAtStart , isAtEnd }
}
//光标设置
const setCursorToElement = ( element : HTMLElement , position : 'start' | 'end' ) => {
const selection = window . getSelection ( )
const range = document . createRange ( )
const selection = window . getSelection ( )
const range = document . createRange ( )
if ( element . classList . contains ( 'input-content' ) && element . classList . contains ( 'has-placeholder' ) ) {
// placeholder状态的特殊处理
range . selectNodeContents ( element )
range . collapse ( position === 'start' )
} else if ( element . childNodes . length > 0 ) {
const targetNode = position === 'start' ? elem ent . firstChild ! : element . lastChild !
if ( targetNode . nodeType === Node . TEXT _NODE ) {
const off set = position === 'start' ? 0 : ( target Node. textContent || '' ) . length
range . setStar t ( targetNode , offset )
range . setEnd ( targetNode , offset )
} else {
range . selectNodeContents ( elemen t )
range . collapse ( position === 'start' )
}
} else {
range . selectNodeContents ( element )
range . collapse ( position === 'start' )
}
if (
element . classList . contains ( 'input-content' ) &&
element . classList . contains ( 'has-placeholder' )
) {
// placeholder状态的特殊处理
range . selectNodeCont ents ( element )
range . collapse ( position === 'start' )
} el se if ( element . child Nodes . length > 0 ) {
const targetNode = position === 'start' ? elemen t . firstChild ! : element . lastChild !
if ( targetNode . nodeType === Node . TEXT _NODE ) {
const offset = position === 'start' ? 0 : ( targetNode . textContent || '' ) . length
range . setStart ( targetNode , offse t )
range . setEnd ( targetNode , offset )
} else {
range . selectNodeContents ( element )
range . collapse ( position === 'start' )
}
} else {
range . selectNodeContents ( element )
range . collapse ( position === 'start' )
}
selection ? . removeAllRanges ( )
selection ? . addRange ( range )
selection ? . removeAllRanges ( )
selection ? . addRange ( range )
}
// 键盘事件处理
const handleKeydown = ( event : KeyboardEvent ) => {
const elementInfo = getCurrentElementInfo ( )
if ( ! elementInfo ) return
const elementInfo = getCurrentElementInfo ( )
if ( ! elementInfo ) return
const { index , type , isAtStart , isAtEnd } = elementInfo
const { index , type , isAtStart , isAtEnd } = elementInfo
switch ( event . key ) {
case 'Backspace' :
if ( isAtStart && index > 0 ) {
event . preventDefault ( )
handleCrossElementDelete ( index )
} else if ( type === 'input' && elementInfo . element ? . classList . contains ( 'has-placeholder' ) ) {
event . preventDefault ( )
}
// 其他情况让浏览器正常处理删除
break
switch ( event . key ) {
case 'Backspace' :
if ( isAtStart && index > 0 ) {
event . preventDefault ( )
handleCrossElementDelete ( index )
} else if (
type === 'input' &&
elementInfo . element ? . classList . contains ( 'has-placeholder' )
) {
event . preventDefault ( )
}
// 其他情况让浏览器正常处理删除
break
case 'ArrowLeft' :
if ( isAtStart && index > 0 ) {
event . preventDefault ( )
navigateToElement ( index - 1 , 'end' )
}
break
case 'ArrowLeft' :
if ( isAtStart && index > 0 ) {
event . preventDefault ( )
navigateToElement ( index - 1 , 'end' )
}
break
case 'ArrowRight' :
if ( isAtEnd && index < content . value . length - 1 ) {
event . preventDefault ( )
navigateToElement ( index + 1 , 'start' )
} else if ( isAtEnd && index === content . value . length - 1 ) {
// 在最后一个元素末尾按右箭头,确保有一个空文本框
ensureEmptyTextAtEnd ( )
nextTick ( ( ) => {
navigateToElement ( index + 1 , 'start' )
} )
}
break
}
case 'ArrowRight' :
if ( isAtEnd && index < content . value . length - 1 ) {
event . preventDefault ( )
navigateToElement ( index + 1 , 'start' )
} else if ( isAtEnd && index === content . value . length - 1 ) {
// 在最后一个元素末尾按右箭头,确保有一个空文本框
ensureEmptyTextAtEnd ( )
nextTick ( ( ) => {
navigateToElement ( index + 1 , 'start' )
} )
}
break
}
}
// 跨元素删除逻辑
const handleCrossElementDelete = ( currentIndex : number ) => {
const prevIndex = currentIndex - 1
const prevItem = content . value [ prevIndex ]
const prevIndex = currentIndex - 1
const prevItem = content . value [ prevIndex ]
if ( prevItem . type === 'input' ) {
if ( prevItem . value . trim ( ) === '' ) {
// 删除空输入框
content . value . splice ( prevIndex , 1 )
nextTick ( ( ) => {
// 删除输入框后,先删除末尾的空文本框
removeLastEmptyTextIfNeeded ( )
// 然后聚焦到正确的位置
if ( prevIndex < content . value . length ) {
focusElement ( prevIndex , 'end' )
} else if ( content . value . length > 0 ) {
focusElement ( content . value . length - 1 , 'end' )
}
} )
} else {
// 删除输入框最后一个字符,但保留输入框
const newValue = prevItem . value . slice ( 0 , - 1 )
content . value [ prevIndex ] . value = newValue
updateInputDisplay ( prevIndex )
nextTick ( ( ) => focusElement ( prevIndex , 'end' ) )
}
} else {
// 文本框:移动到前一个文本框末尾,让浏览器正常删除
// 先删除末尾的空文本框
removeLastEmptyTextIfNeeded ( )
focusElement ( prevIndex , 'end' )
}
if ( prevItem . type === 'input' ) {
if ( prevItem . value . trim ( ) === '' ) {
// 删除空输入框
content . value . splice ( prevIndex , 1 )
nextTick ( ( ) => {
// 删除输入框后,先删除末尾的空文本框
removeLastEmptyTextIfNeeded ( )
// 然后聚焦到正确的位置
if ( prevIndex < content . value . length ) {
focusElement ( prevIndex , 'end' )
} else if ( content . value . length > 0 ) {
focusElement ( content . value . length - 1 , 'end' )
}
} )
} else {
// 删除输入框最后一个字符,但保留输入框
const newValue = prevItem . value . slice ( 0 , - 1 )
content . value [ prevIndex ] . value = newValue
updateInputDisplay ( prevIndex )
nextTick ( ( ) => focusElement ( prevIndex , 'end' ) )
}
} else {
// 文本框:移动到前一个文本框末尾,让浏览器正常删除
// 先删除末尾的空文本框
removeLastEmptyTextIfNeeded ( )
focusElement ( prevIndex , 'end' )
}
}
// 导航到元素
const navigateToElement = ( targetIndex : number , position : 'start' | 'end' ) => {
const targetItem = content . value [ targetIndex ]
const element = targetItem . type === 'text'
? editableArea . value ? . querySelector ( ` .text-field[data-index=" ${ targetIndex } "] ` ) as HTMLElement
: editableArea . value ? . querySelector ( ` .input-field[data-index=" ${ targetIndex } "] .input-content ` ) as HTMLElement
const targetItem = content . value [ targetIndex ]
const element =
targetItem . type === 'text'
? ( editableArea . value ? . querySelector (
` .text-field[data-index=" ${ targetIndex } "] `
) as HTMLElement )
: ( editableArea . value ? . querySelector (
` .input-field[data-index=" ${ targetIndex } "] .input-content `
) as HTMLElement )
if ( element ) setCursorToElement ( element , position )
if ( element ) setCursorToElement ( element , position )
}
// 焦点设置
const focusElement = ( index : number , position : 'start' | 'end' ) => {
const item = content . value [ index ]
const element = item . type === 'text'
? editableArea . value ? . querySelector ( ` .text-field[data-index=" ${ index } "] ` ) as HTMLElement
: editableArea . value ? . querySelector ( ` .input-field[data-index=" ${ index } "] .input-content ` ) as HTMLElement
const item = content . value [ index ]
const element =
item . type === 'text'
? ( editableArea . value ? . querySelector (
` .text-field[data-index=" ${ index } "] `
) as HTMLElement )
: ( editableArea . value ? . querySelector (
` .input-field[data-index=" ${ index } "] .input-content `
) as HTMLElement )
if ( element ) setCursorToElement ( element , position )
if ( element ) setCursorToElement ( element , position )
}
// 输入框显示管理
const updateInputDisplay = ( index : number ) => {
const item = content . value [ index ]
if ( item . type !== 'input' ) return
const item = content . value [ index ]
if ( item . type !== 'input' ) return
const inputElement = editableArea . value ? . querySelector (
` .input-field[data-index=" ${ index } "] .input-content `
) as HTMLElement
const inputElement = editableArea . value ? . querySelector (
` .input-field[data-index=" ${ index } "] .input-content `
) as HTMLElement
if ( ! inputElement ) return
if ( ! inputElement ) return
const showPlaceholder = item . value . trim ( ) === '' && item . placeholder
const showPlaceholder = item . value . trim ( ) === '' && item . placeholder
if ( showPlaceholder ) {
inputElement . classList . add ( 'has-placeholder' )
inputElement . textContent = item . placeholder
} else {
inputElement . classList . remove ( 'has-placeholder' )
inputElement . textContent = item . value
}
if ( showPlaceholder ) {
inputElement . classList . add ( 'has-placeholder' )
inputElement . textContent = item . placeholder
} else {
inputElement . classList . remove ( 'has-placeholder' )
inputElement . textContent = item . value
}
}
// 输入框内容变化处理
const handleInputChange = ( index : number , event : Event ) => {
const target = event . target as HTMLSpanElement
const item = content . value [ index ]
const target = event . target as HTMLSpanElement
const item = content . value [ index ]
// 如果当前显示placeholder, 不更新实际值
if ( ! target . classList . contains ( 'has-placeholder' ) ) {
const newValue = target . textContent || ''
content . value [ index ] . value = newValue
// 如果当前显示placeholder, 不更新实际值
if ( ! target . classList . contains ( 'has-placeholder' ) ) {
const newValue = target . textContent || ''
content . value [ index ] . value = newValue
// 如果内容变空, 显示placeholder
if ( newValue . trim ( ) === '' && item . placeholder ) {
target . classList . add ( 'has-placeholder' )
target . textContent = item . placeholder
}
}
// 如果内容变空, 显示placeholder
if ( newValue . trim ( ) === '' && item . placeholder ) {
target . classList . add ( 'has-placeholder' )
target . textContent = item . placeholder
}
}
}
// 输入框键盘事件
const handleInputKeydown = ( event : KeyboardEvent , index : number ) => {
const target = event . target as HTMLSpanElement
const target = event . target as HTMLSpanElement
if ( event . key === 'Backspace' ) {
// 如果显示placeholder, 阻止删除
if ( target . classList . contains ( 'has-placeholder' ) ) {
event . preventDefault ( )
return
}
if ( event . key === 'Backspace' ) {
// 如果显示placeholder, 阻止删除
if ( target . classList . contains ( 'has-placeholder' ) ) {
event . preventDefault ( )
return
}
const selection = window . getSelection ( )
if ( selection && selection . rangeCount > 0 ) {
const range = selection . getRangeAt ( 0 )
const isAtStart = range . startOffset === 0
const selection = window . getSelection ( )
if ( selection && selection . rangeCount > 0 ) {
const range = selection . getRangeAt ( 0 )
const isAtStart = range . startOffset === 0
// 如果光标在输入框开头, 阻止默认行为, 让外部的handleBackspace处理
if ( isAtStart ) {
event . preventDefault ( )
return
}
}
} else if ( event . key . length === 1 && ! event . ctrlKey && ! event . metaKey ) {
// 普通字符输入
if ( target . classList . contains ( 'has-placeholder' ) ) {
event . preventDefault ( )
target . textContent = event . key
target . classList . remove ( 'has-placeholder' )
content . value [ index ] . value = event . key
// 如果光标在输入框开头, 阻止默认行为, 让外部的handleBackspace处理
if ( isAtStart ) {
event . preventDefault ( )
return
}
}
} else if ( event . key . length === 1 && ! event . ctrlKey && ! event . metaKey ) {
// 普通字符输入
if ( target . classList . contains ( 'has-placeholder' ) ) {
event . preventDefault ( )
target . textContent = event . key
target . classList . remove ( 'has-placeholder' )
content . value [ index ] . value = event . key
// 移动光标到末尾
nextTick ( ( ) => {
setCursorToElement ( target , 'end' )
} )
}
}
// 移动光标到末尾
nextTick ( ( ) => {
setCursorToElement ( target , 'end' )
} )
}
}
}
const handleInputBlur = ( index : number ) => {
updateInputDisplay ( index )
updateInputDisplay ( index )
}
// 容器点击处理
const handleContainerClick = ( event : MouseEvent ) => {
const target = event . target as HTMLElement
const target = event . target as HTMLElement
if ( target === editableArea . value ) {
event . preventDefault ( )
cursorState . value . isContainerClick = true
if ( target === editableArea . value ) {
event . preventDefault ( )
cursorState . value . isContainerClick = true
// 确保末尾有空文本框并聚焦到它
ensureEmptyTextAtEnd ( )
nextTick ( ( ) => {
focusElement ( content . value . length - 1 , 'start' )
} )
}
// 确保末尾有空文本框并聚焦到它
ensureEmptyTextAtEnd ( )
nextTick ( ( ) => {
focusElement ( content . value . length - 1 , 'start' )
} )
}
}
// 初始化
const initPlaceholders = ( ) => {
nextTick ( ( ) => {
content . value . forEach ( ( _ , index ) => updateInputDisplay ( index ) )
// 确保初始状态下有一个空文本框
ensureEmptyTextAtEnd ( )
} )
nextTick ( ( ) => {
content . value . forEach ( ( _ , index ) => updateInputDisplay ( index ) )
// 确保初始状态下有一个空文本框
ensureEmptyTextAtEnd ( )
} )
}
const getFullText = ( ) => {
if ( assistModel . value ) {
return content . value . map ( item => {
if ( item . type === 'text' ) {
return item . value
} else {
// 如果 input 没有输入 value, 则用 placeholder 填充,并去掉首尾的 []
if ( item . value ) {
return ` ${ item . value } `
} else if ( item . placeholder ) {
let placeholderText = item . placeholder
// 去掉首尾的 []
if ( placeholderText . startsWith ( '[' ) && placeholderText . endsWith ( ']' ) ) {
placeholderText = placeholderText . slice ( 1 , - 1 )
}
return ` ${ placeholderText } `
}
return ''
}
} ) . join ( '' )
}
return textareaValue . value
if ( assistModel . value ) {
return content . value
. map ( item => {
if ( item . type === 'text' ) {
return item . value
} else {
// 如果 input 没有输入 value, 则用 placeholder 填充,并去掉首尾的 []
if ( item . value ) {
return ` ${ item . value } `
} else if ( item . placeholder ) {
let placeholderText = item . placeholder
// 去掉首尾的 []
if ( placeholderText . startsWith ( '[' ) && placeholderText . endsWith ( ']' ) ) {
placeholderText = placeholderText . slice ( 1 , - 1 )
}
return ` ${ placeholderText } `
}
return ''
}
} )
. join ( '' )
}
return textareaValue . value
}
const textareaValue = ref ( '' )
const assistModel = ref ( false )
const assistModel = ref ( false )
const handleClickAssistBtn = ( ) => {
assistModel . value = ! assistModel . value
assistModel . value = ! assistModel . value
}
// 监听 assistModel 变化,切换到 textarea 模式时调整高度
watch ( assistModel , ( newVal ) => {
if ( ! newVal ) {
// 切换到 textarea 模式
nextTick ( ( ) => {
handleInputResize ( )
} )
}
} )
const textareaRef = useTemplateRef < HTMLTextAreaElement > ( 'textareaRef' )
const handleInputResize = ( ) => {
const textarea = textareaRef . value
if ( textarea ) {
textarea . style . height = 'auto'
textarea . style . height = textarea . scrollHeight + 'px'
}
}
onMounted ( ( ) => {
initPlaceholders ( )
// 如果初始状态是 textarea 模式,设置初始高度
if ( ! assistModel . value ) {
nextTick ( ( ) => {
handleInputResize ( )
} )
}
initPlaceholders ( )
} )
defineExpose ( {
getFullText ,
content
getFullText ,
content
} )
< / script >
< template >
< div v-show = "!assistModel" class="textarea-container" >
< textarea
class = "area"
v-model = "textareaValue"
ref = "textareaRef"
@input ="handleInputResize "
:placeholder = "$t('poseTransfer.PormptPlaceholder')"
/ >
< div class = "asistant-btn" @click ="handleClickAssistBtn" >
< i class = "fi fi-bs-magic-wand asistant-icon" > < / i >
< span > { { $t ( 'ProductImg.PromptAssit' ) } } < / span >
< / div >
< / div >
< div v-show = "assistModel" ref="editableArea" class="promptInput" @keydown="handleKeydown" @click="handleContainerClick" >
< template v-for = "(item, index) in content" :key="item.id" >
< span
v-if = "item.type === 'text' "
class = "text-field "
:data-index = "index"
contenteditable = "plaintext-only " >
{ { item . value } }
< / span >
< div v-show = "!assistModel" class="textarea-container" >
< textarea
class = "area"
v-model = "textareaValue"
ref = "textareaRef"
:placeholder = "$t('poseTransfer.PormptPlaceholder') "
/ >
< div class = "asistant-btn" @click ="handleClickAssistBtn" >
< i class = "fi fi-bs-magic-wand asistant-icon" > < / i >
< span > { { $t ( 'ProductImg.PromptAssit' ) } } < / span >
< / div >
< / div >
< div
v-show = "assistModel"
ref = "editableArea"
class = "promptInput"
@keydown ="handleKeydown "
@click ="handleContainerClick "
>
< div class = "promptinput-wrapper " >
< template v-for = "(item, index) in content" :key="item.id" >
< span
v-if = "item.type === 'text'"
class = "text-field"
:data-index = "index"
contenteditable = "plaintext-only"
>
{ { item . value } }
< / span >
< span v-else class = "input-field" :data-index = "index" >
< span
class = "input-content"
contenteditable = "plaintext-only"
@input ="(e) => handleInputChange(index, e)"
@keydown ="(e) => handleInputKeydown(e, index)"
@blur ="() => handleInputBlur(index)" > < / span >
< / span >
< / template >
< div class = "asistant-btn" @click ="handleClickAssistBtn" >
< i class = "fi fi-bs-magic-wand asistant-icon" > < / i >
< span > { { $t ( 'ProductImg.PromptAssit' ) } } < / span >
< / div >
< / div >
< span v-else class = "input-field" :data-index = "index" >
< span
class = "input-content"
contenteditable = "plaintext-only"
@input ="e => handleInputChange(index, e)"
@keydown ="e => handleInputKeydown(e, index)"
@blur ="() => handleInputBlur(index)"
> < / span >
< / span >
< / template >
< / div >
< div class = "asistant-btn" @click ="handleClickAssistBtn" >
< i class = "fi fi-bs-magic-wand asistant-icon" > < / i >
< span > { { $t ( 'ProductImg.PromptAssit' ) } } < / span >
< / div >
< / div >
< / template >
< style lang = "less" scoped >
. promptInput {
-- promptInputBorderRadius : 10 px ;
-- promptInputBorder : 2 px solid # dcdfe6 ;
-- promptInputPadding : 1.5 rem ;
-- promptInputBorderRadius : 10 px ;
-- promptInputBorder : 2 px solid # dcdfe6 ;
-- promptInputPadding : 1.5 rem ;
width : 100 % ;
min - h eight: 12 rem ;
border - radius : var ( -- promptInputBorderRadius ) ;
border : var ( -- promptInputBorder ) ;
padding : var ( -- promptInputPadding ) ;
background : white ;
line - height : 1.6 ;
outline : none ;
white - space : pre - wrap ;
user - select : text ;
cursor : text ;
position : relative ;
font - w eight: 500 ;
border - radius : var ( -- promptInputBorderRadius ) ;
border : var ( -- promptInputBorder ) ;
padding : var ( -- promptInputPadding ) ;
background : white ;
line - height : 1.6 ;
outline : none ;
white - space : pre - wrap ;
user - select : text ;
cursor : text ;
position : relative ;
padding - bottom : 4 rem ;
box - sizing : content - box ;
. text - field {
display : inline ;
outline : none ;
padding : .2 rem 0 ;
font - size : 1.8 rem ;
min - width : 2 px ;
/* 确保空文本框也能点击 */
. promptinput - wrapper {
min - height : 12 rem ;
max - height : 14 rem ;
overflow - y : auto ;
}
. inpu t- field {
display : inline - block ;
// background: #e3f2fd;
// border: 1px solid #bbdefb;
margin : 0 .2 rem ;
padd ing : .2 rem 1 rem ;
font - size : 1.8 rem ;
border - radius : 4 px ;
. tex t- field {
display : inline ;
outline : none ;
padding : 0.2 rem 0 ;
font - size : 1.8 rem ;
m in - width : 2 px ;
font - weight : 400 ;
/* 确保空文本框也能点击 */
}
. input - content {
outline : none ;
display : inline - block ;
min - width : 2 rem ;
. input - field {
display : inline - block ;
// background: #e3f2fd;
// border: 1px solid #bbdefb;
margin : 0 0.2 rem ;
padding : 0.2 rem 1 rem ;
font - size : 1.8 rem ;
border - radius : 4 px ;
& . has - placeholder {
color : # b9b9b9 ;
// font-style: italic;
}
}
}
. input - content {
outline : none ;
display : inline - block ;
min - width : 2 rem ;
& . has - placeholder {
color : # b9b9b9 ;
// font-style: italic;
}
}
}
}
. textarea - container {
position : relative ;
border - radius : 10 px ;
border : 2 px solid # dcdfe6 ;
padding : 1.5 rem 1.5 rem 3 rem ;
height : auto ;
. area {
. textarea - container {
position : relative ;
border - radius : 10 px ;
border : 2 px solid # dcdfe6 ;
padding : 1.5 rem 1.5 rem 3 rem ;
height : auto ;
. area {
width : 100 % ;
min - height : 12 rem ;
height : auto ;
max - height: 14 rem ;
background : white ;
line - height : 1.6 ;
outline : none ;
@@ -509,34 +520,34 @@ defineExpose({
user - select : text ;
cursor : text ;
position : relative ;
// padding-bottom: 4rem;
resize : none ;
border : none ;
overflow - y : auto ;
}
}
. asistant - btn {
height : 2.3 rem ;
padding : 0 0.6 rem ;
font - size : 1 rem ;
font - weight : 400 ;
color : # 313131 ;
position : absolute ;
bottom : 1.3 rem ;
left : 1.3 rem ;
display : flex ;
column - gap : 0.3 rem ;
justify - content : center ;
align - items : center ;
background - color : # f2f2f2 ;
border : 1 px solid # dfdfdf ;
border - radius : 0.5 rem ;
cursor : pointer ;
. asistant - icon {
font - size : 1 rem ;
margin - right : 0 ;
width : initial ;
// margin-top: -0.2rem;
}
height : 2.3 rem ;
padding : 0 0.6 rem ;
font - size : 1 rem ;
font - weight : 400 ;
color : # 313131 ;
position : absolute ;
bottom : 1.3 rem ;
left : 1.3 rem ;
display : flex ;
column - gap : 0.3 rem ;
justify - content : center ;
align - items : center ;
background - color : # f2f2f2 ;
border : 1 px solid # dfdfdf ;
border - radius : 0.5 rem ;
cursor : pointer ;
. asistant - icon {
font - size : 1 rem ;
margin - right : 0 ;
width : initial ;
// margin-top: -0.2rem;
}
}
< / style >
< / style >