feat: hr save.
This commit is contained in:
@ -2,11 +2,80 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
"hr_receiver/config"
|
"hr_receiver/config"
|
||||||
"hr_receiver/models"
|
"hr_receiver/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TrainingController struct {
|
||||||
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTrainingController() *TrainingController {
|
||||||
|
return &TrainingController{DB: config.DB}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收训练记录
|
||||||
|
func (tc *TrainingController) CreateTrainingRecord(c *gin.Context) {
|
||||||
|
var record models.TrainRecord
|
||||||
|
|
||||||
|
// 绑定并验证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,
|
||||||
|
"people_num": record.PeopleNum,
|
||||||
|
"name": record.Name,
|
||||||
|
"evaluation": record.Evaluation,
|
||||||
|
}),
|
||||||
|
}).Omit("HeartRates", "belts").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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//// 保存腰带关联关系
|
||||||
|
//if len(record.Belts) > 0 {
|
||||||
|
// if err := tx.Model(&record).Association("Belts").Replace(record.Belts); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusCreated, record)
|
||||||
|
}
|
||||||
|
|
||||||
func ReceiveTrainingData(c *gin.Context) {
|
func ReceiveTrainingData(c *gin.Context) {
|
||||||
var data models.TrainingData
|
var data models.TrainingData
|
||||||
|
|
||||||
|
|||||||
3
main.go
3
main.go
@ -13,8 +13,9 @@ func main() {
|
|||||||
// 连接数据库
|
// 连接数据库
|
||||||
config.ConnectDB()
|
config.ConnectDB()
|
||||||
|
|
||||||
|
config.DB.Debug()
|
||||||
// 自动迁移模型
|
// 自动迁移模型
|
||||||
config.DB.AutoMigrate(&models.TrainingData{})
|
config.DB.AutoMigrate(&models.TrainRecord{}, &models.TrainingData{}, &models.Belt{}, &models.HeartRate{})
|
||||||
|
|
||||||
// 启动服务
|
// 启动服务
|
||||||
r := routes.SetupRouter()
|
r := routes.SetupRouter()
|
||||||
|
|||||||
@ -9,3 +9,37 @@ type TrainingData struct {
|
|||||||
Probability float64 `gorm:"type:decimal(5,4)" json:"probability"`
|
Probability float64 `gorm:"type:decimal(5,4)" json:"probability"`
|
||||||
SessionID string `gorm:"index" json:"session_id"`
|
SessionID string `gorm:"index" json:"session_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 对应Flutter的Belt结构
|
||||||
|
type Belt struct {
|
||||||
|
gorm.Model
|
||||||
|
Addr string `gorm:"uniqueIndex;size:255" json:"addr"` // 对应Dart的addr字段[6](@ref)
|
||||||
|
BID uint `gorm:"column:bid" json:"bid"` // 对应Dart的bid字段
|
||||||
|
Name string `gorm:"size:100" json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对应Flutter的HeartRate结构
|
||||||
|
type HeartRate struct {
|
||||||
|
gorm.Model
|
||||||
|
TrainId uint `gorm:"column:train_id; index" json:"trainId"` // 外键关联训练记录[4](@ref)
|
||||||
|
BeltId uint `gorm:"column:belt_id;index" json:"bid"` // 对应Dart的bid字段
|
||||||
|
BeltAddr string `gorm:"column:belt_addr;size:255" json:"beltAddr"` // 对应Dart的beltAddr字段
|
||||||
|
Time int64 `gorm:"type:bigint" json:"time"` // 保持与前端一致的毫秒时间戳[3](@ref)
|
||||||
|
Value int `gorm:"type:int" json:"value"`
|
||||||
|
Identifier string `gorm:"uniqueIndex;type:varchar(255)" json:"identifier"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对应Flutter的TrainRecord结构
|
||||||
|
type TrainRecord 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"`
|
||||||
|
MaxHeartRate int `gorm:"type:int" json:"maxHeartRate"`
|
||||||
|
Duration int `gorm:"type:int" json:"duration"` // 持续时间(秒)
|
||||||
|
PeopleNum int `gorm:"type:int" json:"peopleNum"`
|
||||||
|
Evaluation string `gorm:"size:50" json:"evaluation"`
|
||||||
|
Belts []Belt `gorm:"many2many:train_record_belts;" json:"belts"` // 多对多关联[4](@ref)
|
||||||
|
HeartRates []HeartRate `gorm:"foreignKey:TrainId;references:TrainId" json:"heart_rates"`
|
||||||
|
}
|
||||||
|
|||||||
@ -7,11 +7,15 @@ import (
|
|||||||
|
|
||||||
func SetupRouter() *gin.Engine {
|
func SetupRouter() *gin.Engine {
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
trainingController := controllers.NewTrainingController()
|
||||||
|
|
||||||
api := r.Group("/api/v1")
|
v1 := r.Group("/api/v1")
|
||||||
{
|
{
|
||||||
api.POST("/training", controllers.ReceiveTrainingData)
|
records := v1.Group("/train-records")
|
||||||
|
{
|
||||||
|
records.POST("", trainingController.CreateTrainingRecord)
|
||||||
|
// 可扩展其他路由:GET, PUT, DELETE等
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user