feat: 数据概览/操作日志/批量操作 + 首页合格档案数
CI / Go (api) (pull_request) Successful in 13s
CI / Python (ingestion) (pull_request) Successful in 9s
CI / Migrations (postgres) (pull_request) Successful in 14s

后台新增「数据概览」(商品/合格/按状态/品牌/分类/待审核) 与「操作日志」(全局审计分页);商品列表支持多选批量改状态/分类。公开首页标题改为「天工」并展示合格档案数;新增公开接口 /api/v1/stats 与后台 /api/stats、/api/audit、/api/products/bulk。合格口径=quality_score≥0.6 且在用。

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
sulaimaannaasif6866
2026-06-21 01:45:28 +00:00
parent a36700076e
commit f382c27200
15 changed files with 847 additions and 9 deletions
+38
View File
@@ -481,6 +481,44 @@ type AuditEntry struct {
CreatedAt string `json:"created_at"`
}
// AuditLogRow is one global audit-log row for the operations log view.
type AuditLogRow struct {
ID string `json:"id"`
Actor string `json:"actor"`
Action string `json:"action"`
Entity string `json:"entity"`
EntityID *string `json:"entity_id"`
Fields []string `json:"fields"`
CreatedAt string `json:"created_at"`
}
// ListAllAudit returns a page of the global audit log, newest first, along with
// the total row count.
func (s *Store) ListAllAudit(ctx context.Context, limit, offset int) ([]AuditLogRow, int, error) {
var total int
if err := s.pool.QueryRow(ctx, "SELECT count(*) FROM audit_log").Scan(&total); err != nil {
return nil, 0, err
}
rows, err := s.pool.Query(ctx, `
SELECT id, actor, action, entity, entity_id::text, fields, created_at::text
FROM audit_log
ORDER BY created_at DESC
LIMIT $1 OFFSET $2`, limit, offset)
if err != nil {
return nil, 0, err
}
defer rows.Close()
out := []AuditLogRow{}
for rows.Next() {
var e AuditLogRow
if err := rows.Scan(&e.ID, &e.Actor, &e.Action, &e.Entity, &e.EntityID, &e.Fields, &e.CreatedAt); err != nil {
return nil, 0, err
}
out = append(out, e)
}
return out, total, rows.Err()
}
// ListAudit returns audit history for one product, newest first.
func (s *Store) ListAudit(ctx context.Context, productID string, limit int) ([]AuditEntry, error) {
rows, err := s.pool.Query(ctx, `