106 lines
4.2 KiB
Go
106 lines
4.2 KiB
Go
package knowledge
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/access"
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/audit"
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/auth"
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/response"
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/datatypes"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type Handler struct{ db *gorm.DB }
|
|
|
|
func NewHandler(db *gorm.DB) *Handler { return &Handler{db: db} }
|
|
|
|
type input struct {
|
|
ScenarioID uint64 `json:"scenario_id" binding:"required"`
|
|
Title string `json:"title" binding:"required,max=128"`
|
|
Content map[string]interface{} `json:"content" binding:"required"`
|
|
}
|
|
|
|
func (h *Handler) List(c *gin.Context) {
|
|
p, _ := auth.PrincipalFromContext(c)
|
|
type row struct {
|
|
model.KnowledgeCard
|
|
Content datatypes.JSON `json:"content"`
|
|
}
|
|
items := make([]row, 0)
|
|
query := h.db.Table("knowledge_cards kc").Select("kc.*, kcv.content").Joins("JOIN scenarios sc ON sc.id = kc.scenario_id").Joins("LEFT JOIN knowledge_card_versions kcv ON kcv.knowledge_card_id = kc.id AND kcv.status = ?", "published")
|
|
query = access.ScopeScenarios(query, p, "sc")
|
|
err := query.Where("kc.tenant_id = ? AND kc.status <> ?", p.TenantID, "archived").Order("kc.updated_at DESC").Scan(&items).Error
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "查询知识卡失败")
|
|
return
|
|
}
|
|
response.OK(c, gin.H{"items": items, "total": len(items)})
|
|
}
|
|
|
|
func (h *Handler) Create(c *gin.Context) {
|
|
p, _ := auth.PrincipalFromContext(c)
|
|
var body input
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
response.Error(c, http.StatusBadRequest, "INVALID_ARGUMENT", "知识卡内容不完整")
|
|
return
|
|
}
|
|
if !access.CanEditScenario(h.db, p, body.ScenarioID) {
|
|
response.Error(c, http.StatusNotFound, "NOT_FOUND", "场景不存在或不可编辑")
|
|
return
|
|
}
|
|
content, _ := json.Marshal(body.Content)
|
|
var card model.KnowledgeCard
|
|
err := h.db.Transaction(func(tx *gorm.DB) error {
|
|
card = model.KnowledgeCard{TenantID: p.TenantID, ScenarioID: body.ScenarioID, Title: body.Title, Status: "published", CreatedBy: p.UserID}
|
|
if err := tx.Create(&card).Error; err != nil {
|
|
return err
|
|
}
|
|
return tx.Create(&model.KnowledgeCardVersion{TenantID: p.TenantID, KnowledgeCardID: card.ID, Version: 1, Content: datatypes.JSON(content), Status: "published"}).Error
|
|
})
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "CREATE_FAILED", "创建知识卡失败")
|
|
return
|
|
}
|
|
_ = audit.Record(h.db, p, "create", "knowledge_card", card.ID, body)
|
|
response.Created(c, card)
|
|
}
|
|
|
|
func (h *Handler) Delete(c *gin.Context) {
|
|
p, _ := auth.PrincipalFromContext(c)
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
|
if err != nil {
|
|
response.Error(c, http.StatusBadRequest, "INVALID_ID", "知识卡 ID 不正确")
|
|
return
|
|
}
|
|
var card model.KnowledgeCard
|
|
if err := h.db.Where("id = ? AND tenant_id = ?", id, p.TenantID).First(&card).Error; err != nil || !access.CanEditScenario(h.db, p, card.ScenarioID) {
|
|
response.Error(c, http.StatusNotFound, "NOT_FOUND", "知识卡不存在或不可归档")
|
|
return
|
|
}
|
|
var references int64
|
|
err = h.db.Table("sop_nodes n").Joins("JOIN sop_versions sv ON sv.id = n.sop_version_id").Joins("JOIN sops s ON s.id = sv.sop_id").Where(
|
|
"n.tenant_id = ? AND s.scenario_id = ? AND sv.status IN ? AND n.type = ? AND JSON_UNQUOTE(JSON_EXTRACT(n.config, '$.knowledge_card_id')) = ?",
|
|
p.TenantID, card.ScenarioID, []string{"published", "offline", "superseded"}, "knowledge", strconv.FormatUint(id, 10),
|
|
).Count(&references).Error
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "检查知识卡引用失败")
|
|
return
|
|
}
|
|
if references > 0 {
|
|
response.Error(c, http.StatusConflict, "KNOWLEDGE_IN_USE", "知识卡已被发布版本引用,不能归档")
|
|
return
|
|
}
|
|
result := h.db.Model(&model.KnowledgeCard{}).Where("id = ? AND tenant_id = ?", id, p.TenantID).Update("status", "archived")
|
|
if result.Error != nil || result.RowsAffected == 0 {
|
|
response.Error(c, http.StatusNotFound, "NOT_FOUND", "知识卡不存在")
|
|
return
|
|
}
|
|
_ = audit.Record(h.db, p, "archive", "knowledge_card", id, nil)
|
|
response.OK(c, gin.H{"id": id})
|
|
}
|