feat: swag.

This commit is contained in:
2026-05-04 16:20:46 +08:00
parent 3fbbbbc6a8
commit b7843641ca
24 changed files with 9376 additions and 19 deletions
+17
View File
@@ -283,6 +283,23 @@ func callAIForAnalysis(prompt string) (*aiAnalysisResult, error) {
}, nil }, nil
} }
// @Summary AI分析
// @Description 上传心率CSV和教案文件通过AI生成课堂分析报告支持流式和非流式输出
// @Tags AI分析
// @Accept multipart/form-data
// @Produce json
// @Param heart_rate_data formData file true "心率数据CSV文件"
// @Param step_data formData file false "步数数据CSV文件(analysis_type为heart_rate_with_steps时必填)"
// @Param teaching_plan formData file false "教案DOCX文件(teaching_plan_source为upload/wechat时必填)"
// @Param analysis_type formData string false "分析类型: heart_rate_only(默认) | heart_rate_with_steps"
// @Param teaching_plan_source formData string false "教案来源: upload(默认) | cloud | wechat"
// @Param regionid formData string false "区域ID"
// @Param trainid formData string false "训练ID"
// @Param lesson_plan_id formData string false "云端教案ID(teaching_plan_source=cloud时必填)"
// @Param stream formData string false "是否流式输出: true | false"
// @Success 200 {object} SwagAPIResponse "分析成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /train-records/analysis-by-ai [post]
func (tc *TrainingController) AnalyzeByAI(c *gin.Context) { func (tc *TrainingController) AnalyzeByAI(c *gin.Context) {
form, err := c.MultipartForm() form, err := c.MultipartForm()
if err != nil { if err != nil {
+54 -11
View File
@@ -36,9 +36,17 @@ func NewGatewayAdminController() *GatewayAdminController {
return &GatewayAdminController{DB: config.DB} return &GatewayAdminController{DB: config.DB}
} }
// List 获取网关列表 // @Summary 获取网关列表
// GET /api/v1/gateways?keyword=&isSold=&projectType=&regionId= // @Description 查询网关列表,支持关键词/售出状态/项目类型/区域筛选。超级管理员可查全部,操作员只能查所属区域
// 超级管理员可查询全部;操作员/区域管理员仅能查询所属 regionIDs 网关 // @Tags 网关管理
// @Produce json
// @Param keyword query string false "关键词(名称/MAC模糊搜索)"
// @Param isSold query bool false "售出状态"
// @Param projectType query string false "项目类型"
// @Param regionId query int false "区域ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/gateways [get]
func (gc *GatewayAdminController) List(c *gin.Context) { func (gc *GatewayAdminController) List(c *gin.Context) {
var items []models.Gateway var items []models.Gateway
query := gc.DB.Model(&models.Gateway{}).Order("region_id ASC, created_at DESC") query := gc.DB.Model(&models.Gateway{}).Order("region_id ASC, created_at DESC")
@@ -91,8 +99,16 @@ func (gc *GatewayAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "查询成功", items) writeSuccess(c, http.StatusOK, "查询成功", items)
} }
// GetByMACForUser MAC 查询网关信息 // @Summary 按MAC查询网关
// GET /api/v1/gateways/by-mac?mac= // @Description 根据MAC地址查询网关信息支持格式兼容带冒号/横线/纯数字)
// @Tags 网关管理
// @Produce json
// @Param mac query string true "MAC地址"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Failure 400 {object} SwagAPIResponse "MAC参数为空"
// @Failure 404 {object} SwagAPIResponse "未找到该网关"
// @Router /gateways/by-mac [get]
func (gc *GatewayAdminController) GetByMACForUser(c *gin.Context) { func (gc *GatewayAdminController) GetByMACForUser(c *gin.Context) {
macInput := strings.ToUpper(strings.TrimSpace(c.Query("mac"))) macInput := strings.ToUpper(strings.TrimSpace(c.Query("mac")))
if macInput == "" { if macInput == "" {
@@ -132,8 +148,17 @@ func (gc *GatewayAdminController) GetByMACForUser(c *gin.Context) {
writeSuccess(c, http.StatusOK, "查询成功", item) writeSuccess(c, http.StatusOK, "查询成功", item)
} }
// Create 创建网关 // @Summary 创建网关
// POST /api/gateways // @Description 创建新的网关记录,自动同步到产品库存
// @Tags 网关管理
// @Accept json
// @Produce json
// @Param gateway body gatewayPayload true "网关信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 409 {object} SwagAPIResponse "MAC地址已存在"
// @Router /admin/gateways [post]
func (gc *GatewayAdminController) Create(c *gin.Context) { func (gc *GatewayAdminController) Create(c *gin.Context) {
var payload gatewayPayload var payload gatewayPayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -188,8 +213,18 @@ func (gc *GatewayAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "创建成功", record) writeSuccess(c, http.StatusCreated, "创建成功", record)
} }
// Update 更新网关信息 // @Summary 更新网关信息
// PUT /api/gateways/:id // @Description 更新指定网关的详细信息,自动同步到产品库存
// @Tags 网关管理
// @Accept json
// @Produce json
// @Param id path int true "网关ID"
// @Param gateway body gatewayPayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "网关不存在"
// @Router /admin/gateways/{id} [put]
func (gc *GatewayAdminController) Update(c *gin.Context) { func (gc *GatewayAdminController) Update(c *gin.Context) {
record, err := gc.findByID(c.Param("id")) record, err := gc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -246,8 +281,16 @@ func (gc *GatewayAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "更新成功", record) writeSuccess(c, http.StatusOK, "更新成功", record)
} }
// Delete 删除网关 // @Summary 删除网关
// DELETE /api/gateways/:id // @Description 删除指定网关(已售出的网关禁止删除),自动同步删除产品库存
// @Tags 网关管理
// @Produce json
// @Param id path int true "网关ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 403 {object} SwagAPIResponse "已售出无法删除"
// @Failure 404 {object} SwagAPIResponse "网关不存在"
// @Router /admin/gateways/{id} [delete]
func (gc *GatewayAdminController) Delete(c *gin.Context) { func (gc *GatewayAdminController) Delete(c *gin.Context) {
record, err := gc.findByID(c.Param("id")) record, err := gc.findByID(c.Param("id"))
if err != nil { if err != nil {
+40
View File
@@ -26,6 +26,14 @@ func NewKindergartenAdminController() *KindergartenAdminController {
return &KindergartenAdminController{DB: config.DB} return &KindergartenAdminController{DB: config.DB}
} }
// @Summary 获取幼儿园列表
// @Description 查询幼儿园列表,支持按名称/地址模糊搜索
// @Tags 幼儿园管理
// @Produce json
// @Param keyword query string false "关键词(名称/地址模糊搜索)"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/kindergartens [get]
func (kc *KindergartenAdminController) List(c *gin.Context) { func (kc *KindergartenAdminController) List(c *gin.Context) {
var items []models.Kindergarten var items []models.Kindergarten
query := kc.DB.Model(&models.Kindergarten{}).Order("region_id ASC, id ASC") query := kc.DB.Model(&models.Kindergarten{}).Order("region_id ASC, id ASC")
@@ -42,6 +50,16 @@ func (kc *KindergartenAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", items) writeSuccess(c, http.StatusOK, "query success", items)
} }
// @Summary 创建幼儿园
// @Description 创建新的幼儿园记录
// @Tags 幼儿园管理
// @Accept json
// @Produce json
// @Param kindergarten body kindergartenPayload true "幼儿园信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/kindergartens [post]
func (kc *KindergartenAdminController) Create(c *gin.Context) { func (kc *KindergartenAdminController) Create(c *gin.Context) {
var payload kindergartenPayload var payload kindergartenPayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -65,6 +83,18 @@ func (kc *KindergartenAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", record) writeSuccess(c, http.StatusCreated, "create success", record)
} }
// @Summary 更新幼儿园信息
// @Description 更新指定幼儿园的名称、地址和区域
// @Tags 幼儿园管理
// @Accept json
// @Produce json
// @Param id path int true "幼儿园ID"
// @Param kindergarten body kindergartenPayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "幼儿园不存在"
// @Router /admin/kindergartens/{id} [put]
func (kc *KindergartenAdminController) Update(c *gin.Context) { func (kc *KindergartenAdminController) Update(c *gin.Context) {
record, err := kc.findByID(c.Param("id")) record, err := kc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -93,6 +123,16 @@ func (kc *KindergartenAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", record) writeSuccess(c, http.StatusOK, "update success", record)
} }
// @Summary 删除幼儿园
// @Description 删除指定幼儿园,如果被用户绑定则无法删除
// @Tags 幼儿园管理
// @Produce json
// @Param id path int true "幼儿园ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "幼儿园不存在"
// @Failure 409 {object} SwagAPIResponse "已绑定用户无法删除"
// @Router /admin/kindergartens/{id} [delete]
func (kc *KindergartenAdminController) Delete(c *gin.Context) { func (kc *KindergartenAdminController) Delete(c *gin.Context) {
record, err := kc.findByID(c.Param("id")) record, err := kc.findByID(c.Param("id"))
if err != nil { if err != nil {
+78
View File
@@ -53,6 +53,18 @@ func NewLessonPlanController() *LessonPlanController {
return &LessonPlanController{DB: config.DB} return &LessonPlanController{DB: config.DB}
} }
// @Summary 上传教案文件
// @Description 上传 .docx 格式的教案文件支持MD5去重最大10MB
// @Tags 教案管理
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "教案文件(.docx)"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "上传成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Failure 409 {object} SwagAPIResponse "文件已存在"
// @Router /lesson-plans/upload [post]
func (lc *LessonPlanController) Upload(c *gin.Context) { func (lc *LessonPlanController) Upload(c *gin.Context) {
fileHeader, err := c.FormFile(lessonPlanFieldName) fileHeader, err := c.FormFile(lessonPlanFieldName)
if err != nil { if err != nil {
@@ -152,6 +164,14 @@ func (lc *LessonPlanController) Upload(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "upload success", record) writeSuccess(c, http.StatusCreated, "upload success", record)
} }
// @Summary 获取教案列表
// @Description 获取教案文件列表(非分页),按创建时间倒序
// @Tags 教案管理
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Router /lesson-plans [get]
func (lc *LessonPlanController) List(c *gin.Context) { func (lc *LessonPlanController) List(c *gin.Context) {
userID, _, ok := currentUser(c) userID, _, ok := currentUser(c)
if !ok { if !ok {
@@ -173,6 +193,22 @@ func (lc *LessonPlanController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", records) writeSuccess(c, http.StatusOK, "query success", records)
} }
// @Summary 分页查询教案
// @Description 分页获取教案文件列表,支持文件名模糊搜索、上传者搜索、区域筛选、排序
// @Tags 教案管理
// @Produce json
// @Param pageNum query int false "页码(默认1)"
// @Param pageSize query int false "每页数量(默认10,最大100)"
// @Param keyword query string false "文件名模糊搜索"
// @Param uploaderName query string false "上传者名模糊搜索"
// @Param regionId query int false "区域ID"
// @Param sortBy query string false "排序字段: file_size | created_at"
// @Param sortOrder query string false "排序方向: asc | desc"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Router /lesson-plans/page [get]
func (lc *LessonPlanController) Page(c *gin.Context) { func (lc *LessonPlanController) Page(c *gin.Context) {
userID, _, ok := currentUser(c) userID, _, ok := currentUser(c)
if !ok { if !ok {
@@ -312,6 +348,17 @@ func (lc *LessonPlanController) Page(c *gin.Context) {
}) })
} }
// @Summary 下载教案文件
// @Description 通过ID下载教案文件自动更新下载计数和最后下载时间
// @Tags 教案管理
// @Produce application/octet-stream
// @Param id path int true "教案ID"
// @Security BearerAuth
// @Success 200 {file} binary "教案文件"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Failure 403 {object} SwagAPIResponse "无权限"
// @Failure 404 {object} SwagAPIResponse "文件不存在"
// @Router /lesson-plans/{id}/download [get]
func (lc *LessonPlanController) Download(c *gin.Context) { func (lc *LessonPlanController) Download(c *gin.Context) {
record, err := lc.findLessonPlan(c.Param("id")) record, err := lc.findLessonPlan(c.Param("id"))
if err != nil { if err != nil {
@@ -344,6 +391,17 @@ func (lc *LessonPlanController) Download(c *gin.Context) {
c.FileAttachment(record.FilePath, record.OriginalFilename) c.FileAttachment(record.FilePath, record.OriginalFilename)
} }
// @Summary 生成分享码
// @Description 为教案文件生成6位数字分享码有效期5分钟每次生成会失效之前的分享码
// @Tags 教案管理
// @Produce json
// @Param id path int true "教案ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "生成成功"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Failure 403 {object} SwagAPIResponse "无权限"
// @Failure 404 {object} SwagAPIResponse "文件不存在"
// @Router /lesson-plans/{id}/share-code [post]
func (lc *LessonPlanController) GenerateShareCode(c *gin.Context) { func (lc *LessonPlanController) GenerateShareCode(c *gin.Context) {
record, err := lc.findLessonPlan(c.Param("id")) record, err := lc.findLessonPlan(c.Param("id"))
if err != nil { if err != nil {
@@ -399,6 +457,15 @@ func (lc *LessonPlanController) GenerateShareCode(c *gin.Context) {
}) })
} }
// @Summary 通过分享码下载教案
// @Description 通过6位分享码下载教案文件无需认证
// @Tags 教案管理
// @Produce application/octet-stream
// @Param code path string true "6位分享码"
// @Success 200 {file} binary "教案文件"
// @Failure 400 {object} SwagAPIResponse "分享码无效"
// @Failure 404 {object} SwagAPIResponse "分享码过期或不存在"
// @Router /lesson-plans/share/{code}/download [get]
func (lc *LessonPlanController) DownloadByShareCode(c *gin.Context) { func (lc *LessonPlanController) DownloadByShareCode(c *gin.Context) {
shareCode := strings.TrimSpace(c.Param("code")) shareCode := strings.TrimSpace(c.Param("code"))
if len(shareCode) != shareCodeDigits { if len(shareCode) != shareCodeDigits {
@@ -439,6 +506,17 @@ func (lc *LessonPlanController) DownloadByShareCode(c *gin.Context) {
c.FileAttachment(record.FilePath, record.OriginalFilename) c.FileAttachment(record.FilePath, record.OriginalFilename)
} }
// @Summary 删除教案文件
// @Description 删除教案文件及其关联的分享码
// @Tags 教案管理
// @Produce json
// @Param id path int true "教案ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Failure 403 {object} SwagAPIResponse "无权限"
// @Failure 404 {object} SwagAPIResponse "文件不存在"
// @Router /lesson-plans/{id} [delete]
func (lc *LessonPlanController) Delete(c *gin.Context) { func (lc *LessonPlanController) Delete(c *gin.Context) {
record, err := lc.findLessonPlan(c.Param("id")) record, err := lc.findLessonPlan(c.Param("id"))
if err != nil { if err != nil {
+21 -2
View File
@@ -29,7 +29,16 @@ type AuthResponse struct {
User models.User `json:"user"` User models.User `json:"user"`
} }
// Register 用户注册 // @Summary 用户注册
// @Description 注册新用户返回JWT Token
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body SwagRegisterRequest true "注册信息"
// @Success 201 {object} SwagAPIResponse "注册成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 409 {object} SwagAPIResponse "用户名已存在"
// @Router /register [post]
func Register(c *gin.Context) { func Register(c *gin.Context) {
var req RegisterRequest var req RegisterRequest
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
@@ -73,7 +82,17 @@ func Register(c *gin.Context) {
}) })
} }
// Login 用户登录 // @Summary 用户登录
// @Description 用户名密码登录返回JWT Token和用户信息
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body SwagLoginRequest true "登录信息"
// @Success 200 {object} SwagAPIResponse "登录成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "用户名或密码错误"
// @Failure 403 {object} SwagAPIResponse "用户已禁用"
// @Router /login [post]
func Login(c *gin.Context) { func Login(c *gin.Context) {
var req LoginRequest var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
+42
View File
@@ -32,6 +32,16 @@ func NewProductDefinitionAdminController() *ProductDefinitionAdminController {
return &ProductDefinitionAdminController{DB: config.DB} return &ProductDefinitionAdminController{DB: config.DB}
} }
// @Summary 获取产品定义列表
// @Description 查询产品定义列表,支持按关键词/分类/启用状态筛选
// @Tags 产品定义管理
// @Produce json
// @Param keyword query string false "关键词(代码/名称/描述模糊搜索)"
// @Param category query string false "分类筛选"
// @Param isActive query bool false "是否启用"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/product-definitions [get]
func (pc *ProductDefinitionAdminController) List(c *gin.Context) { func (pc *ProductDefinitionAdminController) List(c *gin.Context) {
var items []models.ProductDefinition var items []models.ProductDefinition
query := pc.DB.Model(&models.ProductDefinition{}).Order("sort ASC, id ASC") query := pc.DB.Model(&models.ProductDefinition{}).Order("sort ASC, id ASC")
@@ -59,6 +69,16 @@ func (pc *ProductDefinitionAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", items) writeSuccess(c, http.StatusOK, "query success", items)
} }
// @Summary 创建产品定义
// @Description 创建新的产品定义
// @Tags 产品定义管理
// @Accept json
// @Produce json
// @Param productDefinition body productDefinitionPayload true "产品定义信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/product-definitions [post]
func (pc *ProductDefinitionAdminController) Create(c *gin.Context) { func (pc *ProductDefinitionAdminController) Create(c *gin.Context) {
var payload productDefinitionPayload var payload productDefinitionPayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -87,6 +107,18 @@ func (pc *ProductDefinitionAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", record) writeSuccess(c, http.StatusCreated, "create success", record)
} }
// @Summary 更新产品定义
// @Description 更新指定产品定义的信息
// @Tags 产品定义管理
// @Accept json
// @Produce json
// @Param id path int true "产品定义ID"
// @Param productDefinition body productDefinitionPayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "产品定义不存在"
// @Router /admin/product-definitions/{id} [put]
func (pc *ProductDefinitionAdminController) Update(c *gin.Context) { func (pc *ProductDefinitionAdminController) Update(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -120,6 +152,16 @@ func (pc *ProductDefinitionAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", record) writeSuccess(c, http.StatusOK, "update success", record)
} }
// @Summary 删除产品定义
// @Description 删除指定产品定义(被库存或模板引用的无法删除)
// @Tags 产品定义管理
// @Produce json
// @Param id path int true "产品定义ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "产品定义不存在"
// @Failure 409 {object} SwagAPIResponse "已被引用无法删除"
// @Router /admin/product-definitions/{id} [delete]
func (pc *ProductDefinitionAdminController) Delete(c *gin.Context) { func (pc *ProductDefinitionAdminController) Delete(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
+46
View File
@@ -40,6 +40,20 @@ func NewProductInventoryAdminController() *ProductInventoryAdminController {
return &ProductInventoryAdminController{DB: config.DB} return &ProductInventoryAdminController{DB: config.DB}
} }
// @Summary 获取产品库存列表
// @Description 查询产品库存列表,支持多条件筛选
// @Tags 产品库存管理
// @Produce json
// @Param keyword query string false "关键词(资产名称/序列号/购买方等模糊搜索)"
// @Param productCode query string false "产品代码筛选"
// @Param projectTypeCode query string false "项目类型代码筛选"
// @Param suiteCode query string false "套件代码筛选"
// @Param status query string false "状态筛选"
// @Param soldTargetType query string false "购买方类型筛选"
// @Param regionId query int false "区域ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/product-inventories [get]
func (pc *ProductInventoryAdminController) List(c *gin.Context) { func (pc *ProductInventoryAdminController) List(c *gin.Context) {
var items []models.ProductInventory var items []models.ProductInventory
query := pc.DB.Model(&models.ProductInventory{}).Order("updated_at DESC, id DESC") query := pc.DB.Model(&models.ProductInventory{}).Order("updated_at DESC, id DESC")
@@ -79,6 +93,16 @@ func (pc *ProductInventoryAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", items) writeSuccess(c, http.StatusOK, "query success", items)
} }
// @Summary 创建产品库存记录
// @Description 创建新的产品库存记录
// @Tags 产品库存管理
// @Accept json
// @Produce json
// @Param inventory body productInventoryPayload true "库存信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/product-inventories [post]
func (pc *ProductInventoryAdminController) Create(c *gin.Context) { func (pc *ProductInventoryAdminController) Create(c *gin.Context) {
var payload productInventoryPayload var payload productInventoryPayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -121,6 +145,18 @@ func (pc *ProductInventoryAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", record) writeSuccess(c, http.StatusCreated, "create success", record)
} }
// @Summary 更新产品库存
// @Description 更新指定产品库存记录
// @Tags 产品库存管理
// @Accept json
// @Produce json
// @Param id path int true "库存ID"
// @Param inventory body productInventoryPayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "库存记录不存在"
// @Router /admin/product-inventories/{id} [put]
func (pc *ProductInventoryAdminController) Update(c *gin.Context) { func (pc *ProductInventoryAdminController) Update(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -167,6 +203,16 @@ func (pc *ProductInventoryAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", record) writeSuccess(c, http.StatusOK, "update success", record)
} }
// @Summary 删除产品库存
// @Description 删除指定产品库存记录(已售出的无法删除)
// @Tags 产品库存管理
// @Produce json
// @Param id path int true "库存ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "库存记录不存在"
// @Failure 409 {object} SwagAPIResponse "已售出无法删除"
// @Router /admin/product-inventories/{id} [delete]
func (pc *ProductInventoryAdminController) Delete(c *gin.Context) { func (pc *ProductInventoryAdminController) Delete(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
+41
View File
@@ -33,6 +33,16 @@ func NewProductPrototypeAdminController() *ProductPrototypeAdminController {
return &ProductPrototypeAdminController{DB: config.DB} return &ProductPrototypeAdminController{DB: config.DB}
} }
// @Summary 获取产品原型列表
// @Description 查询产品原型列表,支持按关键词/产品代码/项目类型筛选
// @Tags 产品原型管理
// @Produce json
// @Param keyword query string false "关键词(名称/备注模糊搜索)"
// @Param productCode query string false "产品代码筛选"
// @Param projectTypeCode query string false "项目类型代码筛选"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/product-prototypes [get]
func (pc *ProductPrototypeAdminController) List(c *gin.Context) { func (pc *ProductPrototypeAdminController) List(c *gin.Context) {
var items []models.ProductPrototype var items []models.ProductPrototype
query := pc.DB.Model(&models.ProductPrototype{}).Order("updated_at DESC, id DESC") query := pc.DB.Model(&models.ProductPrototype{}).Order("updated_at DESC, id DESC")
@@ -55,6 +65,16 @@ func (pc *ProductPrototypeAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", items) writeSuccess(c, http.StatusOK, "query success", items)
} }
// @Summary 创建产品原型
// @Description 创建新的产品原型
// @Tags 产品原型管理
// @Accept json
// @Produce json
// @Param productPrototype body productPrototypePayload true "产品原型信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/product-prototypes [post]
func (pc *ProductPrototypeAdminController) Create(c *gin.Context) { func (pc *ProductPrototypeAdminController) Create(c *gin.Context) {
var payload productPrototypePayload var payload productPrototypePayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -88,6 +108,18 @@ func (pc *ProductPrototypeAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", record) writeSuccess(c, http.StatusCreated, "create success", record)
} }
// @Summary 更新产品原型
// @Description 更新指定产品原型的信息
// @Tags 产品原型管理
// @Accept json
// @Produce json
// @Param id path int true "产品原型ID"
// @Param productPrototype body productPrototypePayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "产品原型不存在"
// @Router /admin/product-prototypes/{id} [put]
func (pc *ProductPrototypeAdminController) Update(c *gin.Context) { func (pc *ProductPrototypeAdminController) Update(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -122,6 +154,15 @@ func (pc *ProductPrototypeAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", record) writeSuccess(c, http.StatusOK, "update success", record)
} }
// @Summary 删除产品原型
// @Description 删除指定产品原型
// @Tags 产品原型管理
// @Produce json
// @Param id path int true "产品原型ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "产品原型不存在"
// @Router /admin/product-prototypes/{id} [delete]
func (pc *ProductPrototypeAdminController) Delete(c *gin.Context) { func (pc *ProductPrototypeAdminController) Delete(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
+40
View File
@@ -36,6 +36,15 @@ func NewProductSuiteAdminController() *ProductSuiteAdminController {
return &ProductSuiteAdminController{DB: config.DB} return &ProductSuiteAdminController{DB: config.DB}
} }
// @Summary 获取产品套件列表
// @Description 查询产品套件列表,含套件下的库存明细
// @Tags 产品套件管理
// @Produce json
// @Param keyword query string false "关键词(代码/名称/备注模糊搜索)"
// @Param projectTypeCode query string false "项目类型代码筛选"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/product-suites [get]
func (pc *ProductSuiteAdminController) List(c *gin.Context) { func (pc *ProductSuiteAdminController) List(c *gin.Context) {
var suites []models.ProductSuite var suites []models.ProductSuite
query := pc.DB.Model(&models.ProductSuite{}).Order("updated_at DESC, id DESC") query := pc.DB.Model(&models.ProductSuite{}).Order("updated_at DESC, id DESC")
@@ -69,6 +78,16 @@ func (pc *ProductSuiteAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", result) writeSuccess(c, http.StatusOK, "query success", result)
} }
// @Summary 创建产品套件
// @Description 创建新的产品套件,可选关联库存记录
// @Tags 产品套件管理
// @Accept json
// @Produce json
// @Param suite body productSuitePayload true "套件信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/product-suites [post]
func (pc *ProductSuiteAdminController) Create(c *gin.Context) { func (pc *ProductSuiteAdminController) Create(c *gin.Context) {
var payload productSuitePayload var payload productSuitePayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -107,6 +126,18 @@ func (pc *ProductSuiteAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", record) writeSuccess(c, http.StatusCreated, "create success", record)
} }
// @Summary 更新产品套件
// @Description 更新指定产品套件的信息和关联库存
// @Tags 产品套件管理
// @Accept json
// @Produce json
// @Param id path int true "套件ID"
// @Param suite body productSuitePayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "套件不存在"
// @Router /admin/product-suites/{id} [put]
func (pc *ProductSuiteAdminController) Update(c *gin.Context) { func (pc *ProductSuiteAdminController) Update(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -149,6 +180,15 @@ func (pc *ProductSuiteAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", record) writeSuccess(c, http.StatusOK, "update success", record)
} }
// @Summary 删除产品套件
// @Description 删除指定产品套件,自动解除关联库存的绑定
// @Tags 产品套件管理
// @Produce json
// @Param id path int true "套件ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "套件不存在"
// @Router /admin/product-suites/{id} [delete]
func (pc *ProductSuiteAdminController) Delete(c *gin.Context) { func (pc *ProductSuiteAdminController) Delete(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -31,6 +31,14 @@ func NewProjectProductTemplateAdminController() *ProjectProductTemplateAdminCont
return &ProjectProductTemplateAdminController{DB: config.DB} return &ProjectProductTemplateAdminController{DB: config.DB}
} }
// @Summary 获取项目产品模板列表
// @Description 查询项目产品模板列表,含项目类型和产品名称
// @Tags 项目产品模板管理
// @Produce json
// @Param projectTypeCode query string false "项目类型代码筛选"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/project-product-templates [get]
func (pc *ProjectProductTemplateAdminController) List(c *gin.Context) { func (pc *ProjectProductTemplateAdminController) List(c *gin.Context) {
var items []models.ProjectProductTemplate var items []models.ProjectProductTemplate
query := pc.DB.Model(&models.ProjectProductTemplate{}).Order("project_type_code ASC, sort ASC, id ASC") query := pc.DB.Model(&models.ProjectProductTemplate{}).Order("project_type_code ASC, sort ASC, id ASC")
+42
View File
@@ -29,6 +29,16 @@ func NewProjectTypeAdminController() *ProjectTypeAdminController {
return &ProjectTypeAdminController{DB: config.DB} return &ProjectTypeAdminController{DB: config.DB}
} }
// @Summary 获取项目类型列表
// @Description 查询项目类型列表,支持按关键词/是否支持网关/是否启用筛选
// @Tags 项目类型管理
// @Produce json
// @Param keyword query string false "关键词(代码/名称/描述模糊搜索)"
// @Param supportsGateway query bool false "是否支持网关"
// @Param isActive query bool false "是否启用"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/project-types [get]
func (pc *ProjectTypeAdminController) List(c *gin.Context) { func (pc *ProjectTypeAdminController) List(c *gin.Context) {
var items []models.ProjectType var items []models.ProjectType
query := pc.DB.Model(&models.ProjectType{}).Order("sort ASC, id ASC") query := pc.DB.Model(&models.ProjectType{}).Order("sort ASC, id ASC")
@@ -61,6 +71,16 @@ func (pc *ProjectTypeAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", items) writeSuccess(c, http.StatusOK, "query success", items)
} }
// @Summary 创建项目类型
// @Description 创建新的项目类型
// @Tags 项目类型管理
// @Accept json
// @Produce json
// @Param projectType body projectTypePayload true "项目类型信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/project-types [post]
func (pc *ProjectTypeAdminController) Create(c *gin.Context) { func (pc *ProjectTypeAdminController) Create(c *gin.Context) {
var payload projectTypePayload var payload projectTypePayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -87,6 +107,18 @@ func (pc *ProjectTypeAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", record) writeSuccess(c, http.StatusCreated, "create success", record)
} }
// @Summary 更新项目类型
// @Description 更新指定项目类型的信息
// @Tags 项目类型管理
// @Accept json
// @Produce json
// @Param id path int true "项目类型ID"
// @Param projectType body projectTypePayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "项目类型不存在"
// @Router /admin/project-types/{id} [put]
func (pc *ProjectTypeAdminController) Update(c *gin.Context) { func (pc *ProjectTypeAdminController) Update(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
@@ -118,6 +150,16 @@ func (pc *ProjectTypeAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", record) writeSuccess(c, http.StatusOK, "update success", record)
} }
// @Summary 删除项目类型
// @Description 删除指定项目类型(被网关引用的无法删除)
// @Tags 项目类型管理
// @Produce json
// @Param id path int true "项目类型ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "项目类型不存在"
// @Failure 409 {object} SwagAPIResponse "已被网关引用无法删除"
// @Router /admin/project-types/{id} [delete]
func (pc *ProjectTypeAdminController) Delete(c *gin.Context) { func (pc *ProjectTypeAdminController) Delete(c *gin.Context) {
record, err := pc.findByID(c.Param("id")) record, err := pc.findByID(c.Param("id"))
if err != nil { if err != nil {
+38
View File
@@ -15,3 +15,41 @@ func writeSuccess(c *gin.Context, httpStatus int, msg string, data interface{})
func writeError(c *gin.Context, httpStatus int, msg string) { func writeError(c *gin.Context, httpStatus int, msg string) {
c.JSON(httpStatus, APIResponse{Data: nil, Msg: msg, Code: httpStatus}) c.JSON(httpStatus, APIResponse{Data: nil, Msg: msg, Code: httpStatus})
} }
// Swagger response model types
// SwagAPIResponse 通用API响应
type SwagAPIResponse struct {
Data interface{} `json:"data"` // 响应数据
Msg string `json:"msg"` // 响应消息
Code int `json:"code"` // HTTP状态码
}
// SwagPagination 分页信息
type SwagPagination struct {
CurrentPage int `json:"currentPage"` // 当前页码
PageSize int `json:"pageSize"` // 每页数量
TotalList int64 `json:"totalList"` // 总记录数
TotalPage int `json:"totalPage"` // 总页数
}
// SwagPaginationData 分页响应数据
type SwagPaginationData struct {
List interface{} `json:"list"`
Pagination SwagPagination `json:"pagination"`
}
// SwagLoginRequest 登录请求
type SwagLoginRequest struct {
Username string `json:"username"` // 用户名
Password string `json:"password"` // 密码
}
// SwagRegisterRequest 注册请求
type SwagRegisterRequest struct {
Username string `json:"username"` // 用户名
Password string `json:"password"` // 密码
Role string `json:"role"` // 角色
FlavorType string `json:"flavorType"` // 类型
RegionIDs []uint32 `json:"regionIds"` // 区域ID列表
}
+52
View File
@@ -34,6 +34,18 @@ type analysisRecordListParams struct {
// --- 查询接口 --- // --- 查询接口 ---
// @Summary 获取AI分析记录列表
// @Description 分页查询AI分析记录支持按区域和时间范围筛选
// @Tags 统计管理
// @Produce json
// @Param pageNum query int false "页码(默认1)"
// @Param pageSize query int false "每页数量(默认10,最大100)"
// @Param regionId query int false "区域ID"
// @Param startTime query int false "开始时间(毫秒时间戳)"
// @Param endTime query int false "结束时间(毫秒时间戳)"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/statistics/ai-analysis-records [get]
func (sc *StatisticsController) ListAIAnalysisRecords(c *gin.Context) { func (sc *StatisticsController) ListAIAnalysisRecords(c *gin.Context) {
var params analysisRecordListParams var params analysisRecordListParams
if err := c.ShouldBindQuery(&params); err != nil { if err := c.ShouldBindQuery(&params); err != nil {
@@ -84,6 +96,15 @@ func (sc *StatisticsController) ListAIAnalysisRecords(c *gin.Context) {
// --- 删除接口 --- // --- 删除接口 ---
// @Summary 删除AI分析记录
// @Description 删除指定的AI分析记录
// @Tags 统计管理
// @Produce json
// @Param id path int true "记录ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 404 {object} SwagAPIResponse "记录不存在"
// @Router /admin/statistics/ai-analysis-records/{id} [delete]
func (sc *StatisticsController) DeleteAIAnalysisRecord(c *gin.Context) { func (sc *StatisticsController) DeleteAIAnalysisRecord(c *gin.Context) {
id := strings.TrimSpace(c.Param("id")) id := strings.TrimSpace(c.Param("id"))
if id == "" { if id == "" {
@@ -137,6 +158,16 @@ type regionStatisticsItem struct {
LastUsedAt *time.Time `json:"lastUsedAt"` LastUsedAt *time.Time `json:"lastUsedAt"`
} }
// @Summary AI分析区域统计
// @Description 按区域统计AI分析的使用情况包括调用次数、Token消耗、费用等
// @Tags 统计管理
// @Produce json
// @Param regionId query int false "区域ID"
// @Param startTime query int false "开始时间(毫秒时间戳)"
// @Param endTime query int false "结束时间(毫秒时间戳)"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/statistics/ai-analysis [get]
func (sc *StatisticsController) StatisticsByRegion(c *gin.Context) { func (sc *StatisticsController) StatisticsByRegion(c *gin.Context) {
regionIDStr := c.Query("regionId") regionIDStr := c.Query("regionId")
startTimeStr := c.Query("startTime") startTimeStr := c.Query("startTime")
@@ -395,6 +426,17 @@ type trainingSessionRegionStatisticsItem struct {
LastPublishedAt *time.Time `json:"lastPublishedAt"` LastPublishedAt *time.Time `json:"lastPublishedAt"`
} }
// @Summary 训练会话区域统计
// @Description 按区域统计MQTT训练会话情况包括开始、结束、完成、进行中的会话数
// @Tags 统计管理
// @Produce json
// @Param regionId query int false "区域ID"
// @Param flavorType query string false "类型筛选"
// @Param startTime query int false "开始时间(毫秒时间戳)"
// @Param endTime query int false "结束时间(毫秒时间戳)"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/statistics/mqtt-training-sessions [get]
func (sc *StatisticsController) TrainingSessionStatisticsByRegion(c *gin.Context) { func (sc *StatisticsController) TrainingSessionStatisticsByRegion(c *gin.Context) {
regionIDStr := c.Query("regionId") regionIDStr := c.Query("regionId")
flavorType := strings.TrimSpace(c.Query("flavorType")) flavorType := strings.TrimSpace(c.Query("flavorType"))
@@ -624,6 +666,16 @@ func (sc *StatisticsController) TrainingSessionStatisticsByRegion(c *gin.Context
}) })
} }
// @Summary AI分析时间线统计
// @Description 按日期统计AI分析的使用情况趋势含总体和分区域数据
// @Tags 统计管理
// @Produce json
// @Param regionId query int false "区域ID"
// @Param startTime query int false "开始时间(毫秒时间戳)"
// @Param endTime query int false "结束时间(毫秒时间戳)"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/statistics/ai-analysis-timeline [get]
func (sc *StatisticsController) TimelineStatistics(c *gin.Context) { func (sc *StatisticsController) TimelineStatistics(c *gin.Context) {
regionIDStr := c.Query("regionId") regionIDStr := c.Query("regionId")
startTimeStr := c.Query("startTime") startTimeStr := c.Query("startTime")
+45 -1
View File
@@ -24,7 +24,17 @@ func NewStepTrainingController() *StepTrainingController {
return &StepTrainingController{DB: config.DB} return &StepTrainingController{DB: config.DB}
} }
// 接收训练记录 // @Summary 创建踏步训练记录
// @Description 接收并保存踏步训练记录,包含心率和步频数据,异步计算回归结果
// @Tags 踏步训练
// @Accept json
// @Produce json
// @Param record body SwagAPIResponse true "踏步训练记录"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "保存成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Router /step [post]
func (tc *StepTrainingController) CreateTrainingRecord(c *gin.Context) { func (tc *StepTrainingController) CreateTrainingRecord(c *gin.Context) {
var record models.StepTrainRecord var record models.StepTrainRecord
@@ -123,6 +133,17 @@ func (tc *StepTrainingController) CreateTrainingRecord(c *gin.Context) {
}) })
} }
// @Summary 获取踏步训练记录列表
// @Description 分页获取当前用户的踏步训练记录,按开始时间倒序
// @Tags 踏步训练
// @Produce json
// @Param pageNum query int false "页码(默认1)"
// @Param pageSize query int false "每页数量(默认10,最大100)"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Router /step/train-records [get]
func (tc *StepTrainingController) GetTrainingRecords(c *gin.Context) { func (tc *StepTrainingController) GetTrainingRecords(c *gin.Context) {
// 定义分页参数结构 // 定义分页参数结构
type PaginationParams struct { type PaginationParams struct {
@@ -191,6 +212,18 @@ func (tc *StepTrainingController) GetTrainingRecords(c *gin.Context) {
}, },
}) })
} }
// @Summary 获取踏步训练详情
// @Description 根据训练ID获取踏步训练的详细信息包含心率和步频数据
// @Tags 踏步训练
// @Produce json
// @Param trainId path int true "训练ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Failure 404 {object} SwagAPIResponse "训练记录不存在"
// @Router /step/train-data/{trainId} [get]
func (tc *StepTrainingController) GetTrainingRecordByTrainId(c *gin.Context) { func (tc *StepTrainingController) GetTrainingRecordByTrainId(c *gin.Context) {
// 从URL路径参数获取trainId // 从URL路径参数获取trainId
trainId := c.Param("trainId") trainId := c.Param("trainId")
@@ -748,6 +781,17 @@ func (tc *StepTrainingController) GetRegressionResult(c *gin.Context) {
}) })
} }
// @Summary 获取训练排名
// @Description 根据训练ID和回归类型获取训练排名
// @Tags 踏步训练
// @Produce json
// @Param trainId path int true "训练ID"
// @Param type query int true "回归类型: 1=线性回归 | 3=二次回归"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 401 {object} SwagAPIResponse "未认证"
// @Router /step/train-rank/{trainId} [get]
func (tc *StepTrainingController) GetTrainingRank(c *gin.Context) { func (tc *StepTrainingController) GetTrainingRank(c *gin.Context) {
// 参数解析 // 参数解析
trainIdStr := c.Param("trainId") trainIdStr := c.Param("trainId")
+29
View File
@@ -29,6 +29,13 @@ func NewSystemDebugController() *SystemDebugController {
return &SystemDebugController{} return &SystemDebugController{}
} }
// @Summary 获取MQTT调试状态
// @Description 获取MQTT调试服务的当前运行状态
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/system-debug/mqtt/status [get]
func (sc *SystemDebugController) MqttStatus(c *gin.Context) { func (sc *SystemDebugController) MqttStatus(c *gin.Context) {
service := mqtt.GetDebugService() service := mqtt.GetDebugService()
if service == nil { if service == nil {
@@ -38,6 +45,15 @@ func (sc *SystemDebugController) MqttStatus(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", service.Status()) writeSuccess(c, http.StatusOK, "query success", service.Status())
} }
// @Summary 启动MQTT调试
// @Description 启动MQTT调试服务
// @Tags 系统调试
// @Accept json
// @Produce json
// @Param persist body mqttDebugStartRequest false "是否持久化到数据库"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "启动成功"
// @Router /admin/system-debug/mqtt/start [post]
func (sc *SystemDebugController) StartMqtt(c *gin.Context) { func (sc *SystemDebugController) StartMqtt(c *gin.Context) {
service := mqtt.GetDebugService() service := mqtt.GetDebugService()
if service == nil { if service == nil {
@@ -56,6 +72,13 @@ func (sc *SystemDebugController) StartMqtt(c *gin.Context) {
writeSuccess(c, http.StatusOK, "start success", service.Status()) writeSuccess(c, http.StatusOK, "start success", service.Status())
} }
// @Summary 停止MQTT调试
// @Description 停止MQTT调试服务
// @Tags 系统调试
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "停止成功"
// @Router /admin/system-debug/mqtt/stop [post]
func (sc *SystemDebugController) StopMqtt(c *gin.Context) { func (sc *SystemDebugController) StopMqtt(c *gin.Context) {
service := mqtt.GetDebugService() service := mqtt.GetDebugService()
if service == nil { if service == nil {
@@ -66,6 +89,12 @@ func (sc *SystemDebugController) StopMqtt(c *gin.Context) {
writeSuccess(c, http.StatusOK, "stop success", service.Status()) writeSuccess(c, http.StatusOK, "stop success", service.Status())
} }
// @Summary MQTT WebSocket连接
// @Description 通过WebSocket实时监听MQTT消息需要SuperAdmin权限
// @Tags 系统调试
// @Param token query string true "JWT Token"
// @Success 101 "切换为WebSocket协议"
// @Router /admin/system-debug/mqtt/ws [get]
func (sc *SystemDebugController) MqttWebSocket(c *gin.Context) { func (sc *SystemDebugController) MqttWebSocket(c *gin.Context) {
service := mqtt.GetDebugService() service := mqtt.GetDebugService()
if service == nil { if service == nil {
+31 -2
View File
@@ -41,7 +41,15 @@ func NewTrainingController() *TrainingController {
return &TrainingController{DB: config.DB} return &TrainingController{DB: config.DB}
} }
// 接收训练记录 // @Summary 创建训练记录
// @Description 接收并保存训练记录及心率数据支持重复上传按train_id去重更新
// @Tags 训练管理
// @Accept json
// @Produce json
// @Param record body SwagAPIResponse true "训练记录数据"
// @Success 201 {object} SwagAPIResponse "保存成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /train-records [post]
func (tc *TrainingController) CreateTrainingRecord(c *gin.Context) { func (tc *TrainingController) CreateTrainingRecord(c *gin.Context) {
var record models.TrainRecord var record models.TrainRecord
@@ -121,6 +129,15 @@ type trainingSessionRequest struct {
AppName string `json:"appName"` AppName string `json:"appName"`
} }
// @Summary 上传训练会话
// @Description 上传训练开始/结束会话用于MQTT训练会话追踪
// @Tags 训练管理
// @Accept json
// @Produce json
// @Param session body trainingSessionRequest true "训练会话数据"
// @Success 200 {object} SwagAPIResponse "操作成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /train-records/session [post]
func (tc *TrainingController) UploadTrainingSession(c *gin.Context) { func (tc *TrainingController) UploadTrainingSession(c *gin.Context) {
var req trainingSessionRequest var req trainingSessionRequest
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
@@ -225,6 +242,12 @@ type cloudLessonPlanItem struct {
UploaderName string `json:"uploaderName"` UploaderName string `json:"uploaderName"`
} }
// @Summary 获取云端教案列表
// @Description 获取所有云端教案文件列表
// @Tags 训练管理
// @Produce json
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /train-records/cloud-files [get]
func (tc *TrainingController) ListCloudLessonPlans(c *gin.Context) { func (tc *TrainingController) ListCloudLessonPlans(c *gin.Context) {
var records []models.AppFile var records []models.AppFile
if err := tc.DB.Where("file_type = ?", models.AppFileTypeLessonPlan).Order("created_at DESC").Find(&records).Error; err != nil { if err := tc.DB.Where("file_type = ?", models.AppFileTypeLessonPlan).Order("created_at DESC").Find(&records).Error; err != nil {
@@ -266,7 +289,13 @@ type CurvePoint struct {
Y float64 `json:"y"` // Y坐标 Y float64 `json:"y"` // Y坐标
} }
// analysis_handler.go // @Summary 心率曲线分析
// @Description 对历史心率数据进行统计分析和正态分布曲线拟合
// @Tags 训练管理
// @Produce json
// @Success 200 {object} SwagAPIResponse "分析成功"
// @Failure 400 {object} SwagAPIResponse "数据量不足"
// @Router /train-records/analysis [get]
func (tc *TrainingController) HandleCurveAnalysis(c *gin.Context) { func (tc *TrainingController) HandleCurveAnalysis(c *gin.Context) {
// 获取数据库连接(根据实际项目配置调整) // 获取数据库连接(根据实际项目配置调整)
+42
View File
@@ -49,6 +49,16 @@ func NewUserAdminController() *UserAdminController {
return &UserAdminController{DB: config.DB} return &UserAdminController{DB: config.DB}
} }
// @Summary 获取用户列表
// @Description 查询系统用户列表,支持按关键词/角色/类型筛选
// @Tags 用户管理
// @Produce json
// @Param keyword query string false "关键词(用户名/邮箱/手机号模糊搜索)"
// @Param role query string false "角色筛选"
// @Param flavorType query string false "类型筛选"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "查询成功"
// @Router /admin/users [get]
func (uc *UserAdminController) List(c *gin.Context) { func (uc *UserAdminController) List(c *gin.Context) {
var users []models.User var users []models.User
query := uc.DB.Preload("Regions").Order("id ASC") query := uc.DB.Preload("Regions").Order("id ASC")
@@ -76,6 +86,16 @@ func (uc *UserAdminController) List(c *gin.Context) {
writeSuccess(c, http.StatusOK, "query success", items) writeSuccess(c, http.StatusOK, "query success", items)
} }
// @Summary 创建用户
// @Description 创建新的系统用户
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param user body userAdminPayload true "用户信息"
// @Security BearerAuth
// @Success 201 {object} SwagAPIResponse "创建成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Router /admin/users [post]
func (uc *UserAdminController) Create(c *gin.Context) { func (uc *UserAdminController) Create(c *gin.Context) {
var payload userAdminPayload var payload userAdminPayload
if err := c.ShouldBindJSON(&payload); err != nil { if err := c.ShouldBindJSON(&payload); err != nil {
@@ -127,6 +147,18 @@ func (uc *UserAdminController) Create(c *gin.Context) {
writeSuccess(c, http.StatusCreated, "create success", items[0]) writeSuccess(c, http.StatusCreated, "create success", items[0])
} }
// @Summary 更新用户信息
// @Description 更新指定用户的详细信息支持重置密码和吊销Token
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param id path int true "用户ID"
// @Param user body userAdminPayload true "更新信息"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "更新成功"
// @Failure 400 {object} SwagAPIResponse "请求参数错误"
// @Failure 404 {object} SwagAPIResponse "用户不存在"
// @Router /admin/users/{id} [put]
func (uc *UserAdminController) Update(c *gin.Context) { func (uc *UserAdminController) Update(c *gin.Context) {
user, err := uc.findUserByID(c.Param("id")) user, err := uc.findUserByID(c.Param("id"))
if err != nil { if err != nil {
@@ -212,6 +244,16 @@ func (uc *UserAdminController) Update(c *gin.Context) {
writeSuccess(c, http.StatusOK, "update success", items[0]) writeSuccess(c, http.StatusOK, "update success", items[0])
} }
// @Summary 删除用户
// @Description 删除指定用户不能删除admin账号和当前登录用户
// @Tags 用户管理
// @Produce json
// @Param id path int true "用户ID"
// @Security BearerAuth
// @Success 200 {object} SwagAPIResponse "删除成功"
// @Failure 400 {object} SwagAPIResponse "无法删除受保护账号"
// @Failure 404 {object} SwagAPIResponse "用户不存在"
// @Router /admin/users/{id} [delete]
func (uc *UserAdminController) Delete(c *gin.Context) { func (uc *UserAdminController) Delete(c *gin.Context) {
user, err := uc.findUserByID(c.Param("id")) user, err := uc.findUserByID(c.Param("id"))
if err != nil { if err != nil {
+3273
View File
File diff suppressed because it is too large Load Diff
+3251
View File
File diff suppressed because it is too large Load Diff
+2078
View File
File diff suppressed because it is too large Load Diff
+17 -3
View File
@@ -15,6 +15,9 @@ require (
) )
require ( require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
@@ -24,6 +27,10 @@ require (
github.com/fumiama/imgsz v0.0.2 // indirect github.com/fumiama/imgsz v0.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-pdf/fpdf v0.9.0 // indirect github.com/go-pdf/fpdf v0.9.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -37,9 +44,11 @@ require (
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
@@ -51,16 +60,21 @@ require (
github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/gin-swagger v1.6.1 // indirect
github.com/swaggo/swag v1.8.12 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.32.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.33.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.12.0 // indirect golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.29.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/tools v0.26.0 // indirect
google.golang.org/protobuf v1.36.1 // indirect google.golang.org/protobuf v1.36.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
+77
View File
@@ -1,3 +1,9 @@
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
@@ -6,6 +12,7 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -25,6 +32,16 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-pdf/fpdf v0.9.0 h1:PPvSaUuo1iMi9KkaAn90NuKi+P4gwMedWPHhj8YlJQw= github.com/go-pdf/fpdf v0.9.0 h1:PPvSaUuo1iMi9KkaAn90NuKi+P4gwMedWPHhj8YlJQw=
github.com/go-pdf/fpdf v0.9.0/go.mod h1:oO8N111TkmKb9D7VvWGLvLJlaZUQVPM+6V42pp3iV4Y= github.com/go-pdf/fpdf v0.9.0/go.mod h1:oO8N111TkmKb9D7VvWGLvLJlaZUQVPM+6V42pp3iV4Y=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@@ -58,18 +75,27 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -77,6 +103,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -103,6 +130,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -111,10 +139,17 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs7cY=
github.com/swaggo/gin-swagger v1.6.1/go.mod h1:LQ+hJStHakCWRiK/YNYtJOu4mR2FP+pxLnILT/qNiTw=
github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
@@ -122,26 +157,68 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
+8
View File
@@ -1,3 +1,11 @@
// @title 智能心率采集分析平台 API
// @version 1.0
// @description 智能心率采集分析平台后端服务,基于 Gin 框架提供心率采集、AI 分析、教案管理、设备管理等功能
// @host localhost:8081
// @BasePath /api/v1
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
package main package main
import ( import (
+6
View File
@@ -2,7 +2,10 @@ package routes
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"hr_receiver/controllers" "hr_receiver/controllers"
_ "hr_receiver/docs"
"hr_receiver/middleware" "hr_receiver/middleware"
"net/http" "net/http"
) )
@@ -46,6 +49,9 @@ func SetupRouter() *gin.Engine {
r.GET("/auth/token", deviceTokenHandler) r.GET("/auth/token", deviceTokenHandler)
// Swagger API文档
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
v1 := r.Group("/api/v1") v1 := r.Group("/api/v1")
{ {
records := v1.Group("/train-records") //.Use(middleware.AuthMiddleware()) records := v1.Group("/train-records") //.Use(middleware.AuthMiddleware())