首页 > 其他分享 >实现一个 AI 聊天输入框:从基础到高级的指南

实现一个 AI 聊天输入框:从基础到高级的指南

时间:2024-07-13 11:30:26浏览次数:22  
标签:指南 node container newLineDiv AI child 输入框 input const

引言

随着人工智能和自然语言处理(NLP)技术的快速发展,基于 AI 的聊天系统变得越来越普遍。无论是简单的问答系统还是复杂的客服聊天机器人,聊天输入框都是用户与系统交互的关键组件。本文将详细介绍如何实现一个功能丰富的 AI 聊天输入框,从基础组件到高级功能,包括用户输入处理、界面设计以及与 AI 模型的集成。

功能介绍

基础功能

  • 输入数据并发送聊天消息;
  • 支持shift+enter换行;

高级功能

  • 表单内容支持:允许嵌套select元素;

实现步骤

实现基础功能

普通的聊天输入框只需要一个简单的input元素即可;

import React, { useState } from 'react';

const ChatInput = ({ onSend }) => {
  const [input, setInput] = useState('');

  const handleSend = () => {
    if (input.trim()) {
      onSend(input);
      setInput('');
    }
  };

  return (
    <div className="chat-input">
      <input
        type="text"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        onKeyPress={(e) => e.key === 'Enter' && handleSend()}
      />
      <button onClick={handleSend}>Send</button>
    </div>
  );
};

export default ChatInput;

支持换行的聊天输入框只需要一个简单的textarea元素即可;

import React, { useState } from 'react';

const ChatInput = ({ onSend }) => {
  const [input, setInput] = useState('');

  const handleSend = () => {
    if (input.trim()) {
      onSend(input);
      setInput('');
    }
  };

  const handleKeyPress = (e) => {
    if (e.key === 'Enter') {
      if (e.shiftKey) {
        // 插入换行符
        setInput(input + '\n');
      } else {
        // 发送消息
        e.preventDefault(); // 防止输入框获得默认的按键行为
        handleSend();
      }
    }
  };

  return (
    <div className="chat-input">
      <textarea
        value={input}
        onChange={(e) => setInput(e.target.value)}
        onKeyPress={handleKeyPress}
        rows="3" // 可以根据需要调整行数
      />
      <button onClick={handleSend}>Send</button>
    </div>
  );
};

export default ChatInput;

实现高级功能

表单内容支持:允许嵌套select元素

需要将元素的contenteditable设置为true,最后需要提取元素的字符内容

select元素不能采用受控组件的方式,会有数据同步的问题

export function getSelectValueAndTextContentByDiv(htmlString) {
  const parser = new DOMParser();
  const htmlDocument = parser.parseFromString(htmlString, 'text/html');
  const rootNode = htmlDocument.body;
  const iconCharRegex = /[\uE000-\uF8FF]/g;
  const lines: string[] = [];

  rootNode.childNodes.forEach(child => {
    let lineText = '';

    if (child.nodeType === Node.ELEMENT_NODE) {
      if (child.nodeName === 'SELECT') {
        const selectedOption = child.options[child.selectedIndex].text;
        lineText += selectedOption;
      } else {
        lineText += getTextFromNode(child);
      }
    } else if (child.nodeType === Node.TEXT_NODE) {
      lineText += child.textContent.replace(iconCharRegex, '').trim();
    }
    if (lineText) {
      lines.push(lineText);
    }
  });

  function getTextFromNode(node) {
    if (node.nodeType === Node.TEXT_NODE) {
      return node.textContent.replace(iconCharRegex, '').trim();
    } else if (node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'SELECT') {
      return node.options[node.selectedIndex].text;
    } else {
      return Array.from(node.childNodes).map(getTextFromNode).join('');
    }
  }

  const result = lines.join('\n');
  return result;
}

同时需要支持输入时换行处理

function insertNewLineAtCaret(el) {
    const selection = window.getSelection();
    if (!el || !selection.rangeCount) return;
    const range = selection.getRangeAt(0);
    let container = range.startContainer;

    let newLineDiv = document.createElement('div');
    newLineDiv.appendChild(document.createElement('br'));

    if (container.nodeType === Node.TEXT_NODE && range.startOffset !== 0 && range.startOffset !== container.length) {
      const secondPart = container.splitText(range.startOffset);
      newLineDiv = document.createElement('div');
      newLineDiv.appendChild(secondPart);
    }

    while (container && container.parentNode !== el) {
      container = container.parentNode;
    }

    if (range.startOffset === 0) {
      el.insertBefore(newLineDiv, container);
    } else {
      el.insertBefore(newLineDiv, container.nextSibling);
    }

    const newRange = document.createRange();
    newRange.selectNodeContents(newLineDiv);
    newRange.collapse(true);
    selection.removeAllRanges();
    selection.addRange(newRange);
  }

目前采用的是最简单基础的方式,之后会分析富文本编辑器,比如 QuillDraft.js实现的方式。

标签:指南,node,container,newLineDiv,AI,child,输入框,input,const
From: https://blog.csdn.net/vitalityxyl/article/details/140396353

相关文章

  • 疑惑...2024年是不是转行AI产品经理的好时机?
    这两年AI突然“火起来”了,算是出现了一个“大转折”。因为就在这2年里,全球所有“大厂”几乎同一时间挤破头在跟进AI技术,从ChatGPT发布,到谷歌、Facebook、亚马逊等都紧跟其后,再到国内百度、腾讯、阿里、字节等也随之在冲在后面。对市场趋势敏感的产品经理们,想必也感受到......
  • 快手快影可灵ai快速申请渠道当天通过教程
    1.引言随着快手快影可灵AI功能的推出,许多用户希望能够快速获得内测资格。本文将提供一份详细的申请教程,并分析当前市场的需求和机遇。2.快手快影可灵AI概述简要介绍快手快影可灵AI的功能和用户价值,以及为何有大量用户希望申请内测。3.快速申请教程提供一份详细的申请......
  • 小红书平台变现策略与运营指南
    1.引言小红书作为一个新兴的社交平台,为内容创作者和品牌提供了丰富的变现机会。本文将揭示如何在小红书实现高效的内容变现。2.IP时代的多元化变现途径讨论了在个人品牌(IP)竞争激烈的环境下,除了传统的"卖脸"方式外,还有哪些变现途径。3.抖音思维与小红书运营差异分析了......
  • 最新AI指令合集,一份高质量Ai指令,解决你的内容创作
    1.引言随着人工智能技术的不断进步,AI已成为内容创作领域的重要辅助工具。本文提供了一系列AI指令,旨在提升内容创作的质量和效率。2.AI指令与教程概览以下是AI辅助内容创作的指令集,每个指令都配有详细的教程,以指导用户如何有效使用:文案创作框架:提供10种文案框架和5种风格......
  • 小红书一周涨粉过万,蜡笔手绘风格的ai绘画也太火了!(附教程)
    爆火蜡笔手绘风格蜡笔手绘风格的模型,在小红书又引领了一波新热度新爆款。很多人开始起新号专门做蜡笔手绘的头像,每篇的点赞收藏都很多,涨粉也很快,很多博主基本都是发一周涨粉过万。示例如下,今天的教程来教你做这种头像和定制漫改目前这种风格也正处于热度很高的阶段,受到......
  • AI绘画变现之MJ制作表情包(附教程)
    前期构思:●主题:明确表情包的主题,例如快乐或悲伤、卡通人物或的动物等;●形象:描述表情包中角色的外貌特征,例如发型、着装、配饰等;●表情和动作:描述角色的表情和动作,例如微笑、大笑、哭泣、生气、难过、眨眼等;●背景和场景:建议尽量使用白色背景,方便制作完成后抠图和制作GIF......
  • 【大白话讲清楚:什么是 Langchain 及其核心概念】
    文末有福利!在AI和机器学习领域,每天都有新技术和框架涌现。今天,我们来聊聊最近引起广泛关注的一个框架——Langchain。https://python.langchain.com/docs/get_started/introduction那么,Langchain到底是什么,它为什么这么受欢迎,以及它是如何工作的呢?别担心,我会用大白话......
  • 麦克风设计指南
    前言:本指南基于乐鑫的ESP32-S3系列语音开发板。整机mic要求麦克风电器性能推荐麦克类型:全向型MEMS麦克风SMD-4P,2.8x1.9mmMEMS麦克风顶视图MEMS麦克风底视图灵敏度1Pa声压下模拟麦灵敏度不低于-38dBV,数字麦灵敏度要求不低于-26d......
  • AI写歌词,为你的音乐之旅添彩
    在追求音乐梦想的道路上,每一个音符都承载着我们的情感与故事。而精彩的歌词,更是让这些音符焕发出耀眼光芒的关键。如今,AI写词的出现,为我们的音乐之旅增添了绚丽的色彩。“妙笔生词智能写歌词软件(53650899)”便是这场音乐变革中的璀璨之星。它运用强大的人工智能技术,如同一位才华......
  • AI 作词:赋予音符以灵魂的魔法
    在音乐的浩瀚宇宙中,作词一直是那道璀璨星河中最神秘而迷人的部分。它将抽象的情感和思绪转化为具体的文字,与音符交织共舞,触动着人们内心深处的共鸣。而如今,AI作词的出现,犹如一场神奇的魔法,为音乐创作带来了前所未有的变革。在众多AI作词的工具中,“妙笔生词智能写歌词软件(53650......