微信小程序 | 借ChatGPT之手重构社交聊天小程序
Posted 陶人超有料
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序 | 借ChatGPT之手重构社交聊天小程序相关的知识,希望对你有一定的参考价值。
一、 ChatGPT效果分析
体验过ChatGPT
这一产品的小伙伴对于GPT模型的恢复效果不知道有没有一种让人感觉到真的在和真人交流的感觉。不管你的问题有多么的刁钻,它总是能以一种宠辱不惊的状态回复你。
但是对于一些很无理的要求,它有的时候也是很果断的😂
没有体验过的小伙伴也可以直接从效果图中看出,AI的每一句回答都是一个字一个字或者一小段一小段地给予回复,给人一种无比地丝滑感,这才是真的真的聊天啊!
那么这个时候,如果可以把ChatGPT
这个AI的丝滑聊天动效直接迁移到我们现在使用的聊天场景中来,把这些死板的、一次性的消息框效果直接全量优化!让我们的社交更加具有趣味性!😜
二、关键技术点
针对这一效果我们静下心来思考一下你会发现:ChatGPT
的这个聊天框的响应反馈不仅仅是有一个动态光标的存在,更重要的是它返回的真的有够快的。
试想一下,按照我们在日常开发中的发起Http请求
业务开发过程中,都是在三次握手
之后客户端与服务端才开始交流感情!而且都是要到后端处理完全部逻辑之后才进行数据的返回,然后前端再拿这些数据进行渲染操作,所以要做到这么快就有两种设想:
- (1)后端处理完全部逻辑后速度返回,前端速度解析,然后配以光标效果进行渲染。(
Bug:数据量一爆炸,前端的响应速度并不能保证!
) - (2)后端一边处理一边返回数据,前端同时接收并渲染。(
后端服务采用流式数据响应,从而实现不等待式实时渲染
)
2.1 前端动效的支持
ChatGPT
中对话框进行文字输入的时候,我们可以明显看到,在每个文字的后面都有一个闪烁的光标,正是这一效果可以给予用户一种真在动态输入的感觉,让体验倍加丝滑!
要实现这一效果,我们可以使用定时器,每100毫秒逐个渲染出文本内容,并在文本后面添加了一个闪烁的光标。注意要在组件中设置ref属性来获取span元素的引用。
<template>
<div>
<span ref="text"></span><span ref="cursor" class="blink">_</span>
</div>
</template>
<script>
export default
mounted()
const text = this.$refs.text;
const cursor = this.$refs.cursor;
const textContent = "这是一段需要逐个渲染的文字";
let index = 0;
setInterval(() =>
if (index <= textContent.length)
text.textContent = textContent.slice(0, index);
cursor.style.opacity = index % 2 === 0 ? 1 : 0;
index++;
, 100);
,
;
</script>
<style>
.blink
animation: blink-animation 1s steps(1) infinite;
@keyframes blink-animation
0%
opacity: 0;
50%
opacity: 1;
100%
opacity: 0;
</style>
2.2 消息数据的实时响应
在前端中,可以使用流式处理(Streaming)的方式,实时加载从 HTTP 请求返回的 JSON 数据。这种方式可以避免一次性加载大量数据所造成的性能问题,而是在数据流到达时逐步处理数据。
以下是使用流式处理加载 JSON 数据的示例代码:
function loadJSON(url, onData)
let xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.responseType = 'json'
xhr.onprogress = function()
let chunk = xhr.response.slice(xhr.loaded, xhr.response.length)
onData(chunk)
xhr.onload = function()
if (xhr.status === 200)
onData(xhr.response)
xhr.send()
在上面的代码中,定义了一个 loadJSON 函数
,该函数使用 XMLHttpRequest 对象
发送 GET 请求
,并指定 responseType:json
参数。然后,在 onprogress 事件
中,获取从服务器返回的 JSON 数据
的最新一块数据,并通过 onData 回调函数将数据传递给客户端。在 onload 事件
中,将最后一块数据发送给客户端。
三、丝滑聊天功能实现
3.1 小程序端
- 光标元素
- 完整代码
<template>
<view class="content">
<view class="content-box" @touchstart="touchstart" id="content-box" :class="'content-showfn':showFunBtn">
<!-- 背景图- 定位方式 -->
<image class="content-box-bg" :src="_user_info.chatBgImg" :style=" height: imgHeight "></image>
<view class="content-box-loading" v-if="!loading"><u-loading mode="flower"></u-loading></view>
<view class="message" v-for="(item, index) in messageList" :key="index" :id="`msg-$item.hasBeenSentId`">
<view class="message-item " :class="item.isItMe ? 'right' : 'left'">
<image class="img" :src="item.fromUserHeadImg" mode="" @tap="linkToBusinessCard(item.fromUserId)"></image>
<!-- contentType = 1 文本 -->
<view class="content" v-if="item.contentType == 1">
<!-- <span ref="text" value="item.content"></span><span ref="cursor" class="blink">_</span> -->
<!-- generateTextSpan(item,index)
<span :ref="'text'+index" :value="item.content" :index="index"></span>
<span ref="cursor" class="blink">_</span> -->
<chat-record :content="item.content"></chat-record>
</view>
<!-- <view class="content" v-if="item.contentType == 1"> item.content </view> -->
<!-- contentType = 2 语音 -->
<view
class="content contentType2"
:class="[ 'content-type-right': item.isItMe ]"
v-if="item.contentType == 2"
@tap="handleAudio(item)"
hover-class="contentType2-hover-class"
:style="width:`$130+(item.contentDuration*2)rpx`"
>
<view
class="voice_icon"
:class="[
voice_icon_right: item.isItMe ,
voice_icon_left: !item.isItMe ,
voice_icon_right_an: item.anmitionPlay && item.isItMe ,
voice_icon_left_an: item.anmitionPlay && !item.isItMe
]"
></view>
<view class=""> item.contentDuration ''</view>
</view>
<!-- contentType = 3 图片 -->
<view
class="content contentType3"
v-if="item.contentType == 3"
@tap="viewImg([item.content])"
>
<image :src="item.content" class="img" mode="widthFix"></image>
</view>
</view>
</view>
</view>
<!-- 底部聊天输入框 -->
<view class="input-box" :class=" 'input-box-mpInputMargin': mpInputMargin ">
<view class="input-box-flex">
<!-- #ifndef H5 -->
<image v-if="chatType === 'voice'" class="icon_img" :src="require('@/static/voice.png')" @click="switchChatType('keyboard')"></image>
<image v-if="chatType === 'keyboard'" class="icon_img" :src="require('@/static/keyboard.png')" @click="switchChatType('voice')"></image>
<!-- #endif -->
<view class="input-box-flex-grow">
<input
v-if="chatType === 'voice'"
type="text"
class="content"
id="input"
v-model="formData.content"
:hold-keyboard="true"
:confirm-type="'send'"
:confirm-hold="true"
placeholder-style="color:#DDDDDD;"
:cursor-spacing="10"
@confirm="sendMsg(null)"
/>
<view
class="voice_title"
v-if="chatType === 'keyboard'"
:style=" background: recording ? '#c7c6c6' : '#FFFFFF' "
@touchstart.stop.prevent="startVoice"
@touchmove.stop.prevent="moveVoice"
@touchend.stop="endVoice"
@touchcancel.stop="cancelVoice"
>
voiceTitle
</view>
</view>
<!-- 功能性按钮 -->
<image class=" icon_btn_add" :src="require('@/static/add.png')" @tap="switchFun"></image>
<!-- #ifdef H5 -->
<button class="btn" type="primary" size="mini" @touchend.prevent="sendMsg(null)">发送</button>
<!-- #endif -->
</view>
<view class="fun-box" :class="'show-fun-box':showFunBtn">
<u-grid :col="4" hover-class="contentType2-hover-class" :border="false" @click="clickGrid">
<u-grid-item v-for="(item, index) in funList" :index="index" :key="index" bg-color="#eaeaea">
<u-icon :name="item.icon" :size="52"></u-icon>
<view class="grid-text"> item.title </view>
</u-grid-item>
</u-grid>
</view>
</view>
<!-- //语音动画 -->
<view class="voice_an" v-if="recording">
<view class="voice_an_icon">
<view id="one" class="wave"></view>
<view id="two" class="wave"></view>
<view id="three" class="wave"></view>
<view id="four" class="wave"></view>
<view id="five" class="wave"></view>
<view id="six" class="wave"></view>
<view id="seven" class="wave"></view>
</view>
<view class="text">voiceIconText</view>
</view>
</view>
</template>
<script>
import chatRecord from '@/components/chatRecord/index.vue'
export default
components:chatRecord,
data()
return
lines:[],
fromUserInfo: ,
formData:
content: '',
limit: 15,
index: 1
,
messageList: [],
loading: true, //标识是否正在获取数据
imgHeight: '1000px',
mpInputMargin: false, //适配微信小程序 底部输入框高度被顶起的问题
chatType:"voice", // 图标类型 'voice'语音 'keyboard'键盘
voiceTitle: '按住 说话',
Recorder: uni.getRecorderManager(),
Audio: uni.createInnerAudioContext(),
recording: false, //标识是否正在录音
isStopVoice: false, //加锁 防止点击过快引起的当录音正在准备(还没有开始录音)的时候,却调用了stop方法但并不能阻止录音的问题
voiceInterval:null,
voiceTime:0, //总共录音时长
canSend:true, //是否可以发送
PointY:0, //坐标位置
voiceIconText:"正在录音...",
showFunBtn:false, //是否展示功能型按钮
AudioExam:null, //正在播放音频的实例
funList: [
icon:"photo-fill",title:"照片",uploadType:["album"] ,
icon:"camera-fill",title:"拍摄",uploadType:["camera"] ,
],
;
,
updated(<自己做一个ChatGPT微信小程序(代码开源)
自己做一个ChatGPT微信小程序(代码开源)
微信扫一扫 或者 微信搜索 superBot 即可找到
离职在家 闲来无事看最近ChatGPT很火 花了一天时间 用Uniapp写了一个小程序端的ChatGPT,实在是看不惯~ 一大堆利用ChatGPT收费的应用(小程序) 整个开源的玩玩
另外主要是自己本身是后端开发人员~ 刚好用uniapp实践一下小程序开发
先看看主页面效果图吧
演示视频-> 学会自己开发ChatGPT3.5turbo小程序( 含小程序开源代码)
说一下大概有的功能
- 微信小程序已上线 搜索 SuperBot
- 模型新增GPT3.5增强版( 响应速度先比之前的模型快很多很多 ) 旧的模型也有保留 请在lottie悬浮窗中开启 (默认使用003 推荐使用turbo 响应速度更快)
- Lottie动画悬浮球控制台 可开启历史回溯 清除Ai会话 主/次页面返回 清理页面数据
- Ai回复内容时模拟文字打印机+手机短频震动效果 如不喜欢 两者可在配置文件中选择性开启
- 支持Ai回复的内容包含代码高亮 java .net c++ css html c python php sql go 如不够可自行添加高亮文件
- 支持ai渲染内容选择性复制 如果Ai回复内容为 代码 则长按复制代码
- 支持Ai保留会话功能 (能记住你的上一次对话,最多5条 可配置更改, 比如 用户: 中国历史有多长?Ai: 5000年 用户:那和美国相比呢?ai:中国更长!支持手动清除 或自动监测清除
- 支持开启历史回溯 ( 下一次打开保留对话记录和会话信息)
- 点击自己的回答时会直接填入文本框中清除
- 支持开启历史回溯 ( 下一次打开保留对话记录和会话信息)
- 点击自己的回答时会直接填入文本框中
支持发布的平台
只测试了
- 微信小程序
- 支付宝小程序
- 抖音小程序
- 其他的未测试
如何使用呢?
GitHub地址: dulaiduwang003/ChatGPT_wechat (github.com) 感觉可以或者喜欢的话可以点个star
以上是关于微信小程序 | 借ChatGPT之手重构社交聊天小程序的主要内容,如果未能解决你的问题,请参考以下文章