package service import ( "context" "encoding/json" "errors" "fmt" "giter.top/smart/internal/system/entity" "giter.top/smart/internal/system/repository" "giter.top/smart/pkg/utils/id" "github.com/redis/go-redis/v9" ) // ErrInvalidParam 参数无效 var ErrInvalidParam = errors.New("invalid param") // ParamService 系统参数业务逻辑层 type ParamService interface { // CreateParam 创建系统参数 CreateParam(ctx context.Context, req *CreateParamRequest, creatorID string) (*entity.SystemParam, error) // UpdateParam 更新系统参数 UpdateParam(ctx context.Context, id string, req *UpdateParamRequest, lastUpdaterID string) (*entity.SystemParam, error) // DeleteParam 删除系统参数 DeleteParam(ctx context.Context, id string) error // DeleteParams 批量删除 DeleteParams(ctx context.Context, ids []string) error // GetParam 获取单个参数 GetParam(ctx context.Context, id string) (*entity.SystemParam, error) // GetParamByKey 根据键获取参数 GetParamByKey(ctx context.Context, key string) (*entity.SystemParam, error) // ListParams 获取参数列表 ListParams(ctx context.Context, group string, paramKey string, page, pageSize int) (*ParamListResponse, error) // GetAllParams 获取所有参数(用于缓存) GetAllParams(ctx context.Context) (map[string]entity.SystemParam, error) // GetParamValue 获取参数值(便捷方法) GetParamValue(ctx context.Context, key string) (string, error) // GetParamValueWithDefault 获取参数值,不存在则返回默认值 GetParamValueWithDefault(ctx context.Context, key string, defaultValue string) string } // CreateParamRequest 创建参数请求 type CreateParamRequest struct { ParamKey string `json:"param_key" binding:"required,max=100"` ParamValue string `json:"param_value" binding:"required"` ParamType string `json:"param_type" binding:"required,oneof=text number boolean select"` ParamGroup string `json:"param_group" binding:"required,max:50"` ParamDesc string `json:"param_desc" max:"500"` } // UpdateParamRequest 更新参数请求 type UpdateParamRequest struct { ParamValue string `json:"param_value"` ParamType string `json:"param_type" binding:"omitempty,oneof=text number boolean select"` ParamDesc string `json:"param_desc" max:"500"` } // ParamListResponse 参数列表响应 type ParamListResponse struct { Items []entity.SystemParam `json:"items"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` TotalPages int `json:"total_pages"` } type paramService struct { repo repository.ParamRepository cache redis.UniversalClient cacheKey string } // NewParamService 创建参数服务实例(与 cache.NewRedisClient 返回的 redis.UniversalClient 一致,便于 Wire 注入) func NewParamService(repo repository.ParamRepository, cacheClient redis.UniversalClient) ParamService { return ¶mService{ repo: repo, cache: cacheClient, cacheKey: "system:params:*", } } func (s *paramService) CreateParam(ctx context.Context, req *CreateParamRequest, creatorID string) (*entity.SystemParam, error) { // 生成唯一 ID (UUID v7) id := id.New() // 检查键是否已存在 exists, err := s.repo.ExistsByKey(ctx, req.ParamKey, "") if err != nil { return nil, fmt.Errorf("检查参数键失败:%w", err) } if exists { return nil, fmt.Errorf("参数键 %s 已存在", req.ParamKey) } param := &entity.SystemParam{ ID: id, ParamKey: req.ParamKey, ParamValue: req.ParamValue, ParamType: req.ParamType, ParamGroup: req.ParamGroup, ParamDesc: req.ParamDesc, CreatorID: creatorID, LastUpdaterID: creatorID, } if err := s.repo.Create(ctx, param); err != nil { return nil, fmt.Errorf("创建参数失败:%w", err) } // 刷新缓存 s.refreshCache(ctx) return param, nil } func (s *paramService) UpdateParam(ctx context.Context, id string, req *UpdateParamRequest, lastUpdaterID string) (*entity.SystemParam, error) { // 获取现有参数 param, err := s.repo.GetByID(ctx, id) if err != nil { if errors.Is(err, repository.ErrNotFound) { return nil, fmt.Errorf("参数不存在") } return nil, fmt.Errorf("获取参数失败:%w", err) } // 更新字段 if req.ParamValue != "" { param.ParamValue = req.ParamValue } if req.ParamType != "" { param.ParamType = req.ParamType } if req.ParamDesc != "" { param.ParamDesc = req.ParamDesc } param.LastUpdaterID = lastUpdaterID if err := s.repo.Update(ctx, param); err != nil { return nil, fmt.Errorf("更新参数失败:%w", err) } // 刷新缓存 s.refreshCache(ctx) return param, nil } func (s *paramService) DeleteParam(ctx context.Context, id string) error { if err := s.repo.Delete(ctx, id); err != nil { return fmt.Errorf("删除参数失败:%w", err) } // 刷新缓存 s.refreshCache(ctx) return nil } func (s *paramService) DeleteParams(ctx context.Context, ids []string) error { if len(ids) == 0 { return nil } if err := s.repo.DeleteBatch(ctx, ids); err != nil { return fmt.Errorf("批量删除参数失败:%w", err) } // 刷新缓存 s.refreshCache(ctx) return nil } func (s *paramService) GetParam(ctx context.Context, id string) (*entity.SystemParam, error) { param, err := s.repo.GetByID(ctx, id) if err != nil { if errors.Is(err, repository.ErrNotFound) { return nil, fmt.Errorf("参数不存在") } return nil, err } return param, nil } func (s *paramService) GetParamByKey(ctx context.Context, key string) (*entity.SystemParam, error) { param, err := s.repo.GetByKey(ctx, key) if err != nil { if errors.Is(err, repository.ErrNotFound) { return nil, fmt.Errorf("参数 %s 不存在", key) } return nil, err } return param, nil } func (s *paramService) ListParams(ctx context.Context, group string, paramKey string, page, pageSize int) (*ParamListResponse, error) { if page <= 0 { page = 1 } if pageSize <= 0 { pageSize = 10 } items, total, err := s.repo.List(ctx, group, paramKey, page, pageSize) if err != nil { return nil, fmt.Errorf("获取参数列表失败:%w", err) } totalPages := int(total) / pageSize if int(total)%pageSize != 0 { totalPages++ } return &ParamListResponse{ Items: items, Total: total, Page: page, PageSize: pageSize, TotalPages: totalPages, }, nil } func (s *paramService) GetAllParams(ctx context.Context) (map[string]entity.SystemParam, error) { // 先从缓存获取 if s.cache != nil { cached := s.cache.Get(ctx, "system:params:all").Val() if cached != "" { var params map[string]entity.SystemParam if err := json.Unmarshal([]byte(cached), ¶ms); err == nil { return params, nil } else { return nil, fmt.Errorf("解析缓存数据失败:%w", err) } } } // 缓存未命中,从数据库获取 params, err := s.repo.GetAll(ctx) if err != nil { return nil, err } // 写入缓存 if s.cache != nil { data, _ := json.Marshal(params) s.cache.Set(ctx, "system:params:all", string(data), 0) // 0 表示永不过期 } return params, nil } func (s *paramService) GetParamValue(ctx context.Context, key string) (string, error) { param, err := s.GetParamByKey(ctx, key) if err != nil { return "", err } return param.ParamValue, nil } func (s *paramService) GetParamValueWithDefault(ctx context.Context, key string, defaultValue string) string { value, err := s.GetParamValue(ctx, key) if err != nil { return defaultValue } return value } // refreshCache 刷新缓存 func (s *paramService) refreshCache(ctx context.Context) { if s.cache == nil { return } // 删除缓存,让下次请求重新构建 s.cache.Del(ctx, "system:params:all") }