- Wails v2.16.0 + React 19 + TypeScript + Vite 7 - 插件系统(build tag 控制编译,plugin.json 运行时配置) - 支付插件(授权、账号、订单、退款、账单) - 高并发基础设施(任务池、批量处理器、限流器、环形缓冲、管道) - Windows 系统托盘(Win32 API) - CodeGraph 索引 + .memory 记忆包 - 默认图标 assets/icon.png
151 lines
3.1 KiB
Go
151 lines
3.1 KiB
Go
// Package plugins 插件系统核心接口与注册中心
|
|
package plugins
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
// Plugin 插件接口,所有插件必须实现
|
|
type Plugin interface {
|
|
Name() string
|
|
Init(ctx context.Context) error
|
|
Register(app *App) error
|
|
Shutdown() error
|
|
Enabled() bool
|
|
}
|
|
|
|
// App 插件可见的应用上下文
|
|
type App struct {
|
|
ctx context.Context
|
|
config map[string]interface{}
|
|
}
|
|
|
|
// NewApp 创建应用上下文
|
|
func NewApp(ctx context.Context, config map[string]interface{}) *App {
|
|
return &App{ctx: ctx, config: config}
|
|
}
|
|
|
|
// Registry 插件注册中心(线程安全)
|
|
type Registry struct {
|
|
mu sync.Mutex
|
|
plugins map[string]Plugin
|
|
}
|
|
|
|
var globalRegistry *Registry
|
|
var once sync.Once
|
|
|
|
func getGlobalRegistry() *Registry {
|
|
once.Do(func() {
|
|
globalRegistry = &Registry{plugins: make(map[string]Plugin)}
|
|
})
|
|
return globalRegistry
|
|
}
|
|
|
|
// Register 全局注册插件(由各插件 build.go 的 init() 调用)
|
|
func Register(p Plugin) {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.plugins[p.Name()] = p
|
|
log.Printf("[plugins] registered: %s (enabled=%v)", p.Name(), p.Enabled())
|
|
}
|
|
|
|
// Get 获取已注册插件
|
|
func Get(name string) Plugin {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
return r.plugins[name]
|
|
}
|
|
|
|
// List 列出所有已注册插件名
|
|
func List() []string {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
names := make([]string, 0, len(r.plugins))
|
|
for name := range r.plugins {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|
|
|
|
// Count 返回已注册插件数
|
|
func Count() int {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
return len(r.plugins)
|
|
}
|
|
|
|
// Start 启动所有已启用的插件
|
|
func Start(ctx context.Context) error {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
for name, p := range r.plugins {
|
|
if !p.Enabled() {
|
|
log.Printf("[plugins] skip disabled: %s", name)
|
|
continue
|
|
}
|
|
if err := p.Init(ctx); err != nil {
|
|
log.Printf("[plugins] init %s failed: %v", name, err)
|
|
continue
|
|
}
|
|
if err := p.Register(NewApp(ctx, nil)); err != nil {
|
|
log.Printf("[plugins] register %s failed: %v", name, err)
|
|
continue
|
|
}
|
|
log.Printf("[plugins] started: %s", name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Shutdown 关闭所有插件
|
|
func Shutdown() error {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
for name, p := range r.plugins {
|
|
if err := p.Shutdown(); err != nil {
|
|
log.Printf("[plugins] shutdown %s error: %v", name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// EnabledPlugins 返回所有已启用插件列表
|
|
func EnabledPlugins() []Plugin {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
result := make([]Plugin, 0)
|
|
for _, p := range r.plugins {
|
|
if p.Enabled() {
|
|
result = append(result, p)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// PrintStatus 打印当前插件状态(调试用)
|
|
func PrintStatus() {
|
|
r := getGlobalRegistry()
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
fmt.Println("[plugins] current status:")
|
|
for name, p := range r.plugins {
|
|
status := "disabled"
|
|
if p.Enabled() {
|
|
status = "enabled"
|
|
}
|
|
fmt.Printf(" - %s: %s\n", name, status)
|
|
}
|
|
if len(r.plugins) == 0 {
|
|
fmt.Println(" (no plugins registered — check build tags)")
|
|
}
|
|
}
|