healthapp
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

183 lines
5.2 KiB

package handler
import (
"strconv"
"health-ai/internal/api/middleware"
"health-ai/internal/service"
"health-ai/pkg/response"
"github.com/gin-gonic/gin"
)
type ConversationHandler struct {
convService *service.ConversationService
}
func NewConversationHandler() *ConversationHandler {
return &ConversationHandler{
convService: service.NewConversationService(),
}
}
// GetConversations 获取对话列表
// @Summary 获取对话列表
// @Tags AI对话
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Success 200 {object} response.Response{data=[]service.ConversationResponse}
// @Router /api/conversations [get]
func (h *ConversationHandler) GetConversations(c *gin.Context) {
userID := middleware.GetUserID(c)
convs, err := h.convService.GetConversations(userID)
if err != nil {
response.Error(c, 500, err.Error())
return
}
response.Success(c, convs)
}
// CreateConversation 创建新对话
// @Summary 创建新对话
// @Tags AI对话
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Param request body service.CreateConversationRequest true "对话标题(可选)"
// @Success 200 {object} response.Response{data=service.ConversationResponse}
// @Router /api/conversations [post]
func (h *ConversationHandler) CreateConversation(c *gin.Context) {
userID := middleware.GetUserID(c)
var req service.CreateConversationRequest
c.ShouldBindJSON(&req)
conv, err := h.convService.CreateConversation(userID, req.Title)
if err != nil {
response.Error(c, 500, err.Error())
return
}
response.Success(c, conv)
}
// GetConversation 获取对话详情
// @Summary 获取对话详情(含消息历史)
// @Tags AI对话
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Param id path int true "对话ID"
// @Success 200 {object} response.Response{data=service.ConversationResponse}
// @Router /api/conversations/{id} [get]
func (h *ConversationHandler) GetConversation(c *gin.Context) {
userID := middleware.GetUserID(c)
convID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
response.BadRequest(c, "无效的对话ID")
return
}
conv, err := h.convService.GetConversation(userID, uint(convID))
if err != nil {
response.Error(c, 404, err.Error())
return
}
response.Success(c, conv)
}
// DeleteConversation 删除对话
// @Summary 删除对话
// @Tags AI对话
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Param id path int true "对话ID"
// @Success 200 {object} response.Response
// @Router /api/conversations/{id} [delete]
func (h *ConversationHandler) DeleteConversation(c *gin.Context) {
userID := middleware.GetUserID(c)
convID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
response.BadRequest(c, "无效的对话ID")
return
}
if err := h.convService.DeleteConversation(userID, uint(convID)); err != nil {
response.Error(c, 400, err.Error())
return
}
response.SuccessWithMessage(c, "对话已删除", nil)
}
// SendMessage 发送消息
// @Summary 发送消息并获取AI回复
// @Tags AI对话
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Param id path int true "对话ID"
// @Param request body service.SendMessageRequest true "消息内容"
// @Success 200 {object} response.Response{data=service.MessageResponse}
// @Router /api/conversations/{id}/messages [post]
func (h *ConversationHandler) SendMessage(c *gin.Context) {
userID := middleware.GetUserID(c)
convID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
response.BadRequest(c, "无效的对话ID")
return
}
var req service.SendMessageRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请输入消息内容")
return
}
if req.Content == "" {
response.BadRequest(c, "消息内容不能为空")
return
}
reply, err := h.convService.SendMessage(c.Request.Context(), userID, uint(convID), req.Content)
if err != nil {
response.Error(c, 500, "AI回复失败: "+err.Error())
return
}
response.Success(c, reply)
}
// SendMessageStream 流式发送消息(SSE)
// @Summary 流式发送消息
// @Tags AI对话
// @Accept json
// @Produce text/event-stream
// @Param Authorization header string true "Bearer Token"
// @Param id path int true "对话ID"
// @Param request body service.SendMessageRequest true "消息内容"
// @Router /api/conversations/{id}/messages/stream [post]
func (h *ConversationHandler) SendMessageStream(c *gin.Context) {
userID := middleware.GetUserID(c)
convID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
response.BadRequest(c, "无效的对话ID")
return
}
var req service.SendMessageRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请输入消息内容")
return
}
// 设置 SSE 响应头
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
err = h.convService.SendMessageStream(c.Request.Context(), userID, uint(convID), req.Content, c.Writer)
if err != nil {
c.SSEvent("error", err.Error())
}
c.SSEvent("done", "")
}