From 6c3a421bce3cdcd5705cd694938642885db605e4 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Thu, 12 Feb 2026 09:37:43 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 uniapps/work-app/src/manifest.json                                  |    4 
 applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue |  191 +++++++++++++++++++++----------------
 applications/drone-command/src/views/audioCall.vue                  |    8 
 uniapps/work-app/src/hooks/useGlobalWS.js                           |    9 +
 uniapps/work-app/src/subPackages/voiceCallDetail/index.vue          |   61 ++++++------
 uniapps/work-app/src/App.vue                                        |   12 -
 6 files changed, 155 insertions(+), 130 deletions(-)

diff --git a/applications/drone-command/src/views/audioCall.vue b/applications/drone-command/src/views/audioCall.vue
index aa0cbaf..7bdc103 100644
--- a/applications/drone-command/src/views/audioCall.vue
+++ b/applications/drone-command/src/views/audioCall.vue
@@ -36,10 +36,10 @@
 import { ref, computed, onBeforeUnmount } from 'vue'
 
 /** ✅ 你的 WS 地址前缀(后面拼 userId) */
-const WS_BASE = 'wss://wrj.shuixiongit.com/ws/chat?userId='
+const WS_BASE = 'ws://218.202.104.82:38201/ws/chat'
 
-const uid = ref('2')
-const peerUid = ref('3')
+const uid = ref('2021474568497131521')
+const peerUid = ref('2021475329842999298')
 
 const connected = ref(false)
 const state = ref('idle') // idle | calling | ringing | in-call
@@ -310,7 +310,7 @@
 function connectWS() {
 	if (ws) ws.close()
 
-	ws = new WebSocket(WS_BASE + encodeURIComponent(uid.value))
+	ws = new WebSocket(WS_BASE, "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoyMDIxNDc0NTY4NDk3MTMxNTIxLCJ1c2VyX2tleSI6ImI4MzJhNzJhLTA5NDMtNGI1ZC04ZDRhLTZiYjlmZTJmM2VmMyIsInVzZXJuYW1lIjoiemhpZmVpIn0.amIbSnRkyof2nAal8U1uPO407fg9JfJk1yKoaAnX6nxbWwG5Yf8VY4Bto0D0EBvUNdoSFB2hbcOv5a80XEDDmA")
 
 	ws.onopen = () => {
 		connected.value = true
diff --git a/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue b/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
index ec529b9..79c9fb0 100644
--- a/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
+++ b/applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
@@ -8,7 +8,7 @@
 			<div class="contactAvatar">
 				<img :src="defaultAvatar" alt=""></img>
 			</div>
-			
+
 			<!--  联系人名称-->
 			<div class="contactName">
 				{{ contactName }}
@@ -39,77 +39,14 @@
 <script setup>
 import { useRoute } from 'vue-router'
 import defaultAvatar from '@/appDataSource/appwork/defaultAvatar.svg'
+import { showToast } from 'vant'
 const route = useRoute()
 /** ✅ 你的 WS 地址前缀(后面拼 userId) */
 // const WS_BASE = 'ws://218.202.104.82:38201/ws/chat?userId='
 const WS_BASE = 'ws://218.202.104.82:38201/ws/chat'
-// 解析URL参数
-const parseUrlParams = () => {
-	// 1. 优先从route.query.voiceparams获取参数
-	if (route.query && route.query.voiceparams) {
-		console.log('从route.query.voiceparams获取参数:', route.query.voiceparams);
-		try {
-			// 解码并解析voiceparams参数
-			const params = JSON.parse(decodeURIComponent(route.query.voiceparams));
-			console.log('解析后的voiceparams:', params);
-			
-			if (params.peerUid) {
-				peerUid.value = String(params.peerUid);
-				log('🔗 从voiceparams获取peerUid:', params.peerUid);
-			}
-			
-			// 如果是来电类型,直接触发来电状态
-			if (params.type === 'incoming') {
-				log('📞 voiceparams检测到来电,直接进入来电状态');
-				incomingFrom = String(params.from);
-				peerUid.value = incomingFrom;
-				acceptedByMe = false;
-				offeredByPeer = false;
-				
-				state.value = 'ringing';
-				log('📞 收到来电 call,来自', incomingFrom);
 
-				// 开始来电提示(铃声和震动)
-				playRingtone();
-				startVibration();
-			}
-		} catch (e) {
-			log('❌ 解析voiceparams参数失败:', String(e));
-		}
-	}
-	
-	// 2. 同时保留原有的URL参数解析逻辑,作为备选
-	const url = new URL(window.location.href);
-	const paramsStr = url.searchParams.get('params');
-	if (paramsStr) {
-		try {
-			const params = JSON.parse(decodeURIComponent(paramsStr));
-			if (params.peerUid) {
-				peerUid.value = String(params.peerUid);
-				log('🔗 从URL参数获取peerUid:', params.peerUid);
-			}
-		} catch (e) {
-			log('❌ 解析URL参数失败:', String(e));
-		}
-	}
-}
-
-// 从URL参数或本地存储获取用户ID
-const getUserIdFromStorage = () => {
-	// 从url获取用户id
-	const contact = JSON.parse(decodeURIComponent(receiveParameters.value))
-	console.log('从url获取用户id',contact?.userId)
-	// 从本地获取用户id
-	const userId = localStorage.getItem('userId') || sessionStorage.getItem('userId')
-	console.log('从本地存储获取userId:', userId)
-	if (userId) {
-		return userId
-	}
-	return '3' // 默认值
-}
-
-const uid = ref('3')
-const peerUid = ref('2')
+const uid = ref('2021475329842999298')
+const peerUid = ref('2021474568497131521')
 // 联系人名称
 const contactName = ref('张三')
 
@@ -150,6 +87,70 @@
 function stopTimer() {
 	if (timer) clearInterval(timer)
 	timer = null
+}
+// 解析URL参数
+const parseUrlParams = () => {
+	// 1. 优先从route.query.voiceparams获取参数
+	if (route.query && route.query.voiceparams) {
+		console.log('从route.query.voiceparams获取参数:', route.query.voiceparams);
+		try {
+			// 解码并解析voiceparams参数
+			const params = JSON.parse(decodeURIComponent(route.query.voiceparams));
+			console.log('解析后的voiceparams:', params);
+
+			if (params.peerUid) {
+				peerUid.value = String(params.peerUid);
+				log('🔗 从voiceparams获取peerUid:', params.peerUid);
+			}
+
+			// 如果是来电类型,直接触发来电状态
+			if (params.type === 'incoming') {
+				log('📞 voiceparams检测到来电,直接进入来电状态');
+				incomingFrom = String(params.from);
+				peerUid.value = incomingFrom;
+				acceptedByMe = false;
+				offeredByPeer = false;
+
+				state.value = 'ringing';
+				log('📞 收到来电 call,来自', incomingFrom);
+
+				// 开始来电提示(铃声和震动)
+				playRingtone();
+				startVibration();
+			}
+		} catch (e) {
+			log('❌ 解析voiceparams参数失败:', String(e));
+		}
+	}
+
+	// 2. 同时保留原有的URL参数解析逻辑,作为备选
+	const url = new URL(window.location.href);
+	const paramsStr = url.searchParams.get('params');
+	if (paramsStr) {
+		try {
+			const params = JSON.parse(decodeURIComponent(paramsStr));
+			if (params.peerUid) {
+				peerUid.value = String(params.peerUid);
+				log('🔗 从URL参数获取peerUid:', params.peerUid);
+			}
+		} catch (e) {
+			log('❌ 解析URL参数失败:', String(e));
+		}
+	}
+}
+
+// 从URL参数或本地存储获取用户ID
+const getUserIdFromStorage = () => {
+	// 从url获取用户id
+	const contact = JSON.parse(decodeURIComponent(receiveParameters.value))
+	console.log('从url获取用户id',contact?.userId)
+	// 从本地获取用户id
+	const userId = localStorage.getItem('userId') || sessionStorage.getItem('userId')
+	console.log('从本地存储获取userId:', userId)
+	if (userId) {
+		return userId
+	}
+	return '2021475329842999298' // 默认值
 }
 
 // 心跳
@@ -229,21 +230,43 @@
 	}
 
 	try {
-		localStream = await navigator.mediaDevices.getUserMedia({ 
-			audio: {
-				echoCancellation: true,
-				noiseSuppression: true,
-				autoGainControl: true,
-				// 移动端特定配置
-				channelCount: 1,
-				sampleRate: 16000,
-				sampleSize: 16
-			}
-	  	})
-		log('✅ 已获取本地麦克风')
+		// 尝试使用完整约束
+		try {
+			localStream = await navigator.mediaDevices.getUserMedia({
+				audio: {
+					echoCancellation: true,
+					noiseSuppression: true,
+					autoGainControl: true,
+					channelCount: 1,
+					sampleRate: 16000,
+					sampleSize: 16
+				}
+			})
+			log('✅ 已获取本地麦克风(标准约束)')
+		} catch (strictError) {
+			// 如果标准约束失败,尝试最简单的约束
+			log('⚠️ 标准约束失败,尝试简化约束:', String(strictError))
+			localStream = await navigator.mediaDevices.getUserMedia({
+				audio: true
+			})
+			log('✅ 已获取本地麦克风(简化约束)')
+		}
 		return localStream
 	} catch (e) {
 		log('❌ 获取麦克风失败:', String(e))
+
+		// 提供更详细的错误信息
+		if (e.name === 'NotReadableError') {
+			log('❌ NotReadableError: 麦克风可能被其他应用占用,或权限未正确配置')
+			showToast('麦克风被占用或权限未授予')
+		} else if (e.name === 'NotAllowedError') {
+			log('❌ NotAllowedError: 用户拒绝了麦克风权限')
+			showToast('请授予麦克风权限')
+		} else if (e.name === 'NotFoundError') {
+			log('❌ NotFoundError: 未找到麦克风设备')
+			showToast('未找到麦克风设备')
+		}
+
 		throw e
 	}
 }
@@ -530,13 +553,13 @@
 	lastOfferSdp = null
 
 	state.value = 'idle'
-	
+
 	// 清除之前的定时器
 	if (endTimer.value) {
 		clearTimeout(endTimer.value)
 		endTimer.value = null
 	}
-	
+
 	// 根据是谁发起的挂断决定不同的行为
 	if (sendToPeer) {
 		// 自己主动挂断:不提示,不延迟,直接跳转
@@ -552,7 +575,7 @@
 		// 对方挂断:显示提示,延迟10秒跳转
 		callEnded.value = true
 		endMessage.value = '对方已挂断'
-		
+
 		// 延迟5秒后跳转页面
 		endTimer.value = setTimeout(() => {
 			// 返回上一页(uni-app的语音通话列表页面)
@@ -580,7 +603,7 @@
 			if (params.access_token) {
 				accessToken.value = params.access_token;
 				log('🔗 从params获取access_token:', accessToken.value);
-			}	
+			}
 		} catch (e) {
 			log('❌ 解析params参数失败:', String(e));
 		}
@@ -882,4 +905,4 @@
 	height: 220px;
 	margin-bottom: 60px;
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/uniapps/work-app/src/App.vue b/uniapps/work-app/src/App.vue
index cfaebb6..deec9d2 100644
--- a/uniapps/work-app/src/App.vue
+++ b/uniapps/work-app/src/App.vue
@@ -4,7 +4,7 @@
 import { useGlobalWS } from '@/hooks/useGlobalWS.js'
 // #ifdef APP-PLUS
 import { keepAliveStart, requestIgnoreBatteryOptimization } from '@/uni_modules/keep-app'
-import { openDialog, allowFloat,getBatteryCapacity } from '@/uni_modules/lgh-dialog'
+import { openDialog, allowFloat, getBatteryCapacity } from '@/uni_modules/lgh-dialog'
 // #endif
 
 const appStore = useAppStore()
@@ -24,11 +24,8 @@
 // testKeep()
 
 // 开启悬浮窗
-allowFloat()
+// allowFloat()
 // 假设五秒后来电
-setTimeout(() => {
-	openDialog()
-}, 5000)
 // #endif
 
 useGlobalWS()
@@ -57,9 +54,9 @@
 	// 初始化系统信息
 	appStore.initSystemInfo()
 	// #ifdef APP-PLUS
-	keepAliveStart()
+	// keepAliveStart()
 	// 请求用户允许忽略电池优化(重要:用于保活)
-	setTimeout(requestIgnoreBatteryOptimization, 2000)
+	// setTimeout(requestIgnoreBatteryOptimization, 2000)
 	// #endif
 	if (!userStore.userInfo) {
 		//不存在则跳转至登录页
@@ -106,4 +103,3 @@
 	background: transparent !important;
 }
 </style>
-
diff --git a/uniapps/work-app/src/hooks/useGlobalWS.js b/uniapps/work-app/src/hooks/useGlobalWS.js
index b8595a3..a337b9e 100644
--- a/uniapps/work-app/src/hooks/useGlobalWS.js
+++ b/uniapps/work-app/src/hooks/useGlobalWS.js
@@ -6,11 +6,14 @@
 	const userStore = useUserStore();
   const appStore = useAppStore();
   const callStatus = ref(null)
+  // token 存储
+  const accessToken = ref('')
 
   // 设置默认用户ID为3
-  const defaultUserId = '8';
+  const defaultUserId = '2021475329842999298';
   // WebSocket基础URL
-  const WS_BASE = 'wss://wrj.shuixiongit.com/ws/chat?userId=';
+  // const WS_BASE = 'wss://wrj.shuixiongit.com/ws/chat?userId=';
+  const WS_BASE = 'ws://218.202.104.82:38201/ws/chat';
 
 	// 消息处理
   function messageHandler(payload) {
@@ -76,6 +79,8 @@
 
   // 初始化WebSocket连接
   function initWS() {
+    const userStore = useUserStore()
+    accessToken.value =userStore?.userInfo.access_token
     try {
 
       websocketService.setOnMessageCallback(messageHandler);
diff --git a/uniapps/work-app/src/manifest.json b/uniapps/work-app/src/manifest.json
index e47c752..7d1d57e 100644
--- a/uniapps/work-app/src/manifest.json
+++ b/uniapps/work-app/src/manifest.json
@@ -53,12 +53,14 @@
                     "<uses-feature android:name=\"android.hardware.camera\"/>",
                     "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
                     "<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\" />",
                     "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />",
                     "<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />",
                     "<uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />",
                     "<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\" />",
                     "<uses-permission android:name=\"android.permission.USE_FULL_SCREEN_INTENT\" />"
-                ]
+                ],
+                "minSdkVersion" : 21
             },
             /* ios打包配置 */
             "ios" : {
diff --git a/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue b/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue
index 86c915e..6798ebd 100644
--- a/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue
+++ b/uniapps/work-app/src/subPackages/voiceCallDetail/index.vue
@@ -23,42 +23,41 @@
  */
 async function requestAndroidMicPermission() {
   try {
-    // 使用 uni 的权限 API(需要 HBuilderX 3.4.0+)
-    if (uni.requestPermissions) {
-      const result = await uni.requestPermissions({
-        permissions: ['android.permission.RECORD_AUDIO']
-      })
-      
-      console.log('权限请求结果:', result)
-      
-      if (result[0].granted) {
-        console.log('✅ 麦克风权限已授予')
-        return true
-      } else {
-        console.warn('⚠️ 麦克风权限被拒绝')
-        
-        // 可以提示用户
-        uni.showModal({
-          title: '权限提示',
-          content: '语音通话需要麦克风权限,请前往设置开启',
-          showCancel: false,
-          success: () => {
-            // 跳转到应用设置
-            plus.runtime.openURL(plus.runtime.getProperty('package') + '://settings')
+    // 获取麦克风权限
+    return await new Promise((resolve) => {
+      plus.android.requestPermissions(
+        ['android.permission.RECORD_AUDIO'],
+        (result) => {
+          if (result.granted.length > 0) {
+            console.log('麦克风权限已获取')
+            resolve(true)
+            return
           }
-        })
-        return false
-      }
-    }
-    
-    // 降级方案:使用原生方法
-    return await requestAndroidMicPermissionNative()
-    
+          if (result.deniedAlways.length > 0) {
+            uni.showModal({
+              title: '提示',
+              content: '需要麦克风权限才能正常使用语音功能,请前往系统设置开启',
+              success(res) {
+                if (res.confirm) {
+                  plus.runtime.openURL('app-settings:')
+                }
+              },
+            })
+          }
+          resolve(false)
+        },
+        (error) => {
+          console.error('请求麦克风权限失败', error)
+          resolve(false)
+        }
+      )
+    })
   } catch (error) {
-    console.error('❌ 请求麦克风权限失败:', error)
+    console.error('❌ 请求麦克风权限失败', error)
     return false
   }
 }
+
 // #endif
 
 onLoad(async (options) => {

--
Gitblit v1.9.3