用Vue实现小Q聊天机器人(四)

    技术2022-07-11  83

    GitHub:https://github.com/baiyuliang/Qrobot_Vue

    本项目所用的闲聊接口为腾讯开放平台提供,具体可参考: 用Flutter实现小Q聊天机器人(五) 或者官方文档: https://ai.qq.com/doc/nlpchat.shtml

    说到前端网络请求,就不得不说跨域问题了,本项目仍然会面临跨域问题而导致无法去直接请求接口,一般的跨域解决办法有这么几种:jsonp,后端允许跨域,代理。由于本项目环境无法使用jsonp,所以就剩下后端允许跨域和代理两种办法了,让腾讯去为我们允许跨域?显然是不可能的,那么就只能用代理了吗?其实还有一种解决办法就是proxy,网上也有很多案例,这里我也贴出具体操作步骤:

    1.新建vue.config.js:

    module.exports = { devServer: { proxy: { "/api": { target: 'https://api.ai.qq.com', changeOrigin: true, pathRewrite: { '^/api': '/' } } } } };

    2.设置request.js中axios的baseUrl=‘/api’

    const request = axios.create({ baseURL: '/api', timeout: 8000 })

    这种办法最大的缺点就是只能用于开发环境,无法用于生产环境,所以其实并没有什么卵用,只用来自己做项目联系倒是有点用!而我本人则是使用nodejs代理的方式实现,但项目中给大家的示例是使用的proxy方式,大家在没有相关资源的情况下,用这种方法进行练习也是可以的!

    这里贴出ApiChat.js相关代码:

    import request from "@/api/base/request"; import md5 from 'js-md5'; export function getChatResponse(text) { return request({ url:'fcgi-bin/nlp/nlp_textchat?'+getChatParams(text), method: 'get' }) } function getChatParams(text) { let app_id = 2151744249; let app_key = 'AWNcQGMMWi0OUceN'; let nonce_str = 'fa577ce340859f9fe'; let question = encodeURIComponent(text); let session = 10000; let time_stamp = parseInt(Date.now() / 1000); let params = 'app_id=' + app_id + '&nonce_str=' + nonce_str + '&question=' + question + '&session=' + session + '&time_stamp=' + time_stamp + '&app_key=' + app_key; let sign = md5(params).toUpperCase() return params+'&sign='+sign }

    剩下的主要就是请求接口和展示数据了: Chat.vue:

    <script> import Vue from "vue"; import {getChatResponse} from "@/api/ApiChat"; import LeftItem from "@/components/LeftItem"; import RightItem from "@/components/RightItem"; Vue.directive('scroll', { inserted(el) { el.scrollIntoView() } }) export default { name: "Chat", components: {LeftItem, RightItem}, data: () => { return { text: '', msglist: [{ id: 1, type: 1, content: '欢迎你!', me: false }] } }, methods: { send() { if (this.text) { this.msglist.push({ id: this.msglist[this.msglist.length - 1].id + 1, type: 1, content: this.text, me: true }) if (this.text === '图片') { this.msglist.push({ id: this.msglist[this.msglist.length - 1].id + 1, type: 2, content: 'http://6emm.hxzdhn.com/img/2020/06/28/jausoellbtf.jpg', me: false }) } else { this.getResponse(this.text) } this.text = '' } }, getResponse(text) { getChatResponse(text).then(res => { console.log(res) this.msglist.push({ id: this.msglist[this.msglist.length - 1].id + 1, type: 1, content: res.data.answer, me: false }) }) } } } </script>

    其中有一个需要注意的问题,就是聊天消息列表如何能自动滑动到底部? 网上有不少方法说的是用 el.scrollTop=el.offsetHeight这种方式解决,不过我没有试验成功!本项目是使用了vue自定义指令:v-scroll:

    Vue.directive('scroll', { inserted(el) { el.scrollIntoView() } })

    在li最下面放上一个高度为0的元素,并添加v-scroll指令:

    <li v-for="(item,index) in msglist" :key="index"> <RightItem :id="item.id" :type="item.type" :content="item.content" v-if="item.me"></RightItem> <LeftItem :id="item.id" :type="item.type" :content="item.content" v-else></LeftItem> <div v-scroll style="height: 0"></div> </li>

    github:https://github.com/baiyuliang/Qrobot_Vue

    Processed: 0.011, SQL: 9