| 
					
				 | 
			
			
				@@ -1,6 +1,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <template>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		<u-navbar title="对话" bgColor="transparent" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}">
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		<u-navbar title="对话" bgColor="#F6F6F8" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}">
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			<view class="u-nav-slot" slot="left" style="display: flex;background-color: transparent;">
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/09/10/2f7cc90a-848c-4369-b573-4448125591a9.png" style="width: 45rpx;height: 45rpx;" @tap="toBack"></image>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				<!-- <image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/09/10/3580b8d2-8ddb-4385-8516-fb6f47ce5fea.png" style="width: 42rpx;height: 42rpx;margin-left: 40rpx;" @tap="startNewDialog"></image> -->
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -40,7 +40,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 								</view>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							</template>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							<template v-else>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								<u-parse :content="item.answer"></u-parse>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								<u-parse :content="item.answer" style="font-size: 28rpx;line-height: 54rpx;color: #252525;"></u-parse>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							</template>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							<div class="dc_btns adfacjb" v-if="item.answer">
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 								<div class="db_l">
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -49,7 +49,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 									<image :src="item.comment?require('@/static/comment_active.png'):require('@/static/comment.png')" @tap="toComment(item,index)"></image>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 								</div>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 								<div class="db_r">
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								<!-- 	<image :src="item.share?require('@/static/share_active.png'):require('@/static/share.png')" @tap="toShare(item,index)"></image> -->
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									<image :src="item.share?require('@/static/share_active.png'):require('@/static/share.png')" @tap="toShare(item,index)"></image>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 								</div>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							</div>
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						</div>
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -81,166 +81,198 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	let requestTask = null;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	import { BaseApi } from '../http/baseApi.js'
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	import * as TextEncoding from "text-encoding-shim";
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import { webSocketConnect } from '@/common/xiaoZhiConnect.js';
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	export default {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		data(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				isDialog:false,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				retryCount: 3, // 最大重试次数
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				currentRetry: 0, // 当前重试次数
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				isRequesting: false, // 请求状态锁
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				question:'',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				streamingResponse:'',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				receivedData:'',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				dialogList:[],
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				windex:0,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				commentShow:false,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				content:'',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				cindex:'',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				chzq:false,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				lwss:false,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				fixBottom: 0
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				fixBottom: 0,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 对话
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				config: {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					deviceMac: '',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					deviceName: '小智AI设备',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					clientId: 'uniapp_xiaozhi_client',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					token: 'xiaozhi-ai',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					otaUrl: 'http://i.ringzle.com:8002/xiaozhi/ota/',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					serverUrl: 'ws://i.ringzle.com:8000/xiaozhi/v1/'
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				isConnected: false,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				textMessage: '',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				socketTask: null,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		computed: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			displayMac() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return this.config.deviceMac; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			displayClient() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return this.config.clientId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		onReady() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		    uni.onKeyboardHeightChange(res => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		      this.fixBottom = res.height||0;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		    });
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		onLoad(option) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.config.deviceMac = option?.deviceMac;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.connectToServer();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		onUnload() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.disconnectFromServer();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		    uni.offKeyboardHeightChange();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			this.fixBottom = 0;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		methods:{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			toBack(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				uni.navigateBack();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			startNewDialog(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				clearInterval(timer)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				this.dialogList = [];
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				this.question = '';
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				this.streamingResponse = '';
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// 封装带重试机制的请求方法
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			async sendRequestWithRetry() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if (this.isRequesting) return;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				this.isRequesting = true;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				this.currentRetry = 0;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				try {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					await this._executeRequest();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} catch (error) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					  this.$showToast('请求失败,请稍后重试')
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} finally {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					this.isRequesting = false;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			async connectToServer() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (this.socketTask) return;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				console.log('开始连接流程...');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const task = await webSocketConnect(
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.config.otaUrl,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.config.serverUrl,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.config
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if(task) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.socketTask = task;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.setupSocketListeners();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			_executeRequest2(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return new Promise((resolve, reject) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					this.$api.post('/core/chat/sendChatMessageStream',{query:this.question},false).then(res=>{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						if(res.data.code!==0) return this.$showToast(res.data.msg)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						let answer = this.dialogList[this.dialogList.length-1].answer+res.data.data;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						this.$set(this.dialogList[this.dialogList.length-1],'answer',answer);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						this.$set(this.dialogList[this.dialogList.length-1],'think',false);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						setTimeout(()=>{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							this.scrollToBottom();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						},100)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						resolve()
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			setupSocketListeners() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.socketTask.onOpen(() => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.isConnected = true;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log('WebSocket连接已打开', 'success');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.sendHelloMessage();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.socketTask.onClose(() => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.isConnected = false;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log('WebSocket连接已关闭', 'info');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.socketTask = null;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.socketTask.onError((err) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.isConnected = false;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log(`WebSocket错误: ${JSON.stringify(err)}`, 'error');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.socketTask.onMessage((res) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (typeof res.data === 'string') {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						this.handleTextMessage(res.data);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} else {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						this.handleBinaryMessage(res.data);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// 实际执行请求的方法
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			_executeRequest() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return new Promise((resolve, reject) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					requestTask = uni.request({
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						url: `${BaseApi}/core/chat/sendChatMessageStream`,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						method: 'POST',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						timeout: 10000,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						data:{ 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							query: this.question,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							identity:'被教练者',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						header: {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						  'Content-Type': 'application/json',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						  'token': uni.getStorageSync('token') || ''
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						enableChunked: true, // 启用流式接收
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						responseType:'text',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						success: (res) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							if (res.statusCode === 200) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								this._handleSuccess(res.data);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								resolve();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							} else {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								this._handleError(`状态码异常: ${res.statusCode}`, resolve, reject);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						fail: (err) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							this._handleError(err.errMsg, resolve, reject);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						complete: (com) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							console.log('请求完成',com)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					requestTask.onChunkReceived(async (res) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						const uint8Array = new Uint8Array(res.data);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						const decoder = new TextEncoding.TextDecoder("utf-8");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						const decodedString = decoder.decode(uint8Array);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						try {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							let newtext = decodedString.replaceAll('data:','').replaceAll(':keepAlive','');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							let ntArr = newtext.split('\n\n');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							if(ntArr.length){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								ntArr.forEach(n=>{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-									if(!n.trim()) return
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-									let nj = JSON.parse(n);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-									if(nj.event=='message'){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										let answer = this.dialogList[this.dialogList.length-1].answer+nj.answer?.replace(/(\r\n|\n|\r)+/g, '<br>');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										this.$set(this.dialogList[this.dialogList.length-1],'answer',answer);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										this.$set(this.dialogList[this.dialogList.length-1],'id',nj.id);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										this.$set(this.dialogList[this.dialogList.length-1],'task_id',nj.task_id);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										this.$set(this.dialogList[this.dialogList.length-1],'message_id',nj.message_id);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										this.$set(this.dialogList[this.dialogList.length-1],'conversation_id',nj.conversation_id);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-										this.$set(this.dialogList[this.dialogList.length-1],'think',false);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-									}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								setTimeout(()=>{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-									this.scrollToBottom();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								},100)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						} catch (e) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							console.error('解析失败', e, '原始数据:', decodedString);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			disconnectFromServer() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (this.socketTask) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.socketTask.close({
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						code: 1000,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						reason: 'manual disconnection'
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log('手动断开连接', 'info');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sendSocketMessage(data) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!this.isConnected || !this.socketTask) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log('无法发送消息,连接未建立', 'error');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				uni.sendSocketMessage({
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					data: data,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					fail: (err) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						console.log(`发送消息失败: ${JSON.stringify(err)}`, 'error');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				});
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// 成功处理
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			_handleSuccess(data) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if (data) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				  this.streamingResponse += data;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sendHelloMessage() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const helloMessage = {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					type: 'hello',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					device_id: this.config.deviceMac,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					device_name: this.config.deviceName,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					device_mac: this.config.deviceMac,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					token: this.config.token,
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					features: { mcp: true }
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				};
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				console.log('发送hello握手消息', 'info');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.sendSocketMessage(JSON.stringify(helloMessage));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			addConversationMessage(text, isUser = false) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				console.log(text,isUser);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				text = text+'<br>'
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if(!isUser){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					let answer = this.dialogList[this.dialogList.length-1].answer+text?.replace(/(\r\n|\n|\r)+/g, '<br>');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.$set(this.dialogList[this.dialogList.length-1],'answer',answer);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.$set(this.dialogList[this.dialogList.length-1],'think',false);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					setTimeout(()=>{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						this.scrollToBottom();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					},100)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				this.currentRetry = 0; // 重置重试计数器
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// 错误处理
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			_handleError(errorMsg, resolve, reject) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if (this._shouldRetry(errorMsg)) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					this.currentRetry++;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					setTimeout(() => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						this._executeRequest().then(resolve).catch(reject);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					}, this._getRetryDelay());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				} else {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					reject(errorMsg);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sendTextMessage() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const message = this.question.trim();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!message) return;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const listenMessage = {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					type: 'listen',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					mode: 'manual',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					state: 'detect',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					text: message
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				};
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.sendSocketMessage(JSON.stringify(listenMessage));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.addConversationMessage(message, true);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				console.log(`发送文本: ${message}`, 'info');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			handleTextMessage(jsonString) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				try {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const message = JSON.parse(jsonString);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log(`收到文本消息: ${message.type}`, 'debug');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					switch (message.type) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						case 'hello':
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							console.log(`服务器回应: Session ID ${message.session_id}`, 'success');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							break;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						case 'tts':
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							if(message.state === 'sentence_start' && message.text) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.addConversationMessage(message.text);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							break;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						case 'llm':
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							if(message.text && message.text !== '😊') {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.addConversationMessage(message.text);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							break;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						default:
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							console.log(`收到消息: ${jsonString}`, 'info');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} catch (e) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log(`解析JSON失败: ${e.message}`, 'error');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.log(`原始数据: ${jsonString}`, 'debug');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// 判断是否需要重试
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			_shouldRetry(errorMsg) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				const retryableErrors = [
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					'timeout', 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					'request:fail', 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					'Network Error'
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				];
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return this.currentRetry < this.retryCount && retryableErrors.some(e => errorMsg.includes(e));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			handleBinaryMessage(arrayBuffer) {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				console.log(`收到二进制数据,大小: ${arrayBuffer.byteLength}字节`, 'debug');
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// 获取指数退避延迟时间
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			_getRetryDelay() {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return Math.min(1000 * Math.pow(2, this.currentRetry), 10000);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			toBack(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				uni.navigateBack();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			startNewDialog(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				uni.showModal({
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					title:'温馨提示',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					content:'是否开启新的一轮对话?',
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					success: (res) => {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if(res.confirm){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							clearInterval(timer)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.dialogList = [];
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.question = '';
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			sendQuestion(){
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				if(!this.question) return this.$showToast('请输入您的问题');
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -257,7 +289,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				this.dialogList = [...this.dialogList,...[qa]];
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				this.$nextTick(()=>{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					this.scrollToBottom();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					this.sendRequestWithRetry();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.sendTextMessage();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					this.question = '';
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			},
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -321,7 +353,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	.page{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		background: linear-gradient( 227deg, #EEEFF8 0%, #F6ECF4 100%, #F6ECF4 100%);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		background: #F6F6F8;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		padding: 0 30rpx 200rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		box-sizing: border-box;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -356,6 +388,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			padding-top: 34rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			box-sizing: border-box;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			overflow-y: auto;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			padding-bottom: 50rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			.d_answer{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				margin-top: 40rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				&.init{
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -409,13 +442,13 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				display: flex;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				justify-content: flex-end;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				.dq_text{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					background: #833478;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					background: #D9F159;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					border-radius: 24rpx 4rpx 24rpx 24rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					font-family: PingFangSC, PingFang SC;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					font-weight: 400;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					font-size: 30rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					color: #FFFFFF;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					line-height: 48rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					font-size: 28rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					color: #252525;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					line-height: 40rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					// text-align: right;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					padding: 26rpx 30rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				}
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -424,7 +457,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		.ask_box{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			width: 100%;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			min-height: 176rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			background: linear-gradient( 227deg, #EEEFF8 0%, #F6ECF4 100%, #F6ECF4 100%);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			background: #F6F6F8;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			padding: 0 30rpx 60rpx;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			position: fixed;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			left: 0;
 
			 |