diff --git a/.gitignore b/.gitignore index 706fd07..9fe7eec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea .vscode +*.so \ No newline at end of file diff --git a/examples/plugin/admin/plugins/plugins.json b/examples/plugin/admin/plugins/plugins.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/examples/plugin/admin/plugins/plugins.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/examples/plugin/admin/web_admin.go b/examples/plugin/admin/web_admin.go index 28bb926..c0713cf 100644 --- a/examples/plugin/admin/web_admin.go +++ b/examples/plugin/admin/web_admin.go @@ -405,6 +405,19 @@ func APIPluginsHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") plugins := pm.GetPluginInfos() + fmt.Printf("API请求: 找到 %d 个插件\n", len(plugins)) + + // 打印每个插件的信息 + for i, p := range plugins { + fmt.Printf("插件 %d: 名称=%s, 版本=%s, 作者=%s, 类型=%s, 启用=%v\n", + i+1, p.Name, p.Version, p.Author, p.Type, p.Enabled) + } + + // 如果没有插件,返回一个空数组而不是 null + if plugins == nil { + plugins = []plugin.PluginInfo{} + } + if err := json.NewEncoder(w).Encode(plugins); err != nil { http.Error(w, fmt.Sprintf("编码JSON失败: %v", err), http.StatusInternalServerError) } @@ -427,7 +440,7 @@ func getPluginInfo(name string) (*plugin.PluginInfo, map[string]interface{}) { // 插件目录 var pluginsDir = "./plugins" -func main3() { +func main() { // 创建插件管理器 pm = plugin.NewPluginManager(pluginsDir) diff --git a/examples/plugin/client_generator.go b/examples/plugin/client_generator.go index 6c3153b..9f78aa8 100644 --- a/examples/plugin/client_generator.go +++ b/examples/plugin/client_generator.go @@ -134,16 +134,6 @@ type PluginInfo struct { Config map[string]interface{} ` + "`json:\"config,omitempty\"`" + ` } -// PluginType 插件类型 -type PluginType string - -const ( - PluginTypeGeneral PluginType = "General" - PluginTypeStorage PluginType = "Storage" - PluginTypeUtils PluginType = "Utils" - PluginTypeNetwork PluginType = "Network" -) - // OperationInfo 操作信息 type OperationInfo struct { Name string ` + "`json:\"name\"`" + ` diff --git a/examples/plugin/manager/plugin_manager.go b/examples/plugin/manager/plugin_manager.go index e782638..783485a 100644 --- a/examples/plugin/manager/plugin_manager.go +++ b/examples/plugin/manager/plugin_manager.go @@ -236,7 +236,7 @@ func (p *LogPlugin) Log(message string) { func main() { // 创建插件管理器 - pluginsDir := "./plugins" + pluginsDir := "../admin/plugins" pm := plugin.NewPluginManager(pluginsDir) // 检查当前系统是否支持动态加载插件 diff --git a/examples/plugin/plugin.go b/examples/plugin/plugin.go index 741ccf9..e5b4b75 100644 --- a/examples/plugin/plugin.go +++ b/examples/plugin/plugin.go @@ -3,7 +3,6 @@ package plugin import ( "context" "encoding/json" - "errors" "fmt" "io/fs" "os" @@ -978,36 +977,445 @@ func (pm *PluginManager) loadPlugin(path string) error { return fmt.Errorf("查找Plugin变量失败: %v", err) } - // 类型断言 - plugin, ok := symPlugin.(Plugin) - if !ok { - return errors.New("插件类型错误") + // 使用反射检查插件对象 + pluginValue := reflect.ValueOf(symPlugin) + fmt.Printf("加载插件: %s, 类型: %s\n", path, pluginValue.Type()) + + // 查找基本字段或方法 + var pluginName, pluginVersion, pluginAuthor, pluginDesc string + var pluginType PluginType = PluginTypeGeneral + var enabled = true + + // 直接检查方法 + // 尝试通过方法获取信息 + nameFound := false + if nameMethod := pluginValue.MethodByName("Name"); nameMethod.IsValid() { + results := nameMethod.Call(nil) + if len(results) > 0 && results[0].Kind() == reflect.String { + pluginName = results[0].String() + nameFound = true + } + } + + if versionMethod := pluginValue.MethodByName("Version"); versionMethod.IsValid() { + results := versionMethod.Call(nil) + if len(results) > 0 && results[0].Kind() == reflect.String { + pluginVersion = results[0].String() + } + } + + if descMethod := pluginValue.MethodByName("Description"); descMethod.IsValid() { + results := descMethod.Call(nil) + if len(results) > 0 && results[0].Kind() == reflect.String { + pluginDesc = results[0].String() + } + } + + if authorMethod := pluginValue.MethodByName("Author"); authorMethod.IsValid() { + results := authorMethod.Call(nil) + if len(results) > 0 && results[0].Kind() == reflect.String { + pluginAuthor = results[0].String() + } + } + + if typeMethod := pluginValue.MethodByName("Type"); typeMethod.IsValid() { + results := typeMethod.Call(nil) + if len(results) > 0 { + // 尝试匹配插件类型 + typeStr := fmt.Sprint(results[0].Interface()) + switch typeStr { + case "storage": + pluginType = PluginTypeStorage + case "security": + pluginType = PluginTypeSecurity + case "network": + pluginType = PluginTypeNetwork + case "utils": + pluginType = PluginTypeUtils + case "hardware": + pluginType = PluginTypeHardware + case "ui": + pluginType = PluginTypeUI + } + } + } + + // 直接检查字段(仅在方法不可用时) + if !nameFound && pluginValue.Kind() == reflect.Ptr && !pluginValue.IsNil() { + elemValue := pluginValue.Elem() + + // 检查elemValue是否为结构体 + if elemValue.Kind() == reflect.Struct { + // 检查是否有name字段 + if nameField := elemValue.FieldByName("name"); nameField.IsValid() && nameField.Kind() == reflect.String { + pluginName = nameField.String() + } + + // 检查是否有version字段 + if versionField := elemValue.FieldByName("version"); versionField.IsValid() && versionField.Kind() == reflect.String { + pluginVersion = versionField.String() + } + + // 检查是否有description字段 + if descField := elemValue.FieldByName("description"); descField.IsValid() && descField.Kind() == reflect.String { + pluginDesc = descField.String() + } + + // 检查是否有author字段 + if authorField := elemValue.FieldByName("author"); authorField.IsValid() && authorField.Kind() == reflect.String { + pluginAuthor = authorField.String() + } + + // 检查是否有pluginType字段 + if typeField := elemValue.FieldByName("pluginType"); typeField.IsValid() { + // 转换为字符串并尝试匹配已知类型 + typeStr := fmt.Sprint(typeField.Interface()) + switch typeStr { + case "storage": + pluginType = PluginTypeStorage + case "security": + pluginType = PluginTypeSecurity + case "network": + pluginType = PluginTypeNetwork + case "utils": + pluginType = PluginTypeUtils + case "hardware": + pluginType = PluginTypeHardware + case "ui": + pluginType = PluginTypeUI + } + } + + // 检查是否有enabled字段 + if enabledField := elemValue.FieldByName("enabled"); enabledField.IsValid() && enabledField.Kind() == reflect.Bool { + enabled = enabledField.Bool() + } + } + } + + // 如果名称仍为空,则使用文件名 + if pluginName == "" { + // 从路径中提取文件名并去掉扩展名 + fileName := filepath.Base(path) + pluginName = strings.TrimSuffix(fileName, filepath.Ext(fileName)) + } + + fmt.Printf("创建适配器插件: 名称=%s, 版本=%s, 作者=%s, 类型=%s\n", + pluginName, pluginVersion, pluginAuthor, pluginType) + + // 创建一个自定义插件结构体 + customPlugin := &DynamicPlugin{ + original: symPlugin, + name: pluginName, + version: pluginVersion, + description: pluginDesc, + author: pluginAuthor, + pluginType: pluginType, + enabled: enabled, } // 检查插件名称是否已存在 pm.mu.Lock() defer pm.mu.Unlock() - if _, exists := pm.plugins[plugin.Name()]; exists { - return fmt.Errorf("插件 %s 已存在", plugin.Name()) + if _, exists := pm.plugins[customPlugin.Name()]; exists { + return fmt.Errorf("插件 %s 已存在", customPlugin.Name()) } // 设置插件启用状态 - if config, exists := pm.configs[plugin.Name()]; exists { + if config, exists := pm.configs[customPlugin.Name()]; exists { if enabled, ok := config["enabled"].(bool); ok { - plugin.SetEnabled(enabled) - } else { - plugin.SetEnabled(true) // 默认启用 + customPlugin.enabled = enabled } - } else { - plugin.SetEnabled(true) // 默认启用 } // 注册插件 - pm.registerPlugin(plugin) + pm.registerPlugin(customPlugin) + fmt.Printf("已成功注册插件: %s\n", customPlugin.Name()) return nil } +// DynamicPlugin 完全动态的插件实现 +type DynamicPlugin struct { + original interface{} + name string + version string + description string + author string + pluginType PluginType + enabled bool +} + +// Name 返回插件名称 +func (p *DynamicPlugin) Name() string { + return p.name +} + +// Version 返回插件版本 +func (p *DynamicPlugin) Version() string { + return p.version +} + +// Description 返回插件描述 +func (p *DynamicPlugin) Description() string { + return p.description +} + +// Author 返回插件作者 +func (p *DynamicPlugin) Author() string { + return p.author +} + +// Type 返回插件类型 +func (p *DynamicPlugin) Type() PluginType { + return p.pluginType +} + +// IsEnabled 返回插件是否启用 +func (p *DynamicPlugin) IsEnabled() bool { + return p.enabled +} + +// SetEnabled 设置插件启用状态 +func (p *DynamicPlugin) SetEnabled(enabled bool) { + p.enabled = enabled + + // 尝试调用原始插件的SetEnabled方法 + method := reflect.ValueOf(p.original).MethodByName("SetEnabled") + if method.IsValid() { + method.Call([]reflect.Value{reflect.ValueOf(enabled)}) + } +} + +// Init 初始化插件 +func (p *DynamicPlugin) Init(ctx context.Context, config map[string]interface{}) error { + method := reflect.ValueOf(p.original).MethodByName("Init") + if !method.IsValid() { + return nil // 如果方法不存在,就不做任何事情 + } + + // 确定方法参数数量和类型 + methodType := method.Type() + numParams := methodType.NumIn() + + // 准备参数 + var args []reflect.Value + + // 对于不同参数数量的处理 + switch numParams { + case 0: + // 无参数 + case 1: + // 只有一个参数,可能是配置 + args = append(args, reflect.ValueOf(config)) + case 2: + // 两个参数,可能是上下文和配置 + args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(config)) + default: + // 不支持更多参数 + return fmt.Errorf("不支持的Init方法参数数量: %d", numParams) + } + + // 调用方法 + results := method.Call(args) + + // 处理返回值 + if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !results[0].IsNil() { + return results[0].Interface().(error) + } + } + + return nil +} + +// Start 启动插件 +func (p *DynamicPlugin) Start(ctx context.Context) error { + method := reflect.ValueOf(p.original).MethodByName("Start") + if !method.IsValid() { + return nil // 如果方法不存在,就不做任何事情 + } + + // 确定方法参数数量和类型 + methodType := method.Type() + numParams := methodType.NumIn() + + // 准备参数 + var args []reflect.Value + + // 对于不同参数数量的处理 + switch numParams { + case 0: + // 无参数 + case 1: + // 一个参数,可能是上下文 + args = append(args, reflect.ValueOf(ctx)) + default: + // 不支持更多参数 + return fmt.Errorf("不支持的Start方法参数数量: %d", numParams) + } + + // 调用方法 + results := method.Call(args) + + // 处理返回值 + if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !results[0].IsNil() { + return results[0].Interface().(error) + } + } + + return nil +} + +// Stop 停止插件 +func (p *DynamicPlugin) Stop(ctx context.Context) error { + method := reflect.ValueOf(p.original).MethodByName("Stop") + if !method.IsValid() { + return nil // 如果方法不存在,就不做任何事情 + } + + // 确定方法参数数量和类型 + methodType := method.Type() + numParams := methodType.NumIn() + + // 准备参数 + var args []reflect.Value + + // 对于不同参数数量的处理 + switch numParams { + case 0: + // 无参数 + case 1: + // 一个参数,可能是上下文 + args = append(args, reflect.ValueOf(ctx)) + default: + // 不支持更多参数 + return fmt.Errorf("不支持的Stop方法参数数量: %d", numParams) + } + + // 调用方法 + results := method.Call(args) + + // 处理返回值 + if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !results[0].IsNil() { + return results[0].Interface().(error) + } + } + + return nil +} + +// Execute 执行插件功能 +func (p *DynamicPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) { + method := reflect.ValueOf(p.original).MethodByName("Execute") + if !method.IsValid() { + return nil, fmt.Errorf("插件不支持Execute方法") + } + + // 确定方法参数数量和类型 + methodType := method.Type() + numParams := methodType.NumIn() + + // 准备参数 + var args []reflect.Value + + // 对于不同参数数量的处理 + switch numParams { + case 2: + // 两个参数,可能是action和params + args = append(args, reflect.ValueOf(action), reflect.ValueOf(params)) + case 3: + // 三个参数,可能是ctx、action和params + args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(action), reflect.ValueOf(params)) + default: + // 不支持其他参数数量 + return nil, fmt.Errorf("不支持的Execute方法参数数量: %d", numParams) + } + + // 调用方法 + results := method.Call(args) + + // 处理返回值 + var result interface{} + var err error + + switch len(results) { + case 1: + // 只有一个返回值,检查是否为错误 + if results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !results[0].IsNil() { + err = results[0].Interface().(error) + } + } else { + result = results[0].Interface() + } + case 2: + // 两个返回值,第一个是结果,第二个是错误 + if !results[0].IsNil() { + result = results[0].Interface() + } + + if results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !results[1].IsNil() { + err = results[1].Interface().(error) + } + } + } + + return result, err +} + +// GetOperationInfo 获取操作的参数信息 +func (p *DynamicPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) { + method := reflect.ValueOf(p.original).MethodByName("GetOperationInfo") + if !method.IsValid() { + return map[string]interface{}{}, nil + } + + results := method.Call([]reflect.Value{reflect.ValueOf(operation)}) + + var result map[string]interface{} + var err error + + if len(results) > 0 && !results[0].IsNil() { + if m, ok := results[0].Interface().(map[string]interface{}); ok { + result = m + } else { + result = map[string]interface{}{} + } + } else { + result = map[string]interface{}{} + } + + if len(results) > 1 && results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { + if !results[1].IsNil() { + err = results[1].Interface().(error) + } + } + + return result, err +} + +// GetAllOperations 获取所有操作及其参数信息 +func (p *DynamicPlugin) GetAllOperations() map[string]map[string]interface{} { + method := reflect.ValueOf(p.original).MethodByName("GetAllOperations") + if !method.IsValid() { + return map[string]map[string]interface{}{} + } + + results := method.Call(nil) + + if len(results) > 0 && !results[0].IsNil() { + if m, ok := results[0].Interface().(map[string]map[string]interface{}); ok { + return m + } + } + + return map[string]map[string]interface{}{} +} + // registerPlugin 注册插件到插件管理器 func (pm *PluginManager) registerPlugin(plugin Plugin) { pluginType := plugin.Type() @@ -1460,4 +1868,4 @@ func (pm *PluginManager) GetAllPluginsOperations() map[string]map[string]map[str } return result -} +} \ No newline at end of file diff --git a/examples/plugin/plugins/build.sh b/examples/plugin/plugins/build.sh old mode 100644 new mode 100755 index 2c1e4b1..bd375ab --- a/examples/plugin/plugins/build.sh +++ b/examples/plugin/plugins/build.sh @@ -3,14 +3,14 @@ # 构建脚本,用于编译所有插件 # 确保输出目录存在 -mkdir -p dist +mkdir -p ../../admin/plugins echo "===== 开始编译插件 =====" # 编译带有明确类型的日志插件 echo "编译日志插件 (明确类型)..." cd logger -go build -buildmode=plugin -o ../dist/logger.so +go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/logger.so if [ $? -eq 0 ]; then echo "日志插件编译成功!" else @@ -22,7 +22,7 @@ cd .. # 编译使用默认类型的日志插件 echo "编译默认日志插件 (默认类型)..." cd defaultlogger -go build -buildmode=plugin -o ../dist/defaultlogger.so +go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/defaultlogger.so if [ $? -eq 0 ]; then echo "默认日志插件编译成功!" else @@ -34,7 +34,7 @@ cd .. # 编译统计插件 echo "编译统计插件..." cd stats -go build -buildmode=plugin -o ../dist/stats.so +go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/stats.so if [ $? -eq 0 ]; then echo "统计插件编译成功!" else @@ -46,7 +46,7 @@ cd .. # 编译存储插件 echo "编译存储插件..." cd storage -go build -buildmode=plugin -o ../dist/storage.so +go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/storage.so if [ $? -eq 0 ]; then echo "存储插件编译成功!" else @@ -56,8 +56,6 @@ fi cd .. echo "===== 所有插件编译完成 =====" -echo "插件文件保存在 dist 目录中:" -ls -la dist/ # 对于Windows系统,添加.exe后缀 # go build -buildmode=plugin -o ../dist/plugin_name.dll \ No newline at end of file diff --git a/examples/plugin/plugins/defaultlogger/default_logger_plugin.go b/examples/plugin/plugins/defaultlogger/default_logger_plugin.go index fad6541..13b310b 100644 --- a/examples/plugin/plugins/defaultlogger/default_logger_plugin.go +++ b/examples/plugin/plugins/defaultlogger/default_logger_plugin.go @@ -14,22 +14,73 @@ import ( // DefaultLoggerPlugin 默认日志插件 // 提供文件日志和控制台日志功能,使用默认插件类型 type DefaultLoggerPlugin struct { - *plugin.BasePlugin // 嵌入基本插件结构 - logFile *os.File // 日志文件 - logger *log.Logger // 日志记录器 - config map[string]interface{} // 配置 + plugin.Plugin // 嵌入接口,确保类型检查 + name string // 插件名称 + version string // 插件版本 + description string // 插件描述 + author string // 插件作者 + pluginType plugin.PluginType // 插件类型 + enabled bool // 是否启用 + logFile *os.File // 日志文件 + logger *log.Logger // 日志记录器 + config map[string]interface{} // 配置 } // Plugin 导出的插件变量 // 注意:变量名必须是Plugin,大小写敏感 // 这个插件使用默认的通用插件类型(PluginTypeGeneral) var Plugin = &DefaultLoggerPlugin{ - BasePlugin: plugin.NewBasePluginWithDefaultType( - "DefaultLoggerPlugin", - "1.0.0", - "使用默认通用类型的日志记录插件", - "开发者", - ), // 将自动使用 PluginTypeGeneral 类型 + name: "DefaultLoggerPlugin", + version: "1.0.0", + description: "使用默认通用类型的日志记录插件", + author: "开发者", + pluginType: plugin.PluginTypeGeneral, // 使用通用插件类型 + enabled: true, +} + +// Name 返回插件名称 +func (p *DefaultLoggerPlugin) Name() string { + return p.name +} + +// Version 返回插件版本 +func (p *DefaultLoggerPlugin) Version() string { + return p.version +} + +// Description 返回插件描述 +func (p *DefaultLoggerPlugin) Description() string { + return p.description +} + +// Author 返回插件作者 +func (p *DefaultLoggerPlugin) Author() string { + return p.author +} + +// Type 返回插件类型 +func (p *DefaultLoggerPlugin) Type() plugin.PluginType { + return p.pluginType +} + +// IsEnabled 返回插件是否启用 +func (p *DefaultLoggerPlugin) IsEnabled() bool { + return p.enabled +} + +// SetEnabled 设置插件启用状态 +func (p *DefaultLoggerPlugin) SetEnabled(enabled bool) { + p.enabled = enabled +} + +// GetOperationInfo 获取操作的参数信息 +func (p *DefaultLoggerPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) { + return map[string]interface{}{}, nil +} + +// GetAllOperations 获取所有操作及其参数信息 +func (p *DefaultLoggerPlugin) GetAllOperations() map[string]map[string]interface{} { + return map[string]map[string]interface{}{} } // Init 初始化插件 diff --git a/examples/plugin/plugins/logger/logger_plugin.go b/examples/plugin/plugins/logger/logger_plugin.go index 9092acf..bc30991 100644 --- a/examples/plugin/plugins/logger/logger_plugin.go +++ b/examples/plugin/plugins/logger/logger_plugin.go @@ -14,36 +14,73 @@ import ( // LoggerPlugin 日志插件 // 提供文件日志和控制台日志功能 type LoggerPlugin struct { - *plugin.BasePlugin // 嵌入基本插件结构 - logFile *os.File // 日志文件 - logger *log.Logger // 日志记录器 - config map[string]interface{} // 配置 + plugin.Plugin // 嵌入接口,确保类型检查 + name string // 插件名称 + version string // 插件版本 + description string // 插件描述 + author string // 插件作者 + pluginType plugin.PluginType // 插件类型 + enabled bool // 是否启用 + logFile *os.File // 日志文件 + logger *log.Logger // 日志记录器 + config map[string]interface{} // 配置 } // Plugin 导出的插件变量 // 注意:变量名必须是Plugin,大小写敏感 -// 使用方式1: 明确指定插件类型 var Plugin = &LoggerPlugin{ - BasePlugin: plugin.NewBasePlugin( - "LoggerPlugin", - "1.0.0", - "简单的日志记录插件", - "开发者", - plugin.PluginTypeUtils, // 明确指定为工具类插件 - ), + name: "LoggerPlugin", + version: "1.0.0", + description: "简单的日志记录插件", + author: "开发者", + pluginType: plugin.PluginTypeUtils, // 明确指定为工具类插件 + enabled: true, } -// 使用方式2: 使用默认插件类型(通用插件) -// 如果您不关心插件类型或想使用默认的通用插件类型,可以使用以下方式: -// -// var Plugin = &LoggerPlugin{ -// BasePlugin: plugin.NewBasePluginWithDefaultType( -// "LoggerPlugin", -// "1.0.0", -// "简单的日志记录插件", -// "开发者", -// ), // 将自动使用 PluginTypeGeneral 类型 -// } +// Name 返回插件名称 +func (p *LoggerPlugin) Name() string { + return p.name +} + +// Version 返回插件版本 +func (p *LoggerPlugin) Version() string { + return p.version +} + +// Description 返回插件描述 +func (p *LoggerPlugin) Description() string { + return p.description +} + +// Author 返回插件作者 +func (p *LoggerPlugin) Author() string { + return p.author +} + +// Type 返回插件类型 +func (p *LoggerPlugin) Type() plugin.PluginType { + return p.pluginType +} + +// IsEnabled 返回插件是否启用 +func (p *LoggerPlugin) IsEnabled() bool { + return p.enabled +} + +// SetEnabled 设置插件启用状态 +func (p *LoggerPlugin) SetEnabled(enabled bool) { + p.enabled = enabled +} + +// GetOperationInfo 获取操作的参数信息 +func (p *LoggerPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) { + return map[string]interface{}{}, nil +} + +// GetAllOperations 获取所有操作及其参数信息 +func (p *LoggerPlugin) GetAllOperations() map[string]map[string]interface{} { + return map[string]map[string]interface{}{} +} // Init 初始化插件 func (p *LoggerPlugin) Init(ctx context.Context, config map[string]interface{}) error { diff --git a/examples/plugin/plugins/stats/stats_plugin.go b/examples/plugin/plugins/stats/stats_plugin.go index 754e1e6..2336f46 100644 --- a/examples/plugin/plugins/stats/stats_plugin.go +++ b/examples/plugin/plugins/stats/stats_plugin.go @@ -12,13 +12,19 @@ import ( // StatsPlugin 统计插件 // 用于收集和记录系统运行时统计数据 type StatsPlugin struct { - *plugin.BasePluginImpl // 改为使用BasePluginImpl - stats map[string]int64 - startTime time.Time - mu sync.RWMutex - tickerStop chan bool - ticker *time.Ticker - config map[string]interface{} + plugin.Plugin // 嵌入接口,确保类型检查 + name string // 插件名称 + version string // 插件版本 + description string // 插件描述 + author string // 插件作者 + pluginType plugin.PluginType // 插件类型 + enabled bool // 是否启用 + stats map[string]int64 + startTime time.Time + mu sync.RWMutex + tickerStop chan bool + ticker *time.Ticker + config map[string]interface{} } // StatsParams 统计请求参数结构体 @@ -33,29 +39,60 @@ type StatsParams struct { // Plugin 导出的插件变量 var Plugin = &StatsPlugin{ - // 使用默认构造函数,不指定插件类型,将默认为通用插件 - BasePluginImpl: plugin.NewPluginWithDefaultType( - "StatsPlugin", - "1.0.0", - "系统运行时统计插件", - "开发者", - ), - stats: make(map[string]int64), - tickerStop: make(chan bool), + name: "StatsPlugin", + version: "1.0.0", + description: "系统运行时统计插件", + author: "开发者", + pluginType: plugin.PluginTypeUtils, // 指定为工具类插件 + enabled: true, + stats: make(map[string]int64), + tickerStop: make(chan bool), } -// 为展示如何指定类型,我们也可以显式设置插件类型 -// var Plugin = &StatsPlugin{ -// BasePlugin: plugin.NewBasePlugin( -// "StatsPlugin", -// "1.0.0", -// "系统运行时统计插件", -// "开发者", -// plugin.PluginTypeUtils, // 明确指定为工具类插件 -// ), -// stats: make(map[string]int64), -// tickerStop: make(chan bool), -// } +// Name 返回插件名称 +func (p *StatsPlugin) Name() string { + return p.name +} + +// Version 返回插件版本 +func (p *StatsPlugin) Version() string { + return p.version +} + +// Description 返回插件描述 +func (p *StatsPlugin) Description() string { + return p.description +} + +// Author 返回插件作者 +func (p *StatsPlugin) Author() string { + return p.author +} + +// Type 返回插件类型 +func (p *StatsPlugin) Type() plugin.PluginType { + return p.pluginType +} + +// IsEnabled 返回插件是否启用 +func (p *StatsPlugin) IsEnabled() bool { + return p.enabled +} + +// SetEnabled 设置插件启用状态 +func (p *StatsPlugin) SetEnabled(enabled bool) { + p.enabled = enabled +} + +// GetOperationInfo 获取操作的参数信息 +func (p *StatsPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) { + return map[string]interface{}{}, nil +} + +// GetAllOperations 获取所有操作及其参数信息 +func (p *StatsPlugin) GetAllOperations() map[string]map[string]interface{} { + return map[string]map[string]interface{}{} +} // Init 初始化插件 func (p *StatsPlugin) Init(ctx context.Context, config map[string]interface{}) error { @@ -242,7 +279,15 @@ func (p *StatsPlugin) logStats() { // GetAvailableOperations 获取可用操作列表 // 这是一个帮助方法,列出所有可通过Execute调用的操作 func (p *StatsPlugin) GetAvailableOperations() []string { - return p.GetAvailableActions() + // 返回硬编码的操作列表,而不是调用不存在的方法 + return []string{ + "incrementstat", + "getstat", + "recordrequest", + "resetstats", + "generatestatsreport", + "getallstats", + } } // main 函数是必须的,但不会被调用 diff --git a/examples/plugin/plugins/storage/storage_plugin.go b/examples/plugin/plugins/storage/storage_plugin.go index f4f4771..162cc87 100644 --- a/examples/plugin/plugins/storage/storage_plugin.go +++ b/examples/plugin/plugins/storage/storage_plugin.go @@ -14,22 +14,72 @@ import ( // StoragePlugin 存储插件 // 提供简单的文件存储功能 type StoragePlugin struct { - *plugin.BasePlugin // 嵌入基本插件结构 - storageDir string // 存储目录 - config map[string]interface{} // 配置 - mu sync.RWMutex // 读写锁 + plugin.Plugin // 嵌入接口,确保类型检查 + name string // 插件名称 + version string // 插件版本 + description string // 插件描述 + author string // 插件作者 + pluginType plugin.PluginType // 插件类型 + enabled bool // 是否启用 + storageDir string // 存储目录 + config map[string]interface{} // 配置 + mu sync.RWMutex // 读写锁 } // Plugin 导出的插件变量 // 注意:变量名必须是Plugin,大小写敏感 var Plugin = &StoragePlugin{ - BasePlugin: plugin.NewBasePlugin( - "StoragePlugin", - "1.0.0", - "简单的文件存储插件", - "开发者", - plugin.PluginTypeStorage, // 设置插件类型为存储插件 - ), + name: "StoragePlugin", + version: "1.0.0", + description: "简单的文件存储插件", + author: "开发者", + pluginType: plugin.PluginTypeStorage, // 设置插件类型为存储插件 + enabled: true, +} + +// Name 返回插件名称 +func (p *StoragePlugin) Name() string { + return p.name +} + +// Version 返回插件版本 +func (p *StoragePlugin) Version() string { + return p.version +} + +// Description 返回插件描述 +func (p *StoragePlugin) Description() string { + return p.description +} + +// Author 返回插件作者 +func (p *StoragePlugin) Author() string { + return p.author +} + +// Type 返回插件类型 +func (p *StoragePlugin) Type() plugin.PluginType { + return p.pluginType +} + +// IsEnabled 返回插件是否启用 +func (p *StoragePlugin) IsEnabled() bool { + return p.enabled +} + +// SetEnabled 设置插件启用状态 +func (p *StoragePlugin) SetEnabled(enabled bool) { + p.enabled = enabled +} + +// GetOperationInfo 获取操作的参数信息 +func (p *StoragePlugin) GetOperationInfo(operation string) (map[string]interface{}, error) { + return map[string]interface{}{}, nil +} + +// GetAllOperations 获取所有操作及其参数信息 +func (p *StoragePlugin) GetAllOperations() map[string]map[string]interface{} { + return map[string]map[string]interface{}{} } // Init 初始化插件