@@ -756,28 +756,50 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
756756 }
757757 } )
758758
759+ // --- 必须严格修改此 useEffect 以处理多个插入 --- (根据规划重写)
759760 useEffect ( ( ) => {
760- if ( pendingInsertions . length === 0 || ! textAreaRef . current ) {
761- return
762- }
763-
764- const path = pendingInsertions [ 0 ]
765- const currentTextArea = textAreaRef . current
766- const currentValue = currentTextArea . value
767- const currentCursorPos =
768- intendedCursorPosition ??
769- ( currentTextArea . selectionStart >= 0 ? currentTextArea . selectionStart : currentValue . length )
770-
771- const mentionTextToInsert = path + " "
772- const { newValue, mentionIndex } = insertMention ( currentValue , currentCursorPos , mentionTextToInsert )
773- const newCursorPosition = mentionIndex + mentionTextToInsert . length // 声明移到 useEffect 内部
761+ // 确保 textAreaRef.current 存在且 pendingInsertions 有内容
762+ if ( pendingInsertions . length > 0 && textAreaRef . current ) {
763+ const currentTextArea = textAreaRef . current // 引用当前文本区域
764+ // 将所有待插入路径用空格连接成一个字符串
765+ const textToInsert = pendingInsertions . join ( " " )
766+ // 获取当前光标位置,若无则取输入值末尾
767+ const currentCursorPos = currentTextArea . selectionStart ?? inputValue . length
768+ // 确定插入起始位置:优先使用记录的拖放初始位置,否则使用当前光标位置
769+ const startPos = intendedCursorPosition ?? currentCursorPos
770+
771+ // 构建插入后的新输入值
772+ const newValue =
773+ inputValue . substring ( 0 , startPos ) + // 插入点之前的部分
774+ textToInsert + // 要插入的所有路径字符串
775+ " " + // 在所有路径后追加一个空格,以便继续输入
776+ inputValue . substring ( startPos ) // 插入点之后的部分
777+
778+ // 调用回调函数更新父组件或全局状态中的输入值
779+ // 注意:这里直接调用 setInputValue,因为它是 props 传入的 state setter
780+ setInputValue ( newValue )
781+ // 一次性清空待插入项数组
782+ setPendingInsertions ( [ ] )
774783
775- setInputValue ( newValue )
784+ // 计算插入后的新光标位置(位于插入内容和末尾空格之后)
785+ const newCursorPos = startPos + textToInsert . length + 1 // +1 是因为加了空格
776786
777- setIntendedCursorPosition ( newCursorPosition )
787+ // 使用 requestAnimationFrame 确保在 DOM 更新后设置光标和焦点
788+ requestAnimationFrame ( ( ) => {
789+ if ( textAreaRef . current ) {
790+ textAreaRef . current . selectionStart = newCursorPos
791+ textAreaRef . current . selectionEnd = newCursorPos
792+ // 确保文本区域获得焦点,以便用户可以立即输入
793+ textAreaRef . current . focus ( )
794+ }
795+ } )
778796
779- setPendingInsertions ( ( prev ) => prev . slice ( 1 ) )
780- } , [ pendingInsertions , setInputValue , intendedCursorPosition ] )
797+ // 重置记录的初始光标位置
798+ setIntendedCursorPosition ( null )
799+ }
800+ // 依赖项数组:当这些值变化时,此 effect 会重新运行
801+ // 需要包含所有在 effect 内部使用的、可能变化的外部变量/状态/回调
802+ } , [ pendingInsertions , inputValue , setInputValue , intendedCursorPosition , setIntendedCursorPosition ] ) // 确保依赖项完整
781803
782804 const placeholderBottomText = `\n(${ t ( "chat:addContext" ) } ${ shouldDisableImages ? `, ${ t ( "chat:dragFiles" ) } ` : `, ${ t ( "chat:dragFilesImages" ) } ` } )`
783805
0 commit comments