工作台应用开发
Lim 工作台中的应用(子应用)通过 @lim/jssdk 与客户端基座通信:路由导航、窗口管理、HTTP 代理、登录态同步等能力统一封装为 SDK 接口,子应用无需关心底层 IPC 细节。
ts
import { sdk } from '@lim/jssdk'工作台支持两类应用接入:
- 内部应用(internal):应用包由 Lim 客户端统一安装、运行
- 外部应用(external):由管理员配置 URL 接入的网页应用
注意:SDK 依赖 Lim 客户端运行环境。在浏览器中独立调试时 IPC 桥不可用,相关调用会报“IPC 不可用”或静默降级,建议以 Lim 客户端作为调试宿主。
快速开始
ts
import axios from 'axios'
import { sdk } from '@lim/jssdk'
// 以本地 axios 实例为例
const http = axios.create()
// 1. 启动时预拉一次登录态(避免首屏请求早于 token 就绪)
const token = await sdk.auth.getToken()
if (token) {
http.defaults.headers.common['Authorization'] = `${token.tokenType} ${token.accessToken}`
}
// 2. 订阅 token 变更 / 清除,让本地请求头与主进程始终一致
sdk.auth.onTokenChanged((info) => {
http.defaults.headers.common['Authorization'] = `${info.tokenType} ${info.accessToken}`
})
sdk.auth.onTokenCleared(() => {
delete http.defaults.headers.common['Authorization']
})
// 3. 让基座代为发起 HTTP 请求(自动携带登录态)
const resp = await sdk.http.get('/api/v1/users/me')路由导航(sdk.router)
| 方法 | 说明 |
|---|---|
push(params) | 跳转到指定路径,支持跨应用跳转 |
replace(params) | 替换当前页 |
back() | 返回上一页 |
PushParams 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
path | string | 目标路径(必填) |
app | string | 目标子应用名(跨应用跳转时传,同应用内可省略) |
query | Record<string, string> | query 参数 |
ts
// 同应用内跳转
await sdk.router.push({ path: '/order/list', query: { status: 'open' } })
// 跨应用跳转
await sdk.router.push({ app: 'approval', path: '/detail/42' })
await sdk.router.replace({ path: '/home' })
await sdk.router.back()窗口与视图(sdk.app)
| 方法 | 说明 |
|---|---|
show({ name }) | 切换到已打开的视图(仅切换,不创建) |
close({ name }) | 关闭视图 |
open({ name, extraQuery?, windowName? }) | 在独立窗口中打开子应用 |
web({ url, windowName? }) | 在独立窗口中打开任意 URL(每次新建窗口) |
getInfo({ name }) | 获取应用信息(返回 AppInfo) |
getInfo 返回的 AppInfo:
| 字段 | 说明 |
|---|---|
appId | 应用 ID |
name | 应用名称 |
appType | internal / external |
currentUrl | 当前运行 URL |
description | 应用描述(可选) |
典型用法——拿到应用当前地址后拼接子页面,在独立窗口中打开:
ts
const info = await sdk.app.getInfo({ name: 'im-service' })
if (!info?.currentUrl) return
sdk.app.web({
url: `${info.currentUrl.replace(/\/$/, '')}/article/${articleId}`,
windowName: '文章详情',
})HTTP 请求(sdk.http)
除了自行管理 token 的本地请求外,子应用也可以直接通过基座代理发起请求:自动注入登录态,收到 401 时基座会自动刷新 token 并重试一次。
| 方法 | 说明 |
|---|---|
request(config) | 通用请求 |
get(url, options?) | GET |
post(url, data?, options?) | POST |
put(url, data?, options?) | PUT |
patch(url, data?, options?) | PATCH |
delete(url, options?) | DELETE |
请求配置 HttpRequestConfig:
| 字段 | 类型 | 说明 |
|---|---|---|
url | string | 必填。http(s):// 完整地址(校验协议白名单),或以 / 开头的相对路径(自动拼接 API 基础地址) |
method | GET / POST / PUT / PATCH / DELETE | 请求方法,默认 GET |
params | Record<string, unknown> | 查询参数 |
data | unknown | 请求体(POST / PUT / PATCH) |
headers | Record<string, string> | 自定义请求头 |
withAuth | boolean | 是否自动携带登录态,默认 true;传 false 表示无认证请求 |
timeout | number | 超时毫秒数,默认 15000 |
responseType | json / text / blob / arraybuffer | 响应类型,默认 json |
返回 HttpResponse:{ status, data, headers, error? }。
- HTTP 层失败(网络错误、非 2xx、URL 不合法)时 SDK 直接抛出
Error - 业务错误码请在拿到
data后自行判断(例如code !== '00000')
ts
// 相对路径:自动拼接 API 基础地址
const resp = await sdk.http.post('/api/v1/orders', payload)
if (resp.data.code !== '00000') throw new Error(resp.data.msg)
// 完整地址:须为 http(s) 协议,且可关闭登录态注入
await sdk.http.get('https://api.example.com/health', { withAuth: false })
// 获取二进制内容
const blob = await sdk.http.get('/api/v1/files/1/download', { responseType: 'blob' })登录态同步(sdk.auth)
设计原则:refreshToken 永不离开主进程,子应用只能拿到 accessToken / tokenType。
| 方法 | 说明 |
|---|---|
getToken() | 主动拉取当前 token:{ accessToken, tokenType, expiresIn? } 或 null |
refresh() | 主动触发刷新(主进程加锁,并发重复调用只刷新一次),失败返回 null |
hasRefreshToken() | 主进程是否持有可用的 refreshToken(可用于 UI 状态展示) |
onTokenChanged(handler) | 订阅 token 变更(含主进程自动刷新),返回取消订阅函数 |
onTokenCleared(handler) | 订阅 token 清除(退出登录 / 刷新失败),返回取消订阅函数 |
建议启动时先 getToken() 预拉一次,再订阅两个事件持续同步,保证请求头与主进程一致:
ts
const offChanged = sdk.auth.onTokenChanged(({ accessToken, tokenType }) => {
// 更新本地 axios 默认 header
})
const offCleared = sdk.auth.onTokenCleared(() => {
// 清空本地 header 与缓存
})
// 组件卸载 / 应用退出时取消订阅
offChanged()
offCleared()事件与底层调用
| 方法 | 说明 |
|---|---|
sdk.on(event, handler) | 订阅基座推送的事件,handler 收到 (payload, from),返回取消订阅函数 |
sdk.emit(event, payload) | 向基座发送单向事件(无响应) |
sdk.invoke(method, params) | 按方法名调用基座(经消息总线路由,默认 10 秒超时) |
sdk.invokeHost(channel, ...args) | 直接调用主进程 IPC 通道(高级用法,绕过消息总线) |
sdk.destroy() | 销毁 SDK:清理全部事件监听 |
常规场景优先使用上层模块(router / app / http / auth);内置模块未覆盖的能力,再通过 invoke / invokeHost 自定义调用。
ts
// 订阅自定义事件
const off = sdk.on('my-app:data-updated', (payload, from) => {
console.log('来自', from, '的更新', payload)
})
off()
// 发送事件与自定义调用
sdk.emit('app:ready', { version: '1.0.0' })
await sdk.invoke('some.method', { foo: 'bar' })底层 IPC 桥也从 @lim/jssdk/ipc 单独导出,可用于判断当前是否运行在客户端环境:
ts
import { ipc } from '@lim/jssdk/ipc'
if (ipc.available) {
// 运行在 Lim 客户端内,IPC 桥可用
}类型导出
所有接口类型均可从包根导入:
ts
import type {
PushParams,
ReplaceParams,
AppParams,
OpenAppParams,
HttpRequestConfig,
HttpResponse,
HttpMethod,
HttpClient,
AuthTokenInfo,
AuthTokenClearedInfo,
AuthClient,
EventHandler,
} from '@lim/jssdk'