package controllers import ( "errors" "github.com/gin-gonic/gin" "gorm.io/gorm" "gorm.io/gorm/clause" "hr_receiver/config" "hr_receiver/models" "math" "net/http" "strconv" ) type StepTrainingController struct { DB *gorm.DB } func NewStepTrainingController() *StepTrainingController { return &StepTrainingController{DB: config.DB} } // 接收训练记录 func (tc *StepTrainingController) CreateTrainingRecord(c *gin.Context) { var record models.StepTrainRecord // 绑定并验证JSON数据 if err := c.ShouldBindJSON(&record); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 使用事务保存数据[4](@ref) err := tc.DB.Transaction(func(tx *gorm.DB) error { // 保存主记录 if err := tx.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "train_id"}}, // 指定冲突的列 DoUpdates: clause.Assignments(map[string]interface{}{ "max_heart_rate": record.MaxHeartRate, "start_time": record.StartTime, "end_time": record.EndTime, "duration": record.Duration, "dead_zone": record.DeadZone, "name": record.Name, "evaluation": record.Evaluation, }), }).Omit("HeartRates", "StrideFreqs").Create(&record).Error; err != nil { return err } // 保存关联的心率数据 for i := range record.HeartRates { if err := tx.Clauses( clause.OnConflict{ Columns: []clause.Column{{Name: "identifier"}}, // 指定冲突的列 DoUpdates: clause.Assignments(map[string]interface{}{"heart_rate_type": record.HeartRates[i].HeartRateType, "value": record.HeartRates[i].Value, "time": record.HeartRates[i].Time}), }, ).Create(&record.HeartRates[i]).Error; err != nil { return err } } for i := range record.StrideFreqs { if err := tx.Clauses( clause.OnConflict{ Columns: []clause.Column{{Name: "identifier"}}, // 指定冲突的列 DoUpdates: clause.Assignments(map[string]interface{}{"value": record.StrideFreqs[i].Value, "time": record.StrideFreqs[i].Time}), }, ).Create(&record.StrideFreqs[i]).Error; err != nil { return err } } return nil }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{ "message": "数据保存成功", "id": record.TrainId, }) } func (tc *StepTrainingController) GetTrainingRecords(c *gin.Context) { // 定义分页参数结构 type PaginationParams struct { PageNum int `form:"pageNum,default=1"` // 页码,默认第一页 PageSize int `form:"pageSize,default=10"` // 每页数量,默认10条 } var params PaginationParams if err := c.ShouldBindQuery(¶ms); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 验证分页参数有效性 if params.PageNum < 1 { params.PageNum = 1 } if params.PageSize < 1 || params.PageSize > 100 { params.PageSize = 10 } // 计算偏移量 offset := (params.PageNum - 1) * params.PageSize var ( records []models.StepTrainRecord totalRows int64 ) // 获取总记录数 if err := tc.DB.Model(&models.StepTrainRecord{}).Count(&totalRows).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "获取记录总数失败"}) return } // 查询分页数据(按开始时间倒序排列) result := tc.DB. Order("start_time DESC"). // 按开始时间倒序 Offset(offset). Limit(params.PageSize). Find(&records) if result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return } // 计算总页数 totalPages := int(math.Ceil(float64(totalRows) / float64(params.PageSize))) c.JSON(http.StatusOK, gin.H{ "message": "查询成功", "data": gin.H{ "list": records, "pagination": gin.H{ "currentPage": params.PageNum, "pageSize": params.PageSize, "totalPage": totalPages, "totalList": totalRows, }, }, }) } func (tc *StepTrainingController) GetTrainingRecordByTrainId(c *gin.Context) { // 从URL路径参数获取trainId trainId := c.Param("trainId") if trainId == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "训练ID不能为空"}) return } // 将字符串trainId转换为uint类型 tid, err := strconv.ParseInt(trainId, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的训练ID格式"}) return } var record models.StepTrainRecord // 查询主记录并预加载关联的心率和步频数据 result := tc.DB.Where("train_id = ?", uint(tid)). Preload("HeartRates"). Preload("StrideFreqs"). First(&record) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "训练记录不存在"}) } else { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) } return } // 成功返回数据 c.JSON(http.StatusOK, gin.H{ "message": "查询成功", "data": record, }) }