558 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			558 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package migrations
 | ||
| 
 | ||
| import (
 | ||
| 	"fmt"
 | ||
| 	"time"
 | ||
| 
 | ||
| 	"gorm.io/gorm"
 | ||
| 
 | ||
| 	"tyapi-server/internal/domains/statistics/entities"
 | ||
| )
 | ||
| 
 | ||
| // StatisticsMigration 统计模块数据迁移
 | ||
| type StatisticsMigration struct {
 | ||
| 	db *gorm.DB
 | ||
| }
 | ||
| 
 | ||
| // NewStatisticsMigration 创建统计模块数据迁移
 | ||
| func NewStatisticsMigration(db *gorm.DB) *StatisticsMigration {
 | ||
| 	return &StatisticsMigration{
 | ||
| 		db: db,
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // Migrate 执行数据迁移
 | ||
| func (m *StatisticsMigration) Migrate() error {
 | ||
| 	fmt.Println("开始执行统计模块数据迁移...")
 | ||
| 
 | ||
| 	// 迁移统计指标表
 | ||
| 	err := m.migrateStatisticsMetrics()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("迁移统计指标表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 迁移统计报告表
 | ||
| 	err = m.migrateStatisticsReports()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("迁移统计报告表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 迁移统计仪表板表
 | ||
| 	err = m.migrateStatisticsDashboards()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("迁移统计仪表板表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 创建索引
 | ||
| 	err = m.createIndexes()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 插入初始数据
 | ||
| 	err = m.insertInitialData()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("插入初始数据失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计模块数据迁移完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // migrateStatisticsMetrics 迁移统计指标表
 | ||
| func (m *StatisticsMigration) migrateStatisticsMetrics() error {
 | ||
| 	fmt.Println("迁移统计指标表...")
 | ||
| 
 | ||
| 	// 自动迁移表结构
 | ||
| 	err := m.db.AutoMigrate(&entities.StatisticsMetric{})
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("自动迁移统计指标表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计指标表迁移完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // migrateStatisticsReports 迁移统计报告表
 | ||
| func (m *StatisticsMigration) migrateStatisticsReports() error {
 | ||
| 	fmt.Println("迁移统计报告表...")
 | ||
| 
 | ||
| 	// 自动迁移表结构
 | ||
| 	err := m.db.AutoMigrate(&entities.StatisticsReport{})
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("自动迁移统计报告表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计报告表迁移完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // migrateStatisticsDashboards 迁移统计仪表板表
 | ||
| func (m *StatisticsMigration) migrateStatisticsDashboards() error {
 | ||
| 	fmt.Println("迁移统计仪表板表...")
 | ||
| 
 | ||
| 	// 自动迁移表结构
 | ||
| 	err := m.db.AutoMigrate(&entities.StatisticsDashboard{})
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("自动迁移统计仪表板表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计仪表板表迁移完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // createIndexes 创建索引
 | ||
| func (m *StatisticsMigration) createIndexes() error {
 | ||
| 	fmt.Println("创建统计模块索引...")
 | ||
| 
 | ||
| 	// 统计指标表索引
 | ||
| 	err := m.createStatisticsMetricsIndexes()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建统计指标表索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 统计报告表索引
 | ||
| 	err = m.createStatisticsReportsIndexes()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建统计报告表索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 统计仪表板表索引
 | ||
| 	err = m.createStatisticsDashboardsIndexes()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建统计仪表板表索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计模块索引创建完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // createStatisticsMetricsIndexes 创建统计指标表索引
 | ||
| func (m *StatisticsMigration) createStatisticsMetricsIndexes() error {
 | ||
| 	// 复合索引:metric_type + date
 | ||
| 	err := m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_metrics_type_date 
 | ||
| 		ON statistics_metrics (metric_type, date)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 复合索引:metric_type + dimension + date
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_metrics_type_dimension_date 
 | ||
| 		ON statistics_metrics (metric_type, dimension, date)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 复合索引:metric_type + metric_name + date
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_metrics_type_name_date 
 | ||
| 		ON statistics_metrics (metric_type, metric_name, date)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 单列索引:dimension
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_metrics_dimension 
 | ||
| 		ON statistics_metrics (dimension)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建维度索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // createStatisticsReportsIndexes 创建统计报告表索引
 | ||
| func (m *StatisticsMigration) createStatisticsReportsIndexes() error {
 | ||
| 	// 复合索引:report_type + created_at
 | ||
| 	err := m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_reports_type_created 
 | ||
| 		ON statistics_reports (report_type, created_at)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 复合索引:user_role + created_at
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_reports_role_created 
 | ||
| 		ON statistics_reports (user_role, created_at)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 复合索引:status + created_at
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_reports_status_created 
 | ||
| 		ON statistics_reports (status, created_at)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 单列索引:generated_by
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_reports_generated_by 
 | ||
| 		ON statistics_reports (generated_by)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建生成者索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 单列索引:expires_at
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_reports_expires_at 
 | ||
| 		ON statistics_reports (expires_at)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建过期时间索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // createStatisticsDashboardsIndexes 创建统计仪表板表索引
 | ||
| func (m *StatisticsMigration) createStatisticsDashboardsIndexes() error {
 | ||
| 	// 复合索引:user_role + is_active
 | ||
| 	err := m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_role_active 
 | ||
| 		ON statistics_dashboards (user_role, is_active)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 复合索引:user_role + is_default
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_role_default 
 | ||
| 		ON statistics_dashboards (user_role, is_default)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建复合索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 单列索引:created_by
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_created_by 
 | ||
| 		ON statistics_dashboards (created_by)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建创建者索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 单列索引:access_level
 | ||
| 	err = m.db.Exec(`
 | ||
| 		CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_access_level 
 | ||
| 		ON statistics_dashboards (access_level)
 | ||
| 	`).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建访问级别索引失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // insertInitialData 插入初始数据
 | ||
| func (m *StatisticsMigration) insertInitialData() error {
 | ||
| 	fmt.Println("插入统计模块初始数据...")
 | ||
| 
 | ||
| 	// 插入默认仪表板
 | ||
| 	err := m.insertDefaultDashboards()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("插入默认仪表板失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 插入初始指标数据
 | ||
| 	err = m.insertInitialMetrics()
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("插入初始指标数据失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计模块初始数据插入完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // insertDefaultDashboards 插入默认仪表板
 | ||
| func (m *StatisticsMigration) insertDefaultDashboards() error {
 | ||
| 	// 管理员默认仪表板
 | ||
| 	adminDashboard := &entities.StatisticsDashboard{
 | ||
| 		Name:            "管理员仪表板",
 | ||
| 		Description:     "系统管理员专用仪表板,包含所有统计信息",
 | ||
| 		UserRole:        "admin",
 | ||
| 		IsDefault:       true,
 | ||
| 		IsActive:        true,
 | ||
| 		AccessLevel:     "private",
 | ||
| 		RefreshInterval: 300,
 | ||
| 		CreatedBy:       "system",
 | ||
| 		Layout:          `{"columns": 3, "rows": 4}`,
 | ||
| 		Widgets:         `[{"type": "api_calls", "position": {"x": 0, "y": 0}}, {"type": "users", "position": {"x": 1, "y": 0}}, {"type": "finance", "position": {"x": 2, "y": 0}}]`,
 | ||
| 		Settings:        `{"theme": "dark", "auto_refresh": true}`,
 | ||
| 	}
 | ||
| 
 | ||
| 	err := m.db.Create(adminDashboard).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建管理员仪表板失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 用户默认仪表板
 | ||
| 	userDashboard := &entities.StatisticsDashboard{
 | ||
| 		Name:            "用户仪表板",
 | ||
| 		Description:     "普通用户专用仪表板,包含基础统计信息",
 | ||
| 		UserRole:        "user",
 | ||
| 		IsDefault:       true,
 | ||
| 		IsActive:        true,
 | ||
| 		AccessLevel:     "private",
 | ||
| 		RefreshInterval: 600,
 | ||
| 		CreatedBy:       "system",
 | ||
| 		Layout:          `{"columns": 2, "rows": 3}`,
 | ||
| 		Widgets:         `[{"type": "api_calls", "position": {"x": 0, "y": 0}}, {"type": "users", "position": {"x": 1, "y": 0}}]`,
 | ||
| 		Settings:        `{"theme": "light", "auto_refresh": false}`,
 | ||
| 	}
 | ||
| 
 | ||
| 	err = m.db.Create(userDashboard).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建用户仪表板失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 经理默认仪表板
 | ||
| 	managerDashboard := &entities.StatisticsDashboard{
 | ||
| 		Name:            "经理仪表板",
 | ||
| 		Description:     "经理专用仪表板,包含管理相关统计信息",
 | ||
| 		UserRole:        "manager",
 | ||
| 		IsDefault:       true,
 | ||
| 		IsActive:        true,
 | ||
| 		AccessLevel:     "private",
 | ||
| 		RefreshInterval: 300,
 | ||
| 		CreatedBy:       "system",
 | ||
| 		Layout:          `{"columns": 3, "rows": 3}`,
 | ||
| 		Widgets:         `[{"type": "api_calls", "position": {"x": 0, "y": 0}}, {"type": "users", "position": {"x": 1, "y": 0}}, {"type": "finance", "position": {"x": 2, "y": 0}}]`,
 | ||
| 		Settings:        `{"theme": "dark", "auto_refresh": true}`,
 | ||
| 	}
 | ||
| 
 | ||
| 	err = m.db.Create(managerDashboard).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建经理仪表板失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	// 分析师默认仪表板
 | ||
| 	analystDashboard := &entities.StatisticsDashboard{
 | ||
| 		Name:            "分析师仪表板",
 | ||
| 		Description:     "数据分析师专用仪表板,包含详细分析信息",
 | ||
| 		UserRole:        "analyst",
 | ||
| 		IsDefault:       true,
 | ||
| 		IsActive:        true,
 | ||
| 		AccessLevel:     "private",
 | ||
| 		RefreshInterval: 180,
 | ||
| 		CreatedBy:       "system",
 | ||
| 		Layout:          `{"columns": 4, "rows": 4}`,
 | ||
| 		Widgets:         `[{"type": "api_calls", "position": {"x": 0, "y": 0}}, {"type": "users", "position": {"x": 1, "y": 0}}, {"type": "finance", "position": {"x": 2, "y": 0}}, {"type": "products", "position": {"x": 3, "y": 0}}]`,
 | ||
| 		Settings:        `{"theme": "dark", "auto_refresh": true, "show_trends": true}`,
 | ||
| 	}
 | ||
| 
 | ||
| 	err = m.db.Create(analystDashboard).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("创建分析师仪表板失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("默认仪表板创建完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // insertInitialMetrics 插入初始指标数据
 | ||
| func (m *StatisticsMigration) insertInitialMetrics() error {
 | ||
| 	now := time.Now()
 | ||
| 	today := now.Truncate(24 * time.Hour)
 | ||
| 
 | ||
| 	// 插入初始API调用指标
 | ||
| 	apiMetrics := []*entities.StatisticsMetric{
 | ||
| 		{
 | ||
| 			MetricType: "api_calls",
 | ||
| 			MetricName: "total_count",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "api_calls",
 | ||
| 			MetricName: "success_count",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "api_calls",
 | ||
| 			MetricName: "failed_count",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "api_calls",
 | ||
| 			MetricName: "response_time",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 	}
 | ||
| 
 | ||
| 	// 插入初始用户指标
 | ||
| 	userMetrics := []*entities.StatisticsMetric{
 | ||
| 		{
 | ||
| 			MetricType: "users",
 | ||
| 			MetricName: "total_count",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "users",
 | ||
| 			MetricName: "certified_count",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "users",
 | ||
| 			MetricName: "active_count",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 	}
 | ||
| 
 | ||
| 	// 插入初始财务指标
 | ||
| 	financeMetrics := []*entities.StatisticsMetric{
 | ||
| 		{
 | ||
| 			MetricType: "finance",
 | ||
| 			MetricName: "total_amount",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "finance",
 | ||
| 			MetricName: "recharge_amount",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "finance",
 | ||
| 			MetricName: "deduct_amount",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 	}
 | ||
| 
 | ||
| 	// 插入初始产品指标
 | ||
| 	productMetrics := []*entities.StatisticsMetric{
 | ||
| 		{
 | ||
| 			MetricType: "products",
 | ||
| 			MetricName: "total_products",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "products",
 | ||
| 			MetricName: "active_products",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "products",
 | ||
| 			MetricName: "total_subscriptions",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "products",
 | ||
| 			MetricName: "active_subscriptions",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 	}
 | ||
| 
 | ||
| 	// 插入初始认证指标
 | ||
| 	certificationMetrics := []*entities.StatisticsMetric{
 | ||
| 		{
 | ||
| 			MetricType: "certification",
 | ||
| 			MetricName: "total_certifications",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "certification",
 | ||
| 			MetricName: "completed_certifications",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "certification",
 | ||
| 			MetricName: "pending_certifications",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 		{
 | ||
| 			MetricType: "certification",
 | ||
| 			MetricName: "failed_certifications",
 | ||
| 			Dimension:  "realtime",
 | ||
| 			Value:      0,
 | ||
| 			Date:       today,
 | ||
| 		},
 | ||
| 	}
 | ||
| 
 | ||
| 	// 批量插入所有指标
 | ||
| 	allMetrics := append(apiMetrics, userMetrics...)
 | ||
| 	allMetrics = append(allMetrics, financeMetrics...)
 | ||
| 	allMetrics = append(allMetrics, productMetrics...)
 | ||
| 	allMetrics = append(allMetrics, certificationMetrics...)
 | ||
| 
 | ||
| 	err := m.db.CreateInBatches(allMetrics, 100).Error
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("批量插入初始指标失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("初始指标数据创建完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // Rollback 回滚迁移
 | ||
| func (m *StatisticsMigration) Rollback() error {
 | ||
| 	fmt.Println("开始回滚统计模块数据迁移...")
 | ||
| 
 | ||
| 	// 删除表
 | ||
| 	err := m.db.Migrator().DropTable(&entities.StatisticsDashboard{})
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("删除统计仪表板表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	err = m.db.Migrator().DropTable(&entities.StatisticsReport{})
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("删除统计报告表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	err = m.db.Migrator().DropTable(&entities.StatisticsMetric{})
 | ||
| 	if err != nil {
 | ||
| 		return fmt.Errorf("删除统计指标表失败: %w", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	fmt.Println("统计模块数据迁移回滚完成")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 |