Files
hr_data_analyzer/controllers/step_train.go
2025-06-27 09:31:42 +08:00

190 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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{}{"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(&params); 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,
})
}