customer-chat-sdk
v1.4.8
Published
Customer Service SDK - One-line integration for customer support chat
Maintainers
Readme
CustomerSDK 使用文档
简介
CustomerSDK 是一个轻量级的客服 SDK,提供图标管理和截图功能。适用于需要自行管理弹窗组件的项目场景。
特性
- ✅ 悬浮图标 - 可拖动的悬浮图标,支持侧边吸附和磁性吸附
- ✅ 截图功能 - 自动截图、压缩、上传
- ✅ 设备识别 - 自动获取设备指纹 ID
- ✅ 通知提醒 - 支持数字和文本通知徽章
- ✅ 无 iframe - 不包含 iframe 管理,由项目自行实现弹窗
安装
npm install customer-chat-sdk
# 或
pnpm add customer-chat-sdk
# 或
yarn add customer-chat-sdk快速开始
基础用法
import { CustomerSDK } from 'customer-chat-sdk'
// 创建 SDK 实例
const sdk = new CustomerSDK()
// 初始化(返回初始化结果,包含设备ID等)
const initResult = await sdk.init({
debug: true, // 开发环境开启
iconPosition: { x: 20, y: 80 },
target: '#app'
})
console.log('Device ID:', initResult.deviceId)
// 设置图标点击回调
sdk.onIconClick(() => {
// 打开您的弹窗组件
openChatPopup()
})完整示例(Vue 3)
<template>
<div id="app">
<ChatPopup
ref="chatPopupRef"
v-model:visible="chatVisible"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { CustomerSDK } from 'customer-chat-sdk'
const chatVisible = ref(false)
const chatPopupRef = ref()
let sdk: CustomerSDK | null = null
onMounted(async () => {
sdk = new CustomerSDK()
const initResult = await sdk.init({
debug: true,
screenshot: {
engine: 'modern-screenshot',
quality: 0.15,
compress: true,
interval: 5000
},
iconPosition: { x: 20, y: 80 },
target: '#app',
sideAttach: true,
magnetic: true
}, {
sendData: (data) => {
// 处理截图数据
chatPopupRef.value?.handleScreenshotData(data)
}
})
// 获取设备ID等信息
console.log('Device ID:', initResult.deviceId)
console.log('Referrer:', initResult.referrer)
// 图标点击打开弹窗
sdk.onIconClick(async () => {
chatVisible.value = true
// 启用截图
const config = await fetchScreenshotConfig()
if (config) {
sdk?.triggerScreenshotConfig(JSON.stringify(config))
}
})
})
onUnmounted(() => {
sdk?.destroy()
})
</script>React 示例
import { useEffect, useRef, useState } from 'react'
import { CustomerSDK } from 'customer-chat-sdk'
function App() {
const [chatVisible, setChatVisible] = useState(false)
const sdkRef = useRef<CustomerSDK | null>(null)
useEffect(() => {
const sdk = new CustomerSDK()
sdkRef.current = sdk
sdk.init({
debug: true,
screenshot: {
engine: 'modern-screenshot',
quality: 0.15,
compress: true
},
iconPosition: { x: 20, y: 80 },
target: '#app'
}, {
sendData: (data) => {
// 发送截图数据到后端
fetch('/api/upload-screenshot', {
method: 'POST',
headers: { 'Content-Type': 'application/octet-stream' },
body: data.data
})
}
}).then((initResult) => {
// 获取设备ID等信息
console.log('Device ID:', initResult.deviceId)
sdk.onIconClick(async () => {
setChatVisible(true)
const config = await fetchScreenshotConfig()
if (config) {
sdk.triggerScreenshotConfig(JSON.stringify(config))
}
})
})
return () => {
sdk.destroy()
}
}, [])
return <div id="app">...</div>
}API 文档
CustomerSDK 类
构造函数
const sdk = new CustomerSDK()init(config, screenshotCallback?)
初始化 SDK
const initResult = await sdk.init(config, screenshotCallback?)返回值:
返回 InitResult 对象,包含:
deviceId: string- 设备ID(md5后的)referrer: string- 页面来源agent?: string- 代理商ID(如果配置了)timestamp: number- 初始化时间戳
参数:
config: SDKConfig- SDK 配置screenshotCallback?: ScreenshotMessageCallback- 截图回调(可选)
配置选项:
interface SDKConfig {
debug?: boolean // 调试模式
screenshot?: ScreenshotOptions // 截图配置
iconPosition?: { // 图标位置
x?: number | string
y?: number | string
}
target?: HTMLElement | string // 图标挂载目标
sideAttach?: boolean // 侧边吸附(默认 true)
sideHideRatio?: number // 侧边隐藏比例(默认 0.5)
magnetic?: boolean // 磁性吸附(默认 true)
magneticDirection?: 'x' | 'y' | 'both' // 磁性方向(默认 'x')
margin?: number // 边距(默认 10px)
autoAttachDelay?: number // 自动吸附延迟(默认 3000ms)
referrer?: string // 页面来源
agent?: string // 代理商ID
token?: string // 认证令牌
}截图配置:
interface ScreenshotOptions {
engine?: 'modern-screenshot' | 'snapdom' | 'html2canvas'
quality?: number // 0-1,默认 0.15
compress?: boolean // 是否压缩
interval?: number // 默认间隔(毫秒)
maxWidth?: number // 最大宽度
maxHeight?: number // 最大高度
outputFormat?: 'webp' | 'jpeg' | 'png'
enableCORS?: boolean // 启用 CORS
proxyUrl?: string // 代理 URL
corsMode?: 'simple' | 'smart' | 'proxy' | 'blob' | 'canvas-proxy'
debug?: boolean // 截图调试
}截图回调:
interface ScreenshotMessageCallback {
sendData?: (data: {
type: 'screenshotBinary'
data: ArrayBuffer
}) => void
onConfig?: (config: string) => void
}onIconClick(callback)
设置图标点击回调(也可以在 init 中配置)
// 方式1: 使用函数式 API(default 导出)- 可以直接调用
const CustomerSDK = await import('customer-chat-sdk')
await CustomerSDK.default.init(config)
CustomerSDK.default.onIconClick(() => {
openChatPopup()
})
// 方式2: 使用类(命名导出)- 在 init 中配置(推荐)
const sdk = new CustomerSDK()
await sdk.init(config, screenshotCallback, {
onIconClick: () => {
openChatPopup()
}
})
// 方式3: 使用类(命名导出)- 单独设置
const sdk = new CustomerSDK()
await sdk.init(config)
sdk.onIconClick(() => {
openChatPopup()
})updateToken(token, screenshotCallback?, initCallback?)
更新 token(用于用户登录/退出场景)
// 更新 token(会自动重新初始化)
await sdk.updateToken('new-token')
// 更新 token 并更新回调
await sdk.updateToken('new-token', {
sendData: (data) => { /* ... */ }
}, {
onIconClick: () => { /* ... */ }
})showNotification(badgeCount, options?)
显示通知
sdk.showNotification(5, { pulse: true, autoHide: 5000 })
sdk.showNotification('新', { pulse: true })clearNotification()
清除通知
sdk.clearNotification()triggerScreenshotConfig(configJson)
启用/停止截图
// 启用截图
const config = {
agent: 'your-agent-id',
sign: 'your-sign',
type: 1,
topic: 'screenshot',
routingKey: 'route-key',
ttl: Date.now() + 3600000, // 1小时后过期
duration: 5000 // 5秒间隔
}
sdk.triggerScreenshotConfig(JSON.stringify(config))
// 停止截图
sdk.triggerScreenshotConfig(JSON.stringify({
...config,
ttl: 0 // 禁用
}))showIcon() / hideIcon()
显示/隐藏图标
sdk.showIcon()
sdk.hideIcon()getDeviceId()
获取设备ID(md5后的)
const deviceId = sdk.getDeviceId()
console.log('Device ID:', deviceId)getInitResult()
获取初始化结果(包含设备ID等信息)
const initResult = sdk.getInitResult()
if (initResult) {
console.log('Device ID:', initResult.deviceId)
console.log('Referrer:', initResult.referrer)
console.log('Timestamp:', initResult.timestamp)
}getScreenshotManager() / getIconManager()
获取管理器实例(用于高级操作)
const screenshotManager = sdk.getScreenshotManager()
const iconManager = sdk.getIconManager()destroy()
销毁 SDK
sdk.destroy()完整工作流程
1. 初始化
const sdk = new CustomerSDK()
const initResult = await sdk.init({
debug: true,
screenshot: { /* ... */ },
iconPosition: { x: 20, y: 80 },
target: '#app'
}, {
// 截图回调
sendData: (data) => {
// 处理截图数据
}
}, {
// 初始化回调(图标点击)
onIconClick: async () => {
openChatPopup()
// 启用截图
const config = await fetchScreenshotConfig()
if (config) {
sdk.triggerScreenshotConfig(JSON.stringify(config))
}
}
})
// 获取设备ID等信息
console.log('Device ID:', initResult.deviceId)
console.log('Referrer:', initResult.referrer)2. 弹窗打开时启用截图
// 方式1: 在 init 中配置(推荐)
await sdk.init(config, screenshotCallback, {
onIconClick: async () => {
openChatPopup()
const config = await fetchScreenshotConfig()
sdk.triggerScreenshotConfig(JSON.stringify(config))
}
})
// 方式2: 单独设置
sdk.onIconClick(async () => {
openChatPopup()
const config = await fetchScreenshotConfig()
sdk.triggerScreenshotConfig(JSON.stringify(config))
})2.1. 更新 token
// 用户登录后更新 token
await sdk.updateToken('new-token')3. 弹窗关闭时停止截图
function closeChatPopup() {
closePopup()
sdk.triggerScreenshotConfig(JSON.stringify({
...config,
ttl: 0
}))
}4. 清理
onUnmounted(() => {
sdk?.destroy()
})常见场景
只使用图标功能
const sdk = new CustomerSDK()
await sdk.init({
debug: true,
iconPosition: { x: 20, y: 80 },
target: '#app'
})
sdk.onIconClick(() => {
openChatPopup()
})图标 + 截图
const sdk = new CustomerSDK()
await sdk.init({
screenshot: {
engine: 'modern-screenshot',
quality: 0.15,
compress: true
}
}, {
sendData: (data) => {
sendToBackend(data)
}
})注意事项
- 调试模式:生产环境请关闭
debug: true - 截图性能:合理设置截图间隔,避免过于频繁
- 内存管理:及时调用
destroy()清理资源 - 错误处理:所有异步操作都应添加错误处理
- CORS 问题:如果遇到跨域问题,配置
proxyUrl或调整corsMode
动态导入示例
方式 1: 使用类(推荐)
const initCustomerSDK = async () => {
// 动态导入
const mod = await import('customer-chat-sdk')
// 获取 CustomerSDK 类(命名导出)
const { CustomerSDK } = mod
// ✅ 重要:必须先实例化
const sdk = new CustomerSDK()
// 初始化(调用实例方法)
const initResult = await sdk.init({
debug: true,
iconPosition: { x: 20, y: 80 },
target: '#app'
}, {
sendData: (data) => {
// 处理截图数据
}
})
// 设置图标点击回调(调用实例方法)
sdk.onIconClick(() => {
openChatPopup()
})
return sdk
}方式 2: 使用函数式 API(default 导出)
const initCustomerSDK = async () => {
// 动态导入
const mod = await import('customer-chat-sdk')
// 获取 default 导出(函数式 API)
const SDK = mod.default
// ✅ 直接调用函数(不需要实例化)
const initResult = await SDK.init({
debug: true,
iconPosition: { x: 20, y: 80 },
target: '#app'
})
// 使用其他函数式 API
SDK.showIcon()
SDK.showNotification(5)
return SDK
}注意:函数式 API 使用全局单例,只能有一个实例。如果需要多个实例或更好的类型支持,推荐使用类的方式。
兼容性动态导入(自动检测)
const initCustomerSDK = async () => {
const mod = await import('customer-chat-sdk')
// 优先使用类的方式(推荐)
if (mod.CustomerSDK && typeof mod.CustomerSDK === 'function') {
const sdk = new mod.CustomerSDK()
await sdk.init({ /* ... */ })
sdk.onIconClick(() => { /* ... */ })
return sdk
}
// 回退到函数式 API
if (mod.default && mod.default.init) {
const SDK = mod.default
await SDK.init({ /* ... */ })
SDK.showIcon()
return SDK
}
throw new Error('CustomerSDK 未找到')
}类型定义
import type {
CustomerSDK,
ScreenshotMessageCallback,
SDKConfig,
ScreenshotOptions,
InitResult
} from 'customer-chat-sdk'许可证
MIT
