Browse Source

neck_ring: 脖环数据

Yi 2 months ago
parent
commit
f420bd4149

+ 2 - 2
dep/di_crontab.go

@@ -86,9 +86,9 @@ func EntryCrontab(dependency CrontabDependency) *cron.Crontab {
 		panic(err)
 	}
 
-	err = newCrontab.Bind("UpdateActiveHabit", cs.NeckRingCalculate, dependency.CrontabHub.NeckRingCalculate)
+	err = newCrontab.Bind("NeckRingCalculate", cs.NeckRingCalculate, dependency.CrontabHub.NeckRingCalculate)
 	if err != nil {
-		zaplog.Error("EntryCrontab", zap.Any("UpdateActiveHabit", err))
+		zaplog.Error("EntryCrontab", zap.Any("NeckRingCalculate", err))
 		panic(err)
 	}
 

+ 25 - 0
http/handler/upload/upload.go

@@ -63,3 +63,28 @@ func Photos(c *gin.Context) {
 func Files(c *gin.Context) {
 
 }
+
+func OssVideo(c *gin.Context) {
+	filename := c.Param("name")
+	videoPath := fmt.Sprintf("%s/files/video/%s", config.WorkDir, filename)
+
+	// 打开视频文件
+	file, err := os.Open(videoPath)
+	if err != nil {
+		c.JSON(http.StatusNotFound, gin.H{"error": "Video not found"})
+		return
+	}
+	defer file.Close()
+	fileInfo, err := file.Stat()
+	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not get file info"})
+		return
+	}
+
+	// 设置响应头
+	c.Header("Content-Type", "video/mp4")
+	c.Header("Content-Length", fmt.Sprintf("%d", fileInfo.Size()))
+
+	// 流式传输文件内容
+	http.ServeContent(c.Writer, c.Request, fileInfo.Name(), fileInfo.ModTime(), file)
+}

+ 4 - 0
http/route/files_api.go

@@ -15,5 +15,9 @@ func FilesManageAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		uploadRoute := authRouteGroup(s, "/api/v1/upload/")
 		uploadRoute.POST("/photos", upload.Photos)
 		uploadRoute.POST("/files", upload.Files)
+
+		// 获取文件列表
+		//ossRoute := authRouteGroup(s, "/api/v1/oss/")
+		s.Static("api/v1/oss/video", "./files/video/")
 	}
 }

+ 4 - 4
model/cow.go

@@ -484,10 +484,10 @@ type CowBehaviorCurveResponse struct {
 }
 
 type CowBehaviorCurveData struct {
-	OriginalDataList []int32                                 `json:"originalDataList"` // 原始行为数据
-	ChangeDataList   []int32                                 `json:"changeDataList"`   // 变化数据
-	SumDataList      []int32                                 `json:"sumDataList"`      // 累计24小时数据
-	DataTimeList     []string                                `json:"dataTimeList"`     // 时间数据
+	OriginalDateList []int32                                 `json:"originalDateList"` // 原始行为数据
+	ChangeDateList   []int32                                 `json:"changeDateList"`   // 变化数据
+	SumDateList      []int32                                 `json:"sumDateList"`      // 累计24小时数据
+	DateTimeList     []string                                `json:"dateTimeList"`     // 时间数据
 	EstrusList       map[pasturePb.EstrusLevel_Kind][]string `json:"estrusList"`       // 发情预警
 	EventList        map[string][]string                     `json:"eventList"`        // 事件数据
 	EventMap         map[pasturePb.EventType_Kind]string     `json:"eventMap"`         // 所有事件

+ 1 - 1
model/event_mating.go

@@ -143,7 +143,7 @@ func NewEventMatingNaturalEstrus(cow *Cow, req *pasturePb.EventMating, currentUs
 	}
 }
 
-// NewEventMatingList 同配种
+// NewEventMatingList 同配种
 func NewEventMatingList(pastureId int64, cowList []*Cow, planDay int64, exposeEstrusType pasturePb.ExposeEstrusType_Kind) []*EventMating {
 	var matingList []*EventMating
 	for _, cow := range cowList {

+ 79 - 21
model/neck_active_habit.go

@@ -2,6 +2,11 @@ package model
 
 import (
 	"fmt"
+	"kpt-pasture/util"
+	"math"
+	"strconv"
+	"strings"
+	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
 )
@@ -100,42 +105,95 @@ func NewNeckActiveHabit(data *NeckRingOriginalMerge) *NeckActiveHabit {
 
 type NeckActiveHabitSlice []*NeckActiveHabit
 
-func (n NeckActiveHabitSlice) ToPB(curveName string) *CowBehaviorCurveData {
+func (n NeckActiveHabitSlice) Len() int      { return len(n) }
+func (n NeckActiveHabitSlice) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
+func (n NeckActiveHabitSlice) Less(i, j int) bool {
+	if n[i].HeatDate != n[j].HeatDate {
+		return n[i].HeatDate < n[j].HeatDate
+	}
+	return n[i].Frameid < n[j].Frameid
+}
+
+func (n NeckActiveHabitSlice) ToPB(curveName, startDateTime, endDateTime string) *CowBehaviorCurveData {
 	res := &CowBehaviorCurveData{
-		OriginalDataList: make([]int32, 0),
-		ChangeDataList:   make([]int32, 0),
-		SumDataList:      make([]int32, 0),
-		DataTimeList:     make([]string, 0),
-		EstrusList:       make(map[pasturePb.EstrusLevel_Kind][]string, 0),
+		OriginalDateList: make([]int32, 0),
+		ChangeDateList:   make([]int32, 0),
+		SumDateList:      make([]int32, 0),
+		DateTimeList:     make([]string, 0),
+		EstrusList:       make(map[pasturePb.EstrusLevel_Kind][]string),
 		EventList:        make(map[string][]string),
 		EventMap:         make(map[pasturePb.EventType_Kind]string),
 	}
 
+	//dayTimeRange, _ := util.GetDaysBetween(startDateTime, endDateTime)
+	initFrameId := int32(0)
+	dateFrameMap := make(map[string][]int32)
 	for _, v := range n {
-		res.DataTimeList = append(res.DataTimeList, fmt.Sprintf("%s %02d", v.HeatDate, v.Frameid*2+1))
+		if dateFrameMap[v.HeatDate] == nil {
+			initFrameId = 0
+			dateFrameMap[v.HeatDate] = make([]int32, 0)
+		}
+		// 补全结尾不够的数据
+		if initFrameId == 0 && len(res.DateTimeList) > 0 {
+			lastDateTime := res.DateTimeList[len(res.DateTimeList)-1]
+			lastDatePase := strings.Split(lastDateTime, " ")
+			if len(lastDatePase) == 2 {
+				lastDay := lastDatePase[0]
+				lastHourStr := lastDatePase[1]
+				lastHour, _ := strconv.ParseInt(lastHourStr, 10, 64)
+				maxHour := util.ExpectedFrameIDs[len(util.ExpectedFrameIDs)-1]
+				xframeId := int32(lastHour-1)/2 + 1
+				if xframeId != maxHour {
+					for ; xframeId <= maxHour; xframeId++ {
+						res.DateTimeList = append(res.DateTimeList, fmt.Sprintf("%s %02d", lastDay, util.ExpectedFrameIDs[xframeId]*2+1))
+						res.OriginalDateList = append(res.OriginalDateList, 0)
+						res.ChangeDateList = append(res.ChangeDateList, 0)
+						res.SumDateList = append(res.SumDateList, 0)
+					}
+				}
+			}
+		}
+		expectedFrameId := util.ExpectedFrameIDs[initFrameId]
+		if expectedFrameId != v.Frameid {
+			maxFrameId := int32(math.Abs(float64(expectedFrameId - v.Frameid)))
+			for ; expectedFrameId < maxFrameId; expectedFrameId++ {
+				res.DateTimeList = append(res.DateTimeList, fmt.Sprintf("%s %02d", v.HeatDate, util.ExpectedFrameIDs[expectedFrameId]*2+1))
+				res.OriginalDateList = append(res.OriginalDateList, 0)
+				res.ChangeDateList = append(res.ChangeDateList, 0)
+				res.SumDateList = append(res.SumDateList, 0)
+			}
+			initFrameId = expectedFrameId
+		}
+
+		// 格式化为到小时的字符串
+		parsedTime, _ := time.Parse(LayoutTime, v.ActiveTime)
+		hourStr := parsedTime.Format(LayoutHour)
+		res.DateTimeList = append(res.DateTimeList, hourStr)
 		switch curveName {
 		case "active": // 活动量
-			res.OriginalDataList = append(res.OriginalDataList, v.High)
-			res.ChangeDataList = append(res.ChangeDataList, v.ChangeFilter)
+			res.OriginalDateList = append(res.OriginalDateList, v.High)
+			res.ChangeDateList = append(res.ChangeDateList, v.ChangeFilter)
 		case "rumina": // 反刍
-			res.OriginalDataList = append(res.OriginalDataList, v.Rumina)
-			res.ChangeDataList = append(res.ChangeDataList, v.ChangeRumina)
-			res.SumDataList = append(res.SumDataList, v.SumRumina)
+			res.OriginalDateList = append(res.OriginalDateList, v.Rumina)
+			res.ChangeDateList = append(res.ChangeDateList, v.ChangeRumina)
+			res.SumDateList = append(res.SumDateList, v.SumRumina)
 		case "intake": // 采食
-			res.OriginalDataList = append(res.OriginalDataList, v.Intake)
-			res.SumDataList = append(res.SumDataList, v.SumIntake)
+			res.OriginalDateList = append(res.OriginalDateList, v.Intake)
+			res.SumDateList = append(res.SumDateList, v.SumIntake)
 		case "inactive": // 休息
-			res.OriginalDataList = append(res.OriginalDataList, v.Inactive)
-			res.SumDataList = append(res.SumDataList, v.SumInactive)
+			res.OriginalDateList = append(res.OriginalDateList, v.Inactive)
+			res.SumDateList = append(res.SumDateList, v.SumInactive)
 		case "chew": // 咀嚼
-			res.OriginalDataList = append(res.OriginalDataList, 0)
-			res.ChangeDataList = append(res.ChangeDataList, v.ChangeChew)
-			res.SumDataList = append(res.SumDataList, 0)
+			res.OriginalDateList = append(res.OriginalDateList, v.FilterChew)
+			res.ChangeDateList = append(res.ChangeDateList, v.ChangeChew)
+			res.SumDateList = append(res.SumDateList, 0)
 		case "immobility": // 静止
-			res.OriginalDataList = append(res.OriginalDataList, 0)
-			res.SumDataList = append(res.SumDataList, 0)
+			res.OriginalDateList = append(res.OriginalDateList, 0)
+			res.SumDateList = append(res.SumDateList, 0)
 		}
+		initFrameId++
 	}
+
 	return res
 }
 

+ 1 - 1
module/backend/calendar.go

@@ -277,7 +277,7 @@ func (s *StoreEntry) SameTimeCowList(ctx context.Context, req *pasturePb.ItemsRe
 				"matingTimes":      "本胎次配次",
 				"calvingAtFormat":  "产犊日期",
 				"abortionAtFormat": "流产日期",
-				"sameTimeName":     "同名称",
+				"sameTimeName":     "同名称",
 			},
 			List: model.SameTimeBodySlice(sameTimeBodyList).ToPB(breedStatusMap, penMap, sameTimeTypeMap),
 		},

+ 1 - 1
module/backend/config_data_other.go

@@ -475,7 +475,7 @@ func (s *StoreEntry) EventTypeEnumList(isAll string) []*pasturePb.ConfigOptionsL
 		Disabled: true,
 	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.EventType_Seme_Time),
-		Label:    "同",
+		Label:    "同",
 		Disabled: true,
 	}, &pasturePb.ConfigOptionsList{
 		Value:    int32(pasturePb.EventType_Mating),

+ 2 - 3
module/backend/cow.go

@@ -186,8 +186,7 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 		Find(&eventLogList).Error; err != nil {
 		return nil, xerr.WithStack(err)
 	}
-
-	data := model.NeckActiveHabitSlice(neckActiveHabitList).ToPB(req.CurveName)
+	data := model.NeckActiveHabitSlice(neckActiveHabitList).ToPB(req.CurveName, startDataTime, endDataTime)
 	data.EventMap = s.EventTypeMap()
 
 	for _, v := range eventLogList {
@@ -215,8 +214,8 @@ func (s *StoreEntry) BehaviorCurve(ctx context.Context, req *pasturePb.CowBehavi
 			data.EstrusList[v.Level] = make([]string, 0)
 		}
 		if len(v.EstrusStartDate) > 0 {
-			parsedTime, _ := time.Parse(model.LayoutTime, v.EstrusStartDate)
 			// 格式化为到小时的字符串
+			parsedTime, _ := time.Parse(model.LayoutTime, v.EstrusStartDate)
 			hourStr := parsedTime.Format(model.LayoutHour)
 			data.EstrusList[v.Level] = append(data.EstrusList[v.Level], hourStr)
 		}

+ 43 - 0
module/backend/test_service.go

@@ -55,6 +55,49 @@ func (s *StoreEntry) CowNeckRingNumberBound(ctx context.Context, pagination *pas
 	return nil
 }
 
+func (s *StoreEntry) CowNeckRingNumberBound2(ctx context.Context, pagination *pasturePb.PaginationModel) error {
+	currentUser, err := s.GetCurrentSystemUser(ctx)
+	if err != nil {
+		return xerr.Custom("当前用户信息错误,请退出重新登录")
+	}
+
+	lastNeckRing := &model.NeckRing{}
+	if err = s.DB.Model(new(model.NeckRing)).
+		Order("cow_id desc").
+		First(lastNeckRing).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	cowList := make([]*model.Cow, 0)
+	if err = s.DB.Model(new(model.Cow)).
+		Where("neck_ring_number != ?", "").
+		Limit(int(pagination.PageSize)).
+		Offset(int(pagination.PageOffset)).
+		Find(&cowList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+
+	newNeckRingList := make([]*model.NeckRing, 0)
+	newNeckRingBindLogList := make([]*model.NeckRingBindLog, 0)
+	for _, v := range cowList {
+		newNeckRing := model.NewNeckRing(currentUser.PastureId, v.NeckRingNumber, v.Id, currentUser)
+		newNeckRingList = append(newNeckRingList, newNeckRing)
+		newNeckRingBindLog := model.NewNeckRingBindLog(v.NeckRingNumber, v.Id, currentUser)
+		newNeckRingBindLogList = append(newNeckRingBindLogList, newNeckRingBindLog)
+	}
+
+	if err = s.DB.Model(new(model.NeckRing)).
+		Create(newNeckRingList).Error; err != nil {
+		zaplog.Error("CowNeckRingNumberBound-NewNeckRing", zap.Any("error", err))
+	}
+
+	if err = s.DB.Model(new(model.NeckRingBindLog)).
+		Create(newNeckRingBindLogList).Error; err != nil {
+		zaplog.Error("CowNeckRingNumberBound-NeckRingBindLog", zap.Any("error", err))
+	}
+	return nil
+}
+
 func (s *StoreEntry) UpdateCowPen(ctx context.Context, pagination *pasturePb.PaginationModel) error {
 	cowList := make([]*model.Cow, 0)
 	if err := s.DB.Model(new(model.Cow)).

+ 1 - 1
module/crontab/cow_cron.go

@@ -245,7 +245,7 @@ func (e *Entry) SameTimePlan() error {
 	return nil
 }
 
-// UpdateSameTime 更新每天同数据
+// UpdateSameTime 更新每天同数据
 func (e *Entry) UpdateSameTime() error {
 	calendarTypeList := backend.CalendarTypeEnumList("")
 	showDay := time.Now().Format(model.LayoutDate2)

+ 119 - 68
module/crontab/neck_ring_handle.go

@@ -5,6 +5,7 @@ import (
 	"kpt-pasture/model"
 	"kpt-pasture/util"
 	"math"
+	"sort"
 	"time"
 
 	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
@@ -23,36 +24,21 @@ const (
 )
 
 var (
-	defaultLimit = int32(1000)
-	isDelete     bool
+	defaultLimit       = int32(1000)
+	isDelete           bool
+	mergeIsRunning     bool
+	calculateIsRunning bool
 )
 
 // NeckRingOriginalMergeData 把脖环数据合并成2个小时的
-func (e *Entry) NeckRingOriginalMergeData() error {
-	var (
-		err error
-	)
-	limit := e.Cfg.NeckRingLimit
-	if limit <= 0 {
-		limit = defaultLimit
-	}
-	newTime := time.Now()
-	//createdAt := newTime.Add(-1 * time.Hour)
-
-	neckRingList := make([]*model.NeckRingOriginal, 0)
-	if err = e.DB.Model(new(model.NeckRingOriginal)).
-		Where("is_show = ?", pasturePb.IsShow_No).
-		Where("neck_ring_number IN (?)", "10027").
-		//Where("created_at <= ?", createdAt.Unix()).
-		Order("active_date,neck_ring_number,frameid").
-		Limit(int(limit)).Find(&neckRingList).Error; err != nil {
-		return xerr.WithStack(err)
-	}
-	if len(neckRingList) <= 0 {
+func (e *Entry) NeckRingOriginalMergeData() (err error) {
+	if mergeIsRunning {
 		return nil
 	}
-
+	newTime := time.Now()
+	mergeIsRunning = true
 	defer func() {
+		mergeIsRunning = false
 		if newTime.Day()%15 == 0 && !isDelete {
 			// 原始数据删除15天前的
 			e.DB.Model(new(model.NeckRingOriginal)).
@@ -68,6 +54,28 @@ func (e *Entry) NeckRingOriginalMergeData() error {
 			isDelete = true
 		}
 	}()
+	limit := e.Cfg.NeckRingLimit
+	if limit <= 0 {
+		limit = defaultLimit
+	}
+
+	//createdAt := newTime.Add(-1 * time.Hour)
+	//neckRingNumber := []string{"10026", "10027", "10028", "10029", "10030", "10031", "10032", "10033", "10034", "10035"}
+	neckRingNumber := []string{"10027"}
+
+	neckRingList := make([]*model.NeckRingOriginal, 0)
+	if err = e.DB.Model(new(model.NeckRingOriginal)).
+		Where("is_show = ?", pasturePb.IsShow_No).
+		Where("neck_ring_number IN (?)", neckRingNumber).
+		//Where("created_at <= ?", createdAt.Unix()).
+		Order("active_date,frameid,neck_ring_number").
+		Limit(int(limit)).Find(&neckRingList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	if len(neckRingList) <= 0 {
+		return nil
+	}
+
 	// 计算合并
 	neckActiveHabitList := e.recalculate(neckRingList)
 	if len(neckActiveHabitList) <= 0 {
@@ -92,24 +100,14 @@ func (e *Entry) NeckRingOriginalMergeData() error {
 			}
 			continue
 		}
-
-		if historyNeckActiveHabit == nil || historyNeckActiveHabit.Id <= 0 {
-			zaplog.Error("NeckRingOriginalMergeData-3",
-				zap.Any("ct", ct),
-				zap.Any("historyNeckActiveHabit", historyNeckActiveHabit),
-				zap.Any("neckActiveHabit", habit),
-			)
-			continue
-		}
-
 		// 重新计算
 		newNeckActiveHabit := e.againRecalculate(historyNeckActiveHabit)
 		if newNeckActiveHabit != nil {
 			if err = e.DB.Model(new(model.NeckActiveHabit)).
-				Select("rumina", "intake", "inactive", "gasp", "other", "high", "active").
+				Select("rumina", "intake", "inactive", "gasp", "other", "high", "active", "is_show").
 				Where("id = ?", historyNeckActiveHabit.Id).
 				Updates(newNeckActiveHabit).Error; err != nil {
-				zaplog.Error("NeckRingOriginalMergeData-5",
+				zaplog.Error("NeckRingOriginalMergeData-3",
 					zap.Any("err", err),
 					zap.Any("ct", ct),
 					zap.Any("historyNeckActiveHabit", historyNeckActiveHabit),
@@ -127,11 +125,19 @@ func (e *Entry) NeckRingCalculate() error {
 		return nil
 	}
 
+	if calculateIsRunning {
+		return nil
+	}
+	defer func() {
+		calculateIsRunning = false
+	}()
+
+	calculateIsRunning = true
 	for _, pasture := range pastureList {
 		if err := e.EntryUpdateActiveHabit(pasture.Id); err != nil {
-			zaplog.Error("PastureUpdateActiveHabit", zap.Any("err", err), zap.Any("pasture", pasture))
+			zaplog.Error("NeckRingCalculate", zap.Any("err", err), zap.Any("pasture", pasture))
 		}
-		zaplog.Info(fmt.Sprintf("PastureUpdateActiveHabit Success %d", pasture.Id))
+		zaplog.Info(fmt.Sprintf("NeckRingCalculate Success %d", pasture.Id))
 	}
 	return nil
 }
@@ -167,7 +173,9 @@ func (e *Entry) recalculate(neckRingList []*model.NeckRingOriginal) []*model.Nec
 		}
 		v.SumAvg()
 	}
-	return model.NeckRingOriginalMap(originalMapData).ForMatData()
+	dataList := model.NeckRingOriginalMap(originalMapData).ForMatData()
+	sort.Sort(model.NeckActiveHabitSlice(dataList))
+	return dataList
 }
 
 func (e *Entry) againRecalculate(data *model.NeckActiveHabit) *model.NeckActiveHabit {
@@ -185,7 +193,12 @@ func (e *Entry) againRecalculate(data *model.NeckActiveHabit) *model.NeckActiveH
 	if len(newDataList) != 1 {
 		return nil
 	}
-	return newDataList[0]
+	res := newDataList[0]
+	if res.Id <= 0 {
+		return nil
+	}
+	res.IsShow = pasturePb.IsShow_No
+	return res
 }
 
 func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
@@ -236,19 +249,26 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 		}
 	}()
 
+	var processIds []int64
 	// 更新活动滤波
-	if err = e.FirstFilterUpdate(pastureId, xToday); err != nil {
-		zaplog.Error("EntryUpdateActiveHabit", zap.Any("FirstFilterUpdate", err), zap.Any("xToday", xToday))
+	processIds, err = e.FirstFilterUpdate(pastureId, xToday)
+	if err != nil {
+		zaplog.Error("NeckRingCalculate", zap.Any("FirstFilterUpdate", err), zap.Any("xToday", xToday))
 	}
 
-	// 二次更新滤波
-	if err = e.SecondUpdateChangeFilter(pastureId, xToday); err != nil {
-		zaplog.Error("EntryUpdateActiveHabit", zap.Any("SecondUpdateChangeFilter", err), zap.Any("xToday", xToday))
+	if len(processIds) > 0 {
+		if err = e.WeeklyUpdateActiveHabit(pastureId, processIds, xToday); err != nil {
+			zaplog.Error("NeckRingCalculate", zap.Any("WeeklyUpdateActiveHabit", err), zap.Any("xToday", xToday))
+		}
+		// 二次更新滤波
+		if err = e.SecondUpdateChangeFilter(pastureId, xToday); err != nil {
+			zaplog.Error("NeckRingCalculate", zap.Any("SecondUpdateChangeFilter", err), zap.Any("xToday", xToday))
+		}
 	}
 
 	// 活动量校正系数和健康评分
 	if err = e.FilterCorrectAndScoreUpdate(pastureId, xToday); err != nil {
-		zaplog.Error("EntryUpdateActiveHabit", zap.Any("ActivityVolumeChanges", err), zap.Any("xToday", xToday))
+		zaplog.Error("NeckRingCalculate", zap.Any("ActivityVolumeChanges", err), zap.Any("xToday", xToday))
 	}
 
 	if err = e.DB.Model(new(model.NeckActiveHabit)).
@@ -267,12 +287,10 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 	if err = e.DB.Model(new(model.NeckActiveHabit)).
 		Where("id BETWEEN ? AND  ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
 		Where("pasture_id = ?", pastureId).
-		Where("is_show = ?", pasturePb.IsShow_No).
 		Where("change_filter < ?", 0).
 		Where("filter_correct < ?", model.DefaultFilterCorrect).
 		Updates(map[string]interface{}{
 			"filter_correct": model.DefaultFilterCorrect,
-			"is_show":        pasturePb.IsShow_Ok,
 		}).Error; err != nil {
 		zaplog.Error("EntryUpdateActiveHabit", zap.Any("filter_correct", err), zap.Any("xToday", xToday))
 	}
@@ -285,17 +303,16 @@ func (e *Entry) EntryUpdateActiveHabit(pastureId int64) (err error) {
 }
 
 // FirstFilterUpdate 首次更新活动滤波
-func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (err error) {
+func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (processIds []int64, err error) {
 	newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
 	if err = e.DB.Model(new(model.NeckActiveHabit)).
 		Where("id BETWEEN ? AND ?", xToDay.LastMaxHabitId, xToDay.CurrMaxHabitId).
 		Where("pasture_id = ?", pastureId).
 		Where("is_show = ?", pasturePb.IsShow_No).
-		Where("change_filter = ?", model.InitChangeFilter).
 		Where(e.DB.Where("high >= ?", xToDay.High).Or("rumina >= ?", xToDay.Rumina)).
 		Order("heat_date,neck_ring_number,frameid").
 		Limit(int(defaultLimit)).Find(&newNeckActiveHabitList).Error; err != nil {
-		return xerr.WithStack(err)
+		return nil, xerr.WithStack(err)
 	}
 	// 活动量滤波
 	for _, v := range newNeckActiveHabitList {
@@ -343,6 +360,42 @@ func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (err error) {
 			}
 		}
 
+		processIds = append(processIds, v.Id)
+
+		// 更新过滤值
+		if err = e.DB.Model(new(model.NeckActiveHabit)).
+			Select(
+				"filter_high", "filter_rumina", "filter_chew", "cow_id", "lact", "calving_age",
+			).Where("id = ?", v.Id).
+			Updates(map[string]interface{}{
+				"filter_high":   firstFilterData.FilterHigh,
+				"filter_rumina": firstFilterData.FilterRumina,
+				"filter_chew":   firstFilterData.FilterChew,
+				"cow_id":        cowInfo.Id,
+				"lact":          cowInfo.Lact,
+				"calving_age":   cowInfo.CalvingAge,
+			}).Error; err != nil {
+			zaplog.Error("FirstFilterUpdate",
+				zap.Any("error", err),
+				zap.Any("firstFilterData", firstFilterData),
+				zap.Any("NeckActiveHabit", v),
+				zap.Any("cowInfo", cowInfo),
+				zap.Any("xToday", xToDay),
+			)
+		}
+	}
+	return processIds, nil
+}
+
+func (e *Entry) WeeklyUpdateActiveHabit(pastureId int64, processIds []int64, xToDay *XToday) (err error) {
+	newNeckActiveHabitList := make([]*model.NeckActiveHabit, 0)
+	if err = e.DB.Model(new(model.NeckActiveHabit)).
+		Where("id IN (?)", processIds).
+		Order("heat_date,neck_ring_number,frameid").
+		Find(&newNeckActiveHabitList).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	for _, v := range newNeckActiveHabitList {
 		// 前七天的
 		weekHabitData := e.FindWeekHabitData(pastureId, v.NeckRingNumber, v.HeatDate, v.Frameid, xToDay)
 		highDiff := v.FilterHigh - weekHabitData.WeekHighHabit
@@ -370,18 +423,11 @@ func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (err error) {
 		// 更新过滤值
 		if err = e.DB.Model(new(model.NeckActiveHabit)).
 			Select(
-				"filter_high", "filter_rumina", "filter_chew", "cow_id", "lact", "calving_age",
 				"week_high_habit", "week_rumina_habit", "week_chew_habit", "week_intake_habit", "week_inactive_habit",
 				"sum_rumina", "sum_intake", "sum_inactive", "sum_active", "sum_max_high", "sum_min_high", "sum_min_chew",
 				"change_high", "change_rumina", "change_chew", "before_three_sum_rumina", "before_three_sum_intake",
 			).Where("id = ?", v.Id).
 			Updates(map[string]interface{}{
-				"filter_high":             firstFilterData.FilterHigh,
-				"filter_rumina":           firstFilterData.FilterRumina,
-				"filter_chew":             firstFilterData.FilterChew,
-				"cow_id":                  cowInfo.Id,
-				"lact":                    cowInfo.Lact,
-				"calving_age":             cowInfo.CalvingAge,
 				"week_high_habit":         weekHabitData.WeekHighHabit,
 				"week_rumina_habit":       weekHabitData.WeekRuminaHabit,
 				"week_chew_habit":         weekHabitData.WeekChewHabit,
@@ -400,11 +446,14 @@ func (e *Entry) FirstFilterUpdate(pastureId int64, xToDay *XToday) (err error) {
 				"before_three_sum_rumina": before3DaysNeckActiveHabit.SumRumina,
 				"before_three_sum_intake": before3DaysNeckActiveHabit.SumIntake,
 			}).Error; err != nil {
-			return xerr.WithStack(err)
+			zaplog.Error("WeeklyUpdateActiveHabit",
+				zap.Error(err),
+				zap.Any("NeckActiveHabit", v),
+				zap.Any("pastureId", pastureId),
+			)
 		}
 	}
-	zaplog.Info("EntryUpdateActiveHabit-FilterUpdate-Success")
-	return nil
+	return err
 }
 
 // SecondUpdateChangeFilter 第二次更新变化趋势滤波
@@ -493,7 +542,6 @@ func (e *Entry) SecondUpdateChangeFilter(pastureId int64, xToday *XToday) (err e
 			zaplog.Error("SecondUpdateChangeFilter-1", zap.Any("error", err), zap.Any("xToday", xToday))
 		}
 	}
-	zaplog.Info("SecondUpdateChangeFilter-Success")
 	return nil
 }
 
@@ -557,7 +605,6 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 			continue
 		}
 	}
-	zaplog.Info("EntryUpdateActiveHabit-ActivityVolumeChanges-Success")
 	return nil
 }
 
@@ -565,11 +612,6 @@ func (e *Entry) FilterCorrectAndScoreUpdate(pastureId int64, xToday *XToday) err
 func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
 	res := make([]*model.NeckRingBarChange, 0)
 	oneDayAgo := time.Now().AddDate(0, 0, -1).Format(model.LayoutDate2)
-	//SELECT h.neck_ring_number,h.heat_date, h.frameid, c.pen_id, c.pen_name, COUNT(*) as nb, ROUND(AVG(h.change_high)) as change_high,
-	//ROUND(AVG(h.change_filter)) as change_filter F
-	//ROM neck_active_habit as h JOIN cow as c ON h.neck_ring_number = c.neck_ring_number
-	//WHERE h.pasture_id = 1 AND h.heat_date >= '2025-01-16' AND h.cow_id >= 0
-	//GROUP BY h.heat_date, h.frameid, c.pen_id ORDER BY h.heat_date, h.frameid, c.pen_name
 	if err := e.DB.Table(fmt.Sprintf("%s as h", new(model.NeckActiveHabit).TableName())).
 		Select("h.neck_ring_number,h.heat_date, h.frameid, c.pen_id, c.pen_name, COUNT(*) as nb, ROUND(AVG(h.change_high)) as change_high, ROUND(AVG(h.change_filter)) as change_filter").
 		Joins("JOIN cow as c ON h.neck_ring_number = c.neck_ring_number").
@@ -592,6 +634,15 @@ func (e *Entry) UpdateChangeAdJust(pastureId int64, xToday *XToday) error {
 			zaplog.Error("UpdateChangeAdJust-1", zap.Any("error", err), zap.Any("xToday", xToday))
 		}
 	}
+
+	// 更新所有的显示状态为否的记录为是
+	if err := e.DB.Model(new(model.NeckActiveHabit)).
+		Where("id BETWEEN ? AND ?", xToday.LastMaxHabitId, xToday.CurrMaxHabitId).
+		Where("pasture_id = ?", pastureId).
+		Where("is_show = ?", pasturePb.IsShow_No).
+		Update("is_show = ?", pasturePb.IsShow_Ok).Error; err != nil {
+		zaplog.Error("UpdateChangeAdJust-2", zap.Any("error", err), zap.Any("xToday", xToday))
+	}
 	return nil
 }
 

+ 3 - 4
module/crontab/sql.go

@@ -108,8 +108,7 @@ func (e *Entry) IsExistNeckActiveHabit(neckRingNumber, heatDate string, frameId
 		Where("neck_ring_number = ?", neckRingNumber).
 		Where("heat_date = ?", heatDate).
 		Where("frameid = ?", frameId).
-		Count(&count).
-		First(neckActiveHabit).Error; err != nil {
+		Count(&count).First(neckActiveHabit).Error; err != nil {
 		return nil, 0
 	}
 	return neckActiveHabit, count
@@ -225,11 +224,11 @@ func (e *Entry) FindSumHabitData(pastureId int64, neckRingNumber, heatDate strin
 			fmt.Sprintf("MIN( CASE WHEN filter_chew > %d THEN filter_chew WHEN filter_rumina >= %d THEN filter_rumina ELSE 0 END) as sum_min_chew", model.DefaultChangeFilter, model.DefaultRuminaFilter),
 		).
 		Where("pasture_id = ?", pastureId).
-		Where("heat_date BETWEEN ? AND ?", before1DayDate, beginDayDate).
+		Where("heat_date BETWEEN ? AND ?", before1DayDate, heatDate).
 		Where("active_time BETWEEN ? AND ?", activeStartTime, activeTime).
 		Where(e.DB.Where("high > ?", xToday.High).Or("rumina >= ?", xToday.Rumina)).
 		Where("neck_ring_number = ? AND frameid = ?", neckRingNumber, frameid).
-		Group("neck_ring_number").First(sumHabitData).Error; err != nil {
+		Group("neck_ring_number").First(sumHabitData).Debug().Error; err != nil {
 		zaplog.Error("WeeklyActiveAvgUpdate-2",
 			zap.Any("error", err),
 			zap.Any("neckRingNumber", neckRingNumber),

+ 29 - 0
util/util.go

@@ -63,6 +63,7 @@ var (
 		22: 118, // 04-06
 		23: 118,
 	}
+	ExpectedFrameIDs = []int32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
 )
 
 // GenerateRandomNumberString 生成指定长度的数字串
@@ -362,6 +363,34 @@ func DaysBetween(startDayUnix int64, endDayUnix int64) int64 {
 	return daysDiff
 }
 
+// GetDaysBetween 获取两个日期之间的所有天数
+func GetDaysBetween(startDate, endDate string) ([]string, error) {
+	// 解析日期
+	start, err := time.Parse("2006-01-02", startDate)
+	if err != nil {
+		return nil, fmt.Errorf("解析开始日期失败: %v", err)
+	}
+	end, err := time.Parse("2006-01-02", endDate)
+	if err != nil {
+		return nil, fmt.Errorf("解析结束日期失败: %v", err)
+	}
+
+	// 确保开始日期早于或等于结束日期
+	if start.After(end) {
+		return nil, fmt.Errorf("开始日期不能晚于结束日期")
+	}
+
+	// 存储日期的数组
+	var days []string
+
+	// 遍历日期
+	for current := start; !current.After(end); current = current.AddDate(0, 0, 1) {
+		days = append(days, current.Format("2006-01-02"))
+	}
+
+	return days, nil
+}
+
 // MsgFormat 格式化消息字符串 字符串里面有多个冒号,仅删除冒号前后的空格(如果存在)
 func MsgFormat(input string) string {
 	// 定义正则表达式,用于匹配冒号两边的空格

+ 3 - 20
util/util_test.go

@@ -506,26 +506,9 @@ func TestGetNeckRingActiveTimer(t *testing.T) {
 	}
 }
 
-type XToday struct {
-	XBegDate       string
-	XEndDate       string
-	LastMaxHabitId int64
-	CurrMaxHabitId int64
-	XMin2Id        int64
-	XMin7Id        int64
-	ActiveLowest   int64
-	RuminaLowest   int64
-	ActiveLow      int64
-	ActiveMiddle   int64
-	ActiveHigh     int64
-}
-
 func Test_demo(t *testing.T) {
-	res := make([]int64, 0)
-	for i := 1; i <= 100; i++ {
-		res = append(res, int64(i))
-	}
 
-	fmt.Println(res[:50])
-	fmt.Println(res[50:])
+	for i := 0; i <= 11; i++ {
+		fmt.Println(FrameIds(int32(i)))
+	}
 }