瀏覽代碼

enum: add matingWindowPeriod

Yi 1 月之前
父節點
當前提交
0ab65797d8

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250425035842-15ee838b15e8
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250427091240-4d1fa51de52c
 	gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eclipse/paho.mqtt.golang v1.4.3

+ 6 - 0
go.sum

@@ -70,6 +70,12 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250425025152-491564f7b245 h1:WSBs/sMm
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250425025152-491564f7b245/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250425035842-15ee838b15e8 h1:8EsgPwBQn44Ntxxk8Ysat0IAAlFaEGwl/fszj38I+wc=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250425035842-15ee838b15e8/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250427081352-93a6cd4b4694 h1:S4N8wO1YcY7Up+fPH6ggDsVaqRDxWKP3wT36m5sH3Ac=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250427081352-93a6cd4b4694/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250427084730-8129eb58bb83 h1:BlREMV1B0/dRYN5Z9ju6FWzGnx6caPxzqwL/aMY/+XE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250427084730-8129eb58bb83/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250427091240-4d1fa51de52c h1:oRoz0BJWx7zMsXWA1x/2EILg9e0iPFprs23NWDcU2zA=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250427091240-4d1fa51de52c/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b h1:w05MxH7yqveRlaRbxHhbif5YjPrJFodRPfOjYhXn7Zk=
 gitee.com/xuyiping_admin/pkg v0.0.0-20241108060137-caea58c59f5b/go.mod h1:8tF25X6pE9WkFCczlNAC0K2mrjwKvhhp02I7o0HtDxY=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=

+ 37 - 6
model/neck_ring_estrus_warning.go

@@ -73,9 +73,10 @@ func (n *NeckRingEstrusWarning) CalculatePzHour(lact int32) time.Time {
 
 type NeckRingEstrusWarningSlice []*NeckRingEstrusWarning
 
-func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[int64]string) []*pasturePb.EstrusItem {
-	res := make([]*pasturePb.EstrusItem, len(n))
-	for i, v := range n {
+func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[int64]string, matingWindowPeriodKind pasturePb.MatingWindowPeriod_Kind) []*pasturePb.EstrusItem {
+	res := make([]*pasturePb.EstrusItem, 0)
+	nowTime := time.Now().Local()
+	for _, v := range n {
 		cow, ok := cowMap[v.CowId]
 		if !ok {
 			cow = &Cow{Id: v.CowId}
@@ -93,7 +94,34 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 			diff := pzHour.Sub(lastTime)
 			estrusInterval = int32(diff.Hours() / 24)
 		}
-		res[i] = &pasturePb.EstrusItem{
+
+		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
+			}
+		}
+
+		firstTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.FirstTime)
+		afterAlarmTimeForHours := int32(nowTime.Sub(firstTimeParseLocal).Hours())
+		postPeakTimeForHours := int32(0)
+		if v.IsPeak == pasturePb.IsShow_Ok {
+			dateTimeParseLocal, _ := util.TimeParseLocal(LayoutTime, v.DateTime)
+			postPeakTimeForHours = int32(nowTime.Sub(dateTimeParseLocal).Hours())
+		}
+
+		data := &pasturePb.EstrusItem{
 			Id:                     int32(v.Id),
 			CowId:                  int32(v.CowId),
 			EarNumber:              v.EarNumber,
@@ -103,15 +131,18 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 			Lact:                   cow.Lact,
 			CalvingAge:             cow.CalvingAge,
 			AbortionAge:            cow.AbortionAge,
-			OptimumMatingStartTime: pzHour.Add(-4 * time.Hour).Format(LayoutTime),
-			OptimumMatingEndTime:   pzHour.Add(4 * time.Hour).Format(LayoutTime),
+			OptimumMatingStartTime: optimumMatingStartTime.Format(LayoutTime),
+			OptimumMatingEndTime:   optimumMatingEndTime.Format(LayoutTime),
 			LastBreedEventDetails:  lastBreedEventDetails,
 			Level:                  v.Level,
 			EstrusInterval:         estrusInterval,
 			BestMatingTime:         pzHour.Format(LayoutTime),
 			EstrusStartTime:        pzHour.Add(-8 * time.Hour).Format(LayoutTime),
 			EstrusEndTime:          pzHour.Add(8 * time.Hour).Format(LayoutTime),
+			AfterAlarmTimeForHours: afterAlarmTimeForHours,
+			PostPeakTimeForHours:   postPeakTimeForHours,
 		}
+		res = append(res, data)
 	}
 	return res
 }

+ 0 - 60
module/backend/config_data_base.go

@@ -383,63 +383,3 @@ func (s *StoreEntry) CowDeathDestinationList(isAll string) []*pasturePb.ConfigOp
 	})
 	return configOptions
 }
-
-func (s *StoreEntry) WarningHealthLevel(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(0),
-				Label:    "全部",
-				Disabled: true,
-			})
-	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WarningHealthLevel_Preliminary),
-		Label:    "初级疑似",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WarningHealthLevel_Moderate),
-		Label:    "中级疑似",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WarningHealthLevel_Height),
-		Label:    "高度疑似",
-		Disabled: true,
-	})
-	return configOptions
-}
-
-func (s *StoreEntry) Behavior(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	if isAll == model.IsAllYes {
-		configOptions = append(configOptions,
-			&pasturePb.ConfigOptionsList{
-				Value:    int32(0),
-				Label:    "全部",
-				Disabled: true,
-			})
-	}
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Behavior_Rumina),
-		Label:    "反刍",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Behavior_Intake),
-		Label:    "采食",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Behavior_Reset),
-		Label:    "休息",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Behavior_Immobility),
-		Label:    "静止",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Behavior_Chew),
-		Label:    "咀嚼",
-		Disabled: true,
-	})
-	return configOptions
-}

+ 0 - 96
module/backend/config_data_breed.go

@@ -278,64 +278,6 @@ func (s *StoreEntry) NeckRingStatusEnumList(isAll string) []*pasturePb.ConfigOpt
 	return configOptions
 }
 
-func (s *StoreEntry) WorkOrderSubUnitEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderSubscribeUnit_Person),
-		Label:    "个人",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderSubscribeUnit_dept),
-		Label:    "部门",
-		Disabled: true,
-	})
-	return configOptions
-}
-
-func (s *StoreEntry) WorkOrderPriorityEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Priority_Low),
-		Label:    "低",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Priority_Middle),
-		Label:    "一般",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.Priority_High),
-		Label:    "紧急",
-		Disabled: true,
-	})
-	return configOptions
-}
-
-func (s *StoreEntry) WorkOrderCategoryEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderCategory_Health),
-		Label:    "保健",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderCategory_Breed),
-		Label:    "繁殖",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderCategory_Nutrition),
-		Label:    "营养",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderCategory_Ordinary),
-		Label:    "日常",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.WorkOrderCategory_Other),
-		Label:    "其他",
-		Disabled: true,
-	})
-	return configOptions
-}
-
 func CalendarTypeEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
@@ -438,44 +380,6 @@ func (s *StoreEntry) AbortionReasonsEnumList(isAll string) []*pasturePb.ConfigOp
 	return configOptions
 }
 
-func (s *StoreEntry) HealthStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
-	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
-	if isAll == model.IsAllYes {
-		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-			Value:    int32(pasturePb.HealthStatus_Invalid),
-			Label:    "全部",
-			Disabled: true,
-		})
-	}
-
-	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.HealthStatus_Health),
-		Label:    "健康",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.HealthStatus_Disease),
-		Label:    "发病",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.HealthStatus_Treatment),
-		Label:    "治疗中",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.HealthStatus_Curable),
-		Label:    "治愈",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.HealthStatus_Out),
-		Label:    "淘汰",
-		Disabled: true,
-	}, &pasturePb.ConfigOptionsList{
-		Value:    int32(pasturePb.HealthStatus_Dead),
-		Label:    "死亡",
-		Disabled: true,
-	})
-	return configOptions
-}
-
 func (s *StoreEntry) CalvingAnalysisMethodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {

+ 182 - 0
module/backend/config_data_extend.go

@@ -6,6 +6,64 @@ import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
+func (s *StoreEntry) WorkOrderSubUnitEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderSubscribeUnit_Person),
+		Label:    "个人",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderSubscribeUnit_dept),
+		Label:    "部门",
+		Disabled: true,
+	})
+	return configOptions
+}
+
+func (s *StoreEntry) WorkOrderPriorityEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Priority_Low),
+		Label:    "低",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Priority_Middle),
+		Label:    "一般",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Priority_High),
+		Label:    "紧急",
+		Disabled: true,
+	})
+	return configOptions
+}
+
+func (s *StoreEntry) WorkOrderCategoryEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderCategory_Health),
+		Label:    "保健",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderCategory_Breed),
+		Label:    "繁殖",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderCategory_Nutrition),
+		Label:    "营养",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderCategory_Ordinary),
+		Label:    "日常",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WorkOrderCategory_Other),
+		Label:    "其他",
+		Disabled: true,
+	})
+	return configOptions
+}
+
 func (s *StoreEntry) AdmissionStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
 	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
 	if isAll == model.IsAllYes {
@@ -81,3 +139,127 @@ func (s *StoreEntry) ForbiddenMatingReasonsEnumList(isAll string) []*pasturePb.C
 	})
 	return configOptions
 }
+
+func (s *StoreEntry) WarningHealthLevel(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	if isAll == model.IsAllYes {
+		configOptions = append(configOptions,
+			&pasturePb.ConfigOptionsList{
+				Value:    int32(0),
+				Label:    "全部",
+				Disabled: true,
+			})
+	}
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WarningHealthLevel_Preliminary),
+		Label:    "初级疑似",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WarningHealthLevel_Moderate),
+		Label:    "中级疑似",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.WarningHealthLevel_Height),
+		Label:    "高度疑似",
+		Disabled: true,
+	})
+	return configOptions
+}
+
+func (s *StoreEntry) Behavior(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	if isAll == model.IsAllYes {
+		configOptions = append(configOptions,
+			&pasturePb.ConfigOptionsList{
+				Value:    int32(0),
+				Label:    "全部",
+				Disabled: true,
+			})
+	}
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Behavior_Rumina),
+		Label:    "反刍",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Behavior_Intake),
+		Label:    "采食",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Behavior_Reset),
+		Label:    "休息",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Behavior_Immobility),
+		Label:    "静止",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.Behavior_Chew),
+		Label:    "咀嚼",
+		Disabled: true,
+	})
+	return configOptions
+}
+
+func (s *StoreEntry) HealthStatusEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	if isAll == model.IsAllYes {
+		configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+			Value:    int32(pasturePb.HealthStatus_Invalid),
+			Label:    "全部",
+			Disabled: true,
+		})
+	}
+
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.HealthStatus_Health),
+		Label:    "健康",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.HealthStatus_Disease),
+		Label:    "发病",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.HealthStatus_Treatment),
+		Label:    "治疗中",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.HealthStatus_Curable),
+		Label:    "治愈",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.HealthStatus_Out),
+		Label:    "淘汰",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.HealthStatus_Dead),
+		Label:    "死亡",
+		Disabled: true,
+	})
+	return configOptions
+}
+
+func (s *StoreEntry) MatingWindowPeriodEnumList(isAll string) []*pasturePb.ConfigOptionsList {
+	configOptions := make([]*pasturePb.ConfigOptionsList, 0)
+	if isAll == model.IsAllYes {
+		configOptions = append(configOptions,
+			&pasturePb.ConfigOptionsList{
+				Value:    int32(0),
+				Label:    "全部",
+				Disabled: true,
+			})
+	}
+	configOptions = append(configOptions, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.MatingWindowPeriod_Front),
+		Label:    "早期",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.MatingWindowPeriod_Middle),
+		Label:    "最优",
+		Disabled: true,
+	}, &pasturePb.ConfigOptionsList{
+		Value:    int32(pasturePb.MatingWindowPeriod_Behind),
+		Label:    "晚期",
+		Disabled: true,
+	})
+	return configOptions
+}

+ 1 - 0
module/backend/enum_options.go

@@ -222,6 +222,7 @@ func (s *StoreEntry) SystemBaseConfigOptions(ctx context.Context, optionsName, i
 		"deathDestination":           s.CowDeathDestinationList,
 		"warningHealthLevel":         s.WarningHealthLevel,
 		"behavior":                   s.Behavior,
+		"matingWindowPeriod":         s.MatingWindowPeriodEnumList,
 	}
 
 	getConfigFunc, ok := getConfigFuncMap[optionsName]

+ 1 - 1
module/backend/neck_ring_warning.go

@@ -80,7 +80,7 @@ func (s *StoreEntry) NeckRingWarningEstrusOrAbortionCowList(ctx context.Context,
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.EstrusData{
-			List:     model.NeckRingEstrusWarningSlice(neckRingEstrusList).ToPB(cowMap, eventLogMap),
+			List:     model.NeckRingEstrusWarningSlice(neckRingEstrusList).ToPB(cowMap, eventLogMap, req.MatingWindowPeriod),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,