幻影网络科技知识库

幻影网络科技知识库

首页
公告
幻影二级域名分发系统
幻影短连接
幻影导航页
模板开发使用教程安装教程
幻影聚合系统
Api
关于
登录 →
幻影网络科技知识库

幻影网络科技知识库

首页 公告 幻影二级域名分发系统 幻影短连接 幻影导航页
模板开发使用教程安装教程
幻影聚合系统 Api 关于
登录
  1. 首页
  2. 幻影聚合系统
  3. 插件开发教程-page页面类型

插件开发教程-page页面类型

0
  • 幻影聚合系统
  • 发布于 2025-09-07
  • 15 次阅读
幻影
幻影
# 🚀 插件开发完整指南

> 本指南提供了完整的插件开发、页面集成和导航结构的详细说明,帮助开发者快速创建功能丰富的插件。

## 📋 目录

- [系统概述](#系统概述)
- [快速开始](#快速开始)
- [插件结构](#插件结构)
- [导航系统](#导航系统)
- [页面开发](#页面开发)
- [AJAX处理](#ajax处理)
- [数据库操作](#数据库操作)
- [钩子系统](#钩子系统)
- [示例插件](#示例插件)
- [最佳实践](#最佳实践)
- [故障排除](#故障排除)

---

## 🎯 系统概述

本插件系统提供了完整的页面功能集成方案,支持:

- ✅ **智能导航集成** - 自动在用户中心生成导航菜单
- ✅ **灵活页面路由** - 支持多页面插件和单页面插件
- ✅ **统一AJAX处理** - 标准化的请求处理机制
- ✅ **数据库集成** - 完整的数据持久化支持
- ✅ **钩子系统** - 与系统事件深度集成
- ✅ **权限控制** - 完善的用户权限管理

### 核心文件

| 文件 | 功能 |
|------|------|
| `user/plugin_page.php` | 插件页面路由系统 |
| `user/plugin_ajax.php` | 插件AJAX请求处理器 |
| `user/index.php` | 用户中心主页(增强导航) |
| `admin/plugin.php` | 插件管理后台 |
| `includes/PluginManager.php` | 插件管理器 |

---

## 🚀 快速开始

### 1. 创建插件目录

```bash
mkdir plugin/my_plugin
cd plugin/my_plugin
```

### 2. 创建基本文件

```
plugin/my_plugin/
├── config.json          # 插件配置
├── index.php            # 插件主文件
├── ajax.php             # AJAX处理
└── pages/               # 用户页面
    └── index.php        # 主页面
```

### 3. 配置文件示例

```json
{
    "name": "我的插件",
    "identifier": "my_plugin",
    "version": "1.0.0",
    "author": "开发者",
    "description": "插件描述",
    "icon": "layui-icon-component",
    "user_pages": [
        {
            "action": "index",
            "title": "主页面",
            "icon": "layui-icon-home"
        }
    ]
}
```

### 4. 扫描并启用

1. 访问 `admin/plugin.php`
2. 点击"扫描插件"
3. 启用您的插件
4. 在用户中心查看效果

---

## 📁 插件结构

### 标准目录结构

```
plugin/your_plugin/
├── config.json          # 📄 插件配置文件
├── index.php            # 🔧 插件主文件(钩子处理)
├── ajax.php             # 🌐 AJAX请求处理
├── pages/               # 📱 用户页面目录
│   ├── index.php        # 🏠 主页面
│   ├── feature1.php     # ⚙️ 功能页面1
│   └── feature2.php     # ⚙️ 功能页面2
├── assets/              # 🎨 静态资源(可选)
│   ├── css/
│   ├── js/
│   └── images/
└── README.md            # 📖 插件说明(可选)
```

### 配置文件详解 (config.json)

```json
{
    "name": "插件显示名称",
    "identifier": "plugin_unique_id",
    "version": "1.0.0",
    "author": "作者名称",
    "description": "插件功能描述",
    "icon": "layui-icon-component",
    "user_pages": [
        {
            "action": "index",
            "title": "主页面",
            "icon": "layui-icon-home"
        },
        {
            "action": "settings",
            "title": "设置",
            "icon": "layui-icon-set"
        }
    ],
    "config": [
        {
            "name": "enable_feature",
            "title": "启用功能",
            "type": "switch",
            "default": "1",
            "tips": "是否启用此功能"
        },
        {
            "name": "api_key",
            "title": "API密钥",
            "type": "input",
            "default": "",
            "tips": "请输入API密钥"
        }
    ]
}
```

**字段说明:**

| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `name` | string | ✅ | 插件显示名称 |
| `identifier` | string | ✅ | 插件唯一标识符 |
| `version` | string | ✅ | 插件版本号 |
| `author` | string | ❌ | 作者信息 |
| `description` | string | ❌ | 插件描述 |
| `icon` | string | ❌ | 插件图标(LayUI图标类名) |
| `user_pages` | array | ❌ | 用户页面配置 |
| `config` | array | ❌ | 插件配置项 |

---

## 🧭 导航系统

### 导航生成规则

插件导航系统支持一级导航和二级导航的灵活组合:

#### 🔹 情况1:有 index + 子页面

**配置:**
```json
{
    "name": "个人工具箱",
    "icon": "layui-icon-util",
    "user_pages": [
        {
            "action": "index",
            "title": "工具箱",
            "icon": "layui-icon-util"
        },
        {
            "action": "qrcode",
            "title": "二维码生成"
        },
        {
            "action": "password",
            "title": "密码生成器"
        }
    ]
}
```

**生成效果:**
```
📁 个人工具箱 ▼
  ├─ 主页面          ← index页面
  ├─ 二维码生成      ← 子功能
  └─ 密码生成器      ← 子功能
```

#### 🔹 情况2:只有 index 页面

**配置:**
```json
{
    "user_pages": [
        {
            "action": "index",
            "title": "工具箱",
            "icon": "layui-icon-util"
        }
    ]
}
```

**生成效果:**
```
📁 工具箱            ← 简单一级导航
```

#### 🔹 情况3:无 index,多页面

**配置:**
```json
{
    "name": "用户中心工具",
    "icon": "layui-icon-user",
    "user_pages": [
        {
            "action": "profile",
            "title": "个人资料管理"
        },
        {
            "action": "security",
            "title": "安全设置"
        }
    ]
}
```

**生成效果:**
```
📁 用户中心工具 ▼    ← 使用插件名
  ├─ 个人资料管理
  └─ 安全设置
```

#### 🔹 情况4:无 index,单页面

**配置:**
```json
{
    "name": "文件管理",
    "user_pages": [
        {
            "action": "upload",
            "title": "文件上传"
        }
    ]
}
```

**生成效果:**
```
📁 文件管理          ← 直接访问功能
```

### 导航配置最佳实践

#### 1. **工具箱类插件**(推荐有 index)
```json
{
    "name": "实用工具箱",
    "icon": "layui-icon-util",
    "user_pages": [
        {
            "action": "index",
            "title": "工具箱",
            "icon": "layui-icon-util"
        },
        {
            "action": "qrcode",
            "title": "二维码生成"
        },
        {
            "action": "password",
            "title": "密码生成器"
        }
    ]
}
```

#### 2. **功能模块类插件**(可以没有 index)
```json
{
    "name": "账户管理",
    "icon": "layui-icon-user",
    "user_pages": [
        {
            "action": "profile",
            "title": "个人资料"
        },
        {
            "action": "security",
            "title": "安全设置"
        }
    ]
}
```

#### 3. **单功能插件**(简单导航)
```json
{
    "name": "文件上传",
    "icon": "layui-icon-upload",
    "user_pages": [
        {
            "action": "upload",
            "title": "文件上传",
            "icon": "layui-icon-upload"
        }
    ]
}
```

---

## 📱 页面开发

### 页面模板

创建 `pages/xxx.php` 文件:

```php
<?php
/**
 * 插件页面模板
 */
if(!defined('IN_CRONLITE')) exit('Access Denied');

// 可用变量:
// $plugin_config - 插件配置数组
// $plugin_info - 插件信息数组  
// $title - 页面标题
// $userrow - 当前用户信息
// $conf - 系统配置
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><?=$title?> - <?=$conf['title']?></title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../assets/libs/layui/css/layui.css">
    <style>
        .plugin-container {
            padding: 15px;
        }
        .feature-card {
            margin-bottom: 15px;
        }
        .stats-item {
            text-align: center;
            padding: 20px;
        }
    </style>
</head>
<body>
    <div class="layui-fluid plugin-container">
        <!-- 页面头部 -->
        <div class="layui-card">
            <div class="layui-card-header">
                <i class="layui-icon layui-icon-component"></i>
                <?=$title?>
            </div>
            <div class="layui-card-body">
                <!-- 主要内容区域 -->
                <div class="layui-row layui-col-space15">
                    <div class="layui-col-md8">
                        <!-- 功能区域 -->
                        <div class="layui-card feature-card">
                            <div class="layui-card-header">功能操作</div>
                            <div class="layui-card-body">
                                <form class="layui-form" lay-filter="pluginForm">
                                    <div class="layui-form-item">
                                        <label class="layui-form-label">输入内容</label>
                                        <div class="layui-input-block">
                                            <input type="text" name="content" placeholder="请输入内容" class="layui-input">
                                        </div>
                                    </div>
                                    <div class="layui-form-item">
                                        <div class="layui-input-block">
                                            <button type="submit" class="layui-btn" lay-submit lay-filter="submit">
                                                <i class="layui-icon layui-icon-ok"></i> 执行操作
                                            </button>
                                        </div>
                                    </div>
                                </form>
                            </div>
                        </div>
                        
                        <!-- 结果显示区域 -->
                        <div class="layui-card">
                            <div class="layui-card-header">操作结果</div>
                            <div class="layui-card-body" id="resultArea">
                                <div class="layui-text">
                                    <p>操作结果将在这里显示...</p>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <div class="layui-col-md4">
                        <!-- 侧边栏 -->
                        <div class="layui-card">
                            <div class="layui-card-header">使用统计</div>
                            <div class="layui-card-body">
                                <div class="stats-item">
                                    <div class="layui-text">
                                        <h3 id="todayCount">0</h3>
                                        <p>今日使用</p>
                                    </div>
                                </div>
                                <div class="stats-item">
                                    <div class="layui-text">
                                        <h3 id="totalCount">0</h3>
                                        <p>总计使用</p>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                        <!-- 帮助信息 -->
                        <div class="layui-card">
                            <div class="layui-card-header">使用说明</div>
                            <div class="layui-card-body">
                                <div class="layui-text">
                                    <p>1. 在输入框中输入内容</p>
                                    <p>2. 点击执行操作按钮</p>
                                    <p>3. 查看操作结果</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="../../assets/libs/layui/layui.js"></script>
    <script>
        layui.use(['form', 'layer'], function(){
            var form = layui.form;
            var layer = layui.layer;
            
            // 加载统计数据
            loadStats();
            
            // 表单提交
            form.on('submit(submit)', function(data){
                var loadIndex = layer.load(2);
                
                $.ajax({
                    type: 'POST',
                    url: '../plugin_ajax.php',
                    data: {
                        plugin: '<?=$plugin_info['identifier']?>',
                        action: 'process_content',
                        content: data.field.content
                    },
                    dataType: 'json',
                    success: function(res) {
                        layer.close(loadIndex);
                        if(res.code == 0) {
                            $('#resultArea').html('<div class="layui-text"><p>' + res.data + '</p></div>');
                            layer.msg('操作成功!', {icon: 1});
                            loadStats(); // 重新加载统计
                        } else {
                            layer.msg(res.msg, {icon: 2});
                        }
                    },
                    error: function() {
                        layer.close(loadIndex);
                        layer.msg('请求失败,请重试!', {icon: 2});
                    }
                });
                
                return false;
            });
            
            // 加载统计数据
            function loadStats() {
                $.ajax({
                    type: 'POST',
                    url: '../plugin_ajax.php',
                    data: {
                        plugin: '<?=$plugin_info['identifier']?>',
                        action: 'get_stats'
                    },
                    dataType: 'json',
                    success: function(res) {
                        if(res.code == 0) {
                            $('#todayCount').text(res.data.today || 0);
                            $('#totalCount').text(res.data.total || 0);
                        }
                    }
                });
            }
        });
    </script>
</body>
</html>
```

### 页面开发要点

1. **安全检查**:页面开头必须检查 `IN_CRONLITE` 常量
2. **响应式设计**:使用 LayUI 的栅格系统适配不同屏幕
3. **用户体验**:提供加载提示、操作反馈和错误处理
4. **数据交互**:通过 AJAX 与后端交互,避免页面刷新

---

## 🌐 AJAX处理

### AJAX处理文件 (ajax.php)

```php
<?php
/**
 * 插件AJAX处理
 */
if(!defined('IN_CRONLITE')) exit('Access Denied');

$action = $GLOBALS['plugin_action'];
$plugin_config = $GLOBALS['plugin_config'];
$plugin_info = $GLOBALS['plugin_info'];

switch($action) {
    case 'process_content':
        // 处理内容
        $content = daddslashes($_POST['content']);
        
        if(empty($content)) {
            json_format(['code' => '-1', 'msg' => '内容不能为空!']);
        }
        
        // 记录使用统计
        recordUsage('process_content');
        
        // 处理业务逻辑
        $result = processContent($content);
        
        json_format([
            'code' => 0,
            'msg' => '处理成功',
            'data' => $result
        ]);
        break;
        
    case 'get_stats':
        // 获取使用统计
        $stats = getUsageStats();
        json_format([
            'code' => 0,
            'data' => $stats
        ]);
        break;
        
    default:
        json_format(['code' => '-1', 'msg' => '未知操作!']);
        break;
}

/**
 * 处理内容的业务逻辑
 */
function processContent($content) {
    // 这里实现具体的业务逻辑
    return "处理结果:" . $content;
}

/**
 * 记录使用统计
 */
function recordUsage($action) {
    global $DB, $dbconfig, $userrow, $date;
    
    $tableName = $dbconfig['dbqz'] . '_plugin_stats';
    $userId = $userrow['id'];
    $today = date('Y-m-d');
    
    // 确保统计表存在
    createStatsTable();
    
    try {
        // 检查今天是否已有记录
        $existing = $DB->getRow("SELECT id, use_count FROM `{$tableName}` WHERE user_id='{$userId}' AND action='{$action}' AND use_date='{$today}'");
        
        if($existing) {
            // 更新使用次数
            $newCount = $existing['use_count'] + 1;
            $DB->update($tableName, [
                'use_count' => $newCount,
                'updated_at' => $date
            ], ['id' => $existing['id']]);
        } else {
            // 插入新记录
            $data = [
                'user_id' => $userId,
                'action' => $action,
                'use_date' => $today,
                'use_count' => 1,
                'created_at' => $date,
                'updated_at' => $date
            ];
            $DB->insert($tableName, $data);
        }
    } catch(Exception $e) {
        // 忽略统计错误,不影响主功能
        error_log("recordUsage error: " . $e->getMessage());
    }
}

/**
 * 获取使用统计
 */
function getUsageStats() {
    global $DB, $dbconfig, $userrow;
    
    $tableName = $dbconfig['dbqz'] . '_plugin_stats';
    $userId = $userrow['id'];
    $today = date('Y-m-d');
    
    try {
        // 今日使用次数
        $todayCount = $DB->getColumn("SELECT SUM(use_count) FROM `{$tableName}` WHERE user_id='{$userId}' AND use_date='{$today}'") ?: 0;
        
        // 总使用次数
        $totalCount = $DB->getColumn("SELECT SUM(use_count) FROM `{$tableName}` WHERE user_id='{$userId}'") ?: 0;
        
        return [
            'today' => $todayCount,
            'total' => $totalCount
        ];
    } catch(Exception $e) {
        return ['today' => 0, 'total' => 0];
    }
}

/**
 * 创建统计表
 */
function createStatsTable() {
    global $DB, $dbconfig;
    
    $tableName = $dbconfig['dbqz'] . '_plugin_stats';
    
    try {
        $DB->exec("CREATE TABLE IF NOT EXISTS `{$tableName}` (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `user_id` int(11) NOT NULL,
            `action` varchar(50) NOT NULL,
            `use_date` date NOT NULL,
            `use_count` int(11) DEFAULT 1,
            `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
            `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (`id`),
            UNIQUE KEY `unique_usage` (`user_id`, `action`, `use_date`),
            KEY `idx_user_date` (`user_id`, `use_date`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='插件使用统计表'");
    } catch(Exception $e) {
        error_log("createStatsTable error: " . $e->getMessage());
    }
}
?>
```

### AJAX请求规范

#### 前端请求格式
```javascript
$.ajax({
    type: 'POST',
    url: '../plugin_ajax.php',
    data: {
        plugin: 'plugin_identifier',  // 插件标识符
        action: 'action_name',        // 操作名称
        // 其他参数...
    },
    dataType: 'json',
    success: function(data) {
        if(data.code == 0) {
            // 成功处理
        } else {
            // 错误处理
        }
    }
});
```

#### 后端响应格式
```php
// 成功响应
json_format([
    'code' => 0,
    'msg' => '操作成功',
    'data' => $result
]);

// 错误响应
json_format([
    'code' => '-1',
    'msg' => '错误信息'
]);
```

---

## 🗄️ 数据库操作

### 创建插件数据表

```php
/**
 * 在插件主文件 index.php 中创建表
 */
function createPluginTables() {
    global $DB, $dbconfig;
    
    $tableName = $dbconfig['dbqz'] . '_my_plugin_data';
    
    $sql = "CREATE TABLE IF NOT EXISTS `{$tableName}` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `user_id` int(11) NOT NULL,
        `title` varchar(255) NOT NULL,
        `content` text,
        `status` tinyint(1) DEFAULT 1,
        `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
        `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (`id`),
        KEY `idx_user_id` (`user_id`),
        KEY `idx_status` (`status`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='我的插件数据表'";
    
    try {
        $DB->exec($sql);
        return true;
    } catch(Exception $e) {
        error_log("创建表失败: " . $e->getMessage());
        return false;
    }
}
```

### 标准数据库操作

```php
// 插入数据
$data = [
    'user_id' => $userrow['id'],
    'title' => $title,
    'content' => $content,
    'created_at' => $date
];
$result = $DB->insert($tableName, $data);

// 更新数据
$updateData = [
    'title' => $newTitle,
    'updated_at' => $date
];
$result = $DB->update($tableName, $updateData, ['id' => $id]);

// 查询数据
$item = $DB->getRow("SELECT * FROM `{$tableName}` WHERE id='{$id}' AND user_id='{$userId}'");

// 删除数据
$result = $DB->delete($tableName, "id='{$id}' AND user_id='{$userId}'");

// 分页查询
$page = intval($_POST['page']) ?: 1;
$limit = 10;
$offset = ($page - 1) * $limit;

$count = $DB->getColumn("SELECT COUNT(*) FROM `{$tableName}` WHERE user_id='{$userId}'");
$list = $DB->query("SELECT * FROM `{$tableName}` WHERE user_id='{$userId}' ORDER BY id DESC LIMIT {$offset},{$limit}");
```

---

## 🔗 钩子系统

### 插件主文件 (index.php)

```php
<?php
/**
 * 插件主文件 - 钩子处理
 */
if(!defined('IN_CRONLITE')) exit('Access Denied');

/**
 * 插件初始化
 */
function my_plugin_init() {
    // 创建数据表
    createPluginTables();
    
    // 注册钩子
    add_hook('user_login', 'my_plugin_user_login');
    add_hook('page_visit', 'my_plugin_page_visit');
}

/**
 * 用户登录钩子
 */
function my_plugin_user_login($userInfo) {
    // 记录用户登录
    recordUserLogin($userInfo);
    return true;
}

/**
 * 页面访问钩子
 */
function my_plugin_page_visit($pageInfo) {
    // 记录页面访问
    recordPageVisit($pageInfo);
    return true;
}

/**
 * 插件卸载清理
 */
function my_plugin_uninstall() {
    global $DB, $dbconfig;
    
    // 删除插件数据表
    $tableName = $dbconfig['dbqz'] . '_my_plugin_data';
    $DB->exec("DROP TABLE IF EXISTS `{$tableName}`");
    
    return true;
}

// 插件初始化
my_plugin_init();
?>
```

### 可用钩子事件

| 钩子名称 | 触发时机 | 参数 |
|----------|----------|------|
| `user_login` | 用户登录成功 | 用户信息数组 |
| `user_register` | 用户注册成功 | 用户信息数组 |
| `page_visit` | 页面访问 | 页面信息数组 |
| `order_create` | 订单创建 | 订单信息数组 |
| `payment_success` | 支付成功 | 支付信息数组 |

---

## 📚 示例插件

### 个人工具箱插件

我们提供了一个完整的示例插件"个人工具箱",包含:

#### 功能特性
- 🏠 **工具箱主页** - 工具概览和使用统计
- 🔗 **二维码生成器** - 支持文本、网址、WiFi、联系人等
- 🔐 **密码生成器** - 可自定义长度、字符类型、强度分析
- 📊 **使用统计** - 记录和展示使用数据
- ⚙️ **配置管理** - 灵活的插件配置选项

#### 目录结构
```
plugin/user_toolbox/
├── config.json         # 插件配置
├── index.php           # 主文件
├── ajax.php            # AJAX处理
└── pages/              # 页面文件
    ├── index.php       # 主页面
    ├── qrcode.php      # 二维码生成
    └── password.php    # 密码生成器
```

#### 核心代码片段

**二维码生成功能:**
```php
case 'generate_qrcode':
    $text = daddslashes($_POST['text']);
    $size = intval($_POST['size']) ?: 200;
    
    if(empty($text)) {
        json_format(['code' => '-1', 'msg' => '内容不能为空!']);
    }
    
    // 生成二维码
    $qrcode = generateQRCode($text, $size);
    
    // 记录使用统计
    recordToolUsage('qrcode');
    
    json_format([
        'code' => 0,
        'msg' => '生成成功',
        'data' => $qrcode
    ]);
    break;
```

**密码生成功能:**
```php
case 'generate_password':
    $length = intval($_POST['length']) ?: 12;
    $includeNumbers = $_POST['numbers'] == '1';
    $includeSymbols = $_POST['symbols'] == '1';
    
    $password = generateSecurePassword($length, $includeNumbers, $includeSymbols);
    $strength = analyzePasswordStrength($password);
    
    recordToolUsage('password');
    
    json_format([
        'code' => 0,
        'data' => [
            'password' => $password,
            'strength' => $strength
        ]
    ]);
    break;
```

---

## 💡 最佳实践

### 1. 安全性

#### 输入验证
```php
// 过滤用户输入
$content = daddslashes($_POST['content']);
$id = intval($_POST['id']);

// 验证用户权限
if($islogins != 1) {
    loginsmsg('请登录后再操作!');
}

// 检查数据所有权
$item = $DB->getRow("SELECT * FROM `{$tableName}` WHERE id='{$id}' AND user_id='{$userrow['id']}'");
if(!$item) {
    json_format(['code' => '-1', 'msg' => '数据不存在或无权限!']);
}
```

#### 文件安全
```php
// 页面文件开头
if(!defined('IN_CRONLITE')) exit('Access Denied');

// 文件上传验证
$allowedTypes = ['jpg', 'png', 'gif'];
$fileExt = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
if(!in_array($fileExt, $allowedTypes)) {
    json_format(['code' => '-1', 'msg' => '不支持的文件类型!']);
}
```

### 2. 性能优化

#### 数据库优化
```php
// 使用索引
$sql = "CREATE INDEX idx_user_date ON `{$tableName}` (user_id, created_at)";

// 分页查询
$limit = min(intval($_POST['limit']) ?: 10, 100); // 限制最大查询数量

// 缓存查询结果
$cacheKey = "plugin_data_{$userId}_{$page}";
$result = cache_get($cacheKey);
if(!$result) {
    $result = $DB->query($sql);
    cache_set($cacheKey, $result, 300); // 缓存5分钟
}
```

#### 前端优化
```javascript
// 防抖处理
var searchTimer;
$('#searchInput').on('input', function() {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(function() {
        performSearch();
    }, 500);
});

// 加载状态管理
var isLoading = false;
function loadData() {
    if(isLoading) return;
    isLoading = true;
    
    $.ajax({
        // ...
        complete: function() {
            isLoading = false;
        }
    });
}
```

### 3. 用户体验

#### 操作反馈
```javascript
// 成功提示
layer.msg('操作成功!', {icon: 1, time: 2000});

// 错误提示
layer.msg('操作失败:' + res.msg, {icon: 2, time: 3000});

// 加载提示
var loadIndex = layer.load(2, {shade: [0.3, '#000']});
// 操作完成后
layer.close(loadIndex);

// 确认对话框
layer.confirm('确定要删除这条记录吗?', {icon: 3}, function(index) {
    // 执行删除操作
    layer.close(index);
});
```

#### 响应式设计
```css
/* 移动端适配 */
@media screen and (max-width: 768px) {
    .layui-col-md4 {
        margin-top: 15px;
    }
    
    .plugin-container {
        padding: 10px;
    }
    
    .layui-card {
        margin-bottom: 10px;
    }
}
```

### 4. 代码规范

#### 命名规范
```php
// 函数命名:小写+下划线
function generate_qr_code($text, $size) {}

// 变量命名:小写+下划线
$user_id = $userrow['id'];
$table_name = $dbconfig['dbqz'] . '_plugin_data';

// 常量命名:大写+下划线
define('PLUGIN_VERSION', '1.0.0');
```

#### 注释规范
```php
/**
 * 生成二维码
 * @param string $text 二维码内容
 * @param int $size 二维码尺寸
 * @return string 二维码图片base64编码
 */
function generateQRCode($text, $size = 200) {
    // 实现代码...
}
```

---

## 🔧 故障排除

### 常见问题

#### 1. 插件页面不显示

**可能原因:**
- 插件未启用
- `config.json` 配置错误
- 页面文件不存在
- 权限问题

**解决方法:**
```bash
# 检查插件状态
SELECT * FROM fenfa_plugins WHERE identifier='your_plugin';

# 检查文件权限
ls -la plugin/your_plugin/

# 检查配置文件
cat plugin/your_plugin/config.json | python -m json.tool
```

#### 2. AJAX请求失败

**可能原因:**
- `ajax.php` 文件不存在
- 请求参数错误
- 权限验证失败
- 数据库连接问题

**调试方法:**
```javascript
// 在浏览器控制台查看请求详情
$.ajax({
    // ...
    error: function(xhr, status, error) {
        console.log('Status:', status);
        console.log('Error:', error);
        console.log('Response:', xhr.responseText);
    }
});
```

#### 3. 数据库操作错误

**可能原因:**
- 表名前缀错误
- SQL语法错误
- 字段类型不匹配
- 权限不足

**调试方法:**
```php
// 开启错误日志
try {
    $result = $DB->insert($tableName, $data);
} catch(Exception $e) {
    error_log("Database error: " . $e->getMessage());
    json_format(['code' => '-1', 'msg' => '数据库操作失败']);
}
```

#### 4. 导航不显示

**检查清单:**
- [ ] 插件已启用
- [ ] `user_pages` 配置正确
- [ ] 页面文件存在
- [ ] 用户已登录
- [ ] 浏览器缓存已清除

### 调试工具

#### 1. 插件测试页面
访问 `admin/test_plugin_system.php` 进行系统诊断

#### 2. 数据库测试脚本
```php
// plugin/your_plugin/test_db.php
<?php
include("../../includes/common.php");

echo "<h3>数据库连接测试</h3>";
try {
    $tableName = $dbconfig['dbqz'] . '_test';
    $DB->exec("CREATE TABLE IF NOT EXISTS `{$tableName}` (id int PRIMARY KEY)");
    echo "✅ 数据库连接正常<br>";
    
    $DB->exec("DROP TABLE `{$tableName}`");
    echo "✅ 表操作正常<br>";
} catch(Exception $e) {
    echo "❌ 数据库错误: " . $e->getMessage() . "<br>";
}
?>
```

#### 3. 日志查看
```bash
# 查看错误日志
tail -f /var/log/php_errors.log

# 查看访问日志
tail -f /var/log/nginx/access.log
```

---

## 📖 总结

通过本指南,您已经掌握了:

- ✅ **插件系统架构** - 了解核心文件和工作原理
- ✅ **导航系统设计** - 灵活的一级/二级导航结构
- ✅ **页面开发技巧** - 响应式设计和用户体验优化
- ✅ **AJAX处理规范** - 标准化的请求响应机制
- ✅ **数据库操作** - 安全高效的数据持久化
- ✅ **钩子系统集成** - 与系统事件深度集成
- ✅ **安全最佳实践** - 输入验证和权限控制
- ✅ **性能优化技巧** - 数据库和前端优化方案

现在您可以开始创建功能丰富、用户友好的插件了!

### 快速开始检查清单

- [ ] 创建插件目录和基本文件
- [ ] 编写 `config.json` 配置文件
- [ ] 创建页面文件和AJAX处理
- [ ] 在管理后台扫描并启用插件
- [ ] 在用户中心测试功能
- [ ] 优化用户体验和性能

### 获取帮助

如果在开发过程中遇到问题:

1. 📖 **查阅文档** - 仔细阅读本指南相关章节
2. 🔍 **检查示例** - 参考"个人工具箱"插件代码
3. 🧪 **使用调试工具** - 运行测试脚本诊断问题
4. 📝 **查看日志** - 检查错误日志获取详细信息

祝您开发愉快!🎉

相关文章

插件开发教程-page页面类型 2025-09-07 11:03

# 🚀 插件开发完整指南 > 本指南提供了完整的插件开发、页面集成和导航结构的详细说明,帮助开发者快速创建功能丰富的插件。 ## 📋 目录 - [系统概述](#系统概述) - [快速开始](#快速开始) - [插件结构](#插件结构) - [导航系统](#导航系统) - [页面开发](#页

目录
Copyright © 2024 . Powered by 幻影网络科技.
鲁ICP备2022028556号-3