docs: 添加 CLAUDE.md + 各 package README + 架构总览 + 模块待开发说明

Agent 8 文档生成:
- CLAUDE.md 项目上下文
- 各 package README (common/update/push/im/xwebview/license/log)
- docs/架构总览.md
- docs/模块待开发说明.md
这个提交包含在:
XuqmGroup 2026-06-16 12:14:52 +08:00
父节点 16750b0421
当前提交 4c3019edab
共有 10 个文件被更改,包括 867 次插入37 次删除

查看文件

@ -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/` - 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-common` | packages/common | 0.4.0 | 核心层初始化、HTTP、设备、XWebView Bridge、API hooks |
| `@xuqm/rn-update` | packages/update | — | 活跃开发 | | `@xuqm/rn-update` | packages/update | 0.4.0 | OTA 热更新、APK 更新 |
| `@xuqm/rn-xwebview` | packages/xwebview | — | 活跃开发 | | `@xuqm/rn-push` | packages/push | 0.2.2 | 厂商推送(代码冻结,仅文档) |
| `@xuqm/rn-log` | packages/log | 0.1.0(新) | 新建中 | | `@xuqm/rn-im` | packages/im | 0.2.2 | IM 会话、消息(代码冻结,仅文档) |
| `@xuqm/rn-push` | packages/push | — | 代码冻结(仅文档) | | `@xuqm/rn-xwebview` | packages/xwebview | 0.2.2 | WebView 容器 + JSBridge UI 组件 |
| `@xuqm/rn-im` | packages/im | — | 代码冻结(仅文档) | | `@xuqm/rn-license` | packages/license | 0.3.0 | 证书授权(代码冻结,仅文档) |
| `@xuqm/rn-license` | packages/license | — | 代码冻结(仅文档 | | `@xuqm/rn-log` | packages/log | 0.1.0 | 日志、错误追踪、漏斗分析(新 |
**代码冻结模块push/im/license不修改代码,仅补充文档。** **代码冻结模块push/im/license不修改代码,仅补充文档。**
## 技术约束 ## 技术
- **React Native ≥ 0.76**Bridgeless Mode,New Architecture - React Native >= 0.76Bridgeless Mode,New Architecture
- **TypeScript 5.x strict**`noImplicitAny: true`,禁止 `any` - TypeScript 5.x strict — `noImplicitAny: true`,禁止 `any`
- **向下兼容**:公开接口不删除不修改,新字段一律可选 - yarn workspaces monorepo
- **无静默降级**autoInit 失败时 `__DEV__` 模式 throw,生产模式 console.error - 发布到 Nexus npm 私有仓库
## 核心 API@xuqm/rn-common ## 初始化(两种方式)
### 初始化(两种方式,均不得修改签名)
**方式 A — 配置文件自动初始化(推荐)** **方式 A — 配置文件自动初始化(推荐)**
宿主配置 Babel alias `@xuqm/autoinit-config` → 加密配置文件。SDK 自动读取并初始化,App 代码无需调用任何 init。 宿主配置 Babel alias `@xuqm/autoinit-config` → 加密配置文件XUQM-CONFIG-V1 格式)。SDK 自动读取并初始化,App 无需调用任何 init。
**方式 B — 手动初始化** **方式 B — 手动初始化**
```ts ```ts
// 仅传 appKey → 使用内置公有平台 import { XuqmSDK } from '@xuqm/rn-common'
// 公有平台
await XuqmSDK.initialize({ appKey: 'xxx' }) await XuqmSDK.initialize({ appKey: 'xxx' })
// 传 appKey + platformUrl → 使用指定私有化平台 // 私有化平台
await XuqmSDK.initialize({ appKey: 'xxx', platformUrl: 'https://xxx' }) await XuqmSDK.initialize({ appKey: 'xxx', platformUrl: 'https://xxx' })
// 等待异步平台配置拉取 // 等待异步平台配置拉取
await XuqmSDK.awaitInitialization() await XuqmSDK.awaitInitialization()
``` ```
**两种平台互相独立,不允许自动降级到默认公有平台。** **两种平台互相独立,不允许自动降级。**
## 用户信息
### 用户信息
```ts ```ts
XuqmSDK.setUserInfo({ userId: 'u001', userSig: 'sig', name: '张三' }) 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 ```ts
import { XLog } from '@xuqm/rn-log' // 注意是 XLog 不是 Log import { XLog } from '@xuqm/rn-log'
XLog.setLogLevel('debug') XLog.setLogLevel('debug')
XLog.setEnvironment('production') XLog.setEnvironment('production')
XLog.startCapture() // 开启全局错误捕获 XLog.startCapture() // 开启全局错误捕获
XLog.event('page_view', { page: 'home' }) XLog.event('page_view', { page: 'home' })
XLog.captureError(new Error('xxx')) XLog.captureError(new Error('xxx'))
XLog.defineFunnel('checkout', ['cart_view', 'checkout_start', 'payment_done'])
``` ```
`logApiUrl` 由 SDK 在 init 后从 `/api/sdk/config` 自动获取,无需 App 传入。 `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 ## XWebView JSBridge 标准 Handler
`docs/XWebView-JSBridge.md`(已有文档,以该文档为准)。 `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`
## 常用命令 ## 常用命令
@ -87,4 +92,8 @@ XLog.captureError(new Error('xxx'))
yarn workspace @xuqm/rn-common typecheck yarn workspace @xuqm/rn-common typecheck
yarn workspace @xuqm/rn-log typecheck yarn workspace @xuqm/rn-log typecheck
yarn workspace @xuqm/rn-update 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 普通文件
查看文件

@ -0,0 +1,105 @@
# XuqmGroup RN SDK 架构总览
## 整体架构
```
宿主 AppYiwangxinApp4 等)
└── 初始化方式A: 配置文件自动 / 方式B: 手动 initialize
@xuqm/rn-common (核心层 v0.4.0
├── XuqmSDK.initialize() → 拉取 /api/sdk/config
├── XuqmSDK.setUserInfo() → 通知所有子 SDK订阅者模式
├── api/useApi / usePageApi / apiRequest
├── device设备信息 / 厂商检测)
├── xwebviewJSBridge 桥接控制)
├── 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
子 SDKupdate/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
```

查看文件

@ -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 普通文件
查看文件

@ -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 普通文件
查看文件

@ -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 普通文件
查看文件

@ -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 普通文件
查看文件

@ -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 普通文件
查看文件

@ -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 普通文件
查看文件

@ -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 普通文件
查看文件

@ -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 — 全屏 WebViewReact 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`