feat: harden pet consultation SOP execution

This commit is contained in:
Eric 1549169735@qq.com
2026-08-08 22:03:08 +08:00
parent 0ec1d0f39d
commit 97a76250f7
14 changed files with 588 additions and 15 deletions

View File

@@ -190,12 +190,16 @@ func (h *Handler) Validate(c *gin.Context) {
if !ok {
return
}
_, version, nodes, edges, err := h.loadLatest(id, p.TenantID)
item, version, nodes, edges, err := h.loadLatest(id, p.TenantID)
if err != nil {
response.Error(c, http.StatusNotFound, "NOT_FOUND", "SOP 不存在")
return
}
problems := ValidateGraph(version.StartNodeKey, nodes, edges)
problems, err := h.validateForPublish(item, version.StartNodeKey, nodes, edges, p.TenantID)
if err != nil {
response.Error(c, http.StatusInternalServerError, "VALIDATION_FAILED", "校验流程失败")
return
}
response.OK(c, gin.H{"valid": len(problems) == 0, "problems": problems})
}
@@ -210,7 +214,11 @@ func (h *Handler) SubmitReview(c *gin.Context) {
response.Error(c, http.StatusConflict, "NO_DRAFT_VERSION", "没有可提交审核的草稿版本")
return
}
problems := ValidateGraph(version.StartNodeKey, nodes, edges)
problems, validationErr := h.validateForPublish(item, version.StartNodeKey, nodes, edges, p.TenantID)
if validationErr != nil {
response.Error(c, http.StatusInternalServerError, "VALIDATION_FAILED", "校验流程失败")
return
}
if len(problems) > 0 {
response.Error(c, http.StatusUnprocessableEntity, "INVALID_GRAPH", problems[0])
return
@@ -240,7 +248,11 @@ func (h *Handler) Publish(c *gin.Context) {
response.Error(c, http.StatusConflict, "NO_REVIEW_VERSION", "没有可发布的审核版本")
return
}
problems := ValidateGraph(version.StartNodeKey, nodes, edges)
problems, validationErr := h.validateForPublish(item, version.StartNodeKey, nodes, edges, p.TenantID)
if validationErr != nil {
response.Error(c, http.StatusInternalServerError, "VALIDATION_FAILED", "校验流程失败")
return
}
if len(problems) > 0 {
response.Error(c, http.StatusUnprocessableEntity, "INVALID_GRAPH", problems[0])
return
@@ -368,6 +380,22 @@ func (h *Handler) loadLatest(sopID, tenantID uint64) (model.SOP, model.SOPVersio
return item, version, nodes, edges, nil
}
func (h *Handler) validateForPublish(item model.SOP, startNodeKey string, nodes []model.SOPNode, edges []model.SOPEdge, tenantID uint64) ([]string, error) {
var fields []model.ScenarioField
if err := h.db.Where("scenario_id = ? AND tenant_id = ?", item.ScenarioID, tenantID).Find(&fields).Error; err != nil {
return nil, err
}
var cards []model.KnowledgeCard
if err := h.db.Where("scenario_id = ? AND tenant_id = ? AND status = ?", item.ScenarioID, tenantID, "published").Find(&cards).Error; err != nil {
return nil, err
}
cardIDs := make(map[uint64]bool, len(cards))
for _, card := range cards {
cardIDs[card.ID] = true
}
return ValidateForPublish(startNodeKey, nodes, edges, ValidationContext{Fields: fields, PublishedKnowledgeCardIDs: cardIDs}), nil
}
func toModels(tenantID, versionID uint64, input graphInput) ([]model.SOPNode, []model.SOPEdge) {
nodes := make([]model.SOPNode, 0, len(input.Nodes))
for _, item := range input.Nodes {