From 21811f4d6372e22a36034c28877e001820b1c106 Mon Sep 17 00:00:00 2001 From: shanshanzhong147 Date: Mon, 8 Jun 2026 22:24:51 -0700 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D(#13):=20=E9=82=80=E8=AF=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E8=BF=94=E5=9B=9E=E8=AE=BE=E5=A4=87=E6=A0=87?= =?UTF-8?q?=E8=AF=86=E5=92=8C=E8=AE=BE=E5=A4=87=E5=8F=B7=20(#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: multica-agent --- apis/admin/invite.api | 2 ++ internal/logic/admin/invite/benefits.go | 24 +++++++++---- internal/logic/admin/invite/benefits_test.go | 34 +++++++++++++++++++ .../admin/invite/getInviteManageListLogic.go | 8 +++-- internal/types/types.go | 2 ++ 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/apis/admin/invite.api b/apis/admin/invite.api index 3fda0ad..988b9f9 100644 --- a/apis/admin/invite.api +++ b/apis/admin/invite.api @@ -21,8 +21,10 @@ type ( InviteManageRecord { InviterId int64 `json:"inviter_id"` InviterIdentifier string `json:"inviter_identifier"` + InviterDeviceNo string `json:"inviter_device_no"` InviteeId int64 `json:"invitee_id"` InviteeIdentifier string `json:"invitee_identifier"` + InviteeDeviceNo string `json:"invitee_device_no"` InviteeAvatar string `json:"invitee_avatar"` InviteeEnable bool `json:"invitee_enable"` InvitedAt int64 `json:"invited_at"` diff --git a/internal/logic/admin/invite/benefits.go b/internal/logic/admin/invite/benefits.go index d826f43..c37d1f6 100644 --- a/internal/logic/admin/invite/benefits.go +++ b/internal/logic/admin/invite/benefits.go @@ -5,6 +5,7 @@ import ( "slices" modellog "github.com/perfect-panel/server/internal/model/log" + "github.com/perfect-panel/server/pkg/tool" "github.com/perfect-panel/server/pkg/xerr" "github.com/pkg/errors" "gorm.io/gorm" @@ -188,26 +189,35 @@ func fillGiftBenefits(ctx context.Context, db *gorm.DB, benefits map[int64]Benef return nil } -func QueryIdentifiers(ctx context.Context, db *gorm.DB, userIds []int64) (map[int64]string, error) { - identifiers := make(map[int64]string, len(userIds)) +type DeviceIdentifier struct { + Identifier string + DeviceNo string +} + +func QueryDeviceIdentifiers(ctx context.Context, db *gorm.DB, userIds []int64) (map[int64]DeviceIdentifier, error) { + identifiers := make(map[int64]DeviceIdentifier, len(userIds)) if len(userIds) == 0 { return identifiers, nil } type identifierRow struct { UserId int64 `gorm:"column:user_id"` + DeviceId int64 `gorm:"column:device_id"` Identifier string `gorm:"column:identifier"` } var rows []identifierRow if err := db.WithContext(ctx). - Table("user_auth_methods uam"). - Select("uam.user_id, uam.auth_identifier as identifier"). - Joins("JOIN (SELECT user_id, MIN(id) AS id FROM user_auth_methods WHERE user_id IN ? GROUP BY user_id) first_uam ON first_uam.id = uam.id", userIds). + Table("user_device ud"). + Select("ud.user_id, ud.id as device_id, ud.identifier as identifier"). + Joins("JOIN (SELECT user_id, MIN(id) AS id FROM user_device WHERE user_id IN ? GROUP BY user_id) first_ud ON first_ud.id = ud.id", userIds). Scan(&rows).Error; err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user identifiers failed: %v", err) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query user device identifiers failed: %v", err) } for _, row := range rows { - identifiers[row.UserId] = row.Identifier + identifiers[row.UserId] = DeviceIdentifier{ + Identifier: row.Identifier, + DeviceNo: tool.DeviceIdToHash(row.DeviceId), + } } return identifiers, nil } diff --git a/internal/logic/admin/invite/benefits_test.go b/internal/logic/admin/invite/benefits_test.go index 844ae0a..21e6233 100644 --- a/internal/logic/admin/invite/benefits_test.go +++ b/internal/logic/admin/invite/benefits_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/DATA-DOG/go-sqlmock" + "github.com/perfect-panel/server/pkg/tool" "gorm.io/driver/mysql" "gorm.io/gorm" ) @@ -73,6 +74,39 @@ func TestQueryBenefitsKeepsDirectInviteeGift(t *testing.T) { assertBenefitsExpectations(t, mock) } +func TestQueryDeviceIdentifiersReturnsDeviceIdentifierAndNo(t *testing.T) { + db, mock, cleanup := newBenefitsTestDB(t) + defer cleanup() + + mock.ExpectQuery("FROM user_device ud"). + WithArgs(int64(100), int64(200)). + WillReturnRows(sqlmock.NewRows([]string{"user_id", "device_id", "identifier"}). + AddRow(100, 11, "inviter-hash"). + AddRow(200, 22, "invitee-hash")) + + identifiers, err := QueryDeviceIdentifiers(context.Background(), db, []int64{100, 200}) + if err != nil { + t.Fatalf("QueryDeviceIdentifiers returned error: %v", err) + } + + inviter := identifiers[100] + if inviter.Identifier != "inviter-hash" { + t.Fatalf("inviter identifier = %q, want inviter-hash", inviter.Identifier) + } + if inviter.DeviceNo != tool.DeviceIdToHash(11) { + t.Fatalf("inviter device no = %q, want %q", inviter.DeviceNo, tool.DeviceIdToHash(11)) + } + + invitee := identifiers[200] + if invitee.Identifier != "invitee-hash" { + t.Fatalf("invitee identifier = %q, want invitee-hash", invitee.Identifier) + } + if invitee.DeviceNo != tool.DeviceIdToHash(22) { + t.Fatalf("invitee device no = %q, want %q", invitee.DeviceNo, tool.DeviceIdToHash(22)) + } + assertBenefitsExpectations(t, mock) +} + func newBenefitsTestDB(t *testing.T) (*gorm.DB, sqlmock.Sqlmock, func()) { t.Helper() diff --git a/internal/logic/admin/invite/getInviteManageListLogic.go b/internal/logic/admin/invite/getInviteManageListLogic.go index 070cc15..46374de 100644 --- a/internal/logic/admin/invite/getInviteManageListLogic.go +++ b/internal/logic/admin/invite/getInviteManageListLogic.go @@ -68,7 +68,7 @@ func (l *GetInviteManageListLogic) GetInviteManageList(req *types.GetInviteManag if err != nil { return nil, err } - identifiers, err := QueryIdentifiers(l.ctx, l.svcCtx.DB, userIds) + devices, err := QueryDeviceIdentifiers(l.ctx, l.svcCtx.DB, userIds) if err != nil { return nil, err } @@ -78,9 +78,11 @@ func (l *GetInviteManageListLogic) GetInviteManageList(req *types.GetInviteManag benefit := benefits[row.InviteeId] list = append(list, types.InviteManageRecord{ InviterId: row.InviterId, - InviterIdentifier: identifiers[row.InviterId], + InviterIdentifier: devices[row.InviterId].Identifier, + InviterDeviceNo: devices[row.InviterId].DeviceNo, InviteeId: row.InviteeId, - InviteeIdentifier: identifiers[row.InviteeId], + InviteeIdentifier: devices[row.InviteeId].Identifier, + InviteeDeviceNo: devices[row.InviteeId].DeviceNo, InviteeAvatar: row.InviteeAvatar, InviteeEnable: row.InviteeEnable, InvitedAt: row.InvitedAt, diff --git a/internal/types/types.go b/internal/types/types.go index 1ebe57c..2fda0e3 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -1845,8 +1845,10 @@ type InviteConfig struct { type InviteManageRecord struct { InviterId int64 `json:"inviter_id"` InviterIdentifier string `json:"inviter_identifier"` + InviterDeviceNo string `json:"inviter_device_no"` InviteeId int64 `json:"invitee_id"` InviteeIdentifier string `json:"invitee_identifier"` + InviteeDeviceNo string `json:"invitee_device_no"` InviteeAvatar string `json:"invitee_avatar"` InviteeEnable bool `json:"invitee_enable"` InvitedAt int64 `json:"invited_at"`