从零写出你的第一个插件

这一节我们完整走一遍流程:建骨架、写配置、跑通、验证。你最终会得到一个「读取当前选中素材并显示其尺寸与标签」的窗口插件,它能用上 manifest.json、index.html、plugin.js 三个文件和四个 Eagle API。

第一步:确认环境

  1. 安装并启动 Eagle 桌面应用(下载页面)。建议用最新版,因为后续章节会用到需要 4.0 build18 以上的能力。
  2. 在 Eagle 窗口按 P 键,或点工具栏的「插件」按钮,打开插件面板。
  3. 在菜单里选择「开发者选项」→「创建插件」。
  4. 在弹出的类型选择里选「窗口」。
  5. 选一个空目录作为保存位置,完成创建。

创建完成后目录里会有四个条目:manifest.json、logo.png、index.html、js/plugin.js。用 VS Code 打开整个文件夹(不是单个文件),接下来所有编辑都在这里进行。

第二步:写 manifest.json

窗口插件的入口由 main 对象定义。最精简可用的配置如下:

{
    "id": "LBCZE8V6LPCKD",
    "version": "1.0.0",
    "name": "我的第一个插件",
    "logo": "/logo.png",
    "keywords": ["screenshot", "image"],
    "devTools": true,
    "main": {
        "url": "index.html",
        "width": 640,
        "height": 480,
        "minWidth": 480,
        "minHeight": 320
    }
}

几个字段值得解释:

  • id 是插件的唯一标识,创建时由 Eagle 生成,之后不要随意改动——商店和已安装列表都靠它认插件。
  • logo 指向图标文件,官方建议用 128×128 的 PNG,因为 PNG 对透明度支持最好。开发阶段可以先放着不管。
  • devTools 这里设成 true,方便按 F12 调试。发布前必须改回 false,这是审核标准的硬性要求之一。
  • minWidth/minHeight 限制窗口不能被拖到太小,避免布局被压坏。

第三步:写 index.html

页面骨架很薄,核心是引入 plugin.js:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
    <title>我的第一个插件</title>
    <script type="text/javascript" src="js/plugin.js"></script>
    <style>
        body {
            font-family: -apple-system, "Segoe UI", sans-serif;
            margin: 0;
            padding: 16px;
        }
        .card {
            border: 1px solid rgba(128,128,128,.3);
            border-radius: 6px;
            padding: 12px;
            margin-bottom: 8px;
        }
    </style>
</head>
<body>
    <div id="summary">正在读取选中素材…</div>
    <div id="detail"></div>
</body>
</html>

那个 viewport 里的 maximum-scale=1, user-scalable=no 是官方模板的写法:插件窗口是可缩放的原生窗口,但页面内容不该被用户捏大捏小。

第四步:写 plugin.js

eagle.onPluginCreate(async (plugin) => {
    // 插件自身信息,来自 manifest.json
    console.log('id:', plugin.manifest.id);
    console.log('path:', plugin.path);

    // 读取用户在 Eagle 中当前选中的素材
    const items = await eagle.item.getSelected();
    const summary = document.querySelector('#summary');
    const detail = document.querySelector('#detail');

    if (items.length === 0) {
        summary.textContent = '请先在 Eagle 中选中至少一个素材';
        return;
    }

    summary.textContent = `已选中 ${items.length} 个素材`;

    for (const item of items) {
        const card = document.createElement('div');
        card.className = 'card';
        card.innerHTML = `
            <strong>${item.name}</strong><br>
            尺寸:${item.width} × ${item.height}<br>
            标签:${item.tags.length ? item.tags.join(', ') : '无'}<br>
            评分:${item.star} 星
        `;
        detail.appendChild(card);
    }
});

eagle.onPluginShow(() => {
    console.log('插件窗口显示');
});

eagle.onPluginHide(() => {
    console.log('插件窗口隐藏');
});

eagle.item.getSelected() 返回的是 Item 实例数组,name、width、height、tags、star 都是实例属性,直接读就行——不需要额外调用任何方法。

第五步:运行与验证

  1. 点插件面板上的「插件」按钮。
  2. 在菜单里找到「我的第一个插件」,点击它,窗口会弹出。
  3. 在 Eagle 主界面里用鼠标点选几个素材,然后切回插件窗口——你会看到卡片数量跟着变化;如果插件窗口被隐藏过,onPluginShow 会在 Console 里留下日志。
  4. 按 F12 打开 DevTools,切到 Console 面板,确认能看到 id: 和 path: 两行输出。

四条验证全部通过,就说明链路完全打通了:Eagle 加载了 manifest、载入了 index.html、执行了 plugin.js、eagle.item API 正常返回数据。

下一步可以加什么

现在这个插件还只是「读」。加一个写操作的演示,只要两行:

// 给选中的素材统一打上标签并保存
for (const item of items) {
    item.tags = ['processed', '2026'];
    await item.save();
}

这里体现了 Eagle Plugin API 的核心设计哲学:取回来的对象是活的引用,改完调 save() 才落盘。不要试图去磁盘上找 metadata.json 手改,那是审核明确不建议、也最容易把资源库改坏的做法。

常见坑

忘了把 devTools 改回 false。 本地开发全程开着很方便,但发布版本的 manifest.json 里 devTools 必须是 false,否则在「发布设置与可审核性」这一项直接不通过。

在 plugin.js 里混用两套模块语法。 Eagle 插件的模块加载走 CommonJS。跨文件复用要写 require('./xxx.js'),然后用 module.exports 导出;不要用 ESM 的 import/export。同理,index.html 里只能通过 script 标签引入本地 js 文件,不能直接引 npm 包。

用 item.save() 之前忘了 await。 所有 Eagle API 都返回 Promise。漏掉 await 时代码不会报错,但 save() 可能还没落盘窗口就关了,表现为「改了没生效」这种极难排查的问题。

整理人:WorkBuddy