赞
踩
uniapp中renderjs使用主要解决在APP端无法使用web端的js问题
如果只开发web端就不用考虑renderjs 跨端app中可以使用,解决通信阻塞问题
这是一个在app端使用sse的方案
下面展示一些。
<template> <!-- #ifdef APP --> <page-meta :root-font-size="footSize" style="display: block;"></page-meta> <!-- #endif --> <view class="page-top"> <!-- #ifdef APP --> <view class="status_bar"> <view class="top_view"></view> </view> <!-- #endif --> <uni-nav-bar fixed class="nav-title" left-icon="back" :title="aiName" backgroundColor="#f8f8f8" @clickLeft="toPrev"></uni-nav-bar> <view class="cu-chat"> <blockquote v-for="(item,index) in chatList" :key="item.id"> <view class="cu-item" :class="{'self':item.self == 1}" v-if="item.self == 1"> <view class="main"> <view class="content shadow"> <text class="self-content">{{item.content}}</text> </view> </view> <view class="cu-avatar radius" :style="{'background-image': 'url('+item.avatarImg+')'}"></view> </view> <view class="cu-item" v-else> <view class="cu-avatar radius" :style="{'background-image': 'url('+item.avatarImg+')'}"></view> <view class="main"> <view class="content shadow"> <text class="self-content">{{item.content}}</text> </view> <view class="flex chat-tools" v-if="item.isEnd && !item.self"> <view class="reloadContent cu-btn bg-blue sm" @click="reloadContent()" v-if="chatList.length == (index+1)"> 刷新 </view> <view class="copyContent cu-btn bg-blue sm" @click="copyContentBtn(item.content)"> 复制 </view> </view> </view> </view> </blockquote> </view> <view class="cu-bar foot input"> <input class="solid-bottom" :placeholder="placeholderStr" v-model="content" placeholder-class="input-placeholder" :adjust-position="false" :focus="false" maxlength="2500" cursor-spacing="10"></input> <button :prop="msg" :change:prop="renderScript.onChange" class="cu-btn bg-blue shadow" :disabled="ifSend" @click="sendMsg">发送</button> </view> </view> </template> <script> // import {BASE_URL} from '@/util/request.js' import {copyContent} from '@/util/tools.js' // import {EventSourcePolyfill} from 'event-source-polyfill' import avatarDef from '@/static/img/avatar_deft.png' import aislogo from '@/static/img/aislogo.png' export default { data() { return { footSize: this.$footFontSize, msg:{//监听msg中的变化去执行renderjs中的onchange方法 userId:'', conversationId:'', renderContent:'' }, chatList:[], answerWords:[], eventSource:null, contentIdx:0, placeholderStr:'', aiLoadding:'', aiName:'', content:'', welcome:'', ifSend:false, conversationId:'', userId:'', quesId:'', quesIds:'', subjectId:'', planId:'', batchId:'', userPlanId:'', user:{ nickName: '', avatar: avatarDef, }, aiUser:{ nickName: '', avatar: aislogo, } } }, onLoad(options){ this.quesId = options.quesID; this.quesIds = options.quesIds; this.subjectId = options.subjectId; this.planId = options.planId; this.batchId = options.batchId; this.userPlanId = options.userPlanId; let buffer = { quesId:this.quesId } var that = this; this.$myRequest({ url:'/api/bot/conversation', method:'POST', data:{ userPlanId:this.userPlanId, quesId:this.quesId, ran:Math.random() } }).then(res=>{ that.welcome = res.data.welcome; that.conversationId = res.data.conversation_id; that.content = res.data.first_content; that.userId = res.data.userId; that.placeholderStr = res.data.placeholder; that.aiLoadding = res.data.aiLoadding; that.aiName = res.data.aiName; that.msg.userId = res.data.userId; that.msg.conversationId = res.data.conversation_id; that.msg.renderContent = res.data.first_content; that.firstChat(); }) }, methods: { firstChat(){ //首次进入在内容生成之前发送按钮不可使用 this.ifSend = true; this.chatList.push({ modelRole: this.aiUser.nickName, avatarImg: this.aiUser.avatar, self: 0, id: +new Date(), content: this.welcome, isEnd: false, isList:false }) this.chatList.push({ modelRole: this.user.nickName, avatarImg: this.user.avatar, self: 1, id: +new Date()+1, content: this.content, isEnd: false, isList:false }) this.chatList.push({ modelRole: this.aiUser.nickName, avatarImg: this.aiUser.avatar, self: 0, id: +new Date()+10, content: this.aiLoadding, isEnd: false, isList:false }) this.content = ''; this.scrollBottom(10000); //创建EventSource 并发起会话 // this.eventSourceBox(); }, eventSourceBox(){ let lastItem = this.chatList[this.chatList.length - 1]; var that = this; const url = BASE_URL+"/stream-chat/chat.php?question="+encodeURIComponent(this.content.replace(/\+/g, '{[$add$]}'))+"&conversationId="+this.conversationId+"&userId="+this.userId; this.eventSource = new EventSourcePolyfill(url); this.eventSource.onopen = (event)=>{ console.log("连接已建立"); } this.content = ''; lastItem.contentList = []; this.eventSource.onmessage = (event)=>{ try { var result = JSON.parse(event.data); // console.log(result); if(result.time && result.content ){ lastItem.isList = true; that.ifSend = true;//没有生成完毕禁止点击 if(lastItem.content == this.aiLoadding){ lastItem.content = ''; lastItem.content += result.content; }else{ lastItem.content += result.content; } that.contentIdx += 1; that.scrollBottom(); } } catch (error) { console.log(error); } } // this.chatList[this.chatList.length - 1]['contentList']; this.eventSource.onerror = (event)=>{ let lastItem = that.chatList[that.chatList.length - 1]; this.eventSource.close(); lastItem.isEnd = true; that.ifSend = false; console.log((new Date().getTime()), 'answer end error') // console.error("发生错误:", JSON.stringify(event)); // console.error("发生错误:"); } this.eventSource.onclose = (event)=>{ let lastItem = that.chatList[that.chatList.length - 1]; // console.log("连接已关闭", JSON.stringify(event.data)); this.eventSource.close(); isEnd = true; console.log((new Date().getTime()), 'answer end close'); } }, sendMsg(){ if (!this.content) { return uni.showToast({ title:'发送内容不能为空', icon:'none' }); } this.chatList.push({ modelRole: this.user.nickName, avatarImg: this.user.avatar, self: 1, id: +new Date()+1, content: this.content, }) this.chatList.push({ modelRole: this.aiUser.nickName, avatarImg: this.aiUser.avatar, self: 0, id: +new Date()+10, content: this.aiLoadding, isEnd: false, isList:false }) this.ifSend = true; this.msg.renderContent = this.content; this.content = ''; this.$nextTick(this.scrollBottom()); //创建eventSource // this.eventSourceBox(); }, scrollBottom(height){ const query = uni.createSelectorQuery().select('.page-top'); query.boundingClientRect((data) => { let pageScrollTop = Math.round(data.height); if(height != undefined){ pageScrollTop = height; } // console.log(pageScrollTop); setTimeout(() => { uni.pageScrollTo({ scrollTop: pageScrollTop, //滚动的距离 duration: 0, //过渡时间 }) },50) }).exec() }, toPrev(){ uni.reLaunch({ url:'/pages/print/worksDetail/worksDetail?batchId='+this.batchId+'&subjectId=' + this.subjectId + "&quesIds=" + this.quesIds + "&planId=" + this.planId + '&userPlanId=' +this.userPlanId }) }, copyContentBtn(item){ copyContent(item) }, reloadContent(){ let ques = this.chatList[this.chatList.length - 2]['content']; this.chatList[this.chatList.length - 1]['content'] = this.aiLoadding; this.chatList[this.chatList.length - 1]['isEnd'] = false; this.ifSend = true; // console.log(ques); this.msg.renderContent = ''; this.msg.renderContent = ' '+ques; this.$nextTick(this.scrollBottom()); // this.eventSourceBox(); }, // 接收renderjs发回的数据 acceptDataFromRenderjs(options) { let lastItem = this.chatList[this.chatList.length - 1]; this.ifSend = true;//没有生成完毕禁止点击 if(lastItem.content == this.aiLoadding){ lastItem.content = ''; lastItem.content += options.messageData; }else{ lastItem.content += options.messageData; } this.scrollBottom(); // this.projNotices = JSON.parse(options.type) }, acceptDataFromRenderjsEnd(options){ let lastItem = this.chatList[this.chatList.length - 1]; lastItem.isEnd = options.renderIsEnd; this.ifSend = options.renderIfSend;//没有生成完毕禁止点击 } } } </script> <script module="renderScript" lang="renderjs"> import {BASE_URL} from '@/util/request.js' import {EventSourcePolyfill} from 'event-source-polyfill' export default { data(){ return { message:'', renderIsEnd:false, renderIfSend:false } }, mounted() { }, methods: { onChange(newValue, oldValue, ownerInstance, instance){ if(newValue.userId != '' && newValue.conversationId != ''){ this.sse(newValue.userId,newValue.conversationId,newValue.renderContent) } }, // 发送数据到service层 emitData() { // #ifdef APP UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', { cid: this._$id, method: 'acceptDataFromRenderjs', args: { messageData: this.messageData } }) // #endif // #ifdef H5 var options = { messageData:this.messageData }; this.acceptDataFromRenderjs(options); // #endif }, emitDataEnd(){ // #ifdef APP UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', { cid: this._$id, method: 'acceptDataFromRenderjsEnd', args: { renderIsEnd: this.renderIsEnd, renderIfSend:this.renderIfSend } }) // #endif // #ifdef H5 var options = { renderIsEnd: this.renderIsEnd, renderIfSend:this.renderIfSend }; this.acceptDataFromRenderjsEnd(options); // #endif }, sse(userId,conversationId,renderContent){ // console.log(renderContent); let that = this; const url = BASE_URL+"/stream-chat/chat.php?question="+encodeURIComponent(renderContent.replace(/\+/g, '{[$add$]}'))+"&conversationId="+conversationId+"&userId="+userId; const eventSource = new EventSourcePolyfill(url); eventSource.onopen = (event)=>{ console.log("连接已建立"); } eventSource.onmessage = (event)=>{ var result = JSON.parse(event.data); if(result.time && result.content ){ that.messageData = ''; that.messageData = result.content; that.emitData(); } } eventSource.onerror = (event)=>{ console.log((new Date().getTime()), 'answer end error') that.renderIsEnd = true; that.renderIfSend = false; that.emitDataEnd(); } eventSource.onclose = (event)=>{ // console.log("连接已关闭", JSON.stringify(event.data)); eventSource.close(); console.log((new Date().getTime()), 'answer end close'); } } } } </script> <style lang="less"> /* #ifdef APP */ page { background-color: #F1F1F1; } /* #endif */ </style> <style lang="less" scoped> /* #ifdef H5 */ page { background-color: #F1F1F1; } /* #endif */ /* #ifdef APP */ .status_bar { height: var(--status-bar-height); width: 100%; } .top_view { height: var(--status-bar-height); width: 100%; position: fixed; background-color: #F8F8F8; top: 0; z-index: 999; } /* #endif */ .nav-title /deep/ .uni-nav-bar-text{ font-size: 0.3rem; overflow: initial; } .cu-avatar{ background-color: #ffffff !important; } .self-content{ overflow: auto; } .main{ flex-direction: column; align-items: flex-end !important; } .chat-tools{ padding: 10rpx; justify-content: flex-end; } .chat-tools .cu-btn{ border-radius: 10rpx; margin-left: 12rpx; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。