Beekeeper Studio 插件视图(Plugin Views)开发指南:Tab、Shell-Tab 与视图状态管理
【免费下载链接】beekeeper-studioModern and easy to use SQL client for MySQL, Postgres, SQLite, SQL Server, and more. Linux, MacOS, and Windows.项目地址: https://gitcode.com/GitHub_Trending/be/beekeeper-studio
本文是 Beekeeper Studio 插件开发体系中关于「视图」的实战指南,完整讲解插件如何通过manifest.json声明base-tab、shell-tab与(规划中的)sidebar 视图,以及如何使用getViewState/setViewState实现跨重启的视图状态持久化与实例隔离。读完本文,你将能根据插件形态选择正确的视图类型、编写合法的 manifest 配置,并理解视图状态在宿主应用中的底层存储机制。
注意:Beekeeper Studio 的插件系统目前仍处于 Beta 阶段(自 Beekeeper Studio 5.3+ 提供),官方欢迎社区反馈。
视图类型总览
插件通过「视图(View)」与 Beekeeper Studio 集成,视图决定了插件界面在应用中出现的位置与形态。视图声明统一放在manifest.json的capabilities.views数组中,每个视图由四个字段描述:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 视图的唯一标识,供菜单、命令等引用 |
name | string | 是 | 显示在标签页 / 侧边栏上的名称 |
type | ViewType | 是 | 视图类型,决定布局形态 |
entry | string | 是 | 相对插件根目录的 HTML 入口文件路径 |
当前可用的视图类型如下:
| 类型 | 状态 | 说明 |
|---|---|---|
shell-tab | 可用 | 插件 iframe 位于上方、可折叠的结果表格位于下方的标签页 |
base-tab | 可用 | 占据整个标签页空间的独立界面 |
primary-sidebar | 规划中 | 主侧边栏面板 |
secondary-sidebar | 规划中 | 次级侧边栏面板 |
其中「标签页视图」让插件像查询标签页一样出现在主工作区中,是当前插件系统的主力形态;侧边栏视图则面向「常驻面板」的使用场景,目前仍在规划阶段。
Tab 视图:插件的主战场
Tab 视图会让插件作为标签页出现在主工作区,与查询标签页(Query Tab)及其他内容并列展示。Tab 视图又细分为两种布局。
Base Tab:全屏独立界面
Base Tab 的插件界面会占据整个标签页空间,适合工具型、面板型插件——所有内容都由插件自己的 HTML 自行组织,宿主不附加任何特殊 UI。从源码看,TabPluginBase.vue 的模板非常精简,只在容器中渲染一个isolated-plugin-view(即插件入口 HTML 的隔离 iframe),没有任何多余外壳。
Shell Tab:上方控件 + 下方结果表
Shell Tab 在底部提供一个可打开 / 关闭的结果表格面板:插件 iframe 位于上方,用户在上方操作插件控件,查询或分析结果则以熟悉的表格格式显示在下方。这种布局非常适合「查询 / 分析类」插件——控制逻辑与数据查看分离,交互效率高。
Manifest 示例:
{ "capabilities": { "views": [ { "id": "data-analyzer", "name": "Data Analyzer", "type": "shell-tab", "entry": "index.html", } ] } }Shell Tab 的宿主实现原理
从源码结构看,Shell Tab 的实际承载组件是 TabPluginShell.vue。它的布局由split.js驱动:Split([topPanel, bottomPanel], { direction: "vertical", sizes: [100, 0] })建立垂直分割,插件 iframe(isolated-plugin-view)在上、result-table在下,初始状态下表格面板完全折叠(占比 0%)。其中:
expandTableResult()会把分割比例调整为[60, 40],即插件占 60%、结果表占 40%;- 面板可见性判定存在 5% 的阈值(
VISIBLE_THRESHOLD = 5),底部占比超过 5% 才被视为可见; - 用户可通过状态栏上的「Hide result / Show result」按钮手动折叠 / 展开表格。
在 TabPluginShell.vue 的handleRequest中,宿主为 Shell Tab 注册了runQuery、expandTableResult、setTabTitle、getViewState、setViewState、toggleStatusBarUI等请求处理,这也是@beekeeperstudio/plugin中对应 API 的落地通道。
Sidebar 视图(规划中)
Sidebar 视图将插件作为应用侧边栏中的常驻面板呈现,在用户处理其他内容时保持可见,适合「随时查阅」型功能(例如 SQL 参考手册、速查表)。官方计划支持primary-sidebar(主侧边栏)与secondary-sidebar(次级侧边栏)两种类型,当前仍未开放。
Manifest 示例(规划中的声明格式):
{ "capabilities": { "views": [ { "id": "quick-reference", "name": "SQL Reference", "type": "secondary-sidebar", "entry": "sidebar.html", } ] } }一个插件声明多个视图
单个插件可以在capabilities.views数组中声明任意多个视图,每个视图拥有独立的id、name、type与entry。例如一个插件既提供主分析界面,又提供一个快捷工具面板:
{ "capabilities": { "views": [ { "id": "main-interface", "name": "Data Processor", "type": "shell-tab", "entry": "main.html", }, { "id": "quick-tools", "name": "Quick Tools", "type": "secondary-sidebar", "entry": "tools.html", } ] } }视图声明完毕后,可以通过capabilities.menus中的菜单项把视图暴露给用户(例如placement: "newTabDropdown"让用户从「新建标签」下拉菜单中打开你的视图),菜单项通过view字段引用视图的id。完整字段说明见 Manifest Reference。
视图状态(View State):跨重启持久化
每个插件视图都可以通过getViewState与setViewState两个 API 存取自己的状态,状态在应用重启后依然保留。这在「保存会话」类功能中尤其有用,例如 AI 助手保存对话记录、数据分析工具保存上次的筛选条件。
典型用法示例:
// 用户交互时保存状态 await setViewState({ conversations: [ "Ai: Hello, how can I help you today?", "Human: Make a plain sandwich recipe using SQL.", ] }); // 视图加载时恢复状态 const state = await getViewState(); if (state) { setConversations(state.conversations); }API 签名(详见 API Reference):
async function getViewState<T>(): Promise<T>; async function setViewState<T>(state: T): Promise<void>;状态隔离规则
视图状态按「视图实例」隔离,遵循三条规则:
- 每个视图维护自己独立的状态;
- 视图之间无法互相访问对方的状态;
- 用户打开同一插件的多个标签页时,每个标签页拥有完全独立的状态。
例如,用户创建了两个 AI Shell 标签页,两个标签页各自保存互不相通的状态数据,彼此无法读取对方存储的信息。这一隔离保证不会出现「一个标签页的会话串到另一个标签页」之类的串扰问题。
源码视角:状态是如何持久化的
从源码看,视图状态并非存放在插件 iframe 内部,而是挂载在宿主侧的标签页上下文上。在 TabPluginShell.vue 与 TabPluginBase.vue 中,两个组件的处理逻辑一致:
getViewState请求:直接返回this.tab.context.state;setViewState请求:把状态写入this.tab.context.state,随后派发tabs/save动作保存标签页。
由于标签页本身由 Beekeeper Studio 的标签持久化机制管理(标签会跨重启恢复),挂载在标签页上下文上的state也随之获得跨重启持久化能力。这也是「同一插件不同标签页状态独立」的根源——状态绑定在单个 tab 实例上,而非绑定在插件全局。
视图类型与 manifest 的进阶核对
在 manifest.md 的ViewType表中,可用类型明确列为shell-tab与base-tab;同时源码 types.ts 也印证了这一点:TabType只有"shell" | "base"两种取值,视图类型即${TabType}-tab,并注明shell-tab的宿主结构是「上方插件 iframe + 下方可完全折叠的结果表」。需要留意的是,manifest 文档「Type Definitions」一节中把全屏标签类型写作plain-tab,与ViewType表及源码中的base-tab存在命名出入——开发时请以当前源码与ViewType表采用的base-tab为准。
此外,manifestVersion默认值为0(旧版格式使用capabilities.views.tabTypes数组,元素含kind: "shell"等字段),新版请使用本文展示的manifestVersion: 1+capabilities.views数组格式,并在根目录放置manifest.json。
延伸阅读
- 创建你的第一个插件(Creating Your First Plugin):从零构建 Hello World 插件,体验
shell-tab视图与数据库交互 - Manifest Reference(manifest.json 完整参考):
capabilities.views、PluginMenuItem、PluginMenuItemPlacement等全部字段 - Plugin API Reference(插件 API 参考):
getViewState/setViewState、expandTableResult、runQuery、broadcast等完整 API 清单
【免费下载链接】beekeeper-studioModern and easy to use SQL client for MySQL, Postgres, SQLite, SQL Server, and more. Linux, MacOS, and Windows.项目地址: https://gitcode.com/GitHub_Trending/be/beekeeper-studio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考