190 lines
4.8 KiB
Go
190 lines
4.8 KiB
Go
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(¶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,
|
||
})
|
||
}
|