| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- package controller
- import (
- "log"
- "net/http"
- "strconv"
- "github.com/2930134478/AI-CS/backend/service"
- "github.com/gin-gonic/gin"
- )
- // DocumentController 文档控制器
- type DocumentController struct {
- documentService *service.DocumentService
- embeddingConfigService *service.EmbeddingConfigService
- }
- // NewDocumentController 创建文档控制器实例
- func NewDocumentController(documentService *service.DocumentService, embeddingConfigService *service.EmbeddingConfigService) *DocumentController {
- return &DocumentController{
- documentService: documentService,
- embeddingConfigService: embeddingConfigService,
- }
- }
- func (c *DocumentController) checkKBAccess(ctx *gin.Context) bool {
- userID := getUserIDFromHeader(ctx)
- if userID == 0 {
- return true
- }
- if err := c.embeddingConfigService.CheckKnowledgeBaseAccess(userID); err != nil {
- ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
- return false
- }
- return true
- }
- // ListDocuments 获取文档列表
- func (c *DocumentController) ListDocuments(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- // 获取查询参数
- kbIDStr := ctx.Query("knowledge_base_id")
- pageStr := ctx.DefaultQuery("page", "1")
- pageSizeStr := ctx.DefaultQuery("page_size", "20")
- keyword := ctx.Query("keyword")
- status := ctx.Query("status")
- var knowledgeBaseID uint
- if kbIDStr != "" {
- id, err := strconv.ParseUint(kbIDStr, 10, 64)
- if err == nil {
- knowledgeBaseID = uint(id)
- }
- }
- page, _ := strconv.Atoi(pageStr)
- pageSize, _ := strconv.Atoi(pageSizeStr)
- result, err := c.documentService.ListDocuments(knowledgeBaseID, page, pageSize, keyword, status)
- if err != nil {
- log.Printf("获取文档列表失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": "获取文档列表失败"})
- return
- }
- ctx.JSON(http.StatusOK, result)
- }
- // GetDocument 获取文档详情
- func (c *DocumentController) GetDocument(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- idStr := ctx.Param("id")
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil || id == 0 {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
- return
- }
- doc, err := c.documentService.GetDocument(uint(id))
- if err != nil {
- log.Printf("获取文档详情失败: %v", err)
- ctx.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, doc)
- }
- // CreateDocument 创建文档
- func (c *DocumentController) CreateDocument(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- var req struct {
- KnowledgeBaseID uint `json:"knowledge_base_id" binding:"required"`
- Title string `json:"title" binding:"required"`
- Content string `json:"content" binding:"required"`
- Summary string `json:"summary"`
- Type string `json:"type"`
- Status string `json:"status"`
- }
- if err := ctx.ShouldBindJSON(&req); err != nil {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
- return
- }
- doc, err := c.documentService.CreateDocument(service.CreateDocumentInput{
- KnowledgeBaseID: req.KnowledgeBaseID,
- Title: req.Title,
- Content: req.Content,
- Summary: req.Summary,
- Type: req.Type,
- Status: req.Status,
- })
- if err != nil {
- log.Printf("创建文档失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, doc)
- }
- // UpdateDocument 更新文档
- func (c *DocumentController) UpdateDocument(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- idStr := ctx.Param("id")
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil || id == 0 {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
- return
- }
- var req struct {
- Title *string `json:"title"`
- Content *string `json:"content"`
- Summary *string `json:"summary"`
- Type *string `json:"type"`
- Status *string `json:"status"`
- }
- if err := ctx.ShouldBindJSON(&req); err != nil {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
- return
- }
- doc, err := c.documentService.UpdateDocument(uint(id), service.UpdateDocumentInput{
- Title: req.Title,
- Content: req.Content,
- Summary: req.Summary,
- Type: req.Type,
- Status: req.Status,
- })
- if err != nil {
- log.Printf("更新文档失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, doc)
- }
- // DeleteDocument 删除文档
- func (c *DocumentController) DeleteDocument(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- idStr := ctx.Param("id")
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil || id == 0 {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
- return
- }
- if err := c.documentService.DeleteDocument(uint(id)); err != nil {
- log.Printf("删除文档失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, gin.H{"message": "删除成功"})
- }
- // SearchDocuments 向量检索搜索文档
- func (c *DocumentController) SearchDocuments(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- query := ctx.Query("query")
- topKStr := ctx.DefaultQuery("top_k", "5")
- kbIDStr := ctx.Query("knowledge_base_id")
- if query == "" {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "查询内容不能为空"})
- return
- }
- topK, _ := strconv.Atoi(topKStr)
- if topK <= 0 {
- topK = 5
- }
- var knowledgeBaseID *uint
- if kbIDStr != "" {
- id, err := strconv.ParseUint(kbIDStr, 10, 64)
- if err == nil {
- kbID := uint(id)
- knowledgeBaseID = &kbID
- }
- }
- docs, err := c.documentService.SearchDocuments(query, topK, knowledgeBaseID)
- if err != nil {
- log.Printf("搜索文档失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": "向量检索失败: " + err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, gin.H{
- "count": len(docs),
- "documents": docs,
- })
- }
- // HybridSearchDocuments 混合检索搜索文档(当前实现与向量检索相同)
- func (c *DocumentController) HybridSearchDocuments(ctx *gin.Context) {
- c.SearchDocuments(ctx)
- }
- // UpdateDocumentStatus 更新文档状态
- func (c *DocumentController) UpdateDocumentStatus(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- idStr := ctx.Param("id")
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil || id == 0 {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
- return
- }
- var req struct {
- Status string `json:"status" binding:"required"`
- }
- if err := ctx.ShouldBindJSON(&req); err != nil {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
- return
- }
- if err := c.documentService.UpdateDocumentStatus(uint(id), req.Status); err != nil {
- log.Printf("更新文档状态失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, gin.H{"message": "更新成功"})
- }
- // PublishDocument 发布文档
- func (c *DocumentController) PublishDocument(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- idStr := ctx.Param("id")
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil || id == 0 {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
- return
- }
- if err := c.documentService.PublishDocument(uint(id)); err != nil {
- log.Printf("发布文档失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, gin.H{"message": "发布成功"})
- }
- // UnpublishDocument 取消发布文档
- func (c *DocumentController) UnpublishDocument(ctx *gin.Context) {
- if !c.checkKBAccess(ctx) {
- return
- }
- idStr := ctx.Param("id")
- id, err := strconv.ParseUint(idStr, 10, 64)
- if err != nil || id == 0 {
- ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
- return
- }
- if err := c.documentService.UnpublishDocument(uint(id)); err != nil {
- log.Printf("取消发布文档失败: %v", err)
- ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- ctx.JSON(http.StatusOK, gin.H{"message": "取消发布成功"})
- }
|