插件安装与更新
从核心 v0.0.4 开始,插件使用「独立插件仓库 + 标准 ZIP 发行包 + 安装器 CLI + 编译期注册」模式。安装器负责校验发行包、安装前后端源码、保存迁移、生成注册文件、执行受限迁移并登记元数据;不支持运行时加载未知 Go 代码或远程 JavaScript。
版本基线
接口端和管理端使用同一核心标签。正式开发新插件统一基于 v0.0.4:
git fetch --tags --prune
git switch -c plugin/news-v1.0.0 v0.0.4推荐一个插件一个仓库,插件在自己的分支与标签上演进,升级不再把开发商分支合并回核心主分支。
标准发行包结构
news-v1.0.0/
├── plugin.json # 插件清单(位于 ZIP 根目录)
├── README.md CHANGELOG.md LICENSE
├── docs/
│ ├── API.md api/v1.0.0.md
│ ├── DATABASE.md database/v1.0.0.md
│ └── updates/v1.0.0.md
├── server_api/ # internal/plugins/news/...
├── admin_client/ # src/plugins/news/...
└── database/migrations/v1.0.0.sql固定规则:后端入口必须位于 server_api/internal/plugins/{plugin_id}/plugin.go;管理端插件只能位于 admin_client/src/plugins/{plugin_id};迁移位于发行包 database/ 目录;包内不得包含配置文件、密钥、证书、node_modules 或 dist;docs/api/v{version}.md 与 docs/database/v{version}.md 为强制交付文件,缺失或为空时安装器拒绝校验。
plugin.json 清单
{
"plugin_id": "news",
"name": "新闻资讯",
"version": "1.0.0",
"core_version": "0.0.4",
"logo": "plugins/news/logo.png",
"author": "开发者或维护团队",
"homepage": "https://example.com/plugins/news",
"description": "提供新闻分类、文章发布和用户端阅读能力",
"dependencies": [],
"migrations": [
{
"version": "1.0.0",
"file": "database/migrations/v1.0.0.sql",
"checksum": "迁移文件的64位SHA256",
"description": "创建新闻资讯基础表"
}
],
"menus": [
{ "key": "news", "parent_key": "", "name": "新闻资讯", "type": 1, "path": "/plugin/news", "api_path": "", "icon": "Document", "sort": 10, "status": 1 },
{ "key": "article", "parent_key": "news", "name": "文章管理", "type": 2, "path": "/plugin/news/article", "api_path": "GET:/admin/plugin/news/article/list", "icon": "DocumentCopy", "sort": 1, "status": 1 },
{ "key": "article_create", "parent_key": "article", "name": "新增文章", "type": 3, "path": "", "api_path": "POST:/admin/plugin/news/article/create", "sort": 1, "status": 1 }
]
}菜单要点:
- 只使用
key与parent_key描述层级,禁止提供id/parent_id;安装器按业务键创建自增 ID 并写入sys_plugin_menu; - 菜单类型:1 目录、2 页面、3 按钮;页面路径必须位于
/plugin/{plugin_id}/; api_path与实际请求方法和路径一致(METHOD:/route);- 管理员自定义过父级后,升级保留实际
parent_id;名称、路径、接口等声明字段继续由新清单同步。
打包与校验
cd news-v1.0.0
zip -r ../news-v1.0.0.zip .
shasum -a 256 ../news-v1.0.0.zip
cd server_api
go run . plugin validate /path/news-v1.0.0.zip校验内容包括:ZIP ≤ 100MB、文件数 ≤ 2000、禁止路径穿越与符号链接、核心版本精确匹配、后端入口存在、菜单业务键唯一且父级存在、页面路径前缀正确、迁移 SHA256 一致、迁移 SQL 只操作当前插件表。
安装
安装前
验证 ZIP 摘要 → 审查源码、SQL、依赖与许可证 → 备份数据库与构建产物 → 确认目标目录没有未提交修改 → 在测试环境先安装。
只安装源码
go run . plugin install /path/news-v1.0.0.zip \
--server-root . \
--admin-root ../admin_client该方式不连接数据库,输出 数据库=false:插件记录、迁移记录、菜单映射和安装日志都不会写入。之后准备好数据库时,用同一个发行包重新执行 --apply-database 补齐,不能使用 upgrade(数据库中尚无插件记录)。
完整安装(含数据库)
go run . plugin install /path/news-v1.0.0.zip \
--server-root . \
--admin-root ../admin_client \
--config config.yaml \
--apply-database数据库安装器会:获取插件级数据库互斥锁 → 执行可安全重试的业务表迁移 → 在同一事务写入迁移记录、系统菜单、菜单映射、插件信息与安装日志 → 任一失败回滚整个元数据事务。MySQL DDL 会隐式提交,因此迁移脚本必须可重复执行,安装器保证的是元数据原子提交。
新插件安装后默认 status=2(停用)。
构建与启用
# 后端
gofmt -l . && go vet ./... && go test ./... && go build ./...
# 管理端
pnpm exec vue-tsc --noEmit && pnpm build- 发布后端与管理端构建产物;
- 在「系统维护 → 插件管理」确认安装版本与程序版本一致;
- 启用插件(安装器不会自动启用);
- 重启管理端 API 与用户端 API(启停均需重启生效);
- 给普通角色分配插件菜单与按钮权限,完成冒烟测试。
启用前访问 /admin/plugin/{id}/* 或 /api/plugin/{id}/* 返回 404 属正常现象;权限不足应返回 403。
更新
版本升级规则
| 变化 | 版本动作 |
|---|---|
| 不兼容的接口、配置或数据结构调整 | 主版本 +1,其余归零(1.4.2 → 2.0.0) |
| 向后兼容的新功能 | 次版本 +1(1.4.2 → 1.5.0) |
| 兼容的修复、UI 与文档调整 | 修订版本 +1(1.4.2 → 1.4.3) |
每次发布使用高于已安装版本的新版本号,禁止同版本重新打包。开发商侧需同步更新 plugin.json.version、Manifest.Version、迁移、菜单、CHANGELOG 与三份版本文档。
升级流程
升级前先在插件管理页面停用插件并重启服务,然后:
go run . plugin upgrade /path/news-v1.1.0.zip \
--server-root . \
--admin-root ../admin_client \
--config config.yaml \
--apply-database升级器要求:插件已安装且处于停用状态、目标版本高于当前版本、依赖插件已启用且版本一致、已执行迁移的摘要不得改变。升级通过菜单业务键更新原菜单;未出现在新清单中的旧菜单不会自动删除,避免误删角色授权。
完成后重新构建、发布、启用并重启两个 API 服务。
停用、移除与彻底清理
停用
在插件管理页面停用 → 重启两个 API 服务 → 确认路由与后台任务不再运行。停用不删除业务表、菜单、授权、文件、迁移记录或源码。
可恢复移除(remove)
go run . plugin remove news \
--server-root . \
--admin-root ../admin_client \
--config config.yaml执行条件:插件已停用并完成重启、没有已启用插件依赖当前插件。执行结果:单事务删除角色授权、菜单、菜单映射和插件记录(物理删除,避免唯一键占用);保留业务表、迁移历史、安装日志和上传文件;删除前后端源码并重新生成注册文件;命令中断后可重复执行继续清理。
彻底清理(purge)
go run . plugin purge news \
--server-root . \
--admin-root ../admin_client \
--config config.yaml \
--confirm news不可恢复,必须先备份。要求最新归档版本存在非空的 database/v{version}.md;先执行可恢复移除,再删除 plg_{id}_* 业务表;所有业务表删除成功后才事务删除迁移历史与安装日志。检测到插件表被其他前缀的表外键引用时拒绝清理;上传文件不会自动删除,需按数据库引用文档单独审查。
失败与恢复
- ZIP 校验失败时不会写入源码或数据库;
- 源码复制或注册文件生成失败时恢复原插件目录并重新生成;
- 数据库处理失败时插件保持停用,不会被加载;MySQL DDL 可能已部分提交,应对照迁移脚本与备份检查;
- 不允许通过修改迁移摘要绕过校验,不允许直接改数据库插件状态绕过安装器;
- 安装后编译失败:修复源码或恢复安装前代码,再执行
go run . plugin generate --server-root .。
安装检查清单
- [ ] ZIP 摘要、源码、SQL、依赖与许可证已审查,数据库与构建产物已备份;
- [ ] 已在测试环境完成安装;
- [ ]
register_gen.go只包含预期插件; - [ ] 迁移记录、菜单映射、安装日志检查无误;
- [ ] 后端与管理端构建通过,构建产物已发布;
- [ ] 插件已启用,两个 API 服务已重启;
- [ ] 角色权限已分配,冒烟测试通过。