104 lines
3.1 KiB
Go
104 lines
3.1 KiB
Go
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
|
||
}
|