创新实训-搭建聊天界面

该篇主要为搭建聊天容器,实现对话显示,使用技术有vue,vuex,tailwind

类定义使用了TS,编译出来的 JavaScript 可以运行在任何浏览器上,且方便管理不同的类

Message

messageType定义了发给后端的信息,包含的信息有

  1. idx用于定义一条message在一个conversation中是第几条
  2. loading表示该对话是否在加载中
  3. role表示的是说话角色,这里我们按照智谱清言的定义方式,其中assistant为ai的回答,user为用户的问题,system为系统设定(system在实际中不常使用)
  4. speech为回答数组,用于ai重新生成回答时使用
  5. timestamp为消息发送时间
export interface messageType {
    idx: number;
    loading: boolean;
    role: string;
    timestamp?: number;
    suitable: number[];
    speeches: string[];
}
ConvType

convType在多个message集合中,加入以下属性扩展

  1. id这里的id表示的是当前有几个会话
  2. title指的是会话的标题
  3. timestamp表示会话创建时间
  4. msgList表示messageType的数组
  5. selected表示该会话是否被选择,可以用于样式的更新
export interface convType {
    id: number;
    title: string;
    timestamp?: number;
    msgList?: messageType[];
    selected?:boolean;
    editable?:boolean;
}
StateType

主要用于管理会话的状态

  1. conversationList表示会话的列表
  2. conversation表示当前对话是否被选中
  3. chatStatus指当前会话状态
    export interface stateType {
        conversationList: convType[]|null;
        conversation?: convType|null;
        chatStatus?: "chatting"|"available";
        chatMsg: string;
        selectedIdx?: number;
    
    ​}

输入框

功能:

  1. 信息输入,用户输入信息,输入框要随着输入信息而扩大
  2. 问题发送,这个功能比较麻烦,需要和后端和其他模块进行交互
  3. 重新回答:点击之后重新生成回答
<input type="checkbox" :id="option.value" @change="selectOption(option)" v-model="option.selected"
                  :value="option.value" class="p-1 rounded-md hover:bg-gray-100 dark:hover:bg-gray-900">
<button @click.stop.prevent="send" :disabled="convLoading"
            class="absolute p-1 rounded-md text-gray-500 bottom-1.5 right-1 md:bottom-2.5 md:right-2 hover:bg-gray-100 dark:hover:text-gray-400 dark:hover:bg-gray-900 disabled:hover:bg-transparent dark:disabled:hover:bg-transparent">
            <div v-if="convLoading" class="text-2xl" style="line-height: 1.3rem;">
              <span class="load_dot1">·</span><span class="load_dot2">·</span><span class="load_dot3">·</span>
            </div>
            <svg v-else stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round"
              stroke-linejoin="round" class="h-4 w-4 mr-1" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
              <line x1="22" y1="2" x2="11" y2="13"></line>
              <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
            </svg>
          </button>
<button v-if="!convLoading && this.messageList.length > 0" @click.stop.prevent="chatRepeat" id="chatRepeat"
            class="btn flex justify-center gap-2 btn-neutral border-0 md:border">
            <svg stroke="currentColor" fill="none" stroke-width="1.5" viewBox="0 0 24 24" stroke-linecap="round"
              stroke-linejoin="round" class="h-3 w-3" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
              <polyline points="1 4 1 10 7 10"></polyline>
              <polyline points="23 20 23 14 17 14"></polyline>
              <path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"></path>
            </svg>
            <p class="none">Regenerate response</p>
          </button>

首先将chatMsg和textarea使用v-model进行双向绑定,对于chatMsg进行监听,在chatMsg变化的时候调用方法改变文本框高度

接着实现修改高度的方法,实现的changeHeight方法如下

    changeHeight() {
      var elem = this.$refs.inputChat;
      elem.style.height = '24px';
      var scrollHeight = elem.scrollHeight;
      if (24 >= scrollHeight || this.chatMsg.length == 0) {
        this.resetHeight();
        return;
      }
 
      elem.style.removeProperty("overflow-y")
      elem.style.height = scrollHeight + 'px';
      console.log(scrollHeight)
 
    },

信息初始化

实现流程:生成两条信息,分别为用户提问和ai回答,用户提问的信息内容为chatMsg即输入框中的内容

addInitMessage() {
      this.addMessage({
        "idx": 0,
        "role": "user",
        "message": this.chatMsg
      })
      var message = {
        "idx": 0,
        "loading": true,
        "role": "assistant",
        "suitable": [0],
        "speeches": [""]
      }
      this.addMessage(message)
    },

聊天实现

chat() {
      // console.log("bus-send",that.conversation)
      bus.emit('bus-send')
      const chatMsgCopy = this.chatMsg;
      this.chatMsg = "";
      aiLongChat(this.model, chatMsgCopy, this.conversation.id).then((res) => {
        var tmpMessage = this.conversation.msgList[this.conversation.msgList?.length - 1]
        tmpMessage["speeches"][0] += res.data.message
        tmpMessage["loading"] = false;
        this.conversation.msgList[this.conversation.msgList?.length - 1] = tmpMessage;
        this.updateConversation(this.conversation);
        this.handleScrollBottom();
        console.log(res.data.message)

      }).catch((err) => {
        console.log(err)
      })
      this.convLoading = false;

    },

发送实现

send() {

      if (this.chatMsg.trim().length == 0) {
        return;
      }

      if (this.convLoading) {
        return;
      }

      this.convLoading = true;
      this.chatMsg = this.chatMsg.trim().replace(/\n/g, "")
      this.addInitMessage()
      // 滚动到最下面
      this.handleScrollBottom();
      //this.streamChat();
      this.chat();
      //this.convLoading = false;

    },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值