From 880e036a0d85cd542034794c1dac2a4e433c5553 Mon Sep 17 00:00:00 2001 From: WXL <1785969728@qq.com> Date: 星期四, 03 七月 2025 10:51:04 +0800 Subject: [PATCH] 测试完成 --- src/views/followvisit/record/detailpage/index.vue | 8 + src/utils/sipService.js | 87 +++++++++++++++++ package.json | 1 src/components/CallButton/index.vue | 148 +++++++++++++++++++++++++++++ 4 files changed, 244 insertions(+), 0 deletions(-) diff --git a/package.json b/package.json index 2994555..291269c 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "js-beautify": "1.13.0", "js-cookie": "3.0.1", "jsencrypt": "^3.3.2", + "jssip": "^3.10.1", "lemon-imui": "^1.7.7", "moment": "^2.30.1", "nprogress": "0.2.0", diff --git a/src/components/CallButton/index.vue b/src/components/CallButton/index.vue new file mode 100644 index 0000000..57690ea --- /dev/null +++ b/src/components/CallButton/index.vue @@ -0,0 +1,148 @@ +<template> + <div class="call-container"> + <!-- 鍙风爜杈撳叆 --> + <input + v-model="phoneNumber" + type="text" + placeholder="杈撳叆鐢佃瘽鍙风爜" + @keyup.enter="startCall" + > + + <!-- 鍛煎彨鎸夐挳 --> + <button + :class="['call-btn', { 'calling': isCalling }]" + @click="startCall" + > + {{ isCalling ? '閫氳瘽涓�...' : '涓�閿懠鍙�' }} + </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> + +<script> +import sipService from '@/utils/sipService' + +export default { + data() { + return { + phoneNumber: '', + isCalling: false, + callStatus: '鍑嗗灏辩华', + sipConfig: { + wsUrl: 'wss://192.168.100.6:7443', + sipUri: '1000@192.168.100.6', + password: 'Smartor@2023', + displayName: 'Web 灏忛緳', + realm: '192.168.100.6:8090' + } + } + }, + mounted() { + // 鍒濆鍖朣IP杩炴帴 + sipService.init(this.sipConfig) + }, + beforeDestroy() { + // 缁勪欢閿�姣佹椂缁撴潫閫氳瘽 + this.endCall() + }, + methods: { + // 寮�濮嬪懠鍙� + async startCall() { + if (!this.phoneNumber) { + this.callStatus = '璇疯緭鍏ョ數璇濆彿鐮�' + return + } + try { + this.isCalling = true + this.callStatus = '鍛煎彨涓�...' + // 璋冪敤SIP鏈嶅姟 + sipService.makeCall(this.phoneNumber) + + this.callStatus = '閫氳瘽宸插缓绔�' + } catch (error) { + console.error('鍛煎彨澶辫触:', error) + this.callStatus = `鍛煎彨澶辫触: ${error.message}` + this.isCalling = false + } + }, + + // 缁撴潫閫氳瘽 + endCall() { + sipService.endCall() + this.isCalling = false + this.callStatus = '閫氳瘽宸茬粨鏉�' + } + } +} +</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-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; +} +</style> diff --git a/src/utils/sipService.js b/src/utils/sipService.js new file mode 100644 index 0000000..95ac836 --- /dev/null +++ b/src/utils/sipService.js @@ -0,0 +1,87 @@ +import JsSIP from 'jssip' + +class SipService { + constructor() { + this.ua = null + this.currentSession = null + } + + // 鍒濆鍖朣IP瀹㈡埛绔� + init(config) { + this.ua = new JsSIP.UA({ + sockets: [new JsSIP.WebSocketInterface(config.wsUrl)], + uri: config.sipUri, + password: config.password, + display_name: config.displayName, + realm: config.realm, + ha1: config.ha1, + register: true + }) + + this.ua.start() + + // 娉ㄥ唽浜嬩欢鐩戝惉 + this.ua.on('registered', () => { + console.log('SIP娉ㄥ唽鎴愬姛') + }) + + this.ua.on('registrationFailed', (e) => { + console.error('SIP娉ㄥ唽澶辫触:', e) + }) + + // 鐩戝惉鏉ョ數 + this.ua.on('newRTCSession', (data) => { + this.handleIncomingCall(data.session) + }) + } + + // 涓�閿嫧鍙� + makeCall(targetNumber) { + if (!this.ua) { + console.error('SIP瀹㈡埛绔湭鍒濆鍖�') + return + } + + const options = { + eventHandlers: { + progress: (e) => console.log('鍛煎彨涓�...'), + failed: (e) => console.error('鍛煎彨澶辫触:', e), + ended: (e) => console.log('閫氳瘽缁撴潫'), + confirmed: (e) => console.log('閫氳瘽宸叉帴閫�') + }, + mediaConstraints: { audio: true, video: false }, + rtcOfferConstraints: { offerToReceiveAudio: 1 } + } + + this.currentSession = this.ua.call(`sip:${targetNumber}`, options) + this.setupAudio(this.currentSession) + } + + // 鎸傛柇褰撳墠閫氳瘽 + endCall() { + if (this.currentSession) { + this.currentSession.terminate() + this.currentSession = null + } + } + + // 澶勭悊闊抽娴� + setupAudio(session) { + session.connection.addEventListener('addstream', (e) => { + const audioElement = document.getElementById('remoteAudio') + if (audioElement) { + audioElement.srcObject = e.stream + } + }) + } + + // 澶勭悊鏉ョ數 + handleIncomingCall(session) { + if (session.direction === 'incoming') { + console.log('鏉ョ數:', session.remote_identity.uri.toString()) + // 杩欓噷鍙互瑙﹀彂UI閫氱煡 + } + } +} + +export default new SipService() diff --git a/src/views/followvisit/record/detailpage/index.vue b/src/views/followvisit/record/detailpage/index.vue index 0abf723..0cffc18 100644 --- a/src/views/followvisit/record/detailpage/index.vue +++ b/src/views/followvisit/record/detailpage/index.vue @@ -354,6 +354,10 @@ </div> </div> <div> + <h2>涓�閿懠鍙姛鑳�</h2> + <CallButton/> + </div> + <div> <el-tabs v-model="activeName" type="border-card"> <el-tab-pane name="wj"> <span class="mulsz" slot="label" @@ -744,7 +748,11 @@ alterpatient, listcontactinformation, } from "@/api/patient/homepage"; +import CallButton from "@/components/CallButton"; export default { + components: { + CallButton, + }, dicts: ["sys_normal_disable", "sys_user_sex", "sys_yujing", "sys_suggest"], data() { return { -- Gitblit v1.9.3