| | |
| | | <div class="contactAvatar"> |
| | | <img :src="defaultAvatar" alt=""></img> |
| | | </div> |
| | | |
| | | |
| | | <!-- 联系人名称--> |
| | | <div class="contactName"> |
| | | {{ contactName }} |
| | |
| | | <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=' |
| | |
| | | } |
| | | |
| | | 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 |
| | | } |
| | | } |
| | |
| | | lastOfferSdp = null |
| | | |
| | | state.value = 'idle' |
| | | |
| | | |
| | | // 清除之前的定时器 |
| | | if (endTimer.value) { |
| | | clearTimeout(endTimer.value) |
| | | endTimer.value = null |
| | | } |
| | | |
| | | |
| | | // 根据是谁发起的挂断决定不同的行为 |
| | | if (sendToPeer) { |
| | | // 自己主动挂断:不提示,不延迟,直接跳转 |
| | |
| | | // 对方挂断:显示提示,延迟10秒跳转 |
| | | callEnded.value = true |
| | | endMessage.value = '对方已挂断' |
| | | |
| | | |
| | | // 延迟5秒后跳转页面 |
| | | endTimer.value = setTimeout(() => { |
| | | // 返回上一页(uni-app的语音通话列表页面) |
| | |
| | | if (params.access_token) { |
| | | accessToken.value = params.access_token; |
| | | log('🔗 从params获取access_token:', accessToken.value); |
| | | } |
| | | } |
| | | } catch (e) { |
| | | log('❌ 解析params参数失败:', String(e)); |
| | | } |
| | |
| | | height: 220px; |
| | | margin-bottom: 60px; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | 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() |
| | |
| | | // testKeep() |
| | | |
| | | // 开启悬浮窗 |
| | | allowFloat() |
| | | // allowFloat() |
| | | // 假设五秒后来电 |
| | | setTimeout(() => { |
| | | openDialog() |
| | | }, 5000) |
| | | // #endif |
| | | |
| | | useGlobalWS() |
| | |
| | | // 初始化系统信息 |
| | | appStore.initSystemInfo() |
| | | // #ifdef APP-PLUS |
| | | keepAliveStart() |
| | | // keepAliveStart() |
| | | // 请求用户允许忽略电池优化(重要:用于保活) |
| | | setTimeout(requestIgnoreBatteryOptimization, 2000) |
| | | // setTimeout(requestIgnoreBatteryOptimization, 2000) |
| | | // #endif |
| | | if (!userStore.userInfo) { |
| | | //不存在则跳转至登录页 |
| | |
| | | background: transparent !important; |
| | | } |
| | | </style> |
| | | |
| | |
| | | "<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" : { |
| | |
| | | */ |
| | | async function requestAndroidMicPermission() { |
| | | try { |
| | | // 获取麦克风权限 |
| | | // #ifdef APP-PLUS |
| | | plus.android.requestPermissions( |
| | | ['android.permission.RECORD_AUDIO'], |
| | | (result) => { |
| | | if (result.granted.length > 0) { |
| | | console.log('麦克风权限已获取') |
| | | } |
| | | if (result.deniedAlways.length > 0) { |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '需要麦克风权限才能正常使用语音功能,请前往系统设置开启', |
| | | success(res) { |
| | | if (res.confirm) { |
| | | plus.runtime.openURL('app-settings:') |
| | | } |
| | | }, |
| | | }) |
| | | } |
| | | }, |
| | | (error) => { |
| | | console.error('请求麦克风权限失败:', error) |
| | | } |
| | | ) |
| | | // #endif |
| | | |
| | | |
| | | // 获取麦克风权限 |
| | | return await new Promise((resolve) => { |
| | | plus.android.requestPermissions( |
| | | ['android.permission.RECORD_AUDIO'], |
| | | (result) => { |
| | | if (result.granted.length > 0) { |
| | | console.log('麦克风权限已获取') |
| | | resolve(true) |
| | | return |
| | | } |
| | | 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) => { |