Appearance
SDK2.1.0对接文档
对接SDK2.1.0版本,请优先使用谷歌浏览器。
版本号
版本号 | 发布时间 | 备注信息 |
---|---|---|
2.1.0 | 2024-03-22 | |
2.1.1 | 2024-04-11 | |
2.1.2 | 2024-05-23 | |
2.1.3 | 2024-05-30 | |
2.1.4 | 2024-06-06 | |
2.1.5 | 2024-06-13 | 和2.1.4版本保持一致 |
2.2.0 | 2024-07-01 | |
2.2.1 | 2024-07-18 | 当前最新版本 |
引入
在html文件的body中通过script引入cdn文件
html
<!--测试环境-->
<script src="https://cc2webuat.diankongcloud.cn/sdk/dkCloud-webrtcSDK.js"></script>
<!--生产环境-->
<script src="https://ccadmin.diankongcloud.cn/sdk/dkCloud-webrtcSDK.js"></script>
注意:对接需要使用的分机座席等账号信息请向我方申请调配。
体验地址
js
// 测试地址
https://cc2webuat.diankongcloud.cn/toolbar/
//生产地址
https://ccadmin.diankongcloud.cn/toolbar/
介绍
SDK2版本中定义了一个构造函数DKY,座席和分机的所有操作都是调用该构造函数的内部方法,并通过监听内部的事件系统获取到对应操作的回调数据。
js
const dky = new DKY()
1、初始化
说明
init()
函数为了便于客户对接,将座席登录和分机注册进行了合并封装,客户在进行对接时只需要传递指定的参数,而不需要关注座席和分机的逻辑关系。
使用
js
dky.init(object, callback)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
mode | 必传 | 取值为mixin/single ,默认为mixin(值为空或者随意的内容值,默认都是mixin) |
agentNumber | 必传 | 座席号(工号) |
agentType | 座席号类型(0:默认座席工号 1:自定义座席工号)不传默认0 | |
extensionNumber | 必传 | 分机号 |
extensionPassword | 必传 | 分机注册密码 |
projectId | 必传 | 企业编码 |
token | 必传 | 创建企业时,系统生成的指定token |
agentWebscoketUrl | 必传 | 座席登录的webScoekt地址 |
initType | 必传 | 初始化类型 取值: 1 - IP话机类型, 2 - webrtc类型,3 - 手机号 |
initialState | 初始状态,取值:2 - 空闲,3 - 忙碌,默认为空闲状态 | |
delayTime | 是否接收网络延迟检测事件,true为接收,false为不接收,默认为false | |
isEncrypt | 分机密码是否为加密密文,取值:true/false,默认为false |
callback回调函数
事件监听的回调函数,如果不传递,将监听不到任何事件。
监听回调事件
dky:init
事件只有在mode为minix时会触发
js
dky.on('dky:init', (data) => {
console.log('初始化的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 初始化的模式 |
state | 状态:init - 初始化成功,error - 初始化发生错误 |
agentId | 座席工号 |
agentRole | 座席角色:ordinary - 普通座席,monitor - 班长座席 |
description | 状态描述 |
2、退出/注销
logoff()
函数无论是mixin的模式还是single模式都会将座席和分机同时进行退出或者注销。
使用
js
dky.logoff(object)
object参数说明
参数名称 | 要求 | 备注 |
---|---|---|
agentId | 班长座席强制其他座席进行下线的指定座席号 | |
bindState | 在使用非webrtc分机进行退出时为必传 | bindState可取值为:bind - 退出时不解绑绑定的分机或者手机号,unbind - 退出时解绑绑定的分机或者手机号,默认值为unbind(退出同时解绑绑定的分机号或者手机号) |
监听回调事件
js
dky.on('dky:logoff', (data) => {
console.log('退出/注销的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 初始化的模式 |
state | 状态:logoff |
description | 状态描述(中文):系统注销完成 |
3、座席登录
agentLogin()
用于座席的登录,这里的座席 登录是单独的座席登录,如果需要注册分机还需要在座席登录完成后再手动调用分机的注册,因此建议对接开发人员在没有特殊业务逻辑的情况优先考虑使用初始化mixin
模式 。
使用
js
dky.agentLogin()
监听回调事件
dky:agentLogin
事件只有在mode为single时触发
js
dky.on('dky:agentLogin', (data) => {
console.log('座席登录的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
code | 状态码,200为成功,非200为失败 |
projectId | 登录注册的企业编码 |
agentId | 登录注册的座席号 |
extension | 登录注册的分机号 |
eventType | 事件类型 |
message | 提示信息 |
type | 类型 |
realm | 注册的域名 |
webrtcip | 分机需要注册的地址 |
4、座席退出
agentExit()
函数用于座席的退出,该函数仅退出座席,不会对分机产生任何影响。
使用
js
dky.agentExit(bindState)
参数说明
参数名称 | 要求 | 备注 |
---|---|---|
bindState | 在使用非webrtc分机进行退出时为必传 | bindState可取值为:bind - 退出时不解绑绑定的分机或者手机号,unbind - 退出时解绑绑定的分机或者手机号,默认值为unbind(退出同时解绑绑定的分机号或者手机号) |
监听回调事件
dky:agentOut
事件只有在mode为single时触发
js
dky.on('dky:agentExit', (data) => {
console.log('座席退出的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
code | 状态码,200为成功,非200为失败 |
projectId | 登录注册的企业编码 |
agentId | 登录注册的座席号 |
extension | 登录注册的分机号 |
eventType | 事件类型 |
message | 提示信息 |
type | 类型 |
5、分机注册
extensionRegister()
用于分机的注册,这里的分机注册是单独的分机注册,需要先进行座席的登录才可以进行分机的注册,因此建议对接开发人员在没有特殊业务逻辑的情况优先考虑使用初始化mixin
模式 。
使用
js
dky.extensionRegister()
监听回调事件
dky:extensionRegister
事件只有在mode为single时触发
js
dky.on('dky:extensionRegister', (data) => {
console.log('分机注册的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 初始化的模式 |
state | 状态 |
description | 状态的描述 |
6、分机注销
extensionCancel()
用于分机的注销,因此建议对接开发人员在没有特殊业务逻辑的情况优先考虑使用初始化mixin
模式 。
使用
js
dky.extensionCancel()
监听回调事件
dky:extensionOff
事件只有在mode为single时触发
js
dky.on('dky:extensionCancel', (data) => {
console.log('分机注销的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 初始化的模式 |
state | 状态 |
description | 状态的描述 |
7、网络延迟时间
SDK2版本提供了网络延迟时间监听事件,当初始化参数delayTime设置为true时,通过dky:networkDelay
事件便可以实时监听当前座席的网络延迟时间,如果初始化参数delayTime设置为false,将不会接收到网络延迟时间的事件信息。
监听回调事件
js
dky.on('dky:networkDelay', (data) => {
console.log('网络延迟时间的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 初始化的模式 |
delayTime | 网络延迟时间,单位毫秒 |
description | 状态的描述 |
8、座席外呼
callphone()
函数用于座席的外呼操作,外呼后,会触发dky:callphone
事件。
使用
js
dky.callphone(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
callednum | 必传 | 需要外呼的被叫号码,例如:18212345678 |
userfield | 用户自定义数据,定制对接。255位长字符串 不含特殊符号 推荐base64 | |
tag | 风控标签 | |
mobileTelx | 指定手机外显 (若指定外显 手机外显/固话外显/中继组外显 三个选项只能选一) | |
fixedTelx | 指定固话外显(若指定外显 手机外显/固话外显/中继组外显 三个选项只能选一) | |
trunkNumberGroup | 指定中继组外显(若指定外显 手机外显/固话外显/中继组外显 三个选项只能选一) | |
callStrategy | 中继组外显 呼叫策略 1-本地打本地2-省会托底 (选择中继组时需要配合该策略使用 默认本地打本地) |
监听回调事件
js
dky.on('dky:callphone', (data) => {
console.log('外呼操作的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
code | 状态码,200为成功,非200为失败 |
projectId | 登录注册的企业编码 |
agentId | 登录注册的座席号 |
extension | 登录注册的分机号 |
eventType | 事件类型 |
message | 提示信息 |
type | 类型 |
linkedId | 通话唯一标识 |
外呼code状态码非200对照表
code | message |
---|---|
400 | 参数相关错误提示 |
403 | 无权限,请联系管理员 该号码不在白名单中 未开启呼入手动满意度 未开启呼出手动满意度 座席仅限外呼国内号码 座席仅限外呼国际号码 |
10000 | 外呼号码为黑名单号码 |
26 | 外呼号码触发风控 |
500 | 系统繁忙,请稍后再试! 当前通话未结束 呼叫失败 号码资源相关错误(直接返回dialresource项目返回的错误提示) 当前无通话 监听失败,当前座席无通话 监听失败,当前座席通话不是三方模式 咨询失败,当前坐席处于通话中 该时间段不可呼叫 |
501 | 自备卡号未在白名单中 |
502 | 队列/技能相关错误 登录失败,当前座席未绑定队列 登录失败,当前座席未绑定对应技能 登陆失败,座席未绑定队列为 %s 的技能 相同队列号已存在,请重新添加 该优先级已存在队列,请重新添加 队列【123】已在语音导航中配置,无法删除 |
503 | 数据重复 |
504 | 该数据不存在 |
20001 | 超出座席登陆并发数 |
20002 | 分机未绑定 |
20003 | 分机不存在 |
20004 | 分机不可用 |
20005 | 号码:{}不可用,已被座席:{},工号:{}使用 |
20006 | 未找到该座席编号 |
20007 | 该座席未启用 |
20008 | 座席未登录 转接失败,当前座席未登录 咨询失败,当前座席未登录 监听失败,当前座席未登录 |
20009 | 分机未注册 转接失败,当前座席分机未注册 咨询失败,当前座席分机未注册 |
9、响铃事件
响铃事件在座席外呼和客户呼入时均会触发,开发人员对接时只需设置监听即可。
监听回调事件
js
dky.on('dky:ring', (data) => {
console.log('响铃事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
code | 状态码,200为成功,非200为失败 |
projectId | 登录注册的企业编码 |
agentId | 登录注册的座席号 |
extension | 登录注册的分机号 |
eventType | 事件类型 |
message | 提示信息 |
type | 类型 |
linkedId | 通话唯一标识 |
agentNumber | 座席号 |
agentTelNumber | 座席侧分机号码 |
callLeg | 角色:agent - 座席侧,customer - 客户侧 |
callType | 通话类型:0 - 单呼,2 - 双呼,4 - 预测外呼,5 - IVR语音,7 - webcall,8 - 监听,9 - 强插,10 - 耳语,11 - 转接座席,12 - 转外线,13 - 转IVR,14 - 转队列,15 - 咨询转座席,16 - 咨询转外线,17 - 咨询三方,18 - 监听三方,19 - 咨询座席,20 - 咨询线,21 - 强拆,30 - 呼入直呼节点,31 - 呼入进队列,32 - 预测外呼溢出到队列 |
customerTelNumber | 客户侧号码 |
eventTime | 事件触发时间 |
option | 通话方向:out - 外呼,in - 呼入 |
requestId | 请求的唯一值 |
initiateAgentId | 原始座席号 |
initateChannelId | 原始的通道id值 |
initateExtensionNo | 原始的分机号 |
transferAgentId | 转接的座席 |
transferChannelId | 转接的通道id值 |
transferExtension | 转接的分机 |
transferTime | 转接的时间 |
10、座席接听
answer()
函数用于当座席有来电时的接听,接听后会触发dky:answer
事件,同时在座席外呼时,客户侧接听后也会触发dky:answer
事件
使用
js
dky.answer()
监听回调事件
js
dky.on('dky:answer', (data) =>{
console.log('接听事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
code | 状态码,200为成功,非200为失败 |
projectId | 登录注册的企业编码 |
agentId | 登录注册的座席号 |
extension | 登录注册的分机号 |
eventType | 事件类型 |
message | 提示信息 |
type | 类型 |
linkedId | 通话唯一标识 |
agentNumber | 座席号 |
agentTelNumber | 座席侧分机号码 |
callLeg | 角色:agent - 座席侧,customer - 客户侧 |
callType | 通话类型:0 - 单呼,2 - 双呼,4 - 预测外呼,5 - IVR语音,7 - webcall,8 - 监听,9 - 强插,10 - 耳语,11 - 转接座席,12 - 转外线,13 - 转IVR,14 - 转队列,15 - 咨询转座席,16 - 咨询转外线,17 - 咨询三方,18 - 监听三方,19 - 咨询座席,20 - 咨询线,21 - 强拆,30 - 呼入直呼节点,31 - 呼入进队列,32 - 预测外呼溢出到队列 |
customerTelNumber | 客户侧号码 |
eventTime | 事件触发时间 |
option | 通话方向:out - 外呼,in - 呼入 |
requestId | 请求的唯一值 |
initiateAgentId | 原始座席号 |
initateChannelId | 原始的通道id值 |
initateExtensionNo | 原始的分机号 |
transferAgentId | 转接的座席 |
transferChannelId | 转接的通道id值 |
transferExtension | 转接的分机 |
transferTime | 转接的时间 |
11、座席挂断
hangup()
函数用于座席通话的挂断,挂断后会触发dky:hangup
事件,同时,客户侧挂断后也会触发dky:hangup
事件
使用
js
dky.hangup(agentId)
参数说明
参数名称 | 要求 | 类型 | 说明 |
---|---|---|---|
agentId | String | 班长座席进行强拆时,必须传递需要强拆的座席号,其他情况可不传 |
监听回调事件
js
dky.on('dky:hangup', (data) => {
console.log('挂断事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
code | 状态码,200为成功,非200为失败 |
projectId | 登录注册的企业编码 |
agentId | 登录注册的座席号 |
extension | 登录注册的分机号 |
eventType | 事件类型 |
message | 提示信息 |
type | 类型 |
linkedId | 通话唯一标识 |
agentNumber | 座席号 |
agentTelNumber | 座席侧分机号码 |
callLeg | 角色:agent - 座席侧,customer - 客户侧 |
callType | 通话类型:0 - 单呼,2 - 双呼,4 - 预测外呼,5 - IVR语音,7 - webcall,8 - 监听,9 - 强插,10 - 耳语,11 - 转接座席,12 - 转外线,13 - 转IVR,14 - 转队列,15 - 咨询转座席,16 - 咨询转外线,17 - 咨询三方,18 - 监听三方,19 - 咨询座席,20 - 咨询线,21 - 强拆,30 - 呼入直呼节点,31 - 呼入进队列,32 - 预测外呼溢出到队列 |
customerTelNumber | 客户侧号码 |
eventTime | 事件触发时间 |
option | 通话方向:out - 外呼,in - 呼入 |
requestId | 请求的唯一值 |
initiateAgentId | 原始座席号 |
initateChannelId | 原始的通道id值 |
initateExtensionNo | 原始的分机号 |
transferAgentId | 转接的座席 |
transferChannelId | 转接的通道id值 |
transferExtension | 转接的分机 |
transferTime | 转接的时间 |
enterSatisfaction | 是否进满意度:1 进满意度后挂机,默认为空 |
12、座席状态
setAgentState()
函数用于设置座席的状态,设置后会触发dky:agentState
事件。座席状态分为空闲和置忙两种。
使用
js
dky.setAgentState(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
agentId | 班长座席调整的指定座席的座席号 | |
state | 必传 | 取值:2 - 空闲,3 - 忙碌 设置为忙碌时,只影响接听电话,不影响外呼电话。 |
reason | 取值于管理系统设置的自定义置忙原因,比如:meeting |
监听回调事件
js
dky.on('dky:agentState', (data) => {
console.log('座席状态的事件', data)
})
回调事件中的data对象参数介绍
参数描述 | 描述 |
---|---|
agentNumber | 座席号/工号 |
projectId | 企业编码 |
extension | 分机号 |
state | 座席状态:2 - 空闲,3 - 忙碌 |
reason | 座席状态原因 |
requestId | 请求唯一值 |
13、座席转接
blindMove()
函数用于座席电话的转接功能。转接后,将当前座席的当前通话转接给其他座席或者外线号码,转接座席侧响铃,当前座席自动挂断。执行后会触发dky:blindMove
事件。
使用
js
dky.blindMove(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
mode | 0 - 将电话转接给内部座席,座席必须登录 1 - 将电话转接给外部号码 2 - 将电话转给IVR 3 - 将电话转入队列, 默认值为0 | |
transferNumber | 必传 | 当mode为0时 传转接的座席的id,座席必须登录,当mode为1时,传需要转接的外线号码,当mode为2时,传需要转接的IVR的id,当mode为3时,传需要转接的队列号 |
ivrNodeId | ivr节点id ivrNodeId和ivrNodeType 搭配使用两个参数不传 则默认当前ivrId起始位置播放两个参数传入 则从对应ivr节点开始播放 | |
ivrNodeType | ivr节点类型ivrNodeId和ivrNodeType 搭配使用两个参数不传 则默认当前ivrId起始位置播放两个参数传入 则从对应ivr节点开始播放 |
监听回调事件
js
dky.on('dky:blindfer', (data) => {
console.log('座席转接的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
agentNumber | 监听发起的座席号 |
extension | 监听发起的分机号 |
mode | 转接模式:0 - 将电话转接给内部座席,座席必须登录 1 - 将电话转接给外部号码 2 - 将电话转给IVR 3 - 将电话转入队列 |
projectId | 企业编号 |
requestId | 请求唯一值 |
14、通话保持
hold()
函数用于座席通话的通话保持功能,通话保持执行后客户侧开始播放等待音乐,同时触发dky:hold
事件
使用
js
dky.hold()
监听回调事件
js
dky.on('dky:hold', (data) => {
console.log('呼叫保持的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 状态:hold- 通话保持开启,unhold - 通话保持结束 |
agentNumber | 座席号/工号 |
extension | 分机号 |
projectId | 企业编码 |
requestId | 请求唯一值 |
description | 描述信息 |
15、取消通话保持
unhold()
函数用于座席通话的取消通话保持,取消通话保持后客户侧恢复与座席侧的通话,同时触发dky:hold
事件
使用
js
dky.unhold()
监听回调事件
js
dky.on('dky:hold', (data) => {
console.log('取消呼叫保持的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 状态:hold- 通话保持开启,unhold - 通话保持结束 |
agentNumber | 座席号/工号 |
extension | 分机号 |
projectId | 企业编码 |
requestId | 请求唯一值 |
description | 描述信息 |
16、二次拨号
playdtmf()
用于二次拨号功能, 座席与客户的号码接通后,座席可能听到对方是一段语音,“直拨分机号码,查号请按0”。这时需要调用此接口,将需要的按键,如802发送到对方的线路上,相当于在电话上按了802。执行后会触发dky:playDtmf
事件
使用
js
dky.playdtmf(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
digit | 必传 | 按键值,例如:0123456789*# |
agentId | 必传 | 根据agentType 传入对应内容:坐席工号/客户crmId(需要创建坐席时指定) |
agentType | 坐席类型 0 - 系统坐席工号(默认) ,1 - 客户crmId |
监听回调事件
js
dky.on('dky:playDtmf', (data) => {
console.log('二次拨号的事件', data)
})
17、监听
chanspy()
函数用于操作班长座席的监听或者咨询功能,根据参数不同可以做到一下功能:
- 静音模式 (班长可以听到座席和客户的声音,座席及客户听不到班长的声音)
- 耳语模式(班长说话,只能座席听到)
执行后会触发dky:chanspy
事件
使用
js
dky.chanspy(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
mode | 必传 | 监听模式:0 - 耳语模式, 1 - 监听模式, 2-强插,3-监听三方 |
agentId | 必传 | 监听的座席号码 |
point | 指定班长侧号码方式:0 - 默认值 班长号为内部坐席 1 - 班长号为外线号码 | |
monitorNumber | 必传 | 班长的号码 point 为0时传班长坐席号 point 为1时传外线号码 |
监听回调事件
js
dky.on('dky:chanspy', (data) => {
console.log('监听/咨询的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
agentNumber | 监听发起的座席号 |
extension | 监听发起的分机号 |
mode | 监听模式:0 - 耳语模式, 1 - 静音模式,2-强插,3-监听三方 |
projectId | 企业编号 |
requestId | 请求唯一值 |
18、满意度
serviceLevel()
用于座席与客户通话结束后,座席通过调用后,给客户播放满意度评价录音,客户按键,完成此次通话的评价,执行后会触发dky:serviceLevel
事件
使用
js
dky.serviceLevel()
监听回调事件
js
dky.on('dky:serviceLevel', (data) => {
console.log('满意度的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
19、静音
mute()
函数用于操作座席的静音/取消静音,执行后会触发dky:agentMute
事件
使用
js
dky.mute()
监听回调事件
js
dky.on('dky:agentMute', (data) => {
console.log('座席静音的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 状态:mute - 静音开启,unmute - 静音结束 |
agentNumber | 座席号/工号 |
extension | 分机号 |
projectId | 企业编码 |
requestId | 请求唯一值 |
description | 描述信息 |
20、恢复静音
unmute()
函数用于操作座席的静音/取消静音,执行后会触发dky:agentMute
事件
使用
js
dky.unmute()
监听回调事件
js
dky.on('dky:agentMute', (data) => {
console.log('座席取消静音的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
mode | 状态:mute - 静音开启,unmute - 静音结束 |
agentNumber | 座席号/工号 |
extension | 分机号 |
projectId | 企业编码 |
requestId | 请求唯一值 |
description | 描述信息 |
21、音频设备检测
说明
checkMedia()
函数,可以获取到当前浏览器音频设备是否可以正常进行使用。
使用
js
dky.checkMedia()
监听回调事件
js
dky.on('dky:deviceDetection', (data) => {
console.log('音频设备检测事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
state | 设备状态,success为正常,error为错误 |
info | 获取到的设备信息 |
22、事件监听函数
on()
函数用于监听事件
使用
js
dky.on(event, fn)
参数说明
参数名称 | 要求 | 备注 |
---|---|---|
event | 必传 | 需要监听的事件名称 |
fn | 必传 | 监听事件的回调函数 |
23、呼入非接通挂断置忙事件
座席被呼入后,如果座席或者用户在未接通状态下进行了挂断,那么当前座席会自动进行置忙,并接收到该事件的推送信息。
监听回调事件
js
dky.on('dky:incomingNotConnectedHangup', (data) => {
console.log('呼入非接通挂断置忙事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
agentId | 座席号/工号 |
agentState | 座席状态:3 - 忙碌 |
linkedId | 当前通话唯一值 |
extension | 分机号 |
message | 描述 信息 |
24、咨询三方
座席发起对另一个座席或者外线号码的咨询请求,被发起座席或者外线号码接听后加入到当前通话中进行通话。执行后触发dky:meet
事件
使用
js
dky.meet(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
mode | 必传 | 0 - 默认 咨询内部坐席, 1 - 咨询外线号码监听的座席号码 |
agentId | 必传 | 座席号码 |
meetrNumber | 必传 | 咨询号码,mdoe 为0时传座席号,mode为1时传外线号码 |
js
dky.on('dky:meet', (data) => {
console.log('咨询三方的事件', data)
})
回调事件中的data对象参数介绍
参数名称 | 描述 |
---|---|
agentNumber | 监听发起的座席号 |
extension | 监听发起的分机号 |
mode | 0 - 咨询内部坐席, 1 - 咨询外线号码 |
projectId | 企业编号 |
requestId | 请求唯一值 |
25、咨询转接
将座席当前通话转接给其他坐席或外线,在和其他转接侧交谈后,如果选择挂断,则客户和转接侧实现通话,如果转接侧选择挂断,则恢复客户与座席的通话。执行后会触发dky:atxfer
事件。
使用
js
dky.atxfer(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
mode | 必传 | 0 - 默认 咨询内部座席, 1 - 咨询外线号码监听的座席号码 |
atxferNumber | 必传 | 需要咨询转接的座席号:mode为0时 传转接的座席id,mode为1时,传外线号码,座席必须登录 |
js
dky.on('dky:atxfer', (e) => {
console.log('咨询转接的事件', e)
})
回调事件中的对象参数介绍
参数名称 | 描述 |
---|---|
agentNumber | 监听发起的座席号 |
extension | 监听发起的分机号 |
mode | 0 - 咨询内部坐席, 1 - 咨询外线号码 |
projectId | 企业编号 |
requestId | 请求唯一值 |
26、咨询转接(咨询) 挂断(接回)
咨询转接发出后,在被转接座席未接通前或者接通后,将通话进行接回,恢复和客户侧的正常通话。调用后会触发dky:hangup
挂断事件。
使用
js
dky.atxferHangup()
27、强制下线事件
当座席被班长座席强制指定下线后,会接收到dky:forceOffline
事件。
js
dky.on('dky:forceOffline', (e) => {
console.log('强制下线事件', e)
})
回调事件中的对象参数介绍
参数名称 | 描述 |
---|---|
agentNumber | 当前的座席号 |
extension | 当前的分机号 |
monitorAgentId | 班长的座席号 |
projectId | 企业编号 |
requestId | 请求唯一值 |
state | 错误状态:success - 操作成功,error - 操作失败 |
description | 描述信息 |
28、实时数据事件
首次登录和每次通话结束后,会主动推送一次dky:realTimeData
实时数据事件。
js
dky.on('dky:realTimeData', (e) => {
console.log('实时数据事件', e)
})
回调事件中的对象参数介绍
参数名称 | 描述 |
---|---|
callCount | 外呼次数 |
effectiveCallCount | 有效外呼次数 |
effectiveCallDuration | 有效外呼时长,单位:秒 |
29、咨询
将座席当前通话转接给其他坐席或外线,在和其他转接侧交谈后,通过咨询接回,恢复客户与座席的通话。被咨询座席 在接受座席咨询时,不能够主动挂断咨询来电,执行后会触发dky:consult
事件。
js
dky.consult(object)
object对象参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
mode | 必传 | 0 - 默认 咨询内部座席, 1 - 咨询外线号码监听的座席号码 |
atxferNumber | 必传 | 需要咨询转接的座席号:mode为0时 传转接的座席id,mode为1时,传外线号码,座席必须登录 |
js
dky.on('dky:consult', (e) => {
console.log('咨询的事件', e)
})
回调事件中的对象参数介绍
参数名称 | 描述 |
---|---|
agentNumber | 监听发起的座席号 |
extension | 监听发起的分机号 |
mode | 0 - 咨询内部坐席, 1 - 咨询外线号码 |
projectId | 企业编号 |
requestId | 请求唯一值 |
30、咨询三方挂断/接回
咨询三方后进行挂断或者接回操作。
js
dky.meetHangup(type)
type参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
type | 必传 | hangup - 咨询三方挂断,retrieve - 咨询三方接回 |
事件名称 | 描述 |
---|---|
dky:init | 初始化 |
dky:deviceDetection | 音频设备检测 |
dky:logoff | 退出/注销 |
dky:agentLogin | 座席登录 |
dky:agentExit | 座席退出 |
dky:extensionRegister | 分机注册 |
dky:extensionCancel | 分机注销 |
dky:networkDelay | 网络延迟时间 |
dky:callphone | 座席外呼 |
dky:ring | 响铃 |
dky:answer | 接听事件 |
dky:hangup | 挂断事件 |
dky:agentState | 座席状态 |
dky:blindfer | 座席盲转 |
dky:hold | 呼叫保持 |
dky:playDtmf | 二次拨号 |
dky:serviceLevel | 满意度 |
dky:agentMute | 座席静音/取消静音 |
dky:agentWebsocketOpen | 座席的webscoket连接开启事件 |
dky:agentWebscoketClose | 座席的webscoket连接断开事件 |
dky:agentWebscoketError | 座席的webscoket连接发生错误事件 |
dky:squeeze | 未退出的重新登录,被挤下线 |
dky:networkDisconnected | 浏览器网络连接情况:networkDisconnected - 网络断开,networkConnected - 网络连接恢复 |
dky:reconnect | 掉线重连:每十秒钟会触发重连一次,重连10次都未成功后,自动断开不再进行重连 state: reconnected-重连成功,reconnecting-重连中,reconnectFail-重连失败结束重连,num:重连的次数 |
dky:incomingNotConnectedHangup | 呼入非接通挂断置忙事件 |
dky:meet | 咨询三方 |
dky:atxfer | 咨询转接 |
31、座席状态查询
agentState()
函数用于查询并获取当前座席状态,执行后会触发dky:agentState
事件
js
dky.agentState()
事件参数
参数名 | 类型 | 备注 |
---|---|---|
crmId | Integer | 客户crmId |
agentNumber | string | 座席编号 |
agentName | string | 座席姓名 |
currentState | string | 当前座席状态(文字描述):空闲、置忙、整理、 外呼发起、外呼振铃中、外呼通话中; 发起咨询中、发起咨询振铃中、被发起咨询振铃中、咨询通话中、被咨询通话中; 发起咨询转移中、发起咨询转移振铃中、被发起咨询转移振铃中、发起咨询转移通话中、被发起转移通话中; 被发起转移振铃中、被转移通话中; 发起咨询三方中、发起咨询三方振铃中、被发起咨询三方振铃中、咨询三方通话中、被咨询三方通话中; 监听中、耳语中、监听三方中、强插中等等 |
currentStateTime | string | 当前状态持续时长(HH:mm:ss) |
telb | string | 客户号码 |
option | string | 呼叫指向(in:呼入;out:呼出;) |
loginTime | string | 登录时长(HH:mm:ss) |
currentExtension | string | 当前分机号 |
32、设置座席外呼时的自动接听状态
在使用后端接口进行外呼时,但其他操作仍然调用SDK的api时,需要在调用后端接口前调用SDK的该api,设置座席自动接听 状态,当接口外呼后,呼入到座席时座席会进行自动接听。在没有设置外呼失败的语音提示时,在调用后端接口外呼失败后需要再次调用以便将内部状态进行恢复,如果设置了语音提示,则只需要设置座席自动接听不需要在外呼失败时进行恢复。
参数介绍
参数名称 | 要求 | 备注 |
---|---|---|
option | 必传 | 取值:autoAnswer - 座席外呼自动接听,recovery - 恢复原有状态 |
使用
js
const call = () => {
dky.setApiCallAutoAnswer('autoAnswer')
let timestamp = parseInt(new Date().getTime() / 1000) //时间戳
let projectid = '' //机构编码
let token = '' //token
let md = md5(projectid + token + timestamp); //md5加密内容
let data = {
agentId:'', //发起外呼的座席号
callednum:'' //被叫号码
}
axios.post(`https://ip/gw2/dky-open-api/version-2.0.0/placecall?projectId=${projectid}×tamp=${timestamp}&sign=${md}`,data)
.then(res => {
consloe.log('外呼成功返回的值')
})
.catch(err => {
console.log('外呼失败返回的值')
dky.setApiCallAutoAnswer('recovery')//这里在没有开启呼叫失败的语音提示时进行调用,开启了语音提示则不需要调用
})
}
示例代码
html文件
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
<title>SDK验证</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="sdk">
<div class="left">
<div class="init-area">
<fieldset>
<legend>初始化</legend>
初始化模式:
<input type="radio" value="mixin" name="type" id="mixin" checked><label for="mixin">mixin</label>
<input type="radio" value="single" name="type" id="single"><label for="single">single</label>
<br/>
初始化类型:
<input type="radio" value="1" name="type1" id="ipPhone"><label for="ipPhone">IP话机</label>
<input type="radio" value="2" name="type1" id="webrtc" checked><label for="webrtc">webrtc</label>
<input type="radio" value="3" name="type1" id="phone"><label for="phone">手机号</label>
<br/>
projectId:
<input type="text" value="" id="projectId">
agentId:
<input type="text" value="" id="agentId">
<br>
extension:
<input type="text" value="" id="extension">
password:
<input type="text" value="" id="password"><input type="checkbox" value="1" name="status" id="ciphertextRadio"><label for="ciphertextRadio">密文</label>
<br>
token:
<input type="text" value="" id="token">
queue:
<input type="text" value="" id="queue">
<br>
url:
<input type="text" value="" id="url">
initialstate:
<input type="text" value="" id="initialstate">
<br>
<button id="start">初始化</button>
<button id="logout">注销</button>
<div class="single">
<button id="agentLogin">座席登录</button>
<button id="extensionRegister">分机注册</button>
<button id="agentOut">座席退出</button>
<button id="extensionOut">分机注销</button>
</div>
</fieldset>
</div>
<div class="call-area">
<fieldset style="padding:15px;">
<legend>通话相关</legend>
<input type="text" id="phone-number" value=""><br><br>
<button id="call">拨打</button>
<button id="answer">接听</button>
<button id="hangup">挂断</button>
<button id="reject">拒接</button>
<button id="hold">保持</button>
<button id="resume">保持结束</button>
<button id="mute">静音</button>
<button id="restore">静音恢复</button>
<button id="satisfaction">满意度</button>
<button id="double">二次拨号</button>
<button id="dismantling">强拆</button>
<button id="agentState">座席状态</button>
<button id="backCall">拨打</button>
</fieldset>
</div>
<div class="agent">
<fieldset>
<legend>座席状态</legend>
<input type="radio" value="2" name="status" id="free" checked><label for="free">空闲</label>
<input type="radio" value="3" name="status" id="busy"><label for="busy">忙碌</label>
<div>
<select name="reason" id="reason">
<option value="">选择忙碌原因</option>
<option value="private">private</option>
<option value="public">public</option>
<option value="teabreak">teabreak</option>
<option value="meeting">meeting</option>
</select>
</div>
<button id="agent-set">设置</button>
</fieldset>
</div>
<div class="switch">
<fieldset>
<legend>转接相关</legend>
<input type="radio" value="0" name="mode" id="inside" checked><label for="inside">内部</label>
<input type="radio" value="1" name="mode" id="outside"><label for="outside">外部</label>
<input type="text" value="9001" id="blindChange-input">
<button id="blindChange">盲转</button>
<button id="atxfer">咨询转接</button>
<button id="atxferHangup">转接挂断</button>
<button id="consult">咨询</button><br><br>
监听模式:
<input type="radio" value="0" name="listen" id="quiet" checked><label for="quiet">耳语模式</label>
<input type="radio" value="1" name="listen" id="whisper"><label for="whisper">监听(静音)模式</label>
<input type="radio" value="2" name="listen" id="insert"><label for="insert">强插</label>
<input type="radio" value="3" name="listen" id="listenIn"><label for="listenIn">监听三方</label>
<input type="radio" value="4" name="listen" id="tripartite"><label for="tripartite">咨询三方</label>
<br>
<input type="text" value="" placeholder="监听的座席号" id="listen-input">
<button id="listen">执行</button>
</fieldset>
</div>
<div class="switch">
<fieldset>
<legend>加解密</legend>
<input type="text" value="" id="ciphertext-input">
<button id="encrypt">加密</button>
<button id="decrypt">解密</button>
</fieldset>
</div>
</div>
<div class="right">
<div class="status">
<div class="title">当前状态:</div>
<div class="info" id="info">等待上线</div>
<div id="sortOut"></div>
<div class="delay" id="delay">等待网络连接</div>
</div>
<div class="content">
<div class="content-title">事件信息:</div>
<textarea id="content-info" name="sendMessage" rows="50" cols="170" readonly="readonly"></textarea>
</div>
</div>
</div>
<script src="https://cc2webtest.diankongcloud.cn/sdk/dkCloud-webrtcSDK2.1.0.js"></script>
<script src="./index.js"></script>
</body>
</html>
css文件
css
* {
padding: 0;
margin: 0;
}
html, body {
width: 100%;
height: 100%;
}
.sdk {
width: 100%;
height: 100%;
display: flex;
}
input:focus {
outline: 1px solid #1e75fe;
border: none;
}
fieldset {
padding: 15px;
}
select {
width: 200px;
height: 30px;
border-radius: 4px;
display: none;
}
select:focus{
outline: 1px solid #1e75fe;
border: none;
}
.sdk .left {
width: 35%;
height: 100%;
border-right: 1px solid #bfbfbf;
overflow-y: auto;
}
.sdk .left .init-area ,.call-area ,.agent, .switch {
padding: 15px
}
.sdk .left .init-area .single {
display: none;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.sdk .left .init-area .single button {
width: 45%;
height: 35px;
}
.sdk .left .init-area input {
height: 16px;
margin: 10px 0;
padding: 5px;
}
.sdk .left .init-area button {
width: 100%;
height: 35px;
background-color: #1e75fe;
color:#fff;
border: none;
border-radius: 4px;
font-size: 16px;
margin: 5px 0;
}
.sdk .left .init-area button:active {
background-color: blue;
}
.sdk .left .call-area input, .switch input {
height: 16px;
padding: 5px;
}
.sdk .left .call-area button ,.agent button, .switch button {
width: 60px;
height: 38px;
background-color: #1e75fe;
border: none;
border-radius: 4px;
color: #fff;
margin: 5px 0;
}
#answer{
background-color: #67C23A;
}
#hangup, #dismantling, #atxferHangup, #reject{
background-color: red;
}
.sdk .right {
width: 65%;
padding: 15px 0;
}
.sdk .right .status {
height: 60px;
padding-left: 15px;
display: flex;
align-items: center;
border-bottom: 1px solid #bfbfbf;
}
.sdk .right .status .title {
font-size: 18px;
font-weight: 600;
}
.sdk .right .status .info {
font-size: 18px;
font-weight: 600;
color:#bfbfbf;
margin-right: 15px;
}
.sdk .right .status .delay {
margin:3px 0 0 25px;
font-size: 12px;
font-weight: 600;
color:red;
}
.sdk .right .content {
padding: 15px;
}
.sdk .right .content .content-title {
height: 30px;
font-size: 18px;
font-weight: 600;
}
.sdk .right .content .content-info {
height: 800px;
margin-top:10px;
border-radius: 4px;
/* border: 2px solid #bfbfbf; */
}
.agent div{
margin: 5px 0;
}
textarea {
width: 1213px;
height: 835px;
}
js文件
js
const mixin = document.getElementById("mixin");
const single = document.getElementById("single");
const ipPhone = document.getElementById("ipPhone");
const webrtc = document.getElementById("webrtc");
const phone = document.getElementById("phone");
const projectId = document.getElementById("projectId");
const agentId = document.getElementById("agentId");
const extension = document.getElementById("extension");
const password = document.getElementById("password");
const token = document.getElementById("token");
const queue = document.getElementById("queue");
const url = document.getElementById("url");
const initialstate = document.getElementById("initialstate");
const start = document.getElementById("start");
const logout = document.getElementById("logout");
const agentLogin = document.getElementById("agentLogin");
const extensionRegister = document.getElementById("extensionRegister");
const singleDiv = document.querySelector(".single");
const agentOut = document.getElementById("agentOut");
const extensionOut = document.getElementById("extensionOut");
const phoneNumber = document.getElementById("phone-number");
const call = document.getElementById("call");
const answer = document.getElementById("answer");
const hangup = document.getElementById("hangup");
const reject = document.getElementById("reject");
const dismantling = document.getElementById("dismantling");
const hold = document.getElementById("hold");
const resume = document.getElementById("resume");
const mute = document.getElementById("mute");
const restore = document.getElementById("restore");
const double = document.getElementById("double");
const info = document.getElementById("info");
const contentInfo = document.getElementById("content-info");
const delay = document.getElementById("delay");
const free = document.getElementById("free");
const busy = document.getElementById("busy");
const reason = document.getElementById("reason");
const agentSet = document.getElementById("agent-set");
const satisfaction = document.getElementById("satisfaction");
const quiet = document.getElementById("quiet");
const whisper = document.getElementById("whisper");
const insert = document.getElementById("insert");
const listenIn = document.getElementById("listenIn");
const tripartite = document.getElementById("tripartite");
const listenInput = document.getElementById("listen-input");
const listen = document.getElementById("listen");
const inside = document.getElementById("inside");
const outside = document.getElementById("outside");
const blindChangeInput = document.getElementById("blindChange-input");
const blindChange = document.getElementById("blindChange");
const atxfer = document.getElementById("atxfer");
const atxferHangup = document.getElementById("atxferHangup");
const consult = document.getElementById("consult");
const sortOut = document.getElementById("sortOut");
const agentState = document.getElementById("agentState");
const backCall = document.getElementById("backCall");
const ciphertextInput = document.getElementById("ciphertext-input");
const encrypt = document.getElementById("encrypt");
const decrypt = document.getElementById("decrypt");
const ciphertextRadio = document.getElementById('ciphertextRadio')
let timer = null;
const dky = new DKY();
//获取版本信息
// console.log('当前SDK版本信息', dky.version())
//初始化
start.addEventListener("click", function () {
console.log('HTML文件的',new RTCPeerConnection({iceServers:[{urls:"stun:1.92.71.219:3478"}]}));
console.log(navigator);
console.log('执行了');
info.innerHTML = "连接中...";
info.style.color = "#333";
let config = {
mode: "mixin",
projectId: projectId.value,
agentNumber: agentId.value,
extensionNumber: extension.value,
extensionPassword: password.value,
token: token.value,
queueNumber: queue.value,
agentWebscoketUrl: url.value,
initialState: initialstate.value,
initType: null,
delayTime: true,
agentType: 0,
// source:1,
isEncrypt:false
};
if (single.checked) {
config.mode = single.value;
} else {
config.mode = "mixin";
}
if (ipPhone.checked) {
config.initType = 1;
} else if (webrtc.checked) {
config.initType = 2;
} else {
config.initType = 3;
}
if(ciphertextRadio.checked) {
config.isEncrypt = true
}
dky.init(config, eventFuncion);
});
//注销
logout.addEventListener("click", () => {
dky.logoff();
// dky.checkMedia()
});
//座席登录
agentLogin.addEventListener("click", () => {
let init_query = {
mode: "single",
projectId: projectId.value,
agentNumber: agentId.value,
extensionNumber: extension.value,
extensionPassword: password.value,
token: token.value,
queueNumber: queue.value,
agentWebscoketUrl: url.value,
initialState: initialstate.value,
initType: 2,
queueNumber:''
};
dky.init(init_query, eventFuncion);
dky.agentLogin();
});
//座席退出
agentOut.addEventListener("click", () => {
dky.agentExit();
});
//分机注册
extensionRegister.addEventListener("click", () => {
dky.extensionRegister();
});
//分机退出
extensionOut.addEventListener("click", () => {
dky.extensionCancel();
});
//拨号
call.addEventListener("click", () => {
let call_info = {
callednum: phoneNumber.value,
};
dky.callphone(call_info);
});
//接听
answer.addEventListener("click", () => {
dky.answer();
});
//挂断
hangup.addEventListener("click", () => {
dky.hangup()
});
//拒接
reject.addEventListener("click", () => {
dky.reject();
});
//强拆
dismantling.addEventListener("click", () => {
dky.forceHangup({ agentId: phoneNumber.value });
});
//保持结束
resume.addEventListener("click", () => {
dky.unhold();
});
//保持
hold.addEventListener("click", () => {
dky.hold();
});
//静音
mute.addEventListener("click", () => {
dky.mute();
});
//静音恢复
restore.addEventListener("click", () => {
dky.unmute();
});
//满意度
satisfaction.addEventListener("click", (data) => {
dky.serviceLevel();
});
//二次拨号
double.addEventListener("click", () => {
let data = {
digit: phoneNumber.value,
};
dky.playdtmf(data);
});
//座席状态
free.addEventListener("change", () => {
if (free.checked) {
reason.style.display = "none";
} else {
reason.style.display = "block";
}
});
busy.addEventListener("change", () => {
if (free.checked) {
reason.style.display = "none";
reason.value = "";
} else {
reason.style.display = "block";
}
});
agentSet.addEventListener("click", () => {
console.log(free.checked, free.value, busy.checked, busy.value, reason.value);
let query = {
state: "2",
reason: "",
};
if (free.checked) {
query.state = free.value;
query.reason = "";
}
if (busy.checked) {
query.state = busy.value;
query.reason = reason.value;
}
dky.setAgentState(query);
});
//盲转
blindChange.addEventListener("click", () => {
let data = {
mode: "",
transferNumber: blindChangeInput.value,
};
if (inside.checked) {
data.mode = inside.value;
}
if (outside.checked) {
data.mode = outside.value;
}
dky.blindMove(data);
});
//咨询转接
atxfer.addEventListener("click", () => {
let data = {
mode: "",
atxferNumber: blindChangeInput.value,
};
if (inside.checked) {
data.mode = inside.value;
}
if (outside.checked) {
data.mode = outside.value;
}
dky.atxfer(data);
});
//咨询转接挂断
atxferHangup.addEventListener("click", () => {
dky.atxferHangup();
});
consult.addEventListener("click", () => {
let data = {
mode: "",
atxferNumber: blindChangeInput.value,
};
if (inside.checked) {
data.mode = inside.value;
}
if (outside.checked) {
data.mode = outside.value;
}
dky.consult(data);
});
//监听咨询
listen.addEventListener("click", () => {
let data = null;
if (quiet.checked || whisper.checked || insert.checked || listenIn.checked) {
data = {
mode: "",
agentId: listenInput.value,
point: 0,
monitorNumber: agentId.value,
};
} else {
data = {
mode: 0,
meetNumber: listenInput.value,
};
}
if (quiet.checked) {
data.mode = quiet.value;
dky.chanspy(data);
}
if (whisper.checked) {
data.mode = whisper.value;
dky.chanspy(data);
}
if (insert.checked) {
data.mode = insert.value;
dky.chanspy(data);
}
if (listenIn.checked) {
data.mode = listenIn.value;
dky.chanspy(data);
}
if (tripartite.checked) {
dky.meet(data);
}
});
mixin.addEventListener("click", () => {
start.style.display = "block";
logout.style.display = "block";
singleDiv.style.display = "none";
});
single.addEventListener("click", () => {
start.style.display = "none";
logout.style.display = "none";
singleDiv.style.display = "flex";
});
//座席状态
agentState.addEventListener("click", () => {
dky.agentState();
});
//加密
encrypt.addEventListener("click", () => {
let ciphertext = dky.encrypt(ciphertextInput.value, token.value);
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (加密)" +
"\n" +
"原文 ==> " +
ciphertextInput.value +
" " +
"密文 ==> " +
ciphertext +
"\n";
});
//解密
decrypt.addEventListener("click", () => {
let text = dky.decrypt(ciphertextInput.value, token.value);
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (解密)" +
"\n" +
"密文 ==> " +
ciphertextInput.value +
" " +
"原文 ==> " +
text +
"\n";
});
let currentState = null;
function eventFuncion() {
dky.on("dky:init", (data) => {
if (data.state == "init") {
info.innerHTML = "已上线";
info.style.color = "#67C23A";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (初始化)" +
"\n" +
JSON.stringify(data) +
"\n";
} else {
info.innerHTML = data.description;
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (初始化)" +
"\n" +
JSON.stringify(data) +
"\n";
}
});
dky.on("dky:logoff", (e) => {
if (e.state == "error") {
info.innerHTML = e.description;
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (注销)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
info.innerHTML = "已下线";
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (注销)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:forceDisconnectCall", (e) => {
console.log(e, "强拆触发");
});
dky.on("dky:squeeze", (data) => {
info.innerHTML = "被挤下线";
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被挤下线)" +
"\n" +
JSON.stringify(data) +
"\n";
});
dky.on("dky:agentLogin", (data) => {
if (data.state == "error") {
info.innerHTML = data.description;
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (初始化)" +
"\n" +
JSON.stringify(data) +
"\n";
} else {
info.innerHTML = "座席登录成功";
info.style.color = "#67C23A";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席登录)" +
"\n" +
JSON.stringify(data) +
"\n";
}
});
dky.on("dky:agentExit", (e) => {
if (e.state == "error") {
info.innerHTML = e.message;
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席退出)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
info.innerHTML = "座席已退出";
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席退出)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:extensionRegister", (data) => {
info.innerHTML = "分机注册完成";
info.style.color = "#67C23A";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (分机注册)" +
"\n" +
JSON.stringify(data) +
"\n";
});
dky.on("dky:extensionCancel", (data) => {
info.innerHTML = "分机已注销";
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (分机注销)" +
"\n" +
JSON.stringify(data) +
"\n";
});
dky.on("dky:callphone", (data) => {
if (data.code == 200) {
info.innerHTML = "呼叫中...";
info.style.color = "#67C23A";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (拨打)" +
"\n" +
JSON.stringify(data) +
"\n";
} else {
info.innerHTML = "拨号失败";
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (拨打 - 失败)" +
"\n" +
JSON.stringify(data) +
"\n";
}
});
dky.on("dky:ring", (e) => {
if (e.code == 200) {
currentState = e.data.callType;
if (e.data.option == "out" && e.data.callLeg == "customer") {
info.innerHTML = "客户响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (客户响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
if (e.data.option == "in" && e.data.callLeg == "agent") {
info.innerHTML = "座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
} else if (e.data.callType == "11") {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = item;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId != e.data.agentNumber) {
info.innerHTML = "被转转接的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (转接响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId != e.data.agentNumber) {
info.innerHTML = "被转转接的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (转接响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
} else if (e.data.callType == 15) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询转接的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询转接响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询转接的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询转接的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询转接响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询转接的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
} else if (e.data.callType == 19) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询的座席响铃中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询响铃)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
}
}
info.style.color = "#67C23A";
} else {
info.innerHTML = "系统异常,请联系开发人员";
info.style.color = "red";
}
// contentInfo.value = contentInfo.value + '\n' + getCurrentTimes() + ' (响铃)' + '\n' + JSON.stringify(e) + '\n'
// console.log("看看这里打印了什么-1", RTCPeerConnection());
// console.log('看看这里打印了什么-2',RTCIceCandidate());
// console.log('看看这里打印了什么-3',RTCSessionDescription());
// console.log('看看这里打印了什么-4',o_pc);
});
dky.on("dky:answer", (e) => {
if (e.code == 200) {
if (e.data.option == "out" && e.data.callLeg == "customer") {
info.innerHTML = "通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (客户接听)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
if (e.data.option == "in" && e.data.callLeg == "agent") {
info.innerHTML = "通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席接听)" +
"\n" +
JSON.stringify(e) +
"\n";
} else if (e.data.callType == "11") {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = item;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId != e.data.agentNumber) {
info.innerHTML = "被转转接的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (转接通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId != e.data.agentNumber) {
info.innerHTML = "被转转接的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (转接通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
} else if (e.data.callType == 15) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询转接的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询转接通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询转接的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询转接的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询转接通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询转接的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
} else if (e.data.callType == 19) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询的座席通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询通话中...)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
}
}
info.style.color = "#67C23A";
} else {
info.innerHTML = "系统异常,请联系开发人员";
info.style.color = "red";
}
});
dky.on("dky:hangup", (e) => {
if (e.code == 200) {
if (e.data.callType == "11") {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = item;
target = e.data.transferMessage[item];
}
}
}
info.innerHTML = "被转转接的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (转接挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
info.innerHTML = "被转转接的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (转接挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
info.style.color = "red";
setTimeout(() => {
info.innerHTML = "空闲中...";
info.style.color = "#67C23A";
}, 3000);
} else if (e.data.callType == 15) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询转接的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询转接挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询转接的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询转接的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询转接挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询转接的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
info.style.color = "red";
setTimeout(() => {
info.innerHTML = "空闲中...";
info.style.color = "#67C23A";
}, 3000);
} else if (e.data.callType == 19) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
info.innerHTML = "被咨询的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "咨询的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (被咨询挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
setTimeout(() => {
info.innerHTML = "通话中...";
info.style.color = "#67C23A";
}, 3000);
} else {
info.innerHTML = "被咨询的座席挂断";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询通挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
setTimeout(() => {
info.innerHTML = "空闲中...";
info.style.color = "#67C23A";
}, 3000);
}
}
info.style.color = "red";
} else {
if (e.data.hasOwnProperty("transferMessage")) {
let maxTime = null;
let target = null;
if (Object.keys(e.data.transferMessage).length > 1) {
for (let item in e.data.transferMessage) {
if (maxTime == null) {
maxTime = new Date(
e.data.transferMessage[item].transferTime
).getTime();
} else {
let time = new Date(
e.data.transferMessage[item].transferTime
).getTime();
if (maxTime < time) {
maxTime = time;
target = e.data.transferMessage[item];
}
}
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "通话结束";
info.style.color = "red";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
processSortout(e.data.wrapupTime);
} else {
info.innerHTML = "通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
for (let item in e.data.transferMessage) {
target = e.data.transferMessage[item];
}
if (target.initiateAgentId == e.data.agentNumber) {
info.innerHTML = "通话结束";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
processSortout(e.data.wrapupTime);
} else {
info.innerHTML = "通话中...";
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
}
} else {
if (e.data.callLeg == "agent") {
processSortout(e.data.wrapupTime);
}
}
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (挂断)" +
"\n" +
JSON.stringify(e) +
"\n";
}
} else {
info.innerHTML = "系统异常,请联系开发人员";
info.style.color = "red";
}
});
dky.on("dky:agentState", (data) => {
if (data.state == 2) {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席状态:空闲)" +
"\n" +
JSON.stringify(data) +
"\n";
}
if (data.state == 3) {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席状态:忙碌)" +
"\n" +
JSON.stringify(data) +
"\n";
}
});
dky.on("dky:hold", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (通话保持 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
if (e.mode == "hold") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (通话保持开启)" +
"\n" +
JSON.stringify(e) +
"\n";
}
if (e.mode == "unhold") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (通话保持结束)" +
"\n" +
JSON.stringify(e) +
"\n";
}
});
dky.on("dky:agentMute", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (静音 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
if (e.mode == "mute") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (静音开启)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (静音结束)" +
"\n" +
JSON.stringify(e) +
"\n";
}
});
dky.on("dky:service_level", (data) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (满意度)" +
"\n" +
JSON.stringify(data) +
"\n";
});
dky.on("dky:play_dtmf", (data) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (二次拨号)" +
"\n" +
JSON.stringify(data) +
"\n";
});
dky.on("dky:blindMove", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (盲转 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (盲转)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:incomingNotConnectedHangup", (data) => {
console.log("监听到呼入非接通挂断", data);
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (呼入非接通挂断的置忙)" +
"\n" +
JSON.stringify(data) +
"\n";
});
dky.on("dky:networkDelay", (data) => {
delay.innerHTML = "网络延迟:" + data.delayTime + "ms";
// contentInfo.value =
// contentInfo.value +
// "\n" +
// getCurrentTimes() +
// " (座席websocket开启事件)" +
// "\n" +
// JSON.stringify(data) +
// "\n";
if (data.delayTime < 100) {
delay.style.color = "#67C23A";
} else {
delay.style.color = "red";
}
});
dky.on("dky:agentWebsocketOpen", (e) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席websocket开启事件)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:agentWebsocketClose", (e) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席websocket关闭事件)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:reconnect", (e) => {
console.log("出发了");
if (e.state == "reconnected") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (重连成功)" +
"\n" +
JSON.stringify(e) +
"\n";
} else if (e.state == "reconnecting") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (第" +
e.num +
"次重连)" +
"\n" +
JSON.stringify(e) +
"\n";
} else {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (重连十次,重连失败)" +
"\n" +
JSON.stringify(e) +
"\n";
}
});
dky.on("dky:networkSituation", (e) => {
if (e.state == "networkDisconnected") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (网络断开)" +
"\n" +
JSON.stringify(e) +
"\n";
} else if (e.state == "networkConnected") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (网络连接/恢复)" +
"\n" +
JSON.stringify(e) +
"\n";
}
});
dky.on("dky:serviceLevel", (e) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (满意度)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:chanspy", (e) => {
if (e.mode == 0) {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (监听/咨询 - 耳语模式)" +
"\n" +
JSON.stringify(e) +
"\n";
}
if (e.mode == 1) {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (监听/咨询 - 静音模式)" +
"\n" +
JSON.stringify(e) +
"\n";
}
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (监听 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
}
});
dky.on("dky:meet", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询三方 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询三方)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:atxfer", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询转接)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:forceOffline", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (强制下线 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (强制下线)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:realTimeData", (e) => {
if (e.state == "error") {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (通话数据 - 错误)" +
"\n" +
JSON.stringify(e) +
"\n";
return;
}
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (通话数据)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:consult", (e) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (咨询)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:networkSituation", (e) => {
console.log("监听网络断开", e);
});
dky.on("dky:agentState", (e) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (座席状态)" +
"\n" +
JSON.stringify(e) +
"\n";
});
dky.on("dky:deviceDetection", (e) => {
contentInfo.value =
contentInfo.value +
"\n" +
getCurrentTimes() +
" (媒体设备)" +
"\n" +
JSON.stringify(e) +
"\n";
});
}
//处理挂断后的整理状态
function processSortout(time) {
info.innerHTML = "通话结束";
info.style.color = "red";
processCountdown(time);
timer = setInterval(() => {
info.innerHTML = "整理中...";
info.style.color = "yellow";
time = parseInt(time - 1);
sortOut.innerHTML = processCountdown(time);
if (time == 0) {
clearInterval(timer);
timer = null;
info.innerHTML = "空闲中...";
info.style.color = "#67C23A";
sortOut.innerHTML = "";
}
}, 1000);
}
//获取当前时间
function getCurrentTimes(type) {
let date = new Date();
let year = date.getFullYear();
let month =
date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth();
let days = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
let h = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
let m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
let s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
let ms =
date.getMilliseconds() > 9
? date.getMilliseconds() > 99
? date.getMilliseconds()
: "0" + date.getMilliseconds()
: "00" + date.getMilliseconds();
return ( year + "-" + month + "-" + days + " " + h + ":" + m + ":" + s + ":" + ms );
}
//处理整理的倒计时
function processCountdown(time) {
let s = time % 60,
m = parseInt(time / 60);
if (m >= 60) {
h = parseInt(m / 60);
m = m % 60;
} else {
h = parseInt(m / 60);
}
if (time >= 0 && time < 10) {
return "0" + h + ":" + "0" + m + ":" + "0" + s;
} else if (time >= 10 && time < 60) {
return "0" + h + ":" + "0" + m + ":" + s;
} else {
if (s >= 0 && s < 10 && m >= 0 && m < 10 && h >= 0 && h < 10) {
return "0" + h + ":" + "0" + m + ":" + "0" + s;
} else if (s >= 10 && s < 60 && m >= 0 && m < 10 && h >= 0 && h < 10) {
return "0" + h + ":" + "0" + m + ":" + s;
} else if (s >= 0 && s < 10 && m >= 10 && m < 60 && h >= 0 && h < 10) {
return "0" + h + ":" + m + ":" + "0" + s;
} else if (s >= 10 && s < 60 && m >= 10 && m < 60 && h >= 0 && h < 10) {
return "0" + h + ":" + m + ":" + s;
} else if (s >= 0 && s < 10 && m >= 0 && m < 10 && h >= 10 && h < 60) {
return h + ":" + "0" + m + ":" + "0" + s;
} else if (s >= 0 && s < 10 && m >= 10 && m < 0 && h >= 10 && h < 60) {
return h + ":" + m + ":" + "0" + s;
} else if (s >= 10 && s < 60 && m >= 10 && m < 0 && h >= 10 && h < 60) {
return h + ":" + m + ":" + s;
}
}
}
SIP 响应码
1xx
100 Trying 说明caller正在呼叫,但还没联系上callee。
180 Ringing 说明callee已经被联系上,callee的铃正在响.收到这个信息后,等待200 OK
181 Call is being forwarded 说明call被重新路由到另外一个目的地
182 Queued 说明callee当前是不可获得的,但是对方不想直接拒绝呼叫,而是选择放在呼叫队列中
183 Session progress 用来警告caller频段(inband)错误。当从PSTN收到一个ISDN消息,SIP gateway 产生183 Session progress 。
2xx
200 OK
3xx
300 Multiple choices 说明呼叫的地址被解析成多个地址,所有的地址都被提供出来,用户或用户代理可以从中选择联系哪个。
301 Moved permanently 说明指定地址的用户已经永远不可用,在头中已经用另外一个地址替换了.
302 Moved temporarily 说明指定地址的用户临时不可用,在头中已经用另外一个地址代替了.
305 Use proxy 说明caller必须用一个proxy来联系callee.
380 Alternative service 说明call不成功,但是可选择其他的服务
4xx
400 Bad Request 说明由于非法格式,请求不能被理解。
401 Unauthorized 说明请求需要用户认证。
402 Payment required 说明完成会话需要付费.
403 Forbidden 说明server已经收到并能理解请求但不提供服务。
404 Not Found 说明server有明确的信息在指定的域中用户不存在.
405 Method Not Allowed 说明请求中指定的方法是不被允许的。将返回一个允许的方法列表。
406 Not Acceptable 说明被请求的资源只对某些特殊的请求作出响应,对目前头(header)中指定的请求不接受.
407 Proxy authentication required 和401 Unauthorized response相似.但是,它说明client必须首先在proxy上认证自己。
408 Request timeout 说明在timeout时间过期前,server不能产生响应.
409 Conflict 说明由于和当前资源状态产生冲突,请求不能被处理。
410 Gone 说明请求资源在server上永远不可用,也没有转发的地址。
411 Length required 说明用户拒绝接受没有定义content长度的请求。
413 Request entity too large 说明server拒绝处理请求,因为它太大,超过了server能处理的大小。
414 Request-URI too long 说明server拒绝处理请求,因为请求的URI太长,server不能解释它。
415 Unsupported media 说明server拒绝处理请求,因为body格式不被目的终端支持
420 Bad extension 说明server不能理解在header中指出的扩展协议。
480 Temporarily unavailable 说明callee已经被联系上,但是暂时不可用。
481 Call leg/transaction does not exist 说明server正在忽略请求,由于它是一个没有匹配legID的BYE或 者是一个没有匹配事务的CANCEL。
482 Loop detected 说明server收到了一个包含它自己路径的请求.
483 Too many hops 说明server收到了一个请求,它需要的hop数超过了在header中允许的最大hop数.
484 Address incomplete 说明server收到一个地址不完整的请求.
485 Ambiguous 说明server收到一个请求,其中callee的地址是不明确的,也没有可能备用的地址供选择。
486 Busy here 说明callee已经被联系上,但是它们的系统不能承受额外的call.
487 呼叫被终止
488 (暂时不能进行)。
5xx
500 Server internal error 说明server或gateway发生意外错误从而不能处理请求.
501 Not implemented 说明server或gateway不支持完成请求所需的功能.
502 Bad gateway 说明server或gateway从下游server收到一个非法响应.
503 Service unavailable 说明由于超负载或维护问题,server或gateway不能处理请求.
504 Gateway timeout 说明server或gateway没有从另外一个server(如location server)收到一个及时的响应.
505 Version not supported 说明server或gateway不支持在请求中用到的SIP版本。
6xx
600 Busy everywhere 说明callee已经被联系上,但是处于忙状态中,在这个时间不能接受call。
603 Decline 说明callee已经被联系上,但是不能或不想加入call。
604 Does not exist anywhere 说明server有正式的信息说明callee不存在于网络中。
606 Not acceptable 说明callee已经被联系上,但是session描述的某些方面不被接受。