|
|
@@ -174,14 +174,10 @@
|
|
|
|
|
|
<script>
|
|
|
import TRTC from 'trtc-sdk-v5';
|
|
|
- import {
|
|
|
- BasicBeauty
|
|
|
- } from 'trtc-sdk-v5/plugins/video-effect/basic-beauty';
|
|
|
+ import { BasicBeauty } from 'trtc-sdk-v5/plugins/video-effect/basic-beauty';
|
|
|
import smhTimer from '@/components/smh-timer/smh-timer.vue'
|
|
|
export default {
|
|
|
- components: {
|
|
|
- smhTimer
|
|
|
- },
|
|
|
+ components: { smhTimer },
|
|
|
data() {
|
|
|
return {
|
|
|
sdkAppId: parseInt(uni.getStorageSync('sdkAppId')), //trtcSdkAppId
|
|
|
@@ -197,16 +193,10 @@
|
|
|
trtc: null, //trtc单例对象
|
|
|
isOpenMicrophone: true, //是否打开麦克风
|
|
|
isOpenCamera: true, //摄像头是否开启
|
|
|
- resumesIdInfo: {
|
|
|
- resumesName: '',
|
|
|
- avatar: '',
|
|
|
- }, //用户简历
|
|
|
- company: {
|
|
|
- companyLogo: '',
|
|
|
- companyName: '',
|
|
|
- }, //企业信息
|
|
|
+ resumesIdInfo: { resumesName: '', avatar: '' }, //用户简历
|
|
|
+ company: { companyLogo: '', companyName: '' }, //企业信息
|
|
|
userType: 1, //1:用户 2:企业
|
|
|
- postPushId: '', //岗位id,
|
|
|
+ postPushId: '', //岗位id
|
|
|
resumesId: '', //简历id
|
|
|
isRemoterAvailable: false, //是否拉取到别人的视频流
|
|
|
cameraType: 1, //默认使用前置摄像头
|
|
|
@@ -217,11 +207,10 @@
|
|
|
//通话中
|
|
|
if (this.videoStatus == 2) {
|
|
|
console.log('开始拉取视频')
|
|
|
- //接通后开启音频
|
|
|
- this.startLocalAudio()
|
|
|
+ // 新增:接通后先校验麦克风权限,再开启音频
|
|
|
+ this.checkMicPermissionThenStartAudio();
|
|
|
this.isJie = true
|
|
|
-
|
|
|
- } else if (this.videoStatus == 4) { //如果等于4,那么就是挂断电话
|
|
|
+ } else if (this.videoStatus == 4) { //挂断电话
|
|
|
console.log(this.videoStatus, '走这里了4444444')
|
|
|
this.exitRoom()
|
|
|
}
|
|
|
@@ -231,53 +220,21 @@
|
|
|
//定时获取通话状态
|
|
|
this.getVideoStatus()
|
|
|
let systemInfo = uni.getSystemInfoSync();
|
|
|
- console.log(systemInfo, '系统信息')
|
|
|
- //获取屏幕高度
|
|
|
- //获取手机系统状态栏高度
|
|
|
this.screenHeight = systemInfo.windowHeight - systemInfo.statusBarHeight;
|
|
|
- if (option.byUserId) {
|
|
|
- this.byUserId = option.byUserId
|
|
|
- }
|
|
|
- if (option.isRol) {
|
|
|
- this.isRol = option.isRol
|
|
|
- }
|
|
|
- if (option.messageType) {
|
|
|
- this.messageType = option.messageType
|
|
|
- }
|
|
|
- if (option.chatConversationId) {
|
|
|
- this.chatConversationId = option.chatConversationId
|
|
|
- }
|
|
|
+
|
|
|
+ //赋值参数
|
|
|
+ if (option.byUserId) this.byUserId = option.byUserId
|
|
|
+ if (option.isRol) this.isRol = option.isRol
|
|
|
+ if (option.messageType) this.messageType = option.messageType
|
|
|
+ if (option.chatConversationId) this.chatConversationId = option.chatConversationId
|
|
|
if (option.chatContentId) {
|
|
|
this.chatContentId = option.chatContentId
|
|
|
- //获取getUserSig 开始进房操作
|
|
|
- this.getUserSig()
|
|
|
- }
|
|
|
- if (option.postPushId) {
|
|
|
- this.postPushId = option.postPushId
|
|
|
+ // 新增:获取签名前先校验基础权限(防止无权限进房)
|
|
|
+ this.checkBasePermissionThenGetSig();
|
|
|
}
|
|
|
- if (option.resumesId) {
|
|
|
- this.resumesId = option.resumesId
|
|
|
- }
|
|
|
- // if (option.userType) {
|
|
|
- // this.userType = option.userType
|
|
|
- // if (this.userType == 1) { //发起人是用户
|
|
|
- // if (this.isRol == 1) { //发起人
|
|
|
- // //查询企业信息
|
|
|
- // this.selectPostPushDetails()
|
|
|
- // } else { //接受人
|
|
|
- // //查询用户简历信息
|
|
|
- // this.selectResumesByResumesId()
|
|
|
- // }
|
|
|
- // } else { //发起人是企业
|
|
|
- // if (this.isRol == 1) { //发起人
|
|
|
- // //查询用户简历信息
|
|
|
- // this.selectResumesByResumesId()
|
|
|
- // } else { //接受人
|
|
|
- // //查询企业信息
|
|
|
- // this.selectPostPushDetails()
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
+ if (option.postPushId) this.postPushId = option.postPushId
|
|
|
+ if (option.resumesId) this.resumesId = option.resumesId
|
|
|
+
|
|
|
this.userType = uni.getStorageSync('userType')
|
|
|
this.selectPostPushDetails()
|
|
|
this.selectResumesByResumesId()
|
|
|
@@ -286,250 +243,253 @@
|
|
|
this.addRefreshListener()
|
|
|
},
|
|
|
onUnload(e) {
|
|
|
- console.log(e, '页面卸载')
|
|
|
clearInterval(this.videoStatusInter)
|
|
|
this.videoStatusInter = null
|
|
|
this.unloadRoom()
|
|
|
},
|
|
|
onBackPress(e) {
|
|
|
- if (e.from != 'navigateBack') { //如果不是挂断也走挂断操作
|
|
|
+ if (e.from != 'navigateBack') {
|
|
|
this.jieOrGuaCall(5)
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
- //翻转摄像头
|
|
|
+ // 新增:校验音视频基础权限后再获取签名(核心)
|
|
|
+ async checkBasePermissionThenGetSig() {
|
|
|
+ // 1. 校验麦克风权限(所有通话必选)
|
|
|
+ const hasMic = await this.$queue.checkPermission(
|
|
|
+ 'microphone',
|
|
|
+ '音视频通话需要麦克风权限,用于正常语音沟通'
|
|
|
+ );
|
|
|
+ if (!hasMic) {
|
|
|
+ uni.showToast({ title: '麦克风权限不足,无法进行通话', icon: 'none' });
|
|
|
+ this.exitRoom();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 视频通话额外校验相机权限
|
|
|
+ if (this.messageType === 20) {
|
|
|
+ const hasCamera = await this.$queue.checkPermission(
|
|
|
+ 'camera',
|
|
|
+ '视频通话需要相机权限,用于正常视频展示'
|
|
|
+ );
|
|
|
+ if (!hasCamera) {
|
|
|
+ uni.showToast({ title: '相机权限不足,无法进行视频通话', icon: 'none' });
|
|
|
+ this.exitRoom();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 权限通过,才获取签名并进房
|
|
|
+ this.getUserSig();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 新增:校验麦克风权限后再开启音频
|
|
|
+ async checkMicPermissionThenStartAudio() {
|
|
|
+ const hasMic = await this.$queue.checkPermission('microphone', '通话需要麦克风权限');
|
|
|
+ if (hasMic) {
|
|
|
+ this.startLocalAudio();
|
|
|
+ } else {
|
|
|
+ this.isOpenMicrophone = false;
|
|
|
+ uni.showToast({ title: '麦克风权限不足,无法正常通话', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 翻转摄像头
|
|
|
async selectVideoCamera() {
|
|
|
- if (this.cameraType == 2) { //切换至前置摄像头
|
|
|
- await this.trtc.updateLocalVideo({
|
|
|
- option: {
|
|
|
- useFrontCamera: true
|
|
|
- }
|
|
|
- });
|
|
|
+ // 切换摄像头前再次校验相机权限
|
|
|
+ if (this.messageType === 20) {
|
|
|
+ const hasCamera = await this.$queue.checkPermission('camera', '切换摄像头需要相机权限');
|
|
|
+ if (!hasCamera) {
|
|
|
+ uni.showToast({ title: '相机权限不足,无法切换摄像头', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.cameraType == 2) {
|
|
|
+ await this.trtc.updateLocalVideo({ option: { useFrontCamera: true } });
|
|
|
this.cameraType = 1
|
|
|
- } else { //切换至后置摄像头
|
|
|
- await this.trtc.updateLocalVideo({
|
|
|
- option: {
|
|
|
- useFrontCamera: false
|
|
|
- }
|
|
|
- });
|
|
|
+ } else {
|
|
|
+ await this.trtc.updateLocalVideo({ option: { useFrontCamera: false } });
|
|
|
this.cameraType = 2
|
|
|
}
|
|
|
},
|
|
|
- //计时回掉
|
|
|
- timing(e) {
|
|
|
|
|
|
- },
|
|
|
- //打开摄像头
|
|
|
+ // 打开摄像头(加权限校验)
|
|
|
async openCamera() {
|
|
|
- // 打开摄像头
|
|
|
- await this.trtc.updateLocalVideo({
|
|
|
- mute: false
|
|
|
- });
|
|
|
+ const hasCamera = await this.$queue.checkPermission('camera', '打开摄像头需要相机权限');
|
|
|
+ if (!hasCamera) {
|
|
|
+ uni.showToast({ title: '相机权限不足,无法打开摄像头', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ await this.trtc.updateLocalVideo({ mute: false });
|
|
|
this.isOpenCamera = true
|
|
|
},
|
|
|
- //关闭摄像头
|
|
|
+
|
|
|
+ // 关闭摄像头
|
|
|
async closeCamera() {
|
|
|
- // 关闭摄像头,在关闭摄像头后,摄像头预览画面会变成黑屏,您可以在此时显示业务侧自身的 UI 遮罩。
|
|
|
- await this.trtc.updateLocalVideo({
|
|
|
- mute: true
|
|
|
- });
|
|
|
+ await this.trtc.updateLocalVideo({ mute: true });
|
|
|
this.isOpenCamera = false
|
|
|
},
|
|
|
- //获取企业信息
|
|
|
+
|
|
|
+ // 获取企业信息
|
|
|
selectPostPushDetails() {
|
|
|
- let data = {
|
|
|
- postPushId: this.postPushId
|
|
|
- }
|
|
|
+ let data = { postPushId: this.postPushId }
|
|
|
this.$Request.getT('/app/postPush/selectPostPushDetails', data).then(res => {
|
|
|
- if (res.code == 0) {
|
|
|
- this.company = res.data.company
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- title: res.msg,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- }
|
|
|
+ if (res.code == 0) this.company = res.data.company
|
|
|
+ else uni.showToast({ title: res.msg, icon: 'none' })
|
|
|
})
|
|
|
},
|
|
|
- //获取用户简历
|
|
|
+
|
|
|
+ // 获取用户简历
|
|
|
selectResumesByResumesId() {
|
|
|
- let data = {
|
|
|
- resumesId: this.resumesId
|
|
|
- }
|
|
|
+ let data = { resumesId: this.resumesId }
|
|
|
this.$Request.getT('/app/resumes/selectResumesByResumesId', data).then(res => {
|
|
|
- if (res.code == 0) {
|
|
|
- this.resumesIdInfo = res.data
|
|
|
- }
|
|
|
+ if (res.code == 0) this.resumesIdInfo = res.data
|
|
|
})
|
|
|
},
|
|
|
- //监听页面是否刷新了
|
|
|
+
|
|
|
+ // 监听页面刷新
|
|
|
addRefreshListener() {
|
|
|
- // 监听页面显示的事件,可以用来判断是否刷新了页面
|
|
|
window.addEventListener('pageshow', (event) => {
|
|
|
- console.log(event, '页面刷新了')
|
|
|
- // alert('页面刷新了')
|
|
|
this.jieOrGuaCall(5)
|
|
|
- // 页面刷新了直接挂断电话
|
|
|
});
|
|
|
},
|
|
|
- //退房并销毁trtc
|
|
|
+
|
|
|
+ // 退房并销毁trtc
|
|
|
async unloadRoom() {
|
|
|
- await this.trtc.exitRoom();
|
|
|
- // 退房成功后,若后续无需使用 trtc 实例,则可以调用 trtc.destroy 方法销毁实例,及时释放相关资源。销毁后的 trtc 实例无法继续使用,需要重新创建新的实例。
|
|
|
- this.trtc.destroy();
|
|
|
+ if (this.trtc) {
|
|
|
+ await this.trtc.exitRoom();
|
|
|
+ this.trtc.destroy();
|
|
|
+ this.trtc = null;
|
|
|
+ }
|
|
|
},
|
|
|
- //关闭/开启摄像头
|
|
|
+
|
|
|
+ // 关闭/开启麦克风(加权限校验)
|
|
|
async setStopLocalAudio() {
|
|
|
- if (this.isOpenMicrophone) { //如果开启则静音
|
|
|
- await this.trtc.updateLocalAudio({
|
|
|
- mute: true
|
|
|
- })
|
|
|
+ const hasMic = await this.$queue.checkPermission('microphone', '操作麦克风需要权限');
|
|
|
+ if (!hasMic) {
|
|
|
+ uni.showToast({ title: '麦克风权限不足,无法操作', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.isOpenMicrophone) {
|
|
|
+ await this.trtc.updateLocalAudio({ mute: true })
|
|
|
this.isOpenMicrophone = false
|
|
|
} else {
|
|
|
- await this.trtc.updateLocalAudio({
|
|
|
- mute: false
|
|
|
- })
|
|
|
+ await this.trtc.updateLocalAudio({ mute: false })
|
|
|
this.isOpenMicrophone = true
|
|
|
}
|
|
|
},
|
|
|
- //退房
|
|
|
+
|
|
|
+ // 退房
|
|
|
async exitRoom() {
|
|
|
let pages = getCurrentPages();
|
|
|
let hasPrevPage = pages.length > 1;
|
|
|
+ uni.setStorageSync('isDial', false)
|
|
|
if (hasPrevPage) {
|
|
|
- // 有上一页
|
|
|
- //直接返回
|
|
|
uni.navigateBack()
|
|
|
- uni.setStorageSync('isDial', false)
|
|
|
} else {
|
|
|
- // 没有上一页
|
|
|
- //返回首页
|
|
|
- uni.switchTab({
|
|
|
- url: '/pages/index/index'
|
|
|
- })
|
|
|
- uni.setStorageSync('isDial', false)
|
|
|
+ uni.switchTab({ url: '/pages/index/index' })
|
|
|
}
|
|
|
},
|
|
|
- //接电话或拒绝
|
|
|
+
|
|
|
+ // 接/挂电话(加权限校验)
|
|
|
jieOrGuaCall(type) {
|
|
|
- let data = {
|
|
|
- videoStatus: type,
|
|
|
- chatContentId: this.chatContentId,
|
|
|
- }
|
|
|
+ let data = { videoStatus: type, chatContentId: this.chatContentId }
|
|
|
this.$Request.post('/app/chat/updateChatContent', data).then(res => {
|
|
|
if (res.code == 0) {
|
|
|
if (type == 4 || type == 5) {
|
|
|
this.exitRoom()
|
|
|
- } else if (type == 2) { //接通(接受人)
|
|
|
+ } else if (type == 2) { // 接受人接通
|
|
|
this.isJie = true
|
|
|
- if (this.messageType == 20) { //视频通话时开启摄像头
|
|
|
- setTimeout(() => {
|
|
|
- this.openCameraAndAudio()
|
|
|
- }, 500)
|
|
|
+ if (this.messageType == 20) {
|
|
|
+ // 接通视频前再次校验相机权限
|
|
|
+ this.$queue.checkPermission('camera', '视频通话需要相机权限').then(hasCamera => {
|
|
|
+ if (hasCamera) {
|
|
|
+ setTimeout(() => { this.openCameraAndAudio() }, 500)
|
|
|
+ } else {
|
|
|
+ this.jieOrGuaCall(4); // 权限不足自动挂断
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
- uni.showToast({
|
|
|
- title: res.msg,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
+ uni.showToast({ title: res.msg, icon: 'none' })
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
- //获取sign
|
|
|
+
|
|
|
+ // 获取sign(原有逻辑,权限校验已提前)
|
|
|
getUserSig() {
|
|
|
this.$Request.getT('/app/chat/selectSign').then(res => {
|
|
|
- if (res.code == 0) {
|
|
|
- //进房
|
|
|
- this.setEnterRoom(res.data)
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- title: res.msg,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- }
|
|
|
+ if (res.code == 0) this.setEnterRoom(res.data)
|
|
|
+ else uni.showToast({ title: res.msg, icon: 'none' })
|
|
|
})
|
|
|
},
|
|
|
- //h5进房
|
|
|
+
|
|
|
+ // 进房(权限已提前校验)
|
|
|
async setEnterRoom(userSig) {
|
|
|
try {
|
|
|
let data = {
|
|
|
strRoomId: this.chatContentId.toString(),
|
|
|
- scene: 'rtc', //rtc实时通话模式 live在线直播模式
|
|
|
+ scene: 'rtc',
|
|
|
sdkAppId: this.sdkAppId,
|
|
|
userId: uni.getStorageSync('userId') + '',
|
|
|
userSig: userSig,
|
|
|
- role: 'anchor', //anchor:“主播”角色,可以推流和拉流。 audience:“观众”角色,只能拉流观看,无法推流。
|
|
|
- autoReceiveAudio: true, //自动接收音频
|
|
|
+ role: 'anchor',
|
|
|
+ autoReceiveAudio: true,
|
|
|
}
|
|
|
await this.trtc.enterRoom(data);
|
|
|
- if (this.messageType == 20) { //视频通话时开启摄像头
|
|
|
- // if (this.isRol == 1) { //是发起人则直接打开摄像头
|
|
|
- // this.openCameraAndAudio()
|
|
|
- // }
|
|
|
+
|
|
|
+ // 视频通话开启摄像头(权限已校验)
|
|
|
+ if (this.messageType == 20) {
|
|
|
this.openCameraAndAudio()
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
console.log('进房成功');
|
|
|
} catch (error) {
|
|
|
console.error('进房失败 ' + error);
|
|
|
}
|
|
|
},
|
|
|
+
|
|
|
+ // 开启摄像头和音频(权限已提前校验)
|
|
|
async openCameraAndAudio() {
|
|
|
- //开启摄像头
|
|
|
const view = 'local-video';
|
|
|
- await this.trtc.startLocalVideo({
|
|
|
- view
|
|
|
- });
|
|
|
- // 设置基础美颜效果
|
|
|
+ await this.trtc.startLocalVideo({ view });
|
|
|
+ // 基础美颜
|
|
|
await this.trtc.startPlugin('BasicBeauty', {
|
|
|
- beauty: 0.5, // 美颜
|
|
|
- brightness: 0.5, // 明亮
|
|
|
- ruddy: 0.5, // 红润
|
|
|
+ beauty: 0.5, brightness: 0.5, ruddy: 0.5,
|
|
|
});
|
|
|
- //摄像头状态设置为开启
|
|
|
this.isOpenCamera = true
|
|
|
},
|
|
|
- //对方退房(挂断)
|
|
|
+
|
|
|
+ // 监听对方退房
|
|
|
getRemoteUserExit() {
|
|
|
- //监听对方是否退房
|
|
|
+ if (!this.trtc) return;
|
|
|
this.trtc.on(TRTC.EVENT.REMOTE_USER_EXIT, event => {
|
|
|
- // 如果对方退房了则是对方挂断了了,自己也走退房
|
|
|
this.exitRoom()
|
|
|
});
|
|
|
},
|
|
|
- //创建trtc单例并监听视频流
|
|
|
+
|
|
|
+ // 创建trtc实例
|
|
|
onRemoteVideoAvailable() {
|
|
|
- //创建trtc实例
|
|
|
- this.trtc = TRTC.create({
|
|
|
- plugins: [BasicBeauty]
|
|
|
- });
|
|
|
- this.trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, ({
|
|
|
- userId,
|
|
|
- streamType
|
|
|
- }) => {
|
|
|
- this.isRemoterAvailable = true
|
|
|
- // 为了播放视频画面,您需在 DOM 中放置一个 HTMLElement,可以是一个 div 标签,假设其 id 为 `${userId}_${streamType}`
|
|
|
- const view = 'myLocalVideo';
|
|
|
- this.trtc.startRemoteVideo({
|
|
|
- userId,
|
|
|
- streamType,
|
|
|
- view
|
|
|
+ if (!this.trtc) {
|
|
|
+ this.trtc = TRTC.create({ plugins: [BasicBeauty] });
|
|
|
+ this.trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, ({ userId, streamType }) => {
|
|
|
+ this.isRemoterAvailable = true
|
|
|
+ const view = 'myLocalVideo';
|
|
|
+ this.trtc.startRemoteVideo({ userId, streamType, view });
|
|
|
});
|
|
|
- console.log('已拉取到别人的视频流')
|
|
|
- //已拉取到别人的视频流
|
|
|
-
|
|
|
- });
|
|
|
+ }
|
|
|
},
|
|
|
- //开启麦克风
|
|
|
+
|
|
|
+ // 开启麦克风(权限已提前校验)
|
|
|
async startLocalAudio() {
|
|
|
- //开启麦克风
|
|
|
await this.trtc.startLocalAudio();
|
|
|
this.isOpenMicrophone = true
|
|
|
},
|
|
|
- //定时器获取接电话的状态
|
|
|
+
|
|
|
+ // 定时获取通话状态
|
|
|
getVideoStatus() {
|
|
|
this.videoStatus = uni.getStorageSync('videoStatus')
|
|
|
this.videoStatusInter = setInterval(() => {
|
|
|
@@ -540,6 +500,7 @@
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
+
|
|
|
<style lang="scss">
|
|
|
.videoContont {
|
|
|
background-image: radial-gradient(circle at center, #00DD9A 10%, #0D0D0D 100%);
|