package services import ( "context" "os" "time" "quyun/v2/app/errorx" user_dto "quyun/v2/app/http/v1/dto" "quyun/v2/app/jobs/args" "quyun/v2/app/requests" "quyun/v2/database/models" "quyun/v2/providers/job" ) // @provider type notification struct { job *job.Job } func (s *notification) List(ctx context.Context, tenantID, userID int64, page int, typeArg string) (*requests.Pager, error) { tbl, q := models.NotificationQuery.QueryContext(ctx) q = q.Where(tbl.UserID.Eq(userID)) if tenantID > 0 { q = q.Where(tbl.TenantID.Eq(tenantID)) } if typeArg != "" && typeArg != "all" { q = q.Where(tbl.Type.Eq(typeArg)) } q = q.Order(tbl.CreatedAt.Desc()) p := requests.Pagination{Page: int64(page), Limit: 20} total, err := q.Count() if err != nil { return nil, errorx.ErrDatabaseError.WithCause(err) } list, err := q.Offset(int(p.Offset())).Limit(int(p.Limit)).Find() if err != nil { return nil, errorx.ErrDatabaseError.WithCause(err) } data := make([]user_dto.Notification, len(list)) for i, v := range list { data[i] = user_dto.Notification{ ID: v.ID, Type: v.Type, Title: v.Title, Content: v.Content, Read: v.IsRead, Time: v.CreatedAt.Format(time.RFC3339), } } return &requests.Pager{ Pagination: requests.Pagination{Page: p.Page, Limit: p.Limit}, Total: total, Items: data, }, nil } func (s *notification) MarkRead(ctx context.Context, tenantID, userID, id int64) error { tbl, q := models.NotificationQuery.QueryContext(ctx) q = q.Where(tbl.ID.Eq(id), tbl.UserID.Eq(userID)) if tenantID > 0 { q = q.Where(tbl.TenantID.Eq(tenantID)) } _, err := q.UpdateSimple(tbl.IsRead.Value(true)) if err != nil { return errorx.ErrDatabaseError.WithCause(err) } return nil } func (s *notification) MarkAllRead(ctx context.Context, tenantID, userID int64) error { tbl, q := models.NotificationQuery.QueryContext(ctx) q = q.Where(tbl.UserID.Eq(userID), tbl.IsRead.Is(false)) if tenantID > 0 { q = q.Where(tbl.TenantID.Eq(tenantID)) } _, err := q.UpdateSimple(tbl.IsRead.Value(true)) if err != nil { return errorx.ErrDatabaseError.WithCause(err) } return nil } func (s *notification) Send(ctx context.Context, tenantID, userID int64, typ, title, content string) error { arg := args.NotificationArgs{ TenantID: tenantID, UserID: userID, Type: typ, Title: title, Content: content, } // 测试环境下同步写入,避免异步任务未启动导致结果不确定。 if os.Getenv("JOB_INLINE") == "1" { n := &models.Notification{ TenantID: tenantID, UserID: userID, Type: typ, Title: title, Content: content, IsRead: false, } if err := models.NotificationQuery.WithContext(ctx).Create(n); err != nil { return errorx.ErrDatabaseError.WithCause(err) } return nil } return s.job.Add(arg) }