package handler import ( "errors" "net/http" "strings" "github.com/gin-gonic/gin" "xly/server/internal/model" "xly/server/internal/service" ) // HTTPHandler 负责注册 HTTP 路由。 // 控制层只做参数校验和响应包装,不承担上游调用逻辑。 type HTTPHandler struct { ai *service.AIService } // NewHTTPHandler 创建 HTTP 控制器。 func NewHTTPHandler(ai *service.AIService) *HTTPHandler { return &HTTPHandler{ai: ai} } // Register 将接口注册到 Gin 路由树。 func (h *HTTPHandler) Register(router gin.IRouter) { router.GET("/healthz", h.healthz) router.GET("/api/v1/ai/status", h.aiStatus) router.POST("/api/v1/ai/interpret", h.aiInterpret) } func (h *HTTPHandler) healthz(ctx *gin.Context) { ctx.JSON(http.StatusOK, model.APIResponse[map[string]string]{ Data: &map[string]string{ "status": "ok", }, Message: "service is healthy", }) } func (h *HTTPHandler) aiStatus(ctx *gin.Context) { status := h.ai.Status() ctx.JSON(http.StatusOK, model.APIResponse[model.AIStatusResponse]{ Data: &status, Message: "ok", }) } func (h *HTTPHandler) aiInterpret(ctx *gin.Context) { var request model.InterpretRequest if err := ctx.ShouldBindJSON(&request); err != nil { ctx.JSON(http.StatusBadRequest, model.APIResponse[model.InterpretResponse]{ Message: "请求体无效,请检查解卦上下文是否完整。", }) return } request.Question = strings.TrimSpace(request.Question) if request.Question == "" { ctx.JSON(http.StatusBadRequest, model.APIResponse[model.InterpretResponse]{ Message: "所问之事不能为空。", }) return } content, err := h.ai.Interpret(ctx.Request.Context(), request) if err != nil { statusCode := http.StatusBadGateway message := "AI 解卦失败。" switch { case errors.Is(err, service.ErrAIUnavailable): statusCode = http.StatusServiceUnavailable message = "后端 AI 服务尚未完成配置。" default: message = err.Error() } ctx.JSON(statusCode, model.APIResponse[model.InterpretResponse]{ Message: message, }) return } response := model.InterpretResponse{Content: content} ctx.JSON(http.StatusOK, model.APIResponse[model.InterpretResponse]{ Data: &response, Message: "ok", }) }