1. 前端
插件化手册
  • FH2 插件开发手册
    • 产品简介
    • 典型场景
    • 发版说明
    • 快速开始
      • 快速开始总览
      • 第一个插件
      • 后端插件
      • 全栈闭环
    • AI辅助开发
      • AI 开发 Skill
      • 安装与复验
      • 第一个工程
      • 真实需求示例:现场问题上报
      • 改造已有工程
      • 调试与交付
    • 开发指南
      • 开发指南
      • 基础概念
        • 基础概念总览
        • 什么是插件开发
        • 平台架构
        • 前端宿主、扩展点与能力
        • 后端运行时、入口与权限
        • 开发流程
        • 安全与隔离
        • 支持范围与问题反馈
      • 开发指南
        • 开发指南总览
        • 前端插件
          • 前端插件深度指南
          • 前端工程结构
          • 插件清单(fh2-plugin.json)
          • 入口与生命周期
          • 界面与状态
          • 多宿主插件
          • 跨宿主通信服务
          • HTTP、WebSocket 与事件
          • 存储、Blob 与定时器
          • 工具链与本地调试页面
        • 后端插件
          • 后端开发深度指南
          • 后端插件的结构
          • 后端源清单 fh2-plugin.json
          • HTTP 接口处理函数
          • 消息订阅与事件处理函数
          • ctx 与能力注入
          • 数据存储与缓存
          • 流程编排
          • 触发方式
          • 连接外部系统
          • 流程编排练习(DAG)
        • 前后端协作
          • 前后端协作总览
          • 前后端共享契约
          • 端到端幂等
          • 事件、通知与状态
          • 统一错误模型
          • 链路标识与诊断日志
        • 完整练习
          • 环境准备
          • 第一个前端插件
          • 第一个后端插件
          • 第一个全栈插件
      • 能力总览
        • 能力地图
        • 能力可用性矩阵
        • 前端能力
          • 平台通用能力
            • 平台通用能力总览
            • 基础运行时:HTTP、事件、WebSocket 与存储
            • 导航、位置与通知
            • 弹窗、音频与剪贴板
            • 地图能力
            • 项目设备能力
            • WPMZ 与航线预览
            • 受控对象上传
          • 项目宿主
            • 项目宿主总览
            • 项目上下文
            • 项目侧边栏入口
            • 项目插件路由
            • 项目工作区
          • 消息宿主
            • 消息宿主总览
            • 消息告警弹层
            • 消息导航与通知
          • 计划库宿主
            • 计划库宿主总览
            • 计划库表单上下文
            • 计划库表单扩展
            • 校验、提交与 `biz_ext`
          • 驾驶舱
            • 驾驶舱插件能力总览
            • 驾驶舱扩展点
            • 上下文与遥测
            • 相机、检测与 AI
            • 场景几何与直播指针
            • 飞控、云台与任务
            • 驾驶舱平台事件
        • 后端能力
          • 后端能力地图
          • 后端能力总览
          • 配置、受管出网与集成连接
          • 事件与流程
          • 飞行任务与违停巡逻
          • 数据存储
          • 媒体与前端通知
          • 资源租约
          • 作业、目标轨迹与视频处理
      • 调试与测试
        • 调试与测试总览
        • 快速入门排错
        • 本地开发
        • Web IDE:打开工程与保存改动
        • 工作流编辑器:节点、接线与交付
        • 知识与 MCP:先判断需要哪一层事实
        • 前端本地调试
        • 后端运行时与流程调试
        • 模拟数据与测试数据
        • 集成测试与 E2E
        • 日志与链路追踪
        • 常见问题排查
      • 完整示例
        • 示例与案例总览
        • 项目侧边栏与工作区
        • 消息告警卡片
        • 计划表单任务清单
        • 驾驶舱动作与左侧面板
        • 最小后端插件
        • 最小全栈插件
        • 多宿主插件实战
        • 事故快处
        • 交通抓拍
        • 违停巡逻完整案例
      • 构建发布与安全
        • 构建、发布与安全
        • 质量门禁
        • 行业包构建与打包
        • 能力版本发布
        • 安装、升级与回滚
        • 安全基线
      • API参考
        • API 参考总览
        • 前端
          • 前端 API 参考
          • 前端插件清单结构
          • 前端 SDK API
          • 前端扩展点目录
          • 前端能力目录
          • 前端平台事件目录
          • 跨宿主通信服务 API
          • 工具链命令行参考(`fh2-plugin`)
        • 后端
          • 后端 API 参考
          • 后端插件源清单
          • 后端 HTTP 接口参考
          • 后端事件消费参考
          • 后端脚本上下文(`ctx`)
          • 后端数据存储
          • 流程编排语言
          • 流程触发器参考
          • 后端能力目录
          • 后端 HTTP API
        • 共享契约
          • 共享契约参考
          • 类型与契约目录
          • 错误模型
          • 版本兼容性
      • 附录
        • 错误码
        • 术语表
        • 常见问题
  1. 前端

前端 SDK API

fh2-plugin-sdk 是插件开发 SDK,提供 definePlugin、上下文 ctx、界面定义和扩展点、能力、事件目录。
本页模块名用于说明 SDK 的 API 与子入口,不是公共 npm 安装坐标。实际依赖与导入路径保留开发者工具生成的配置,获取与安装见环境准备。

包入口#

入口内容
fh2-plugin-sdkdefinePlugin、defineView、definePluginView、createViewState、上下文类型、错误码、清单契约、manifestSchema(界面相关的成员也从这个根入口导入即可)
fh2-plugin-sdk/view同上中界面相关成员的子路径导出(可选,二选一)
fh2-plugin-sdk/catalog宿主、扩展点、能力、平台事件目录
fh2-plugin-sdk/schema/manifest.schema.json清单 JSON 结构定义
SDK 只提供插件作者 API。宿主创建、安装和资源管理由平台负责,不通过 SDK 导入宿主实现。

入口定义#

// plugin.ts
import { definePlugin } from 'fh2-plugin-sdk'

export default definePlugin({
  async activate(ctx) {
    // 贡献扩展、申请能力、订阅事件都从这里开始
    return {
      dispose({ reason }) {
        // 业务收尾:停止自己的业务逻辑
      },
    }
  },
})
规则:
插件入口构建产物的默认导出必须是 definePlugin() 的结果,一个插件只有一个入口。
activate 返回值里的 dispose 只做业务收尾;扩展、界面、定时器、订阅、Blob URL、跨宿主通信服务由平台统一回收,不必重复清理。
同一入口可在 cockpit | plan | message | project 四个宿主分别激活,用 ctx.host.id 分流。
dispose 的 reason 取值:host-unmount | plugin-disabled | plugin-uninstalled | config-changed | activation-failed | runtime-terminated。

上下文成员(ctx)#

ctx 是平台传给 activate 的上下文对象,插件的一切宿主交互都通过它。
成员说明
plugin{id, name, version} 当前插件身份
host{id, instanceId} 当前宿主
locale语言(宿主创建时的快照)
config配置项求值结果(只读)
permissions实际授权的能力 ID 列表
lifecycle{signal, disposed};停用时 signal 发出中止信号
timerssetTimeout/clearTimeout/setInterval/clearInterval,停用时统一回收
extensions.contribute(id, impl)贡献一个清单已声明的扩展,返回句柄(见扩展点目录)
capabilities.get(id)取能力调用方;未授权或宿主未提供时返回 undefined(见能力目录)
services.provide / connect同插件跨宿主通信(见跨宿主通信服务)
storage.local / session键值存储 get/set/remove/keys,值必须是可序列化 JSON
blobs二进制存取 get/put/remove/url
events.on(name, handler)订阅平台事件(见平台事件目录)
ws.onBizCode(bizCode, handler)只读订阅宿主 WebSocket 业务消息
loggerdebug/info/warn/error(message, detail?)
apiCall(endpoint, options?)插件入口的受管 HTTP 出口;相对路径访问平台内部接口,绝对 HTTP(S) URL 经网关出网
views.get(viewId, initialState?)取得界面句柄;实际显示还需扩展点或弹窗等宿主出口挂载
views.handle(viewId, provider)接管一个界面(配合 definePluginView)

HTTP 调用选项(apiCall)#

const res = await ctx.apiCall('/plugin/invoke', {
  method: 'POST',                             // 默认 GET
  body: {pluginId: 'exp_demo', handler: 'demo.status', input: {}},
  timeoutMs: 10000,
  idempotencyKey: 'capture-001',              // 1-256 字符,不含换行
})
限制值
相对路径 endpoint单个 / 开头,不能自带 /plugin-api 前缀、//、反斜杠、fragment 或路径穿越
绝对 URL endpoint仅 HTTP(S),不能带 userinfo/fragment;必须命中宿主网关出网白名单
相对路径 bodyJSON 值,或 Blob(≤10MB),或受控多部分表单(≤8 个文件、单文件 ≤10MB、总 ≤20MB)
绝对 URL body仅 JSON 值;不开放自定义 Header
GET 请求不能带请求体
返回值JSON 原始响应,不自动提取 data
失败不返回失败信封:网关业务码非零时直接抛 PluginError(code 为 PLUGIN_GATEWAY_ERROR,网关业务码在 detail.gatewayCode),用 isPluginError 判断后读取
idempotencyKey1–256 字符、非空、无 CR/LF;平台映射为 Idempotency-Key 请求头,实际去重语义以后端契约为准

界面#

import { defineView } from 'fh2-plugin-sdk'

export default defineView({
  mount(viewCtx) {
    // viewCtx: {viewId, mountElement, styleTarget, overlayElement, port, locale, direction, theme}
    viewCtx.mountElement.textContent = 'hello'
    return { dispose() {} }
  },
})
界面构建产物的默认导出必须是 defineView() 的结果。
界面拿不到 ctx(PluginContext)和能力;与入口之间只有一条通信通道(状态 + 方法)。
import { definePluginView, createViewState } from 'fh2-plugin-sdk'

const panel = definePluginView<{
  state: {count: number}
  methods: {increment(delta: number): number}
}>('panel')

// 入口侧:接管界面。对象形态(state 是 createViewState 之类的状态源):
const state = createViewState({count: 0})
await panel.handle(ctx, {
  state,
  methods: {
    increment: delta => {
      state.update(v => ({count: v.count + delta}))
      return state.get().count
    },
  },
})

// 界面侧:contract.client(port) 得到 { state, <各方法平铺>, dispose },
// 方法直接调用:await client.increment(1)
提示:panel.handle(ctx, provider) 内部委托给 ctx.views.handle;推荐使用契约对象,让类型检查约束状态、方法和初始状态。
契约未声明 initialState 时,使用上例的 handle(ctx, {state, methods}) 会话对象,get(ctx) 返回初始状态为 null 的界面句柄。
契约声明了 initialState 时,必须使用 handle(ctx, (initialState, call) => ({state, methods})) 工厂,并通过 get(ctx, initialState) 传入初始状态;工厂创建的完整初始状态必须包含相同字段和值,不能把上例的会话对象直接传入。
createViewState().update(updater) 返回 void;上例 increment 声明返回 number,因此更新后显式返回 state.get().count。
约束:方法最多 1 个参数;参数、返回值、状态必须满足 PluginValue(可跨边界克隆的值);initialState 必须是 JSON 值且为状态的部分形状。

常见问题#

现象原因与处理
Entry 里裸 fetch / XMLHttpRequest / WebSocket 被拦截改用 ctx.apiCall() / ctx.ws。Guard 错误不是 PLUGIN_NETWORK_BLOCKED;后者表示 apiCall 参数校验失败
ctx.apiCall 返回的不是业务数据它返回完整信封,业务数据在 data 字段里
ctx.apiCall 报 PLUGIN_GATEWAY_ERROR网关业务码非零会以异常抛出;isPluginError 判断后读 error.detail.gatewayCode
界面里拿 ctx 是 undefined界面设计上就没有上下文;需要数据就走插件入口↔界面通道
定时器在插件停用后还跑用 ctx.timers 而不是全局 setTimeout,平台会统一回收
修改于 2026-10-22 03:40:04
上一页
前端插件清单结构
下一页
前端扩展点目录
Built with