npm package: @lynker-desktop/web
Description: lynker-web-sdk
Latest version: 0.0.161

---
title: JSSDK
order: 0
nav:
  title: JSSDK
  order: 0
---

# Lynker Desktop Web SDK

[![npm version](https://img.shields.io/npm/v/@lynker-desktop/web.svg)](https://www.npmjs.com/package/@lynker-desktop/web)

一个功能强大的 JavaScript SDK，用于在 Web 环境中与 Lynker Desktop 桌面应用进行无缝交互。支持窗口管理、用户信息获取、文件操作、UI 组件调用等丰富的功能。

## 📋 目录

- [安装](#-安装)
- [快速开始](#-快速开始)
- [API 参考](#-api-参考)
  - [基础功能](#基础功能)
  - [窗口管理](#窗口管理)
  - [用户信息](#用户信息)
  - [文件操作](#文件操作)
  - [UI 组件](#ui-组件)
  - [主菜单操作](#主菜单操作)
  - [消息模块](#消息模块)
  - [数智工场模块](#数智工场模块)
  - [数字平台模块](#数字平台模块)
  - [广场模块](#广场模块)
  - [大市场模块](#大市场模块)
  - [独立窗口标签](#独立窗口标签)
- [完整使用示例](#-完整使用示例)
- [类型定义](#-类型定义)
- [常见问题](#-常见问题)
- [故障排除](#-故障排除)
- [更新日志](#-更新日志)
- [贡献指南](#-贡献指南)
- [许可证](#-许可证)

## 📦 安装

### npm

```bash
npm install @lynker-desktop/web
```

### yarn

```bash
yarn add @lynker-desktop/web
```

### pnpm

```bash
pnpm add @lynker-desktop/web
```

## 🚀 快速开始

### 基础用法

```javascript
import jssdk from '@lynker-desktop/web';

// 检查是否在桌面端环境
if (jssdk.isDesktop) {
  console.log('当前运行在桌面端环境');

  // 获取用户信息
  const userInfo = await jssdk.getUserInfo();
  console.log('用户信息:', userInfo);
} else {
  console.log('当前运行在浏览器环境');
}
```

### TypeScript 支持

```typescript
import jssdk, { LynkerSDKConfig, UserInfo } from '@lynker-desktop/web';

// 类型安全的配置获取
const config: LynkerSDKConfig = await jssdk.getConfig();
const userInfo: UserInfo = await jssdk.getUserInfo();
```

### 环境检测

```javascript
// 推荐的环境检测方式
if (jssdk.isDesktop) {
  // 桌面端环境下的操作
  await jssdk.openWebWindow({
    name: '新窗口',
    url: 'https://example.com',
  });
} else {
  // 浏览器环境下的降级处理
  window.open('https://example.com', '_blank');
}
```

## 📚 API 参考

> 💡 **提示**: 所有 API 方法都是异步的，需要使用 `await` 或 `.then()` 处理返回值。

### 基础功能

#### `isDesktop` - 检查是否在桌面端

```typescript
readonly isDesktop: boolean
```

检查当前是否在桌面端环境中运行。

#### `platform` - 获取平台信息

```typescript
readonly platform: 'win32' | 'darwin' | 'linux' | 'android' | 'ios' | 'unknown'
```

获取当前运行平台信息。

**返回值：** 平台标识符，包括 Windows、macOS、Linux、Android、iOS 或未知平台。

#### `arch` - 获取架构信息

```typescript
readonly arch: 'x64' | 'ia32' | 'arm64' | 'unknown'
```

获取当前系统架构信息。

**返回值：** 架构标识符，包括 x64、ia32、arm64 或未知架构。

#### `env` - 获取环境信息

```typescript
readonly env: object
```

获取 Electron 环境信息对象。

**返回值：** 包含 Electron 进程环境信息的对象。

#### `isOnline` - 检查网络状态

```typescript
readonly isOnline: boolean
```

检查当前网络连接状态。

**返回值：** `true` 表示在线，`false` 表示离线。

#### `fs` - 获取文件系统

```typescript
readonly fs: typeof import('node:fs')
```

获取 Node.js 文件系统模块（仅在桌面端可用）。

**返回值：** Node.js fs 模块对象。

#### `path` - 获取路径模块

```typescript
readonly path: typeof import('node:path')
```

获取 Node.js 路径模块（仅在桌面端可用）。

**返回值：** Node.js path 模块对象。

#### `openDesktop(launchOptions?: string)` - 打开桌面端

```typescript
openDesktop(launchOptions?: string): void
```

通过自定义协议打开桌面端应用。

**参数：**

- `launchOptions` (可选): 启动参数字符串

**示例：**

```javascript
jssdk.openDesktop();
jssdk.openDesktop('{"action": "openChat", "userId": "123"}');
```

#### `getConfig()` - 获取配置信息

```typescript
getConfig(): Promise<LynkerSDKConfig>
```

获取桌面端的配置信息。

**返回值：** `LynkerSDKConfig` 对象，包含环境、域名、国际化等配置。

#### `getLocalStorage(key: string)` - 获取本地存储

```typescript
getLocalStorage(key: string): Promise<string | null>
```

获取桌面端主窗口的 localStorage 值。

#### `setLocalStorage(key: string, value: string | null)` - 设置本地存储

```typescript
setLocalStorage(key: string, value: string | null): Promise<boolean>
```

设置桌面端主窗口的 localStorage 值。

#### `getLaunchOptions()` - 获取启动参数

```typescript
getLaunchOptions(): Promise<string | null>
```

获取桌面端的启动/唤起参数。

#### `delLaunchOptions()` - 清除启动参数

```typescript
delLaunchOptions(): Promise<string | null>
```

清除桌面端的启动/唤起参数。

#### `getRandomUUID(key?: string)` - 生成随机 UUID

```typescript
getRandomUUID(key?: string): string
```

生成一个基于时间戳和随机数的唯一 UUID。

#### `getH5Url(path, env?, clearCache?)` - 获取 H5 URL

```typescript
getH5Url(path: string, env?: LynkerSDKConfig['env'], clearCache?: boolean): string
```

根据环境和路径生成 H5 URL。

**参数：**
- `path`: 路径字符串
- `env` (可选): 环境标识，默认为 'PROD'
- `clearCache` (可选): 是否清除缓存，默认为 false

#### `getH5UrlWithParams(options)` - 获取带参数的 H5 URL

```typescript
getH5UrlWithParams(options: {
  path: string;
  params: Record<string, any>;
}): Promise<string>
```

获取带有环境参数的 H5 URL。

#### `openPath(query)` - 打开路径

```typescript
openPath(query: MsgQuery['openPath']['query']): Promise<void>
```

使用系统默认程序打开指定路径。

#### `appStore(options)` - 应用数据存储

```typescript
appStore(options: {
  name: string;
  method: 'get' | 'set' | 'delete' | 'clear';
  key?: string;
  value?: any;
}): Promise<any>
```

操作应用数据存储，支持获取、设置、删除和清空操作。

#### `shell(options)` - Shell 操作

```typescript
shell(options: {
  method: string;
  options: string | string[];
}): Promise<any>
```

执行系统 Shell 命令。

#### `clipboard(options)` - 剪贴板操作

```typescript
clipboard(options: {
  method: string;
  options: string | string[];
}): Promise<any>
```

操作系统剪贴板。

#### `nativeImage(options)` - 原生图片操作

```typescript
nativeImage(options: {
  method: string;
  options: string | string[];
}): Promise<any>
```

操作原生图片对象。

#### `setDebug(debug: boolean)` - 设置调试模式

```typescript
setDebug(debug: boolean): void
```

开启或关闭调试日志输出。

### 原始 ipcRenderer - `ipcRenderer`

```typescript
readonly ipcRenderer: Electron.IpcRenderer | null
```

> ⚠️ **已废弃**: 请优先使用 `ipc` 属性，该属性即将被移除。

原始 Electron IPC 渲染器实例，用于与主进程进行通信。

**注意**: 此属性已被标记为废弃，建议使用 `ipc` 属性替代。

### 基础 IPC 组件 - `ipc`

```typescript
readonly ipc: RendererIPC
```

基于 `@lynker-desktop/electron-ipc` 的基础 IPC 组件，提供更高级的进程间通信功能。

**功能特性**:

- 类型安全的 IPC 通信
- 自动错误处理
- 支持事件监听和响应
- 更好的开发体验
- 支持窗口间通信

##### IPC API 方法

###### 主进程通信

#### `invokeMain(channel, ...args)` - 发送消息到主进程

```typescript
static invokeMain(channel: string, ...args: any[]): Promise<any>
```

发送消息到主进程，使用 Electron 原生的 invoke 方法，支持并发请求。

**参数**:

- `channel`: 通信频道名称
- `...args`: 传递给主进程的参数

**返回值**: Promise<any> - 主进程的响应数据

**特性**:
- 支持并发请求，不会互相干扰
- 使用 Electron 原生 invoke 方法
- 自动处理错误和超时

#### `handleMain(channel, handler)` - 处理主进程消息

```typescript
static handleMain(
  channel: string,
  handler: (...args: any[]) => Promise<any>
): {
  cancel: () => void;
}
```

处理主进程发送过来的消息。

**参数**:

- `channel`: 通信频道名称
- `handler`: 消息处理函数，接收除 requestId 外的所有参数

**返回值**: 返回取消函数，用于移除处理器

**特性**:
- 返回取消函数，支持动态移除处理器
- 处理函数必须返回 Promise

###### 渲染进程通信

#### `invokeRenderer(channel, ...args)` - 发送消息到所有渲染进程

```typescript
static invokeRenderer(channel: string, ...args: any[]): Promise<any>
```

发送消息到所有渲染进程，使用唯一的 requestId 确保并发请求不会互相干扰。

**参数**:

- `channel`: 通信频道名称
- `...args`: 传递给渲染进程的参数

**返回值**: Promise<any> - 渲染进程的响应数据

**特性**:
- 向所有渲染进程发送消息
- 使用 requestId 机制避免并发冲突
- 自动等待渲染进程加载完成

#### `handleRenderer(channel, handler)` - 处理渲染进程消息

```typescript
static handleRenderer(
  channel: string,
  handler: (...args: any[]) => Promise<any>
): {
  cancel: () => void;
}
```

处理渲染进程发送过来的消息。

**参数**:

- `channel`: 通信频道名称
- `handler`: 消息处理函数，接收除 requestId 外的所有参数

**返回值**: 返回取消函数，用于移除处理器

**特性**:
- 返回取消函数，支持动态移除处理器
- 处理函数必须返回 Promise

###### 工具方法

#### `getCurrentWebContentId()` - 获取当前渲染进程 ID

```typescript
static getCurrentWebContentId(): Promise<number>
```

获取当前渲染进程的 WebContents ID。

**返回值**: Promise<number> - 当前渲染进程的 ID

#### `openCurrentWebContentDevTools()` - 打开开发者工具

```typescript
static openCurrentWebContentDevTools(): Promise<number>
```

打开当前窗口的开发者工具。

**返回值**: Promise<number> - 操作结果

### 窗口管理

#### `executeJavaScript(options)` - 执行 JavaScript

```typescript
executeJavaScript(options?: {
  name?: string;
  webContentsId?: number;
  script?: string;
}): Promise<any>
```

在指定窗口中执行 JavaScript 代码。

**参数：**
- `name` (可选): 窗口名称
- `webContentsId` (可选): WebContents ID
- `script` (可选): 要执行的 JavaScript 代码

#### `getWebContentsId(options)` - 获取 WebContents ID

```typescript
getWebContentsId(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<number | undefined>
```

获取指定窗口的 WebContents ID。

#### `focus(options)` - 聚焦窗口

```typescript
focus(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

将指定窗口置于前台并聚焦。

#### `blur(options)` - 失焦窗口

```typescript
blur(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

使指定窗口失去焦点。

#### `minimize(options)` - 最小化窗口

```typescript
minimize(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

最小化指定窗口。

#### `maximize(options)` - 最大化窗口

```typescript
maximize(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

最大化指定窗口。

#### `unmaximize(options)` - 取消最大化窗口

```typescript
unmaximize(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

取消最大化指定窗口。

#### `isMaximized(options)` - 检查窗口是否最大化

```typescript
isMaximized(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

检查指定窗口是否处于最大化状态。

#### `isFullScreen(options)` - 检查窗口是否全屏

```typescript
isFullScreen(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

检查指定窗口是否处于全屏状态。

#### `setFullScreen(options)` - 设置窗口全屏

```typescript
setFullScreen(options?: {
  name?: string;
  webContentsId?: number;
  fullscreen?: boolean;
}): Promise<boolean>
```

设置指定窗口的全屏状态。

#### `goBack(options)` - 后退

```typescript
goBack(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

在指定窗口中执行后退操作。

#### `reload(options)` - 重新加载

```typescript
reload(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

重新加载指定窗口的内容。

#### `goForward(options)` - 前进

```typescript
goForward(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

在指定窗口中执行前进操作。

#### `loadURL(options)` - 加载 URL

```typescript
loadURL(options?: {
  name?: string;
  webContentsId?: number;
  url?: string;
}): Promise<boolean>
```

在指定窗口中加载指定的 URL。

#### `close(options)` - 关闭窗口

```typescript
close(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

关闭指定窗口。

#### `restore(options)` - 恢复窗口

```typescript
restore(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

从最小化状态恢复指定窗口。

#### `setWindowOpenHandler(options)` - 设置窗口打开处理程序

```typescript
setWindowOpenHandler(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

为指定窗口设置新窗口打开处理程序。

#### `openDevTools(options)` - 打开开发者工具

```typescript
openDevTools(options?: {
  name?: string;
  webContentsId?: number;
}): Promise<boolean>
```

为指定窗口打开开发者工具。

#### `openWebWindow(options)` - 打开 Web 窗口

```typescript
openWebWindow(options: {
  name: string;
  url: string;
  extraData?: string;
  openDevTools?: boolean;
}): Promise<number>
```

> ⚠️ **已废弃**: 请优先使用 `openWindow`，该方法即将被移除。

#### `openNewWindow(options)` - 打开新窗口

```typescript
openNewWindow(options: ElectronWindowsManagerOptions): Promise<number | undefined>
```

#### `openExternalWindow(options)` - 打开外部窗口

```typescript
openExternalWindow(options: {
  url: string;
  options?: ElectronWindowsManagerOptions;
}): Promise<BrowserWindow>
```

#### `openWindow(options, tabsID?)` - 打开窗口（简化版）

```typescript
openWindow(options?: Omit<MsgQuery['windowsTabs_openTab']['query']['options'], ''>, tabsID?: string): Promise<any>
```

#### `closeWindow(query?)` - 关闭窗口

```typescript
closeWindow(query?: MsgQuery['windowsTabs_closeTab']['query']): Promise<any>
```

#### `getCurrentWindow()` - 获取当前窗口信息

```typescript
getCurrentWindow(): Promise<MsgQuery['windowsTabs_openTab']['query'] | undefined>
```

### 用户信息

#### `getUserInfo()` - 获取用户信息

```typescript
getUserInfo(): Promise<UserInfo>
```

获取当前登录用户的详细信息。

**返回值：** `UserInfo` 对象，包含用户 ID、昵称、头像、邮箱等信息。

#### `getUniqueId()` - 获取唯一 ID

```typescript
getUniqueId(): Promise<string>
```

获取桌面端的唯一标识符。

### 文件操作

#### `previewImage(options)` - 预览图片

```typescript
previewImage(options: PreviewImageOptions | PreviewImageOptions2): Promise<void>
```

#### `previewVideo(options)` - 预览视频

```typescript
previewVideo(options: PreviewVideoOptions): Promise<void>
```

#### `previewFile(options)` - 预览文件

```typescript
previewFile(options: PreviewFileOptions): Promise<void>
```

#### `downloadFile(options)` - 下载文件

```typescript
downloadFile(options: DownloadFileOptions): Promise<string>
```

#### `startCapture()` - 开始捕获

```typescript
startCapture(): Promise<void>
```

#### `stopCapture()` - 停止捕获

```typescript
stopCapture(): Promise<void>
```

#### `transcodeVideo(options, callbacks?)` - 转码视频

```typescript
transcodeVideo(options: VideoDownloadOptions, callbacks?: (data: VideoTranscodeChangeCallback) => void): Promise<string>
```

转码视频文件，支持进度回调。

**参数：**
- `options`: 视频下载选项
- `callbacks` (可选): 转码进度回调函数

**返回值：** Promise<string> - 转码后的文件路径

**回调数据：**
```typescript
interface VideoTranscodeChangeCallback {
  type: 'progress' | 'complete' | 'error';
  data?: {
    outputPath: string;
    progress: number;
  };
  error?: string;
}
```

#### `cache(options)` - 资源缓存

```typescript
cache(options: {
  method: 'add' | 'delete' | 'clear' | 'stats';
  urls?: string | string[];
  force?: boolean;
  id?: string;
  onProgress?: (progress: {
    current: number;        // 当前完成的 URL 数量
    total: number;          // 总 URL 数量
    url: string;            // 当前处理的 URL
    success: boolean;       // 当前 URL 是否成功
    result?: {              // 当前 URL 的处理结果
      filePath?: string;
      hostPath?: string;
      mimeType?: string;
      size?: number;
      error?: string;
    };
    percentage: number;     // 进度百分比 (0-100)
    downloadProgress?: {   // 下载进度（如果正在下载）
      downloaded: number;
      total: number;
      percentage: number;
      speed: number;
    };
  }) => void;
}): Promise<CacheResult>
```

缓存资源文件（图片、视频、文件等），支持进度回调和批量操作。

**参数：**
- `method`: 操作方法
  - `'add'`: 添加资源到缓存
  - `'delete'`: 删除缓存资源
  - `'clear'`: 清空所有缓存
  - `'stats'`: 获取缓存统计信息
- `urls` (可选): 要缓存的 URL 或 URL 数组（仅 `add` 和 `delete` 方法需要）
- `force` (可选): 是否强制重新下载（默认 false）
- `id` (可选): 唯一标识符
- `onProgress` (可选): 进度回调函数

**返回值：**
- `method: 'add'`: 返回单个或数组形式的缓存结果对象
  ```typescript
  {
    url: string;
    success: boolean;
    filePath?: string;      // 本地文件路径
    hostPath?: string;    // 可用于访问的本地路径
    error?: string;
    mineType: string;
    size: number;
  } | Array<...>
  ```
- `method: 'delete'`: 返回 `boolean` - 是否删除成功
- `method: 'clear'`: 返回 `boolean` - 是否清空成功
- `method: 'stats'`: 返回统计信息
  ```typescript
  {
    size: number;          // 当前缓存大小（字节）
    totalSize: number;     // 总缓存大小（字节）
  }
  ```

**使用示例：**

```typescript
// 缓存单个资源
const result = await jssdk.cache({
  method: 'add',
  urls: 'https://example.com/image.jpg',
  onProgress: (progress) => {
    console.log(`进度: ${progress.percentage}%`);
    if (progress.downloadProgress) {
      console.log(`下载速度: ${progress.downloadProgress.speed} B/s`);
    }
  }
});
console.log('缓存路径:', result.hostPath);

// 批量缓存资源
const results = await jssdk.cache({
  method: 'add',
  urls: [
    'https://example.com/image1.jpg',
    'https://example.com/image2.jpg',
    'https://example.com/video.mp4'
  ],
  onProgress: (progress) => {
    console.log(`处理 ${progress.current}/${progress.total}: ${progress.url}`);
  }
});

// 删除缓存
await jssdk.cache({
  method: 'delete',
  urls: 'https://example.com/image.jpg'
});

// 获取缓存统计
const stats = await jssdk.cache({
  method: 'stats'
});
console.log(`缓存大小: ${(stats.totalSize / 1024 / 1024).toFixed(2)} MB`);

// 清空所有缓存
await jssdk.cache({
  method: 'clear'
});
```

#### `downloader(options)` - 下载文件

```typescript
downloader(options: {
  url: string;
  id?: string;
  outputPath?: string;
  outputDir?: string;
  fileName?: string;
  override?: boolean;
  showSaveDialog?: boolean;
  defaultPath?: string;
  timeout?: number;
  retry?: {
    maxRetries?: number;
    delay?: number;
  };
  onProgress?: (progress: {
    url: string;            // 正在下载的 URL
    downloaded: number;     // 已下载字节数
    total: number;          // 总字节数（如果服务器提供 Content-Length）
    percentage: number;      // 下载进度百分比 (0-100)，如果 total 未知则为 -1
    speed: number;          // 下载速度（字节/秒）
  }) => void;
  httpRequestOptions?: {
    headers?: Record<string, string>;
    followRedirect?: boolean;
    maxRedirects?: number;
  };
}): Promise<{
  success: boolean;
  filePath?: string;
  error?: string;
  size?: number;
}>
```

下载文件到本地，支持进度回调、重试机制和自定义 HTTP 请求选项。

**参数：**
- `url`: 要下载的文件 URL（必需）
- `id` (可选): 唯一标识符（IPC 调用时必需）
- `outputPath` (可选): 输出文件完整路径（如果不提供则使用 URL 的文件名）
- `outputDir` (可选): 输出目录（如果不提供则使用当前目录）
- `fileName` (可选): 输出文件名（如果不提供则从 URL 提取）
- `override` (可选): 是否覆盖已存在的文件（默认 true）
- `showSaveDialog` (可选): 是否弹窗选择保存路径（默认 false）
- `defaultPath` (可选): 保存对话框的默认文件名
- `timeout` (可选): 超时时间（毫秒，默认 10 分钟）
- `retry` (可选): 重试配置
  - `maxRetries`: 最大重试次数
  - `delay`: 重试延迟（毫秒）
- `onProgress` (可选): 下载进度回调函数
- `httpRequestOptions` (可选): HTTP 请求选项
  - `headers`: 自定义请求头
  - `followRedirect`: 是否跟随重定向（默认 true）
  - `maxRedirects`: 最大重定向次数

**返回值：**
```typescript
{
  success: boolean;        // 是否成功
  filePath?: string;       // 下载的文件路径
  error?: string;         // 错误信息
  size?: number;          // 文件大小（字节）
}
```

**使用示例：**

```typescript
// 基本下载
const result = await jssdk.downloader({
  url: 'https://example.com/file.pdf',
  fileName: 'document.pdf'
});
if (result.success) {
  console.log('下载成功:', result.filePath);
}

// 带进度回调的下载
const result = await jssdk.downloader({
  url: 'https://example.com/large-file.zip',
  outputDir: '/path/to/downloads',
  onProgress: (progress) => {
    if (progress.percentage >= 0) {
      console.log(`下载进度: ${progress.percentage.toFixed(2)}%`);
    }
    console.log(`下载速度: ${(progress.speed / 1024 / 1024).toFixed(2)} MB/s`);
    console.log(`已下载: ${(progress.downloaded / 1024 / 1024).toFixed(2)} MB`);
    if (progress.total > 0) {
      console.log(`总大小: ${(progress.total / 1024 / 1024).toFixed(2)} MB`);
    }
  }
});

// 带重试机制的下载
const result = await jssdk.downloader({
  url: 'https://example.com/unstable-file.zip',
  retry: {
    maxRetries: 3,
    delay: 1000
  },
  onProgress: (progress) => {
    console.log(`进度: ${progress.percentage}%`);
  }
});

// 使用保存对话框
const result = await jssdk.downloader({
  url: 'https://example.com/file.pdf',
  showSaveDialog: true,
  defaultPath: 'document.pdf'
});

// 自定义 HTTP 请求头
const result = await jssdk.downloader({
  url: 'https://example.com/protected-file.zip',
  httpRequestOptions: {
    headers: {
      'Authorization': 'Bearer token123',
      'User-Agent': 'MyApp/1.0'
    },
    followRedirect: true,
    maxRedirects: 5
  },
  onProgress: (progress) => {
    console.log(`下载中: ${progress.percentage}%`);
  }
});

// 格式化下载速度的工具函数
function formatSpeed(bytesPerSecond: number): string {
  if (!bytesPerSecond || bytesPerSecond === 0) {
    return '';
  }
  if (bytesPerSecond < 1024) {
    return `${bytesPerSecond} B/s`;
  }
  if (bytesPerSecond < 1024 * 1024) {
    return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`;
  }
  return `${(bytesPerSecond / (1024 * 1024)).toFixed(1)} MB/s`;
}

// 在进度回调中使用
jssdk.downloader({
  url: 'https://example.com/file.zip',
  onProgress: (progress) => {
    const speed = formatSpeed(progress.speed);
    console.log(`速度: ${speed}, 进度: ${progress.percentage}%`);
  }
});
```

### UI 组件

#### `showMessage(options)` - 显示消息

```typescript
showMessage(options: {
  id?: string;
  theme?: 'info' | 'success' | 'warning' | 'error' | 'loading';
  message: string;
  width: number;
  height?: number;
  duration?: number;
  customCode?: string;
  winId?: number;
}): Promise<void>
```

#### `hideMessage(id?: string)` - 隐藏消息

```typescript
hideMessage(id?: string): Promise<void>
```

#### `showDialog(options)` - 显示对话框

```typescript
showDialog(options: {
  id?: string;
  theme?: 'confirm' | 'alert';
  header?: string;
  body: string;
  confirmBtn?: string;
  cancelBtn?: string;
  closeBtn?: boolean;
  width?: number;
  customCode?: string;
  winId?: number;
}): Promise<void>
```

#### `hideDialog(id?: string)` - 隐藏对话框

```typescript
hideDialog(id?: string): Promise<void>
```

#### `showDrawer(options)` - 显示抽屉

```typescript
showDrawer(options: {
  id?: string;
  placement?: 'right' | 'left' | 'top' | 'bottom';
  header?: string;
  body: string;
  confirmBtn?: string;
  cancelBtn?: string;
  customCode?: string;
  winId?: number;
}): Promise<void>
```

#### `hideDrawer(id?: string)` - 隐藏抽屉

```typescript
hideDrawer(id?: string): Promise<void>
```

#### `showNotification(options)` - 显示通知

```typescript
showNotification(options: {
  id?: string;
  theme?: 'info' | 'success' | 'warning' | 'error';
  placement?: 'top-right' | 'top-left' | 'bottom-left' | 'bottom-right';
  title: string;
  content: string;
  duration?: number;
  width?: number;
  height?: number;
  icon?: boolean;
  closeBtn?: boolean;
  customCode?: string;
  winId?: number;
}): Promise<void>
```

#### `hideNotification(id?: string)` - 隐藏通知

```typescript
hideNotification(id?: string): Promise<void>
```

### 主菜单操作

#### `mainMenu_openMessage()` - 打开消息

```typescript
mainMenu_openMessage(): Promise<void>
```

#### `mainMenu_openWorkBench(options)` - 打开数智工场

```typescript
mainMenu_openWorkBench(options: MainMenuOpenWorkBenchQuery): Promise<boolean | undefined>
```

#### `mainMenu_openSquare()` - 打开广场

```typescript
mainMenu_openSquare(): Promise<void>
```

#### `mainMenu_openDigitalPlatform(options?)` - 打开数字平台

```typescript
mainMenu_openDigitalPlatform(options?: {
  teamId?: string;
  query?: Record<string, string>;
}): Promise<void>
```

#### `mainMenu_openAddressBook()` - 打开地址簿

```typescript
mainMenu_openAddressBook(): Promise<void>
```

#### `mainMenu_openActivities()` - 打开活动

```typescript
mainMenu_openActivities(): Promise<void>
```

#### `mainMenu_openDisk()` - 打开网盘

```typescript
mainMenu_openDisk(): Promise<void>
```

### 消息模块

#### `message_openChat(options)` - 打开聊天

```typescript
message_openChat(options: {
  main: string;
  peer?: string;
  group?: string;
  assistant?: string;
  extInfo?: {
    type: 'service_content';
    content: any;
  };
  rela?: string;
}): Promise<void>
```

#### `message_openMessage(options)` - 打开消息

```typescript
message_openMessage(options: {
  messageId: string;
  type: 'GROUP' | 'SINGLE';
  cardId: string;
  fromId: string;
}): Promise<void>
```

#### `message_openDrawerForWebview(options)` - 打开抽屉（WebView）

```typescript
message_openDrawerForWebview(options: {
  id: string;
  title: string;
  url: string;
}): Promise<void>
```

#### `message_closeDrawerForWebview(options)` - 关闭抽屉（WebView）

```typescript
message_closeDrawerForWebview(options: {
  id: string;
}): Promise<void>
```

### 数智工场模块

#### `workBench_getActiveTeamId()` - 获取当前团队 ID

```typescript
workBench_getActiveTeamId(): Promise<string | undefined>
```

#### `workBench_getTabList()` - 获取标签列表

```typescript
workBench_getTabList(): Promise<WorkBenchTabOptions[]>
```

#### `workBench_openTab(options)` - 打开标签

```typescript
workBench_openTab(options: WorkBenchOpenTabQuery): Promise<boolean | undefined>
```

#### `workBench_closeTab(options)` - 关闭标签

```typescript
workBench_closeTab(options: {
  path_uuid: string;
}): Promise<void>
```

#### `workBench_updateTab(options)` - 更新标签

```typescript
workBench_updateTab(options: {
  path_uuid: string;
  title?: string;
  icon?: string;
  activeIcon?: string;
  beforeCloseOptions?: WorkBenchTabOptions['beforeCloseOptions'];
  beforeRefreshOptions?: WorkBenchTabOptions['beforeRefreshOptions'];
  query?: Record<string, string>;
}): Promise<void>
```

#### `workBench_openTabForIframe(options)` - 打开标签（iframe）

```typescript
workBench_openTabForIframe(options: WorkBenchOpenTabForIframeQuery): Promise<boolean | undefined>
```

#### `workBench_openTabForWebview(options)` - 打开标签（WebView）

```typescript
workBench_openTabForWebview(options: WorkBenchOpenTabForWebviewQuery): Promise<boolean | undefined>
```

#### `workBench_openDrawerForWebview(options)` - 打开抽屉（WebView）

```typescript
workBench_openDrawerForWebview(options: {
  id: string;
  title: string;
  url: string;
  teamId?: string;
}): Promise<void>
```

#### `workBench_closeDrawerForWebview(options)` - 关闭抽屉（WebView）

```typescript
workBench_closeDrawerForWebview(options: {
  id: string;
}): Promise<void>
```

#### `workBench_openTabForEnterprise(options)` - 打开企业标签

```typescript
workBench_openTabForEnterprise(options: WorkBenchOpenTabForEnterpriseQuery): Promise<boolean | undefined>
```

#### `workBench_openTabForMerchantApply(options)` - 打开商户申请标签

```typescript
workBench_openTabForMerchantApply(options: WorkBenchOpenTabForMerchantApplyQuery): Promise<boolean | undefined>
```

#### `workBench_openTabForReceiveDetail(options)` - 打开接收详情标签

```typescript
workBench_openTabForReceiveDetail(options: WorkBenchOpenTabForReceiveDetailQuery): Promise<boolean | undefined>
```

#### `workBench_openTabForRefundDetail(options)` - 打开退款详情标签

```typescript
workBench_openTabForRefundDetail(options: WorkBenchOpenTabForRefundDetailQuery): Promise<boolean | undefined>
```

#### `workBench_openTabForSettlementDetail(options)` - 打开结算详情标签

```typescript
workBench_openTabForSettlementDetail(options: WorkBenchOpenTabForSettlementDetailQuery): Promise<boolean | undefined>
```

#### `workBench_openTeamCertification(options)` - 打开组织认证

```typescript
workBench_openTeamCertification(options: {
  teamId?: string;
}): Promise<void>
```

#### `workBench_reload()` - 刷新数智工场

```typescript
workBench_reload(): Promise<boolean>
```

### 数字平台模块

#### `digitalPlatform_setActiveTeamId(options)` - 设置当前团队 ID

```typescript
digitalPlatform_setActiveTeamId(options: {
  teamId: string;
}): Promise<boolean>
```

#### `digitalPlatform_getActiveTeamId()` - 获取当前团队 ID

```typescript
digitalPlatform_getActiveTeamId(): Promise<string | undefined>
```

#### `digitalPlatform_reload()` - 刷新数字平台

```typescript
digitalPlatform_reload(): Promise<boolean>
```

#### `digitalPlatform_getTabList()` - 获取标签列表

```typescript
digitalPlatform_getTabList(): Promise<DigitalPlatformTabOptions[]>
```

#### `digitalPlatform_openTab(options)` - 打开标签

```typescript
digitalPlatform_openTab(options: DigitalPlatformOpenTabQuery): Promise<boolean | undefined>
```

#### `digitalPlatform_closeTab(options)` - 关闭标签

```typescript
digitalPlatform_closeTab(options: {
  path_uuid: string;
}): Promise<void>
```

#### `digitalPlatform_updateTab(options)` - 更新标签

```typescript
digitalPlatform_updateTab(options: {
  path_uuid: string;
  title?: string;
  icon?: string;
  activeIcon?: string;
  beforeCloseOptions?: {
    title?: string;
    content?: string;
  };
  beforeRefreshOptions?: {
    title?: string;
    content?: string;
  };
  query?: Record<string, string>;
}): Promise<void>
```

#### `digitalPlatform_openTabForWebview(options)` - 打开标签（WebView）

```typescript
digitalPlatform_openTabForWebview(options: DigitalPlatformOpenTabForWebviewQuery): Promise<boolean | undefined>
```

### 广场模块

#### `square_setActiveTeamId(options)` - 设置当前团队 ID

```typescript
square_setActiveTeamId(options: {
  teamId: string;
}): Promise<boolean>
```

#### `square_getActiveTeamId()` - 获取当前团队 ID

```typescript
square_getActiveTeamId(): Promise<string | undefined>
```

#### `square_reload()` - 刷新广场

```typescript
square_reload(): Promise<boolean>
```

#### `square_openTab(options)` - 打开标签

```typescript
square_openTab(options: SquareOpenTabQuery): Promise<boolean>
```

#### `square_closeTab(options)` - 关闭标签

```typescript
square_closeTab(options: {
  path_uuid: string;
  title?: string;
  beforeCloseOptions?: {
    title?: string;
    content?: string;
  };
  beforeRefreshOptions?: {
    title?: string;
    content?: string;
  };
}): Promise<void>
```

#### `square_updateTab(options)` - 更新标签

```typescript
square_updateTab(options: {
  path_uuid: string;
  title?: string;
  icon?: string;
  activeIcon?: string;
  beforeCloseOptions?: {
    title?: string;
    content?: string;
  };
  beforeRefreshOptions?: {
    title?: string;
    content?: string;
  };
  query?: Record<string, string>;
}): Promise<void>
```

#### `square_openTabForWebview(options)` - 打开标签（WebView）

```typescript
square_openTabForWebview(options: WorkBenchOpenTabForWebviewQuery): Promise<boolean | undefined>
```

### 大市场模块

#### `bigMarket_setActiveTeamId(options)` - 设置当前团队 ID

```typescript
bigMarket_setActiveTeamId(options: {
  teamId: string;
}): Promise<boolean>
```

#### `bigMarket_getActiveTeamId()` - 获取当前团队 ID

```typescript
bigMarket_getActiveTeamId(): Promise<string | undefined>
```

#### `bigMarket_reload()` - 刷新大市场

```typescript
bigMarket_reload(): Promise<boolean>
```

#### `bigMarket_openTab(options)` - 打开标签

```typescript
bigMarket_openTab(options: BigMarketOpenTabQuery): Promise<boolean>
```

#### `bigMarket_closeTab(options)` - 关闭标签

```typescript
bigMarket_closeTab(options: {
  path_uuid: string;
  title?: string;
  beforeCloseOptions?: {
    title?: string;
    content?: string;
  };
  beforeRefreshOptions?: {
    title?: string;
    content?: string;
  };
}): Promise<void>
```

#### `bigMarket_updateTab(options)` - 更新标签

```typescript
bigMarket_updateTab(options: {
  path_uuid: string;
  title?: string;
  icon?: string;
  activeIcon?: string;
  beforeCloseOptions?: {
    title?: string;
    content?: string;
  };
  beforeRefreshOptions?: {
    title?: string;
    content?: string;
  };
  query?: Record<string, string>;
}): Promise<void>
```

#### `bigMarket_openTabForWebview(options)` - 打开标签（WebView）

```typescript
bigMarket_openTabForWebview(options: WorkBenchOpenTabForWebviewQuery): Promise<boolean | undefined>
```

### 身份卡管理

#### `openIdentityCardEdit(options)` - 打开身份卡编辑窗口

```typescript
openIdentityCardEdit(options: MsgQuery['jssdk:windows:identityCardEdit:open']['query']): Promise<any>
```

打开身份卡编辑窗口。

**参数：**
- `options`: 身份卡编辑选项

#### `openIdentityCardPreview(options)` - 打开身份卡预览窗口

```typescript
openIdentityCardPreview(options: MsgQuery['jssdk:windows:identityCardPreview:open']['query']): Promise<any>
```

打开身份卡预览窗口。

**参数：**
- `options`: 身份卡预览选项

### 独立窗口标签

#### `windowsTabs_openTab(options)` - 打开标签

```typescript
windowsTabs_openTab(options: {
  options: {
    id?: string;
    title?: string;
    url?: string;
    icon?: string;
    activeIcon?: string;
    hideCloseButton?: boolean;
    beforeCloseOptions?: {
      title: string;
      content?: string;
    };
    beforeRefreshOptions?: {
      title?: string;
      content?: string;
    };
    query?: Record<string, string>;
  };
  isOnlyOneTabHideTabs?: boolean;
  showBrowserTools?: boolean;
  tabsId?: string | 'square' | 'digitalPlatform' | 'smartWorkshop' | 'bigMarket';
  tabsTitle?: string;
}): Promise<void>
```

#### `windowsTabs_closeTab(options)` - 关闭标签

```typescript
windowsTabs_closeTab(options?: {
  id?: string;
  tabsId?: string | 'square' | 'digitalPlatform' | 'smartWorkshop' | 'bigMarket';
}): Promise<void>
```

#### `windowsTabs_getCurrentTab()` - 获取当前标签信息

```typescript
windowsTabs_getCurrentTab(): Promise<MsgQuery['windowsTabs_openTab']['query'] | undefined>
```

### 其他功能

#### `openBrowser(url)` - 打开浏览器

```typescript
openBrowser(url: string): Promise<boolean>
```

#### `openMyHelpWindow(options?)` - 打开帮助中心

```typescript
openMyHelpWindow(options?: {
  id: number;
  module_id: number;
  directory_id: number;
}): Promise<number | undefined>
```

#### `openMyOrderWindow(options?)` - 打开我的订单

```typescript
openMyOrderWindow(options?: any): Promise<number | undefined>
```

#### `openMyInvoiceWindow()` - 打开发票中心

```typescript
openMyInvoiceWindow(): Promise<number | undefined>
```

#### `openSelectMember(options?)` - 打开选人组件

```typescript
openSelectMember(options?: {
  webContentsId?: number;
  query?: {
    menu?: string[];
    max?: number;
    disableList?: any[];
    selectList?: any[];
    changeMenus?: boolean;
    disabledCard?: boolean;
    activeCardId?: string[];
    showMyGroupMenu?: boolean;
    showDropdownMenu?: boolean;
    isImMember?: boolean;
    groupID?: string;
    diyData?: any[];
    extend?: Record<string, any>;
    extendFrom?: string[];
    emptyCardId?: boolean;
    useSelectedGroup?: boolean;
  };
}): Promise<Array<any>>
```

#### `openJoinDigitalPlatformDrawer(options?)` - 打开加入数字平台抽屉

```typescript
openJoinDigitalPlatformDrawer(options?: {
  webContentsId?: number;
  query?: Record<string, any>;
}): Promise<Array<any>>
```

#### `openOrgAuthDrawer(options?)` - 打开组织认证抽屉

```typescript
openOrgAuthDrawer(options?: {
  webContentsId?: number;
  query: {
    region: string;
    teamId: string;
    orgType: string;
    showType: 'detail' | 'edit';
  };
}): Promise<Array<any>>
```

#### `openAddContactsDialog(options?)` - 打开添加联系人对话框

```typescript
openAddContactsDialog(options?: {
  webContentsId?: number;
  query?: {
    searchValue?: string;
  };
}): Promise<Array<any>>
```

#### `openAnnualFeeDrawer(options?)` - 打开年费抽屉

```typescript
openAnnualFeeDrawer(options?: {
  webContentsId?: number;
  query?: {
    teamId: string;
    squareId?: string;
    title?: string;
    open?: boolean;
    inviteCode?: string;
    upgrade?: boolean;
  };
}): Promise<{
  type: 'success' | 'upgrade-loaded' | 'close';
  data?: any;
}>
```

#### `openExternalApp(options)` - 打开外部应用

```typescript
openExternalApp(options: {
  url: string;
  title?: string;
  isInApp?: boolean;
}): Promise<string>
```

#### `setEnv(env)` - 设置环境

```typescript
setEnv(env: 'DEV' | 'TEST' | 'PRE' | 'PROD' | 'RESET'): Promise<void>
```

#### `checkIsManualEnv()` - 检查是否为手动环境

```typescript
checkIsManualEnv(): Promise<boolean>
```

#### `openSettingWindow(query)` - 打开设置窗口

```typescript
openSettingWindow(query: string): Promise<BrowserWindow>
```

#### `openSetGroupWindow()` - 打开设置组窗口

```typescript
openSetGroupWindow(): Promise<BrowserWindow>
```

#### `openMyAddressWindow(query)` - 打开我的地址窗口

```typescript
openMyAddressWindow(query: string): Promise<BrowserWindow>
```

#### `openPolicyDetailWindow(options)` - 打开政策详情窗口

```typescript
openPolicyDetailWindow(options: {
  url: string;
}): Promise<BrowserWindow>
```

#### `openPolicyDetailWindow2(options)` - 打开政策详情窗口 2

```typescript
openPolicyDetailWindow2(options: {
  url: string;
}): Promise<BrowserWindow>
```

#### `logout()` - 注销

```typescript
logout(): Promise<void>
```

#### `openDebugTools()` - 打开调试工具

```typescript
openDebugTools(): Promise<void>
```

## 💡 完整使用示例

> 💡 **建议**: 在每个示例前都先引入 jssdk：
>
> ```ts
> import jssdk from '@lynker-desktop/web';
> ```

### 🎯 实际应用场景

#### 场景 1: 用户登录后获取信息

```typescript
async function handleUserLogin() {
  if (!jssdk.isDesktop) {
    console.warn('请在桌面端环境中使用此功能');
    return;
  }

  try {
    // 获取用户信息
    const userInfo = await jssdk.getUserInfo();
    console.log('用户登录成功:', userInfo.title);

    // 获取配置信息
    const config = await jssdk.getConfig();
    console.log('当前环境:', config.env);

    // 显示欢迎消息
    await jssdk.showMessage({
      theme: 'success',
      message: `欢迎回来，${userInfo.title}！`,
      width: 300,
      duration: 3000,
    });
  } catch (error) {
    console.error('获取用户信息失败:', error);
  }
}
```

#### 场景 2: 文件预览和下载

```typescript
async function handleFileOperation(fileUrl: string, fileName: string) {
  if (!jssdk.isDesktop) {
    // 浏览器环境降级处理
    window.open(fileUrl, '_blank');
    return;
  }

  try {
    // 预览文件
    await jssdk.previewFile({
      title: fileName,
      url: fileUrl,
      type: 'pdf',
      size: 1024 * 1024,
    });

    // 提供下载选项
    const shouldDownload = await jssdk.showDialog({
      theme: 'confirm',
      header: '文件预览',
      body: '是否下载此文件？',
      confirmBtn: '下载',
      cancelBtn: '取消',
    });

    if (shouldDownload) {
      const filePath = await jssdk.downloadFile({
        title: fileName,
        url: fileUrl,
      });
      console.log('文件已下载到:', filePath);
    }
  } catch (error) {
    console.error('文件操作失败:', error);
  }
}
```

#### 场景 3: 资源缓存和文件下载

```typescript
// 缓存资源文件
async function cacheResources(imageUrls: string[]) {
  if (!jssdk.isDesktop) return;

  try {
    const results = await jssdk.cache({
      method: 'add',
      urls: imageUrls,
      onProgress: (progress) => {
        console.log(`缓存进度: ${progress.percentage}%`);
        if (progress.downloadProgress) {
          const speed = (progress.downloadProgress.speed / 1024 / 1024).toFixed(2);
          console.log(`下载速度: ${speed} MB/s`);
        }
      }
    });

    // 处理缓存结果
    if (Array.isArray(results)) {
      results.forEach((result, index) => {
        if (result.success) {
          console.log(`图片 ${index + 1} 缓存成功:`, result.hostPath);
        } else {
          console.error(`图片 ${index + 1} 缓存失败:`, result.error);
        }
      });
    } else if (results.success) {
      console.log('缓存成功:', results.hostPath);
    }

    // 获取缓存统计
    const stats = await jssdk.cache({ method: 'stats' });
    console.log(`缓存总大小: ${(stats.totalSize / 1024 / 1024).toFixed(2)} MB`);
  } catch (error) {
    console.error('缓存失败:', error);
  }
}

// 下载文件并显示进度
async function downloadFileWithProgress(fileUrl: string, fileName: string) {
  if (!jssdk.isDesktop) {
    // 浏览器环境降级处理
    const link = document.createElement('a');
    link.href = fileUrl;
    link.download = fileName;
    link.click();
    return;
  }

  try {
    const result = await jssdk.downloader({
      url: fileUrl,
      fileName: fileName,
      showSaveDialog: true,
      onProgress: (progress) => {
        if (progress.percentage >= 0) {
          console.log(`下载进度: ${progress.percentage.toFixed(2)}%`);
        }
        const speed = (progress.speed / 1024 / 1024).toFixed(2);
        const downloaded = (progress.downloaded / 1024 / 1024).toFixed(2);
        console.log(`已下载: ${downloaded} MB, 速度: ${speed} MB/s`);
      }
    });

    if (result.success) {
      console.log('文件下载成功:', result.filePath);
      await jssdk.showMessage({
        theme: 'success',
        message: '文件下载成功',
        width: 200,
        duration: 3000
      });
    } else {
      throw new Error(result.error || '下载失败');
    }
  } catch (error) {
    console.error('下载失败:', error);
    await jssdk.showMessage({
      theme: 'error',
      message: '文件下载失败',
      width: 200,
      duration: 3000
    });
  }
}

// 视频播放前先缓存
async function playVideoWithCache(videoUrl: string) {
  if (!jssdk.isDesktop) return videoUrl;

  try {
    // 先缓存视频
    const cacheResult = await jssdk.cache({
      method: 'add',
      urls: videoUrl,
      onProgress: (progress) => {
        if (progress.downloadProgress) {
          const percentage = progress.downloadProgress.percentage;
          console.log(`视频缓存进度: ${percentage.toFixed(2)}%`);
        }
      }
    });

    // 使用缓存后的路径
    if (cacheResult && typeof cacheResult === 'object' && 'hostPath' in cacheResult) {
      return cacheResult.hostPath || videoUrl;
    }
    return videoUrl;
  } catch (error) {
    console.error('视频缓存失败，使用原始 URL:', error);
    return videoUrl;
  }
}
```

#### 场景 4: 工作台标签管理

```typescript
async function manageWorkbenchTabs() {
  if (!jssdk.isDesktop) return;

  try {
    // 获取当前标签列表
    const tabs = await jssdk.workBench_getTabList();
    console.log('当前标签:', tabs);

    // 打开新标签
    await jssdk.workBench_openTab({
      options: {
        fullPath: '/workbench/new-tab',
        title: '新标签页',
        icon: 'icon-url',
        teamId: 'team-001',
      },
      openWorkBench: true,
    });

    // 更新标签信息
    await jssdk.workBench_updateTab({
      path_uuid: 'tab-uuid',
      title: '更新后的标题',
      icon: 'new-icon-url',
    });
  } catch (error) {
    console.error('标签管理失败:', error);
  }
}
```

---

### 1. 判断是否在桌面端

```ts
if (jssdk.isDesktop) {
  console.log('当前运行在桌面端环境');
}
```

### 2. 打开桌面端

```ts
jssdk.openDesktop();
// 或带参数
jssdk.openDesktop('{"action": "openChat", "userId": "123"}');
```

### 3. 获取桌面端配置信息

```ts
const config = await jssdk.getConfig();
console.log(config.env); // DEV/TEST/PRE/PROD
console.log(config.h5Host); // 域名配置
console.log(config.token); // 用户token
```

### 4. 获取 LocalStorage

```ts
const token = await jssdk.getLocalStorage('token');
console.log(token);
```

### 5. 设置 LocalStorage

```ts
await jssdk.setLocalStorage({ key: 'token', value: '测试' });
```

### 6. 获取启动/唤起参数

```ts
const launchOptions = await jssdk.getLaunchOptions();
console.log(launchOptions);
```

### 7. 清除启动/唤起参数

```ts
await jssdk.delLaunchOptions();
```

### 8. 打开 web 窗口

```ts
await jssdk.openWebWindow({
  name: '新窗口',
  url: 'https://www.baidu.com',
  extraData: '自定义数据',
  openDevTools: false,
});
```

### 9. 打开浏览器

```ts
await jssdk.openBrowser('https://www.baidu.com');
```

### 10. 打开帮助中心

```ts
await jssdk.openMyHelpWindow({
  id: 1,
  module_id: 2,
  directory_id: 3,
});
// 或无参数
await jssdk.openMyHelpWindow();
```

### 11. 打开我的订单

```ts
await jssdk.openMyOrderWindow();
```

### 12. 打开发票中心

```ts
await jssdk.openMyInvoiceWindow();
```

### 13. 打开选人组件

```ts
const members = await jssdk.openSelectMember({
  query: {
    menu: ['recent', 'friend'],
    max: 5,
    selectList: [],
    changeMenus: true,
  },
});
// 返回数组
console.log(members);
```

### 14. 打开新窗口

```ts
await jssdk.openNewWindow({
  name: '新窗口',
  url: 'https://www.baidu.com',
  width: 800,
  height: 600,
  // 其他 ElectronWindowsManagerOptions 字段
});
```

### 15. 设置 debug 模式

```ts
jssdk.setDebug(true);
```

### 16. 获取用户信息

```ts
const userInfo = await jssdk.getUserInfo();
console.log(userInfo.openid, userInfo.title, userInfo.email);
```

### 17. 使用原始 IPC 渲染器（已废弃）

```ts
// ⚠️ 已废弃，请使用 jssdk.ipc 替代
if (jssdk.ipcRenderer) {
  const result = await jssdk.ipcRenderer.invoke('some-channel', {
    data: 'test',
  });
  console.log(result);
}
```

### 18. 使用基础 IPC 组件

#### 18.1 主进程通信

```ts
// 发送消息到主进程
const result1 = await jssdk.ipc.invokeMain('get-app-version');
console.log('应用版本:', result1);

// 发送消息到主进程（支持并发请求）
const result2 = await jssdk.ipc.invokeMain('get-user-data', { userId: '123' });
console.log('用户数据:', result2);

// 处理主进程发送过来的消息
const handler = jssdk.ipc.handleMain('config-updated', async (newConfig) => {
  console.log('配置已更新:', newConfig);
  // 更新本地状态
  return 'config-received';
});

// 处理完成后可以取消处理器
// handler.cancel();

// 处理应用初始化消息
jssdk.ipc.handleMain('app-ready', async () => {
  console.log('应用已准备就绪');
  return 'renderer-ready';
});
```

#### 18.2 渲染进程通信

```ts
// 发送消息到所有渲染进程
const result3 = await jssdk.ipc.invokeRenderer('sync-data', { data: 'sync' });
console.log('同步结果:', result3);

// 发送消息到所有渲染进程
const result4 = await jssdk.ipc.invokeRenderer('window-message', {
  message: 'Hello from all windows',
});
console.log('窗口响应:', result4);

// 处理其他渲染进程发送的消息
const rendererHandler = jssdk.ipc.handleRenderer('window-communication', async (data) => {
  console.log('收到其他窗口消息:', data);
  return { status: 'received' };
});

// 处理完成后可以取消处理器
// rendererHandler.cancel();

// 处理初始化同步消息
jssdk.ipc.handleRenderer('initial-sync', async (initData) => {
  console.log('初始同步数据:', initData);
  return 'sync-complete';
});
```

#### 18.3 工具方法使用

```ts
// 获取当前渲染进程ID
const currentId = await jssdk.ipc.getCurrentWebContentId();
console.log('当前窗口ID:', currentId);

// 打开开发者工具
await jssdk.ipc.openCurrentWebContentDevTools();
console.log('开发者工具已打开');
```

#### 18.4 实际应用场景

```ts
// 场景1: 监听配置变化
jssdk.ipc.handleRenderer('__APP_CONFIG_CHANGE__', async (config) => {
  console.log('配置已更新:', config);
  // 更新UI状态
  updateUIWithConfig(config);
  return 'OK';
});

// 场景2: 窗口间数据同步
async function syncDataBetweenWindows(data) {
  try {
    // 向所有渲染进程发送同步数据
    await jssdk.ipc.invokeRenderer('sync-data', data);
    console.log('数据同步完成');
  } catch (error) {
    console.error('数据同步失败:', error);
  }
}

// 场景3: 处理主进程事件
jssdk.ipc.handleMain('user-login', async (userInfo) => {
  console.log('用户登录:', userInfo);
  // 更新用户状态
  updateUserState(userInfo);
  return 'login-processed';
});

// 场景4: 错误处理
async function safeIpcCall() {
  try {
    const result = await jssdk.ipc.invokeMain('risky-operation');
    return result;
  } catch (error) {
    console.error('IPC调用失败:', error);
    // 降级处理
    return null;
  }
}

// 场景5: 消息模块通信
async function openMessageChat(options) {
  try {
    // 打开消息窗口
    await jssdk.mainMenu_openMessage();
    // 发送消息到消息模块
    await jssdk.ipc.invokeRenderer('message-open-chat', options);
  } catch (error) {
    console.error('打开聊天失败:', error);
  }
}

// 场景6: 数智工场模块通信
async function manageWorkbench() {
  try {
    // 检查数智工场是否已初始化
    const isInited = await jssdk.ipc.invokeRenderer('zhixing-is-inited');
    if (!isInited) {
      console.warn('数智工场未初始化');
      return;
    }

    // 获取当前团队ID
    const teamId = await jssdk.ipc.invokeRenderer('zhixing-get-active-team-id');
    console.log('当前团队ID:', teamId);

    // 刷新数智工场
    await jssdk.ipc.invokeRenderer('zhixing-reload');
  } catch (error) {
    console.error('数智工场操作失败:', error);
  }
}

// 场景7: 广场模块通信
async function manageSquare() {
  try {
    // 检查广场是否已初始化
    const isInited = await jssdk.ipc.invokeRenderer('square-is-inited');
    if (!isInited) {
      console.warn('广场未初始化');
      return;
    }

    // 设置当前团队ID
    await jssdk.ipc.invokeRenderer('square-set-active-team-id', { teamId: 'team-001' });

    // 获取标签列表
    const tabs = await jssdk.ipc.invokeRenderer('get-square-tab-list');
    console.log('广场标签列表:', tabs);

    // 打开新标签
    await jssdk.ipc.invokeRenderer('open-square-tab-item', {
      label: '新标签',
      fullPath: '/square/new-tab',
      teamId: 'team-001'
    });
  } catch (error) {
    console.error('广场操作失败:', error);
  }
}

// 场景8: 大市场模块通信
async function manageBigMarket() {
  try {
    // 检查大市场是否已初始化
    const isInited = await jssdk.ipc.invokeRenderer('big-market-is-inited');
    if (!isInited) {
      console.warn('大市场未初始化');
      return;
    }

    // 设置当前团队ID
    await jssdk.ipc.invokeRenderer('big-market-set-active-team-id', { teamId: 'team-001' });

    // 刷新大市场
    await jssdk.ipc.invokeRenderer('big-market-reload');
  } catch (error) {
    console.error('大市场操作失败:', error);
  }
}

// 场景9: 应用初始化处理
async function handleAppInitialization() {
  // 处理应用初始化消息
  const initHandler = jssdk.ipc.handleMain('app-ready', async () => {
    console.log('应用已准备就绪');
    // 执行初始化逻辑
    await initializeApp();
    return 'initialization-complete';
  });

  // 发送初始化完成信号
  await jssdk.ipc.invokeMain('renderer-ready');

  // 初始化完成后可以取消处理器
  // initHandler.cancel();
}

// 场景10: 窗口间文件共享
async function shareFileBetweenWindows(fileData) {
  try {
    // 发送文件数据到所有渲染进程
    await jssdk.ipc.invokeRenderer('file-share', {
      fileName: fileData.name,
      fileContent: fileData.content,
      fileType: fileData.type
    });
    console.log('文件共享成功');
  } catch (error) {
    console.error('文件共享失败:', error);
  }
}
```

### 19. 获取唯一 ID

```ts
const uniqueId = await jssdk.getUniqueId();
console.log(uniqueId);
```

### 20. 设置环境

```ts
await jssdk.setEnv('DEV'); // DEV/TEST/PRE/PROD/RESET
```

### 21. 检查是否为手动环境

```ts
const isManual = await jssdk.checkIsManualEnv();
console.log(isManual);
```

### 22. 获取当前窗口

```ts
const win = await jssdk.getCurrentWindow();
console.log(win.id, win.title);
```

### 23. 打开外部窗口

```ts
await jssdk.openExternalWindow({
  url: 'https://www.baidu.com',
  options: {
    width: 800,
    height: 600,
    // 其他 ElectronWindowsManagerOptions 字段
  },
});
```

### 24. 打开设置窗口

```ts
await jssdk.openSettingWindow('general');
```

### 25. 打开设置组窗口

```ts
await jssdk.openSetGroupWindow();
```

### 26. 打开我的地址窗口

```ts
await jssdk.openMyAddressWindow('user-address-key');
```

### 27. 打开政策详情窗口

```ts
await jssdk.openPolicyDetailWindow({ url: 'https://example.com/policy/123' });
```

### 28. 打开政策详情窗口 2

```ts
await jssdk.openPolicyDetailWindow2({ url: 'https://example.com/policy/456' });
```

### 29. 注销

```ts
await jssdk.logout();
```

### 30. 打开调试工具

```ts
await jssdk.openDebugTools();
```

### 31. 预览图片

```ts
await jssdk.previewImage({
  images: ['https://example.com/image1.png', 'https://example.com/image2.png'],
  index: 0,
  url: 'https://example.com/image1.png',
});
```

### 32. 预览视频

```ts
await jssdk.previewVideo({
  title: '演示视频',
  url: 'https://example.com/video.mp4',
  type: 'mp4',
  size: 1024 * 1024 * 10,
});
```

### 33. 预览文件

```ts
await jssdk.previewFile({
  title: '文档',
  url: 'https://example.com/file.pdf',
  type: 'pdf',
  size: 1024 * 1024,
  officeId: 'office-123',
});
```

### 34. 下载文件

```ts
const filePath = await jssdk.downloadFile({
  title: '下载文件',
  url: 'https://example.com/file.pdf',
});
console.log(filePath);
```

### 35. 开始捕获

```ts
await jssdk.startCapture();
```

### 36. 停止捕获

```ts
await jssdk.stopCapture();
```

### 37. 显示消息

```ts
await jssdk.showMessage({
  theme: 'success',
  message: '操作成功',
  width: 200,
  duration: 3000,
});
```

### 38. 显示对话框

```ts
await jssdk.showDialog({
  theme: 'confirm',
  header: '确认操作',
  body: '您确定要执行此操作吗？',
  confirmBtn: '确定',
  cancelBtn: '取消',
});
```

### 39. 显示抽屉

```ts
await jssdk.showDrawer({
  placement: 'right',
  header: '设置',
  body: '抽屉内容',
  confirmBtn: '保存',
  cancelBtn: '取消',
});
```

### 40. 显示通知

```ts
await jssdk.showNotification({
  theme: 'info',
  placement: 'top-right',
  title: '通知标题',
  content: '通知内容',
  duration: 5000,
});
```

### 41. 主菜单打开数智工场

```ts
await jssdk.mainMenu_openWorkBench({
  url: 'https://example.com/workbench',
  selected_path_uuid: 'uuid1',
  click_path_uuid: 'uuid2',
  teamId: 'team-001',
});
```

### 42. 数智工场打开标签

```ts
await jssdk.workBench_openTab({
  options: {
    fullPath: '/workbench/tab',
    title: '标签页',
    icon: 'icon-url',
    teamId: 'team-001',
  },
  openWorkBench: true,
});
```

### 43. 数智工场打开标签用于 iframe

```ts
await jssdk.workBench_openTabForIframe({
  title: 'iframe标签',
  url: 'https://example.com/iframe',
  teamId: 'team-001',
});
```

### 44. 数智工场打开标签用于 webview

```ts
await jssdk.workBench_openTabForWebview({
  title: 'webview标签',
  url: 'https://example.com/webview',
  teamId: 'team-001',
});
```

### 45. 数智工场打开标签用于企业

```ts
await jssdk.workBench_openTabForEnterprise({
  teamId: 'team-001',
  menuId: 'menu-001',
});
```

### 46. 数智工场打开标签用于商户申请

```ts
await jssdk.workBench_openTabForMerchantApply({
  teamId: 'team-001',
});
```

### 47. 数智工场打开标签用于接收详情

```ts
await jssdk.workBench_openTabForReceiveDetail({
  title: '接收详情',
  url: 'https://example.com/receive',
  teamId: 'team-001',
  sn: 'SN123456',
});
```

### 48. 数智工场打开标签用于退款详情

```ts
await jssdk.workBench_openTabForRefundDetail({
  title: '退款详情',
  url: 'https://example.com/refund',
  teamId: 'team-001',
  sn: 'SN654321',
  openLeftMenu: true,
});
```

### 49. 数智工场打开标签用于结算详情

```ts
await jssdk.workBench_openTabForSettlementDetail({
  title: '结算详情',
  url: 'https://example.com/settlement',
  teamId: 'team-001',
  sn: 'SN789012',
});
```

### 50. 数智工场打开组织认证

```ts
await jssdk.workBench_openTeamCertification({
  teamId: 'team-001',
});
```

### 51. 数智工场刷新

```ts
await jssdk.workBench_reload();
```

### 52. 数字平台操作

```ts
// 设置当前团队ID
await jssdk.digitalPlatform_setActiveTeamId({ teamId: 'team-001' });

// 获取当前团队ID
const teamId = await jssdk.digitalPlatform_getActiveTeamId();

// 打开标签
await jssdk.digitalPlatform_openTab({
  options: {
    name: '数字平台页面',
    path: '/digital-platform',
    title: '数字平台',
    icon: 'icon-url',
    teamId: 'team-001',
  },
});

// 刷新
await jssdk.digitalPlatform_reload();
```

### 53. 广场操作

```ts
// 设置当前团队ID
await jssdk.square_setActiveTeamId({ teamId: 'team-001' });

// 打开标签
await jssdk.square_openTab({
  options: {
    label: '广场页面',
    fullPath: '/square',
    teamId: 'team-001',
  },
});

// 刷新
await jssdk.square_reload();
```

### 54. 大市场操作

```ts
// 设置当前团队ID
await jssdk.bigMarket_setActiveTeamId({ teamId: 'team-001' });

// 打开标签
await jssdk.bigMarket_openTab({
  options: {
    label: '大市场页面',
    fullPath: '/big-market',
    teamId: 'team-001',
  },
});

// 刷新
await jssdk.bigMarket_reload();
```

### 55. 独立窗口标签操作

```ts
// 打开标签
await jssdk.windowsTabs_openTab({
  options: {
    id: 'tab-001',
    title: '独立标签',
    url: 'https://example.com',
    icon: 'icon-url',
  },
  tabsId: 'window-001',
  tabsTitle: '窗口标题',
});

// 获取当前标签信息
const currentTab = await jssdk.windowsTabs_getCurrentTab();

// 关闭标签
await jssdk.windowsTabs_closeTab({
  id: 'tab-001',
  tabsId: 'window-001',
});
```

### 56. 消息模块操作

```ts
// 打开聊天
await jssdk.message_openChat({
  main: 'card-001',
  peer: 'card-002',
});

// 打开消息
await jssdk.message_openMessage({
  messageId: 'msg-001',
  type: 'SINGLE',
  cardId: 'card-001',
  fromId: 'user-001',
});

// 打开抽屉（WebView）
await jssdk.message_openDrawerForWebview({
  id: 'drawer-001',
  title: '消息抽屉',
  url: 'https://example.com/message-drawer',
});
```

### 57. 打开外部应用

```ts
await jssdk.openExternalApp({
  url: 'https://example.com',
  title: '外部应用',
  isInApp: true,
});
```

### 58. 打开加入数字平台抽屉

```ts
const result = await jssdk.openJoinDigitalPlatformDrawer({
  query: {
    teamId: 'team-001',
    inviteCode: 'INVITE123',
  },
});
```

### 59. 打开组织认证抽屉

```ts
const result = await jssdk.openOrgAuthDrawer({
  query: {
    region: 'CN',
    teamId: 'team-001',
    orgType: 'enterprise',
    showType: 'detail',
  },
});
```

### 60. 打开添加联系人对话框

```ts
const result = await jssdk.openAddContactsDialog({
  query: {
    searchValue: '联系人名称',
  },
});
```

### 61. 打开年费抽屉

```ts
const result = await jssdk.openAnnualFeeDrawer({
  query: {
    teamId: 'team-001',
    title: '年费管理',
    open: true,
    upgrade: false,
  },
});
```

### 62. 平台检测

```ts
// 获取平台信息
console.log('当前平台:', jssdk.platform); // 'win32' | 'darwin' | 'linux' | 'android' | 'ios' | 'unknown'
console.log('系统架构:', jssdk.arch);     // 'x64' | 'ia32' | 'arm64' | 'unknown'
console.log('网络状态:', jssdk.isOnline); // true | false

// 获取环境信息
console.log('环境信息:', jssdk.env);
```

### 63. 窗口管理

```ts
// 执行 JavaScript
await jssdk.executeJavaScript({
  script: 'console.log("Hello from SDK");'
});

// 窗口操作
await jssdk.focus();           // 聚焦当前窗口
await jssdk.minimize();        // 最小化当前窗口
await jssdk.maximize();        // 最大化当前窗口
await jssdk.setFullScreen({ fullscreen: true }); // 设置全屏

// 浏览器操作
await jssdk.goBack();          // 后退
await jssdk.goForward();       // 前进
await jssdk.reload();          // 重新加载
await jssdk.loadURL({ url: 'https://example.com' }); // 加载新 URL
```

### 64. 工具类操作

```ts
// 获取 H5 URL
const h5Url = jssdk.getH5Url('/path/to/page', 'PROD', true);
console.log('H5 URL:', h5Url);

// 获取带参数的 H5 URL
const urlWithParams = await jssdk.getH5UrlWithParams({
  path: '/dashboard',
  params: { userId: '123', theme: 'dark' }
});

// 应用数据存储
await jssdk.appStore({
  name: 'myApp',
  method: 'set',
  key: 'userSettings',
  value: { theme: 'dark', language: 'zh-CN' }
});

const settings = await jssdk.appStore({
  name: 'myApp',
  method: 'get',
  key: 'userSettings'
});

// Shell 操作
await jssdk.shell({
  method: 'openPath',
  options: '/path/to/file'
});

// 剪贴板操作
await jssdk.clipboard({
  method: 'writeText',
  options: 'Hello World'
});
```

### 65. 视频转码

```ts
// 转码视频
const outputPath = await jssdk.transcodeVideo({
  url: 'https://example.com/video.mp4',
  outputPath: '/path/to/output',
  format: 'mp4',
  quality: 'high'
}, (data) => {
  if (data.type === 'progress') {
    console.log('转码进度:', data.data.progress + '%');
  } else if (data.type === 'complete') {
    console.log('转码完成:', data.data.outputPath);
  } else if (data.type === 'error') {
    console.error('转码失败:', data.error);
  }
});
```

### 66. 身份卡管理

```ts
// 打开身份卡编辑窗口
await jssdk.openIdentityCardEdit({
  cardId: 'card-123',
  mode: 'edit',
  data: {
    name: '张三',
    department: '技术部',
    position: '工程师'
  }
});

// 打开身份卡预览窗口
await jssdk.openIdentityCardPreview({
  cardId: 'card-123',
  readonly: true
});
```

### 67. Pinia 持久化插件使用

```ts
// main.ts
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { createPiniaPersistPlugin } from '@lynker-desktop/web';
import App from './App.vue';

const app = createApp(App);
const pinia = createPinia();

// 添加持久化插件
pinia.use(createPiniaPersistPlugin(), {
  rkPersistEnable: true,
  piniaPersistTempKey: 'my-app'
});

app.use(pinia);
app.mount('#app');

// store/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '',
    avatar: '',
    preferences: {}
  }),
  actions: {
    updateUser(userData) {
      this.name = userData.name;
      this.avatar = userData.avatar;
      // 状态会自动同步到桌面端应用存储
    }
  }
});

// 在组件中使用
const userStore = useUserStore();
userStore.updateUser({ name: '张三', avatar: 'avatar.jpg' });
// 状态变化会自动同步到其他窗口
```

### Pinia 持久化插件

#### `createPiniaPersistPlugin()` - 创建 Pinia 持久化插件

```typescript
createPiniaPersistPlugin(): PiniaPluginContext<{ options: PiniaPersistOptions }>['plugin']
```

创建 Pinia 持久化插件，支持在桌面端环境中自动同步状态到应用存储。

**功能特性：**
- 自动将 Pinia 状态同步到桌面端应用存储
- 支持多窗口状态同步
- 防止死循环更新
- 仅在桌面端环境中生效

**使用示例：**

```typescript
import { createPinia } from 'pinia';
import { createPiniaPersistPlugin } from '@lynker-desktop/web';

const pinia = createPinia();

// 添加持久化插件
pinia.use(createPiniaPersistPlugin(), {
  rkPersistEnable: true,
   /** 是否持久化存储（重启后保留数据）
   * - true: 持久化存储，数据在应用重启后保留
   * - false: 临时存储，数据在应用重启后清空（默认值）
   *
   * 注意：临时存储的文件名会添加 __temp__ 前缀标识
   */
  rkPersistIsPersistent: true
});

// 在组件中使用
const store = useStore();
// 状态变化会自动同步到桌面端应用存储
store.updateData(newData);
```

**配置选项：**

```typescript
interface PiniaPersistOptions {
  rkPersistEnable: boolean;  // 是否启用持久化
  rkPersistIsPersistent?: boolean; // 是否持久化存储（重启后保留数据）
}
```

**注意事项：**
- 仅在桌面端环境中生效，浏览器环境中会被忽略
- 状态同步是异步的，可能存在短暂延迟
- 建议在应用初始化时设置，避免中途启用导致状态不一致

## 📝 类型定义

### 核心接口

#### LynkerSDKConfig

```typescript
interface LynkerSDKConfig {
  readonly env: 'DEV' | 'TEST' | 'PRE' | 'PROD';
  readonly h5Host: h5HostEnum;
  readonly h5Getway: h5GetwayEnum;
  i18n: string;
  token: string;
  launchOptions: string;
  preloadPath: string;
  viteConfig: {
    VITE_APP_TITLE: string;
    VITE_MAP_KEY: string;
    VITE_APP_REGION: string;
    VITE_API_ENV: string;
    VITE_IM_KEY: string;
    VITE_WPS_KEY: string;
    VITE_UMEN_PID: string;
    VITE_USER_NODE_ENV: string;
    VITE_APP_CONFIG_INFO: string;
    VITE_APP_MAS: boolean;
  };
}
```

#### UserInfo

```typescript
interface UserInfo {
  openid: string;
  title: string;
  avatar: string;
  gender: number;
  email: string;
  cellphone: string;
  telephone: string;
  birthday: number;
  region: string;
  hidden: null;
  slogan: string;
  attachments: {
    options: AttachmentOption[];
  };
  area: string;
  link_id: string;
  account_email: string;
  account_mobile: string;
  account_mobile_region: string;
  removed: boolean;
  address: string;
  apply_removed: boolean;
  psn_auth: boolean;
  channel: string;
  channel_params: string;
  account_login_info: AccountLoginInfo;
}
```

#### WorkBenchTabOptions

```typescript
interface WorkBenchTabOptions {
  fullPath: string;
  title: string;
  icon: string;
  teamId?: string;
  activeIcon?: string;
  pathName?: string;
  updateKey?: string;
  type?: number;
  query?: Record<string, string>;
  beforeCloseOptions?: {
    title?: string;
    content?: string;
  };
  beforeRefreshOptions?: {
    title?: string;
    content?: string;
  };
}
```

### 枚举类型

#### h5HostEnum

```typescript
enum h5HostEnum {
  'TEST' = 'https://web-qa.ringkol.com',
  'DEV' = 'https://web-dev.ringkol.com',
  'PRE' = 'https://web-pre.ringkol.com',
  'PROD' = 'https://web.ringkol.com',
}
```

#### h5GetwayEnum

```typescript
enum h5GetwayEnum {
  'TEST' = 'https://h5-qa.ringkol.com',
  'DEV' = 'https://h5-dev.ringkol.com',
  'PRE' = 'https://h5-pre.ringkol.com',
  'PROD' = 'https://h5.ringkol.com',
}
```

#### RendererIPC

```typescript
/**
 * 基于 @lynker-desktop/electron-ipc 的渲染进程 IPC 通信类
 * 提供类型安全的进程间通信功能，支持并发请求和 requestId 机制
 */
class RendererIPC {
  /**
   * 原生 ipcRenderer 实例
   * 提供对 Electron 原生 IPC 功能的访问
   */
  static get ipcRenderer(): Electron.IpcRenderer;

  // ==================== 主进程通信 ====================

  /**
   * 发送消息到主进程
   * 使用 Electron 原生的 invoke 方法，支持并发请求
   *
   * @param channel 消息通道名称
   * @param args 传递给处理器的参数
   * @returns Promise<any> 返回处理结果
   *
   * 特性：
   * - 支持并发请求，不会互相干扰
   * - 使用 Electron 原生 invoke 方法
   * - 自动处理错误和超时
   */
  static invokeMain(channel: string, ...args: any[]): Promise<any>;

  /**
   * 处理主进程发送过来的消息
   *
   * @param channel 消息通道名称
   * @param handler 处理函数，接收除 requestId 外的所有参数
   * @returns 返回取消函数，用于移除处理器
   *
   * 特性：
   * - 返回取消函数，支持动态移除处理器
   * - 处理函数必须返回 Promise
   */
  static handleMain(
    channel: string,
    handler: (...args: any[]) => Promise<any>
  ): {
    cancel: () => void;
  };

  // ==================== 渲染进程通信 ====================

  /**
   * 发送消息到所有渲染进程
   * 使用唯一的 requestId 确保并发请求不会互相干扰
   *
   * @param channel 消息通道名称
   * @param args 传递给渲染进程的参数
   * @returns Promise<any> 返回渲染进程的处理结果
   *
   * 特性：
   * - 向所有渲染进程发送消息
   * - 使用 requestId 机制避免并发冲突
   * - 自动等待渲染进程加载完成
   */
  static invokeRenderer(channel: string, ...args: any[]): Promise<any>;


  /**
   * 处理渲染进程发送过来的消息
   * @param channel 消息通道名称
   * @param handler 处理函数，接收除 requestId 外的所有参数
   * @returns 返回取消函数，用于移除处理器
   *
   * 特性：
   * - 返回取消函数，支持动态移除处理器
   * - 处理函数必须返回 Promise
   */
  static handleRenderer(
    channel: string,
    handler: (...args: any[]) => Promise<any>
  ): {
    cancel: () => void;
  };

  // ==================== 工具方法 ====================

  /**
   * 获取当前渲染进程的 WebContents ID
   * @returns Promise<number> 当前渲染进程的 ID
   */
  static getCurrentWebContentId(): Promise<number>;

  /**
   * 打开当前窗口的开发者工具
   * @returns Promise<number> 操作结果
   */
  static openCurrentWebContentDevTools(): Promise<number>;
}
```

#### MainIPC

```typescript
/**
 * 主进程 IPC 通信类
 * 负责处理主进程与渲染进程之间的消息通信
 * 使用单例模式确保全局唯一实例
 *
 * 修复说明：
 * - 为每个请求生成唯一的 requestId，解决并发请求数据错乱问题
 * - 确保请求和响应能够正确匹配，避免多个并发请求互相干扰
 */
class MainIPC {
  static instance: MainIPC;
  private eventEmitter: EventEmitter;

  constructor();

  // ==================== 主进程通信 ====================

  /**
   * 发送给主进程消息
   * 使用唯一的 requestId 确保并发请求不会互相干扰
   *
   * @param channel 消息通道名称
   * @param args 传递给处理器的参数
   * @returns Promise<unknown> 返回处理结果
   *
   * 修复说明：
   * - 为每个请求生成唯一的 requestId
   * - 监听 `${channel}-reply-${requestId}` 事件，确保只接收对应请求的回复
   * - 发送请求时包含 requestId，让处理器知道如何回复
   */
  invokeMain(channel: string, ...args: any[]): Promise<unknown>;

  /**
   * 处理主进程发送过来的消息
   * 持续监听指定通道的消息
   *
   * @param channel 消息通道名称
   * @param handler 处理函数，接收除 requestId 外的所有参数
   * @returns 返回取消函数，用于移除处理器
   *
   * 修复说明：
   * - 接收 requestId 作为第一个参数
   * - 使用 `${channel}-reply-${requestId}` 发送回复，确保回复给正确的请求
   * - 支持多个并发请求，每个请求都有独立的回复通道
   */
  handleMain(
    channel: string,
    handler: (...args: any[]) => Promise<any>
  ): {
    cancel: () => void;
  };

  // ==================== 渲染进程通信 ====================

  /**
   * 发送给渲染进程消息
   * 使用唯一的 requestId 确保并发请求不会互相干扰
   *
   * @param webContents 目标渲染进程的 WebContents 对象
   * @param channel 消息通道名称
   * @param args 传递给渲染进程的参数
   * @returns Promise<any> 返回渲染进程的处理结果
   *
   * 修复说明：
   * - 为每个请求生成唯一的 requestId
   * - 监听 `${channel}-reply-${requestId}` 事件，确保只接收对应请求的回复
   * - 发送请求时包含 requestId，让渲染进程知道如何回复
   * - 等待渲染进程加载完成后再发送消息，确保消息能够被正确接收
   */
  invokeRenderer(
    webContents: Electron.WebContents,
    channel: string,
    ...args: any[]
  ): Promise<any>;

  /**
   * 发送给所有渲染进程消息
   * 向所有渲染进程发送消息并收集所有响应
   *
   * @param channel 消息通道名称
   * @param args 传递给所有渲染进程的参数
   * @returns Promise<any> 返回所有渲染进程的处理结果数组
   *
   * 修复说明：
   * - 为每个请求生成唯一的 requestId
   * - 收集所有渲染进程的响应，当所有响应都收到时才 resolve
   * - 使用 `${channel}-reply-${requestId}` 确保只接收对应请求的回复
   * - 如果没有渲染进程，直接返回空数组
   * - 等待每个渲染进程加载完成后再发送消息
   */
  invokeAllRenderer(channel: string, ...args: any[]): Promise<any>;

  /**
   * 处理渲染进程发送过来的消息
   * 持续监听指定通道的消息，支持超时处理
   *
   * @param channel 消息通道名称
   * @param handler 处理函数，接收除 requestId 外的所有参数
   * @returns 返回取消函数，用于移除处理器
   *
   * 修复说明：
   * - 接收 requestId 作为第一个参数
   * - 使用 ipcMain.handle 替代 ipcMain.on，提供更好的错误处理
   * - 支持 8 秒超时机制，避免长时间等待
   * - 支持并发请求，每个请求都有独立的处理流程
   * - 提供详细的错误日志记录
   */
  handleRenderer(
    channel: string,
    handler: (...args: any[]) => Promise<any>
  ): {
    cancel: () => void;
  };

  // ==================== 消息中继 ====================

  /**
   * 初始化消息中继功能
   * 设置消息转发和回复机制，支持跨渲染进程通信
   *
   * 功能说明：
   * - relay-message: 转发消息到指定的渲染进程或所有渲染进程
   * - relay-reply: 处理回复消息，广播给所有渲染进程
   * - __GetCurrentWebContentId__: 获取当前 WebContent ID
   * - __OpenCurrentWebContentDevTools__: 打开当前 WebContent 的开发者工具
   */
  relayMessage(): void;
}

/**
 * 全局 MainIPC 实例
 * 使用全局变量确保单例模式，避免重复创建实例
 */
declare const mainIPC: MainIPC;

/**
 * 初始化 IPC 通信系统
 * 设置消息中继功能，确保跨进程通信正常工作
 *
 * @returns MainIPC 实例
 *
 * 功能说明：
 * - 检查是否已经初始化，避免重复初始化
 * - 设置消息中继功能，支持跨渲染进程通信
 * - 返回全局 MainIPC 实例
 */
declare const initialize: () => MainIPC;
```

## ❓ 常见问题

### Q: 如何判断当前是否在桌面端环境？

A: 使用 `jssdk.isDesktop` 属性进行判断：

```javascript
if (jssdk.isDesktop) {
  // 桌面端环境
} else {
  // 浏览器环境
}
```

### Q: 为什么某些 API 调用失败？

A: 可能的原因包括：

- 未在桌面端环境中运行
- 桌面端应用版本过低
- 网络连接问题
- 权限不足

### Q: 如何处理异步操作？

A: 所有 API 方法都是异步的，建议使用 async/await：

```javascript
try {
  const result = await jssdk.getUserInfo();
  console.log(result);
} catch (error) {
  console.error('操作失败:', error);
}
```

### Q: 如何开启调试模式？

A: 调用 `jssdk.setDebug(true)` 开启调试日志：

```javascript
jssdk.setDebug(true);
// 现在会输出详细的调试信息
```

### Q: IPC 通信失败怎么办？

A: 可能的原因和解决方案：

- 检查频道名称是否正确
- 确保主进程已注册对应的处理器
- 检查参数类型是否匹配
- 使用 try-catch 处理异步错误

### Q: 如何选择合适的 IPC 方法？

A: 根据使用场景选择：

- `invokeMain` / `handleMain`: 主进程通信，支持并发请求
- `invokeRenderer` / `handleRenderer`: 广播消息到所有渲染进程
- 使用 `cancel()` 方法可以动态移除处理器

### Q: IPC 消息处理函数必须返回 Promise 吗？

A: 是的，所有 IPC 消息处理函数都必须返回 Promise，即使没有异步操作：

```javascript
// ✅ 正确
jssdk.ipc.handleMain('sync-data', async (data) => {
  console.log(data);
  return 'success'; // 返回普通值
});

// ✅ 正确
jssdk.ipc.handleMain('async-operation', async (data) => {
  const result = await someAsyncOperation(data);
  return result; // 返回Promise
});
```

### Q: 如何调试 IPC 通信问题？

A: 可以通过以下方式调试：

```javascript
// 1. 开启调试模式
jssdk.setDebug(true);

// 2. 添加日志记录
jssdk.ipc.handleMain('debug-channel', async (data) => {
  console.log('收到主进程消息:', data);
  return { received: true, ti