From 48c72f1eb4e0dafd92d4161a12f665664c3d778c Mon Sep 17 00:00:00 2001 From: martin <406615373@qq.com> Date: Sat, 25 Jul 2026 19:59:28 +0800 Subject: [PATCH] =?UTF-8?q?chore:=E6=8A=BD=E5=8F=96=E5=85=AC=E5=85=B1?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E9=99=8D=E4=BD=8E=E9=87=8D=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/logic/admin/audit.go | 126 ++++++++------------------- internal/logic/admin/dashboard.go | 28 ++---- internal/logic/monitor/alert_rule.go | 41 ++------- internal/logic/tenant/billing.go | 25 ++---- 4 files changed, 61 insertions(+), 159 deletions(-) diff --git a/internal/logic/admin/audit.go b/internal/logic/admin/audit.go index 342f45c..66b8c20 100644 --- a/internal/logic/admin/audit.go +++ b/internal/logic/admin/audit.go @@ -6,6 +6,7 @@ import ( "fmt" "strings" + "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" @@ -89,15 +90,38 @@ func (s *sAdmin) UpdateAuditConfig(ctx context.Context, req *v1.AuditConfigUpdat // queryPage 使用 GoFrame ORM 分页查询,返回 []map[string]any。 // 使用主库查询审计表(aud_request_logs 之外的审计表数据量小,无需独立库)。 -// 分开调用 Count 和 All 避免 ScanAndCount 对 map[string]any 的 bug。 func queryPage(ctx context.Context, table, fields, where, orderBy string, page, pageSize int, args ...any) ([]map[string]any, int, error) { - mainDB := g.DB() - m := mainDB.Ctx(ctx).Model(table).Safe() + m := g.DB().Ctx(ctx).Model(table).Safe() if where != "" { m = m.Where(where, args...) } + if fields != "" { + m = m.Fields(fields) + } + if orderBy != "" { + m = m.Order(orderBy) + } - total, err := m.Count() + var items []map[string]any + var total int + err := m.Page(page, pageSize).ScanAndCount(&items, &total, false) + if err != nil { + return nil, 0, err + } + if items == nil { + items = []map[string]any{} + } + return items, total, nil +} + +// queryAuditPage 查询审计表分页数据,自动计数、分页、转换并批量填充关联名称。 +// 用于 ListRequestAuditLogs 和 ContentFilterLogList 的公共分页逻辑。 +func queryAuditPage(ctx context.Context, db gdb.DB, table, fields, where string, args []any, page, pageSize int) ([]map[string]any, int, error) { + countM := db.Ctx(ctx).Model(table).Safe() + if where != "" { + countM = countM.Where(where, args...) + } + total, err := countM.Count() if err != nil { return nil, 0, err } @@ -105,19 +129,11 @@ func queryPage(ctx context.Context, table, fields, where, orderBy string, page, return []map[string]any{}, 0, nil } - // 重新构建查询(Count 会消耗 Model 状态) - q := mainDB.Ctx(ctx).Model(table).Safe() - if fields != "" { - q = q.Fields(fields) - } + dataM := db.Ctx(ctx).Model(table).Safe().Fields(fields).OrderDesc("created_at").Page(page, pageSize) if where != "" { - q = q.Where(where, args...) + dataM = dataM.Where(where, args...) } - if orderBy != "" { - q = q.Order(orderBy) - } - - result, err := q.Page(page, pageSize).All() + result, err := dataM.All() if err != nil { return nil, 0, err } @@ -130,6 +146,8 @@ func queryPage(ctx context.Context, table, fields, where, orderBy string, page, } items = append(items, m) } + + common.EnrichAuditRecords(ctx, items) return items, total, nil } @@ -328,46 +346,12 @@ func (s *sAdmin) ListRequestAuditLogs(ctx context.Context, req *v1.RequestAuditL } where := strings.Join(conditions, " AND ") + auditFields := "id, tenant_id, user_id, api_key_id, project_id, request_id, method, path, query_params, status_code, client_ip, user_agent, latency_ms, first_token_ms, audit_level, created_at" - // Step 1: 从审计库查询审计记录(不带 JOIN) - auditDB := common.GetAuditDB() - countM := auditDB.Ctx(ctx).Model("aud_request_logs").Safe() - if where != "" { - countM = countM.Where(where, args...) - } - total, err := countM.Count() + items, total, err := queryAuditPage(ctx, common.GetAuditDB(), "aud_request_logs", auditFields, where, args, page, pageSize) if err != nil { return nil, err } - if total == 0 { - return &v1.RequestAuditLogListRes{ - List: []map[string]any{}, Total: 0, Page: page, PageSize: pageSize, - }, nil - } - - dataM := auditDB.Ctx(ctx).Model("aud_request_logs").Safe(). - Fields("id, tenant_id, user_id, api_key_id, project_id, request_id, method, path, query_params, status_code, client_ip, user_agent, latency_ms, first_token_ms, audit_level, created_at"). - OrderDesc("created_at"). - Page(page, pageSize) - if where != "" { - dataM = dataM.Where(where, args...) - } - result, err := dataM.All() - if err != nil { - return nil, err - } - - items := make([]map[string]any, 0, len(result)) - for _, row := range result { - m := make(map[string]any, len(row)) - for k, v := range row { - m[k] = v.Val() - } - items = append(items, m) - } - - // Step 2: 从主库批量查询关联信息并合并 - common.EnrichAuditRecords(ctx, items) return &v1.RequestAuditLogListRes{ List: items, @@ -545,48 +529,12 @@ func (s *sAdmin) ContentFilterLogList(ctx context.Context, req *v1.ContentFilter } where := strings.Join(conditions, " AND ") + cfFields := "id, tenant_id, user_id, api_key_id, project_id, request_id, method, path, client_ip, filter_mode, matched_words, original_snippet, blocked, created_at" - // Step 1: 从主库查询内容过滤日志(数据量小,无需独立库) - mainDB := g.DB() - fields := "id, tenant_id, user_id, api_key_id, project_id, request_id, method, path, client_ip, filter_mode, matched_words, original_snippet, blocked, created_at" - - countM := mainDB.Ctx(ctx).Model("aud_content_filter_logs").Safe() - if where != "" { - countM = countM.Where(where, args...) - } - total, err := countM.Count() + items, total, err := queryAuditPage(ctx, g.DB(), "aud_content_filter_logs", cfFields, where, args, page, pageSize) if err != nil { return nil, err } - if total == 0 { - return &v1.ContentFilterLogListRes{ - List: []map[string]any{}, Total: 0, Page: page, PageSize: pageSize, - }, nil - } - - dataM := mainDB.Ctx(ctx).Model("aud_content_filter_logs").Safe(). - Fields(fields). - OrderDesc("created_at"). - Page(page, pageSize) - if where != "" { - dataM = dataM.Where(where, args...) - } - result, err := dataM.All() - if err != nil { - return nil, err - } - - items := make([]map[string]any, 0, len(result)) - for _, row := range result { - m := make(map[string]any, len(row)) - for k, v := range row { - m[k] = v.Val() - } - items = append(items, m) - } - - // Step 2: 从主库批量查询关联信息并合并 - common.EnrichAuditRecords(ctx, items) return &v1.ContentFilterLogListRes{ List: items, diff --git a/internal/logic/admin/dashboard.go b/internal/logic/admin/dashboard.go index e78656e..3649db0 100644 --- a/internal/logic/admin/dashboard.go +++ b/internal/logic/admin/dashboard.go @@ -549,26 +549,14 @@ func (s *sAdmin) SetWarningThreshold(ctx context.Context, req *v1.AdminWalletSet func (s *sAdmin) GetAllTransactions(ctx context.Context, req *v1.AdminTransactionListReq) (*v1.AdminTransactionListRes, error) { page, pageSize := common.NormalizePagination(req.Page, req.PageSize) - query := dao.BilTransactions.Ctx(ctx) - - if req.TenantID > 0 { - query = query.Where("bil_transactions.tenant_id", req.TenantID) - } - if req.Type != "" { - query = query.Where("bil_transactions.type", req.Type) - } - if req.Username != "" { - query = query.Where("tu.username LIKE ?", "%"+req.Username+"%") - } - if req.ModelName != "" { - query = query.Where("bil_transactions.model_name LIKE ?", "%"+req.ModelName+"%") - } - if req.StartDate != "" { - query = query.Where("bil_transactions.created_at >= ?", req.StartDate+" 00:00:00") - } - if req.EndDate != "" { - query = query.Where("bil_transactions.created_at <= ?", req.EndDate+" 23:59:59") - } + query := billing.BuildTransactionQuery(ctx, billing.TransactionQueryParams{ + TenantID: req.TenantID, + Type: req.Type, + Username: req.Username, + ModelName: req.ModelName, + StartDate: req.StartDate, + EndDate: req.EndDate, + }) type transactionRow struct { Id int64 `json:"id"` diff --git a/internal/logic/monitor/alert_rule.go b/internal/logic/monitor/alert_rule.go index fc5fbd5..bbe14e5 100644 --- a/internal/logic/monitor/alert_rule.go +++ b/internal/logic/monitor/alert_rule.go @@ -197,7 +197,7 @@ func ListAlertRules(ctx context.Context, page, pageSize int, metricType, level s // Post-process: parse array text fields and add display names for i, rule := range rules { - parseRuleArrayFields(rules, i, rule) + parseRuleArrayFields(rule) addRuleDisplayNames(rules, i, rule) } @@ -208,20 +208,20 @@ func ListAlertRules(ctx context.Context, page, pageSize int, metricType, level s }, nil } -// parseRuleArrayFields parses PostgreSQL array text fields into Go slices. -func parseRuleArrayFields(rules []map[string]any, i int, rule map[string]any) { +// parseRuleArrayFields parses PostgreSQL array text fields in a rule map into Go slices. +func parseRuleArrayFields(rule map[string]any) { if nmStr := gconv.String(rule["notification_methods"]); nmStr != "" { nmStr = strings.Trim(nmStr, "{}") if nmStr == "" { - rules[i]["notification_methods"] = []string{} + rule["notification_methods"] = []string{} } else { - rules[i]["notification_methods"] = strings.Split(nmStr, ",") + rule["notification_methods"] = strings.Split(nmStr, ",") } } if nuiStr := gconv.String(rule["notify_user_ids"]); nuiStr != "" { nuiStr = strings.Trim(nuiStr, "{}") if nuiStr == "" { - rules[i]["notify_user_ids"] = []int64{} + rule["notify_user_ids"] = []int64{} } else { parts := strings.Split(nuiStr, ",") ids := make([]int64, 0, len(parts)) @@ -230,7 +230,7 @@ func parseRuleArrayFields(rules []map[string]any, i int, rule map[string]any) { ids = append(ids, idVal) } } - rules[i]["notify_user_ids"] = ids + rule["notify_user_ids"] = ids } } } @@ -260,32 +260,7 @@ func GetAlertRule(ctx context.Context, id int64) (map[string]any, error) { return nil, common.NewNotFoundError("规则") } rule := record.Map() - - // Parse array text fields - if nmStr := gconv.String(rule["notification_methods"]); nmStr != "" { - nmStr = strings.Trim(nmStr, "{}") - if nmStr == "" { - rule["notification_methods"] = []string{} - } else { - rule["notification_methods"] = strings.Split(nmStr, ",") - } - } - if nuiStr := gconv.String(rule["notify_user_ids"]); nuiStr != "" { - nuiStr = strings.Trim(nuiStr, "{}") - if nuiStr == "" { - rule["notify_user_ids"] = []int64{} - } else { - parts := strings.Split(nuiStr, ",") - ids := make([]int64, 0, len(parts)) - for _, p := range parts { - if idVal, e := strconv.ParseInt(p, 10, 64); e == nil { - ids = append(ids, idVal) - } - } - rule["notify_user_ids"] = ids - } - } - + parseRuleArrayFields(rule) return rule, nil } diff --git a/internal/logic/tenant/billing.go b/internal/logic/tenant/billing.go index d743087..1c912b9 100644 --- a/internal/logic/tenant/billing.go +++ b/internal/logic/tenant/billing.go @@ -74,30 +74,21 @@ func (s *sTenant) WalletTransactions(ctx context.Context, req *v1.TenantWalletTr tenantID := middleware.GetTenantID(ctx) page, pageSize := common.NormalizePagination(req.Page, req.PageSize) - query := dao.BilTransactions.Ctx(ctx). - Where("bil_transactions.tenant_id", tenantID) + query := billing.BuildTransactionQuery(ctx, billing.TransactionQueryParams{ + TenantID: tenantID, + Type: req.Type, + Username: req.Username, + ModelName: req.ModelName, + StartDate: req.StartDate, + EndDate: req.EndDate, + }) - if req.Type != "" { - query = query.Where("bil_transactions.type", req.Type) - } - if req.StartDate != "" { - query = query.Where("bil_transactions.created_at >= ?", req.StartDate+" 00:00:00") - } - if req.EndDate != "" { - query = query.Where("bil_transactions.created_at <= ?", req.EndDate+" 23:59:59") - } if req.AmountMin != 0 { query = query.Where("bil_transactions.amount >= ?", req.AmountMin) } if req.AmountMax != 0 { query = query.Where("bil_transactions.amount <= ?", req.AmountMax) } - if req.Username != "" { - query = query.Where("tu.username LIKE ?", "%"+req.Username+"%") - } - if req.ModelName != "" { - query = query.Where("bil_transactions.model_name LIKE ?", "%"+req.ModelName+"%") - } type transactionRow struct { Id int64 `json:"id"`