Browse Source

替换智能体组件

dev_des
1054425342@qq.com 1 month ago
parent
commit
8cd5aedce3
  1. 436
      components/GPT/index.vue
  2. 209
      components/GPT/utils/audio.js
  3. 127
      components/GPT/utils/pcm-player.js
  4. 10
      components/GPT/utils/socket.js
  5. 2
      components/GPT/utils/util.js
  6. 9
      components/IPComponents.vue

436
components/GPT/index.vue

@ -5,12 +5,21 @@
<!-- <ClientChat @send="onSendQuestion" /> -->
<scroll-view class="chat-wrapper" :scroll-into-view="bottom" :scroll-y="true" :scroll-with-animation="true" scroll-into-view-offset="10">
<view class="list-container">
<view class="info">
<view class="head-img">
<image class="rot-head-img" :src="robotObj.headImage"></image>
</view>
<view class="rot-title">
<view>你好我是数字领航员</view>
<view>{{ robotObj.name }}</view>
</view>
</view>
<!-- for循环 -->
<view class="chat-list" v-for="n,index in msgList" :key="index">
<view class="msg-container other" v-if="n.type =='reply' ">
<image class="ava" :src="robotObj.headImage"></image>
<!-- <image class="ava" :src="robotObj.headImage"></image> -->
<view class="msg">
<view class="msg-nickname">{{robotObj.name}}</view>
<!-- <view class="msg-nickname">{{robotObj.name}}</view> -->
<view :class="n.contentType==='img' ? 'msg-content-img' : '' " class="msg-content">
<template v-if="n.pending">
<Pending></Pending>
@ -19,8 +28,8 @@
<template v-if="n.contentType === 'text'">
<rich-text v-if="n.contentType === 'text'" :nodes="n.content"></rich-text>
<view v-if="n.is_final" class="msg-btns">
<image mode="widthFix" class="btn-img" @click="copy(n.content)" src="./../../static/imgs/icon-copy.png"></image>
<image mode="widthFix" class="btn-img" @click="audio(n)" :src="audioActive == n.timestamp ? './../../static/imgs/icon-bf-active.png':'./../../static/imgs/icon-bf.png'"></image>
<image class="btn-img" @click="copy(n.content)" src="./../../static/imgs/icon-copy.png"></image>
<image class="btn-img" @click="audio(n)" :src="audioActive == n.timestamp ? './../../static/imgs/icon-bf-active.png':'./../../static/imgs/icon-bf.png'"></image>
</view>
</template>
@ -47,33 +56,43 @@
</view>
<view class="chat-wrap__main-footer">
<view class="disabled-loadding" v-if="disabledStatus"></view>
<view class="chatinput-wrapper">
<view class="chatinput-content">
<view class="chatinput-btn-wrap">
<image :src="videoStatus ? './../../static/imgs/icon-txt.png' :'./../../static/imgs/icon-video.png'" class='chatinput-img' @click="changeVideoStatus"></image>
</view>
<view class='chatinput-input-wrap' v-if="videoStatus">
<view style="text-align: center; flex: 1" @longpress="startVideo" @touchend="stopVideo">
按住 说话
<view style="text-align: center; flex: 1; color:#9FA0A0" @longpress="startVideo" @touchend="stopVideo">
点击 说话
</view>
</view>
<view v-else class='chatinput-input-wrap'>
<input v-model="inputValue" @focus="inputFocus" @input="inputChange" @confirm="inputSend" placeholder="想对TA说点什么呢…" confirm-type='send' />
</view>
<view class="chatinput-btn-wrap">
<image v-if="!isEditInput" src="./../../static/imgs/icon-pic.png" class='chatinput-img' @click="tapChooseImage"></image>
<button v-if="isEditInput" class="chatinput-send">发送</button>
<!-- <image v-if="!isEditInput" :src="videoStatus ? './../../static/imgs/icon-txt.png' :'./../../static/imgs/icon-video.png'" class='chatinput-img' @click="changeVideoStatus"></image> -->
<!-- <image v-if="!isEditInput" src="./../../static/imgs/icon-pic.png" class='chatinput-img' @click="tapChooseImage"></image> -->
<!-- <button v-if="isEditInput" class="chatinput-send">发送</button> -->
<template v-if="videoStatus">
<image src="./../../static/imgs/icon-txt.png" class="chatinput-img" @click="changeVideoStatus"></image>
</template>
<template v-else>
<image v-if="inputValue" src="./../../static/imgs/icon-up.png" class='chatinput-img' @click="inputSend"></image>
<image v-else src="./../../static/imgs/icon-video.png" class='chatinput-img' @click="changeVideoStatus"></image>
</template>
</view>
</view>
</view>
</view>
<!-- <live-player src="https://domain/pull_stream" mode="RTC" autoplay bindstatechange="statechange" binderror="error" style="width: 300px; height: 225px;" /> -->
</view>
</template>
<script>
import Socket from './utils/socket'
import Audio from './utils/audio'
import PCMPlayer from './utils/pcm-player'
import { splitTextForTTS } from './utils/util'
import {
getHistroyMsg,
@ -122,7 +141,9 @@ export default {
lastTxt: {},
txtAudioStaus: {},
requestMsg: {},
disabledStatus: false
disabledStatus: false,
audioOBJ: null,
reAudioType: false
}
},
onLoad() {
@ -135,122 +156,193 @@ export default {
console.log('【destroy message connect type------>】',);
this.socketObj.selfCloseStatus = true
this.socketObj.destroy()
this.audioOBJ.selfCloseStatus = true
this.audioOBJ.destroy()
this.audioCtx && this.audioCtx.destroy()
this.audioCtx = null
this.audioActive = ''
this.audioStatus = false
this.asrStatus = false
this.player && this.player.destroy()
},
onHide() {
console.log('【hide message connect type------>】',);
},
onShow() {
this.scrollToBottom()
},
methods: {
/* 4. 滚动日志 */
appendLog(str) {
console.log(1111, str)
},
async init() {
this.player = new PCMPlayer({
sampleRate: 16000,
onPlay: (obj) => {
console.log('播放文字', obj)
this.disabledStatus = true
if (obj.is_final) {
//
console.log('=========最后一条语音=========', obj);
this.disabledStatus = false //
this.audioActive = ''
}
if (this.reAudioType) {
return
}
const index = self.msgList.findIndex(it => it.request_id == obj.request_id && it.type == 'reply')
if (index > -1) {
self.msgList[index].content += obj.content
self.msgList[index].is_final = obj.is_final
self.$nextTick(() => {
self.scrollToBottom()
})
} else {
if (self.msgList.length) {
const item = self.msgList[self.msgList.length - 1]
const tmpinfo = {
timestamp: new Date().getTime(),
name: this.robotObj.name,
headImage: this.robotObj.headImage,
type: 'reply',
contentType: 'text',
...item,
pending: false,
request_id: obj.request_id,
content: obj.content,
}
if (item.pending) {
self.msgList[self.msgList.length - 1] = tmpinfo
self.$nextTick(() => {
self.scrollToBottom()
})
} else {
self.msgList.push(tmpinfo)
}
} else {
const tmp = {
...obj,
type: 'reply',
contentType: 'text',
timestamp: new Date().getTime(),
name: this.robotObj.name,
headImage: this.robotObj.headImage,
content: obj.content,
pending: false
}
self.msgList.push(tmp)
self.$nextTick(() => {
self.scrollToBottom()
})
}
}
self.scrollToBottom()
},
onAudioEnd: () => {
console.log('语音播放结束')
},
})
// 使
// const player = new AudioStreamPlayer()
this.audioOBJ = new Audio({
onMessage: (e) => {
if (e instanceof ArrayBuffer) {
this.player.feed(e)
return
}
if (e.type == 2) {
//
if (e.data.result && e.data) {
this.player.addText(e.data)
}
}
if (e.type == 3) {
//
}
return
if (e instanceof ArrayBuffer) {
//
player.processChunk(e)
return
}
if (e.type == 2) {
//
player.processChunkTxt(e.data.result)
}
if (e.type == 0) {
//
// player.play((txt) => {
// const index = self.msgList.findIndex(it => it.request_id == e.request_id && it.type == 'reply')
// if (index > -1) {
// self.msgList[index].content += txt
// self.$nextTick(() => {
// self.scrollToBottom()
// })
// } else {
// if (self.msgList.length) {
// const obj = self.msgList[self.msgList.length - 1]
// if (obj.pending) {
// const tmp = {
// ...e,
// pending: false,
// content: txt
// }
// self.msgList[self.msgList.length - 1] = tmp
// self.$nextTick(() => {
// self.scrollToBottom()
// })
// } else {
// self.msgList.push(e)
// }
// } else {
// const tmp = {
// ...e,
// content: txt,
// pending: false
// }
// self.msgList.push(tmp)
// self.$nextTick(() => {
// self.scrollToBottom()
// })
// }
// }
// self.scrollToBottom()
// })
//
// player.processChunk()
}
}
})
this.audioOBJ.init()
this.audioStatus = true
this.asrStatus = true
uni.showLoading()
console.log('【init message connect type------>】',);
const self = this
this.socketObj = new Socket({
agentId: this.agentId,
onMessage: (e) => {
console.log(e.request_id + '回复内容', e.content)
// const index = this.msgList.findIndex(it => it.request_id == e.request_id && it.type == 'reply')
// this.tmpMsg[e.request_id] = this.tmpMsg[e.request_id] ?? []
// if (this.tmpMsg[e.request_id].length) {
// const txt = e.content
// if (txt) {
// this.tmpMsg[e.request_id].push(txt)
// }
// } else {
// this.tmpMsg[e.request_id].push(e.content)
// }
// this.lastTxt[e.request_id] = e.content
// if (!this.txtAudioStaus[e.request_id]) {
// this.txtAudioStaus[e.request_id] = true
// this.renderTxt(e)
// }
// console.log(e.content)
e.pending = false
//
// if (index > -1) {
// this.msgList[index] = {
// ...e,
// content: this.msgList[index].content + e.content
// }
// } else {
// if (this.msgList.length) {
// const obj = this.msgList[this.msgList.length - 1]
// if (obj.pending) {
// this.$nextTick(() => {
// this.msgList[this.msgList.length - 1] = e
// })
// } else {
// this.msgList.push(e)
// }
// } else {
// this.msgList.push(e)
// }
// }
// //
// if (!e.is_from_self && e.is_final) {
// setMsgData(this.msgList[index])
// }
this.requestMsg[e.request_id] = (this.requestMsg[e.request_id] ? this.requestMsg[e.request_id] : '') + e.content
self.requestMsg[e.request_id] = (self.requestMsg[e.request_id] ? self.requestMsg[e.request_id] : '') + e.content
if (!e.is_from_self && e.is_final) {
e.content = this.requestMsg[e.request_id]
e.content = self.requestMsg[e.request_id]
const audioParams = e
//
//
setMsgData(audioParams)
console.log('开始',audioParams);
this.audio(audioParams, (txt)=> {
const index = this.msgList.findIndex(it => it.request_id == e.request_id && it.type == 'reply')
console.log(1111111, txt, index)
if (index > -1) {
console.log(11111111, this.msgList[index].content, txt)
this.msgList[index].content += txt
this.$nextTick(() => {
this.scrollToBottom()
})
} else {
if (this.msgList.length) {
const obj = this.msgList[this.msgList.length - 1]
if (obj.pending) {
const tmp = {
...e,
pending: false,
content: txt
}
this.msgList[this.msgList.length - 1] = tmp
this.$nextTick(() => {
this.scrollToBottom()
})
} else {
this.msgList.push(e)
}
} else {
const tmp = {
...e,
content: txt,
pending: false
}
this.msgList.push(tmp)
this.$nextTick(() => {
this.scrollToBottom()
})
}
}
this.scrollToBottom()
})
// //
// this.disabledStatus = false
console.log('开始', audioParams);
self.audio(audioParams, true)
}
this.scrollToBottom()
self.scrollToBottom()
}
})
this.getRecord(this.agentId)
@ -262,15 +354,19 @@ export default {
this.robotObj = this.socketObj.robotObj
wx.hideLoading()
this.sendMsg()
wx.setNavigationBarTitle({
title: '数字领航员-' + this.robotObj.name
})
},
async renderTxt(e) {
for (let index = 0; index < this.tmpMsg[e.request_id].length; index++) {
const txt = this.tmpMsg[e.request_id][index];
const params = {
content: txt,
timestamp: e.timestamp
}
await this.audio(params)
const params = {
content: txt,
timestamp: e.timestamp
}
await this.audio(params)
}
},
sendMsg() {
@ -293,32 +389,42 @@ export default {
});
},
async audio(n, cb) {
console.log('【audio------>】', n);
this.audioArray = this.audioArray.slice(-10)
async audio(n, status) {
console.log('【audio------>】', n, status);
this.reAudioType = !status
this.audioArray = []
// this.audioArray = this.audioArray.slice(-10)
const txt = this.stripHtmlTags(n.content)
if (!txt) { return }
this.audioCtx && this.audioCtx.destroy()
this.audioCtx = null
if (this.audioActive == n.timestamp) {
this.audioActive = ''
return
}
const texts = splitTextForTTS(txt)
console.log('语言划分', texts)
this.audioActive = n.timestamp
for (let index = 0; index < texts.length; index++) {
const txt = texts[index];
const nextText = texts[index + 1] ?? ''
if (nextText) {
this.loadAudioUrl(nextText)
this.player && this.player.destroy()
uni.request({
method: "post",
data: {
sessionId: this.audioOBJ.session_id,
text: txt,
voiceType: this.socketObj.robotObj.voiceType ?? 1002
},
dataType: "json",
url: `https://des.js-dyyj.com/xcx/api/voice/tts/flow`,
success: (res) => {
this.audioActive = n.timestamp
},
fail: (err) => {
wx.showToast({
title: '识别失败',
icon: 'error'
});
},
complete: () => {
}
await this.audioText(txt, cb)
}
this.disabledStatus = false //
this.audioActive = ''
});
},
audioText(text, cb) {
@ -331,11 +437,19 @@ export default {
this.audioCtx = wx.createInnerAudioContext();
this.audioCtx.src = 'data:audio/wav;base64,' + url
// this.audioCtx.src = 'data:audio/wav;base64,'+ url
// console.log('App Launch', this.audioCtx.src)
this.audioCtx.play()
this.audioCtx.onStop(() => {
console.log('语音播放停止', text)
resolve()
})
this.audioCtx.onEnded(() => {
console.log('语音播放结束', text)
resolve()
})
this.audioCtx.onError((error) => {
console.log('语音播放失败', text, error)
resolve()
})
});
@ -626,6 +740,28 @@ export default {
}
</script>
<style scoped lang="scss">
.info {
display: flex;
align-items: center;
flex-direction: column;
padding-top: 100rpx;
.head-img {
width: 35vw;
height: 35vw;
.rot-head-img {
width: 100%;
height: 100%;
}
}
.rot-title {
margin-top: 40rpx;
font-weight: bold;
font-size: 26rpx;
text-align: center;
}
}
.chat-wrap__main {
display: flex;
flex-direction: column;
@ -633,7 +769,7 @@ export default {
height: 100%;
min-height: 700px;
overflow: hidden;
background: var(--color-bg-0);
background: #f8f8f8;
border-radius: 12px;
&-chat-content {
@ -663,7 +799,6 @@ export default {
padding-bottom: 10px;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
background-color: #f8f8f8;
position: relative;
.disabled-loadding {
@ -682,17 +817,21 @@ export default {
// border-top: 1px solid #ddd;
// border-bottom: 1px solid #ddd;
.chatinput-content {
height: 100rpx;
padding: 10rpx 0 20rpx;
height: 80rpx;
padding: 20rpx;
border-radius: 10rpx;
display: flex;
align-items: center;
margin: 0 20rpx;
background: #fff;
.chatinput-input-wrap {
flex: 1;
height: 80rpx;
padding: 0 20rpx;
box-sizing: border-box;
display: flex;
align-items: center;
color: #9fa0a0;
background: #fff;
input {
height: 76rpx;
@ -726,6 +865,10 @@ export default {
}
}
}
image {
width: 40rpx;
height: 40rpx;
}
}
}
@ -749,29 +892,32 @@ export default {
.msg-content {
box-sizing: border-box;
word-wrap: break-word;
max-width: 60vw;
padding: 8px;
border-radius: 5rpx;
max-width: 80vw;
padding: 30rpx 30rpx 20rpx;
border-radius: 10rpx;
background: #fff;
border: 1px solid #e7e7e7;
/* border: 1px solid #e7e7e7; */
max-width: "calc(100vw - 110px)";
color: #000;
font-size: 28rpx;
.msg-btns {
border-top: 1px solid #e7e7e7;
margin-top: 5px;
padding-top: 10px;
margin-top: 40rpx;
padding-top: 20rpx;
border-top: 1px dashed #000;
.btn-img {
margin: 0 10px;
width: 20px;
height: 20px;
margin-right: 10px;
width: 40rpx;
height: 40rpx;
cursor: pointer;
}
}
}
&.self {
justify-content: flex-end;
padding-right: 10px;
padding-right: 40rpx;
.msg {
display: flex;
flex-direction: column;
@ -783,12 +929,14 @@ export default {
}
.msg-content {
width: auto;
color: #fff;
background-color: #0097ff;
border-color: #0097ff;
color: #000;
background-color: #acf8f8;
/* border-color:#acf8f8; */
padding: 30rpx;
}
}
&.other {
padding-left: 40rpx;
.msg {
display: flex;
flex-direction: column;

209
components/GPT/utils/audio.js

@ -0,0 +1,209 @@
// 心跳间隔
const HEART_BEAT_TIME = 15000;
// 心跳最大失败次数(超过此次数重连)
const HEART_BEAT_FAIL_NUM = 1;
// 重连间隔
const RECONNECT_TIME = 3000;
import { generateRequestId } from "./util";
export default class Audio {
constructor(option) {
this._options = option;
this.socket = null;
this.session_id = null;
this.selfCloseStatus = false
this.connectSocketTimeOut = null
}
getToken() {
return new Promise((resolve, reject) => {
console.log("-----开始请求token-----");
uni.request({
method: "GET",
dataType: "json",
// url: `http://192.168.124.118:8083/xcx/framework/agent/${this._options.agentId}`,
url: `https://des.js-dyyj.com/getDemoToken?id=${this._options.agentId}`,
success: (res) => {
console.log("请求token成功", res);
resolve(res);
},
fail: (err) => {
wx.showToast({
title: "创建失败",
icon: "none",
});
console.log("请求token失败", err);
reject();
},
});
});
}
async init() {
return this.createSocket();
}
async createSocket(options) {
console.log("开始创建socket", options);
return new Promise(async (resolve, reject) => {
const origin = "wss://des.js-dyyj.com/xcx/tts-websocket";
// 建立连接
const socket = wx.connectSocket({
url: `${origin}`,
success: (e) => {
console.log("创建语音长链接成功", e);
},
complete: (e) => {
console.log("socket - complete", e);
},
});
this.socket = socket;
socket.onOpen((e) => {
console.log("socket.onOpen", e);
// 监听发送
options && options.complete && options.complete();
});
socket.onMessage((e) => {
const { data } = e;
if (data instanceof ArrayBuffer) {
this._options.onMessage && this._options.onMessage(data);
} else {
if ( Object.prototype.toString.call(data) === "[object String]" ) {
const tmp = JSON.parse(data);
if (Object.prototype.toString.call(tmp.type) === "[object Number]") {
this._options.onMessage && this._options.onMessage(tmp);
} else {
if (!this.session_id) {
this.session_id = tmp.data
}
}
}
}
// this.on(type, e);
resolve();
// this.createInter();
});
// 失败
socket.onError((e) => {
console.log("websocket error 创建语音长链接报错", e);
//
});
// 关闭
socket.onClose((e) => {
console.log("websocket close 语音长链接关闭", e);
this.connectSocketTimeOut && clearTimeout(this.connectSocketTimeOut);
//非自动关闭重连
if (e.code != 1000) {
this.doConnectTimeout();
}
});
});
}
doConnectTimeout() {
if (this.selfCloseStatus){
// 主动退出 不在重连
return
}
// 重连一次
console.log("websocket 异常关闭 开始重连");
this.connectSocketTimeOut = setTimeout(() => {
this.createSocket({
complete: function (res) {
// this.reconnectLock = false;
},
});
}, RECONNECT_TIME);
}
send(e, t) {
console.log("开始请求 websocket send", e);
this.socket && this.socket.send(e);
}
getMsgData(e) {
if (e && typeof e == "string") {
const status = e.indexOf("42");
const index = e.indexOf("[");
if (status > -1 && index > -1) {
const txt = e.substring(index);
const item = JSON.parse(txt);
const [type, obj] = item;
const payload = obj.payload ? obj.payload : {};
const params = {
chatId: this._options.agentId,
type,
contentType: "text", //默认文字
timestamp: new Date().getTime(),
...payload,
};
// 缓存聊天记录
return params;
}
}
return null;
}
emit(type, text, contentType) {
console.log("emit", type, text);
switch (type) {
case "send":
// 发送消息
// 发送消息
// const socketParams = {
// request_id: generateRequestId()
// };
const socketParams = {
session_id: this.session_id,
message_id: generateRequestId(),
action: "ACTION_SYNTHESIS",
data: text,
};
this.send({ data: JSON.stringify(socketParams) }, contentType);
break;
}
}
// 监听
on(type, params) {
switch (type) {
case "reply":
// 回复结束
const tmpParams = {
...params,
name: this.robotObj.name,
headImage: this.robotObj.headImage,
};
if (
params &&
params.type === "reply" &&
!params.is_from_self &&
params.can_rating
) {
// 回复消息
console.log("reply回复内容", tmpParams.content, tmpParams);
this._options.onMessage && this._options.onMessage(tmpParams);
}
if (!params.is_from_self && params.is_final) {
if (this.failMsg[tmpParams.request_id]) {
this.failMsg[tmpParams.request_id].status = true;
// 已回复 状态为true
}
// 回复结束 写入缓存
// setMsgData(tmpParams);
}
// 回复
break;
}
}
// 关闭socket
destroy() {
if (this.socket && this.socket.readyState == 1) {
this.socket && this.socket.close();
this.socket = null;
}
}
}

127
components/GPT/utils/pcm-player.js

@ -0,0 +1,127 @@
// utils/pcm-player.js
export default class PCMPlayer {
constructor(options) {
this.queue = [];
this._options = options
this.AllTexts = [];
this.audioCtx = null;
this.startTime = 0;
this._t = null
}
feed(data) {
if (!this.audioCtx) {
this.audioCtx = wx.createWebAudioContext();
}
this.playPCM(data);
}
playPCM(pcmBuffer, sampleRate = 16000) {
const length = pcmBuffer.byteLength / 2; // 16-bit = 2 bytes per sample
const audioBuffer = this.audioCtx.createBuffer(1, length, sampleRate);
const channelData = audioBuffer.getChannelData(0); // Float32Array
const view = new DataView(pcmBuffer);
// 将 16-bit PCM 转换为 Float32 [-1, 1]
for (let i = 0; i < length; i++) {
const sample = view.getInt16(i * 2, true); // little-endian
channelData[i] = sample / 0x8000; // convert to [-1, 1]
}
this.queue.push(audioBuffer);
if (!this.isPlaying) {
// 开始播放
this.startTime = this.audioCtx.currentTime ?? 0;
this.playNext();
this.isPlaying = true;
setTimeout(() => {
this.syncLoop();
});
}
}
// 监听音频播放进度
syncLoop() {
const loop = () => {
const now = this.audioCtx.currentTime - this.startTime;
// 找当前字幕
const index = this.AllTexts.findIndex(
(s) => now >= s.beginTime && now < s.endTime
);
if (index > -1) {
const obj = this.AllTexts[index];
if (this.AllTexts.length == 1) {
// 最后一条数据
obj.is_final = true
}
const tmp = this.AllTexts.shift();
this._options.onPlay && this._options.onPlay(tmp);
if (!this.AllTexts.length) {
clearTimeout(this._t);
return
}
}
if (!this.AllTexts.length) {
this._t = setTimeout(loop, 16);
} else {
if (now < this.AllTexts[this.AllTexts.length - 1].endTime) {
this._t = setTimeout(loop, 16);
} else {
// 结束
clearTimeout(this._t);
console.log('语音播放结束')
this.destroy()
}
}
};
loop();
}
playNext() {
if (this.queue.length === 0) {
// 结束
this.isPlaying = true;
return;
}
this.isPlaying = true;
const source = this.audioCtx.createBufferSource();
source.buffer = this.queue.shift();
source.connect(this.audioCtx.destination);
source.start();
source.onended = () => {
setTimeout(() => {
this.playNext();
});
};
}
// 增加文字
addText(res) {
if (res.result && res.result.subtitles && res.result.subtitles.length) {
const tmpText = res.result.subtitles.map((it) => {
return {
...it,
content: it.text,
beginTime: it.beginTime / 1000,
endTime: it.endTime / 1000,
request_id: res.requestId,
sessionId: res.sessionId
};
});
this.AllTexts = [...this.AllTexts, ...tmpText];
}
}
close() {
this.isPlaying = false;
this.audioCtx.close();
}
destroy() {
this.queue = [];
this.isPlaying = false;
this.audioCtx && this.audioCtx.close();
this.audioCtx = null;
this.AllTexts = [];
this.startTime = 0;
this._options.onAudioEnd && this._options.onAudioEnd()
}
}

10
components/GPT/utils/socket.js

@ -7,7 +7,7 @@ const HEART_BEAT_TIME = 15000;
// 心跳最大失败次数(超过此次数重连)
const HEART_BEAT_FAIL_NUM = 1;
// 重连间隔
const RECONNECT_TIME = 1000;
const RECONNECT_TIME = 3000;
export default class Socket {
constructor(option) {
@ -80,10 +80,6 @@ export default class Socket {
this.socket = socket;
GLOBAL_OBJ.SOCKET = this;
let systemEventEmit = (eventName, data) => {
Vue.prototype.$eventHub.$emit(eventName, data);
};
socket.onOpen((e) => {
// 监听发送
if (initSocket === 1) {
@ -126,7 +122,7 @@ export default class Socket {
if (data == 2) {
// 触发浪涌
this.send({
data: 3,
data: '3',
});
}
@ -156,7 +152,7 @@ export default class Socket {
console.log("websocket close 长链接关闭", e);
this.connectSocketTimeOut && clearTimeout(this.connectSocketTimeOut);
//非自动关闭重连
if (e.code == 1006) {
if (e.code != 1000) {
this.doConnectTimeout();
}
});

2
components/GPT/utils/util.js

@ -81,7 +81,7 @@ function escapeHtml (str) {
}
export const splitTextForTTS = (text, maxLength = 15) => {
export const splitTextForTTS = (text, maxLength = 25) => {
// 定义优先分割的标点符号
const punctuation = ['。', ',', ';', '?', '!', ',', ';', '?', '!', '、'];
let segments = [];

9
components/IPComponents.vue

@ -7,7 +7,6 @@
align-items: center;
justify-content: space-between;
"
@click="handleMoreClick"
>
<text class="title">文化IP合作体</text>
</div>
@ -39,7 +38,7 @@
class="carousel-item"
v-for="(item, index) in list"
:key="index"
@click="gotoUrlNew(item)"
@click="gotoDetail"
v-if="item && item.image"
>
<view class="issue-card">
@ -119,6 +118,12 @@ export default {
url:'/pages/index/readingBody'
})
},
gotoDetail(){
uni.showToast({
title:'功能暂未开放',
icon:'none'
})
},
getList() {
// this.Post(
// {

Loading…
Cancel
Save