QQ扫一扫联系
FocusAny 是一个专注高效的AI工具条,可以使用 Alt / Option+空格 一键唤起,通过插件快速安装,可以扩展出非常多的功能。
目前支持 Windows、MacOS、Linux 系统。
创建一个文件夹,写入以下几个文件,即可完成一个最简单的插件开发。
config.json
index.html
logo.png
config.json
{ "name": "MyPlugin", "title": "我的插件", "description": "这是一个测试插件", "version": "1.0.0", "logo": "logo.png", "main": "index.html", "actions": [ { "name": "default", "type": "web", "matches": [ "我的插件" ] } ]}
index.html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>hello world</h1> </body> </html>
logo.png
准备一个你喜欢的图片,重命名为 logo.png,尺寸为 128x128 放入到插件目录中。
插件管理 → 选择本地目录插件 ,选择刚刚创建的插件目录。
在 FocusAny 中输入 我的插件,即可看到刚刚创建的插件。
这样,一个最简单的插件就开发完成了 🎉🎉🎉
随后,你可以使用前端技术开发更丰富的功能,插件的每部分功能说明可以参考详细的配置。
开发好的插件目录应该包含所有已打包好的资源文件(包括 js、css、图片等)。
如果使用的是 vue、react 等框架,请在插件管理中重新添加打包目录(如 dist 或 build)验证插件是否正常。
① 在 focusany.com注册账号
② 进入到个人中心,完成实名认证 focusany.com/member_cer
进入到 用户中心 → 开发的插件 页面,添加一个新的插件,填写插件的相关信息。
插件创建完成后,创建一个新的版本,上传插件的压缩包,等待审核通过后即可发布。
审核完成后,插件进入预发布状态,需要手动点击发布按钮,即可成功发布到插件市场。
{ // 插件定义 schema,可以方便输入提示和校验 "$schema": "https://focusany.com/sdk/config.schema.json", // 插件名称,整个平台唯一,格式为大写驼峰命名 "name": "BasicExample", // 插件版本,格式为 主版本号.次版本号.修订版本号 // 主版本号:功能大的升级 // 次版本号:日常迭代功能更新 // 修订版本号:修复 bug "version": "1.0.0", // 插件标题,显示在插件列表中 "title": "示例插件", // 插件作者 "author": "focusany", // 插件主页 "homepage": "https://focusany.com", // 插件说明 "description": "示例插件说明", // 插件主页面 "main": "index.html", // 插件快捷面板主页面 "mainFastPanel": "fastpanel.html", // 插件 logo,尺寸为 128x128,相对于插件目录 "logo": "logo.svg", // 插件预加载文件,相对于插件目录 "preload": "preload.cjs", // 插件支持的平台,不填写则支持所有平台 "platforms": [ "win", "mac", "linux" ], // 插件依赖的软件版本,如 * 或 >=1.0.0 或 <=1.0.0 或 >1.0.0 或 <1.0.0,此为选填,留空表示不限制 FocusAny 版本。 "versionRequire": "*", // 插件动作配置 "actions": [ // 打开插件(使用文本匹配) { "name": "text-simple", "title": "使用text匹配(简单)", "matches": [ "example-text-simple" ] }, // 打开插件(使用文本匹配) { "name": "text", "title": "使用text匹配", "matches": [ { "type": "text", "minLength": 1, "maxLength": 10, "text": "example-text" } ] }, // 打开插件(使用key匹配) { "name": "key", "title": "使用key匹配", "matches": [ { "type": "key", "key": "example" } ] }, // 打开插件(使用正则匹配) { "name": "regex", "title": "使用正则匹配", "matches": [ { "type": "regex", "regex": "/example/" } ] }, // 打开插件(使用文件匹配) { "name": "file", "title": "使用文件匹配(文件)", "matches": [ { "type": "file", "minCount": 1, "maxCount": 10, "filterFileType": "file", "filterExtensions": [ "xlsx", "png" ] } ] }, // 打开插件(使用文件匹配) { "name": "file-directory", "title": "使用文件匹配(文件夹)", "matches": [ { "type": "file", "minCount": 1, "maxCount": 10, "filterFileType": "directory" } ] }, // 打开插件(使用窗口匹配) { "name": "window", "title": "使用窗口匹配", "matches": [ { "type": "window", "nameRegex": "/iTerm2/" }, { "type": "window", "titleRegex": "/Electron/" }, { "type": "window", "attrRegex": { "url": "/github.com/" } } ] }, // 打开插件(使用图片匹配) { "name": "image", "title": "使用图片匹配", "matches": [ { "type": "image" } ] }, // 执行render代码 { "name": "code", "title": "使用code匹配(简单)", "type": "code", "matches": [ "example-code" ] }, // 执行后台代码 { "name": "backend", "title": "使用backend匹配(简单)", "type": "backend", "matches": [ "example-backend" ] }, // 执行命令 { "name": "command", "title": "执行一个命令", "type": "command", "matches": [ "example-command" ], "data": { "command": "notepad.exe" } }, // 自定义渲染 { "name": "view", "title": "显示view", "type": "view", "matches": [ { "type": "regex", "regex": "/^\\s*[a-zA-Z0-9]+\\s*$/" } ] }, // 编辑器匹配 { "name": "editor", "title": "使用editor匹配", "matches": [ { "type": "editor", "faDataTypes": [ "FileEditorExample" ] } ] } ], // 插件设置 "setting": { // 插件是否打开即自动分离,默认为 false "autoDetach": false, // 分离模式默认位置,可选 center left-top left-bottom right-top right-bottom "detachPosition": "center", // 分离模式默认是否置顶 "detachAlwaysOnTop": false, // 默认高度,支持 数字 或 百分比,设置后窗口大小将默认为分离模式 "height": "600", // 默认宽度,支持 数字 或 百分比,设置后窗口大小将默认为分离模式 "width": "800", // 快速面板高度,单位为像素,默认为 100 "heightFastPanel": 100, // 是否只允许打开一个窗口,默认为 true "singleton": true, // 窗口默认缩放比例,100表示原始大小 "zoom": 100 }, // 开发配置 "development": { // 开发环境,prod 表示生产环境,dev 表示开发环境,prod 环境会忽略 development 的所有配置。 "env": "prod", // 入口文件,当该配置为空时,表示插件应用为模板插件应用。 main 与 preload 至少存在其一。 "main": "http://localhost:8080", // 快速面板入口文件,当该配置为空时,使用主入口文件。 "mainFastPanel": "http://localhost:8080/fastpanel.html" }}
系统会打开一个窗口,加载插件的 main 页面。
系统会打开一个渲染窗口,但是不会显示这个窗口,同时执行 preload.cjs 中定义的代码,比如在 preload.cjs 中定义了 plugin-example-code,那么在插件中就可以执行这个动作。
window.exports = { "code": { "plugin-example-code": async (data) => { console.log('plugin-example-code', data); } } }
系统会在主进程执行 preload 定义的代码。
系统会在主进程执行 data.command 定义的命令。
系统会在快捷面板中渲染该视图。
使用简单的文字匹配,包括拼音、简写等。
使用严格的匹配规则,只有完全匹配才会触发。
使用正则表达式匹配,可以匹配更复杂的规则。
使用图片匹配,可以匹配图片中的内容。
使用文件匹配,可以匹配文件的类型、扩展名等。
使用窗口匹配,可以匹配窗口的标题、名称、属性等。
使用编辑器匹配,用户主动打开某个类型的文件可以触发。
在浏览器开发时,是禁止执行一些本地操作的(比如读取文件、执行系统命令等),但是在插件中,我们可以通过 preload.cjs 文件来执行这些操作。
比如将以下代码写入到 preload.cjs 文件中,即可在插件中读取文件。
const fs = require("fs");window.myFocusAnyApi = { readFile(path) { return fs.readFileSync(path, "utf8"); },};
一个完整的 backend.cjs 文件示例:
module.exports = { "hook": { "installed": async (focusany) => { focusany.showToast('插件已安装') }, "beforeUninstall": async (focusany) => { focusany.showToast('插件即将卸载') }, }, "event": { "testEvent": async (focusany, data) => { console.log('testEvent.focusany', focusany); console.log('testEvent.data', data); focusany.showToast('事件已触发'); return "data from backend : " + JSON.stringify(data) } }, "action": { "plugin-example-backend": async (focusany, data) => { console.log('plugin-example-backend.focusany', focusany); console.log('plugin-example-backend.data', data); // console.log('test', await focusany.showSaveDialog()); focusany.showToast('后台进程已执行'); return 'ok' } }}
随后在插件的页面中,就可以通过 window.myFocusAnyApi.readFile 函数来读取文件。
本示例代码已经上传到 Gitee 和 Github,可以直接根据地址查看。
Gitee 地址:https://gitee.com/modstart-lib/focusany-plugin-example
Github 地址:https://github.com/modstart-lib/focusany-plugin-example
原生 HTML、CSS、JS 开发,无任何框架,可以查看到最基础的插件开发方式。
基于 vue3 + vite + tailwindcss 开发的基础文件编辑器,可以使用很轻量的方式集成一些文件编辑器。
基于 vue3 + vite + tailwindcss 开发的插件示例,可以查看到如何使用 vue3 开发插件。