feat: step train.
This commit is contained in:
84
controllers/step_train.go
Normal file
84
controllers/step_train.go
Normal file
@ -0,0 +1,84 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"hr_receiver/config"
|
||||
"hr_receiver/models"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
9
main.go
9
main.go
@ -15,7 +15,14 @@ func main() {
|
||||
|
||||
config.DB.Debug()
|
||||
// 自动迁移模型
|
||||
config.DB.AutoMigrate(&models.TrainRecord{}, &models.TrainingData{}, &models.Belt{}, &models.HeartRate{}, &models.BeltAnalysis{})
|
||||
config.DB.AutoMigrate(&models.TrainRecord{},
|
||||
&models.TrainingData{},
|
||||
&models.Belt{},
|
||||
&models.HeartRate{},
|
||||
&models.BeltAnalysis{},
|
||||
&models.StepTrainRecord{},
|
||||
&models.StepHeartRate{},
|
||||
&models.StepStrideFreq{})
|
||||
|
||||
// 启动服务
|
||||
r := routes.SetupRouter()
|
||||
|
||||
38
models/step_train.go
Normal file
38
models/step_train.go
Normal file
@ -0,0 +1,38 @@
|
||||
package models
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type StepStrideFreq struct {
|
||||
gorm.Model
|
||||
TrainId uint `gorm:"column:train_id; index" json:"trainId"` // 外键关联训练记录[4](@ref)
|
||||
Time int64 `gorm:"type:bigint" json:"time"` // 保持与前端一致的毫秒时间戳[3](@ref)
|
||||
Value int `gorm:"type:int" json:"value"`
|
||||
PredictValue int `gorm:"type:int" json:"predictValue"`
|
||||
Identifier string `gorm:"uniqueIndex;type:varchar(255)" json:"identifier"`
|
||||
}
|
||||
|
||||
// 对应Flutter的HeartRate结构
|
||||
type StepHeartRate struct {
|
||||
gorm.Model
|
||||
TrainId uint `gorm:"column:train_id; index" json:"trainId"` // 外键关联训练记录[4](@ref)
|
||||
Time int64 `gorm:"type:bigint" json:"time"` // 保持与前端一致的毫秒时间戳[3](@ref)
|
||||
Value int `gorm:"type:int" json:"value"`
|
||||
HeartRateType int `gorm:"type:int" json:"predictValue"`
|
||||
Identifier string `gorm:"uniqueIndex;type:varchar(255)" json:"identifier"`
|
||||
}
|
||||
|
||||
// 对应Flutter的TrainRecord结构
|
||||
type StepTrainRecord struct {
|
||||
gorm.Model
|
||||
TrainId uint `gorm:"uniqueIndex" json:"tid"` // 对应Dart的tid字段
|
||||
StartTime int64 `gorm:"type:bigint" json:"time"` // 开始时间戳
|
||||
EndTime int64 `gorm:"type:bigint" json:"endTime"` // 结束时间戳[3](@ref)
|
||||
Name string `gorm:"size:100" json:"name"`
|
||||
RunType string `gorm:"size:100" json:"RunType"`
|
||||
MaxHeartRate int `gorm:"type:int" json:"maxHeartRate"`
|
||||
Duration int `gorm:"type:int" json:"duration"` // 持续时间(秒)
|
||||
DeadZone int `gorm:"type:int" json:"deadZone"`
|
||||
Evaluation string `gorm:"size:50" json:"evaluation"`
|
||||
HeartRates []StepHeartRate `gorm:"foreignKey:TrainId;references:TrainId" json:"HeartRates"`
|
||||
StrideFreqs []StepStrideFreq `gorm:"foreignKey:TrainId;references:TrainId" json:"strideFreqs"`
|
||||
}
|
||||
@ -12,6 +12,7 @@ func SetupRouter() *gin.Engine {
|
||||
r := gin.Default()
|
||||
r.Use(middleware.GzipMiddleware())
|
||||
trainingController := controllers.NewTrainingController()
|
||||
stepTrainController := controllers.NewStepTrainingController()
|
||||
|
||||
v1 := r.Group("/api/v1")
|
||||
{
|
||||
@ -21,6 +22,11 @@ func SetupRouter() *gin.Engine {
|
||||
records.GET("/analysis", trainingController.HandleCurveAnalysis)
|
||||
// 可扩展其他路由:GET, PUT, DELETE等
|
||||
}
|
||||
steps := v1.Group("/step") //.Use(middleware.AuthMiddleware())
|
||||
{
|
||||
steps.POST("", stepTrainController.CreateTrainingRecord)
|
||||
// 可扩展其他路由:GET, PUT, DELETE等
|
||||
}
|
||||
auth := v1.Group("/auth")
|
||||
{
|
||||
auth.GET("/token", func(c *gin.Context) {
|
||||
|
||||
Reference in New Issue
Block a user