247 lines
6.6 KiB
Go
247 lines
6.6 KiB
Go
package template
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// ConfigLoader loads template configuration from YAML files
|
|
type ConfigLoader struct {
|
|
configPath string
|
|
logger *slog.Logger
|
|
}
|
|
|
|
// NewConfigLoader creates a new template config loader
|
|
func NewConfigLoader(configPath string) *ConfigLoader {
|
|
return &ConfigLoader{
|
|
configPath: configPath,
|
|
logger: slog.With("component", "template_config"),
|
|
}
|
|
}
|
|
|
|
// TemplateConfigFile represents the structure of template configuration file
|
|
type TemplateConfigFile struct {
|
|
Templates map[string]struct {
|
|
Name string `yaml:"name"`
|
|
Type string `yaml:"type"`
|
|
Description string `yaml:"description"`
|
|
Fields map[string]string `yaml:"fields"`
|
|
Config map[string]interface{} `yaml:"config"`
|
|
} `yaml:"templates"`
|
|
TemplateTypes map[string]struct {
|
|
Layout string `yaml:"layout"`
|
|
Fields map[string]string `yaml:"fields"`
|
|
Options map[string]interface{} `yaml:"options"`
|
|
} `yaml:"template_types"`
|
|
}
|
|
|
|
|
|
|
|
// LoadTemplateConfig loads template configuration from YAML files
|
|
func (cl *ConfigLoader) LoadTemplateConfig() (*TemplateConfigFile, error) {
|
|
viper.SetConfigName("templates")
|
|
viper.SetConfigType("yaml")
|
|
|
|
// Add search paths
|
|
viper.AddConfigPath(cl.configPath)
|
|
viper.AddConfigPath("./config/templates")
|
|
viper.AddConfigPath("./web/templates")
|
|
viper.AddConfigPath("/etc/database-render/templates")
|
|
|
|
// Set default values
|
|
viper.SetDefault("templates", map[string]interface{}{})
|
|
viper.SetDefault("template_types", map[string]interface{}{
|
|
"list": map[string]interface{}{
|
|
"layout": "table",
|
|
"fields": map[string]string{
|
|
"default": "raw",
|
|
"time": "time",
|
|
"tag": "tag",
|
|
},
|
|
"options": map[string]interface{}{
|
|
"striped": true,
|
|
"hover": true,
|
|
},
|
|
},
|
|
"card": map[string]interface{}{
|
|
"layout": "grid",
|
|
"fields": map[string]string{
|
|
"default": "raw",
|
|
"time": "relative",
|
|
"tag": "badge",
|
|
},
|
|
"options": map[string]interface{}{
|
|
"columns": "3",
|
|
"spacing": "md",
|
|
},
|
|
},
|
|
})
|
|
|
|
// Read configuration
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
|
cl.logger.Warn("template config file not found, using defaults")
|
|
return cl.createDefaultConfig(), nil
|
|
}
|
|
return nil, fmt.Errorf("failed to read template config: %w", err)
|
|
}
|
|
|
|
var config TemplateConfigFile
|
|
if err := viper.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal template config: %w", err)
|
|
}
|
|
|
|
cl.logger.Info("template configuration loaded successfully",
|
|
"config_file", viper.ConfigFileUsed(),
|
|
"templates_count", len(config.Templates),
|
|
"types_count", len(config.TemplateTypes))
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// createDefaultConfig creates default template configuration
|
|
func (cl *ConfigLoader) createDefaultConfig() *TemplateConfigFile {
|
|
return &TemplateConfigFile{
|
|
Templates: map[string]struct {
|
|
Name string `yaml:"name"`
|
|
Type string `yaml:"type"`
|
|
Description string `yaml:"description"`
|
|
Fields map[string]string `yaml:"fields"`
|
|
Config map[string]interface{} `yaml:"config"`
|
|
}{
|
|
"articles": {
|
|
Name: "文章列表",
|
|
Type: "list",
|
|
Description: "技术文章列表视图",
|
|
Fields: map[string]string{
|
|
"title": "string",
|
|
"content": "markdown",
|
|
"category": "category",
|
|
"tags": "tag",
|
|
"created_at": "time",
|
|
},
|
|
Config: map[string]interface{}{
|
|
"page_size": 15,
|
|
"show_pagination": true,
|
|
},
|
|
},
|
|
"logs": {
|
|
Name: "系统日志",
|
|
Type: "table",
|
|
Description: "系统日志表格视图",
|
|
Fields: map[string]string{
|
|
"level": "tag",
|
|
"message": "string",
|
|
"timestamp": "time",
|
|
},
|
|
Config: map[string]interface{}{
|
|
"page_size": 50,
|
|
"show_filter": true,
|
|
},
|
|
},
|
|
},
|
|
TemplateTypes: map[string]struct {
|
|
Layout string `yaml:"layout"`
|
|
Fields map[string]string `yaml:"fields"`
|
|
Options map[string]interface{} `yaml:"options"`
|
|
}{
|
|
"list": {
|
|
Layout: "table",
|
|
Fields: map[string]string{
|
|
"default": "raw",
|
|
"time": "time",
|
|
"tag": "tag",
|
|
},
|
|
Options: map[string]interface{}{
|
|
"striped": true,
|
|
"hover": true,
|
|
},
|
|
},
|
|
"card": {
|
|
Layout: "grid",
|
|
Fields: map[string]string{
|
|
"default": "raw",
|
|
"time": "relative",
|
|
"tag": "badge",
|
|
},
|
|
Options: map[string]interface{}{
|
|
"columns": "3",
|
|
"spacing": "md",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// ValidateTemplateConfig validates template configuration
|
|
func (cl *ConfigLoader) ValidateTemplateConfig(config *TemplateConfigFile) error {
|
|
for name, template := range config.Templates {
|
|
if template.Name == "" {
|
|
return fmt.Errorf("template %s: name cannot be empty", name)
|
|
}
|
|
if template.Type == "" {
|
|
return fmt.Errorf("template %s: type cannot be empty", name)
|
|
}
|
|
}
|
|
|
|
for name, templateType := range config.TemplateTypes {
|
|
if templateType.Layout == "" {
|
|
return fmt.Errorf("template type %s: layout cannot be empty", name)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetTemplateConfig returns template configuration for a specific table
|
|
func (cl *ConfigLoader) GetTemplateConfig(tableName string) (interface{}, bool) {
|
|
config, err := cl.LoadTemplateConfig()
|
|
if err != nil {
|
|
cl.logger.Error("failed to load template config", "error", err)
|
|
return nil, false
|
|
}
|
|
|
|
template, exists := config.Templates[tableName]
|
|
return template, exists
|
|
}
|
|
|
|
// GetTemplateType returns template type configuration
|
|
func (cl *ConfigLoader) GetTemplateType(typeName string) (interface{}, bool) {
|
|
config, err := cl.LoadTemplateConfig()
|
|
if err != nil {
|
|
cl.logger.Error("failed to load template config", "error", err)
|
|
return nil, false
|
|
}
|
|
|
|
typeConfig, exists := config.TemplateTypes[typeName]
|
|
return typeConfig, exists
|
|
}
|
|
|
|
// GetAvailableTemplates returns all available templates
|
|
func (cl *ConfigLoader) GetAvailableTemplates() map[string]string {
|
|
config, err := cl.LoadTemplateConfig()
|
|
if err != nil {
|
|
cl.logger.Error("failed to load template config", "error", err)
|
|
return map[string]string{"list": "默认列表"}
|
|
}
|
|
|
|
result := make(map[string]string)
|
|
for key, template := range config.Templates {
|
|
result[key] = template.Description
|
|
}
|
|
|
|
// Add built-in templates if not overridden
|
|
if _, exists := result["list"]; !exists {
|
|
result["list"] = "列表视图"
|
|
}
|
|
if _, exists := result["card"]; !exists {
|
|
result["card"] = "卡片视图"
|
|
}
|
|
if _, exists := result["timeline"]; !exists {
|
|
result["timeline"] = "时间轴视图"
|
|
}
|
|
|
|
return result
|
|
} |