413 lines
9.7 KiB
Go
413 lines
9.7 KiB
Go
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
|
|
} |