3、插件项目结构:package.json配置、入口文件、manifest清单、资源文件组织
好,咱们直接进入正题。一个CVAT插件项目,说白了就是一堆文件按照特定规则摆在一起。我刚开始接触时也觉得挺乱的,但摸清楚套路后,你会发现其实就那么几样东西。
我个人习惯把插件项目比作一个「工具箱」。package.json是箱子的标签,入口文件是开箱的把手,manifest清单是工具清单,资源文件就是里面的扳手螺丝刀。缺一个,这箱子就用不顺手。
3.1 package.json:插件的身份证
每个插件项目根目录下都得有一个 package.json。这玩意儿不光给npm看,CVAT的插件加载器也会读它。我见过不少新手直接复制别人的配置,结果字段名写错了,插件死活加载不上。
核心字段就这几个:
| 字段 | 说明 | 示例值 |
|---|---|---|
name |
插件唯一标识,建议用 cvat- 前缀 |
cvat-plugin-auto-annotate |
version |
语义化版本号 | 1.0.0 |
main |
入口文件路径 | dist/index.js |
cvat |
CVAT专属配置块 | 见下方代码 |
这里有个坑——cvat 字段是CVAT自己定义的,不是npm标准字段。我曾经在升级插件时忘了加这个字段,结果CVAT后台根本识别不到我的插件,排查了半天才发现。
{
"name": "cvat-plugin-auto-annotate",
"version": "1.0.0",
"description": "自动标注辅助插件",
"main": "dist/index.js",
"cvat": {
"name": "自动标注工具",
"type": "annotation",
"version": "2.0",
"description": "基于预训练模型的自动标注插件"
},
"dependencies": {
"axios": "^0.21.0"
}
}
cvat.type 字段我一般填 annotation 或 interaction。填错了虽然不会报错,但插件会出现在错误的菜单分类里,用户找起来很费劲。
3.2 入口文件:插件的启动开关
入口文件就是 package.json 里 main 字段指向的那个文件。CVAT加载插件时,会先执行这个文件。说白了,这就是插件的「main函数」。
入口文件必须导出一个函数或一个对象。我习惯导出一个函数,因为这样可以在函数内部做初始化逻辑。你想想看,如果导出一个对象,那所有逻辑都得在模块作用域里执行,调试起来很不方便。
// dist/index.js
import CVATPlugin from './core/plugin';
export default function(context) {
// context 是CVAT提供的上下文对象
const plugin = new CVATPlugin(context);
plugin.init();
return plugin;
}
嗯,这里要注意:context 对象里包含了CVAT的核心API,比如 context.jobs(任务列表)、context.shapes(标注形状)等。我刚开始写插件时,总想着自己维护状态,后来发现直接用 context 里的东西就够了,省事不少。
3.3 manifest清单:告诉CVAT你的插件长啥样
manifest清单文件通常叫 cvat-plugin.json 或直接写在 package.json 的 cvat 字段里。我个人更推荐单独写一个文件,因为这样结构更清晰,尤其是当插件功能复杂时。
manifest里最重要的几个东西:
- 插件名称:显示在CVAT界面上的名字
- 图标:插件按钮的图标,支持SVG或字体图标
- 权限声明:插件需要访问哪些CVAT资源
- UI插槽:插件要挂载到CVAT的哪个位置
{
"name": "自动标注工具",
"icon": "icon-auto-annotate.svg",
"permissions": ["read:job", "write:shape"],
"slots": {
"sidebar": "sidebar.html",
"toolbar": "toolbar-button"
}
}
permissions 里只写了 read:job,结果插件想往任务里写数据时直接报403。记住,权限声明是白名单机制,没写的权限默认都没有。
3.4 资源文件组织:别把文件堆成一团
资源文件包括HTML模板、CSS样式、图片图标、语言包等。我见过最乱的项目,所有文件都扔在根目录下,找起来跟大海捞针似的。
我建议按功能模块来组织目录:
my-cvat-plugin/
├── package.json
├── cvat-plugin.json
├── src/
│ ├── index.js # 入口文件
│ ├── core/ # 核心逻辑
│ │ ├── plugin.js
│ │ └── utils.js
│ ├── ui/ # UI相关
│ │ ├── sidebar.html
│ │ └── styles.css
│ └── assets/ # 静态资源
│ ├── icons/
│ └── locales/
├── dist/ # 构建输出
└── README.md
为什么这么分?因为CVAT加载资源时,会根据 slots 配置去找对应的文件。比如 sidebar.html 放在 ui/ 目录下,manifest里写 "sidebar": "ui/sidebar.html",这样路径清晰,别人接手你的代码也容易看懂。
3.5 知识体系总览
说了这么多,咱们用一张图把整个结构串起来。我画了个SVG图,你看一眼就明白了:
这张图把四个核心组件的关系画得很清楚。你写插件时,就按这个结构来组织代码,基本不会出大问题。
3.6 实战中的一些碎碎念
最后聊几个我踩过的坑:
- 路径问题:manifest里的路径是相对于插件根目录的,不是相对于入口文件。我一开始写成了
../ui/sidebar.html,结果CVAT报404。 - 构建产物:如果你用Webpack或Rollup打包,记得把
dist/目录提交到git。我见过有人只提交了src/,结果别人拉下来跑不了。 - 版本兼容:CVAT版本升级后,
cvat.version字段要跟着改。我吃过一次亏,插件在CVAT 2.0上跑得好好的,升级到2.1后直接崩了,就是因为API变了但版本号没更新。
一句话总结: package.json管身份,入口文件管启动,manifest管权限和位置,资源文件管长相。把这四样理清楚,你的插件项目就稳了。