同步历史版本代码
This commit is contained in:
@@ -56,6 +56,18 @@ func (m *customUserModel) QueryDeviceList(ctx context.Context, userId int64) ([]
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
func (m *customUserModel) QueryDeviceListByUserIds(ctx context.Context, userIds []int64) ([]*Device, int64, error) {
|
||||
var list []*Device
|
||||
var total int64
|
||||
if len(userIds) == 0 {
|
||||
return list, total, nil
|
||||
}
|
||||
err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Model(&Device{}).Where("`user_id` IN ?", userIds).Count(&total).Find(&list).Error
|
||||
})
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
func (m *customUserModel) UpdateDevice(ctx context.Context, data *Device, tx ...*gorm.DB) error {
|
||||
old, err := m.FindOneDevice(ctx, data.Id)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
FamilyStatusActive uint8 = 1
|
||||
FamilyRoleOwner uint8 = 1
|
||||
FamilyRoleMember uint8 = 2
|
||||
FamilyMemberActive uint8 = 1
|
||||
FamilyMemberLeft uint8 = 2
|
||||
FamilyMemberRemoved uint8 = 3
|
||||
DefaultFamilyMaxSize int64 = 5
|
||||
)
|
||||
|
||||
type UserFamily struct {
|
||||
Id int64 `gorm:"primaryKey"`
|
||||
OwnerUserId int64 `gorm:"uniqueIndex:uniq_owner_user_id;not null;comment:Owner User ID"`
|
||||
MaxMembers int64 `gorm:"not null;default:5;comment:Max members in family"`
|
||||
Status uint8 `gorm:"type:tinyint(1);not null;default:1;comment:Status: 1=active, 0=disabled"`
|
||||
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
|
||||
UpdatedAt time.Time `gorm:"comment:Update Time"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:Deletion Time"`
|
||||
}
|
||||
|
||||
func (*UserFamily) TableName() string {
|
||||
return "user_family"
|
||||
}
|
||||
|
||||
type UserFamilyMember struct {
|
||||
Id int64 `gorm:"primaryKey"`
|
||||
FamilyId int64 `gorm:"index:idx_family_status,priority:1;not null;comment:Family ID"`
|
||||
UserId int64 `gorm:"uniqueIndex:uniq_user_id;not null;comment:Member User ID"`
|
||||
Role uint8 `gorm:"type:tinyint(1);not null;default:2;comment:Role: 1=owner, 2=member"`
|
||||
Status uint8 `gorm:"index:idx_family_status,priority:2;type:tinyint(1);not null;default:1;comment:Status: 1=active, 2=left, 3=removed"`
|
||||
JoinSource string `gorm:"type:varchar(32);not null;default:'';comment:Join source"`
|
||||
JoinedAt time.Time `gorm:"not null;comment:Joined time"`
|
||||
LeftAt *time.Time `gorm:"default:NULL;comment:Left time"`
|
||||
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
|
||||
UpdatedAt time.Time `gorm:"comment:Update Time"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:Deletion Time"`
|
||||
}
|
||||
|
||||
func (*UserFamilyMember) TableName() string {
|
||||
return "user_family_member"
|
||||
}
|
||||
@@ -99,6 +99,7 @@ type customUserLogicModel interface {
|
||||
FindOneByEmail(ctx context.Context, email string) (*User, error)
|
||||
FindOneDevice(ctx context.Context, id int64) (*Device, error)
|
||||
QueryDeviceList(ctx context.Context, userid int64) ([]*Device, int64, error)
|
||||
QueryDeviceListByUserIds(ctx context.Context, userIds []int64) ([]*Device, int64, error)
|
||||
QueryDevicePageList(ctx context.Context, userid, subscribeId int64, page, size int) ([]*Device, int64, error)
|
||||
UpdateDevice(ctx context.Context, data *Device, tx ...*gorm.DB) error
|
||||
FindOneDeviceByIdentifier(ctx context.Context, id string) (*Device, error)
|
||||
@@ -110,6 +111,13 @@ type customUserLogicModel interface {
|
||||
|
||||
QueryDailyUserStatisticsList(ctx context.Context, date time.Time) ([]UserStatisticsWithDate, error)
|
||||
QueryMonthlyUserStatisticsList(ctx context.Context, date time.Time) ([]UserStatisticsWithDate, error)
|
||||
FindActiveSubscribe(ctx context.Context, userId int64) (*Subscribe, error)
|
||||
FindActiveSubscribesByUserIds(ctx context.Context, userIds []int64) (map[int64]*UserStatusInfo, error)
|
||||
}
|
||||
|
||||
type UserStatusInfo struct {
|
||||
MemberStatus string
|
||||
LastTrafficAt *time.Time
|
||||
}
|
||||
|
||||
type UserStatisticsWithDate struct {
|
||||
@@ -334,3 +342,17 @@ func (m *customUserModel) QueryMonthlyUserStatisticsList(ctx context.Context, da
|
||||
|
||||
return results, err
|
||||
}
|
||||
|
||||
// FindActiveSubscribe finds the active subscription for a user
|
||||
func (m *customUserModel) FindActiveSubscribe(ctx context.Context, userId int64) (*Subscribe, error) {
|
||||
var subscribe Subscribe
|
||||
err := m.QueryNoCacheCtx(ctx, &subscribe, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Where("user_id = ? AND status IN (0, 1) AND expire_time > ?", userId, time.Now()).
|
||||
Order("expire_time DESC").
|
||||
First(v).Error
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &subscribe, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// FindActiveSubscribesByUserIds Find active subscriptions for multiple users
|
||||
func (m *customUserModel) FindActiveSubscribesByUserIds(ctx context.Context, userIds []int64) (map[int64]*UserStatusInfo, error) {
|
||||
if len(userIds) == 0 {
|
||||
return map[int64]*UserStatusInfo{}, nil
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
UserId int64
|
||||
Name string
|
||||
UpdatedAt *time.Time
|
||||
}
|
||||
var results []Result
|
||||
|
||||
// Query latest active subscription for each user
|
||||
err := m.QueryNoCacheCtx(ctx, &results, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Table("user_subscribe").
|
||||
Select("user_subscribe.user_id, subscribe.name, user_subscribe.updated_at").
|
||||
Joins("LEFT JOIN subscribe ON user_subscribe.subscribe_id = subscribe.id").
|
||||
Where("user_subscribe.user_id IN ? AND user_subscribe.status IN (0, 1) AND user_subscribe.expire_time > ?", userIds, time.Now()).
|
||||
Order("user_subscribe.created_at ASC"). // Ascending so we can overwrite in map to get the latest
|
||||
Scan(v).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*UserStatusInfo)
|
||||
for _, r := range results {
|
||||
userMap[r.UserId] = &UserStatusInfo{
|
||||
MemberStatus: r.Name,
|
||||
LastTrafficAt: r.UpdatedAt,
|
||||
}
|
||||
}
|
||||
return userMap, nil
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -74,18 +75,29 @@ func (m *defaultUserModel) FindUsersSubscribeBySubscribeId(ctx context.Context,
|
||||
// QueryUserSubscribe returns a list of records that meet the conditions.
|
||||
func (m *defaultUserModel) QueryUserSubscribe(ctx context.Context, userId int64, status ...int64) ([]*SubscribeDetails, error) {
|
||||
var list []*SubscribeDetails
|
||||
key := fmt.Sprintf("%s%d", cacheUserSubscribeUserPrefix, userId)
|
||||
|
||||
// Check if includeExpired is set in context
|
||||
includeExpired, _ := ctx.Value(constant.CtxKeyIncludeExpired).(string)
|
||||
cacheKeySuffix := ""
|
||||
if includeExpired == "all" {
|
||||
cacheKeySuffix = ":all"
|
||||
}
|
||||
|
||||
key := fmt.Sprintf("%s%d%s", cacheUserSubscribeUserPrefix, userId, cacheKeySuffix)
|
||||
err := m.QueryCtx(ctx, &list, key, func(conn *gorm.DB, v interface{}) error {
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
// 获取当前时间向前推 7 天
|
||||
sevenDaysAgo := time.Now().Add(-7 * 24 * time.Hour)
|
||||
// 基础条件查询
|
||||
conn = conn.Model(&Subscribe{}).Where("`user_id` = ?", userId)
|
||||
if len(status) > 0 {
|
||||
conn = conn.Where("`status` IN ?", status)
|
||||
}
|
||||
// 订阅过期时间大于当前时间或者订阅结束时间大于当前时间
|
||||
|
||||
if includeExpired == "all" {
|
||||
// 查询所有订阅(包括已过期的)
|
||||
return conn.Preload("Subscribe").Find(&list).Error
|
||||
}
|
||||
|
||||
// 默认只查询有效订阅
|
||||
now := time.Now()
|
||||
sevenDaysAgo := time.Now().Add(-7 * 24 * time.Hour)
|
||||
return conn.Where("`expire_time` > ? OR `finished_at` >= ? OR `expire_time` = ?", now, sevenDaysAgo, time.UnixMilli(0)).
|
||||
Preload("Subscribe").
|
||||
Find(&list).Error
|
||||
|
||||
@@ -28,6 +28,9 @@ type User struct {
|
||||
AuthMethods []AuthMethods `gorm:"foreignKey:UserId;references:Id"`
|
||||
UserDevices []Device `gorm:"foreignKey:UserId;references:Id"`
|
||||
Rules string `gorm:"type:TEXT;comment:User Rules"`
|
||||
LastLoginTime *time.Time `gorm:"default:NULL;comment:Last Login Time"`
|
||||
MemberStatus string `gorm:"type:varchar(20);default:'';comment:Member Status"`
|
||||
Remark string `gorm:"type:varchar(255);default:'';comment:Remark"`
|
||||
CreatedAt time.Time `gorm:"<-:create;comment:Creation Time"`
|
||||
UpdatedAt time.Time `gorm:"comment:Update Time"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;comment:Deletion Time"`
|
||||
|
||||
Reference in New Issue
Block a user