feat: swag.
This commit is contained in:
@@ -283,6 +283,23 @@ func callAIForAnalysis(prompt string) (*aiAnalysisResult, error) {
|
||||
}, 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) {
|
||||
form, err := c.MultipartForm()
|
||||
if err != nil {
|
||||
|
||||
+54
-11
@@ -36,9 +36,17 @@ func NewGatewayAdminController() *GatewayAdminController {
|
||||
return &GatewayAdminController{DB: config.DB}
|
||||
}
|
||||
|
||||
// List 获取网关列表
|
||||
// GET /api/v1/gateways?keyword=&isSold=&projectType=®ionId=
|
||||
// 超级管理员可查询全部;操作员/区域管理员仅能查询所属 regionIDs 的网关
|
||||
// @Summary 获取网关列表
|
||||
// @Description 查询网关列表,支持关键词/售出状态/项目类型/区域筛选。超级管理员可查全部,操作员只能查所属区域
|
||||
// @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) {
|
||||
var items []models.Gateway
|
||||
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)
|
||||
}
|
||||
|
||||
// GetByMACForUser 按 MAC 查询网关信息
|
||||
// GET /api/v1/gateways/by-mac?mac=
|
||||
// @Summary 按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) {
|
||||
macInput := strings.ToUpper(strings.TrimSpace(c.Query("mac")))
|
||||
if macInput == "" {
|
||||
@@ -132,8 +148,17 @@ func (gc *GatewayAdminController) GetByMACForUser(c *gin.Context) {
|
||||
writeSuccess(c, http.StatusOK, "查询成功", item)
|
||||
}
|
||||
|
||||
// Create 创建新网关
|
||||
// POST /api/gateways
|
||||
// @Summary 创建网关
|
||||
// @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) {
|
||||
var payload gatewayPayload
|
||||
if err := c.ShouldBindJSON(&payload); err != nil {
|
||||
@@ -188,8 +213,18 @@ func (gc *GatewayAdminController) Create(c *gin.Context) {
|
||||
writeSuccess(c, http.StatusCreated, "创建成功", record)
|
||||
}
|
||||
|
||||
// Update 更新网关信息
|
||||
// PUT /api/gateways/:id
|
||||
// @Summary 更新网关信息
|
||||
// @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) {
|
||||
record, err := gc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -246,8 +281,16 @@ func (gc *GatewayAdminController) Update(c *gin.Context) {
|
||||
writeSuccess(c, http.StatusOK, "更新成功", record)
|
||||
}
|
||||
|
||||
// Delete 删除网关
|
||||
// DELETE /api/gateways/:id
|
||||
// @Summary 删除网关
|
||||
// @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) {
|
||||
record, err := gc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -26,6 +26,14 @@ func NewKindergartenAdminController() *KindergartenAdminController {
|
||||
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) {
|
||||
var items []models.Kindergarten
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload kindergartenPayload
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
record, err := kc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -93,6 +123,16 @@ func (kc *KindergartenAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
record, err := kc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -53,6 +53,18 @@ func NewLessonPlanController() *LessonPlanController {
|
||||
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) {
|
||||
fileHeader, err := c.FormFile(lessonPlanFieldName)
|
||||
if err != nil {
|
||||
@@ -152,6 +164,14 @@ func (lc *LessonPlanController) Upload(c *gin.Context) {
|
||||
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) {
|
||||
userID, _, ok := currentUser(c)
|
||||
if !ok {
|
||||
@@ -173,6 +193,22 @@ func (lc *LessonPlanController) List(c *gin.Context) {
|
||||
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) {
|
||||
userID, _, ok := currentUser(c)
|
||||
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) {
|
||||
record, err := lc.findLessonPlan(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -344,6 +391,17 @@ func (lc *LessonPlanController) Download(c *gin.Context) {
|
||||
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) {
|
||||
record, err := lc.findLessonPlan(c.Param("id"))
|
||||
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) {
|
||||
shareCode := strings.TrimSpace(c.Param("code"))
|
||||
if len(shareCode) != shareCodeDigits {
|
||||
@@ -439,6 +506,17 @@ func (lc *LessonPlanController) DownloadByShareCode(c *gin.Context) {
|
||||
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) {
|
||||
record, err := lc.findLessonPlan(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
+21
-2
@@ -29,7 +29,16 @@ type AuthResponse struct {
|
||||
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) {
|
||||
var req RegisterRequest
|
||||
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) {
|
||||
var req LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -32,6 +32,16 @@ func NewProductDefinitionAdminController() *ProductDefinitionAdminController {
|
||||
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) {
|
||||
var items []models.ProductDefinition
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload productDefinitionPayload
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -120,6 +152,16 @@ func (pc *ProductDefinitionAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -40,6 +40,20 @@ func NewProductInventoryAdminController() *ProductInventoryAdminController {
|
||||
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) {
|
||||
var items []models.ProductInventory
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload productInventoryPayload
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -167,6 +203,16 @@ func (pc *ProductInventoryAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -33,6 +33,16 @@ func NewProductPrototypeAdminController() *ProductPrototypeAdminController {
|
||||
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) {
|
||||
var items []models.ProductPrototype
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload productPrototypePayload
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -122,6 +154,15 @@ func (pc *ProductPrototypeAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -36,6 +36,15 @@ func NewProductSuiteAdminController() *ProductSuiteAdminController {
|
||||
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) {
|
||||
var suites []models.ProductSuite
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload productSuitePayload
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -149,6 +180,15 @@ func (pc *ProductSuiteAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -31,6 +31,14 @@ func NewProjectProductTemplateAdminController() *ProjectProductTemplateAdminCont
|
||||
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) {
|
||||
var items []models.ProjectProductTemplate
|
||||
query := pc.DB.Model(&models.ProjectProductTemplate{}).Order("project_type_code ASC, sort ASC, id ASC")
|
||||
|
||||
@@ -29,6 +29,16 @@ func NewProjectTypeAdminController() *ProjectTypeAdminController {
|
||||
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) {
|
||||
var items []models.ProjectType
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload projectTypePayload
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -118,6 +150,16 @@ func (pc *ProjectTypeAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
record, err := pc.findByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
@@ -15,3 +15,41 @@ func writeSuccess(c *gin.Context, httpStatus int, msg string, data interface{})
|
||||
func writeError(c *gin.Context, httpStatus int, msg string) {
|
||||
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列表
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
var params analysisRecordListParams
|
||||
if err := c.ShouldBindQuery(¶ms); 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) {
|
||||
id := strings.TrimSpace(c.Param("id"))
|
||||
if id == "" {
|
||||
@@ -137,6 +158,16 @@ type regionStatisticsItem struct {
|
||||
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) {
|
||||
regionIDStr := c.Query("regionId")
|
||||
startTimeStr := c.Query("startTime")
|
||||
@@ -395,6 +426,17 @@ type trainingSessionRegionStatisticsItem struct {
|
||||
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) {
|
||||
regionIDStr := c.Query("regionId")
|
||||
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) {
|
||||
regionIDStr := c.Query("regionId")
|
||||
startTimeStr := c.Query("startTime")
|
||||
|
||||
@@ -24,7 +24,17 @@ func NewStepTrainingController() *StepTrainingController {
|
||||
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) {
|
||||
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) {
|
||||
// 定义分页参数结构
|
||||
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) {
|
||||
// 从URL路径参数获取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) {
|
||||
// 参数解析
|
||||
trainIdStr := c.Param("trainId")
|
||||
|
||||
@@ -29,6 +29,13 @@ func NewSystemDebugController() *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) {
|
||||
service := mqtt.GetDebugService()
|
||||
if service == nil {
|
||||
@@ -38,6 +45,15 @@ func (sc *SystemDebugController) MqttStatus(c *gin.Context) {
|
||||
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) {
|
||||
service := mqtt.GetDebugService()
|
||||
if service == nil {
|
||||
@@ -56,6 +72,13 @@ func (sc *SystemDebugController) StartMqtt(c *gin.Context) {
|
||||
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) {
|
||||
service := mqtt.GetDebugService()
|
||||
if service == nil {
|
||||
@@ -66,6 +89,12 @@ func (sc *SystemDebugController) StopMqtt(c *gin.Context) {
|
||||
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) {
|
||||
service := mqtt.GetDebugService()
|
||||
if service == nil {
|
||||
|
||||
+31
-2
@@ -41,7 +41,15 @@ func NewTrainingController() *TrainingController {
|
||||
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) {
|
||||
var record models.TrainRecord
|
||||
|
||||
@@ -121,6 +129,15 @@ type trainingSessionRequest struct {
|
||||
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) {
|
||||
var req trainingSessionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -225,6 +242,12 @@ type cloudLessonPlanItem struct {
|
||||
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) {
|
||||
var records []models.AppFile
|
||||
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坐标
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 获取数据库连接(根据实际项目配置调整)
|
||||
|
||||
|
||||
@@ -49,6 +49,16 @@ func NewUserAdminController() *UserAdminController {
|
||||
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) {
|
||||
var users []models.User
|
||||
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)
|
||||
}
|
||||
|
||||
// @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) {
|
||||
var payload userAdminPayload
|
||||
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])
|
||||
}
|
||||
|
||||
// @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) {
|
||||
user, err := uc.findUserByID(c.Param("id"))
|
||||
if err != nil {
|
||||
@@ -212,6 +244,16 @@ func (uc *UserAdminController) Update(c *gin.Context) {
|
||||
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) {
|
||||
user, err := uc.findUserByID(c.Param("id"))
|
||||
if err != nil {
|
||||
|
||||
+3273
File diff suppressed because it is too large
Load Diff
+3251
File diff suppressed because it is too large
Load Diff
+2078
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,9 @@ 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/loader v0.1.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
@@ -24,6 +27,10 @@ require (
|
||||
github.com/fumiama/imgsz v0.0.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // 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-playground/locales v0.14.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/jinzhu/inflection v1.0.0 // 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/klauspost/cpuid/v2 v2.2.7 // 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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // 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/pflag v1.0.6 // 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/ugorji/go/codec v1.2.12 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.38.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/tools v0.26.0 // 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
|
||||
)
|
||||
|
||||
@@ -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/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
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/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
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/go.mod h1:oO8N111TkmKb9D7VvWGLvLJlaZUQVPM+6V42pp3iV4Y=
|
||||
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/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
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/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.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
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/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/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/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/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/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
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/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
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/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
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.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
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/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/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/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
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.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
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/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/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/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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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.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/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/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/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 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/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-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
|
||||
|
||||
@@ -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
|
||||
|
||||
import (
|
||||
|
||||
@@ -2,7 +2,10 @@ package routes
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"hr_receiver/controllers"
|
||||
_ "hr_receiver/docs"
|
||||
"hr_receiver/middleware"
|
||||
"net/http"
|
||||
)
|
||||
@@ -46,6 +49,9 @@ func SetupRouter() *gin.Engine {
|
||||
|
||||
r.GET("/auth/token", deviceTokenHandler)
|
||||
|
||||
// Swagger API文档
|
||||
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
||||
v1 := r.Group("/api/v1")
|
||||
{
|
||||
records := v1.Group("/train-records") //.Use(middleware.AuthMiddleware())
|
||||
|
||||
Reference in New Issue
Block a user