435 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			435 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package entities | |||
|  | 
 | |||
|  | import ( | |||
|  | 	"errors" | |||
|  | 	"time" | |||
|  | 
 | |||
|  | 	"github.com/google/uuid" | |||
|  | 	"gorm.io/gorm" | |||
|  | ) | |||
|  | 
 | |||
|  | // StatisticsDashboard 仪表板配置实体 | |||
|  | // 用于存储仪表板的配置信息 | |||
|  | type StatisticsDashboard struct { | |||
|  | 	// 基础标识 | |||
|  | 	ID          string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"仪表板唯一标识"` | |||
|  | 	Name        string `gorm:"type:varchar(100);not null" json:"name" comment:"仪表板名称"` | |||
|  | 	Description string `gorm:"type:text" json:"description" comment:"仪表板描述"` | |||
|  | 	UserRole    string `gorm:"type:varchar(20);not null;index" json:"user_role" comment:"用户角色"` | |||
|  | 	IsDefault   bool   `gorm:"default:false" json:"is_default" comment:"是否为默认仪表板"` | |||
|  | 	IsActive    bool   `gorm:"default:true" json:"is_active" comment:"是否激活"` | |||
|  | 
 | |||
|  | 	// 仪表板配置 | |||
|  | 	Layout     string `gorm:"type:json" json:"layout" comment:"布局配置"` | |||
|  | 	Widgets    string `gorm:"type:json" json:"widgets" comment:"组件配置"` | |||
|  | 	Settings   string `gorm:"type:json" json:"settings" comment:"设置配置"` | |||
|  | 	RefreshInterval int `gorm:"default:300" json:"refresh_interval" comment:"刷新间隔(秒)"` | |||
|  | 
 | |||
|  | 	// 权限和访问控制 | |||
|  | 	CreatedBy string `gorm:"type:varchar(36);not null" json:"created_by" comment:"创建者ID"` | |||
|  | 	AccessLevel string `gorm:"type:varchar(20);default:'private'" json:"access_level" comment:"访问级别"` | |||
|  | 
 | |||
|  | 	// 时间戳字段 | |||
|  | 	CreatedAt time.Time      `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"` | |||
|  | 	UpdatedAt time.Time      `gorm:"autoUpdateTime" json:"updated_at" comment:"更新时间"` | |||
|  | 	DeletedAt gorm.DeletedAt `gorm:"index" json:"-" comment:"软删除时间"` | |||
|  | 
 | |||
|  | 	// 领域事件 (不持久化) | |||
|  | 	domainEvents []interface{} `gorm:"-" json:"-"` | |||
|  | } | |||
|  | 
 | |||
|  | // TableName 指定数据库表名 | |||
|  | func (StatisticsDashboard) TableName() string { | |||
|  | 	return "statistics_dashboards" | |||
|  | } | |||
|  | 
 | |||
|  | // BeforeCreate GORM钩子:创建前自动生成UUID | |||
|  | func (s *StatisticsDashboard) BeforeCreate(tx *gorm.DB) error { | |||
|  | 	if s.ID == "" { | |||
|  | 		s.ID = uuid.New().String() | |||
|  | 	} | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // 实现 Entity 接口 - 提供统一的实体管理接口 | |||
|  | // GetID 获取实体唯一标识 | |||
|  | func (s *StatisticsDashboard) GetID() string { | |||
|  | 	return s.ID | |||
|  | } | |||
|  | 
 | |||
|  | // GetCreatedAt 获取创建时间 | |||
|  | func (s *StatisticsDashboard) GetCreatedAt() time.Time { | |||
|  | 	return s.CreatedAt | |||
|  | } | |||
|  | 
 | |||
|  | // GetUpdatedAt 获取更新时间 | |||
|  | func (s *StatisticsDashboard) GetUpdatedAt() time.Time { | |||
|  | 	return s.UpdatedAt | |||
|  | } | |||
|  | 
 | |||
|  | // Validate 验证仪表板配置信息 | |||
|  | // 检查仪表板必填字段是否完整,确保数据的有效性 | |||
|  | func (s *StatisticsDashboard) Validate() error { | |||
|  | 	if s.Name == "" { | |||
|  | 		return NewValidationError("仪表板名称不能为空") | |||
|  | 	} | |||
|  | 	if s.UserRole == "" { | |||
|  | 		return NewValidationError("用户角色不能为空") | |||
|  | 	} | |||
|  | 	if s.CreatedBy == "" { | |||
|  | 		return NewValidationError("创建者ID不能为空") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 验证用户角色 | |||
|  | 	if !s.IsValidUserRole() { | |||
|  | 		return NewValidationError("无效的用户角色") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 验证访问级别 | |||
|  | 	if !s.IsValidAccessLevel() { | |||
|  | 		return NewValidationError("无效的访问级别") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 验证刷新间隔 | |||
|  | 	if s.RefreshInterval < 30 { | |||
|  | 		return NewValidationError("刷新间隔不能少于30秒") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // IsValidUserRole 检查用户角色是否有效 | |||
|  | func (s *StatisticsDashboard) IsValidUserRole() bool { | |||
|  | 	validRoles := []string{ | |||
|  | 		"admin",     // 管理员 | |||
|  | 		"user",      // 普通用户 | |||
|  | 		"manager",   // 经理 | |||
|  | 		"analyst",   // 分析师 | |||
|  | 	} | |||
|  | 
 | |||
|  | 	for _, validRole := range validRoles { | |||
|  | 		if s.UserRole == validRole { | |||
|  | 			return true | |||
|  | 		} | |||
|  | 	} | |||
|  | 	return false | |||
|  | } | |||
|  | 
 | |||
|  | // IsValidAccessLevel 检查访问级别是否有效 | |||
|  | func (s *StatisticsDashboard) IsValidAccessLevel() bool { | |||
|  | 	validLevels := []string{ | |||
|  | 		"private",   // 私有 | |||
|  | 		"public",    // 公开 | |||
|  | 		"shared",    // 共享 | |||
|  | 	} | |||
|  | 
 | |||
|  | 	for _, validLevel := range validLevels { | |||
|  | 		if s.AccessLevel == validLevel { | |||
|  | 			return true | |||
|  | 		} | |||
|  | 	} | |||
|  | 	return false | |||
|  | } | |||
|  | 
 | |||
|  | // GetUserRoleName 获取用户角色的中文名称 | |||
|  | func (s *StatisticsDashboard) GetUserRoleName() string { | |||
|  | 	roleNames := map[string]string{ | |||
|  | 		"admin":   "管理员", | |||
|  | 		"user":    "普通用户", | |||
|  | 		"manager": "经理", | |||
|  | 		"analyst": "分析师", | |||
|  | 	} | |||
|  | 
 | |||
|  | 	if name, exists := roleNames[s.UserRole]; exists { | |||
|  | 		return name | |||
|  | 	} | |||
|  | 	return s.UserRole | |||
|  | } | |||
|  | 
 | |||
|  | // GetAccessLevelName 获取访问级别的中文名称 | |||
|  | func (s *StatisticsDashboard) GetAccessLevelName() string { | |||
|  | 	levelNames := map[string]string{ | |||
|  | 		"private": "私有", | |||
|  | 		"public":  "公开", | |||
|  | 		"shared":  "共享", | |||
|  | 	} | |||
|  | 
 | |||
|  | 	if name, exists := levelNames[s.AccessLevel]; exists { | |||
|  | 		return name | |||
|  | 	} | |||
|  | 	return s.AccessLevel | |||
|  | } | |||
|  | 
 | |||
|  | // NewStatisticsDashboard 工厂方法 - 创建仪表板配置 | |||
|  | func NewStatisticsDashboard(name, description, userRole, createdBy string) (*StatisticsDashboard, error) { | |||
|  | 	if name == "" { | |||
|  | 		return nil, errors.New("仪表板名称不能为空") | |||
|  | 	} | |||
|  | 	if userRole == "" { | |||
|  | 		return nil, errors.New("用户角色不能为空") | |||
|  | 	} | |||
|  | 	if createdBy == "" { | |||
|  | 		return nil, errors.New("创建者ID不能为空") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	dashboard := &StatisticsDashboard{ | |||
|  | 		Name:          name, | |||
|  | 		Description:   description, | |||
|  | 		UserRole:      userRole, | |||
|  | 		CreatedBy:     createdBy, | |||
|  | 		IsDefault:     false, | |||
|  | 		IsActive:      true, | |||
|  | 		AccessLevel:   "private", | |||
|  | 		RefreshInterval: 300, // 默认5分钟 | |||
|  | 		domainEvents:  make([]interface{}, 0), | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 验证仪表板 | |||
|  | 	if err := dashboard.Validate(); err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	dashboard.addDomainEvent(&StatisticsDashboardCreatedEvent{ | |||
|  | 		DashboardID: dashboard.ID, | |||
|  | 		Name:        name, | |||
|  | 		UserRole:    userRole, | |||
|  | 		CreatedBy:   createdBy, | |||
|  | 		CreatedAt:   time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return dashboard, nil | |||
|  | } | |||
|  | 
 | |||
|  | // SetAsDefault 设置为默认仪表板 | |||
|  | func (s *StatisticsDashboard) SetAsDefault() error { | |||
|  | 	if !s.IsActive { | |||
|  | 		return NewValidationError("只有激活状态的仪表板才能设置为默认") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	s.IsDefault = true | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardSetAsDefaultEvent{ | |||
|  | 		DashboardID: s.ID, | |||
|  | 		SetAt:       time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // RemoveAsDefault 取消默认状态 | |||
|  | func (s *StatisticsDashboard) RemoveAsDefault() error { | |||
|  | 	if !s.IsDefault { | |||
|  | 		return NewValidationError("当前仪表板不是默认仪表板") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	s.IsDefault = false | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardRemovedAsDefaultEvent{ | |||
|  | 		DashboardID: s.ID, | |||
|  | 		RemovedAt:   time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // Activate 激活仪表板 | |||
|  | func (s *StatisticsDashboard) Activate() error { | |||
|  | 	if s.IsActive { | |||
|  | 		return NewValidationError("仪表板已经是激活状态") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	s.IsActive = true | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardActivatedEvent{ | |||
|  | 		DashboardID: s.ID, | |||
|  | 		ActivatedAt: time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // Deactivate 停用仪表板 | |||
|  | func (s *StatisticsDashboard) Deactivate() error { | |||
|  | 	if !s.IsActive { | |||
|  | 		return NewValidationError("仪表板已经是停用状态") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	s.IsActive = false | |||
|  | 
 | |||
|  | 	// 如果是默认仪表板,需要先取消默认状态 | |||
|  | 	if s.IsDefault { | |||
|  | 		s.IsDefault = false | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardDeactivatedEvent{ | |||
|  | 		DashboardID:   s.ID, | |||
|  | 		DeactivatedAt: time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // UpdateLayout 更新布局配置 | |||
|  | func (s *StatisticsDashboard) UpdateLayout(layout string) error { | |||
|  | 	if layout == "" { | |||
|  | 		return NewValidationError("布局配置不能为空") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	s.Layout = layout | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardLayoutUpdatedEvent{ | |||
|  | 		DashboardID: s.ID, | |||
|  | 		UpdatedAt:   time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // UpdateWidgets 更新组件配置 | |||
|  | func (s *StatisticsDashboard) UpdateWidgets(widgets string) error { | |||
|  | 	if widgets == "" { | |||
|  | 		return NewValidationError("组件配置不能为空") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	s.Widgets = widgets | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardWidgetsUpdatedEvent{ | |||
|  | 		DashboardID: s.ID, | |||
|  | 		UpdatedAt:   time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // UpdateSettings 更新设置配置 | |||
|  | func (s *StatisticsDashboard) UpdateSettings(settings string) error { | |||
|  | 	s.Settings = settings | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardSettingsUpdatedEvent{ | |||
|  | 		DashboardID: s.ID, | |||
|  | 		UpdatedAt:   time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // UpdateRefreshInterval 更新刷新间隔 | |||
|  | func (s *StatisticsDashboard) UpdateRefreshInterval(interval int) error { | |||
|  | 	if interval < 30 { | |||
|  | 		return NewValidationError("刷新间隔不能少于30秒") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	oldInterval := s.RefreshInterval | |||
|  | 	s.RefreshInterval = interval | |||
|  | 
 | |||
|  | 	// 添加领域事件 | |||
|  | 	s.addDomainEvent(&StatisticsDashboardRefreshIntervalUpdatedEvent{ | |||
|  | 		DashboardID:  s.ID, | |||
|  | 		OldInterval:  oldInterval, | |||
|  | 		NewInterval:  interval, | |||
|  | 		UpdatedAt:    time.Now(), | |||
|  | 	}) | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } | |||
|  | 
 | |||
|  | // CanBeModified 检查仪表板是否可以被修改 | |||
|  | func (s *StatisticsDashboard) CanBeModified() bool { | |||
|  | 	return s.IsActive | |||
|  | } | |||
|  | 
 | |||
|  | // CanBeDeleted 检查仪表板是否可以被删除 | |||
|  | func (s *StatisticsDashboard) CanBeDeleted() bool { | |||
|  | 	return !s.IsDefault && s.IsActive | |||
|  | } | |||
|  | 
 | |||
|  | // ================ 领域事件管理 ================ | |||
|  | 
 | |||
|  | // addDomainEvent 添加领域事件 | |||
|  | func (s *StatisticsDashboard) addDomainEvent(event interface{}) { | |||
|  | 	if s.domainEvents == nil { | |||
|  | 		s.domainEvents = make([]interface{}, 0) | |||
|  | 	} | |||
|  | 	s.domainEvents = append(s.domainEvents, event) | |||
|  | } | |||
|  | 
 | |||
|  | // GetDomainEvents 获取领域事件 | |||
|  | func (s *StatisticsDashboard) GetDomainEvents() []interface{} { | |||
|  | 	return s.domainEvents | |||
|  | } | |||
|  | 
 | |||
|  | // ClearDomainEvents 清除领域事件 | |||
|  | func (s *StatisticsDashboard) ClearDomainEvents() { | |||
|  | 	s.domainEvents = make([]interface{}, 0) | |||
|  | } | |||
|  | 
 | |||
|  | // ================ 领域事件定义 ================ | |||
|  | 
 | |||
|  | // StatisticsDashboardCreatedEvent 仪表板创建事件 | |||
|  | type StatisticsDashboardCreatedEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	Name        string    `json:"name"` | |||
|  | 	UserRole    string    `json:"user_role"` | |||
|  | 	CreatedBy   string    `json:"created_by"` | |||
|  | 	CreatedAt   time.Time `json:"created_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardSetAsDefaultEvent 仪表板设置为默认事件 | |||
|  | type StatisticsDashboardSetAsDefaultEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	SetAt       time.Time `json:"set_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardRemovedAsDefaultEvent 仪表板取消默认事件 | |||
|  | type StatisticsDashboardRemovedAsDefaultEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	RemovedAt   time.Time `json:"removed_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardActivatedEvent 仪表板激活事件 | |||
|  | type StatisticsDashboardActivatedEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	ActivatedAt time.Time `json:"activated_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardDeactivatedEvent 仪表板停用事件 | |||
|  | type StatisticsDashboardDeactivatedEvent struct { | |||
|  | 	DashboardID   string    `json:"dashboard_id"` | |||
|  | 	DeactivatedAt time.Time `json:"deactivated_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardLayoutUpdatedEvent 仪表板布局更新事件 | |||
|  | type StatisticsDashboardLayoutUpdatedEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	UpdatedAt   time.Time `json:"updated_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardWidgetsUpdatedEvent 仪表板组件更新事件 | |||
|  | type StatisticsDashboardWidgetsUpdatedEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	UpdatedAt   time.Time `json:"updated_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardSettingsUpdatedEvent 仪表板设置更新事件 | |||
|  | type StatisticsDashboardSettingsUpdatedEvent struct { | |||
|  | 	DashboardID string    `json:"dashboard_id"` | |||
|  | 	UpdatedAt   time.Time `json:"updated_at"` | |||
|  | } | |||
|  | 
 | |||
|  | // StatisticsDashboardRefreshIntervalUpdatedEvent 仪表板刷新间隔更新事件 | |||
|  | type StatisticsDashboardRefreshIntervalUpdatedEvent struct { | |||
|  | 	DashboardID  string    `json:"dashboard_id"` | |||
|  | 	OldInterval  int       `json:"old_interval"` | |||
|  | 	NewInterval  int       `json:"new_interval"` | |||
|  | 	UpdatedAt    time.Time `json:"updated_at"` | |||
|  | } | |||
|  | 
 |