npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lynker-desktop/web

v0.0.161

Published

lynker-web-sdk

Downloads

615

Readme


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

Lynker Desktop Web SDK

npm version

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

📋 目录

📦 安装

npm

npm install @lynker-desktop/web

yarn

yarn add @lynker-desktop/web

pnpm

pnpm add @lynker-desktop/web

🚀 快速开始

基础用法

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

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

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

TypeScript 支持

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

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

环境检测

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

📚 API 参考

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

基础功能

isDesktop - 检查是否在桌面端

readonly isDesktop: boolean

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

platform - 获取平台信息

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

获取当前运行平台信息。

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

arch - 获取架构信息

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

获取当前系统架构信息。

返回值: 架构标识符,包括 x64、ia32、arm64 或未知架构。

env - 获取环境信息

readonly env: object

获取 Electron 环境信息对象。

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

isOnline - 检查网络状态

readonly isOnline: boolean

检查当前网络连接状态。

返回值: true 表示在线,false 表示离线。

fs - 获取文件系统

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

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

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

path - 获取路径模块

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

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

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

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

openDesktop(launchOptions?: string): void

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

参数:

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

示例:

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

getConfig() - 获取配置信息

getConfig(): Promise<LynkerSDKConfig>

获取桌面端的配置信息。

返回值: LynkerSDKConfig 对象,包含环境、域名、国际化等配置。

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

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

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

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

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

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

getLaunchOptions() - 获取启动参数

getLaunchOptions(): Promise<string | null>

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

delLaunchOptions() - 清除启动参数

delLaunchOptions(): Promise<string | null>

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

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

getRandomUUID(key?: string): string

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

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

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

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

参数:

  • path: 路径字符串
  • env (可选): 环境标识,默认为 'PROD'
  • clearCache (可选): 是否清除缓存,默认为 false

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

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

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

openPath(query) - 打开路径

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

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

appStore(options) - 应用数据存储

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

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

shell(options) - Shell 操作

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

执行系统 Shell 命令。

clipboard(options) - 剪贴板操作

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

操作系统剪贴板。

nativeImage(options) - 原生图片操作

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

操作原生图片对象。

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

setDebug(debug: boolean): void

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

原始 ipcRenderer - ipcRenderer

readonly ipcRenderer: Electron.IpcRenderer | null

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

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

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

基础 IPC 组件 - ipc

readonly ipc: RendererIPC

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

功能特性:

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

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

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

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

参数:

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

返回值: Promise - 主进程的响应数据

特性:

  • 支持并发请求,不会互相干扰
  • 使用 Electron 原生 invoke 方法
  • 自动处理错误和超时

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

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

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

参数:

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

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

特性:

  • 返回取消函数,支持动态移除处理器
  • 处理函数必须返回 Promise
渲染进程通信

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

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

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

参数:

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

返回值: Promise - 渲染进程的响应数据

特性:

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

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

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

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

参数:

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

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

特性:

  • 返回取消函数,支持动态移除处理器
  • 处理函数必须返回 Promise
工具方法

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

static getCurrentWebContentId(): Promise<number>

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

返回值: Promise - 当前渲染进程的 ID

openCurrentWebContentDevTools() - 打开开发者工具

static openCurrentWebContentDevTools(): Promise<number>

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

返回值: Promise - 操作结果

窗口管理

executeJavaScript(options) - 执行 JavaScript

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

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

参数:

  • name (可选): 窗口名称
  • webContentsId (可选): WebContents ID
  • script (可选): 要执行的 JavaScript 代码

getWebContentsId(options) - 获取 WebContents ID

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

获取指定窗口的 WebContents ID。

focus(options) - 聚焦窗口

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

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

blur(options) - 失焦窗口

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

使指定窗口失去焦点。

minimize(options) - 最小化窗口

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

最小化指定窗口。

maximize(options) - 最大化窗口

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

最大化指定窗口。

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

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

取消最大化指定窗口。

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

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

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

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

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

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

setFullScreen(options) - 设置窗口全屏

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

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

goBack(options) - 后退

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

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

reload(options) - 重新加载

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

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

goForward(options) - 前进

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

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

loadURL(options) - 加载 URL

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

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

close(options) - 关闭窗口

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

关闭指定窗口。

restore(options) - 恢复窗口

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

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

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

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

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

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

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

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

openWebWindow(options) - 打开 Web 窗口

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

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

openNewWindow(options) - 打开新窗口

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

openExternalWindow(options) - 打开外部窗口

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

openWindow(options, tabsID?) - 打开窗口(简化版)

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

closeWindow(query?) - 关闭窗口

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

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

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

用户信息

getUserInfo() - 获取用户信息

getUserInfo(): Promise<UserInfo>

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

返回值: UserInfo 对象,包含用户 ID、昵称、头像、邮箱等信息。

getUniqueId() - 获取唯一 ID

getUniqueId(): Promise<string>

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

文件操作

previewImage(options) - 预览图片

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

previewVideo(options) - 预览视频

previewVideo(options: PreviewVideoOptions): Promise<void>

previewFile(options) - 预览文件

previewFile(options: PreviewFileOptions): Promise<void>

downloadFile(options) - 下载文件

downloadFile(options: DownloadFileOptions): Promise<string>

startCapture() - 开始捕获

startCapture(): Promise<void>

stopCapture() - 停止捕获

stopCapture(): Promise<void>

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

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

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

参数:

  • options: 视频下载选项
  • callbacks (可选): 转码进度回调函数

返回值: Promise - 转码后的文件路径

回调数据:

interface VideoTranscodeChangeCallback {
  type: 'progress' | 'complete' | 'error';
  data?: {
    outputPath: string;
    progress: number;
  };
  error?: string;
}

cache(options) - 资源缓存

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 数组(仅 adddelete 方法需要)
  • force (可选): 是否强制重新下载(默认 false)
  • id (可选): 唯一标识符
  • onProgress (可选): 进度回调函数

返回值:

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

使用示例:

// 缓存单个资源
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) - 下载文件

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: 最大重定向次数

返回值:

{
  success: boolean;        // 是否成功
  filePath?: string;       // 下载的文件路径
  error?: string;         // 错误信息
  size?: number;          // 文件大小(字节)
}

使用示例:

// 基本下载
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) - 显示消息

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) - 隐藏消息

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

showDialog(options) - 显示对话框

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) - 隐藏对话框

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

showDrawer(options) - 显示抽屉

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) - 隐藏抽屉

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

showNotification(options) - 显示通知

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) - 隐藏通知

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

主菜单操作

mainMenu_openMessage() - 打开消息

mainMenu_openMessage(): Promise<void>

mainMenu_openWorkBench(options) - 打开数智工场

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

mainMenu_openSquare() - 打开广场

mainMenu_openSquare(): Promise<void>

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

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

mainMenu_openAddressBook() - 打开地址簿

mainMenu_openAddressBook(): Promise<void>

mainMenu_openActivities() - 打开活动

mainMenu_openActivities(): Promise<void>

mainMenu_openDisk() - 打开网盘

mainMenu_openDisk(): Promise<void>

消息模块

message_openChat(options) - 打开聊天

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

message_openMessage(options) - 打开消息

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

message_openDrawerForWebview(options) - 打开抽屉(WebView)

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

message_closeDrawerForWebview(options) - 关闭抽屉(WebView)

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

数智工场模块

workBench_getActiveTeamId() - 获取当前团队 ID

workBench_getActiveTeamId(): Promise<string | undefined>

workBench_getTabList() - 获取标签列表

workBench_getTabList(): Promise<WorkBenchTabOptions[]>

workBench_openTab(options) - 打开标签

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

workBench_closeTab(options) - 关闭标签

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

workBench_updateTab(options) - 更新标签

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)

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

workBench_openTabForWebview(options) - 打开标签(WebView)

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

workBench_openDrawerForWebview(options) - 打开抽屉(WebView)

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

workBench_closeDrawerForWebview(options) - 关闭抽屉(WebView)

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

workBench_openTabForEnterprise(options) - 打开企业标签

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

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

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

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

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

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

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

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

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

workBench_openTeamCertification(options) - 打开组织认证

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

workBench_reload() - 刷新数智工场

workBench_reload(): Promise<boolean>

数字平台模块

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

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

digitalPlatform_getActiveTeamId() - 获取当前团队 ID

digitalPlatform_getActiveTeamId(): Promise<string | undefined>

digitalPlatform_reload() - 刷新数字平台

digitalPlatform_reload(): Promise<boolean>

digitalPlatform_getTabList() - 获取标签列表

digitalPlatform_getTabList(): Promise<DigitalPlatformTabOptions[]>

digitalPlatform_openTab(options) - 打开标签

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

digitalPlatform_closeTab(options) - 关闭标签

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

digitalPlatform_updateTab(options) - 更新标签

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)

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

广场模块

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

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

square_getActiveTeamId() - 获取当前团队 ID

square_getActiveTeamId(): Promise<string | undefined>

square_reload() - 刷新广场

square_reload(): Promise<boolean>

square_openTab(options) - 打开标签

square_openTab(options: SquareOpenTabQuery): Promise<boolean>

square_closeTab(options) - 关闭标签

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

square_updateTab(options) - 更新标签

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)

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

大市场模块

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

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

bigMarket_getActiveTeamId() - 获取当前团队 ID

bigMarket_getActiveTeamId(): Promise<string | undefined>

bigMarket_reload() - 刷新大市场

bigMarket_reload(): Promise<boolean>

bigMarket_openTab(options) - 打开标签

bigMarket_openTab(options: BigMarketOpenTabQuery): Promise<boolean>

bigMarket_closeTab(options) - 关闭标签

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

bigMarket_updateTab(options) - 更新标签

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)

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

身份卡管理

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

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

打开身份卡编辑窗口。

参数:

  • options: 身份卡编辑选项

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

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

打开身份卡预览窗口。

参数:

  • options: 身份卡预览选项

独立窗口标签

windowsTabs_openTab(options) - 打开标签

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) - 关闭标签

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

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

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

其他功能

openBrowser(url) - 打开浏览器

openBrowser(url: string): Promise<boolean>

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

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

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

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

openMyInvoiceWindow() - 打开发票中心

openMyInvoiceWindow(): Promise<number | undefined>

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

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?) - 打开加入数字平台抽屉

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

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

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

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

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

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

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) - 打开外部应用

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

setEnv(env) - 设置环境

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

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

checkIsManualEnv(): Promise<boolean>

openSettingWindow(query) - 打开设置窗口

openSettingWindow(query: string): Promise<BrowserWindow>

openSetGroupWindow() - 打开设置组窗口

openSetGroupWindow(): Promise<BrowserWindow>

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

openMyAddressWindow(query: string): Promise<BrowserWindow>

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

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

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

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

logout() - 注销

logout(): Promise<void>

openDebugTools() - 打开调试工具

openDebugTools(): Promise<void>

💡 完整使用示例

💡 建议: 在每个示例前都先引入 jssdk:

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

🎯 实际应用场景

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

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: 文件预览和下载

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: 资源缓存和文件下载

// 缓存资源文件
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: 工作台标签管理

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. 判断是否在桌面端

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

2. 打开桌面端

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

3. 获取桌面端配置信息

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

4. 获取 LocalStorage

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

5. 设置 LocalStorage

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

6. 获取启动/唤起参数

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

7. 清除启动/唤起参数

await jssdk.delLaunchOptions();

8. 打开 web 窗口

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

9. 打开浏览器

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

10. 打开帮助中心

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

11. 打开我的订单

await jssdk.openMyOrderWindow();

12. 打开发票中心

await jssdk.openMyInvoiceWindow();

13. 打开选人组件

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

14. 打开新窗口

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

15. 设置 debug 模式

jssdk.setDebug(true);

16. 获取用户信息

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

17. 使用原始 IPC 渲染器(已废弃)

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

18. 使用基础 IPC 组件

18.1 主进程通信

// 发送消息到主进程
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 渲染进程通信

// 发送消息到所有渲染进程
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 工具方法使用

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

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

18.4 实际应用场景

// 场景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

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

20. 设置环境

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

21. 检查是否为手动环境

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

22. 获取当前窗口

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

23. 打开外部窗口

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

24. 打开设置窗口

await jssdk.openSettingWindow('general');

25. 打开设置组窗口

await jssdk.openSetGroupWindow();

26. 打开我的地址窗口

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

27. 打开政策详情窗口

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

28. 打开政策详情窗口 2

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

29. 注销

await jssdk.logout();

30. 打开调试工具

await jssdk.openDebugTools();

31. 预览图片

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

32. 预览视频

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

33. 预览文件

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

34. 下载文件

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

35. 开始捕获

await jssdk.startCapture();

36. 停止捕获

await jssdk.stopCapture();

37. 显示消息

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

38. 显示对话框

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

39. 显示抽屉

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

40. 显示通知

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

41. 主菜单打开数智工场

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

42. 数智工场打开标签

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

51. 数智工场刷新

await jssdk.workBench_reload();

52. 数字平台操作

// 设置当前团队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. 广场操作

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

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

// 刷新
await jssdk.square_reload();

54. 大市场操作

// 设置当前团队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. 独立窗口标签操作

// 打开标签
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. 消息模块操作

// 打开聊天
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. 打开外部应用

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

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

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

59. 打开组织认证抽屉

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

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

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

61. 打开年费抽屉

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

62. 平台检测

// 获取平台信息
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. 窗口管理

// 执行 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. 工具类操作

// 获取 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. 视频转码

// 转码视频
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. 身份卡管理

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

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

67. Pinia 持久化插件使用

// 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 持久化插件

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

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

功能特性:

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

使用示例:

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);

配置选项:

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

注意事项:

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

📝 类型定义

核心接口

LynkerSDKConfig

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

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

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

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

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

/**
 * 基于 @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

/**
 * 主进程 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 属性进行判断:

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

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

A: 可能的原因包括:

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

Q: 如何处理异步操作?

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

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

Q: 如何开启调试模式?

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

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

Q: IPC 通信失败怎么办?

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

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

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

A: 根据使用场景选择:

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

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

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

// ✅ 正确
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: 可以通过以下方式调试:

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

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