# 开发 mm Plugin 插件

## 规则（Rules）

- 插件位于 `app/{模块名}/plugin/{插件名}/` 下
- 一个插件必须包含 `plugin.json` + `index.js`
- API 目录支持多种命名模式（同一插件可并存）：
  - `api_client` — 简洁模式，不带模块前缀
  - `api_{模块名}_client` — 显式模式，带模块前缀
  - `api_{模块名}_web` — Web 页面
  - `api_upload` 等 — 特殊功能目录
- `plugin.json` 中 `app` 字段指定所属应用，`name` 全局唯一
- **所有开发操作前必须先调用 `get_run_path` 获取运行路径**

## 方法（Methods）

### 步骤0：获取运行路径

使用 `get_run_path` 工具获取当前程序运行根目录，确认 mm_os 项目路径。后续所有文件操作基于此路径。

### 步骤1：确定插件所属模块并参考现有结构

明确插件属于哪个 App（如 sys、tool、user）。使用 `ls` 查看 `app/{模块名}/plugin/` 下的现有插件，**优先参考 `app/sys/plugin/main/` 和 `app/sys/plugin/tencent/`** 的目录结构和 api.json 写法。

### 步骤2：创建目录结构

使用 `make_dir` 创建目录（此步骤只创建目录，不创建文件）。选择一种或多种 API 目录模式：

```
app/{模块名}/plugin/{插件名}/
├── plugin.json
├── index.js
├── api_client/                  # 简洁模式：不带模块前缀
│   └── {接口名}/
├── api_{模块名}_client/         # 显式模式：带模块前缀
│   └── {接口名}/
├── api_{模块名}_web/            # Web页面
│   └── index/
├── api_upload/                  # 特殊功能（可选）
│   └── {功能名}/
├── static/                      # 静态资源（可选）
└── task/                        # 定时任务（可选）
    └── {任务名}/
```

### 步骤3：编写 plugin.json

使用 `write_text` 创建插件配置文件：

```json
{
    "name": "my_plugin",
    "title": "我的插件",
    "description": "插件描述",
    "version": "1.0.0",
    "app": "sys",
    "author": "作者名",
    "main": "./index.js",
    "state": 1,
    "icon": "/sys/my_plugin/img/logo.png",
    "cmd": "sys.my_plugin"
}
```

### 步骤4：编写 index.js 生命周期

使用 `write_text` 创建插件主逻辑。返回值：`null` 成功，非空字符串为错误。

```javascript
module.exports = {
    async _init(option) {
        var err = null;
        var api = $.admin.api('名称', '标题');
        await api.call('update', 'app/');
        return err;
    },

    async install(option) {
        var err = null;
        return err;
    },

    async uninstall(option) {
        var err = null;
        return err;
    },

    async start(option) {
        var err = null;
        return err;
    },

    async stop(option) {
        var err = null;
        return err;
    },

    main(param1, param2) {
        var ret = null;
        return ret;
    },

    cmd(content) {
        var ret = "";
        return ret;
    }
};
```

### 步骤5：创建 API 接口文件

在每个 API 目录中使用 `write_text` 创建 `api.json` + `index.js`（可选 `param.json`）。

- **Client 类型 API**（`api_client` / `api_{模块名}_client` 下）：`name` 和 `path` 无固定格式，参考现有插件的写法
- **Web 类型 API**（`api_{模块名}_web` 下）：需要额外字段 `"type": "web"`、`"app"`、`"plugin"`
- 完整示例和字段说明见 `develop_mm_api` work

### 步骤6：注册并验证

将 `state` 设为 1，重启服务端，检查日志确认插件加载成功。

## 技巧（Tips）

- **API 目录命名**：同一插件中两种模式可并存（如 `sys/plugin/main/` 同时有 `api_client` 和 `api_sys_client`）。简洁模式用于内部 API，显式模式用于需标识来源的场景
- **name/path 无固定格式**：`name` 可以是 `api_ls` 或 `sys_pendant`，`path` 可以是 `/api/sys/ls` 或 `/sys/pendant`，参照已有插件保持风格一致即可
- **配置选项**：在 plugin.json 的 `options` 数组中定义可配置项，框架自动生成配置页面
- **参考实现**：`app/sys/plugin/main/` 和 `app/sys/plugin/tencent/` 是功能完整的插件示例
- **运行路径**：始终通过 `get_run_path` 获取正确路径，不硬编码绝对路径
