<template>
|
<div class="call-container">
|
<div class="sip-status" :class="sipStatusClass">
|
SIP状态: {{ sipStatus }}
|
</div>
|
|
<!-- 状态显示 -->
|
<div class="call-status" :class="callStatusClass">
|
{{ callStatusText }}
|
</div>
|
|
<!-- 呼叫按钮 -->
|
<button
|
:class="['call-btn', { calling: isCalling }]"
|
@click="startCall"
|
:disabled="isCalling || sipStatus !== '已注册'"
|
>
|
{{ callButtonText }}
|
</button>
|
|
<!-- 挂断按钮 -->
|
<button v-if="isCalling" class="end-call-btn" @click="endCall">挂断</button>
|
|
<!-- 音频元素(隐藏) -->
|
<audio id="remoteAudio" autoplay></audio>
|
</div>
|
</template>
|
|
<script>
|
import sipService from "@/utils/sipService";
|
|
export default {
|
props: {
|
phoneNumber: {
|
type: String,
|
default: "",
|
},
|
},
|
data() {
|
const randomNum = Math.floor(Math.random() * 11) + 1000; // 内部定义
|
return {
|
isCalling: false,
|
callStatus: "idle", // idle, calling, connected, ended
|
sipStatus: "未连接",
|
sipStatusClass: "status-disconnected",
|
sipConfig: {
|
wsUrl: "wss://192.168.10.124:7443",
|
sipUri: `${randomNum}` + "@192.168.10.124",
|
password: "Smartor@2023",
|
displayName: "Web 小龙",
|
},
|
};
|
},
|
computed: {
|
callStatusText() {
|
const statusMap = {
|
idle: "准备就绪",
|
calling: "呼叫中...",
|
connected: "通话中",
|
ended: "通话结束",
|
};
|
return statusMap[this.callStatus];
|
},
|
callStatusClass() {
|
return `status-${this.callStatus}`;
|
},
|
callButtonText() {
|
return this.isCalling ? "通话中..." : "一键呼叫";
|
},
|
},
|
mounted() {
|
sipService.init(this.sipConfig);
|
sipService.onStatusChange = (status) => {
|
this.sipStatus = status.text;
|
this.sipStatusClass = `status-${status.type}`;
|
};
|
|
// 监听通话状态变化
|
sipService.onCallStatusChange = (status) => {
|
this.callStatus = status.type;
|
this.isCalling = status.type === "calling" || status.type === "connected";
|
|
// 通知父组件通话状态变化
|
this.$emit("call-status-change", status);
|
};
|
},
|
methods: {
|
async startCall() {
|
if (!this.phoneNumber) {
|
this.$message.error("请输入电话号码");
|
return;
|
}
|
|
try {
|
this.callStatus = "calling";
|
this.isCalling = true;
|
|
await sipService.makeCall(this.phoneNumber);
|
} catch (error) {
|
console.error("呼叫失败:", error);
|
this.callStatus = "ended";
|
this.isCalling = false;
|
this.$message.error(`呼叫失败: ${error.message}`);
|
}
|
},
|
|
endCall() {
|
sipService.endCall();
|
this.callStatus = "ended";
|
this.isCalling = false;
|
},
|
},
|
};
|
</script>
|
|
<style scoped>
|
.call-container {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
max-width: 300px;
|
margin: 0 auto;
|
padding: 20px;
|
border: 1px solid #eee;
|
border-radius: 8px;
|
}
|
|
input {
|
padding: 8px;
|
border: 1px solid #ccc;
|
border-radius: 4px;
|
}
|
|
.call-btn {
|
padding: 10px;
|
background-color: #4caf50;
|
color: white;
|
border: none;
|
border-radius: 4px;
|
cursor: pointer;
|
}
|
.call-status {
|
padding: 8px;
|
margin: 10px 0;
|
border-radius: 4px;
|
text-align: center;
|
}
|
|
.status-idle {
|
background-color: #f5f5f5;
|
color: #666;
|
}
|
|
.status-calling {
|
background-color: #fff8e1;
|
color: #ff8f00;
|
}
|
|
.status-connected {
|
background-color: #e8f5e9;
|
color: #2e7d32;
|
}
|
|
.status-ended {
|
background-color: #ffebee;
|
color: #c62828;
|
}
|
|
/* 原有样式保持不变 */
|
.call-container {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
max-width: 300px;
|
margin: 0 auto;
|
padding: 20px;
|
border: 1px solid #eee;
|
border-radius: 8px;
|
}
|
|
.call-btn {
|
padding: 10px;
|
background-color: #4caf50;
|
color: white;
|
border: none;
|
border-radius: 4px;
|
cursor: pointer;
|
}
|
|
.call-btn:hover:not(:disabled) {
|
background-color: #45a049;
|
}
|
|
.call-btn:disabled {
|
background-color: #cccccc;
|
cursor: not-allowed;
|
}
|
|
.call-btn.calling {
|
background-color: #2196f3;
|
}
|
|
.end-call-btn {
|
padding: 10px;
|
background-color: #f44336;
|
color: white;
|
border: none;
|
border-radius: 4px;
|
cursor: pointer;
|
}
|
|
.end-call-btn:hover {
|
background-color: #d32f2f;
|
}
|
|
.sip-status {
|
padding: 8px;
|
margin-bottom: 10px;
|
border-radius: 4px;
|
text-align: center;
|
}
|
|
.status-disconnected {
|
background-color: #ffebee;
|
color: #c62828;
|
}
|
|
.status-connecting {
|
background-color: #fff8e1;
|
color: #ff8f00;
|
}
|
|
.status-registered {
|
background-color: #e8f5e9;
|
color: #2e7d32;
|
}
|
|
.status-failed {
|
background-color: #ffebee;
|
color: #c62828;
|
}
|
.call-btn:hover {
|
background-color: #45a049;
|
}
|
|
.call-btn.calling {
|
background-color: #2196f3;
|
}
|
|
.end-call-btn {
|
padding: 10px;
|
background-color: #f44336;
|
color: white;
|
border: none;
|
border-radius: 4px;
|
cursor: pointer;
|
}
|
|
.end-call-btn:hover {
|
background-color: #d32f2f;
|
}
|
|
.call-status {
|
margin-top: 10px;
|
font-size: 14px;
|
color: #666;
|
}
|
.sip-status {
|
padding: 8px;
|
margin-bottom: 10px;
|
border-radius: 4px;
|
text-align: center;
|
}
|
|
.status-disconnected {
|
background-color: #ffebee;
|
color: #c62828;
|
}
|
|
.status-connecting {
|
background-color: #fff8e1;
|
color: #ff8f00;
|
}
|
|
.status-registered {
|
background-color: #e8f5e9;
|
color: #2e7d32;
|
}
|
|
.status-failed {
|
background-color: #ffebee;
|
color: #c62828;
|
}
|
</style>
|