---
name: create-plugin
description: 快速创建 ThinkCMF 插件的脚手架工具。根据用户需求生成插件主类、控制器、视图模板和配置文件。当用户需要创建新插件、开发插件、生成插件模板时使用此技能。
---

# 快速创建 ThinkCMF 插件

## 工作流程

1. 收集插件需求（名称、功能、是否需要后台管理/API/配置）
2. 创建目录结构
3. 生成插件主类文件
4. 按需生成控制器、视图、配置文件
5. **后台管理控制器**：调用 `create-admin-menu` 技能生成 `@adminMenu` 菜单注解（插件后台菜单 parent 固定为 `'plugin/index'`）

## 需求收集

创建前必须明确以下信息（未提供则询问用户）：

| 参数 | 说明 | 示例 |
|------|------|------|
| 插件英文名 | PascalCase，带 Plugin 后缀 | `Demo`、`CustomLogin` |
| 插件中文名 | 后台显示标题 | `演示插件`、`自定义登录` |
| 功能描述 | 一句话描述 | `提供自定义登录界面` |
| hasAdmin | 是否需要后台管理界面 | 0 或 1 |
| 需要的控制器 | 前台/后台/API | 按需选择 |
| 需要配置项 | 是否需要 config.php | 是/否 |
| 钩子方法 | 需要挂载的钩子点 | `adminDashboard` 等 |

## 命名转换规则

```
类名 CustomAdminLogin → 目录名 custom_admin_login
类名 Demo → 目录名 demo
主文件 CustomAdminLoginPlugin.php
命名空间 plugins\custom_admin_login
```

## 目录结构

```
public/plugins/{plugin_dir}/
├─ controller/                  # [可选] 控制器目录
│  ├─ AdminIndexController.php  # [可选] 后台管理控制器
│  ├─ IndexController.php       # [可选] 前台控制器
│  ├─ ApiAdminIndexController.php # [可选] 后台 API 控制器
│  └─ ApiIndexController.php    # [可选] 前台 API 控制器
├─ view/                        # [可选] 视图目录
│  └─ widget.html               # [可选] Widget 模板
├─ config.php                   # [可选] 插件配置
└─ {PluginName}Plugin.php       # [必须] 插件主类
```

## 文件模板

### 1. 插件主类（必须）

```php
<?php
namespace plugins\{plugin_dir};

use cmf\lib\Plugin;

class {PluginName}Plugin extends Plugin
{
    /**
     * 插件信息
     */
    public $info = [
        'name'        => '{PluginName}',
        'title'       => '{中文名}',
        'description' => '{功能描述}',
        'status'      => 1,
        'author'      => '{作者}',
        'version'     => '1.0'
    ];

    /**
     * 是否有后台管理界面
     */
    public $hasAdmin = {0或1};

    /**
     * 插件安装
     * @return bool
     */
    public function install(): bool
    {
        return true;
    }

    /**
     * 插件卸载
     * @return bool
     */
    public function uninstall(): bool
    {
        return true;
    }

    // 钩子方法按需添加
}
```

### 2. 后台管理控制器

基类：`cmf\controller\PluginAdminBaseController`

菜单注解规则（参考 `create-admin-menu` 技能）：
- 插件后台控制器**不使用** `@adminMenuRoot`（插件菜单统一挂载到系统插件管理下）
- `@adminMenu` 的 `parent` 固定为 `'plugin/index'`
- `index` 方法 `display=true, hasView=true`，其余方法 `display=false`

```php
<?php
namespace plugins\{plugin_dir}\controller;

use cmf\controller\PluginAdminBaseController;

class AdminIndexController extends PluginAdminBaseController
{
    /**
     * 初始化
     */
    protected function initialize()
    {
        parent::initialize();
    }

    /**
     * 插件后台首页
     * @adminMenu(
     *     'name'   => '{中文名}',
     *     'parent' => 'plugin/index',
     *     'display'=> true,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '{功能描述}'
     * )
     */
    public function index()
    {
        return $this->fetch('/index');
    }
}
```

### 3. 前台控制器

基类：`cmf\controller\PluginBaseController`

```php
<?php
namespace plugins\{plugin_dir}\controller;

use cmf\controller\PluginBaseController;

class IndexController extends PluginBaseController
{
    /**
     * 前台首页
     */
    public function index()
    {
        return $this->fetch('/index');
    }
}
```

### 4. 后台 API 控制器

基类：`cmf\controller\PluginRestAdminBaseController`

```php
<?php
namespace plugins\{plugin_dir}\controller;

use cmf\controller\PluginRestAdminBaseController;

class ApiAdminIndexController extends PluginRestAdminBaseController
{
    /**
     * 获取数据列表
     */
    public function index()
    {
        $this->success('success', []);
    }
}
```

### 5. 前台 API 控制器

基类：`cmf\controller\PluginRestBaseController`

```php
<?php
namespace plugins\{plugin_dir}\controller;

use cmf\controller\PluginRestBaseController;

class ApiIndexController extends PluginRestBaseController
{
    /**
     * 获取数据
     */
    public function index()
    {
        $this->success('success', []);
    }
}
```

### 6. 配置文件

```php
<?php
// 插件配置项，后台可视化编辑
return [
    '{config_key}' => [
        'title' => '{配置标题}',
        'type'  => 'text',        // text|password|number|textarea|select|radio|checkbox|date|datetime|color|image|location
        'value' => '',
        'tip'   => '{帮助提示}',
    ],
];
```

### 7. Widget 视图模板

```html
<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title">{$title}</h3>
    </div>
    <div class="panel-body">
        <!-- 插件内容 -->
    </div>
</div>
```

## 控制器基类选择指南

| 场景 | 基类 |
|------|------|
| 插件前台页面 | `PluginBaseController` |
| 插件后台管理 | `PluginAdminBaseController` |
| 插件后台 API | `PluginRestAdminBaseController` |
| 插件前台 API | `PluginRestBaseController` |

## 钩子实现模式

### 仪表板 Widget（返回数组）

```php
public function adminDashboard()
{
    $config = $this->getConfig();
    $this->assign('config', $config);
    return [
        'width'  => 6,
        'view'   => $this->fetch('widget')->getContent(),
        'plugin' => '{PluginName}'
    ];
}
```

### 视图注入（直接输出）

```php
public function footerStart($param)
{
    $config = $this->getConfig();
    $this->assign($config);
    echo $this->fetch('widget');
}
```

### 视图返回

```php
public function hookName($param)
{
    $config = $this->getConfig();
    $this->assign('config', $config);
    return $this->fetch('widget');
}
```

## 模板语法速查

| 语法 | 说明 |
|------|------|
| `{$var}` | 输出变量 |
| `{$var\|default=''}` | 带默认值 |
| `{:func()}` | 调用函数 |
| `{:lang('KEY')}` | 国际化 |
| `{:cmf_plugin_url('Name://Ctrl/act')}` | 插件 URL |
| `__PLUGIN_TMPL__` | 插件模板目录路径 |
| `<volist name="list" id="vo">` | 循环 |
| `<if condition="$var">` | 条件 |
| `<empty name="var">` | 空值判断 |

## 数据库表规范

插件数据表命名：`plugin_{插件目录名}_{表名}`

示例：`plugin_demo_records`

## 检查清单

- [ ] 插件主类继承 `cmf\lib\Plugin`
- [ ] `$info` 数组包含 name、title、description、status、author、version
- [ ] `install()` 和 `uninstall()` 方法存在且返回 bool
- [ ] 命名空间与目录路径一致
- [ ] 控制器继承正确的基类
- [ ] 后台管理控制器包含 `@adminMenu` 注解，parent 为 `'plugin/index'`（参考 `create-admin-menu` 技能）
- [ ] 数据表使用 `plugin_{name}_` 前缀
- [ ] 代码中无 `exit` 或 `die`
- [ ] 中文注释完整
