#4 v1.0

已關閉
xuyiping 請求將 27 次代碼提交從 xuyiping/feature/event 合併至 xuyiping/develop
共有 96 個文件被更改,包括 4074 次插入2220 次删除
  1. 1 1
      go.mod
  2. 28 0
      go.sum
  3. 47 0
      http/handler/cow/cow.go
  4. 2 1
      http/handler/system/user.go
  5. 14 16
      http/handler/upload/upload.go
  6. 3 5
      http/middleware/i18n.go
  7. 2 0
      http/route/cow_api.go
  8. 5 0
      http/route/pasture_api.go
  9. 162 1
      locales/en.json
  10. 234 1
      locales/zh.json
  11. 16 16
      model/config_abortion_reasons.go
  12. 30 9
      model/config_barn_type.go
  13. 29 8
      model/config_breed_status.go
  14. 38 0
      model/config_calendar_type.go
  15. 38 0
      model/config_calving_analysis_method.go
  16. 38 0
      model/config_calving_level.go
  17. 38 0
      model/config_child_number.go
  18. 38 0
      model/config_cow_death_destination.go
  19. 29 8
      model/config_cow_kind.go
  20. 38 0
      model/config_cow_out_reason.go
  21. 38 0
      model/config_cow_purpose.go
  22. 29 8
      model/config_cow_source.go
  23. 38 8
      model/config_cow_type.go
  24. 38 0
      model/config_death_reason.go
  25. 38 0
      model/config_disease_analysis_method.go
  26. 33 10
      model/config_disease_type.go
  27. 38 0
      model/config_dystocia_reason.go
  28. 38 0
      model/config_event_category.go
  29. 38 0
      model/config_immunization_conditions.go
  30. 38 0
      model/config_indicators_category.go
  31. 39 0
      model/config_lact.go
  32. 38 0
      model/config_lact_interval_symbol.go
  33. 38 0
      model/config_mating_result.go
  34. 40 0
      model/config_multi_factor_analysis_method.go
  35. 38 0
      model/config_neck_ring_isbind.go
  36. 38 0
      model/config_neck_ring_status.go
  37. 38 0
      model/config_pregnant_check_result.go
  38. 38 0
      model/config_sale_cow_analysis_method.go
  39. 38 0
      model/config_same_time_cow_type.go
  40. 38 0
      model/config_same_time_type.go
  41. 38 0
      model/config_single_factor_analysis_method.go
  42. 29 8
      model/config_transfer_pen_reason.go
  43. 1 315
      model/cow.go
  44. 415 0
      model/cow_more.go
  45. 8 0
      model/data_warning_items.go
  46. 7 2
      model/disease.go
  47. 1 0
      model/event_cow_log.go
  48. 24 0
      model/flow.go
  49. 24 0
      model/flow_node.go
  50. 19 0
      model/flow_node_conditions.go
  51. 170 4
      model/neck_active_habit.go
  52. 34 14
      model/neck_ring_estrus_warning.go
  53. 7 3
      model/neck_ring_health_warning.go
  54. 2 0
      model/system_user.go
  55. 1 1
      module/backend/analysis_cow.go
  56. 2 3
      module/backend/analysis_more.go
  57. 4 4
      module/backend/analysis_other.go
  58. 3 3
      module/backend/calendar.go
  59. 6 6
      module/backend/calendar_more.go
  60. 227 375
      module/backend/config_data.go
  61. 113 359
      module/backend/config_data_base.go
  62. 192 313
      module/backend/config_data_breed.go
  63. 11 11
      module/backend/config_data_extend.go
  64. 20 16
      module/backend/config_data_other.go
  65. 18 292
      module/backend/cow.go
  66. 479 0
      module/backend/cow_more.go
  67. 8 33
      module/backend/dashboard.go
  68. 2 2
      module/backend/dashboard_more.go
  69. 133 104
      module/backend/enum_map.go
  70. 41 14
      module/backend/enum_options.go
  71. 70 5
      module/backend/event_base.go
  72. 1 1
      module/backend/event_base_more.go
  73. 1 1
      module/backend/event_breed.go
  74. 6 6
      module/backend/event_breed_more.go
  75. 5 5
      module/backend/event_check.go
  76. 14 10
      module/backend/event_cow_log.go
  77. 4 4
      module/backend/event_health.go
  78. 23 19
      module/backend/goods.go
  79. 4 4
      module/backend/indicators.go
  80. 4 2
      module/backend/interface.go
  81. 35 5
      module/backend/neck_ring_warning.go
  82. 34 8
      module/backend/pasture.go
  83. 14 9
      module/backend/prescription.go
  84. 6 2
      module/backend/sql.go
  85. 10 2
      module/backend/system_service.go
  86. 16 12
      module/backend/test_service.go
  87. 107 132
      module/backend/upload_file.go
  88. 12 7
      module/backend/work.go
  89. 2 1
      module/crontab/cow_neck_ring_error.go
  90. 2 1
      module/crontab/health_waning.go
  91. 5 3
      module/crontab/neck_ring_estrus.go
  92. 21 0
      module/crontab/neck_ring_health.go
  93. 4 0
      module/crontab/other.go
  94. 0 1
      util/util.go
  95. 50 0
      util/util_more_test.go
  96. 6 6
      util/util_test.go

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250813060227-ac0a14292eb8
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250911063919-b4f2c741a7be
 	gitee.com/xuyiping_admin/pkg v0.0.0-20250613101634-36c36a2d27d0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eclipse/paho.mqtt.golang v1.4.3

+ 28 - 0
go.sum

@@ -1335,6 +1335,34 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250812064516-17d87a02cad2 h1:vnNX8F32
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250812064516-17d87a02cad2/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250813060227-ac0a14292eb8 h1:MFeaHtBnwmLb9ljU90N1JpnHZPgXiHhlHGU3M3+5W7E=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250813060227-ac0a14292eb8/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250822092947-b3acec2e3359 h1:HcFY+HPtrZbxYkPnRX+ZjG6sR7szSuqh5rrnr2JXrTc=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250822092947-b3acec2e3359/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250828014705-705e31707eaf h1:ZDcAav9r7va8fKGGd4mLprqbWwVS8TrQ+ScdwGuhbGI=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250828014705-705e31707eaf/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903070416-403c999b1f63 h1:uj9/4zOKfrjk8CWNv50qto93fxfS/JcadN5tRwhBlpM=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903070416-403c999b1f63/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903071045-49078fb63665 h1:piCMbecQI3/DxDs510Zu6R0K/zSHY2kWDnze3QixBho=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903071045-49078fb63665/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903071322-6d5bbf06b445 h1:uLq0mFqhKlix/r9Fb8HHIYn3HLtVirdBAnH1oPlolg4=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903071322-6d5bbf06b445/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903073133-7d5ef92c5ff6 h1:O76VxKdx0S1eiR1WoAEJFnqNWIB7IpJdjDe+DGwTEIw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903073133-7d5ef92c5ff6/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903092259-88c4bd8e87c2 h1:Hxgj54WgHZT6e9HJXvWgkC8g+HeCRyD7WeAc2jW0Si4=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903092259-88c4bd8e87c2/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903094829-eb25a6aec6c4 h1:2381qSPRvM4cExQSZX8H8B9NwxuKiosN6PGhrTznS34=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250903094829-eb25a6aec6c4/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250905070832-566f6cc39123 h1:aiwgZ4QJ2luQu+uMgi0iyKlQ7BA3H0Jr6XGASUaD59Q=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250905070832-566f6cc39123/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250905075804-317725621249 h1:mBZ25jc4szOQ7lyhTG3M5qbQyaNnXWSbYAJkNgoJZy0=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250905075804-317725621249/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250908021214-0b0a0a501b87 h1:pi2uqAIu/ANKro8a22I8v/d4gXBfnpQCR3ZqESZee7A=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250908021214-0b0a0a501b87/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250908022339-e9d9f19403e8 h1:UgJCyRGDRarvtFJ/kjaXqR9UmgbTp2TmaJGuxQx3wLk=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250908022339-e9d9f19403e8/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250909031528-0279ad4ad300 h1:PnxMhAEkE3tEOnoj+CEhjZoauRXmUDwlndiJeKkfAZM=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250909031528-0279ad4ad300/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250911063919-b4f2c741a7be h1:xeWwbWkT8lnJhSnVVLhRDnl9csnq4vV1R2ynYckMO+k=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250911063919-b4f2c741a7be/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20250613101634-36c36a2d27d0 h1:ZCOqEAnGm6+DTAhACigzWKbwMKtleb8/7OzP2xfHG7g=
 gitee.com/xuyiping_admin/pkg v0.0.0-20250613101634-36c36a2d27d0/go.mod h1:8tF25X6pE9WkFCczlNAC0K2mrjwKvhhp02I7o0HtDxY=
 github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 47 - 0
http/handler/cow/cow.go

@@ -98,6 +98,53 @@ func BehaviorCurve(c *gin.Context) {
 	c.JSON(http.StatusOK, res)
 }
 
+func BehaviorCurveApp(c *gin.Context) {
+	var req pasturePb.CowBehaviorCurveRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.EarNumber, valid.Required),
+		valid.Field(&req.Days, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.BehaviorCurveApp(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
+func BehaviorCurveGroupComparison(c *gin.Context) {
+	var req pasturePb.CowBehaviorCurveRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := valid.ValidateStruct(&req,
+		valid.Field(&req.EarNumber, valid.Required),
+		valid.Field(&req.Days, valid.Required),
+		valid.Field(&req.CurveName, valid.Required),
+	); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.BehaviorCurveGroupComparison(c, &req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	ginutil.JSONResp(c, res)
+}
+
 func GrowthCurve(c *gin.Context) {
 	var req pasturePb.CowGrowthCurveRequest
 	if err := ginutil.BindProto(c, &req); err != nil {

+ 2 - 1
http/handler/system/user.go

@@ -30,7 +30,8 @@ func Login(c *gin.Context) {
 		return
 	}
 
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.Login(c, &req)
+	platform := c.GetHeader("Platform")
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.Login(c, platform, &req)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return

+ 14 - 16
http/handler/upload/upload.go

@@ -52,7 +52,7 @@ func Files(c *gin.Context) {
 		return
 	}
 
-	cf := GetExcelImportConfig(c.GetHeader("farmid"))
+	cf := GetExcelImportConfig()
 	// 2. 验证文件基本属性
 	if err = validateFile(file, cf); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
@@ -73,13 +73,15 @@ func Files(c *gin.Context) {
 		apierr.AbortBadRequest(c, http.StatusInternalServerError, err)
 		return
 	}
+
 	// 5. 验证表头
 	if err = validateHeaders(excelData[0], cf.RequiredHeaders); err != nil {
 		apierr.AbortBadRequest(c, http.StatusInternalServerError, err)
 		return
 	}
+
 	// 实现处理逻辑
-	if err = middleware.BackendOperation(c).OpsService.ImportExcel2(c, excelData, cf.RequiredHeaders); err != nil {
+	if err = middleware.BackendOperation(c).OpsService.ImportExcel2(c, excelData, cf.RequiredHeaders, cf.HeadOfField); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
@@ -115,6 +117,7 @@ func readExcelFile(filePath, ext string) ([][]string, error) {
 	// 获取第一个工作表
 	sheetName := f.GetSheetName(0)
 	rows, err := f.GetRows(sheetName)
+
 	if err != nil {
 		return nil, xerr.Customf("读取工作表失败: %s", err.Error())
 	}
@@ -133,20 +136,15 @@ func readXlsFile(filePath string) ([][]string, error) {
 	return nil, xerr.Custom("暂不支持.xls格式文件")
 }
 
-func GetExcelImportConfig(farmId string) *ExcelImportConfig {
-	switch farmId {
-	case "e50cd455dec93edf3d8135abbc770680":
-		return &ExcelImportConfig{
-			AllowedExtensions: []string{".xlsx", ".xls"},
-			RequiredHeaders: []string{"", "", "耳号", "牛舍名称", "性别", "出生日期", "胎次", "进场日期", "父号", "母号", "最近配种日期", "预产期", "配后天数",
-				"累计配次", "最近妊检日期", "最近产犊日期", "产后天数", "品种", "出生重量", "断奶日期", "是否禁配", "体重", "体高", "流产日期", "流产原因"},
-			HeadOfField: []string{"", "", "earNumber", "penName", "sex", "birthAt", "lact", "admissionAt", "fatherNumber", "motherNumber",
-				"lastMatingAt", "", "matingAge", "allMatingTimes", "lastPregnantCheckAt", "lastCalvingAt", "lactationAge",
-				"cowKind", "birthWeight", "weaningAt", "isForbiddenMating", "currentWeight", "currenWtHeight", "lastAbortionAt", ""},
-			MaxFileSize: 10 << 20,
-		}
-	default:
-		return nil
+func GetExcelImportConfig() *ExcelImportConfig {
+	return &ExcelImportConfig{
+		AllowedExtensions: []string{".xlsx", ".xls"},
+		RequiredHeaders: []string{"序号", "牛号", "性别", "出生日期", "栏舍名称", "牛只类型", "牛只品种", "牛只来源", "入场日期", "当前体重(KG)", "用途",
+			"胎次", "配种日期", "孕检日期", "孕检结果", "产犊日期", "流产日期", "是否禁配", "配次", "与公牛配", "脖环号", "父号", "母号", "批次号", "购买价格(¥)"},
+		HeadOfField: []string{"id", "earNumber", "sex", "birthDate", "penName", "cowType", "cowKind", "sourceKind", "admissionDate", "currentWeight",
+			"purposeKind", "lact", "matingDate", "pregnantDate", "calvingDate", "abortionDate", "isForbiddenMating", "matingTimes", "bullNumber",
+			"neckRingNumber", "fatherNumber", "motherNumber", "batchNumber", "admissionPrice"},
+		MaxFileSize: 10 << 20,
 	}
 }
 

+ 3 - 5
http/middleware/i18n.go

@@ -79,17 +79,13 @@ func loadTranslations() error {
 			continue
 		}
 
-		messageFile, err := bundle.ParseMessageFileBytes(data, filePath)
+		_, err = bundle.ParseMessageFileBytes(data, filePath)
 		if err != nil {
 			zaplog.Error("Failed to parse translation file",
 				zap.String("file", filePath),
 				zap.Error(err))
 			continue
 		}
-
-		zaplog.Info("Loaded translation",
-			zap.String("language", messageFile.Tag.String()),
-			zap.Any("messageFile", messageFile))
 		loaded = true
 	}
 
@@ -115,6 +111,8 @@ func detectLanguage(r *http.Request) string {
 	if acceptLang := r.Header.Get("Accept-Language"); acceptLang != "" {
 		if langs := strings.Split(acceptLang, ","); len(langs) > 0 {
 			return normalizeLanguage(langs[0])
+		} else {
+			return normalizeLanguage(acceptLang)
 		}
 	}
 	// 默认返回中文

+ 2 - 0
http/route/cow_api.go

@@ -17,6 +17,8 @@ func CowAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		cowRoute.POST("/list", cow.List)
 		cowRoute.POST("/event/list", cow.EventList)
 		cowRoute.POST("/behavior/curve", cow.BehaviorCurve)
+		cowRoute.POST("/behavior/curve/app", cow.BehaviorCurveApp)
+		cowRoute.POST("/behavior/curve/group/comparison", cow.BehaviorCurveGroupComparison)
 		cowRoute.POST("/growth/curve", cow.GrowthCurve)
 		cowRoute.POST("/lact/curve", cow.LactCurve)
 		cowRoute.POST("/behavior/rate", cow.BehaviorRate)

+ 5 - 0
http/route/pasture_api.go

@@ -15,14 +15,19 @@ func PastureManageAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		pastureRoute := authRouteGroup(s, "/api/v1/pasture/")
 		pastureRoute.POST("/barn/list", pasture.SearchBarnList)
 		pastureRoute.POST("/barn/createOrUpdate", pasture.CreatedOrUpdateBarn)
+
 		pastureRoute.POST("/barn/type/list", pasture.SearchBarnTypeList)
 		pastureRoute.POST("/barn/type/createOrUpdate", pasture.CreatedOrUpdateBarnType)
+
 		pastureRoute.POST("/breed/status/list", pasture.SearchBreedStatusList)
 		pastureRoute.POST("/breed/status/createOrUpdate", pasture.CreatedOrUpdateBreedStatus)
+
 		pastureRoute.POST("/cow/kind/list", pasture.SearchCowKindList)
 		pastureRoute.POST("/cow/kind/createOrUpdate", pasture.CreatedOrUpdateCowKind)
+
 		pastureRoute.POST("/cow/status/list", pasture.SearchCowStatusList)
 		pastureRoute.POST("/cow/status/createOrUpdate", pasture.CreatedOrUpdateCowStatus)
+
 		pastureRoute.POST("/cow/type/list", pasture.SearchCowTypeList)
 		pastureRoute.POST("/cow/type/createOrUpdate", pasture.CreatedOrUpdateCowType)
 		pastureRoute.POST("/transfer/pen/reason/list", pasture.SearchTransferPenReasonList)

+ 162 - 1
locales/en.json

@@ -57,6 +57,7 @@
   "validate.matingDataItemAlready": "The breeding list already has the data for this cow: {{.earNumber}}, and the breeding data has been submitted today!",
   "validate.CowNotPregnant": "Cow: {{.earNumber}}, not pregnant!",
   "validate.AbortionDateBirthDate": "Cattle: {{.earNumber}}, abortion time cannot be earlier than the cow's birth time!",
+  "validate.neckRingAppDays": "The number of days cannot exceed 60 days",
   "analysis.wrongMethod": "Incorrect statistical method!",
   "analysis.wrongLact": "Incorrect lactation interval symbol!",
   "analysis.wrongDateRange": "Start time cannot be later than end time!",
@@ -96,5 +97,165 @@
   "goods.frozenSemenNotExist": "The frozen semen information does not exist!",
   "goods.frozenSemenNotEnough": "Insufficient quantity of frozen semen!",
   "pasture.dealerNotExist": "This dealer information was not found!",
-  "pasture.dealerError": "Dealer data exception!"
+  "pasture.dealerError": "Dealer data exception!",
+  "config.saleCowAnalysisMethod0":"All",
+  "config.saleCowAnalysisMethod1":"Month",
+  "config.saleCowAnalysisMethod2":"Dealer",
+  "config.barnType0": "All",
+  "config.barnType1": "Calve Barn",
+  "config.barnType2": "Weaning Barn",
+  "config.barnType3": "Nurturing Barn",
+  "config.barnType4": "Youth Barn",
+  "config.barnType5": "Lactation Barn",
+  "config.barnType6": "Perinatal Barn",
+  "config.barnType7": "Dry Dairy Barn",
+  "config.barnType8": "Disease Barn",
+  "config.barnType9": "Out Barn",
+  "config.barnType10": "Segregate Barn",
+  "config.barnType11": "Bull Barn",
+  "config.barnType12": "Reserve Barn",
+  "config.breedStatus0": "All",
+  "config.breedStatus1": "UnBreed",
+  "config.breedStatus2": "Breeding",
+  "config.breedStatus3": "Pregnant",
+  "config.breedStatus4": "Empty",
+  "config.breedStatus5": "Calving",
+  "config.breedStatus6": "Abortion",
+  "config.breedStatus7": "NoMating",
+  "config.cowKind0": "All",
+  "config.cowKind1": "Holstein",
+  "config.cowKind2": "Jersey",
+  "config.cowKind3": "Sanhe",
+  "config.cowKind4": "Xinjiang Brown",
+  "config.cowKind5": "Yak",
+  "config.cowKind6": "Simmental",
+  "config.cowKind7": "Angus",
+  "config.cowKind8": "Charolais",
+  "config.cowKind9": "Limousin",
+  "config.cowKind10": "Hereford",
+  "config.cowKind11": "Wagyu",
+  "config.cowKind12": "Huaxi",
+  "config.cowSource0": "All",
+  "config.cowSource1": "Calving",
+  "config.cowSource2": "Transfer In",
+  "config.cowSource3": "Buy",
+  "config.sameTimeCowType0": "All",
+  "config.sameTimeCowType1": "Empty",
+  "config.sameTimeCowType2": "Breeding Calf",
+  "config.sameTimeType0": "All",
+  "config.sameTimeType1": "PG1",
+  "config.sameTimeType2": "PG2",
+  "config.sameTimeType3": "RnGH",
+  "config.sameTimeType4": "TAI",
+  "config.cowType0": "All",
+  "config.cowType1": "Lactating Calf",
+  "config.cowType2": "Weaned Calf",
+  "config.cowType3": "Youth Calf",
+  "config.cowType4": "Fattening Calf",
+  "config.cowType5": "Reserve Calf",
+  "config.cowType6": "Breeding Calf",
+  "config.cowType7": "Bull",
+  "config.immunizationConditions0": "All",
+  "config.immunizationConditions1": "Day Age",
+  "config.immunizationConditions2": "Postpartum days",
+  "config.immunizationConditions3": "Pregnancy days",
+  "config.immunizationConditions4": "Month",
+  "config.immunizationConditions5": "Admission days",
+  "config.immunizationConditions6": "After Other Vaccines",
+  "config.transferPenReason0": "All",
+  "config.transferPenReason1": "Normal Transfer",
+  "config.transferPenReason2": "Feed Transfer",
+  "config.transferPenReason3": "Dry Milk Transfer",
+  "config.transferPenReason4": "Pregnant Transfer",
+  "config.transferPenReason5": "Overantibody Transfer",
+  "config.childNumber0": "All",
+  "config.childNumber1": "One",
+  "config.childNumber2": "Two",
+  "config.childNumber3": "Three",
+  "config.childNumber4": "Four",
+  "config.calvingLevel0": "All",
+  "config.calvingLevel1": "Natural Childbirth",
+  "config.calvingLevel2": "Artificial midwifery(1-2)",
+  "config.calvingLevel3": "Artificial midwifery(3)",
+  "config.calvingLevel4": "Cesarean",
+  "config.dystociaReason0": "All",
+  "config.dystociaReason1": "Malposition",
+  "config.dystociaReason2": "Fetal Overgrowth",
+  "config.dystociaReason3": "Uterine Atony",
+  "config.dystociaReason4": "Pelvic Stenosis",
+  "config.dystociaReason5": "SubHealth",
+  "config.pregnantCheckResult0": "All",
+  "config.pregnantCheckResult1": "Pregnant",
+  "config.pregnantCheckResult2": "UnPregnant",
+  "config.cowDeathDestination0": "All",
+  "config.cowDeathDestination1": "No Pollution Treatment",
+  "config.cowDeathDestination2": "Slaughterhouse",
+  "config.cowDeathDestination10": "Other",
+  "config.abortion.reasons0": "All",
+  "config.abortion.reasons1": "Mechanical Abortion",
+  "config.abortion.reasons2": "Malnutrition Abortion",
+  "config.abortion.reasons3": "Mycotoxin Abortion",
+  "config.abortion.reasons4": "Habitual abortion",
+  "config.abortion.reasons5": "Brucellosis Abortion",
+  "config.abortion.reasons6": "Inflammatory Abortion",
+  "config.abortion.reasons7": "Heat Stress Abortion",
+  "config.abortion.reasons8": "Infectious Disease Abortion",
+  "config.abortion.reasons19": "Unknown Reason",
+  "config.abortion.reasons20": "Other Reason",
+  "config.diseaseAnalysisMethod0": "All",
+  "config.diseaseAnalysisMethod1": "Month",
+  "config.diseaseAnalysisMethod2": "Disease Category",
+  "config.diseaseAnalysisMethod3": "Disease Name",
+  "config.diseaseAnalysisMethod4": "Veterinarian",
+  "config.diseaseAnalysisMethod5": "Prescription",
+  "config.singleFactorAnalysisMethod0": "All",
+  "config.singleFactorAnalysisMethod1": "Periodic Analysis",
+  "config.singleFactorAnalysisMethod2": "Month Analysis",
+  "config.singleFactorAnalysisMethod3": "Mathing Count Analysis",
+  "config.singleFactorAnalysisMethod4": "Mathing Method",
+  "config.singleFactorAnalysisMethod5": "Breeding Company Analysis",
+  "config.singleFactorAnalysisMethod6": "Veterinary Analysis",
+  "config.singleFactorAnalysisMethod7": "Mating Interval Analysis",
+  "config.singleFactorAnalysisMethod8": "Bull Number Analysis",
+  "config.singleFactorAnalysisMethod9": "Mating Cycle Analysis",
+  "config.singleFactorAnalysisMethod10": "Week Analysis",
+  "config.singleFactorAnalysisMethod11": "Parity Analysis",
+  "config.lactIntervalSymbol0": "All",
+  "config.lactIntervalSymbol1": "Less Than",
+  "config.lactIntervalSymbol2": "Less Than AND Equal",
+  "config.lactIntervalSymbol3": "Greater Than",
+  "config.lactIntervalSymbol4": "Greater Than AND Equal",
+  "config.lactIntervalSymbol5": "Equal",
+  "config.lactIntervalSymbol6": "Not Equal",
+  "config.lactIntervalSymbol7": "Between",
+  "config.lactIntervalSymbol8": "Include",
+  "config.lactIntervalSymbol9": "Not Include",
+  "config.multiFactorAnalysisMethod0": "All",
+  "config.multiFactorAnalysisMethod1": "Month",
+  "config.multiFactorAnalysisMethod2": "Week",
+  "config.multiFactorAnalysisMethod3": "Breeder",
+  "config.multiFactorAnalysisMethod4": "Bull",
+  "config.multiFactorAnalysisMethod5": "Lact",
+  "config.multiFactorAnalysisMethod6": "Mating Times",
+  "config.multiFactorAnalysisMethod7": "Mating Type",
+  "config.neckRingIsbind0": "All",
+  "config.neckRingIsbind1": "Bind",
+  "config.neckRingIsbind2": "Not Bind",
+  "config.neckRingStatus0": "All",
+  "config.neckRingStatus1": "Normal",
+  "config.neckRingStatus2": "Abnormal",
+  "config.calendarType0": "All",
+  "config.calendarType1": "Immunity",
+  "config.calendarType2": "PG",
+  "config.calendarType3": "RnGH",
+  "config.calendarType4": "Pregnancy Test",
+  "config.calendarType5": "Work Order",
+  "config.calendarType6": "Weaning",
+  "config.calendarType7": "Disease",
+  "config.calendarType8": "Mating",
+  "config.calendarType9": "Calving",
+  "config.calendarType10": "Dry Milk",
+  "config.calvingAnalysisMethod0": "All",
+  "config.calvingAnalysisMethod1": "Month",
+  "config.calvingAnalysisMethod2": "Cow Kind"
 }

+ 234 - 1
locales/zh.json

@@ -57,6 +57,7 @@
   "validate.matingDataItemAlready": "配种清单已经有该牛只数据: {{.earNumber}},今天已经提交过配种数据!",
   "validate.CowNotPregnant": "牛只: {{.earNumber}},不是怀孕状态!",
   "validate.AbortionDateBirthDate": "牛只: {{.earNumber}},流产时间不能早于牛只出生时间!",
+  "validate.neckRingAppDays": "天数不能大于60天",
   "analysis.wrongMethod": "错误的统计方式!",
   "analysis.wrongLact": "错误的胎次区间符号!",
   "analysis.wrongDateRange": "开始时间不能大于结束时间!",
@@ -96,5 +97,237 @@
   "goods.frozenSemenNotExist": "该冻精信息不存在!",
   "goods.frozenSemenNotEnough": "冻精数量不足!",
   "pasture.dealerNotExist": "未找到该经销商信息!",
-  "pasture.dealerError": "经销商数据异常!"
+  "pasture.dealerError": "经销商数据异常!",
+  "config.saleCowAnalysisMethod0":"全部",
+  "config.saleCowAnalysisMethod1":"月份",
+  "config.saleCowAnalysisMethod2":"经销商",
+  "config.barnType0": "全部",
+  "config.barnType1": "犊牛牛舍",
+  "config.barnType2": "断奶牛舍",
+  "config.barnType3": "育成牛舍",
+  "config.barnType4": "青年牛舍",
+  "config.barnType5": "成母牛舍",
+  "config.barnType6": "围产牛舍",
+  "config.barnType7": "干奶牛舍",
+  "config.barnType8": "病牛牛舍",
+  "config.barnType9": "淘汰牛舍",
+  "config.barnType10": "隔离牛舍",
+  "config.barnType11": "公牛牛舍",
+  "config.barnType12": "后备牛舍",
+  "config.breedStatus0": "全部",
+  "config.breedStatus1": "未配",
+  "config.breedStatus2": "已配未检",
+  "config.breedStatus3": "怀孕",
+  "config.breedStatus4": "空怀",
+  "config.breedStatus5": "产犊",
+  "config.breedStatus6": "流产",
+  "config.breedStatus7": "禁配",
+  "config.cowKind0": "全部",
+  "config.cowKind1": "荷斯坦",
+  "config.cowKind2": "娟姗牛",
+  "config.cowKind3": "三河牛",
+  "config.cowKind4": "新疆褐牛",
+  "config.cowKind5": "牦牛",
+  "config.cowKind6": "西门塔尔牛",
+  "config.cowKind7": "安格斯牛",
+  "config.cowKind8": "夏洛莱牛",
+  "config.cowKind9": "利木赞牛",
+  "config.cowKind10": "海福特牛",
+  "config.cowKind11": "和牛",
+  "config.cowKind12": "华西牛",
+  "config.cowSource0": "全部",
+  "config.cowSource1": "产犊",
+  "config.cowSource2": "调入",
+  "config.cowSource3": "购买",
+  "config.sameTimeCowType0": "全部",
+  "config.sameTimeCowType1": "空怀牛",
+  "config.sameTimeCowType2": "成母牛",
+  "config.sameTimeType0": "全部",
+  "config.sameTimeType1": "PG保健",
+  "config.sameTimeType2": "PG同期",
+  "config.sameTimeType3": "RnGH",
+  "config.sameTimeType4": "配种",
+  "config.cowType0": "全部",
+  "config.cowType1": "犊牛",
+  "config.cowType2": "育成牛",
+  "config.cowType3": "青年牛",
+  "config.cowType4": "育肥牛",
+  "config.cowType5": "后备牛",
+  "config.cowType6": "成母牛",
+  "config.cowType7": "种公牛",
+  "config.immunizationConditions0": "全部",
+  "config.immunizationConditions1": "日龄",
+  "config.immunizationConditions2": "产后天数",
+  "config.immunizationConditions3": "怀孕天数",
+  "config.immunizationConditions4": "月份",
+  "config.immunizationConditions5": "入场天数",
+  "config.immunizationConditions6": "基于其他疫苗之后",
+  "config.transferPenReason0": "全部",
+  "config.transferPenReason1": "正常转群",
+  "config.transferPenReason2": "饲喂转群",
+  "config.transferPenReason3": "干奶转群",
+  "config.transferPenReason4": "怀孕转群",
+  "config.transferPenReason5": "过抗转群",
+  "config.childNumber0": "全部",
+  "config.childNumber1": "单胎",
+  "config.childNumber2": "双胎",
+  "config.childNumber3": "三胎",
+  "config.childNumber4": "四胎",
+  "config.calvingLevel0": "全部",
+  "config.calvingLevel1": "自然分娩",
+  "config.calvingLevel2": "人工助产(1-2人)",
+  "config.calvingLevel3": "人工助产(3人以上)",
+  "config.calvingLevel4": "剖腹产",
+  "config.dystociaReason0": "全部",
+  "config.dystociaReason1": "胎位不正",
+  "config.dystociaReason2": "胎儿过大",
+  "config.dystociaReason3": "子宫收缩无力",
+  "config.dystociaReason4": "盆骨狭小",
+  "config.dystociaReason5": "母牛亚健康状态",
+  "config.pregnantCheckResult0": "全部",
+  "config.pregnantCheckResult1": "有胎",
+  "config.pregnantCheckResult2": "无胎",
+  "config.cowDeathDestination10": "其他",
+  "config.cowDeathDestination1": "无公害处理",
+  "config.cowDeathDestination2": "屠宰场",
+  "config.cowDeathDestination3": "其他",
+  "config.cowOutReason0": "全部",
+  "config.cowOutReason1": "呼吸系统疾病",
+  "config.cowOutReason2": "营养代谢疾病",
+  "config.cowOutReason3": "繁殖疾病",
+  "config.cowOutReason4": "乳房疾病",
+  "config.cowOutReason5": "久配不孕",
+  "config.cowOutReason6": "多次流产",
+  "config.cowOutReason7": "久治不愈",
+  "config.cowOutReason8": "产后瘫痪",
+  "config.cowOutReason9": "乳房炎",
+  "config.cowOutReason10": "蹄病",
+  "config.cowOutReason11": "先天畸形",
+  "config.cowOutReason12": "发育不良",
+  "config.cowOutReason13": "疝气",
+  "config.cowOutReason14": "月龄过大",
+  "config.cowOutReason15": "体重过肥",
+  "config.cowOutReason16": "其他疾病",
+  "config.cowOutReason17": "弱仔",
+  "config.cowOutReason18": "恶癖牛",
+  "config.cowOutReason19": "低产",
+  "config.cowOutReason20": "生长缓慢",
+  "config.cowOutReason99": "其他",
+  "config.cowOutReason100": "未知原因",
+  "config.cowPurpose0": "全部",
+  "config.cowPurpose1": "繁殖",
+  "config.cowPurpose2": "育肥",
+  "config.indicatorsCategory0": "全部",
+  "config.indicatorsCategory1": "基本指标",
+  "config.indicatorsCategory2": "繁殖指标",
+  "config.indicatorsCategory3": "健康指标",
+  "config.indicatorsCategory4": "饲喂指标",
+  "config.indicatorsCategory5": "犊牛指标",
+  "config.indicatorsCategory6": "育肥指标",
+  "config.matingResult0": "全部",
+  "config.matingResult1": "未知",
+  "config.matingResult2": "复配",
+  "config.matingResult3": "怀孕",
+  "config.matingResult4": "空怀",
+  "config.matingResult5": "流产",
+  "config.deathReason0": "全部",
+  "config.deathReason1": "消化性疾病",
+  "config.deathReason2": "呼吸性疾病",
+  "config.deathReason3": "繁殖性疾病",
+  "config.deathReason4": "繁殖性疾病",
+  "config.deathReason5": "繁殖性疾病",
+  "config.deathReason6": "难产",
+  "config.deathReason7": "意外死亡",
+  "config.deathReason8": "热应激",
+  "config.deathReason9": "外伤",
+  "config.deathReason10": "肺炎",
+  "config.deathReason11": "腹泻",
+  "config.deathReason13": "酮病",
+  "config.deathReason14": "酸中毒",
+  "config.deathReason15": "瘤胃积食",
+  "config.deathReason16": "肠扭转",
+  "config.deathReason99": "其他",
+  "config.abortion.reasons0": "全部",
+  "config.abortion.reasons1": "机械性流产",
+  "config.abortion.reasons2": "营养不良流产",
+  "config.abortion.reasons3": "霉菌毒素流产",
+  "config.abortion.reasons4": "习惯性流产",
+  "config.abortion.reasons5": "布病流产",
+  "config.abortion.reasons6": "产道炎症性流产",
+  "config.abortion.reasons7": "热应激流产",
+  "config.abortion.reasons8": "传染病性流产",
+  "config.abortion.reasons19": "未知原因",
+  "config.abortion.reasons20": "其他原因",
+  "config.lact0": "全部",
+  "config.lact1": "1",
+  "config.lact2": "2",
+  "config.lact3": "3",
+  "config.lact4": "4",
+  "config.diseaseAnalysisMethod0": "全部",
+  "config.diseaseAnalysisMethod1": "月份",
+  "config.diseaseAnalysisMethod2": "疾病分类",
+  "config.diseaseAnalysisMethod3": "疾病名称",
+  "config.diseaseAnalysisMethod4": "兽医",
+  "config.diseaseAnalysisMethod5": "处方",
+  "config.diseaseType0": "全部",
+  "config.diseaseType1": "繁殖系统疾病",
+  "config.diseaseType2": "消化系统疾病",
+  "config.diseaseType3": "乳房疾病",
+  "config.diseaseType4": "代谢系统疾病",
+  "config.diseaseType5": "呼吸系统疾病",
+  "config.diseaseType6": "蹄病",
+  "config.diseaseType7": "皮肤系统疾病",
+  "config.diseaseType8": "传染系统疾病",
+  "config.diseaseType9": "外科系统疾病",
+  "config.diseaseType10": "其他疾病",
+  "config.singleFactorAnalysisMethod0": "全部",
+  "config.singleFactorAnalysisMethod1": "按周期分析",
+  "config.singleFactorAnalysisMethod2": "按月份分析",
+  "config.singleFactorAnalysisMethod3": "按配种次数分析",
+  "config.singleFactorAnalysisMethod4": "按配种方式分析",
+  "config.singleFactorAnalysisMethod5": "按育种公司分析",
+  "config.singleFactorAnalysisMethod6": "按兽医人员分析",
+  "config.singleFactorAnalysisMethod7": "按配种间隔分析",
+  "config.singleFactorAnalysisMethod8": "按公牛号分析",
+  "config.singleFactorAnalysisMethod9": "按配种周期分析",
+  "config.singleFactorAnalysisMethod10": "按星期分析",
+  "config.singleFactorAnalysisMethod11": "按胎次分析",
+  "config.lactIntervalSymbol0": "全部",
+  "config.lactIntervalSymbol1": "小于",
+  "config.lactIntervalSymbol2": "小于等于",
+  "config.lactIntervalSymbol3": "大于",
+  "config.lactIntervalSymbol4": "大于等于",
+  "config.lactIntervalSymbol5": "等于",
+  "config.lactIntervalSymbol6": "不等于",
+  "config.lactIntervalSymbol7": "区间",
+  "config.lactIntervalSymbol8": "包含",
+  "config.lactIntervalSymbol9": "不包含",
+  "config.multiFactorAnalysisMethod0": "全部",
+  "config.multiFactorAnalysisMethod1": "月份",
+  "config.multiFactorAnalysisMethod2": "周",
+  "config.multiFactorAnalysisMethod3": "配种员",
+  "config.multiFactorAnalysisMethod4": "公牛",
+  "config.multiFactorAnalysisMethod5": "胎次",
+  "config.multiFactorAnalysisMethod6": "配种次数",
+  "config.multiFactorAnalysisMethod7": "配种方式",
+  "config.neckRingIsbind0": "全部",
+  "config.neckRingIsbind1": "已绑定",
+  "config.neckRingIsbind2": "未绑定",
+  "config.neckRingStatus0": "全部",
+  "config.neckRingStatus1": "正常",
+  "config.neckRingStatus2": "异常",
+  "config.calendarType0": "全部",
+  "config.calendarType1": "免疫",
+  "config.calendarType2": "PG同期",
+  "config.calendarType3": "RnGH",
+  "config.calendarType4": "孕检",
+  "config.calendarType5": "工单",
+  "config.calendarType6": "断奶",
+  "config.calendarType7": "疾病",
+  "config.calendarType8": "配种",
+  "config.calendarType9": "产犊",
+  "config.calendarType10": "干奶",
+  "config.calvingAnalysisMethod0": "全部",
+  "config.calvingAnalysisMethod1": "月份",
+  "config.calvingAnalysisMethod2": "品种"
 }

+ 16 - 16
model/config_abortion_reasons.go

@@ -1,18 +1,19 @@
 package model
 
-import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
 
 type ConfigAbortionReasons struct {
-	Id        int32                          `json:"id"`
-	PastureId int64                          `json:"pastureId"`
-	Kind      pasturePb.AbortionReasons_Kind `json:"kind"`
-	Zh        string                         `json:"zh"`
-	En        string                         `json:"en"`
-	Category  pasturePb.PastureCategory_Kind `json:"category"`
-	Remarks   string                         `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind          `json:"is_show"`
-	CreatedAt int64                          `json:"created_at"`
-	UpdatedAt int64                          `json:"updated_at"`
+	Id           int32                          `json:"id"`
+	PastureId    int64                          `json:"pastureId"`
+	Kind         pasturePb.AbortionReasons_Kind `json:"kind"`
+	I18nFieldTag string                         `json:"i18nFieldTag"`
+	Remarks      string                         `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind          `json:"isShow"`
+	CreatedAt    int64                          `json:"createdAt"`
+	UpdatedAt    int64                          `json:"updatedAt"`
 }
 
 func (c *ConfigAbortionReasons) TableName() string {
@@ -21,13 +22,12 @@ func (c *ConfigAbortionReasons) TableName() string {
 
 type ConfigAbortionReasonsSlice []*ConfigAbortionReasons
 
-func (c ConfigAbortionReasonsSlice) ToPB(lang string) []*pasturePb.ConfigOptionsList {
+func (c ConfigAbortionReasonsSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
 	res := make([]*pasturePb.ConfigOptionsList, 0)
 	for _, v := range c {
-		label := v.Zh
-		if lang == "en" {
-			label = v.En
-		}
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
 		res = append(res, &pasturePb.ConfigOptionsList{
 			Value:    int32(v.Kind),
 			Label:    label,

+ 30 - 9
model/config_barn_type.go

@@ -2,29 +2,35 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigPenType struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                  `json:"id"`
+	PastureId    int64                  `json:"pastureId"`
+	Kind         pasturePb.PenType_Kind `json:"kind"`
+	I18nFieldTag string                 `json:"i18nFieldTag"`
+	Remarks      string                 `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind  `json:"isShow"`
+	CreatedAt    int64                  `json:"createdAt"`
+	UpdatedAt    int64                  `json:"updatedAt"`
 }
 
 func (c *ConfigPenType) TableName() string {
-	return "config_pen_type"
+	return "config_barn_type"
 }
 
 type ConfigBarnTypeSlice []*ConfigPenType
 
-func (c ConfigBarnTypeSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigBarnTypeSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      name,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -33,3 +39,18 @@ func (c ConfigBarnTypeSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	}
 	return res
 }
+
+func (c ConfigBarnTypeSlice) ToPB2(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 29 - 8
model/config_breed_status.go

@@ -2,15 +2,18 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigBreedStatus struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                      `json:"id"`
+	PastureId    int64                      `json:"pastureId"`
+	Kind         pasturePb.BreedStatus_Kind `json:"kind"`
+	I18nFieldTag string                     `json:"i18nFieldTag"`
+	Remarks      string                     `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind      `json:"isShow"`
+	CreatedAt    int64                      `json:"createdAt"`
+	UpdatedAt    int64                      `json:"updatedAt"`
 }
 
 func (c *ConfigBreedStatus) TableName() string {
@@ -19,12 +22,15 @@ func (c *ConfigBreedStatus) TableName() string {
 
 type ConfigBreedStatusSlice []*ConfigBreedStatus
 
-func (c ConfigBreedStatusSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigBreedStatusSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      name,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -33,3 +39,18 @@ func (c ConfigBreedStatusSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	}
 	return res
 }
+
+func (c ConfigBreedStatusSlice) ToPB2(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_calendar_type.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigCalendarType struct {
+	Id           int32                       `json:"id"`
+	PastureId    int64                       `json:"pastureId"`
+	Kind         pasturePb.CalendarType_Kind `json:"kind"`
+	I18nFieldTag string                      `json:"i18nFieldTag"`
+	Remarks      string                      `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind       `json:"is_show"`
+	CreatedAt    int64                       `json:"created_at"`
+	UpdatedAt    int64                       `json:"updated_at"`
+}
+
+func (c *ConfigCalendarType) TableName() string {
+	return "config_calendar_type"
+}
+
+type ConfigCalendarTypeSlice []*ConfigCalendarType
+
+func (c ConfigCalendarTypeSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_calving_analysis_method.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigCalvingAnalysisMethod struct {
+	Id           int32                                `json:"id"`
+	PastureId    int64                                `json:"pastureId"`
+	Kind         pasturePb.CalvingAnalysisMethod_Kind `json:"kind"`
+	I18nFieldTag string                               `json:"i18nFieldTag"`
+	Remarks      string                               `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind                `json:"is_show"`
+	CreatedAt    int64                                `json:"created_at"`
+	UpdatedAt    int64                                `json:"updated_at"`
+}
+
+func (c *ConfigCalvingAnalysisMethod) TableName() string {
+	return "config_calving_analysis_method"
+}
+
+type ConfigCalvingAnalysisMethodSlice []*ConfigCalvingAnalysisMethod
+
+func (c ConfigCalvingAnalysisMethodSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_calving_level.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigCalvingLevel struct {
+	Id           int32                       `json:"id"`
+	PastureId    int64                       `json:"pastureId"`
+	Kind         pasturePb.CalvingLevel_Kind `json:"kind"`
+	I18nFieldTag string                      `json:"i18nFieldTag"`
+	Remarks      string                      `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind       `json:"isShow"`
+	CreatedAt    int64                       `json:"createdAt"`
+	UpdatedAt    int64                       `json:"updatedAt"`
+}
+
+func (c *ConfigCalvingLevel) TableName() string {
+	return "config_calving_level"
+}
+
+type ConfigCalvingLevelSlice []*ConfigCalvingLevel
+
+func (c ConfigCalvingLevelSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_child_number.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigChildNumber struct {
+	Id           int32                      `json:"id"`
+	PastureId    int64                      `json:"pastureId"`
+	Kind         pasturePb.ChildNumber_Kind `json:"kind"`
+	I18nFieldTag string                     `json:"i18nFieldTag"`
+	Remarks      string                     `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind      `json:"isShow"`
+	CreatedAt    int64                      `json:"createdAt"`
+	UpdatedAt    int64                      `json:"updatedAt"`
+}
+
+func (c *ConfigChildNumber) TableName() string {
+	return "config_child_number"
+}
+
+type ConfigChildNumberSlice []*ConfigChildNumber
+
+func (c ConfigChildNumberSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    name,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_cow_death_destination.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigCowDeathDestination struct {
+	Id           int64                           `json:"id"`
+	PastureId    int64                           `json:"pastureId"`
+	Kind         pasturePb.DeathDestination_Kind `json:"kind"`
+	I18nFieldTag string                          `json:"i18nFieldTag"`
+	Remarks      string                          `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind           `json:"isShow"`
+	CreatedAt    int64                           `json:"createdAt"`
+	UpdatedAt    int64                           `json:"updatedAt"`
+}
+
+func (c *ConfigCowDeathDestination) TableName() string {
+	return "config_cow_death_destination"
+}
+
+type ConfigCowDeathDestinationSlice []*ConfigCowDeathDestination
+
+func (c ConfigCowDeathDestinationSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 29 - 8
model/config_cow_kind.go

@@ -2,15 +2,18 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigCowKind struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                  `json:"id"`
+	PastureId    int64                  `json:"pastureId"`
+	Kind         pasturePb.CowKind_Kind `json:"kind"`
+	I18nFieldTag string                 `json:"i18nFieldTag"`
+	Remarks      string                 `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind  `json:"isShow"`
+	CreatedAt    int64                  `json:"createdAt"`
+	UpdatedAt    int64                  `json:"updatedAt"`
 }
 
 func (c *ConfigCowKind) TableName() string {
@@ -19,12 +22,15 @@ func (c *ConfigCowKind) TableName() string {
 
 type ConfigCowKindSlice []*ConfigCowKind
 
-func (c ConfigCowKindSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigCowKindSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      label,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -33,3 +39,18 @@ func (c ConfigCowKindSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	}
 	return res
 }
+
+func (c ConfigCowKindSlice) ToPB2(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_cow_out_reason.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigCowOutReason struct {
+	Id           int64                     `json:"id"`
+	PastureId    int64                     `json:"pastureId"`
+	Kind         pasturePb.OutReasons_Kind `json:"kind"`
+	I18nFieldTag string                    `json:"i18nFieldTag"`
+	Remarks      string                    `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind     `json:"isShow"`
+	CreatedAt    int64                     `json:"createdAt"`
+	UpdatedAt    int64                     `json:"updatedAt"`
+}
+
+func (c *ConfigCowOutReason) TableName() string {
+	return "config_cow_out_reason"
+}
+
+type ConfigCowOutReasonSlice []*ConfigCowOutReason
+
+func (c ConfigCowOutReasonSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_cow_purpose.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigCowPurpose struct {
+	Id           int64                  `json:"id"`
+	PastureId    int64                  `json:"pastureId"`
+	Kind         pasturePb.Purpose_Kind `json:"kind"`
+	I18nFieldTag string                 `json:"i18nFieldTag"`
+	Remarks      string                 `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind  `json:"isShow"`
+	CreatedAt    int64                  `json:"createdAt"`
+	UpdatedAt    int64                  `json:"updatedAt"`
+}
+
+func (c *ConfigCowPurpose) TableName() string {
+	return "config_cow_purpose"
+}
+
+type ConfigCowPurposeSlice []*ConfigCowPurpose
+
+func (c ConfigCowPurposeSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 29 - 8
model/config_cow_source.go

@@ -2,15 +2,18 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigCowSource struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                    `json:"id"`
+	PastureId    int64                    `json:"pastureId"`
+	Kind         pasturePb.CowSource_Kind `json:"kind"`
+	I18nFieldTag string                   `json:"i18nFieldTag"`
+	Remarks      string                   `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind    `json:"isShow"`
+	CreatedAt    int64                    `json:"createdAt"`
+	UpdatedAt    int64                    `json:"updatedAt"`
 }
 
 func (c *ConfigCowSource) TableName() string {
@@ -19,12 +22,15 @@ func (c *ConfigCowSource) TableName() string {
 
 type ConfigCowSourceSlice []*ConfigCowSource
 
-func (c ConfigCowSourceSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigCowSourceSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      label,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -33,3 +39,18 @@ func (c ConfigCowSourceSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	}
 	return res
 }
+
+func (c ConfigCowSourceSlice) ToPB2(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 8
model/config_cow_type.go

@@ -2,15 +2,17 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigCowType struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                  `json:"id"`
+	Kind         pasturePb.CowType_Kind `json:"kind"`
+	I18nFieldTag string                 `json:"i18nFieldTag"`
+	Remarks      string                 `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind  `json:"isShow"`
+	CreatedAt    int64                  `json:"createdAt"`
+	UpdatedAt    int64                  `json:"updatedAt"`
 }
 
 func (c *ConfigCowType) TableName() string {
@@ -19,12 +21,15 @@ func (c *ConfigCowType) TableName() string {
 
 type ConfigCowTypeSlice []*ConfigCowType
 
-func (c ConfigCowTypeSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigCowTypeSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      name,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -33,3 +38,28 @@ func (c ConfigCowTypeSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	}
 	return res
 }
+
+func (c ConfigCowTypeSlice) ToPB2(userModel *UserModel, optionName string) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+
+		if optionName == "breed" && !isBreedingOrReserveCalf(v.Kind) {
+			continue
+		}
+
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}
+
+// 辅助函数:判断是否为 Breeding_Calf 或 Reserve_Calf
+func isBreedingOrReserveCalf(kind pasturePb.CowType_Kind) bool {
+	return kind == pasturePb.CowType_Breeding_Calf || kind == pasturePb.CowType_Reserve_Calf
+}

+ 38 - 0
model/config_death_reason.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigDeathReason struct {
+	Id           int64                      `json:"id"`
+	PastureId    int64                      `json:"pastureId"`
+	Kind         pasturePb.DeathReason_Kind `json:"kind"`
+	I18nFieldTag string                     `json:"i18nFieldTag"`
+	Remarks      string                     `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind      `json:"isShow"`
+	CreatedAt    int64                      `json:"createdAt"`
+	UpdatedAt    int64                      `json:"updatedAt"`
+}
+
+func (c *ConfigDeathReason) TableName() string {
+	return "config_death_reason"
+}
+
+type ConfigDeathReasonSlice []*ConfigDeathReason
+
+func (c ConfigDeathReasonSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_disease_analysis_method.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigDiseaseAnalysisMethod struct {
+	Id           int32                                `json:"id"`
+	PastureId    int64                                `json:"pastureId"`
+	Kind         pasturePb.DiseaseAnalysisMethod_Kind `json:"kind"`
+	I18nFieldTag string                               `json:"i18NFieldTag"`
+	Remarks      string                               `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind                `json:"is_show"`
+	CreatedAt    int64                                `json:"created_at"`
+	UpdatedAt    int64                                `json:"updated_at"`
+}
+
+func (c *ConfigDiseaseAnalysisMethod) TableName() string {
+	return "config_disease_analysis_method"
+}
+
+type ConfigDiseaseAnalysisMethodSlice []*ConfigDiseaseAnalysisMethod
+
+func (c ConfigDiseaseAnalysisMethodSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 33 - 10
model/config_disease_type.go

@@ -2,15 +2,18 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigDiseaseType struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                 `json:"id"`
+	PastureId    int64                 `json:"pastureId"`
+	Kind         int32                 `json:"kind"`
+	I18nFieldTag string                `json:"i18nFieldTag"`
+	Remarks      string                `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind `json:"is_show"`
+	CreatedAt    int64                 `json:"created_at"`
+	UpdatedAt    int64                 `json:"updated_at"`
 }
 
 func (c *ConfigDiseaseType) TableName() string {
@@ -19,12 +22,15 @@ func (c *ConfigDiseaseType) TableName() string {
 
 type ConfigDiseaseTypeSlice []*ConfigDiseaseType
 
-func (c ConfigDiseaseTypeSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigDiseaseTypeSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      name,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -34,7 +40,7 @@ func (c ConfigDiseaseTypeSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	return res
 }
 
-func (c ConfigDiseaseTypeSlice) ToPB2(diseaseList []*Disease) []*pasturePb.ConfigOptionsList {
+func (c ConfigDiseaseTypeSlice) ToPB2(userModel *UserModel, diseaseList []*Disease) []*pasturePb.ConfigOptionsList {
 	res := make([]*pasturePb.ConfigOptionsList, len(c))
 	for i, d := range c {
 		children := make([]*pasturePb.ConfigOptionsList, 0)
@@ -50,12 +56,29 @@ func (c ConfigDiseaseTypeSlice) ToPB2(diseaseList []*Disease) []*pasturePb.Confi
 				})
 			}
 		}
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.ConfigOptionsList{
 			Value:    int32(d.Id),
-			Label:    d.Name,
+			Label:    label,
 			Disabled: true,
 			Children: children,
 		}
 	}
 	return res
 }
+func (c ConfigDiseaseTypeSlice) ToPB3(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_dystocia_reason.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigDystociaReason struct {
+	Id           int32                         `json:"id"`
+	PastureId    int64                         `json:"pastureId"`
+	Kind         pasturePb.DystociaReason_Kind `json:"kind"`
+	I18nFieldTag string                        `json:"i18nFieldTag"`
+	Remarks      string                        `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind         `json:"isShow"`
+	CreatedAt    int64                         `json:"createdAt"`
+	UpdatedAt    int64                         `json:"updatedAt"`
+}
+
+func (c *ConfigDystociaReason) TableName() string {
+	return "config_dystocia_reason"
+}
+
+type ConfigDystociaReasonSlice []*ConfigDystociaReason
+
+func (c ConfigDystociaReasonSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_event_category.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigEventCategory struct {
+	Id           int32                        `json:"id"`
+	PastureId    int64                        `json:"pastureId"`
+	Kind         pasturePb.EventCategory_Kind `json:"kind"`
+	I18nFieldTag string                       `json:"i18nFieldTag"`
+	Remarks      string                       `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind        `json:"isShow"`
+	CreatedAt    int64                        `json:"createdAt"`
+	UpdatedAt    int64                        `json:"updatedAt"`
+}
+
+func (c *ConfigEventCategory) TableName() string {
+	return "config_event_category"
+}
+
+type ConfigEventCategorySlice []*ConfigEventCategory
+
+func (c ConfigEventCategorySlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_immunization_conditions.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigImmunizationConditions struct {
+	Id           int32                                 `json:"id"`
+	PastureId    int64                                 `json:"pastureId"`
+	Kind         pasturePb.ImmunizationConditions_Kind `json:"kind"`
+	I18nFieldTag string                                `json:"i18nFieldTag"`
+	Remarks      string                                `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind                 `json:"isShow"`
+	CreatedAt    int64                                 `json:"createdAt"`
+	UpdatedAt    int64                                 `json:"updatedAt"`
+}
+
+func (c *ConfigImmunizationConditions) TableName() string {
+	return "config_immunization_conditions"
+}
+
+type ConfigImmunizationConditionsSlice []*ConfigImmunizationConditions
+
+func (c ConfigImmunizationConditionsSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_indicators_category.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigIndicatorsCategory struct {
+	Id           int64                        `json:"id"`
+	PastureId    int64                        `json:"pastureId"`
+	Kind         pasturePb.IndicatorType_Kind `json:"kind"`
+	I18nFieldTag string                       `json:"i18nFieldTag"`
+	Remarks      string                       `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind        `json:"isShow"`
+	CreatedAt    int64                        `json:"createdAt"`
+	UpdatedAt    int64                        `json:"updatedAt"`
+}
+
+func (c *ConfigIndicatorsCategory) TableName() string {
+	return "config_indicators_category"
+}
+
+type ConfigIndicatorsCategorySlice []*ConfigIndicatorsCategory
+
+func (c ConfigIndicatorsCategorySlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 39 - 0
model/config_lact.go

@@ -0,0 +1,39 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigLact struct {
+	Id           int32                          `json:"id"`
+	PastureId    int64                          `json:"pastureId"`
+	Kind         int32                          `json:"kind"`
+	I18nFieldTag string                         `json:"i18nFieldTag"`
+	Category     pasturePb.PastureCategory_Kind `json:"category"`
+	Remarks      string                         `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind          `json:"is_show"`
+	CreatedAt    int64                          `json:"created_at"`
+	UpdatedAt    int64                          `json:"updated_at"`
+}
+
+func (c *ConfigLact) TableName() string {
+	return "config_lact"
+}
+
+type ConfigLactSlice []*ConfigLact
+
+func (c ConfigLactSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    v.Kind,
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_lact_interval_symbol.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigLactIntervalSymbol struct {
+	Id           int32                        `json:"id"`
+	PastureId    int64                        `json:"pastureId"`
+	Kind         pasturePb.CompareSymbol_Kind `json:"kind"`
+	I18nFieldTag string                       `json:"i18nFieldTag"`
+	Remarks      string                       `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind        `json:"is_show"`
+	CreatedAt    int64                        `json:"created_at"`
+	UpdatedAt    int64                        `json:"updated_at"`
+}
+
+func (c *ConfigLactIntervalSymbol) TableName() string {
+	return "config_lact_interval_symbol"
+}
+
+type ConfigLactIntervalSymbolSlice []*ConfigLactIntervalSymbol
+
+func (c ConfigLactIntervalSymbolSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_mating_result.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigMatingResult struct {
+	Id           int64                       `json:"id"`
+	PastureId    int64                       `json:"pastureId"`
+	Kind         pasturePb.MatingResult_Kind `json:"kind"`
+	I18nFieldTag string                      `json:"i18nFieldTag"`
+	Remarks      string                      `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind       `json:"isShow"`
+	CreatedAt    int64                       `json:"createdAt"`
+	UpdatedAt    int64                       `json:"updatedAt"`
+}
+
+func (c *ConfigMatingResult) TableName() string {
+	return "config_mating_result"
+}
+
+type ConfigMatingResultSlice []*ConfigMatingResult
+
+func (c ConfigMatingResultSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 40 - 0
model/config_multi_factor_analysis_method.go

@@ -0,0 +1,40 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigMultiFactorAnalysisMethod struct {
+	Id           int32                                    `json:"id"`
+	PastureId    int64                                    `json:"pastureId"`
+	Kind         pasturePb.MultiFactorAnalysisMethod_Kind `json:"kind"`
+	I18nFieldTag string                                   `json:"i18nFieldTag"`
+	Props        string                                   `json:"props"`
+	Remarks      string                                   `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind                    `json:"is_show"`
+	CreatedAt    int64                                    `json:"created_at"`
+	UpdatedAt    int64                                    `json:"updated_at"`
+}
+
+func (c *ConfigMultiFactorAnalysisMethod) TableName() string {
+	return "config_multi_factor_analysis_method"
+}
+
+type ConfigMultiFactorAnalysisMethodSlice []*ConfigMultiFactorAnalysisMethod
+
+func (c ConfigMultiFactorAnalysisMethodSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+			Props:    v.Props,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_neck_ring_isbind.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigNeckRingIsBind struct {
+	Id           int32                         `json:"id"`
+	PastureId    int64                         `json:"pastureId"`
+	Kind         pasturePb.NeckRingIsBind_Kind `json:"kind"`
+	I18nFieldTag string                        `json:"i18nFieldTag"`
+	Remarks      string                        `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind         `json:"is_show"`
+	CreatedAt    int64                         `json:"created_at"`
+	UpdatedAt    int64                         `json:"updated_at"`
+}
+
+func (c *ConfigNeckRingIsBind) TableName() string {
+	return "config_neck_ring_isbind"
+}
+
+type ConfigNeckRingIsBindSlice []*ConfigNeckRingIsBind
+
+func (c ConfigNeckRingIsBindSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_neck_ring_status.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigNeckRingStatus struct {
+	Id           int32                         `json:"id"`
+	PastureId    int64                         `json:"pastureId"`
+	Kind         pasturePb.NeckRingStatus_Kind `json:"kind"`
+	I18nFieldTag string                        `json:"i18nFieldTag"`
+	Remarks      string                        `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind         `json:"is_show"`
+	CreatedAt    int64                         `json:"created_at"`
+	UpdatedAt    int64                         `json:"updated_at"`
+}
+
+func (c *ConfigNeckRingStatus) TableName() string {
+	return "config_neck_ring_status"
+}
+
+type ConfigNeckRingStatusSlice []*ConfigNeckRingStatus
+
+func (c ConfigNeckRingStatusSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_pregnant_check_result.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigPregnantCheckResult struct {
+	Id           int32                              `json:"id"`
+	PastureId    int64                              `json:"pastureId"`
+	Kind         pasturePb.PregnantCheckResult_Kind `json:"kind"`
+	I18nFieldTag string                             `json:"i18nFieldTag"`
+	Remarks      string                             `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind              `json:"is_show"`
+	CreatedAt    int64                              `json:"created_at"`
+	UpdatedAt    int64                              `json:"updated_at"`
+}
+
+func (c *ConfigPregnantCheckResult) TableName() string {
+	return "config_pregnant_check_result"
+}
+
+type ConfigPregnantCheckResultSlice []*ConfigPregnantCheckResult
+
+func (c ConfigPregnantCheckResultSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_sale_cow_analysis_method.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigSaleCowAnalysisMethod struct {
+	Id           int32                                `json:"id"`
+	PastureId    int64                                `json:"pastureId"`
+	Kind         pasturePb.SaleCowAnalysisMethod_Kind `json:"kind"`
+	I18nFieldTag string                               `json:"i18nFieldTag"`
+	Remarks      string                               `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind                `json:"isShow"`
+	CreatedAt    int64                                `json:"createdAt"`
+	UpdatedAt    int64                                `json:"updatedAt"`
+}
+
+func (c *ConfigSaleCowAnalysisMethod) TableName() string {
+	return "config_sale_cow_analysis_method"
+}
+
+type ConfigSaleCowAnalysisMethodSlice []*ConfigSaleCowAnalysisMethod
+
+func (c ConfigSaleCowAnalysisMethodSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_same_time_cow_type.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigSameTimeCowType struct {
+	Id           int32                          `json:"id"`
+	PastureId    int64                          `json:"pastureId"`
+	Kind         pasturePb.SameTimeCowType_Kind `json:"kind"`
+	I18nFieldTag string                         `json:"i18nFieldTag"`
+	Remarks      string                         `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind          `json:"isShow"`
+	CreatedAt    int64                          `json:"createdAt"`
+	UpdatedAt    int64                          `json:"updatedAt"`
+}
+
+func (c *ConfigSameTimeCowType) TableName() string {
+	return "config_same_time_cow_type"
+}
+
+type ConfigSameTimeCowTypeSlice []*ConfigSameTimeCowType
+
+func (c ConfigSameTimeCowTypeSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    name,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_same_time_type.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigSameTimeType struct {
+	Id           int32                       `json:"id"`
+	PastureId    int64                       `json:"pastureId"`
+	Kind         pasturePb.SameTimeType_Kind `json:"kind"`
+	I18nFieldTag string                      `json:"i18nFieldTag"`
+	Remarks      string                      `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind       `json:"isShow"`
+	CreatedAt    int64                       `json:"createdAt"`
+	UpdatedAt    int64                       `json:"updatedAt"`
+}
+
+func (c *ConfigSameTimeType) TableName() string {
+	return "config_same_time_type"
+}
+
+type ConfigSameTimeTypeSlice []*ConfigSameTimeType
+
+func (c ConfigSameTimeTypeSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    name,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 38 - 0
model/config_single_factor_analysis_method.go

@@ -0,0 +1,38 @@
+package model
+
+import (
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+type ConfigSingleFactorAnalysisMethod struct {
+	Id           int32                                     `json:"id"`
+	PastureId    int64                                     `json:"pastureId"`
+	Kind         pasturePb.SingleFactorAnalysisMethod_Kind `json:"kind"`
+	I18nFieldTag string                                    `json:"i18NFieldTag"`
+	Remarks      string                                    `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind                     `json:"is_show"`
+	CreatedAt    int64                                     `json:"created_at"`
+	UpdatedAt    int64                                     `json:"updated_at"`
+}
+
+func (c *ConfigSingleFactorAnalysisMethod) TableName() string {
+	return "config_single_factor_analysis_method"
+}
+
+type ConfigSingleFactorAnalysisMethodSlice []*ConfigSingleFactorAnalysisMethod
+
+func (c ConfigSingleFactorAnalysisMethodSlice) ToPB(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 29 - 8
model/config_transfer_pen_reason.go

@@ -2,15 +2,18 @@ package model
 
 import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
 )
 
 type ConfigTransferPenReason struct {
-	Id        int64                 `json:"id"`
-	Name      string                `json:"name"`
-	Remarks   string                `json:"remarks"`
-	IsShow    pasturePb.IsShow_Kind `json:"is_show"`
-	CreatedAt int64                 `json:"created_at"`
-	UpdatedAt int64                 `json:"updated_at"`
+	Id           int64                            `json:"id"`
+	PastureId    int64                            `json:"pastureId"`
+	Kind         pasturePb.TransferPenReason_Kind `json:"kind"`
+	I18nFieldTag string                           `json:"i18nFieldTag"`
+	Remarks      string                           `json:"remarks"`
+	IsShow       pasturePb.IsShow_Kind            `json:"isShow"`
+	CreatedAt    int64                            `json:"createdAt"`
+	UpdatedAt    int64                            `json:"updatedAt"`
 }
 
 func (c *ConfigTransferPenReason) TableName() string {
@@ -19,12 +22,15 @@ func (c *ConfigTransferPenReason) TableName() string {
 
 type ConfigTransferPenReasonSlice []*ConfigTransferPenReason
 
-func (c ConfigTransferPenReasonSlice) ToPB() []*pasturePb.SearchBaseConfigList {
+func (c ConfigTransferPenReasonSlice) ToPB(userModel *UserModel) []*pasturePb.SearchBaseConfigList {
 	res := make([]*pasturePb.SearchBaseConfigList, len(c))
 	for i, d := range c {
+		name, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: d.I18nFieldTag,
+		})
 		res[i] = &pasturePb.SearchBaseConfigList{
 			Id:        int32(d.Id),
-			Name:      d.Name,
+			Name:      name,
 			Remarks:   d.Remarks,
 			IsShow:    d.IsShow,
 			CreatedAt: int32(d.CreatedAt),
@@ -33,3 +39,18 @@ func (c ConfigTransferPenReasonSlice) ToPB() []*pasturePb.SearchBaseConfigList {
 	}
 	return res
 }
+
+func (c ConfigTransferPenReasonSlice) ToPB2(userModel *UserModel) []*pasturePb.ConfigOptionsList {
+	res := make([]*pasturePb.ConfigOptionsList, 0)
+	for _, v := range c {
+		label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: v.I18nFieldTag,
+		})
+		res = append(res, &pasturePb.ConfigOptionsList{
+			Value:    int32(v.Kind),
+			Label:    label,
+			Disabled: true,
+		})
+	}
+	return res
+}

+ 1 - 315
model/cow.go

@@ -1,13 +1,13 @@
 package model
 
 import (
-	"fmt"
 	"math"
 	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
+const NeckRingDataDays = 50 // 默认获取50天的脖环数据
 type Cow struct {
 	Id                    int64                          `json:"id"`
 	PastureId             int64                          `json:"pastureId"`             // 牧场id
@@ -576,317 +576,3 @@ func (c CowSlice) ToPB(
 	}
 	return res
 }
-
-func (c CowSlice) ToPB2(penWeightSlice PenWeightSlice) []*pasturePb.CowList {
-	res := make([]*pasturePb.CowList, len(c))
-	for i, v := range c {
-		penWeight := penWeightSlice.GetPenWeight(v.PenId)
-		penAvgWeight := float32(0)
-		cowPenAvgWeightDiffValue := float32(0)
-
-		if penWeight != nil {
-			penAvgWeight = float32(penWeight.AvgWeight) / 1000
-			cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
-		}
-
-		res[i] = &pasturePb.CowList{
-			CowId:                    int32(v.Id),
-			DayAge:                   v.DayAge,
-			AverageDailyWeightGain:   float32(v.GetAverageDailyWeight()),
-			EarNumber:                v.EarNumber,
-			PenName:                  v.PenName,
-			BirthAt:                  int32(v.BirthAt),
-			BirthWeight:              float32(v.BirthWeight) / 1000,
-			CurrentWeight:            float32(v.CurrentWeight) / 1000,
-			LastWeightAt:             int32(v.LastWeightAt),
-			AdmissionAge:             v.AdmissionAge,
-			AdmissionWeight:          float32(v.AbortionAge) / 1000,
-			PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
-			PenAvgWeight:             penAvgWeight,
-			CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
-		}
-	}
-	return res
-}
-
-// NewEnterCow 入场新增牛只
-func NewEnterCow(pastureId int64, req *pasturePb.EventEnterRequest, penMap map[int32]*Pen) *Cow {
-	var isPregnant = pasturePb.IsShow_No
-	if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
-		isPregnant = pasturePb.IsShow_Ok
-	}
-
-	admissionAt := int64(0)
-	switch req.CowSource {
-	case pasturePb.CowSource_Calving:
-		admissionAt = int64(req.BirthAt)
-	case pasturePb.CowSource_Transfer_In:
-		admissionAt = int64(req.EnterAt)
-	case pasturePb.CowSource_Buy:
-		admissionAt = int64(req.EnterAt)
-	}
-
-	breedStatus := pasturePb.BreedStatus_Invalid
-	isForbiddenMating := pasturePb.IsShow_No
-	cowType := pasturePb.CowType_Invalid
-	if req.Sex == pasturePb.Genders_Female {
-
-		if req.Lact == 0 && req.MatingAt <= 0 {
-			breedStatus = pasturePb.BreedStatus_UnBreed
-			cowType = pasturePb.CowType_Reserve_Calf
-		}
-
-		if req.MatingAt > 0 && (req.PregnantCheckResult != pasturePb.PregnantCheckResult_Pregnant &&
-			req.PregnantCheckResult != pasturePb.PregnantCheckResult_UnPregnant) &&
-			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
-			breedStatus = pasturePb.BreedStatus_Breeding
-			if req.Lact == 0 {
-				cowType = pasturePb.CowType_Reserve_Calf
-			} else {
-				cowType = pasturePb.CowType_Breeding_Calf
-			}
-		}
-
-		if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant &&
-			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
-			breedStatus = pasturePb.BreedStatus_Pregnant
-			if req.Lact == 0 {
-				cowType = pasturePb.CowType_Reserve_Calf
-			} else {
-				cowType = pasturePb.CowType_Breeding_Calf
-			}
-		}
-
-		if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant &&
-			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
-			breedStatus = pasturePb.BreedStatus_Empty
-			if req.Lact == 0 {
-				cowType = pasturePb.CowType_Reserve_Calf
-			} else {
-				cowType = pasturePb.CowType_Breeding_Calf
-			}
-		}
-
-		if req.CalvingAt > 0 && req.CalvingAt >= req.MatingAt && req.CalvingAt >= req.AbortionAt {
-			breedStatus = pasturePb.BreedStatus_Calving
-			cowType = pasturePb.CowType_Breeding_Calf
-		}
-
-		if req.AbortionAt > 0 && req.AbortionAt >= req.CalvingAt && req.AbortionAt >= req.MatingAt {
-			breedStatus = pasturePb.BreedStatus_Abort
-			cowType = pasturePb.CowType_Breeding_Calf
-		}
-	}
-
-	if breedStatus == pasturePb.BreedStatus_No_Mating {
-		isForbiddenMating = pasturePb.IsShow_Ok
-	}
-
-	cow := &Cow{
-		PastureId:           pastureId,
-		Sex:                 req.Sex,
-		EarNumber:           req.EarNumber,
-		PenId:               req.PenId,
-		PenName:             penMap[req.PenId].Name,
-		Lact:                req.Lact,
-		CowType:             cowType,
-		BreedStatus:         breedStatus,
-		CowKind:             req.CowKind,
-		SourceKind:          req.CowSource,
-		FatherNumber:        req.FatherNumber,
-		MotherNumber:        req.MotherNumber,
-		AdmissionStatus:     pasturePb.AdmissionStatus_Admission,
-		HealthStatus:        pasturePb.HealthStatus_Health,
-		PurposeKind:         req.PurposeKind,
-		EleEarNumber:        req.EleEarNumber,
-		IsPregnant:          isPregnant,
-		IsForbiddenMating:   isForbiddenMating,
-		WeaningAt:           int64(req.WeaningAt),
-		BirthAt:             int64(req.BirthAt),
-		AdmissionWeight:     int64(req.Weight * 1000),
-		FirstMatingAt:       int64(req.MatingAt),
-		LastMatingAt:        int64(req.MatingAt),
-		LastPregnantCheckAt: int64(req.PregnancyCheckAt),
-		AdmissionAt:         admissionAt,
-		BirthWeight:         int64(req.Weight * 1000),
-		LastWeightAt:        int64(req.EstrusAt),
-		CurrentWeight:       int64(req.Weight * 1000),
-		LastDryMilkAt:       int64(req.DryMilkAt),
-		MatingTimes:         req.MatingTimes,
-		LastCalvingAt:       int64(req.CalvingAt),
-		LastBullNumber:      req.BullNumber,
-		LastAbortionAt:      int64(req.AbortionAt),
-		AdmissionPrice:      req.Price,
-		BatchNumber:         req.BatchNumber,
-		NeckRingNumber:      req.NeckRingNumber,
-	}
-	cow.AdmissionAge = cow.GetAdmissionAge()
-	cow.DayAge = cow.GetDayAge()
-	return cow
-}
-
-// NewCalfCow 产犊新增
-func NewCalfCow(matherInfo *Cow, calf *CalvingCalf) *Cow {
-	return &Cow{
-		PastureId:       calf.PastureId,
-		Sex:             calf.Sex,
-		EarNumber:       calf.EarNumber,
-		PenId:           calf.PenId,
-		PenName:         calf.PenName,
-		CowType:         pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
-		BreedStatus:     pasturePb.BreedStatus_UnBreed,    // 未配
-		CowKind:         matherInfo.CowKind,               // 牛只品种
-		BirthWeight:     calf.BirthWeight,
-		BirthAt:         calf.BirthAt,
-		SourceKind:      pasturePb.CowSource_Calving, // 产犊方式
-		FatherNumber:    matherInfo.LastBullNumber,
-		MotherNumber:    matherInfo.EarNumber,
-		AdmissionStatus: pasturePb.AdmissionStatus_Admission,
-		IsPregnant:      pasturePb.IsShow_No,
-		AdmissionAt:     calf.BirthAt,
-	}
-}
-
-type BarCowStruct struct {
-	Number int32                  `json:"number"`
-	TypeId pasturePb.CowType_Kind `json:"type_id"`
-}
-
-// BarCowStructSlice 首页牛群结构
-type BarCowStructSlice []*BarCowStruct
-
-func (b BarCowStructSlice) ToPB(cowTypeMap map[pasturePb.CowType_Kind]string, count int32) []*pasturePb.BarCowStruct {
-	var pb []*pasturePb.BarCowStruct
-	for _, v := range b {
-		name := fmt.Sprintf("%s", cowTypeMap[v.TypeId])
-		pb = append(pb, &pasturePb.BarCowStruct{Name: name, Value: v.Number})
-	}
-	return pb
-}
-
-type CowWeightRange struct {
-	WeightRange string `json:"weight_range"`
-	Count       int32  `json:"count"`
-}
-
-func (c CowSlice) WeightRangeToPB(penMap map[int32]*Pen) []*pasturePb.CowList {
-	res := make([]*pasturePb.CowList, len(c))
-	for i, v := range c {
-		penName := ""
-		if pen, ok := penMap[v.PenId]; ok {
-			penName = pen.Name
-		}
-		res[i] = &pasturePb.CowList{
-			CowId:                    int32(v.Id),
-			DayAge:                   v.DayAge,
-			AverageDailyWeightGain:   float32(v.GetAverageDailyWeight()),
-			PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
-			EarNumber:                v.EarNumber,
-			PenName:                  penName,
-			BirthAt:                  int32(v.BirthAt),
-			BirthWeight:              float32(v.BirthWeight) / 1000,
-			CurrentWeight:            float32(v.CurrentWeight) / 1000,
-			LastWeightAt:             int32(v.LastWeightAt),
-			AdmissionAge:             v.AdmissionAge,
-		}
-	}
-	return res
-}
-
-func (c CowSlice) LongTermInfertilityToPB(breedStatusMap map[pasturePb.BreedStatus_Kind]string) []*pasturePb.LongTermInfertility {
-	res := make([]*pasturePb.LongTermInfertility, len(c))
-	for i, v := range c {
-		breedStatusName := ""
-		if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
-			breedStatusName = breedStatus
-		}
-		lastCalvingAtFormat := ""
-		if v.LastCalvingAt > 0 {
-			lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Local().Format(LayoutDate2)
-		}
-		lastAbortionAtFormat := ""
-		if v.LastAbortionAt > 0 {
-			lastAbortionAtFormat = time.Unix(v.LastAbortionAt, 0).Local().Format(LayoutDate2)
-		}
-		lastMatingAtFormat := ""
-		if v.LastMatingAt > 0 {
-			lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Local().Format(LayoutDate2)
-		}
-		res[i] = &pasturePb.LongTermInfertility{
-			CowId:                int32(v.Id),
-			EarNumber:            v.EarNumber,
-			Lact:                 v.Lact,
-			PenId:                v.PenId,
-			CalvingAge:           v.CalvingAge,
-			PenName:              v.PenName,
-			BreedStatusName:      breedStatusName,
-			BreedStatus:          v.BreedStatus,
-			LastCalvingAtFormat:  lastCalvingAtFormat,
-			LastAbortionAtFormat: lastAbortionAtFormat,
-			LastMatingAtFormat:   lastMatingAtFormat,
-			MatingTimes:          v.MatingTimes,
-			LastBullNumber:       v.LastBullNumber,
-			AbortionTimes:        v.AbortionTimes,
-		}
-	}
-	return res
-}
-
-func (c CowSlice) CanSaleToPB(cowKindMap map[pasturePb.CowKind_Kind]string) []*pasturePb.CanSalesReport {
-	res := make([]*pasturePb.CanSalesReport, len(c))
-	for i, v := range c {
-		cowKindName, lastWeightAtFormat, admissionAtFormat := "", "", ""
-		if name, ok := cowKindMap[v.CowKind]; ok {
-			cowKindName = name
-		}
-		if v.LastWeightAt > 0 {
-			lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Local().Format(LayoutDate2)
-		}
-		if v.AdmissionAt > 0 {
-			admissionAtFormat = time.Unix(v.AdmissionAt, 0).Local().Format(LayoutDate2)
-		}
-		res[i] = &pasturePb.CanSalesReport{
-			CowId:              int32(v.Id),
-			EarNumber:          v.EarNumber,
-			BatchNumber:        v.BatchNumber,
-			CowKindName:        cowKindName,
-			PenName:            v.PenName,
-			Weight:             float32(v.CurrentWeight) / 1000,
-			AdmissionAge:       v.AdmissionAge,
-			EnterWeight:        0,
-			EnterPrice:         0,
-			LastWeightAtFormat: lastWeightAtFormat,
-			DayAvgFeedCost:     0,
-			AllFeedCost:        0,
-			AllMedicalCharge:   0,
-			OtherCost:          0,
-			ProfitAndLoss:      0,
-			AdmissionAtFormat:  admissionAtFormat,
-			DayAvgWeight:       0,
-		}
-	}
-	return res
-}
-
-// CowBehaviorCurveResponse 脖环行为数据
-type CowBehaviorCurveResponse struct {
-	Code int32                 `json:"code"`
-	Msg  string                `json:"msg"`
-	Data *CowBehaviorCurveData `json:"data"`
-}
-
-type CowBehaviorCurveData struct {
-	OriginalDateList []int32                                 `json:"originalDateList"` // 原始行为数据
-	ChangeDateList   []int32                                 `json:"changeDateList"`   // 变化数据
-	SumDateList      []int32                                 `json:"sumDateList"`      // 累计24小时数据
-	SumChewList      []int32                                 `json:"sumChewList"`      // 累计24小时咀嚼
-	DateTimeList     []string                                `json:"dateTimeList"`     // 时间数据
-	EstrusList       map[pasturePb.EstrusLevel_Kind][]string `json:"estrusList"`       // 发情预警
-	EventList        []*pasturePb.CowEvent                   `json:"eventList"`        // 事件数据
-	EventMap         map[pasturePb.EventType_Kind]string     `json:"eventMap"`         // 所有事件
-	RuminaChange     []int32                                 `json:"ruminaChange"`     // 反刍变化
-	LowActivity      int32                                   `json:"lowActivity"`      // 低活动量参数
-	MiddleActivity   int32                                   `json:"middleActivity"`   // 中活动量行数
-	IQR1             []int32                                 `json:"IQR1"`             // 1IQR
-	IQR3             []int32                                 `json:"IQR3"`             // 3IQR
-}

+ 415 - 0
model/cow_more.go

@@ -0,0 +1,415 @@
+package model
+
+import (
+	"fmt"
+	"time"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+)
+
+func (c CowSlice) ToPB2(penWeightSlice PenWeightSlice) []*pasturePb.CowList {
+	res := make([]*pasturePb.CowList, len(c))
+	for i, v := range c {
+		penWeight := penWeightSlice.GetPenWeight(v.PenId)
+		penAvgWeight := float32(0)
+		cowPenAvgWeightDiffValue := float32(0)
+
+		if penWeight != nil {
+			penAvgWeight = float32(penWeight.AvgWeight) / 1000
+			cowPenAvgWeightDiffValue = float32(v.CurrentWeight-int64(penWeight.AvgWeight)) / 1000
+		}
+
+		res[i] = &pasturePb.CowList{
+			CowId:                    int32(v.Id),
+			DayAge:                   v.DayAge,
+			AverageDailyWeightGain:   float32(v.GetAverageDailyWeight()),
+			EarNumber:                v.EarNumber,
+			PenName:                  v.PenName,
+			BirthAt:                  int32(v.BirthAt),
+			BirthWeight:              float32(v.BirthWeight) / 1000,
+			CurrentWeight:            float32(v.CurrentWeight) / 1000,
+			LastWeightAt:             int32(v.LastWeightAt),
+			AdmissionAge:             v.AdmissionAge,
+			AdmissionWeight:          float32(v.AbortionAge) / 1000,
+			PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
+			PenAvgWeight:             penAvgWeight,
+			CowPenAvgWeightDiffValue: cowPenAvgWeightDiffValue,
+		}
+	}
+	return res
+}
+
+// NewEnterCow 入场新增牛只
+func NewEnterCow(pastureId int64, req *pasturePb.EventEnterRequest, penMap map[int32]*Pen) *Cow {
+	var isPregnant = pasturePb.IsShow_No
+	if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
+		isPregnant = pasturePb.IsShow_Ok
+	}
+
+	admissionAt := int64(0)
+	switch req.CowSource {
+	case pasturePb.CowSource_Calving:
+		admissionAt = int64(req.BirthAt)
+	case pasturePb.CowSource_Transfer_In:
+		admissionAt = int64(req.EnterAt)
+	case pasturePb.CowSource_Buy:
+		admissionAt = int64(req.EnterAt)
+	}
+
+	breedStatus := pasturePb.BreedStatus_Invalid
+	isForbiddenMating := pasturePb.IsShow_No
+	cowType := pasturePb.CowType_Invalid
+	if req.Sex == pasturePb.Genders_Female {
+
+		if req.Lact == 0 && req.MatingAt <= 0 {
+			breedStatus = pasturePb.BreedStatus_UnBreed
+			cowType = pasturePb.CowType_Reserve_Calf
+		}
+
+		if req.MatingAt > 0 && (req.PregnantCheckResult != pasturePb.PregnantCheckResult_Pregnant &&
+			req.PregnantCheckResult != pasturePb.PregnantCheckResult_UnPregnant) &&
+			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Breeding
+			if req.Lact == 0 {
+				cowType = pasturePb.CowType_Reserve_Calf
+			} else {
+				cowType = pasturePb.CowType_Breeding_Calf
+			}
+		}
+
+		if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant &&
+			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Pregnant
+			if req.Lact == 0 {
+				cowType = pasturePb.CowType_Reserve_Calf
+			} else {
+				cowType = pasturePb.CowType_Breeding_Calf
+			}
+		}
+
+		if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant &&
+			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Empty
+			if req.Lact == 0 {
+				cowType = pasturePb.CowType_Reserve_Calf
+			} else {
+				cowType = pasturePb.CowType_Breeding_Calf
+			}
+		}
+
+		if req.CalvingAt > 0 && req.CalvingAt >= req.MatingAt && req.CalvingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Calving
+			cowType = pasturePb.CowType_Breeding_Calf
+		}
+
+		if req.AbortionAt > 0 && req.AbortionAt >= req.CalvingAt && req.AbortionAt >= req.MatingAt {
+			breedStatus = pasturePb.BreedStatus_Abort
+			cowType = pasturePb.CowType_Breeding_Calf
+		}
+	}
+
+	if breedStatus == pasturePb.BreedStatus_No_Mating {
+		isForbiddenMating = pasturePb.IsShow_Ok
+	}
+
+	cow := &Cow{
+		PastureId:           pastureId,
+		Sex:                 req.Sex,
+		EarNumber:           req.EarNumber,
+		PenId:               req.PenId,
+		PenName:             penMap[req.PenId].Name,
+		Lact:                req.Lact,
+		CowType:             cowType,
+		BreedStatus:         breedStatus,
+		CowKind:             req.CowKind,
+		SourceKind:          req.CowSource,
+		FatherNumber:        req.FatherNumber,
+		MotherNumber:        req.MotherNumber,
+		AdmissionStatus:     pasturePb.AdmissionStatus_Admission,
+		HealthStatus:        pasturePb.HealthStatus_Health,
+		PurposeKind:         req.PurposeKind,
+		EleEarNumber:        req.EleEarNumber,
+		IsPregnant:          isPregnant,
+		IsForbiddenMating:   isForbiddenMating,
+		WeaningAt:           int64(req.WeaningAt),
+		BirthAt:             int64(req.BirthAt),
+		AdmissionWeight:     int64(req.Weight * 1000),
+		FirstMatingAt:       int64(req.MatingAt),
+		LastMatingAt:        int64(req.MatingAt),
+		LastPregnantCheckAt: int64(req.PregnancyCheckAt),
+		AdmissionAt:         admissionAt,
+		BirthWeight:         int64(req.Weight * 1000),
+		LastWeightAt:        int64(req.EstrusAt),
+		CurrentWeight:       int64(req.Weight * 1000),
+		LastDryMilkAt:       int64(req.DryMilkAt),
+		MatingTimes:         req.MatingTimes,
+		LastCalvingAt:       int64(req.CalvingAt),
+		LastBullNumber:      req.BullNumber,
+		LastAbortionAt:      int64(req.AbortionAt),
+		AdmissionPrice:      req.Price,
+		BatchNumber:         req.BatchNumber,
+		NeckRingNumber:      req.NeckRingNumber,
+	}
+	cow.AdmissionAge = cow.GetAdmissionAge()
+	cow.DayAge = cow.GetDayAge()
+	return cow
+}
+
+// NewCalfCow 产犊新增
+func NewCalfCow(matherInfo *Cow, calf *CalvingCalf) *Cow {
+	return &Cow{
+		PastureId:       calf.PastureId,
+		Sex:             calf.Sex,
+		EarNumber:       calf.EarNumber,
+		PenId:           calf.PenId,
+		PenName:         calf.PenName,
+		CowType:         pasturePb.CowType_Lactating_Calf, // 哺乳犊牛
+		BreedStatus:     pasturePb.BreedStatus_UnBreed,    // 未配
+		CowKind:         matherInfo.CowKind,               // 牛只品种
+		BirthWeight:     calf.BirthWeight,
+		BirthAt:         calf.BirthAt,
+		SourceKind:      pasturePb.CowSource_Calving, // 产犊方式
+		FatherNumber:    matherInfo.LastBullNumber,
+		MotherNumber:    matherInfo.EarNumber,
+		AdmissionStatus: pasturePb.AdmissionStatus_Admission,
+		IsPregnant:      pasturePb.IsShow_No,
+		AdmissionAt:     calf.BirthAt,
+	}
+}
+
+// ExcelEnterCow excel导入入场新增牛只
+func ExcelEnterCow(pastureId int64, req *pasturePb.EventEnterRequest) *Cow {
+	var isPregnant = pasturePb.IsShow_No
+	if req.BreedStatus == pasturePb.BreedStatus_Pregnant {
+		isPregnant = pasturePb.IsShow_Ok
+	}
+
+	admissionAt := int64(0)
+	switch req.CowSource {
+	case pasturePb.CowSource_Calving:
+		admissionAt = int64(req.BirthAt)
+	case pasturePb.CowSource_Transfer_In:
+		admissionAt = int64(req.EnterAt)
+	case pasturePb.CowSource_Buy:
+		admissionAt = int64(req.EnterAt)
+	}
+
+	breedStatus := pasturePb.BreedStatus_Invalid
+	if req.Sex == pasturePb.Genders_Female {
+		if req.Lact == 0 && req.MatingAt <= 0 {
+			breedStatus = pasturePb.BreedStatus_UnBreed
+		}
+
+		if req.MatingAt > 0 && (req.PregnantCheckResult != pasturePb.PregnantCheckResult_Pregnant &&
+			req.PregnantCheckResult != pasturePb.PregnantCheckResult_UnPregnant) &&
+			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Breeding
+
+		}
+
+		if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant &&
+			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Pregnant
+
+		}
+
+		if req.MatingAt > 0 && req.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant &&
+			req.MatingAt >= req.CalvingAt && req.MatingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Empty
+		}
+
+		if req.CalvingAt > 0 && req.CalvingAt >= req.MatingAt && req.CalvingAt >= req.AbortionAt {
+			breedStatus = pasturePb.BreedStatus_Calving
+		}
+
+		if req.AbortionAt > 0 && req.AbortionAt >= req.CalvingAt && req.AbortionAt >= req.MatingAt {
+			breedStatus = pasturePb.BreedStatus_Abort
+		}
+	}
+
+	cow := &Cow{
+		PastureId:           pastureId,
+		Sex:                 req.Sex,
+		EarNumber:           req.EarNumber,
+		PenId:               req.PenId,
+		PenName:             req.PenName,
+		Lact:                req.Lact,
+		CowType:             req.CowType,
+		BreedStatus:         breedStatus,
+		CowKind:             req.CowKind,
+		SourceKind:          req.CowSource,
+		FatherNumber:        req.FatherNumber,
+		MotherNumber:        req.MotherNumber,
+		AdmissionStatus:     pasturePb.AdmissionStatus_Admission,
+		HealthStatus:        pasturePb.HealthStatus_Health,
+		PurposeKind:         req.PurposeKind,
+		EleEarNumber:        req.EleEarNumber,
+		IsPregnant:          isPregnant,
+		IsForbiddenMating:   req.IsForbiddenMatingKind,
+		WeaningAt:           int64(req.WeaningAt),
+		BirthAt:             int64(req.BirthAt),
+		AdmissionWeight:     int64(req.Weight * 1000),
+		FirstMatingAt:       int64(req.MatingAt),
+		LastMatingAt:        int64(req.MatingAt),
+		LastPregnantCheckAt: int64(req.PregnancyCheckAt),
+		AdmissionAt:         admissionAt,
+		BirthWeight:         int64(req.Weight * 1000),
+		LastWeightAt:        int64(req.EstrusAt),
+		CurrentWeight:       int64(req.Weight * 1000),
+		LastDryMilkAt:       int64(req.DryMilkAt),
+		MatingTimes:         req.MatingTimes,
+		LastCalvingAt:       int64(req.CalvingAt),
+		LastBullNumber:      req.BullNumber,
+		LastAbortionAt:      int64(req.AbortionAt),
+		AdmissionPrice:      req.Price,
+		BatchNumber:         req.BatchNumber,
+		NeckRingNumber:      req.NeckRingNumber,
+	}
+	cow.AdmissionAge = cow.GetAdmissionAge()
+	cow.DayAge = cow.GetDayAge()
+	return cow
+}
+
+type BarCowStruct struct {
+	Number int32                  `json:"number"`
+	TypeId pasturePb.CowType_Kind `json:"type_id"`
+}
+
+// BarCowStructSlice 首页牛群结构
+type BarCowStructSlice []*BarCowStruct
+
+func (b BarCowStructSlice) ToPB(cowTypeMap map[pasturePb.CowType_Kind]string, count int32) []*pasturePb.BarCowStruct {
+	var pb []*pasturePb.BarCowStruct
+	for _, v := range b {
+		name := fmt.Sprintf("%s", cowTypeMap[v.TypeId])
+		pb = append(pb, &pasturePb.BarCowStruct{Name: name, Value: v.Number})
+	}
+	return pb
+}
+
+type CowWeightRange struct {
+	WeightRange string `json:"weight_range"`
+	Count       int32  `json:"count"`
+}
+
+func (c CowSlice) WeightRangeToPB(penMap map[int32]*Pen) []*pasturePb.CowList {
+	res := make([]*pasturePb.CowList, len(c))
+	for i, v := range c {
+		penName := ""
+		if pen, ok := penMap[v.PenId]; ok {
+			penName = pen.Name
+		}
+		res[i] = &pasturePb.CowList{
+			CowId:                    int32(v.Id),
+			DayAge:                   v.DayAge,
+			AverageDailyWeightGain:   float32(v.GetAverageDailyWeight()),
+			PreviousStageDailyWeight: float32(v.GetPreviousStageDailyWeight()),
+			EarNumber:                v.EarNumber,
+			PenName:                  penName,
+			BirthAt:                  int32(v.BirthAt),
+			BirthWeight:              float32(v.BirthWeight) / 1000,
+			CurrentWeight:            float32(v.CurrentWeight) / 1000,
+			LastWeightAt:             int32(v.LastWeightAt),
+			AdmissionAge:             v.AdmissionAge,
+		}
+	}
+	return res
+}
+
+func (c CowSlice) LongTermInfertilityToPB(breedStatusMap map[pasturePb.BreedStatus_Kind]string) []*pasturePb.LongTermInfertility {
+	res := make([]*pasturePb.LongTermInfertility, len(c))
+	for i, v := range c {
+		breedStatusName := ""
+		if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
+			breedStatusName = breedStatus
+		}
+		lastCalvingAtFormat := ""
+		if v.LastCalvingAt > 0 {
+			lastCalvingAtFormat = time.Unix(v.LastCalvingAt, 0).Local().Format(LayoutDate2)
+		}
+		lastAbortionAtFormat := ""
+		if v.LastAbortionAt > 0 {
+			lastAbortionAtFormat = time.Unix(v.LastAbortionAt, 0).Local().Format(LayoutDate2)
+		}
+		lastMatingAtFormat := ""
+		if v.LastMatingAt > 0 {
+			lastMatingAtFormat = time.Unix(v.LastMatingAt, 0).Local().Format(LayoutDate2)
+		}
+		res[i] = &pasturePb.LongTermInfertility{
+			CowId:                int32(v.Id),
+			EarNumber:            v.EarNumber,
+			Lact:                 v.Lact,
+			PenId:                v.PenId,
+			CalvingAge:           v.CalvingAge,
+			PenName:              v.PenName,
+			BreedStatusName:      breedStatusName,
+			BreedStatus:          v.BreedStatus,
+			LastCalvingAtFormat:  lastCalvingAtFormat,
+			LastAbortionAtFormat: lastAbortionAtFormat,
+			LastMatingAtFormat:   lastMatingAtFormat,
+			MatingTimes:          v.MatingTimes,
+			LastBullNumber:       v.LastBullNumber,
+			AbortionTimes:        v.AbortionTimes,
+		}
+	}
+	return res
+}
+
+func (c CowSlice) CanSaleToPB(cowKindMap map[pasturePb.CowKind_Kind]string) []*pasturePb.CanSalesReport {
+	res := make([]*pasturePb.CanSalesReport, len(c))
+	for i, v := range c {
+		cowKindName, lastWeightAtFormat, admissionAtFormat := "", "", ""
+		if name, ok := cowKindMap[v.CowKind]; ok {
+			cowKindName = name
+		}
+		if v.LastWeightAt > 0 {
+			lastWeightAtFormat = time.Unix(v.LastWeightAt, 0).Local().Format(LayoutDate2)
+		}
+		if v.AdmissionAt > 0 {
+			admissionAtFormat = time.Unix(v.AdmissionAt, 0).Local().Format(LayoutDate2)
+		}
+		res[i] = &pasturePb.CanSalesReport{
+			CowId:              int32(v.Id),
+			EarNumber:          v.EarNumber,
+			BatchNumber:        v.BatchNumber,
+			CowKindName:        cowKindName,
+			PenName:            v.PenName,
+			Weight:             float32(v.CurrentWeight) / 1000,
+			AdmissionAge:       v.AdmissionAge,
+			EnterWeight:        0,
+			EnterPrice:         0,
+			LastWeightAtFormat: lastWeightAtFormat,
+			DayAvgFeedCost:     0,
+			AllFeedCost:        0,
+			AllMedicalCharge:   0,
+			OtherCost:          0,
+			ProfitAndLoss:      0,
+			AdmissionAtFormat:  admissionAtFormat,
+			DayAvgWeight:       0,
+		}
+	}
+	return res
+}
+
+// CowBehaviorCurveResponse 脖环行为数据PC端
+type CowBehaviorCurveResponse struct {
+	Code int32                 `json:"code"`
+	Msg  string                `json:"msg"`
+	Data *CowBehaviorCurveData `json:"data"`
+}
+
+type CowBehaviorCurveData struct {
+	OriginalDateList []int32                                 `json:"originalDateList"` // 原始行为数据
+	ChangeDateList   []int32                                 `json:"changeDateList"`   // 变化数据
+	SumDateList      []int32                                 `json:"sumDateList"`      // 累计24小时数据
+	SumChewList      []int32                                 `json:"sumChewList"`      // 累计24小时咀嚼
+	DateTimeList     []string                                `json:"dateTimeList"`     // 时间数据
+	EstrusList       map[pasturePb.EstrusLevel_Kind][]string `json:"estrusList"`       // 发情预警
+	EventList        []*pasturePb.CowEvent                   `json:"eventList"`        // 事件数据
+	EventMap         map[pasturePb.EventType_Kind]string     `json:"eventMap"`         // 所有事件
+	RuminaChange     []int32                                 `json:"ruminaChange"`     // 反刍变化
+	LowActivity      int32                                   `json:"lowActivity"`      // 低活动量参数
+	MiddleActivity   int32                                   `json:"middleActivity"`   // 中活动量行数
+	IQR1             []int32                                 `json:"IQR1"`             // IQR1
+	IQR3             []int32                                 `json:"IQR3"`             // IQR3
+}

+ 8 - 0
model/data_warning_items.go

@@ -79,6 +79,14 @@ var DefaultDataWarningItemsMap = map[pasturePb.DataWarningType_Kind][]*pasturePb
 			Value:     "150",
 			IsShow:    pasturePb.IsShow_Ok,
 		},
+		{
+			GroupId:   1,
+			FieldName: "purpose_kind",
+			FieldDesc: "用途",
+			Operator:  "=",
+			Value:     fmt.Sprintf("%d", pasturePb.Purpose_Fatten),
+			IsShow:    pasturePb.IsShow_Ok,
+		},
 	},
 	pasturePb.DataWarningType_Over_Age_UnPregnant_Young: {
 		{

+ 7 - 2
model/disease.go

@@ -3,6 +3,8 @@ package model
 import (
 	"strings"
 
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
@@ -26,7 +28,7 @@ func (d *Disease) TableName() string {
 
 type DiseaseSlice []*Disease
 
-func (d DiseaseSlice) ToPB(user []*SystemUser, diseaseTypeList []*ConfigDiseaseType) []*pasturePb.SearchDiseaseList {
+func (d DiseaseSlice) ToPB(userModel *UserModel, user []*SystemUser, diseaseTypeList []*ConfigDiseaseType) []*pasturePb.SearchDiseaseList {
 	res := make([]*pasturePb.SearchDiseaseList, len(d))
 	for i, dl := range d {
 		operationName, diseaseTypeName := "", ""
@@ -39,7 +41,10 @@ func (d DiseaseSlice) ToPB(user []*SystemUser, diseaseTypeList []*ConfigDiseaseT
 
 		for _, dt := range diseaseTypeList {
 			if dt.Id == int64(dl.DiseaseType) {
-				diseaseTypeName = dt.Name
+				label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+					MessageID: dt.I18nFieldTag,
+				})
+				diseaseTypeName = label
 				break
 			}
 		}

+ 1 - 0
model/event_cow_log.go

@@ -106,6 +106,7 @@ func (e EventCowLogSlice) ToPB(eventCategoryMap map[pasturePb.EventCategory_Kind
 			EventAtFormat:     eventAtFormat,
 			EventCategoryKind: v.EventCategoryKind,
 			EventCategoryName: eventCategoryMap[v.EventCategoryKind],
+			EventTypeKind:     v.EventType,
 		}
 	}
 	return res

+ 24 - 0
model/flow.go

@@ -0,0 +1,24 @@
+package model
+
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
+type Flow struct {
+	Id            int64                 `json:"id"`
+	PastureId     int64                 `json:"pastureId"`
+	Name          string                `json:"name"`
+	Category      int32                 `json:"category"`
+	Type          int32                 `json:"type"`
+	EndConditions string                `json:"endConditions"`
+	Remarks       string                `json:"remarks"`
+	IsShow        pasturePb.IsShow_Kind `json:"isShow"`
+	IsDelete      pasturePb.IsShow_Kind `json:"isDelete"`
+	ExtendData    string                `json:"extendData"`
+	OperationId   int64                 `json:"operationId"`
+	OperationName string                `json:"operationName"`
+	CreatedAt     int64                 `json:"createdAt"`
+	UpdatedAt     int64                 `json:"updatedAt"`
+}
+
+func (f *Flow) TableName() string {
+	return "flow"
+}

+ 24 - 0
model/flow_node.go

@@ -0,0 +1,24 @@
+package model
+
+import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
+type FlowNode struct {
+	Id             int64                 `json:"id"`
+	PastureId      int64                 `json:"pastureId"`
+	FlowId         int64                 `json:"flowId"`
+	NodeId         int64                 `json:"nodeId"`
+	NodeName       string                `json:"nodeName"`
+	IsCut          pasturePb.IsShow_Kind `json:"isCut"`
+	IsMust         pasturePb.IsShow_Kind `json:"isMust"`
+	IsStop         pasturePb.IsShow_Kind `json:"isStop"`
+	IsFirstNode    pasturePb.IsShow_Kind `json:"isFirstNode"`
+	CompletionDays int32                 `json:"completionDays"`
+	CutConditions  string                `json:"cutConditions"`
+	ExtendData     string                `json:"extendData"`
+	CreatedAt      int64                 `json:"createdAt"`
+	UpdatedAt      int64                 `json:"updatedAt"`
+}
+
+func (f *FlowNode) TableName() string {
+	return "flow_node"
+}

+ 19 - 0
model/flow_node_conditions.go

@@ -0,0 +1,19 @@
+package model
+
+type FlowNodeConditions struct {
+	Id                    int64  `json:"id"`
+	PastureId             int64  `json:"pastureId"`
+	FlowId                int64  `json:"flowId"`
+	NodeId                int64  `json:"nodeId"`
+	NextNodeId            int64  `json:"nextNodeId"`
+	BaseTimeName          string `json:"baseTimeName"`
+	BaseTimeField         string `json:"baseTimeField"`
+	ExecTime              string `json:"execTime"`
+	CirculationConditions string `json:"circulationConditions"`
+	CreatedAt             int64  `json:"createdAt"`
+	UpdatedAt             int64  `json:"updatedAt"`
+}
+
+func (f *FlowNodeConditions) TableName() string {
+	return "flow_node_conditions"
+}

+ 170 - 4
model/neck_active_habit.go

@@ -82,10 +82,6 @@ func (n *NeckActiveHabit) UnShardTableName() string {
 	return "neck_active_habit"
 }
 
-/*func (n *NeckActiveHabit) TableName() string {
-	return fmt.Sprintf("%s_%06d", n.UnShardTableName(), n.PastureId)
-}*/
-
 func (n *NeckActiveHabit) TableName() string {
 	return "neck_active_habit"
 }
@@ -303,6 +299,176 @@ func (n NeckActiveHabitSlice) ToPB2(dataBetween []string, groupNeckActiveHabitLi
 	return data
 }
 
+func (n NeckActiveHabitSlice) ToPBApp() *pasturePb.CowNeckRingAppData {
+	res := &pasturePb.CowNeckRingAppData{
+		DateTime: make([]string, 0),
+		Activity: &pasturePb.ActivityData{
+			ChangeActivity: make([]int32, 0),
+			ChangeRumina:   make([]int32, 0),
+		},
+		Rumina: &pasturePb.RuminaData{
+			ChangeRumina: make([]int32, 0),
+			SumRumina:    make([]int32, 0),
+		},
+		Chew: &pasturePb.ChewData{
+			ChangeChew: make([]int32, 0),
+			SumChew:    make([]int32, 0),
+		},
+		Intake: &pasturePb.SumData{
+			SumData: make([]int32, 0),
+		},
+		Inactive: &pasturePb.SumData{
+			SumData: make([]int32, 0),
+		},
+		Immobility: &pasturePb.SumData{
+			SumData: make([]int32, 0),
+		},
+		Gasp: &pasturePb.SumData{
+			SumData: make([]int32, 0),
+		},
+		EstrusList: make([]string, 0),
+		EventList:  make([]*pasturePb.EventDetail, 0),
+	}
+	initFrameId := int32(0)
+	dateFrameMap := make(map[string][]int32)
+
+	for _, v := range n {
+		if dateFrameMap[v.HeatDate] == nil {
+			initFrameId = 0
+			dateFrameMap[v.HeatDate] = make([]int32, 0)
+		}
+		// 补全结尾不够的数据
+		if initFrameId == 0 && len(res.DateTime) > 0 {
+			lastDateTime := res.DateTime[len(res.DateTime)-1]
+			lastDatePare := strings.Split(lastDateTime, " ")
+			if len(lastDatePare) == 2 {
+				lastDay := lastDatePare[0]
+				lastHourStr := lastDatePare[1]
+				lastHour, _ := strconv.ParseInt(lastHourStr, 10, 64)
+				maxHour := util.ExpectedFrameIDs[len(util.ExpectedFrameIDs)-1]
+				xframeId := int32(lastHour-1)/2 + 1
+				if xframeId != maxHour {
+					for ; xframeId <= maxHour; xframeId++ {
+						res.DateTime = append(res.DateTime, fmt.Sprintf("%s %02d", lastDay, util.ExpectedFrameIDs[xframeId]*2+1))
+						res.Activity.ChangeActivity = append(res.Activity.ChangeActivity, 0)
+						res.Activity.ChangeRumina = append(res.Activity.ChangeRumina, 0)
+						res.Rumina.ChangeRumina = append(res.Rumina.ChangeRumina, 0)
+						res.Rumina.SumRumina = append(res.Rumina.SumRumina, 0)
+						res.Intake.SumData = append(res.Intake.SumData, 0)
+						res.Inactive.SumData = append(res.Inactive.SumData, 0)
+						res.Chew.ChangeChew = append(res.Chew.ChangeChew, 0)
+						res.Chew.SumChew = append(res.Chew.SumChew, 0)
+						res.Immobility.SumData = append(res.Immobility.SumData, 0)
+					}
+				}
+			}
+		}
+		expectedFrameId := util.ExpectedFrameIDs[initFrameId]
+		if expectedFrameId != v.Frameid {
+			maxFrameId := int32(math.Abs(float64(expectedFrameId - v.Frameid)))
+			for ; expectedFrameId < maxFrameId; expectedFrameId++ {
+				res.DateTime = append(res.DateTime, fmt.Sprintf("%s %02d", v.HeatDate, util.ExpectedFrameIDs[expectedFrameId]*2+1))
+				res.Activity.ChangeActivity = append(res.Activity.ChangeActivity, 0)
+				res.Activity.ChangeRumina = append(res.Activity.ChangeRumina, 0)
+				res.Rumina.ChangeRumina = append(res.Rumina.ChangeRumina, 0)
+				res.Rumina.SumRumina = append(res.Rumina.SumRumina, 0)
+				res.Intake.SumData = append(res.Intake.SumData, 0)
+				res.Inactive.SumData = append(res.Inactive.SumData, 0)
+				res.Chew.ChangeChew = append(res.Chew.ChangeChew, 0)
+				res.Chew.SumChew = append(res.Chew.SumChew, 0)
+				res.Immobility.SumData = append(res.Immobility.SumData, 0)
+			}
+			initFrameId = expectedFrameId
+		}
+
+		// 格式化为到小时的字符串
+		parsedTime, _ := util.TimeParseLocal(LayoutTime, v.ActiveTime)
+		hourStr := parsedTime.Format(LayoutHour)
+		res.DateTime = append(res.DateTime, hourStr)
+
+		// 活动量
+		changeDateList := v.ChangeFilter * v.FilterCorrect / 100
+		if changeDateList == DefaultChangeFilter {
+			changeDateList = 0
+		}
+		res.Activity.ChangeActivity = append(res.Activity.ChangeActivity, changeDateList)
+		res.Activity.ChangeRumina = append(res.Activity.ChangeRumina, v.RuminaFilter)
+		// 反刍
+		res.Rumina.ChangeRumina = append(res.Rumina.ChangeRumina, v.RuminaFilter)
+		res.Rumina.SumRumina = append(res.Rumina.SumRumina, v.SumRumina)
+		// 咀嚼
+		res.Chew.ChangeChew = append(res.Chew.ChangeChew, v.ChewFilter)
+		res.Chew.SumChew = append(res.Chew.SumChew, v.SumRumina+v.SumIntake)
+		// 采食
+		res.Intake.SumData = append(res.Intake.SumData, v.SumRumina+v.SumIntake)
+		// 休息
+		res.Inactive.SumData = append(res.Inactive.SumData, v.SumInactive)
+		// 静止
+		res.Immobility.SumData = append(res.Immobility.SumData, 60*24-v.SumActive)
+		initFrameId++
+	}
+	return res
+}
+
+func (n NeckActiveHabitSlice) ToOriginalDataList(curveName string) (originalDataList []int32, datetimeList []string) {
+	initFrameId := int32(0)
+	dateFrameMap := make(map[string][]int32)
+	for _, v := range n {
+		if dateFrameMap[v.HeatDate] == nil {
+			initFrameId = 0
+			dateFrameMap[v.HeatDate] = make([]int32, 0)
+		}
+		// 补全结尾不够的数据
+		if initFrameId == 0 && len(datetimeList) > 0 {
+			lastDateTime := datetimeList[len(datetimeList)-1]
+			lastDatePare := strings.Split(lastDateTime, " ")
+			if len(lastDatePare) == 2 {
+				lastDay := lastDatePare[0]
+				lastHourStr := lastDatePare[1]
+				lastHour, _ := strconv.ParseInt(lastHourStr, 10, 64)
+				maxHour := util.ExpectedFrameIDs[len(util.ExpectedFrameIDs)-1]
+				xframeId := int32(lastHour-1)/2 + 1
+				if xframeId != maxHour {
+					for ; xframeId <= maxHour; xframeId++ {
+						datetimeList = append(datetimeList, fmt.Sprintf("%s %02d", lastDay, util.ExpectedFrameIDs[xframeId]*2+1))
+						originalDataList = append(originalDataList, 0)
+					}
+				}
+			}
+		}
+		expectedFrameId := util.ExpectedFrameIDs[initFrameId]
+		if expectedFrameId != v.Frameid {
+			maxFrameId := int32(math.Abs(float64(expectedFrameId - v.Frameid)))
+			for ; expectedFrameId < maxFrameId; expectedFrameId++ {
+				datetimeList = append(datetimeList, fmt.Sprintf("%s %02d", v.HeatDate, util.ExpectedFrameIDs[expectedFrameId]*2+1))
+				originalDataList = append(originalDataList, 0)
+			}
+			initFrameId = expectedFrameId
+		}
+
+		// 格式化为到小时的字符串
+		parsedTime, _ := util.TimeParseLocal(LayoutTime, v.ActiveTime)
+		hourStr := parsedTime.Format(LayoutHour)
+		datetimeList = append(datetimeList, hourStr)
+		switch curveName {
+		case "active": // 活动量
+			originalDataList = append(originalDataList, v.High)
+		case "rumina": // 反刍
+			originalDataList = append(originalDataList, v.Rumina)
+		case "intake": // 采食
+			originalDataList = append(originalDataList, v.Intake)
+		case "inactive": // 休息
+			originalDataList = append(originalDataList, v.Inactive)
+		case "chew": // 咀嚼
+			originalDataList = append(originalDataList, v.Rumina+v.Intake)
+		case "immobility": // 静止
+			originalDataList = append(originalDataList, 120-v.Active)
+		}
+		initFrameId++
+	}
+	return
+}
+
 type MaxHabitIdModel struct {
 	Id int64 `json:"id"`
 }

+ 34 - 14
model/neck_ring_estrus_warning.go

@@ -63,7 +63,6 @@ func (n *NeckRingEstrusWarning) CalculatePzHour(lact int32) time.Time {
 	} else {
 		pzHour = firstTime.Add(16 * time.Hour) // v.firsttime + INTERVAL 16 HOUR
 	}
-
 	// 胎次调整
 	if lact >= 3 {
 		pzHour = pzHour.Add(-1 * time.Hour) // 减去 1 小时
@@ -73,7 +72,12 @@ func (n *NeckRingEstrusWarning) CalculatePzHour(lact int32) time.Time {
 
 type NeckRingEstrusWarningSlice []*NeckRingEstrusWarning
 
-func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[int64]string, matingWindowPeriodKind pasturePb.MatingWindowPeriod_Kind) []*pasturePb.EstrusItem {
+func (n NeckRingEstrusWarningSlice) ToPB(
+	cowMap map[int64]*Cow,
+	eventLogMap map[int64]string,
+	matingWindowPeriodKind pasturePb.MatingWindowPeriod_Kind,
+	matingWindowPeriodKindList []pasturePb.MatingWindowPeriod_Kind,
+) []*pasturePb.EstrusItem {
 	res := make([]*pasturePb.EstrusItem, 0)
 	nowTime := time.Now().Local()
 	for _, v := range n {
@@ -98,21 +102,24 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 		optimumMatingStartTime := pzHour.Add(-4 * time.Hour)
 		optimumMatingEndTime := pzHour.Add(4 * time.Hour)
 
-		switch matingWindowPeriodKind {
-		case pasturePb.MatingWindowPeriod_Front:
-			if !nowTime.Before(optimumMatingStartTime) {
-				continue
-			}
-		case pasturePb.MatingWindowPeriod_Middle:
-			if !(nowTime.After(optimumMatingStartTime) && nowTime.Before(optimumMatingEndTime)) {
-				continue
-			}
-		case pasturePb.MatingWindowPeriod_Behind:
-			if !nowTime.After(optimumMatingEndTime) {
-				continue
+		found := false
+		if len(matingWindowPeriodKindList) > 0 && len(matingWindowPeriodKindList) <= 2 {
+			for _, periodKind := range matingWindowPeriodKindList {
+				if isIPeriod(periodKind, nowTime, optimumMatingStartTime, optimumMatingEndTime) {
+					found = true
+					break
+				}
 			}
 		}
 
+		if matingWindowPeriodKind > pasturePb.MatingWindowPeriod_Invalid {
+			found = isIPeriod(matingWindowPeriodKind, nowTime, optimumMatingStartTime, optimumMatingEndTime)
+		}
+
+		if found {
+			continue
+		}
+
 		firstTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.FirstTime)
 		afterAlarmTimeForHours := int32(nowTime.Sub(firstTimeParseLocal).Hours())
 		postPeakTimeForHours := int32(0)
@@ -147,6 +154,19 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 	return res
 }
 
+func isIPeriod(periodKind pasturePb.MatingWindowPeriod_Kind, nowTime, optimumMatingStartTime, optimumMatingEndTime time.Time) bool {
+	switch periodKind {
+	case pasturePb.MatingWindowPeriod_Front:
+		return !nowTime.Before(optimumMatingStartTime)
+	case pasturePb.MatingWindowPeriod_Middle:
+		return !(nowTime.After(optimumMatingStartTime) && nowTime.Before(optimumMatingEndTime))
+	case pasturePb.MatingWindowPeriod_Behind:
+		return !(nowTime.After(optimumMatingEndTime))
+	default:
+		return false
+	}
+}
+
 const (
 	Nb1    = 12
 	Nb2    = 8

+ 7 - 3
model/neck_ring_health_warning.go

@@ -63,6 +63,7 @@ func (n NeckRingHealthWarningSlice) ToPB(
 	cowMap map[int64]*Cow,
 	eventLogMap map[int64]string,
 	healthStatusMap map[pasturePb.HealthStatus_Kind]string,
+	dayData map[int64]*NeckActiveHabit,
 ) []*pasturePb.HealthWarningItem {
 	res := make([]*pasturePb.HealthWarningItem, len(n))
 	for i, v := range n {
@@ -70,13 +71,10 @@ func (n NeckRingHealthWarningSlice) ToPB(
 		if ln, ok := warningHealthLevelMap[v.Level]; ok {
 			levelName = ln
 		}
-
 		data := &pasturePb.HealthWarningItem{
 			Id:                     int32(v.Id),
 			CowId:                  int32(v.CowId),
 			EarNumber:              v.EarNumber,
-			PenId:                  0,
-			PenName:                "",
 			Score:                  v.Score,
 			HeatDate:               v.HeatDate,
 			MinHigh:                v.MinHigh,
@@ -88,6 +86,12 @@ func (n NeckRingHealthWarningSlice) ToPB(
 			Level:                  v.Level,
 			LevelName:              levelName,
 			ChangeChewTime:         v.ChewSum - v.BeforeThreeSumChew,
+			ChangeHigh:             float32(dayData[v.CowId].ChangeHigh),
+			ChangeRumina:           float32(dayData[v.CowId].ChangeRumina),
+			DayRumina:              float32(dayData[v.CowId].Rumina),
+			DayIntake:              float32(dayData[v.CowId].Intake),
+			DayInactive:            float32(dayData[v.CowId].Inactive),
+			DayImmobility:          float32(dayData[v.CowId].Active),
 		}
 
 		if cow, ok := cowMap[v.CowId]; ok {

+ 2 - 0
model/system_user.go

@@ -11,6 +11,8 @@ import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
+const AdminUser = "kpt_user"
+
 type SystemUser struct {
 	Id              int64                  `json:"id"`
 	Name            string                 `json:"name"`

+ 1 - 1
module/backend/analysis_cow.go

@@ -208,7 +208,7 @@ func (s *StoreEntry) TwentyOnePregnantDetail(ctx context.Context, req *pasturePb
 		return nil, xerr.WithStack(err)
 	}
 
-	cowTypeMap := s.CowTypeMap()
+	cowTypeMap := s.CowTypeMap(userModel)
 	switch req.Type {
 	case pasturePb.TwentyOnePregnantType_ShouldBreed:
 		shouldBreedCowList, _ := s.TwentyOnePregnantShouldBreedList(pastureId, req.CowType, stopBreedingDay, middleDay)

+ 2 - 3
module/backend/analysis_more.go

@@ -72,7 +72,7 @@ func (s *StoreEntry) PenBehaviorDaily(ctx context.Context, req *pasturePb.BarnMo
 			headers = append(headers, v.Name)
 		}
 	} else {
-		behaviorEnumList := s.Behavior("")
+		behaviorEnumList := s.Behavior(userModel, "")
 		for _, v := range behaviorEnumList {
 			headers = append(headers, v.Label)
 		}
@@ -126,7 +126,6 @@ func (s *StoreEntry) CowBehaviorDistribution(ctx context.Context, req *pasturePb
 		Select("b.*").
 		Where("a.pasture_id = ?", userModel.AppPasture.Id).
 		Where("a.neck_ring_number != ?", "").
-		Where("a.sex = ?", pasturePb.Genders_Female).
 		Where("b.heat_date = ? ", req.DateTime).
 		Where("b.day_high > ?", 0)
 
@@ -175,7 +174,7 @@ func (s *StoreEntry) CowBehaviorDistribution(ctx context.Context, req *pasturePb
 		},
 	}
 
-	breedStatus := s.BreedStatusEnumList()
+	breedStatus := s.BreedStatusEnumList(userModel, "")
 	for _, v := range breedStatus {
 		if v.Value == int32(pasturePb.BreedStatus_Abort) ||
 			v.Value == int32(pasturePb.BreedStatus_Calving) ||

+ 4 - 4
module/backend/analysis_other.go

@@ -48,8 +48,8 @@ func (s *StoreEntry) PregnancyReport(ctx context.Context, req *pasturePb.Pregnan
 		return nil, xerr.WithStack(err)
 	}
 
-	pregnantCheckResultMap := s.PregnantCheckResultMap()
-	pregnantCheckMethodMap := s.PregnantCheckMethodMap()
+	pregnantCheckResultMap := s.PregnantCheckResultMap(userModel)
+	pregnantCheckMethodMap := s.PregnantCheckMethodMap(userModel)
 	return &pasturePb.PregnancyReportResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -148,7 +148,7 @@ func (s *StoreEntry) CalvingReport(ctx context.Context, req *pasturePb.CalvingRe
 		}
 	}
 
-	cowKindMap := s.CowKindMap()
+	cowKindMap := s.CowKindMap(userModel)
 	for _, v := range eventCalving1 {
 		if req.AnalysisMethod == pasturePb.CalvingAnalysisMethod_CowKind {
 			v.StatisticMethod = cowKindMap[v.CowKind]
@@ -254,7 +254,7 @@ func (s *StoreEntry) DiseaseCureReport(ctx context.Context, req *pasturePb.Disea
 		case pasturePb.DiseaseAnalysisMethod_Months:
 			v.StatisticMethod = v.Months
 		case pasturePb.DiseaseAnalysisMethod_Disease_Category:
-			diseaseTypeMap := s.DiseaseTypeMap()
+			diseaseTypeMap := s.DiseaseTypeMap(userModel)
 			v.StatisticMethod = diseaseTypeMap[v.DiseaseType]
 		case pasturePb.DiseaseAnalysisMethod_Disease:
 			v.StatisticMethod = v.DiseaseName

+ 3 - 3
module/backend/calendar.go

@@ -168,7 +168,7 @@ func (s *StoreEntry) CalendarToDoList(ctx context.Context, req *pasturePb.Calend
 		dMap[v.CalendarTypeKind] = v.Count
 	}
 
-	list, total := Paginate(calendarToDoList, req, pagination)
+	list, total := s.Paginate(userModel, calendarToDoList, req, pagination)
 	return &pasturePb.CalendarToDoResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -358,8 +358,8 @@ func (s *StoreEntry) SameTimeCowList(ctx context.Context, req *pasturePb.ItemsRe
 		Find(&sameTimeBodyList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
-	breedStatusMap := s.CowBreedStatusMap()
-	sameTimeTypeMap := s.SameTimeTypeMap()
+	breedStatusMap := s.CowBreedStatusMap(userModel)
+	sameTimeTypeMap := s.SameTimeTypeMap(userModel)
 	return &pasturePb.SameTimeItemResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",

+ 6 - 6
module/backend/calendar_more.go

@@ -47,7 +47,7 @@ func (s *StoreEntry) CalvingCowList(ctx context.Context, req *pasturePb.ItemsReq
 		return nil, xerr.WithStack(err)
 	}
 
-	breedStatusMap := s.CowBreedStatusMap()
+	breedStatusMap := s.CowBreedStatusMap(userModel)
 	for _, v := range calvingItems {
 		breedStatusName := ""
 		if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
@@ -121,7 +121,7 @@ func (s *StoreEntry) DryMilkCowList(ctx context.Context, req *pasturePb.ItemsReq
 		return nil, xerr.WithStack(err)
 	}
 
-	breedStatusMap := s.CowBreedStatusMap()
+	breedStatusMap := s.CowBreedStatusMap(userModel)
 	for _, v := range dryMilkItems {
 		breedStatusName := ""
 		if breedStatus, ok := breedStatusMap[v.BreedStatus]; ok {
@@ -187,7 +187,7 @@ func (s *StoreEntry) TreatmentCowList(ctx context.Context, req *pasturePb.ItemsR
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.EventCowDiseaseData{
-			List:       model.EventCowDiseaseSlice(diseaseItems).ToPB(s.HealthStatusMap()),
+			List:       model.EventCowDiseaseSlice(diseaseItems).ToPB(s.HealthStatusMap(userModel)),
 			Total:      int32(count),
 			PageSize:   pagination.PageSize,
 			Page:       pagination.Page,
@@ -211,11 +211,11 @@ func (s *StoreEntry) WorkOrderCowList(ctx context.Context, req *pasturePb.ItemsR
 }
 
 // Paginate 函数用于对切片进行分页
-func Paginate(slice []*pasturePb.CalendarToDoList, req *pasturePb.CalendarToDoRequest, pagination *pasturePb.PaginationModel) ([]*pasturePb.CalendarToDoList, int32) {
+func (s *StoreEntry) Paginate(userModel *model.UserModel, slice []*pasturePb.CalendarToDoList, req *pasturePb.CalendarToDoRequest, pagination *pasturePb.PaginationModel) ([]*pasturePb.CalendarToDoList, int32) {
 	newSlice := make([]*pasturePb.CalendarToDoList, 0)
 
 	if req.CalendarType > 0 {
-		calendarTypeName := CalendarTypeMap()[req.CalendarType]
+		calendarTypeName := s.CalendarTypeMap(userModel)[req.CalendarType]
 		if len(calendarTypeName) > 0 {
 			re := regexp.MustCompile(`[a-zA-Z]`) // 使用正则表达式替换匹配的字母为空字符串
 			calendarTypeName = re.ReplaceAllString(calendarTypeName, "")
@@ -307,7 +307,7 @@ func (s *StoreEntry) TaskDetail(ctx context.Context, req *pasturePb.CalendarToDo
 		return nil, xerr.WithStack(err)
 	}
 
-	calendarToDoList, _ = Paginate(calendarToDoList, req, pagination)
+	calendarToDoList, _ = s.Paginate(userModel, calendarToDoList, req, pagination)
 	taskItemsList := make([]*pasturePb.TaskItems, 0)
 	for _, v := range calendarToDoList {
 		if v.CalendarType == pasturePb.CalendarType_Disease {

+ 227 - 375
module/backend/config_data.go

@@ -3,24 +3,47 @@ package backend
 import (
 	"kpt-pasture/model"
 
+	"go.uber.org/zap"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
 )
 
-func (s *StoreEntry) BarnTypeEnumList(excludeTypes []pasturePb.PenType_Kind) []*pasturePb.ConfigOptionsList {
-	allBarnTypes := s.BarnTypeMap()
+func (s *StoreEntry) BarnTypeEnumList(userModel *model.UserModel, excludeTypes []pasturePb.PenType_Kind, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigPenType, 0)
+	pref := s.DB.Model(new(model.ConfigPenType)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.PenType_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.PenType_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("BarnTypeEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	allBarnTypes := model.ConfigBarnTypeSlice(dataList).ToPB2(userModel)
 	barnTypeList := make([]*pasturePb.ConfigOptionsList, 0)
-	for v1 := range allBarnTypes {
+	if len(excludeTypes) == 0 || excludeTypes == nil {
+		return allBarnTypes
+	}
+
+	for _, v1 := range allBarnTypes {
 		var info bool
 		for _, v2 := range excludeTypes {
-			if v1 == v2 {
+			if v1.Value == int32(v2) {
 				info = true
 				break
 			}
 		}
 		if !info {
 			barnTypeList = append(barnTypeList, &pasturePb.ConfigOptionsList{
-				Value:    int32(v1),
-				Label:    allBarnTypes[v1],
+				Value:    v1.Value,
+				Label:    v1.Label,
 				Disabled: true,
 			})
 		}
@@ -28,417 +51,246 @@ func (s *StoreEntry) BarnTypeEnumList(excludeTypes []pasturePb.PenType_Kind) []*
 	return barnTypeList
 }
 
-func (s *StoreEntry) BreedStatusEnumList() []*pasturePb.ConfigOptionsList {
-	breedStatusList := make([]*pasturePb.ConfigOptionsList, 0)
-	breedStatusList = append(breedStatusList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_UnBreed),
-		Label:    "未配",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_Breeding),
-		Label:    "已配未检",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_Pregnant),
-		Label:    "怀孕",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_Empty),
-		Label:    "空怀",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_Calving),
-		Label:    "产犊",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_Abort),
-		Label:    "流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.BreedStatus_No_Mating),
-		Label:    "禁配",
-		Disabled: true,
-	})
-	return breedStatusList
+func (s *StoreEntry) BreedStatusEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigBreedStatus, 0)
+	pref := s.DB.Model(new(model.ConfigBreedStatus)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.BreedStatus_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.BreedStatus_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("ConfigBreedStatus", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigBreedStatusSlice(dataList).ToPB2(userModel)
 }
 
-func (s *StoreEntry) CowKindEnumList() []*pasturePb.ConfigOptionsList {
-	cowKindList := make([]*pasturePb.ConfigOptionsList, 0)
-	cowKindList = append(cowKindList,
-		&pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_JSN),
-			Label:    "娟姗牛",
-			Disabled: true,
-		},
-		&pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_XMTEN),
-			Label:    "西门塔尔牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_AGSN),
-			Label:    "安格斯牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_XNLN),
-			Label:    "夏洛莱牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_LMZN),
-			Label:    "利木赞牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_HFTN),
-			Label:    "海福特牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_HN),
-			Label:    "和牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowKind_HX),
-			Label:    "华西牛",
-			Disabled: true,
-		})
-	return cowKindList
+func (s *StoreEntry) CowKindEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCowKind, 0)
+	pref := s.DB.Model(new(model.ConfigCowKind)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.CowKind_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CowKind_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CowKindEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigCowKindSlice(dataList).ToPB2(userModel)
 }
 
-func (s *StoreEntry) CowSourceEnumList() []*pasturePb.ConfigOptionsList {
-	cowSourceList := make([]*pasturePb.ConfigOptionsList, 0)
-	cowSourceList = append(cowSourceList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowSource_Calving),
-		Label:    "产犊",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowSource_Transfer_In),
-		Label:    "调入",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowSource_Buy),
-		Label:    "购买",
-		Disabled: true,
-	})
-	return cowSourceList
+func (s *StoreEntry) CowSourceEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCowSource, 0)
+	pref := s.DB.Model(new(model.ConfigCowSource)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.CowSource_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CowSource_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CowKindEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigCowSourceSlice(dataList).ToPB2(userModel)
 }
 
-func (s *StoreEntry) CowTypeEnumList(optionName, isAll string) []*pasturePb.ConfigOptionsList {
-	cowTypeList := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) CowTypeEnumList(userModel *model.UserModel, optionName, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCowType, 0)
+	pref := s.DB.Model(new(model.ConfigCowType)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowType_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.CowType_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CowType_Invalid)
 	}
-	if optionName == "breed" {
-		cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowType_Reserve_Calf),
-			Label:    "后备牛",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CowType_Breeding_Calf),
-			Label:    "成母牛",
-			Disabled: true,
-		})
-		return cowTypeList
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CowKindEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
 
-	cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Lactating_Calf),
-		Label:    "哺乳犊牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Weaned_Calf),
-		Label:    "育成牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Youth_Calf),
-		Label:    "青年牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Fattening_Calf),
-		Label:    "育肥牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Reserve_Calf),
-		Label:    "后备牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Breeding_Calf),
-		Label:    "成母牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Breeding_Bull),
-		Label:    "种公牛",
-		Disabled: true,
-	})
-	return cowTypeList
+	return model.ConfigCowTypeSlice(dataList).ToPB2(userModel, optionName)
 }
 
-func (s *StoreEntry) SameTimeCowTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	cowTypeList := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) SameTimeCowTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigSameTimeCowType, 0)
+	pref := s.DB.Model(new(model.ConfigSameTimeCowType)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.SameTimeCowType_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.SameTimeCowType_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.SameTimeCowType_Invalid)
 	}
-	cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeCowType_Empty),
-		Label:    "空怀牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeCowType_Breeding_Calf),
-		Label:    "成母牛",
-		Disabled: true,
-	})
-	return cowTypeList
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("ConfigSameTimeCowType", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigSameTimeCowTypeSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) SameTimeTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	cowTypeList := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) SameTimeTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigSameTimeType, 0)
+	pref := s.DB.Model(new(model.ConfigSameTimeType)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.SameTimeType_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.SameTimeType_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.SameTimeType_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("SameTimeTypeEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeType_PGBJ),
-		Label:    "PG保健",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeType_PGTQ),
-		Label:    "PG同期",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeType_RnGH),
-		Label:    "RnGH",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SameTimeType_TAI),
-		Label:    "TAI输精",
-		Disabled: true,
-	})
-	return cowTypeList
+
+	return model.ConfigSameTimeTypeSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) ImmunizationCowTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	cowTypeList := make([]*pasturePb.ConfigOptionsList, 0)
-	cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Lactating_Calf),
-		Label:    "犊牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Weaned_Calf),
-		Label:    "育成牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Youth_Calf),
-		Label:    "青年牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Fattening_Calf),
-		Label:    "育肥牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Reserve_Calf),
-		Label:    "后备牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Breeding_Calf),
-		Label:    "成母牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CowType_Breeding_Bull),
-		Label:    "种公牛",
-		Disabled: true,
-	})
-	return cowTypeList
+func (s *StoreEntry) ImmunizationCowTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	return s.CowTypeEnumList(userModel, "", isAll)
 }
 
-func (s *StoreEntry) ImmunizationConditionsEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	cowTypeList := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) ImmunizationConditionsEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigImmunizationConditions, 0)
+	pref := s.DB.Model(new(model.ConfigImmunizationConditions)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.ImmunizationConditions_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.ImmunizationConditions_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.ImmunizationConditions_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("ImmunizationConditionsEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	cowTypeList = append(cowTypeList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.ImmunizationConditions_Days_Age),
-		Label:    "日龄",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.ImmunizationConditions_Days_After_Delivery),
-		Label:    "产后天数",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.ImmunizationConditions_Days_Of_Pregnancy),
-		Label:    "怀孕天数",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.ImmunizationConditions_Admission_Days),
-		Label:    "入场天数",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.ImmunizationConditions_Other_Vaccine_After),
-		Label:    "基于其他疫苗之后",
-		Disabled: true,
-	})
-	return cowTypeList
+
+	return model.ConfigImmunizationConditionsSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) TransferPenEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	transferPenList := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) TransferPenEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigTransferPenReason, 0)
+	pref := s.DB.Model(new(model.ConfigTransferPenReason)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		transferPenList = append(transferPenList, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.TransferPenReason_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.TransferPenReason_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.TransferPenReason_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("TransferPenEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	transferPenList = append(transferPenList, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.TransferPenReason_Normal),
-		Label:    "正常转群",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.TransferPenReason_Feed),
-		Label:    "饲喂转群",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.TransferPenReason_Dry_Milk),
-		Label:    "干奶转群",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.TransferPenReason_Pregnant),
-		Label:    "怀孕转群",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.TransferPenReason_Overantibody),
-		Label:    "过抗转群",
-		Disabled: true,
-	})
-	return transferPenList
+
+	return model.ConfigTransferPenReasonSlice(dataList).ToPB2(userModel)
 }
 
-func (s *StoreEntry) ChildNumberEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) ChildNumberEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigChildNumber, 0)
+	pref := s.DB.Model(new(model.ConfigChildNumber)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.ChildNumber_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.ChildNumber_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.ChildNumber_Invalid)
 	}
-	configOptions = append(configOptions,
-		&pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.ChildNumber_One),
-			Label:    "单胎",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.ChildNumber_Two),
-			Label:    "双胎",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.ChildNumber_Three),
-			Label:    "三胎",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.ChildNumber_Four),
-			Label:    "四胎",
-			Disabled: true,
-		})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("ChildNumberEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigChildNumberSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) CalvingLevelEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) CalvingLevelEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCalvingLevel, 0)
+	pref := s.DB.Model(new(model.ConfigCalvingLevel)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.CalvingLevel_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.CalvingLevel_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CalvingLevel_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CalvingLevelEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	configOptions = append(configOptions,
-		&pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CalvingLevel_Natural_Childbirth),
-			Label:    "自然分娩",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CalvingLevel_Artificial_Midwifery1),
-			Label:    "人工助产(1-2人)",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CalvingLevel_Artificial_Midwifery2),
-			Label:    "人工助产(3人以上)",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CalvingLevel_Caesarean_Section),
-			Label:    "剖腹产",
-			Disabled: true,
-		})
-	return configOptions
+
+	return model.ConfigCalvingLevelSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) DystociaReasonEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) DystociaReasonEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigDystociaReason, 0)
+	pref := s.DB.Model(new(model.ConfigDystociaReason)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.DystociaReason_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.DystociaReason_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.DystociaReason_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CalvingLevelEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	configOptions = append(configOptions,
-		&pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.DystociaReason_Malposition),
-			Label:    "胎位不正",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.DystociaReason_Fetal_Overgrowth),
-			Label:    "胎儿过大",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.DystociaReason_Uterine_Atony),
-			Label:    "子宫收缩无力",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.DystociaReason_Pelvic_Stenosis),
-			Label:    "盆骨狭小",
-			Disabled: true,
-		}, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.DystociaReason_Sub_Health),
-			Label:    "母牛亚健康状态",
-			Disabled: true,
-		})
-	return configOptions
+
+	return model.ConfigDystociaReasonSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) PregnantCheckResultEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) PregnantCheckResultEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigPregnantCheckResult, 0)
+	pref := s.DB.Model(new(model.ConfigPregnantCheckResult)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.PregnantCheckResult_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.PregnantCheckResult_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.PregnantCheckResult_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.PregnantCheckResult_Pregnant),
-		Label:    "有胎",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.PregnantCheckResult_UnPregnant),
-		Label:    "无胎",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("PregnantCheckResultEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigPregnantCheckResultSlice(dataList).ToPB(userModel)
 }

+ 113 - 359
module/backend/config_data_base.go

@@ -3,301 +3,93 @@ package backend
 import (
 	"kpt-pasture/model"
 
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"go.uber.org/zap"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
-func (s *StoreEntry) OutReasonEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) DeathReasonEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigDeathReason, 0)
+	pref := s.DB.Model(new(model.ConfigDeathReason)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.OutReasons_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.DeathReason_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.DeathReason_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Respiratory_System_Disease),
-		Label:    "呼吸系统疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Nutritional_Metabolic_Disease),
-		Label:    "营养代谢疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Breeding_Disease),
-		Label:    "繁殖疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Breast_Disease),
-		Label:    "乳房疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Long_Term_infertility),
-		Label:    "久配不孕",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Multiple_Miscarriages),
-		Label:    "多次流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Long_Treatment_Without_Recovery),
-		Label:    "久治不愈",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Postpartum_Paralysis),
-		Label:    "产后瘫痪",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Mastitis),
-		Label:    "乳房炎",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Hoof_Disease),
-		Label:    "蹄病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Congenital_Malformation),
-		Label:    "先天畸形",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Congenital_Malformation),
-		Label:    "先天畸形",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Dysplasia),
-		Label:    "发育不良",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Hernia),
-		Label:    "疝气",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Excessive_Age),
-		Label:    "月龄过大",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Excessive_Age),
-		Label:    "月龄过大",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Excessive_Weight),
-		Label:    "体重过肥",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Other_Disease),
-		Label:    "其他疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Weak_Child),
-		Label:    "弱仔",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Obsessive_Bull),
-		Label:    "恶癖牛",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Low_Milk),
-		Label:    "低产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Slow_Growing),
-		Label:    "生长缓慢",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Other),
-		Label:    "其他",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Unknown),
-		Label:    "未知原因",
-		Disabled: true,
-	})
-	return configOptions
-}
 
-func (s *StoreEntry) DeathReasonEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.DeathReason_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("DeathReasonEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Digestive_System_Diseases),
-		Label:    "消化性疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Respiratory_System_Diseases),
-		Label:    "呼吸性疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Reproductive_System_Diseases),
-		Label:    "繁殖性疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Metabolic_System_Diseases),
-		Label:    "代谢性疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Infectious_Diseases),
-		Label:    "传染性疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Difficult_Birth),
-		Label:    "难产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Accident_Dead),
-		Label:    "意外死亡",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Stress),
-		Label:    "应激",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Trauma),
-		Label:    "外伤",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Pneumonia),
-		Label:    "肺炎",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Diarrhea),
-		Label:    "腹泻",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Ketosis),
-		Label:    "酮症",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Acidosis),
-		Label:    "酸中毒",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Rumina_Impaction),
-		Label:    "瘤胃积食",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Intestinal_Torsion),
-		Label:    "肠扭转",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathReason_Other),
-		Label:    "其他",
-		Disabled: true,
-	})
-	return configOptions
+
+	return model.ConfigDeathReasonSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) MatingResultEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) MatingResultEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigMatingResult, 0)
+	pref := s.DB.Model(new(model.ConfigMatingResult)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.MatingResult_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.MatingResult_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.MatingResult_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MatingResult_Unknown),
-		Label:    "未知",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MatingResult_ReMatch),
-		Label:    "复配",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MatingResult_Pregnant),
-		Label:    "怀孕",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MatingResult_Empty),
-		Label:    "空怀",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MatingResult_Abort),
-		Label:    "流产",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("MatingResultEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigMatingResultSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) EventCategoryEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) EventCategoryEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigEventCategory, 0)
+	pref := s.DB.Model(new(model.ConfigEventCategory)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.EventCategory_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.EventCategory_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.EventCategory_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.EventCategory_Base),
-		Label:    "基础事件",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.EventCategory_Breed),
-		Label:    "繁殖事件",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.EventCategory_Health),
-		Label:    "兽医事件",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.EventCategory_Other),
-		Label:    "其他事件",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("EventCategoryEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigEventCategorySlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) IndicatorsCategoryEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) IndicatorsCategoryEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigIndicatorsCategory, 0)
+	pref := s.DB.Model(new(model.ConfigIndicatorsCategory)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(0),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.IndicatorType_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.IndicatorType_Invalid)
 	}
 
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.IndicatorType_Basic),
-		Label:    "基本指标",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.IndicatorType_Breed),
-		Label:    "繁殖指标",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.IndicatorType_Health),
-		Label:    "健康指标",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.IndicatorType_Feed),
-		Label:    "饲喂指标",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.IndicatorType_Calf),
-		Label:    "犊牛指标",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.IndicatorType_Fatten),
-		Label:    "育肥指标",
-		Disabled: true,
-	})
-	return configOptions
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("IndicatorsCategoryEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigIndicatorsCategorySlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) IndicatorsDetailsList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) IndicatorsDetailsList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -324,100 +116,62 @@ func (s *StoreEntry) IndicatorsDetailsList(isAll string) []*pasturePb.ConfigOpti
 	return configOptions
 }
 
-func (s *StoreEntry) CowPurposeList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) CowPurposeList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCowPurpose, 0)
+	pref := s.DB.Model(new(model.ConfigCowPurpose)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(0),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.Purpose_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.Purpose_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Purpose_Breeding),
-		Label:    "繁殖",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Purpose_Fatten),
-		Label:    "育肥",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CowPurposeList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigCowPurposeSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) CowOutReasonList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) CowOutReasonEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCowOutReason, 0)
+	pref := s.DB.Model(new(model.ConfigCowOutReason)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(0),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.OutReasons_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.OutReasons_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Respiratory_System_Disease),
-		Label:    "呼吸系统疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Nutritional_Metabolic_Disease),
-		Label:    "营养代谢疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Breeding_Disease),
-		Label:    "繁殖疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Breast_Disease),
-		Label:    "乳房疾病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Hoof_Disease),
-		Label:    "蹄病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Low_Milk),
-		Label:    "低产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Slow_Growing),
-		Label:    "生长缓慢",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Slow_Growing),
-		Label:    "生长缓慢",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.OutReasons_Other),
-		Label:    "其他原因",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CowOutReasonList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigCowOutReasonSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) CowDeathDestinationList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) CowDeathDestinationList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCowDeathDestination, 0)
+	pref := s.DB.Model(new(model.ConfigCowDeathDestination)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(0),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.DeathDestination_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.DeathDestination_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathDestination_NuisanceLess),
-		Label:    "无公害处理",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathDestination_Slaughterhouse),
-		Label:    "屠宰场",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DeathDestination_Other),
-		Label:    "其他",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CowDeathDestinationList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigCowDeathDestinationSlice(dataList).ToPB(userModel)
 }

+ 192 - 313
module/backend/config_data_breed.go

@@ -8,274 +8,204 @@ import (
 	"go.uber.org/zap"
 )
 
-func (s *StoreEntry) LactEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) LactEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	configLactList := make([]*model.ConfigLact, 0)
+	pref := s.DB.Model(new(model.ConfigLact)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-			Value:    int32(0),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", 0)
+	} else {
+		pref = pref.Where("kind > ?", 0)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(1),
-		Label:    "1",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(2),
-		Label:    "2",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(3),
-		Label:    "3",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(4),
-		Label:    ">3",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&configLactList).Error; err != nil {
+		zaplog.Error("LactEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigLactSlice(configLactList).ToPB(userModel)
 }
 
-func (s *StoreEntry) DiseaseAnalysisMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) DiseaseAnalysisMethodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigDiseaseAnalysisMethod, 0)
+	pref := s.DB.Model(new(model.ConfigDiseaseAnalysisMethod)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.DiseaseAnalysisMethod_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.DiseaseAnalysisMethod_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.DiseaseAnalysisMethod_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DiseaseAnalysisMethod_Months),
-		Label:    "按月份",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DiseaseAnalysisMethod_Disease_Category),
-		Label:    "疾病分类",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DiseaseAnalysisMethod_Disease),
-		Label:    "疾病名称",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DiseaseAnalysisMethod_Operator),
-		Label:    "兽医",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.DiseaseAnalysisMethod_Prescription),
-		Label:    "处方",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("DiseaseAnalysisMethodEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigDiseaseAnalysisMethodSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) diseaseTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configDiseaseTypeList := make([]*model.ConfigDiseaseType, 0)
-	configOptionsList := make([]*pasturePb.ConfigOptionsList, 0)
-	if err := s.DB.Where("is_show = ?", pasturePb.IsShow_Ok).Find(&configDiseaseTypeList).Error; err != nil {
-		zaplog.Error("diseaseTypeEnumList", zap.Any("Find", err))
+func (s *StoreEntry) diseaseTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigDiseaseType, 0)
+	pref := s.DB.Model(new(model.ConfigDiseaseType)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", 0)
+	} else {
+		pref = pref.Where("kind > ?", 0)
 	}
 
-	for _, v := range configDiseaseTypeList {
-		configOptionsList = append(configOptionsList, &pasturePb.ConfigOptionsList{
-			Value:    int32(v.Id),
-			Label:    v.Name,
-			Disabled: true,
-		})
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("DiseaseAnalysisMethodEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	return configOptionsList
+
+	return model.ConfigDiseaseTypeSlice(dataList).ToPB3(userModel)
 }
 
-func (s *StoreEntry) SingleFactorAnalysisMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Cycle),
-		Label:    "按周期分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Months),
-		Label:    "按月份分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Mating_Times),
-		Label:    "按配种次数分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Breeding_Method),
-		Label:    "按配种方式分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Breeding_Company),
-		Label:    "按育种公司分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Operation),
-		Label:    "按兽医人员分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Mating_Interval),
-		Label:    "按配种间隔分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Bull),
-		Label:    "按公牛号分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Breeding_Cycle),
-		Label:    "按配种周期分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Week),
-		Label:    "按星期分析",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SingleFactorAnalysisMethod_Lact),
-		Label:    "按胎次分析",
-		Disabled: true,
-	})
-	return configOptions
+func (s *StoreEntry) SingleFactorAnalysisMethodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigSingleFactorAnalysisMethod, 0)
+	pref := s.DB.Model(new(model.ConfigSingleFactorAnalysisMethod)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.DiseaseAnalysisMethod_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.DiseaseAnalysisMethod_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("SingleFactorAnalysisMethodEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigSingleFactorAnalysisMethodSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) LactIntervalSymbolEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Less_Than),
-		Label:    "<",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Less_Than_Or_Equal_To),
-		Label:    "<=",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Greater_Than),
-		Label:    ">",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Greater_Than_Or_Equal_To),
-		Label:    ">=",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Equal_To),
-		Label:    "=",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Not_Equal_To),
-		Label:    "!=",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Between),
-		Label:    "区间",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Include),
-		Label:    "包含",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CompareSymbol_Not_Include),
-		Label:    "不包含",
-		Disabled: true,
-	})
-	return configOptions
+func (s *StoreEntry) LactIntervalSymbolEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigLactIntervalSymbol, 0)
+	pref := s.DB.Model(new(model.ConfigLactIntervalSymbol)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.CompareSymbol_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CompareSymbol_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("LactIntervalSymbolEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigLactIntervalSymbolSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) MultiFactorAnalysisMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Months),
-		Label:    "月份",
-		Props:    "months",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Week),
-		Label:    "周",
-		Props:    "week",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Operation),
-		Label:    "配种员",
-		Props:    "operationName",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Bull),
-		Label:    "公牛",
-		Props:    "bull",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Lact),
-		Label:    "胎次",
-		Props:    "lact",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Mating_Times),
-		Label:    "配次",
-		Props:    "matingTimes",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.MultiFactorAnalysisMethod_Breeding_Method),
-		Label:    "配种方式",
-		Props:    "exposeEstrusType",
-		Disabled: true,
-	})
-	return configOptions
+func (s *StoreEntry) MultiFactorAnalysisMethodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigMultiFactorAnalysisMethod, 0)
+	pref := s.DB.Model(new(model.ConfigMultiFactorAnalysisMethod)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.CompareSymbol_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CompareSymbol_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("LactIntervalSymbolEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigMultiFactorAnalysisMethodSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) SaleCowAnalysisMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SaleCowAnalysisMethod_Months),
-		Label:    "月份",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.SaleCowAnalysisMethod_Dealer),
-		Label:    "经销商",
-		Disabled: true,
-	})
-	return configOptions
+func (s *StoreEntry) SaleCowAnalysisMethodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigSaleCowAnalysisMethod, 0)
+	pref := s.DB.Model(new(model.ConfigSaleCowAnalysisMethod)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.CompareSymbol_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CompareSymbol_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("LactIntervalSymbolEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigSaleCowAnalysisMethodSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) NeckRingIsBindEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) NeckRingIsBindEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigNeckRingIsBind, 0)
+	pref := s.DB.Model(new(model.ConfigNeckRingStatus)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.NeckRingIsBind_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.NeckRingIsBind_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.NeckRingIsBind_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.NeckRingIsBind_Bind),
-		Label:    "已绑定",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.NeckRingIsBind_Unbind),
-		Label:    "未绑定",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("NeckRingIsBindEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigNeckRingIsBindSlice(dataList).ToPB(userModel)
 }
 
-func (s *StoreEntry) NeckRingStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) NeckRingStatusEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigNeckRingStatus, 0)
+	pref := s.DB.Model(new(model.ConfigNeckRingStatus)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(pasturePb.NeckRingStatus_Invalid),
-				Label:    "全部",
-				Disabled: true,
-			})
+		pref = pref.Where("kind >= ?", pasturePb.NeckRingStatus_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.NeckRingStatus_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.NeckRingStatus_Normal),
-		Label:    "正常",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.NeckRingStatus_Abnormal),
-		Label:    "异常",
-		Disabled: true,
-	})
-	return configOptions
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("NeckRingStatusEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigNeckRingStatusSlice(dataList).ToPB(userModel)
+}
+
+func (s *StoreEntry) CalendarTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCalendarType, 0)
+	pref := s.DB.Model(new(model.ConfigCalendarType)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
+	if isAll == model.IsAllYes {
+		pref = pref.Where("kind >= ?", pasturePb.CalendarType_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CalendarType_Invalid)
+	}
+
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CalendarTypeEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
+	}
+
+	return model.ConfigCalendarTypeSlice(dataList).ToPB(userModel)
 }
 
 func CalendarTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
@@ -327,8 +257,8 @@ func CalendarTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 	return configOptions
 }
 
-func (s *StoreEntry) AbortionReasonsEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	/*configAbortionReasonList := make([]*model.ConfigAbortionReasons, 0)
+func (s *StoreEntry) AbortionReasonsEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigAbortionReasons, 0)
 	pref := s.DB.Model(new(model.ConfigAbortionReasons)).
 		Where("is_show =? ", pasturePb.IsShow_Ok).
 		Where("pasture_id =? ", userModel.AppPasture.Id)
@@ -339,81 +269,30 @@ func (s *StoreEntry) AbortionReasonsEnumList(isAll string) []*pasturePb.ConfigOp
 	}
 
 	if err := pref.Order("kind ASC").
-		Find(&configAbortionReasonList).Error; err != nil {
-		return nil, xerr.WithStack(err)
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("AbortionReasonsEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
 
-	return model.ConfigAbortionReasonsSlice(configAbortionReasonList).ToPB(userModel.Language)*/
+	return model.ConfigAbortionReasonsSlice(dataList).ToPB(userModel)
+}
 
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+func (s *StoreEntry) CalvingAnalysisMethodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
+	dataList := make([]*model.ConfigCalvingAnalysisMethod, 0)
+	pref := s.DB.Model(new(model.ConfigCalvingAnalysisMethod)).
+		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Where("pasture_id =? ", userModel.AppPasture.Id)
 	if isAll == model.IsAllYes {
-		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.AbortionReasons_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+		pref = pref.Where("kind >= ?", pasturePb.CalvingAnalysisMethod_Invalid)
+	} else {
+		pref = pref.Where("kind > ?", pasturePb.CalvingAnalysisMethod_Invalid)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Mechanical_Abortion),
-		Label:    "机械性流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Malnutrition_Abortion),
-		Label:    "营养不良流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Mycotoxin_Abortion),
-		Label:    "霉菌毒素流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Habitual_Abortion),
-		Label:    "习惯性流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Brucellosis_Abortion),
-		Label:    "布病流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Inflammatory_Abortion),
-		Label:    "产道炎症性流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Heat_Stress_Abortion),
-		Label:    "热应激流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Infectious_Abortion),
-		Label:    "传染病性流产",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Unknown),
-		Label:    "未知原因",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.AbortionReasons_Other),
-		Label:    "其他",
-		Disabled: true,
-	})
-	return configOptions
-}
 
-func (s *StoreEntry) CalvingAnalysisMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	if isAll == model.IsAllYes {
-		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.CalvingAnalysisMethod_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
+	if err := pref.Order("kind ASC").
+		Find(&dataList).Error; err != nil {
+		zaplog.Error("CalvingAnalysisMethodEnumList", zap.Any("err", err))
+		return make([]*pasturePb.ConfigOptionsList, 0)
 	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CalvingAnalysisMethod_Months),
-		Label:    "按月份统计",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.CalvingAnalysisMethod_CowKind),
-		Label:    "按照品种统计",
-		Disabled: true,
-	})
-	return configOptions
+
+	return model.ConfigCalvingAnalysisMethodSlice(dataList).ToPB(userModel)
 }

+ 11 - 11
module/backend/config_data_extend.go

@@ -12,7 +12,7 @@ import (
 	"gitee.com/xuyiping_admin/pkg/xerr"
 )
 
-func (s *StoreEntry) WorkOrderSubUnitEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) WorkOrderSubUnitEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.WorkOrderSubscribeUnit_Person),
@@ -26,7 +26,7 @@ func (s *StoreEntry) WorkOrderSubUnitEnumList(isAll string) []*pasturePb.ConfigO
 	return configOptions
 }
 
-func (s *StoreEntry) WorkOrderPriorityEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) WorkOrderPriorityEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.Priority_Low),
@@ -44,7 +44,7 @@ func (s *StoreEntry) WorkOrderPriorityEnumList(isAll string) []*pasturePb.Config
 	return configOptions
 }
 
-func (s *StoreEntry) WorkOrderCategoryEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) WorkOrderCategoryEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.WorkOrderCategory_Health),
@@ -70,7 +70,7 @@ func (s *StoreEntry) WorkOrderCategoryEnumList(isAll string) []*pasturePb.Config
 	return configOptions
 }
 
-func (s *StoreEntry) AdmissionStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) AdmissionStatusEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -104,7 +104,7 @@ func (s *StoreEntry) AdmissionStatusEnumList(isAll string) []*pasturePb.ConfigOp
 	return configOptions
 }
 
-func (s *StoreEntry) ForbiddenMatingReasonsEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) ForbiddenMatingReasonsEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -146,7 +146,7 @@ func (s *StoreEntry) ForbiddenMatingReasonsEnumList(isAll string) []*pasturePb.C
 	return configOptions
 }
 
-func (s *StoreEntry) WarningHealthLevel(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) WarningHealthLevel(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -172,7 +172,7 @@ func (s *StoreEntry) WarningHealthLevel(isAll string) []*pasturePb.ConfigOptions
 	return configOptions
 }
 
-func (s *StoreEntry) Behavior(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) Behavior(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -206,7 +206,7 @@ func (s *StoreEntry) Behavior(isAll string) []*pasturePb.ConfigOptionsList {
 	return configOptions
 }
 
-func (s *StoreEntry) HealthStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) HealthStatusEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
@@ -244,7 +244,7 @@ func (s *StoreEntry) HealthStatusEnumList(isAll string) []*pasturePb.ConfigOptio
 	return configOptions
 }
 
-func (s *StoreEntry) MatingWindowPeriodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) MatingWindowPeriodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -270,7 +270,7 @@ func (s *StoreEntry) MatingWindowPeriodEnumList(isAll string) []*pasturePb.Confi
 	return configOptions
 }
 
-func (s *StoreEntry) DataWaringTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) DataWaringTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -314,7 +314,7 @@ func (s *StoreEntry) DataWaringTypeEnumList(isAll string) []*pasturePb.ConfigOpt
 	return configOptions
 }
 
-func (s *StoreEntry) NeckRingErrorEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) NeckRingErrorEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,

+ 20 - 16
module/backend/config_data_other.go

@@ -9,7 +9,7 @@ import (
 	"go.uber.org/zap"
 )
 
-func (s *StoreEntry) PregnantCheckMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) PregnantCheckMethodEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -33,7 +33,7 @@ func (s *StoreEntry) PregnantCheckMethodEnumList(isAll string) []*pasturePb.Conf
 	return configOptions
 }
 
-func (s *StoreEntry) DrugCategoryEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) DrugCategoryEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -107,7 +107,7 @@ func (s *StoreEntry) DrugCategoryEnumList(isAll string) []*pasturePb.ConfigOptio
 	return configOptions
 }
 
-func (s *StoreEntry) DrugUsageEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) DrugUsageEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -142,7 +142,7 @@ func (s *StoreEntry) DrugUsageEnumList(isAll string) []*pasturePb.ConfigOptionsL
 	return configOptions
 }
 
-func (s *StoreEntry) UnitEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) UnitEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	configOptions = append(configOptions,
 		&pasturePb.ConfigOptionsList{
@@ -189,7 +189,7 @@ func (s *StoreEntry) UnitEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 	return configOptions
 }
 
-func (s *StoreEntry) ExposeEstrusTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) ExposeEstrusTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -217,7 +217,7 @@ func (s *StoreEntry) ExposeEstrusTypeEnumList(isAll string) []*pasturePb.ConfigO
 	return configOptions
 }
 
-func (s *StoreEntry) FrozenSemenTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) FrozenSemenTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -240,11 +240,11 @@ func (s *StoreEntry) FrozenSemenTypeEnumList(isAll string) []*pasturePb.ConfigOp
 	return configOptions
 }
 
-func (s *StoreEntry) BullNumberEnumList(isAll string, pastureId int64) []*pasturePb.BullOptionsList {
+func (s *StoreEntry) BullNumberEnumList(userModel *model.UserModel, isAll string) []*pasturePb.BullOptionsList {
 	frozenSemenList := make([]*model.FrozenSemen, 0)
 	bullNumberList := make([]*pasturePb.BullOptionsList, 0)
 	if err := s.DB.Model(new(model.FrozenSemen)).
-		Where("pasture_id = ?", pastureId).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
 		Where("quantity > 0").
 		Group("bull_id").
 		Find(&frozenSemenList).Error; err != nil {
@@ -261,7 +261,7 @@ func (s *StoreEntry) BullNumberEnumList(isAll string, pastureId int64) []*pastur
 	return bullNumberList
 }
 
-func (s *StoreEntry) WeekEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) WeekEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	configOptions = append(configOptions,
 		&pasturePb.ConfigOptionsList{
@@ -296,7 +296,7 @@ func (s *StoreEntry) WeekEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 	return configOptions
 }
 
-func (s *StoreEntry) MonthEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) MonthEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	for v := 1; v <= 31; v++ {
 		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
@@ -308,7 +308,7 @@ func (s *StoreEntry) MonthEnumList(isAll string) []*pasturePb.ConfigOptionsList
 	return configOptions
 }
 
-func (s *StoreEntry) WorkOrderFrequencyEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) WorkOrderFrequencyEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.WorkOrderFrequency_None),
@@ -330,7 +330,7 @@ func (s *StoreEntry) WorkOrderFrequencyEnumList(isAll string) []*pasturePb.Confi
 	return configOptions
 }
 
-func (s *StoreEntry) OutTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) OutTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -352,7 +352,7 @@ func (s *StoreEntry) OutTypeEnumList(isAll string) []*pasturePb.ConfigOptionsLis
 	return configOptions
 }
 
-func (s *StoreEntry) AuditStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) AuditStatusEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -386,7 +386,7 @@ func (s *StoreEntry) AuditStatusEnumList(isAll string) []*pasturePb.ConfigOption
 	return configOptions
 }
 
-func (s *StoreEntry) PregnantCheckNameEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) PregnantCheckNameEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -408,7 +408,7 @@ func (s *StoreEntry) PregnantCheckNameEnumList(isAll string) []*pasturePb.Config
 	return configOptions
 }
 
-func (s *StoreEntry) UnMatingReasonsEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) UnMatingReasonsEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -442,7 +442,7 @@ func (s *StoreEntry) UnMatingReasonsEnumList(isAll string) []*pasturePb.ConfigOp
 	return configOptions
 }
 
-func (s *StoreEntry) EventTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+func (s *StoreEntry) EventTypeEnumList(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
 		configOptions = append(configOptions,
@@ -540,6 +540,10 @@ func (s *StoreEntry) EventTypeEnumList(isAll string) []*pasturePb.ConfigOptionsL
 		Value:    int32(pasturePb.EventType_UnForbiddenMating),
 		Label:    "解禁",
 		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.EventType_Perinatal_Transition),
+		Label:    "转围产",
+		Disabled: true,
 	})
 	return configOptions
 }

+ 18 - 292
module/backend/cow.go

@@ -9,7 +9,6 @@ import (
 	"net/http"
 	"sort"
 	"strings"
-	"sync"
 	"time"
 
 	"github.com/nicksnyder/go-i18n/v2/i18n"
@@ -57,13 +56,13 @@ func (s *StoreEntry) Detail(ctx context.Context, req *pasturePb.SearchEventReque
 		}
 	}
 
-	cowTypeMap := s.CowTypeMap()
-	breedStatusMap := s.CowBreedStatusMap()
-	cowKindMap := s.CowKindMap()
-	cowSourceMap := s.CowSourceMap()
-	admissionStatusMap := s.AdmissionStatusMap()
-	healthStatusMap := s.HealthStatusMap()
-	purposeMap := s.PurposeMap()
+	cowTypeMap := s.CowTypeMap(userModel)
+	breedStatusMap := s.CowBreedStatusMap(userModel)
+	cowKindMap := s.CowKindMap(userModel)
+	cowSourceMap := s.CowSourceMap(userModel)
+	admissionStatusMap := s.AdmissionStatusMap(userModel)
+	healthStatusMap := s.HealthStatusMap(userModel)
+	purposeMap := s.PurposeMap(userModel)
 	systemBasic, err := s.GetSystemBasicByName(ctx, userModel.AppPasture.Id, model.PregnancyAge)
 	if err != nil {
 		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
@@ -159,13 +158,13 @@ func (s *StoreEntry) List(ctx context.Context, req *pasturePb.SearchEventRequest
 		return nil, xerr.WithStack(err)
 	}
 
-	cowTypeMap := s.CowTypeMap()
-	breedStatusMap := s.CowBreedStatusMap()
-	cowKindMap := s.CowKindMap()
-	cowSourceMap := s.CowSourceMap()
-	admissionStatusMap := s.AdmissionStatusMap()
-	healthStatusMap := s.HealthStatusMap()
-	purposeMap := s.PurposeMap()
+	cowTypeMap := s.CowTypeMap(userModel)
+	breedStatusMap := s.CowBreedStatusMap(userModel)
+	cowKindMap := s.CowKindMap(userModel)
+	cowSourceMap := s.CowSourceMap(userModel)
+	admissionStatusMap := s.AdmissionStatusMap(userModel)
+	healthStatusMap := s.HealthStatusMap(userModel)
+	purposeMap := s.PurposeMap(userModel)
 	return &pasturePb.SearchCowListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -216,7 +215,7 @@ func (s *StoreEntry) EventList(ctx context.Context, req *pasturePb.SearchCowEven
 		return nil, xerr.WithStack(err)
 	}
 
-	eventCategoryMap := s.EventCategoryMap()
+	eventCategoryMap := s.EventCategoryMap(userModel)
 	return &pasturePb.CowEventListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -246,7 +245,7 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 	nowTime := time.Now().Local()
 	nowDayZero := util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2))
 	endDataTime := nowTime.Format(model.LayoutDate2)
-	startDataTime := nowTime.AddDate(0, 0, -50).Format(model.LayoutDate2)
+	startDataTime := nowTime.AddDate(0, 0, -model.NeckRingDataDays).Format(model.LayoutDate2)
 
 	dayRange, err := util.GetDaysBetween(startDataTime, endDataTime)
 	if err != nil {
@@ -277,7 +276,7 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 	q1, q3 := s.CowIQR(cowInfo, req.CurveName, dayRange, data.DateTimeList)
 	data.IQR3 = q3
 	data.IQR1 = q1
-	eventMapList := s.EventTypeMap()
+	eventMapList := s.EventTypeMap(userModel)
 	for k, v := range eventMapList {
 		if k == pasturePb.EventType_Enter || k == pasturePb.EventType_Body_Score || k == pasturePb.EventType_Birth ||
 			k == pasturePb.EventType_Weaning || k == pasturePb.EventType_Sale || k == pasturePb.EventType_Weight ||
@@ -294,7 +293,7 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 	if err = s.DB.Table(eventLog.TableName()).
 		Where("cow_id = ?", cowInfo.Id).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("event_at BETWEEN ? AND ?", nowDayZero-(30*86400), nowDayZero+86400).
+		Where("event_at BETWEEN ? AND ?", nowDayZero-(model.NeckRingDataDays*86400), nowDayZero+86400).
 		Order("event_at").
 		Find(&eventLogList).Error; err != nil {
 		return nil, xerr.WithStack(err)
@@ -438,276 +437,3 @@ func (s *StoreEntry) CowIQR(cowInfo *model.Cow, curveName string, dayRange []str
 	}
 	return q1, q3
 }
-
-func (s *StoreEntry) GetNeckActiveHabitsConcurrent(cowInfo *model.Cow, cowIds []int64, dayRange []string) ([]*model.NeckActiveHabit, error) {
-	const (
-		batchSize   = 100
-		workerCount = 5
-	)
-
-	resultsChan := make(chan []*model.NeckActiveHabit)
-	errChan := make(chan error, 1) // 缓冲 1,避免 goroutine 阻塞
-	doneChan := make(chan struct{})
-
-	var (
-		neckActiveHabitList []*model.NeckActiveHabit
-		mu                  sync.Mutex
-	)
-
-	// 结果收集 goroutine
-	go func() {
-		defer close(doneChan)
-		for batchResults := range resultsChan {
-			mu.Lock()
-			neckActiveHabitList = append(neckActiveHabitList, batchResults...)
-			mu.Unlock()
-		}
-	}()
-
-	sem := make(chan struct{}, workerCount)
-	var wg sync.WaitGroup
-
-	// 分发任务
-	go func() {
-		defer func() {
-			wg.Wait()          // 等待所有 goroutine 完成
-			close(resultsChan) // 安全关闭
-		}()
-
-		for i := 0; i < len(cowIds); i += batchSize {
-			end := i + batchSize
-			if end > len(cowIds) {
-				end = len(cowIds)
-			}
-			batch := cowIds[i:end]
-
-			wg.Add(1)
-			sem <- struct{}{} // 获取令牌(可能阻塞,但不会死锁)
-
-			go func(batch []int64) {
-				defer func() {
-					<-sem // 释放令牌
-					wg.Done()
-				}()
-
-				var batchResults []*model.NeckActiveHabit
-				if err := s.DB.Table(new(model.NeckActiveHabit).TableName()).
-					Select("rumina,intake,inactive,gasp,high,active,active_time").
-					Where("pasture_id = ?", cowInfo.PastureId).
-					Where("is_show = ?", pasturePb.IsShow_Ok).
-					Where("cow_id IN (?)", batch).
-					Where("heat_date BETWEEN ? AND ?", dayRange[0], dayRange[len(dayRange)-1]).
-					Find(&batchResults).Error; err != nil {
-					select {
-					case errChan <- fmt.Errorf("batch query error: %v", err):
-					default:
-					}
-					return
-				}
-
-				if len(batchResults) > 0 {
-					resultsChan <- batchResults
-				}
-			}(batch)
-		}
-	}()
-
-	// 等待结果
-	select {
-	case err := <-errChan:
-		return nil, err
-	case <-doneChan:
-		return neckActiveHabitList, nil
-	}
-}
-
-func (s *StoreEntry) CowGrowthCurve(ctx context.Context, req *pasturePb.CowGrowthCurveRequest) (*pasturePb.CowGrowthCurveResponse, error) {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	cowInfo, err := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, req.EarNumber)
-	if err != nil {
-		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
-			MessageID:    "auth.errorCow",
-			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
-		})
-		return nil, xerr.Customf(messageId)
-	}
-
-	weightList := make([]*model.EventWeight, 0)
-	if err = s.DB.Table(new(model.EventWeight).TableName()).
-		Where("cow_id = ?", cowInfo.Id).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Order("weight_at").
-		Find(&weightList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	eventCowLogList := make([]*model.EventCowLog, 0)
-	eventCowLog := &model.EventCowLog{CowId: cowInfo.Id}
-	if err = s.DB.Table(eventCowLog.TableName()).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("cow_id = ?", cowInfo.Id).
-		Order("id desc").
-		Find(&eventCowLogList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.CowGrowthCurveResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: model.EventWeightSlice(weightList).ToPB(eventCowLogList),
-	}, nil
-}
-
-func (s *StoreEntry) CowLactCurve(ctx context.Context, req *pasturePb.CowLactCurveRequest) (*pasturePb.CowLactCurveResponse, error) {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	cowInfo, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(req.CowId))
-	if err != nil {
-		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
-			MessageID:    "auth.errorCow",
-			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
-		})
-		return nil, xerr.Customf(messageId)
-	}
-
-	cowLactList := make([]*model.CowLact, 0)
-	if err = s.DB.Table(new(model.CowLact).TableName()).
-		Where("cow_id = ?", req.CowId).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Order("lact").
-		Find(&cowLactList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	data := &pasturePb.CowLactCurveData{
-		DateTime:            make(map[int32]string),
-		WeekAvgMilk:         make([]float32, 0),
-		DayMilk:             make([]float32, 0),
-		DHI:                 make([]float32, 0),
-		MilkProductionTrend: make([]float32, 0),
-		DayHigh:             make([]int32, 0),
-		DayRumina:           make([]int32, 0),
-		DayIntake:           make([]int32, 0),
-		DayInactive:         make([]int32, 0),
-		DayChew:             make([]int32, 0),
-		DayImmobility:       make([]int32, 0),
-		EstrusWarning:       make(map[int32]int32),
-	}
-
-	if len(cowLactList) <= 0 {
-		return &pasturePb.CowLactCurveResponse{
-			Code: http.StatusOK,
-			Msg:  "ok",
-			Data: data,
-		}, nil
-	}
-	starTime := ""
-	endTime := ""
-	cowLactMap := make(map[int32]*model.CowLact)
-	for _, v := range cowLactList {
-		cowLactMap[v.Lact] = v
-		if v.Lact == req.Lact {
-			starTime = v.StartTime
-		}
-	}
-	if st, ok := cowLactMap[req.Lact+1]; ok {
-		et, _ := util.TimeParseLocal(model.LayoutDate2, st.StartTime)
-		endTime = et.AddDate(0, 0, -1).Format(model.LayoutDate2)
-	} else {
-		endTime = time.Now().Local().Format(model.LayoutDate2)
-	}
-
-	neckRingList := make([]*model.NeckActiveHabit, 0)
-	if err = s.DB.Model(new(model.NeckActiveHabit)).
-		Where("neck_ring_number = ?", cowInfo.NeckRingNumber).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("cow_id > ?", 0).
-		Where("heat_date BETWEEN ? AND ?", starTime, endTime).
-		Order("heat_date, frameid").Find(&neckRingList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	return &pasturePb.CowLactCurveResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: data,
-	}, nil
-}
-
-func (s *StoreEntry) BehaviorRate(ctx context.Context, req *pasturePb.CowBehaviorRateRequest) (*pasturePb.CowBehaviorRateResponse, error) {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	cowInfo, err := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, req.EarNumber)
-	if err != nil {
-		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
-			MessageID:    "auth.errorCow",
-			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
-		})
-		return nil, xerr.Customf(messageId)
-	}
-
-	if req.EndAt <= 0 || req.StartAt <= 0 || req.EndAt < req.StartAt {
-		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
-			MessageID: "auth.errorDateRange",
-		})
-		return nil, xerr.Customf(messageId)
-	}
-
-	t1 := time.Unix(int64(req.StartAt), 0).Local().Format(model.LayoutDate2)
-	t2 := time.Unix(int64(req.EndAt), 0).Local().Format(model.LayoutDate2)
-
-	dataBetween, err := util.GetDaysBetween(t1, t2)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
-	if err = s.DB.Model(new(model.NeckActiveHabit)).
-		Select("heat_date,SUM(rumina) as rumina,SUM(intake) as intake,SUM(inactive) as inactive,SUM(gasp) AS gasp").
-		Where("neck_ring_number = ?", cowInfo.NeckRingNumber).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("cow_id > ?", 0).
-		Where("heat_date BETWEEN ? AND ?", t1, t2).
-		Order("heat_date").
-		Group("heat_date").
-		Find(&neckActiveHabitList).Error; err != nil {
-	}
-
-	cowList := make([]*model.Cow, 0)
-	if err = s.DB.Model(new(model.Cow)).
-		Where("neck_ring_number != ?", "").
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("pen_id = ?", cowInfo.PenId).
-		Find(&cowList).Error; err != nil {
-	}
-
-	neckRingNumbers := make([]string, 0)
-	for _, v := range cowList {
-		neckRingNumbers = append(neckRingNumbers, v.NeckRingNumber)
-	}
-
-	groupNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
-	if err = s.DB.Model(new(model.NeckActiveHabit)).
-		Select("heat_date,SUM(rumina) as rumina,SUM(intake) as intake,SUM(inactive) as inactive,SUM(gasp) AS gasp").
-		Where("neck_ring_number IN ?", neckRingNumbers).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("cow_id > ?", 0).
-		Where("heat_date BETWEEN ? AND ?", t1, t2).
-		Order("heat_date").
-		Group("heat_date").
-		Find(&groupNeckActiveHabitList).Error; err != nil {
-	}
-
-	return &pasturePb.CowBehaviorRateResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: model.NeckActiveHabitSlice(neckActiveHabitList).ToPB2(dataBetween, groupNeckActiveHabitList),
-	}, nil
-}

+ 479 - 0
module/backend/cow_more.go

@@ -0,0 +1,479 @@
+package backend
+
+import (
+	"context"
+	"fmt"
+	"kpt-pasture/model"
+	"kpt-pasture/util"
+	"net/http"
+	"strings"
+	"sync"
+	"time"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+)
+
+func (s *StoreEntry) GetNeckActiveHabitsConcurrent(cowInfo *model.Cow, cowIds []int64, dayRange []string) ([]*model.NeckActiveHabit, error) {
+	const (
+		batchSize   = 100
+		workerCount = 5
+	)
+
+	resultsChan := make(chan []*model.NeckActiveHabit)
+	errChan := make(chan error, 1) // 缓冲 1,避免 goroutine 阻塞
+	doneChan := make(chan struct{})
+
+	var (
+		neckActiveHabitList []*model.NeckActiveHabit
+		mu                  sync.Mutex
+	)
+
+	// 结果收集 goroutine
+	go func() {
+		defer close(doneChan)
+		for batchResults := range resultsChan {
+			mu.Lock()
+			neckActiveHabitList = append(neckActiveHabitList, batchResults...)
+			mu.Unlock()
+		}
+	}()
+
+	sem := make(chan struct{}, workerCount)
+	var wg sync.WaitGroup
+
+	// 分发任务
+	go func() {
+		defer func() {
+			wg.Wait()          // 等待所有 goroutine 完成
+			close(resultsChan) // 安全关闭
+		}()
+
+		for i := 0; i < len(cowIds); i += batchSize {
+			end := i + batchSize
+			if end > len(cowIds) {
+				end = len(cowIds)
+			}
+			batch := cowIds[i:end]
+
+			wg.Add(1)
+			sem <- struct{}{} // 获取令牌(可能阻塞,但不会死锁)
+
+			go func(batch []int64) {
+				defer func() {
+					<-sem // 释放令牌
+					wg.Done()
+				}()
+
+				var batchResults []*model.NeckActiveHabit
+				if err := s.DB.Table(new(model.NeckActiveHabit).TableName()).
+					Select("rumina,intake,inactive,gasp,high,active,active_time").
+					Where("pasture_id = ?", cowInfo.PastureId).
+					Where("is_show = ?", pasturePb.IsShow_Ok).
+					Where("cow_id IN (?)", batch).
+					Where("heat_date BETWEEN ? AND ?", dayRange[0], dayRange[len(dayRange)-1]).
+					Find(&batchResults).Error; err != nil {
+					select {
+					case errChan <- fmt.Errorf("batch query error: %v", err):
+					default:
+					}
+					return
+				}
+
+				if len(batchResults) > 0 {
+					resultsChan <- batchResults
+				}
+			}(batch)
+		}
+	}()
+
+	// 等待结果
+	select {
+	case err := <-errChan:
+		return nil, err
+	case <-doneChan:
+		return neckActiveHabitList, nil
+	}
+}
+
+func (s *StoreEntry) CowGrowthCurve(ctx context.Context, req *pasturePb.CowGrowthCurveRequest) (*pasturePb.CowGrowthCurveResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	cowInfo, err := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, req.EarNumber)
+	if err != nil {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID:    "auth.errorCow",
+			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	weightList := make([]*model.EventWeight, 0)
+	if err = s.DB.Table(new(model.EventWeight).TableName()).
+		Where("cow_id = ?", cowInfo.Id).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Order("weight_at").
+		Find(&weightList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	eventCowLogList := make([]*model.EventCowLog, 0)
+	eventCowLog := &model.EventCowLog{CowId: cowInfo.Id}
+	if err = s.DB.Table(eventCowLog.TableName()).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("cow_id = ?", cowInfo.Id).
+		Order("id desc").
+		Find(&eventCowLogList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.CowGrowthCurveResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: model.EventWeightSlice(weightList).ToPB(eventCowLogList),
+	}, nil
+}
+
+func (s *StoreEntry) CowLactCurve(ctx context.Context, req *pasturePb.CowLactCurveRequest) (*pasturePb.CowLactCurveResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	cowInfo, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(req.CowId))
+	if err != nil {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID:    "auth.errorCow",
+			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	cowLactList := make([]*model.CowLact, 0)
+	if err = s.DB.Table(new(model.CowLact).TableName()).
+		Where("cow_id = ?", req.CowId).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Order("lact").
+		Find(&cowLactList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	data := &pasturePb.CowLactCurveData{
+		DateTime:            make(map[int32]string),
+		WeekAvgMilk:         make([]float32, 0),
+		DayMilk:             make([]float32, 0),
+		DHI:                 make([]float32, 0),
+		MilkProductionTrend: make([]float32, 0),
+		DayHigh:             make([]int32, 0),
+		DayRumina:           make([]int32, 0),
+		DayIntake:           make([]int32, 0),
+		DayInactive:         make([]int32, 0),
+		DayChew:             make([]int32, 0),
+		DayImmobility:       make([]int32, 0),
+		EstrusWarning:       make(map[int32]int32),
+	}
+
+	if len(cowLactList) <= 0 {
+		return &pasturePb.CowLactCurveResponse{
+			Code: http.StatusOK,
+			Msg:  "ok",
+			Data: data,
+		}, nil
+	}
+	starTime := ""
+	endTime := ""
+	cowLactMap := make(map[int32]*model.CowLact)
+	for _, v := range cowLactList {
+		cowLactMap[v.Lact] = v
+		if v.Lact == req.Lact {
+			starTime = v.StartTime
+		}
+	}
+	if st, ok := cowLactMap[req.Lact+1]; ok {
+		et, _ := util.TimeParseLocal(model.LayoutDate2, st.StartTime)
+		endTime = et.AddDate(0, 0, -1).Format(model.LayoutDate2)
+	} else {
+		endTime = time.Now().Local().Format(model.LayoutDate2)
+	}
+
+	neckRingList := make([]*model.NeckActiveHabit, 0)
+	if err = s.DB.Model(new(model.NeckActiveHabit)).
+		Where("neck_ring_number = ?", cowInfo.NeckRingNumber).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("cow_id > ?", 0).
+		Where("heat_date BETWEEN ? AND ?", starTime, endTime).
+		Order("heat_date, frameid").Find(&neckRingList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return &pasturePb.CowLactCurveResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: data,
+	}, nil
+}
+
+func (s *StoreEntry) BehaviorRate(ctx context.Context, req *pasturePb.CowBehaviorRateRequest) (*pasturePb.CowBehaviorRateResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	cowInfo, err := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, req.EarNumber)
+	if err != nil {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID:    "auth.errorCow",
+			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	if req.EndAt <= 0 || req.StartAt <= 0 || req.EndAt < req.StartAt {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: "auth.errorDateRange",
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	t1 := time.Unix(int64(req.StartAt), 0).Local().Format(model.LayoutDate2)
+	t2 := time.Unix(int64(req.EndAt), 0).Local().Format(model.LayoutDate2)
+
+	dataBetween, err := util.GetDaysBetween(t1, t2)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
+	if err = s.DB.Model(new(model.NeckActiveHabit)).
+		Select("heat_date,SUM(rumina) as rumina,SUM(intake) as intake,SUM(inactive) as inactive,SUM(gasp) AS gasp").
+		Where("neck_ring_number = ?", cowInfo.NeckRingNumber).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("cow_id > ?", 0).
+		Where("heat_date BETWEEN ? AND ?", t1, t2).
+		Order("heat_date").
+		Group("heat_date").
+		Find(&neckActiveHabitList).Error; err != nil {
+	}
+
+	cowList := make([]*model.Cow, 0)
+	if err = s.DB.Model(new(model.Cow)).
+		Where("neck_ring_number != ?", "").
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("pen_id = ?", cowInfo.PenId).
+		Find(&cowList).Error; err != nil {
+	}
+
+	neckRingNumbers := make([]string, 0)
+	for _, v := range cowList {
+		neckRingNumbers = append(neckRingNumbers, v.NeckRingNumber)
+	}
+
+	groupNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
+	if err = s.DB.Model(new(model.NeckActiveHabit)).
+		Select("heat_date,SUM(rumina) as rumina,SUM(intake) as intake,SUM(inactive) as inactive,SUM(gasp) AS gasp").
+		Where("neck_ring_number IN ?", neckRingNumbers).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("cow_id > ?", 0).
+		Where("heat_date BETWEEN ? AND ?", t1, t2).
+		Order("heat_date").
+		Group("heat_date").
+		Find(&groupNeckActiveHabitList).Error; err != nil {
+	}
+
+	return &pasturePb.CowBehaviorRateResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: model.NeckActiveHabitSlice(neckActiveHabitList).ToPB2(dataBetween, groupNeckActiveHabitList),
+	}, nil
+}
+
+func (s *StoreEntry) BehaviorCurveApp(ctx context.Context, req *pasturePb.CowBehaviorCurveRequest) (*pasturePb.CowNeckRingAppResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	if req.Days > model.NeckRingDataDays+10 {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: "validate.neckRingAppDays",
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	cowInfo, err := s.GetCowEventByEarNumber(ctx, userModel.AppPasture.Id, req.EarNumber)
+	if err != nil {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID:    "auth.errorCow",
+			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	nowTime := time.Now().Local()
+	nowDayZero := util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2))
+	endDataTime := nowTime.Format(model.LayoutDate2)
+	startDataTime := nowTime.AddDate(0, 0, int(-req.Days)+1).Format(model.LayoutDate2)
+
+	dayRange, err := util.GetDaysBetween(startDataTime, endDataTime)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	if len(dayRange) <= 0 {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: "auth.errorDateRange",
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	// 行为曲线数据
+	neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
+	if err = s.DB.Table(new(model.NeckActiveHabit).TableName()).
+		Where("neck_ring_number = ?", cowInfo.NeckRingNumber).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("is_show = ?", pasturePb.IsShow_Ok).
+		Where("cow_id > ?", 0).
+		Where("heat_date IN (?)", dayRange).
+		Order("heat_date, frameid").
+		Find(&neckActiveHabitList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	data := model.NeckActiveHabitSlice(neckActiveHabitList).ToPBApp()
+	eventMapList := s.EventTypeMap(userModel)
+	for k, v := range eventMapList {
+		if k == pasturePb.EventType_Enter || k == pasturePb.EventType_Body_Score || k == pasturePb.EventType_Birth ||
+			k == pasturePb.EventType_Weaning || k == pasturePb.EventType_Sale || k == pasturePb.EventType_Weight ||
+			k == pasturePb.EventType_Castrated || k == pasturePb.EventType_Perinatal_Transition || k == pasturePb.EventType_Insect_Repellent {
+			continue
+		}
+		data.EventMap = append(data.EventMap, &pasturePb.EventMap{
+			EventTypeKind: k,
+			EventTypeName: v,
+		})
+	}
+	data.LowActivity = model.LowActivity
+	data.MiddleActivity = model.MiddleActivity
+	// 牛只事件列表
+	eventLogList := make([]*model.EventCowLog, 0)
+	eventLog := &model.EventCowLog{CowId: cowInfo.Id}
+	if err = s.DB.Table(eventLog.TableName()).
+		Where("cow_id = ?", cowInfo.Id).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("event_at BETWEEN ? AND ?", nowDayZero-(int64(req.Days+1)*86400), nowDayZero).
+		Order("event_at").
+		Find(&eventLogList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	for _, v := range eventLogList {
+		if v.EventType == pasturePb.EventType_Enter || v.EventType == pasturePb.EventType_Body_Score ||
+			v.EventType == pasturePb.EventType_Birth || v.EventType == pasturePb.EventType_Weaning ||
+			v.EventType == pasturePb.EventType_Sale || v.EventType == pasturePb.EventType_Weight ||
+			v.EventType == pasturePb.EventType_Castrated {
+			continue
+		}
+
+		if v.EventAt <= 0 {
+			continue
+		}
+
+		eventAt := time.Unix(v.EventAt, 0).Local()
+		data.EventList = append(data.EventList, &pasturePb.EventDetail{
+			EventTypeKind:    v.EventType,
+			EventTypeName:    v.EventTypeName,
+			EventDescription: v.EventDescription,
+			EventAtFormat:    fmt.Sprintf("%s 09", eventAt.Format(model.LayoutDate2)),
+		})
+	}
+
+	// 发情数据
+	estrusList := make([]*model.NeckRingEstrus, 0)
+	if err = s.DB.Model(new(model.NeckRingEstrus)).
+		Select("id,active_level,MAX(active_time) AS active_time,is_peak").
+		Where("cow_id = ?", cowInfo.Id).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("active_time BETWEEN ? AND ?", fmt.Sprintf("%s 00:00:00", startDataTime), fmt.Sprintf("%s 23:59:59", endDataTime)).
+		Where("is_peak = ?", pasturePb.IsShow_Ok).
+		Group("first_time").
+		Find(&estrusList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	for _, v := range estrusList {
+		if data.EstrusList == nil {
+			data.EstrusList = make([]string, 0)
+		}
+		data.EstrusList = append(data.EstrusList, strings.TrimSuffix(v.ActiveTime, ":00:00")+fmt.Sprintf("/%d", v.ActiveLevel))
+	}
+
+	return &pasturePb.CowNeckRingAppResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: data,
+	}, nil
+}
+
+func (s *StoreEntry) BehaviorCurveGroupComparison(ctx context.Context, req *pasturePb.CowBehaviorCurveRequest) (*pasturePb.BehaviorCurveGroupComparisonResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	if req.Days > model.NeckRingDataDays+10 {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: "validate.neckRingAppDays",
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	cowInfo, err := s.GetCowEventByEarNumber(ctx, userModel.AppPasture.Id, req.EarNumber)
+	if err != nil {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID:    "auth.errorCow",
+			TemplateData: map[string]interface{}{"earNumber": req.EarNumber},
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	nowTime := time.Now().Local()
+	endDataTime := nowTime.Format(model.LayoutDate2)
+	startDataTime := nowTime.AddDate(0, 0, int(-req.Days)+1).Format(model.LayoutDate2)
+
+	dayRange, err := util.GetDaysBetween(startDataTime, endDataTime)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	if len(dayRange) <= 0 {
+		messageId, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+			MessageID: "auth.errorDateRange",
+		})
+		return nil, xerr.Customf(messageId)
+	}
+
+	// 行为曲线数据
+	neckActiveHabitList := make([]*model.NeckActiveHabit, 0)
+	if err = s.DB.Table(new(model.NeckActiveHabit).TableName()).
+		Where("neck_ring_number = ?", cowInfo.NeckRingNumber).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("is_show = ?", pasturePb.IsShow_Ok).
+		Where("cow_id > ?", 0).
+		Where("heat_date IN (?)", dayRange).
+		Order("heat_date, frameid").
+		Find(&neckActiveHabitList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	originalDataList, dataTimeList := model.NeckActiveHabitSlice(neckActiveHabitList).ToOriginalDataList(req.CurveName)
+	q1, q3 := s.CowIQR(cowInfo, req.CurveName, dayRange, dataTimeList)
+	return &pasturePb.BehaviorCurveGroupComparisonResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &pasturePb.CowNeckRingGroupComparisonData{
+			DateTime:         dataTimeList,
+			OriginalDataList: originalDataList,
+			IQR1:             q1,
+			IQR3:             q3,
+		},
+	}, nil
+}

+ 8 - 33
module/backend/dashboard.go

@@ -190,13 +190,13 @@ func (s *StoreEntry) DataWarningPop(ctx context.Context, req *pasturePb.WarningD
 		zaplog.Error("UpdateWarningData", zap.Any("err", err), zap.Any("query", query), zap.Any("params", params))
 	}
 
-	cowTypeMap := s.CowTypeMap()
-	breedStatusMap := s.CowBreedStatusMap()
-	cowKindMap := s.CowKindMap()
-	cowSourceMap := s.CowSourceMap()
-	admissionStatusMap := s.AdmissionStatusMap()
-	healthStatusMap := s.HealthStatusMap()
-	purposeMap := s.PurposeMap()
+	cowTypeMap := s.CowTypeMap(userModel)
+	breedStatusMap := s.CowBreedStatusMap(userModel)
+	cowKindMap := s.CowKindMap(userModel)
+	cowSourceMap := s.CowSourceMap(userModel)
+	admissionStatusMap := s.AdmissionStatusMap(userModel)
+	healthStatusMap := s.HealthStatusMap(userModel)
+	purposeMap := s.PurposeMap(userModel)
 	resp.Data.Total = int32(count)
 	systemBasic, err := s.GetSystemBasicByName(ctx, userModel.AppPasture.Id, model.PregnancyAge)
 	if err != nil {
@@ -229,38 +229,13 @@ func (s *StoreEntry) FindDataWarningItems(pastureId, userId int64) ([]*model.Dat
 	if err := s.DB.Model(new(model.DataWarningItems)).
 		Where("pasture_id = ?", pastureId).
 		Where("user_id = ?", userId).
+		Order("warning_id ASC").
 		Find(&dataWarningItemsList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
 	return dataWarningItemsList, nil
 }
 
-/*func (s *StoreEntry) FindDataWarningMap(ctx context.Context, pastureId, userId int64) (map[int64]*model.DataWarning, error) {
-	dataWarning, err := s.FindDataWarning(ctx, pastureId, userId)
-	if err != nil {
-		return nil, xerr.Custom("默认预警数据有误,请联系管理员!")
-	}
-	dataWarningMap := make(map[int64]*model.DataWarning)
-	for _, v := range dataWarning {
-		dataWarningMap[v.Id] = v
-	}
-	return dataWarningMap, nil
-}
-
-func (s *StoreEntry) FindDataWarningItemsMap(ctx context.Context, userId int64) (map[int64]*model.DataWarningItems, error) {
-	dataWarningItemsList := make([]*model.DataWarningItems, 0)
-	if err := s.DB.Model(new(model.DataWarningItems)).
-		Where("user_id = ?", userId).
-		Find(&dataWarningItemsList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	dataWarningItemsMap := make(map[int64]*model.DataWarningItems)
-	for _, v := range dataWarningItemsList {
-		dataWarningItemsMap[v.Id] = v
-	}
-	return dataWarningItemsMap, nil
-}*/
-
 // UpdateWarningData 更新计算数据
 func (s *StoreEntry) UpdateWarningData(userModel *model.UserModel, needUpdateWarningIds []int64) {
 	if len(needUpdateWarningIds) <= 0 {

+ 2 - 2
module/backend/dashboard_more.go

@@ -280,14 +280,14 @@ func (s *StoreEntry) Equipment(ctx context.Context) (*pasturePb.EquipmentRespons
 	}
 
 	equipmentList = append(equipmentList, &pasturePb.Equipment{
-		Name:           "异常脖环数",
+		Name:           "脖环佩戴数",
 		Describe:       "脖环",
 		NormalNumber:   normalNumber,
 		AbnormalNumber: abnormalNumber,
 		Icon:           "/assets/welcome/ring@2x.png",
 		Kind:           pasturePb.EquipmentType_Neck_Ring,
 	}, &pasturePb.Equipment{
-		Name:           "离线接收器",
+		Name:           "接收器数量",
 		Describe:       "接收器",
 		NormalNumber:   int32(receiverCount),
 		AbnormalNumber: int32(0),

+ 133 - 104
module/backend/enum_map.go

@@ -1,136 +1,173 @@
 package backend
 
-import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+import (
+	"kpt-pasture/model"
 
-func (s *StoreEntry) DrugCategoryMaps() map[pasturePb.DrugCategory_Kind]string {
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+)
+
+func (s *StoreEntry) DrugCategoryMaps(userModel *model.UserModel) map[pasturePb.DrugCategory_Kind]string {
 	res := make(map[pasturePb.DrugCategory_Kind]string)
-	for _, v := range s.DrugCategoryEnumList("") {
+	for _, v := range s.DrugCategoryEnumList(userModel, "") {
 		res[pasturePb.DrugCategory_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) DrugUsageMaps() map[pasturePb.DrugUsage_Kind]string {
+func (s *StoreEntry) DrugUsageMaps(userModel *model.UserModel) map[pasturePb.DrugUsage_Kind]string {
 	res := make(map[pasturePb.DrugUsage_Kind]string)
-	for _, v := range s.DrugUsageEnumList("") {
+	for _, v := range s.DrugUsageEnumList(userModel, "") {
 		res[pasturePb.DrugUsage_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) ExposeEstrusTypeMap() map[pasturePb.ExposeEstrusType_Kind]string {
+func (s *StoreEntry) ExposeEstrusTypeMap(userModel *model.UserModel) map[pasturePb.ExposeEstrusType_Kind]string {
 	res := make(map[pasturePb.ExposeEstrusType_Kind]string)
-	for _, v := range s.ExposeEstrusTypeEnumList("") {
+	for _, v := range s.ExposeEstrusTypeEnumList(userModel, "") {
 		res[pasturePb.ExposeEstrusType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) FrozenSemenTypeMap() map[pasturePb.FrozenSemenType_Kind]string {
+func (s *StoreEntry) FrozenSemenTypeMap(userModel *model.UserModel) map[pasturePb.FrozenSemenType_Kind]string {
 	res := make(map[pasturePb.FrozenSemenType_Kind]string)
-	for _, v := range s.FrozenSemenTypeEnumList("") {
+	for _, v := range s.FrozenSemenTypeEnumList(userModel, "") {
 		res[pasturePb.FrozenSemenType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) UnitMap() map[pasturePb.Unit_Kind]string {
+func (s *StoreEntry) UnitMap(userModel *model.UserModel) map[pasturePb.Unit_Kind]string {
 	res := make(map[pasturePb.Unit_Kind]string)
-	for _, v := range s.UnitEnumList("") {
+	for _, v := range s.UnitEnumList(userModel, "") {
 		res[pasturePb.Unit_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) WeekMap() map[pasturePb.Week_Kind]string {
+func (s *StoreEntry) WeekMap(userModel *model.UserModel) map[pasturePb.Week_Kind]string {
 	res := make(map[pasturePb.Week_Kind]string)
-	for _, v := range s.WeekEnumList("") {
+	for _, v := range s.WeekEnumList(userModel, "") {
 		res[pasturePb.Week_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) MonthMap() map[int32]string {
+func (s *StoreEntry) MonthMap(userModel *model.UserModel) map[int32]string {
 	res := make(map[int32]string)
-	for _, v := range s.MonthEnumList("") {
+	for _, v := range s.MonthEnumList(userModel, "") {
 		res[v.Value] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CowTypeMap() map[pasturePb.CowType_Kind]string {
+func (s *StoreEntry) CowTypeMap(userModel *model.UserModel) map[pasturePb.CowType_Kind]string {
 	res := make(map[pasturePb.CowType_Kind]string)
 	optionName, isAll := "", ""
-	for _, v := range s.CowTypeEnumList(optionName, isAll) {
+	for _, v := range s.CowTypeEnumList(userModel, optionName, isAll) {
 		res[pasturePb.CowType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CowBreedStatusMap() map[pasturePb.BreedStatus_Kind]string {
+func (s *StoreEntry) CowTypeMap2(userModel *model.UserModel) map[string]pasturePb.CowType_Kind {
+	res := make(map[string]pasturePb.CowType_Kind)
+	optionName, isAll := "", ""
+	for _, v := range s.CowTypeEnumList(userModel, optionName, isAll) {
+		res[v.Label] = pasturePb.CowType_Kind(v.Value)
+	}
+	return res
+}
+
+func (s *StoreEntry) CowBreedStatusMap(userModel *model.UserModel) map[pasturePb.BreedStatus_Kind]string {
 	res := make(map[pasturePb.BreedStatus_Kind]string)
-	for _, v := range s.BreedStatusEnumList() {
+	for _, v := range s.BreedStatusEnumList(userModel, "") {
 		res[pasturePb.BreedStatus_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CowKindMap() map[pasturePb.CowKind_Kind]string {
+func (s *StoreEntry) CowKindMap(userModel *model.UserModel) map[pasturePb.CowKind_Kind]string {
 	res := make(map[pasturePb.CowKind_Kind]string)
-	for _, v := range s.CowKindEnumList() {
+	for _, v := range s.CowKindEnumList(userModel, "") {
 		res[pasturePb.CowKind_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CowSourceMap() map[pasturePb.CowSource_Kind]string {
+func (s *StoreEntry) CowKindMap2(userModel *model.UserModel) map[string]pasturePb.CowKind_Kind {
+	res := make(map[string]pasturePb.CowKind_Kind)
+	for _, v := range s.CowKindEnumList(userModel, "") {
+		res[v.Label] = pasturePb.CowKind_Kind(v.Value)
+	}
+	return res
+}
+
+func (s *StoreEntry) CowSourceMap(userModel *model.UserModel) map[pasturePb.CowSource_Kind]string {
 	res := make(map[pasturePb.CowSource_Kind]string)
-	for _, v := range s.CowSourceEnumList() {
+	for _, v := range s.CowSourceEnumList(userModel, "") {
 		res[pasturePb.CowSource_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) WorkOrderCategoryMap() map[pasturePb.WorkOrderCategory_Kind]string {
+func (s *StoreEntry) CowSourceMap2(userModel *model.UserModel) map[string]pasturePb.CowSource_Kind {
+	res := make(map[string]pasturePb.CowSource_Kind)
+	for _, v := range s.CowSourceEnumList(userModel, "") {
+		res[v.Label] = pasturePb.CowSource_Kind(v.Value)
+	}
+	return res
+}
+
+func (s *StoreEntry) WorkOrderCategoryMap(userModel *model.UserModel) map[pasturePb.WorkOrderCategory_Kind]string {
 	res := make(map[pasturePb.WorkOrderCategory_Kind]string)
-	for _, v := range s.WorkOrderCategoryEnumList("") {
+	for _, v := range s.WorkOrderCategoryEnumList(userModel, "") {
 		res[pasturePb.WorkOrderCategory_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) WorkOrderFrequencyMap() map[pasturePb.WorkOrderFrequency_Kind]string {
+func (s *StoreEntry) WorkOrderFrequencyMap(userModel *model.UserModel) map[pasturePb.WorkOrderFrequency_Kind]string {
 	res := make(map[pasturePb.WorkOrderFrequency_Kind]string)
-	for _, v := range s.WorkOrderFrequencyEnumList("") {
+	for _, v := range s.WorkOrderFrequencyEnumList(userModel, "") {
 		res[pasturePb.WorkOrderFrequency_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) WorkOrderSubUnitMap() map[pasturePb.WorkOrderSubscribeUnit_Kind]string {
+func (s *StoreEntry) WorkOrderSubUnitMap(userModel *model.UserModel) map[pasturePb.WorkOrderSubscribeUnit_Kind]string {
 	res := make(map[pasturePb.WorkOrderSubscribeUnit_Kind]string)
-	for _, v := range s.WorkOrderSubUnitEnumList("") {
+	for _, v := range s.WorkOrderSubUnitEnumList(userModel, "") {
 		res[pasturePb.WorkOrderSubscribeUnit_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) WorkOrderPriorityMap() map[pasturePb.Priority_Kind]string {
+func (s *StoreEntry) WorkOrderPriorityMap(userModel *model.UserModel) map[pasturePb.Priority_Kind]string {
 	res := make(map[pasturePb.Priority_Kind]string)
-	for _, v := range s.WorkOrderPriorityEnumList("") {
+	for _, v := range s.WorkOrderPriorityEnumList(userModel, "") {
 		res[pasturePb.Priority_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) SameTimeCowTypeMap() map[pasturePb.SameTimeCowType_Kind]string {
+func (s *StoreEntry) SameTimeCowTypeMap(userModel *model.UserModel) map[pasturePb.SameTimeCowType_Kind]string {
 	res := make(map[pasturePb.SameTimeCowType_Kind]string)
-	for _, v := range s.SameTimeCowTypeEnumList("") {
+	for _, v := range s.SameTimeCowTypeEnumList(userModel, "") {
 		res[pasturePb.SameTimeCowType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
+func (s *StoreEntry) CalendarTypeMap(userModel *model.UserModel) map[pasturePb.CalendarType_Kind]string {
+	res := make(map[pasturePb.CalendarType_Kind]string)
+	for _, v := range s.CalendarTypeEnumList(userModel, "") {
+		res[pasturePb.CalendarType_Kind(v.Value)] = v.Label
+	}
+	return res
+}
+
 func CalendarTypeMap() map[pasturePb.CalendarType_Kind]string {
 	res := make(map[pasturePb.CalendarType_Kind]string)
 	for _, v := range CalendarTypeEnumList("") {
@@ -139,49 +176,57 @@ func CalendarTypeMap() map[pasturePb.CalendarType_Kind]string {
 	return res
 }
 
-func (s *StoreEntry) AbortionReasonsMap() map[pasturePb.AbortionReasons_Kind]string {
+func (s *StoreEntry) AbortionReasonsMap(userModel *model.UserModel) map[pasturePb.AbortionReasons_Kind]string {
 	res := make(map[pasturePb.AbortionReasons_Kind]string)
-	for _, v := range s.AbortionReasonsEnumList("") {
+	for _, v := range s.AbortionReasonsEnumList(userModel, "") {
 		res[pasturePb.AbortionReasons_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) PregnantCheckMethodMap() map[pasturePb.PregnantCheckMethod_Kind]string {
+func (s *StoreEntry) PregnantCheckMethodMap(userModel *model.UserModel) map[pasturePb.PregnantCheckMethod_Kind]string {
 	res := make(map[pasturePb.PregnantCheckMethod_Kind]string)
-	for _, v := range s.PregnantCheckMethodEnumList("") {
+	for _, v := range s.PregnantCheckMethodEnumList(userModel, "") {
 		res[pasturePb.PregnantCheckMethod_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) PregnantCheckResultMap() map[pasturePb.PregnantCheckResult_Kind]string {
+func (s *StoreEntry) PregnantCheckResultMap(userModel *model.UserModel) map[pasturePb.PregnantCheckResult_Kind]string {
 	res := make(map[pasturePb.PregnantCheckResult_Kind]string)
-	for _, v := range s.PregnantCheckResultEnumList("") {
+	for _, v := range s.PregnantCheckResultEnumList(userModel, "") {
 		res[pasturePb.PregnantCheckResult_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) HealthStatusMap() map[pasturePb.HealthStatus_Kind]string {
+func (s *StoreEntry) HealthStatusMap(userModel *model.UserModel) map[pasturePb.HealthStatus_Kind]string {
 	res := make(map[pasturePb.HealthStatus_Kind]string)
-	for _, v := range s.HealthStatusEnumList("") {
+	for _, v := range s.HealthStatusEnumList(userModel, "") {
 		res[pasturePb.HealthStatus_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) PurposeMap() map[pasturePb.Purpose_Kind]string {
+func (s *StoreEntry) PurposeMap(userModel *model.UserModel) map[pasturePb.Purpose_Kind]string {
 	res := make(map[pasturePb.Purpose_Kind]string)
-	for _, v := range s.CowPurposeList("") {
+	for _, v := range s.CowPurposeList(userModel, "") {
 		res[pasturePb.Purpose_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) DiseaseTypeMap() map[int32]string {
+func (s *StoreEntry) PurposeMap2(userModel *model.UserModel) map[string]pasturePb.Purpose_Kind {
+	res := make(map[string]pasturePb.Purpose_Kind)
+	for _, v := range s.CowPurposeList(userModel, "") {
+		res[v.Label] = pasturePb.Purpose_Kind(v.Value)
+	}
+	return res
+}
+
+func (s *StoreEntry) DiseaseTypeMap(userModel *model.UserModel) map[int32]string {
 	res := make(map[int32]string)
-	for _, v := range s.diseaseTypeEnumList("") {
+	for _, v := range s.diseaseTypeEnumList(userModel, "") {
 		res[v.Value] = v.Label
 	}
 	return res
@@ -199,177 +244,161 @@ func (s *StoreEntry) MultiFactorAnalysisMethodMap() map[pasturePb.MultiFactorAna
 	}
 }
 
-func (s *StoreEntry) NeckRingIsBindMap() map[pasturePb.NeckRingIsBind_Kind]string {
+func (s *StoreEntry) NeckRingIsBindMap(userModel *model.UserModel) map[pasturePb.NeckRingIsBind_Kind]string {
 	res := make(map[pasturePb.NeckRingIsBind_Kind]string)
-	for _, v := range s.NeckRingIsBindEnumList("") {
+	for _, v := range s.NeckRingIsBindEnumList(userModel, "") {
 		res[pasturePb.NeckRingIsBind_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) NeckRingStatusMap() map[pasturePb.NeckRingStatus_Kind]string {
+func (s *StoreEntry) NeckRingStatusMap(userModel *model.UserModel) map[pasturePb.NeckRingStatus_Kind]string {
 	res := make(map[pasturePb.NeckRingStatus_Kind]string)
-	for _, v := range s.NeckRingStatusEnumList("") {
+	for _, v := range s.NeckRingStatusEnumList(userModel, "") {
 		res[pasturePb.NeckRingStatus_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) SaleCowAnalysisMap() map[pasturePb.SaleCowAnalysisMethod_Kind]string {
+func (s *StoreEntry) SaleCowAnalysisMap(userModel *model.UserModel) map[pasturePb.SaleCowAnalysisMethod_Kind]string {
 	res := make(map[pasturePb.SaleCowAnalysisMethod_Kind]string)
-	for _, v := range s.SaleCowAnalysisMethodEnumList("") {
+	for _, v := range s.SaleCowAnalysisMethodEnumList(userModel, "") {
 		res[pasturePb.SaleCowAnalysisMethod_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) OutTypeMap() map[pasturePb.OutType_Kind]string {
+func (s *StoreEntry) OutTypeMap(userModel *model.UserModel) map[pasturePb.OutType_Kind]string {
 	res := make(map[pasturePb.OutType_Kind]string)
-	for _, v := range s.OutTypeEnumList("") {
+	for _, v := range s.OutTypeEnumList(userModel, "") {
 		res[pasturePb.OutType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) AuditStatusMap() map[pasturePb.AuditStatus_Kind]string {
+func (s *StoreEntry) AuditStatusMap(userModel *model.UserModel) map[pasturePb.AuditStatus_Kind]string {
 	res := make(map[pasturePb.AuditStatus_Kind]string)
-	for _, v := range s.AuditStatusEnumList("") {
+	for _, v := range s.AuditStatusEnumList(userModel, "") {
 		res[pasturePb.AuditStatus_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) AdmissionStatusMap() map[pasturePb.AdmissionStatus_Kind]string {
+func (s *StoreEntry) AdmissionStatusMap(userModel *model.UserModel) map[pasturePb.AdmissionStatus_Kind]string {
 	res := make(map[pasturePb.AdmissionStatus_Kind]string)
-	for _, v := range s.AdmissionStatusEnumList("") {
+	for _, v := range s.AdmissionStatusEnumList(userModel, "") {
 		res[pasturePb.AdmissionStatus_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) SameTimeTypeMap() map[pasturePb.SameTimeType_Kind]string {
+func (s *StoreEntry) SameTimeTypeMap(userModel *model.UserModel) map[pasturePb.SameTimeType_Kind]string {
 	res := make(map[pasturePb.SameTimeType_Kind]string)
-	for _, v := range s.SameTimeTypeEnumList("") {
+	for _, v := range s.SameTimeTypeEnumList(userModel, "") {
 		res[pasturePb.SameTimeType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) EventTypeMap() map[pasturePb.EventType_Kind]string {
+func (s *StoreEntry) EventTypeMap(userModel *model.UserModel) map[pasturePb.EventType_Kind]string {
 	res := make(map[pasturePb.EventType_Kind]string)
-	for _, v := range s.EventTypeEnumList("") {
+	for _, v := range s.EventTypeEnumList(userModel, "") {
 		res[pasturePb.EventType_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CalvingLevelMap() map[pasturePb.CalvingLevel_Kind]string {
+func (s *StoreEntry) CalvingLevelMap(userModel *model.UserModel) map[pasturePb.CalvingLevel_Kind]string {
 	res := make(map[pasturePb.CalvingLevel_Kind]string)
-	for _, v := range s.CalvingLevelEnumList("") {
+	for _, v := range s.CalvingLevelEnumList(userModel, "") {
 		res[pasturePb.CalvingLevel_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) DystociaReasonMap() map[pasturePb.DystociaReason_Kind]string {
+func (s *StoreEntry) DystociaReasonMap(userModel *model.UserModel) map[pasturePb.DystociaReason_Kind]string {
 	res := make(map[pasturePb.DystociaReason_Kind]string)
-	for _, v := range s.DystociaReasonEnumList("") {
+	for _, v := range s.DystociaReasonEnumList(userModel, "") {
 		res[pasturePb.DystociaReason_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) DeadReasonMap() map[pasturePb.DeathReason_Kind]string {
+func (s *StoreEntry) DeadReasonMap(userModel *model.UserModel) map[pasturePb.DeathReason_Kind]string {
 	res := make(map[pasturePb.DeathReason_Kind]string)
-	for _, v := range s.DeathReasonEnumList("") {
+	for _, v := range s.DeathReasonEnumList(userModel, "") {
 		res[pasturePb.DeathReason_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) OutReasonMap() map[pasturePb.OutReasons_Kind]string {
-	res := make(map[pasturePb.OutReasons_Kind]string)
-	for _, v := range s.OutReasonEnumList("") {
-		res[pasturePb.OutReasons_Kind(v.Value)] = v.Label
-	}
-	return res
-}
-
-func (s *StoreEntry) MatingResultMap() map[pasturePb.MatingResult_Kind]string {
+func (s *StoreEntry) MatingResultMap(userModel *model.UserModel) map[pasturePb.MatingResult_Kind]string {
 	res := make(map[pasturePb.MatingResult_Kind]string)
-	for _, v := range s.MatingResultEnumList("") {
+	for _, v := range s.MatingResultEnumList(userModel, "") {
 		res[pasturePb.MatingResult_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) EventCategoryMap() map[pasturePb.EventCategory_Kind]string {
+func (s *StoreEntry) EventCategoryMap(userModel *model.UserModel) map[pasturePb.EventCategory_Kind]string {
 	res := make(map[pasturePb.EventCategory_Kind]string)
-	for _, v := range s.EventCategoryEnumList("") {
+	for _, v := range s.EventCategoryEnumList(userModel, "") {
 		res[pasturePb.EventCategory_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) GroupTransferReasonMap() map[int32]string {
+func (s *StoreEntry) GroupTransferReasonMap(userModel *model.UserModel) map[int32]string {
 	res := make(map[int32]string)
-	for _, v := range s.TransferPenEnumList("") {
+	for _, v := range s.TransferPenEnumList(userModel, "") {
 		res[v.Value] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) BarnTypeMap() map[pasturePb.PenType_Kind]string {
-	return map[pasturePb.PenType_Kind]string{
-		pasturePb.PenType_Lactating_Calves: "哺乳牛舍",
-		pasturePb.PenType_Weaned_Calves:    "断奶牛舍",
-		pasturePb.PenType_Youth:            "青年牛舍",
-		pasturePb.PenType_Nurturing:        "育成牛舍",
-		pasturePb.PenType_Lactation:        "成母牛舍",
-		pasturePb.PenType_Peripartum:       "围产牛舍",
-		pasturePb.PenType_Dry_Milking:      "干奶牛舍",
-		pasturePb.PenType_Sick_Cow:         "病牛牛舍",
-		pasturePb.PenType_Out:              "淘汰牛舍",
-		pasturePb.PenType_Segregate:        "隔离牛舍",
-		pasturePb.PenType_Bull:             "公牛牛舍",
+func (s *StoreEntry) BarnTypeMap(userModel *model.UserModel) map[pasturePb.PenType_Kind]string {
+	res := make(map[pasturePb.PenType_Kind]string)
+	for _, v := range s.BarnTypeEnumList(userModel, nil, "") {
+		res[pasturePb.PenType_Kind(v.Value)] = v.Label
 	}
+	return res
 }
 
-func (s *StoreEntry) UnMatingReasonsMap() map[pasturePb.UnMatingReasons_Kind]string {
+func (s *StoreEntry) UnMatingReasonsMap(userModel *model.UserModel) map[pasturePb.UnMatingReasons_Kind]string {
 	res := make(map[pasturePb.UnMatingReasons_Kind]string)
-	for _, v := range s.UnMatingReasonsEnumList("") {
+	for _, v := range s.UnMatingReasonsEnumList(userModel, "") {
 		res[pasturePb.UnMatingReasons_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) ForbiddenMatingReasonsMap() map[pasturePb.ForbiddenMatingReasons_Kind]string {
+func (s *StoreEntry) ForbiddenMatingReasonsMap(userModel *model.UserModel) map[pasturePb.ForbiddenMatingReasons_Kind]string {
 	res := make(map[pasturePb.ForbiddenMatingReasons_Kind]string)
-	for _, v := range s.ForbiddenMatingReasonsEnumList("") {
+	for _, v := range s.ForbiddenMatingReasonsEnumList(userModel, "") {
 		res[pasturePb.ForbiddenMatingReasons_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CowOutReasonsMap() map[pasturePb.OutReasons_Kind]string {
+func (s *StoreEntry) CowOutReasonsMap(userModel *model.UserModel) map[pasturePb.OutReasons_Kind]string {
 	res := make(map[pasturePb.OutReasons_Kind]string)
-	for _, v := range s.CowOutReasonList("") {
+	for _, v := range s.CowOutReasonEnumList(userModel, "") {
 		res[pasturePb.OutReasons_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) CowDeathDestinationMap() map[pasturePb.DeathDestination_Kind]string {
+func (s *StoreEntry) CowDeathDestinationMap(userModel *model.UserModel) map[pasturePb.DeathDestination_Kind]string {
 	res := make(map[pasturePb.DeathDestination_Kind]string)
-	for _, v := range s.CowDeathDestinationList("") {
+	for _, v := range s.CowDeathDestinationList(userModel, "") {
 		res[pasturePb.DeathDestination_Kind(v.Value)] = v.Label
 	}
 	return res
 }
 
-func (s *StoreEntry) WarningHealthLevelMap() map[pasturePb.WarningHealthLevel_Kind]string {
+func (s *StoreEntry) WarningHealthLevelMap(userModel *model.UserModel) map[pasturePb.WarningHealthLevel_Kind]string {
 	res := make(map[pasturePb.WarningHealthLevel_Kind]string)
-	for _, v := range s.WarningHealthLevel("") {
+	for _, v := range s.WarningHealthLevel(userModel, "") {
 		res[pasturePb.WarningHealthLevel_Kind(v.Value)] = v.Label
 	}
 	return res

+ 41 - 14
module/backend/enum_options.go

@@ -25,7 +25,7 @@ func (s *StoreEntry) BarnTypeOptions(ctx context.Context) (*pasturePb.ConfigOpti
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.BarnTypeEnumList(excludeTypes),
+		Data: s.BarnTypeEnumList(userModel, excludeTypes, ""),
 	}, nil
 }
 
@@ -51,7 +51,7 @@ func (s *StoreEntry) BarnListOptions(ctx context.Context, penType int, isAll str
 		excludeTypes = append(excludeTypes, pasturePb.PenType_Dry_Milking, pasturePb.PenType_Peripartum)
 	}
 
-	barnTypeList := s.BarnTypeEnumList(excludeTypes)
+	barnTypeList := s.BarnTypeEnumList(userModel, excludeTypes, "")
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -67,6 +67,7 @@ func (s *StoreEntry) DiseaseTypeOptions(ctx context.Context, isChildren string)
 	diseaseTypeList := make([]*model.ConfigDiseaseType, 0)
 	if err = s.DB.Table(new(model.ConfigDiseaseType).TableName()).
 		Where("is_show =? ", pasturePb.IsShow_Ok).
+		Order("kind ASC").
 		Find(&diseaseTypeList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
@@ -84,7 +85,7 @@ func (s *StoreEntry) DiseaseTypeOptions(ctx context.Context, isChildren string)
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: model.ConfigDiseaseTypeSlice(diseaseTypeList).ToPB2(diseaseList),
+		Data: model.ConfigDiseaseTypeSlice(diseaseTypeList).ToPB2(userModel, diseaseList),
 	}, nil
 }
 
@@ -129,41 +130,62 @@ func (s *StoreEntry) PrescriptionOptions(ctx context.Context) (*pasturePb.Config
 }
 
 func (s *StoreEntry) BreedStatusOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.BreedStatusEnumList(),
+		Data: s.BreedStatusEnumList(userModel, ""),
 	}, nil
 }
 func (s *StoreEntry) CowKindOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.CowKindEnumList(),
+		Data: s.CowKindEnumList(userModel, ""),
 	}, nil
 }
 
 func (s *StoreEntry) CowSourceOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.CowSourceEnumList(),
+		Data: s.CowSourceEnumList(userModel, ""),
 	}, nil
 }
 
 func (s *StoreEntry) CowTypeOptions(ctx context.Context, optionName, isAll string) (*pasturePb.ConfigOptionsListResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.CowTypeEnumList(optionName, isAll),
+		Data: s.CowTypeEnumList(userModel, optionName, isAll),
 	}, nil
 }
 
 func (s *StoreEntry) CowTransferPenReasonOptions(ctx context.Context) (*pasturePb.ConfigOptionsListResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	return &pasturePb.ConfigOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.TransferPenEnumList(""),
+		Data: s.TransferPenEnumList(userModel, ""),
 	}, nil
 }
 
@@ -236,15 +258,20 @@ func (s *StoreEntry) BullOptions(ctx context.Context) (*pasturePb.BullOptionsLis
 	return &pasturePb.BullOptionsListResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: s.BullNumberEnumList("", userModel.AppPasture.Id),
+		Data: s.BullNumberEnumList(userModel, ""),
 	}, nil
 }
 
 func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName, isAll string) (*pasturePb.ConfigOptionsListResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
 	if optionsName == "" {
 		return nil, xerr.New("optionsName is empty")
 	}
-	getConfigFuncMap := map[string]func(isAll string) []*pasturePb.ConfigOptionsList{
+	getConfigFuncMap := map[string]func(userModel *model.UserModel, isAll string) []*pasturePb.ConfigOptionsList{
 		"childNumber":                s.ChildNumberEnumList,
 		"calvingLevel":               s.CalvingLevelEnumList,
 		"dystociaReason":             s.DystociaReasonEnumList,
@@ -267,7 +294,7 @@ func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName, i
 		"immunizationConditions":     s.ImmunizationConditionsEnumList,
 		"abortionReasons":            s.AbortionReasonsEnumList,
 		"healthStatus":               s.HealthStatusEnumList,
-		"calendarType":               CalendarTypeEnumList,
+		"calendarType":               s.CalendarTypeEnumList,
 		"calvingAnalysisMethod":      s.CalvingAnalysisMethodEnumList,
 		"lact":                       s.LactEnumList,
 		"diseaseAnalysisMethod":      s.DiseaseAnalysisMethodEnumList,
@@ -281,13 +308,13 @@ func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName, i
 		"pregnantCheckName":          s.PregnantCheckNameEnumList,
 		"unMatingReasons":            s.UnMatingReasonsEnumList,
 		"evenType":                   s.EventTypeEnumList,
-		"outReason":                  s.OutReasonEnumList,
+		"outReason":                  s.CowOutReasonEnumList,
 		"deathReason":                s.DeathReasonEnumList,
 		"categoryKind":               s.EventCategoryEnumList,
 		"indicatorsDetails":          s.IndicatorsDetailsList,
 		"purposeKind":                s.CowPurposeList,
 		"forbiddenMatingReasons":     s.ForbiddenMatingReasonsEnumList,
-		"cowOutReason":               s.CowOutReasonList,
+		"cowOutReason":               s.CowOutReasonEnumList,
 		"deathDestination":           s.CowDeathDestinationList,
 		"warningHealthLevel":         s.WarningHealthLevel,
 		"behavior":                   s.Behavior,
@@ -301,7 +328,7 @@ func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName, i
 		return nil, fmt.Errorf("invalid optionsName: %s", optionsName)
 	}
 
-	configOptions := getConfigFunc(isAll)
+	configOptions := getConfigFunc(userModel, isAll)
 	if configOptions == nil {
 		return nil, fmt.Errorf("failed to retrieve configOptions for %s", optionsName)
 	}

+ 70 - 5
module/backend/event_base.go

@@ -70,10 +70,10 @@ func (s *StoreEntry) EnterList(ctx context.Context, req *pasturePb.SearchEventRe
 	}
 
 	penMap := s.PenMap(ctx, userModel.AppPasture.Id)
-	breedStatusMap := s.CowBreedStatusMap()
-	cowSourceMap := s.CowSourceMap()
-	cowTypeMap := s.CowTypeMap()
-	cowKindMap := s.CowKindMap()
+	breedStatusMap := s.CowBreedStatusMap(userModel)
+	cowSourceMap := s.CowSourceMap(userModel)
+	cowTypeMap := s.CowTypeMap(userModel)
+	cowKindMap := s.CowKindMap(userModel)
 
 	return &pasturePb.SearchEnterEventResponse{
 		Code: http.StatusOK,
@@ -171,6 +171,71 @@ func (s *StoreEntry) CreateEnter(ctx context.Context, req *pasturePb.EventEnterR
 	return nil
 }
 
+func (s *StoreEntry) ExcelImportEnter(ctx context.Context, req *pasturePb.EventEnterRequest) (err error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	if err = s.EnterCheck(userModel, req); err != nil {
+		return xerr.WithStack(err)
+	}
+
+	pastureId := userModel.AppPasture.Id
+	req.MessengerId = int32(userModel.SystemUser.Id)
+	req.MessengerName = userModel.SystemUser.Name
+
+	operationSystemUser, err := s.GetSystemUserById(ctx, int64(req.OperationId))
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+	req.OperationName = operationSystemUser.Name
+
+	penMap := s.PenMap(ctx, pastureId)
+	if len(penMap) <= 0 {
+		return xerr.Customf("请先设置牛舍信息")
+	}
+
+	newCow := model.ExcelEnterCow(pastureId, req)
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
+		// 新增牛只信息
+		if err = tx.Model(new(model.Cow)).Create(newCow).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		// 新增入场事件
+		newEventEnter := model.NewEventEnter(pastureId, newCow, req)
+		if err = tx.Model(new(model.EventEnter)).Create(newEventEnter).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		// 脖环绑定
+		if newCow.NeckRingNumber != "" {
+			newCowNeckRing := model.NewNeckRing(pastureId, newCow.NeckRingNumber, newCow, operationSystemUser)
+			if err = tx.Model(new(model.NeckRing)).
+				Create(newCowNeckRing).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+
+			newNeckRingBindLog := model.NewNeckRingBindLog(pastureId, newCow.NeckRingNumber, newCow, userModel.SystemUser, model.EventEnterBind)
+			if err = tx.Model(new(model.NeckRingBindLog)).
+				Create(newNeckRingBindLog).Error; err != nil {
+				return xerr.WithStack(err)
+			}
+		}
+
+		// 记录事件日志
+		cowLogs := s.SubmitEventLog(ctx, pastureId, newCow, pasturePb.EventType_Enter, req)
+		if err = tx.Table(cowLogs.TableName()).Create(cowLogs).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		return nil
+	}); err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
 func (s *StoreEntry) GroupTransferList(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchTransferGroupEventResponse, error) {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
@@ -237,7 +302,7 @@ func (s *StoreEntry) CreateGroupTransfer(ctx context.Context, req *pasturePb.Tra
 		return xerr.Custom("一次最多只能转移50头牛")
 	}
 
-	transferReasonMap := s.GroupTransferReasonMap()
+	transferReasonMap := s.GroupTransferReasonMap(userModel)
 	penMap := s.PenMap(ctx, userModel.AppPasture.Id)
 
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {

+ 1 - 1
module/backend/event_base_more.go

@@ -201,7 +201,7 @@ func (s *StoreEntry) CowSaleCreate(ctx context.Context, req *pasturePb.EventCowS
 	}
 
 	if req.SalesType == pasturePb.SalesType_Out {
-		if name, ok := s.CowOutReasonsMap()[req.OutReasonsKind]; ok {
+		if name, ok := s.CowOutReasonsMap(userModel)[req.OutReasonsKind]; ok {
 			req.OutReasonsName = name
 		}
 	}

+ 1 - 1
module/backend/event_breed.go

@@ -357,7 +357,7 @@ func (s *StoreEntry) SameTimeList(
 		return nil, xerr.WithStack(err)
 	}
 
-	sameTimeTypeMap := s.SameTimeTypeMap()
+	sameTimeTypeMap := s.SameTimeTypeMap(userModel)
 	return &pasturePb.SearchSameTimeResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",

+ 6 - 6
module/backend/event_breed_more.go

@@ -49,8 +49,8 @@ func (s *StoreEntry) PregnantCheckList(ctx context.Context, req *pasturePb.Searc
 		return nil, xerr.WithStack(err)
 	}
 
-	pregnantCheckResultMap := s.PregnantCheckResultMap()
-	pregnantCheckMethodMap := s.PregnantCheckMethodMap()
+	pregnantCheckResultMap := s.PregnantCheckResultMap(userModel)
+	pregnantCheckMethodMap := s.PregnantCheckMethodMap(userModel)
 	return &pasturePb.EventPregnantCheckResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -74,8 +74,8 @@ func (s *StoreEntry) PregnantCheckCreateBatch(ctx context.Context, req *pastureP
 		return xerr.WithStack(err)
 	}
 
-	abortionReasonsMap := s.AbortionReasonsMap()
-	matingResultMap := s.MatingResultMap()
+	abortionReasonsMap := s.AbortionReasonsMap(userModel)
+	matingResultMap := s.MatingResultMap(userModel)
 
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
 		for _, item := range pregnantCheckBatchModelList {
@@ -319,7 +319,7 @@ func (s *StoreEntry) MatingList(ctx context.Context, req *pasturePb.SearchEventR
 		return nil, xerr.WithStack(err)
 	}
 
-	exposeEstrusTypeMap := s.ExposeEstrusTypeMap()
+	exposeEstrusTypeMap := s.ExposeEstrusTypeMap(userModel)
 	return &pasturePb.EventMatingResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -474,7 +474,7 @@ func (s *StoreEntry) NaturalEstrusToMating(ctx context.Context, tx *gorm.DB, use
 		}
 
 		// 更新牛只配种结果日志
-		if err = s.UpdateMatingResultEventCowLogByCowId(ctx, item.Cow.Id, s.MatingResultMap()[pasturePb.MatingResult_Empty]); err != nil {
+		if err = s.UpdateMatingResultEventCowLogByCowId(ctx, item.Cow.Id, s.MatingResultMap(userModel)[pasturePb.MatingResult_Empty]); err != nil {
 			zaplog.Error("MatingCreate", zap.Any("UpdateEventCowLogByCowId", err), zap.Any("cow", item.Cow))
 		}
 	}

+ 5 - 5
module/backend/event_check.go

@@ -356,7 +356,7 @@ func (s *StoreEntry) EstrusCheckDataCheck(ctx context.Context, userModel *model.
 	if req.ExposeEstrusType == pasturePb.ExposeEstrusType_Neck_Ring {
 		exposeEstrusType = pasturePb.ExposeEstrusType_Neck_Ring
 	}
-	unMatingReasonsMap := s.UnMatingReasonsMap()
+	unMatingReasonsMap := s.UnMatingReasonsMap(userModel)
 
 	res := &model.EventEstrusBatch{
 		ExposeEstrusType: exposeEstrusType,
@@ -520,7 +520,7 @@ func (s *StoreEntry) AbortionEventDataCheck(ctx context.Context, userModel *mode
 		}
 
 		item.OperationName = operationUser.Name
-		item.AbortionReasonsName = s.AbortionReasonsMap()[item.AbortionReasons]
+		item.AbortionReasonsName = s.AbortionReasonsMap(userModel)[item.AbortionReasons]
 		newEventAbortion := model.NewEventAbortion(userModel.AppPasture.Id, cow, item, pasturePb.IsShow_No)
 		abortionCheckBatchModelList = append(abortionCheckBatchModelList, &AbortionCheckBatchModel{
 			EventAbortion: newEventAbortion,
@@ -534,7 +534,7 @@ func (s *StoreEntry) AbortionEventDataCheck(ctx context.Context, userModel *mode
 
 func (s *StoreEntry) ForbiddenMatingCheck(ctx context.Context, userModel *model.UserModel, items []*pasturePb.ForbiddenMatingItem) ([]*model.EventForbiddenMatingItem, error) {
 	res := make([]*model.EventForbiddenMatingItem, 0)
-	forbiddenMatingReasonsMap := s.ForbiddenMatingReasonsMap()
+	forbiddenMatingReasonsMap := s.ForbiddenMatingReasonsMap(userModel)
 	for _, v := range items {
 		cowInfo, err := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, v.EarNumber)
 		if err != nil {
@@ -608,7 +608,7 @@ func (s *StoreEntry) DeathCheck(ctx context.Context, userModel *model.UserModel,
 			return nil, xerr.Customf(messageId)
 		}
 
-		if name, ok := s.DeadReasonMap()[item.DeathReasonKind]; ok {
+		if name, ok := s.DeadReasonMap(userModel)[item.DeathReasonKind]; ok {
 			item.DeathReasonName = name
 		}
 
@@ -621,7 +621,7 @@ func (s *StoreEntry) DeathCheck(ctx context.Context, userModel *model.UserModel,
 			return nil, xerr.Customf(messageId)
 		}
 
-		if name, ok := s.CowDeathDestinationMap()[item.DeathDestinationKind]; ok {
+		if name, ok := s.CowDeathDestinationMap(userModel)[item.DeathDestinationKind]; ok {
 			item.DeathDestinationName = name
 		}
 

+ 14 - 10
module/backend/event_cow_log.go

@@ -17,13 +17,17 @@ import (
 )
 
 func (s *StoreEntry) SubmitEventLog(ctx context.Context, pastureId int64, cow *model.Cow, eventType pasturePb.EventType_Kind, req interface{}) *model.EventCowLog {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil
+	}
 	var (
 		desc, remarks    = "", ""
-		eventTypeName    = s.EventTypeMap()[eventType]
+		eventTypeName    = s.EventTypeMap(userModel)[eventType]
 		eventAt          = int64(0)
 		eventCategoryMap = s.eventCategoryMap()
 		penMap           = s.PenMap(ctx, pastureId)
-		cowTypeMap       = s.CowTypeMap()
+		cowTypeMap       = s.CowTypeMap(userModel)
 		operationUser    = &model.SystemUser{}
 	)
 
@@ -32,7 +36,7 @@ func (s *StoreEntry) SubmitEventLog(ctx context.Context, pastureId int64, cow *m
 		data := req.(*pasturePb.EventEnterRequest)
 		eventAt = int64(data.EnterAt)
 		remarks = data.Remarks
-		sourceMap := s.CowSourceMap()
+		sourceMap := s.CowSourceMap(userModel)
 		operationUser.Id = int64(data.OperationId)
 		operationUser.Name = data.OperationName
 		sex := "公"
@@ -61,15 +65,15 @@ func (s *StoreEntry) SubmitEventLog(ctx context.Context, pastureId int64, cow *m
 		data := req.(*PregnantCheckBatchModel)
 		eventAt = int64(data.PregnantCheckAt)
 		if data.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant {
-			desc += fmt.Sprintf("孕检方式: %s; 孕检结果: %s", s.PregnantCheckMethodMap()[data.PregnantCheckMethod], s.MatingResultMap()[pasturePb.MatingResult_Pregnant])
+			desc += fmt.Sprintf("孕检方式: %s; 孕检结果: %s", s.PregnantCheckMethodMap(userModel)[data.PregnantCheckMethod], s.MatingResultMap(userModel)[pasturePb.MatingResult_Pregnant])
 		}
 		if data.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant {
-			desc += fmt.Sprintf("孕检方式: %s", s.PregnantCheckMethodMap()[data.PregnantCheckMethod])
+			desc += fmt.Sprintf("孕检方式: %s", s.PregnantCheckMethodMap(userModel)[data.PregnantCheckMethod])
 			if cow.BreedStatus == pasturePb.BreedStatus_Abort {
-				desc += fmt.Sprintf("; 复检结果: %s", s.MatingResultMap()[pasturePb.MatingResult_Abort])
+				desc += fmt.Sprintf("; 复检结果: %s", s.MatingResultMap(userModel)[pasturePb.MatingResult_Abort])
 			}
 			if cow.BreedStatus == pasturePb.BreedStatus_Empty {
-				desc += fmt.Sprintf("; 孕检结果: %s", s.MatingResultMap()[pasturePb.MatingResult_Empty])
+				desc += fmt.Sprintf("; 孕检结果: %s", s.MatingResultMap(userModel)[pasturePb.MatingResult_Empty])
 			}
 		}
 		operationUser.Id = data.OperationUser.Id
@@ -82,16 +86,16 @@ func (s *StoreEntry) SubmitEventLog(ctx context.Context, pastureId int64, cow *m
 		if data.IsMating == pasturePb.IsShow_Ok {
 			isMating = "是"
 		}
-		desc = fmt.Sprintf("发情揭发方式:%s;是否配种:%s;", s.ExposeEstrusTypeMap()[data.ExposeEstrusType], isMating)
+		desc = fmt.Sprintf("发情揭发方式:%s;是否配种:%s;", s.ExposeEstrusTypeMap(userModel)[data.ExposeEstrusType], isMating)
 		operationUser.Id = data.OperationId
 		operationUser.Name = data.OperationName
 		remarks = data.Remarks
 	case pasturePb.EventType_Calving:
 		data := req.(*pasturePb.EventCalving)
 		eventAt = int64(data.CalvingAt)
-		desc = fmt.Sprintf("怀孕天数:%d;难产等级: %s;产子数量: %d;", cow.PregnancyAge, s.CalvingLevelMap()[data.CalvingLevel], data.ChildNumber)
+		desc = fmt.Sprintf("怀孕天数:%d;难产等级: %s;产子数量: %d;", cow.PregnancyAge, s.CalvingLevelMap(userModel)[data.CalvingLevel], data.ChildNumber)
 		if data.CalvingLevel > pasturePb.CalvingLevel_Natural_Childbirth {
-			desc += fmt.Sprintf("难产原因: %s", s.DystociaReasonMap()[data.DystociaReason])
+			desc += fmt.Sprintf("难产原因: %s", s.DystociaReasonMap(userModel)[data.DystociaReason])
 		}
 		ly, qy, die := 0, 0, 0
 		earNumber := ""

+ 4 - 4
module/backend/event_health.go

@@ -65,7 +65,7 @@ func (s *StoreEntry) CowDiseaseList(ctx context.Context, req *pasturePb.SearchEv
 		return nil, xerr.WithStack(err)
 	}
 
-	healthStatusMap := s.HealthStatusMap()
+	healthStatusMap := s.HealthStatusMap(userModel)
 	return &pasturePb.EventCowDiseaseResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -229,7 +229,7 @@ func (s *StoreEntry) CowDiseaseCreate(ctx context.Context, req *pasturePb.EventC
 		}
 		// 3. 创建治疗记录
 		if len(prescriptionDetail) > 0 {
-			diseaseTypeMap := s.DiseaseTypeMap()
+			diseaseTypeMap := s.DiseaseTypeMap(userModel)
 			newCowTreatmentRequest := &pasturePb.CowTreatmentRequest{
 				CowId:              req.CowId,
 				PrescriptionId:     prescription.Id,
@@ -443,7 +443,7 @@ func (s *StoreEntry) CowDiseaseTreatment(ctx context.Context, req *pasturePb.Cow
 	}
 
 	// 处方详情
-	unitMap := s.UnitMap()
+	unitMap := s.UnitMap(userModel)
 	prescriptionDetail := make([]*pasturePb.PrescriptionDrugsList, len(prescriptionDrugs))
 	for i, v := range prescriptionDrugs {
 		prescriptionDetail[i] = &pasturePb.PrescriptionDrugsList{
@@ -467,7 +467,7 @@ func (s *StoreEntry) CowDiseaseTreatment(ctx context.Context, req *pasturePb.Cow
 	if req.TreatmentResult == pasturePb.TreatmentResult_Dead {
 		healthStatus = pasturePb.HealthStatus_Dead
 	}
-	diseaseTypeMap := s.DiseaseTypeMap()
+	diseaseTypeMap := s.DiseaseTypeMap(userModel)
 	newEventCowTreatment := model.NewEventCowTreatment(pastureId, prescription, req, diseaseTypeMap, operationUser, userModel.SystemUser)
 
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {

+ 23 - 19
module/backend/goods.go

@@ -61,9 +61,9 @@ func (s *StoreEntry) DrugsCreateOrUpdate(ctx context.Context, req *pasturePb.Sea
 		return xerr.WithStack(err)
 	}
 
-	req.CategoryName = s.DrugCategoryMaps()[req.CategoryId]
-	req.UnitName = s.UnitMap()[req.Unit]
-	req.UsageName = s.DrugUsageMaps()[req.Usage]
+	req.CategoryName = s.DrugCategoryMaps(userModel)[req.CategoryId]
+	req.UnitName = s.UnitMap(userModel)[req.Unit]
+	req.UsageName = s.DrugUsageMaps(userModel)[req.Usage]
 
 	newDrugs := model.NewDrugs(userModel.AppPasture.Id, req, userModel.SystemUser)
 	if req.Id <= 0 {
@@ -98,7 +98,7 @@ func (s *StoreEntry) MedicalEquipmentList(ctx context.Context, req *pasturePb.Se
 		return nil, xerr.WithStack(err)
 	}
 
-	unitMap := s.UnitMap()
+	unitMap := s.UnitMap(userModel)
 	return &pasturePb.SearchMedicalEquipmentResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -204,10 +204,14 @@ func (s *StoreEntry) NeckRingCreateOrUpdate(ctx context.Context, req *pasturePb.
 				if err = tx.Model(new(model.NeckRing)).
 					Where("id = ?", neckRing.Id).
 					Updates(map[string]interface{}{
-						"cow_id":     0,
-						"ear_number": "",
-						"wear_at":    0,
-						"is_bind":    pasturePb.NeckRingIsBind_Unbind,
+						"cow_id":       0,
+						"ear_number":   "",
+						"wear_at":      0,
+						"status":       pasturePb.IsShow_Ok,
+						"is_bind":      pasturePb.NeckRingIsBind_Unbind,
+						"error_kind":   pasturePb.NeckRingNumberError_Invalid,
+						"error_reason": "",
+						"describe":     "",
 					}).Error; err != nil {
 					return xerr.WithStack(err)
 				}
@@ -304,8 +308,8 @@ func (s *StoreEntry) NeckRingList(ctx context.Context, req *pasturePb.SearchNeck
 		return nil, xerr.WithStack(err)
 	}
 
-	neckRingIsBindMap := s.NeckRingIsBindMap()
-	neckRingStatusMap := s.NeckRingStatusMap()
+	neckRingIsBindMap := s.NeckRingIsBindMap(userModel)
+	neckRingStatusMap := s.NeckRingStatusMap(userModel)
 	return &pasturePb.SearchNeckRingResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -430,7 +434,7 @@ func (s *StoreEntry) OutboundApply(ctx context.Context, req *pasturePb.OutboundA
 		})
 		return xerr.Custom(messageId)
 	}
-	unitMap := s.UnitMap()
+	unitMap := s.UnitMap(userModel)
 	if err = s.DB.Transaction(func(tx *gorm.DB) error {
 		if req.Id > 0 {
 			if err = tx.Model(new(model.Outbound)).
@@ -503,8 +507,8 @@ func (s *StoreEntry) OutboundList(ctx context.Context, req *pasturePb.SearchOutb
 		return nil, xerr.WithStack(err)
 	}
 
-	outTypeMap := s.OutTypeMap()
-	auditStatusMap := s.AuditStatusMap()
+	outTypeMap := s.OutTypeMap(userModel)
+	auditStatusMap := s.AuditStatusMap(userModel)
 
 	return &pasturePb.SearchOutboundApplyResponse{
 		Code: http.StatusOK,
@@ -620,8 +624,8 @@ func (s *StoreEntry) OutboundDetail(ctx context.Context, id int64) (*pasturePb.O
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
-	outTypeMap := s.OutTypeMap()
-	auditStatusMap := s.AuditStatusMap()
+	outTypeMap := s.OutTypeMap(userModel)
+	auditStatusMap := s.AuditStatusMap(userModel)
 	applicantAtFormat, examineAtFormat := "", ""
 	if outbound.ApplicantAt > 0 {
 		applicantAtFormat = time.Unix(outbound.ApplicantAt, 0).Local().Format(model.LayoutTime)
@@ -630,7 +634,7 @@ func (s *StoreEntry) OutboundDetail(ctx context.Context, id int64) (*pasturePb.O
 		examineAtFormat = time.Unix(outbound.ExamineAt, 0).Local().Format(model.LayoutTime)
 	}
 
-	unitMap := s.UnitMap()
+	unitMap := s.UnitMap(userModel)
 	return &pasturePb.OutboundDetailResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -723,8 +727,8 @@ func (s *StoreEntry) FrozenSemenList(ctx context.Context, req *pasturePb.FrozenS
 		return nil, xerr.WithStack(err)
 	}
 
-	frozenSemenTypeMap := s.FrozenSemenTypeMap()
-	unitMap := s.UnitMap()
+	frozenSemenTypeMap := s.FrozenSemenTypeMap(userModel)
+	unitMap := s.UnitMap(userModel)
 
 	return &pasturePb.FrozenSemenResponse{
 		Code: http.StatusOK,
@@ -744,7 +748,7 @@ func (s *StoreEntry) FrozenSemenCreate(ctx context.Context, req *pasturePb.Searc
 		return xerr.WithStack(err)
 	}
 
-	req.CowKindName = s.CowKindMap()[req.CowKind]
+	req.CowKindName = s.CowKindMap(userModel)[req.CowKind]
 	if req.Id > 0 {
 		histData := &model.FrozenSemen{}
 		if err = s.DB.Model(new(model.FrozenSemen)).

+ 4 - 4
module/backend/indicators.go

@@ -123,7 +123,7 @@ func (s *StoreEntry) LongTermInfertility(ctx context.Context, req *pasturePb.Lon
 		return nil, xerr.WithStack(err)
 	}
 
-	breedStatusMap := s.CowBreedStatusMap()
+	breedStatusMap := s.CowBreedStatusMap(userModel)
 	return &pasturePb.LongTermInfertilityResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -219,8 +219,8 @@ func (s *StoreEntry) AlreadySale(ctx context.Context, req *pasturePb.AlreadySale
 		cowMap[v.Id] = v
 	}
 
-	sourceMap := s.CowSourceMap()
-	cowKindMap := s.CowKindMap()
+	sourceMap := s.CowSourceMap(userModel)
+	cowKindMap := s.CowKindMap(userModel)
 	result.Data.Total = int32(len(eventSaleCowList))
 	result.Data.List = model.EventSaleCowSlice(eventSaleCowList).ToPB(eventSaleMap, cowKindMap, cowMap, sourceMap)
 	return result, nil
@@ -272,7 +272,7 @@ func (s *StoreEntry) CanSale(ctx context.Context, req *pasturePb.CanSalesReportR
 	if len(cowList) <= 0 {
 		return result, nil
 	}
-	cowKindMap := s.CowKindMap()
+	cowKindMap := s.CowKindMap(userModel)
 	result.Data.Total = int32(count)
 	result.Data.List = model.CowSlice(cowList).CanSaleToPB(cowKindMap)
 	return result, nil

+ 4 - 2
module/backend/interface.go

@@ -67,7 +67,7 @@ type KptService interface {
 //go:generate mockgen -destination mock/SystemService.go -package kptservicemock kpt-pasture/module/backend SystemService
 type SystemService interface {
 	// Login 系统用户相关
-	Login(ctx context.Context, req *pasturePb.SearchUserRequest) (*pasturePb.SystemUserResponse, error)
+	Login(ctx context.Context, platform string, req *pasturePb.SearchUserRequest) (*pasturePb.SystemUserResponse, error)
 	SearchSystemUserList(ctx context.Context, req *pasturePb.SearchUserRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchUserResponse, error)
 	IsShowSystemUser(ctx context.Context, userId int64) error
 	DeleteSystemUser(ctx context.Context, userId int64) error
@@ -257,6 +257,8 @@ type CowService interface {
 	List(ctx context.Context, req *pasturePb.SearchEventRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchCowListResponse, error)
 	EventList(ctx context.Context, req *pasturePb.SearchCowEventListRequest, pagination *pasturePb.PaginationModel) (*pasturePb.CowEventListResponse, error)
 	BehaviorCurve(ctx context.Context, req *pasturePb.CowBehaviorCurveRequest) (*model.CowBehaviorCurveResponse, error)
+	BehaviorCurveApp(ctx context.Context, req *pasturePb.CowBehaviorCurveRequest) (*pasturePb.CowNeckRingAppResponse, error)
+	BehaviorCurveGroupComparison(ctx context.Context, req *pasturePb.CowBehaviorCurveRequest) (*pasturePb.BehaviorCurveGroupComparisonResponse, error)
 	CowGrowthCurve(ctx context.Context, req *pasturePb.CowGrowthCurveRequest) (*pasturePb.CowGrowthCurveResponse, error)
 	CowLactCurve(ctx context.Context, req *pasturePb.CowLactCurveRequest) (*pasturePb.CowLactCurveResponse, error)
 	BehaviorRate(ctx context.Context, req *pasturePb.CowBehaviorRateRequest) (*pasturePb.CowBehaviorRateResponse, error)
@@ -364,7 +366,7 @@ type MilkHallService interface {
 type UploadService interface {
 	Photos(ctx context.Context, files []*multipart.FileHeader) ([]string, error)
 	ImportExcel(ctx context.Context, data [][]string) error
-	ImportExcel2(ctx context.Context, data [][]string, excelHeader []string) error
+	ImportExcel2(ctx context.Context, data [][]string, excelHeader []string, headOfField []string) error
 }
 
 type FeedingService interface {

+ 35 - 5
module/backend/neck_ring_warning.go

@@ -49,6 +49,10 @@ func (s *StoreEntry) NeckRingWarningEstrusOrAbortionCowList(ctx context.Context,
 		pref.Where("a.level = ?", req.Level)
 	}
 
+	if len(req.EstrusLevels) > 0 {
+		pref.Where("a.level IN ?", req.EstrusLevels)
+	}
+
 	if len(req.PenIds) > 0 {
 		pref.Where("b.pen_id IN ?", req.PenIds)
 	}
@@ -84,7 +88,7 @@ func (s *StoreEntry) NeckRingWarningEstrusOrAbortionCowList(ctx context.Context,
 			cowMap[cow.Id] = cow
 		}
 	}
-	list := model.NeckRingEstrusWarningSlice(neckRingEstrusList).ToPB(cowMap, eventLogMap, req.MatingWindowPeriod)
+	list := model.NeckRingEstrusWarningSlice(neckRingEstrusList).ToPB(cowMap, eventLogMap, req.MatingWindowPeriod, req.MatingWindowPeriods)
 	// 排序 先按照高峰时间正序排,然后再按照发情等级倒叙排
 	sort.Slice(list, func(i, j int) bool {
 		if list[i].PostPeakTimeForHours != list[j].PostPeakTimeForHours {
@@ -144,7 +148,7 @@ func (s *StoreEntry) NeckRingWarningHealthCowList(ctx context.Context, req *past
 		pref.Where("a.level = ?", req.Level)
 	}
 
-	if err = pref.Order("a.level DESC").
+	if err = pref.Order("a.level DESC,a.score ASC").
 		Group("a.cow_id").
 		Count(&count).
 		Limit(int(pagination.PageSize)).
@@ -153,8 +157,8 @@ func (s *StoreEntry) NeckRingWarningHealthCowList(ctx context.Context, req *past
 		return nil, xerr.WithStack(err)
 	}
 
-	warningHealthLevelMap := s.WarningHealthLevelMap()
-	healthStatusMap := s.HealthStatusMap()
+	warningHealthLevelMap := s.WarningHealthLevelMap(userModel)
+	healthStatusMap := s.HealthStatusMap(userModel)
 	cowMap := make(map[int64]*model.Cow)
 	eventLogMap := make(map[int64]string)
 	cowIds := make([]int64, 0)
@@ -166,14 +170,39 @@ func (s *StoreEntry) NeckRingWarningHealthCowList(ctx context.Context, req *past
 		}
 	}
 
+	dayData := make(map[int64]*model.NeckActiveHabit)
 	if len(cowIds) > 0 {
 		cowList, _ := s.GetCowInfoByCowIds(ctx, userModel.AppPasture.Id, cowIds)
 		for _, cow := range cowList {
 			cowMap[cow.Id] = cow
 		}
 
-		// 获取牛的牛当前脖环数据
+		neckRingHabitList := make([]*model.NeckActiveHabit, 0)
+		if err = s.DB.Model(new(model.NeckActiveHabit)).
+			Select("rumina,intake,inactive,active,change_rumina,change_high,active_time").
+			Where("pasture_id = ?", userModel.AppPasture.Id).
+			Where("cow_id IN ?", cowIds).
+			Where("heat_date = ?", time.Now().Format(model.LayoutDate2)).
+			Where("is_show = ?", pasturePb.IsShow_Ok).
+			Find(&neckRingHabitList).Error; err != nil {
+			zaplog.Error("GetNeckRingHabitList", zap.Error(err))
+		}
 
+		if len(neckRingHabitList) > 0 {
+			for _, v := range neckRingHabitList {
+				if _, ok := dayData[v.CowId]; ok {
+					dayData[v.CowId].Active += 120 - v.Active
+					dayData[v.CowId].Inactive += v.Inactive
+					dayData[v.CowId].Intake += v.Intake
+					dayData[v.CowId].Rumina += v.Rumina
+					if dayData[v.CowId].ActiveTime < v.ActiveTime {
+						dayData[v.CowId].ChangeRumina = v.ChangeRumina
+						dayData[v.CowId].ActiveTime = v.ActiveTime
+						dayData[v.CowId].ChangeHigh = v.ChangeHigh
+					}
+				}
+			}
+		}
 	}
 
 	return &pasturePb.HealthWarningResponse{
@@ -188,6 +217,7 @@ func (s *StoreEntry) NeckRingWarningHealthCowList(ctx context.Context, req *past
 				cowMap,
 				eventLogMap,
 				healthStatusMap,
+				dayData,
 			),
 		},
 	}, nil

+ 34 - 8
module/backend/pasture.go

@@ -40,7 +40,7 @@ func (s *StoreEntry) SearchBarnList(ctx context.Context, req *pasturePb.SearchNa
 	}
 
 	//configBarnTypeList := make([]*model.ConfigPenType, 0)
-	barnTypeMap := s.BarnTypeMap()
+	barnTypeMap := s.BarnTypeMap(userModel)
 	return &pasturePb.SearchBarnResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -90,6 +90,11 @@ func (s *StoreEntry) CreateOrUpdateBarn(ctx context.Context, req *pasturePb.Sear
 }
 
 func (s *StoreEntry) SearchBarnTypeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
 	barnTypeList := make([]*model.ConfigPenType, 0)
 	var count int64 = 0
 
@@ -107,7 +112,7 @@ func (s *StoreEntry) SearchBarnTypeList(ctx context.Context, req *pasturePb.Sear
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigBarnTypeSlice(barnTypeList).ToPB(),
+			List:     model.ConfigBarnTypeSlice(barnTypeList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -138,6 +143,10 @@ func (s *StoreEntry) CreateOrUpdateBarnType(ctx context.Context, req *pasturePb.
 }
 
 func (s *StoreEntry) SearchBreedStatusList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	breedStatusList := make([]*model.ConfigBreedStatus, 0)
 	var count int64 = 0
 
@@ -155,7 +164,7 @@ func (s *StoreEntry) SearchBreedStatusList(ctx context.Context, req *pasturePb.S
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigBreedStatusSlice(breedStatusList).ToPB(),
+			List:     model.ConfigBreedStatusSlice(breedStatusList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -186,6 +195,10 @@ func (s *StoreEntry) CreateOrUpdateBreedStatus(ctx context.Context, req *pasture
 }
 
 func (s *StoreEntry) SearchCowKindList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	configCowKindList := make([]*model.ConfigCowKind, 0)
 	var count int64 = 0
 
@@ -203,7 +216,7 @@ func (s *StoreEntry) SearchCowKindList(ctx context.Context, req *pasturePb.Searc
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigCowKindSlice(configCowKindList).ToPB(),
+			List:     model.ConfigCowKindSlice(configCowKindList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -282,6 +295,11 @@ func (s *StoreEntry) CreateOrUpdateCowStatus(ctx context.Context, req *pasturePb
 }
 
 func (s *StoreEntry) SearchCowTypeList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
 	configCowTypeList := make([]*model.ConfigCowType, 0)
 	var count int64 = 0
 
@@ -299,7 +317,7 @@ func (s *StoreEntry) SearchCowTypeList(ctx context.Context, req *pasturePb.Searc
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigCowTypeSlice(configCowTypeList).ToPB(),
+			List:     model.ConfigCowTypeSlice(configCowTypeList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -330,6 +348,10 @@ func (s *StoreEntry) CreateOrUpdateCowType(ctx context.Context, req *pasturePb.S
 }
 
 func (s *StoreEntry) SearchTransferPenReasonList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	configTransferPenReasonList := make([]*model.ConfigTransferPenReason, 0)
 	var count int64 = 0
 
@@ -338,7 +360,7 @@ func (s *StoreEntry) SearchTransferPenReasonList(ctx context.Context, req *pastu
 		pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))
 	}
 
-	if err := pref.Order("id desc").Count(&count).Limit(int(pagination.PageSize)).Offset(int(pagination.PageOffset)).
+	if err = pref.Order("id desc").Count(&count).Limit(int(pagination.PageSize)).Offset(int(pagination.PageOffset)).
 		Find(&configTransferPenReasonList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
@@ -347,7 +369,7 @@ func (s *StoreEntry) SearchTransferPenReasonList(ctx context.Context, req *pastu
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigTransferPenReasonSlice(configTransferPenReasonList).ToPB(),
+			List:     model.ConfigTransferPenReasonSlice(configTransferPenReasonList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -378,6 +400,10 @@ func (s *StoreEntry) CreateOrUpdateTransferPenReason(ctx context.Context, req *p
 }
 
 func (s *StoreEntry) SearchCowSourceList(ctx context.Context, req *pasturePb.SearchNameRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchBaseConfigResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
 	configCowSourceList := make([]*model.ConfigCowSource, 0)
 	var count int64 = 0
 
@@ -395,7 +421,7 @@ func (s *StoreEntry) SearchCowSourceList(ctx context.Context, req *pasturePb.Sea
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigCowSourceSlice(configCowSourceList).ToPB(),
+			List:     model.ConfigCowSourceSlice(configCowSourceList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,

+ 14 - 9
module/backend/prescription.go

@@ -9,6 +9,8 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/nicksnyder/go-i18n/v2/i18n"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	"gitee.com/xuyiping_admin/pkg/xerr"
 	"gorm.io/gorm"
@@ -66,8 +68,8 @@ func (s *StoreEntry) SearchSameTimeList(ctx context.Context, req *pasturePb.Sear
 		return nil, xerr.WithStack(err)
 	}
 
-	weekMap := s.WeekMap()
-	sameTimeCowTypeMap := s.SameTimeCowTypeMap()
+	weekMap := s.WeekMap(userModel)
+	sameTimeCowTypeMap := s.SameTimeCowTypeMap(userModel)
 	systemUser, _ := s.SystemUserList(ctx, pastureId)
 	return &pasturePb.SameTimeResponse{
 		Code: http.StatusOK,
@@ -134,13 +136,13 @@ func (s *StoreEntry) SearchDiseaseList(ctx context.Context, req *pasturePb.Searc
 	}
 
 	systemUserList, _ := s.SystemUserList(ctx, pastureId)
-	diseaseTypeList, _ := s.DiseaseTypeList(ctx)
+	diseaseTypeList, _ := s.DiseaseTypeList(pastureId)
 
 	return &pasturePb.SearchDiseaseResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchDiseaseData{
-			List:     model.DiseaseSlice(diseaseList).ToPB(systemUserList, diseaseTypeList),
+			List:     model.DiseaseSlice(diseaseList).ToPB(userModel, systemUserList, diseaseTypeList),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -163,11 +165,14 @@ func (s *StoreEntry) CreateOrUpdateDisease(ctx context.Context, req *pasturePb.S
 		}
 	}
 
-	diseaseTypeList, _ := s.DiseaseTypeList(ctx)
+	diseaseTypeList, _ := s.DiseaseTypeList(userModel.AppPasture.Id)
 	if req.DiseaseTypeId > 0 {
 		for _, v := range diseaseTypeList {
 			if int32(v.Id) == req.DiseaseTypeId {
-				req.DiseaseTypeName = v.Name
+				label, _ := userModel.LanguageContent.Localize(&i18n.LocalizeConfig{
+					MessageID: v.I18nFieldTag,
+				})
+				req.DiseaseTypeName = label
 			}
 		}
 	}
@@ -212,7 +217,7 @@ func (s *StoreEntry) SearchDiseaseTypeList(ctx context.Context, req *pasturePb.S
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.SearchBaseConfigData{
-			List:     model.ConfigDiseaseTypeSlice(diseaseTypeList).ToPB(),
+			List:     model.ConfigDiseaseTypeSlice(diseaseTypeList).ToPB(userModel),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,
@@ -448,8 +453,8 @@ func (s *StoreEntry) ImmunizationSetList(ctx context.Context, req *pasturePb.Imm
 		return nil, xerr.WithStack(err)
 	}
 
-	CowTypeOptions := s.ImmunizationCowTypeEnumList("")
-	conditionsOptions := s.ImmunizationConditionsEnumList("")
+	CowTypeOptions := s.ImmunizationCowTypeEnumList(userModel, "")
+	conditionsOptions := s.ImmunizationConditionsEnumList(userModel, "")
 	return &pasturePb.SearchImmunizationResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",

+ 6 - 2
module/backend/sql.go

@@ -32,6 +32,8 @@ func (s *StoreEntry) GetUserModel(ctx context.Context) (*model.UserModel, error)
 		return nil, xerr.WithStack(err)
 	}
 
+	currentUserLanguage := s.GetCurrentUserLanguage(ctx)
+
 	systemUserPastureIds := strings.Split(systemUser.PastureIds, ",")
 	if len(systemUserPastureIds) == 0 {
 		message, _ := i18nTemplate.Localize(&i18n.LocalizeConfig{
@@ -58,6 +60,7 @@ func (s *StoreEntry) GetUserModel(ctx context.Context) (*model.UserModel, error)
 		SystemUser:      systemUser,
 		AppPasture:      appPasture,
 		LanguageContent: i18nTemplate,
+		Language:        currentUserLanguage,
 	}, nil
 }
 
@@ -222,7 +225,7 @@ func (s *StoreEntry) GetPenList(ctx context.Context, pastureId int64) ([]*model.
 		Where("is_delete = ?", pasturePb.IsShow_Ok).
 		Where("pasture_id = ?", pastureId).
 		Find(&penList).Error; err != nil {
-		return nil, xerr.WithStack(err)
+		return penList, xerr.WithStack(err)
 	}
 	return penList, nil
 }
@@ -362,9 +365,10 @@ func (s *StoreEntry) GetDrugsById(ctx context.Context, pastureId, drugsId int64)
 	return drugs, nil
 }
 
-func (s *StoreEntry) DiseaseTypeList(ctx context.Context) ([]*model.ConfigDiseaseType, error) {
+func (s *StoreEntry) DiseaseTypeList(pastureId int64) ([]*model.ConfigDiseaseType, error) {
 	diseaseTypeList := make([]*model.ConfigDiseaseType, 0)
 	if err := s.DB.Model(new(model.ConfigDiseaseType)).
+		Where("pasture_id = ?", pastureId).
 		Where("is_show = ?", pasturePb.IsShow_Ok).
 		Find(&diseaseTypeList).Error; err != nil {
 		return nil, xerr.WithStack(err)

+ 10 - 2
module/backend/system_service.go

@@ -30,7 +30,7 @@ const (
 )
 
 // Login 用户登录
-func (s *StoreEntry) Login(ctx context.Context, req *pasturePb.SearchUserRequest) (*pasturePb.SystemUserResponse, error) {
+func (s *StoreEntry) Login(ctx context.Context, platform string, req *pasturePb.SearchUserRequest) (*pasturePb.SystemUserResponse, error) {
 	i18nTemplate, err := s.GetI18nTemplate(ctx)
 	if err != nil {
 		return nil, xerr.WithStack(err)
@@ -116,6 +116,11 @@ func (s *StoreEntry) Login(ctx context.Context, req *pasturePb.SearchUserRequest
 		roleNameList = append(roleNameList, role.Name)
 	}
 
+	userId := int32(0)
+	if platform == "h5" {
+		userId = int32(systemUser.Id)
+	}
+
 	return &pasturePb.SystemUserResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -127,6 +132,8 @@ func (s *StoreEntry) Login(ctx context.Context, req *pasturePb.SearchUserRequest
 			Roles:        roleNameList,
 			Avatar:       systemUser.Avatar,
 			FarmId:       farmList[0].FarmId,
+			FarmName:     farmList[0].Name,
+			UserId:       userId,
 		},
 	}, nil
 }
@@ -142,7 +149,8 @@ func (s *StoreEntry) SearchSystemUserList(ctx context.Context, req *pasturePb.Se
 	var count int64 = 0
 	pref := s.DB.Model(new(model.SystemUser)).
 		Where("is_delete = ?", operationPb.IsShow_OK).
-		Where("FIND_IN_SET(?, pasture_ids) > ?", userModel.AppPasture.Id, 0)
+		Where("FIND_IN_SET(?, pasture_ids) > ?", userModel.AppPasture.Id, 0).
+		Where("name != ?", model.AdminUser)
 
 	if req.Name != "" {
 		pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))

+ 16 - 12
module/backend/test_service.go

@@ -128,19 +128,23 @@ func (s *StoreEntry) UpdateCowPen(ctx context.Context, pagination *pasturePb.Pag
 }
 
 func (s *StoreEntry) PastureInit(ctx context.Context, pastureId int64) error {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
 	if pastureId <= 0 {
 		return xerr.New("pastureId invalid")
 	}
 
 	pasture := &model.AppPastureList{}
-	if err := s.DB.Model(new(model.AppPastureList)).
+	if err = s.DB.Model(new(model.AppPastureList)).
 		Where("id = ?", pastureId).
 		First(pasture).Error; err != nil {
 		return xerr.Customf("该牧场不存在:%d", pastureId)
 	}
 
 	deptList := make([]*model.SystemDept, 0)
-	if err := s.DB.Model(new(model.SystemDept)).
+	if err = s.DB.Model(new(model.SystemDept)).
 		Where("id = ?", pasture.Id).
 		Find(&deptList).Error; err != nil {
 		return xerr.Customf("牧场初始化数据失败:%s", err.Error())
@@ -150,44 +154,44 @@ func (s *StoreEntry) PastureInit(ctx context.Context, pastureId int64) error {
 		return xerr.Customf("该牧场已初始化:%d", pastureId)
 	}
 
-	dataWaringTypeEnumList := s.DataWaringTypeEnumList("all")
+	dataWaringTypeEnumList := s.DataWaringTypeEnumList(userModel, "all")
 	dataWarningList := model.DataWarningInitData(pastureId, dataWaringTypeEnumList)
 
-	if err := s.DB.Transaction(func(tx *gorm.DB) error {
+	if err = s.DB.Transaction(func(tx *gorm.DB) error {
 		for _, dataWarning := range dataWarningList {
-			if err := tx.Model(new(model.DataWarning)).
+			if err = tx.Model(new(model.DataWarning)).
 				Create(dataWarning).Error; err != nil {
 				zaplog.Error("PastureInit-DataWarning", zap.Any("error", err))
 			}
 			dataWarningItemsList := model.DataWarningItemsInitData(pastureId, dataWarning)
-			if err := tx.Model(new(model.DataWarningItems)).
+			if err = tx.Model(new(model.DataWarningItems)).
 				Create(dataWarningItemsList).Error; err != nil {
 				zaplog.Error("PastureInit-DataWarningItems", zap.Any("error", err))
 			}
 		}
 
 		nackRingConfigureList := model.NeckRingConfigureInit(pastureId)
-		if err := tx.Model(new(model.NeckRingConfigure)).
+		if err = tx.Model(new(model.NeckRingConfigure)).
 			Create(nackRingConfigureList).Error; err != nil {
 			zaplog.Error("PastureInit-NeckRingConfigure", zap.Any("error", err))
 		}
 
 		// 初始化牧场和部门数据
 		newSystemPastureDept := model.NewSystemPastureDeptInit(pasture)
-		if err := tx.Model(new(model.SystemDept)).
+		if err = tx.Model(new(model.SystemDept)).
 			Create(newSystemPastureDept).Error; err != nil {
 			zaplog.Error("PastureInit-SystemDept", zap.Any("error", err))
 		}
 
 		newSystemDept := model.NewSystemDeptInit(pasture.Id, newSystemPastureDept.Id)
-		if err := tx.Model(new(model.SystemDept)).
+		if err = tx.Model(new(model.SystemDept)).
 			Create(newSystemDept).Error; err != nil {
 			zaplog.Error("PastureInit-SystemDept", zap.Any("error", err))
 		}
 
 		// 初始化菜单
 		systemMenuList := make([]*model.SystemPastureMenu, 0)
-		if err := tx.Model(new(model.SystemPastureMenu)).
+		if err = tx.Model(new(model.SystemPastureMenu)).
 			Where("pasture_id = ?", 0).
 			Find(&systemMenuList).Error; err != nil {
 			zaplog.Error("PastureInit-SystemMenu", zap.Any("error", err))
@@ -202,12 +206,12 @@ func (s *StoreEntry) PastureInit(ctx context.Context, pastureId int64) error {
 			newSystemMenuList = append(newSystemMenuList, newSystemMenu)
 		}
 
-		if err := tx.Model(new(model.SystemPastureMenu)).
+		if err = tx.Model(new(model.SystemPastureMenu)).
 			Create(newSystemMenuList).Error; err != nil {
 			zaplog.Error("PastureInit-SystemMenu", zap.Any("error", err))
 		}
 
-		// 初始化用户和角色
+		// 初始化用户和角色 todo
 
 		return nil
 	}); err != nil {

+ 107 - 132
module/backend/upload_file.go

@@ -9,9 +9,7 @@ import (
 	"mime/multipart"
 	"os"
 	"path/filepath"
-	"reflect"
 	"strconv"
-	"strings"
 	"time"
 
 	"gorm.io/gorm"
@@ -199,189 +197,169 @@ func (s *StoreEntry) ImportExcel(ctx context.Context, data [][]string) error {
 	return s.ExecExcelData(ctx, pastureId, eventEnterList)
 }
 
-func (s *StoreEntry) ImportExcel2(ctx context.Context, data [][]string, excelHeader []string) error {
+func (s *StoreEntry) ImportExcel2(ctx context.Context, data [][]string, excelHeader []string, headOfField []string) error {
 	// 获取当前用户信息
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
 		return err
 	}
+	// excelHeader ["序号","牛号","性别","出生日期","栏舍名称","牛只类型","牛只品种","牛只来源","入场日期","当前体重(KG)","用途","胎次","配种日期","孕检日期","孕检结果","产犊日期","流产日期","是否禁配",
 
-	penMap := s.PenMap2(ctx, userModel.AppPasture.Id)
+	pastureId := userModel.AppPasture.Id
 	if userModel.AppPasture.Id <= 0 {
 		return xerr.Custom("无效的牧场ID")
 	}
+	penMap := s.PenMap2(ctx, pastureId)
+	if len(penMap) <= 0 {
+		return xerr.Custom("当前牧场没有配置栏舍信息")
+	}
+
+	cowTypeMap := s.CowTypeMap2(userModel)
+	cowKindMap := s.CowKindMap2(userModel)
+	cowSourceMap := s.CowSourceMap2(userModel)
+	purposeMap := s.PurposeMap2(userModel)
+
 	// 处理Excel数据
-	//headers := data[0]
 	eventEnterList := make([]*pasturePb.EventEnterRequest, 0)
-	/*for _, row := range data[1:] {
-		if len(row) <= 0 {
+	// 遍历数据行(跳过表头)
+	for _, rows := range data[1:] {
+		if len(rows) == 0 { //  [1 HS10034 母 08-12-22 东区1号 成母牛 西门塔尔牛 产犊 09-12-23 500 繁育 1 12-05-24 01-15-25 有胎   否 2  789]
 			continue
 		}
+
 		ts := &pasturePb.EventEnterRequest{
 			OperationId:   int32(userModel.SystemUser.Id),
 			OperationName: userModel.SystemUser.Name,
 			MessengerId:   int32(userModel.SystemUser.Id),
 			MessengerName: userModel.SystemUser.Name,
 		}
-		for j, d := range row {
-			switch j {
-			case 0:
+
+		for j, _ := range rows {
+			if j == 0 {
 				continue
+			}
+			value := rows[j]
+			switch j {
 			case 1:
-				continue
+				ts.EarNumber = value
 			case 2:
-				ts.EarNumber = d
-			case 3:
-				if pn, ok := penMap[d]; ok {
-					ts.PenId = pn.Id
-					ts.PenName = pn.Name
-				}
-			case 4:
 				ts.Sex = pasturePb.Genders_Female
-				if d == "公" {
+				if value == "公" {
 					ts.Sex = pasturePb.Genders_Male
 				}
-			case 5:
-				if d == "成母牛" {
-					ts.CowType = pasturePb.CowType_Breeding_Calf
-				} else if d == "犊牛" {
-					ts.CowType = pasturePb.CowType_Lactating_Calf
-				} else if d == "青年牛" {
-					ts.CowType = pasturePb.CowType_Youth_Calf
-				} else if d == "育成牛" {
-					ts.CowType = pasturePb.CowType_Reserve_Calf
+			case 3:
+				bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
+				if !bat.IsZero() {
+					ts.BirthAt = int32(bat.Unix())
+				} else {
+					ts.BirthAt = 0
 				}
+			case 4:
+				ts.PenName = value
+			case 5:
+				ts.CowTypeName = value
 			case 6:
-				continue
+				ts.CowKindName = value
 			case 7:
-				bat, _ := util.TimeParseLocal(model.LayoutTime2, d)
-				if !bat.IsZero() {
-					ts.BirthAt = int32(bat.Local().Unix())
+				if cs, ok := cowSourceMap[value]; ok {
+					ts.CowSource = cs
 				}
 			case 8:
-				lact, _ := strconv.Atoi(d)
-				ts.Lact = int32(lact)
-			case 9:
-				eat, _ := util.TimeParseLocal(model.LayoutTime2, d)
-				if !eat.IsZero() {
-					ts.EnterAt = int32(eat.Local().Unix())
+				bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
+				if !bat.IsZero() {
+					ts.EnterAt = int32(bat.Unix())
+				} else {
+					ts.EnterAt = 0
 				}
+			case 9:
+				ct, _ := strconv.ParseFloat(value, 64)
+				ts.Weight = float32(ct)
 			case 10:
-				ts.FatherNumber = d
+				ts.PurposeName = value
 			case 11:
-				ts.MotherNumber = d
+				lact, _ := strconv.Atoi(value)
+				ts.Lact = int32(lact)
 			case 12:
-				mat, _ := util.TimeParseLocal(model.LayoutTime2, d)
-				if !mat.IsZero() {
-					ts.MatingAt = int32(mat.Local().Unix())
+				bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
+				if !bat.IsZero() {
+					ts.MatingAt = int32(bat.Unix())
+				} else {
+					ts.MatingAt = 0
 				}
 			case 13:
-				continue
+				bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
+				if !bat.IsZero() {
+					ts.PregnancyCheckAt = int32(bat.Unix())
+				} else {
+					ts.PregnancyCheckAt = 0
+				}
 			case 14:
-				continue
+				ts.PregnantCheckResult = pasturePb.PregnantCheckResult_Pregnant
+				if value == "无胎" {
+					ts.PregnantCheckResult = pasturePb.PregnantCheckResult_UnPregnant
+				}
 			case 15:
-				mt, _ := strconv.Atoi(d)
-				ts.MatingTimes = int32(mt)
+				bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
+				if !bat.IsZero() {
+					ts.CalvingAt = int32(bat.Unix())
+				} else {
+					ts.CalvingAt = 0
+				}
 			case 16:
-				continue
+				bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
+				if !bat.IsZero() {
+					ts.AbortionAt = int32(bat.Unix())
+				} else {
+					ts.AbortionAt = 0
+				}
 			case 17:
-				pat, _ := util.TimeParseLocal(model.LayoutTime2, d)
-				if !pat.IsZero() {
-					ts.PregnancyCheckAt = int32(pat.Local().Unix())
+				ts.BreedStatus = pasturePb.BreedStatus_UnBreed
+				ts.IsForbiddenMatingKind = pasturePb.IsShow_No
+				if value == "是" {
+					ts.BreedStatus = pasturePb.BreedStatus_No_Mating
+					ts.IsForbiddenMatingKind = pasturePb.IsShow_Ok
 				}
 			case 18:
-				continue
+				mts, _ := strconv.Atoi(value)
+				ts.MatingTimes = int32(mts)
 			case 19:
-				continue
+				ts.BullNumber = value
 			case 20:
-				cat, _ := util.TimeParseLocal(model.LayoutTime2, d)
-				if !cat.IsZero() {
-					ts.CalvingAt = int32(cat.Local().Unix())
-				}
+				ts.NeckRingNumber = value
 			case 21:
-				continue
+				ts.MotherNumber = value
 			case 22:
-				continue
+				ts.FatherNumber = value
 			case 23:
-				continue
+				ts.BatchNumber = value
 			case 24:
-				ts.CowKind = pasturePb.CowKind_AGSN
+				price, _ := strconv.ParseFloat(value, 64)
+				ts.Price = float32(price)
 			}
 		}
-		eventEnterList = append(eventEnterList, ts)
-	}*/
-	// 遍历数据行(跳过表头)
-	for _, row := range data[1:] {
-		if len(row) == 0 {
-			continue
-		}
 
-		ts := &pasturePb.EventEnterRequest{
-			OperationId:   int32(userModel.SystemUser.Id),
-			OperationName: userModel.SystemUser.Name,
-			MessengerId:   int32(userModel.SystemUser.Id),
-			MessengerName: userModel.SystemUser.Name,
-		}
-
-		// 使用反射动态匹配字段
-		val := reflect.ValueOf(ts).Elem()
-		typ := val.Type()
-
-		for i := 0; i < val.NumField(); i++ {
-			field := typ.Field(i)
-			fieldVal := val.Field(i)
-
-			// 获取字段的 excel 标签(如 excel:"耳标号")
-			excelTag := strings.ReplaceAll(field.Tag.Get("json"), ",omitempty", "")
-			if excelTag == "" {
-				continue // 没有 excel 标签的字段跳过
-			}
-
-			// 查找 excelHeader 中匹配的列索引
-			colIndex := -1
-			for j, colName := range excelHeader {
-				if colName == "" {
-					continue // 跳过空列名
-				}
-				if colName == excelTag {
-					colIndex = j
-					break
-				}
+		// 特殊处理 PenId 和 PenName(依赖 penMap)
+		if ts.PenName != "" {
+			if pen, ok := penMap[ts.PenName]; ok {
+				ts.PenId = pen.Id
 			}
+		}
 
-			if colIndex == -1 || colIndex >= len(row) {
-				continue // 列名不匹配或数据越界
+		if ts.CowTypeName != "" {
+			if ct, ok := cowTypeMap[ts.CowTypeName]; ok {
+				ts.CowType = ct
 			}
+		}
 
-			cellValue := row[colIndex]
-			if cellValue == "" {
-				continue // 空值跳过
-			}
-			// 根据字段类型设置值
-			switch fieldVal.Kind() {
-			case reflect.String:
-				fieldVal.SetString(cellValue)
-			case reflect.Int32:
-				if num, err := strconv.ParseInt(cellValue, 10, 32); err == nil {
-					fieldVal.SetInt(num)
-				}
-			case reflect.Struct: // 处理枚举或时间类型
-				switch field.Type {
-				case reflect.TypeOf(pasturePb.Genders_Female):
-					if cellValue == "公" {
-						fieldVal.Set(reflect.ValueOf(pasturePb.Genders_Male))
-					} else {
-						fieldVal.Set(reflect.ValueOf(pasturePb.Genders_Female))
-					}
-					// 添加其他自定义类型的处理...
-				}
+		if ts.CowKindName != "" {
+			if ck, ok := cowKindMap[ts.CowKindName]; ok {
+				ts.CowKind = ck
 			}
 		}
 
-		// 特殊处理 PenId 和 PenName(依赖 penMap)
-		if ts.PenName != "" {
-			if pen, ok := penMap[ts.PenName]; ok {
-				ts.PenId = pen.Id
+		if ts.PurposeName != "" {
+			if p, ok := purposeMap[ts.PurposeName]; ok {
+				ts.PurposeKind = p
 			}
 		}
 
@@ -390,9 +368,7 @@ func (s *StoreEntry) ImportExcel2(ctx context.Context, data [][]string, excelHea
 	if len(eventEnterList) <= 0 {
 		return nil
 	}
-
-	return nil
-	return s.ExecExcelData(ctx, userModel.AppPasture.Id, eventEnterList)
+	return s.ExecExcelData(ctx, pastureId, eventEnterList)
 }
 
 func (s *StoreEntry) ExecExcelData(ctx context.Context, pastureId int64, dataList []*pasturePb.EventEnterRequest) error {
@@ -412,8 +388,7 @@ func (s *StoreEntry) ExecExcelData(ctx context.Context, pastureId int64, dataLis
 			if count > 0 {
 				continue
 			}
-
-			if err := s.CreateEnter(ctx, data); err != nil {
+			if err := s.ExcelImportEnter(ctx, data); err != nil {
 				return err
 			}
 		}

+ 12 - 7
module/backend/work.go

@@ -18,6 +18,11 @@ import (
 )
 
 func (s *StoreEntry) OrderList(ctx context.Context, req *pasturePb.SearchWorkOrderRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchWorkOrderResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
 	workOrderList := make([]*model.WorkOrderMaster, 0)
 	var count int64 = 0
 
@@ -51,11 +56,11 @@ func (s *StoreEntry) OrderList(ctx context.Context, req *pasturePb.SearchWorkOrd
 		return nil, xerr.WithStack(err)
 	}
 
-	priorityMap := s.WorkOrderPriorityMap()
-	frequencyMap := s.WorkOrderFrequencyMap()
-	subscribeUnitMap := s.WorkOrderSubUnitMap()
-	weekMap := s.WeekMap()
-	monthMap := s.MonthMap()
+	priorityMap := s.WorkOrderPriorityMap(userModel)
+	frequencyMap := s.WorkOrderFrequencyMap(userModel)
+	subscribeUnitMap := s.WorkOrderSubUnitMap(userModel)
+	weekMap := s.WeekMap(userModel)
+	monthMap := s.MonthMap(userModel)
 	return &pasturePb.SearchWorkOrderResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
@@ -76,7 +81,7 @@ func (s *StoreEntry) OrderCreateOrUpdate(ctx context.Context, req *pasturePb.Wor
 	if err != nil {
 		return xerr.WithStack(err)
 	}
-	workOrderCategoryMap := s.WorkOrderCategoryMap()
+	workOrderCategoryMap := s.WorkOrderCategoryMap(userModel)
 	systemUserList, _ := s.SystemUserList(ctx, userModel.AppPasture.Id)
 	newWorkOrderMaster := model.NewWorkOrderMaster(userModel.AppPasture.Id, req, userModel.SystemUser, systemUserList, workOrderCategoryMap)
 	if req.Id <= 0 {
@@ -278,7 +283,7 @@ func (s *StoreEntry) UserWorkOrderList(ctx context.Context, workOrderStatus past
 		mMap[workOrderMaster.Id] = workOrderMaster
 	}
 
-	priorityMap := s.WorkOrderPriorityMap()
+	priorityMap := s.WorkOrderPriorityMap(userModel)
 
 	return &pasturePb.UserWorkOrderResponse{
 		Code: http.StatusOK,

+ 2 - 1
module/crontab/cow_neck_ring_error.go

@@ -121,6 +121,7 @@ func (e *Entry) CowNeckRingError(pastureId int64) {
 		}
 	}
 
+	zaplog.Info("CowNeckRingError", zap.Any("updateNeckRingMap", updateNeckRingMap))
 	if len(updateNeckRingMap) > 0 {
 		for id, v := range updateNeckRingMap {
 			if err := e.DB.Model(new(model.NeckRing)).
@@ -244,7 +245,7 @@ func (e *Entry) NeckRingErrorOfReceivingLess(pastureId int64, neckRing *model.Ne
 		Where("id >= ?", originalMinId).
 		Where("neck_ring_number = ?", neckRing.NeckRingNumber).
 		Where("pasture_id = ?", pastureId).
-		Where("heat_date >= ?", dateTime).
+		Where("active_date >= ?", dateTime).
 		First(&originalStats).Error; err != nil {
 		zaplog.Error("NeckRingOriginal", zap.Any("err", err), zap.Any("pasture_id", pastureId))
 		return pasturePb.NeckRingNumberError_Invalid

+ 2 - 1
module/crontab/health_waning.go

@@ -148,7 +148,8 @@ func (e *Entry) FindNeckRingError(pastureId int64, neckRingNumber string) bool {
 		Where("pasture_id = ?", pastureId).
 		Where("neck_ring_number = ?", neckRingNumber).
 		Where("status = ?", pasturePb.IsShow_No).
-		Where("error_kind = ?", pasturePb.NeckRingNumberError_Suspected_Fall_Off).
+		Where(e.DB.Where("error_kind = ?", pasturePb.NeckRingNumberError_Suspected_Fall_Off).
+			Or("error_kind = ?", pasturePb.NeckRingNumberError_Receiving_Less)).
 		Count(&count).Error; err != nil {
 		return false
 	}

+ 5 - 3
module/crontab/neck_ring_estrus.go

@@ -143,6 +143,11 @@ func (e *Entry) CowEstrusWarning(pastureId int64, xToday *XToday, nowTime time.T
 				zaplog.Error("CowEstrusWarning", zap.Any("FindCowInfoByCowId", cowId))
 				continue
 			}
+
+			if cowInfo.Sex == pasturePb.Genders_Male || cowInfo.PurposeKind == pasturePb.Purpose_Fatten {
+				continue
+			}
+
 			isShow := pasturePb.IsShow_Ok
 			if cowInfo != nil && cowInfo.IsPregnant == pasturePb.IsShow_Ok && level == pasturePb.EstrusLevel_Low {
 				isShow = pasturePb.IsShow_No
@@ -155,7 +160,6 @@ func (e *Entry) CowEstrusWarning(pastureId int64, xToday *XToday, nowTime time.T
 			if e.HistoryNeckRingEstrus(pastureId, cowInfo.NeckRingNumber, activeTime) {
 				continue
 			}
-
 			zaplog.Info("CowEstrusWarning",
 				zap.Any("level", level),
 				zap.Any("b48", b48),
@@ -396,7 +400,6 @@ func calculateActiveLevel(cft float32, cowEstrus *CowEstrus, xToday *XToday) pas
 // getResult 根据b3数据计算结果
 func getResult(b3 *model.NeckRingEstrus, cft float32, cowEstrus *CowEstrus) pasturePb.CheckResult_Kind {
 	result := pasturePb.CheckResult_Pending
-
 	if b3.CheckResult == pasturePb.CheckResult_Correct {
 		result = pasturePb.CheckResult_Correct
 	}
@@ -404,6 +407,5 @@ func getResult(b3 *model.NeckRingEstrus, cft float32, cowEstrus *CowEstrus) past
 	if b3.CheckResult == pasturePb.CheckResult_Fail && b3.DayHigh > int32(cft)+cowEstrus.HadJust {
 		result = pasturePb.CheckResult_Fail
 	}
-
 	return result
 }

+ 21 - 0
module/crontab/neck_ring_health.go

@@ -4,6 +4,7 @@ import (
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"math"
+	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 
@@ -46,6 +47,9 @@ func (e *Entry) HealthWarning(pastureId int64, processIds []int64) {
 
 func (e *Entry) updateNeckRingHealth(pastureId int64, healthWarningList []*model.NeckRingHealth) {
 	for _, v := range healthWarningList {
+		if ok := e.CalculateNeckRingData(pastureId, v.CowId); !ok {
+			continue
+		}
 		startAt := util.TimeParseLocalUnix(v.HeatDate)
 		endAt := util.TimeParseLocalEndUnix(v.HeatDate)
 		isMove := e.isEventCowLog(pastureId, v.CowId, startAt, endAt, pasturePb.EventType_Transfer_Ben)
@@ -92,6 +96,23 @@ func (e *Entry) isEventCowLog(pastureId int64, CowId int64, startAt, endAt int64
 	return count > 0
 }
 
+// CalculateNeckRingData 判断牛只脖环数据是否大于3天
+func (e *Entry) CalculateNeckRingData(pastureId, cowId int64) bool {
+	var count int64
+	before3DaysDate := time.Now().AddDate(0, 0, -3).Local().Format(model.LayoutDate2)
+	if err := e.DB.Model(new(model.NeckActiveHabit)).
+		Where("pasture_id = ?", pastureId).
+		Where("cow_id = ?", cowId).
+		Where("heat_date = ?", before3DaysDate).
+		Count(&count).Error; err != nil {
+		return false
+	}
+	if count > 12 {
+		return true
+	}
+	return false
+}
+
 func calculateNewScore(data *model.NeckRingHealth) int32 {
 	otherScore := int32(0)
 

+ 4 - 0
module/crontab/other.go

@@ -108,6 +108,10 @@ func (e *Entry) NeckRingErrorEnumList(isAll string) []*pasturePb.ConfigOptionsLi
 		Value:    int32(pasturePb.NeckRingNumberError_Receiving_Less),
 		Label:    "接受率低",
 		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.NeckRingNumberError_Low_Battery),
+		Label:    "低电量",
+		Disabled: true,
 	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.NeckRingNumberError_Data_Latency),
 		Label:    "数据延迟",

+ 0 - 1
util/util.go

@@ -124,7 +124,6 @@ func TimeParseLocalUnix(DayTime string) int64 {
 	if len(DayTime) <= 11 {
 		value = fmt.Sprintf("%s 00:00:00", DayTime)
 	}
-
 	theTime, _ := TimeParseLocal(LayoutTime, value)
 	return theTime.Unix()
 }

+ 50 - 0
util/util_more_test.go

@@ -0,0 +1,50 @@
+package util
+
+import (
+	"fmt"
+	"sync"
+	"testing"
+)
+
+func cat(catCh, dogCh chan struct{}, wg *sync.WaitGroup) {
+	defer wg.Done()
+	for i := 0; i < 100; i++ {
+		<-catCh
+		fmt.Println("cat", i)
+		dogCh <- struct{}{}
+	}
+}
+
+func dog(dogCh, fishCh chan struct{}, wg *sync.WaitGroup) {
+	defer wg.Done()
+	for i := 0; i < 100; i++ {
+		<-dogCh
+		fmt.Println("dog", i)
+		fishCh <- struct{}{}
+	}
+}
+
+func fish(fishCh, catCh chan struct{}, wg *sync.WaitGroup) {
+	defer wg.Done()
+	for i := 0; i < 100; i++ {
+		<-fishCh
+		fmt.Println("fish", i)
+		catCh <- struct{}{}
+	}
+}
+
+func Test001(T *testing.T) {
+	catCh := make(chan struct{}, 1)
+	dogCh := make(chan struct{}, 1)
+	fishCh := make(chan struct{}, 1)
+	var wg sync.WaitGroup
+	wg.Add(3)
+
+	go cat(catCh, dogCh, &wg)
+	go dog(dogCh, fishCh, &wg)
+	go fish(fishCh, catCh, &wg)
+
+	catCh <- struct{}{}
+	wg.Wait()
+
+}

+ 6 - 6
util/util_test.go

@@ -535,10 +535,10 @@ type WeeklyActiveModel struct {
 }
 
 func Test_demo(t *testing.T) {
-	nowTime := time.Now().Local()
-	currentMonth := nowTime.Format(LayoutMonth)
-	startTime := time.Date(nowTime.Year(), nowTime.Month(), 1, 0, 0, 0, 0, nowTime.Location())
-	startMonth := startTime.AddDate(0, -5, 0).Format(LayoutMonth)
-	monthRang, _ := GetMonthsBetween(startMonth, currentMonth)
-	fmt.Println("currentMonth:", currentMonth, "startMonth:", startMonth, "monthRang", monthRang)
+	a := true
+	if !a {
+		fmt.Println("a")
+	} else {
+		fmt.Println("b")
+	}
 }