87 lines
3.6 KiB
Go
87 lines
3.6 KiB
Go
package run
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"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"
|
|
)
|
|
|
|
type DetailHeader struct {
|
|
model.SOPRun
|
|
SOPName string `json:"sop_name"`
|
|
ScenarioName string `json:"scenario_name"`
|
|
Version int `json:"version"`
|
|
OperatorName string `json:"operator_name"`
|
|
}
|
|
|
|
type DetailEvent struct {
|
|
model.SOPRunEvent
|
|
NodeTitle string `json:"node_title"`
|
|
NodeType string `json:"node_type"`
|
|
NodeContent string `json:"node_content"`
|
|
NodeConfig datatypes.JSON `json:"-"`
|
|
Knowledge *KnowledgeView `json:"knowledge,omitempty" gorm:"-"`
|
|
}
|
|
|
|
type DetailFeedback struct {
|
|
model.SOPFeedback
|
|
UserName string `json:"user_name"`
|
|
}
|
|
|
|
func (h *Handler) Detail(c *gin.Context) {
|
|
principal, _ := auth.PrincipalFromContext(c)
|
|
id, ok := runID(c)
|
|
if !ok {
|
|
return
|
|
}
|
|
var header DetailHeader
|
|
err := h.db.Table("sop_runs r").Select(
|
|
"r.*, s.name AS sop_name, sc.name AS scenario_name, sv.version, u.display_name AS operator_name",
|
|
).Joins("JOIN sops s ON s.id = r.sop_id").Joins("JOIN scenarios sc ON sc.id = s.scenario_id").Joins("JOIN sop_versions sv ON sv.id = r.sop_version_id").Joins("JOIN users u ON u.id = r.operator_id").Where("r.id = ? AND r.tenant_id = ?", id, principal.TenantID).Scan(&header).Error
|
|
if err != nil || header.ID == 0 || !canViewRun(principal, header.SOPRun) {
|
|
response.Error(c, http.StatusNotFound, "NOT_FOUND", "执行记录不存在")
|
|
return
|
|
}
|
|
events := make([]DetailEvent, 0)
|
|
if err := h.db.Table("sop_run_events e").Select("e.*, n.title AS node_title, n.type AS node_type, n.content AS node_content, n.config AS node_config").Joins("LEFT JOIN sop_nodes n ON n.sop_version_id = ? AND n.node_key = e.node_key", header.SOPVersionID).Where("e.run_id = ? AND e.tenant_id = ?", id, principal.TenantID).Order("e.created_at, e.id").Scan(&events).Error; err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "查询执行事件失败")
|
|
return
|
|
}
|
|
knowledgeCache := map[string]*KnowledgeView{}
|
|
for i := range events {
|
|
if events[i].NodeType != "knowledge" {
|
|
continue
|
|
}
|
|
cacheKey := string(events[i].NodeConfig)
|
|
if cached, ok := knowledgeCache[cacheKey]; ok {
|
|
events[i].Knowledge = cached
|
|
continue
|
|
}
|
|
knowledge, err := loadKnowledgeView(h.db, model.SOPNode{Type: events[i].NodeType, Config: events[i].NodeConfig}, principal.TenantID)
|
|
if err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "KNOWLEDGE_NOT_FOUND", "执行记录关联的知识卡版本不存在")
|
|
return
|
|
}
|
|
events[i].Knowledge = &knowledge
|
|
knowledgeCache[cacheKey] = &knowledge
|
|
}
|
|
feedback := make([]DetailFeedback, 0)
|
|
if err := h.db.Table("sop_feedback f").Select("f.*, u.display_name AS user_name").Joins("JOIN users u ON u.id = f.user_id").Where("f.run_id = ? AND f.tenant_id = ?", id, principal.TenantID).Order("f.created_at").Scan(&feedback).Error; err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "查询执行反馈失败")
|
|
return
|
|
}
|
|
fields := make([]model.ScenarioField, 0)
|
|
if err := h.db.Table("scenario_fields sf").Joins("JOIN sops s ON s.scenario_id = sf.scenario_id").Where("s.id = ? AND sf.tenant_id = ?", header.SOPID, principal.TenantID).Order("sf.sort_order, sf.id").Find(&fields).Error; err != nil {
|
|
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "查询场景字段失败")
|
|
return
|
|
}
|
|
if header.Answers == nil {
|
|
header.Answers = datatypes.JSON([]byte(`{}`))
|
|
}
|
|
response.OK(c, gin.H{"run": header, "events": events, "feedback": feedback, "fields": fields})
|
|
}
|