Browse Source

dashboard: 首页关注指标

ping 1 month ago
parent
commit
28563a5fa4

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250211104420-863ff8fc2535
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250212025811-9b8f9f1277a3
 	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

@@ -179,6 +179,12 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250211104144-848fe88b8c1e h1:x+sO/2mr
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250211104144-848fe88b8c1e/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250211104420-863ff8fc2535 h1:fiM+bgvJRorAZCwgzMTXgolvF7AhEM7hx/MkmokhrOk=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250211104420-863ff8fc2535/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250211131456-ede951183da7 h1:5KZ1y+jPDf572OW5xrrm0cMhpTbnAxKaDMJW13P7AWA=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250211131456-ede951183da7/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250211132718-87536ed342b5 h1:Bt+bNBIYPDROpk9V8Vdr+iSBQsjaYeYJusXGAXqQxYQ=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250211132718-87536ed342b5/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250212025811-9b8f9f1277a3 h1:J6mQy1zYbBeFDdCECev2DS1HEAnuroTfC4EP4FtzmFA=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250212025811-9b8f9f1277a3/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=

+ 23 - 0
http/handler/dashboard/dashboard.go

@@ -4,6 +4,10 @@ import (
 	"kpt-pasture/http/middleware"
 	"net/http"
 
+	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+
 	"gitee.com/xuyiping_admin/pkg/valid"
 
 	"gitee.com/xuyiping_admin/pkg/apierr"
@@ -42,3 +46,22 @@ func FocusIndicators(c *gin.Context) {
 	}
 	ginutil.JSONResp(c, res)
 }
+
+func FocusIndicatorsSet(c *gin.Context) {
+	var req pasturePb.IndexFocusIndicatorsSetRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+
+	if err := middleware.Dependency(c).StoreEventHub.OpsService.FocusIndicatorsSet(c, &req); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}

+ 1 - 0
http/route/dashboard_api.go

@@ -16,5 +16,6 @@ func DashboardApi(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		dashboardRoute.GET("/bar", dashboard.Bar)
 		dashboardRoute.GET("/neck_ring/warning", dashboard.NeckRingWarning)
 		dashboardRoute.GET("/focus/indicators/:dimension", dashboard.FocusIndicators)
+		dashboardRoute.POST("/focus/indicators/set", dashboard.FocusIndicatorsSet)
 	}
 }

+ 38 - 0
model/event_estrus.go

@@ -1,6 +1,9 @@
 package model
 
 import (
+	"fmt"
+	"kpt-pasture/store/kptstore"
+
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
@@ -63,3 +66,38 @@ func NewEventEstrus(
 		MessageName:      currentUser.Name,
 	}
 }
+
+type EventEstrusSlice []*EventEstrus
+
+func (e EventEstrusSlice) ToPB(
+	dB *kptstore.DB,
+	getCowInfo func(dB *kptstore.DB, cowId int64) *Cow,
+	getCowLastEvent func(DB *kptstore.DB, cowId int64, eventCategoryId pasturePb.EventCategory_Kind) *EventCowLog,
+) []*pasturePb.EstrusItems {
+	res := make([]*pasturePb.EstrusItems, len(e))
+	for i, v := range e {
+		cowInfo := getCowInfo(dB, v.CowId)
+		lastEventLog := getCowLastEvent(dB, v.CowId, pasturePb.EventCategory_Breed)
+		planDay, optimumMatingTime := "", ""
+		lastBreedEventDetails := ""
+		if lastEventLog != nil {
+			lastBreedEventDetails = fmt.Sprintf("%s %s", lastEventLog.EventTypeName, lastEventLog.EventDescription)
+		}
+		res[i] = &pasturePb.EstrusItems{
+			Id:                     int32(v.Id),
+			CowId:                  int32(v.CowId),
+			EarNumber:              v.EarNumber,
+			DayAge:                 cowInfo.DayAge,
+			Lact:                   v.Lact,
+			PenName:                cowInfo.PenName,
+			Status:                 v.IsShow,
+			CalvingAge:             cowInfo.CalvingAge,
+			PlanDay:                planDay,
+			MatingTimes:            cowInfo.MatingTimes,
+			OptimumMatingStartTime: optimumMatingTime,
+			OptimumMatingEndTime:   optimumMatingTime,
+			LastBreedEventDetails:  lastBreedEventDetails,
+		}
+	}
+	return res
+}

+ 24 - 0
model/indicators_details.go

@@ -2,6 +2,8 @@ package model
 
 import pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 
+const DefaultFocusIndicators = "all_cow,output_number,input_number,fatten_cattle_number,sales_volume"
+
 type IndicatorsDetails struct {
 	Id           int                          `json:"id"`
 	Kind         string                       `json:"kind"`
@@ -17,3 +19,25 @@ type IndicatorsDetails struct {
 func (IndicatorsDetails) TableName() string {
 	return "indicators_details"
 }
+
+type IndicatorsDetailsSlice []*IndicatorsDetails
+
+func (i IndicatorsDetailsSlice) ToPB(userFocusIndicators []string) []*pasturePb.FocusIndicatorsSetData {
+	res := make([]*pasturePb.FocusIndicatorsSetData, len(i))
+	for k, v := range i {
+		isShow := pasturePb.IsShow_No
+		for _, useIndicators := range userFocusIndicators {
+			if useIndicators == v.Kind {
+				isShow = pasturePb.IsShow_Ok
+			}
+		}
+		res[k] = &pasturePb.FocusIndicatorsSetData{
+			Name:              v.Name,
+			Kind:              v.Kind,
+			IndicatorTypeKind: v.CategoryType,
+			IndicatorTypeName: v.CategoryName,
+			IsShow:            isShow,
+		}
+	}
+	return res
+}

+ 0 - 38
model/neck_ring_estrus.go

@@ -1,9 +1,6 @@
 package model
 
 import (
-	"fmt"
-	"kpt-pasture/store/kptstore"
-
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
@@ -53,38 +50,3 @@ func NewNeckRingEstrus(
 		CheckResult:      checkResult,
 	}
 }
-
-type NeckRingEstrusSlice []*NeckRingEstrus
-
-func (e NeckRingEstrusSlice) ToPB(
-	dB *kptstore.DB,
-	getCowInfo func(dB *kptstore.DB, cowId int64) *Cow,
-	getCowLastEvent func(DB *kptstore.DB, cowId int64, eventCategoryId pasturePb.EventCategory_Kind) *EventCowLog,
-) []*pasturePb.EstrusItems {
-	res := make([]*pasturePb.EstrusItems, len(e))
-	for i, v := range e {
-		cowInfo := getCowInfo(dB, v.CowId)
-		lastEventLog := getCowLastEvent(dB, v.CowId, pasturePb.EventCategory_Breed)
-		planDay, optimumMatingTime := "", ""
-		lastBreedEventDetails := ""
-		if lastEventLog != nil {
-			lastBreedEventDetails = fmt.Sprintf("%s %s", lastEventLog.EventTypeName, lastEventLog.EventDescription)
-		}
-		res[i] = &pasturePb.EstrusItems{
-			Id:                     int32(v.Id),
-			CowId:                  int32(v.CowId),
-			EarNumber:              v.EarNumber,
-			DayAge:                 cowInfo.DayAge,
-			Lact:                   v.Lact,
-			PenName:                cowInfo.PenName,
-			Status:                 v.IsShow,
-			CalvingAge:             cowInfo.CalvingAge,
-			PlanDay:                planDay,
-			MatingTimes:            cowInfo.MatingTimes,
-			OptimumMatingStartTime: optimumMatingTime,
-			OptimumMatingEndTime:   optimumMatingTime,
-			LastBreedEventDetails:  lastBreedEventDetails,
-		}
-	}
-	return res
-}

+ 21 - 13
module/backend/calendar.go

@@ -425,8 +425,15 @@ func (s *StoreEntry) MatingCowList(ctx context.Context, req *pasturePb.ItemsRequ
 	matingItems := make([]*pasturePb.MatingItems, 0)
 	count := int64(0)
 	pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.EventMating).TableName())).
-		Select(`a.id,a.cow_id,a.status,a.ear_number,b.breed_status,b.cow_type,b.pen_id,b.day_age,
-		b.calving_age,b.abortion_age,c.name as pen_name`).
+		Select(`a.id,a.cow_id,a.status,a.ear_number,
+		CASE a.expose_estrus_type
+        WHEN 1 THEN '脖环揭发'
+        WHEN 2 THEN '脚环/计步器'
+        WHEN 3 THEN '自然发情'
+        WHEN 4 THEN '同期'
+        ELSE '其他'
+		END AS expose_estrus_type_name,
+		b.breed_status,b.cow_type,b.pen_id,b.day_age,b.calving_age,b.abortion_age,c.name as pen_name`).
 		Joins("left join cow as b on a.cow_id = b.id").
 		Joins("left join pen as c on a.pen_id = c.id").
 		Where("a.pasture_id = ?", userModel.AppPasture.Id).
@@ -461,17 +468,18 @@ func (s *StoreEntry) MatingCowList(ctx context.Context, req *pasturePb.ItemsRequ
 			Page:     pagination.Page,
 			PageSize: pagination.PageSize,
 			Header: map[string]string{
-				"id":              "编号",
-				"cowId":           "牛号",
-				"earNumber":       "耳标号",
-				"breedStatusName": "繁殖状态",
-				"cowTypeName":     "牛只类型",
-				"penName":         "栏舍",
-				"lact":            "胎次",
-				"calvingAge":      "产后天数",
-				"abortionAge":     "流产天数",
-				"dayAge":          "日龄",
-				"status":          "状态",
+				"id":                   "编号",
+				"cowId":                "牛号",
+				"earNumber":            "耳标号",
+				"breedStatusName":      "繁殖状态",
+				"cowTypeName":          "牛只类型",
+				"penName":              "栏舍",
+				"lact":                 "胎次",
+				"calvingAge":           "产后天数",
+				"abortionAge":          "流产天数",
+				"dayAge":               "日龄",
+				"status":               "状态",
+				"exposeEstrusTypeName": "发情揭发方式",
 			},
 			List: matingItems,
 		},

+ 28 - 5
module/backend/dashboard.go

@@ -88,7 +88,7 @@ func (s *StoreEntry) NeckRingWarning(ctx context.Context) (*pasturePb.IndexNeckR
 
 }
 
-func (s *StoreEntry) FocusIndicators(ctx context.Context, dimension string) (*pasturePb.IndexFocusIndicatorsResponse, error) {
+func (s *StoreEntry) FocusIndicatorsList(ctx context.Context, dimension string) (*pasturePb.IndexFocusIndicatorsResponse, error) {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
 		return nil, xerr.WithStack(err)
@@ -96,7 +96,7 @@ func (s *StoreEntry) FocusIndicators(ctx context.Context, dimension string) (*pa
 
 	userFocusIndicators := userModel.SystemUser.IndicatorsKinds
 	if len(userFocusIndicators) <= 0 {
-		userFocusIndicators = "all_cow,output_number,input_number,fatten_cattle_number,sales_volume"
+		userFocusIndicators = model.DefaultFocusIndicators
 	}
 	userFocusIndicatorsList := strings.Split(userFocusIndicators, ",")
 	indicatorsDataList := make([]*model.IndicatorsData, 0)
@@ -121,7 +121,7 @@ func (s *StoreEntry) FocusIndicators(ctx context.Context, dimension string) (*pa
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
-	data := make([]*pasturePb.FocusData, 0)
+	focusIndicatorsList := make([]*pasturePb.FocusIndicators, 0)
 	for _, v := range indicatorsDataList {
 		indicatorsDetails, ok := indicatorsDetailsMap[v.Kind]
 		if !ok {
@@ -145,7 +145,7 @@ func (s *StoreEntry) FocusIndicators(ctx context.Context, dimension string) (*pa
 				}
 			}
 		}
-		data = append(data, &pasturePb.FocusData{
+		focusIndicatorsList = append(focusIndicatorsList, &pasturePb.FocusIndicators{
 			Kind:     indicatorsDetails.Kind,
 			Name:     indicatorsDetails.Name,
 			Value:    v.Value,
@@ -155,9 +155,32 @@ func (s *StoreEntry) FocusIndicators(ctx context.Context, dimension string) (*pa
 			OnYear:   onYear,
 		})
 	}
+
+	indicatorsDetailsList, _ := s.FindIndicatorsDetailsList(ctx)
+
 	return &pasturePb.IndexFocusIndicatorsResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: data,
+		Data: &pasturePb.FocusData{
+			FocusIndicators: focusIndicatorsList,
+			IndicatorsSet:   model.IndicatorsDetailsSlice(indicatorsDetailsList).ToPB(userFocusIndicatorsList),
+		},
 	}, err
 }
+
+func (s *StoreEntry) FocusIndicatorsSet(ctx context.Context, req *pasturePb.IndexFocusIndicatorsSetRequest) error {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	if len(req.IndicatorsKind) <= 0 {
+		return nil
+	}
+
+	userFocusIndicators := strings.Join(req.IndicatorsKind, ",")
+	if err = s.DB.Model(new(model.SystemUser)).Where("id = ?", userModel.SystemUser.Id).Update("indicators_kinds", userFocusIndicators).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}

+ 3 - 3
module/backend/event_breed.go

@@ -318,9 +318,9 @@ func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.EstrusItemsR
 		return nil, xerr.WithStack(err)
 	}
 
-	estrusList := make([]*model.NeckRingEstrus, 0)
+	estrusList := make([]*model.EventEstrus, 0)
 	var count int64 = 0
-	pref := s.DB.Table(new(model.NeckRingEstrus).TableName()).
+	pref := s.DB.Table(new(model.EventEstrus).TableName()).
 		Where("is_show = ?", pasturePb.IsShow_Ok).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
 		Where("expose_estrus_type = ?", pasturePb.ExposeEstrusType_Natural_Estrus)
@@ -351,7 +351,7 @@ func (s *StoreEntry) EstrusList(ctx context.Context, req *pasturePb.EstrusItemsR
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &pasturePb.EstrusItemsData{
-			List:     model.NeckRingEstrusSlice(estrusList).ToPB(s.DB, getCowInfoByCowId, getCowLastEvent),
+			List:     model.EventEstrusSlice(estrusList).ToPB(s.DB, getCowInfoByCowId, getCowLastEvent),
 			Total:    int32(count),
 			PageSize: pagination.PageSize,
 			Page:     pagination.Page,

+ 2 - 1
module/backend/interface.go

@@ -261,7 +261,8 @@ type AnalyseService interface {
 type DashboardService interface {
 	Bar(ctx context.Context) (*pasturePb.BarCowStructResponse, error)
 	NeckRingWarning(ctx context.Context) (*pasturePb.IndexNeckRingResponse, error)
-	FocusIndicators(ctx context.Context, dimension string) (*pasturePb.IndexFocusIndicatorsResponse, error)
+	FocusIndicatorsList(ctx context.Context, dimension string) (*pasturePb.IndexFocusIndicatorsResponse, error)
+	FocusIndicatorsSet(ctx context.Context, req *pasturePb.IndexFocusIndicatorsSetRequest) error
 }
 
 //go:generate mockgen -destination mock/WorkService.go -package kptservicemock kpt-pasture/module/backend WorkService