From 741805d8daa2d2baa0b6b75bc1724488baf9c6bc Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期一, 15 六月 2026 14:55:10 +0800
Subject: [PATCH] 测试完成
---
src/components/CallButton/index.vue | 551 ++++++++++++++++++++++++++++++++++++------------------
1 files changed, 369 insertions(+), 182 deletions(-)
diff --git a/src/components/CallButton/index.vue b/src/components/CallButton/index.vue
index bc17eea..d95fb2f 100644
--- a/src/components/CallButton/index.vue
+++ b/src/components/CallButton/index.vue
@@ -2,6 +2,9 @@
<div class="call-container">
<div class="sip-status" :class="sipStatusClass">
SIP鐘舵��: {{ sipStatus }}
+ <span v-if="reconnectCount > 0" class="reconnect-info">
+ (閲嶈繛: {{ reconnectCount }}娆�)
+ </span>
</div>
<!-- 鐘舵�佹樉绀� -->
@@ -11,11 +14,29 @@
<!-- 鍛煎彨鎸夐挳 -->
<button
- :class="['call-btn', { calling: isCalling }]"
+ :class="[
+ 'call-btn',
+ {
+ calling: isCalling,
+ registering: isRegistering,
+ reconnecting: isReconnecting,
+ },
+ ]"
@click="startCall"
- :disabled="isCalling || sipStatus !== '宸叉敞鍐�'"
+ :disabled="isButtonDisabled"
>
+ <i v-if="isRegistering || isReconnecting" class="el-icon-loading"></i>
{{ callButtonText }}
+ </button>
+
+ <!-- 鎵嬪姩閲嶈繛鎸夐挳 -->
+ <button
+ v-if="showManualReconnect"
+ class="reconnect-btn"
+ @click="manualReconnect"
+ :disabled="isRegistering"
+ >
+ 鎵嬪姩閲嶈繛
</button>
<!-- 鎸傛柇鎸夐挳 -->
@@ -38,20 +59,28 @@
},
},
data() {
- const randomNum = Math.floor(Math.random() * 20) + 1000; // 瀹氫箟闅忔満鍒嗘満鍙�
+ const randomNum = Math.floor(Math.random() * 20) + 1000;
return {
isCalling: false,
+ isRegistering: true,
+ isReconnecting: false, // 娣诲姞閲嶈繛涓姸鎬�
randomNum: randomNum,
randomID: null,
- callStatus: "idle", // idle, calling, connected, ended
+ orgname: localStorage.getItem("orgname"),
+ callStatus: "idle",
sipStatus: "鏈繛鎺�",
sipStatusClass: "status-disconnected",
+ reconnectCount: 0, // 閲嶈繛娆℃暟
+ lastActivityTime: null, // 鏈�鍚庢椿鍔ㄦ椂闂�
+ heartbeatTimer: null, // 蹇冭烦瀹氭椂鍣�
+ reconnectTimer: null, // 閲嶈繛瀹氭椂鍣�
+ maxReconnectAttempts: 5, // 鏈�澶ч噸杩炲皾璇曟鏁�
+ reconnectDelay: 5000, // 閲嶈繛寤惰繜(ms)
sipConfig: {
- wsUrl: "wss://192.168.10.124:7443",
+ wsUrl: "",
sipUri: "",
password: "Smartor@2023",
displayName: "Web 灏忛緳",
- // realm: "9.208.5.18:8090",
},
};
},
@@ -67,48 +96,246 @@
},
countdownText() {
if (this.sipStatus !== "宸叉敞鍐�") return "";
-
const { canCall, reason } = sipService.canMakeCall();
if (!canCall && reason.includes("绛夊緟")) {
return reason;
}
return "";
},
+ isButtonDisabled() {
+ return (
+ this.isCalling ||
+ this.sipStatus !== "宸叉敞鍐�" ||
+ this.isRegistering ||
+ this.isReconnecting
+ );
+ },
+ callButtonText() {
+ if (this.isRegistering) return "娉ㄥ唽涓�...";
+ if (this.isReconnecting) return "閲嶈繛涓�...";
+ return this.isCalling ? "閫氳瘽涓�..." : "涓�閿懠鍙�";
+ },
callStatusClass() {
return `status-${this.callStatus}`;
},
- callButtonText() {
- return this.isCalling ? "閫氳瘽涓�..." : "涓�閿懠鍙�";
+ showManualReconnect() {
+ return (
+ !this.isCalling &&
+ !this.isRegistering &&
+ this.sipStatus !== "宸叉敞鍐�" &&
+ this.sipStatus !== "杩炴帴涓�"
+ );
},
},
created() {
- // CallgetList();
+ if (
+ this.orgname == "绗竴浜烘皯鍖婚櫌婀栨花闄㈠尯" ||
+ this.orgname == "绗竴浜烘皯鍖婚櫌鍚村北闄㈠尯"
+ ) {
+ this.sipConfig.password = "heskj@1234";
+ } else {
+ this.sipConfig.password = "Smartor@2023";
+ }
},
async mounted() {
+ const orgName = localStorage.getItem("orgname");
+ if (orgName == "鏅畞鐣叉棌鑷不鍘夸汉姘戝尰闄�") {
+ return;
+ }
await this.CallgetList();
- sipService.init(this.sipConfig);
- // 璁剧疆鐘舵�佸洖璋�
- sipService.onStatusChange = (status) => {
- this.sipStatus = status.text;
- this.sipStatusClass = `status-${status.type}`;
-
- // 澶勭悊娉ㄥ唽澶辫触鍜屾柇寮�杩炴帴鎯呭喌
- if (status.type === "failed" || status.type === "disconnected") {
- this.overCallsetState(); // 閲婃斁鍒嗘満鍙�
- }
- };
-
- // 鐩戝惉閫氳瘽鐘舵�佸彉鍖�
- sipService.onCallStatusChange = (status) => {
- this.callStatus = status.type;
- this.isCalling = status.type === "calling" || status.type === "connected";
-
- // 閫氱煡鐖剁粍浠堕�氳瘽鐘舵�佸彉鍖�
- this.$emit("call-status-change", status);
- };
+ this.isRegistering = true;
+ this.initSipService();
+ this.setupHeartbeat();
},
methods: {
+ async initSipService() {
+ try {
+ // 鍒濆鍖杝ipService
+ sipService.init(this.sipConfig);
+
+ // 璁剧疆鐘舵�佸洖璋�
+ sipService.onStatusChange = (status) => {
+ this.sipStatus = status.text;
+ this.sipStatusClass = `status-${status.type}`;
+
+ // 澶勭悊鍚勭鐘舵��
+ if (status.type === "registered") {
+ this.handleRegistered();
+ } else if (status.type === "failed" || status.type === "disconnected") {
+ this.handleDisconnected();
+ } else if (status.type === "connecting") {
+ this.handleConnecting();
+ }
+ };
+
+ // 鐩戝惉閫氳瘽鐘舵�佸彉鍖�
+ sipService.onCallStatusChange = (status) => {
+ this.callStatus = status.type;
+ this.isCalling = status.type === "calling" || status.type === "connected";
+ this.updateLastActivityTime(); // 閫氳瘽鐘舵�佸彉鍖栨椂鏇存柊娲诲姩鏃堕棿
+
+ this.$emit("call-status-change", status);
+ };
+
+ // 璁剧疆瓒呮椂澶勭悊
+ this.setupRegistrationTimeout();
+
+ } catch (error) {
+ console.error("SIP鏈嶅姟鍒濆鍖栧け璐�:", error);
+ this.handleDisconnected();
+ }
+ },
+
+ handleRegistered() {
+ console.log("SIP娉ㄥ唽鎴愬姛");
+ this.isRegistering = false;
+ this.isReconnecting = false;
+ this.reconnectCount = 0; // 閲嶇疆閲嶈繛璁℃暟
+ this.updateLastActivityTime();
+ this.startCallsetState();
+
+ // 娓呴櫎閲嶈繛瀹氭椂鍣�
+ if (this.reconnectTimer) {
+ clearTimeout(this.reconnectTimer);
+ this.reconnectTimer = null;
+ }
+ },
+
+ handleDisconnected() {
+ console.log("SIP杩炴帴鏂紑");
+ this.isRegistering = false;
+ this.overCallsetState();
+
+ // 濡傛灉涓嶆槸閫氳瘽涓柇寮�锛屽皾璇曢噸杩�
+ if (!this.isCalling) {
+ this.scheduleReconnect();
+ }
+ },
+
+ handleConnecting() {
+ this.isReconnecting = true;
+ },
+
+ setupRegistrationTimeout() {
+ setTimeout(() => {
+ if (this.isRegistering && this.sipStatus !== "宸叉敞鍐�") {
+ this.isRegistering = false;
+ this.$message.warning("SIP娉ㄥ唽瓒呮椂锛屾鍦ㄥ皾璇曢噸杩�...");
+ this.scheduleReconnect();
+ }
+ }, 10000);
+ },
+
+ // 璁剧疆蹇冭烦妫�娴�
+ setupHeartbeat() {
+ this.heartbeatTimer = setInterval(() => {
+ this.checkConnection();
+ }, 60000); // 姣�30绉掓鏌ヤ竴娆¤繛鎺�
+ },
+
+ // 妫�鏌ヨ繛鎺ョ姸鎬�
+ async checkConnection() {
+ // 濡傛灉姝e湪娉ㄥ唽銆侀噸杩炴垨閫氳瘽涓紝涓嶆鏌�
+ if (this.isRegistering || this.isReconnecting || this.isCalling) {
+ return;
+ }
+
+ // 妫�鏌IP杩炴帴鐘舵��
+ if (sipService && sipService.ua) {
+ const isConnected = sipService.ua.isConnected();
+ const isRegistered = sipService.ua.isRegistered();
+
+ if (!isConnected || !isRegistered) {
+ console.log("蹇冭烦妫�娴�: 杩炴帴寮傚父锛屽皾璇曢噸杩�");
+ await this.reconnectSip();
+ } else {
+ console.log("蹇冭烦妫�娴�: 杩炴帴姝e父");
+ this.updateLastActivityTime();
+ }
+ } else {
+ console.log("蹇冭烦妫�娴�: UA涓嶅瓨鍦紝灏濊瘯閲嶆柊鍒濆鍖�");
+ await this.reconnectSip();
+ }
+ },
+
+ // 璁″垝閲嶈繛
+ scheduleReconnect() {
+ if (this.reconnectTimer || this.isReconnecting) {
+ return;
+ }
+
+ if (this.reconnectCount >= this.maxReconnectAttempts) {
+ console.log("杈惧埌鏈�澶ч噸杩炴鏁帮紝鍋滄閲嶈繛");
+ this.$message.error("SIP杩炴帴澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯");
+ return;
+ }
+
+ this.reconnectCount++;
+ const delay = Math.min(this.reconnectDelay * Math.pow(1.5, this.reconnectCount - 1), 30000);
+
+ console.log(`璁″垝鍦�${delay}ms鍚庨噸杩烇紝绗�${this.reconnectCount}娆″皾璇昤);
+
+ this.reconnectTimer = setTimeout(() => {
+ this.reconnectSip();
+ }, delay);
+ },
+
+ // 閲嶆柊杩炴帴SIP
+ async reconnectSip() {
+ if (this.isReconnecting || this.isRegistering) {
+ return;
+ }
+
+ console.log("寮�濮嬮噸杩濻IP鏈嶅姟...");
+ this.isReconnecting = true;
+
+ try {
+ // 娓呯悊鐜版湁杩炴帴
+ this.cleanupSipConnection();
+
+ // 绛夊緟涓�娈垫椂闂�
+ await new Promise(resolve => setTimeout(resolve, 1000));
+
+ // 閲嶆柊鍒濆鍖�
+ await this.CallgetList(); // 閲嶆柊鑾峰彇鍒嗘満鍙�
+ this.initSipService();
+
+ } catch (error) {
+ console.error("閲嶈繛澶辫触:", error);
+ this.isReconnecting = false;
+ this.scheduleReconnect(); // 澶辫触鍚庣户缁噸璇�
+ } finally {
+ if (this.reconnectTimer) {
+ clearTimeout(this.reconnectTimer);
+ this.reconnectTimer = null;
+ }
+ }
+ },
+
+ // 娓呯悊SIP杩炴帴
+ cleanupSipConnection() {
+ if (sipService && sipService.ua) {
+ try {
+ sipService.ua.stop();
+ sipService.ua.unregister();
+ } catch (e) {
+ console.warn("娓呯悊SIP杩炴帴鏃跺嚭閿�:", e);
+ }
+ }
+ },
+
+ // 鎵嬪姩閲嶈繛
+ async manualReconnect() {
+ this.reconnectCount = 0; // 閲嶇疆閲嶈繛璁℃暟
+ await this.reconnectSip();
+ },
+
+ // 鏇存柊鏈�鍚庢椿鍔ㄦ椂闂�
+ updateLastActivityTime() {
+ this.lastActivityTime = Date.now();
+ },
+
async startCall() {
if (!this.phoneNumber) {
this.$message.error("璇疯緭鍏ョ數璇濆彿鐮�");
@@ -119,53 +346,60 @@
// 鍏堟鏌ユ槸鍚﹀彲浠ュ懠鍙�
const { canCall, reason } = sipService.canMakeCall();
if (!canCall) {
- const { canCall, reason } = sipService.canMakeCall();
- //this.$message.warning(reason);
- //return;
+ // 鍙��: 鍙互鏄剧ず鎻愮ず
}
+
this.callStatus = "calling";
this.isCalling = true;
console.log("寮�濮嬪懠鍙細", sipService);
await sipService.makeCall(this.phoneNumber);
} catch (error) {
- let registrationTime = Date.now(); // 璁板綍娉ㄩ攢鎴愬姛鏃堕棿
- console.log(registrationTime, "鍛煎彨澶辫触鏃堕棿");
console.error("鍛煎彨澶辫触1:", error);
- // this.callStatus = "ended";
- // this.isCalling = false;
- //this.$message.error(`鍛煎彨澶辫触: ${error.message}`);
+
try {
- // 鍏堟鏌ユ槸鍚﹀彲浠ュ懠鍙�
+ // 灏濊瘯鍔�0鍐嶆鍛煎彨
const { canCall, reason } = sipService.canMakeCall();
if (!canCall) {
- const { canCall, reason } = sipService.canMakeCall();
+ // 鍙�夊鐞�
}
this.callStatus = "calling";
this.isCalling = true;
- console.log("寮�濮嬪懠鍙細", sipService);
+ console.log("灏濊瘯鍔�0鍐嶆鍛煎彨锛�", sipService);
await sipService.makeCall("0" + this.phoneNumber);
} catch (error) {
this.callStatus = "ended";
this.isCalling = false;
+ this.$message.error("鍛煎彨澶辫触锛岃妫�鏌ョ綉缁滄垨鍙风爜");
}
}
},
+
// 鏌ヨ鍙敤鍒嗘満鍙�
async CallgetList() {
try {
const res = await CallgetList();
this.randomNum = res.data[0].tel;
this.randomID = res.data[0].id;
- // 姝g‘璁剧疆 sipUri
- this.sipConfig.sipUri = `${this.randomNum}@192.168.10.124`;
- this.startCallsetState();
+
+ const orgName = localStorage.getItem("orgname");
+ if (orgName == "涓芥按甯備腑鍖婚櫌") {
+ this.sipConfig.sipUri = `${this.randomNum}@192.168.10.124`;
+ } else if (orgName == "榫欐硥甯備汉姘戝尰闄�") {
+ this.sipConfig.sipUri = `${this.randomNum}@10.10.0.220`;
+ } else if (
+ orgName == "绗竴浜烘皯鍖婚櫌婀栨花闄㈠尯" ||
+ orgName == "绗竴浜烘皯鍖婚櫌鍚村北闄㈠尯"
+ ) {
+ this.sipConfig.sipUri = `${this.randomNum}@192.169.129.198`;
+ }
} catch (error) {
console.error("鑾峰彇鍒嗘満鍙峰け璐�:", error);
- this.updateStatus("failed", "鑾峰彇鍒嗘満鍙峰け璐�");
+ throw error; // 鎶涘嚭閿欒浠ヤ究涓婂眰澶勭悊
}
},
+
async startCallsetState() {
try {
await CallsetState({ id: this.randomID, state: 1 });
@@ -185,12 +419,25 @@
console.error("閲婃斁鍒嗘満鍙峰け璐�:", error);
}
},
+
endCall() {
sipService.endCall();
this.callStatus = "ended";
this.isCalling = false;
},
+
cleanupResources() {
+ // 娓呴櫎鎵�鏈夊畾鏃跺櫒
+ if (this.heartbeatTimer) {
+ clearInterval(this.heartbeatTimer);
+ this.heartbeatTimer = null;
+ }
+
+ if (this.reconnectTimer) {
+ clearTimeout(this.reconnectTimer);
+ this.reconnectTimer = null;
+ }
+
// 缁撴潫閫氳瘽
if (this.isCalling) {
sipService.endCall();
@@ -200,19 +447,17 @@
this.overCallsetState();
// 鏂紑 SIP 杩炴帴
- if (sipService.ua) {
- sipService.ua.stop();
- }
+ this.cleanupSipConnection();
},
},
beforeUnmount() {
- // 缁勪欢閿�姣佹椂纭繚閲婃斁璧勬簮
this.cleanupResources();
},
};
</script>
<style scoped>
+/* 淇濇寔鍘熸湁鏍峰紡涓嶅彉锛屽彧娣诲姞鏂版牱寮� */
.call-container {
display: flex;
flex-direction: column;
@@ -224,25 +469,93 @@
border-radius: 8px;
}
-input {
- padding: 8px;
- border: 1px solid #ccc;
- border-radius: 4px;
+.reconnect-info {
+ font-size: 12px;
+ color: #666;
+ margin-left: 5px;
}
-.call-btn {
+.reconnect-btn {
+ padding: 8px 12px;
+ background-color: #ff9800;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 12px;
+}
+
+.reconnect-btn:hover:not(:disabled) {
+ background-color: #f57c00;
+}
+
+.reconnect-btn:disabled {
+ background-color: #cccccc;
+ cursor: not-allowed;
+}
+
+.call-btn.reconnecting {
+ background-color: #ff9800;
+}
+
+.call-btn:hover:not(:disabled) {
+ background-color: #45a049;
+}
+
+.call-btn:disabled {
+ background-color: #cccccc;
+ cursor: not-allowed;
+}
+
+.call-btn.calling {
+ background-color: #2196f3;
+}
+
+.call-btn.registering,
+.call-btn.reconnecting {
+ position: relative;
+}
+
+.end-call-btn {
padding: 10px;
- background-color: #4caf50;
+ background-color: #f44336;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
+
+.end-call-btn:hover {
+ background-color: #d32f2f;
+}
+
+/* 鐘舵�佹牱寮忎繚鎸佷笉鍙� */
+.sip-status,
.call-status {
padding: 8px;
- margin: 10px 0;
+ 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;
}
.status-idle {
@@ -261,132 +574,6 @@
}
.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;
}
--
Gitblit v1.9.3