Bläddra i källkod

cow: 牛只活动曲线

Yi 1 vecka sedan
förälder
incheckning
78d7dbfc20

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250313095848-b25e11bbb7d0
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250319122035-8a8593d0cae9
 	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

+ 8 - 0
go.sum

@@ -40,6 +40,14 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250309141840-4e483354df00 h1:ejRZ6U1v
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250309141840-4e483354df00/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250313095848-b25e11bbb7d0 h1:OqYENfy4l9CwmAqvBqL88K5eAb7CVQC4QHdxCU67du8=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250313095848-b25e11bbb7d0/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319100822-e116d54d9576 h1:GdTqhxbWyJFWdvf6nfyj7sOhLoXV/T/wdBLJXWwB4C8=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319100822-e116d54d9576/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319101442-da4bbb71c8f0 h1:5sTGq6O8p7Wjb79bDGfIthCANaRj7A+/ENzlQa59OR4=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319101442-da4bbb71c8f0/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319101753-c158097ddaa7 h1:Ex4WiajO+A5O3vvstrsONguSN0SAyI0tpvn35cP0Olw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319101753-c158097ddaa7/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319122035-8a8593d0cae9 h1:4HUr1cFR5aIFjiiSgyoL0s5zTWwUFC79Jf0JDEyUCgU=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250319122035-8a8593d0cae9/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=

+ 22 - 0
http/handler/work/item.go

@@ -131,3 +131,25 @@ func NeckRingWarningEstrusItem(c *gin.Context) {
 
 	ginutil.JSONResp(c, res)
 }
+
+func NeckRingWarningAbortionItem(c *gin.Context) {
+	var req pasturePb.EstrusItemsRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	pagination := &pasturePb.PaginationModel{
+		Page:       int32(c.GetInt(middleware.Page)),
+		PageSize:   int32(c.GetInt(middleware.PageSize)),
+		PageOffset: int32(c.GetInt(middleware.PageOffset)),
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.EstrusCowList(c, &req, pagination)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, res)
+}

+ 1 - 0
http/route/work_api.go

@@ -31,6 +31,7 @@ func WorkOrderAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		workRoute.POST("/mating/items", work.MatingCowList)
 		workRoute.POST("/calving/items", work.CalvingList)
 		workRoute.POST("/estrus/items", work.NeckRingWarningEstrusItem)
+		workRoute.POST("/abortion/items", work.NeckRingWarningAbortionItem)
 		workRoute.POST("/disease/items", event.CowDiseaseList)
 	}
 }

+ 1 - 0
model/cow.go

@@ -523,6 +523,7 @@ 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        map[string][]string                     `json:"eventList"`        // 事件数据

+ 7 - 2
model/neck_active_habit.go

@@ -162,6 +162,7 @@ func (n NeckActiveHabitSlice) ToPB(curveName string) *CowBehaviorCurveData {
 						res.ChangeDateList = append(res.ChangeDateList, 0)
 						res.SumDateList = append(res.SumDateList, 0)
 						res.RuminaChange = append(res.RuminaChange, 0)
+						res.SumChewList = append(res.SumChewList, 0)
 					}
 				}
 			}
@@ -175,6 +176,7 @@ func (n NeckActiveHabitSlice) ToPB(curveName string) *CowBehaviorCurveData {
 				res.ChangeDateList = append(res.ChangeDateList, 0)
 				res.SumDateList = append(res.SumDateList, 0)
 				res.RuminaChange = append(res.RuminaChange, 0)
+				res.SumChewList = append(res.SumChewList, 0)
 			}
 			initFrameId = expectedFrameId
 		}
@@ -194,17 +196,20 @@ func (n NeckActiveHabitSlice) ToPB(curveName string) *CowBehaviorCurveData {
 			res.RuminaChange = append(res.RuminaChange, v.RuminaFilter)
 		case "rumina": // 反刍
 			res.OriginalDateList = append(res.OriginalDateList, v.Rumina)
-			res.ChangeDateList = append(res.ChangeDateList, v.FilterRumina)
+			res.ChangeDateList = append(res.ChangeDateList, v.RuminaFilter)
 			res.SumDateList = append(res.SumDateList, v.SumRumina)
+			res.SumChewList = append(res.SumChewList, v.SumRumina+v.SumIntake)
 		case "intake": // 采食
 			res.OriginalDateList = append(res.OriginalDateList, v.Intake)
 			res.SumDateList = append(res.SumDateList, v.SumIntake)
+			res.SumChewList = append(res.SumChewList, v.SumRumina+v.SumIntake)
 		case "inactive": // 休息
 			res.OriginalDateList = append(res.OriginalDateList, v.Inactive)
 			res.SumDateList = append(res.SumDateList, v.SumInactive)
 		case "chew": // 咀嚼
-			res.OriginalDateList = append(res.OriginalDateList, v.FilterChew)
+			res.OriginalDateList = append(res.OriginalDateList, v.Rumina+v.Intake)
 			res.ChangeDateList = append(res.ChangeDateList, v.ChangeChew)
+			res.SumDateList = append(res.ChangeDateList, v.SumRumina+v.SumIntake)
 		case "immobility": // 静止
 			res.OriginalDateList = append(res.OriginalDateList, 120-v.Active)
 			res.SumDateList = append(res.SumDateList, 60*24-v.SumActive)

+ 3 - 4
model/neck_ring_estrus_warning.go

@@ -73,8 +73,8 @@ func (n *NeckRingEstrusWarning) calculatePzHour(lact int32) time.Time {
 
 type NeckRingEstrusWarningSlice []*NeckRingEstrusWarning
 
-func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[int64]string) []*pasturePb.EstrusItems {
-	res := make([]*pasturePb.EstrusItems, len(n))
+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 {
 		cow, ok := cowMap[v.CowId]
 		if !ok {
@@ -93,13 +93,12 @@ func (n NeckRingEstrusWarningSlice) ToPB(cowMap map[int64]*Cow, eventLogMap map[
 			diff := pzHour.Sub(lastTime)
 			estrusInterval = int32(diff.Hours() / 24)
 		}
-		res[i] = &pasturePb.EstrusItems{
+		res[i] = &pasturePb.EstrusItem{
 			Id:                     int32(v.Id),
 			CowId:                  int32(v.CowId),
 			EarNumber:              v.EarNumber,
 			PenId:                  cow.PenId,
 			PenName:                cow.PenName,
-			DayAge:                 cow.DayAge,
 			MatingTimes:            cow.MatingTimes,
 			Lact:                   cow.Lact,
 			CalvingAge:             cow.CalvingAge,

+ 0 - 82
module/backend/event_health.go

@@ -4,7 +4,6 @@ import (
 	"context"
 	"fmt"
 	"kpt-pasture/model"
-	"kpt-pasture/util"
 	"net/http"
 	"strings"
 	"time"
@@ -188,87 +187,6 @@ func (s *StoreEntry) CowDiseaseCreate(ctx context.Context, req *pasturePb.EventC
 	return nil
 }
 
-func (s *StoreEntry) EstrusCowList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EventEstrusResponse, error) {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	systemBasic, err := s.FindSystemBasic(ctx, userModel.AppPasture.Id, model.EstrusWaringDays)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	nowTime := time.Now()
-	startTime := time.Unix(util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
-	entTime := time.Unix(util.TimeParseLocalEndUnix(nowTime.AddDate(0, 0, 1).Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
-	var count int64
-	neckRingEstrusList := make([]*model.NeckRingEstrusWarning, 0)
-	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.NeckRingEstrusWarning).TableName())).
-		Joins(fmt.Sprintf("JOIN %s AS b on a.cow_id = b.id", new(model.Cow).TableName())).
-		Where("b.last_mating_at < UNIX_TIMESTAMP(a.date_time)").
-		Where("b.admission_status = ?", pasturePb.AdmissionStatus_Admission).
-		Where("b.is_not_mating = ?", pasturePb.IsShow_No).
-		Where("a.level >= ?", pasturePb.EstrusLevel_Low).
-		Where("a.pasture_id = ?", userModel.AppPasture.Id).
-		Where("a.date_time BETWEEN ? AND ?", startTime, entTime).
-		Where(s.DB.Where("b.last_mating_at < UNIX_TIMESTAMP(a.first_time)").
-			Or(s.DB.Where("b.last_mating_at = ?", 0).
-				Where("b.calving_age > ?", systemBasic.MinValue).
-				Or("b.lact = ?", 0))).
-		Where("a.is_show = ?", pasturePb.IsShow_Ok)
-
-	if len(req.EarNumber) > 0 {
-		pref.Where("a.ear_number = ?", req.EarNumber)
-	}
-
-	if req.Level > 0 {
-		pref.Where("a.level = ?", req.Level)
-	}
-
-	if len(req.PenIds) > 0 {
-		penIds := strings.Split(util.ArrayInt32ToStrings(req.PenIds, ","), ",")
-		pref.Where("b.pen_id IN ?", penIds)
-	}
-
-	if err = pref.Order("a.level DESC").
-		Count(&count).
-		Limit(int(pagination.PageSize)).
-		Offset(int(pagination.PageOffset)).
-		Find(&neckRingEstrusList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	cowMap := make(map[int64]*model.Cow)
-	eventLogMap := make(map[int64]string)
-	cowIds := make([]int64, 0)
-	for _, v := range neckRingEstrusList {
-		cowIds = append(cowIds, v.CowId)
-		lastEventLog := s.GetCowLastEvent(userModel.AppPasture.Id, v.CowId, pasturePb.EventCategory_Breed)
-		if lastEventLog != nil {
-			eventLogMap[v.CowId] = lastEventLog.EventDescription
-		}
-	}
-
-	if len(cowIds) > 0 {
-		cowList, _ := s.GetCowInfoByCowIds(ctx, userModel.AppPasture.Id, cowIds)
-		for _, cow := range cowList {
-			cowMap[cow.Id] = cow
-		}
-	}
-
-	return &pasturePb.EventEstrusResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &pasturePb.EstrusItemsData{
-			List:     model.NeckRingEstrusWarningSlice(neckRingEstrusList).ToPB(cowMap, eventLogMap),
-			Total:    int32(count),
-			PageSize: pagination.PageSize,
-			Page:     pagination.Page,
-		},
-	}, nil
-}
-
 // CowDiseaseList 发病牛只清单
 func (s *StoreEntry) CowDiseaseList(ctx context.Context, req *pasturePb.SearchEventCowTreatmentRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EventCowDiseaseResponse, error) {
 	userModel, err := s.GetUserModel(ctx)

+ 1 - 1
module/backend/interface.go

@@ -298,7 +298,7 @@ type WorkService interface {
 	MatingCowList(ctx context.Context, req *pasturePb.ItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.MatingItemsResponse, error)
 	CalvingCowList(ctx context.Context, req *pasturePb.ItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.CalvingItemsResponse, error)
 	CowDiseaseList(ctx context.Context, req *pasturePb.SearchEventCowTreatmentRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EventCowDiseaseResponse, error)
-	EstrusCowList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EventEstrusResponse, error)
+	EstrusCowList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusResponse, error)
 }
 
 type TestService interface {

+ 95 - 0
module/backend/neck_ring_warning.go

@@ -0,0 +1,95 @@
+package backend
+
+import (
+	"context"
+	"fmt"
+	"kpt-pasture/model"
+	"kpt-pasture/util"
+	"net/http"
+	"strings"
+	"time"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+)
+
+func (s *StoreEntry) EstrusCowList(ctx context.Context, req *pasturePb.EstrusItemsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.EstrusResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	systemBasic, err := s.FindSystemBasic(ctx, userModel.AppPasture.Id, model.EstrusWaringDays)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	nowTime := time.Now()
+	startTime := time.Unix(util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
+	entTime := time.Unix(util.TimeParseLocalEndUnix(nowTime.AddDate(0, 0, 1).Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
+	var count int64
+	neckRingEstrusList := make([]*model.NeckRingEstrusWarning, 0)
+	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.NeckRingEstrusWarning).TableName())).
+		Joins(fmt.Sprintf("JOIN %s AS b on a.cow_id = b.id", new(model.Cow).TableName())).
+		Where("b.last_mating_at < UNIX_TIMESTAMP(a.date_time)").
+		Where("b.admission_status = ?", pasturePb.AdmissionStatus_Admission).
+		Where("b.is_not_mating = ?", pasturePb.IsShow_No).
+		Where("a.level >= ?", pasturePb.EstrusLevel_Low).
+		Where("a.pasture_id = ?", userModel.AppPasture.Id).
+		Where("a.date_time BETWEEN ? AND ?", startTime, entTime).
+		Where(s.DB.Where("b.last_mating_at < UNIX_TIMESTAMP(a.first_time)").
+			Or(s.DB.Where("b.last_mating_at = ?", 0).
+				Where("b.calving_age > ?", systemBasic.MinValue).
+				Or("b.lact = ?", 0))).
+		Where("a.is_show = ?", pasturePb.IsShow_Ok)
+
+	if len(req.EarNumber) > 0 {
+		pref.Where("a.ear_number = ?", req.EarNumber)
+	}
+
+	if req.Level > 0 {
+		pref.Where("a.level = ?", req.Level)
+	}
+
+	if len(req.PenIds) > 0 {
+		penIds := strings.Split(util.ArrayInt32ToStrings(req.PenIds, ","), ",")
+		pref.Where("b.pen_id IN ?", penIds)
+	}
+
+	if err = pref.Order("a.level DESC").
+		Count(&count).
+		Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&neckRingEstrusList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	cowMap := make(map[int64]*model.Cow)
+	eventLogMap := make(map[int64]string)
+	cowIds := make([]int64, 0)
+	for _, v := range neckRingEstrusList {
+		cowIds = append(cowIds, v.CowId)
+		lastEventLog := s.GetCowLastEvent(userModel.AppPasture.Id, v.CowId, pasturePb.EventCategory_Breed)
+		if lastEventLog != nil {
+			eventLogMap[v.CowId] = lastEventLog.EventDescription
+		}
+	}
+
+	if len(cowIds) > 0 {
+		cowList, _ := s.GetCowInfoByCowIds(ctx, userModel.AppPasture.Id, cowIds)
+		for _, cow := range cowList {
+			cowMap[cow.Id] = cow
+		}
+	}
+
+	return &pasturePb.EstrusResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &pasturePb.EstrusData{
+			List:     model.NeckRingEstrusWarningSlice(neckRingEstrusList).ToPB(cowMap, eventLogMap),
+			Total:    int32(count),
+			PageSize: pagination.PageSize,
+			Page:     pagination.Page,
+		},
+	}, nil
+}