package service import ( "context" "errors" "time" "github.com/topfans/backend/pkg/models" pb "github.com/topfans/backend/pkg/proto/moderation" "github.com/topfans/backend/services/moderationService/client" "github.com/topfans/backend/services/moderationService/config" "github.com/topfans/backend/services/moderationService/repository" ) type FeedbackService struct { repo *repository.ModerationRepository category *CategoryService notifClient *client.NotificationClient cfg config.ModerationConfig } func NewFeedbackService( repo *repository.ModerationRepository, category *CategoryService, notifClient *client.NotificationClient, cfg config.ModerationConfig, ) *FeedbackService { return &FeedbackService{repo: repo, category: category, notifClient: notifClient, cfg: cfg} } func (s *FeedbackService) SubmitFeedback(ctx context.Context, req *pb.SubmitFeedbackRequest) (*pb.SubmitFeedbackResponse, error) { now := time.Now().UnixMilli() // 验证分类启用 enabled, err := s.category.IsFeedbackCategoryEnabled(ctx, req.CategoryCode) if err != nil { return nil, err } if !enabled { return nil, ErrFeedbackCatInvalid } if len(req.Title) > 100 { return nil, ErrDescriptionTooLong } if len(req.Contact) > s.cfg.MaxContactLen { return nil, ErrDescriptionTooLong } if len(req.EvidenceKeys) > s.cfg.MaxEvidenceCount { return nil, ErrTooManyEvidence } feedback := &models.Feedback{ UserID: req.UserId, CategoryCode: req.CategoryCode, Title: req.Title, Content: req.Content, IsAnonymous: req.IsAnonymous, Status: "pending", ClaimedBy: nil, ClaimedAt: nil, CreatedAt: now, UpdatedAt: now, } if req.StarId > 0 { sid := req.StarId feedback.StarID = &sid } if req.Contact != "" { c := req.Contact feedback.Contact = &c } if err := s.repo.CreateFeedback(ctx, feedback); err != nil { return nil, err } for i, key := range req.EvidenceKeys { ev := &models.FeedbackEvidence{ FeedbackID: feedback.ID, OSSKey: key, SortOrder: int32(i), CreatedAt: now, } if err := s.repo.CreateFeedbackEvidence(ctx, ev); err != nil { return nil, err } } return &pb.SubmitFeedbackResponse{ FeedbackId: feedback.ID, Status: feedback.Status, ClaimedBy: 0, ClaimedAt: 0, CreatedAt: feedback.CreatedAt, }, nil } func (s *FeedbackService) ListMyFeedbacks(ctx context.Context, req *pb.ListMyFeedbacksRequest) (*pb.ListMyFeedbacksResponse, error) { page := int(req.Page) if page < 1 { page = 1 } pageSize := int(req.PageSize) if pageSize < 1 || pageSize > 100 { pageSize = 20 } fbs, total, err := s.repo.ListMyFeedbacks(ctx, req.UserId, req.Status, page, pageSize) if err != nil { return nil, err } resp := &pb.ListMyFeedbacksResponse{Total: int32(total)} for _, fb := range fbs { item := &pb.FeedbackSummary{ Id: fb.ID, CategoryCode: fb.CategoryCode, Title: fb.Title, Status: fb.Status, CreatedAt: fb.CreatedAt, } if fb.RepliedAt != nil { item.RepliedAt = *fb.RepliedAt } resp.Feedbacks = append(resp.Feedbacks, item) } return resp, nil } func (s *FeedbackService) GetFeedback(ctx context.Context, req *pb.GetFeedbackRequest) (*pb.GetFeedbackResponse, error) { fb, err := s.repo.GetFeedbackByID(ctx, req.Id) if err != nil { return nil, ErrReportNotFound } if fb.UserID != req.UserId { return nil, ErrReportNotFound } resp := &pb.GetFeedbackResponse{ Feedback: &pb.FeedbackSummary{ Id: fb.ID, CategoryCode: fb.CategoryCode, Title: fb.Title, Status: fb.Status, CreatedAt: fb.CreatedAt, }, Content: fb.Content, } if fb.ReplyContent != nil { resp.ReplyContent = *fb.ReplyContent } if fb.RepliedAt != nil { resp.Feedback.RepliedAt = *fb.RepliedAt } evs, _ := s.repo.GetFeedbackEvidence(ctx, fb.ID) for _, ev := range evs { item := &pb.EvidenceSummary{OssKey: ev.OSSKey} if ev.OSSURL != nil { item.OssUrl = *ev.OSSURL } resp.Evidence = append(resp.Evidence, item) } return resp, nil } // avoid unused import warning var _ = errors.New