第一版完成
This commit is contained in:
413
internal/service/config.go
Normal file
413
internal/service/config.go
Normal file
@@ -0,0 +1,413 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"cms-api/internal/dao"
|
||||
"cms-api/internal/model"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type sConfig struct{}
|
||||
|
||||
func Config() *sConfig {
|
||||
return &sConfig{}
|
||||
}
|
||||
|
||||
// GetByKey 根据配置键获取配置
|
||||
func (s *sConfig) GetByKey(ctx context.Context, key string) (*model.SiteConfig, error) {
|
||||
return dao.Config.GetByKey(ctx, key)
|
||||
}
|
||||
|
||||
// GetValue 获取配置值
|
||||
func (s *sConfig) GetValue(ctx context.Context, key string, defaultValue ...interface{}) interface{} {
|
||||
config, err := s.GetByKey(ctx, key)
|
||||
if err != nil || config == nil {
|
||||
if len(defaultValue) > 0 {
|
||||
return defaultValue[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据配置类型转换值
|
||||
switch config.ConfigType {
|
||||
case "number":
|
||||
return gconv.Int(config.ConfigValue)
|
||||
case "boolean":
|
||||
return gconv.Bool(config.ConfigValue)
|
||||
case "json", "array":
|
||||
var result interface{}
|
||||
if err := json.Unmarshal([]byte(config.ConfigValue), &result); err == nil {
|
||||
return result
|
||||
}
|
||||
return config.ConfigValue
|
||||
default:
|
||||
return config.ConfigValue
|
||||
}
|
||||
}
|
||||
|
||||
// GetString 获取字符串配置值
|
||||
func (s *sConfig) GetString(ctx context.Context, key string, defaultValue ...string) string {
|
||||
value := s.GetValue(ctx, key)
|
||||
if value == nil {
|
||||
if len(defaultValue) > 0 {
|
||||
return defaultValue[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return gconv.String(value)
|
||||
}
|
||||
|
||||
// GetInt 获取整数配置值
|
||||
func (s *sConfig) GetInt(ctx context.Context, key string, defaultValue ...int) int {
|
||||
value := s.GetValue(ctx, key)
|
||||
if value == nil {
|
||||
if len(defaultValue) > 0 {
|
||||
return defaultValue[0]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return gconv.Int(value)
|
||||
}
|
||||
|
||||
// GetBool 获取布尔配置值
|
||||
func (s *sConfig) GetBool(ctx context.Context, key string, defaultValue ...bool) bool {
|
||||
value := s.GetValue(ctx, key)
|
||||
if value == nil {
|
||||
if len(defaultValue) > 0 {
|
||||
return defaultValue[0]
|
||||
}
|
||||
return false
|
||||
}
|
||||
return gconv.Bool(value)
|
||||
}
|
||||
|
||||
// List 获取配置列表
|
||||
func (s *sConfig) List(ctx context.Context, req *model.ConfigListRequest) (*model.PageResponse, error) {
|
||||
var (
|
||||
page = req.Page
|
||||
pageSize = req.PageSize
|
||||
)
|
||||
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
// 设置分页参数
|
||||
req.Page = page
|
||||
req.PageSize = pageSize
|
||||
|
||||
// 获取列表
|
||||
configs, total, err := dao.Config.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.PageResponse{
|
||||
List: configs,
|
||||
Total: total,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
TotalPages: (total + pageSize - 1) / pageSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetByGroup 根据分组获取配置
|
||||
func (s *sConfig) GetByGroup(ctx context.Context, groupName string) ([]*model.SiteConfig, error) {
|
||||
return dao.Config.GetByGroup(ctx, groupName)
|
||||
}
|
||||
|
||||
// GetGroups 获取所有配置分组
|
||||
func (s *sConfig) GetGroups(ctx context.Context) ([]string, error) {
|
||||
return dao.Config.GetGroups(ctx)
|
||||
}
|
||||
|
||||
// Create 创建配置
|
||||
func (s *sConfig) Create(ctx context.Context, req *model.CreateConfigRequest) error {
|
||||
// 检查配置键是否存在
|
||||
existConfig, err := dao.Config.GetByKey(ctx, req.ConfigKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existConfig != nil {
|
||||
return gerror.New("配置键已存在")
|
||||
}
|
||||
|
||||
// 验证配置值格式
|
||||
if err := s.validateConfigValue(req.ConfigValue, req.ConfigType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建配置
|
||||
config := &model.SiteConfig{
|
||||
ConfigKey: req.ConfigKey,
|
||||
ConfigValue: req.ConfigValue,
|
||||
ConfigType: req.ConfigType,
|
||||
GroupName: req.GroupName,
|
||||
Description: req.Description,
|
||||
SortOrder: req.SortOrder,
|
||||
IsSystem: req.IsSystem,
|
||||
CreatedAt: gtime.Now(),
|
||||
UpdatedAt: gtime.Now(),
|
||||
}
|
||||
|
||||
_, err = dao.Config.Create(ctx, config)
|
||||
return err
|
||||
}
|
||||
|
||||
// Update 更新配置
|
||||
func (s *sConfig) Update(ctx context.Context, key string, req *model.UpdateConfigRequest) error {
|
||||
// 检查配置是否存在
|
||||
config, err := s.GetByKey(ctx, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config == nil {
|
||||
return gerror.New("配置不存在")
|
||||
}
|
||||
|
||||
// 验证配置值格式
|
||||
if err := s.validateConfigValue(req.ConfigValue, req.ConfigType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新配置
|
||||
updateData := g.Map{
|
||||
"config_value": req.ConfigValue,
|
||||
"config_type": req.ConfigType,
|
||||
"group_name": req.GroupName,
|
||||
"description": req.Description,
|
||||
"sort_order": req.SortOrder,
|
||||
"is_system": req.IsSystem,
|
||||
"updated_at": gtime.Now(),
|
||||
}
|
||||
|
||||
return dao.Config.UpdateByKey(ctx, key, updateData)
|
||||
}
|
||||
|
||||
// UpdateValue 更新配置值
|
||||
func (s *sConfig) UpdateValue(ctx context.Context, key string, value interface{}) error {
|
||||
// 检查配置是否存在
|
||||
config, err := s.GetByKey(ctx, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config == nil {
|
||||
return gerror.New("配置不存在")
|
||||
}
|
||||
|
||||
// 转换值为字符串
|
||||
var valueStr string
|
||||
switch config.ConfigType {
|
||||
case "json", "array":
|
||||
if jsonBytes, err := json.Marshal(value); err == nil {
|
||||
valueStr = string(jsonBytes)
|
||||
} else {
|
||||
return gerror.New("配置值格式错误")
|
||||
}
|
||||
default:
|
||||
valueStr = gconv.String(value)
|
||||
}
|
||||
|
||||
// 验证配置值格式
|
||||
if err := s.validateConfigValue(valueStr, config.ConfigType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新配置值
|
||||
return dao.Config.UpdateValue(ctx, key, valueStr)
|
||||
}
|
||||
|
||||
// BatchUpdate 批量更新配置
|
||||
func (s *sConfig) BatchUpdate(ctx context.Context, req *model.BatchUpdateConfigRequest) error {
|
||||
for key, value := range req.Configs {
|
||||
if err := s.UpdateValue(ctx, key, value); err != nil {
|
||||
g.Log().Error(ctx, "批量更新配置失败, 键:", key, "错误:", err)
|
||||
// 继续更新其他配置,不中断整个过程
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete 删除配置
|
||||
func (s *sConfig) Delete(ctx context.Context, key string) error {
|
||||
// 检查配置是否存在
|
||||
config, err := s.GetByKey(ctx, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config == nil {
|
||||
return gerror.New("配置不存在")
|
||||
}
|
||||
|
||||
// 检查是否为系统配置
|
||||
if config.IsSystem == 1 {
|
||||
return gerror.New("系统配置不能删除")
|
||||
}
|
||||
|
||||
return dao.Config.DeleteByKey(ctx, key)
|
||||
}
|
||||
|
||||
// InitDefaultConfigs 初始化默认配置
|
||||
func (s *sConfig) InitDefaultConfigs(ctx context.Context) error {
|
||||
defaultConfigs := []model.SiteConfig{
|
||||
{
|
||||
ConfigKey: "site_name",
|
||||
ConfigValue: "企业官网CMS系统",
|
||||
ConfigType: "string",
|
||||
GroupName: "基础设置",
|
||||
Description: "网站名称",
|
||||
SortOrder: 1,
|
||||
IsSystem: 1,
|
||||
},
|
||||
{
|
||||
ConfigKey: "site_title",
|
||||
ConfigValue: "企业官网CMS系统 - 专业的内容管理平台",
|
||||
ConfigType: "string",
|
||||
GroupName: "基础设置",
|
||||
Description: "网站标题",
|
||||
SortOrder: 2,
|
||||
IsSystem: 1,
|
||||
},
|
||||
{
|
||||
ConfigKey: "site_description",
|
||||
ConfigValue: "专业的企业官网内容管理系统,提供完整的内容发布和管理功能",
|
||||
ConfigType: "string",
|
||||
GroupName: "基础设置",
|
||||
Description: "网站描述",
|
||||
SortOrder: 3,
|
||||
IsSystem: 1,
|
||||
},
|
||||
{
|
||||
ConfigKey: "site_keywords",
|
||||
ConfigValue: "企业官网,CMS,内容管理,新闻发布",
|
||||
ConfigType: "string",
|
||||
GroupName: "基础设置",
|
||||
Description: "网站关键词",
|
||||
SortOrder: 4,
|
||||
IsSystem: 1,
|
||||
},
|
||||
{
|
||||
ConfigKey: "contact_phone",
|
||||
ConfigValue: "400-123-4567",
|
||||
ConfigType: "string",
|
||||
GroupName: "联系方式",
|
||||
Description: "联系电话",
|
||||
SortOrder: 1,
|
||||
IsSystem: 0,
|
||||
},
|
||||
{
|
||||
ConfigKey: "contact_email",
|
||||
ConfigValue: "contact@example.com",
|
||||
ConfigType: "string",
|
||||
GroupName: "联系方式",
|
||||
Description: "联系邮箱",
|
||||
SortOrder: 2,
|
||||
IsSystem: 0,
|
||||
},
|
||||
{
|
||||
ConfigKey: "contact_address",
|
||||
ConfigValue: "北京市朝阳区xxx大厦xxx室",
|
||||
ConfigType: "string",
|
||||
GroupName: "联系方式",
|
||||
Description: "联系地址",
|
||||
SortOrder: 3,
|
||||
IsSystem: 0,
|
||||
},
|
||||
{
|
||||
ConfigKey: "upload_max_size",
|
||||
ConfigValue: "10485760",
|
||||
ConfigType: "number",
|
||||
GroupName: "上传设置",
|
||||
Description: "最大上传文件大小(字节)",
|
||||
SortOrder: 1,
|
||||
IsSystem: 1,
|
||||
},
|
||||
{
|
||||
ConfigKey: "allowed_file_types",
|
||||
ConfigValue: `["jpg","jpeg","png","gif","pdf","doc","docx","xls","xlsx"]`,
|
||||
ConfigType: "array",
|
||||
GroupName: "上传设置",
|
||||
Description: "允许上传的文件类型",
|
||||
SortOrder: 2,
|
||||
IsSystem: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, config := range defaultConfigs {
|
||||
// 检查配置是否已存在
|
||||
existConfig, err := dao.Config.GetByKey(ctx, config.ConfigKey)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if existConfig != nil {
|
||||
continue // 跳过已存在的配置
|
||||
}
|
||||
|
||||
// 创建配置
|
||||
config.CreatedAt = gtime.Now()
|
||||
config.UpdatedAt = gtime.Now()
|
||||
dao.Config.Create(ctx, &config)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateConfigValue 验证配置值格式
|
||||
func (s *sConfig) validateConfigValue(value, configType string) error {
|
||||
switch configType {
|
||||
case "number":
|
||||
if _, err := strconv.ParseFloat(value, 64); err != nil {
|
||||
return gerror.New("配置值必须是数字")
|
||||
}
|
||||
case "boolean":
|
||||
if value != "true" && value != "false" && value != "1" && value != "0" {
|
||||
return gerror.New("配置值必须是布尔值")
|
||||
}
|
||||
case "json", "array":
|
||||
var temp interface{}
|
||||
if err := json.Unmarshal([]byte(value), &temp); err != nil {
|
||||
return gerror.New("配置值必须是有效的JSON格式")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// isNumeric 检查字符串是否为数字
|
||||
func (s *sConfig) isNumeric(str string) bool {
|
||||
matched, _ := regexp.MatchString(`^-?\d+(\.\d+)?$`, str)
|
||||
return matched
|
||||
}
|
||||
|
||||
// GetPublicConfigs 获取公开配置(前台可访问)
|
||||
func (s *sConfig) GetPublicConfigs(ctx context.Context) (map[string]interface{}, error) {
|
||||
// 定义公开配置键
|
||||
publicKeys := []string{
|
||||
"site_name",
|
||||
"site_title",
|
||||
"site_description",
|
||||
"site_keywords",
|
||||
"contact_phone",
|
||||
"contact_email",
|
||||
"contact_address",
|
||||
}
|
||||
|
||||
result := make(map[string]interface{})
|
||||
for _, key := range publicKeys {
|
||||
value := s.GetValue(ctx, key)
|
||||
if value != nil {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user