package handler import ( "net/http" "github.com/gin-gonic/gin" "kefu-sys/server/internal/middleware" "kefu-sys/server/internal/model" ) type KnowledgeHandler struct{} func NewKnowledgeHandler() *KnowledgeHandler { return &KnowledgeHandler{} } func requireKnowledgeManager(c *gin.Context) bool { if middleware.HasAnyRole(c, "admin", "supervisor") { return true } c.JSON(http.StatusForbidden, gin.H{"code": 403, "message": "仅主管或管理员可管理知识库"}) return false } func hasKnowledgeCapacity(tenantID uint) (bool, error) { var tenant model.Tenant if err := model.DB.First(&tenant, tenantID).Error; err != nil { return false, err } if tenant.PlanID == nil { return true, nil } var plan model.Plan if err := model.DB.First(&plan, *tenant.PlanID).Error; err != nil { return false, err } if plan.KBLimit == 0 { return true, nil } var count int64 if err := model.DB.Model(&model.KnowledgeEntry{}).Where("tenant_id = ?", tenantID).Count(&count).Error; err != nil { return false, err } return count < int64(plan.KBLimit), nil } func (h *KnowledgeHandler) ListCategories(c *gin.Context) { tenantID := middleware.GetTenantID(c) var categories []model.Category model.DB.Where("tenant_id = ?", tenantID).Find(&categories) middleware.JSON(c, categories) } func (h *KnowledgeHandler) CreateCategory(c *gin.Context) { if !requireKnowledgeManager(c) { return } var category model.Category if err := c.ShouldBindJSON(&category); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "参数错误"}) return } category.TenantID = middleware.GetTenantID(c) if err := model.DB.Create(&category).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "创建失败"}) return } middleware.JSON(c, category) } func (h *KnowledgeHandler) ListEntries(c *gin.Context) { tenantID := middleware.GetTenantID(c) page, pageSize := middleware.GetPageParams(c) categoryID := c.Query("category_id") search := c.Query("search") status := c.Query("status") var entries []model.KnowledgeEntry var total int64 query := model.DB.Where("tenant_id = ?", tenantID) if categoryID != "" { query = query.Where("category_id = ?", categoryID) } if search != "" { query = query.Where("title LIKE ? OR content LIKE ?", "%"+search+"%", "%"+search+"%") } if status != "" { query = query.Where("status = ?", status) } query.Model(&model.KnowledgeEntry{}).Count(&total) query.Order("updated_at desc").Offset((page - 1) * pageSize).Limit(pageSize).Find(&entries) middleware.JSONList(c, entries, total, page, pageSize) } func (h *KnowledgeHandler) CreateEntry(c *gin.Context) { if !requireKnowledgeManager(c) { return } var entry model.KnowledgeEntry if err := c.ShouldBindJSON(&entry); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "参数错误"}) return } entry.TenantID = middleware.GetTenantID(c) available, err := hasKnowledgeCapacity(entry.TenantID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "校验知识库容量失败"}) return } if !available { c.JSON(http.StatusConflict, gin.H{"code": 409, "message": "当前套餐知识库容量已达上限"}) return } var category model.Category if err := model.DB.Where("id = ? AND tenant_id = ?", entry.CategoryID, entry.TenantID).First(&category).Error; err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "知识分类不存在"}) return } if err := model.DB.Create(&entry).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "创建失败"}) return } middleware.JSON(c, entry) } func (h *KnowledgeHandler) UpdateEntry(c *gin.Context) { if !requireKnowledgeManager(c) { return } tenantID := middleware.GetTenantID(c) id := c.Param("id") var entry model.KnowledgeEntry if err := model.DB.Where("id = ? AND tenant_id = ?", id, tenantID).First(&entry).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "条目不存在"}) return } var updates map[string]interface{} if err := c.ShouldBindJSON(&updates); err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "参数错误"}) return } allowed := map[string]bool{"category_id": true, "title": true, "content": true, "status": true} for key := range updates { if !allowed[key] { delete(updates, key) } } if categoryID, exists := updates["category_id"]; exists { var category model.Category if err := model.DB.Where("id = ? AND tenant_id = ?", categoryID, tenantID).First(&category).Error; err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "知识分类不存在"}) return } } if len(updates) == 0 { c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "没有可更新字段"}) return } if err := model.DB.Model(&entry).Updates(updates).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"code": 500, "message": "更新失败"}) return } model.DB.First(&entry, entry.ID) middleware.JSON(c, entry) } func (h *KnowledgeHandler) DeleteEntry(c *gin.Context) { if !requireKnowledgeManager(c) { return } tenantID := middleware.GetTenantID(c) id := c.Param("id") result := model.DB.Where("id = ? AND tenant_id = ?", id, tenantID).Delete(&model.KnowledgeEntry{}) if result.RowsAffected == 0 { c.JSON(http.StatusNotFound, gin.H{"code": 404, "message": "条目不存在"}) return } middleware.JSON(c, gin.H{"message": "已删除"}) }