View 命令带有界面,运行在 iframe 中。推荐使用 Vite 进行前端构建(React/Vue/原生均可)。
关键点
- 宿主在加载时给 UI 入口附加查询参数:
?sid=<sessionId>&cmd=<command>,可按需读取。 - 与宿主的通信与能力调用通过
@sofastapp/api暴露的 API 完成。 - UI 需要被构建为静态资源,并由宿主通过本地 HTTP 服务托管。
读取会话信息
ts
// 在 UI 中可选读取 sessionId 与当前命令名
const sid = new URLSearchParams(location.search).get('sid');
const cmd = new URLSearchParams(location.search).get('cmd');常用 API 示例(UI 环境)
ts
import { Context, Screenshot, LocalStorage } from '@sofastapp/api';
// 读取/清空/监听 搜索框内容
const text = await Context.getSearchContent();
await Context.clearSearchContent();
const unwatch = Context.watchSearchContent((val) => {
console.log('context changed:', val);
});
// 触发宿主截图流程
await Screenshot.start();
// 插件私有存储(键值对)
const cur = (await LocalStorage.getItem<number>('counter')) ?? 0;
await LocalStorage.setItem('counter', cur + 1);
const all = await LocalStorage.allItems<Record<string, any>>();
await LocalStorage.clear();Vite 基础配置(示例 React)
ts
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
base: './',
plugins: [react()],
build: {
outDir: 'dist',
rollupOptions: { output: { manualChunks: undefined } },
},
});说明 宿主会按命令启动一个会话,并通过本地 HTTP 服务托管插件目录,默认入口为
index.html,无需在清单中指定入口文件。
多指令路由(同一个 UI 复用)
- 一个插件可以在
commands中声明多个view指令,它们会共享同一个index.html。 - 宿主在加载时会添加查询参数:
?sid=<sessionId>&cmd=<command>。 - UI 侧应读取
cmd,据此切换到对应的页面/组件(可以是条件渲染,也可以映射到内部路由)。
示例(React):
tsx
import React from 'react';
const pages = {
'hello-view': () => <div>Hello</div>,
'time-view': () => <div>{new Date().toLocaleTimeString()}</div>,
'api-storage': () => <StorageDemo />,
} as const;
export default function App() {
const params = new URLSearchParams(location.search);
const cmd = params.get('cmd') || 'hello-view';
const Page = (pages as any)[cmd] || (() => <div>Unknown: {cmd}</div>);
return <Page />;
}要点
- 不需要额外的清单配置,一个
index.html可以承载所有view指令。 - 只需在 UI 中读取
cmd并切换渲染;sid可用于需要与宿主进行会话关联的场景。