
<template>
<view>
</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'
},
},
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;
},
init1V1Chat() {
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)
}
})
},
clearAllListeners() {
if (this.stateChangeListener) {
wx.offVoIPChatStateChanged(this.stateChangeListener);
this.stateChangeListener = null;
}
if (this.membersChangeListener) {
wx.offVoIPChatMembersChanged(this.membersChangeListener);
this.membersChangeListener = null;
}
if (this.interruptedListener) {
wx.offVoIPChatInterrupted(this.interruptedListener);
this.interruptedListener = null;
}
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() {
await requestVoipPermission(this.roomType)
const roomType = this.roomType === '1' ? 'video' : 'voice';
this.clearAllListeners();
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);
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);
this.interruptedListener = () => {
console.log('通话异常中断');
this.handleCallEnded('通话异常中断');
this.$emit('call-interrupted');
};
wx.onVoIPChatInterrupted(this.interruptedListener);
this.chatSpeakersChangedListener = (res) => {
console.log('成员通话状态变化事件==', res);
if (res.openIdList.length === 0) {
this.isCalling = false
}
};
wx.onVoIPChatSpeakersChanged(this.chatSpeakersChangedListener);
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);
}
});
});
throw new Error('当前平台不支持1v1通话功能');
},
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() {
wx.leaveVoIPChat({
success: () => {
console.log('主动挂断成功');
this.handleCallEnded('您已挂断通话');
this.$emit('call-hangup', {
reason: '主动挂断'
});
},
fail: (err) => {
console.error('主动挂断失败:', err);
uni.showToast({
title: '挂断失败',
icon: 'none'
});
}
});
}
},
onHide() {
this.clearAllListeners();
if (wx.leaveVoIPChat) {
wx.leaveVoIPChat({
success: () => console.log('页面隐藏,退出通话房间'),
fail: (err) => console.error('页面隐藏退出房间失败:', err)
});
}
},
onUnload() {
this.clearAllListeners();
if (wx.leaveVoIPChat) {
wx.leaveVoIPChat({
success: () => console.log('页面卸载,退出通话房间'),
fail: (err) => console.error('页面卸载退出房间失败:', err)
});
}
}
}
</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>