只在第一次启动平台导入预设数据

This commit is contained in:
2025-11-26 15:05:34 +08:00
parent ca85671a4c
commit 35eae7b3ec

View File

@@ -18,13 +18,22 @@ import (
) )
// SeederFunc 定义了处理一种特定类型预设数据文件的函数签名。 // SeederFunc 定义了处理一种特定类型预设数据文件的函数签名。
type SeederFunc func(tx *gorm.DB, jsonData []byte) error type SeederFunc func(ctx context.Context, tx *gorm.DB, jsonData []byte) error
// isTableEmpty 检查给定模型对应的数据库表是否为空。
func isTableEmpty(tx *gorm.DB, model interface{}) (bool, error) {
var count int64
if err := tx.Model(model).Count(&count).Error; err != nil {
return false, fmt.Errorf("查询表记录数失败: %w", err)
}
return count == 0, nil
}
// SeedFromPreset 是一个通用的数据播种函数。 // SeedFromPreset 是一个通用的数据播种函数。
// 它会读取指定目录下的所有 .json 文件,并根据文件内容中的 "type" 字段进行分发。 // 它会读取指定目录下的所有 .json 文件,并根据文件内容中的 "type" 字段进行分发。
// 同时,它会校验所有必需的预设类型是否都已成功加载。 // 同时,它会校验所有必需的预设类型是否都已成功加载。
func SeedFromPreset(ctx context.Context, db *gorm.DB, presetDir string) error { func SeedFromPreset(ctx context.Context, db *gorm.DB, presetDir string) error {
logger := logs.TraceLogger(ctx, ctx, "SeedFromPreset") seedCtx, logger := logs.Trace(ctx, ctx, "SeedFromPreset")
// 定义必须存在的预设数据类型及其处理顺序 // 定义必须存在的预设数据类型及其处理顺序
// 确保 "nutrient" 在 "pig_nutrient_requirements" 之前处理,因为后者依赖于前者。 // 确保 "nutrient" 在 "pig_nutrient_requirements" 之前处理,因为后者依赖于前者。
@@ -97,7 +106,7 @@ func SeedFromPreset(ctx context.Context, db *gorm.DB, presetDir string) error {
for _, jsonData := range jsonDatas { for _, jsonData := range jsonDatas {
// 获取原始文件路径用于错误报告 // 获取原始文件路径用于错误报告
originalFilePath := typeToFileMap[dataTypeStr] originalFilePath := typeToFileMap[dataTypeStr]
if err := seederFunc(tx, jsonData); err != nil { if err := seederFunc(seedCtx, tx, jsonData); err != nil {
return fmt.Errorf("处理文件 (type: %s, path: %s) 时发生错误: %w", dataTypeStr, originalFilePath, err) return fmt.Errorf("处理文件 (type: %s, path: %s) 时发生错误: %w", dataTypeStr, originalFilePath, err)
} }
} }
@@ -126,7 +135,19 @@ type rawMaterialInfo struct {
} }
// seedNutrients 先严格校验JSON源文件然后以“有则跳过”的模式播种数据。 // seedNutrients 先严格校验JSON源文件然后以“有则跳过”的模式播种数据。
func seedNutrients(tx *gorm.DB, jsonData []byte) error { func seedNutrients(ctx context.Context, tx *gorm.DB, jsonData []byte) error {
logger := logs.GetLogger(ctx)
// 检查 Nutrient 表是否为空,如果非空则跳过播种
isEmpty, err := isTableEmpty(tx, &models.Nutrient{})
if err != nil {
return fmt.Errorf("检查 Nutrient 表是否为空失败: %w", err)
}
if !isEmpty {
logger.Info("已存在原料数据, 跳过数据播种")
return nil
}
// 1. 严格校验JSON文件检查内部重复键 // 1. 严格校验JSON文件检查内部重复键
if err := validateAndParseNutrientJSON(jsonData); err != nil { if err := validateAndParseNutrientJSON(jsonData); err != nil {
return fmt.Errorf("JSON源文件校验失败: %w", err) return fmt.Errorf("JSON源文件校验失败: %w", err)
@@ -154,7 +175,6 @@ func seedNutrients(tx *gorm.DB, jsonData []byte) error {
// 3. 将通过校验的、干净的数据写入数据库 // 3. 将通过校验的、干净的数据写入数据库
dataNode := gjson.GetBytes(jsonData, "data") dataNode := gjson.GetBytes(jsonData, "data")
var err error // 用于捕获 ForEach 内部的错误
dataNode.ForEach(func(rawMaterialKey, rawMaterialValue gjson.Result) bool { dataNode.ForEach(func(rawMaterialKey, rawMaterialValue gjson.Result) bool {
rawMaterialName := rawMaterialKey.String() rawMaterialName := rawMaterialKey.String()
var rawMaterial models.RawMaterial var rawMaterial models.RawMaterial
@@ -213,7 +233,19 @@ func seedNutrients(tx *gorm.DB, jsonData []byte) error {
} }
// seedPigNutrientRequirements 先严格校验JSON源文件然后以“有则跳过”的模式播种数据。 // seedPigNutrientRequirements 先严格校验JSON源文件然后以“有则跳过”的模式播种数据。
func seedPigNutrientRequirements(tx *gorm.DB, jsonData []byte) error { func seedPigNutrientRequirements(ctx context.Context, tx *gorm.DB, jsonData []byte) error {
logger := logs.GetLogger(ctx)
// 检查 PigBreed 表是否为空,如果非空则跳过播种
isEmpty, err := isTableEmpty(tx, &models.PigBreed{})
if err != nil {
return fmt.Errorf("检查 PigBreed 表是否为空失败: %w", err)
}
if !isEmpty {
logger.Info("已存在猪种数据, 跳过数据播种")
return nil
}
// 1. 严格校验JSON文件检查内部重复键 // 1. 严格校验JSON文件检查内部重复键
if err := validateAndParsePigNutrientRequirementJSON(jsonData); err != nil { if err := validateAndParsePigNutrientRequirementJSON(jsonData); err != nil {
return fmt.Errorf("JSON源文件校验失败: %w", err) return fmt.Errorf("JSON源文件校验失败: %w", err)
@@ -271,7 +303,6 @@ func seedPigNutrientRequirements(tx *gorm.DB, jsonData []byte) error {
// 3. 将通过校验的、干净的数据写入数据库 // 3. 将通过校验的、干净的数据写入数据库
dataNode := gjson.GetBytes(jsonData, "data") dataNode := gjson.GetBytes(jsonData, "data")
var err error // 用于捕获 ForEach 内部的错误
dataNode.ForEach(func(breedKey, breedValue gjson.Result) bool { dataNode.ForEach(func(breedKey, breedValue gjson.Result) bool {
breedName := breedKey.String() breedName := breedKey.String()
var pigBreed models.PigBreed var pigBreed models.PigBreed