# voice9-sdk

Voice9 WebRTC 坐席 SDK —— 面向呼叫中心座席的浏览器端实时通信 SDK。

基于 WebRTC / Janus / WebSocket 实现，纯前端，无需安装插件。支持语音通话、转接、咨询、多方会议、班长监控（监听/强插/辅导）、DTMF、静音/保持、视频通话、随路数据等呼叫中心核心能力。

## 特性

- 🎧 语音通话（外呼 / 内呼 / 来电应答）
- 🔄 转接：普通转接、盲转
- 💬 咨询：发起咨询、取消咨询、结束咨询、咨询转接、转多方会议
- 👥 班长监控：监听、取消监听、强拆、强插、辅导
- 🎵 通话控制：静音/取消静音、保持/取消保持、DTMF 按键、视频通话
- 📦 随路数据：外呼随路、通话随路数据更新、自定义消息
- 🔌 多接听方式：WebRTC / SIP 分机 / 手机号
- ♻️ 断线自动重连

## 安装

### npm

```bash
npm install voice9
```

### CDN

```html
<script src="https://unpkg.com/voice9"></script>
<!-- 或 -->
<script src="https://cdn.jsdelivr.net/npm/voice9"></script>
<!-- 指定版本 -->
<script src="https://cdn.jsdelivr.net/npm/voice9@3.0.0"></script>
```

## 快速开始

### 1. 引入 SDK

**浏览器（script 标签）**

```html
<script src="voice9.sdk.min.js"></script>
```

**ES Module**

```js
import Voice9 from 'voice9';
```

### 2. 登录

登录需要先通过服务端接口换取登录凭证（token），再用凭证初始化 SDK：

```html
<audio id="peerVideo" autoplay style="visibility:hidden"></audio>
<audio id="remoteVideo" autoplay style="visibility:hidden"></audio>
```

```js
var voice9 = new Voice9();

// 服务端登录换取 token（示例，按实际服务端接口调整）
fetch('/fs-api/index/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        agentKey: '1001@test',
        agentCode: '',
        passwd: sha256('12345678'),
        loginType: 2,        // 1=sip号 2=webrtc 3=手机号
        workType: 1,         // 1=普通 2=预测
        loginState: 'READY'  // 登录后状态：READY=空闲 NOT_READY=忙碌
    })
})
    .then(function (res) { return res.json(); })
    .then(function (res) {
        if (res.code !== 0) { throw new Error(res.message); }
        voice9.init(res.data);
    });
```

### 3. 监听事件

```js
// 所有服务端消息都会通过 message 事件派发
voice9.addEventListener('message', function (data) {
    console.log('type:', data.type, 'code:', data.code, 'data:', data.data);
});

voice9.addEventListener('logout', function () {
    console.log('已断开连接');
});
```

### 4. 常用操作

```js
voice9.setReady();                    // 置空闲
voice9.setNotReady();                 // 置忙碌
voice9.makeCall('13300001234');       // 外呼
voice9.makeCall('13300001234', { followData: { key: 'value' } }); // 外呼（带随路数据）
voice9.acceptCall();                  // 应答
voice9.hangupCall();                  // 挂机
voice9.sendDtmf('1234');              // 发送 DTMF
voice9.mutePhone();                   // 静音
voice9.muteCancel();                  // 取消静音
voice9.holdTalking();                 // 保持
voice9.holdCancel();                  // 取消保持
voice9.logout();                      // 退出登录
```

## API 参考

| 方法 | 说明 |
| --- | --- |
| `init(data)` | 使用服务端返回的登录凭证初始化 SDK |
| `logout()` | 退出登录 |
| `setReady()` / `setNotReady()` / `setBusy()` | 置空闲 / 置忙碌 |
| `setWorkNotReady(desc)` | 自定义忙碌（可传原因描述） |
| `makeCall(telNum, options)` | 外呼，`options.followData` 可传随路数据 |
| `makeCallByFollowData(followData)` | 按随路数据外呼 |
| `acceptCall()` | 应答来电 |
| `hangupCall()` | 挂机 / 取消监听 |
| `sendDtmf(code)` | 发送 DTMF 按键 |
| `startVideo()` | 开启对方视频 |
| `phoneTransfer(telNum)` | 转接 |
| `phoneBlindTransfer(telNum)` | 盲转 |
| `phoneConsult(telNum)` | 发起咨询 |
| `phoneConsultCancel()` | 取消咨询 |
| `phoneConsultStop()` | 结束咨询 |
| `phoneConsultTransfer(telNum)` | 咨询转接 |
| `phoneConsultParty()` | 转多方会议 |
| `conferenceRemove(agentKey, callId)` | 从会议中移除成员 |
| `mutePhone()` / `muteCancel()` | 静音 / 取消静音 |
| `holdTalking()` / `holdCancel()` | 保持 / 取消保持 |
| `monitorCall(agentKey, callId)` | 监听（班长） |
| `interceptCall()` | 强拆（班长） |
| `bargeCall(agentKey, callId)` | 强插（班长） |
| `coachCall(agentKey, callId)` | 辅导（班长） |
| `updateCallFollowData(...)` | 更新通话随路数据 |
| `customMessage(data)` | 发送自定义消息 |
| `checkWebrtcSupport()` | 检测是否支持 WebRTC 拨打（含麦克风授权状态，异步） |
| `on(event, callback)` / `addEventListener(event, callback)` | 注册事件监听 |
| `off(event, callback)` | 移除事件监听 |

### 事件

| 事件 | 说明 |
| --- | --- |
| `message` | 所有服务端推送消息（含状态变更），`data.type` 为状态类型 |
| `logout` | 连接断开 / 退出登录 |

`message` 事件中 `data.type` 常见取值：`LOGIN`、`LOGOUT`、`READY`、`NOT_READY`、`OUT_CALL`、`OUT_CALLER_RING`、`OUT_CALLED_RING`、`INBOUND_RING`、`TALKING`、`HOLD_TALKING`、`MUTE_TALKING`、`TRANSFER`、`CONSULT`、`CONFERENCE_TALKING` 等。

## 本地开发

直接运行 Demo 联调：

1. `npm install` 安装依赖
2. `npm run build` 编译生成 `lib/voice9.sdk.min.js`
3. 直接用浏览器打开 `demo.html`，填入坐席账号并登录即可联调（需可访问的 Voice9 服务端）

## 目录结构

```
voice9-sdk
├── src/                    # SDK 源码
│   ├── voice9.sdk.js       # 入口（ES Module）
│   └── static/             # 依赖（janus.js / worker-module.js 等）
├── lib/                   # 构建产物（npm run build 生成）
│   └── voice9.sdk.min.js   # 压缩版 UMD 包（浏览器 / npm 通用）
├── demo.html               # 集成测试 Demo
├── rollup.config.js        # Rollup 构建配置
└── package.json
```

## 编译与发布

### 编译

```bash
npm run build
```

基于 Rollup 将 `src/voice9.sdk.js` 打包成 UMD 格式并压缩，输出到 `lib/voice9.sdk.min.js`（同时通过 `__SDK_VERSION__` 占位符注入版本号）。

### 推送到 npm

```bash
# 1. 登录 npm（仅首次需要）
npm login

# 2. 更新版本号（patch / minor / major，会自动改 package.json 并打 git tag）
npm version patch

# 3. 发布（prepublishOnly 会自动执行 npm run build，只打包 files 字段指定的 lib 目录）
npm publish
```

发布后可验证：

```bash
npm view voice9 version        # 查看最新版本
npm view voice9                # 查看包信息
```

发布内容：`lib/voice9.sdk.min.js`，同时支持 `import Voice9 from 'voice9'`、CDN `<script>` 标签（全局变量 `Voice9`）两种引用方式。

## License

MIT
