只在第一次启动平台导入预设数据
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user