Skip to content

插件开发指南

本页给出从示例插件复制、改名、开发到本地安装验证的最短路径。

选择插件形态

形态何时使用
kind=app完整业务应用,需要作为租户后台一级菜单出现
kind=plugin可复用能力、配置面板、装修组件或其他插件依赖

如果插件会给租户提供完整业务闭环,例如商城、CMS、CRM,优先使用 kind=app

复制示例插件

bash
cd server/plugins
cp -R mall demo-shop

然后修改:

  • plugin.json 中的 codenamedescriptionpsr4lifecycleentitlement
  • PHP 命名空间,例如 Plugin\Mall\ 改为 Plugin\DemoShop\
  • 菜单 code、权限 code、路由、表名和迁移文件名。
  • 租户前端页面路径和 API 封装。
  • UniApp 分包路径和页面路径。

后端开发

插件后端放在 server/plugins/{code}/app/,通过插件自己的 PSR-4 命名空间加载。

推荐分层:

text
app/
├── model/
├── repository/
├── service/
├── tenantapi/
│   ├── controller/
│   └── route.php
├── api/
│   ├── controller/
│   └── route.php
└── hooks/
    └── Lifecycle.php

租户 API 路由只写裸路由:

php
use think\facade\Route;
use Plugin\DemoShop\app\tenantapi\controller\ProductController;

Route::get('products', ProductController::class . '@index');
Route::post('products', ProductController::class . '@store');

框架运行时会自动包装为 /tenantapi/{plugin_code}/products,并挂载租户上下文、认证、生命周期、权益、RBAC 和日志中间件。

租户级业务表必须包含 tenant_id,Repository 必须使用 $this->query()

php
public function list(array $params): array
{
    return $this->query()
        ->when(!empty($params['keyword']), fn ($q) => $q->whereLike('name', "%{$params['keyword']}%"))
        ->order('id', 'desc')
        ->paginate()
        ->toArray();
}

数据库迁移

迁移放在插件的 migrations/ 目录:

text
server/plugins/demo-shop/migrations/20260605000100_demo_shop_init.php

表结构变更放迁移,不要放生命周期 hook。迁移应可重复执行或安全失败,避免升级中断后无法恢复。

租户后台页面

租户后台源码放在:

text
server/plugins/demo-shop/tenant/
├── api/
└── views/

manifest 菜单中的 component 使用 plugins/{code}/{view} 约定。平台安装或重建时,scripts/sync-plugins.mjs 会把插件前端源码同步进 tenant/srcplatform/src 构建目录。

生命周期

生命周期类用于处理安装、卸载、启用和禁用时的副作用:

php
namespace Plugin\DemoShop\hooks;

use core\plugin\contracts\LifecycleHook;

final class Lifecycle implements LifecycleHook
{
    public function install(): void {}
    public function uninstall(): void {}
    public function enable(int $tenantId): void {}
    public function disable(int $tenantId): void {}
}

生命周期适合处理默认配置、缓存清理、初始化非结构化数据等工作。表结构变更仍然放迁移。

本地安装验证

  1. 登录平台后台。
  2. 插件管理中选择「登记内置插件」,填写 demo-shop
  3. 执行安装。
  4. 到套餐管理中给目标套餐授权插件。
  5. 登录租户后台,在插件应用中启用插件。
  6. 给租户角色分配对应菜单和按钮权限。
  7. 访问插件菜单,创建和查询数据。

打包发布

zip 包要求:

  • plugin.json 必须在 zip 根目录。
  • 插件源码路径不能使用 ../ 或绝对路径。
  • 图标建议放根目录,例如 icon.png
  • 不要打包 node_modules、运行时缓存、构建产物。

推荐结构:

text
demo-shop.zip
├── plugin.json
├── icon.png
├── app/
├── migrations/
├── tenant/
└── uniapp/

发布前检查

  • plugin.json 能通过校验。
  • 插件 code、菜单 code、权限 code 不与已有插件冲突。
  • 依赖插件写入 depends
  • 租户级表包含 tenant_id
  • Repository 没有绕过 $this->query()
  • 启用、禁用、卸载、重新安装能安全执行。
  • 移动端声明了 uniapp.pages 时,源码目录存在。
  • 跑一遍红线测试,确认没有破坏租户隔离。

基于 Apache-2.0 协议开源