package service import ( "context" "errors" "fmt" "strconv" "time" "github.com/user-management-system/internal/domain" "github.com/user-management-system/internal/repository" ) // CustomFieldService 自定义字段服务 type CustomFieldService struct { fieldRepo *repository.CustomFieldRepository valueRepo *repository.UserCustomFieldValueRepository } // NewCustomFieldService 创建自定义字段服务 func NewCustomFieldService( fieldRepo *repository.CustomFieldRepository, valueRepo *repository.UserCustomFieldValueRepository, ) *CustomFieldService { return &CustomFieldService{ fieldRepo: fieldRepo, valueRepo: valueRepo, } } // CreateFieldRequest 创建字段请求 type CreateFieldRequest struct { Name string `json:"name" binding:"required"` FieldKey string `json:"field_key" binding:"required"` Type int `json:"type" binding:"required"` Required bool `json:"required"` Default string `json:"default"` MinLen int `json:"min_len"` MaxLen int `json:"max_len"` MinVal float64 `json:"min_val"` MaxVal float64 `json:"max_val"` Options string `json:"options"` Sort int `json:"sort"` } // UpdateFieldRequest 更新字段请求 type UpdateFieldRequest struct { Name string `json:"name"` Type int `json:"type"` Required *bool `json:"required"` Default string `json:"default"` MinLen int `json:"min_len"` MaxLen int `json:"max_len"` MinVal float64 `json:"min_val"` MaxVal float64 `json:"max_val"` Options string `json:"options"` Sort int `json:"sort"` Status *int `json:"status"` } // CreateField 创建自定义字段 func (s *CustomFieldService) CreateField(ctx context.Context, req *CreateFieldRequest) (*domain.CustomField, error) { // 检查field_key是否已存在 existing, err := s.fieldRepo.GetByFieldKey(ctx, req.FieldKey) if err == nil && existing != nil { return nil, errors.New("字段标识符已存在") } field := &domain.CustomField{ Name: req.Name, FieldKey: req.FieldKey, Type: domain.CustomFieldType(req.Type), Required: req.Required, DefaultVal: req.Default, MinLen: req.MinLen, MaxLen: req.MaxLen, MinVal: req.MinVal, MaxVal: req.MaxVal, Options: req.Options, Sort: req.Sort, Status: 1, } if err := s.fieldRepo.Create(ctx, field); err != nil { return nil, err } return field, nil } // UpdateField 更新自定义字段 func (s *CustomFieldService) UpdateField(ctx context.Context, id int64, req *UpdateFieldRequest) (*domain.CustomField, error) { field, err := s.fieldRepo.GetByID(ctx, id) if err != nil { return nil, errors.New("字段不存在") } if req.Name != "" { field.Name = req.Name } if req.Type > 0 { field.Type = domain.CustomFieldType(req.Type) } if req.Required != nil { field.Required = *req.Required } if req.Default != "" { field.DefaultVal = req.Default } if req.MinLen > 0 { field.MinLen = req.MinLen } if req.MaxLen > 0 { field.MaxLen = req.MaxLen } if req.MinVal > 0 { field.MinVal = req.MinVal } if req.MaxVal > 0 { field.MaxVal = req.MaxVal } if req.Options != "" { field.Options = req.Options } if req.Sort > 0 { field.Sort = req.Sort } if req.Status != nil { field.Status = *req.Status } if err := s.fieldRepo.Update(ctx, field); err != nil { return nil, err } return field, nil } // DeleteField 删除自定义字段 func (s *CustomFieldService) DeleteField(ctx context.Context, id int64) error { field, err := s.fieldRepo.GetByID(ctx, id) if err != nil { return errors.New("字段不存在") } // 删除字段定义 if err := s.fieldRepo.Delete(ctx, id); err != nil { return err } // 清理用户的该字段值(可选,取决于业务需求) _ = field return nil } // GetField 获取自定义字段 func (s *CustomFieldService) GetField(ctx context.Context, id int64) (*domain.CustomField, error) { return s.fieldRepo.GetByID(ctx, id) } // ListFields 获取所有启用的自定义字段 func (s *CustomFieldService) ListFields(ctx context.Context) ([]*domain.CustomField, error) { return s.fieldRepo.List(ctx) } // ListAllFields 获取所有自定义字段 func (s *CustomFieldService) ListAllFields(ctx context.Context) ([]*domain.CustomField, error) { return s.fieldRepo.ListAll(ctx) } // SetUserFieldValue 设置用户的自定义字段值 func (s *CustomFieldService) SetUserFieldValue(ctx context.Context, userID int64, fieldKey string, value string) error { // 获取字段定义 field, err := s.fieldRepo.GetByFieldKey(ctx, fieldKey) if err != nil { return errors.New("字段不存在") } // 验证值 if err := s.validateFieldValue(field, value); err != nil { return err } return s.valueRepo.Set(ctx, userID, field.ID, fieldKey, value) } // BatchSetUserFieldValues 批量设置用户的自定义字段值 func (s *CustomFieldService) BatchSetUserFieldValues(ctx context.Context, userID int64, values map[string]string) error { // 获取所有启用的字段定义 fields, err := s.fieldRepo.List(ctx) if err != nil { return err } fieldMap := make(map[string]*domain.CustomField) for _, f := range fields { fieldMap[f.FieldKey] = f } // 验证每个值 for fieldKey, value := range values { field, ok := fieldMap[fieldKey] if !ok { return fmt.Errorf("字段不存在: %s", fieldKey) } if err := s.validateFieldValue(field, value); err != nil { return err } } // 批量设置值 return s.valueRepo.BatchSet(ctx, userID, values) } // GetUserFieldValues 获取用户的所有自定义字段值 func (s *CustomFieldService) GetUserFieldValues(ctx context.Context, userID int64) ([]*domain.CustomFieldValueResponse, error) { // 获取所有启用的字段定义 fields, err := s.fieldRepo.List(ctx) if err != nil { return nil, err } // 获取用户的字段值 values, err := s.valueRepo.GetByUserID(ctx, userID) if err != nil { return nil, err } // 构建字段值映射 valueMap := make(map[int64]*domain.UserCustomFieldValue) for _, v := range values { valueMap[v.FieldID] = v } // 构建响应 fieldMap := make(map[string]*domain.CustomField) for _, f := range fields { fieldMap[f.FieldKey] = f } var result []*domain.CustomFieldValueResponse for _, field := range fields { resp := &domain.CustomFieldValueResponse{ FieldKey: field.FieldKey, } if val, ok := valueMap[field.ID]; ok { resp.Value = val.GetValueAsInterface(field) } else if field.DefaultVal != "" { resp.Value = field.DefaultVal } else { resp.Value = nil } result = append(result, resp) } return result, nil } // DeleteUserFieldValue 删除用户的自定义字段值 func (s *CustomFieldService) DeleteUserFieldValue(ctx context.Context, userID int64, fieldKey string) error { field, err := s.fieldRepo.GetByFieldKey(ctx, fieldKey) if err != nil { return errors.New("字段不存在") } return s.valueRepo.Delete(ctx, userID, field.ID) } // validateFieldValue 验证字段值 func (s *CustomFieldService) validateFieldValue(field *domain.CustomField, value string) error { // 检查必填 if field.Required && value == "" { return errors.New("字段值不能为空") } // 如果值为空且有默认值,跳过验证 if value == "" && field.DefaultVal != "" { return nil } switch field.Type { case domain.CustomFieldTypeString: // 字符串长度验证 if field.MinLen > 0 && len(value) < field.MinLen { return fmt.Errorf("值长度不能小于%d", field.MinLen) } if field.MaxLen > 0 && len(value) > field.MaxLen { return fmt.Errorf("值长度不能大于%d", field.MaxLen) } case domain.CustomFieldTypeNumber: // 数字验证 numVal, err := strconv.ParseFloat(value, 64) if err != nil { return errors.New("值必须是数字") } if field.MinVal > 0 && numVal < field.MinVal { return fmt.Errorf("值不能小于%.2f", field.MinVal) } if field.MaxVal > 0 && numVal > field.MaxVal { return fmt.Errorf("值不能大于%.2f", field.MaxVal) } case domain.CustomFieldTypeBoolean: // 布尔验证 if value != "true" && value != "false" && value != "1" && value != "0" { return errors.New("值必须是布尔值(true/false/1/0)") } case domain.CustomFieldTypeDate: // 日期验证 _, err := time.Parse("2006-01-02", value) if err != nil { return errors.New("值必须是有效的日期格式(YYYY-MM-DD)") } } return nil }