Skip to content

插件安装与更新 ​

从核心 v0.0.4 开始,插件使用「独立插件仓库 + 标准 ZIP 发行包 + 安装器 CLI + 编译期注册」模式。安装器负责校验发行包、安装前后端源码、保存迁移、生成注册文件、执行受限迁移并登记元数据;不支持运行时加载未知 Go 代码或远程 JavaScript。

版本基线 ​

接口端和管理端使用同一核心标签。正式开发新插件统一基于 v0.0.4:

bash
git fetch --tags --prune
git switch -c plugin/news-v1.0.0 v0.0.4

推荐一个插件一个仓库,插件在自己的分支与标签上演进,升级不再把开发商分支合并回核心主分支。

标准发行包结构 ​

text
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 清单 ​

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;名称、路径、接口等声明字段继续由新清单同步。

打包与校验 ​

bash
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、依赖与许可证 → 备份数据库与构建产物 → 确认目标目录没有未提交修改 → 在测试环境先安装。

只安装源码 ​

bash
go run . plugin install /path/news-v1.0.0.zip \
  --server-root . \
  --admin-root ../admin_client

该方式不连接数据库,输出 数据库=false:插件记录、迁移记录、菜单映射和安装日志都不会写入。之后准备好数据库时,用同一个发行包重新执行 --apply-database 补齐,不能使用 upgrade(数据库中尚无插件记录)。

完整安装(含数据库) ​

bash
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(停用)。

构建与启用 ​

bash
# 后端
gofmt -l . && go vet ./... && go test ./... && go build ./...

# 管理端
pnpm exec vue-tsc --noEmit && pnpm build
  1. 发布后端与管理端构建产物;
  2. 在「系统维护 → 插件管理」确认安装版本与程序版本一致;
  3. 启用插件(安装器不会自动启用);
  4. 重启管理端 API 与用户端 API(启停均需重启生效);
  5. 给普通角色分配插件菜单与按钮权限,完成冒烟测试。

启用前访问 /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 与三份版本文档。

升级流程 ​

升级前先在插件管理页面停用插件并重启服务,然后:

bash
go run . plugin upgrade /path/news-v1.1.0.zip \
  --server-root . \
  --admin-root ../admin_client \
  --config config.yaml \
  --apply-database

升级器要求:插件已安装且处于停用状态、目标版本高于当前版本、依赖插件已启用且版本一致、已执行迁移的摘要不得改变。升级通过菜单业务键更新原菜单;未出现在新清单中的旧菜单不会自动删除,避免误删角色授权。

完成后重新构建、发布、启用并重启两个 API 服务。

停用、移除与彻底清理 ​

停用 ​

在插件管理页面停用 → 重启两个 API 服务 → 确认路由与后台任务不再运行。停用不删除业务表、菜单、授权、文件、迁移记录或源码。

可恢复移除(remove) ​

bash
go run . plugin remove news \
  --server-root . \
  --admin-root ../admin_client \
  --config config.yaml

执行条件:插件已停用并完成重启、没有已启用插件依赖当前插件。执行结果:单事务删除角色授权、菜单、菜单映射和插件记录(物理删除,避免唯一键占用);保留业务表、迁移历史、安装日志和上传文件;删除前后端源码并重新生成注册文件;命令中断后可重复执行继续清理。

彻底清理(purge) ​

bash
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 服务已重启;
  • [ ] 角色权限已分配,冒烟测试通过。