- Wails v2.16.0 + React 19 + TypeScript + Vite 7 - 插件系统(build tag 控制编译,plugin.json 运行时配置) - 支付插件(授权、账号、订单、退款、账单) - 高并发基础设施(任务池、批量处理器、限流器、环形缓冲、管道) - Windows 系统托盘(Win32 API) - CodeGraph 索引 + .memory 记忆包 - 默认图标 assets/icon.png
154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package plugins
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
)
|
||
|
||
// Config 插件配置文件结构
|
||
type Config struct {
|
||
Version string `json:"version"`
|
||
Plugins map[string]PluginOption `json:"plugins"`
|
||
}
|
||
|
||
// PluginOption 单个插件配置项
|
||
type PluginOption struct {
|
||
Enabled bool `json:"enabled"`
|
||
Description string `json:"description"`
|
||
// Params 插件专用参数,由插件自己解析
|
||
Params map[string]interface{} `json:"params,omitempty"`
|
||
}
|
||
|
||
// Loader 插件配置加载器
|
||
type Loader struct {
|
||
mu sync.RWMutex
|
||
cfg *Config
|
||
path string
|
||
}
|
||
|
||
// NewLoader 创建配置加载器
|
||
func NewLoader(path string) *Loader {
|
||
return &Loader{path: path}
|
||
}
|
||
|
||
// Load 从文件加载配置
|
||
func (l *Loader) Load() (*Config, error) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
|
||
data, err := os.ReadFile(l.path)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var cfg Config
|
||
if err := json.Unmarshal(data, &cfg); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 环境变量覆盖优先级最高
|
||
if v := os.Getenv("PLUGIN_ICONFONT"); v == "false" || v == "0" {
|
||
tmp := cfg.Plugins["iconfont"]; tmp.Enabled = false; cfg.Plugins["iconfont"] = tmp
|
||
}
|
||
if v := os.Getenv("PLUGIN_AI"); v == "true" || v == "1" {
|
||
tmp := cfg.Plugins["ai"]; tmp.Enabled = true; cfg.Plugins["ai"] = tmp
|
||
}
|
||
if v := os.Getenv("PLUGIN_CONCURRENT"); v == "false" || v == "0" {
|
||
tmp := cfg.Plugins["concurrent"]; tmp.Enabled = false; cfg.Plugins["concurrent"] = tmp
|
||
}
|
||
|
||
l.cfg = &cfg
|
||
return l.cfg, nil
|
||
}
|
||
|
||
// IsEnabled 查询插件启用状态
|
||
func (l *Loader) IsEnabled(name string) bool {
|
||
l.mu.RLock()
|
||
defer l.mu.RUnlock()
|
||
if l.cfg == nil {
|
||
return false
|
||
}
|
||
pc, ok := l.cfg.Plugins[name]
|
||
return ok && pc.Enabled
|
||
}
|
||
|
||
// GetEnabledNames 返回所有已启用插件名
|
||
func (l *Loader) GetEnabledNames() []string {
|
||
l.mu.RLock()
|
||
defer l.mu.RUnlock()
|
||
if l.cfg == nil {
|
||
return nil
|
||
}
|
||
result := make([]string, 0)
|
||
for name, pc := range l.cfg.Plugins {
|
||
if pc.Enabled {
|
||
result = append(result, name)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// Save 保存配置
|
||
func (l *Loader) Save(cfg *Config) error {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
data, err := json.MarshalIndent(cfg, "", " ")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
dir := filepath.Dir(l.path)
|
||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||
return err
|
||
}
|
||
return os.WriteFile(l.path, data, 0644)
|
||
}
|
||
|
||
// LoadOrDefault 加载配置,找不到则返回默认值
|
||
func LoadOrDefault() (*Config, error) {
|
||
paths := []string{"config/plugin.json", "./plugin.json"}
|
||
exe, _ := os.Executable()
|
||
if exe != "" {
|
||
dir := filepath.Dir(exe)
|
||
paths = append([]string{
|
||
filepath.Join(dir, "config", "plugin.json"),
|
||
filepath.Join(dir, "plugin.json"),
|
||
}, paths...)
|
||
}
|
||
for _, p := range paths {
|
||
if _, err := os.Stat(p); err == nil {
|
||
loader := NewLoader(p)
|
||
if cfg, err := loader.Load(); err == nil {
|
||
return cfg, nil
|
||
}
|
||
}
|
||
}
|
||
return defaultConfig(), nil
|
||
}
|
||
|
||
// EnsureConfig 确保配置文件存在
|
||
func EnsureConfig() error {
|
||
_, err := os.Stat("config/plugin.json")
|
||
if err == nil {
|
||
return nil
|
||
}
|
||
cfg, _ := LoadOrDefault()
|
||
loader := NewLoader("config/plugin.json")
|
||
if mkErr := os.MkdirAll("config", 0755); mkErr != nil {
|
||
return mkErr
|
||
}
|
||
return loader.Save(cfg)
|
||
}
|
||
|
||
func defaultConfig() *Config {
|
||
return &Config{
|
||
Version: "1.0.0",
|
||
Plugins: map[string]PluginOption{
|
||
"iconfont": {Enabled: false, Description: "阿里IconFont图标库,支持字体图标"},
|
||
"ai": {Enabled: false, Description: "AI大模型集成,支持对话、分析等功能"},
|
||
"concurrent": {Enabled: true, Description: "高并发工具集,任务池、限流器等"},
|
||
},
|
||
}
|
||
}
|