joytalk 0.0.1
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/README.md +640 -0
- package/dist/apis/index.d.ts +24 -0
- package/dist/apis/request.d.ts +2 -0
- package/dist/index.cjs.js +6 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.es.js +2297 -0
- package/dist/index.umd.js +6 -0
- package/dist/lib/index.d.ts +121 -0
- package/dist/lib/modules/api-client.d.ts +12 -0
- package/dist/lib/modules/connection-manager.d.ts +74 -0
- package/dist/lib/modules/faq-manager.d.ts +23 -0
- package/dist/lib/modules/file-uploader.d.ts +29 -0
- package/dist/lib/modules/message-handler.d.ts +62 -0
- package/dist/lib/modules/user-manager.d.ts +25 -0
- package/dist/main.d.ts +1 -0
- package/dist/types/index.d.ts +77 -0
- package/dist/types/message.d.ts +316 -0
- package/dist/types/request.d.ts +91 -0
- package/dist/utils/event-emitter.d.ts +30 -0
- package/dist/utils/http-handler.d.ts +2 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
# 客服 SDK
|
|
2
|
+
|
|
3
|
+
一个功能完善的客服 SDK,用于在项目中快速集成客服功能。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- ✅ TypeScript 支持
|
|
8
|
+
- ✅ 自动重连机制
|
|
9
|
+
- ✅ 心跳机制
|
|
10
|
+
- ✅ 事件驱动架构
|
|
11
|
+
- ✅ 支持多种消息类型(文本、图片、视频、文件、FAQ)
|
|
12
|
+
- ✅ 完整的类型定义
|
|
13
|
+
- ✅ 支持 CommonJS 和 ES Module
|
|
14
|
+
- ✅ 使用 Vite 构建,快速高效
|
|
15
|
+
- ✅ 文件上传支持
|
|
16
|
+
- ✅ 视频缩略图生成
|
|
17
|
+
|
|
18
|
+
## 安装
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install joytalk
|
|
22
|
+
# 或
|
|
23
|
+
yarn add joytalk
|
|
24
|
+
# 或
|
|
25
|
+
pnpm add joytalk
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 快速开始
|
|
29
|
+
|
|
30
|
+
### 基本使用
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import JoyTalk, { EventType, ChatType, MessageCode } from 'joytalk';
|
|
34
|
+
|
|
35
|
+
// 创建 SDK 实例
|
|
36
|
+
const sdk = new JoyTalk({
|
|
37
|
+
token: 'your-token',
|
|
38
|
+
autoReconnect: true,
|
|
39
|
+
reconnectInterval: 3000,
|
|
40
|
+
maxReconnectAttempts: 5,
|
|
41
|
+
heartbeatTimeout: 10000,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 监听连接事件
|
|
45
|
+
sdk.on(EventType.CONNECTED, () => {
|
|
46
|
+
console.log('已连接到服务器');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// 监听消息事件
|
|
50
|
+
sdk.on(EventType.MESSAGE, (message) => {
|
|
51
|
+
console.log('收到消息:', message);
|
|
52
|
+
|
|
53
|
+
// 根据消息类型处理
|
|
54
|
+
switch (message.code) {
|
|
55
|
+
case MessageCode.SEND_SUCCESS:
|
|
56
|
+
console.log('消息发送成功:', message.data);
|
|
57
|
+
break;
|
|
58
|
+
case MessageCode.MATCH_SUCCESS:
|
|
59
|
+
console.log('匹配成功:', message.data);
|
|
60
|
+
break;
|
|
61
|
+
// ... 其他消息类型
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// 监听错误事件
|
|
66
|
+
sdk.on(EventType.ERROR, (error) => {
|
|
67
|
+
console.error('发生错误:', error);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// 监听状态变化
|
|
71
|
+
sdk.on(EventType.STATUS_CHANGE, (status) => {
|
|
72
|
+
console.log('连接状态变化:', status);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// 连接到服务器(需要传入客户组ID)
|
|
76
|
+
await sdk.connect('customer-group-id');
|
|
77
|
+
|
|
78
|
+
// 发送文本消息
|
|
79
|
+
await sdk.sendText('你好,我需要帮助');
|
|
80
|
+
|
|
81
|
+
// 发送图片消息
|
|
82
|
+
const fileInput = document.querySelector('input[type="file"]') as HTMLInputElement;
|
|
83
|
+
const file = fileInput.files?.[0];
|
|
84
|
+
if (file) {
|
|
85
|
+
await sdk.sendFile({
|
|
86
|
+
file,
|
|
87
|
+
chatType: ChatType.IMAGE,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 发送视频消息(自动生成缩略图)
|
|
92
|
+
const videoFile = fileInput.files?.[0];
|
|
93
|
+
if (videoFile) {
|
|
94
|
+
const thumbnailFile = await sdk.getVideoThumbnail(videoFile);
|
|
95
|
+
await sdk.sendFile({
|
|
96
|
+
file: videoFile,
|
|
97
|
+
thumbnailFile,
|
|
98
|
+
chatType: ChatType.VIDEO,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 获取用户信息
|
|
103
|
+
const userInfo = await sdk.getUserInfo();
|
|
104
|
+
console.log('用户信息:', userInfo);
|
|
105
|
+
|
|
106
|
+
// 获取咨询列表
|
|
107
|
+
const consultationList = await sdk.getConsultationList(entranceId);
|
|
108
|
+
console.log('咨询列表:', consultationList);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 在 Vue 项目中使用
|
|
112
|
+
|
|
113
|
+
```vue
|
|
114
|
+
<template>
|
|
115
|
+
<div>
|
|
116
|
+
<input type="file" @change="handleFileChange" />
|
|
117
|
+
<button @click="sendText">发送文本</button>
|
|
118
|
+
</div>
|
|
119
|
+
</template>
|
|
120
|
+
|
|
121
|
+
<script setup lang="ts">
|
|
122
|
+
import { onMounted, onUnmounted } from 'vue';
|
|
123
|
+
import JoyTalk, { EventType, ChatType } from 'joytalk';
|
|
124
|
+
|
|
125
|
+
const sdk = new JoyTalk({
|
|
126
|
+
token: 'your-token',
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
onMounted(() => {
|
|
130
|
+
sdk.on(EventType.MESSAGE, (message) => {
|
|
131
|
+
console.log('收到消息:', message);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
sdk.connect('customer-group-id');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
onUnmounted(() => {
|
|
138
|
+
sdk.disconnect();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const sendText = async () => {
|
|
142
|
+
await sdk.sendText('Hello');
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const handleFileChange = async (e: Event) => {
|
|
146
|
+
const file = (e.target as HTMLInputElement).files?.[0];
|
|
147
|
+
if (file) {
|
|
148
|
+
await sdk.sendFile({
|
|
149
|
+
file,
|
|
150
|
+
chatType: ChatType.IMAGE,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
</script>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### CDN 引入方式
|
|
158
|
+
|
|
159
|
+
通过 CDN 方式引入 SDK,适合在 HTML 页面中直接使用。
|
|
160
|
+
|
|
161
|
+
#### 简化示例
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<!DOCTYPE html>
|
|
165
|
+
<html lang="zh-CN">
|
|
166
|
+
<head>
|
|
167
|
+
<meta charset="UTF-8">
|
|
168
|
+
<title>客服 SDK 简化示例</title>
|
|
169
|
+
<script src="https://your-cdn.com/joytalk/dist/index.umd.js"></script>
|
|
170
|
+
</head>
|
|
171
|
+
<body>
|
|
172
|
+
<script>
|
|
173
|
+
const JoyTalk = window.JoyTalk.default;
|
|
174
|
+
const { EventType, ChatType } = window.JoyTalk;
|
|
175
|
+
|
|
176
|
+
const sdk = new JoyTalk({ token: 'your-token' });
|
|
177
|
+
|
|
178
|
+
sdk.on(EventType.CONNECTED, () => {
|
|
179
|
+
console.log('连接成功');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
sdk.on(EventType.MESSAGE, (message) => {
|
|
183
|
+
console.log('收到消息:', message);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// 连接并发送消息
|
|
187
|
+
sdk.connect('customer-group-id').then(() => {
|
|
188
|
+
sdk.sendText('你好');
|
|
189
|
+
});
|
|
190
|
+
</script>
|
|
191
|
+
</body>
|
|
192
|
+
</html>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### 完整示例
|
|
196
|
+
|
|
197
|
+
```html
|
|
198
|
+
<!DOCTYPE html>
|
|
199
|
+
<html lang="zh-CN">
|
|
200
|
+
<head>
|
|
201
|
+
<meta charset="UTF-8">
|
|
202
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
203
|
+
<title>客服 SDK 示例</title>
|
|
204
|
+
<!-- 引入 SDK -->
|
|
205
|
+
<script src="https://your-cdn.com/joytalk/dist/index.umd.js"></script>
|
|
206
|
+
</head>
|
|
207
|
+
<body>
|
|
208
|
+
<div id="app">
|
|
209
|
+
<button id="connectBtn">连接</button>
|
|
210
|
+
<button id="sendBtn">发送消息</button>
|
|
211
|
+
<input type="file" id="fileInput" accept="image/*,video/*" />
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<script>
|
|
215
|
+
// 从全局变量中获取 SDK 类和枚举
|
|
216
|
+
// 注意:JoyTalk 是默认导出,其他枚举和类型是命名导出
|
|
217
|
+
const JoyTalk = window.JoyTalk.default;
|
|
218
|
+
const { EventType, ChatType, MessageCode, ConnectionStatus, MessageType } = window.JoyTalk;
|
|
219
|
+
|
|
220
|
+
// 创建 SDK 实例
|
|
221
|
+
const sdk = new JoyTalk({
|
|
222
|
+
token: 'your-token',
|
|
223
|
+
autoReconnect: true,
|
|
224
|
+
reconnectInterval: 3000,
|
|
225
|
+
maxReconnectAttempts: 5,
|
|
226
|
+
heartbeatTimeout: 10000,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// 监听连接事件
|
|
230
|
+
sdk.on(EventType.CONNECTED, () => {
|
|
231
|
+
console.log('已连接到服务器');
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// 监听消息事件
|
|
235
|
+
sdk.on(EventType.MESSAGE, (message) => {
|
|
236
|
+
console.log('收到消息:', message);
|
|
237
|
+
|
|
238
|
+
// 根据消息类型处理
|
|
239
|
+
switch (message.code) {
|
|
240
|
+
case MessageCode.SEND_SUCCESS:
|
|
241
|
+
console.log('消息发送成功:', message.data);
|
|
242
|
+
break;
|
|
243
|
+
case MessageCode.MATCH_SUCCESS:
|
|
244
|
+
console.log('匹配成功:', message.data);
|
|
245
|
+
break;
|
|
246
|
+
// ... 其他消息类型
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// 监听错误事件
|
|
251
|
+
sdk.on(EventType.ERROR, (error) => {
|
|
252
|
+
console.error('发生错误:', error);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// 监听状态变化
|
|
256
|
+
sdk.on(EventType.STATUS_CHANGE, (status) => {
|
|
257
|
+
console.log('连接状态变化:', status);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// 连接按钮
|
|
261
|
+
document.getElementById('connectBtn').addEventListener('click', async () => {
|
|
262
|
+
try {
|
|
263
|
+
await sdk.connect('customer-group-id');
|
|
264
|
+
console.log('连接成功');
|
|
265
|
+
} catch (error) {
|
|
266
|
+
console.error('连接失败:', error);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// 发送消息按钮
|
|
271
|
+
document.getElementById('sendBtn').addEventListener('click', async () => {
|
|
272
|
+
try {
|
|
273
|
+
await sdk.sendText('你好,我需要帮助');
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error('发送失败:', error);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// 文件上传
|
|
280
|
+
document.getElementById('fileInput').addEventListener('change', async (e) => {
|
|
281
|
+
const file = e.target.files[0];
|
|
282
|
+
if (!file) return;
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
if (file.type.startsWith('image/')) {
|
|
286
|
+
// 发送图片
|
|
287
|
+
await sdk.sendFile({
|
|
288
|
+
file: file,
|
|
289
|
+
chatType: ChatType.IMAGE,
|
|
290
|
+
});
|
|
291
|
+
} else if (file.type.startsWith('video/')) {
|
|
292
|
+
// 发送视频(自动生成缩略图)
|
|
293
|
+
const thumbnailFile = await sdk.getVideoThumbnail(file);
|
|
294
|
+
await sdk.sendFile({
|
|
295
|
+
file: file,
|
|
296
|
+
thumbnailFile: thumbnailFile,
|
|
297
|
+
chatType: ChatType.VIDEO,
|
|
298
|
+
});
|
|
299
|
+
} else {
|
|
300
|
+
// 发送文件
|
|
301
|
+
await sdk.sendFile({
|
|
302
|
+
file: file,
|
|
303
|
+
chatType: ChatType.FILE,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
console.log('文件发送成功');
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.error('文件发送失败:', error);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// 获取用户信息示例
|
|
313
|
+
async function loadUserInfo() {
|
|
314
|
+
try {
|
|
315
|
+
const userInfo = await sdk.getUserInfo();
|
|
316
|
+
console.log('用户信息:', userInfo);
|
|
317
|
+
// 可以在页面上显示用户信息
|
|
318
|
+
// document.getElementById('userName').textContent = userInfo.nickname;
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error('获取用户信息失败:', error);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// 获取咨询列表示例
|
|
325
|
+
async function loadConsultationList(entranceId) {
|
|
326
|
+
try {
|
|
327
|
+
const result = await sdk.getConsultationList(entranceId);
|
|
328
|
+
console.log('咨询列表:', result.data.list);
|
|
329
|
+
// 可以在页面上显示咨询列表
|
|
330
|
+
} catch (error) {
|
|
331
|
+
console.error('获取咨询列表失败:', error);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// 页面加载完成后可以调用
|
|
336
|
+
// loadUserInfo();
|
|
337
|
+
// loadConsultationList(123);
|
|
338
|
+
</script>
|
|
339
|
+
</body>
|
|
340
|
+
</html>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**CDN 地址说明:**
|
|
344
|
+
- 将 `https://your-cdn.com/joytalk/dist/index.umd.js` 替换为实际的 CDN 地址
|
|
345
|
+
- 如果使用本地构建文件,可以使用相对路径:`<script src="./dist/index.umd.js"></script>`
|
|
346
|
+
- 建议使用版本号锁定,如:`https://cdn.example.com/joytalk@0.0.1/dist/index.umd.js`
|
|
347
|
+
|
|
348
|
+
**注意事项:**
|
|
349
|
+
- CDN 引入后,SDK 会挂载到 `window.JoyTalk` 全局对象上
|
|
350
|
+
- 默认导出(`default`)是 `JoyTalk` 类,通过 `window.JoyTalk.default` 访问
|
|
351
|
+
- 所有枚举和类型都可以从 `window.JoyTalk` 中获取,如 `EventType`、`ChatType`、`MessageCode`、`ConnectionStatus`、`MessageType` 等
|
|
352
|
+
- 确保 CDN 地址可访问,并且版本正确
|
|
353
|
+
- 如果页面中已经使用了模块化构建工具(如 Webpack、Vite),建议使用 NPM 安装方式而不是 CDN
|
|
354
|
+
|
|
355
|
+
### 配置选项
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
interface SDKConfig {
|
|
359
|
+
/** 认证令牌(必需) */
|
|
360
|
+
token: string;
|
|
361
|
+
/** 自动重连(默认: true) */
|
|
362
|
+
autoReconnect?: boolean;
|
|
363
|
+
/** 重连间隔(毫秒,默认: 3000) */
|
|
364
|
+
reconnectInterval?: number;
|
|
365
|
+
/** 最大重连次数(默认: 5) */
|
|
366
|
+
maxReconnectAttempts?: number;
|
|
367
|
+
/** 心跳超时时间(毫秒,默认: 10000) */
|
|
368
|
+
heartbeatTimeout?: number;
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### 事件类型
|
|
373
|
+
|
|
374
|
+
- `EventType.CONNECTED` - 连接成功
|
|
375
|
+
- `EventType.DISCONNECTED` - 连接断开
|
|
376
|
+
- `EventType.ERROR` - 发生错误
|
|
377
|
+
- `EventType.MESSAGE` - 收到消息
|
|
378
|
+
- `EventType.STATUS_CHANGE` - 连接状态变化
|
|
379
|
+
- `EventType.HEARTBEAT_TIMEOUT` - 心跳超时
|
|
380
|
+
|
|
381
|
+
### 消息类型
|
|
382
|
+
|
|
383
|
+
- `ChatType.TEXT` - 文本消息
|
|
384
|
+
- `ChatType.IMAGE` - 图片消息
|
|
385
|
+
- `ChatType.VIDEO` - 视频消息
|
|
386
|
+
- `ChatType.FILE` - 文件消息
|
|
387
|
+
- `ChatType.FAQ` - FAQ 消息
|
|
388
|
+
|
|
389
|
+
### 连接状态
|
|
390
|
+
|
|
391
|
+
- `ConnectionStatus.DISCONNECTED` - 未连接
|
|
392
|
+
- `ConnectionStatus.CONNECTING` - 连接中
|
|
393
|
+
- `ConnectionStatus.CONNECTED` - 已连接
|
|
394
|
+
- `ConnectionStatus.RECONNECTING` - 重连中
|
|
395
|
+
- `ConnectionStatus.ERROR` - 错误
|
|
396
|
+
|
|
397
|
+
## API 方法
|
|
398
|
+
|
|
399
|
+
### 连接管理
|
|
400
|
+
|
|
401
|
+
#### `connect(customerGroupId: string): Promise<void>`
|
|
402
|
+
连接到服务器
|
|
403
|
+
|
|
404
|
+
**参数:**
|
|
405
|
+
- `customerGroupId` - 客户组ID
|
|
406
|
+
|
|
407
|
+
**示例:**
|
|
408
|
+
```typescript
|
|
409
|
+
await sdk.connect('customer-group-id');
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### `disconnect(): void`
|
|
413
|
+
断开连接
|
|
414
|
+
|
|
415
|
+
**示例:**
|
|
416
|
+
```typescript
|
|
417
|
+
sdk.disconnect();
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### `getStatus(): ConnectionStatus`
|
|
421
|
+
获取当前连接状态
|
|
422
|
+
|
|
423
|
+
**返回值:** `ConnectionStatus` 枚举值
|
|
424
|
+
|
|
425
|
+
#### `isConnected(): boolean`
|
|
426
|
+
检查是否已连接
|
|
427
|
+
|
|
428
|
+
**返回值:** `boolean`
|
|
429
|
+
|
|
430
|
+
### 消息发送
|
|
431
|
+
|
|
432
|
+
#### `sendText(content: string): Promise<boolean>`
|
|
433
|
+
发送文本消息
|
|
434
|
+
|
|
435
|
+
**参数:**
|
|
436
|
+
- `content` - 消息内容
|
|
437
|
+
|
|
438
|
+
**示例:**
|
|
439
|
+
```typescript
|
|
440
|
+
await sdk.sendText('你好');
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
#### `sendFile(params): Promise<string>`
|
|
444
|
+
发送文件消息(图片、视频、文件)
|
|
445
|
+
|
|
446
|
+
**参数:**
|
|
447
|
+
```typescript
|
|
448
|
+
{
|
|
449
|
+
file: File; // 文件对象
|
|
450
|
+
thumbnailFile?: File; // 缩略图文件(可选,用于视频)
|
|
451
|
+
chatType: ChatType.IMAGE | ChatType.VIDEO | ChatType.FILE;
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**返回值:** `Promise<string>` - 返回文件信息的 JSON 字符串
|
|
456
|
+
|
|
457
|
+
**示例:**
|
|
458
|
+
```typescript
|
|
459
|
+
// 发送图片
|
|
460
|
+
await sdk.sendFile({
|
|
461
|
+
file: imageFile,
|
|
462
|
+
chatType: ChatType.IMAGE,
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// 发送视频(带缩略图)
|
|
466
|
+
const thumbnailFile = await sdk.getVideoThumbnail(videoFile);
|
|
467
|
+
await sdk.sendFile({
|
|
468
|
+
file: videoFile,
|
|
469
|
+
thumbnailFile,
|
|
470
|
+
chatType: ChatType.VIDEO,
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// 发送文件
|
|
474
|
+
await sdk.sendFile({
|
|
475
|
+
file: documentFile,
|
|
476
|
+
chatType: ChatType.FILE,
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
#### `sendFaq(faqItem: FaqItem): void`
|
|
481
|
+
发送 FAQ 消息
|
|
482
|
+
|
|
483
|
+
**参数:**
|
|
484
|
+
- `faqItem` - FAQ 项对象
|
|
485
|
+
|
|
486
|
+
**示例:**
|
|
487
|
+
```typescript
|
|
488
|
+
sdk.sendFaq({
|
|
489
|
+
faqId: 1,
|
|
490
|
+
question: '常见问题',
|
|
491
|
+
item: [...],
|
|
492
|
+
isMulti: false,
|
|
493
|
+
});
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### 文件处理
|
|
497
|
+
|
|
498
|
+
#### `getVideoThumbnail(videoFile: File): Promise<File>`
|
|
499
|
+
获取视频文件的首帧作为缩略图
|
|
500
|
+
|
|
501
|
+
**参数:**
|
|
502
|
+
- `videoFile` - 视频文件对象
|
|
503
|
+
|
|
504
|
+
**返回值:** `Promise<File>` - 返回首帧图片的 File 对象
|
|
505
|
+
|
|
506
|
+
**示例:**
|
|
507
|
+
```typescript
|
|
508
|
+
const thumbnailFile = await sdk.getVideoThumbnail(videoFile);
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### 用户信息
|
|
512
|
+
|
|
513
|
+
#### `getUserInfo(): Promise<UserInfo>`
|
|
514
|
+
获取用户信息
|
|
515
|
+
|
|
516
|
+
**返回值:** `Promise<UserInfo>` - 用户信息对象
|
|
517
|
+
|
|
518
|
+
**示例:**
|
|
519
|
+
```typescript
|
|
520
|
+
const userInfo = await sdk.getUserInfo();
|
|
521
|
+
console.log(userInfo.nickname, userInfo.avatar);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### API 调用
|
|
525
|
+
|
|
526
|
+
#### `getConsultationList(entranceId: number)`
|
|
527
|
+
获取咨询列表
|
|
528
|
+
|
|
529
|
+
**参数:**
|
|
530
|
+
- `entranceId` - 入口ID
|
|
531
|
+
|
|
532
|
+
**返回值:** `Promise<ConsultationListResponse>`
|
|
533
|
+
|
|
534
|
+
**示例:**
|
|
535
|
+
```typescript
|
|
536
|
+
const result = await sdk.getConsultationList(123);
|
|
537
|
+
console.log(result.data.list);
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### 事件监听
|
|
541
|
+
|
|
542
|
+
#### `on(event: EventType, callback: EventCallback): void`
|
|
543
|
+
监听事件
|
|
544
|
+
|
|
545
|
+
**示例:**
|
|
546
|
+
```typescript
|
|
547
|
+
sdk.on(EventType.MESSAGE, (message) => {
|
|
548
|
+
console.log('收到消息:', message);
|
|
549
|
+
});
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
#### `off(event: EventType, callback: EventCallback): void`
|
|
553
|
+
取消监听事件
|
|
554
|
+
|
|
555
|
+
**示例:**
|
|
556
|
+
```typescript
|
|
557
|
+
const handler = (message) => console.log(message);
|
|
558
|
+
sdk.on(EventType.MESSAGE, handler);
|
|
559
|
+
sdk.off(EventType.MESSAGE, handler);
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### 公共属性
|
|
563
|
+
|
|
564
|
+
#### `OBS_URL: string`
|
|
565
|
+
OBS 存储地址(只读)
|
|
566
|
+
|
|
567
|
+
#### `userInfo: UserInfo | null`
|
|
568
|
+
当前用户信息(只读)
|
|
569
|
+
|
|
570
|
+
## 类型定义
|
|
571
|
+
|
|
572
|
+
SDK 提供了完整的 TypeScript 类型定义,包括:
|
|
573
|
+
|
|
574
|
+
- `MessageData` - 消息数据
|
|
575
|
+
- `TextMessageData` - 文本消息数据
|
|
576
|
+
- `FileMessageData` - 文件消息数据
|
|
577
|
+
- `FaqMessageData` - FAQ 消息数据
|
|
578
|
+
- `SessionData` - 会话数据
|
|
579
|
+
- `UserInfo` - 用户信息
|
|
580
|
+
- `ChatType` - 聊天类型枚举
|
|
581
|
+
- `MessageType` - 消息类型枚举
|
|
582
|
+
- `EventType` - 事件类型枚举
|
|
583
|
+
- `ConnectionStatus` - 连接状态枚举
|
|
584
|
+
- `MessageCode` - 消息代码枚举
|
|
585
|
+
|
|
586
|
+
## 消息处理示例
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
import JoyTalk, { EventType, MessageCode, ChatType } from 'joytalk';
|
|
590
|
+
|
|
591
|
+
const sdk = new JoyTalk({ token: 'your-token' });
|
|
592
|
+
|
|
593
|
+
sdk.on(EventType.MESSAGE, (message) => {
|
|
594
|
+
switch (message.code) {
|
|
595
|
+
case MessageCode.SEND_SUCCESS:
|
|
596
|
+
// 消息发送成功
|
|
597
|
+
const messageData = message.data;
|
|
598
|
+
if (messageData.contentType === ChatType.TEXT) {
|
|
599
|
+
console.log('文本消息:', messageData.content);
|
|
600
|
+
} else if (messageData.contentType === ChatType.IMAGE) {
|
|
601
|
+
console.log('图片消息:', messageData.content.fileUrl);
|
|
602
|
+
}
|
|
603
|
+
break;
|
|
604
|
+
|
|
605
|
+
case MessageCode.MATCH_SUCCESS:
|
|
606
|
+
// 匹配成功
|
|
607
|
+
const sessionData = message.data;
|
|
608
|
+
console.log('会话ID:', sessionData.sessionId);
|
|
609
|
+
break;
|
|
610
|
+
|
|
611
|
+
case MessageCode.CONNECT_SUCCESS:
|
|
612
|
+
console.log('连接成功');
|
|
613
|
+
break;
|
|
614
|
+
|
|
615
|
+
// ... 其他消息类型
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
## 开发
|
|
621
|
+
|
|
622
|
+
```bash
|
|
623
|
+
# 安装依赖
|
|
624
|
+
npm install
|
|
625
|
+
# 或
|
|
626
|
+
pnpm install
|
|
627
|
+
|
|
628
|
+
# 构建
|
|
629
|
+
npm run build
|
|
630
|
+
|
|
631
|
+
# 开发模式(监听文件变化)
|
|
632
|
+
npm run dev
|
|
633
|
+
|
|
634
|
+
# 类型检查
|
|
635
|
+
npm run type-check
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
## 许可证
|
|
639
|
+
|
|
640
|
+
ISC
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ObsAuthInfo, ConsultationListResponse, RequestResponse, UserAuthParams, AnonymousAuthParams, FaqListResponse, UserInfo } from '../types';
|
|
2
|
+
export declare const getObsAuthInfo: (params: {
|
|
3
|
+
ext: string;
|
|
4
|
+
}) => Promise<RequestResponse<ObsAuthInfo>>;
|
|
5
|
+
export declare const uploadFile: (formData: FormData) => Promise<any>;
|
|
6
|
+
/**
|
|
7
|
+
* 获取咨询列表
|
|
8
|
+
* @returns Promise<ConsultationListResponse>
|
|
9
|
+
*/
|
|
10
|
+
export declare const fetchConsultationList: (params: {
|
|
11
|
+
entranceId: number;
|
|
12
|
+
}) => Promise<RequestResponse<ConsultationListResponse>>;
|
|
13
|
+
/**
|
|
14
|
+
* 登录用户认证
|
|
15
|
+
*/
|
|
16
|
+
export declare const userAuth: (params: UserAuthParams) => Promise<RequestResponse<any>>;
|
|
17
|
+
/**
|
|
18
|
+
* 匿名用户认证
|
|
19
|
+
*/
|
|
20
|
+
export declare const anonymousAuth: (params: AnonymousAuthParams) => Promise<RequestResponse<any>>;
|
|
21
|
+
export declare const fetchFaqList: (params: {
|
|
22
|
+
id: string;
|
|
23
|
+
}) => Promise<RequestResponse<FaqListResponse>>;
|
|
24
|
+
export declare const fetchUserInfo: () => Promise<RequestResponse<UserInfo>>;
|