收藏
回答

鸿蒙机子光震动,不显示接听界面?

<template>
  <view>
   <!-- <button class="chat-button" @tap="handleStartChat" :disabled="isCalling">
    {{ isCalling ? '连接中...' : '开始通话' }}
   </button> -->
  </view>
</template>

<script>
  import * as callApi from '@/api/xcx/home/zx.js'
  // 引入公共权限处理方法
  import {
   requestVoipPermission
  } from '@/utils/authHelper.js'

  export default {
   props: {
    orderId: {
     type: [String, Number],
     required: true
    },
    callerOpenId: {
     type: String,
     default: ''
    },
    listenerOpenId: {
     type: String,
     default: ''
    },
    callerName: {
     type: String,
     default: ''
    },
    zxsMobilePhone: {
     type: String,
     default: ''
    },
    listenerName: {
     type: String,
     default: ''
    },
    roomType: {
     type: String,
     default: '2' // 2=语音,1=视频
    },
   },
   data() {
    return {
     callStatus: '',
     isCalling: false,
     callId: undefined,
     stateChangeListener: null,
     membersChangeListener: null,
     interruptedListener: null,
     chatSpeakersChangedListener: null
    }
   },

   mounted() {
    console.log('====初始化====')
    this.init1V1Chat()
   },

   methods: {
    setRoomType(type) {
     this.roomType = type;
    },

    // 初始化1v1通话,处理权限拒绝逻辑
    init1V1Chat() {
     // #ifdef MP-WEIXIN
     wx.setEnable1v1Chat({
      enable: true,
      success: () => {
       console.log('1v1通话功能启用成功')
      },
      fail: async (error) => {
       console.log('1v1通话功能启用失败==', error)
       // 识别权限拒绝的错误类型
       const errCode = error.errCode;
       const errMsg = error.errMsg;

       await requestVoipPermission(this.roomType)
      }
     })
     // #endif
    },

    // 【关键修复】彻底清理所有监听
    clearAllListeners() {
     // 1. 通话状态监听
     if (this.stateChangeListener) {
      wx.offVoIPChatStateChanged(this.stateChangeListener);
      this.stateChangeListener = null;
     }
     // 2. 成员变化监听
     if (this.membersChangeListener) {
      wx.offVoIPChatMembersChanged(this.membersChangeListener);
      this.membersChangeListener = null;
     }
     // 3. 通话中断监听
     if (this.interruptedListener) {
      wx.offVoIPChatInterrupted(this.interruptedListener);
      this.interruptedListener = null;
     }
     // 4. 扬声器状态监听
     if (this.chatSpeakersChangedListener) {
      wx.offVoIPChatSpeakersChanged(this.chatSpeakersChangedListener);
      this.chatSpeakersChangedListener = null;
     }
    },

    async handleStartChat() {
     // 防止重复点击
     if (this.isCalling) return;

     this.isCalling = true;
     this.callStatus = 'calling';

     try {
      // 调用前先强制退出可能残留的通话房间
      if (wx.leaveVoIPChat) {
       await new Promise((resolve) => {
        wx.leaveVoIPChat({
         success: resolve,
         fail: resolve // 即使失败也继续,避免阻塞
        });
       });
      }

      await this.init1V1Chat(); // 确保初始化执行
      await this.start1v1Chat();
     } catch (err) {
      console.error('发起通话失败:', err);
      this.callStatus = 'failed';
      // 权限拒绝的额外提示:调用公共方法
      if (err.message.includes('权限')) {
       requestVoipPermission(this.roomType);
      } else {
       uni.showToast({
        title: err.errMsg || '发起通话失败',
        icon: 'none'
       });
      }
      this.isCalling = false;
      this.clearAllListeners();
     }
    },

    async start1v1Chat() {
     // #ifdef MP-WEIXIN
     // 1. 申请录音权限(增加权限拒绝处理)
     // await new Promise((resolve, reject) => {
     //   uni.authorize({
     //    scope: 'scope.record',
     //    success: resolve,
     //    fail: (err) => {
     //     console.error('录音权限申请失败:', err);
     //     // 区分“用户拒绝”和“其他错误”
     //     if (err.errMsg.includes('auth deny')) {
     //      reject(new Error('您拒绝了录音权限,无法进行通话,请前往设置开启'));
     //     } else {
     //      reject(new Error('需要录音权限才能进行通话'));
     //     }
     //    }
     //   });
     // });

     // // 2. 视频通话申请摄像头权限(增加权限拒绝处理)
     // if (this.roomType === '1') {
     //   await new Promise((resolve, reject) => {
     //    uni.authorize({
     //     scope: 'scope.camera',
     //     success: resolve,
     //     fail: (err) => {
     //      console.error('摄像头权限申请失败:', err);
     //      if (err.errMsg.includes('auth deny')) {
     //       reject(new Error('您拒绝了摄像头权限,无法进行视频通话,请前往设置开启'));
     //      } else {
     //       reject(new Error('需要摄像头权限才能进行视频通话'));
     //      }
     //     }
     //    });
     //   });
     // }

     await requestVoipPermission(this.roomType)


     const roomType = this.roomType === '1' ? 'video' : 'voice';

     // 先清理之前的监听,防止重复注册
     this.clearAllListeners();

     // 3. 注册通话状态监听
     this.stateChangeListener = (res) => {
      console.log('通话状态变化:', res);
      const {
       state,
       openId,
       reason
      } = res;

      switch (state) {
       case 'connected':
        console.log(`用户 ${openId} 接通通话`);
        this.callStatus = 'success';
        this.$emit('call-connected');
        break;
       case 'disconnected':
        console.log(`通话挂断,原因: ${reason || '未知原因'}`);
        this.handleCallEnded('通话已结束');
        this.$emit('call-hangup', {
         openId,
         reason
        });
        break;
       case 'failed':
        console.log(`通话失败: ${reason || '未知错误'}`);
        this.callStatus = 'failed';
        this.handleCallEnded(`通话失败: ${reason || '未知错误'}`);
        this.$emit('call-failed', {
         reason
        });
        break;
      }
     };
     wx.onVoIPChatStateChanged(this.stateChangeListener);

     // 4. 注册房间成员变化监听
     this.membersChangeListener = (res) => {
      console.log('房间成员变化:', res);
      if ((res.openIdList.length === 1 && res.openIdList[0] === this.callerOpenId) || res.openIdList
       .length === 1 && res.openIdList[0] === this.listenerOpenId) {
       console.log('接听方已挂断===');
      }

      this.isCalling = false

      if (res.openIdList.length === 2) {
       console.log('双方已加入通话');
       callApi.saveCallStart({
        hzyyjlbId: this.orderId,
        bdlx: this.roomType,
        zxsMobilePhone: this.zxsMobilePhone
       }).then((res) => {
        console.log('通话开始时间记录成功');
        this.callId = res;
       }).catch(err => {
        console.error('记录开始时间失败', err);
       });
      }
     };
     wx.onVoIPChatMembersChanged(this.membersChangeListener);

     // 5. 注册通话中断监听
     this.interruptedListener = () => {
      console.log('通话异常中断');
      this.handleCallEnded('通话异常中断');
      this.$emit('call-interrupted');
     };
     wx.onVoIPChatInterrupted(this.interruptedListener);

     // 6. 注册扬声器状态监听
     this.chatSpeakersChangedListener = (res) => {
      console.log('成员通话状态变化事件==', res);
      if (res.openIdList.length === 0) {
       this.isCalling = false
      }
     };
     wx.onVoIPChatSpeakersChanged(this.chatSpeakersChangedListener);

     // 7. 发起通话
     return new Promise((resolve, reject) => {
      wx.join1v1Chat({
       caller: {
        nickname: this.callerName,
        openid: this.callerOpenId || 'oy5ld18ZdfUqHaiCF1QWPAkMe-nM'
       },
       listener: {
        nickname: this.listenerName,
        openid: this.listenerOpenId || 'oy5ld12LFJiyHmDpbz8_r-vnQM-Q'
       },
       roomType: roomType,
       success: (res) => {
        console.log('发起通话请求成功(等待对方接听)');
        this.isCalling = false
        resolve(res);
       },
       fail: (err) => {
        this.isCalling = false
        console.error('join1v1Chat失败:', err);
        reject(err);
       }
      });
     });
     // #endif

     // #ifndef MP-WEIXIN
     throw new Error('当前平台不支持1v1通话功能');
     // #endif
    },

    handleCallEnded(reason) {
     console.log('通话结束:', reason);
     uni.showToast({
      title: reason,
      icon: 'none'
     });

     // 重置状态
     this.isCalling = false;
     this.callStatus = '';

     // 退出通话房间
     if (wx.leaveVoIPChat) {
      wx.leaveVoIPChat({
       success: () => console.log('退出通话房间成功'),
       fail: (err) => console.error('退出通话房间失败:', err)
      });
     }

     // 清理监听
     this.clearAllListeners();
    },

    hangUp() {
     // #ifdef MP-WEIXIN
     wx.leaveVoIPChat({
      success: () => {
       console.log('主动挂断成功');
       this.handleCallEnded('您已挂断通话');
       this.$emit('call-hangup', {
        reason: '主动挂断'
       });
      },
      fail: (err) => {
       console.error('主动挂断失败:', err);
       uni.showToast({
        title: '挂断失败',
        icon: 'none'
       });
      }
     });
     // #endif
    }
   },

   // 页面隐藏时清理资源
   onHide() {
    this.clearAllListeners();
    if (wx.leaveVoIPChat) {
     wx.leaveVoIPChat({
      success: () => console.log('页面隐藏,退出通话房间'),
      fail: (err) => console.error('页面隐藏退出房间失败:', err)
     });
    }
   },

   onUnload() {
    this.clearAllListeners();
    // #ifdef MP-WEIXIN
    if (wx.leaveVoIPChat) {
     wx.leaveVoIPChat({
      success: () => console.log('页面卸载,退出通话房间'),
      fail: (err) => console.error('页面卸载退出房间失败:', err)
     });
    }
    // #endif
   }
  }
</script>

<style>
  .chat-button {
   margin-top: 100px;
   background-color: #07c160;
   width: 200rpx;
   height: 80rpx;
   color: white;
   border: none;
   border-radius: 10rpx;
   font-size: 30rpx;
  }
</style>


回答关注问题邀请回答
收藏

1 个回答

  • 智能回答 智能回答 本次回答由AI生成
    04-15
    有用
    回复
登录 后发表内容