docs: 添加 CLAUDE.md + 各 package README + 架构总览 + 模块待开发说明
Agent 8 文档生成: - CLAUDE.md 项目上下文 - 各 package README (common/update/push/im/xwebview/license/log) - docs/架构总览.md - docs/模块待开发说明.md
这个提交包含在:
父节点
16750b0421
当前提交
4c3019edab
83
CLAUDE.md
83
CLAUDE.md
@ -2,84 +2,89 @@
|
||||
|
||||
## 项目定位
|
||||
|
||||
XuqmGroup React Native SDK monorepo。为集成宿主 App(如 YiwangxinApp4)提供核心能力:初始化、HTTP、设备信息、XWebView、OTA 更新、推送、IM、证书、**日志追踪**。
|
||||
XuqmGroup React Native SDK monorepo。为集成宿主 App(如 YiwangxinApp4)提供核心能力:初始化、HTTP、设备信息、XWebView、OTA 更新、推送、IM、证书、日志追踪。
|
||||
|
||||
- Git 远端:`ssh://git@xuqinmin.com:2222/`(以 `git remote -v` 实际结果为准)
|
||||
- Git 远端:`https://xuqinmin.com/xuqmGroup/XuqmGroup-RNSDK.git`
|
||||
- Nexus npm 发布:`https://nexus.xuqinmin.com/repository/npm-hosted/`
|
||||
- 规范文档:`XuqmGroup-Docs/design/06-sdk-cross-platform-spec.md`
|
||||
|
||||
## 包结构
|
||||
|
||||
| 包名 | 目录 | 当前版本 | 状态 |
|
||||
|------|------|----------|------|
|
||||
| `@xuqm/rn-common` | packages/common | 0.4.0 | 活跃开发 |
|
||||
| `@xuqm/rn-update` | packages/update | — | 活跃开发 |
|
||||
| `@xuqm/rn-xwebview` | packages/xwebview | — | 活跃开发 |
|
||||
| `@xuqm/rn-log` | packages/log | 0.1.0(新) | 新建中 |
|
||||
| `@xuqm/rn-push` | packages/push | — | 代码冻结(仅文档) |
|
||||
| `@xuqm/rn-im` | packages/im | — | 代码冻结(仅文档) |
|
||||
| `@xuqm/rn-license` | packages/license | — | 代码冻结(仅文档) |
|
||||
| 包名 | 目录 | 版本 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `@xuqm/rn-common` | packages/common | 0.4.0 | 核心层:初始化、HTTP、设备、XWebView Bridge、API hooks |
|
||||
| `@xuqm/rn-update` | packages/update | 0.4.0 | OTA 热更新、APK 更新 |
|
||||
| `@xuqm/rn-push` | packages/push | 0.2.2 | 厂商推送(代码冻结,仅文档) |
|
||||
| `@xuqm/rn-im` | packages/im | 0.2.2 | IM 会话、消息(代码冻结,仅文档) |
|
||||
| `@xuqm/rn-xwebview` | packages/xwebview | 0.2.2 | WebView 容器 + JSBridge UI 组件 |
|
||||
| `@xuqm/rn-license` | packages/license | 0.3.0 | 证书授权(代码冻结,仅文档) |
|
||||
| `@xuqm/rn-log` | packages/log | 0.1.0 | 日志、错误追踪、漏斗分析(新) |
|
||||
|
||||
**代码冻结模块(push/im/license):不修改代码,仅补充文档。**
|
||||
|
||||
## 技术约束
|
||||
## 技术栈
|
||||
|
||||
- **React Native ≥ 0.76**(Bridgeless Mode,New Architecture)
|
||||
- **TypeScript 5.x strict** — `noImplicitAny: true`,禁止 `any`
|
||||
- **向下兼容**:公开接口不删除不修改,新字段一律可选
|
||||
- **无静默降级**:autoInit 失败时 `__DEV__` 模式 throw,生产模式 console.error
|
||||
- React Native >= 0.76(Bridgeless Mode,New Architecture)
|
||||
- TypeScript 5.x strict — `noImplicitAny: true`,禁止 `any`
|
||||
- yarn workspaces monorepo
|
||||
- 发布到 Nexus npm 私有仓库
|
||||
|
||||
## 核心 API(@xuqm/rn-common)
|
||||
|
||||
### 初始化(两种方式,均不得修改签名)
|
||||
## 初始化(两种方式)
|
||||
|
||||
**方式 A — 配置文件自动初始化(推荐)**
|
||||
宿主配置 Babel alias `@xuqm/autoinit-config` → 加密配置文件。SDK 自动读取并初始化,App 代码无需调用任何 init。
|
||||
宿主配置 Babel alias `@xuqm/autoinit-config` → 加密配置文件(XUQM-CONFIG-V1 格式)。SDK 自动读取并初始化,App 无需调用任何 init。
|
||||
|
||||
**方式 B — 手动初始化**
|
||||
```ts
|
||||
// 仅传 appKey → 使用内置公有平台
|
||||
import { XuqmSDK } from '@xuqm/rn-common'
|
||||
|
||||
// 公有平台
|
||||
await XuqmSDK.initialize({ appKey: 'xxx' })
|
||||
|
||||
// 传 appKey + platformUrl → 使用指定私有化平台
|
||||
// 私有化平台
|
||||
await XuqmSDK.initialize({ appKey: 'xxx', platformUrl: 'https://xxx' })
|
||||
|
||||
// 等待异步平台配置拉取
|
||||
await XuqmSDK.awaitInitialization()
|
||||
```
|
||||
|
||||
**两种平台互相独立,不允许自动降级到默认公有平台。**
|
||||
**两种平台互相独立,不允许自动降级。**
|
||||
|
||||
## 用户信息
|
||||
|
||||
### 用户信息
|
||||
```ts
|
||||
XuqmSDK.setUserInfo({ userId: 'u001', userSig: 'sig', name: '张三' })
|
||||
XuqmSDK.setUserInfo(null) // 登出
|
||||
XuqmSDK.setUserInfo(null) // 登出,触发所有子 SDK 登出
|
||||
```
|
||||
|
||||
### 日志(@xuqm/rn-log)
|
||||
子 SDK 自动订阅 `setUserInfo` 事件:Push 自动注册/解绑 token,IM 自动登录/断开,Update 更新 userId。
|
||||
|
||||
## 日志 SDK(@xuqm/rn-log)
|
||||
|
||||
```ts
|
||||
import { XLog } from '@xuqm/rn-log' // 注意是 XLog 不是 Log
|
||||
import { XLog } from '@xuqm/rn-log'
|
||||
|
||||
XLog.setLogLevel('debug')
|
||||
XLog.setEnvironment('production')
|
||||
XLog.startCapture() // 开启全局错误捕获
|
||||
XLog.event('page_view', { page: 'home' })
|
||||
XLog.captureError(new Error('xxx'))
|
||||
XLog.defineFunnel('checkout', ['cart_view', 'checkout_start', 'payment_done'])
|
||||
```
|
||||
|
||||
`logApiUrl` 由 SDK 在 init 后从 `/api/sdk/config` 自动获取,无需 App 传入。
|
||||
|
||||
## 关键约束
|
||||
|
||||
- `XuqmSDK.initialize()` 签名不得更改
|
||||
- `XuqmSDK.setUserInfo()` 现有字段不得删除
|
||||
- 新增字段一律为可选,有合理默认值
|
||||
- 不允许静默降级(autoInit 失败时 `__DEV__` 模式 throw)
|
||||
- rn-common 与 rn-log 解耦:rn-common 可独立使用;rn-log peerDep rn-common
|
||||
|
||||
## XWebView JSBridge 标准 Handler
|
||||
|
||||
见 `docs/XWebView-JSBridge.md`(已有文档,以该文档为准)。
|
||||
|
||||
## 任务文档
|
||||
|
||||
开发前阅读 `/Users/xuqinmin/Projects/XuqmProjects/YiwangxinApp4/docs/agent-tasks/` 中对应的 agent 任务文件:
|
||||
|
||||
- Agent 2 任务:`agent2-rn-common.md`
|
||||
- Agent 3 任务:`agent3-rn-update-xwebview.md`
|
||||
- Agent 4 任务:`agent4-rn-log.md`
|
||||
- Agent 8 任务:`agent8-docs.md`
|
||||
见 `docs/XWebView-JSBridge.md`。
|
||||
|
||||
## 常用命令
|
||||
|
||||
@ -87,4 +92,8 @@ XLog.captureError(new Error('xxx'))
|
||||
yarn workspace @xuqm/rn-common typecheck
|
||||
yarn workspace @xuqm/rn-log typecheck
|
||||
yarn workspace @xuqm/rn-update typecheck
|
||||
yarn workspace @xuqm/rn-push typecheck
|
||||
yarn workspace @xuqm/rn-im typecheck
|
||||
yarn workspace @xuqm/rn-xwebview typecheck
|
||||
yarn workspace @xuqm/rn-license typecheck
|
||||
```
|
||||
|
||||
105
docs/架构总览.md
普通文件
105
docs/架构总览.md
普通文件
@ -0,0 +1,105 @@
|
||||
# XuqmGroup RN SDK 架构总览
|
||||
|
||||
## 整体架构
|
||||
|
||||
```
|
||||
宿主 App(YiwangxinApp4 等)
|
||||
└── 初始化(方式A: 配置文件自动 / 方式B: 手动 initialize)
|
||||
↓
|
||||
@xuqm/rn-common (核心层 v0.4.0)
|
||||
├── XuqmSDK.initialize() → 拉取 /api/sdk/config
|
||||
├── XuqmSDK.setUserInfo() → 通知所有子 SDK(订阅者模式)
|
||||
├── api/(useApi / usePageApi / apiRequest)
|
||||
├── device(设备信息 / 厂商检测)
|
||||
├── xwebview(JSBridge 桥接控制)
|
||||
├── ui/(toast / alert / confirm)
|
||||
└── logApiUrl / logEnabled(从平台配置获取)
|
||||
↓ peerDep / 依赖
|
||||
子 SDK(各自独立)
|
||||
├── @xuqm/rn-update → OTA 热更新 / APK 更新
|
||||
├── @xuqm/rn-push → 厂商推送(peerDep: rn-common)
|
||||
├── @xuqm/rn-im → IM 会话 / 消息(peerDep: rn-common)
|
||||
├── @xuqm/rn-xwebview → WebView UI 组件(peerDep: rn-common)
|
||||
├── @xuqm/rn-license → 证书授权(peerDep: rn-common)
|
||||
└── @xuqm/rn-log → 日志 / 追踪(peerDep: rn-common)
|
||||
```
|
||||
|
||||
## 依赖关系
|
||||
|
||||
```
|
||||
rn-common (核心,无 SDK 内部依赖)
|
||||
↑ peerDep
|
||||
├── rn-update (直接依赖 rn-common)
|
||||
├── rn-push (peerDep rn-common)
|
||||
├── rn-im (peerDep rn-common + watermelondb)
|
||||
├── rn-xwebview (peerDep rn-common + webview + navigation)
|
||||
├── rn-license (peerDep rn-common + quick-crypto)
|
||||
└── rn-log (peerDep rn-common)
|
||||
```
|
||||
|
||||
## 用户状态分发机制
|
||||
|
||||
```
|
||||
XuqmSDK.setUserInfo(info)
|
||||
├── PushSDK: 检测厂商 → 获取厂商配置 → 注册 token
|
||||
├── ImSDK: 若 userSig 存在且 imEnabled → 自动登录 WebSocket
|
||||
├── UpdateSDK: 更新 userId(用于定向更新)
|
||||
└── LicenseSDK: 更新用户上下文
|
||||
|
||||
XuqmSDK.setUserInfo(null)
|
||||
├── PushSDK: 解绑 token
|
||||
├── ImSDK: 断开 WebSocket
|
||||
└── 其他子 SDK: 清理用户状态
|
||||
```
|
||||
|
||||
各子 SDK 在模块加载时通过 `_registerUserInfoHandler()` 注册处理器,无需 App 手动协调。
|
||||
|
||||
## 初始化流程
|
||||
|
||||
### 方式 A(自动)
|
||||
|
||||
```
|
||||
Metro alias → @xuqm/autoinit-config → encrypted .xuqmconfig
|
||||
↓ import 时触发
|
||||
autoInit.ts → require('@xuqm/autoinit-config')
|
||||
↓ 解密(PBKDF2 + AES-256-GCM)
|
||||
initWithConfigFile() → initialize({ appKey, platformUrl })
|
||||
↓ HTTP GET
|
||||
/api/sdk/config → 返回 { apiUrl, imWsUrl, fileServiceUrl, ... }
|
||||
```
|
||||
|
||||
### 方式 B(手动)
|
||||
|
||||
```
|
||||
App 代码调用 XuqmSDK.initialize({ appKey })
|
||||
↓ HTTP GET
|
||||
/api/sdk/config → 解析平台配置
|
||||
↓
|
||||
各子 SDK 就绪(等待 setUserInfo 触发具体功能)
|
||||
```
|
||||
|
||||
## 数据流
|
||||
|
||||
```
|
||||
App 代码
|
||||
↓ 调用 API
|
||||
子 SDK(update/push/im/license/log)
|
||||
↓ 使用 apiRequest()
|
||||
rn-common http.ts
|
||||
↓ 附加 Bearer Token + 处理响应
|
||||
平台服务(tenant-service / im-service / push-service / update-service / log-service)
|
||||
```
|
||||
|
||||
## 包发布
|
||||
|
||||
所有包发布到 Nexus npm 私有仓库:`https://nexus.xuqinmin.com/repository/npm-hosted/`
|
||||
|
||||
```bash
|
||||
# 发布单个包
|
||||
cd packages/common && npm publish
|
||||
|
||||
# 发布所有包
|
||||
for pkg in common update push im xwebview license log; do
|
||||
cd packages/$pkg && npm publish && cd ../..
|
||||
done
|
||||
```
|
||||
85
docs/模块待开发说明.md
普通文件
85
docs/模块待开发说明.md
普通文件
@ -0,0 +1,85 @@
|
||||
# 模块待开发说明
|
||||
|
||||
> 以下模块当前代码冻结,仅补充文档。后续开发需单独评估。
|
||||
|
||||
---
|
||||
|
||||
## rn-push(厂商推送)
|
||||
|
||||
### 当前状态
|
||||
|
||||
- FCM/APNS 基础注册已实现
|
||||
- HMS/VIVO/OPPO 厂商推送集成框架已建
|
||||
- 自动厂商检测(通过原生模块 `NativePush`)
|
||||
- Token 注册/解绑 API 完整
|
||||
- 离线推送开关、免打扰时间段 API 已实现
|
||||
|
||||
### 后续待做
|
||||
|
||||
- 厂商推送 token 注册完整流程(华为 HMS 需要 AppGallery Connect 配置)
|
||||
- 设备绑定/解绑统一 API(当前分散在各厂商 SDK)
|
||||
- 角标管理(badge count 同步)
|
||||
- 厂商推送通道选择(高优先级 vs 普通通知)
|
||||
- 推送数据分析(到达率、点击率统计)
|
||||
|
||||
### 技术要点
|
||||
|
||||
- 原生模块 `XuqmPushModule` 需要在宿主 App 中链接
|
||||
- 各厂商 SDK 初始化需要对应的 App ID / App Secret
|
||||
- `setUserInfo(info)` 触发自动注册,`setUserInfo(null)` 触发自动解绑
|
||||
|
||||
---
|
||||
|
||||
## rn-im(即时通讯)
|
||||
|
||||
### 当前状态
|
||||
|
||||
- 腾讯云 IM SDK 封装(WebSocket/STOMP 传输)
|
||||
- WatermelonDB 本地消息持久化
|
||||
- 基础会话/消息 API 完整(15 种消息类型)
|
||||
- 群组管理 API 完整
|
||||
- 关系链(好友/黑名单)API 完整
|
||||
- 离线消息同步、消息搜索(本地)
|
||||
|
||||
### 后续待做
|
||||
|
||||
- 消息已读回执(单聊已读状态同步)
|
||||
- 群组消息已读回执统计
|
||||
- 离线消息补全(当前为 best-effort 同步)
|
||||
- 消息撤回时间窗口控制(服务端策略)
|
||||
- 语音消息录制组件(当前仅发送本地音频文件)
|
||||
- 图片/视频消息缩略图生成
|
||||
- 消息转发、合并转发 UI
|
||||
- @所有人(@all)支持
|
||||
|
||||
### 技术要点
|
||||
|
||||
- 需要 `@nozbe/watermelondb` 依赖
|
||||
- DB 名称由 `appKey + userId` 派生,多账号隔离
|
||||
- 断线重连由 `ImClient` 内部处理(指数退避)
|
||||
- `setUserInfo` 自动触发 IM 登录(若 `imEnabled` 为 true)
|
||||
|
||||
---
|
||||
|
||||
## rn-license(证书授权)
|
||||
|
||||
### 当前状态
|
||||
|
||||
- 证书授权基础流程已实现
|
||||
- 设备 License 验证(`checkLicense`)
|
||||
- License 状态查询(`getStatus`)
|
||||
- 本地缓存(AsyncStorage)
|
||||
|
||||
### 后续待做
|
||||
|
||||
- 证书到期提醒(服务端推送 + 本地定时检查)
|
||||
- 证书自动刷新机制
|
||||
- 多设备 License 管理
|
||||
- 离线 License 验证(降级策略)
|
||||
- License 使用量统计
|
||||
|
||||
### 技术要点
|
||||
|
||||
- 需要 `react-native-quick-crypto` 依赖
|
||||
- 内部自动等待 `XuqmSDK` 初始化完成
|
||||
- License 服务地址从平台配置获取(`licenseUrl`)
|
||||
109
packages/common/README.md
普通文件
109
packages/common/README.md
普通文件
@ -0,0 +1,109 @@
|
||||
# @xuqm/rn-common
|
||||
|
||||
XuqmGroup RN SDK 核心模块。负责 SDK 初始化、HTTP 请求、Token 管理、设备信息、XWebView Bridge、API hooks。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-common @react-native-async-storage/async-storage
|
||||
```
|
||||
|
||||
Peer dependencies:`react >= 18`,`react-native >= 0.76`,`axios >= 1.0.0`
|
||||
|
||||
## 初始化
|
||||
|
||||
### 方式 A — 配置文件自动初始化(推荐)
|
||||
|
||||
在宿主项目中配置 Babel alias `@xuqm/autoinit-config` → 加密配置文件:
|
||||
|
||||
```js
|
||||
// metro.config.js
|
||||
config.resolver.extraNodeModules = {
|
||||
'@xuqm/autoinit-config': './path/to/your.xuqmconfig',
|
||||
};
|
||||
```
|
||||
|
||||
SDK 在 import 时自动调用 `initWithConfigFile()`,App 无需任何 init 代码。
|
||||
|
||||
### 方式 B — 手动初始化
|
||||
|
||||
```ts
|
||||
import { XuqmSDK } from '@xuqm/rn-common'
|
||||
|
||||
await XuqmSDK.initialize({ appKey: 'xxx' }) // 公有平台
|
||||
await XuqmSDK.initialize({ appKey: 'xxx', platformUrl: 'https://xxx' }) // 私有化
|
||||
await XuqmSDK.awaitInitialization() // 等待配置拉取
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### 初始化
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `XuqmSDK.initialize(opts)` | 初始化,拉取平台配置 |
|
||||
| `XuqmSDK.awaitInitialization()` | 等待异步初始化完成 |
|
||||
| `isInitialized()` | 检查 SDK 是否就绪 |
|
||||
| `getConfig()` | 获取已解析的平台配置 |
|
||||
|
||||
### 用户信息
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `XuqmSDK.setUserInfo(info)` | 设置用户信息,触发所有子 SDK 登录 |
|
||||
| `XuqmSDK.setUserInfo(null)` | 登出,触发全局登出 |
|
||||
| `getUserId()` | 获取当前 userId |
|
||||
| `getUserInfo()` | 获取当前用户信息 |
|
||||
| `setUserId(id)` | 直接设置 userId(内部用) |
|
||||
|
||||
### HTTP
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `apiRequest(url, options?)` | 带 Bearer token 的 HTTP 请求 |
|
||||
| `configureHttp(opts)` | 覆盖 HTTP 基础配置 |
|
||||
| `_getToken()` | 获取当前 token(内部用) |
|
||||
| `_saveToken(token)` | 保存 token(内部用) |
|
||||
| `_clearToken()` | 清除 token(内部用) |
|
||||
|
||||
### 设备
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `getDeviceId()` | 获取设备稳定 UUID |
|
||||
| `getDeviceInfo()` | 获取设备品牌/型号/系统信息 |
|
||||
| `detectPushVendor()` | 检测设备推送厂商 |
|
||||
|
||||
### XWebView Bridge
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `openXWebView(url, options?)` | 打开 WebView |
|
||||
| `setXWebViewController(controller)` | 设置全局 WebView 控制器 |
|
||||
| `getXWebViewConfig()` | 获取当前 WebView 配置 |
|
||||
| `XWebViewControl` | WebView 控制器类 |
|
||||
|
||||
### API Hooks
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `useApi(method, url, opts?)` | React hook:带 loading/error 的 API 调用 |
|
||||
| `usePageApi(method, url, opts?)` | React hook:分页 API |
|
||||
| `useRequest(opts?)` | React hook:通用请求 |
|
||||
| `setGlobalApiErrorHandler(handler)` | 设置全局 API 错误处理 |
|
||||
|
||||
### UI
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `showToast(msg)` | 显示 toast |
|
||||
| `showAlert(title, msg)` | 显示 alert |
|
||||
| `showConfirm(title, msg)` | 显示确认对话框 |
|
||||
| `ScaledImage` | 等比缩放图片组件 |
|
||||
|
||||
### 常量
|
||||
|
||||
| 常量 | 说明 |
|
||||
|------|------|
|
||||
| `DEFAULT_TENANT_PLATFORM_URL` | 默认公有平台地址 |
|
||||
| `DEFAULT_IM_WS_URL` | 默认 IM WebSocket 地址 |
|
||||
127
packages/im/README.md
普通文件
127
packages/im/README.md
普通文件
@ -0,0 +1,127 @@
|
||||
# @xuqm/rn-im
|
||||
|
||||
XuqmGroup RN SDK IM 模块。提供 WebSocket 实时通信、会话管理、消息收发、群组管理、关系链管理。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-im @nozbe/watermelondb
|
||||
```
|
||||
|
||||
Peer dependencies:`@nozbe/watermelondb >= 0.27.0`,`react-native >= 0.76`
|
||||
|
||||
## 使用
|
||||
|
||||
**无需手动初始化。** `XuqmSDK.setUserInfo({ userId, userSig })` 被调用时,SDK 自动完成 IM 登录。
|
||||
|
||||
```ts
|
||||
import { ImSDK } from '@xuqm/rn-im'
|
||||
|
||||
// 发送消息
|
||||
await ImSDK.sendTextMessage('user_002', 'SINGLE', 'Hello!')
|
||||
|
||||
// 获取会话列表
|
||||
const conversations = await ImSDK.listConversations()
|
||||
|
||||
// 监听新消息
|
||||
ImSDK.addListener({
|
||||
onMessage: (msg) => console.log('新消息:', msg),
|
||||
onConnected: () => console.log('IM 已连接'),
|
||||
})
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### 连接管理
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `ImSDK.login(userId, userSig)` | 手动登录(通常不需要直接调用) |
|
||||
| `ImSDK.refreshToken(userSig)` | 刷新 userSig(过期时调用) |
|
||||
| `ImSDK.disconnect()` | 断开连接 |
|
||||
| `ImSDK.reconnect()` | 重新连接 |
|
||||
| `ImSDK.isConnected()` | 检查连接状态 |
|
||||
|
||||
### 消息 API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `ImSDK.sendMessage(toId, chatType, msgType, content, mentionedUserIds?)` | 发送消息 |
|
||||
| `ImSDK.sendTextMessage(toId, chatType, content, mentionedUserIds?)` | 发送文本 |
|
||||
| `ImSDK.sendImageMessage(toId, chatType, localUri, width?, height?)` | 发送图片 |
|
||||
| `ImSDK.sendVideoMessage(toId, chatType, localUri, thumbnailUri?, duration?)` | 发送视频 |
|
||||
| `ImSDK.sendAudioMessage(toId, chatType, localUri, duration)` | 发送语音 |
|
||||
| `ImSDK.sendFileMessage(toId, chatType, localUri, filename, size)` | 发送文件 |
|
||||
| `ImSDK.sendQuoteMessage(toId, chatType, quotedMsgId, quotedContent, text)` | 引用回复 |
|
||||
| `ImSDK.sendLocationMessage(toId, chatType, latitude, longitude, title?, address?)` | 发送位置 |
|
||||
| `ImSDK.revokeMessage(messageId)` | 撤回消息 |
|
||||
| `ImSDK.editMessage(messageId, content)` | 编辑消息 |
|
||||
|
||||
### 会话 API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `ImSDK.listConversations()` | 获取会话列表 |
|
||||
| `ImSDK.subscribeConversations(callback)` | 订阅会话变更(返回 unsubscribe) |
|
||||
| `ImSDK.markRead(targetId, chatType?)` | 标记已读 |
|
||||
| `ImSDK.deleteConversation(targetId, chatType)` | 删除会话 |
|
||||
| `ImSDK.getTotalUnreadCount()` | 获取总未读数 |
|
||||
|
||||
### 历史消息
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `ImSDK.fetchHistory(toId, page?, size?)` | 获取单聊历史(优先本地缓存) |
|
||||
| `ImSDK.fetchGroupHistory(groupId, page?, size?)` | 获取群聊历史 |
|
||||
| `ImSDK.fetchHistoryWithFilters(toId, params)` | 按条件查询历史 |
|
||||
| `ImSDK.searchMessages(params)` | 搜索消息(本地 WatermelonDB) |
|
||||
| `ImSDK.locateHistoryPage(toId, messageId)` | 定位消息所在页 |
|
||||
|
||||
### 群组 API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `ImSDK.createGroup(name, memberIds, groupType?)` | 创建群组 |
|
||||
| `ImSDK.listGroups()` | 获取群组列表 |
|
||||
| `ImSDK.getGroupInfo(groupId)` | 获取群组信息 |
|
||||
| `ImSDK.listGroupMembers(groupId)` | 获取群成员 |
|
||||
| `ImSDK.addGroupMember(groupId, userId)` | 添加成员 |
|
||||
| `ImSDK.removeGroupMember(groupId, userId)` | 移除成员 |
|
||||
| `ImSDK.setGroupRole(groupId, userId, role)` | 设置管理员 |
|
||||
| `ImSDK.muteGroupMember(groupId, userId, minutes)` | 禁言 |
|
||||
| `ImSDK.dismissGroup(groupId)` | 解散群组 |
|
||||
|
||||
### 关系链 API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `ImSDK.listFriends()` | 好友列表 |
|
||||
| `ImSDK.addFriend(friendId)` | 添加好友 |
|
||||
| `ImSDK.removeFriend(friendId)` | 删除好友 |
|
||||
| `ImSDK.sendFriendRequest(toUserId, remark?)` | 发送好友申请 |
|
||||
| `ImSDK.acceptFriendRequest(requestId)` | 接受好友申请 |
|
||||
| `ImSDK.addToBlacklist(blockedUserId)` | 加入黑名单 |
|
||||
| `ImSDK.checkBlacklist(targetUserId)` | 检查黑名单 |
|
||||
|
||||
### 事件监听
|
||||
|
||||
```ts
|
||||
ImSDK.addListener({
|
||||
onConnected: () => {},
|
||||
onDisconnected: (code, reason) => {},
|
||||
onMessage: (msg) => {},
|
||||
onGroupMessage: (msg) => {},
|
||||
onSystemMessage: (msg) => {},
|
||||
onRead: (msg) => {},
|
||||
onRevoke: (data) => {},
|
||||
})
|
||||
ImSDK.removeListener(listener)
|
||||
```
|
||||
|
||||
## 消息类型
|
||||
|
||||
`TEXT` / `IMAGE` / `VIDEO` / `AUDIO` / `FILE` / `CUSTOM` / `LOCATION` / `NOTIFY` / `RICH_TEXT` / `CALL_AUDIO` / `CALL_VIDEO` / `QUOTE` / `MERGE` / `REVOKED` / `FORWARD`
|
||||
|
||||
## 本地存储
|
||||
|
||||
使用 WatermelonDB 进行本地消息缓存,支持离线消息同步和本地搜索。DB 名称由 `appKey + userId` 派生。
|
||||
59
packages/license/README.md
普通文件
59
packages/license/README.md
普通文件
@ -0,0 +1,59 @@
|
||||
# @xuqm/rn-license
|
||||
|
||||
XuqmGroup RN SDK 证书授权模块。提供设备 License 验证能力。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-license react-native-quick-crypto
|
||||
```
|
||||
|
||||
Peer dependencies:`react-native >= 0.76`,`@react-native-async-storage/async-storage >= 1.21.0`,`react-native-quick-crypto >= 0.7.0`
|
||||
|
||||
## 使用
|
||||
|
||||
**无需独立初始化。** 内部自动调用 `awaitInitialization()` 等待 `XuqmSDK` 就绪。
|
||||
|
||||
```ts
|
||||
import { checkLicense, getStatus, clear } from '@xuqm/rn-license'
|
||||
|
||||
// 验证 License
|
||||
const result = await checkLicense()
|
||||
if (result.type === 'success') {
|
||||
console.log('License 通过:', result.reason)
|
||||
} else {
|
||||
console.error('License 失败:', result.message)
|
||||
}
|
||||
|
||||
// 获取状态
|
||||
const status = await getStatus() // 'ok' | 'denied' | 'unknown'
|
||||
|
||||
// 清除本地缓存(调试用)
|
||||
await clear()
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `checkLicense(userInfo?)` | 验证设备 License |
|
||||
| `getStatus()` | 获取当前 License 状态 |
|
||||
| `getDeviceId()` | 获取设备 ID |
|
||||
| `clear()` | 清除本地 License 缓存 |
|
||||
|
||||
## 类型
|
||||
|
||||
```ts
|
||||
interface LicenseUserInfo {
|
||||
userId?: string
|
||||
userSig?: string
|
||||
}
|
||||
|
||||
type LicenseStatus = 'ok' | 'denied' | 'unknown'
|
||||
|
||||
interface LicenseResult {
|
||||
type: 'success' | 'denied' | 'error'
|
||||
reason?: string
|
||||
message?: string
|
||||
}
|
||||
```
|
||||
89
packages/log/README.md
普通文件
89
packages/log/README.md
普通文件
@ -0,0 +1,89 @@
|
||||
# @xuqm/rn-log
|
||||
|
||||
XuqmGroup RN SDK 日志模块。提供日志采集、错误追踪、漏斗分析能力。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-log
|
||||
```
|
||||
|
||||
Peer dependencies:`@xuqm/rn-common >= 0.4.0`,`@react-native-async-storage/async-storage >= 1.21.0`,`react-native >= 0.76`
|
||||
|
||||
## 快速开始
|
||||
|
||||
```ts
|
||||
import { XLog } from '@xuqm/rn-log'
|
||||
|
||||
// 1. 设置日志级别
|
||||
XLog.setLogLevel('debug') // 'debug' | 'info' | 'warn' | 'error'
|
||||
|
||||
// 2. 设置环境标签
|
||||
XLog.setEnvironment('production') // 'development' | 'staging' | 'production'
|
||||
|
||||
// 3. 开启全局错误捕获(App 启动时调用一次)
|
||||
XLog.startCapture()
|
||||
|
||||
// 4. 记录自定义事件
|
||||
XLog.event('page_view', { page: 'home' })
|
||||
|
||||
// 5. 上报错误
|
||||
try { ... } catch (e) { XLog.captureError(e) }
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### XLog 对象
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `XLog.setLogLevel(level)` | 设置最低日志级别(低于此级别的事件被丢弃) |
|
||||
| `XLog.setEnvironment(env)` | 设置环境标签(附加到每个事件) |
|
||||
| `XLog.startCapture()` | 开启全局 JS 错误和未处理 Promise rejection 捕获 |
|
||||
| `XLog.event(name, properties?)` | 记录自定义分析事件 |
|
||||
| `XLog.captureError(error, metadata?)` | 上报 JS 异常 |
|
||||
| `XLog.warn(message, metadata?)` | 记录警告(需级别允许) |
|
||||
| `XLog.info(message, metadata?)` | 记录信息事件(需级别允许) |
|
||||
| `XLog.defineFunnel(id, steps)` | 定义漏斗(按步骤顺序追踪转化) |
|
||||
| `XLog.getFunnelProgress(funnelId)` | 获取客户端漏斗进度 |
|
||||
| `XLog.flush()` | 立即刷新所有待发送事件(如 App 进后台前调用) |
|
||||
|
||||
### 事件类型
|
||||
|
||||
| 类型 | 说明 |
|
||||
|------|------|
|
||||
| `LogEvent` | 自定义事件(`type: 'event'`) |
|
||||
| `IssueEvent` | 错误事件(`type: 'js_error'` / `'native_crash'` / `'api_error'` / `'warning'`) |
|
||||
|
||||
### 日志级别
|
||||
|
||||
`'debug'` (0) < `'info'` (1) < `'warn'` (2) < `'error'` (3)
|
||||
|
||||
### 漏斗分析示例
|
||||
|
||||
```ts
|
||||
import { XLog } from '@xuqm/rn-log'
|
||||
|
||||
// 定义漏斗
|
||||
XLog.defineFunnel('checkout', ['cart_view', 'checkout_start', 'payment_done'])
|
||||
|
||||
// 在业务代码中记录步骤事件(SDK 自动推进漏斗)
|
||||
XLog.event('cart_view')
|
||||
XLog.event('checkout_start')
|
||||
XLog.event('payment_done')
|
||||
|
||||
// 查询进度
|
||||
const progress = XLog.getFunnelProgress('checkout')
|
||||
console.log(progress?.completedSteps) // ['cart_view', 'checkout_start', 'payment_done']
|
||||
```
|
||||
|
||||
## 工作原理
|
||||
|
||||
1. **LogQueue**:事件先进入内存队列,按批次异步上传到 `logApiUrl`
|
||||
2. **ErrorCapture**:`startCapture()` 注册全局 `ErrorUtils` handler,自动捕获未处理异常
|
||||
3. **Fingerprint**:为每个错误生成指纹(基于 message + stack),用于服务端去重聚合
|
||||
4. **FunnelTracker**:客户端维护漏斗进度,服务端跨 session 聚合
|
||||
|
||||
## 配置
|
||||
|
||||
`logApiUrl` 和 `logEnabled` 由 `@xuqm/rn-common` 在 init 后从 `/api/sdk/config` 自动获取,无需 App 传入。
|
||||
53
packages/push/README.md
普通文件
53
packages/push/README.md
普通文件
@ -0,0 +1,53 @@
|
||||
# @xuqm/rn-push
|
||||
|
||||
XuqmGroup RN SDK 推送模块。自动检测设备厂商并完成推送 token 注册。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-push
|
||||
```
|
||||
|
||||
Peer dependencies:`react-native >= 0.76`
|
||||
|
||||
## 使用
|
||||
|
||||
**无需手动初始化。** `XuqmSDK.setUserInfo(info)` 被调用时,SDK 自动完成:
|
||||
1. 检测设备厂商(华为/小米/OPPO/vivo/荣耀/FCM/APNs)
|
||||
2. 从平台获取该厂商推送配置
|
||||
3. 调用厂商 SDK 完成设备注册
|
||||
4. 收到 token 后自动上报绑定到平台
|
||||
|
||||
```ts
|
||||
import { PushSDK } from '@xuqm/rn-push'
|
||||
|
||||
// 通常不需要手动调用,setUserInfo 会自动触发
|
||||
// 设置离线推送开关
|
||||
await PushSDK.setOfflinePushEnabled(false)
|
||||
|
||||
// 设置免打扰时间段(24 小时制)
|
||||
await PushSDK.setQuietHours('22:00', '08:00')
|
||||
|
||||
// 清除免打扰
|
||||
await PushSDK.clearQuietHours()
|
||||
|
||||
// 主动登出(通常不需要,setUserInfo(null) 自动触发)
|
||||
await PushSDK.logout()
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `PushSDK.setOfflinePushEnabled(enabled)` | 设置离线推送开关 |
|
||||
| `PushSDK.setQuietHours(start, end)` | 设置免打扰时间段 |
|
||||
| `PushSDK.clearQuietHours()` | 清除免打扰设置 |
|
||||
| `PushSDK.logout()` | 解绑推送 token |
|
||||
|
||||
## 支持厂商
|
||||
|
||||
HUAWEI / XIAOMI / OPPO / VIVO / HONOR / FCM / APNS
|
||||
|
||||
## 依赖
|
||||
|
||||
需要原生模块 `NativeModules.XuqmPushModule` 已链接到宿主 App。
|
||||
116
packages/update/README.md
普通文件
116
packages/update/README.md
普通文件
@ -0,0 +1,116 @@
|
||||
# @xuqm/rn-update
|
||||
|
||||
XuqmGroup RN SDK 更新模块。提供 App 整包更新检查和 RN 插件热更新能力。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-update @react-native-async-storage/async-storage
|
||||
```
|
||||
|
||||
Peer dependencies:`react-native >= 0.76`,`@react-native-async-storage/async-storage >= 1.21.0`
|
||||
|
||||
## 快速开始
|
||||
|
||||
```ts
|
||||
import { UpdateSDK } from '@xuqm/rn-update'
|
||||
|
||||
// 注册插件
|
||||
UpdateSDK.registerPlugins([
|
||||
{ moduleId: 'szyx' },
|
||||
{ moduleId: 'miniapp' },
|
||||
])
|
||||
|
||||
// 注入宿主 BundleRuntime
|
||||
UpdateSDK.setBundleCallbacks({
|
||||
writeBundle: writeBundleFile,
|
||||
reloadBundle: loadBundle,
|
||||
})
|
||||
|
||||
// 检查 App 更新
|
||||
const info = await UpdateSDK.checkAppUpdate()
|
||||
if (info.needsUpdate) {
|
||||
await UpdateSDK.downloadAndInstallApk(info.downloadUrl)
|
||||
}
|
||||
|
||||
// 检查插件更新
|
||||
const pluginInfo = await UpdateSDK.checkPluginUpdate('szyx')
|
||||
if (pluginInfo.needsUpdate) {
|
||||
await UpdateSDK.updatePlugin('szyx', { onProgress: setProgress })
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### 插件注册
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `UpdateSDK.registerPlugins(plugins)` | 批量注册插件 |
|
||||
| `UpdateSDK.registerPlugin(meta)` | 单个注册(向后兼容) |
|
||||
| `UpdateSDK.setBundleCallbacks(callbacks)` | 注入宿主写入/重载能力 |
|
||||
| `UpdateSDK.getRegisteredPlugins()` | 获取已注册插件列表 |
|
||||
|
||||
### App 整包更新
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `UpdateSDK.checkAppUpdate(bypassIgnore?)` | 检查 App 更新(30 分钟缓存) |
|
||||
| `UpdateSDK.downloadApk(info, options?)` | 下载 APK,返回 ArrayBuffer |
|
||||
| `UpdateSDK.downloadAndInstallApk(url, options?)` | 下载 APK 并调起系统安装器(Android) |
|
||||
| `UpdateSDK.openStore(appStoreUrl?, marketUrl?)` | 跳转应用商店 |
|
||||
| `UpdateSDK.getAppVersionCode()` | 获取当前 versionCode |
|
||||
| `UpdateSDK.getAppVersionName()` | 获取当前 versionName |
|
||||
|
||||
### 插件热更新
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `UpdateSDK.checkPluginUpdate(moduleId)` | 检查插件更新(30 分钟缓存) |
|
||||
| `UpdateSDK.updatePlugin(moduleId, options?)` | 一步完成:检查 → 下载 → 写文件 → 重载 |
|
||||
|
||||
### 类型定义
|
||||
|
||||
```ts
|
||||
interface PluginRegistration {
|
||||
moduleId: string
|
||||
}
|
||||
|
||||
interface AppUpdateInfo {
|
||||
needsUpdate: boolean
|
||||
versionName?: string
|
||||
versionCode?: number
|
||||
downloadUrl?: string
|
||||
changeLog?: string
|
||||
forceUpdate?: boolean
|
||||
appStoreUrl?: string
|
||||
marketUrl?: string
|
||||
apkHash?: string | null
|
||||
}
|
||||
|
||||
interface PluginUpdateInfo {
|
||||
needsUpdate: boolean
|
||||
latestVersion: string
|
||||
currentVersion: string
|
||||
downloadUrl: string
|
||||
md5: string
|
||||
minCommonVersion: string
|
||||
note: string
|
||||
forceUpdate?: boolean
|
||||
}
|
||||
|
||||
interface CachedRnBundle {
|
||||
moduleId: string
|
||||
version: string
|
||||
md5: string
|
||||
downloadedAt: string
|
||||
source: string
|
||||
}
|
||||
```
|
||||
|
||||
## 工作原理
|
||||
|
||||
- 版本号由 SDK 自动从本地 AsyncStorage 缓存读取,首次为 `0.0.0`
|
||||
- 更新检查结果缓存 30 分钟(TTL),避免频繁请求
|
||||
- `updatePlugin()` 内部自动完成:`checkPluginUpdate` → `fetch(downloadUrl)` → AsyncStorage 缓存 → `writeBundle` → `reloadBundle`
|
||||
- `silent: true` 时跳过 `reloadBundle`,下次启动生效
|
||||
78
packages/xwebview/README.md
普通文件
78
packages/xwebview/README.md
普通文件
@ -0,0 +1,78 @@
|
||||
# @xuqm/rn-xwebview
|
||||
|
||||
XuqmGroup RN SDK WebView 模块。提供增强型 WebView 组件和 JSBridge 通信能力。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
yarn add @xuqm/rn-xwebview react-native-webview react-native-blob-util react-native-svg
|
||||
```
|
||||
|
||||
Peer dependencies:`react >= 18`,`react-native >= 0.76`,`@react-navigation/native >= 7.0.0`
|
||||
|
||||
## 组件
|
||||
|
||||
### XWebViewScreen — 全屏 WebView(React Navigation screen)
|
||||
|
||||
```tsx
|
||||
import { XWebViewScreen } from '@xuqm/rn-xwebview'
|
||||
|
||||
// 在导航中使用
|
||||
<XWebViewScreen />
|
||||
// URL 通过 openXWebView() 预设
|
||||
```
|
||||
|
||||
### XWebViewView — 嵌入式 WebView 组件
|
||||
|
||||
```tsx
|
||||
import { XWebViewView } from '@xuqm/rn-xwebview'
|
||||
|
||||
<XWebViewView
|
||||
config={{
|
||||
url: 'https://example.com',
|
||||
title: '嵌入式网页',
|
||||
jsBridgeName: 'XWebViewBridge',
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### XWebViewProgress — 进度条
|
||||
|
||||
```tsx
|
||||
import { XWebViewProgress } from '@xuqm/rn-xwebview'
|
||||
|
||||
<XWebViewProgress progress={50} />
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
| API | 说明 |
|
||||
|-----|------|
|
||||
| `openXWebView(url, options?)` | 打开 WebView 页面 |
|
||||
| `setXWebViewController(controller)` | 设置全局 WebView 控制器 |
|
||||
| `getXWebViewConfig()` | 获取当前 WebView 配置 |
|
||||
| `XWebViewControl` | WebView 控制器类 |
|
||||
|
||||
## XWebViewConfig 参数
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `url` | string | 初始加载地址 |
|
||||
| `title` | string | 页面标题 |
|
||||
| `jsBridgeName` | string | JS 桥接对象名(默认 `'XWebViewBridge'`) |
|
||||
| `hideToolbar` | boolean | 隐藏顶栏 |
|
||||
| `userAgent` | string? | 自定义 User-Agent |
|
||||
| `injectedJavaScript` | string? | 页面加载后注入的 JS |
|
||||
| `onMessage` | (event) => void | H5 发送消息回调 |
|
||||
|
||||
## JSBridge 通信
|
||||
|
||||
```js
|
||||
// H5 → Native
|
||||
window.XWebViewBridge.postMessage(JSON.stringify({ type: 'login', token: '...' }))
|
||||
|
||||
// Native → H5
|
||||
controller.postMessageToWeb("window.dispatchEvent(new CustomEvent('nativeMsg', { detail: { key: 'value' } }))")
|
||||
```
|
||||
|
||||
详细 handler 列表见 `@xuqm/rn-common` 的 `xwebview/` 目录和 `docs/XWebView-JSBridge.md`。
|
||||
正在加载...
在新工单中引用
屏蔽一个用户