package handler import ( "net/http" "strconv" "tcm-agent/internal/dao" "github.com/gin-gonic/gin" ) // ======================================================================== // HistoryHandler —— AI 生成历史(DB 长期数据)只读查询 // ======================================================================== // 暴露 3 个端点(前缀 /api/v1/agent): // GET /history 分页列表(场景/状态/via_agent/供应商/日期筛选) // GET /history/:id 单条详情 + 步骤时间线 // GET /history/scenes 出现过的场景列表(前端筛选下拉) // // 与 /agent/runs 的区别: // - runs:内存环形缓冲,最近 200 条,含守卫拦截等"没到 PHP"的运行,重启清零 // - history:读 PHP 落库的 xk_ai_generation(_step),长期审计视角,只读 // ======================================================================== // HistoryHandler 历史查询处理器 type HistoryHandler struct{} // NewHistoryHandler 构造 func NewHistoryHandler() *HistoryHandler { return &HistoryHandler{} } // List 分页查询历史 // GET /api/v1/agent/history?page=1&size=20&scene=&status=-1&via_agent=-1&is_archived=-1&is_correct=-1&provider=&date_start=0&date_end=0 func (h *HistoryHandler) List(c *gin.Context) { filter := dao.AIGenerationListFilter{ Page: queryInt(c, "page", 1), Size: queryInt(c, "size", 20), Scene: c.Query("scene"), Status: queryInt(c, "status", -1), ViaAgent: queryInt(c, "via_agent", -1), Provider: c.Query("provider"), IsArchived: queryInt(c, "is_archived", -1), IsCorrect: queryInt(c, "is_correct", -1), } filter.DateStart = int64(queryInt(c, "date_start", 0)) filter.DateEnd = int64(queryInt(c, "date_end", 0)) rows, total, err := dao.AIGenerationList(filter) if err != nil { c.JSON(http.StatusOK, gin.H{"code": 500, "message": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"code": 200, "data": gin.H{ "list": rows, "total": total, "page": filter.Page, "size": filter.Size, }}) } // Detail 单条详情 + 步骤 // GET /api/v1/agent/history/:id func (h *HistoryHandler) Detail(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { c.JSON(http.StatusOK, gin.H{"code": 400, "message": "id 参数无效"}) return } row, steps, err := dao.AIGenerationGet(uint(id)) if err != nil { c.JSON(http.StatusOK, gin.H{"code": 404, "message": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"code": 200, "data": gin.H{ "generation": row, "steps": steps, }}) } // Scenes 场景下拉数据 // GET /api/v1/agent/history/scenes func (h *HistoryHandler) Scenes(c *gin.Context) { scenes, err := dao.AIGenerationScenes() if err != nil { c.JSON(http.StatusOK, gin.H{"code": 500, "message": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"code": 200, "data": scenes}) } // queryInt 读取整型 query 参数,缺失或非法时返回默认值 func queryInt(c *gin.Context, key string, def int) int { v := c.Query(key) if v == "" { return def } n, err := strconv.Atoi(v) if err != nil { return def } return n }