package service import ( "FileRelay/internal/bootstrap" "FileRelay/internal/model" "FileRelay/internal/storage" "context" "errors" "time" "gorm.io/gorm" ) type BatchService struct { db *gorm.DB } func NewBatchService() *BatchService { return &BatchService{db: bootstrap.DB} } func (s *BatchService) GetBatchByPickupCode(code string) (*model.FileBatch, error) { var batch model.FileBatch err := s.db.Preload("FileItems").Where("pickup_code = ? AND status = ?", code, "active").First(&batch).Error if err != nil { return nil, err } // 检查是否过期 if s.IsExpired(&batch) { s.MarkAsExpired(&batch) return nil, errors.New("batch expired") } return &batch, nil } func (s *BatchService) IsExpired(batch *model.FileBatch) bool { if batch.Status != "active" { return true } switch batch.ExpireType { case "time": if batch.ExpireAt != nil && time.Now().After(*batch.ExpireAt) { return true } case "download": if batch.MaxDownloads > 0 && batch.DownloadCount >= batch.MaxDownloads { return true } } return false } func (s *BatchService) MarkAsExpired(batch *model.FileBatch) error { return s.db.Model(batch).Update("status", "expired").Error } func (s *BatchService) DeleteBatch(ctx context.Context, batchID uint) error { var batch model.FileBatch if err := s.db.Preload("FileItems").First(&batch, batchID).Error; err != nil { return err } // 删除物理文件 for _, item := range batch.FileItems { _ = storage.GlobalStorage.Delete(ctx, item.StoragePath) } // 删除数据库记录 (软删除 Batch) return s.db.Transaction(func(tx *gorm.DB) error { if err := tx.Where("batch_id = ?", batch.ID).Delete(&model.FileItem{}).Error; err != nil { return err } if err := tx.Delete(&batch).Error; err != nil { return err } return nil }) } func (s *BatchService) IncrementDownloadCount(batchID uint) error { return s.db.Model(&model.FileBatch{}).Where("id = ?", batchID). UpdateColumn("download_count", gorm.Expr("download_count + ?", 1)).Error }