diff --git a/server/internal/handler/database_handler.go b/server/internal/handler/database_handler.go index eafc401..7713699 100644 --- a/server/internal/handler/database_handler.go +++ b/server/internal/handler/database_handler.go @@ -17,7 +17,16 @@ func NewDatabaseHandler(svc *service.DatabaseService) *DatabaseHandler { return &DatabaseHandler{service: svc} } -// Check 检查数据库连接 +// @Summary 检查数据库连接 +// @Description 测试数据库连接是否正常 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Param request body model.CheckRequest true "数据库连接信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /database/check [post] func (h *DatabaseHandler) Check(c *gin.Context) { var req model.CheckRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -34,7 +43,16 @@ func (h *DatabaseHandler) Check(c *gin.Context) { c.JSON(http.StatusOK, result) } -// Create 创建数据库信息 +// @Summary 创建数据库 +// @Description 添加新的数据库连接信息 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Param request body model.CreateDatabaseRequest true "数据库信息" +// @Success 201 {object} model.DatabaseInfo +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /database/add [post] func (h *DatabaseHandler) Create(c *gin.Context) { var req model.CreateDatabaseRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -51,7 +69,15 @@ func (h *DatabaseHandler) Create(c *gin.Context) { c.JSON(http.StatusCreated, info) } -// GetByID 获取详情 +// @Summary 获取数据库详情 +// @Description 根据ID获取数据库详细信息 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Param id path string true "数据库ID" +// @Success 200 {object} model.DatabaseInfo +// @Failure 404 {object} map[string]string +// @Router /database/{id} [get] func (h *DatabaseHandler) GetByID(c *gin.Context) { id := c.Param("id") @@ -64,7 +90,14 @@ func (h *DatabaseHandler) GetByID(c *gin.Context) { c.JSON(http.StatusOK, info) } -// List 获取列表 +// @Summary 获取数据库列表 +// @Description 获取所有已添加的数据库列表 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Success 200 {object} map[string]interface{} +// @Failure 500 {object} map[string]string +// @Router /database/list [get] func (h *DatabaseHandler) List(c *gin.Context) { list, err := h.service.List() if err != nil { @@ -79,7 +112,17 @@ func (h *DatabaseHandler) List(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"list": list}) } -// Update 更新 +// @Summary 更新数据库信息 +// @Description 更新指定数据库的信息 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Param id path string true "数据库ID" +// @Param request body model.UpdateDatabaseRequest true "更新信息" +// @Success 200 {object} model.DatabaseInfo +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Router /database/{id} [put] func (h *DatabaseHandler) Update(c *gin.Context) { id := c.Param("id") @@ -98,7 +141,16 @@ func (h *DatabaseHandler) Update(c *gin.Context) { c.JSON(http.StatusOK, info) } -// SaveGraph 保存图谱信息 +// @Summary 保存图谱信息 +// @Description 保存数据库的图谱结构信息 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Param request body model.SaveGraphRequest true "图谱信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /database/graph/save [post] func (h *DatabaseHandler) SaveGraph(c *gin.Context) { var req model.SaveGraphRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -115,7 +167,15 @@ func (h *DatabaseHandler) SaveGraph(c *gin.Context) { c.JSON(http.StatusOK, result) } -// Delete 删除 +// @Summary 删除数据库 +// @Description 删除指定的数据库连接 +// @Tags 数据库管理 +// @Accept json +// @Produce json +// @Param id path string true "数据库ID" +// @Success 200 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Router /database/{id} [delete] func (h *DatabaseHandler) Delete(c *gin.Context) { id := c.Param("id") diff --git a/server/internal/handler/knowledge_handler.go b/server/internal/handler/knowledge_handler.go index 8e8c0c7..95f5d23 100644 --- a/server/internal/handler/knowledge_handler.go +++ b/server/internal/handler/knowledge_handler.go @@ -17,7 +17,15 @@ func NewKnowledgeHandler(s *service.KnowledgeService) *KnowledgeHandler { return &KnowledgeHandler{service: s} } -// Create 创建知识库 +// @Summary 创建知识库 +// @Description 创建一个新的知识库 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param request body model.CreateKnowledgeRequest true "知识库信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Router /api/knowledge/create [post] func (h *KnowledgeHandler) Create(c *gin.Context) { var req model.CreateKnowledgeRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -38,7 +46,14 @@ func (h *KnowledgeHandler) Create(c *gin.Context) { }) } -// List 获取知识库列表 +// @Summary 获取知识库列表 +// @Description 获取所有知识库列表 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Success 200 {object} map[string]interface{} +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/list [get] func (h *KnowledgeHandler) List(c *gin.Context) { list, err := h.service.List() if err != nil { @@ -49,7 +64,16 @@ func (h *KnowledgeHandler) List(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "data": list}) } -// GetByID 获取知识库详情 +// @Summary 获取知识库详情 +// @Description 根据ID获取知识库详细信息 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Router /api/knowledge/{id} [get] func (h *KnowledgeHandler) GetByID(c *gin.Context) { id := c.Param("id") if id == "" { @@ -66,7 +90,17 @@ func (h *KnowledgeHandler) GetByID(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "data": kb}) } -// Update 更新知识库 +// @Summary 更新知识库 +// @Description 更新指定知识库的信息 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Param request body model.UpdateKnowledgeRequest true "更新信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id} [put] func (h *KnowledgeHandler) Update(c *gin.Context) { id := c.Param("id") if id == "" { @@ -88,7 +122,16 @@ func (h *KnowledgeHandler) Update(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "message": "Knowledge base updated"}) } -// Delete 删除知识库 +// @Summary 删除知识库 +// @Description 删除指定的知识库 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id} [delete] func (h *KnowledgeHandler) Delete(c *gin.Context) { id := c.Param("id") if id == "" { @@ -104,7 +147,17 @@ func (h *KnowledgeHandler) Delete(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "message": "Knowledge base deleted"}) } -// ListDocuments 获取知识库下的文档列表 +// @Summary 获取知识库文档列表 +// @Description 获取指定知识库下的所有文档 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Param status query string false "文档状态筛选" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id}/documents [get] func (h *KnowledgeHandler) ListDocuments(c *gin.Context) { id := c.Param("id") if id == "" { @@ -122,7 +175,17 @@ func (h *KnowledgeHandler) ListDocuments(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "data": list}) } -// UploadDocument 上传文档到知识库 +// @Summary 上传文档 +// @Description 上传文档到指定知识库 +// @Tags 知识库 +// @Accept multipart/form-data +// @Produce json +// @Param id path string true "知识库ID" +// @Param file formData file true "文档文件" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id}/documents [post] func (h *KnowledgeHandler) UploadDocument(c *gin.Context) { id := c.Param("id") if id == "" { @@ -161,7 +224,17 @@ func (h *KnowledgeHandler) UploadDocument(c *gin.Context) { }) } -// DeleteDocument 删除文档 +// @Summary 删除文档 +// @Description 删除知识库中的指定文档 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Param doc_id path string true "文档ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id}/documents/{doc_id} [delete] func (h *KnowledgeHandler) DeleteDocument(c *gin.Context) { id := c.Param("id") docID := c.Param("doc_id") @@ -179,7 +252,17 @@ func (h *KnowledgeHandler) DeleteDocument(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "message": "Document deleted"}) } -// ReparseDocument 重新解析文档 +// @Summary 重新解析文档 +// @Description 重新解析指定文档(用于更新解析结果) +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Param doc_id path string true "文档ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id}/documents/{doc_id}/reparse [post] func (h *KnowledgeHandler) ReparseDocument(c *gin.Context) { id := c.Param("id") docID := c.Param("doc_id") @@ -197,7 +280,18 @@ func (h *KnowledgeHandler) ReparseDocument(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "message": "Document reparse started"}) } -// GetDocumentPreview 获取文档预览 +// @Summary 获取文档预览 +// @Description 获取文档的解析预览内容 +// @Tags 知识库 +// @Accept json +// @Produce json +// @Param id path string true "知识库ID" +// @Param doc_id path string true "文档ID" +// @Param page query int false "页码" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/knowledge/{id}/documents/{doc_id}/preview [get] func (h *KnowledgeHandler) GetDocumentPreview(c *gin.Context) { id := c.Param("id") docID := c.Param("doc_id") diff --git a/server/internal/handler/model_handler.go b/server/internal/handler/model_handler.go index 2f91f74..a4b09f8 100644 --- a/server/internal/handler/model_handler.go +++ b/server/internal/handler/model_handler.go @@ -17,7 +17,14 @@ func NewModelHandler(svc *service.ModelService) *ModelHandler { return &ModelHandler{service: svc} } -// List 获取列表 +// @Summary 获取模型列表 +// @Description 获取所有已添加的AI模型列表 +// @Tags 模型管理 +// @Accept json +// @Produce json +// @Success 200 {object} map[string]interface{} +// @Failure 500 {object} map[string]string +// @Router /model/list [get] func (h *ModelHandler) List(c *gin.Context) { list, err := h.service.List() if err != nil { @@ -32,7 +39,15 @@ func (h *ModelHandler) List(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"list": list}) } -// GetByID 获取详情 +// @Summary 获取模型详情 +// @Description 根据ID获取模型详细信息 +// @Tags 模型管理 +// @Accept json +// @Produce json +// @Param id path string true "模型ID" +// @Success 200 {object} model.ModelInfo +// @Failure 404 {object} map[string]string +// @Router /model/{id} [get] func (h *ModelHandler) GetByID(c *gin.Context) { id := c.Param("id") model, err := h.service.GetByID(id) @@ -43,7 +58,16 @@ func (h *ModelHandler) GetByID(c *gin.Context) { c.JSON(http.StatusOK, model) } -// Create 创建 +// @Summary 添加模型 +// @Description 添加新的AI模型配置 +// @Tags 模型管理 +// @Accept json +// @Produce json +// @Param request body model.CreateModelRequest true "模型信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /model/add [post] func (h *ModelHandler) Create(c *gin.Context) { var req model.CreateModelRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -60,7 +84,17 @@ func (h *ModelHandler) Create(c *gin.Context) { c.JSON(http.StatusOK, result) } -// Update 更新 +// @Summary 更新模型 +// @Description 更新指定模型的信息 +// @Tags 模型管理 +// @Accept json +// @Produce json +// @Param id path string true "模型ID" +// @Param request body model.UpdateModelRequest true "更新信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /model/{id} [put] func (h *ModelHandler) Update(c *gin.Context) { id := c.Param("id") var req model.UpdateModelRequest @@ -78,7 +112,15 @@ func (h *ModelHandler) Update(c *gin.Context) { c.JSON(http.StatusOK, result) } -// Delete 删除 +// @Summary 删除模型 +// @Description 删除指定的AI模型 +// @Tags 模型管理 +// @Accept json +// @Produce json +// @Param id path string true "模型ID" +// @Success 200 {object} map[string]bool +// @Failure 500 {object} map[string]string +// @Router /model/{id} [delete] func (h *ModelHandler) Delete(c *gin.Context) { id := c.Param("id") err := h.service.Delete(id) @@ -90,7 +132,16 @@ func (h *ModelHandler) Delete(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true}) } -// Test 测试连接 +// @Summary 测试模型连接 +// @Description 测试AI模型连接是否正常 +// @Tags 模型管理 +// @Accept json +// @Produce json +// @Param request body model.TestModelRequest true "模型测试请求" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /model/test [post] func (h *ModelHandler) Test(c *gin.Context) { var req model.TestModelRequest if err := c.ShouldBindJSON(&req); err != nil { diff --git a/server/internal/handler/neo4j_handler.go b/server/internal/handler/neo4j_handler.go index c74a45d..4950747 100644 --- a/server/internal/handler/neo4j_handler.go +++ b/server/internal/handler/neo4j_handler.go @@ -17,7 +17,16 @@ func NewNeo4jHandler(svc *service.Neo4jService) *Neo4jHandler { return &Neo4jHandler{service: svc} } -// Check 检查 Neo4j 连接 +// @Summary 检查 Neo4j 连接 +// @Description 测试 Neo4j 数据库连接是否正常 +// @Tags Neo4j +// @Accept json +// @Produce json +// @Param request body model.Neo4jCheckRequest true "Neo4j连接信息" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /neo4j/check [post] func (h *Neo4jHandler) Check(c *gin.Context) { var req model.Neo4jCheckRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -34,7 +43,16 @@ func (h *Neo4jHandler) Check(c *gin.Context) { c.JSON(http.StatusOK, result) } -// GetGraphs 获取图谱概览数据 +// @Summary 获取图谱概览 +// @Description 获取 Neo4j 中的图谱概览数据 +// @Tags Neo4j +// @Accept json +// @Produce json +// @Param request body model.Neo4jGraphRequest true "图谱查询请求" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /neo4j/graphs [post] func (h *Neo4jHandler) GetGraphs(c *gin.Context) { var req model.Neo4jGraphRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -51,7 +69,16 @@ func (h *Neo4jHandler) GetGraphs(c *gin.Context) { c.JSON(http.StatusOK, result) } -// GetNodes 获取节点详情 +// @Summary 获取节点列表 +// @Description 获取 Neo4j 中的节点详情 +// @Tags Neo4j +// @Accept json +// @Produce json +// @Param request body model.Neo4jNodeRequest true "节点查询请求" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /neo4j/nodes [post] func (h *Neo4jHandler) GetNodes(c *gin.Context) { var req model.Neo4jNodeRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -68,7 +95,16 @@ func (h *Neo4jHandler) GetNodes(c *gin.Context) { c.JSON(http.StatusOK, result) } -// GetRelationships 获取关系详情 +// @Summary 获取关系列表 +// @Description 获取 Neo4j 中的关系详情 +// @Tags Neo4j +// @Accept json +// @Produce json +// @Param request body model.Neo4jRelRequest true "关系查询请求" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /neo4j/relationships [post] func (h *Neo4jHandler) GetRelationships(c *gin.Context) { var req model.Neo4jRelRequest if err := c.ShouldBindJSON(&req); err != nil { diff --git a/server/internal/handler/sub_table_handler.go b/server/internal/handler/sub_table_handler.go index 31a533d..b27cb27 100644 --- a/server/internal/handler/sub_table_handler.go +++ b/server/internal/handler/sub_table_handler.go @@ -17,7 +17,16 @@ func NewSubTableHandler(svc *service.SubTableService) *SubTableHandler { return &SubTableHandler{service: svc} } -// Create 创建子表信息 +// @Summary 创建子表映射 +// @Description 添加数据库的子表映射关系 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param request body model.CreateSubTableRequest true "子表信息" +// @Success 201 {object} model.SubTableInfo +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /sub-table/add [post] func (h *SubTableHandler) Create(c *gin.Context) { var req model.CreateSubTableRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -34,7 +43,15 @@ func (h *SubTableHandler) Create(c *gin.Context) { c.JSON(http.StatusCreated, info) } -// GetByID 获取详情 +// @Summary 获取子表详情 +// @Description 根据ID获取子表映射详情 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param id path string true "子表ID" +// @Success 200 {object} model.SubTableInfo +// @Failure 404 {object} map[string]string +// @Router /sub-table/{id} [get] func (h *SubTableHandler) GetByID(c *gin.Context) { id := c.Param("id") @@ -47,7 +64,15 @@ func (h *SubTableHandler) GetByID(c *gin.Context) { c.JSON(http.StatusOK, info) } -// ListByDatabase 获取数据库下所有子表 +// @Summary 获取数据库下所有子表 +// @Description 获取指定数据库的所有子表映射列表 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param database_id path string true "数据库ID" +// @Success 200 {object} map[string]interface{} +// @Failure 500 {object} map[string]string +// @Router /sub-table/database/{database_id} [get] func (h *SubTableHandler) ListByDatabase(c *gin.Context) { databaseID := c.Param("database_id") @@ -64,7 +89,15 @@ func (h *SubTableHandler) ListByDatabase(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"list": list}) } -// GetMappingFromFile 从文件获取映射 +// @Summary 从文件获取映射 +// @Description 从文件中读取子表映射关系 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param database_id path string true "数据库ID" +// @Success 200 {object} map[string]interface{} +// @Failure 500 {object} map[string]string +// @Router /sub-table/mapping/{database_id} [get] func (h *SubTableHandler) GetMappingFromFile(c *gin.Context) { databaseID := c.Param("database_id") @@ -82,7 +115,17 @@ func (h *SubTableHandler) GetMappingFromFile(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"mapping": mapping}) } -// Update 更新 +// @Summary 更新子表映射 +// @Description 更新子表映射信息 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param id path string true "子表ID" +// @Param request body model.UpdateSubTableRequest true "更新信息" +// @Success 200 {object} model.SubTableInfo +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Router /sub-table/{id} [put] func (h *SubTableHandler) Update(c *gin.Context) { id := c.Param("id") @@ -101,7 +144,15 @@ func (h *SubTableHandler) Update(c *gin.Context) { c.JSON(http.StatusOK, info) } -// Delete 删除 +// @Summary 删除子表映射 +// @Description 删除指定的子表映射 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param id path string true "子表ID" +// @Success 200 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Router /sub-table/{id} [delete] func (h *SubTableHandler) Delete(c *gin.Context) { id := c.Param("id") @@ -114,7 +165,15 @@ func (h *SubTableHandler) Delete(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "deleted"}) } -// GetTablesDDL 获取数据库下所有表及DDL +// @Summary 获取表结构DDL +// @Description 获取数据库下所有表的DDL语句 +// @Tags 子表管理 +// @Accept json +// @Produce json +// @Param database_id path string true "数据库ID" +// @Success 200 {object} map[string]interface{} +// @Failure 500 {object} map[string]string +// @Router /sub-table/ddl/{database_id} [get] func (h *SubTableHandler) GetTablesDDL(c *gin.Context) { databaseID := c.Param("database_id") diff --git a/server/internal/handler/system_handler.go b/server/internal/handler/system_handler.go index 2408a1e..e37b0c5 100644 --- a/server/internal/handler/system_handler.go +++ b/server/internal/handler/system_handler.go @@ -14,7 +14,14 @@ func NewSystemHandler() *SystemHandler { return &SystemHandler{} } -// GetSystemInfo 获取系统信息 +// @Summary 获取系统信息 +// @Description 获取服务器系统信息(CPU、内存等) +// @Tags 系统 +// @Accept json +// @Produce json +// @Success 200 {object} model.SystemInfo +// @Failure 500 {object} map[string]string +// @Router /system/info [get] func (h *SystemHandler) GetSystemInfo(c *gin.Context) { info, err := getSystemInfo() if err != nil { diff --git a/server/internal/handler/upload_handler.go b/server/internal/handler/upload_handler.go index a51a10b..a65e89e 100644 --- a/server/internal/handler/upload_handler.go +++ b/server/internal/handler/upload_handler.go @@ -20,7 +20,16 @@ func NewUploadHandler(uploadService *service.UploadService, knowledgeRepo *repos return &UploadHandler{uploadService: uploadService, knowledgeRepo: knowledgeRepo} } -// Upload 上传文件 +// @Summary 上传文件 +// @Description 上传文件到服务器(本地存储或MinIO) +// @Tags 文件上传 +// @Accept multipart/form-data +// @Produce json +// @Param file formData file true "要上传的文件" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/file_upload [post] func (h *UploadHandler) Upload(c *gin.Context) { file, err := c.FormFile("file") if err != nil { @@ -48,7 +57,16 @@ func (h *UploadHandler) Upload(c *gin.Context) { c.JSON(http.StatusOK, result) } -// Delete 删除文件 +// @Summary 删除文件 +// @Description 删除指定文件 +// @Tags 文件上传 +// @Accept json +// @Produce json +// @Param filename path string true "文件名" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/file_upload/{filename} [delete] func (h *UploadHandler) Delete(c *gin.Context) { filename := c.Param("filename") if filename == "" { @@ -64,7 +82,17 @@ func (h *UploadHandler) Delete(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "message": "File deleted"}) } -// ProxyFile 代理文件访问(解决 MinIO 内网地址和 HTTPS 问题) +// @Summary 代理文件访问 +// @Description 代理访问文件,解决 MinIO 内网和 HTTPS 问题 +// @Tags 文件上传 +// @Accept json +// @Produce octet-stream +// @Param key query string true "文件Key" +// @Param kb_id query string false "知识库ID" +// @Success 200 {file} binary +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /api/file_proxy [get] func (h *UploadHandler) ProxyFile(c *gin.Context) { fileKey := c.Query("key") kbID := c.Query("kb_id") diff --git a/server/internal/service/knowledge_service.go b/server/internal/service/knowledge_service.go index c067fa3..3ff3c9c 100644 --- a/server/internal/service/knowledge_service.go +++ b/server/internal/service/knowledge_service.go @@ -155,9 +155,9 @@ func (s *KnowledgeService) Delete(id string) error { // 删除每个文档的 MinIO 文件和本地 Markdown 文件 for _, doc := range docs { - // 删除 MinIO 文件 - if doc.FileKey != "" && kb.StorageConfig.Type == "minio" { - s.uploadService.DeleteFileWithConfig(doc.FileKey, kb.StorageConfig) + // 删除存储文件(MinIO 或本地) + if doc.FileKey != "" { + s.uploadService.DeleteFileWithConfig(doc.FileKey, kb.StorageConfig, kb.Name) } // 删除本地 Markdown 文件 if s.markdownLocalPath != "" { @@ -215,15 +215,15 @@ func (s *KnowledgeService) UploadDocument(kbID string, file *multipart.FileHeade // 上传文件(根据知识库的 storage_config 选择存储方式) var result *UploadResponse - if kb.StorageConfig.Type != "" { - // 使用知识库的存储配置 + if kb.StorageConfig.Type != "" && kb.StorageConfig.Type != "local" { + // 使用知识库的存储配置(MinIO) knowledgeDebugLog.Printf("[Knowledge Upload] 使用知识库存储配置: type=%s, endpoint=%s, bucket=%s", kb.StorageConfig.Type, kb.StorageConfig.Endpoint, kb.StorageConfig.Bucket) result, err = s.uploadService.UploadWithConfig(file, kb.StorageConfig) } else { - // 使用全局配置 - knowledgeDebugLog.Printf("[Knowledge Upload] 使用全局存储配置") - result, err = s.uploadService.Upload(file) + // 本地存储,使用知识库名称作为子目录 + knowledgeDebugLog.Printf("[Knowledge Upload] 使用本地存储,路径: resources/%s/", kb.Name) + result, err = s.uploadService.UploadToKnowledgeBase(file, kb.StorageConfig, kb.Name) } if err != nil { knowledgeDebugLog.Printf("[Knowledge Upload] 错误: 上传失败, err=%v", err) @@ -419,13 +419,8 @@ func (s *KnowledgeService) DeleteDocument(kbID, docID string) error { if doc.FileKey != "" { knowledgeDebugLog.Printf("[Knowledge DeleteDocument] 删除文件: kbID=%s, docID=%s, fileKey=%s, storageType=%s", kbID, docID, doc.FileKey, kb.StorageConfig.Type) - if kb.StorageConfig.Type != "" { - // 使用知识库的存储配置删除 - s.uploadService.DeleteFileWithConfig(doc.FileKey, kb.StorageConfig) - } else { - // 使用全局配置删除 - s.uploadService.DeleteFile(doc.FileKey) - } + // 使用知识库的存储配置删除(传入知识库名称) + s.uploadService.DeleteFileWithConfig(doc.FileKey, kb.StorageConfig, kb.Name) } // 删除文档记录 diff --git a/server/internal/service/upload_service.go b/server/internal/service/upload_service.go index 0869c09..07f21d5 100644 --- a/server/internal/service/upload_service.go +++ b/server/internal/service/upload_service.go @@ -94,7 +94,7 @@ func (s *UploadService) Upload(file *multipart.FileHeader) (*UploadResponse, err if s.cfg.UploadMode == "minio" { return s.uploadToMinIO(f, filename, fileKey, file.Size) } - return s.uploadToLocal(f, filename, fileKey) + return s.uploadToLocal(f, filename, fileKey, "") } // UploadWithConfig 上传文件(使用指定配置) @@ -116,7 +116,29 @@ func (s *UploadService) UploadWithConfig(file *multipart.FileHeader, storageConf return s.uploadToMinIOWithConfig(f, filename, fileKey, file.Size, storageConfig) } // 默认使用本地存储 - return s.uploadToLocal(f, filename, fileKey) + return s.uploadToLocal(f, filename, fileKey, "") +} + +// UploadToKnowledgeBase 上传文件到知识库(本地存储时按知识库名称分类) +func (s *UploadService) UploadToKnowledgeBase(file *multipart.FileHeader, storageConfig model.StorageConfig, knowledgeBaseName string) (*UploadResponse, error) { + // 打开文件 + f, err := file.Open() + if err != nil { + return &UploadResponse{Success: false, Message: err.Error()}, nil + } + defer f.Close() + + // 生成唯一文件名 + ext := filepath.Ext(file.Filename) + filename := fmt.Sprintf("%s%s", uuid.New().String(), ext) + fileKey := strings.TrimSuffix(filename, ext) + + // 根据配置选择存储方式 + if storageConfig.Type == "minio" { + return s.uploadToMinIOWithConfig(f, filename, fileKey, file.Size, storageConfig) + } + // 本地存储,使用知识库名称作为子目录 + return s.uploadToLocal(f, filename, fileKey, knowledgeBaseName) } // uploadToMinIOWithConfig 使用指定配置上传到 MinIO @@ -217,9 +239,18 @@ func (s *UploadService) uploadToMinIO(f multipart.File, filename, fileKey string } // uploadToLocal 上传到本地 -func (s *UploadService) uploadToLocal(f multipart.File, filename, fileKey string) (*UploadResponse, error) { - // 确保目录存在 - uploadPath := s.cfg.UploadLocalPath +// knowledgeBaseName: 知识库名称,如果为空则使用全局配置目录,否则使用 resources/{知识库名称}/ +func (s *UploadService) uploadToLocal(f multipart.File, filename, fileKey string, knowledgeBaseName string) (*UploadResponse, error) { + // 确定存储路径 + var uploadPath string + if knowledgeBaseName != "" { + // 使用 resources/{知识库名称}/ 路径 + uploadPath = filepath.Join("resources", knowledgeBaseName) + } else { + // 使用全局配置路径 + uploadPath = s.cfg.UploadLocalPath + } + if err := os.MkdirAll(uploadPath, 0755); err != nil { return &UploadResponse{Success: false, Message: fmt.Sprintf("failed to create directory: %v", err)}, nil } @@ -259,7 +290,8 @@ func (s *UploadService) DeleteFile(filename string) error { } // DeleteFileWithConfig 使用指定配置删除文件 -func (s *UploadService) DeleteFileWithConfig(filename string, storageConfig model.StorageConfig) error { +// 注意:此方法需要知识库名称才能正确删除本地文件 +func (s *UploadService) DeleteFileWithConfig(filename string, storageConfig model.StorageConfig, knowledgeBaseName string) error { if storageConfig.Type == "minio" { // 创建 MinIO 客户端 client, err := minio.New(storageConfig.Endpoint, &minio.Options{ @@ -275,7 +307,12 @@ func (s *UploadService) DeleteFileWithConfig(filename string, storageConfig mode } // 本地删除 - path := filepath.Join(s.cfg.UploadLocalPath, filename) + var path string + if knowledgeBaseName != "" { + path = filepath.Join("resources", knowledgeBaseName, filename) + } else { + path = filepath.Join(s.cfg.UploadLocalPath, filename) + } return os.Remove(path) }