sipCallPhoneDialog.md 6.8 KB

SipCallPhoneDialog 一键外呼组件(公共组件)

文件:@/components/sipCall/sipCallPhoneDialog.vue
本文档面向业务页面接入,参数统一使用 sip 前缀,避免与调用页本地字段冲突。


1. 能力概览

打开弹窗后按步骤执行:

  1. 解析号码:加密号解密 / 或直接使用明文号
  2. 选择线路:展示可用网关列表,必须选择并确认后才会继续
  3. 连接座席(IPCC):按所选线路获取 token 并连接
  4. 注册分机(JsSIP)
  5. 发起外呼
  6. 挂断后:延迟 5 秒同步通话记录,并做防重复同步

高频安全点:

  • 初始化/确认线路/拨号有互斥锁,避免连点重复发起
  • 通话中不可点遮罩关闭;关闭时会取消初始化并清理连接
  • 同一 uuid 同步使用队列 + syncedUuids / syncingUuids 去重,不会重复同步

2. Props(全部 sip 前缀)

Prop(模板写法) 类型 必填 默认 说明
sip-visible.sync Boolean false 弹窗显隐。必须 .sync,对应事件 update:sipVisible
sip-encrypted-phone String 否* '' 加密手机号。与明文二选一,优先使用加密号
sip-plain-phone String 否* '' 明文手机号。无加密号时使用,会跳过解密步骤
sip-dial-type String 'audio' 'audio' / 'video'
sip-record-id String/Number '' 业务关联 ID(如订单号)。挂断后通过事件回传

* sipEncryptedPhonesipPlainPhone 至少传一个,否则无法拨号。


3. Events

事件名 参数 说明
update:sipVisible Boolean 弹窗关闭/打开时触发(.sync 自动处理)
sip-call-ended sipRecordId 通话结束后触发,回传业务 ID

4. 推荐接入示例(问诊详情 / 业务页)

<template>
  <div>
    <el-button type="text" @click="openSipCall">拨号</el-button>

    <!--
      关键接入约定:
      1) 所有绑定字段使用 sip 前缀,避免和页面 phone/visible/recordId 冲突
      2) 高频场景加 sipOpening / sipVisible 防重复点击
      3) 有加密号优先传 sip-encrypted-phone;医生端常见明文则传 sip-plain-phone
    -->
    <call-phone-dialog
      :sip-visible.sync="sipVisible"
      :sip-encrypted-phone="sipEncryptedPhone"
      :sip-plain-phone="sipPlainPhone"
      :sip-dial-type="sipDialType"
      :sip-record-id="sipRecordId"
      @sip-call-ended="onSipCallEnded"
    />
  </div>
</template>

<script>
import CallPhoneDialog from '@/components/sipCall/sipCallPhoneDialog.vue'

export default {
  components: { CallPhoneDialog },
  data() {
    return {
      sipVisible: false,
      sipEncryptedPhone: '',
      sipPlainPhone: '',
      sipDialType: 'audio',
      sipRecordId: '',
      sipOpening: false
    }
  },
  methods: {
    /**
     * 打开一键外呼
     * @param {Object} payload
     * @param {string} [payload.encryptedPhone] 加密号码
     * @param {string} [payload.plainPhone] 明文号码
     * @param {string|number} [payload.recordId] 业务 ID(订单/客户等)
     */
    async openSipCall(payload = {}) {
      // 防重复:弹窗已开或正在准备中
      if (this.sipOpening || this.sipVisible) {
        this.$message.warning('外呼进行中,请勿重复点击')
        return
      }
      const encryptedPhone = payload.encryptedPhone || ''
      const plainPhone = payload.plainPhone || ''
      const recordId = payload.recordId
      if (!encryptedPhone && !plainPhone) {
        this.$message.warning('无可用号码')
        return
      }

      this.sipOpening = true
      try {
        this.sipEncryptedPhone = encryptedPhone
        this.sipPlainPhone = plainPhone
        this.sipRecordId = recordId == null ? '' : recordId
        this.sipDialType = 'audio'
        this.sipVisible = true
      } finally {
        this.sipOpening = false
      }
    },

    onSipCallEnded(recordId) {
      // 可在此刷新通话记录列表、更新订单状态等
      console.log('[业务页] 外呼结束, recordId=', recordId)
    }
  }
}
</script>

问诊详情页当前接入方式

<call-phone-dialog
  :sip-visible.sync="sipVisible"
  :sip-plain-phone="sipPlainPhone"
  :sip-record-id="sipRecordId"
  @sip-call-ended="onSipCallEnded"
/>

点击「拨号」时:

  1. 防重复点击
  2. 优先请求 getOrderUserPhone(orderId) 获取号码,失败则回退页面展示号
  3. 写入 sipPlainPhone / sipRecordId 后打开弹窗
  4. 弹窗内选择线路后才会继续连接 IPCC 并外呼

5. 线路选择说明

  • 号码解析成功后进入「选择线路」步骤
  • 线路卡片展示名称、主叫号、线路类型标签(手机/固话)
  • 未选择并确认前不会连接 IPCC / 注册分机 / 外呼
  • 点击「确认线路并外呼」后,使用所选 gatewayId 作为 myGateway 请求工具条参数并连接

6. 挂断与同步(5 秒 / 防重 / 同步后再关窗)

挂断后流程:

  1. 本地立即结束通话 UI,进入「等待同步」状态(禁止手动关闭弹窗
  2. uuid 规范化后放入同步队列(全局 + 会话去重,避免高频重复同步)
  3. 延迟 5 秒再调用 callEndSyncByUuid(等待后端生成话单)
  4. 失败最多重试 2 次;重复/不存在类错误视为已处理
  5. 无论同步成功或失败,都进入短倒计时后自动关闭窗口
  6. 同步完成前:遮罩点击、Esc、右上角关闭均不可提前关掉

7. 前置条件与注意事项

  1. 当前登录医生需已绑定 SIP 分机(外呼配置页)
  2. 首次使用需授权浏览器麦克风
  3. 加密号场景需配置环境变量 VUE_APP_SIP_PHONE_ENCRYPT_PRIVATE_KEY
  4. 明文号场景请确认业务允许(注意隐私合规)
  5. 通话中请通过弹窗内「挂断」结束;强制关页会尽量兜底同步
  6. 请勿在业务页再定义同名 visible / phone / recordId 去绑定本组件,统一用 sip* 字段

8. 常见问题

现象 可能原因 处理
提示未查询到分机号 未做外呼配置绑定 到「外呼信息 → 外呼配置」绑定分机/线路
提示暂无可用线路 网关列表为空 检查 remoteGateWayList / 工具条网关配置
解密失败 传了明文却走加密流程,或私钥缺失 明文用 sip-plain-phone;加密用 sip-encrypted-phone
重复点击无反应/提示进行中 防重锁生效 等当前弹窗结束再拨
记录未同步 挂断后不足 5 秒刷新、或 uuid 为空 等待同步完成;检查挂断事件是否产出 uuid

9. 版本约定

  • Props / Events 以 sip 前缀为准(旧的 visible / encryptedPhone / recordId / call-ended 已废弃)
  • 同步延迟:5s
  • 自动关闭倒计时:5s