Просмотр исходного кода

修复发布微信小程序相关问题

jiuling 2 месяцев назад
Родитель
Сommit
45daa9731c

+ 17 - 4
components/common/LocationPicker.vue

@@ -10,14 +10,20 @@
         disabled
       />
       <view class="suffix-icons">
+        <!-- 清除按钮 -->
         <view 
           v-if="innerValue && displayLabel"
           @click.stop="clearAddress"
           class="clear-btn"
         >
-          <text class="clear-icon">×</text>
+          <text class="clear-icon"></text> 
         </view>
-        <text class="arrow-icon">></text>
+      
+        <!-- 箭头 -->
+        <text 
+          v-else
+          class="arrow-icon"
+        ></text> 
       </view>
     </view>
     
@@ -386,17 +392,24 @@ if (props.modelValue) {
   height: 32rpx;
 }
 
-.clear-icon {
+.clear-icon{
   font-size: 32rpx;
   color: #999;
   line-height: 1;
 }
+.clear-icon::after{
+  content: "×";
+}
 
-.arrow-icon {
+.arrow-icon{
   font-size: 24rpx;
   color: #999;
 }
 
+.arrow-icon::after {
+	content: ">";
+}
+
 .location-text {
   font-size: 28rpx;
   color: #333;

+ 17 - 8
components/common/jessibuca.vue

@@ -158,13 +158,29 @@ const resize = () => {
 
 // 创建播放器
 const create = () => {
+  // #ifdef H5
+  // H5 环境使用 CDN 加载 decoder
+  const decoderUrl = '/jessibuca/decoder.js'
+  // #endif
+  
+  // #ifdef MP-WEIXIN
+  // 微信小程序不支持 jessibuca,这里不应该被调用
+  console.warn('Jessibuca is not supported in WeChat Mini Program')
+  return
+  // #endif
+
   const options = {
     container: container.value,
     autoWasm: true,
     background: '',
     controlAutoHide: false,
     debug: false,
-    decoder: 'static/js/jessibuca/decoder.js',
+    // #ifdef H5
+    decoder: decoderUrl,
+    // #endif
+    // #ifndef H5
+    decoder: '',
+    // #endif
     forceNoOffscreen: false,
     hasAudio: typeof props.hasAudio === 'undefined' ? true : props.hasAudio,
     heartTimeout: 5,
@@ -255,7 +271,6 @@ const create = () => {
   })
   // #endif
 }
-
 // 播放按钮点击
 const playBtnClick = () => {
   play(props.videoUrl)
@@ -451,12 +466,6 @@ defineExpose({
 </script>
 <!-- #endif -->
 
-<!-- #ifndef H5 -->
-<script setup>
-// 非 H5 平台不支持 Jessibuca
-console.warn('Jessibuca component is only supported on H5 platform')
-</script>
-<!-- #endif -->
 
 <style>
 .jessibuca-container {

+ 4 - 4
components/common/video-player.vue

@@ -64,7 +64,7 @@ const loadError = ref(false)
 const instance = getCurrentInstance()
 
 // 初始化Jessibuca播放器(H5环境)
-const initJessibucaPlayer = () => {
+/* const initJessibucaPlayer = () => {
   if (!isH5.value || !instance?.appContext.config.globalProperties.$jessibuca) {
     console.error('H5环境或Jessibuca插件未初始化')
     loadError.value = true
@@ -112,7 +112,7 @@ const initJessibucaPlayer = () => {
     console.error('Jessibuca播放器初始化失败:', err)
     loadError.value = true
   })
-}
+} */
 
 // 初始化小程序live-player
 const initLivePlayer = () => {
@@ -257,7 +257,7 @@ watch(() => props.videoUrl, () => {
   if (isH5.value && jessibucaPlayer.value) {
     destroyPlayer()
     nextTick(() => {
-      initJessibucaPlayer()
+      // initJessibucaPlayer()
     })
   }
 })
@@ -268,7 +268,7 @@ onMounted(() => {
   // #ifdef H5
   isH5.value = true
   nextTick(() => {
-    initJessibucaPlayer()
+    // initJessibucaPlayer()
   })
   // #endif
   

+ 1 - 0
main.js

@@ -4,6 +4,7 @@ import App from './App.vue'
 import * as filters from './utils/filters.js'
 import store from './store'
 import uviewPlus from 'uview-plus'
+import 'uview-plus/index.scss'
 
 export function createApp() {
   const app = createSSRApp(App)

+ 11 - 1
manifest.json

@@ -106,9 +106,19 @@
     },
     "mp-weixin" : {
         "appid" : "wxc738cddfb96a9176",
+        "lazyCodeLoading" : "requiredComponents",
         "mergeVirtualHostAttributes" : true,
         "setting" : {
-            "urlCheck" : false
+            "urlCheck" : false,
+            "minified" : true,
+            "packOptions" : {
+                "ignore" : [
+                    {
+                        "type" : "file",
+                        "value" : "static/js/jessibuca/decoder.wasm"
+                    }
+                ]
+            }
         },
         "permission" : {
             "scope.userLocation" : {

+ 10 - 7
package-lock.json

@@ -3859,11 +3859,14 @@
 			}
 		},
 		"node_modules/baseline-browser-mapping": {
-			"version": "2.9.17",
-			"resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz",
-			"integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==",
+			"version": "2.10.8",
+			"resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz",
+			"integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==",
 			"bin": {
-				"baseline-browser-mapping": "dist/cli.js"
+				"baseline-browser-mapping": "dist/cli.cjs"
+			},
+			"engines": {
+				"node": ">=6.0.0"
 			}
 		},
 		"node_modules/binary-extensions": {
@@ -4075,9 +4078,9 @@
 			}
 		},
 		"node_modules/caniuse-lite": {
-			"version": "1.0.30001765",
-			"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz",
-			"integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==",
+			"version": "1.0.30001780",
+			"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz",
+			"integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==",
 			"funding": [
 				{
 					"type": "opencollective",

+ 13 - 6
pages/dashboard/index.vue

@@ -18,7 +18,9 @@
           <text class="fixed-subtitle">田间环境概览</text>
         </view>
         <view class="refresh-btn" :class="{ 'rotating': isLoadingWeather }" @click.stop="handleRefresh">
-          <u-icon name="reload" :color="isLoadingWeather ? '#999' : '#3BB44A'" size="20"></u-icon>
+          <!-- <u-icon name="reload" :color="isLoadingWeather ? '#999' : '#3BB44A'" size="20"></u-icon> -->
+		  <!-- <uni-icons type="reload" color='#3BB44A'  size="20"></uni-icons> -->
+			<image src="/static/icons/reload.png" style="width:20px;height:20px;"></image>
         </view>
       </view>
 
@@ -165,14 +167,16 @@
     </view>
     
     <!-- 位置权限使用说明弹窗 -->
-    
+	<!-- #ifndef MP-WEIXIN  -->
     <u-popup 
+	ref="popup"
       :show="showLocationPermissionPopup" 
       mode="top" 
       round="20"
       :closeOnClickOverlay="false"
       :closeable="false"
       :safeAreaInsetTop="true"
+	   @change="showChange"
     >
       <view class="location-permission-popup">
         <view class="permission-header">
@@ -186,7 +190,7 @@
         </view>
       </view>
     </u-popup>
-
+<!-- #endif -->
     <!-- 天气详情弹窗 -->
 <!--    <u-popup 
       :show="showWeatherPopup" 
@@ -235,9 +239,8 @@
         </u-button>
       </view>
     </u-popup> -->
-
     <!-- 文章详情弹窗 -->
-    <u-popup 
+    <!-- <u-popup 
       :show="showArticlePopup" 
       mode="bottom" 
       round="20"
@@ -270,7 +273,7 @@
           去问 AI
         </u-button>
       </view>
-    </u-popup>
+    </u-popup> -->
   </view>
 </template>
 
@@ -424,6 +427,10 @@ const showLocationPermissionGuide = () => {
   showLocationPermissionPopup.value = true
 }
 
+const showChange= (e)=>{
+	showLocationPermissionPopup.value = e.showLocationPermissionPopup
+}
+
 /**
  * 关闭位置权限说明弹窗
  */

+ 109 - 109
pages/device/device-list/detail-camera.vue

@@ -60,13 +60,13 @@
 				</view>
 				<!-- #endif -->
 
-				<!-- #ifdef MP-WEIXIN -->
-				<live-player v-if="isPlaying" id="videoPlayer" :src="getMiniProgramStreamUrl" mode="live"
+				<!--wx-->
+				<!-- <live-player v-if="isPlaying" id="videoPlayer" :src="getMiniProgramStreamUrl" mode="live"
 					:autoplay="true" :muted="isMuted" object-fit="contain" @statechange="onStateChange"
-					@error="onVideoError" @fullscreenchange="onFullscreenChange" class="video-player"></live-player>
-				<!-- #endif -->
+					@error="onVideoError" @fullscreenchange="onFullscreenChange" class="video-player"></live-player> -->
+				
 
-				<!-- #ifdef APP-PLUS || APP-HARMONY -->
+				<!-- #ifndef H5 -->
 				<!-- <live-player v-if="isPlaying" id="appVideoPlayer" :src="getAppStreamUrl" mode="live"
 					:autoplay="true" :muted="isMuted" object-fit="contain" @statechange="onStateChange"
 					@error="onVideoError" @fullscreenchange="onFullscreenChange" 
@@ -322,7 +322,7 @@
 		// #endif
 		// #ifndef H5
 		// 非 H5 平台不支持 Jessibuca 视频播放
-		console.warn('当前平台不支持 Jessibuca 视频播放,请使用 uni-app video 组件')
+		// console.warn('当前平台不支持 Jessibuca 视频播放,请使用 uni-app video 组件')
 		// #endif
 	}
 	
@@ -385,7 +385,7 @@
 							console.warn('未获取到 wss_flv 流地址')
 						}
 						// #endif
-						// #ifdef APP-PLUS || APP-HARMONY
+						// #ifndef H5
 						deviceInfo.originalStreamUrl = res.data.data.fmp4 || deviceInfo.originalStreamUrl
 						// #endif
 					}).catch(err => {
@@ -409,27 +409,27 @@
 		if (!isPlaying.value) {
 			isPlaying.value = true
 
-			// #ifdef MP-WEIXIN
-			setTimeout(() => {
-				if (livePlayerContext.value) {
-					livePlayerContext.value.play({
-						success: () => {
-							console.log('小程序视频播放成功')
-							uni.vibrateShort()
-						},
-						fail: (err) => {
-							console.error('小程序视频播放失败:', err)
-							uni.showToast({
-								title: '视频播放失败',
-								icon: 'none'
-							})
-						}
-					})
-				}
-			}, 300)
-			// #endif
-
-			// #ifdef APP-PLUS || APP-HARMONY
+			// wx
+			// setTimeout(() => {
+			// 	if (livePlayerContext.value) {
+			// 		livePlayerContext.value.play({
+			// 			success: () => {
+			// 				console.log('小程序视频播放成功')
+			// 				uni.vibrateShort()
+			// 			},
+			// 			fail: (err) => {
+			// 				console.error('小程序视频播放失败:', err)
+			// 				uni.showToast({
+			// 					title: '视频播放失败',
+			// 					icon: 'none'
+			// 				})
+			// 			}
+			// 		})
+			// 	}
+			// }, 300)
+			
+
+			// #ifndef H5
 			setTimeout(() => {
 				if (appLivePlayerContext.value) {
 					appLivePlayerContext.value.play({
@@ -484,13 +484,13 @@
 			}
 			// #endif
 
-			// #ifdef MP-WEIXIN
-			if (livePlayerContext.value) {
-				livePlayerContext.value.pause()
-			}
-			// #endif
+			// wx
+			// if (livePlayerContext.value) {
+			// 	livePlayerContext.value.pause()
+			// }
+			
 
-			// #ifdef APP-PLUS || APP-HARMONY
+			// #ifndef H5
 			if (appLivePlayerContext.value) {
 				appLivePlayerContext.value.pause()
 			}
@@ -520,7 +520,7 @@
 		}
 		// #endif
 
-		// #ifdef APP-PLUS || APP-HARMONY
+		// #ifndef H5
 		// App端的静音通过 live-player 的 muted 属性控制,会自动响应
 		uni.showToast({
 			title: isMuted.value ? '已静音' : '已取消静音',
@@ -584,32 +584,32 @@
 		}
 		// #endif
 
-		// #ifdef MP-WEIXIN
-		if (livePlayerContext.value) {
-			if (isFullscreen.value) {
-				livePlayerContext.value.requestFullScreen({
-					direction: 90,
-					success: () => {
-						console.log('进入全屏模式成功')
-					},
-					fail: (err) => {
-						console.error('进入全屏模式失败:', err)
-					}
-				})
-			} else {
-				livePlayerContext.value.exitFullScreen({
-					success: () => {
-						console.log('退出全屏模式成功')
-					},
-					fail: (err) => {
-						console.error('退出全屏模式失败:', err)
-					}
-				})
-			}
-		}
-		// #endif
+		//wx
+		// if (livePlayerContext.value) {
+		// 	if (isFullscreen.value) {
+		// 		livePlayerContext.value.requestFullScreen({
+		// 			direction: 90,
+		// 			success: () => {
+		// 				console.log('进入全屏模式成功')
+		// 			},
+		// 			fail: (err) => {
+		// 				console.error('进入全屏模式失败:', err)
+		// 			}
+		// 		})
+		// 	} else {
+		// 		livePlayerContext.value.exitFullScreen({
+		// 			success: () => {
+		// 				console.log('退出全屏模式成功')
+		// 			},
+		// 			fail: (err) => {
+		// 				console.error('退出全屏模式失败:', err)
+		// 			}
+		// 		})
+		// 	}
+		// }
+		
 
-		// #ifdef APP-PLUS || APP-HARMONY
+		// #ifndef H5
 		if (appLivePlayerContext.value) {
 			if (isFullscreen.value) {
 				appLivePlayerContext.value.requestFullScreen({
@@ -652,45 +652,45 @@
 		}
 		// #endif
 
-		// #ifdef MP-WEIXIN
-		if (livePlayerContext.value && isPlaying.value) {
-			livePlayerContext.value.snapshot({
-				success: (res) => {
-					console.log('截图成功:', res.tempImagePath)
-					uni.saveImageToPhotosAlbum({
-						filePath: res.tempImagePath,
-						success: () => {
-							uni.showToast({
-								title: '截图已保存到相册',
-								icon: 'success'
-							})
-						},
-						fail: (err) => {
-							console.error('保存截图失败:', err)
-							uni.showToast({
-								title: '保存截图失败',
-								icon: 'none'
-							})
-						}
-					})
-				},
-				fail: (err) => {
-					console.error('截图失败:', err)
-					uni.showToast({
-						title: '截图失败',
-						icon: 'none'
-					})
-				}
-			})
-		} else {
-			uni.showToast({
-				title: '请先播放视频',
-				icon: 'none'
-			})
-		}
-		// #endif
+		
+		// if (livePlayerContext.value && isPlaying.value) {
+		// 	livePlayerContext.value.snapshot({
+		// 		success: (res) => {
+		// 			console.log('截图成功:', res.tempImagePath)
+		// 			uni.saveImageToPhotosAlbum({
+		// 				filePath: res.tempImagePath,
+		// 				success: () => {
+		// 					uni.showToast({
+		// 						title: '截图已保存到相册',
+		// 						icon: 'success'
+		// 					})
+		// 				},
+		// 				fail: (err) => {
+		// 					console.error('保存截图失败:', err)
+		// 					uni.showToast({
+		// 						title: '保存截图失败',
+		// 						icon: 'none'
+		// 					})
+		// 				}
+		// 			})
+		// 		},
+		// 		fail: (err) => {
+		// 			console.error('截图失败:', err)
+		// 			uni.showToast({
+		// 				title: '截图失败',
+		// 				icon: 'none'
+		// 			})
+		// 		}
+		// 	})
+		// } else {
+		// 	uni.showToast({
+		// 		title: '请先播放视频',
+		// 		icon: 'none'
+		// 	})
+		// }
+		
 
-		// #ifdef APP-PLUS || APP-HARMONY
+		// #ifndef H5
 		if (appLivePlayerContext.value && isPlaying.value) {
 			appLivePlayerContext.value.snapshot({
 				success: (res) => {
@@ -821,18 +821,18 @@
 		// #endif
 
 		// #ifdef MP-WEIXIN
-		if (streamUrls.miniProgramUrl) {
-			deviceInfo.streamUrl = streamUrls.miniProgramUrl
-		} else {
-			uni.showToast({
-				title: '当前视频流不支持小程序播放',
-				icon: 'none',
-				duration: 3000
-			})
-		}
+		// if (streamUrls.miniProgramUrl) {
+		// 	deviceInfo.streamUrl = streamUrls.miniProgramUrl
+		// } else {
+		// 	uni.showToast({
+		// 		title: '当前视频流不支持小程序播放',
+		// 		icon: 'none',
+		// 		duration: 3000
+		// 	})
+		// }
 		// #endif
 
-		// #ifdef APP-PLUS || APP-HARMONY
+		// #ifndef H5
 		if (streamUrls.miniProgramUrl) {
 			deviceInfo.streamUrl = streamUrls.miniProgramUrl
 		} else {
@@ -994,7 +994,7 @@
 		startTimeUpdate()
 
 		// #ifdef MP-WEIXIN
-		livePlayerContext.value = uni.createLivePlayerContext('videoPlayer')
+		// livePlayerContext.value = uni.createLivePlayerContext('videoPlayer')
 		// #endif
 
 		// #ifdef APP-PLUS || APP-HARMONY

+ 213 - 31
pages/knowledge/ai-chat/index.vue

@@ -338,11 +338,17 @@
 	
 	// 完成流式输出
 	const finishStreaming = (id) => {
-		console.log("消息id2:",id);
+		console.log("完成流式输出,消息id:", id);
 		stopTypingEffect();
 		
 		if (currentTypingMessage.value !== null) {
-			chatMessages.value[currentTypingMessage.value].isTyping = false;
+			// 如果消息内容为空(可能是被中止了),移除这条消息
+			if (!chatMessages.value[currentTypingMessage.value]?.content) {
+				console.log('[完成流式] 消息内容为空,移除消息');
+				chatMessages.value.splice(currentTypingMessage.value, 1);
+			} else {
+				chatMessages.value[currentTypingMessage.value].isTyping = false;
+			}
 			currentTypingMessage.value = null;
 		}
 		
@@ -350,6 +356,11 @@
 		isInThinkingMode.value = false;
 		thinkingBuffer.value = '';
 		
+		// 重置微信小程序中止标记
+		// #ifdef MP-WEIXIN
+		isWeixinRequestAborted = false;
+		// #endif
+		
 		isProcessing.value = false;
 		scrollToBottom();
 		
@@ -360,6 +371,15 @@
 	// 处理流式错误
 	const handleStreamError = (error) => {
 		console.error('流式错误:', error);
+		
+		// 如果是微信小程序的主动中止,不显示错误
+		// #ifdef MP-WEIXIN
+		if (isWeixinRequestAborted) {
+			console.log('[微信小程序] 忽略主动中止的错误');
+			return;
+		}
+		// #endif
+		
 		stopTypingEffect();
 		
 		// 移除正在输入的消息
@@ -448,8 +468,13 @@
 		};
 		// #endif
 		
-		// #ifdef APP-HARMONY || APP-PLUS
-		// 鸿蒙等不支持 renderjs 的平台,使用原生方式
+		// #ifdef MP-WEIXIN
+		// 微信小程序使用普通请求(不支持 SSE)
+		startWeixinRequest(url, requestData);
+		// #endif
+		
+		// #ifdef APP-HARMONY
+		// 鸿蒙平台使用原生方式
 		startSSERequestNative(url, requestData);
 		// #endif
 	}
@@ -457,6 +482,104 @@
 	// 鸿蒙端 SSE 请求任务引用
 	let sseRequestTask = null;
 	
+	// 微信小程序请求任务引用
+	let weixinRequestTask = null;
+	let isWeixinRequestAborted = false; // 标记请求是否被主动中止
+	
+	// 微信小程序请求(不支持 SSE,使用普通请求)
+	const startWeixinRequest = (url, data) => {
+		console.log('[微信小程序] 开始请求:', url);
+		
+		// 重置中止标记
+		isWeixinRequestAborted = false;
+		
+		// 创建请求任务
+		weixinRequestTask = uni.request({
+			url: url,
+			method: 'POST',
+			header: {
+				'Content-Type': 'application/json',
+				'Authorization': `Bearer ${storage.getAccessToken()}`
+			},
+			data: data,
+			timeout: 60000, // 60秒超时
+			success: (res) => {
+				// 如果请求被主动中止,不处理响应
+				if (isWeixinRequestAborted) {
+					console.log('[微信小程序] 请求已被中止,忽略响应');
+					return;
+				}
+				
+				console.log('[微信小程序] 请求成功,状态码:', res.statusCode);
+				
+				if (res.statusCode === 200 && res.data) {
+					// 检查返回数据格式
+					if (typeof res.data === 'string') {
+						console.log('[微信小程序] 收到文本格式数据,长度:', res.data.length);
+						// SSE 格式数据
+						parseSSEResponse(res.data);
+					} else if (res.data.answer || res.data.content) {
+						console.log('[微信小程序] 收到 JSON 格式数据');
+						// JSON 格式数据,直接显示
+						const content = res.data.answer || res.data.content || '';
+						handleMessageData(content);
+						finishStreaming(res.data.id || null);
+					} else {
+						console.error('[微信小程序] 未知的响应格式:', res.data);
+						handleStreamError('响应格式错误');
+					}
+				} else {
+					console.error('[微信小程序] 请求失败,状态码:', res.statusCode);
+					handleStreamError('请求失败,状态码: ' + res.statusCode);
+				}
+			},
+			fail: (err) => {
+				// 如果是主动中止的请求,不显示错误
+				if (isWeixinRequestAborted) {
+					console.log('[微信小程序] 请求已被主动中止');
+					return;
+				}
+				
+				console.error('[微信小程序] 请求失败:', err);
+				
+				// 过滤掉 abort 错误(用户主动中止)
+				if (err.errMsg && err.errMsg.includes('abort')) {
+					console.log('[微信小程序] 请求被中止');
+					return;
+				}
+				
+				// 过滤掉 WebSocket 相关错误(可能是其他组件导致的)
+				if (err.errMsg && err.errMsg.includes('WebSocket')) {
+					console.warn('[微信小程序] 忽略 WebSocket 错误,这可能来自其他组件');
+					return;
+				}
+				
+				handleStreamError(err.errMsg || '网络异常');
+			},
+			complete: () => {
+				weixinRequestTask = null;
+			}
+		});
+	}
+	
+	// 停止微信小程序请求
+	const stopWeixinRequest = () => {
+		if (weixinRequestTask) {
+			console.log('[微信小程序] 准备中止请求');
+			// 设置中止标记
+			isWeixinRequestAborted = true;
+			
+			try {
+				weixinRequestTask.abort();
+				console.log('[微信小程序] 请求已中止');
+			} catch (e) {
+				console.error('[微信小程序] 中止请求失败:', e);
+			}
+			
+			weixinRequestTask = null;
+		}
+	}
+	
 	// 原生方式处理 SSE 请求(用于鸿蒙等平台)
 	const startSSERequestNative = (url, data) => {
 		console.log('[鸿蒙端] 开始 SSE 请求:', url);
@@ -658,14 +781,16 @@
 		stopSSERequestNative();
 		// #endif
 		
+		// #ifdef MP-WEIXIN
+		// 停止微信小程序请求
+		stopWeixinRequest();
+		// #endif
+		
 		// 立即停止打字机效果并完成
 		finishStreaming();
 		
-		uni.showToast({
-			title: '已中止',
-			icon: 'none',
-			duration: 1500
-		});
+		// 不显示 Toast,避免干扰用户
+		console.log('[用户操作] 已中止流式输出');
 	}
 	
 	// 重新生成回复
@@ -866,18 +991,40 @@
 	
 	// 生命周期钩子
 	onMounted(() => {
+		console.log('[生命周期] 组件挂载');
+		
+		// 捕获全局错误,防止 WebSocket 等错误影响功能
+		// #ifdef MP-WEIXIN
+		const originalError = console.error;
+		console.error = function(...args) {
+			// 过滤掉 WebSocket 相关错误(可能来自其他组件或框架)
+			const errorMsg = args.join(' ');
+			if (errorMsg.includes('WebSocket') || errorMsg.includes('closeSocket')) {
+				console.warn('[已过滤] WebSocket 错误:', ...args);
+				return;
+			}
+			originalError.apply(console, args);
+		};
+		// #endif
+		
 		// 初始化防抖函数
 		debouncedSubmitQuestion = debounce(submitQuestion, 300)
 		
 		// 获取系统信息
-		const systemInfo = uni.getSystemInfoSync();
-		statusBarHeight.value = systemInfo.statusBarHeight || 20;
-		isIOS.value = systemInfo.platform === 'ios';
-		
-		// 计算底部安全区域(包含 tabbar 高度)
-		const safeAreaInsetsBottom = systemInfo.safeAreaInsets ? (systemInfo.safeAreaInsets.bottom || 0) : 0;
-		// 转换为 rpx,并确保至少有基础间距
-		safeAreaBottom.value = Math.max(safeAreaInsetsBottom * 2, 0);
+		try {
+			const systemInfo = uni.getSystemInfoSync();
+			statusBarHeight.value = systemInfo.statusBarHeight || 20;
+			isIOS.value = systemInfo.platform === 'ios';
+			
+			// 计算底部安全区域(包含 tabbar 高度)
+			const safeAreaInsetsBottom = systemInfo.safeAreaInsets ? (systemInfo.safeAreaInsets.bottom || 0) : 0;
+			// 转换为 rpx,并确保至少有基础间距
+			safeAreaBottom.value = Math.max(safeAreaInsetsBottom * 2, 0);
+			
+			console.log('[系统信息] 平台:', systemInfo.platform, '状态栏高度:', statusBarHeight.value);
+		} catch (e) {
+			console.error('[系统信息] 获取失败:', e);
+		}
 
 		// 初始化消息
 		initMessages();
@@ -887,44 +1034,79 @@
 			scrollToBottom();
 		});
 		
-		// 监听来自 renderjs 的自定义事件(仅在支持的平台)
-		// #ifdef H5 || APP-PLUS
+		// 监听来自 renderjs 的自定义事件(仅在 H5 平台)
+		// #ifdef H5
 		if (typeof window !== 'undefined') {
 			window.addEventListener('renderjs-stream-data', (event) => {
-				console.log('通过事件接收到数据:', event.detail);
+				console.log('[H5] 通过事件接收到数据:', event.detail);
 				onStreamData(event.detail);
 			});
 		}
 		// #endif
+		
+		console.log('[生命周期] 组件挂载完成');
 	})
 	
 	// 组件销毁时清理资源
 	onBeforeUnmount(() => {
+		console.log('[生命周期] 组件即将卸载,清理资源');
+		
 		// 停止打字机效果
 		stopTypingEffect();
 		
+		// #ifdef H5
 		// 通知 renderjs 停止连接
 		if (isProcessing.value) {
-			renderjsData.value = {
-				action: 'stop',
-				timestamp: Date.now()
-			};
+			try {
+				renderjsData.value = {
+					action: 'stop',
+					timestamp: Date.now()
+				};
+			} catch (e) {
+				console.error('[H5] 停止 renderjs 失败:', e);
+			}
 		}
 		
-		// 清理消息队列
-		messageQueue.value = [];
-		
-		// 移除事件监听器(仅在支持的平台)
-		// #ifdef H5 || APP-PLUS
+		// 移除事件监听器
 		if (typeof window !== 'undefined') {
-			window.removeEventListener('renderjs-stream-data', onStreamData);
+			try {
+				window.removeEventListener('renderjs-stream-data', onStreamData);
+			} catch (e) {
+				console.error('[H5] 移除事件监听失败:', e);
+			}
+		}
+		// #endif
+		
+		// #ifdef APP-HARMONY
+		// 停止鸿蒙端请求
+		if (isProcessing.value) {
+			try {
+				stopSSERequestNative();
+			} catch (e) {
+				console.error('[鸿蒙] 停止请求失败:', e);
+			}
 		}
 		// #endif
+		
+		// #ifdef MP-WEIXIN
+		// 停止微信小程序请求
+		if (isProcessing.value) {
+			try {
+				stopWeixinRequest();
+			} catch (e) {
+				console.error('[微信小程序] 停止请求失败:', e);
+			}
+		}
+		// #endif
+		
+		// 清理消息队列
+		messageQueue.value = [];
+		isProcessing.value = false;
 	})
 </script>
 
 
-<!--  #ifdef H5 || APP-PLUS -->
+<!--  #ifndef APP-HARMONY -->
 <script module="renderModule" lang="renderjs">
 	// renderjs 模块状态
 	let eventSource = null;

+ 11 - 11
pages/login/index.vue

@@ -8,13 +8,13 @@
 		</view>
 
 		<view class="logo-section">
-			<image class="logo" src="/static/images/logo.png" mode="aspectFit"></image>
+			<image class="logo" src="/static/images/n.png" mode="aspectFit"></image>
 			<text class="app-name">农小禹</text>
 			<text class="app-slogan">智慧农业,从此开始</text>
 		</view>
 
 		<view class="login-section">
-			<!-- #ifndef MP-WEIXIN -->
+			<!--  -->
 			<view class="form-container">
 				<view class="input-group">
 					<input type="text" v-model="phoneNumber" placeholder="请输入手机号" class="input-field" maxlength="11" />
@@ -44,21 +44,21 @@
 				
 				<!-- 底部操作区 -->
 				<view class="bottom-actions">
-					<text class="action-link" @click="switchLoginType(loginType === 'password' ? 'code' : 'password')">
-						{{ loginType === 'password' ? '验证码登录' : '密码登录' }}
+					<text class="action-link" @click="switchLoginType(loginType === 'code' ? 'password' : 'code')">
+						{{ loginType === 'code' ? '密码登录' : '验证码登录' }}
 					</text>
 					<text class="action-link" @click="navigateToRegister">注册账号</text>
-					<text v-if="loginType === 'password'" class="action-link" @click="navigateToForgetPassword">忘记密码</text>
+					<text  class="action-link" @click="navigateToForgetPassword">忘记密码</text>
 				</view>
 			</view>
-			<!-- #endif -->
+			
 
-			<!-- #ifdef MP-WEIXIN -->
-			<button type="primary" class="wechat-login-btn" bindtap="getUserProfile" @click="getUserProfile()">
+			
+			<!-- <button type="primary" class="wechat-login-btn" bindtap="getUserProfile" @click="getUserProfile()">
 				<view class="wechat-icon">微</view>
 				<text>一键登录</text>
-			</button>
-			<!-- #endif -->
+			</button> -->
+			
 		</view>
 
 		<view class="privacy-agreement">
@@ -124,7 +124,7 @@
 	const phoneNumber = ref("")
 	const password = ref("")
 	const verificationCode = ref("")
-	const loginType = ref("password") // 'password' 或 'code'
+	const loginType = ref("code") // 'password' 或 'code'
 	const countdown = ref(0)
 	const loading = ref(false)
 	const logingFlag = ref(false)

+ 4 - 3
pages/service/purchase-publish.vue

@@ -27,7 +27,7 @@
 							<!-- {{ formData.categoryLabel || '请选择产品分类' }} -->
 							{{getDictLabel('agricultural_category',formData.categoryId) || '请选择产品分类' }}
 						</text>
-						<text class="arrow-icon">></text>
+						<text class="arrow-icon"></text>
 					</view>
 				</view>
 			</view>
@@ -68,7 +68,7 @@
 							<!-- {{ formData.dictLabel || '请选择价格单位' }} -->
 							{{ getDictLabel('agricultural_unit',formData.unit) || '请选择价格单位'}}
 						</text>
-						<text class="arrow-icon">></text>
+						<text class="arrow-icon"></text>
 					</view>
 				</view>
 			</view>
@@ -831,9 +831,10 @@
 		}
 	}
 
-	.arrow-icon {
+	.arrow-icon, .arrow-icon::after {
 		font-size: 24rpx;
 		color: #999;
+		content: ">";
 	}
 
 	// 带单位的输入框

+ 4 - 3
pages/service/sales-publish.vue

@@ -27,7 +27,7 @@
 							<!-- {{ formData.categoryLabel || '请选择产品分类' }} -->
 							{{getDictLabel('agricultural_category',formData.categoryId) || '请选择产品分类' }}
 						</text>
-						<text class="arrow-icon">></text>
+						<text class="arrow-icon"></text>
 					</view>
 				</view>
 			</view>
@@ -70,7 +70,7 @@
 							<!-- {{ formData.dictLabel || '请选择价格单位' }} -->
 							{{ getDictLabel('agricultural_unit',formData.unit) || '请选择价格单位'}}
 						</text>
-						<text class="arrow-icon">></text>
+						<text class="arrow-icon"></text>
 					</view>
 				</view>
 			</view>
@@ -874,9 +874,10 @@
 		}
 	}
 
-	.arrow-icon {
+	.arrow-icon, .arrow-icon::after {
 		font-size: 24rpx;
 		color: #999;
+		content: ">";
 	}
 
 	// 带单位的输入框

+ 8 - 5
pages/user/index.vue

@@ -18,7 +18,7 @@
 		<view class="info-card">
 			<view class="card-title">
 				<text>我的地块</text>
-				<text class="more" @click="navigateToPlots">查看更多 ></text>
+				<text class="more" @click="navigateToPlots">查看更多</text>
 			</view>
 			<view class="plot-info">
 				<view class="plot-item">
@@ -65,19 +65,19 @@
 					<view class="left">
 						<text>联系客服</text>
 					</view>
-					<text class="arrow">></text>
+					<text class="arrow"></text>
 				</view>
 				<view class="function-item" @click="viewTerms">
 					<view class="left">
 						<text>用户协议</text>
 					</view>
-					<text class="arrow">></text>
+					<text class="arrow"></text>
 				</view>
 				<view class="function-item" @click="viewPrivacy">
 					<view class="left">
 						<text>隐私政策</text>
 					</view>
-					<text class="arrow">></text>
+					<text class="arrow"></text>
 				</view>
 
 <!--        <view class="function-item" @click="navigateToSettings">
@@ -91,7 +91,7 @@
 						<!-- <text class="function-icon">退</text> -->
 						<text>退出登录</text>
 					</view>
-					<text class="arrow">></text>
+					<text class="arrow"></text>
 				</view>
 			</view>
 		</view>
@@ -315,6 +315,9 @@ onShow(() => {
 </script>
 
 <style>
+	.arrow::after,.more::after {
+	  content: ">";
+	}
 	.container {
 		min-height: 100vh;
 		background-color: #f5f5f5;

BIN
static/images/n.png


+ 0 - 0
static/images/video-placeholder.jpg


+ 0 - 4
utils/jessibuca-plugin.js

@@ -59,10 +59,6 @@ function isSupported() {
   // #ifdef H5
   return typeof window !== 'undefined' && typeof document !== 'undefined'
   // #endif
-  
-  // #ifndef H5
-  return false
-  // #endif
 }
 
 export default {

+ 4 - 0
vite.config.js

@@ -37,6 +37,10 @@ server: {
         secure: false,
         rewrite: (path) => path.replace(/^\/base/, ''),
       },
+      '/jessibuca': {
+        target: 'https://nxy.gbdfarm.com:9000',
+        changeOrigin: true
+      },
       // WVP 视频平台代理配置
       '/wvp': {
         target: 'https://nxy.gbdfarm.com:9000',