Compare commits

...

2 Commits

Author SHA1 Message Date
0852f4bc23 feat: gzip response. 2025-06-27 09:46:04 +08:00
19148d7d35 feat: query. 2025-06-27 09:31:42 +08:00
5 changed files with 144 additions and 1 deletions

View File

@ -1,12 +1,15 @@
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 {
@ -82,3 +85,105 @@ func (tc *StepTrainingController) CreateTrainingRecord(c *gin.Context) {
"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,
})
}

View File

@ -4,10 +4,12 @@ import (
"compress/gzip"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func GzipMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 1. 处理请求解压
if c.Request.Header.Get("Content-Encoding") == "gzip" {
gzReader, err := gzip.NewReader(c.Request.Body)
if err != nil {
@ -17,6 +19,39 @@ func GzipMiddleware() gin.HandlerFunc {
defer gzReader.Close()
c.Request.Body = gzReader
}
// 2. 设置响应压缩支持
if strings.Contains(c.Request.Header.Get("Accept-Encoding"), "gzip") {
// 创建gzip writer
gzWriter := gzip.NewWriter(c.Writer)
defer gzWriter.Close()
// 替换原始writer为压缩writer
originalWriter := c.Writer
c.Writer = &gzipResponseWriter{
ResponseWriter: originalWriter,
gzWriter: gzWriter,
}
// 设置响应头
c.Header("Content-Encoding", "gzip")
c.Header("Vary", "Accept-Encoding")
}
c.Next()
}
}
// 自定义ResponseWriter实现gzip压缩
type gzipResponseWriter struct {
gin.ResponseWriter
gzWriter *gzip.Writer
}
func (w *gzipResponseWriter) Write(data []byte) (int, error) {
return w.gzWriter.Write(data)
}
func (w *gzipResponseWriter) WriteString(s string) (int, error) {
return w.gzWriter.Write([]byte(s))
}

1
models/pageination.go Normal file
View File

@ -0,0 +1 @@
package models

View File

@ -33,6 +33,6 @@ type StepTrainRecord struct {
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"`
HeartRates []StepHeartRate `gorm:"foreignKey:TrainId;references:TrainId" json:"heartRates"`
StrideFreqs []StepStrideFreq `gorm:"foreignKey:TrainId;references:TrainId" json:"strideFreqs"`
}

View File

@ -25,6 +25,8 @@ func SetupRouter() *gin.Engine {
steps := v1.Group("/step") //.Use(middleware.AuthMiddleware())
{
steps.POST("", stepTrainController.CreateTrainingRecord)
steps.GET("train-records", stepTrainController.GetTrainingRecords)
steps.GET("train-data/:trainId", stepTrainController.GetTrainingRecordByTrainId)
// 可扩展其他路由GET, PUT, DELETE等
}
auth := v1.Group("/auth")