fix(ui): 自定义工具表单 overflow-y-scroll→auto + 认证方式NONE翻译改为'无' + Captain文档爬虫/同步后端

This commit is contained in:
Rogee
2026-08-01 21:25:55 +08:00
parent 1446cfe701
commit 3a62f01942
20 changed files with 756 additions and 56 deletions
@@ -3,6 +3,7 @@ package v1
import (
"net/http"
"strconv"
"strings"
"github.com/gin-gonic/gin"
"github.com/gochat/gochat/internal/model"
@@ -24,6 +25,7 @@ func NewCaptainDocumentHandler(svc *service.CaptainDocumentService) *CaptainDocu
// Create creates a new captain document.
// POST /api/v1/accounts/:account_id/captain_assistants/:assistant_id/documents
// Supports both JSON (for URL/content input) and multipart/form-data (for PDF upload).
func (h *CaptainDocumentHandler) Create(c *gin.Context) {
accountID := parseAccountIDParam(c)
if accountID == 0 {
@@ -32,10 +34,31 @@ func (h *CaptainDocumentHandler) Create(c *gin.Context) {
}
var req service.CreateDocumentRequest
if err := bindNestedJSONPayload(c, "document", &req); err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
return
contentType := c.GetHeader("Content-Type")
if strings.Contains(contentType, "multipart/form-data") {
// Multipart form-data: PDF file upload or form fields
req.Name = c.PostForm("document[name]")
req.ExternalLink = c.PostForm("document[external_link]")
req.Content = c.PostForm("document[content]")
if assistantIDStr := c.PostForm("document[assistant_id]"); assistantIDStr != "" {
if id, err := strconv.ParseUint(assistantIDStr, 10, 64); err == nil {
req.AssistantID = uint(id)
}
}
// Check for PDF file
if fileHeader, err := c.FormFile("document[pdf_file]"); err == nil {
req.PdfFile = fileHeader
}
} else {
// JSON request
if err := bindNestedJSONPayload(c, "document", &req); err != nil {
response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error())
return
}
}
assistantID := req.AssistantID
if assistantID == 0 {
assistantID, _ = parseUintParam(c, "assistant_id")
@@ -48,7 +71,7 @@ func (h *CaptainDocumentHandler) Create(c *gin.Context) {
doc, err := h.svc.Create(c.Request.Context(), assistantID, accountID, &req)
if err != nil {
applogger.L().Errorf("Create captain document: %v", err)
response.AbortWithStatusError(c, http.StatusUnprocessableEntity, response.ErrValidation, "failed to create document")
response.AbortWithStatusError(c, http.StatusUnprocessableEntity, response.ErrValidation, err.Error())
return
}
@@ -212,16 +235,18 @@ func captainDocumentPayload(doc *model.CaptainDocument) gin.H {
if syncStatus == model.DocumentSyncStatusPending {
syncStatus = "syncing"
}
pdfDocument := doc.ContentType == "application/pdf" || doc.FileURL != ""
payload := gin.H{
"account_id": doc.AccountID,
"assistant": captainDocumentAssistantPayload(doc),
"content": doc.Content,
"content_type": "text/html",
"content_type": doc.ContentType,
"created_at": doc.CreatedAt.Unix(),
"external_link": doc.ExternalLink,
"display_url": doc.ExternalLink,
"file_size": 0,
"pdf_document": false,
"file_size": doc.FileSize,
"file_url": doc.FileURL,
"pdf_document": pdfDocument,
"id": doc.ID,
"name": doc.Name,
"status": status,