591 lines
16 KiB
Go
591 lines
16 KiB
Go
|
|
package migrations
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"time"
|
|||
|
|
|
|||
|
|
"gorm.io/gorm"
|
|||
|
|
|
|||
|
|
"tyapi-server/internal/domains/statistics/entities"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// StatisticsMigrationComplete 统计模块完整数据迁移
|
|||
|
|
type StatisticsMigrationComplete struct {
|
|||
|
|
db *gorm.DB
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewStatisticsMigrationComplete 创建统计模块完整数据迁移
|
|||
|
|
func NewStatisticsMigrationComplete(db *gorm.DB) *StatisticsMigrationComplete {
|
|||
|
|
return &StatisticsMigrationComplete{
|
|||
|
|
db: db,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Migrate 执行完整的数据迁移
|
|||
|
|
func (m *StatisticsMigrationComplete) Migrate() error {
|
|||
|
|
fmt.Println("开始执行统计模块完整数据迁移...")
|
|||
|
|
|
|||
|
|
// 1. 迁移表结构
|
|||
|
|
err := m.migrateTables()
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("迁移表结构失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 创建索引
|
|||
|
|
err = m.createIndexes()
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("创建索引失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 插入初始数据
|
|||
|
|
err = m.insertInitialData()
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("插入初始数据失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fmt.Println("统计模块完整数据迁移完成")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// migrateTables 迁移表结构
|
|||
|
|
func (m *StatisticsMigrationComplete) migrateTables() error {
|
|||
|
|
fmt.Println("迁移统计模块表结构...")
|
|||
|
|
|
|||
|
|
// 迁移统计指标表
|
|||
|
|
err := m.db.AutoMigrate(&entities.StatisticsMetric{})
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("迁移统计指标表失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 迁移统计报告表
|
|||
|
|
err = m.db.AutoMigrate(&entities.StatisticsReport{})
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("迁移统计报告表失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 迁移统计仪表板表
|
|||
|
|
err = m.db.AutoMigrate(&entities.StatisticsDashboard{})
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("迁移统计仪表板表失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fmt.Println("统计模块表结构迁移完成")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// createIndexes 创建索引
|
|||
|
|
func (m *StatisticsMigrationComplete) 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 *StatisticsMigrationComplete) createStatisticsMetricsIndexes() error {
|
|||
|
|
indexes := []string{
|
|||
|
|
// 复合索引:metric_type + date
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_metrics_type_date
|
|||
|
|
ON statistics_metrics (metric_type, date)`,
|
|||
|
|
|
|||
|
|
// 复合索引:metric_type + dimension + date
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_metrics_type_dimension_date
|
|||
|
|
ON statistics_metrics (metric_type, dimension, date)`,
|
|||
|
|
|
|||
|
|
// 复合索引:metric_type + metric_name + date
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_metrics_type_name_date
|
|||
|
|
ON statistics_metrics (metric_type, metric_name, date)`,
|
|||
|
|
|
|||
|
|
// 单列索引:dimension
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_metrics_dimension
|
|||
|
|
ON statistics_metrics (dimension)`,
|
|||
|
|
|
|||
|
|
// 单列索引:metric_name
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_metrics_name
|
|||
|
|
ON statistics_metrics (metric_name)`,
|
|||
|
|
|
|||
|
|
// 单列索引:value(用于范围查询)
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_metrics_value
|
|||
|
|
ON statistics_metrics (value)`,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for _, indexSQL := range indexes {
|
|||
|
|
err := m.db.Exec(indexSQL).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("创建索引失败: %w", err)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// createStatisticsReportsIndexes 创建统计报告表索引
|
|||
|
|
func (m *StatisticsMigrationComplete) createStatisticsReportsIndexes() error {
|
|||
|
|
indexes := []string{
|
|||
|
|
// 复合索引:report_type + created_at
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_reports_type_created
|
|||
|
|
ON statistics_reports (report_type, created_at)`,
|
|||
|
|
|
|||
|
|
// 复合索引:user_role + created_at
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_reports_role_created
|
|||
|
|
ON statistics_reports (user_role, created_at)`,
|
|||
|
|
|
|||
|
|
// 复合索引:status + created_at
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_reports_status_created
|
|||
|
|
ON statistics_reports (status, created_at)`,
|
|||
|
|
|
|||
|
|
// 单列索引:generated_by
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_reports_generated_by
|
|||
|
|
ON statistics_reports (generated_by)`,
|
|||
|
|
|
|||
|
|
// 单列索引:expires_at
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_reports_expires_at
|
|||
|
|
ON statistics_reports (expires_at)`,
|
|||
|
|
|
|||
|
|
// 单列索引:period
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_reports_period
|
|||
|
|
ON statistics_reports (period)`,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for _, indexSQL := range indexes {
|
|||
|
|
err := m.db.Exec(indexSQL).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("创建索引失败: %w", err)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// createStatisticsDashboardsIndexes 创建统计仪表板表索引
|
|||
|
|
func (m *StatisticsMigrationComplete) createStatisticsDashboardsIndexes() error {
|
|||
|
|
indexes := []string{
|
|||
|
|
// 复合索引:user_role + is_active
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_role_active
|
|||
|
|
ON statistics_dashboards (user_role, is_active)`,
|
|||
|
|
|
|||
|
|
// 复合索引:user_role + is_default
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_role_default
|
|||
|
|
ON statistics_dashboards (user_role, is_default)`,
|
|||
|
|
|
|||
|
|
// 单列索引:created_by
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_created_by
|
|||
|
|
ON statistics_dashboards (created_by)`,
|
|||
|
|
|
|||
|
|
// 单列索引:access_level
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_access_level
|
|||
|
|
ON statistics_dashboards (access_level)`,
|
|||
|
|
|
|||
|
|
// 单列索引:name(用于搜索)
|
|||
|
|
`CREATE INDEX IF NOT EXISTS idx_statistics_dashboards_name
|
|||
|
|
ON statistics_dashboards (name)`,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for _, indexSQL := range indexes {
|
|||
|
|
err := m.db.Exec(indexSQL).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("创建索引失败: %w", err)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// insertInitialData 插入初始数据
|
|||
|
|
func (m *StatisticsMigrationComplete) 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 *StatisticsMigrationComplete) insertDefaultDashboards() error {
|
|||
|
|
// 检查是否已存在默认仪表板
|
|||
|
|
var count int64
|
|||
|
|
err := m.db.Model(&entities.StatisticsDashboard{}).Where("is_default = ?", true).Count(&count).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("检查默认仪表板失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果已存在默认仪表板,跳过插入
|
|||
|
|
if count > 0 {
|
|||
|
|
fmt.Println("默认仪表板已存在,跳过插入")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 管理员默认仪表板
|
|||
|
|
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 *StatisticsMigrationComplete) insertInitialMetrics() error {
|
|||
|
|
now := time.Now()
|
|||
|
|
today := now.Truncate(24 * time.Hour)
|
|||
|
|
|
|||
|
|
// 检查是否已存在今日指标数据
|
|||
|
|
var count int64
|
|||
|
|
err := m.db.Model(&entities.StatisticsMetric{}).Where("date = ?", today).Count(&count).Error
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("检查指标数据失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果已存在今日指标数据,跳过插入
|
|||
|
|
if count > 0 {
|
|||
|
|
fmt.Println("今日指标数据已存在,跳过插入")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 插入初始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,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
MetricType: "api_calls",
|
|||
|
|
MetricName: "avg_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,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
MetricType: "users",
|
|||
|
|
MetricName: "new_users_today",
|
|||
|
|
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,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
MetricType: "finance",
|
|||
|
|
MetricName: "recharge_count",
|
|||
|
|
Dimension: "realtime",
|
|||
|
|
Value: 0,
|
|||
|
|
Date: today,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
MetricType: "finance",
|
|||
|
|
MetricName: "deduct_count",
|
|||
|
|
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,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
MetricType: "products",
|
|||
|
|
MetricName: "new_subscriptions_today",
|
|||
|
|
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,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
MetricType: "certification",
|
|||
|
|
MetricName: "certification_rate",
|
|||
|
|
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 *StatisticsMigrationComplete) 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
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetTableInfo 获取表信息
|
|||
|
|
func (m *StatisticsMigrationComplete) GetTableInfo() map[string]interface{} {
|
|||
|
|
info := make(map[string]interface{})
|
|||
|
|
|
|||
|
|
// 获取表统计信息
|
|||
|
|
tables := []string{"statistics_metrics", "statistics_reports", "statistics_dashboards"}
|
|||
|
|
|
|||
|
|
for _, table := range tables {
|
|||
|
|
var count int64
|
|||
|
|
m.db.Table(table).Count(&count)
|
|||
|
|
info[table] = count
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return info
|
|||
|
|
}
|