package transport import ( "strconv" "time" "github.com/gin-gonic/gin" "github.com/geo-platform/tenant-api/internal/ops/app" "github.com/geo-platform/tenant-api/internal/ops/domain" "github.com/geo-platform/tenant-api/internal/shared/response" ) func listAuditsHandler(svc *app.AuditService) gin.HandlerFunc { return func(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) size, _ := strconv.Atoi(c.DefaultQuery("size", "50")) if page <= 0 { page = 1 } if size <= 0 || size > 500 { size = 50 } filter := domain.AuditLogFilter{ Action: c.Query("action"), Limit: size, Offset: (page - 1) * size, } if v := c.Query("operator_id"); v != "" { id, err := strconv.ParseInt(v, 10, 64) if err != nil { response.Error(c, response.ErrBadRequest(40002, "invalid_operator_id", "operator_id 不合法")) return } filter.OperatorID = &id } if v := c.Query("start_at"); v != "" { t, err := time.Parse(time.RFC3339, v) if err != nil { response.Error(c, response.ErrBadRequest(40003, "invalid_start_at", "start_at 必须是 RFC3339")) return } filter.StartAt = &t } if v := c.Query("end_at"); v != "" { t, err := time.Parse(time.RFC3339, v) if err != nil { response.Error(c, response.ErrBadRequest(40004, "invalid_end_at", "end_at 必须是 RFC3339")) return } filter.EndAt = &t } items, total, err := svc.List(c.Request.Context(), filter) if err != nil { response.Error(c, err) return } dtos := make([]auditLogDTO, 0, len(items)) for _, log := range items { dtos = append(dtos, toAuditLogDTO(log)) } response.Success(c, gin.H{ "items": dtos, "total": total, "page": page, "size": size, }) } } type auditLogDTO struct { ID int64 `json:"id"` OperatorID *int64 `json:"operator_id"` OperatorName *string `json:"operator_name"` Action string `json:"action"` TargetType *string `json:"target_type"` TargetID *string `json:"target_id"` Metadata map[string]any `json:"metadata"` IP *string `json:"ip"` IPRegion *string `json:"ip_region"` UserAgent *string `json:"user_agent"` RequestID *string `json:"request_id"` CreatedAt time.Time `json:"created_at"` } func toAuditLogDTO(l domain.AuditLog) auditLogDTO { return auditLogDTO{ ID: l.ID, OperatorID: l.OperatorID, OperatorName: l.OperatorName, Action: l.Action, TargetType: l.TargetType, TargetID: l.TargetID, Metadata: l.Metadata, IP: l.IP, IPRegion: l.IPRegion, UserAgent: l.UserAgent, RequestID: l.RequestID, CreatedAt: l.CreatedAt, } }