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