package mysqldao import ( "context" "git.lzcwy.cn/zhengchiliu/zt-closet-backend/global" "git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/mysqlmodel" "gorm.io/gorm" ) // NotificationDao 用户通知数据访问 type NotificationDao struct { db *gorm.DB } // NewNotificationDao 创建通知 DAO func NewNotificationDao() *NotificationDao { return &NotificationDao{db: global.MysqlEngine} } // NotificationCreate 创建通知 func (d *NotificationDao) NotificationCreate(ctx context.Context, notification *mysqlmodel.UserNotification) error { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationCreate") defer span.End() if err := d.db.WithContext(ctx).Create(notification).Error; err != nil { span.RecordError(err) return err } return nil } // NotificationUpdateReadByUUID 标记通知已读 func (d *NotificationDao) NotificationUpdateReadByUUID(ctx context.Context, notificationUUID string) error { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationUpdateReadByUUID") defer span.End() if err := d.db.WithContext(ctx).Model(&mysqlmodel.UserNotification{}). Where("notification_uuid = ?", notificationUUID). Update("is_read", int8(2)).Error; err != nil { span.RecordError(err) return err } return nil } // NotificationUpdateReadByUUIDIfUnread 条件标记已读(仅未读 -> 已读),返回是否更新成功, // 用于防并发重复扣减未读数。 func (d *NotificationDao) NotificationUpdateReadByUUIDIfUnread(ctx context.Context, notificationUUID string) (bool, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationUpdateReadByUUIDIfUnread") defer span.End() res := d.db.WithContext(ctx).Model(&mysqlmodel.UserNotification{}). Where("notification_uuid = ? AND is_read = ?", notificationUUID, int8(1)). Update("is_read", int8(2)) if res.Error != nil { span.RecordError(res.Error) return false, res.Error } return res.RowsAffected > 0, nil } // NotificationUpdateReadAllByUserID 将该用户全部未读通知标记为已读,返回影响行数。 // 条件带 is_read = 1,保证只统计本次真正从未读变为已读的条数(幂等,重复调用返回 0)。 func (d *NotificationDao) NotificationUpdateReadAllByUserID(ctx context.Context, userID int64) (int64, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationUpdateReadAllByUserID") defer span.End() res := d.db.WithContext(ctx).Model(&mysqlmodel.UserNotification{}). Where("user_id = ? AND is_read = ?", userID, int8(1)). Update("is_read", int8(2)) if res.Error != nil { span.RecordError(res.Error) return 0, res.Error } return res.RowsAffected, nil } // NotificationGetByUUID 按 UUID 查询通知 func (d *NotificationDao) NotificationGetByUUID(ctx context.Context, notificationUUID string) (*mysqlmodel.UserNotification, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationGetByUUID") defer span.End() var notification mysqlmodel.UserNotification if err := d.db.WithContext(ctx).Where("notification_uuid = ?", notificationUUID).First(¬ification).Error; err != nil { span.RecordError(err) return nil, err } return ¬ification, nil } // NotificationCountUnread 统计用户未读数 func (d *NotificationDao) NotificationCountUnread(ctx context.Context, userID int64) (int64, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationCountUnread") defer span.End() var count int64 if err := d.db.WithContext(ctx).Model(&mysqlmodel.UserNotification{}). Where("user_id = ? AND is_read = ?", userID, int8(1)). Count(&count).Error; err != nil { span.RecordError(err) return 0, err } return count, nil } // NotificationListByUserID 分页查询用户通知(isRead/msgType 为 0 不筛选) func (d *NotificationDao) NotificationListByUserID(ctx context.Context, userID int64, isRead, msgType int8, page, pageSize int) ([]mysqlmodel.UserNotification, int64, error) { ctx, span := global.Tracer.Start(ctx, "mysqldao.NotificationListByUserID") defer span.End() var list []mysqlmodel.UserNotification var total int64 q := d.db.WithContext(ctx).Model(&mysqlmodel.UserNotification{}).Where("user_id = ?", userID) if isRead != 0 { q = q.Where("is_read = ?", isRead) } if msgType != 0 { q = q.Where("msg_type = ?", msgType) } if err := q.Count(&total).Error; err != nil { span.RecordError(err) return nil, 0, err } if err := q.Offset((page - 1) * pageSize).Limit(pageSize).Order("id DESC").Find(&list).Error; err != nil { span.RecordError(err) return nil, 0, err } return list, total, nil }