package chat import ( "errors" "net/http" "strconv" "hfb_sys/backend/pkg/response" "github.com/gin-gonic/gin" ) // CreateQrCodeHandler 创建二维码 func (h *Handler) CreateQrCodeHandler(c *gin.Context) { var req CreateQrCodeRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } adminID := c.GetUint64("admin_id") qrcode, err := h.service.repo.CreateQrCode(c.Request.Context(), adminID, req) if err != nil { response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": qrcode}) } // BatchCreateQrCodeHandler 批量创建二维码 func (h *Handler) BatchCreateQrCodeHandler(c *gin.Context) { var req BatchCreateQrCodeRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } adminID := c.GetUint64("admin_id") qrcodes, err := h.service.repo.BatchCreateQrCode(c.Request.Context(), adminID, req) if err != nil { response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": qrcodes}) } // BatchDeleteQrCodeHandler 批量删除二维码 func (h *Handler) BatchDeleteQrCodeHandler(c *gin.Context) { var req BatchDeleteQrCodeRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } deleted, err := h.service.repo.BatchDeleteQrCodes(c.Request.Context(), req.IDs) if err != nil { response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": gin.H{"deleted": deleted}}) } // ListQrCodesHandler 列表查询二维码 func (h *Handler) ListQrCodesHandler(c *gin.Context) { var req QrCodeListRequest if err := c.ShouldBindQuery(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } qrcodes, total, err := h.service.repo.ListQrCodes(c.Request.Context(), req) if err != nil { response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{ "data": PaginatedResult{ Items: qrcodes, Total: total, Page: req.Page, PageSize: req.Limit, }, }) } // GetQrCodeStatsHandler 获取二维码统计 func (h *Handler) GetQrCodeStatsHandler(c *gin.Context) { stats, err := h.service.repo.GetQrCodeStats(c.Request.Context()) if err != nil { response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": stats}) } // RecognizeQrCodeGroupNameHandler 同步调用 PaddleOCR API 识别二维码图片中的企业微信群名(保留向后兼容) func (h *Handler) RecognizeQrCodeGroupNameHandler(c *gin.Context) { file, header, err := c.Request.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "请上传二维码图片"}) return } defer file.Close() result, err := h.service.repo.RecognizeQrCodeGroupName( c.Request.Context(), header.Filename, header.Header.Get("Content-Type"), file, ) if err != nil { if errors.Is(err, ErrQrCodeOCRNotConfigured) { c.JSON(http.StatusBadRequest, gin.H{"error": "请先在系统配置中填写 PaddleOCR API Token"}) return } if errors.Is(err, ErrQrCodeOCRInvalidFile) { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的二维码图片"}) return } if errors.Is(err, ErrQrCodeOCRUnavailable) { response.RecordError(c, err) c.JSON(http.StatusBadGateway, gin.H{"error": "PaddleOCR 服务暂时不可用"}) return } response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": result}) } // SubmitOCRJobHandler 提交 OCR 任务到 PaddleOCR,立即返回任务 ID func (h *Handler) SubmitOCRJobHandler(c *gin.Context) { file, header, err := c.Request.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "请上传二维码图片"}) return } defer file.Close() jobID, err := h.service.repo.SubmitOCRJob( c.Request.Context(), header.Filename, header.Header.Get("Content-Type"), file, ) if err != nil { if errors.Is(err, ErrQrCodeOCRNotConfigured) { c.JSON(http.StatusBadRequest, gin.H{"error": "请先在系统配置中填写 PaddleOCR API Token"}) return } if errors.Is(err, ErrQrCodeOCRInvalidFile) { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的二维码图片"}) return } if errors.Is(err, ErrQrCodeOCRUnavailable) { response.RecordError(c, err) c.JSON(http.StatusBadGateway, gin.H{"error": "PaddleOCR 服务暂时不可用"}) return } if errors.Is(err, ErrQrCodeOCRRedisDisabled) { c.JSON(http.StatusServiceUnavailable, gin.H{"error": "OCR 异步模式需要 Redis"}) return } if errors.Is(err, ErrQrCodeOCRJobNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "OCR 任务不存在或已过期"}) return } response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": gin.H{"job_id": jobID}}) } // GetOCRJobResultHandler 查询异步 OCR 任务状态和结果 func (h *Handler) GetOCRJobResultHandler(c *gin.Context) { jobID := c.Param("jobId") if jobID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "缺少任务 ID"}) return } record, err := h.service.repo.PollOCRJobResult(c.Request.Context(), jobID) if err != nil { if errors.Is(err, ErrQrCodeOCRJobNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "OCR 任务不存在或已过期"}) return } response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"data": record}) } // UpdateQrCodeHandler 更新二维码 func (h *Handler) UpdateQrCodeHandler(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的ID"}) return } var req UpdateQrCodeRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.service.repo.UpdateQrCode(c.Request.Context(), id, req); err != nil { if err == ErrQrCodeNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "二维码不存在"}) return } if err == ErrQrCodeCannotReenable { c.JSON(http.StatusBadRequest, gin.H{"error": "已发放的二维码不能改回待用"}) return } response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"message": "更新成功"}) } // DeleteQrCodeHandler 删除二维码 func (h *Handler) DeleteQrCodeHandler(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的ID"}) return } if err := h.service.repo.DeleteQrCode(c.Request.Context(), id); err != nil { if err == ErrQrCodeNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "二维码不存在"}) return } response.RecordError(c, err) response.InternalServerError(c, "聊天二维码服务暂时不可用") return } c.JSON(http.StatusOK, gin.H{"message": "删除成功"}) }