Browse Source

system: menu update

Yi 2 weeks ago
parent
commit
7a7cf0b4d9

+ 1 - 1
go.mod

@@ -3,7 +3,7 @@ module kpt-pasture
 go 1.17
 
 require (
-	gitee.com/xuyiping_admin/go_proto v0.0.0-20250530090709-1e32a1ade71d
+	gitee.com/xuyiping_admin/go_proto v0.0.0-20250603093658-9b2144518ce7
 	gitee.com/xuyiping_admin/pkg v0.0.0-20250514071642-f92d2ac9a85d
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/eclipse/paho.mqtt.golang v1.4.3

+ 11 - 0
go.sum

@@ -133,6 +133,17 @@ gitee.com/xuyiping_admin/go_proto v0.0.0-20250530051007-6ce1b83221af h1:3SBlTKUW
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250530051007-6ce1b83221af/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250530090709-1e32a1ade71d h1:upETgWdn+raGyxXdP1S70Z4gMuGZep9RjcLsWLIWeF0=
 gitee.com/xuyiping_admin/go_proto v0.0.0-20250530090709-1e32a1ade71d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603022546-465f63606fa5/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603023510-4787586eb99f h1:ESNXR2m+12UOrrBMD1EnC732hf2H4LEwEhON/n1p6RU=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603023510-4787586eb99f/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603030738-6435257183f9 h1:WDBhCOK21ffgnRsgrjYZHQY7LQ3nboMZFJ3P8BYEokQ=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603030738-6435257183f9/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603061552-ea096c7a318d h1:9pPdB8ogY6KxRxjCJNMTss2IpsCAivGxEwWcRxBkGfA=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603061552-ea096c7a318d/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603093243-82ebd7095700 h1:4s7hJ6Vr2FUydlb8gglDoJaPixKD4hnpvN78COUlAsw=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603093243-82ebd7095700/go.mod h1:BKrFW6YLDectlQcQk3FYKBeXvjEiodAKJ5rq7O/QiPE=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603093658-9b2144518ce7 h1:hAbUSi6s55gRk7nJfWq+d66rN5phpOggRqKxyaj1T/M=
+gitee.com/xuyiping_admin/go_proto v0.0.0-20250603093658-9b2144518ce7/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=
 gitee.com/xuyiping_admin/pkg v0.0.0-20250514071642-f92d2ac9a85d h1:vBXmMRggF7mZVPGRDgavZ87igJgkezwX0a3v1/XtIMQ=

+ 10 - 6
http/handler/dashboard/dashboard.go

@@ -58,12 +58,6 @@ func FocusIndicatorsSet(c *gin.Context) {
 }
 
 func TodoCount(c *gin.Context) {
-	var req pasturePb.IndexDataWarningSetRequest
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-
 	res, err := middleware.Dependency(c).StoreEventHub.OpsService.CalendarToDoCount(c)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
@@ -120,3 +114,13 @@ func DataWarningPop(c *gin.Context) {
 	}
 	c.JSON(http.StatusOK, res)
 }
+
+func Equipment(c *gin.Context) {
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.Equipment(c)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, res)
+}

+ 1 - 1
http/handler/system/dept.go

@@ -45,7 +45,7 @@ func DepIsShow(c *gin.Context) {
 		return
 	}
 
-	if err := middleware.Dependency(c).StoreEventHub.OpsService.SystemDepDelete(c, int64(Id)); err != nil {
+	if err := middleware.Dependency(c).StoreEventHub.OpsService.SystemDepthDelete(c, int64(Id)); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}

+ 6 - 27
http/handler/system/menu.go

@@ -3,14 +3,10 @@ package system
 import (
 	"kpt-pasture/http/middleware"
 	"net/http"
-	"strconv"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
-	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"gitee.com/xuyiping_admin/pkg/apierr"
 	"gitee.com/xuyiping_admin/pkg/ginutil"
-	"gitee.com/xuyiping_admin/pkg/valid"
-
 	"github.com/gin-gonic/gin"
 )
 
@@ -36,31 +32,14 @@ func SearchSystemMenuList(c *gin.Context) {
 	ginutil.JSONResp(c, res)
 }
 
-// DeleteSystemMenu 删除菜单
-func DeleteSystemMenu(c *gin.Context) {
-	menuIdStr := c.Param("id")
-	menuId, _ := strconv.Atoi(menuIdStr)
-
-	if err := valid.Validate(menuId, valid.Required, valid.Min(1)); err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-
-	if err := middleware.BackendOperation(c).OpsService.DeleteSystemMenu(c, int64(menuId)); err != nil {
-		apierr.ClassifiedAbort(c, err)
-		return
-	}
-
-	ginutil.JSONResp(c, &operationPb.CommonOK{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &operationPb.Success{Success: true},
-	})
-}
-
 // GetSystemMenuTree 角色菜单
 func GetSystemMenuTree(c *gin.Context) {
-	res, err := middleware.Dependency(c).StoreEventHub.OpsService.SystemMenuTree(c)
+	var req pasturePb.SearchMenuRequest
+	if err := ginutil.BindProto(c, &req); err != nil {
+		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
+		return
+	}
+	res, err := middleware.Dependency(c).StoreEventHub.OpsService.SystemMenuTree(c, &req)
 	if err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return

+ 13 - 0
http/handler/test.go

@@ -156,3 +156,16 @@ func AdmissionAge(c *gin.Context) {
 		Data: &operationPb.Success{Success: true},
 	})
 }
+
+func SystemMenuInit(c *gin.Context) {
+	if err := middleware.BackendOperation(c).OpsService.SystemMenuInit(c); 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

@@ -20,5 +20,6 @@ func DashboardApi(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		dashboardRoute.POST("/data/warning/pop", dashboard.DataWarningPop)
 		dashboardRoute.POST("/data/warning/set", dashboard.DataWarningSet)
 		dashboardRoute.GET("/todo/count", dashboard.TodoCount)
+		dashboardRoute.GET("/equipment/list", dashboard.Equipment)
 	}
 }

+ 1 - 0
http/route/test_api.go

@@ -21,5 +21,6 @@ func TestAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		testRoute.GET("/pasture/init", handler.PastureInit)
 		testRoute.GET("/calving/age", handler.CalvingAge)
 		testRoute.GET("/admission/age", handler.AdmissionAge)
+		testRoute.GET("/system/menu/init", handler.SystemMenuInit)
 	}
 }

+ 5 - 0
model/neck_ring.go

@@ -109,3 +109,8 @@ type NeckRingStats struct {
 	ErrorReason string
 	Describe    string
 }
+
+type DashboardNeckRing struct {
+	Status pasturePb.NeckRingStatus_Kind
+	Number int32
+}

+ 2 - 0
model/neck_ring_health.go

@@ -11,6 +11,7 @@ type NeckRingHealth struct {
 	Id                 int64                      `json:"id"`
 	PastureId          int64                      `json:"pastureId"`
 	NeckRingNumber     string                     `json:"neckRingNumber"`
+	EarNumber          string                     `json:"earNumber"`
 	CowId              int64                      `json:"cowId"`
 	Lact               int32                      `json:"lact"`
 	CalvingAge         int32                      `json:"calvingAge"`
@@ -49,6 +50,7 @@ func NewNeckRingHealth(habit *NeckActiveHabit, sumChew, chew3dago int32) *NeckRi
 	return &NeckRingHealth{
 		PastureId:          habit.PastureId,
 		NeckRingNumber:     habit.NeckRingNumber,
+		EarNumber:          habit.EarNumber,
 		CowId:              habit.CowId,
 		Lact:               habit.Lact,
 		CalvingAge:         habit.CalvingAge,

+ 0 - 1
model/system_dept.go

@@ -37,7 +37,6 @@ func (s *SystemDept) DepthUpdate(req *pasturePb.SearchDeptRequest) {
 	s.Sort = req.Sort
 	s.Remarks = req.Remarks
 	s.IsShow = req.IsShow
-	s.IsDelete = req.IsDelete
 }
 
 func NewSystemDept(pastureId int64, req *pasturePb.SearchDeptRequest) *SystemDept {

+ 26 - 21
model/system_menu.go

@@ -1,6 +1,7 @@
 package model
 
 import (
+	"kpt-pasture/util"
 	"sort"
 	"time"
 
@@ -9,7 +10,6 @@ import (
 
 type SystemMenu struct {
 	Id              int64                   `json:"id"`
-	PastureId       int64                   `json:"pastureId"`
 	Name            string                  `json:"name"`
 	Title           string                  `json:"title"`
 	Path            string                  `json:"path"`
@@ -46,11 +46,11 @@ func (s *SystemMenu) MenuUpdate(req *pasturePb.SearchMenuRequest) {
 	s.Title = req.Title
 	s.ParentId = int64(req.ParentId)
 	s.FrameSrc = req.FrameSrc
-	s.FrameLoading = BooleanToIsShow(req.FrameLoading)
-	s.Keepalive = BooleanToIsShow(req.Keepalive)
-	s.HiddenTag = BooleanToIsShow(req.HiddenTag)
-	s.ShowLink = BooleanToIsShow(req.ShowLink)
-	s.ShowParent = BooleanToIsShow(req.ShowParent)
+	s.FrameLoading = util.BooleanToIsShow(req.FrameLoading)
+	s.Keepalive = util.BooleanToIsShow(req.Keepalive)
+	s.HiddenTag = util.BooleanToIsShow(req.HiddenTag)
+	s.ShowLink = util.BooleanToIsShow(req.ShowLink)
+	s.ShowParent = util.BooleanToIsShow(req.ShowParent)
 	s.Icon = req.Icon
 	s.Component = req.Component
 	s.Redirect = req.Redirect
@@ -60,13 +60,11 @@ func (s *SystemMenu) MenuUpdate(req *pasturePb.SearchMenuRequest) {
 	s.EnterTransition = req.EnterTransition
 	s.ActivePath = req.ActivePath
 	s.IsShow = req.IsShow
-	s.IsDelete = req.IsDelete
 }
 
 // NewSystemMenu AddMenuRequest
-func NewSystemMenu(pastureId int64, req *pasturePb.SearchMenuRequest) *SystemMenu {
+func NewSystemMenu(req *pasturePb.SearchMenuRequest) *SystemMenu {
 	return &SystemMenu{
-		PastureId:       pastureId,
 		Name:            req.Name,
 		Title:           req.Title,
 		Path:            req.Path,
@@ -81,11 +79,11 @@ func NewSystemMenu(pastureId int64, req *pasturePb.SearchMenuRequest) *SystemMen
 		EnterTransition: req.EnterTransition,
 		ActivePath:      req.ActivePath,
 		FrameSrc:        req.FrameSrc,
-		FrameLoading:    BooleanToIsShow(req.FrameLoading),
-		Keepalive:       BooleanToIsShow(req.Keepalive),
-		HiddenTag:       BooleanToIsShow(req.HiddenTag),
-		ShowLink:        BooleanToIsShow(req.ShowLink),
-		ShowParent:      BooleanToIsShow(req.ShowParent),
+		FrameLoading:    util.BooleanToIsShow(req.FrameLoading),
+		Keepalive:       util.BooleanToIsShow(req.Keepalive),
+		HiddenTag:       util.BooleanToIsShow(req.HiddenTag),
+		ShowLink:        util.BooleanToIsShow(req.ShowLink),
+		ShowParent:      util.BooleanToIsShow(req.ShowParent),
 		IsShow:          pasturePb.IsShow_Ok,
 		IsDelete:        pasturePb.IsShow_Ok,
 	}
@@ -162,7 +160,7 @@ func (s SystemMenuSlice) ToTree() []*pasturePb.MenuTree {
 				Icon:     v.Icon,
 				Title:    v.Title,
 				Rank:     v.Rank,
-				Roles:    []string{"admin"},
+				Roles:    []string{},
 				ShowLink: v.ShowLink == pasturePb.IsShow_Ok,
 			},
 			Children: make([]*pasturePb.MenuTree, 0),
@@ -199,10 +197,17 @@ func findByID(menuTreeList []*pasturePb.MenuTree, id int32) *pasturePb.MenuTree
 	return nil
 }
 
-func BooleanToIsShow(isShow bool) pasturePb.IsShow_Kind {
-	showKind := pasturePb.IsShow_No
-	if isShow {
-		showKind = pasturePb.IsShow_Ok
-	}
-	return showKind
+type MenuItem struct {
+	Path     string      `json:"path"`
+	Name     string      `json:"name"`
+	Meta     MenuMeta    `json:"meta"`
+	Children []*MenuItem `json:"children"`
+}
+
+type MenuMeta struct {
+	Icon     string `json:"icon"`
+	Title    string `json:"title"`
+	Rank     int32  `json:"rank"`
+	ShowLink bool   `json:"showLink"`
+	Hidden   bool   `json:"hidden"`
 }

+ 23 - 0
model/system_pasture_menu.go

@@ -0,0 +1,23 @@
+package model
+
+type SystemPastureMenu struct {
+	Id        int64 `json:"id"`
+	PastureId int64 `json:"pastureId"`
+	MenuId    int64 `json:"menuId"`
+	CreatedAt int64 `json:"createdAt"`
+	UpdatedAt int64 `json:"updatedAt"`
+}
+
+func (s *SystemPastureMenu) TableName() string {
+	return "system_pasture_menu"
+}
+
+type SystemPastureMenuSlice []*SystemPastureMenu
+
+func (s SystemPastureMenuSlice) GetMenuIds() []int64 {
+	res := make([]int64, 0)
+	for _, v := range s {
+		res = append(res, v.MenuId)
+	}
+	return res
+}

+ 0 - 1
model/system_role.go

@@ -36,7 +36,6 @@ func (s *SystemRole) RoleUpdate(req *pasturePb.SearchRoleRequest) {
 	s.Name = req.Name
 	s.Remarks = req.Remarks
 	s.IsShow = req.IsShow
-	s.IsDelete = req.IsDelete
 }
 
 func NewSystemRole(pastureId int64, req *pasturePb.SearchRoleRequest) *SystemRole {

+ 1 - 1
model/system_role_menu.go

@@ -12,7 +12,7 @@ func (s *SystemRoleMenu) TableName() string {
 	return "system_role_menu"
 }
 
-func NewSystemMenuPermissions(roleID int64, menuIds []uint32) []*SystemRoleMenu {
+func NewSystemRoleMenu(roleID int64, menuIds []int32) []*SystemRoleMenu {
 	systemRoleMenu := make([]*SystemRoleMenu, len(menuIds))
 	for i, v := range menuIds {
 		systemRoleMenu[i] = &SystemRoleMenu{

+ 0 - 190
module/backend/dashboard.go

@@ -5,7 +5,6 @@ import (
 	"errors"
 	"fmt"
 	"kpt-pasture/model"
-	"kpt-pasture/util"
 	"net/http"
 	"regexp"
 	"strconv"
@@ -21,195 +20,6 @@ import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
-func (s *StoreEntry) NeckRingWarning(ctx context.Context) (*pasturePb.IndexNeckRingResponse, error) {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	var count int64
-	neckRingEstrusList := make([]*model.NeckRingEstrusWarning, 0)
-	estrusWarningLevelItems := map[int32]int32{
-		int32(pasturePb.EstrusLevel_Low):    0,
-		int32(pasturePb.EstrusLevel_Middle): 0,
-		int32(pasturePb.EstrusLevel_High):   0,
-	}
-
-	pref, err := s.EstrusWarningQuery(ctx, userModel.AppPasture.Id)
-	if err != nil {
-		return nil, xerr.Customf("系统错误!")
-	}
-	if err = pref.Order("a.level DESC").
-		Count(&count).
-		Find(&neckRingEstrusList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	countEstrusWarning := 0
-	nowTime := time.Now().Local()
-	optimumMating := map[string]int32{
-		"front":  0,
-		"middle": 0,
-		"behind": 0,
-	}
-	for _, v := range neckRingEstrusList {
-		estrusWarningLevelItems[int32(v.Level)] += 1
-		countEstrusWarning += 1
-		cowInfo, _ := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, v.EarNumber)
-		pzHour := v.CalculatePzHour(cowInfo.Lact)
-		optimumMatingStartTime := pzHour.Add(-4 * time.Hour)
-		optimumMatingEndTime := pzHour.Add(4 * time.Hour)
-
-		// 判断当前时间是否在 pzHour-4h 到 pzHour+4h 之间
-		if nowTime.After(optimumMatingStartTime) && nowTime.Before(optimumMatingEndTime) {
-			optimumMating["middle"] += 1
-		}
-		if nowTime.After(optimumMatingEndTime) {
-			optimumMating["behind"] += 1
-		}
-		if nowTime.Before(optimumMatingStartTime) {
-			optimumMating["front"] += 1
-		}
-	}
-
-	abortionCount := int64(0)
-	pref, err = s.AbortionWarningQuery(ctx, userModel.AppPasture.Id)
-	if err != nil {
-		return nil, xerr.Customf("系统错误!")
-	}
-
-	if err = pref.Group("cow_id").Count(&abortionCount).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	healthWarningNumber := int64(0)
-	if err = s.DB.Model(new(model.NeckRingHealthWarning)).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("is_show = ?", pasturePb.IsShow_Ok).
-		Group("cow_id").
-		Count(&healthWarningNumber).Error; err != nil {
-		zaplog.Error("NeckRingWarning", zap.Any("estrusWarningNumber", err))
-	}
-
-	return &pasturePb.IndexNeckRingResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: &pasturePb.NeckRingData{
-			EstrusWarningNumber:     int32(countEstrusWarning),
-			HealthWarningNumber:     int32(healthWarningNumber),
-			AbortionWarningNumber:   int32(abortionCount),
-			StressWarningNumber:     0,
-			EstrusWarningLevelItems: estrusWarningLevelItems,
-			OptimumMating:           optimumMating,
-		},
-	}, nil
-
-}
-
-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)
-	}
-
-	userFocusIndicators := userModel.SystemUser.IndicatorsKinds
-	if len(userFocusIndicators) <= 0 {
-		userFocusIndicators = model.DefaultFocusIndicators
-	}
-	userFocusIndicatorsList := strings.Split(userFocusIndicators, ",")
-	indicatorsDataList := make([]*model.IndicatorsData, 0)
-	pref := s.DB.Model(new(model.IndicatorsData)).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("kind in (?)", userFocusIndicatorsList)
-
-	/*if dimension == "Year" {
-		pref.Where("date = ?", time.Now().Local().Format(model.LayoutMonth))
-	}*/
-
-	nowTime := time.Now().Local()
-	if dimension == "Month" {
-		pref.Where("date = ?", nowTime.Format(model.LayoutMonth))
-	}
-
-	if err = pref.Find(&indicatorsDataList).Error; err != nil {
-		zaplog.Error("FocusIndicators", zap.Any("err", err))
-	}
-
-	indicatorsDetailsMap, _, err := s.GetIndicatorsDetailsMap(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	focusIndicatorsList := make([]*pasturePb.FocusIndicators, 0)
-	for _, v := range indicatorsDataList {
-		indicatorsDetails, ok := indicatorsDetailsMap[v.Kind]
-		if !ok {
-			continue
-		}
-		onYear, onMonth := "", ""
-		isUp := pasturePb.IsShow_Ok
-		if dimension == "Year" {
-			return nil, xerr.Custom("暂不支持该维度")
-		}
-
-		if dimension == "Month" {
-			lastMonth := nowTime.AddDate(0, -1, 0).Format(model.LayoutMonth)
-			oldIndicators, _ := s.GetIndicatorsDataByDate(userModel.AppPasture.Id, v.Kind, lastMonth)
-			if oldIndicators != nil {
-				if oldIndicators.Value != "" && oldIndicators.Value != "0" {
-					oldValue, _ := strconv.ParseFloat(oldIndicators.Value, 64)
-					currValue, _ := strconv.ParseFloat(v.Value, 64)
-					onMonthValue := (oldValue - currValue) / oldValue * 100
-					omv := util.RoundToTwoDecimals(onMonthValue)
-					if omv < 0 {
-						isUp = pasturePb.IsShow_No
-					}
-					onMonth = strconv.FormatFloat(omv, 'f', 2, 64) + "%"
-				}
-			}
-		}
-		focusIndicatorsList = append(focusIndicatorsList, &pasturePb.FocusIndicators{
-			Kind:     indicatorsDetails.Kind,
-			Name:     indicatorsDetails.Name,
-			Value:    v.Value,
-			Describe: indicatorsDetails.Zh,
-			UnitName: indicatorsDetails.Unit,
-			OnMonth:  onMonth,
-			OnYear:   onYear,
-			IsUp:     isUp,
-		})
-	}
-
-	indicatorsDetailsList, _ := s.FindIndicatorsDetailsList(ctx)
-
-	return &pasturePb.IndexFocusIndicatorsResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		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
-}
-
 func (s *StoreEntry) DataWarningSet(ctx context.Context, req *pasturePb.IndexDataWarningSetRequest) error {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {

+ 261 - 0
module/backend/dashboard_more.go

@@ -0,0 +1,261 @@
+package backend
+
+import (
+	"context"
+	"kpt-pasture/model"
+	"kpt-pasture/util"
+	"net/http"
+	"strconv"
+	"strings"
+	"time"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
+	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
+	"gitee.com/xuyiping_admin/pkg/xerr"
+	"go.uber.org/zap"
+)
+
+func (s *StoreEntry) NeckRingWarning(ctx context.Context) (*pasturePb.IndexNeckRingResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	var count int64
+	neckRingEstrusList := make([]*model.NeckRingEstrusWarning, 0)
+	estrusWarningLevelItems := map[int32]int32{
+		int32(pasturePb.EstrusLevel_Low):    0,
+		int32(pasturePb.EstrusLevel_Middle): 0,
+		int32(pasturePb.EstrusLevel_High):   0,
+	}
+
+	pref, err := s.EstrusWarningQuery(ctx, userModel.AppPasture.Id)
+	if err != nil {
+		return nil, xerr.Customf("系统错误!")
+	}
+	if err = pref.Order("a.level DESC").
+		Count(&count).
+		Find(&neckRingEstrusList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	countEstrusWarning := 0
+	nowTime := time.Now().Local()
+	optimumMating := map[string]int32{
+		"front":  0,
+		"middle": 0,
+		"behind": 0,
+	}
+	for _, v := range neckRingEstrusList {
+		estrusWarningLevelItems[int32(v.Level)] += 1
+		countEstrusWarning += 1
+		cowInfo, _ := s.GetCowInfoByEarNumber(ctx, userModel.AppPasture.Id, v.EarNumber)
+		pzHour := v.CalculatePzHour(cowInfo.Lact)
+		optimumMatingStartTime := pzHour.Add(-4 * time.Hour)
+		optimumMatingEndTime := pzHour.Add(4 * time.Hour)
+
+		// 判断当前时间是否在 pzHour-4h 到 pzHour+4h 之间
+		if nowTime.After(optimumMatingStartTime) && nowTime.Before(optimumMatingEndTime) {
+			optimumMating["middle"] += 1
+		}
+		if nowTime.After(optimumMatingEndTime) {
+			optimumMating["behind"] += 1
+		}
+		if nowTime.Before(optimumMatingStartTime) {
+			optimumMating["front"] += 1
+		}
+	}
+
+	abortionCount := int64(0)
+	pref, err = s.AbortionWarningQuery(ctx, userModel.AppPasture.Id)
+	if err != nil {
+		return nil, xerr.Customf("系统错误!")
+	}
+
+	if err = pref.Group("cow_id").Count(&abortionCount).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	healthWarningNumber := int64(0)
+	if err = s.DB.Model(new(model.NeckRingHealthWarning)).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("is_show = ?", pasturePb.IsShow_Ok).
+		Group("cow_id").
+		Count(&healthWarningNumber).Error; err != nil {
+		zaplog.Error("NeckRingWarning", zap.Any("estrusWarningNumber", err))
+	}
+
+	return &pasturePb.IndexNeckRingResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &pasturePb.NeckRingData{
+			EstrusWarningNumber:     int32(countEstrusWarning),
+			HealthWarningNumber:     int32(healthWarningNumber),
+			AbortionWarningNumber:   int32(abortionCount),
+			StressWarningNumber:     0,
+			EstrusWarningLevelItems: estrusWarningLevelItems,
+			OptimumMating:           optimumMating,
+		},
+	}, nil
+
+}
+
+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)
+	}
+
+	userFocusIndicators := userModel.SystemUser.IndicatorsKinds
+	if len(userFocusIndicators) <= 0 {
+		userFocusIndicators = model.DefaultFocusIndicators
+	}
+	userFocusIndicatorsList := strings.Split(userFocusIndicators, ",")
+	indicatorsDataList := make([]*model.IndicatorsData, 0)
+	pref := s.DB.Model(new(model.IndicatorsData)).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Where("kind in (?)", userFocusIndicatorsList)
+
+	/*if dimension == "Year" {
+		pref.Where("date = ?", time.Now().Local().Format(model.LayoutMonth))
+	}*/
+
+	nowTime := time.Now().Local()
+	if dimension == "Month" {
+		pref.Where("date = ?", nowTime.Format(model.LayoutMonth))
+	}
+
+	if err = pref.Find(&indicatorsDataList).Error; err != nil {
+		zaplog.Error("FocusIndicators", zap.Any("err", err))
+	}
+
+	indicatorsDetailsMap, _, err := s.GetIndicatorsDetailsMap(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	focusIndicatorsList := make([]*pasturePb.FocusIndicators, 0)
+	for _, v := range indicatorsDataList {
+		indicatorsDetails, ok := indicatorsDetailsMap[v.Kind]
+		if !ok {
+			continue
+		}
+		onYear, onMonth := "", ""
+		isUp := pasturePb.IsShow_Ok
+		if dimension == "Year" {
+			return nil, xerr.Custom("暂不支持该维度")
+		}
+
+		if dimension == "Month" {
+			lastMonth := nowTime.AddDate(0, -1, 0).Format(model.LayoutMonth)
+			oldIndicators, _ := s.GetIndicatorsDataByDate(userModel.AppPasture.Id, v.Kind, lastMonth)
+			if oldIndicators != nil {
+				if oldIndicators.Value != "" && oldIndicators.Value != "0" {
+					oldValue, _ := strconv.ParseFloat(oldIndicators.Value, 64)
+					currValue, _ := strconv.ParseFloat(v.Value, 64)
+					onMonthValue := float64(0)
+					if oldValue > 0 {
+						onMonthValue = (oldValue - currValue) / oldValue * 100
+					}
+					omv := util.RoundToTwoDecimals(onMonthValue)
+					if omv < 0 {
+						isUp = pasturePb.IsShow_No
+					}
+					onMonth = strconv.FormatFloat(omv, 'f', 2, 64) + "%"
+				}
+			}
+		}
+		focusIndicatorsList = append(focusIndicatorsList, &pasturePb.FocusIndicators{
+			Kind:     indicatorsDetails.Kind,
+			Name:     indicatorsDetails.Name,
+			Value:    v.Value,
+			Describe: indicatorsDetails.Zh,
+			UnitName: indicatorsDetails.Unit,
+			OnMonth:  onMonth,
+			OnYear:   onYear,
+			IsUp:     isUp,
+		})
+	}
+
+	indicatorsDetailsList, _ := s.FindIndicatorsDetailsList(ctx)
+
+	return &pasturePb.IndexFocusIndicatorsResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		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
+}
+
+func (s *StoreEntry) Equipment(ctx context.Context) (*pasturePb.EquipmentResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	equipmentList := make([]*pasturePb.Equipment, 0)
+	dashboardNeckRingList := make([]*model.DashboardNeckRing, 0)
+	if err = s.DB.Model(new(model.NeckRing)).
+		Select("status, count(*) as number").
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Group("status").
+		Find(&dashboardNeckRingList).Error; err != nil {
+	}
+
+	normalNumber, abnormalNumber := int32(0), int32(0)
+	for _, v := range dashboardNeckRingList {
+		if v.Status == pasturePb.NeckRingStatus_Normal {
+			normalNumber = v.Number
+		}
+		if v.Status == pasturePb.NeckRingStatus_Abnormal {
+			abnormalNumber = v.Number
+		}
+	}
+
+	var receiverCount int64
+	if err = s.DB.Model(new(model.AppPastureReceiver)).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Count(&receiverCount).Error; err != nil {
+	}
+
+	equipmentList = append(equipmentList, &pasturePb.Equipment{
+		Name:           "异常脖环数",
+		Describe:       "脖环",
+		NormalNumber:   normalNumber,
+		AbnormalNumber: abnormalNumber,
+		Icon:           "/assets/welcome/ring@2x.png",
+		Kind:           pasturePb.EquipmentType_Neck_Ring,
+	}, &pasturePb.Equipment{
+		Name:           "离线接收器",
+		Describe:       "接收器",
+		NormalNumber:   int32(receiverCount),
+		AbnormalNumber: int32(0),
+		Icon:           "/assets/welcome/device@2x.png",
+		Kind:           pasturePb.EquipmentType_Receiver,
+	})
+
+	return &pasturePb.EquipmentResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &pasturePb.EquipmentData{EquipmentList: equipmentList},
+	}, nil
+}

+ 5 - 1
module/backend/goods.go

@@ -237,6 +237,10 @@ func (s *StoreEntry) NeckRingList(ctx context.Context, req *pasturePb.SearchNeck
 		pref.Where("a.is_bind = ?", req.IsBind)
 	}
 
+	if req.ErrorKind > 0 {
+		pref.Where("a.error_kind = ?", req.ErrorKind)
+	}
+
 	if req.EarNumber != "" {
 		pref.Where("a.ear_number = ?", req.EarNumber)
 	}
@@ -253,7 +257,7 @@ func (s *StoreEntry) NeckRingList(ctx context.Context, req *pasturePb.SearchNeck
 		pref.Where("a.error_kind = ?", req.ErrorKind)
 	}
 
-	if err = pref.Order("a.id desc").
+	if err = pref.Order("a.status desc").
 		Count(&count).
 		Limit(int(pagination.PageSize)).
 		Offset(int(pagination.PageOffset)).

+ 4 - 3
module/backend/interface.go

@@ -85,12 +85,11 @@ type SystemService interface {
 
 	// SearchSystemMenuList 系统菜单权限
 	SearchSystemMenuList(ctx context.Context, req *pasturePb.SearchMenuRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchMenuResponse, error)
-	DeleteSystemMenu(ctx context.Context, menuId int64) error
-	SystemMenuTree(ctx context.Context) (*pasturePb.SystemMenuTreeResponse, error)
+	SystemMenuTree(ctx context.Context, req *pasturePb.SearchMenuRequest) (*pasturePb.SystemMenuTreeResponse, error)
 
 	// SearchSystemDeptList 部门列表
 	SearchSystemDeptList(ctx context.Context, req *pasturePb.SearchDeptRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchDeptResponse, error)
-	SystemDepDelete(ctx context.Context, id int64) error
+	SystemDepthDelete(ctx context.Context, id int64) error
 	SystemDeptCreateOrUpdate(ctx context.Context, req *pasturePb.SearchDeptRequest) error
 	SystemDeptTree(ctx context.Context, req *pasturePb.SearchDeptRequest) (*pasturePb.DeptTreeResponse, error)
 
@@ -313,6 +312,7 @@ type DashboardService interface {
 	DataWarningList(ctx context.Context) (*pasturePb.IndexDataWarningResponse, error)
 	DataWarningPop(ctx context.Context, req *pasturePb.WarningDataListRequest, pagination *pasturePb.PaginationModel) (*model.WarningDataPopResponse, error)
 	CalendarToDoCount(ctx context.Context) (*pasturePb.TodoCountResponse, error)
+	Equipment(ctx context.Context) (*pasturePb.EquipmentResponse, error)
 }
 
 //go:generate mockgen -destination mock/WorkService.go -package kptservicemock kpt-pasture/module/backend WorkService
@@ -363,4 +363,5 @@ type TestService interface {
 	PastureInit(ctx context.Context, pastureId int64) error
 	AdmissionAge(ctx context.Context) error
 	CalvingAge(ctx context.Context) error
+	SystemMenuInit(ctx context.Context) error
 }

+ 3 - 8
module/backend/neck_ring_warning.go

@@ -246,13 +246,8 @@ func (s *StoreEntry) NeckRingNoDiseaseBatch(ctx context.Context, req *pasturePb.
 
 	nowTime := time.Now().Local()
 	startTime := nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)
-	endTime := nowTime.AddDate(0, 0, 1).Format(model.LayoutDate2)
-
-	startTimeUnix := util.TimeParseLocalUnix(startTime)
-	endTimeUnix := util.TimeParseLocalUnix(endTime)
+	endTime := nowTime.Format(model.LayoutDate2)
 
-	startTime = time.Unix(startTimeUnix, 0).Local().Format(model.LayoutTime)
-	endTime = time.Unix(endTimeUnix, 0).Local().Format(model.LayoutTime)
 	neckRingHealthWarningList := make([]*model.NeckRingHealthWarning, 0)
 	if err = s.DB.Model(new(model.NeckRingHealthWarning)).
 		Where("pasture_id = ?", userModel.AppPasture.Id).
@@ -301,8 +296,8 @@ func (s *StoreEntry) NeckRingNoDiseaseBatch(ctx context.Context, req *pasturePb.
 }
 func (s *StoreEntry) EstrusWarningQuery(ctx context.Context, pastureId int64) (*gorm.DB, error) {
 	nowTime := time.Now().Local()
-	startTime := time.Unix(util.TimeParseLocalUnix(nowTime.Format(model.LayoutDate2)), 0).Local().Format(model.LayoutTime)
-	entTime := time.Unix(util.TimeParseLocalEndUnix(nowTime.AddDate(0, 0, 1).Local().Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
+	startTime := time.Unix(util.TimeParseLocalUnix(nowTime.AddDate(0, 0, -1).Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
+	entTime := time.Unix(util.TimeParseLocalEndUnix(nowTime.Format(model.LayoutDate2)), 0).Format(model.LayoutTime)
 	systemBasic, err := s.FindSystemBasic(ctx, pastureId, model.EstrusWaringDays)
 	if err != nil {
 		return nil, xerr.WithStack(err)

+ 12 - 0
module/backend/sql_more.go

@@ -200,3 +200,15 @@ func (s *StoreEntry) GetAppPastureListByFarmId(ctx context.Context, farmId strin
 
 	return res, nil
 }
+
+func (s *StoreEntry) SystemUserList(ctx context.Context, pastureId int64) ([]*model.SystemUser, error) {
+	systemUserList := make([]*model.SystemUser, 0)
+	if err := s.DB.Model(new(model.SystemUser)).
+		Where("pasture_id = ?", pastureId).
+		Where("is_delete = ?", pasturePb.IsShow_Ok).
+		Where("is_show = ? ", pasturePb.IsShow_Ok).
+		Find(&systemUserList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	return systemUserList, nil
+}

+ 61 - 63
module/backend/system_service.go

@@ -160,18 +160,6 @@ func (s *StoreEntry) SearchSystemUserList(ctx context.Context, req *pasturePb.Se
 	}, nil
 }
 
-func (s *StoreEntry) SystemUserList(ctx context.Context, pastureId int64) ([]*model.SystemUser, error) {
-	systemUserList := make([]*model.SystemUser, 0)
-	if err := s.DB.Model(new(model.SystemUser)).
-		Where("pasture_id = ?", pastureId).
-		Where("is_delete = ?", pasturePb.IsShow_Ok).
-		Where("is_show = ? ", pasturePb.IsShow_Ok).
-		Find(&systemUserList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-	return systemUserList, nil
-}
-
 // DeleteSystemUser 删除系统用户
 func (s *StoreEntry) DeleteSystemUser(ctx context.Context, userId int64) error {
 	systemUser := &model.SystemUser{Id: userId}
@@ -212,6 +200,11 @@ func (s *StoreEntry) IsShowSystemUser(ctx context.Context, userId int64) error {
 
 // SystemUserCreateOrUpdate 创建或者更新系统用户
 func (s *StoreEntry) SystemUserCreateOrUpdate(ctx context.Context, req *pasturePb.SearchUserRequest) error {
+	_, err := s.GetUserModel(ctx)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
 	deptIds, pastureIds := "", ""
 	for _, pasture := range req.PastureDepthList {
 		appPasture, err := s.GetAppPastureListByFarmId(ctx, pasture.FarmId)
@@ -236,13 +229,13 @@ func (s *StoreEntry) SystemUserCreateOrUpdate(ctx context.Context, req *pastureP
 	systemUser := &model.SystemUser{}
 	if req.Id > 0 {
 		systemUser.Id = int64(req.Id)
-		if err := s.DB.Model(new(model.SystemUser)).
+		if err = s.DB.Model(new(model.SystemUser)).
 			First(systemUser).Error; err != nil {
 			return xerr.WithStack(err)
 		}
 
 		systemUser.UserUpdate(req, deptIds, pastureIds)
-		if err := s.DB.Model(new(model.SystemUser)).
+		if err = s.DB.Model(new(model.SystemUser)).
 			Select("name", "nick_name", "mobile", "gender", "dept_ids", "pasture_ids", "remarks", "is_show").
 			Where("id = ?", systemUser.Id).
 			Updates(systemUser).Error; err != nil {
@@ -251,7 +244,7 @@ func (s *StoreEntry) SystemUserCreateOrUpdate(ctx context.Context, req *pastureP
 
 	} else {
 		var count int64
-		if err := s.DB.Model(new(model.SystemUser)).
+		if err = s.DB.Model(new(model.SystemUser)).
 			Where("name = ?", req.Name).
 			Where("mobile = ?", req.Mobile).
 			Where("is_show = ?", pasturePb.IsShow_Ok).
@@ -264,7 +257,7 @@ func (s *StoreEntry) SystemUserCreateOrUpdate(ctx context.Context, req *pastureP
 		}
 
 		newSystemUser := model.NewSystemUser(req, deptIds, pastureIds, req.PastureDepthList)
-		if err := s.DB.Model(new(model.SystemUser)).
+		if err = s.DB.Model(new(model.SystemUser)).
 			Create(newSystemUser).Error; err != nil {
 			return xerr.WithStack(err)
 		}
@@ -273,6 +266,52 @@ func (s *StoreEntry) SystemUserCreateOrUpdate(ctx context.Context, req *pastureP
 	return nil
 }
 
+// GetSystemUserMenu 返回系统用户相关菜单权限
+func (s *StoreEntry) GetSystemUserMenu(ctx context.Context) (*pasturePb.SystemUserMenuTreeResponse, error) {
+	userModel, err := s.GetUserModel(ctx)
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	// 根据用户token获取用户数据
+	systemUser, err := s.GetCurrentSystemUser(ctx)
+	if err != nil {
+		return nil, xerr.Custom("该用户数据不存在")
+	}
+
+	if len(systemUser.RoleIds) <= 0 {
+		return nil, xerr.Custom("该用户没有角色")
+	}
+
+	// 获取用户角色数据
+	systemRoleList := make([]*model.SystemRole, 0)
+	if err = s.DB.Where("id IN ?", systemUser.GetRoleIds()).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Find(&systemRoleList).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, xerr.Custom("该用户角色不存在")
+		}
+		return nil, xerr.WithStack(err)
+	}
+	// 获取用户菜单
+	systemMenuList := make([]*model.SystemMenu, 0)
+	if err = s.DB.Table(fmt.Sprintf("%s as a", new(model.SystemRoleMenu).TableName())).
+		Select("b.*").
+		Joins("LEFT JOIN system_menu AS b ON a.menu_id = b.id").
+		Where("a.role_id IN ? and b.is_delete = ?", systemUser.GetRoleIds(), pasturePb.IsShow_Ok).
+		Order("b.parent_id ASC,b.id ASC").
+		Group("b.id").
+		Find(&systemMenuList).Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	// 获取菜单权限
+	return &pasturePb.SystemUserMenuTreeResponse{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: model.SystemMenuSlice(systemMenuList).ToTree(),
+	}, nil
+}
+
 // ResetPasswordSystemUser 重置系统用户密码
 func (s *StoreEntry) ResetPasswordSystemUser(ctx context.Context, req *pasturePb.ResetUserPasswordRequest) error {
 	systemUser := &model.SystemUser{}
@@ -367,44 +406,6 @@ func (s *StoreEntry) SystemUserRoleSave(ctx context.Context, req *pasturePb.Syst
 	return nil
 }
 
-// GetSystemUserMenu 返回系统用户相关菜单权限
-func (s *StoreEntry) GetSystemUserMenu(ctx context.Context) (*pasturePb.SystemUserMenuTreeResponse, error) {
-	// 根据用户token获取用户数据
-	systemUser, err := s.GetCurrentSystemUser(ctx)
-	if err != nil {
-		return nil, xerr.Custom("该用户数据不存在")
-	}
-	if len(systemUser.RoleIds) <= 0 {
-		return nil, xerr.Custom("该用户没有角色")
-	}
-
-	// 获取用户角色数据
-	systemRoleList := make([]*model.SystemRole, 0)
-	if err = s.DB.Where("id IN ?", systemUser.GetRoleIds()).
-		Find(&systemRoleList).Error; err != nil {
-		if errors.Is(err, gorm.ErrRecordNotFound) {
-			return nil, xerr.Custom("该用户角色不存在")
-		}
-		return nil, xerr.WithStack(err)
-	}
-	// 获取用户菜单
-	systemMenuList := make([]*model.SystemMenu, 0)
-	if err = s.DB.Table(fmt.Sprintf("%s as a", new(model.SystemRoleMenu).TableName())).
-		Select("b.*").
-		Joins("LEFT JOIN system_menu AS b ON a.menu_id = b.id").
-		Where("a.role_id IN ? and b.is_delete = ?", systemUser.GetRoleIds(), pasturePb.IsShow_Ok).
-		Find(&systemMenuList).Error; err != nil {
-		return nil, xerr.WithStack(err)
-	}
-
-	// 获取菜单权限
-	return &pasturePb.SystemUserMenuTreeResponse{
-		Code: http.StatusOK,
-		Msg:  "ok",
-		Data: model.SystemMenuSlice(systemMenuList).ToTree(),
-	}, nil
-}
-
 // SystemRoleCreateOrUpdate 添加角色
 func (s *StoreEntry) SystemRoleCreateOrUpdate(ctx context.Context, req *pasturePb.SearchRoleRequest) error {
 	userModel, err := s.GetUserModel(ctx)
@@ -427,7 +428,7 @@ func (s *StoreEntry) SystemRoleCreateOrUpdate(ctx context.Context, req *pastureP
 
 		systemRole.RoleUpdate(req)
 		if err = s.DB.Model(systemRole).
-			Select("name", "remarks", "is_show", "is_delete").
+			Select("name", "remarks", "is_show").
 			Where("id = ?", req.Id).
 			Where("pasture_id = ?", userModel.AppPasture.Id).
 			Updates(systemRole).Error; err != nil {
@@ -614,14 +615,11 @@ func (s *StoreEntry) RoleMenuSave(ctx context.Context, res *pasturePb.SystemRole
 			Error; err != nil {
 			return xerr.WithStack(err)
 		}
-		for _, menuId := range res.MenuIds {
-			if err = tx.Model(new(model.SystemRoleMenu)).
-				Create(&model.SystemRoleMenu{
-					RoleId: systemRole.Id,
-					MenuId: int64(menuId),
-				}).Error; err != nil {
-				return xerr.WithStack(err)
-			}
+
+		newSystemRoleMenuList := model.NewSystemRoleMenu(systemRole.Id, res.MenuIds)
+		if err = tx.Model(new(model.SystemRoleMenu)).
+			Create(newSystemRoleMenuList).Error; err != nil {
+			return xerr.WithStack(err)
 		}
 		return nil
 	}); err != nil {

+ 38 - 74
module/backend/system_service_more.go

@@ -2,7 +2,6 @@ package backend
 
 import (
 	"context"
-	"errors"
 	"fmt"
 	"kpt-pasture/model"
 	"net/http"
@@ -14,64 +13,43 @@ import (
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 	operationPb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/operation"
 	"gitee.com/xuyiping_admin/pkg/xerr"
-	"gorm.io/gorm"
 )
 
-// CreateOrUpdateSystemMenu 添加或者更新系统菜单权限
-func (s *StoreEntry) CreateOrUpdateSystemMenu(ctx context.Context, req *pasturePb.SearchMenuRequest) error {
+func (s *StoreEntry) SystemMenuTree(ctx context.Context, req *pasturePb.SearchMenuRequest) (*pasturePb.SystemMenuTreeResponse, error) {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
-		return xerr.WithStack(err)
+		return nil, xerr.WithStack(err)
 	}
 
-	if req.Id > 0 {
-		systemMenu := &model.SystemMenu{}
-		if err = s.DB.Model(new(model.SystemMenu)).
-			Where("id = ?", req.Id).
-			Where("pasture_id = ?", userModel.AppPasture.Id).
-			First(systemMenu).Error; err != nil {
-			return xerr.WithStack(err)
-		}
-
-		// 更新数据
-		systemMenu.MenuUpdate(req)
-		if err = s.DB.Model(new(model.SystemMenu)).
-			Select("name", "path", "title", "menu_type", "parent_id", "frame_src", "frame_loading",
-				"keepalive", "hidden_tag", "show_link", "show_parent", "icon", "component", "redirect", "auths",
-				"rank", "extra_icon", "enter_transition", "leave_transition", "active_path", "is_delete", "is_show").
-			Where("id = ?", req.Id).
-			Where("pasture_id = ?", userModel.AppPasture.Id).
-			Updates(systemMenu).
-			Error; err != nil {
-			return xerr.WithStack(err)
-		}
-	} else {
-		newSystemMenu := model.NewSystemMenu(userModel.AppPasture.Id, req)
-		if err = s.DB.Model(new(model.SystemMenu)).Create(newSystemMenu).Error; err != nil {
-			return xerr.WithStack(err)
-		}
+	systemPastureMenuList := make([]*model.SystemPastureMenu, 0)
+	if err = s.DB.Model(new(model.SystemPastureMenu)).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Find(&systemPastureMenuList).
+		Error; err != nil {
+		return nil, xerr.WithStack(err)
 	}
 
-	return nil
-}
-
-func (s *StoreEntry) SystemMenuTree(ctx context.Context) (*pasturePb.SystemMenuTreeResponse, error) {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return nil, xerr.WithStack(err)
+	if len(systemPastureMenuList) <= 0 {
+		return nil, xerr.Customf("系统菜单未初始化,请联系管理员!")
 	}
+
 	systemMenuList := make([]*model.SystemMenu, 0)
-	if err = s.DB.Model(new(model.SystemMenu)).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		Where("is_delete = ?", pasturePb.IsShow_Ok).
-		Where("is_show = ?", pasturePb.IsShow_Ok).
+	pref := s.DB.Model(new(model.SystemMenu)).
+		Where("id IN ? ", model.SystemPastureMenuSlice(systemPastureMenuList).GetMenuIds()).
+		Where("is_delete = ? ", operationPb.IsShow_OK)
+	if req.Name != "" {
+		pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))
+	}
+
+	if err = pref.Order("parent_id ASC,id ASC").
 		Find(&systemMenuList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
+
 	return &pasturePb.SystemMenuTreeResponse{
 		Code: http.StatusOK,
 		Msg:  "ok",
-		Data: model.SystemMenuSlice(systemMenuList).ToPB(),
+		Data: model.SystemMenuSlice(systemMenuList).ToTree(),
 	}, nil
 }
 
@@ -81,17 +59,30 @@ func (s *StoreEntry) SearchSystemMenuList(ctx context.Context, req *pasturePb.Se
 	if err != nil {
 		return nil, xerr.WithStack(err)
 	}
+	systemPastureMenuList := make([]*model.SystemPastureMenu, 0)
+	if err = s.DB.Model(new(model.SystemPastureMenu)).
+		Where("pasture_id = ?", userModel.AppPasture.Id).
+		Find(&systemPastureMenuList).
+		Error; err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	if len(systemPastureMenuList) <= 0 {
+		return nil, xerr.Customf("系统菜单未初始化,请联系管理员!")
+	}
+
 	systemMenuList := make([]*model.SystemMenu, 0)
 	var count int64 = 0
 
 	pref := s.DB.Model(new(model.SystemMenu)).
-		Where("pasture_id = ? ", userModel.AppPasture.Id).
+		Where("id IN ? ", model.SystemPastureMenuSlice(systemPastureMenuList).GetMenuIds()).
 		Where("is_delete = ? ", operationPb.IsShow_OK)
 	if req.Name != "" {
 		pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%"))
 	}
 
-	if err = pref.Order("parent_id").Count(&count).
+	if err = pref.Order("parent_id").
+		Count(&count).
 		Find(&systemMenuList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
@@ -108,33 +99,6 @@ func (s *StoreEntry) SearchSystemMenuList(ctx context.Context, req *pasturePb.Se
 	}, nil
 }
 
-// DeleteSystemMenu 删除系统菜单
-func (s *StoreEntry) DeleteSystemMenu(ctx context.Context, menuId int64) error {
-	userModel, err := s.GetUserModel(ctx)
-	if err != nil {
-		return xerr.WithStack(err)
-	}
-
-	systemMenu := &model.SystemMenu{}
-	if err = s.DB.Model(new(model.SystemMenu)).
-		Where("id = ?", menuId).
-		Where("pasture_id = ?", userModel.AppPasture.Id).
-		First(systemMenu).Error; err != nil {
-		if errors.Is(err, gorm.ErrRecordNotFound) {
-			return xerr.Custom("该数据不存在")
-		}
-		return xerr.WithStack(err)
-	}
-
-	if err = s.DB.Model(new(model.SystemMenu)).
-		Where("id = ?", menuId).
-		Update("is_delete", pasturePb.IsShow_No).
-		Error; err != nil {
-		return xerr.WithStack(err)
-	}
-	return nil
-}
-
 func (s *StoreEntry) SearchSystemDeptList(ctx context.Context, req *pasturePb.SearchDeptRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchDeptResponse, error) {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
@@ -178,7 +142,7 @@ func (s *StoreEntry) SearchSystemDeptList(ctx context.Context, req *pasturePb.Se
 	}, nil
 }
 
-func (s *StoreEntry) SystemDepDelete(ctx context.Context, id int64) error {
+func (s *StoreEntry) SystemDepthDelete(ctx context.Context, id int64) error {
 	userModel, err := s.GetUserModel(ctx)
 	if err != nil {
 		return xerr.WithStack(err)
@@ -230,7 +194,7 @@ func (s *StoreEntry) SystemDeptCreateOrUpdate(ctx context.Context, req *pastureP
 		if err = s.DB.Model(new(model.SystemDept)).
 			Where("id = ?", systemDept.Id).
 			Where("pasture_id = ?", pastureId).
-			Select("name", "parent_id", "sort", "remarks", "is_show", "is_delete").
+			Select("name", "parent_id", "sort", "remarks", "is_show").
 			Updates(systemDept).Error; err != nil {
 			return xerr.WithStack(err)
 		}

+ 1016 - 0
module/backend/test_service.go

@@ -2,6 +2,7 @@ package backend
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
 	"kpt-pasture/model"
 
@@ -184,6 +185,30 @@ func (s *StoreEntry) PastureInit(ctx context.Context, pastureId int64) error {
 			zaplog.Error("PastureInit-SystemDept", zap.Any("error", err))
 		}
 
+		// 初始化菜单
+		systemMenuList := make([]*model.SystemPastureMenu, 0)
+		if err := tx.Model(new(model.SystemPastureMenu)).
+			Where("pasture_id = ?", 0).
+			Find(&systemMenuList).Error; err != nil {
+			zaplog.Error("PastureInit-SystemMenu", zap.Any("error", err))
+		}
+
+		newSystemMenuList := make([]*model.SystemPastureMenu, 0)
+		for _, systemMenu := range systemMenuList {
+			newSystemMenu := &model.SystemPastureMenu{
+				PastureId: pastureId,
+				MenuId:    systemMenu.Id,
+			}
+			newSystemMenuList = append(newSystemMenuList, newSystemMenu)
+		}
+
+		if err := tx.Model(new(model.SystemPastureMenu)).
+			Create(newSystemMenuList).Error; err != nil {
+			zaplog.Error("PastureInit-SystemMenu", zap.Any("error", err))
+		}
+
+		// 初始化用户和角色
+
 		return nil
 	}); err != nil {
 		return xerr.WithStack(err)
@@ -244,3 +269,994 @@ func (s *StoreEntry) CalvingAge(ctx context.Context) error {
 	}*/
 	return nil
 }
+
+func (s *StoreEntry) SystemMenuInit(ctx context.Context) error {
+
+	items := menuDataInit()
+	if err := s.DB.Transaction(func(tx *gorm.DB) error {
+		if err := s.InsertCurrentMenuItem(tx, items, 0); err != nil {
+			zaplog.Error("SystemMenuInit", zap.Any("err", err))
+			return xerr.WithStack(err)
+		}
+		return nil
+	}); err != nil {
+		zaplog.Error("SystemMenuInit", zap.Any("err", err))
+	}
+
+	return nil
+}
+
+func (s *StoreEntry) InsertCurrentMenuItem(tx *gorm.DB, menuList []*model.MenuItem, parentId int64) error {
+	for _, menu := range menuList {
+		showLink := pasturePb.IsShow_Ok
+		if menu.Meta.Hidden || !menu.Meta.ShowLink {
+			showLink = pasturePb.IsShow_No
+		}
+		newSystemMenu := &model.SystemMenu{
+			Name:            menu.Name,
+			Path:            menu.Path,
+			Title:           menu.Meta.Title,
+			MenuType:        1, // menu_type: 1 (menu)
+			ParentId:        parentId,
+			FrameSrc:        "", // frame_src
+			FrameLoading:    1,  // frame_loading
+			Keepalive:       2,  // keepalive
+			HiddenTag:       2,  // hidden_tag
+			ShowLink:        showLink,
+			ShowParent:      2, // show_parent
+			Icon:            menu.Meta.Icon,
+			Component:       "", // component
+			Redirect:        "", // redirect
+			Auths:           "", // auths
+			Rank:            menu.Meta.Rank,
+			ExtraIcon:       "", // extra_icon
+			EnterTransition: "", // enter_transition
+			//"",              // leave_transition
+			ActivePath: "", // active_path
+			IsShow:     1,  // is_show
+			IsDelete:   1,  // is_delete
+		}
+		if err := tx.Model(new(model.SystemMenu)).
+			Create(newSystemMenu).Error; err != nil {
+			zaplog.Error("SystemMenuInit", zap.Any("error", err))
+			return xerr.WithStack(err)
+		}
+
+		if len(menu.Children) > 0 {
+			if err := s.InsertCurrentMenuItem(tx, menu.Children, newSystemMenu.Id); err != nil {
+				zaplog.Error("SystemMenuInit", zap.Any("error", err))
+				return xerr.WithStack(err)
+			}
+		}
+	}
+	return nil
+}
+
+func menuDataInit() []*model.MenuItem {
+	menuData := `[
+    {
+        "path": "/event",
+        "name": "Event",
+        "meta": {
+            "icon": "carbon:cics-sit-overrides",
+            "title": "menus.KptEvent",
+            "rank": 12
+        },
+        "children": [
+            {
+                "path": "/event/base",
+                "meta": {
+                    "title": "menus.KptBaseEvent"
+                },
+                "children": [
+                    {
+                        "path": "/event/base/enter/index",
+                        "name": "EnterEvent",
+                        "meta": {
+                            "title": "menus.KptEnterEvent"
+                        }
+                    },
+                    {
+                        "path": "/event/base/group_transfer/index",
+                        "name": "GroupTransferEvent",
+                        "meta": {
+                            "title": "menus.KptGroupTransferEvent"
+                        }
+                    },
+                    {
+                        "path": "/event/base/add_group/index",
+                        "name": "add_group",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/event/base/weight/index",
+                        "name": "Weight",
+                        "meta": {
+                            "title": "menus.KptWeight"
+                        }
+                    },
+                    {
+                        "path": "/event/base/add_weight/index",
+                        "name": "add_weight",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/event/base/die/index",
+                        "name": "Die",
+                        "meta": {
+                            "title": "menus.KptDie"
+                        }
+                    },
+                    {
+                        "path": "/event/base/add_die/index",
+                        "name": "add_die",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/event/breed",
+                "meta": {
+                    "title": "menus.KptBreedEvent"
+                },
+                "children": [
+                    {
+                        "path": "/event/breed/estrus/index",
+                        "name": "estrusEvent",
+                        "meta": {
+                            "title": "menus.KptEstrusEvent"
+                        }
+                    },
+                    {
+                        "path": "/event/breed/mating/index",
+                        "name": "MatingEvent",
+                        "meta": {
+                            "title": "menus.KptMatingEvent"
+                        }
+                    },
+                    {
+                        "path": "/event/breed/add_mating/index",
+                        "name": "add_mating",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/event/breed/pregnant_check/index",
+                        "name": "PregnantCheckEvent",
+                        "meta": {
+                            "title": "menus.KptPregnantCheckEvent"
+                        }
+                    },
+                    {
+                        "path": "/event/breed/add_pregnant/index",
+                        "name": "add_pregnant",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/event/breed/add_estrus/index",
+                        "name": "add_estrus",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/event/breed/process/index",
+                        "name": "Process",
+                        "meta": {
+                            "title": "menus.Process"
+                        }
+                    },
+                    {
+                        "path": "/event/breed/add_process/index",
+                        "name": "add_process",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/event/breed/forbidden/index",
+                        "name": "forbidden",
+                        "meta": {
+                            "title": "menus.forbidden"
+                        }
+                    },
+                    {
+                        "path": "/event/breed/add_forbidden/index",
+                        "name": "add_forbidde",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/event/vet",
+                "meta": {
+                    "title": "menus.KptVetEvent"
+                },
+                "children": [
+                    {
+                        "path": "/event/vet/illness/index",
+                        "name": "IllNessEvent",
+                        "meta": {
+                            "title": "menus.KptIllNessEvent"
+                        }
+                    },
+                    {
+                        "path": "/event/vet/add_deworm/index",
+                        "name": "add_deworm",
+                        "hidden": true,
+                        "meta": {
+                            "title": "",
+                            "showLink": false
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/event/other",
+                "meta": {
+                    "title": "menus.KptOtherEvent"
+                },
+                "children": [
+                    {
+                        "path": "/event/other/saleMange/index",
+                        "name": "saleMangeEvent",
+                        "meta": {
+                            "title": "menus.KptsaleMange"
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/goods",
+        "redirect": "/goods/drugs/index",
+        "name": "Goods",
+        "meta": {
+            "title": "menus.KptGoods",
+            "icon": "ep:goods",
+            "rank": 23
+        },
+        "children": [
+            {
+                "path": "/goods/vetGoods",
+                "meta": {
+                    "title": "menus.KptVetGoods"
+                },
+                "children": [
+                    {
+                        "path": "/goods/drugs/index",
+                        "name": "Drugs",
+                        "meta": {
+                            "title": "menus.KptDrugs",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/goods/medical_devices/index",
+                        "name": "MedicalDevices",
+                        "meta": {
+                            "title": "menus.KptMedicalDevices",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/goods/hardWareGoods",
+                "meta": {
+                    "title": "menus.KpthardWareGoods"
+                },
+                "children": [
+                    {
+                        "path": "/goods/nech_ring/index",
+                        "name": "NechRingManage",
+                        "meta": {
+                            "title": "menus.KptNechRingManage",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/goods/application",
+                "meta": {
+                    "title": "menus.KptApplication"
+                },
+                "children": [
+                    {
+                        "path": "/goods/application_goods/index",
+                        "name": "ApplicatGoods",
+                        "meta": {
+                            "title": "menus.KptApplicatGoods",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/goods/otherGoods",
+                "meta": {
+                    "title": "menus.KptOtherGoods"
+                },
+                "children": [
+                    {
+                        "path": "/goods/frozen_semen/index",
+                        "name": "FrozenSemen",
+                        "meta": {
+                            "title": "menus.KptFrozenSemen",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/pasture",
+        "redirect": "/pasture/barn/index",
+        "name": "Pasture",
+        "meta": {
+            "title": "menus.kptPasture",
+            "icon": "emojione-monotone:cow",
+            "rank": 25
+        },
+        "children": [
+            {
+                "path": "/pasture/barn",
+                "meta": {
+                    "title": "menus.kptPastureBarn"
+                },
+                "children": [
+                    {
+                        "path": "/pasture/barn/index",
+                        "name": "BarnManage",
+                        "meta": {
+                            "title": "menus.kptPastureInfo",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/pasture/disease",
+                "meta": {
+                    "title": "menus.KptDisease"
+                },
+                "children": [
+                    {
+                        "path": "/pasture/disease/disease/index",
+                        "name": "DiseaseManage",
+                        "meta": {
+                            "title": "menus.KptDiseaseInfo",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/pasture/disease/prescription/index",
+                        "name": "PrescriptionManage",
+                        "meta": {
+                            "title": "menus.KptPrescription",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/pasture/health",
+                "meta": {
+                    "title": "menus.kptPastureHealth"
+                },
+                "children": [
+                    {
+                        "path": "/pasture/immunization/index",
+                        "name": "ImmunizationhManage",
+                        "meta": {
+                            "title": "menus.KptImmunization",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/pasture/health/index",
+                        "name": "HealthManage",
+                        "meta": {
+                            "title": "menus.KptHealth",
+                            "roles": [
+                                "admin"
+                            ],
+                            "showLink": false
+                        }
+                    },
+                    {
+                        "path": "/pasture/same_time/index",
+                        "name": "SameTime",
+                        "meta": {
+                            "title": "menus.KptSameTime",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/pasture/basic_setting/index",
+                "name": "BasicSetting",
+                "meta": {
+                    "title": "menus.KptBasicSettingTitle",
+                    "roles": [
+                        "admin"
+                    ]
+                },
+                "children": [
+                    {
+                        "path": "/pasture/basic_setting/index",
+                        "name": "BasicSettingIndex",
+                        "meta": {
+                            "title": "menus.KptBasicSetting",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/analysis",
+        "redirect": "/analysis/BreedIndicators",
+        "name": "Analysis",
+        "meta": {
+            "title": "menus.KptAnalysis",
+            "icon": "carbon:analytics-custom",
+            "rank": 16
+        },
+        "children": [
+            {
+                "path": "/analysis/BreedIndicators",
+                "meta": {
+                    "title": "menus.KptBreedIndicators"
+                },
+                "children": [
+                    {
+                        "path": "/analysis/21pregnancy_Rate/index",
+                        "name": "21PregnancyRate",
+                        "meta": {
+                            "title": "menus.Kpt21PregnancyRate",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/miscarriage_Rate/index",
+                        "name": "MiscarriageRate",
+                        "meta": {
+                            "title": "menus.KptMiscarriageRate",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/pregnancy_report/index",
+                        "name": "pregnancyReport",
+                        "meta": {
+                            "title": "menus.KptPregnancyReport",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/timely_breed/index",
+                        "name": "timelyBreed",
+                        "meta": {
+                            "title": "menus.KpttimelyBreed",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/single_factor_conception/index",
+                        "name": "SingleFactorConception",
+                        "meta": {
+                            "title": "menus.KptSingleFactorConception",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/multiple_factor_conception/index",
+                        "name": "MultidimensionalConception",
+                        "meta": {
+                            "title": "menus.KptMultidimensionalConception",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/analysis/VetIndicators",
+                "meta": {
+                    "title": "menus.KptVetIndicators"
+                },
+                "children": [
+                    {
+                        "path": "/analysis/disease_cure/index",
+                        "name": "DiseaseCure",
+                        "meta": {
+                            "title": "menus.KptDiseaseCure",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/production_report/index",
+                        "name": "productionReport",
+                        "meta": {
+                            "title": "menus.KptproductionReport",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/analysis/FatIndicators",
+                "meta": {
+                    "title": "menus.KptFatIndicators"
+                },
+                "children": [
+                    {
+                        "path": "/analysis/growth_curve/index",
+                        "name": "GrowthCurve",
+                        "meta": {
+                            "title": "menus.KptGrowthCurve",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/weight_distribution/index",
+                        "name": "WeightDistribution",
+                        "meta": {
+                            "title": "menus.KptWeightDistribution",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/weight_Fance/index",
+                        "name": "WeightFance",
+                        "meta": {
+                            "title": "menus.KptWeightByFance",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/analysis/OtherIndicators",
+                "meta": {
+                    "title": "menus.KptOtherIndicators"
+                },
+                "children": [
+                    {
+                        "path": "/analysis/cattleSales_Report/index",
+                        "name": "CattleSalesReport",
+                        "meta": {
+                            "title": "menus.KptCattleSalesReport",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/behavior_curve/index",
+                        "name": "PenGrowthCurve",
+                        "meta": {
+                            "title": "menus.KptBehaviorCurve",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/pen_behavior_monitor/index",
+                        "name": "PenBehaviorMonitor",
+                        "meta": {
+                            "title": "menus.KptPenBehaviorMonitor",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/analysis/cowBehavior/index",
+                        "name": "CowBehavior",
+                        "meta": {
+                            "title": "menus.KptCowBehavior",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/information",
+        "redirect": "/information/cow/index",
+        "name": "Information",
+        "meta": {
+            "title": "menus.KptInformationQuery",
+            "icon": "carbon:document-preliminary",
+            "rank": 17
+        },
+        "children": [
+            {
+                "path": "/information/cow",
+                "meta": {
+                    "title": "menus.KptCowIndexQuery"
+                },
+                "children": [
+                    {
+                        "path": "/information/cowQuery/index",
+                        "name": "CowQuery",
+                        "meta": {
+                            "title": "menus.KptCowQuery",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/information/groupQuery/index",
+                        "name": "groupCow",
+                        "meta": {
+                            "title": "menus.KptGroupCowQuery",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/information/longTermInfertility/index",
+                        "name": "LongTermInfertility",
+                        "meta": {
+                            "title": "menus.KptLongTermInfertility",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/information/overdueNoMating/index",
+                        "name": "OverdueNoMating",
+                        "meta": {
+                            "title": "menus.KptOverdueNoMating",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/information/moreQuery",
+                "meta": {
+                    "title": "menus.KptMoreQuery"
+                },
+                "children": [
+                    {
+                        "path": "/information/indicatorComparisonQuery/index",
+                        "name": "indicatorComparisonQuery",
+                        "meta": {
+                            "title": "menus.KptIndicatorComparisonQuery",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/work",
+        "redirect": "/work/calendar/index",
+        "name": "Work",
+        "meta": {
+            "icon": "streamline:code-monitor-1",
+            "title": "menus.KptRoutine",
+            "rank": 13
+        },
+        "children": [
+            {
+                "path": "/work/workplan",
+                "meta": {
+                    "title": "menus.KptWorkplan"
+                },
+                "children": [
+                    {
+                        "path": "/work/calendar/index",
+                        "name": "Calendar",
+                        "meta": {
+                            "title": "menus.KptCalendar",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/work/breedPlan",
+                "meta": {
+                    "title": "menus.KptBreedPlan"
+                },
+                "children": [
+                    {
+                        "path": "/work/samePeriod/index",
+                        "name": "samePeriod",
+                        "meta": {
+                            "title": "menus.KptsamePeriod",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/work/pregnancyTest/index",
+                        "name": "PregnancyTest",
+                        "meta": {
+                            "title": "menus.KptPregnancyTest",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/work/breedList/index",
+                        "name": "BreedList",
+                        "meta": {
+                            "title": "menus.KptBreedList",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/work/weanList/index",
+                        "name": "WeanList",
+                        "meta": {
+                            "title": "menus.KptWeanList",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/work/calving/index",
+                        "name": "CalvingList",
+                        "meta": {
+                            "title": "menus.KptCalvingEvent"
+                        }
+                    }
+                ]
+            },
+            {
+                "path": "/work/vetPlan",
+                "meta": {
+                    "title": "menus.KptVetPlan"
+                },
+                "children": [
+                    {
+                        "path": "/work/illnessList/index",
+                        "name": "illnessList",
+                        "meta": {
+                            "title": "menus.KptillnessList",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/work/immunitytList/index",
+                        "name": "immunitytList",
+                        "meta": {
+                            "title": "menus.KptImmunitytList",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/earlyWarn",
+        "redirect": "/earlyWarn/estrueList/index",
+        "name": "earlyWarn",
+        "meta": {
+            "title": "menus.KptEarlyWarnManagementRoter",
+            "icon": "ri:alarm-warning-line",
+            "rank": 26
+        },
+        "children": [
+            {
+                "path": "/earlyWarn/RingWarn",
+                "meta": {
+                    "title": "menus.kptRingEarlyWarn"
+                },
+                "children": [
+                    {
+                        "path": "/earlyWarn/estrueList/index",
+                        "name": "estrueList",
+                        "meta": {
+                            "title": "menus.KptEstrueList",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/earlyWarn/abortWarn/index",
+                        "name": "abortWarn",
+                        "meta": {
+                            "title": "menus.KptabortWarn",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/earlyWarn/healthWarn/index",
+                        "name": "healthWarn",
+                        "meta": {
+                            "title": "menus.KptHealthWarn",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/earlyWarn/stressWarn/index",
+                        "name": "stressWarn",
+                        "meta": {
+                            "title": "menus.KptStressWarn",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "path": "/system",
+        "redirect": "/system/user/index",
+        "name": "System",
+        "meta": {
+            "icon": "ri:settings-3-line",
+            "title": "menus.pureSysManagement",
+            "rank": 32
+        },
+        "children": [
+            {
+                "path": "/system/all",
+                "meta": {
+                    "title": "menus.sysManagement"
+                },
+                "children": [
+                    {
+                        "path": "/system/user/index",
+                        "name": "SystemUser",
+                        "meta": {
+                            "title": "menus.pureUser",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/system/role/index",
+                        "name": "SystemRole",
+                        "meta": {
+                            "title": "menus.pureRole",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/system/menu/index",
+                        "name": "SystemMenu",
+                        "meta": {
+                            "title": "menus.pureSystemMenu",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    },
+                    {
+                        "path": "/system/dept/index",
+                        "name": "SystemDept",
+                        "meta": {
+                            "title": "menus.pureDept",
+                            "roles": [
+                                "admin"
+                            ]
+                        }
+                    }
+                ]
+            }
+        ]
+    }
+]`
+	menuList := make([]*model.MenuItem, 0)
+	if err := json.Unmarshal([]byte(menuData), &menuList); err != nil {
+		zaplog.Error("menuDataInit", zap.Any("err", err))
+	}
+	return menuList
+}

+ 11 - 0
util/util_more.go

@@ -10,6 +10,8 @@ import (
 	"strconv"
 	"strings"
 	"time"
+
+	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
 
 func CurrentMaxFrameId() int32 {
@@ -142,3 +144,12 @@ func SaveUploadedFile(file *multipart.FileHeader, dst string) error {
 	_, err = io.Copy(out, src)
 	return err
 }
+
+// BooleanToIsShow 将布尔值转换为IsShow_Kind
+func BooleanToIsShow(isShow bool) pasturePb.IsShow_Kind {
+	showKind := pasturePb.IsShow_No
+	if isShow {
+		showKind = pasturePb.IsShow_Ok
+	}
+	return showKind
+}

+ 12 - 0
util/util_test.go

@@ -535,5 +535,17 @@ type WeeklyActiveModel struct {
 }
 
 func Test_demo(t *testing.T) {
+	str := "insert into system_pasture_menu (pasture_id,menu_id,created_at,updated_at) values"
+	for i := 36; i <= 134; i++ {
+		str += fmt.Sprintf("(4,%d,1748922530,1748922530),", i)
+	}
+
+	fmt.Println(strings.TrimRight(str, ","))
+
+	str1 := "insert into system_role_menu (role_id,menu_id,created_at,updated_at) values"
+	for i := 36; i <= 134; i++ {
+		str1 += fmt.Sprintf("(10,%d,1748922530,1748922530),", i)
+	}
 
+	fmt.Println(strings.TrimRight(str1, ","))
 }