From 2eff945fb9fc0d17b2098b26aba74ab192ec3727 Mon Sep 17 00:00:00 2001 From: WXL <1785969728@qq.com> Date: 星期三, 06 八月 2025 17:48:54 +0800 Subject: [PATCH] 测试完成 --- dist (2).zip | 0 dist.zip | 0 src/store/modules/user.js | 12 src/views/login.vue | 2 src/views/followvisit/record/detailpage/index.vue | 172 ++++++++++++-- src/utils/sipService-xs.js | 217 ++++++++++++++++++ src/utils/sipService.js | 42 ++ src/components/CallButton/index.vue | 230 ++++++++++++++----- 8 files changed, 576 insertions(+), 99 deletions(-) diff --git "a/dist \0502\051.zip" "b/dist \0502\051.zip" new file mode 100644 index 0000000..ab7d81b --- /dev/null +++ "b/dist \0502\051.zip" Binary files differ diff --git a/dist.zip b/dist.zip new file mode 100644 index 0000000..bfff269 --- /dev/null +++ b/dist.zip Binary files differ diff --git a/src/components/CallButton/index.vue b/src/components/CallButton/index.vue index 51a4995..84a1519 100644 --- a/src/components/CallButton/index.vue +++ b/src/components/CallButton/index.vue @@ -3,29 +3,32 @@ <div class="sip-status" :class="sipStatusClass"> SIP鐘舵��: {{ sipStatus }} </div> - <!-- 鍙风爜杈撳叆 --> - <input - v-model="phoneNumber" - type="text" - placeholder="杈撳叆鐢佃瘽鍙风爜" - @keyup.enter="startCall" - /> + + <!-- 鐘舵�佹樉绀� --> + <div class="call-status" :class="callStatusClass"> + {{ callStatusText }} + </div> <!-- 鍛煎彨鎸夐挳 --> - <button :class="['call-btn', { calling: isCalling }]" @click="startCall"> - {{ isCalling ? "閫氳瘽涓�..." : "涓�閿懠鍙�" }} + <button + :class="['call-btn', { calling: isCalling }]" + @click="startCall" + :disabled="isCalling || sipStatus !== '宸叉敞鍐�'" + > + {{ callButtonText }} </button> <!-- 鎸傛柇鎸夐挳 --> - <button v-if="isCalling" class="end-call-btn" @click="endCall">鎸傛柇</button> + <button + v-if="isCalling" + class="end-call-btn" + @click="endCall" + > + 鎸傛柇 + </button> <!-- 闊抽鍏冪礌锛堥殣钘忥級 --> <audio id="remoteAudio" autoplay></audio> - - <!-- 鐘舵�佹樉绀� --> - <div class="call-status"> - {{ callStatus }} - </div> </div> </template> @@ -33,82 +36,86 @@ import sipService from "@/utils/sipService"; export default { - data() { - return { - // phoneNumber: "", - isCalling: false, - callStatus: "鍑嗗灏辩华", - sipStatus: "鏈繛鎺�", - sipStatusClass: "status-disconnected", - sipConfig: { - wsUrl: "wss://9.208.5.18:7443", - sipUri: "1000@9.208.5.18", - password: "Smartor@2023", - displayName: "Web 灏忛緳", - // realm: "9.208.5.18:8090", - }, - }; - }, props: { phoneNumber: { type: String, default: '' } }, + data() { + return { + isCalling: false, + callStatus: 'idle', // idle, calling, connected, ended + sipStatus: "鏈繛鎺�", + sipStatusClass: "status-disconnected", + sipConfig: { + wsUrl: "wss://192.168.100.6:7443", + sipUri: "1000@192.168.100.6", + 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() { - // 娴嬭瘯 - const ws = new WebSocket("wss://9.208.5.18:7443"); - ws.onopen = () => console.log("WebSocket 杩炴帴鎴愬姛"); - ws.onerror = (e) => console.error("WebSocket 閿欒:", e); - - - // 鍒濆鍖朣IP杩炴帴 - sipService.init(this.sipConfig); sipService.onStatusChange = (status) => { this.sipStatus = status.text; this.sipStatusClass = `status-${status.type}`; + }; - // 鏍规嵁鐘舵�佹洿鏂癠I鎴栨墽琛屽叾浠栨搷浣� - if (status.type === "registered") { - console.log("SIP娉ㄥ唽鎴愬姛锛屽彲浠ュ紑濮嬪懠鍙�"); - } else if (status.type === "failed") { - console.error("SIP娉ㄥ唽澶辫触"); - } + // 鐩戝惉閫氳瘽鐘舵�佸彉鍖� + sipService.onCallStatusChange = (status) => { + this.callStatus = status.type; + this.isCalling = status.type === 'calling' || status.type === 'connected'; + + // 閫氱煡鐖剁粍浠堕�氳瘽鐘舵�佸彉鍖� + this.$emit('call-status-change', status); }; }, - beforeDestroy() { - // 缁勪欢閿�姣佹椂缁撴潫閫氳瘽 - this.endCall(); - }, methods: { - // 寮�濮嬪懠鍙� async startCall() { if (!this.phoneNumber) { - this.callStatus = "璇疯緭鍏ョ數璇濆彿鐮�"; + this.$message.error("璇疯緭鍏ョ數璇濆彿鐮�"); return; } - try { - this.isCalling = true; - this.callStatus = "鍛煎彨涓�..."; - // 璋冪敤SIP鏈嶅姟 - sipService.makeCall(this.phoneNumber); - this.callStatus = "閫氳瘽宸插缓绔�"; + try { + this.callStatus = 'calling'; + this.isCalling = true; + + await sipService.makeCall(this.phoneNumber); + } catch (error) { console.error("鍛煎彨澶辫触:", error); - this.callStatus = `鍛煎彨澶辫触: ${error.message}`; + this.callStatus = 'ended'; this.isCalling = false; + this.$message.error(`鍛煎彨澶辫触: ${error.message}`); } }, - // 缁撴潫閫氳瘽 endCall() { sipService.endCall(); + this.callStatus = 'ended'; this.isCalling = false; - this.callStatus = "閫氳瘽宸茬粨鏉�"; - }, - }, + } + } }; </script> @@ -138,7 +145,106 @@ 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; } diff --git a/src/store/modules/user.js b/src/store/modules/user.js index a64959d..36c9b90 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -144,11 +144,19 @@ localStorage.setItem('deptCode', '01040201'); }else if (orgid=='47246102433112211A2101') { localStorage.setItem('orgname', '缂欎簯鍘夸腑鍖诲尰闄�'); - localStorage.setItem('ZuHuID', '1400360867068907520'); + localStorage.setItem('ZuHuID', '1429338802177000002'); localStorage.setItem('deptCode', ''); }else if (orgid=='47240018433118111A2101') { localStorage.setItem('orgname', '榫欐硥甯備腑鍖诲尰闄�'); - localStorage.setItem('ZuHuID', '1400360867068907520'); + localStorage.setItem('ZuHuID', '1429338802177000003'); + localStorage.setItem('deptCode', ''); + }else if (orgid=='47243006833112611A2101') { + localStorage.setItem('orgname', '搴嗗厓鍘夸腑鍖诲尰闄�'); + localStorage.setItem('ZuHuID', '1429338802177000004'); + localStorage.setItem('deptCode', ''); + }else if (orgid=='47234002X33112111A2101') { + localStorage.setItem('orgname', '闈掔敯鍘夸腑鍖诲尰闄�'); + localStorage.setItem('ZuHuID', '1429338802177000005'); localStorage.setItem('deptCode', ''); } resolve() diff --git a/src/utils/sipService-xs.js b/src/utils/sipService-xs.js new file mode 100644 index 0000000..924ac14 --- /dev/null +++ b/src/utils/sipService-xs.js @@ -0,0 +1,217 @@ +import JsSIP from "jssip"; + +class SipService { + constructor() { + this.ua = null; + this.currentSession = null; + this.onStatusChange = null; + this.onCallStatusChange = null; + this.onIncomingCall = null; + } + + init(config) { + try { + this.updateStatus("connecting", "杩炴帴涓�..."); + + this.ua = new JsSIP.UA({ + sockets: [new JsSIP.WebSocketInterface(config.wsUrl)], + uri: config.sipUri, + password: config.password, + display_name: config.displayName, + iceServers: [{ urls: "stun:stun.l.google.com:19302" }], + register: true, + session_expires: 180, + sessionTimersExpires: 300, + extraHeaders: ["Min-SE: 120"], + register_expires: 300, + connection_recovery_min_interval: 2, + connection_recovery_max_interval: 30, + pcConfig: { + iceTransportPolicy: "all", + rtcpMuxPolicy: "require", + bundlePolicy: "max-bundle" + } + }); + + this.ua.start(); + + // 浜嬩欢鐩戝惉 + this.ua.on("registered", () => this.updateStatus("registered", "宸叉敞鍐�")); + this.ua.on("registrationFailed", (e) => + this.updateStatus("failed", `娉ㄥ唽澶辫触: ${e.cause}`)); + this.ua.on("disconnected", () => + this.updateStatus("disconnected", "杩炴帴鏂紑")); + this.ua.on("connected", () => + this.updateStatus("connecting", "閲嶆柊杩炴帴涓�...")); + this.ua.on("newRTCSession", (data) => + this.handleIncomingCall(data.session)); + + } catch (error) { + this.updateStatus("failed", `鍒濆鍖栧け璐�: ${error.message}`); + console.error("SIP鍒濆鍖栧け璐�:", error); + throw error; + } + } + + makeCall(targetNumber) { + return new Promise((resolve, reject) => { + try { + if (!this.ua) { + throw new Error("SIP瀹㈡埛绔湭鍒濆鍖�"); + } + + if (!this.ua.isRegistered()) { + throw new Error("SIP鏈敞鍐岋紝鏃犳硶鍛煎彨"); + } + + const options = { + sessionTimers: false, // 鏆傛椂绂佺敤浠ュ噺灏戝吋瀹规�ч棶棰� + extraHeaders: [ + "Min-SE: 120", + "Accept: application/sdp", + "Supported: outbound" + ], + mediaConstraints: { audio: true, video: false }, + rtcOfferConstraints: { + offerToReceiveAudio: true, + offerToReceiveVideo: false + }, + eventHandlers: { + progress: () => this.updateCallStatus("calling", "鍛煎彨涓�..."), + failed: (e) => { + this.handleCallFailure(e, reject); + }, + ended: () => this.updateCallStatus("ended", "閫氳瘽缁撴潫"), + confirmed: () => { + this.updateCallStatus("connected", "閫氳瘽宸叉帴閫�"); + resolve(); + } + } + }; + + this.currentSession = this.ua.call( + `sip:${targetNumber}@9.208.5.18`, + options + ); + + this.setupPeerConnection(this.currentSession); + this.setupAudio(this.currentSession); + + } catch (error) { + this.updateCallStatus("failed", `鍛煎彨澶辫触: ${error.message}`); + reject(error); + } + }); + } + + setupPeerConnection(session) { + session.on("peerconnection", (pc) => { + const originalCreateOffer = pc.createOffer.bind(pc); + + pc.createOffer = async (offerOptions) => { + try { + const offer = await originalCreateOffer(offerOptions); + return this.normalizeSDP(offer); + } catch (error) { + console.error("鍒涘缓Offer澶辫触:", error); + throw error; + } + }; + }); + } + + normalizeSDP(offer) { + let sdp = offer.sdp; + + // 1. 鏍囧噯鍖栬繛鎺ヨ + sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n"); + + // 2. 鏍囧噯鍖栭煶棰戝獟浣撹 + sdp = sdp.replace(/m=audio \d+.*\r\n/, + "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n"); + + // 3. 纭繚鍖呭惈鍩烘湰缂栬В鐮佸櫒 + if (!sdp.includes("PCMU/8000")) { + sdp += "a=rtpmap:0 PCMU/8000\r\n"; + } + if (!sdp.includes("PCMA/8000")) { + sdp += "a=rtpmap:8 PCMA/8000\r\n"; + } + + // 4. 娣诲姞蹇呰灞炴�� + sdp += "a=rtcp-mux\r\n"; + sdp += "a=sendrecv\r\n"; + + console.log("鏍囧噯鍖栧悗鐨凷DP:", sdp); + return new RTCSessionDescription({ + type: offer.type, + sdp: sdp + }); + } + + handleCallFailure(e, reject) { + console.error("鍛煎彨澶辫触璇︽儏:", { + cause: e.cause, + message: e.message, + response: e.response && e.response.status_code + }); + + let errorMessage = "鍛煎彨澶辫触"; + switch(e.cause) { + case "Incompatible SDP": + errorMessage = "濯掍綋鍗忓晢澶辫触锛岃妫�鏌ョ紪瑙g爜鍣ㄩ厤缃�"; + break; + case "488": + case "606": + errorMessage = "瀵规柟璁惧涓嶆敮鎸佸綋鍓嶅獟浣撻厤缃�"; + break; + default: + errorMessage = `鍛煎彨澶辫触: ${e.cause || e.message}`; + } + + this.updateCallStatus("failed", errorMessage); + reject(new Error(errorMessage)); + } + + setupAudio(session) { + session.connection.addEventListener("addstream", (e) => { + const audioElement = document.getElementById("remoteAudio"); + if (audioElement) { + audioElement.srcObject = e.stream; + } + }); + } + + endCall() { + if (this.currentSession) { + this.currentSession.terminate(); + this.updateCallStatus("ended", "閫氳瘽宸茬粨鏉�"); + this.currentSession = null; + } + } + + updateStatus(type, text) { + console.log(`SIP鐘舵�佹洿鏂�: ${type} - ${text}`); + if (this.onStatusChange) { + this.onStatusChange({ type, text }); + } + } + + updateCallStatus(type, text) { + console.log(`閫氳瘽鐘舵�佹洿鏂�: ${type} - ${text}`); + if (this.onCallStatusChange) { + this.onCallStatusChange({ type, text }); + } + } + + handleIncomingCall(session) { + if (session.direction === "incoming") { + console.log("鏉ョ數:", session.remote_identity.uri.toString()); + if (this.onIncomingCall) { + this.onIncomingCall(session); + } + } + } +} + +export default new SipService(); diff --git a/src/utils/sipService.js b/src/utils/sipService.js index 4b12914..8318c1a 100644 --- a/src/utils/sipService.js +++ b/src/utils/sipService.js @@ -5,6 +5,7 @@ this.ua = null; this.currentSession = null; this.onStatusChange = null; // 鐘舵�佸彉鍖栧洖璋� + this.onCallStatusChange = null; // 鏂板閫氳瘽鐘舵�佸洖璋� } // 鍒濆鍖朣IP瀹㈡埛绔� @@ -17,7 +18,7 @@ uri: config.sipUri, password: config.password, display_name: config.displayName, - iceservers:[], + iceservers: [], // realm: config.realm, register: true, session_expires: 180, @@ -97,10 +98,18 @@ "Allow: INVITE, ACK, BYE, CANCEL, OPTIONS", ], eventHandlers: { - progress: (e) => console.log("鍛煎彨涓�..."), - failed: (e) => console.error("鍛煎彨澶辫触:", e), - ended: (e) => console.log("閫氳瘽缁撴潫"), - confirmed: (e) => console.log("閫氳瘽宸叉帴閫�"), + progress: (e) => { + this.updateCallStatus("calling", "鍛煎彨涓�..."); + }, + failed: (e) => { + this.updateCallStatus("ended", `鍛煎彨澶辫触: ${e.cause}`); + }, + ended: (e) => { + this.updateCallStatus("ended", "閫氳瘽缁撴潫"); + }, + confirmed: (e) => { + this.updateCallStatus("connected", "閫氳瘽宸叉帴閫�"); + }, }, mediaConstraints: { audio: true, @@ -135,6 +144,7 @@ ); // 鍦ㄤ細璇濆垱寤哄悗淇敼 SDP this.currentSession.on("peerconnection", (pc) => { + this.updateCallStatus('calling', '鍛煎彨涓�...'); pc.createOffer = (offerOptions) => { return RTCPeerConnection.prototype.createOffer .call(pc, offerOptions) @@ -149,6 +159,17 @@ }); }; }); + this.currentSession.on('failed', (e) => { + this.updateCallStatus('failed', `鍛煎彨澶辫触2: ${e.cause}`); + }); + + this.currentSession.on('ended', () => { + this.updateCallStatus('ended', '閫氳瘽宸茬粨鏉�'); + }); + + this.currentSession.on('confirmed', () => { + this.updateCallStatus('connected', '閫氳瘽宸叉帴閫�'); + }); this.setupAudio(this.currentSession); } setupAudio(session) { @@ -161,12 +182,19 @@ } // 鎸傛柇褰撳墠閫氳瘽 endCall() { - if (this.currentSession) { + if (this.currentSession) { this.currentSession.terminate(); + this.updateCallStatus('ended', '閫氳瘽宸茬粨鏉�'); this.currentSession = null; } } - + // 鏂板鏂规硶锛氭洿鏂伴�氳瘽鐘舵�� + updateCallStatus(type, text) { + console.log(`閫氳瘽鐘舵�佹洿鏂�: ${type} - ${text}`); + if (this.onCallStatusChange) { + this.onCallStatusChange({ type, text }); + } + } } export default new SipService(); diff --git a/src/views/followvisit/record/detailpage/index.vue b/src/views/followvisit/record/detailpage/index.vue index fb42e14..ab859d4 100644 --- a/src/views/followvisit/record/detailpage/index.vue +++ b/src/views/followvisit/record/detailpage/index.vue @@ -260,13 +260,37 @@ ></el-input> </el-form-item ></el-col> </el-row> + <div style="margin-left: 30px"> <el-button type="primary" plain @click="Editsingletasksonyic('')" >淇濆瓨鏈嶅姟</el-button > </div> </div> + <el-row :gutter="20" v-if="callStatus !== 'idle'"> + <el-col :span="24"> + <el-alert + :title="callStatusText" + :type="callStatusType" + :closable="false" + show-icon + /> + </el-col> + </el-row> + <!-- 鎸傛柇鎸夐挳锛堜粎鍦ㄩ�氳瘽涓樉绀猴級 --> + <el-row :gutter="20" v-if="callStatus === 'connected'"> + <el-col :span="24" style="text-align: center; margin-top: 10px"> + <el-button + type="danger" + icon="el-icon-phone" + @click="endCurrentCall" + :loading="isEndingCall" + > + 鎸傛柇鐢佃瘽 + </el-button> + </el-col> + </el-row> <el-form-item label="闅忚璁板綍"> <el-input type="textarea" v-model="form.remark"></el-input> </el-form-item> @@ -796,6 +820,10 @@ userid: "", currentPhoneNumber: "", callType: "", // 鐢ㄤ簬鍖哄垎鏄摢涓數璇� + // 宸叉湁鏁版嵁... + callStatus: "idle", // idle, calling, connected, ended, failed + isEndingCall: false, + currentCall: null, // 褰撳墠閫氳瘽瀵硅薄 input: "浠婂ぉ韬綋杩樹笉閿�", radio: "2", taskname: "", @@ -854,9 +882,9 @@ }, pickerOptions: { disabledDate(time) { - // 绂佺敤浠婂ぉ鍙婁箣鍓嶇殑鏃ユ湡 - return time.getTime() < Date.now() - 24 * 60 * 60 * 1000; - }, + // 绂佺敤浠婂ぉ鍙婁箣鍓嶇殑鏃ユ湡 + return time.getTime() < Date.now() - 24 * 60 * 60 * 1000; + }, shortcuts: [ { text: "涓冨ぉ鍚�", @@ -948,7 +976,28 @@ patid: null, }; }, - + computed: { + callStatusText() { + const statusMap = { + idle: "鍑嗗鍛煎彨", + calling: `姝e湪鍛煎彨 ${this.currentPhoneNumber}...`, + connected: `宸叉帴閫� ${this.currentPhoneNumber}`, + ended: "閫氳瘽宸茬粨鏉�", + failed: "鍛煎彨澶辫触", + }; + return statusMap[this.callStatus]; + }, + callStatusType() { + const typeMap = { + idle: "info", + calling: "warning", + connected: "success", + ended: "info", + failed: "error", + }; + return typeMap[this.callStatus]; + }, + }, created() { this.taskid = this.$route.query.taskid; this.id = this.$route.query.id; @@ -1217,28 +1266,95 @@ console.error("鍙戠敓閿欒锛�", error); }); }, - // 楠岃瘉鎵嬫満鍙锋牸寮� - isValidPhone(phone) { - return /^1[3-9]\d{9}$/.test(phone); - }, - // 鍛煎彨澶勭悊 + // 楠岃瘉鐢佃瘽鍙风爜鏍煎紡骞惰繑鍥為敊璇俊鎭� +validatePhoneNumber(phone) { + if (!phone) { + return { isValid: false, message: '璇疯緭鍏ョ數璇濆彿鐮�' }; + } + + // 鎵嬫満鍙锋鍒� + const mobileRegex = /^1[3-9]\d{9}$/; + + // 甯﹀尯鍙风殑鍥哄畾鐢佃瘽锛堝畬鏁存牸寮忥級 + const landlineFullRegex = /^0\d{2,3}-?\d{7,8}$/; + + // 涓嶅甫鍖哄彿鐨勫浐瀹氱數璇濓紙浠呮湰鍦板彿鐮侊級 + const landlineLocalRegex = /^\d{7,8}$/; + + if (mobileRegex.test(phone)) { + return { isValid: true, type: 'mobile' }; + } else if (landlineFullRegex.test(phone)) { + return { isValid: true, type: 'landline' }; + } else if (landlineLocalRegex.test(phone)) { + return { + isValid: false, + message: '鏈湴鍙风爜璇锋坊鍔犲尯鍙凤紙濡�028-1234567锛�' + }; + } else { + return { + isValid: false, + message: '璇疯緭鍏ユ纭殑鐢佃瘽鍙风爜锛堟墜鏈哄彿鎴栧甫鍖哄彿鐨勫浐瀹氱數璇濓級' + }; + } +}, + +// 浣跨敤绀轰緥 +isValidPhone(phone) { + return this.validatePhoneNumber(phone).isValid; +}, handleCall(phone, type) { - if (this.isValidPhone(phone)) { - this.currentPhoneNumber = phone; - this.callType = type; - - // 绛夊緟涓嬩竴涓猼ick纭繚鍊煎凡鏇存柊 - this.$nextTick(() => { - this.$refs.callButton.startCall(); - - // 鍙�夛細鏍规嵁涓嶅悓绫诲瀷鍋氫笉鍚屽鐞� - if (type === "tel") { - console.log("姝e湪鍛煎彨鎮h�呮湰浜�:", phone); - } else { - console.log("姝e湪鍛煎彨鑱旂郴浜�:", phone); - } - }); + if (!this.isValidPhone(phone)) { + this.$message.error("璇疯緭鍏ユ纭殑鎵嬫満鍙风爜"); + return; } + + this.currentPhoneNumber = phone; + this.callType = type; + this.callStatus = "calling"; + + this.$nextTick(() => { + this.$refs.callButton.startCall(); + + // 鐩戝惉閫氳瘽鐘舵�佸彉鍖� + this.$refs.callButton.$on("call-status-change", (status) => { + this.handleCallStatusChange(status); + }); + }); + }, + + // 澶勭悊閫氳瘽鐘舵�佸彉鍖� + handleCallStatusChange(status) { + console.log(status,'status'); + + this.callStatus = status.type; + + if (status.type === "connected") { + this.currentCall = { + phone: this.currentPhoneNumber, + type: this.callType, + startTime: new Date(), + }; + } else if (status.type === "ended" || status.type === "failed") { + this.currentCall = null; + } + + // 鍙互鏍规嵁鐘舵�佹墽琛屽叾浠栨搷浣� + if (status.type === "failed") { + this.$message.error(`鍛煎彨澶辫触: ${status.text}`); + } + }, + + // 缁撴潫褰撳墠閫氳瘽 + endCurrentCall() { + if (!this.currentCall) return; + + this.isEndingCall = true; + this.$refs.callButton.endCall(); + + // 3绉掑悗閲嶇疆鐘舵�� + setTimeout(() => { + this.isEndingCall = false; + }, 3000); }, yuyingetdetail() { this.tableDatatop.forEach((item, index) => { @@ -1285,7 +1401,7 @@ }) .catch(() => { if (this.form.serviceType == 13) { - if (this.visitCount!=1) { + if (this.visitCount != 1) { this.$router.push({ path: "/logisticsservice/zbAgain", }); @@ -1295,7 +1411,7 @@ }); } } else if (form.serviceType == 2) { - if (this.visitCount!=1) { + if (this.visitCount != 1) { this.$router.push({ path: "/followvisit/again", }); @@ -1331,7 +1447,7 @@ this.form = res.rows[0].serviceSubtaskList.find( (item) => item.id == this.id ); - console.log(this.form.serviceType,'serviceType'); + console.log(this.form.serviceType, "serviceType"); this.logsheetlist = res.rows[0].serviceSubtaskList; this.templateid = this.logsheetlist[0].templateid; @@ -1500,7 +1616,7 @@ } // form.id = null; form.sendstate = 2; - console.log(form.serviceType,'form.serviceType'); + console.log(form.serviceType, "form.serviceType"); addserviceSubtask(form).then((res) => { if (res.code == 200) { diff --git a/src/views/login.vue b/src/views/login.vue index fe19af7..68eb677 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -119,6 +119,8 @@ { value: "47231022633110211A2101", label: "涓芥按甯備腑鍖婚櫌" }, { value: "47246102433112211A2101", label: "缂欎簯鍘夸腑鍖诲尰闄� " }, { value: "47240018433118111A2101", label: "榫欐硥甯備腑鍖诲尰闄� " }, + { value: "47243006833112611A2101", label: "搴嗗厓鍘夸腑鍖诲尰闄� " }, + { value: "47234002X33112111A2101", label: "闈掔敯鍘夸腑鍖诲尰闄� " }, ], loginRules: { username: [ -- Gitblit v1.9.3