dezhu-icall-vue 2.0.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/DeZhuICall.vue +76 -143
package/package.json
CHANGED
package/src/DeZhuICall.vue
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
<div ref="callContainer" :style="containerStyle" class="dezhu-icall-container" />
|
|
2
|
+
<div ref="callContainer" class="dezhu-icall-container" style="display: none;" />
|
|
4
3
|
</template>
|
|
5
4
|
|
|
6
5
|
<style>
|
|
@@ -11,64 +10,17 @@
|
|
|
11
10
|
</style>
|
|
12
11
|
|
|
13
12
|
<script>
|
|
14
|
-
/**
|
|
15
|
-
* 得助外呼组件
|
|
16
|
-
* @description 封装得助智能 iCall 外呼功能 - 开箱即用版本
|
|
17
|
-
* @example
|
|
18
|
-
* <DeZhuICall
|
|
19
|
-
* server-url="https://hnzz.dezhuyun.com"
|
|
20
|
-
* :token="deZhuToken"
|
|
21
|
-
* :auto-init="true"
|
|
22
|
-
* @ready="onReady"
|
|
23
|
-
* @error="onError"
|
|
24
|
-
* />
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
13
|
export default {
|
|
28
14
|
name: 'DeZhuICall',
|
|
29
15
|
|
|
30
16
|
props: {
|
|
31
|
-
/** 得助服务器地址,如:https://hnzz.dezhuyun.com */
|
|
32
17
|
serverUrl: {
|
|
33
18
|
type: String,
|
|
34
19
|
required: true
|
|
35
20
|
},
|
|
36
|
-
/** 代理前缀,用于本地开发跨域,如:'/dzfront' */
|
|
37
|
-
proxyPrefix: {
|
|
38
|
-
type: String,
|
|
39
|
-
default: ''
|
|
40
|
-
},
|
|
41
|
-
/** 认证 Token,通过 SSO 接入获取 */
|
|
42
21
|
token: {
|
|
43
22
|
type: String,
|
|
44
23
|
required: true
|
|
45
|
-
},
|
|
46
|
-
/** 是否自动初始化 */
|
|
47
|
-
autoInit: {
|
|
48
|
-
type: Boolean,
|
|
49
|
-
default: true
|
|
50
|
-
},
|
|
51
|
-
/** 是否显示拨号盘界面 */
|
|
52
|
-
visible: {
|
|
53
|
-
type: Boolean,
|
|
54
|
-
default: false
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
computed: {
|
|
59
|
-
containerStyle() {
|
|
60
|
-
return {
|
|
61
|
-
display: this.visible ? 'block' : 'none'
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
watch: {
|
|
67
|
-
serverUrl() {
|
|
68
|
-
if (this.autoInit) this.checkAndInit()
|
|
69
|
-
},
|
|
70
|
-
token() {
|
|
71
|
-
if (this.autoInit) this.checkAndInit()
|
|
72
24
|
}
|
|
73
25
|
},
|
|
74
26
|
|
|
@@ -76,55 +28,50 @@ export default {
|
|
|
76
28
|
return {
|
|
77
29
|
iCall: null,
|
|
78
30
|
isInitialized: false,
|
|
79
|
-
|
|
80
|
-
isCalling: false,
|
|
81
|
-
reconnectTimer: null,
|
|
31
|
+
scriptLoaded: false,
|
|
82
32
|
reconnectCount: 0,
|
|
83
|
-
maxReconnectCount: 5
|
|
33
|
+
maxReconnectCount: 5,
|
|
34
|
+
reconnectTimer: null
|
|
84
35
|
}
|
|
85
36
|
},
|
|
86
37
|
|
|
87
38
|
mounted() {
|
|
88
|
-
if (this.
|
|
89
|
-
|
|
39
|
+
if (this.token) {
|
|
40
|
+
this.loadSDKAndToken()
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
watch: {
|
|
45
|
+
token(newVal) {
|
|
46
|
+
if (newVal && !this.isInitialized) {
|
|
47
|
+
this.loadSDKAndToken()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
90
50
|
},
|
|
91
51
|
|
|
92
52
|
beforeDestroy() {
|
|
93
|
-
document.removeEventListener('visibilitychange', this.handleVisibilityChange)
|
|
94
|
-
this.clearReconnectTimer()
|
|
95
53
|
this.destroy()
|
|
96
54
|
},
|
|
97
55
|
|
|
98
56
|
methods: {
|
|
99
|
-
async
|
|
100
|
-
if (this.isInitializing || this.isInitialized) return
|
|
101
|
-
if (!this.serverUrl || !this.token) return
|
|
102
|
-
|
|
103
|
-
this.isInitializing = true
|
|
57
|
+
async loadSDKAndToken() {
|
|
104
58
|
try {
|
|
105
59
|
await this.loadSDK()
|
|
106
60
|
await this.initICall()
|
|
107
61
|
} catch (error) {
|
|
108
62
|
this.$emit('error', error)
|
|
109
|
-
this.scheduleReconnect()
|
|
110
|
-
} finally {
|
|
111
|
-
this.isInitializing = false
|
|
112
63
|
}
|
|
113
64
|
},
|
|
114
65
|
|
|
115
66
|
loadSDK() {
|
|
116
67
|
if (window.DeZhuFrontIcall) {
|
|
68
|
+
this.scriptLoaded = true
|
|
117
69
|
return Promise.resolve()
|
|
118
70
|
}
|
|
119
71
|
|
|
120
72
|
return new Promise((resolve, reject) => {
|
|
121
73
|
const script = document.createElement('script')
|
|
122
|
-
|
|
123
|
-
// 否则使用完整 serverUrl
|
|
124
|
-
const baseUrl = this.proxyPrefix || this.serverUrl
|
|
125
|
-
// 注意:proxyPrefix 已经包含 /dzfront,所以不需要再拼接
|
|
126
|
-
const path = this.proxyPrefix ? '/icall/lib/icall.js' : '/dzfront/icall/lib/icall.js'
|
|
127
|
-
script.src = `${baseUrl}${path}?time=${Date.now()}`
|
|
74
|
+
script.src = `${this.serverUrl}/dzfront/icall/lib/icall.js?time=${Date.now()}`
|
|
128
75
|
script.async = true
|
|
129
76
|
|
|
130
77
|
const timeout = setTimeout(() => {
|
|
@@ -133,6 +80,7 @@ export default {
|
|
|
133
80
|
|
|
134
81
|
script.onload = () => {
|
|
135
82
|
clearTimeout(timeout)
|
|
83
|
+
this.scriptLoaded = true
|
|
136
84
|
resolve()
|
|
137
85
|
}
|
|
138
86
|
|
|
@@ -153,35 +101,25 @@ export default {
|
|
|
153
101
|
return
|
|
154
102
|
}
|
|
155
103
|
|
|
156
|
-
if (this.iCall
|
|
157
|
-
this.iCall.signOut
|
|
104
|
+
if (this.iCall) {
|
|
105
|
+
if (typeof this.iCall.signOut === 'function') {
|
|
106
|
+
this.iCall.signOut()
|
|
107
|
+
}
|
|
158
108
|
this.iCall = null
|
|
159
109
|
}
|
|
160
110
|
|
|
161
|
-
// 如果有代理前缀,server 配置为空(SDK 会基于当前域名请求)
|
|
162
|
-
const serverConfig = this.proxyPrefix ? '' : this.serverUrl
|
|
163
111
|
this.iCall = new window.DeZhuFrontIcall(container, {
|
|
164
112
|
option: {
|
|
165
|
-
server:
|
|
113
|
+
server: this.serverUrl,
|
|
166
114
|
token: this.token
|
|
167
115
|
},
|
|
168
116
|
event: {
|
|
169
|
-
onCallStatusChange: (
|
|
170
|
-
this.$emit('statusChange',
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
case 'MANUAL_EARLY_MEDIA':
|
|
176
|
-
this.$emit('ringing', params)
|
|
177
|
-
break
|
|
178
|
-
case 'MANUAL_ACTIVE':
|
|
179
|
-
this.$emit('connected', params)
|
|
180
|
-
break
|
|
181
|
-
case 'MANUAL_NOT_ACTIVE':
|
|
182
|
-
this.handleHangup(params)
|
|
183
|
-
break
|
|
184
|
-
}
|
|
117
|
+
onCallStatusChange: (callStatus, params) => {
|
|
118
|
+
this.$emit('statusChange', callStatus, params)
|
|
119
|
+
if (callStatus === 'MANUAL_DIALING') this.$emit('dialing', params)
|
|
120
|
+
if (callStatus === 'MANUAL_EARLY_MEDIA') this.$emit('ringing', params)
|
|
121
|
+
if (callStatus === 'MANUAL_ACTIVE') this.$emit('connected', params)
|
|
122
|
+
if (callStatus === 'MANUAL_NOT_ACTIVE') this.$emit('hangup', params)
|
|
185
123
|
},
|
|
186
124
|
onFinishedAcw: (acwDuration) => {
|
|
187
125
|
this.$emit('finishedAcw', acwDuration)
|
|
@@ -190,18 +128,17 @@ export default {
|
|
|
190
128
|
this.$emit('error', error)
|
|
191
129
|
},
|
|
192
130
|
onDisconnect: () => {
|
|
193
|
-
this.isInitialized = false
|
|
194
131
|
this.$emit('offline')
|
|
195
|
-
this.
|
|
132
|
+
this.isInitialized = false
|
|
133
|
+
this.handleReconnect()
|
|
196
134
|
},
|
|
197
135
|
onReconnect: () => {
|
|
198
|
-
this.reconnectCount = 0
|
|
199
|
-
this.clearReconnectTimer()
|
|
200
136
|
this.$emit('reconnect')
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
137
|
+
this.reconnectCount = 0
|
|
138
|
+
if (this.reconnectTimer) {
|
|
139
|
+
clearTimeout(this.reconnectTimer)
|
|
140
|
+
this.reconnectTimer = null
|
|
141
|
+
}
|
|
205
142
|
}
|
|
206
143
|
}
|
|
207
144
|
}, async () => {
|
|
@@ -219,74 +156,70 @@ export default {
|
|
|
219
156
|
})
|
|
220
157
|
},
|
|
221
158
|
|
|
222
|
-
|
|
223
|
-
this.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
159
|
+
async handleReconnect() {
|
|
160
|
+
if (this.reconnectTimer) {
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (this.reconnectCount >= this.maxReconnectCount) {
|
|
165
|
+
this.$emit('error', new Error(`重连失败,已达最大重连次数: ${this.maxReconnectCount}`))
|
|
166
|
+
return
|
|
227
167
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
168
|
+
|
|
169
|
+
this.reconnectCount++
|
|
170
|
+
const delay = Math.min(1000 * Math.pow(2, this.reconnectCount), 30000)
|
|
171
|
+
|
|
172
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
173
|
+
this.reconnectTimer = null
|
|
174
|
+
try {
|
|
175
|
+
this.$emit('reconnecting', this.reconnectCount, this.maxReconnectCount)
|
|
176
|
+
await this.initICall()
|
|
177
|
+
} catch (error) {
|
|
178
|
+
this.$emit('error', error)
|
|
179
|
+
this.handleReconnect()
|
|
180
|
+
}
|
|
181
|
+
}, delay)
|
|
235
182
|
},
|
|
236
183
|
|
|
237
184
|
async call(phoneNumber) {
|
|
238
185
|
if (!this.iCall || !this.isInitialized) {
|
|
239
186
|
throw new Error('拨号盘未初始化')
|
|
240
187
|
}
|
|
241
|
-
this.isCalling = true
|
|
242
188
|
await this.iCall.call(phoneNumber)
|
|
243
189
|
},
|
|
244
190
|
|
|
245
191
|
async hangup() {
|
|
246
|
-
if (this.iCall
|
|
192
|
+
if (this.iCall) {
|
|
247
193
|
await this.iCall.hangup()
|
|
248
194
|
}
|
|
249
195
|
},
|
|
250
196
|
|
|
251
|
-
|
|
252
|
-
if (this.iCall) {
|
|
253
|
-
|
|
254
|
-
this.iCall.signOut()
|
|
255
|
-
}
|
|
256
|
-
this.iCall = null
|
|
197
|
+
async signIn() {
|
|
198
|
+
if (this.iCall && this.isInitialized) {
|
|
199
|
+
await this.iCall.signIn()
|
|
257
200
|
}
|
|
258
|
-
this.isInitialized = false
|
|
259
|
-
this.isCalling = false
|
|
260
201
|
},
|
|
261
202
|
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
this.
|
|
203
|
+
async signOut() {
|
|
204
|
+
if (this.iCall && this.isInitialized) {
|
|
205
|
+
await this.iCall.signOut()
|
|
265
206
|
}
|
|
266
207
|
},
|
|
267
208
|
|
|
268
|
-
|
|
269
|
-
if (this.reconnectTimer || this.reconnectCount >= this.maxReconnectCount) return
|
|
270
|
-
|
|
271
|
-
this.reconnectCount++
|
|
272
|
-
const delay = Math.min(3000 * this.reconnectCount, 15000)
|
|
273
|
-
|
|
274
|
-
this.reconnectTimer = setTimeout(async () => {
|
|
275
|
-
this.reconnectTimer = null
|
|
276
|
-
try {
|
|
277
|
-
await this.checkAndInit()
|
|
278
|
-
this.$emit('reconnect')
|
|
279
|
-
} catch (error) {
|
|
280
|
-
this.scheduleReconnect()
|
|
281
|
-
}
|
|
282
|
-
}, delay)
|
|
283
|
-
},
|
|
284
|
-
|
|
285
|
-
clearReconnectTimer() {
|
|
209
|
+
destroy() {
|
|
286
210
|
if (this.reconnectTimer) {
|
|
287
211
|
clearTimeout(this.reconnectTimer)
|
|
288
212
|
this.reconnectTimer = null
|
|
289
213
|
}
|
|
214
|
+
if (this.iCall) {
|
|
215
|
+
if (typeof this.iCall.signOut === 'function') {
|
|
216
|
+
this.iCall.signOut()
|
|
217
|
+
}
|
|
218
|
+
this.iCall = null
|
|
219
|
+
}
|
|
220
|
+
this.isInitialized = false
|
|
221
|
+
const scripts = document.querySelectorAll('script[src*="icall.js"]')
|
|
222
|
+
scripts.forEach(s => s.remove())
|
|
290
223
|
}
|
|
291
224
|
}
|
|
292
225
|
}
|