我居然做了一个智障?(聊天机器人的界面实现与交互)

805 阅读4分钟

废话不多说先上gif

loading1.gif

从动图可以看出这个聊天机器人可以功能包括

  • 发送方输入信息
  • 发送信息渲染
  • 接收信息回复的时候显示加载动画
  • 回复信息渲染

接下来我们一步一步按照上面功能来说明

1.发送方输入信息发送

输入框布局上图

Snipaste_2021-06-17 15:35:19.png

WXML代码
 <view class="chat-up" >
      <image 
        bindtouchstart='startRecognize' 
        bindtouchend='endRecognize' 
        class="chat-up-mic" 
        src="../../static/iconfont/mdcubs/mic.svg" />
      <input 
        class="chat-up-input" 
        bindinput="chatChange" 
        placeholder="说点什么吧" 
        value="{{chatMyself}}" />
      <view bindtap="sendChatValue">
          <i class="iconfont icon-fasong"></i>
     </view>
 </view>
WXSS
.chat-up{
  display: flex;
  justify-content: space-around;
  align-items: center;
  position:fixed;
  bottom:80rpx;
  left: 50%;
  transform: translateX(-50%);

  height: 80rpx;
  width: 80%;
  border-radius: 80rpx;

  padding:20rpx;
  background: #e3f6f1;
}

.chat-up-input{
  width: 80%;
  height: 80rpx;
  border: none;
  color: #333;
}
.chat-up .chat-up-mic{
  width: 140rpx;
  height: 100rpx;
}

.icon-fasong::before{
  font-size: 50rpx;
  color: #a8b3c9;
  padding: 0 20rpx;
}
javascript
data: {
    // 发送的新消息
    chatMyself:'',
     //信息列表,is_chat_back表示是否为回复的信息。content表示信息内容   
    chat_list:[
      {is_chat_back:true,content:'今天天气多云转晴,气温下降,注意保暖~'},
    ]
  },
chatChange(e){
    this.setData({chatMyself:e.detail.value})
  },
sendChatValue(){
    let chat_list = this.data.chat_list;
    let chatMyself = this.data.chatMyself;
    let that = this
    if(chatMyself != '') {
      chat_list.push({is_chat_back:false,content:chatMyself});
          this.setData({
            chat_list,
            chatMyself:''
          })
      setTimeout(
        function(){
          that.aiRequest(chatMyself)
        },500)
    }
  },
  aiRequest(msg){
    let that = this
    let chat_list = this.data.chat_list;
    chat_list.push({is_chat_back:true,content:'',state:1});
    this.setData({chat_list})
    wx.request({
      url:'http://api.qingyunke.com/api.php',
      data:{
        key:'free',
        appid:0,
        msg:msg
      },
      success(res){
        let { result, content } = res.data;
        content = content.replace(/(\{br\})/g,'\n');
        chat_list[chat_list.length-1].state = 0;
        chat_list[chat_list.length-1].content = content;
        that.setData({chat_list})
      }
    })
  }

chatChange函数主要是将input框里输入的内容同步到data的chatMyself,用来存储输入的内容方便发送时直接获取data.chatMyself发送新信息。

sendChatValue函数就是点击发送按钮对应函数。在点击发送时:

​ 1.先获取已有的消息列表数组chat_list和发送的消息chatMyself

​ 2.将this存到that变量中,防止下面函数使用this绑定时丢失

​ 3.判断输入的内容是否为空值,不为空则继续往下走,这一步是为了防止发送空文本到消息列表中造成不必要的麻烦

​ 4.利用数组方法push将新消息添加到消息列表数组中,并且设置is_chat_back = false表示该消息为发送方而非回复方,然后通过this.setData设置新的消息数组渲染到页面上,并且清空输入的信息

​ 5.利用setTimeout将消息延迟500ms在进行消息发送调用aiRequest,接收回复。

​ 6.aiRequest中使用了聊天机器人apihttp://api.qingyunke.com/api.php

vjeKFoYfzhXIc3r.pngaiRequest中功能主要是获取发送的信息然后调用api获取回复信息,将回复信息添加到消息列表数组chat_list

​ 6.1.在发送信息接收的时间段使用loading动画提升交互用户体验,所以在获取消息列表后会现push一个新的回复消息,设置state为1表示该消息是一个loading消息进行loading

loading1.gif ​ 6.2调用wx.request发送信息接收回复然后利用结构语法将其解构,这里我们只需要用到回复的消息content

因为回复的消息中表示换行符为{br}在小程序中并不能渲染换行而是会直接渲染出来,所以利用字符串repalce进行了一个基本的处理

content = content.replace(/(\{br\})/g,'\n');

​ 6.3将数组最后一项loading的内容和状态进行改变,将state = 0表示结束loading渲染回复的文本

 chat_list[chat_list.length-1].state = 0;
 chat_list[chat_list.length-1].content = content;

​ 6.4最后将更新的消息列表数组更新到data里

//这里shiyongthat是因为this在此处会丢失无法正常更新消息列表数组
that.setData({chat_list})
2.信息渲染
HTML

1.信息渲染利用了scroll-view进行消息滚动,在内部对chat-list进行遍历渲染消息列表

2.新消息自动滚动到底部利用了scroll-view的scroll-into-view属性,滚动条会自动滚动到设置的内容部分

aD3tLGRAYZfFkrb.png

3.在消息item里对is_chat_back进行判断设置不同的类对回复消息和发送消息进行不同的样式设置,这里的消息文字反转是使用了flex-flow办法进行设置

4.判断state确定是否渲染loading

<scroll-view scroll-y="{{true}}" class="chat-content" scroll-into-view="msg{{chat_list.length-1}}" scroll-with-animation="{{true}}">
    <!-- 多包一层的原因是清除浮动 -->
    <view wx:for="{{chat_list}}" wx:key="index" id="msg{{index}}" style="clear:both">
      <view class="body {{!item.is_chat_back ? 'chat-animate' :'chat-back-animate'}}">
        <view class="loading-box" wx:if="{{item.state == 1}}">
          <view class="loading"></view>
          <view class="loading"></view>
          <view class="loading"></view>
        </view>
        <text>{{item.content}}</text>
      </view>
    </view>
  </scroll-view>
css
.chat-content{
  margin-top: 20rpx;
  height: 1200rpx;
  overflow: hidden;
  line-height: 1.75rem;
  padding: 40rpx;
  box-sizing: border-box;

}
.chat-content .body{
  display:flex;
  flex-direction: column;
  color: #333;
  min-height: 40rpx;
  width: auto;

  border-radius: 40rpx;
  padding: 20rpx;
  margin-bottom: 20rpx;
}

.chat-content .chat-animate{
  border-bottom-right-radius: 0rpx;
  flex-flow: row;
  float: right;
  background: #07c798;
  color: #fff;

  animation: chat-in .3s ease-in;
}
.chat-content .chat-back-animate{
  border-bottom-left-radius: 0rpx;
  background: #b7eade;
  flex-flow: row-reverse;
  float: left;


  animation: chat-back .3s ease-in;
}
/* 动画 */
@keyframes chat-in {
  from{transform:translateX(-300rpx);opacity: 0;}
  to{transform: translateX(0);opacity: 1;}
}
@keyframes chat-back {
  from{transform:translateX(300rpx);opacity: 0;}
  to{transform: translateX(0);opacity: 1;}
}

做完这些就大功告成啦~