1.效果

YOLOv11-智能体 YOLOv11和大模型结合,实现根据输入和图片内容,自动选择模型,识别出结果,分析结果,给出建议

2.代码

<template>
	<view class="chat-container">
		<!-- 聊天内容区域 -->
		<scroll-view class="message-list" scroll-y :scroll-with-animation="true" :scroll-top="scrollTop">
			<view v-for="(msg, index) in messages" :key="index" class="message-item" :class="msg.isMe ? 'me' : 'other'">
				<!-- 我的消息 -->
				<template v-if="msg.isMe">
					<view class="message-bubble">
						<!-- 如果消息中包含图片,则展示 -->
						<image v-if="msg.image" :src="msg.image" class="uploaded-image" mode="widthFix"></image>
						<text class="message-content">{{ msg.text }}</text>
					</view>
					<image class="avatar" :src="userAvatar" mode="aspectFill" />
				</template>
				<!-- AI 的消息 -->
				<template v-else>
					<image class="avatar" :src="aiAvatar" mode="aspectFill" />
					<view class="message-bubble">
						<!-- 修改这里:根据当前消息对象的 image 字段展示图片 -->
						<image v-if="msg.image" :src="msg.image" class="uploaded-image" mode="widthFix"></image>
						<text class="message-content">{{ msg.text }}</text>
					</view>
				</template>
			</view>
		</scroll-view>
		<!-- 底部输入栏 -->
		<view class="input-bar">
			<view class="uploaded-image-container" v-if="tempFilePath">
				<image :src="tempFilePath" class="uploaded-image0" mode="widthFix"></image>
			</view>
			<image class="upload-icon" src="/static/上传.png" @click="selectAndUploadImage"></image>
			<input class="input" v-model="inputMessage" placeholder="请输入消息" confirm-type="send"
				@confirm="sendMessage" />
			<button class="send-btn" @click="sendMessage">发送</button>
		</view>
	</view>
</template>
 
 
<script>
	export default {
		data() {
			return {
				// 不再依赖全局 imagePath 来展示 AI 图片
				// imagePath: '',
				fileId: '',
				uploadStatus: '',
				tempFilePath: '',
	
				inputMessage: '',
				messages: [],
				websocket: null,
				scrollTop: 0,
	
				responseMessage: '',
				uploadUrl: 'http://120.26.121.243:1000/v1/files/upload', // 更新为您的上传URL
				apiKey: 'app-KzmPaq3z46JZvaMX7zwkTDGd', // 更新为您的API密钥
				userId: 'abc-123', // 更新为您的用户ID
	
				reconnectAttempts: 0, // 重连尝试次数
				maxReconnectAttempts: 10, // 最大重连尝试次数
				userAvatar: 'https://756e-uniapp-8glahrpd1003d896-1344127270.tcb.qcloud.la/%E9%A6%99%E8%8F%87.png?sign=870e0498c9d22c4f0c2b2bed5881b90d&t=1741018450', // 用户头像路径
				aiAvatar: 'https://756e-uniapp-8glahrpd1003d896-1344127270.tcb.qcloud.la/AI.png?sign=7343ba007050b965e14e86fa31d1af45&t=1741018327' // AI 头像路径
			};
		},
		onReady() {
			this.connectWebSocket();
		},
		methods: {
			selectAndUploadImage() {
				uni.chooseImage({
					count: 1,
					sizeType: ['original', 'compressed'],
					sourceType: ['album', 'camera'],
					success: (res) => {
						const tempFilePath = res.tempFilePaths[0];
						this.tempFilePath = tempFilePath;
						this.uploadFile(tempFilePath);
					},
				});
			},
	
			uploadFile(filePath) {
				uni.uploadFile({
					url: this.uploadUrl,
					filePath: filePath,
					name: 'file',
					header: {
						'Authorization': `Bearer ${this.apiKey}`,
						'user': this.userId,
					},
					success: (uploadFileRes) => {
						const parsedData = JSON.parse(uploadFileRes.data);
						const fileId = parsedData.id;
						this.fileId = fileId; // 存储 fileId 到组件数据中
						console.log('File uploaded with ID:', fileId);
					},
					fail: (err) => {
						console.error('上传失败:', err);
						uni.showToast({
							title: '上传失败',
							icon: 'none',
						});
					},
				});
			},
	
			connectWebSocket() {
				this.websocket = uni.connectSocket({
					url: 'ws://localhost:8000/api/chat',
					success: () => console.log('WS连接创建'),
					fail: (err) => {
						console.error('WS连接失败:', err);
						this.reconnectWebSocket(); // 连接失败时尝试重连
					}
				});
	
				this.websocket.onOpen(() => {
					console.log('WS已连接');
					this.reconnectAttempts = 0; // 重置重连尝试次数
				});
	
				this.websocket.onMessage((res) => {
					console.log('Received message data:', res.data);
					// 当收到 "azsr1011" 时,开始下载图片并展示
					if (res.data === 'azsr1011') {
						this.downloadImage();
						return;
					}
	
					// 普通消息处理:若上一次消息是 AI 的则追加文本,否则新建消息
					const lastMessage = this.messages[this.messages.length - 1];
					if (lastMessage && !lastMessage.isMe) {
						lastMessage.text += res.data;
					} else {
						this.messages.push({
							text: res.data,
							isMe: false,
							time: new Date().toLocaleTimeString()
						});
					}
					this.scrollToBottom();
				});
	
				this.websocket.onClose(() => {
					console.log('WS连接关闭');
					this.reconnectWebSocket(); // 连接关闭时尝试重连
				});
	
				this.websocket.onError((err) => {
					console.error('WS错误:', err);
					this.reconnectWebSocket(); // 连接出错时尝试重连
				});
			},
	
			reconnectWebSocket() {
				if (this.reconnectAttempts >= this.maxReconnectAttempts) {
					console.error('已达到最大重连尝试次数,无法重新连接');
					return;
				}
	
				const reconnectDelay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000); // 最大延迟 30s
				console.log(
					`WS尝试重新连接 (${this.reconnectAttempts + 1}/${this.maxReconnectAttempts}) 次后将等待 ${reconnectDelay}ms...`
				);
	
				setTimeout(() => {
					this.reconnectAttempts += 1;
					console.log(`正在尝试第 ${this.reconnectAttempts} 次重连...`);
					this.connectWebSocket();
				}, reconnectDelay);
			},
	
			sendMessage() {
				// 如果输入消息为空且没有 fileId,则不执行任何操作
				if (!this.inputMessage.trim() && !this.fileId) return;
	
				// 准备新的消息对象
				const newMsg = {
					text: this.inputMessage,
					isMe: true,
					time: new Date().toLocaleTimeString(),
					fileId: this.fileId, // 包含 fileId
				};
	
				// 当点击发送时,同时在我的消息冒泡中展示图片(如果有)
				if (this.tempFilePath) {
					newMsg.image = this.tempFilePath;
				}
	
				this.messages.push(newMsg); // 将新消息添加到消息列表中
	
				// 准备要发送的数据对象
				const dataToSend = {
					text: this.inputMessage,
					fileId: this.fileId, // 在这里也包含 fileId
				};
	
				// 通过 WebSocket 发送数据
				this.websocket.send({
					data: JSON.stringify(dataToSend),
					success: () => {
						console.log('Message sent:', JSON.stringify(dataToSend));
						this.inputMessage = ''; // 清空输入框
						this.fileId = ''; // 清空 fileId
						this.tempFilePath = ''; // 清空临时文件路径
						this.scrollToBottom(); // 滚动到消息列表底部
					},
					fail: (err) => {
						console.error('发送失败:', err);
					},
				});
			},
	
			scrollToBottom() {
				this.$nextTick(() => {
					const query = uni.createSelectorQuery().in(this);
					query.select('.message-list').scrollIntoView('.message-item:last-child', {
						alignTo: 'center',
						duration: 300,
					});
				});
			},
	
			downloadImage() {
				uni.downloadFile({
					url: 'http://8.137.56.246:32797/get',
					header: {
						'Authorization': 'Bearer 123456'
					},
					success: (downloadRes) => {
						if (downloadRes.statusCode === 200) {
							const downloadedImage = downloadRes.tempFilePath;
							// 将下载到的图片添加为一个新的 AI 消息,不会覆盖之前的消息
							this.messages.push({
								text: '', // 图片消息中可以不包含文字,也可根据需要添加描述
								isMe: false,
								image: downloadedImage,
								time: new Date().toLocaleTimeString()
							});
							console.log('Downloaded image:', downloadRes);
						} else {
							uni.showToast({
								title: '下载失败:无效的状态码',
								icon: 'none'
							});
						}
						this.scrollToBottom();
					},
					fail: (err) => {
						uni.showToast({
							title: '下载失败',
							icon: 'none'
						});
						console.error('Download failed:', err);
					}
				});
			},
		}
	};
</script>
 
 
<style>
	.chat-container {
		height: 100vh;
		display: flex;
		flex-direction: column;
	}
 
	.message-list {
		flex: 1;
		padding: 20rpx;
		background-color: #f5f5f5;
		overflow-y: auto;
		margin-bottom: 100rpx;
	}
 
	.message-item {
		display: flex;
		align-items: flex-start;
		margin: 10px 0;
	}
 
	.me {
		justify-content: flex-end;
	}
 
	.other {
		justify-content: flex-start;
	}
 
	.avatar {
		width: 72rpx;
		height: 72rpx;
		margin: 0 20rpx;
	}
 
	.message-bubble {
		max-width: 70%;
		padding: 16rpx 24rpx;
		padding-right: 14rpx;
		border-radius: 10rpx;
		position: relative;
		word-wrap: break-word;
		background-color: #ffffff;
		box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
	}
 
	.me .message-bubble {
		background-color: #95ec69;
		border-radius: 20rpx 4rpx 20rpx 20rpx;
		align-self: flex-end;
		max-width: 65%;
	}
 
	.other .message-bubble {
		background-color: #ffffff;
		border-radius: 4rpx 20rpx 20rpx 20rpx;
		align-self: flex-start;
		max-width: 66%;
	}
 
	.uploaded-image {
		max-width: 100%;
		height: auto;
		border-radius: 8rpx;
		margin-bottom: 10rpx;
	}
 
	.message-content {
		font-size: 32rpx;
		line-height: 1.5;
		color: #333;
		text-align: justify;
		text-align-last: justify;
	}
 
	.input-bar {
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		padding: 20rpx;
		display: flex;
		align-items: center;
		background-color: #fff;
		border-top: 2rpx solid #eee;
		flex-wrap: wrap;
	}
 
	.uploaded-image-container {
		margin-right: 20rpx;
		margin-bottom: 10rpx;
		display: flex;
		align-items: center;
		width: 100%;
	}
 
	.uploaded-image0 {
		max-width: 30%;
		height: auto;
		border-radius: 8rpx;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
	}
 
	.upload-icon {
		width: 28px;
		height: 28px;
		margin-right: 10px;
		cursor: pointer;
	}
 
	.input {
		flex: 1;
		height: 72rpx;
		padding: 0 20rpx;
		background-color: #f5f5f5;
		border-radius: 36rpx;
		margin-right: 20rpx;
	}
 
	.send-btn {
		background-color: #07c160;
		color: white;
		height: 72rpx;
		line-height: 72rpx;
		padding: 0 40rpx;
		border-radius: 36rpx;
		font-size: 28rpx;
	}
</style>

 

 

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐