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
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", "")
|
|
}
|
|
|