272 lines
7.5 KiB
Go
272 lines
7.5 KiB
Go
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")
|
|
}
|