package logic import ( "context" "strconv" "strings" "time" adminmodel "spark-server/internal/module/admin/model" friendentity "spark-server/internal/module/friend/entity" "spark-server/internal/pkg/errs" ) func (s *Service) ListComplaints(ctx context.Context) ([]ComplaintView, error) { if !s.ready() { return nil, ErrNotReady } rows, err := s.repo.ListComplaints(ctx, 200) if err != nil { return nil, err } return complaintViews(rows), nil } func (s *Service) AddComplaint(ctx context.Context, email, target, reason, detail string) (*ComplaintView, error) { if s.ids == nil || !s.ready() { return nil, ErrNotReady } email = strings.ToLower(strings.TrimSpace(email)) target = strings.TrimSpace(target) var userID, targetID int64 if email != "" { userID, _ = s.repo.LookupUserIDByEmail(ctx, email) } if target != "" { if id, e := strconv.ParseInt(target, 10, 64); e == nil { targetID = id } else { targetID, _ = s.repo.LookupUserIDByEmail(ctx, strings.ToLower(target)) } } if userID <= 0 || targetID <= 0 { return nil, errs.ErrInvalidArgument } id, err := s.ids.NextID() if err != nil { return nil, err } reasonCode := parseReportReason(reason) now := time.Now() err = s.repo.InsertComplaint(ctx, &friendentity.Report{ ID: id, UserID: userID, TargetID: targetID, Reason: reasonCode, Detail: strings.TrimSpace(detail), CreatedAt: now, }) if err != nil { return nil, err } return &ComplaintView{ ID: id, Email: email, Target: target, Reason: reportReasonName(int(reasonCode)), Detail: detail, Status: "open", CreatedAt: now.Format(time.RFC3339), }, nil } func complaintViews(rows []adminmodel.ComplaintRow) []ComplaintView { out := make([]ComplaintView, 0, len(rows)) for _, r := range rows { target := r.TargetMail if target == "" { target = strconv.FormatInt(r.TargetID, 10) } out = append(out, ComplaintView{ ID: r.ID, Email: r.Email, Target: target, Reason: reportReasonName(r.Reason), Detail: r.Detail, Status: "open", CreatedAt: r.CreatedAt.Format(time.RFC3339), }) } return out } func reportReasonName(r int) string { switch friendentity.ReportReason(r) { case friendentity.ReportSpam: return "spam" case friendentity.ReportHarassment: return "harassment" case friendentity.ReportFake: return "fake" default: return "other" } } func parseReportReason(raw string) friendentity.ReportReason { switch strings.ToLower(strings.TrimSpace(raw)) { case "1", "spam", "垃圾": return friendentity.ReportSpam case "2", "harassment", "骚扰": return friendentity.ReportHarassment case "3", "fake", "不实身份": return friendentity.ReportFake default: return friendentity.ReportOther } }