246 行
4.9 KiB
Markdown
246 行
4.9 KiB
Markdown
|
|
# XuqmGroup React Native SDK 文档
|
|||
|
|
|
|||
|
|
> TypeScript · React Native 0.76+ · 发布至 Nexus npm
|
|||
|
|
|
|||
|
|
## 安装
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# .npmrc 已配置私有 registry,直接安装
|
|||
|
|
npm install @xuqm/rn-sdk
|
|||
|
|
# 或
|
|||
|
|
yarn add @xuqm/rn-sdk
|
|||
|
|
|
|||
|
|
# 依赖安装(peerDependencies)
|
|||
|
|
npm install @react-native-async-storage/async-storage
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 目录结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
XuqmGroup-RNSDK/src/
|
|||
|
|
├── core/
|
|||
|
|
│ ├── http.ts # fetch HTTP 客户端,AsyncStorage Token
|
|||
|
|
│ └── sdk.ts # XuqmSDK 初始化入口
|
|||
|
|
├── im/
|
|||
|
|
│ └── imClient.ts # WebSocket IM 客户端,指数退避重连
|
|||
|
|
├── push/
|
|||
|
|
│ └── pushSDK.ts # 推送 Token 注册
|
|||
|
|
├── update/
|
|||
|
|
│ └── updateSDK.ts # 检查更新 / 下载 Bundle
|
|||
|
|
└── index.ts # 统一导出
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 快速开始
|
|||
|
|
|
|||
|
|
### 1. 初始化(App 入口)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { XuqmSDK } from '@xuqm/rn-sdk'
|
|||
|
|
|
|||
|
|
await XuqmSDK.init({
|
|||
|
|
appKey: 'ak_your_app_key',
|
|||
|
|
debug: __DEV__,
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 用户登录后设置 Token
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
await XuqmSDK.setToken('eyJ...')
|
|||
|
|
// 登出时
|
|||
|
|
await XuqmSDK.setToken(null)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Token 持久化存储于 `AsyncStorage`,App 重启后自动恢复。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## HTTP 客户端
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { http } from '@xuqm/rn-sdk'
|
|||
|
|
|
|||
|
|
// 自动附加 Bearer Token
|
|||
|
|
const data = await http.get<UserInfo>('/api/user/profile')
|
|||
|
|
const result = await http.post<LoginResp>('/api/auth/login', { account, password })
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## IM 模块
|
|||
|
|
|
|||
|
|
### ImClient
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { ImClient, MsgType, ChatType } from '@xuqm/rn-sdk'
|
|||
|
|
|
|||
|
|
const im = new ImClient()
|
|||
|
|
|
|||
|
|
im.on('connected', () => console.log('IM 已连接'))
|
|||
|
|
im.on('disconnected', (code, reason) => console.log('断开', code))
|
|||
|
|
im.on('message', (msg) => {
|
|||
|
|
console.log('新消息', msg.content)
|
|||
|
|
// msg: ImMessage
|
|||
|
|
})
|
|||
|
|
im.on('revoke', ({ msgId, operatorId }) => {
|
|||
|
|
console.log('消息被撤回', msgId)
|
|||
|
|
})
|
|||
|
|
im.on('error', (err) => console.error(err))
|
|||
|
|
|
|||
|
|
// 连接
|
|||
|
|
im.connect()
|
|||
|
|
|
|||
|
|
// 发送消息
|
|||
|
|
im.send({
|
|||
|
|
toId: 'user_002',
|
|||
|
|
chatType: ChatType.SINGLE,
|
|||
|
|
msgType: MsgType.TEXT,
|
|||
|
|
content: 'Hello from RN!',
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 撤回
|
|||
|
|
im.revoke('msg-uuid')
|
|||
|
|
|
|||
|
|
// 组件卸载时断开
|
|||
|
|
useEffect(() => {
|
|||
|
|
im.connect()
|
|||
|
|
return () => im.disconnect()
|
|||
|
|
}, [])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### React Hook 封装示例
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { useEffect, useState, useRef } from 'react'
|
|||
|
|
import { ImClient, ImMessage } from '@xuqm/rn-sdk'
|
|||
|
|
|
|||
|
|
export function useIm() {
|
|||
|
|
const [messages, setMessages] = useState<ImMessage[]>([])
|
|||
|
|
const [connected, setConnected] = useState(false)
|
|||
|
|
const imRef = useRef<ImClient | null>(null)
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
const im = new ImClient()
|
|||
|
|
imRef.current = im
|
|||
|
|
im.on('connected', () => setConnected(true))
|
|||
|
|
im.on('disconnected', () => setConnected(false))
|
|||
|
|
im.on('message', (msg) => setMessages(prev => [...prev, msg]))
|
|||
|
|
im.connect()
|
|||
|
|
return () => im.disconnect()
|
|||
|
|
}, [])
|
|||
|
|
|
|||
|
|
const send = (params: Parameters<ImClient['send']>[0]) =>
|
|||
|
|
imRef.current?.send(params)
|
|||
|
|
|
|||
|
|
return { messages, connected, send }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ImMessage 结构
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface ImMessage {
|
|||
|
|
id: string
|
|||
|
|
fromId: string
|
|||
|
|
toId: string
|
|||
|
|
chatType: 'SINGLE' | 'GROUP'
|
|||
|
|
msgType: MsgType
|
|||
|
|
content: string
|
|||
|
|
extra?: string
|
|||
|
|
revoked: boolean
|
|||
|
|
createdAt: string
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 消息类型(MsgType)
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
enum MsgType {
|
|||
|
|
TEXT = 'TEXT',
|
|||
|
|
IMAGE = 'IMAGE',
|
|||
|
|
VIDEO = 'VIDEO',
|
|||
|
|
AUDIO = 'AUDIO',
|
|||
|
|
FILE = 'FILE',
|
|||
|
|
CUSTOM = 'CUSTOM',
|
|||
|
|
LOCATION = 'LOCATION',
|
|||
|
|
NOTIFY = 'NOTIFY',
|
|||
|
|
RICH_TEXT = 'RICH_TEXT',
|
|||
|
|
CALL_AUDIO = 'CALL_AUDIO',
|
|||
|
|
CALL_VIDEO = 'CALL_VIDEO',
|
|||
|
|
FORWARD = 'FORWARD',
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 自动重连
|
|||
|
|
|
|||
|
|
断线后指数退避重连:3s → 6s → 12s → ... → 最大 30s。调用 `disconnect()` 后停止。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 推送模块
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { PushSDK } from '@xuqm/rn-sdk'
|
|||
|
|
|
|||
|
|
// 在获取到设备推送 Token 后调用(如小米、华为推送回调)
|
|||
|
|
await PushSDK.registerToken({
|
|||
|
|
appId: 'ak_xxx',
|
|||
|
|
userId: 'user_001',
|
|||
|
|
vendor: 'XIAOMI', // HUAWEI / XIAOMI / OPPO / VIVO / HONOR / APNS
|
|||
|
|
token: 'device_push_token',
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 版本管理模块
|
|||
|
|
|
|||
|
|
### 检查 App 更新
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { UpdateSDK } from '@xuqm/rn-sdk'
|
|||
|
|
|
|||
|
|
const result = await UpdateSDK.checkAppUpdate({
|
|||
|
|
appId: 'ak_xxx',
|
|||
|
|
platform: 'android', // 'android' | 'ios'
|
|||
|
|
currentVersionCode: 10,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if (result.needsUpdate) {
|
|||
|
|
console.log(result.versionName, result.downloadUrl, result.forceUpdate)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 检查 RN Bundle 热更新
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const rnResult = await UpdateSDK.checkRnUpdate({
|
|||
|
|
appId: 'ak_xxx',
|
|||
|
|
moduleId: 'main',
|
|||
|
|
platform: 'android',
|
|||
|
|
currentVersion: '1.0.0',
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if (rnResult.needsUpdate && rnResult.info) {
|
|||
|
|
const { downloadUrl, md5 } = rnResult.info
|
|||
|
|
// 下载 bundle,校验 md5,调用原生模块热加载
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 发版
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 确认 .npmrc 指向 https://nexus.xuqinmin.com/repository/npm-hosted/
|
|||
|
|
# 登录 Nexus npm(首次)
|
|||
|
|
npm login --registry=https://nexus.xuqinmin.com/repository/npm-hosted/
|
|||
|
|
|
|||
|
|
# 发版
|
|||
|
|
npm publish
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
版本号在 `package.json` 的 `version` 字段维护。
|