vue3 + 微信实现简单的机器人对话

2,256 阅读1分钟

vue3 + 微信实现简单的机器人对话

效果图

wxrobot.gif

前置知识

首先开发一个机器人对话我们需要接入微信的智能对话

image.png 点击前往

登陆后可以看到首页

image.png 提供了一些基本功能如:

  • 简单的对话
  • 一些内置的的技能都可以都选上
  • 配置欢迎语
  • 转人工等等

接入智能对话

  1. 调用signature接口,获取signature
https://chatbot.weixin.qq.com/openapi/sign/{TOKEN}

signature接口返回体如下:

{
    signature: 'xxxxxxxxx'
    expiresIn: 7200
}

如何获取token

  • TOKEN:发布管理>应用绑定>开发API(按步骤就能拿到token)

image.png

2.智能对话接口

https://chatbot.weixin.qq.com/openapi/aibot/{TOKEN}
  • POST请求
    • 参数说明
      • signature:必填,调用signature接口获取到的 signature 返回值
      • query:必填,用户发送的消息
      • env:非必填,默认是online, debug是测试环境,online是线上环境
      • 剩余的参数不做过多说明

至此只能对话的流程完毕。

vue3 实现对话界面 + 逐字出现的效果实现

<template>
  <cu-custom bg-color="bg-white text-black solid-bottom" is-back bg-image="">
    <template #backText>返回</template>
  </cu-custom>
  <div class="chat-box">
    <template v-for="(item, index) in talkList.data" :key="index">
      <div v-if="item.type == 1" class="is-robot mb-2">
        <div class="img"></div>
        <div class="content">
          <div ref="itemRefs"></div>
        </div>
      </div>
      <div v-if="item.type == 0" class="is-question">
        <div class="content">
          <div ref="itemRefs"></div>
        </div>
        <div class="img"></div>
      </div>
    </template>

    <div class="question-panel">
      <input v-model="question" />
      <button class="send" @click="talk">发送</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, nextTick } from "vue";
import { getToken, wxTalk } from "@/api/index";
import Typed from "typed.js";

const signature = ref("");
const question = ref("");
const talkList: any = ref({ data: [] });
const itemRefs = ref([]);
const init = async () => {
  let data: any = await getToken();
  signature.value = data.data;
};

const showTyped = (index: number, data: string) => {
  nextTick(() => {
    let item = itemRefs.value[index];
    new Typed(item, {
      strings: [data],
      typeSpeed: 0,
      backSpeed: 50,
      showCursor: false,
    });
  });
};

const talk = async () => {
  talkList.value.data.push({
    type: 0,
    content: question.value,
  });
  showTyped(talkList.value.data.length - 1, question.value);
  let data: any = await wxTalk({
    signature: signature.value,
    query: question.value,
  });
  if (data.data) {
    talkList.value.data.push({
      type: 1,
      content: data.data[0].content,
    });
    showTyped(talkList.value.data.length - 1, data.data[0].content);
  }
};

onMounted(() => {
  init();
});
</script>

<style lang="scss" scoped>
.chat-box {
  width: 750rpx;
  height: calc(100vh - 45px);
  background: white;
  padding: 10px;
}

.is-robot {
  display: flex;
  .img {
    width: 100rpx;
    height: 100rpx;
    border-radius: 50%;
    background: url("../../static/wx.jpg");
    background-size: 100% 100%;
    border: solid 1px #333;
  }
  .content {
    margin-left: 10rpx;
    padding: 10rpx;
    background-color: #ecf3fe;
    max-width: 500rpx;
    height: min-content;
    border-radius: 20rpx;
  }
}
.is-question {
  display: flex;
  justify-content: flex-end;
  .img {
    width: 100rpx;
    height: 100rpx;
    border-radius: 50%;
    background: url("../../static/sansan.jpg");
    background-size: 100% 100%;
    border: solid 1px #333;
  }
  .content {
    margin-right: 10rpx;
    padding: 10rpx;
    background-color: #ffe7ae;
    max-width: 500rpx;
    border-radius: 20rpx;
    height: min-content;
  }
}
.mb-2 {
  margin-bottom: 20rpx;
}
.question-panel {
  position: fixed;
  bottom: 10px;
  height: 80rpx;
  width: 750rpx;
  display: flex;
  align-content: center;
  left: 0;
  .color {
    line-height: 80rpx;
  }
  input {
    background-color: #f6f6f5;
    height: 80rpx;
    margin-left: 10rpx;
    width: 600rpx;
    border-radius: 20rpx;
  }
}
.send {
  font-size: 14rpx;
  line-height: 80rpx;
  background-color: aquamarine;
}
</style>

  • talkList:通过type区分是机器人回复还是提问
  • getToken:获取signature
  • itemRefs:数组ref实例
  • talk:对话函数
  • showTyped:生成Typed实例

逐字展示的效果依赖第三方库Typed.js

Ending

点个赞吧!