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. 附录

常见问题

按前端、后端、发布分组。结论在前,原因随后。

前端#

插件能直接访问驾驶舱内部状态,或用裸 fetch 发请求吗?#

插件应通过公开能力或平台事件读取状态,不直接访问宿主内部状态存储;界面贡献使用扩展点。插件入口(Entry)的网络护栏会阻止入口代码直接使用原生 fetch、XMLHttpRequest 和 WebSocket。入口的 HTTP 走 ctx.apiCall(),WebSocket 订阅走 ctx.ws.onBizCode()。业务接口使用单 / 开头的相对路径,不自行加 /plugin-api;已获宿主网关白名单放行的外部接口也可用绝对 HTTP(S) URL 受管调用,但请求体只能是 JSON、不能自定义 Header。两种路线的 GET 都不能带请求体,详见HTTP 调用。
这项护栏不适用于插件界面(View)。界面不接收 PluginContext,通过 state / methods 通道与入口交换数据;它的 JavaScript 在宿主同一 Realm 执行,ShadowRoot 只隔离 DOM/CSS,不是 JavaScript 安全沙箱。不接收上下文不代表技术上无法访问浏览器网络;作者仍应把网络请求交给入口的受管通道,不能把样式隔离当作阻止绕过 API 的安全保证。

ctx.capabilities.get('platform:map') 返回 undefined 是怎么回事?#

三种可能:清单 permissions 没声明、当前宿主没提供这个能力、运行环境不满足要求。按「能力缺失」降级处理,不要当网络错误重试:
const map = await ctx.capabilities.get('platform:map')
if (!map) return

清单里能写 trusted、sandbox 或构建字段吗?#

不能,写了整包被拒。运行方式不是作者可声明的概念,trusted、trustLevel、sandbox 一律拒绝;manifestVersion、engines、buildInfo 由 fh2-plugin build 写入构建产物。

为什么要先 build 再发布?#

宿主安装的是构建产物(前端的 dist/fh2-plugin.json、后端的 dist/plugin.json),源码清单缺构建字段会被拒绝。校验、测试后,在生成工程的外层工作区执行 pnpm run pack,由工具链构建成员并生成行业包 zip,见行业包构建与打包。

后端#

文档里的 SDK import 要直接替换生成工程的路径吗?#

不需要。fh2-plugin-sdk 为文档使用的 SDK 模块名;实际路径使用生成工程配置。保留生成工程中的实际 import,不按文档模块名修改依赖或工具链别名;该名称说明不表示存在同名公开 npm 包。

本地跑通的后端能直接部署到生产吗?#

不能。本地 dev 在含后端且非 --frontend-only 时启动 HTTP 模拟器,使用内存模拟存储,不是真实网关,也不执行流程或消息队列。发布前完成工程校验与测试,再从外层工作区运行 pack,构建并组装行业上传包;这些构建 / 打包命令不会启动服务。装载不会自动执行 schema.sql,由部署方落实建表,并在测试环境验证流程、队列和能力提供方,见行业包构建与打包。

后端 HTTP 接口处理函数怎么命名、怎么调用?#

handlers/example/create.ts 里的 export function create,接口名就是 example.create(构建后的稳定入口名 h_example_create 也认)。新增一个接口 = 新增一个文件,不用在清单里登记。调用走统一端点。下面是已部署环境采用 Bearer 鉴权时的协议形状:先取得部署方提供的环境入口、路径前缀和授权凭据;<ENV_API_TOKEN> 不是固定测试值,也不能省略鉴权。入口要求其他认证头时按部署方说明替换。
请求体只允许 pluginId、handler、input 三个顶层字段。成功必须同时满足 HTTP 2xx 和 code: 0。
本地请求使用本次 dev 的调试 Token 和回环地址;当前本地网关返回数字分类,HTTP 状态、消息包装与排序差异见后端调试,不能把本地通过当成目标环境契约验证。

脚本能执行 SQL、访问任意表或直接调内部服务吗?#

不能执行裸 SQL,也不能直接访问内部服务,只能用平台按 allowlist 注入的全局对象。数据存储只覆盖插件自己的库;不要把它当多插件之间的隔离边界,敏感数据不要放插件库。

secret: true 会加密连接配置吗?#

不会。它只让启动日志不打印该字段的值,不会自动过滤业务日志。连接的真实值由部署方维护,不能写进插件清单、流程、日志或文档。插件作者声明连接字段、提交目标主机和用途,并请部署方确认连接绑定与出网白名单;声明权限不代表连接或外部服务已就绪。

事件消费脚本为什么可能被执行两次?#

消息投递是「至少一次」。后端运行时中命中的消费方并发执行、各自独立重试,全部结束后按 Requeue > Discard > Ack(重新入队 > 丢弃 > 确认)聚合消息处置;数组顺序不表达业务依赖,依赖逻辑放同一个消费函数或显式流程编排。去重用业务唯一键 + store.createIfAbsent(),不要「先 query 再 insert」。本地模拟器不用于证明这些并发、重试和处置语义。

事件脚本可以不返回,或直接返回失败信封吗?#

入口必须返回对象,通常为 {}。事件入口顶层返回 {ok:false,error:{code,message}} 会按 error.code 分类;非对象返回是可重试错误。HTTP 接口处理函数和流程脚本不自动提升返回的失败信封,需要失败时显式 throw result.error。重试耗尽后丢弃(Discard),死信保存和人工重放由部署方协助确认,没有自动死信恢复保证。

已绑定视频但流程没有启动,重复事件该直接返回吗?#

不能仅凭 affected === 0 提前返回,也不能无条件启动。申报 data:read,查询记录仍为 waiting_artifacts 且绑定同一个 fileId 后,复用稳定流程名、bizId 和 seed 补启;缺记录、已改绑或状态已推进则返回对象。查询和启动仍非原子,完整检查见事件、通知与状态。

store 的 createdAt 与业务响应数据结构的 created_at 要统一改名吗?#

不要。SQL 物理列仍为 created_at / updated_at,JS store 返回及筛选/排序使用 createdAt / updatedAt;创建和更新时间由平台维护,不能写进业务记录。已约定的业务响应数据结构保留 created_at,从 record.createdAt 映射,不改变传输契约,见共享契约。

插件升级时,正在运行的流程怎么办?#

不要假设流程能安全续跑:流程定义随实例固化,但脚本按名字解析,升级后可能执行新版本脚本。涉及等待、飞行或长任务的流程,先撤掉触发、确认在途实例清零,再替换插件资产。

返回 accepted 或通知 delivered 算不算设备动作完成?#

不算。accepted 只是受理,delivered 只是下游服务收下。用任务、设备或业务记录的权威状态确认最终结果;超时后先查状态,再用同一幂等键决定是否重试。

发布#

只改了前端或后端,需要怎样发布?#

更新有变化的插件版本,在工作区执行 pack,上传本次生成的行业包 zip。前后端源码和版本可独立演进,但平台上传需要行业 / 能力结构,独立前端或后端插件 zip 不能直接上传。发布前共同验证接口兼容性;平台回滚恢复整体插件生效态,操作见安装、升级与回滚。
修改于 2026-10-22 07:02:43
上一页
术语表
Built with