web app sdk for nas
npm install @trimjs/web-app一个用于应用与基座平台通讯的 SDK。
@trimjs/web-app 是一个跨平台通讯 SDK,让你的应用能够轻松调用基座平台的能力。
核心特性:
- 🌐 跨平台支持 - 同时支持在 Web iframe 和 App WebView 中运行
- 🎯 统一 API - 提供统一的接口调用基座平台能力(如设置标题、打开文件等)
- 🔧 自动兼容 - 开发者无需关心底层平台差异,SDK 自动处理兼容性
- 📦 开箱即用 - 简单初始化即可使用,无需复杂配置
使用 npm、yarn 或 pnpm 安装:
``bashnpm
npm install @trimjs/web-app
快速开始
$3
`typescript
import { TrimApp } from "@trimjs/web-app";// 创建实例
const app = new TrimApp();
// 调用方法
await app.setTitle("我的应用");
`$3
`typescript
import { TrimApp } from "@trimjs/web-app";// 创建实例
const app = new TrimApp({
debug: true, // 开启调试模式,会输出日志
});
// 设置应用标题
await app.setTitle("我的应用");
// 打开文件
await app.openFile("/path/to/file.pdf");
// 打开文件管理器
await app.openFileManager("/path/to/folder");
// 设置退出页面提示
await app.setExitPageTips({
title: "确认退出?",
content: "你有未保存的更改",
});
// 获取平台配置
const config = await app.getPlatformConfig();
console.log("主题:", config.theme);
console.log("语言:", config.language);
console.log("日期格式:", config.format.date);
console.log("时间格式:", config.format.time);
// 请求接口(仅 Web 平台)
if (app.isWeb) {
const response = await app.query({
api: "xxx.FileStation.List",
method: "list",
version: 2,
params: { folder_path: "/home" },
});
console.log("文件列表:", response);
}
// 选择文件
const selectedFiles = await app.pickFile({
multiple: true,
accept: [".pdf", ".doc", ".docx"],
title: "选择文档文件",
});
console.log("选中的文件:", selectedFiles);
`> 注意:所有方法都会自动等待 SDK 初始化完成,你可以直接调用,无需手动等待。
API 文档
$3
#### 构造函数
`typescript
new TrimApp(options?: TrimAppOptions)
`创建 TrimApp 实例。
参数:
-
options (可选) - 配置选项
- debug?: boolean - 是否开启调试模式,默认 false示例:
`typescript
// 不带配置
const app = new TrimApp();// 开启调试模式
const app = new TrimApp({ debug: true });
`---
#### setTitle
`typescript
async setTitle(title: string): Promise
`设置应用标题。
参数:
-
title: string - 标题文本返回值:
- 成功时返回
Promise
- 失败时返回 Promise示例:
`typescript
await app.setTitle("我的应用");
`---
#### openFile
`typescript
async openFile(path: string): Promise
`通过应用打开指定文件。
参数:
-
path: string - 文件路径返回值:
- 成功时返回
Promise
- 失败时返回 Promise示例:
`typescript
await app.openFile("/path/to/document.pdf");
`---
#### openFileManager
`typescript
async openFileManager(path: string): Promise
`打开文件管理器并定位到指定路径。
参数:
-
path: string - 文件夹路径返回值:
- 成功时返回
Promise
- 失败时返回 Promise示例:
`typescript
await app.openFileManager("/path/to/folder");
`---
#### setExitPageTips
`typescript
async setExitPageTips(params?: { title?: string; content?: string }): Promise
`设置退出页面时的提示信息。
参数:
-
params (可选) - 提示参数
- title?: string - 提示标题
- content?: string - 提示内容返回值:
- 成功时返回
Promise
- 失败时返回 Promise示例:
`typescript
// 设置提示
await app.setExitPageTips({
title: "确认退出?",
content: "你有未保存的更改",
});// 清除提示
await app.setExitPageTips();
`---
#### getPlatformConfig
`typescript
async getPlatformConfig(): Promise
`获取平台配置信息,包括主题、语言、日期时间格式等。
返回值:
-
Promise - 平台配置对象PlatformConfig 结构:
`typescript
interface PlatformConfig {
theme: "dark" | "light"; // 主题模式
language: string; // 语言代码,如 "zh-CN"、"en-US"
appVersion?: string; // 应用版本号
systemVersion: string; // 系统版本号
format: {
date?: string; // 日期格式,如 "YYYY-MM-DD"、"MM-DD-YYYY"
time?: string; // 时间格式,"12h" 或 "24h"
};
}
`示例:
`typescript
const config = await app.getPlatformConfig();// 根据主题调整 UI
if (config.theme === "dark") {
document.body.classList.add("dark-mode");
}
// 根据语言设置国际化
i18n.setLocale(config.language);
// 根据日期格式格式化日期
const dateFormatter = new Intl.DateTimeFormat(config.language, {
dateStyle: "short",
});
`---
#### close
`typescript
async close(): Promise
`关闭应用。
返回值:
-
Promise示例:
`typescript
app.close();
`---
#### ready
`typescript
async ready(): Promise
`等待 SDK 初始化完成。虽然所有方法都会自动等待初始化,但在某些场景下你可能需要显式等待。
返回值:
-
Promise - 初始化完成时 resolve示例:
`typescript
const app = new TrimApp();// 显式等待初始化完成
await app.ready();
// 现在可以安全地访问属性
console.log("当前平台:", app.isWeb ? "Web" : "Mobile");
`---
#### getOptions
`typescript
getOptions(): TrimAppOptions
`获取当前配置选项。
返回值:
-
TrimAppOptions - 当前配置对象示例:
`typescript
const options = app.getOptions();
console.log("调试模式:", options.debug);
`---
#### setOptions
`typescript
setOptions(options: Partial): void
`更新配置选项。
参数:
-
options: Partial - 要更新的配置项示例:
`typescript
// 开启调试模式
app.setOptions({ debug: true });// 关闭调试模式
app.setOptions({ debug: false });
`---
#### query
`typescript
async query(params: any, config?: QueryConfig): Promise>
`请求接口(仅支持 Web 平台)。用于调用 NAS 系统的 API。
参数:
-
params: any - 请求参数,通常包含 API 名称、方法、版本等信息
- config?: QueryConfig - 可选配置
- timer?: boolean - 是否是定时器请求
- observable?: boolean - 是否返回 Observable
- skipPreflight?: boolean - 是否跳过预检请求
- autoFailTips?: boolean - 是否自动显示失败提示返回值:
-
Promise - 响应数据ResponseData 结构:
`typescript
interface ResponseData {
reqid: string; // 请求 ID
result: ResponseStatus; // 响应状态:'succ' | 'fail' | 'cancel' | 'doing'
taskId?: string; // 任务 ID(如果适用)
type?: string; // 类型
errmsg?: string; // 错误消息
errno?: number; // 错误码
extra?: string; // 额外信息
// ... 其他 T 类型的字段
}
`注意:
- 此方法仅在 Web 平台(iframe)中可用
- 在移动端调用会抛出错误
示例:
`typescript
// 调用文件列表 API
const response = await app.query({
api: "x'x'x.FileStation.List",
method: "list",
version: 2,
params: {
folder_path: "/home",
additional: ["size", "time", "perm", "type"],
},
});if (response.result === "succ") {
console.log("文件列表:", response);
} else {
console.error("请求失败:", response.errmsg);
}
// 使用配置选项
const response2 = await app.query(
{ api: "xxxx", method: "query", version: 1 },
{
timer: false,
autoFailTips: true,
}
);
`---
#### pickFile
`typescript
async pickFile(params: FilePickerParams): Promise
`打开文件选择器,让用户选择文件或文件夹。
参数:
-
params: FilePickerParams - 文件选择器参数
- multiple?: boolean - 是否多选,默认 false
- directory?: boolean - 是否选择文件夹,默认 false
- accept?: string[] - 接受的文件类型,如 ['.pdf', '.doc', '.docx']
- sidebarGroup?: string[] - 侧边栏分组,可选值:'myFiles'、'otherShare'、'external'、'remote'、'favorites'、'storage'、'torrent'、'team',默认 ['myFiles']
- disabledPaths?: string[] - 不可选的路径列表
- selectablePatterns?: [string, string][] - 可选择的正则表达式(预留)
- expandFiles?: Array<{ title: string; extension: string }> - 扩充搜索的文件类型
- creatable?: boolean - 是否允许创建文件夹,默认 true
- title?: string - 对话框标题,默认 '选择文件' 或 '选择文件夹'
- okText?: string - 确认按钮文本,默认 '确定'返回值:
-
Promise - 选中的文件路径数组示例:
`typescript
// 选择单个文件
const files = await app.pickFile({
multiple: false,
accept: [".pdf", ".doc", ".docx"],
title: "选择文档文件",
});
console.log("选中的文件:", files[0]);// 选择多个文件
const multipleFiles = await app.pickFile({
multiple: true,
accept: [".jpg", ".png", ".gif"],
title: "选择图片文件",
});
console.log("选中的文件:", multipleFiles);
// 选择文件夹
const folders = await app.pickFile({
directory: true,
title: "选择文件夹",
});
console.log("选中的文件夹:", folders[0]);
// 限制侧边栏范围
const files = await app.pickFile({
multiple: true,
sidebarGroup: ["myFiles", "favorites"],
accept: [".txt", ".md"],
});
// 禁用某些路径
const files = await app.pickFile({
disabledPaths: ["/vol1/1000/private", "/vol2/1000/temp"],
accept: [".pdf"],
});
`---
#### callAppMethod
`typescript
async callAppMethod(fn: string, params?: string): Promise
`调用移动端 App 的方法(仅移动端可用)。
参数:
-
fn: string - 要调用的方法名
- params?: string - 方法参数(JSON 字符串)返回值:
-
Promise - 方法返回结果,失败时返回 null注意:
- 此方法仅在移动端(WebView)中可用
- 在 Web 平台调用会返回
null
- 建议使用 SDK 提供的标准方法(如 setTitle、openFile 等),而不是直接调用此方法示例:
`typescript
// 调用自定义方法
const result = await app.callAppMethod<{ success: boolean }>(
"customMethod",
JSON.stringify({ key: "value" })
);
`---
$3
#### isWeb
`typescript
readonly isWeb: boolean
`判断当前运行环境是否为 Web 平台。
-
true - 运行在 Web iframe 中
- false - 运行在移动端 WebView 中示例:
`typescript
const app = new TrimApp();
await app.ready();if (app.isWeb) {
console.log("运行在 Web 平台");
// Web 平台特有逻辑
} else {
console.log("运行在移动端");
// 移动端特有逻辑
}
`配置选项
$3
`typescript
interface TrimAppOptions {
/* 是否开启调试模式,开启后会输出日志 /
debug?: boolean;
}
`选项说明:
-
debug (可选) - 是否开启调试模式
- 类型:boolean
- 默认值:false
- 说明:开启后会在控制台输出 SDK 运行日志,方便调试示例:
`typescript
// 开启调试模式
const app = new TrimApp({ debug: true });// 运行时切换调试模式
app.setOptions({ debug: false });
`---
$3
`typescript
interface PlatformConfig {
theme: "dark" | "light"; // 主题模式
language: string; // 语言代码,如 "zh-CN"、"en-US"
appVersion?: string; // 应用版本号
systemVersion: string; // 系统版本号
format: {
date?: string; // 日期格式,如 "YYYY-MM-DD"、"MM-DD-YYYY"、"DD-MM-YYYY"、"YYYY/MM/DD"、"MM/DD/YYYY"、"DD/MM/YYYY"
time?: string; // 时间格式,"12h" 或 "24h"
};
}
`字段说明:
-
theme - 当前主题模式
- "dark" - 深色模式
- "light" - 浅色模式
- language - 语言代码,遵循 BCP 47 标准
- 常见值:"zh-CN"(简体中文)、"en-US"(美式英语)等
- appVersion (可选) - 应用版本号
- systemVersion - 系统版本号
- format.date (可选) - 日期格式
- 支持格式:"YYYY-MM-DD"、"MM-DD-YYYY"、"DD-MM-YYYY"、"YYYY/MM/DD"、"MM/DD/YYYY"、"DD/MM/YYYY"
- format.time (可选) - 时间格式
- "12h" - 12 小时制
- "24h" - 24 小时制平台差异
$3
在 Web 平台中,SDK 通过
postmate 与父窗口(OS)进行通信。支持的方法:
- ✅
setTitle - 设置标题
- ✅ setExitPageTips - 设置退出提示
- ✅ openFile - 打开文件
- ✅ openFileManager - 打开文件管理器
- ✅ getPlatformConfig - 获取平台配置
- ✅ close - 关闭应用
- ✅ query - 请求接口
- ✅ pickFile - 选择文件$3
在移动端平台中,SDK 通过
flutter_inappwebview 与原生 App 进行通信。支持的方法:
- ✅
setTitle - 设置标题
- ✅ setExitPageTips - 设置退出提示
- ✅ openFile - 打开文件
- ✅ openFileManager - 打开文件管理器
- ✅ getPlatformConfig - 获取平台配置
- ✅ close - 关闭页面
- ❌ query - 不支持(会抛出错误)
- ✅ pickFile - 选择文件
- ✅ callAppMethod - 调用自定义 App 方法类型导出
SDK 导出了以下类型,方便你在 TypeScript 项目中使用:
`typescript
import type { TrimAppOptions, PlatformConfig } from "@trimjs/web-app";
`如果需要使用其他类型(如
FilePickerParams、QueryConfig、ResponseData),可以从 @fn/micro-app-postmate 导入:`typescript
import type {
FilePickerParams,
QueryConfig,
ResponseData,
} from "@fn/micro-app-postmate/src/child/type";
import type { ResponseData as ResponseDataType } from "@fn/micro-app-postmate/src/child/os-type";
`使用场景
$3
`typescript
const app = new TrimApp({ debug: true });
const config = await app.getPlatformConfig();// 根据主题切换 UI
if (config.theme === "dark") {
document.body.classList.add("dark-mode");
}
// 根据语言设置国际化
i18n.setLocale(config.language);
// 根据日期格式显示日期
const dateFormat = config.format.date || "YYYY-MM-DD";
const formattedDate = dayjs().format(dateFormat);
`$3
`typescript
// 让用户选择文件
const selectedFiles = await app.pickFile({
multiple: true,
accept: [".jpg", ".png", ".pdf"],
title: "选择要上传的文件",
});if (selectedFiles && selectedFiles.length > 0) {
// 处理选中的文件
for (const filePath of selectedFiles) {
console.log("上传文件:", filePath);
// 执行上传逻辑...
}
}
`$3
`typescript
// 仅在 Web 平台调用 API
if (app.isWeb) {
try {
const response = await app.query({
api: "xxx.FileStation.List",
method: "list",
version: 2,
params: {
folder_path: "/home",
additional: ["size", "time", "perm"],
},
}); if (response.result === "succ") {
console.log("文件列表获取成功");
}
} catch (error) {
console.error("API 调用失败:", error);
}
}
`$3
`typescript
// 在用户有未保存数据时设置退出提示
app.setExitPageTips({
title: "确认离开?",
content: "您有未保存的更改,确定要离开吗?",
});// 保存数据后清除提示
async function saveData() {
// 保存逻辑...
await app.setExitPageTips(); // 清除提示
}
`注意事项
1. 初始化时机:SDK 会在创建实例时自动初始化,所有方法都会自动等待初始化完成,无需手动调用
ready()。2. 平台检测:SDK 会自动检测运行环境(Web 或移动端),通过
isWeb 属性可以判断当前平台。3. 错误处理:某些方法在特定平台可能不可用(如
query 在移动端),调用前建议检查 isWeb 属性。4. 调试模式:开启
debug 选项后,SDK 会在控制台输出详细的运行日志,方便开发和调试。5. 异步方法:所有与平台交互的方法都是异步的,记得使用
await 或 .then() 处理。6. 文件选择器:
pickFile 方法会打开系统文件选择器,用户可能取消选择,返回的数组可能为空,记得处理这种情况。7. API 请求:
query 方法返回的 ResponseData 包含 result 字段,需要检查状态是否为 'succ' 来判断请求是否成功。常见问题
$3
A: 使用
isWeb 属性:`typescript
const app = new TrimApp();
await app.ready();if (app.isWeb) {
console.log("运行在 Web 平台");
} else {
console.log("运行在移动端");
}
`$3
A: 某些方法只在特定平台可用:
-
query() 仅在 Web 平台可用
- 在移动端调用这些方法会抛出错误建议在调用前检查平台:
`typescript
if (app.isWeb) {
await app.query();
} else {
console.log("当前平台不支持 query 方法");
}
`$3
A: 虽然所有方法都会自动等待初始化,但如果你需要显式等待:
`typescript
const app = new TrimApp();
await app.ready();
// 现在可以安全地使用所有功能
`$3
A: 如果用户取消了文件选择,
pickFile 会返回空数组。记得处理这种情况:`typescript
const files = await app.pickFile({ multiple: true });
if (files.length === 0) {
console.log("用户取消了选择");
return;
}
// 处理选中的文件...
`$3
A: 开启
debug 模式,SDK 会在控制台输出详细日志:`typescript
const app = new TrimApp({ debug: true });
// 现在所有操作都会输出日志
`$3
A:
result 字段可能的值:-
'succ' - 成功
- 'fail' - 失败
- 'cancel' - 用户取消
- 'doing' - 任务进行中`typescript
const response = await app.query({
/ ... /
});
if (response.result === "succ") {
// 处理成功情况
} else if (response.result === "fail") {
// 处理失败情况
console.error("错误:", response.errmsg);
}
`$3
A: 不可以。
query 方法仅在 Web 平台可用。在移动端调用会抛出错误。如果需要调用 API,建议在 Web 平台使用,或者通过 callAppMethod 调用移动端原生方法。开发
`bash
安装依赖
pnpm install开发模式
pnpm dev构建
pnpm build类型检查
pnpm typecheck代码检查
pnpm lint
``MIT