只在第一次启动平台导入预设数据
This commit is contained in:
@@ -18,13 +18,22 @@ import (
|
||||
)
|
||||
|
||||
// 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 是一个通用的数据播种函数。
|
||||
// 它会读取指定目录下的所有 .json 文件,并根据文件内容中的 "type" 字段进行分发。
|
||||
// 同时,它会校验所有必需的预设类型是否都已成功加载。
|
||||
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" 之前处理,因为后者依赖于前者。
|
||||
@@ -97,7 +106,7 @@ func SeedFromPreset(ctx context.Context, db *gorm.DB, presetDir string) error {
|
||||
for _, jsonData := range jsonDatas {
|
||||
// 获取原始文件路径用于错误报告
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -126,7 +135,19 @@ type rawMaterialInfo struct {
|
||||
}
|
||||
|
||||
// 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文件,检查内部重复键
|
||||
if err := validateAndParseNutrientJSON(jsonData); err != nil {
|
||||
return fmt.Errorf("JSON源文件校验失败: %w", err)
|
||||
@@ -154,7 +175,6 @@ func seedNutrients(tx *gorm.DB, jsonData []byte) error {
|
||||
|
||||
// 3. 将通过校验的、干净的数据写入数据库
|
||||
dataNode := gjson.GetBytes(jsonData, "data")
|
||||
var err error // 用于捕获 ForEach 内部的错误
|
||||
dataNode.ForEach(func(rawMaterialKey, rawMaterialValue gjson.Result) bool {
|
||||
rawMaterialName := rawMaterialKey.String()
|
||||
var rawMaterial models.RawMaterial
|
||||
@@ -213,7 +233,19 @@ func seedNutrients(tx *gorm.DB, jsonData []byte) error {
|
||||
}
|
||||
|
||||
// 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文件,检查内部重复键
|
||||
if err := validateAndParsePigNutrientRequirementJSON(jsonData); err != nil {
|
||||
return fmt.Errorf("JSON源文件校验失败: %w", err)
|
||||
@@ -271,7 +303,6 @@ func seedPigNutrientRequirements(tx *gorm.DB, jsonData []byte) error {
|
||||
|
||||
// 3. 将通过校验的、干净的数据写入数据库
|
||||
dataNode := gjson.GetBytes(jsonData, "data")
|
||||
var err error // 用于捕获 ForEach 内部的错误
|
||||
dataNode.ForEach(func(breedKey, breedValue gjson.Result) bool {
|
||||
breedName := breedKey.String()
|
||||
var pigBreed models.PigBreed
|
||||
|
||||
Reference in New Issue
Block a user